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