ASoC: wm8776: replace codec to component
[linux-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
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_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_codec_get_drvdata(dai->codec);
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_hw_params(struct snd_pcm_substream *substream,
304                                  struct snd_pcm_hw_params *params,
305                                  struct snd_soc_dai *dai)
306 {
307         struct sun8i_codec *scodec = snd_soc_codec_get_drvdata(dai->codec);
308         int sample_rate;
309         u8 bclk_div;
310
311         /*
312          * The CPU DAI handles only a sample of 16 bits. Configure the
313          * codec to handle this type of sample resolution.
314          */
315         regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
316                            SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK,
317                            SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16);
318
319         bclk_div = sun8i_codec_get_bclk_div(scodec, params_rate(params), 16);
320         regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
321                            SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK,
322                            bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV);
323
324         regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
325                            SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK,
326                            SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_16);
327
328         sample_rate = sun8i_codec_get_hw_rate(params);
329         if (sample_rate < 0)
330                 return sample_rate;
331
332         regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
333                            SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
334                            sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
335         regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
336                            SUN8I_SYS_SR_CTRL_AIF2_FS_MASK,
337                            sample_rate << SUN8I_SYS_SR_CTRL_AIF2_FS);
338
339         return 0;
340 }
341
342 static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = {
343         SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch",
344                         SUN8I_DAC_MXR_SRC,
345                         SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L,
346                         SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R, 1, 0),
347         SOC_DAPM_DOUBLE("AIF1 Slot 1 Digital DAC Playback Switch",
348                         SUN8I_DAC_MXR_SRC,
349                         SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L,
350                         SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R, 1, 0),
351         SOC_DAPM_DOUBLE("AIF2 Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
352                         SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL,
353                         SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR, 1, 0),
354         SOC_DAPM_DOUBLE("ADC Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
355                         SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL,
356                         SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR, 1, 0),
357 };
358
359 static const struct snd_kcontrol_new sun8i_input_mixer_controls[] = {
360         SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch",
361                         SUN8I_AIF1_MXR_SRC,
362                         SUN8I_AIF1_MXR_SRC_AD0L_MXL_SRC_AIF1DA0L,
363                         SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R, 1, 0),
364         SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch", SUN8I_AIF1_MXR_SRC,
365                         SUN8I_AIF1_MXR_SRC_AD0L_MXL_SRC_AIF2DACL,
366                         SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR, 1, 0),
367         SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch",
368                         SUN8I_AIF1_MXR_SRC,
369                         SUN8I_AIF1_MXR_SRC_AD0L_MXL_SRC_ADCL,
370                         SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0),
371         SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",
372                         SUN8I_AIF1_MXR_SRC,
373                         SUN8I_AIF1_MXR_SRC_AD0L_MXL_SRC_AIF2DACR,
374                         SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL, 1, 0),
375 };
376
377 static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = {
378         /* Digital parts of the DACs and ADC */
379         SND_SOC_DAPM_SUPPLY("DAC", SUN8I_DAC_DIG_CTRL, SUN8I_DAC_DIG_CTRL_ENDA,
380                             0, NULL, 0),
381         SND_SOC_DAPM_SUPPLY("ADC", SUN8I_ADC_DIG_CTRL, SUN8I_ADC_DIG_CTRL_ENDA,
382                             0, NULL, 0),
383
384         /* Analog DAC AIF */
385         SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Left", "Playback", 0,
386                             SUN8I_AIF1_DACDAT_CTRL,
387                             SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0),
388         SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Right", "Playback", 0,
389                             SUN8I_AIF1_DACDAT_CTRL,
390                             SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0),
391
392         /* Analog ADC AIF */
393         SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Left ADC", "Capture", 0,
394                             SUN8I_AIF1_ADCDAT_CTRL,
395                             SUN8I_AIF1_ADCDAT_CTRL_AIF1_DA0L_ENA, 0),
396         SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Right ADC", "Capture", 0,
397                             SUN8I_AIF1_ADCDAT_CTRL,
398                             SUN8I_AIF1_ADCDAT_CTRL_AIF1_DA0R_ENA, 0),
399
400         /* DAC and ADC Mixers */
401         SOC_MIXER_ARRAY("Left Digital DAC Mixer", SND_SOC_NOPM, 0, 0,
402                         sun8i_dac_mixer_controls),
403         SOC_MIXER_ARRAY("Right Digital DAC Mixer", SND_SOC_NOPM, 0, 0,
404                         sun8i_dac_mixer_controls),
405         SOC_MIXER_ARRAY("Left Digital ADC Mixer", SND_SOC_NOPM, 0, 0,
406                         sun8i_input_mixer_controls),
407         SOC_MIXER_ARRAY("Right Digital ADC Mixer", SND_SOC_NOPM, 0, 0,
408                         sun8i_input_mixer_controls),
409
410         /* Clocks */
411         SND_SOC_DAPM_SUPPLY("MODCLK AFI1", SUN8I_MOD_CLK_ENA,
412                             SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0),
413         SND_SOC_DAPM_SUPPLY("MODCLK DAC", SUN8I_MOD_CLK_ENA,
414                             SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0),
415         SND_SOC_DAPM_SUPPLY("MODCLK ADC", SUN8I_MOD_CLK_ENA,
416                             SUN8I_MOD_CLK_ENA_ADC, 0, NULL, 0),
417         SND_SOC_DAPM_SUPPLY("AIF1", SUN8I_SYSCLK_CTL,
418                             SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0),
419         SND_SOC_DAPM_SUPPLY("SYSCLK", SUN8I_SYSCLK_CTL,
420                             SUN8I_SYSCLK_CTL_SYSCLK_ENA, 0, NULL, 0),
421
422         SND_SOC_DAPM_SUPPLY("AIF1 PLL", SUN8I_SYSCLK_CTL,
423                             SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL, 0, NULL, 0),
424         /* Inversion as 0=AIF1, 1=AIF2 */
425         SND_SOC_DAPM_SUPPLY("SYSCLK AIF1", SUN8I_SYSCLK_CTL,
426                             SUN8I_SYSCLK_CTL_SYSCLK_SRC, 1, NULL, 0),
427
428         /* Module reset */
429         SND_SOC_DAPM_SUPPLY("RST AIF1", SUN8I_MOD_RST_CTL,
430                             SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0),
431         SND_SOC_DAPM_SUPPLY("RST DAC", SUN8I_MOD_RST_CTL,
432                             SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0),
433         SND_SOC_DAPM_SUPPLY("RST ADC", SUN8I_MOD_RST_CTL,
434                             SUN8I_MOD_RST_CTL_ADC, 0, NULL, 0),
435
436         SND_SOC_DAPM_MIC("Headset Mic", NULL),
437         SND_SOC_DAPM_MIC("Mic", NULL),
438
439 };
440
441 static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = {
442         /* Clock Routes */
443         { "AIF1", NULL, "SYSCLK AIF1" },
444         { "AIF1 PLL", NULL, "AIF1" },
445         { "RST AIF1", NULL, "AIF1 PLL" },
446         { "MODCLK AFI1", NULL, "RST AIF1" },
447         { "DAC", NULL, "MODCLK AFI1" },
448         { "ADC", NULL, "MODCLK AFI1" },
449
450         { "RST DAC", NULL, "SYSCLK" },
451         { "MODCLK DAC", NULL, "RST DAC" },
452         { "DAC", NULL, "MODCLK DAC" },
453
454         { "RST ADC", NULL, "SYSCLK" },
455         { "MODCLK ADC", NULL, "RST ADC" },
456         { "ADC", NULL, "MODCLK ADC" },
457
458         /* DAC Routes */
459         { "AIF1 Slot 0 Right", NULL, "DAC" },
460         { "AIF1 Slot 0 Left", NULL, "DAC" },
461
462         /* DAC Mixer Routes */
463         { "Left Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch",
464           "AIF1 Slot 0 Left"},
465         { "Right Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch",
466           "AIF1 Slot 0 Right"},
467
468         /* ADC routes */
469         { "Left Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch",
470           "AIF1 Slot 0 Left ADC" },
471         { "Right Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch",
472           "AIF1 Slot 0 Right ADC" },
473 };
474
475 static const struct snd_soc_dai_ops sun8i_codec_dai_ops = {
476         .hw_params = sun8i_codec_hw_params,
477         .set_fmt = sun8i_set_fmt,
478 };
479
480 static struct snd_soc_dai_driver sun8i_codec_dai = {
481         .name = "sun8i",
482         /* playback capabilities */
483         .playback = {
484                 .stream_name = "Playback",
485                 .channels_min = 1,
486                 .channels_max = 2,
487                 .rates = SNDRV_PCM_RATE_8000_192000,
488                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
489         },
490         /* capture capabilities */
491         .capture = {
492                 .stream_name = "Capture",
493                 .channels_min = 1,
494                 .channels_max = 2,
495                 .rates = SNDRV_PCM_RATE_8000_192000,
496                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
497                 .sig_bits = 24,
498         },
499         /* pcm operations */
500         .ops = &sun8i_codec_dai_ops,
501 };
502
503 static const struct snd_soc_codec_driver sun8i_soc_codec = {
504         .component_driver = {
505                 .dapm_widgets           = sun8i_codec_dapm_widgets,
506                 .num_dapm_widgets       = ARRAY_SIZE(sun8i_codec_dapm_widgets),
507                 .dapm_routes            = sun8i_codec_dapm_routes,
508                 .num_dapm_routes        = ARRAY_SIZE(sun8i_codec_dapm_routes),
509         },
510 };
511
512 static const struct regmap_config sun8i_codec_regmap_config = {
513         .reg_bits       = 32,
514         .reg_stride     = 4,
515         .val_bits       = 32,
516         .max_register   = SUN8I_DAC_MXR_SRC,
517
518         .cache_type     = REGCACHE_FLAT,
519 };
520
521 static int sun8i_codec_probe(struct platform_device *pdev)
522 {
523         struct resource *res_base;
524         struct sun8i_codec *scodec;
525         void __iomem *base;
526         int ret;
527
528         scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);
529         if (!scodec)
530                 return -ENOMEM;
531
532         scodec->dev = &pdev->dev;
533
534         scodec->clk_module = devm_clk_get(&pdev->dev, "mod");
535         if (IS_ERR(scodec->clk_module)) {
536                 dev_err(&pdev->dev, "Failed to get the module clock\n");
537                 return PTR_ERR(scodec->clk_module);
538         }
539
540         scodec->clk_bus = devm_clk_get(&pdev->dev, "bus");
541         if (IS_ERR(scodec->clk_bus)) {
542                 dev_err(&pdev->dev, "Failed to get the bus clock\n");
543                 return PTR_ERR(scodec->clk_bus);
544         }
545
546         res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
547         base = devm_ioremap_resource(&pdev->dev, res_base);
548         if (IS_ERR(base)) {
549                 dev_err(&pdev->dev, "Failed to map the registers\n");
550                 return PTR_ERR(base);
551         }
552
553         scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
554                                                &sun8i_codec_regmap_config);
555         if (IS_ERR(scodec->regmap)) {
556                 dev_err(&pdev->dev, "Failed to create our regmap\n");
557                 return PTR_ERR(scodec->regmap);
558         }
559
560         platform_set_drvdata(pdev, scodec);
561
562         pm_runtime_enable(&pdev->dev);
563         if (!pm_runtime_enabled(&pdev->dev)) {
564                 ret = sun8i_codec_runtime_resume(&pdev->dev);
565                 if (ret)
566                         goto err_pm_disable;
567         }
568
569         ret = snd_soc_register_codec(&pdev->dev, &sun8i_soc_codec,
570                                      &sun8i_codec_dai, 1);
571         if (ret) {
572                 dev_err(&pdev->dev, "Failed to register codec\n");
573                 goto err_suspend;
574         }
575
576         return ret;
577
578 err_suspend:
579         if (!pm_runtime_status_suspended(&pdev->dev))
580                 sun8i_codec_runtime_suspend(&pdev->dev);
581
582 err_pm_disable:
583         pm_runtime_disable(&pdev->dev);
584
585         return ret;
586 }
587
588 static int sun8i_codec_remove(struct platform_device *pdev)
589 {
590         struct snd_soc_card *card = platform_get_drvdata(pdev);
591         struct sun8i_codec *scodec = snd_soc_card_get_drvdata(card);
592
593         pm_runtime_disable(&pdev->dev);
594         if (!pm_runtime_status_suspended(&pdev->dev))
595                 sun8i_codec_runtime_suspend(&pdev->dev);
596
597         snd_soc_unregister_codec(&pdev->dev);
598         clk_disable_unprepare(scodec->clk_module);
599         clk_disable_unprepare(scodec->clk_bus);
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");