• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * cs4349.c  --  CS4349 ALSA Soc Audio driver
3   *
4   * Copyright 2015 Cirrus Logic, Inc.
5   *
6   * Authors: Tim Howe <Tim.Howe@cirrus.com>
7   *
8   * This program is free software; you can redistribute it and/or modify
9   * it under the terms of the GNU General Public License version 2 as
10   * published by the Free Software Foundation.
11   */
12  
13  #include <linux/module.h>
14  #include <linux/moduleparam.h>
15  #include <linux/kernel.h>
16  #include <linux/init.h>
17  #include <linux/delay.h>
18  #include <linux/gpio.h>
19  #include <linux/gpio/consumer.h>
20  #include <linux/platform_device.h>
21  #include <linux/pm.h>
22  #include <linux/i2c.h>
23  #include <linux/of_device.h>
24  #include <linux/regmap.h>
25  #include <linux/slab.h>
26  #include <sound/core.h>
27  #include <sound/pcm.h>
28  #include <sound/pcm_params.h>
29  #include <sound/soc.h>
30  #include <sound/soc-dapm.h>
31  #include <sound/initval.h>
32  #include <sound/tlv.h>
33  #include "cs4349.h"
34  
35  
36  static const struct reg_default cs4349_reg_defaults[] = {
37  	{ 2, 0x00 },	/* r02	- Mode Control */
38  	{ 3, 0x09 },	/* r03	- Volume, Mixing and Inversion Control */
39  	{ 4, 0x81 },	/* r04	- Mute Control */
40  	{ 5, 0x00 },	/* r05	- Channel A Volume Control */
41  	{ 6, 0x00 },	/* r06	- Channel B Volume Control */
42  	{ 7, 0xB1 },	/* r07	- Ramp and Filter Control */
43  	{ 8, 0x1C },	/* r08	- Misc. Control */
44  };
45  
46  /* Private data for the CS4349 */
47  struct  cs4349_private {
48  	struct regmap			*regmap;
49  	struct gpio_desc		*reset_gpio;
50  	unsigned int			mode;
51  	int				rate;
52  };
53  
cs4349_readable_register(struct device * dev,unsigned int reg)54  static bool cs4349_readable_register(struct device *dev, unsigned int reg)
55  {
56  	switch (reg) {
57  	case CS4349_CHIPID ... CS4349_MISC:
58  		return true;
59  	default:
60  		return false;
61  	}
62  }
63  
cs4349_writeable_register(struct device * dev,unsigned int reg)64  static bool cs4349_writeable_register(struct device *dev, unsigned int reg)
65  {
66  	switch (reg) {
67  	case CS4349_MODE ...  CS4349_MISC:
68  		return true;
69  	default:
70  		return false;
71  	}
72  }
73  
cs4349_set_dai_fmt(struct snd_soc_dai * codec_dai,unsigned int format)74  static int cs4349_set_dai_fmt(struct snd_soc_dai *codec_dai,
75  			      unsigned int format)
76  {
77  	struct snd_soc_component *component = codec_dai->component;
78  	struct cs4349_private *cs4349 = snd_soc_component_get_drvdata(component);
79  	unsigned int fmt;
80  
81  	fmt = format & SND_SOC_DAIFMT_FORMAT_MASK;
82  
83  	switch (fmt) {
84  	case SND_SOC_DAIFMT_I2S:
85  	case SND_SOC_DAIFMT_LEFT_J:
86  	case SND_SOC_DAIFMT_RIGHT_J:
87  		cs4349->mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
88  		break;
89  	default:
90  		return -EINVAL;
91  	}
92  
93  	return 0;
94  }
95  
cs4349_pcm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)96  static int cs4349_pcm_hw_params(struct snd_pcm_substream *substream,
97  			    struct snd_pcm_hw_params *params,
98  			    struct snd_soc_dai *dai)
99  {
100  	struct snd_soc_component *component = dai->component;
101  	struct cs4349_private *cs4349 = snd_soc_component_get_drvdata(component);
102  	int fmt, ret;
103  
104  	cs4349->rate = params_rate(params);
105  
106  	switch (cs4349->mode) {
107  	case SND_SOC_DAIFMT_I2S:
108  		fmt = DIF_I2S;
109  		break;
110  	case SND_SOC_DAIFMT_LEFT_J:
111  		fmt = DIF_LEFT_JST;
112  		break;
113  	case SND_SOC_DAIFMT_RIGHT_J:
114  		switch (params_width(params)) {
115  		case 16:
116  			fmt = DIF_RGHT_JST16;
117  			break;
118  		case 24:
119  			fmt = DIF_RGHT_JST24;
120  			break;
121  		default:
122  			return -EINVAL;
123  		}
124  		break;
125  	default:
126  		return -EINVAL;
127  	}
128  
129  	ret = snd_soc_component_update_bits(component, CS4349_MODE, DIF_MASK,
130  				  MODE_FORMAT(fmt));
131  	if (ret < 0)
132  		return ret;
133  
134  	return 0;
135  }
136  
cs4349_digital_mute(struct snd_soc_dai * dai,int mute)137  static int cs4349_digital_mute(struct snd_soc_dai *dai, int mute)
138  {
139  	struct snd_soc_component *component = dai->component;
140  	int reg;
141  
142  	reg = 0;
143  	if (mute)
144  		reg = MUTE_AB_MASK;
145  
146  	return snd_soc_component_update_bits(component, CS4349_MUTE, MUTE_AB_MASK, reg);
147  }
148  
149  static DECLARE_TLV_DB_SCALE(dig_tlv, -12750, 50, 0);
150  
151  static const char * const chan_mix_texts[] = {
152  	"Mute", "MuteA", "MuteA SwapB", "MuteA MonoB", "SwapA MuteB",
153  	"BothR", "Swap", "SwapA MonoB", "MuteB", "Normal", "BothL",
154  	"MonoB", "MonoA MuteB", "MonoA", "MonoA SwapB", "Mono",
155  	/*Normal == Channel A = Left, Channel B = Right*/
156  };
157  
158  static const char * const fm_texts[] = {
159  	"Auto", "Single", "Double", "Quad",
160  };
161  
162  static const char * const deemph_texts[] = {
163  	"None", "44.1k", "48k", "32k",
164  };
165  
166  static const char * const softr_zeroc_texts[] = {
167  	"Immediate", "Zero Cross", "Soft Ramp", "SR on ZC",
168  };
169  
170  static int deemph_values[] = {
171  	0, 4, 8, 12,
172  };
173  
174  static int softr_zeroc_values[] = {
175  	0, 64, 128, 192,
176  };
177  
178  static const struct soc_enum chan_mix_enum =
179  	SOC_ENUM_SINGLE(CS4349_VMI, 0,
180  			ARRAY_SIZE(chan_mix_texts),
181  			chan_mix_texts);
182  
183  static const struct soc_enum fm_mode_enum =
184  	SOC_ENUM_SINGLE(CS4349_MODE, 0,
185  			ARRAY_SIZE(fm_texts),
186  			fm_texts);
187  
188  static SOC_VALUE_ENUM_SINGLE_DECL(deemph_enum, CS4349_MODE, 0, DEM_MASK,
189  				deemph_texts, deemph_values);
190  
191  static SOC_VALUE_ENUM_SINGLE_DECL(softr_zeroc_enum, CS4349_RMPFLT, 0,
192  				SR_ZC_MASK, softr_zeroc_texts,
193  				softr_zeroc_values);
194  
195  static const struct snd_kcontrol_new cs4349_snd_controls[] = {
196  	SOC_DOUBLE_R_TLV("Master Playback Volume",
197  			 CS4349_VOLA, CS4349_VOLB, 0, 0xFF, 1, dig_tlv),
198  	SOC_ENUM("Functional Mode", fm_mode_enum),
199  	SOC_ENUM("De-Emphasis Control", deemph_enum),
200  	SOC_ENUM("Soft Ramp Zero Cross Control", softr_zeroc_enum),
201  	SOC_ENUM("Channel Mixer", chan_mix_enum),
202  	SOC_SINGLE("VolA = VolB Switch", CS4349_VMI, 7, 1, 0),
203  	SOC_SINGLE("InvertA Switch", CS4349_VMI, 6, 1, 0),
204  	SOC_SINGLE("InvertB Switch", CS4349_VMI, 5, 1, 0),
205  	SOC_SINGLE("Auto-Mute Switch", CS4349_MUTE, 7, 1, 0),
206  	SOC_SINGLE("MUTEC A = B Switch", CS4349_MUTE, 5, 1, 0),
207  	SOC_SINGLE("Soft Ramp Up Switch", CS4349_RMPFLT, 5, 1, 0),
208  	SOC_SINGLE("Soft Ramp Down Switch", CS4349_RMPFLT, 4, 1, 0),
209  	SOC_SINGLE("Slow Roll Off Filter Switch", CS4349_RMPFLT, 2, 1, 0),
210  	SOC_SINGLE("Freeze Switch", CS4349_MISC, 5, 1, 0),
211  	SOC_SINGLE("Popguard Switch", CS4349_MISC, 4, 1, 0),
212  };
213  
214  static const struct snd_soc_dapm_widget cs4349_dapm_widgets[] = {
215  	SND_SOC_DAPM_DAC("HiFi DAC", NULL, SND_SOC_NOPM, 0, 0),
216  
217  	SND_SOC_DAPM_OUTPUT("OutputA"),
218  	SND_SOC_DAPM_OUTPUT("OutputB"),
219  };
220  
221  static const struct snd_soc_dapm_route cs4349_routes[] = {
222  	{"DAC Playback", NULL, "OutputA"},
223  	{"DAC Playback", NULL, "OutputB"},
224  
225  	{"OutputA", NULL, "HiFi DAC"},
226  	{"OutputB", NULL, "HiFi DAC"},
227  };
228  
229  #define CS4349_PCM_FORMATS (SNDRV_PCM_FMTBIT_S8  | \
230  			SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_S16_BE  | \
231  			SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
232  			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
233  			SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
234  			SNDRV_PCM_FMTBIT_S24_LE  | SNDRV_PCM_FMTBIT_S24_BE  | \
235  			SNDRV_PCM_FMTBIT_S32_LE)
236  
237  #define CS4349_PCM_RATES SNDRV_PCM_RATE_8000_192000
238  
239  static const struct snd_soc_dai_ops cs4349_dai_ops = {
240  	.hw_params	= cs4349_pcm_hw_params,
241  	.set_fmt	= cs4349_set_dai_fmt,
242  	.digital_mute	= cs4349_digital_mute,
243  };
244  
245  static struct snd_soc_dai_driver cs4349_dai = {
246  	.name = "cs4349_hifi",
247  	.playback = {
248  		.stream_name	= "DAC Playback",
249  		.channels_min	= 1,
250  		.channels_max	= 2,
251  		.rates		= CS4349_PCM_RATES,
252  		.formats	= CS4349_PCM_FORMATS,
253  	},
254  	.ops = &cs4349_dai_ops,
255  	.symmetric_rates = 1,
256  };
257  
258  static const struct snd_soc_component_driver soc_component_dev_cs4349 = {
259  	.controls		= cs4349_snd_controls,
260  	.num_controls		= ARRAY_SIZE(cs4349_snd_controls),
261  	.dapm_widgets		= cs4349_dapm_widgets,
262  	.num_dapm_widgets	= ARRAY_SIZE(cs4349_dapm_widgets),
263  	.dapm_routes		= cs4349_routes,
264  	.num_dapm_routes	= ARRAY_SIZE(cs4349_routes),
265  	.idle_bias_on		= 1,
266  	.use_pmdown_time	= 1,
267  	.endianness		= 1,
268  	.non_legacy_dai_naming	= 1,
269  };
270  
271  static const struct regmap_config cs4349_regmap = {
272  	.reg_bits		= 8,
273  	.val_bits		= 8,
274  
275  	.max_register		= CS4349_MISC,
276  	.reg_defaults		= cs4349_reg_defaults,
277  	.num_reg_defaults	= ARRAY_SIZE(cs4349_reg_defaults),
278  	.readable_reg		= cs4349_readable_register,
279  	.writeable_reg		= cs4349_writeable_register,
280  	.cache_type		= REGCACHE_RBTREE,
281  };
282  
cs4349_i2c_probe(struct i2c_client * client,const struct i2c_device_id * id)283  static int cs4349_i2c_probe(struct i2c_client *client,
284  				      const struct i2c_device_id *id)
285  {
286  	struct cs4349_private *cs4349;
287  	int ret;
288  
289  	cs4349 = devm_kzalloc(&client->dev, sizeof(*cs4349), GFP_KERNEL);
290  	if (!cs4349)
291  		return -ENOMEM;
292  
293  	cs4349->regmap = devm_regmap_init_i2c(client, &cs4349_regmap);
294  	if (IS_ERR(cs4349->regmap)) {
295  		ret = PTR_ERR(cs4349->regmap);
296  		dev_err(&client->dev, "regmap_init() failed: %d\n", ret);
297  		return ret;
298  	}
299  
300  	/* Reset the Device */
301  	cs4349->reset_gpio = devm_gpiod_get_optional(&client->dev,
302  		"reset", GPIOD_OUT_LOW);
303  	if (IS_ERR(cs4349->reset_gpio))
304  		return PTR_ERR(cs4349->reset_gpio);
305  
306  	gpiod_set_value_cansleep(cs4349->reset_gpio, 1);
307  
308  	i2c_set_clientdata(client, cs4349);
309  
310  	return devm_snd_soc_register_component(&client->dev,
311  		&soc_component_dev_cs4349,
312  		&cs4349_dai, 1);
313  }
314  
cs4349_i2c_remove(struct i2c_client * client)315  static int cs4349_i2c_remove(struct i2c_client *client)
316  {
317  	struct cs4349_private *cs4349 = i2c_get_clientdata(client);
318  
319  	/* Hold down reset */
320  	gpiod_set_value_cansleep(cs4349->reset_gpio, 0);
321  
322  	return 0;
323  }
324  
325  #ifdef CONFIG_PM
cs4349_runtime_suspend(struct device * dev)326  static int cs4349_runtime_suspend(struct device *dev)
327  {
328  	struct cs4349_private *cs4349 = dev_get_drvdata(dev);
329  	int ret;
330  
331  	ret = regmap_update_bits(cs4349->regmap, CS4349_MISC, PWR_DWN, PWR_DWN);
332  	if (ret < 0)
333  		return ret;
334  
335  	regcache_cache_only(cs4349->regmap, true);
336  
337  	/* Hold down reset */
338  	gpiod_set_value_cansleep(cs4349->reset_gpio, 0);
339  
340  	return 0;
341  }
342  
cs4349_runtime_resume(struct device * dev)343  static int cs4349_runtime_resume(struct device *dev)
344  {
345  	struct cs4349_private *cs4349 = dev_get_drvdata(dev);
346  	int ret;
347  
348  	ret = regmap_update_bits(cs4349->regmap, CS4349_MISC, PWR_DWN, 0);
349  	if (ret < 0)
350  		return ret;
351  
352  	gpiod_set_value_cansleep(cs4349->reset_gpio, 1);
353  
354  	regcache_cache_only(cs4349->regmap, false);
355  	regcache_sync(cs4349->regmap);
356  
357  	return 0;
358  }
359  #endif
360  
361  static const struct dev_pm_ops cs4349_runtime_pm = {
362  	SET_RUNTIME_PM_OPS(cs4349_runtime_suspend, cs4349_runtime_resume,
363  			   NULL)
364  };
365  
366  static const struct of_device_id cs4349_of_match[] = {
367  	{ .compatible = "cirrus,cs4349", },
368  	{},
369  };
370  
371  MODULE_DEVICE_TABLE(of, cs4349_of_match);
372  
373  static const struct i2c_device_id cs4349_i2c_id[] = {
374  	{"cs4349", 0},
375  	{}
376  };
377  
378  MODULE_DEVICE_TABLE(i2c, cs4349_i2c_id);
379  
380  static struct i2c_driver cs4349_i2c_driver = {
381  	.driver = {
382  		.name		= "cs4349",
383  		.of_match_table	= cs4349_of_match,
384  		.pm = &cs4349_runtime_pm,
385  	},
386  	.id_table	= cs4349_i2c_id,
387  	.probe		= cs4349_i2c_probe,
388  	.remove		= cs4349_i2c_remove,
389  };
390  
391  module_i2c_driver(cs4349_i2c_driver);
392  
393  MODULE_AUTHOR("Tim Howe <tim.howe@cirrus.com>");
394  MODULE_DESCRIPTION("Cirrus Logic CS4349 ALSA SoC Codec Driver");
395  MODULE_LICENSE("GPL");
396