Merge branches 'for-4.20/upstream-fixes', 'for-4.21/core', 'for-4.21/hid-asus', ...
[linux-2.6-block.git] / sound / soc / sunxi / sun8i-codec.c
1 /*
2  * This driver supports the digital controls for the internal codec
3  * found in Allwinner's A33 SoCs.
4  *
5  * (C) Copyright 2010-2016
6  * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>
7  * huangxin <huangxin@Reuuimllatech.com>
8  * Mylène Josserand <mylene.josserand@free-electrons.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  */
20
21 #include <linux/module.h>
22 #include <linux/delay.h>
23 #include <linux/clk.h>
24 #include <linux/io.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/regmap.h>
27 #include <linux/log2.h>
28
29 #include <sound/pcm_params.h>
30 #include <sound/soc.h>
31 #include <sound/soc-dapm.h>
32
33 #define SUN8I_SYSCLK_CTL                                0x00c
34 #define SUN8I_SYSCLK_CTL_AIF1CLK_ENA                    11
35 #define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL                9
36 #define SUN8I_SYSCLK_CTL_AIF1CLK_SRC                    8
37 #define SUN8I_SYSCLK_CTL_SYSCLK_ENA                     3
38 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC                     0
39 #define SUN8I_MOD_CLK_ENA                               0x010
40 #define SUN8I_MOD_CLK_ENA_AIF1                          15
41 #define SUN8I_MOD_CLK_ENA_ADC                           3
42 #define SUN8I_MOD_CLK_ENA_DAC                           2
43 #define SUN8I_MOD_RST_CTL                               0x014
44 #define SUN8I_MOD_RST_CTL_AIF1                          15
45 #define SUN8I_MOD_RST_CTL_ADC                           3
46 #define SUN8I_MOD_RST_CTL_DAC                           2
47 #define SUN8I_SYS_SR_CTRL                               0x018
48 #define SUN8I_SYS_SR_CTRL_AIF1_FS                       12
49 #define SUN8I_SYS_SR_CTRL_AIF2_FS                       8
50 #define SUN8I_AIF1CLK_CTRL                              0x040
51 #define SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD                15
52 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV                14
53 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV                13
54 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV                9
55 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV                6
56 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ                4
57 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16             (1 << 4)
58 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT                2
59 #define SUN8I_AIF1_ADCDAT_CTRL                          0x044
60 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_DA0L_ENA            15
61 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_DA0R_ENA            14
62 #define SUN8I_AIF1_DACDAT_CTRL                          0x048
63 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA            15
64 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA            14
65 #define SUN8I_AIF1_MXR_SRC                              0x04c
66 #define SUN8I_AIF1_MXR_SRC_AD0L_MXL_SRC_AIF1DA0L        15
67 #define SUN8I_AIF1_MXR_SRC_AD0L_MXL_SRC_AIF2DACL        14
68 #define SUN8I_AIF1_MXR_SRC_AD0L_MXL_SRC_ADCL            13
69 #define SUN8I_AIF1_MXR_SRC_AD0L_MXL_SRC_AIF2DACR        12
70 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R        11
71 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR        10
72 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR            9
73 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL        8
74 #define SUN8I_ADC_DIG_CTRL                              0x100
75 #define SUN8I_ADC_DIG_CTRL_ENDA                 15
76 #define SUN8I_ADC_DIG_CTRL_ADOUT_DTS                    2
77 #define SUN8I_ADC_DIG_CTRL_ADOUT_DLY                    1
78 #define SUN8I_DAC_DIG_CTRL                              0x120
79 #define SUN8I_DAC_DIG_CTRL_ENDA                 15
80 #define SUN8I_DAC_MXR_SRC                               0x130
81 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L 15
82 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L 14
83 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL 13
84 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL             12
85 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R 11
86 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R 10
87 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR 9
88 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR             8
89
90 #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK          GENMASK(15, 12)
91 #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK          GENMASK(11, 8)
92 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK   GENMASK(5, 4)
93 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK   GENMASK(8, 6)
94 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK   GENMASK(12, 9)
95
96 struct sun8i_codec {
97         struct device   *dev;
98         struct regmap   *regmap;
99         struct clk      *clk_module;
100         struct clk      *clk_bus;
101 };
102
103 static int sun8i_codec_runtime_resume(struct device *dev)
104 {
105         struct sun8i_codec *scodec = dev_get_drvdata(dev);
106         int ret;
107
108         ret = clk_prepare_enable(scodec->clk_module);
109         if (ret) {
110                 dev_err(dev, "Failed to enable the module clock\n");
111                 return ret;
112         }
113
114         ret = clk_prepare_enable(scodec->clk_bus);
115         if (ret) {
116                 dev_err(dev, "Failed to enable the bus clock\n");
117                 goto err_disable_modclk;
118         }
119
120         regcache_cache_only(scodec->regmap, false);
121
122         ret = regcache_sync(scodec->regmap);
123         if (ret) {
124                 dev_err(dev, "Failed to sync regmap cache\n");
125                 goto err_disable_clk;
126         }
127
128         return 0;
129
130 err_disable_clk:
131         clk_disable_unprepare(scodec->clk_bus);
132
133 err_disable_modclk:
134         clk_disable_unprepare(scodec->clk_module);
135
136         return ret;
137 }
138
139 static int sun8i_codec_runtime_suspend(struct device *dev)
140 {
141         struct sun8i_codec *scodec = dev_get_drvdata(dev);
142
143         regcache_cache_only(scodec->regmap, true);
144         regcache_mark_dirty(scodec->regmap);
145
146         clk_disable_unprepare(scodec->clk_module);
147         clk_disable_unprepare(scodec->clk_bus);
148
149         return 0;
150 }
151
152 static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params)
153 {
154         unsigned int rate = params_rate(params);
155
156         switch (rate) {
157         case 8000:
158         case 7350:
159                 return 0x0;
160         case 11025:
161                 return 0x1;
162         case 12000:
163                 return 0x2;
164         case 16000:
165                 return 0x3;
166         case 22050:
167                 return 0x4;
168         case 24000:
169                 return 0x5;
170         case 32000:
171                 return 0x6;
172         case 44100:
173                 return 0x7;
174         case 48000:
175                 return 0x8;
176         case 96000:
177                 return 0x9;
178         case 192000:
179                 return 0xa;
180         default:
181                 return -EINVAL;
182         }
183 }
184
185 static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
186 {
187         struct sun8i_codec *scodec = snd_soc_component_get_drvdata(dai->component);
188         u32 value;
189
190         /* clock masters */
191         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
192         case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */
193                 value = 0x1;
194                 break;
195         case SND_SOC_DAIFMT_CBM_CFM: /* Codec Master, DAI slave */
196                 value = 0x0;
197                 break;
198         default:
199                 return -EINVAL;
200         }
201         regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
202                            BIT(SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD),
203                            value << SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD);
204
205         /* clock inversion */
206         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
207         case SND_SOC_DAIFMT_NB_NF: /* Normal */
208                 value = 0x0;
209                 break;
210         case SND_SOC_DAIFMT_IB_IF: /* Inversion */
211                 value = 0x1;
212                 break;
213         default:
214                 return -EINVAL;
215         }
216         regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
217                            BIT(SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV),
218                            value << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV);
219
220         /*
221          * It appears that the DAI and the codec don't share the same
222          * polarity for the LRCK signal when they mean 'normal' and
223          * 'inverted' in the datasheet.
224          *
225          * Since the DAI here is our regular i2s driver that have been
226          * tested with way more codecs than just this one, it means
227          * that the codec probably gets it backward, and we have to
228          * invert the value here.
229          */
230         regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
231                            BIT(SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV),
232                            !value << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV);
233
234         /* DAI format */
235         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
236         case SND_SOC_DAIFMT_I2S:
237                 value = 0x0;
238                 break;
239         case SND_SOC_DAIFMT_LEFT_J:
240                 value = 0x1;
241                 break;
242         case SND_SOC_DAIFMT_RIGHT_J:
243                 value = 0x2;
244                 break;
245         case SND_SOC_DAIFMT_DSP_A:
246         case SND_SOC_DAIFMT_DSP_B:
247                 value = 0x3;
248                 break;
249         default:
250                 return -EINVAL;
251         }
252         regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
253                            BIT(SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT),
254                            value << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT);
255
256         return 0;
257 }
258
259 struct sun8i_codec_clk_div {
260         u8      div;
261         u8      val;
262 };
263
264 static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = {
265         { .div = 1,     .val = 0 },
266         { .div = 2,     .val = 1 },
267         { .div = 4,     .val = 2 },
268         { .div = 6,     .val = 3 },
269         { .div = 8,     .val = 4 },
270         { .div = 12,    .val = 5 },
271         { .div = 16,    .val = 6 },
272         { .div = 24,    .val = 7 },
273         { .div = 32,    .val = 8 },
274         { .div = 48,    .val = 9 },
275         { .div = 64,    .val = 10 },
276         { .div = 96,    .val = 11 },
277         { .div = 128,   .val = 12 },
278         { .div = 192,   .val = 13 },
279 };
280
281 static u8 sun8i_codec_get_bclk_div(struct sun8i_codec *scodec,
282                                    unsigned int rate,
283                                    unsigned int word_size)
284 {
285         unsigned long clk_rate = clk_get_rate(scodec->clk_module);
286         unsigned int div = clk_rate / rate / word_size / 2;
287         unsigned int best_val = 0, best_diff = ~0;
288         int i;
289
290         for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) {
291                 const struct sun8i_codec_clk_div *bdiv = &sun8i_codec_bclk_div[i];
292                 unsigned int diff = abs(bdiv->div - div);
293
294                 if (diff < best_diff) {
295                         best_diff = diff;
296                         best_val = bdiv->val;
297                 }
298         }
299
300         return best_val;
301 }
302
303 static int sun8i_codec_get_lrck_div(unsigned int channels,
304                                     unsigned int word_size)
305 {
306         unsigned int div = word_size * channels;
307
308         if (div < 16 || div > 256)
309                 return -EINVAL;
310
311         return ilog2(div) - 4;
312 }
313
314 static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
315                                  struct snd_pcm_hw_params *params,
316                                  struct snd_soc_dai *dai)
317 {
318         struct sun8i_codec *scodec = snd_soc_component_get_drvdata(dai->component);
319         int sample_rate, lrck_div;
320         u8 bclk_div;
321
322         /*
323          * The CPU DAI handles only a sample of 16 bits. Configure the
324          * codec to handle this type of sample resolution.
325          */
326         regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
327                            SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK,
328                            SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16);
329
330         bclk_div = sun8i_codec_get_bclk_div(scodec, params_rate(params), 16);
331         regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
332                            SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK,
333                            bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV);
334
335         lrck_div = sun8i_codec_get_lrck_div(params_channels(params),
336                                             params_physical_width(params));
337         if (lrck_div < 0)
338                 return lrck_div;
339
340         regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
341                            SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK,
342                            lrck_div << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV);
343
344         sample_rate = sun8i_codec_get_hw_rate(params);
345         if (sample_rate < 0)
346                 return sample_rate;
347
348         regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
349                            SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
350                            sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
351         regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
352                            SUN8I_SYS_SR_CTRL_AIF2_FS_MASK,
353                            sample_rate << SUN8I_SYS_SR_CTRL_AIF2_FS);
354
355         return 0;
356 }
357
358 static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = {
359         SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch",
360                         SUN8I_DAC_MXR_SRC,
361                         SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L,
362                         SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R, 1, 0),
363         SOC_DAPM_DOUBLE("AIF1 Slot 1 Digital DAC Playback Switch",
364                         SUN8I_DAC_MXR_SRC,
365                         SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L,
366                         SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R, 1, 0),
367         SOC_DAPM_DOUBLE("AIF2 Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
368                         SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL,
369                         SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR, 1, 0),
370         SOC_DAPM_DOUBLE("ADC Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
371                         SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL,
372                         SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR, 1, 0),
373 };
374
375 static const struct snd_kcontrol_new sun8i_input_mixer_controls[] = {
376         SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch",
377                         SUN8I_AIF1_MXR_SRC,
378                         SUN8I_AIF1_MXR_SRC_AD0L_MXL_SRC_AIF1DA0L,
379                         SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R, 1, 0),
380         SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch", SUN8I_AIF1_MXR_SRC,
381                         SUN8I_AIF1_MXR_SRC_AD0L_MXL_SRC_AIF2DACL,
382                         SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR, 1, 0),
383         SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch",
384                         SUN8I_AIF1_MXR_SRC,
385                         SUN8I_AIF1_MXR_SRC_AD0L_MXL_SRC_ADCL,
386                         SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0),
387         SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",
388                         SUN8I_AIF1_MXR_SRC,
389                         SUN8I_AIF1_MXR_SRC_AD0L_MXL_SRC_AIF2DACR,
390                         SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL, 1, 0),
391 };
392
393 static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = {
394         /* Digital parts of the DACs and ADC */
395         SND_SOC_DAPM_SUPPLY("DAC", SUN8I_DAC_DIG_CTRL, SUN8I_DAC_DIG_CTRL_ENDA,
396                             0, NULL, 0),
397         SND_SOC_DAPM_SUPPLY("ADC", SUN8I_ADC_DIG_CTRL, SUN8I_ADC_DIG_CTRL_ENDA,
398                             0, NULL, 0),
399
400         /* Analog DAC AIF */
401         SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Left", "Playback", 0,
402                             SUN8I_AIF1_DACDAT_CTRL,
403                             SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0),
404         SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Right", "Playback", 0,
405                             SUN8I_AIF1_DACDAT_CTRL,
406                             SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0),
407
408         /* Analog ADC AIF */
409         SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Left ADC", "Capture", 0,
410                             SUN8I_AIF1_ADCDAT_CTRL,
411                             SUN8I_AIF1_ADCDAT_CTRL_AIF1_DA0L_ENA, 0),
412         SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Right ADC", "Capture", 0,
413                             SUN8I_AIF1_ADCDAT_CTRL,
414                             SUN8I_AIF1_ADCDAT_CTRL_AIF1_DA0R_ENA, 0),
415
416         /* DAC and ADC Mixers */
417         SOC_MIXER_ARRAY("Left Digital DAC Mixer", SND_SOC_NOPM, 0, 0,
418                         sun8i_dac_mixer_controls),
419         SOC_MIXER_ARRAY("Right Digital DAC Mixer", SND_SOC_NOPM, 0, 0,
420                         sun8i_dac_mixer_controls),
421         SOC_MIXER_ARRAY("Left Digital ADC Mixer", SND_SOC_NOPM, 0, 0,
422                         sun8i_input_mixer_controls),
423         SOC_MIXER_ARRAY("Right Digital ADC Mixer", SND_SOC_NOPM, 0, 0,
424                         sun8i_input_mixer_controls),
425
426         /* Clocks */
427         SND_SOC_DAPM_SUPPLY("MODCLK AFI1", SUN8I_MOD_CLK_ENA,
428                             SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0),
429         SND_SOC_DAPM_SUPPLY("MODCLK DAC", SUN8I_MOD_CLK_ENA,
430                             SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0),
431         SND_SOC_DAPM_SUPPLY("MODCLK ADC", SUN8I_MOD_CLK_ENA,
432                             SUN8I_MOD_CLK_ENA_ADC, 0, NULL, 0),
433         SND_SOC_DAPM_SUPPLY("AIF1", SUN8I_SYSCLK_CTL,
434                             SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0),
435         SND_SOC_DAPM_SUPPLY("SYSCLK", SUN8I_SYSCLK_CTL,
436                             SUN8I_SYSCLK_CTL_SYSCLK_ENA, 0, NULL, 0),
437
438         SND_SOC_DAPM_SUPPLY("AIF1 PLL", SUN8I_SYSCLK_CTL,
439                             SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL, 0, NULL, 0),
440         /* Inversion as 0=AIF1, 1=AIF2 */
441         SND_SOC_DAPM_SUPPLY("SYSCLK AIF1", SUN8I_SYSCLK_CTL,
442                             SUN8I_SYSCLK_CTL_SYSCLK_SRC, 1, NULL, 0),
443
444         /* Module reset */
445         SND_SOC_DAPM_SUPPLY("RST AIF1", SUN8I_MOD_RST_CTL,
446                             SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0),
447         SND_SOC_DAPM_SUPPLY("RST DAC", SUN8I_MOD_RST_CTL,
448                             SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0),
449         SND_SOC_DAPM_SUPPLY("RST ADC", SUN8I_MOD_RST_CTL,
450                             SUN8I_MOD_RST_CTL_ADC, 0, NULL, 0),
451
452         SND_SOC_DAPM_MIC("Headset Mic", NULL),
453         SND_SOC_DAPM_MIC("Mic", NULL),
454
455 };
456
457 static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = {
458         /* Clock Routes */
459         { "AIF1", NULL, "SYSCLK AIF1" },
460         { "AIF1 PLL", NULL, "AIF1" },
461         { "RST AIF1", NULL, "AIF1 PLL" },
462         { "MODCLK AFI1", NULL, "RST AIF1" },
463         { "DAC", NULL, "MODCLK AFI1" },
464         { "ADC", NULL, "MODCLK AFI1" },
465
466         { "RST DAC", NULL, "SYSCLK" },
467         { "MODCLK DAC", NULL, "RST DAC" },
468         { "DAC", NULL, "MODCLK DAC" },
469
470         { "RST ADC", NULL, "SYSCLK" },
471         { "MODCLK ADC", NULL, "RST ADC" },
472         { "ADC", NULL, "MODCLK ADC" },
473
474         /* DAC Routes */
475         { "AIF1 Slot 0 Right", NULL, "DAC" },
476         { "AIF1 Slot 0 Left", NULL, "DAC" },
477
478         /* DAC Mixer Routes */
479         { "Left Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch",
480           "AIF1 Slot 0 Left"},
481         { "Right Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch",
482           "AIF1 Slot 0 Right"},
483
484         /* ADC Routes */
485         { "AIF1 Slot 0 Right ADC", NULL, "ADC" },
486         { "AIF1 Slot 0 Left ADC", NULL, "ADC" },
487
488         /* ADC Mixer Routes */
489         { "Left Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch",
490           "AIF1 Slot 0 Left ADC" },
491         { "Right Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch",
492           "AIF1 Slot 0 Right ADC" },
493 };
494
495 static const struct snd_soc_dai_ops sun8i_codec_dai_ops = {
496         .hw_params = sun8i_codec_hw_params,
497         .set_fmt = sun8i_set_fmt,
498 };
499
500 static struct snd_soc_dai_driver sun8i_codec_dai = {
501         .name = "sun8i",
502         /* playback capabilities */
503         .playback = {
504                 .stream_name = "Playback",
505                 .channels_min = 1,
506                 .channels_max = 2,
507                 .rates = SNDRV_PCM_RATE_8000_192000,
508                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
509         },
510         /* capture capabilities */
511         .capture = {
512                 .stream_name = "Capture",
513                 .channels_min = 1,
514                 .channels_max = 2,
515                 .rates = SNDRV_PCM_RATE_8000_192000,
516                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
517                 .sig_bits = 24,
518         },
519         /* pcm operations */
520         .ops = &sun8i_codec_dai_ops,
521 };
522
523 static const struct snd_soc_component_driver sun8i_soc_component = {
524         .dapm_widgets           = sun8i_codec_dapm_widgets,
525         .num_dapm_widgets       = ARRAY_SIZE(sun8i_codec_dapm_widgets),
526         .dapm_routes            = sun8i_codec_dapm_routes,
527         .num_dapm_routes        = ARRAY_SIZE(sun8i_codec_dapm_routes),
528         .idle_bias_on           = 1,
529         .use_pmdown_time        = 1,
530         .endianness             = 1,
531         .non_legacy_dai_naming  = 1,
532 };
533
534 static const struct regmap_config sun8i_codec_regmap_config = {
535         .reg_bits       = 32,
536         .reg_stride     = 4,
537         .val_bits       = 32,
538         .max_register   = SUN8I_DAC_MXR_SRC,
539
540         .cache_type     = REGCACHE_FLAT,
541 };
542
543 static int sun8i_codec_probe(struct platform_device *pdev)
544 {
545         struct resource *res_base;
546         struct sun8i_codec *scodec;
547         void __iomem *base;
548         int ret;
549
550         scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);
551         if (!scodec)
552                 return -ENOMEM;
553
554         scodec->dev = &pdev->dev;
555
556         scodec->clk_module = devm_clk_get(&pdev->dev, "mod");
557         if (IS_ERR(scodec->clk_module)) {
558                 dev_err(&pdev->dev, "Failed to get the module clock\n");
559                 return PTR_ERR(scodec->clk_module);
560         }
561
562         scodec->clk_bus = devm_clk_get(&pdev->dev, "bus");
563         if (IS_ERR(scodec->clk_bus)) {
564                 dev_err(&pdev->dev, "Failed to get the bus clock\n");
565                 return PTR_ERR(scodec->clk_bus);
566         }
567
568         res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
569         base = devm_ioremap_resource(&pdev->dev, res_base);
570         if (IS_ERR(base)) {
571                 dev_err(&pdev->dev, "Failed to map the registers\n");
572                 return PTR_ERR(base);
573         }
574
575         scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
576                                                &sun8i_codec_regmap_config);
577         if (IS_ERR(scodec->regmap)) {
578                 dev_err(&pdev->dev, "Failed to create our regmap\n");
579                 return PTR_ERR(scodec->regmap);
580         }
581
582         platform_set_drvdata(pdev, scodec);
583
584         pm_runtime_enable(&pdev->dev);
585         if (!pm_runtime_enabled(&pdev->dev)) {
586                 ret = sun8i_codec_runtime_resume(&pdev->dev);
587                 if (ret)
588                         goto err_pm_disable;
589         }
590
591         ret = devm_snd_soc_register_component(&pdev->dev, &sun8i_soc_component,
592                                      &sun8i_codec_dai, 1);
593         if (ret) {
594                 dev_err(&pdev->dev, "Failed to register codec\n");
595                 goto err_suspend;
596         }
597
598         return ret;
599
600 err_suspend:
601         if (!pm_runtime_status_suspended(&pdev->dev))
602                 sun8i_codec_runtime_suspend(&pdev->dev);
603
604 err_pm_disable:
605         pm_runtime_disable(&pdev->dev);
606
607         return ret;
608 }
609
610 static int sun8i_codec_remove(struct platform_device *pdev)
611 {
612         pm_runtime_disable(&pdev->dev);
613         if (!pm_runtime_status_suspended(&pdev->dev))
614                 sun8i_codec_runtime_suspend(&pdev->dev);
615
616         return 0;
617 }
618
619 static const struct of_device_id sun8i_codec_of_match[] = {
620         { .compatible = "allwinner,sun8i-a33-codec" },
621         {}
622 };
623 MODULE_DEVICE_TABLE(of, sun8i_codec_of_match);
624
625 static const struct dev_pm_ops sun8i_codec_pm_ops = {
626         SET_RUNTIME_PM_OPS(sun8i_codec_runtime_suspend,
627                            sun8i_codec_runtime_resume, NULL)
628 };
629
630 static struct platform_driver sun8i_codec_driver = {
631         .driver = {
632                 .name = "sun8i-codec",
633                 .of_match_table = sun8i_codec_of_match,
634                 .pm = &sun8i_codec_pm_ops,
635         },
636         .probe = sun8i_codec_probe,
637         .remove = sun8i_codec_remove,
638 };
639 module_platform_driver(sun8i_codec_driver);
640
641 MODULE_DESCRIPTION("Allwinner A33 (sun8i) codec driver");
642 MODULE_AUTHOR("Mylène Josserand <mylene.josserand@free-electrons.com>");
643 MODULE_LICENSE("GPL");
644 MODULE_ALIAS("platform:sun8i-codec");