]> git.karo-electronics.de Git - karo-tx-linux.git/blob - sound/soc/codecs/ad193x.c
Merge tag 'gvt-fixes-2017-03-23' of https://github.com/01org/gvt-linux into drm-intel...
[karo-tx-linux.git] / sound / soc / codecs / ad193x.c
1 /*
2  * AD193X Audio Codec driver supporting AD1936/7/8/9
3  *
4  * Copyright 2010 Analog Devices Inc.
5  *
6  * Licensed under the GPL-2 or later.
7  */
8
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/device.h>
12 #include <linux/regmap.h>
13 #include <linux/slab.h>
14 #include <sound/core.h>
15 #include <sound/pcm.h>
16 #include <sound/pcm_params.h>
17 #include <sound/initval.h>
18 #include <sound/soc.h>
19 #include <sound/tlv.h>
20
21 #include "ad193x.h"
22
23 /* codec private data */
24 struct ad193x_priv {
25         struct regmap *regmap;
26         enum ad193x_type type;
27         int sysclk;
28 };
29
30 /*
31  * AD193X volume/mute/de-emphasis etc. controls
32  */
33 static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
34
35 static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1,
36                             ad193x_deemp);
37
38 static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0);
39
40 static const struct snd_kcontrol_new ad193x_snd_controls[] = {
41         /* DAC volume control */
42         SOC_DOUBLE_R_TLV("DAC1 Volume", AD193X_DAC_L1_VOL,
43                         AD193X_DAC_R1_VOL, 0, 0xFF, 1, adau193x_tlv),
44         SOC_DOUBLE_R_TLV("DAC2 Volume", AD193X_DAC_L2_VOL,
45                         AD193X_DAC_R2_VOL, 0, 0xFF, 1, adau193x_tlv),
46         SOC_DOUBLE_R_TLV("DAC3 Volume", AD193X_DAC_L3_VOL,
47                         AD193X_DAC_R3_VOL, 0, 0xFF, 1, adau193x_tlv),
48         SOC_DOUBLE_R_TLV("DAC4 Volume", AD193X_DAC_L4_VOL,
49                         AD193X_DAC_R4_VOL, 0, 0xFF, 1, adau193x_tlv),
50
51         /* DAC switch control */
52         SOC_DOUBLE("DAC1 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL1_MUTE,
53                 AD193X_DACR1_MUTE, 1, 1),
54         SOC_DOUBLE("DAC2 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL2_MUTE,
55                 AD193X_DACR2_MUTE, 1, 1),
56         SOC_DOUBLE("DAC3 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL3_MUTE,
57                 AD193X_DACR3_MUTE, 1, 1),
58         SOC_DOUBLE("DAC4 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL4_MUTE,
59                 AD193X_DACR4_MUTE, 1, 1),
60
61         /* DAC de-emphasis */
62         SOC_ENUM("Playback Deemphasis", ad193x_deemp_enum),
63 };
64
65 static const struct snd_kcontrol_new ad193x_adc_snd_controls[] = {
66         /* ADC switch control */
67         SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE,
68                 AD193X_ADCR1_MUTE, 1, 1),
69         SOC_DOUBLE("ADC2 Switch", AD193X_ADC_CTRL0, AD193X_ADCL2_MUTE,
70                 AD193X_ADCR2_MUTE, 1, 1),
71
72         /* ADC high-pass filter */
73         SOC_SINGLE("ADC High Pass Filter Switch", AD193X_ADC_CTRL0,
74                         AD193X_ADC_HIGHPASS_FILTER, 1, 0),
75 };
76
77 static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = {
78         SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
79         SND_SOC_DAPM_PGA("DAC Output", AD193X_DAC_CTRL0, 0, 1, NULL, 0),
80         SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0),
81         SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0),
82         SND_SOC_DAPM_VMID("VMID"),
83         SND_SOC_DAPM_OUTPUT("DAC1OUT"),
84         SND_SOC_DAPM_OUTPUT("DAC2OUT"),
85         SND_SOC_DAPM_OUTPUT("DAC3OUT"),
86         SND_SOC_DAPM_OUTPUT("DAC4OUT"),
87 };
88
89 static const struct snd_soc_dapm_widget ad193x_adc_widgets[] = {
90         SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
91         SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0),
92         SND_SOC_DAPM_INPUT("ADC1IN"),
93         SND_SOC_DAPM_INPUT("ADC2IN"),
94 };
95
96 static const struct snd_soc_dapm_route audio_paths[] = {
97         { "DAC", NULL, "SYSCLK" },
98         { "DAC Output", NULL, "DAC" },
99         { "DAC Output", NULL, "VMID" },
100         { "DAC1OUT", NULL, "DAC Output" },
101         { "DAC2OUT", NULL, "DAC Output" },
102         { "DAC3OUT", NULL, "DAC Output" },
103         { "DAC4OUT", NULL, "DAC Output" },
104         { "SYSCLK", NULL, "PLL_PWR" },
105 };
106
107 static const struct snd_soc_dapm_route ad193x_adc_audio_paths[] = {
108         { "ADC", NULL, "SYSCLK" },
109         { "ADC", NULL, "ADC_PWR" },
110         { "ADC", NULL, "ADC1IN" },
111         { "ADC", NULL, "ADC2IN" },
112 };
113
114 static inline bool ad193x_has_adc(const struct ad193x_priv *ad193x)
115 {
116         switch (ad193x->type) {
117         case AD1933:
118         case AD1934:
119                 return false;
120         default:
121                 break;
122         }
123
124         return true;
125 }
126
127 /*
128  * DAI ops entries
129  */
130
131 static int ad193x_mute(struct snd_soc_dai *dai, int mute)
132 {
133         struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(dai->codec);
134
135         if (mute)
136                 regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2,
137                                     AD193X_DAC_MASTER_MUTE,
138                                     AD193X_DAC_MASTER_MUTE);
139         else
140                 regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2,
141                                     AD193X_DAC_MASTER_MUTE, 0);
142
143         return 0;
144 }
145
146 static int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
147                                unsigned int rx_mask, int slots, int width)
148 {
149         struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(dai->codec);
150         unsigned int channels;
151
152         switch (slots) {
153         case 2:
154                 channels = AD193X_2_CHANNELS;
155                 break;
156         case 4:
157                 channels = AD193X_4_CHANNELS;
158                 break;
159         case 8:
160                 channels = AD193X_8_CHANNELS;
161                 break;
162         case 16:
163                 channels = AD193X_16_CHANNELS;
164                 break;
165         default:
166                 return -EINVAL;
167         }
168
169         regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1,
170                 AD193X_DAC_CHAN_MASK, channels << AD193X_DAC_CHAN_SHFT);
171         if (ad193x_has_adc(ad193x))
172                 regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2,
173                                    AD193X_ADC_CHAN_MASK,
174                                    channels << AD193X_ADC_CHAN_SHFT);
175
176         return 0;
177 }
178
179 static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
180                 unsigned int fmt)
181 {
182         struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec_dai->codec);
183         unsigned int adc_serfmt = 0;
184         unsigned int adc_fmt = 0;
185         unsigned int dac_fmt = 0;
186
187         /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
188          * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
189          */
190         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
191         case SND_SOC_DAIFMT_I2S:
192                 adc_serfmt |= AD193X_ADC_SERFMT_TDM;
193                 break;
194         case SND_SOC_DAIFMT_DSP_A:
195                 adc_serfmt |= AD193X_ADC_SERFMT_AUX;
196                 break;
197         default:
198                 if (ad193x_has_adc(ad193x))
199                         return -EINVAL;
200                 break;
201         }
202
203         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
204         case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
205                 break;
206         case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
207                 adc_fmt |= AD193X_ADC_LEFT_HIGH;
208                 dac_fmt |= AD193X_DAC_LEFT_HIGH;
209                 break;
210         case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
211                 adc_fmt |= AD193X_ADC_BCLK_INV;
212                 dac_fmt |= AD193X_DAC_BCLK_INV;
213                 break;
214         case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
215                 adc_fmt |= AD193X_ADC_LEFT_HIGH;
216                 adc_fmt |= AD193X_ADC_BCLK_INV;
217                 dac_fmt |= AD193X_DAC_LEFT_HIGH;
218                 dac_fmt |= AD193X_DAC_BCLK_INV;
219                 break;
220         default:
221                 return -EINVAL;
222         }
223
224         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
225         case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
226                 adc_fmt |= AD193X_ADC_LCR_MASTER;
227                 adc_fmt |= AD193X_ADC_BCLK_MASTER;
228                 dac_fmt |= AD193X_DAC_LCR_MASTER;
229                 dac_fmt |= AD193X_DAC_BCLK_MASTER;
230                 break;
231         case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
232                 adc_fmt |= AD193X_ADC_LCR_MASTER;
233                 dac_fmt |= AD193X_DAC_LCR_MASTER;
234                 break;
235         case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
236                 adc_fmt |= AD193X_ADC_BCLK_MASTER;
237                 dac_fmt |= AD193X_DAC_BCLK_MASTER;
238                 break;
239         case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */
240                 break;
241         default:
242                 return -EINVAL;
243         }
244
245         if (ad193x_has_adc(ad193x)) {
246                 regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1,
247                                    AD193X_ADC_SERFMT_MASK, adc_serfmt);
248                 regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2,
249                                    AD193X_ADC_FMT_MASK, adc_fmt);
250         }
251         regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1,
252                 AD193X_DAC_FMT_MASK, dac_fmt);
253
254         return 0;
255 }
256
257 static int ad193x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
258                 int clk_id, unsigned int freq, int dir)
259 {
260         struct snd_soc_codec *codec = codec_dai->codec;
261         struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
262         switch (freq) {
263         case 12288000:
264         case 18432000:
265         case 24576000:
266         case 36864000:
267                 ad193x->sysclk = freq;
268                 return 0;
269         }
270         return -EINVAL;
271 }
272
273 static int ad193x_hw_params(struct snd_pcm_substream *substream,
274                 struct snd_pcm_hw_params *params,
275                 struct snd_soc_dai *dai)
276 {
277         int word_len = 0, master_rate = 0;
278         struct snd_soc_codec *codec = dai->codec;
279         struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
280
281         /* bit size */
282         switch (params_width(params)) {
283         case 16:
284                 word_len = 3;
285                 break;
286         case 20:
287                 word_len = 1;
288                 break;
289         case 24:
290         case 32:
291                 word_len = 0;
292                 break;
293         }
294
295         switch (ad193x->sysclk) {
296         case 12288000:
297                 master_rate = AD193X_PLL_INPUT_256;
298                 break;
299         case 18432000:
300                 master_rate = AD193X_PLL_INPUT_384;
301                 break;
302         case 24576000:
303                 master_rate = AD193X_PLL_INPUT_512;
304                 break;
305         case 36864000:
306                 master_rate = AD193X_PLL_INPUT_768;
307                 break;
308         }
309
310         regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL0,
311                             AD193X_PLL_INPUT_MASK, master_rate);
312
313         regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2,
314                             AD193X_DAC_WORD_LEN_MASK,
315                             word_len << AD193X_DAC_WORD_LEN_SHFT);
316
317         if (ad193x_has_adc(ad193x))
318                 regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1,
319                                    AD193X_ADC_WORD_LEN_MASK, word_len);
320
321         return 0;
322 }
323
324 static const struct snd_soc_dai_ops ad193x_dai_ops = {
325         .hw_params = ad193x_hw_params,
326         .digital_mute = ad193x_mute,
327         .set_tdm_slot = ad193x_set_tdm_slot,
328         .set_sysclk     = ad193x_set_dai_sysclk,
329         .set_fmt = ad193x_set_dai_fmt,
330 };
331
332 /* codec DAI instance */
333 static struct snd_soc_dai_driver ad193x_dai = {
334         .name = "ad193x-hifi",
335         .playback = {
336                 .stream_name = "Playback",
337                 .channels_min = 2,
338                 .channels_max = 8,
339                 .rates = SNDRV_PCM_RATE_48000,
340                 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
341                         SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
342         },
343         .capture = {
344                 .stream_name = "Capture",
345                 .channels_min = 2,
346                 .channels_max = 4,
347                 .rates = SNDRV_PCM_RATE_48000,
348                 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
349                         SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
350         },
351         .ops = &ad193x_dai_ops,
352 };
353
354 static int ad193x_codec_probe(struct snd_soc_codec *codec)
355 {
356         struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
357         struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
358         int num, ret;
359
360         /* default setting for ad193x */
361
362         /* unmute dac channels */
363         regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0);
364         /* de-emphasis: 48kHz, powedown dac */
365         regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A);
366         /* dac in tdm mode */
367         regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x40);
368
369         /* adc only */
370         if (ad193x_has_adc(ad193x)) {
371                 /* high-pass filter enable */
372                 regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3);
373                 /* sata delay=1, adc aux mode */
374                 regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43);
375         }
376
377         /* pll input: mclki/xi */
378         regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
379         regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04);
380
381         /* adc only */
382         if (ad193x_has_adc(ad193x)) {
383                 /* add adc controls */
384                 num = ARRAY_SIZE(ad193x_adc_snd_controls);
385                 ret = snd_soc_add_codec_controls(codec,
386                                                  ad193x_adc_snd_controls,
387                                                  num);
388                 if (ret)
389                         return ret;
390
391                 /* add adc widgets */
392                 num = ARRAY_SIZE(ad193x_adc_widgets);
393                 ret = snd_soc_dapm_new_controls(dapm,
394                                                 ad193x_adc_widgets,
395                                                 num);
396                 if (ret)
397                         return ret;
398
399                 /* add adc routes */
400                 num = ARRAY_SIZE(ad193x_adc_audio_paths);
401                 ret = snd_soc_dapm_add_routes(dapm,
402                                               ad193x_adc_audio_paths,
403                                               num);
404                 if (ret)
405                         return ret;
406         }
407
408         return 0;
409 }
410
411 static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
412         .probe = ad193x_codec_probe,
413         .component_driver = {
414                 .controls               = ad193x_snd_controls,
415                 .num_controls           = ARRAY_SIZE(ad193x_snd_controls),
416                 .dapm_widgets           = ad193x_dapm_widgets,
417                 .num_dapm_widgets       = ARRAY_SIZE(ad193x_dapm_widgets),
418                 .dapm_routes            = audio_paths,
419                 .num_dapm_routes        = ARRAY_SIZE(audio_paths),
420         },
421 };
422
423 const struct regmap_config ad193x_regmap_config = {
424         .max_register = AD193X_NUM_REGS - 1,
425 };
426 EXPORT_SYMBOL_GPL(ad193x_regmap_config);
427
428 int ad193x_probe(struct device *dev, struct regmap *regmap,
429                  enum ad193x_type type)
430 {
431         struct ad193x_priv *ad193x;
432
433         if (IS_ERR(regmap))
434                 return PTR_ERR(regmap);
435
436         ad193x = devm_kzalloc(dev, sizeof(*ad193x), GFP_KERNEL);
437         if (ad193x == NULL)
438                 return -ENOMEM;
439
440         ad193x->regmap = regmap;
441         ad193x->type = type;
442
443         dev_set_drvdata(dev, ad193x);
444
445         return snd_soc_register_codec(dev, &soc_codec_dev_ad193x,
446                 &ad193x_dai, 1);
447 }
448 EXPORT_SYMBOL_GPL(ad193x_probe);
449
450 MODULE_DESCRIPTION("ASoC ad193x driver");
451 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
452 MODULE_LICENSE("GPL");