.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * This driver supports the digital controls for the internal codec |
---|
3 | 4 | * found in Allwinner's A33 SoCs. |
---|
.. | .. |
---|
6 | 7 | * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com> |
---|
7 | 8 | * huangxin <huangxin@Reuuimllatech.com> |
---|
8 | 9 | * 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 | 10 | */ |
---|
20 | 11 | |
---|
21 | 12 | #include <linux/module.h> |
---|
22 | 13 | #include <linux/delay.h> |
---|
23 | 14 | #include <linux/clk.h> |
---|
24 | 15 | #include <linux/io.h> |
---|
| 16 | +#include <linux/of_device.h> |
---|
25 | 17 | #include <linux/pm_runtime.h> |
---|
26 | 18 | #include <linux/regmap.h> |
---|
| 19 | +#include <linux/log2.h> |
---|
27 | 20 | |
---|
28 | 21 | #include <sound/pcm_params.h> |
---|
29 | 22 | #include <sound/soc.h> |
---|
.. | .. |
---|
31 | 24 | |
---|
32 | 25 | #define SUN8I_SYSCLK_CTL 0x00c |
---|
33 | 26 | #define SUN8I_SYSCLK_CTL_AIF1CLK_ENA 11 |
---|
34 | | -#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL 9 |
---|
35 | | -#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC 8 |
---|
| 27 | +#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL (0x2 << 8) |
---|
| 28 | +#define SUN8I_SYSCLK_CTL_AIF2CLK_ENA 7 |
---|
| 29 | +#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL (0x2 << 4) |
---|
36 | 30 | #define SUN8I_SYSCLK_CTL_SYSCLK_ENA 3 |
---|
37 | 31 | #define SUN8I_SYSCLK_CTL_SYSCLK_SRC 0 |
---|
| 32 | +#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK (0x0 << 0) |
---|
| 33 | +#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK (0x1 << 0) |
---|
38 | 34 | #define SUN8I_MOD_CLK_ENA 0x010 |
---|
39 | 35 | #define SUN8I_MOD_CLK_ENA_AIF1 15 |
---|
40 | 36 | #define SUN8I_MOD_CLK_ENA_ADC 3 |
---|
.. | .. |
---|
52 | 48 | #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV 13 |
---|
53 | 49 | #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV 9 |
---|
54 | 50 | #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV 6 |
---|
55 | | -#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_16 (1 << 6) |
---|
56 | 51 | #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ 4 |
---|
57 | 52 | #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16 (1 << 4) |
---|
58 | 53 | #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT 2 |
---|
59 | 54 | #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 |
---|
| 55 | +#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA 15 |
---|
| 56 | +#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA 14 |
---|
| 57 | +#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC 10 |
---|
| 58 | +#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC 8 |
---|
62 | 59 | #define SUN8I_AIF1_DACDAT_CTRL 0x048 |
---|
63 | 60 | #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA 15 |
---|
64 | 61 | #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA 14 |
---|
| 62 | +#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC 10 |
---|
| 63 | +#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC 8 |
---|
65 | 64 | #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 |
---|
| 65 | +#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L 15 |
---|
| 66 | +#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL 14 |
---|
| 67 | +#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL 13 |
---|
| 68 | +#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR 12 |
---|
70 | 69 | #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R 11 |
---|
71 | 70 | #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR 10 |
---|
72 | 71 | #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR 9 |
---|
73 | 72 | #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL 8 |
---|
74 | 73 | #define SUN8I_ADC_DIG_CTRL 0x100 |
---|
75 | | -#define SUN8I_ADC_DIG_CTRL_ENDA 15 |
---|
| 74 | +#define SUN8I_ADC_DIG_CTRL_ENAD 15 |
---|
76 | 75 | #define SUN8I_ADC_DIG_CTRL_ADOUT_DTS 2 |
---|
77 | 76 | #define SUN8I_ADC_DIG_CTRL_ADOUT_DLY 1 |
---|
78 | 77 | #define SUN8I_DAC_DIG_CTRL 0x120 |
---|
79 | | -#define SUN8I_DAC_DIG_CTRL_ENDA 15 |
---|
| 78 | +#define SUN8I_DAC_DIG_CTRL_ENDA 15 |
---|
80 | 79 | #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 |
---|
| 80 | +#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L 15 |
---|
| 81 | +#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L 14 |
---|
| 82 | +#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL 13 |
---|
84 | 83 | #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 |
---|
| 84 | +#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R 11 |
---|
| 85 | +#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R 10 |
---|
| 86 | +#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR 9 |
---|
88 | 87 | #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR 8 |
---|
89 | 88 | |
---|
| 89 | +#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK GENMASK(9, 8) |
---|
| 90 | +#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK GENMASK(5, 4) |
---|
90 | 91 | #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12) |
---|
91 | 92 | #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 | 93 | #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9) |
---|
| 94 | +#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6) |
---|
| 95 | +#define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4) |
---|
| 96 | +#define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK GENMASK(3, 2) |
---|
| 97 | + |
---|
| 98 | +struct sun8i_codec_quirks { |
---|
| 99 | + bool legacy_widgets : 1; |
---|
| 100 | + bool lrck_inversion : 1; |
---|
| 101 | +}; |
---|
96 | 102 | |
---|
97 | 103 | struct sun8i_codec { |
---|
98 | | - struct device *dev; |
---|
99 | | - struct regmap *regmap; |
---|
100 | | - struct clk *clk_module; |
---|
101 | | - struct clk *clk_bus; |
---|
| 104 | + struct regmap *regmap; |
---|
| 105 | + struct clk *clk_module; |
---|
| 106 | + const struct sun8i_codec_quirks *quirks; |
---|
102 | 107 | }; |
---|
103 | 108 | |
---|
104 | 109 | static int sun8i_codec_runtime_resume(struct device *dev) |
---|
.. | .. |
---|
106 | 111 | struct sun8i_codec *scodec = dev_get_drvdata(dev); |
---|
107 | 112 | int ret; |
---|
108 | 113 | |
---|
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 | 114 | regcache_cache_only(scodec->regmap, false); |
---|
122 | 115 | |
---|
123 | 116 | ret = regcache_sync(scodec->regmap); |
---|
124 | 117 | if (ret) { |
---|
125 | 118 | dev_err(dev, "Failed to sync regmap cache\n"); |
---|
126 | | - goto err_disable_clk; |
---|
| 119 | + return ret; |
---|
127 | 120 | } |
---|
128 | 121 | |
---|
129 | 122 | 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 | 123 | } |
---|
139 | 124 | |
---|
140 | 125 | static int sun8i_codec_runtime_suspend(struct device *dev) |
---|
.. | .. |
---|
143 | 128 | |
---|
144 | 129 | regcache_cache_only(scodec->regmap, true); |
---|
145 | 130 | regcache_mark_dirty(scodec->regmap); |
---|
146 | | - |
---|
147 | | - clk_disable_unprepare(scodec->clk_module); |
---|
148 | | - clk_disable_unprepare(scodec->clk_bus); |
---|
149 | 131 | |
---|
150 | 132 | return 0; |
---|
151 | 133 | } |
---|
.. | .. |
---|
185 | 167 | |
---|
186 | 168 | static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
---|
187 | 169 | { |
---|
188 | | - struct sun8i_codec *scodec = snd_soc_component_get_drvdata(dai->component); |
---|
| 170 | + struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); |
---|
189 | 171 | u32 value; |
---|
190 | 172 | |
---|
191 | 173 | /* clock masters */ |
---|
.. | .. |
---|
219 | 201 | value << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV); |
---|
220 | 202 | |
---|
221 | 203 | /* |
---|
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. |
---|
| 204 | + * It appears that the DAI and the codec in the A33 SoC don't |
---|
| 205 | + * share the same polarity for the LRCK signal when they mean |
---|
| 206 | + * 'normal' and 'inverted' in the datasheet. |
---|
225 | 207 | * |
---|
226 | 208 | * Since the DAI here is our regular i2s driver that have been |
---|
227 | 209 | * tested with way more codecs than just this one, it means |
---|
228 | 210 | * that the codec probably gets it backward, and we have to |
---|
229 | 211 | * invert the value here. |
---|
230 | 212 | */ |
---|
| 213 | + value ^= scodec->quirks->lrck_inversion; |
---|
231 | 214 | regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, |
---|
232 | 215 | BIT(SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV), |
---|
233 | | - !value << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV); |
---|
| 216 | + value << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV); |
---|
234 | 217 | |
---|
235 | 218 | /* DAI format */ |
---|
236 | 219 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
---|
.. | .. |
---|
301 | 284 | return best_val; |
---|
302 | 285 | } |
---|
303 | 286 | |
---|
| 287 | +static int sun8i_codec_get_lrck_div(unsigned int channels, |
---|
| 288 | + unsigned int word_size) |
---|
| 289 | +{ |
---|
| 290 | + unsigned int div = word_size * channels; |
---|
| 291 | + |
---|
| 292 | + if (div < 16 || div > 256) |
---|
| 293 | + return -EINVAL; |
---|
| 294 | + |
---|
| 295 | + return ilog2(div) - 4; |
---|
| 296 | +} |
---|
| 297 | + |
---|
304 | 298 | static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, |
---|
305 | 299 | struct snd_pcm_hw_params *params, |
---|
306 | 300 | struct snd_soc_dai *dai) |
---|
307 | 301 | { |
---|
308 | | - struct sun8i_codec *scodec = snd_soc_component_get_drvdata(dai->component); |
---|
309 | | - int sample_rate; |
---|
| 302 | + struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); |
---|
| 303 | + int sample_rate, lrck_div; |
---|
310 | 304 | u8 bclk_div; |
---|
311 | 305 | |
---|
312 | 306 | /* |
---|
.. | .. |
---|
322 | 316 | SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK, |
---|
323 | 317 | bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV); |
---|
324 | 318 | |
---|
| 319 | + lrck_div = sun8i_codec_get_lrck_div(params_channels(params), |
---|
| 320 | + params_physical_width(params)); |
---|
| 321 | + if (lrck_div < 0) |
---|
| 322 | + return lrck_div; |
---|
| 323 | + |
---|
325 | 324 | regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, |
---|
326 | 325 | SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK, |
---|
327 | | - SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_16); |
---|
| 326 | + lrck_div << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV); |
---|
328 | 327 | |
---|
329 | 328 | sample_rate = sun8i_codec_get_hw_rate(params); |
---|
330 | 329 | if (sample_rate < 0) |
---|
.. | .. |
---|
333 | 332 | regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL, |
---|
334 | 333 | SUN8I_SYS_SR_CTRL_AIF1_FS_MASK, |
---|
335 | 334 | 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 | 335 | |
---|
340 | 336 | return 0; |
---|
341 | 337 | } |
---|
| 338 | + |
---|
| 339 | +static const char *const sun8i_aif_stereo_mux_enum_values[] = { |
---|
| 340 | + "Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono" |
---|
| 341 | +}; |
---|
| 342 | + |
---|
| 343 | +static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum, |
---|
| 344 | + SUN8I_AIF1_ADCDAT_CTRL, |
---|
| 345 | + SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC, |
---|
| 346 | + SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC, |
---|
| 347 | + sun8i_aif_stereo_mux_enum_values); |
---|
| 348 | + |
---|
| 349 | +static const struct snd_kcontrol_new sun8i_aif1_ad0_stereo_mux_control = |
---|
| 350 | + SOC_DAPM_ENUM("AIF1 AD0 Stereo Capture Route", |
---|
| 351 | + sun8i_aif1_ad0_stereo_mux_enum); |
---|
| 352 | + |
---|
| 353 | +static const struct snd_kcontrol_new sun8i_aif1_ad0_mixer_controls[] = { |
---|
| 354 | + SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch", |
---|
| 355 | + SUN8I_AIF1_MXR_SRC, |
---|
| 356 | + SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L, |
---|
| 357 | + SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R, 1, 0), |
---|
| 358 | + SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch", |
---|
| 359 | + SUN8I_AIF1_MXR_SRC, |
---|
| 360 | + SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL, |
---|
| 361 | + SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR, 1, 0), |
---|
| 362 | + SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch", |
---|
| 363 | + SUN8I_AIF1_MXR_SRC, |
---|
| 364 | + SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL, |
---|
| 365 | + SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0), |
---|
| 366 | + SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch", |
---|
| 367 | + SUN8I_AIF1_MXR_SRC, |
---|
| 368 | + SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR, |
---|
| 369 | + SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL, 1, 0), |
---|
| 370 | +}; |
---|
| 371 | + |
---|
| 372 | +static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_da0_stereo_mux_enum, |
---|
| 373 | + SUN8I_AIF1_DACDAT_CTRL, |
---|
| 374 | + SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC, |
---|
| 375 | + SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC, |
---|
| 376 | + sun8i_aif_stereo_mux_enum_values); |
---|
| 377 | + |
---|
| 378 | +static const struct snd_kcontrol_new sun8i_aif1_da0_stereo_mux_control = |
---|
| 379 | + SOC_DAPM_ENUM("AIF1 DA0 Stereo Playback Route", |
---|
| 380 | + sun8i_aif1_da0_stereo_mux_enum); |
---|
342 | 381 | |
---|
343 | 382 | static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = { |
---|
344 | 383 | SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch", |
---|
.. | .. |
---|
357 | 396 | SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR, 1, 0), |
---|
358 | 397 | }; |
---|
359 | 398 | |
---|
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 | 399 | 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), |
---|
| 400 | + /* System Clocks */ |
---|
| 401 | + SND_SOC_DAPM_CLOCK_SUPPLY("mod"), |
---|
384 | 402 | |
---|
385 | | - /* Analog DAC AIF */ |
---|
386 | | - SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Left", "Playback", 0, |
---|
| 403 | + SND_SOC_DAPM_SUPPLY("AIF1CLK", |
---|
| 404 | + SUN8I_SYSCLK_CTL, |
---|
| 405 | + SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0), |
---|
| 406 | + SND_SOC_DAPM_SUPPLY("SYSCLK", |
---|
| 407 | + SUN8I_SYSCLK_CTL, |
---|
| 408 | + SUN8I_SYSCLK_CTL_SYSCLK_ENA, 0, NULL, 0), |
---|
| 409 | + |
---|
| 410 | + /* Module Clocks */ |
---|
| 411 | + SND_SOC_DAPM_SUPPLY("CLK AIF1", |
---|
| 412 | + SUN8I_MOD_CLK_ENA, |
---|
| 413 | + SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0), |
---|
| 414 | + SND_SOC_DAPM_SUPPLY("CLK ADC", |
---|
| 415 | + SUN8I_MOD_CLK_ENA, |
---|
| 416 | + SUN8I_MOD_CLK_ENA_ADC, 0, NULL, 0), |
---|
| 417 | + SND_SOC_DAPM_SUPPLY("CLK DAC", |
---|
| 418 | + SUN8I_MOD_CLK_ENA, |
---|
| 419 | + SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0), |
---|
| 420 | + |
---|
| 421 | + /* Module Resets */ |
---|
| 422 | + SND_SOC_DAPM_SUPPLY("RST AIF1", |
---|
| 423 | + SUN8I_MOD_RST_CTL, |
---|
| 424 | + SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0), |
---|
| 425 | + SND_SOC_DAPM_SUPPLY("RST ADC", |
---|
| 426 | + SUN8I_MOD_RST_CTL, |
---|
| 427 | + SUN8I_MOD_RST_CTL_ADC, 0, NULL, 0), |
---|
| 428 | + SND_SOC_DAPM_SUPPLY("RST DAC", |
---|
| 429 | + SUN8I_MOD_RST_CTL, |
---|
| 430 | + SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0), |
---|
| 431 | + |
---|
| 432 | + /* Module Supplies */ |
---|
| 433 | + SND_SOC_DAPM_SUPPLY("ADC", |
---|
| 434 | + SUN8I_ADC_DIG_CTRL, |
---|
| 435 | + SUN8I_ADC_DIG_CTRL_ENAD, 0, NULL, 0), |
---|
| 436 | + SND_SOC_DAPM_SUPPLY("DAC", |
---|
| 437 | + SUN8I_DAC_DIG_CTRL, |
---|
| 438 | + SUN8I_DAC_DIG_CTRL_ENDA, 0, NULL, 0), |
---|
| 439 | + |
---|
| 440 | + /* AIF "ADC" Outputs */ |
---|
| 441 | + SND_SOC_DAPM_AIF_OUT("AIF1 AD0L", "Capture", 0, |
---|
| 442 | + SUN8I_AIF1_ADCDAT_CTRL, |
---|
| 443 | + SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0), |
---|
| 444 | + SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "Capture", 1, |
---|
| 445 | + SUN8I_AIF1_ADCDAT_CTRL, |
---|
| 446 | + SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA, 0), |
---|
| 447 | + |
---|
| 448 | + /* AIF "ADC" Mono/Stereo Muxes */ |
---|
| 449 | + SND_SOC_DAPM_MUX("AIF1 AD0L Stereo Mux", SND_SOC_NOPM, 0, 0, |
---|
| 450 | + &sun8i_aif1_ad0_stereo_mux_control), |
---|
| 451 | + SND_SOC_DAPM_MUX("AIF1 AD0R Stereo Mux", SND_SOC_NOPM, 0, 0, |
---|
| 452 | + &sun8i_aif1_ad0_stereo_mux_control), |
---|
| 453 | + |
---|
| 454 | + /* AIF "ADC" Mixers */ |
---|
| 455 | + SOC_MIXER_ARRAY("AIF1 AD0L Mixer", SND_SOC_NOPM, 0, 0, |
---|
| 456 | + sun8i_aif1_ad0_mixer_controls), |
---|
| 457 | + SOC_MIXER_ARRAY("AIF1 AD0R Mixer", SND_SOC_NOPM, 0, 0, |
---|
| 458 | + sun8i_aif1_ad0_mixer_controls), |
---|
| 459 | + |
---|
| 460 | + /* AIF "DAC" Mono/Stereo Muxes */ |
---|
| 461 | + SND_SOC_DAPM_MUX("AIF1 DA0L Stereo Mux", SND_SOC_NOPM, 0, 0, |
---|
| 462 | + &sun8i_aif1_da0_stereo_mux_control), |
---|
| 463 | + SND_SOC_DAPM_MUX("AIF1 DA0R Stereo Mux", SND_SOC_NOPM, 0, 0, |
---|
| 464 | + &sun8i_aif1_da0_stereo_mux_control), |
---|
| 465 | + |
---|
| 466 | + /* AIF "DAC" Inputs */ |
---|
| 467 | + SND_SOC_DAPM_AIF_IN("AIF1 DA0L", "Playback", 0, |
---|
387 | 468 | SUN8I_AIF1_DACDAT_CTRL, |
---|
388 | 469 | SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0), |
---|
389 | | - SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Right", "Playback", 0, |
---|
| 470 | + SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "Playback", 1, |
---|
390 | 471 | SUN8I_AIF1_DACDAT_CTRL, |
---|
391 | 472 | SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0), |
---|
392 | 473 | |
---|
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), |
---|
| 474 | + /* ADC Inputs (connected to analog codec DAPM context) */ |
---|
| 475 | + SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 0, 0), |
---|
| 476 | + SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), |
---|
400 | 477 | |
---|
401 | | - /* DAC and ADC Mixers */ |
---|
402 | | - SOC_MIXER_ARRAY("Left Digital DAC Mixer", SND_SOC_NOPM, 0, 0, |
---|
| 478 | + /* DAC Outputs (connected to analog codec DAPM context) */ |
---|
| 479 | + SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), |
---|
| 480 | + SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), |
---|
| 481 | + |
---|
| 482 | + /* DAC Mixers */ |
---|
| 483 | + SOC_MIXER_ARRAY("DACL Mixer", SND_SOC_NOPM, 0, 0, |
---|
403 | 484 | sun8i_dac_mixer_controls), |
---|
404 | | - SOC_MIXER_ARRAY("Right Digital DAC Mixer", SND_SOC_NOPM, 0, 0, |
---|
| 485 | + SOC_MIXER_ARRAY("DACR Mixer", SND_SOC_NOPM, 0, 0, |
---|
405 | 486 | 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 | 487 | }; |
---|
441 | 488 | |
---|
442 | 489 | static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = { |
---|
443 | 490 | /* 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" }, |
---|
| 491 | + { "AIF1CLK", NULL, "mod" }, |
---|
450 | 492 | |
---|
451 | | - { "RST DAC", NULL, "SYSCLK" }, |
---|
452 | | - { "MODCLK DAC", NULL, "RST DAC" }, |
---|
453 | | - { "DAC", NULL, "MODCLK DAC" }, |
---|
| 493 | + { "SYSCLK", NULL, "AIF1CLK" }, |
---|
454 | 494 | |
---|
455 | | - { "RST ADC", NULL, "SYSCLK" }, |
---|
456 | | - { "MODCLK ADC", NULL, "RST ADC" }, |
---|
457 | | - { "ADC", NULL, "MODCLK ADC" }, |
---|
| 495 | + { "CLK AIF1", NULL, "AIF1CLK" }, |
---|
| 496 | + { "CLK AIF1", NULL, "SYSCLK" }, |
---|
| 497 | + { "RST AIF1", NULL, "CLK AIF1" }, |
---|
| 498 | + { "AIF1 AD0L", NULL, "RST AIF1" }, |
---|
| 499 | + { "AIF1 AD0R", NULL, "RST AIF1" }, |
---|
| 500 | + { "AIF1 DA0L", NULL, "RST AIF1" }, |
---|
| 501 | + { "AIF1 DA0R", NULL, "RST AIF1" }, |
---|
458 | 502 | |
---|
459 | | - /* DAC Routes */ |
---|
460 | | - { "AIF1 Slot 0 Right", NULL, "DAC" }, |
---|
461 | | - { "AIF1 Slot 0 Left", NULL, "DAC" }, |
---|
| 503 | + { "CLK ADC", NULL, "SYSCLK" }, |
---|
| 504 | + { "RST ADC", NULL, "CLK ADC" }, |
---|
| 505 | + { "ADC", NULL, "RST ADC" }, |
---|
| 506 | + { "ADCL", NULL, "ADC" }, |
---|
| 507 | + { "ADCR", NULL, "ADC" }, |
---|
| 508 | + |
---|
| 509 | + { "CLK DAC", NULL, "SYSCLK" }, |
---|
| 510 | + { "RST DAC", NULL, "CLK DAC" }, |
---|
| 511 | + { "DAC", NULL, "RST DAC" }, |
---|
| 512 | + { "DACL", NULL, "DAC" }, |
---|
| 513 | + { "DACR", NULL, "DAC" }, |
---|
| 514 | + |
---|
| 515 | + /* AIF "ADC" Output Routes */ |
---|
| 516 | + { "AIF1 AD0L", NULL, "AIF1 AD0L Stereo Mux" }, |
---|
| 517 | + { "AIF1 AD0R", NULL, "AIF1 AD0R Stereo Mux" }, |
---|
| 518 | + |
---|
| 519 | + /* AIF "ADC" Mono/Stereo Mux Routes */ |
---|
| 520 | + { "AIF1 AD0L Stereo Mux", "Stereo", "AIF1 AD0L Mixer" }, |
---|
| 521 | + { "AIF1 AD0L Stereo Mux", "Reverse Stereo", "AIF1 AD0R Mixer" }, |
---|
| 522 | + { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" }, |
---|
| 523 | + { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" }, |
---|
| 524 | + { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" }, |
---|
| 525 | + { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" }, |
---|
| 526 | + |
---|
| 527 | + { "AIF1 AD0R Stereo Mux", "Stereo", "AIF1 AD0R Mixer" }, |
---|
| 528 | + { "AIF1 AD0R Stereo Mux", "Reverse Stereo", "AIF1 AD0L Mixer" }, |
---|
| 529 | + { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" }, |
---|
| 530 | + { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" }, |
---|
| 531 | + { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" }, |
---|
| 532 | + { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" }, |
---|
| 533 | + |
---|
| 534 | + /* AIF "ADC" Mixer Routes */ |
---|
| 535 | + { "AIF1 AD0L Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0L Stereo Mux" }, |
---|
| 536 | + { "AIF1 AD0L Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCL" }, |
---|
| 537 | + |
---|
| 538 | + { "AIF1 AD0R Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0R Stereo Mux" }, |
---|
| 539 | + { "AIF1 AD0R Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCR" }, |
---|
| 540 | + |
---|
| 541 | + /* AIF "DAC" Mono/Stereo Mux Routes */ |
---|
| 542 | + { "AIF1 DA0L Stereo Mux", "Stereo", "AIF1 DA0L" }, |
---|
| 543 | + { "AIF1 DA0L Stereo Mux", "Reverse Stereo", "AIF1 DA0R" }, |
---|
| 544 | + { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0L" }, |
---|
| 545 | + { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0R" }, |
---|
| 546 | + { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0L" }, |
---|
| 547 | + { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0R" }, |
---|
| 548 | + |
---|
| 549 | + { "AIF1 DA0R Stereo Mux", "Stereo", "AIF1 DA0R" }, |
---|
| 550 | + { "AIF1 DA0R Stereo Mux", "Reverse Stereo", "AIF1 DA0L" }, |
---|
| 551 | + { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0L" }, |
---|
| 552 | + { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0R" }, |
---|
| 553 | + { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0L" }, |
---|
| 554 | + { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0R" }, |
---|
| 555 | + |
---|
| 556 | + /* DAC Output Routes */ |
---|
| 557 | + { "DACL", NULL, "DACL Mixer" }, |
---|
| 558 | + { "DACR", NULL, "DACR Mixer" }, |
---|
462 | 559 | |
---|
463 | 560 | /* 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"}, |
---|
| 561 | + { "DACL Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0L Stereo Mux" }, |
---|
| 562 | + { "DACL Mixer", "ADC Digital DAC Playback Switch", "ADCL" }, |
---|
468 | 563 | |
---|
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" }, |
---|
| 564 | + { "DACR Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0R Stereo Mux" }, |
---|
| 565 | + { "DACR Mixer", "ADC Digital DAC Playback Switch", "ADCR" }, |
---|
478 | 566 | }; |
---|
| 567 | + |
---|
| 568 | +static const struct snd_soc_dapm_widget sun8i_codec_legacy_widgets[] = { |
---|
| 569 | + /* Legacy ADC Inputs (connected to analog codec DAPM context) */ |
---|
| 570 | + SND_SOC_DAPM_ADC("AIF1 Slot 0 Left ADC", NULL, SND_SOC_NOPM, 0, 0), |
---|
| 571 | + SND_SOC_DAPM_ADC("AIF1 Slot 0 Right ADC", NULL, SND_SOC_NOPM, 0, 0), |
---|
| 572 | + |
---|
| 573 | + /* Legacy DAC Outputs (connected to analog codec DAPM context) */ |
---|
| 574 | + SND_SOC_DAPM_DAC("AIF1 Slot 0 Left", NULL, SND_SOC_NOPM, 0, 0), |
---|
| 575 | + SND_SOC_DAPM_DAC("AIF1 Slot 0 Right", NULL, SND_SOC_NOPM, 0, 0), |
---|
| 576 | +}; |
---|
| 577 | + |
---|
| 578 | +static const struct snd_soc_dapm_route sun8i_codec_legacy_routes[] = { |
---|
| 579 | + /* Legacy ADC Routes */ |
---|
| 580 | + { "ADCL", NULL, "AIF1 Slot 0 Left ADC" }, |
---|
| 581 | + { "ADCR", NULL, "AIF1 Slot 0 Right ADC" }, |
---|
| 582 | + |
---|
| 583 | + /* Legacy DAC Routes */ |
---|
| 584 | + { "AIF1 Slot 0 Left", NULL, "DACL" }, |
---|
| 585 | + { "AIF1 Slot 0 Right", NULL, "DACR" }, |
---|
| 586 | +}; |
---|
| 587 | + |
---|
| 588 | +static int sun8i_codec_component_probe(struct snd_soc_component *component) |
---|
| 589 | +{ |
---|
| 590 | + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
---|
| 591 | + struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component); |
---|
| 592 | + int ret; |
---|
| 593 | + |
---|
| 594 | + /* Add widgets for backward compatibility with old device trees. */ |
---|
| 595 | + if (scodec->quirks->legacy_widgets) { |
---|
| 596 | + ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_legacy_widgets, |
---|
| 597 | + ARRAY_SIZE(sun8i_codec_legacy_widgets)); |
---|
| 598 | + if (ret) |
---|
| 599 | + return ret; |
---|
| 600 | + |
---|
| 601 | + ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_legacy_routes, |
---|
| 602 | + ARRAY_SIZE(sun8i_codec_legacy_routes)); |
---|
| 603 | + if (ret) |
---|
| 604 | + return ret; |
---|
| 605 | + } |
---|
| 606 | + |
---|
| 607 | + /* |
---|
| 608 | + * AIF1CLK and AIF2CLK share a pair of clock parents: PLL_AUDIO ("mod") |
---|
| 609 | + * and MCLK (from the CPU DAI connected to AIF1). MCLK's parent is also |
---|
| 610 | + * PLL_AUDIO, so using it adds no additional flexibility. Use PLL_AUDIO |
---|
| 611 | + * directly to simplify the clock tree. |
---|
| 612 | + */ |
---|
| 613 | + regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL, |
---|
| 614 | + SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK | |
---|
| 615 | + SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK, |
---|
| 616 | + SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL | |
---|
| 617 | + SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL); |
---|
| 618 | + |
---|
| 619 | + /* Use AIF1CLK as the SYSCLK parent since AIF1 is used most often. */ |
---|
| 620 | + regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL, |
---|
| 621 | + BIT(SUN8I_SYSCLK_CTL_SYSCLK_SRC), |
---|
| 622 | + SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK); |
---|
| 623 | + |
---|
| 624 | + return 0; |
---|
| 625 | +} |
---|
479 | 626 | |
---|
480 | 627 | static const struct snd_soc_dai_ops sun8i_codec_dai_ops = { |
---|
481 | 628 | .hw_params = sun8i_codec_hw_params, |
---|
.. | .. |
---|
510 | 657 | .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets), |
---|
511 | 658 | .dapm_routes = sun8i_codec_dapm_routes, |
---|
512 | 659 | .num_dapm_routes = ARRAY_SIZE(sun8i_codec_dapm_routes), |
---|
| 660 | + .probe = sun8i_codec_component_probe, |
---|
513 | 661 | .idle_bias_on = 1, |
---|
514 | 662 | .use_pmdown_time = 1, |
---|
515 | 663 | .endianness = 1, |
---|
.. | .. |
---|
527 | 675 | |
---|
528 | 676 | static int sun8i_codec_probe(struct platform_device *pdev) |
---|
529 | 677 | { |
---|
530 | | - struct resource *res_base; |
---|
531 | 678 | struct sun8i_codec *scodec; |
---|
532 | 679 | void __iomem *base; |
---|
533 | 680 | int ret; |
---|
.. | .. |
---|
536 | 683 | if (!scodec) |
---|
537 | 684 | return -ENOMEM; |
---|
538 | 685 | |
---|
539 | | - scodec->dev = &pdev->dev; |
---|
540 | | - |
---|
541 | 686 | scodec->clk_module = devm_clk_get(&pdev->dev, "mod"); |
---|
542 | 687 | if (IS_ERR(scodec->clk_module)) { |
---|
543 | 688 | dev_err(&pdev->dev, "Failed to get the module clock\n"); |
---|
544 | 689 | return PTR_ERR(scodec->clk_module); |
---|
545 | 690 | } |
---|
546 | 691 | |
---|
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); |
---|
| 692 | + base = devm_platform_ioremap_resource(pdev, 0); |
---|
555 | 693 | if (IS_ERR(base)) { |
---|
556 | 694 | dev_err(&pdev->dev, "Failed to map the registers\n"); |
---|
557 | 695 | return PTR_ERR(base); |
---|
558 | 696 | } |
---|
559 | 697 | |
---|
560 | | - scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base, |
---|
561 | | - &sun8i_codec_regmap_config); |
---|
| 698 | + scodec->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", base, |
---|
| 699 | + &sun8i_codec_regmap_config); |
---|
562 | 700 | if (IS_ERR(scodec->regmap)) { |
---|
563 | 701 | dev_err(&pdev->dev, "Failed to create our regmap\n"); |
---|
564 | 702 | return PTR_ERR(scodec->regmap); |
---|
565 | 703 | } |
---|
| 704 | + |
---|
| 705 | + scodec->quirks = of_device_get_match_data(&pdev->dev); |
---|
566 | 706 | |
---|
567 | 707 | platform_set_drvdata(pdev, scodec); |
---|
568 | 708 | |
---|
.. | .. |
---|
601 | 741 | return 0; |
---|
602 | 742 | } |
---|
603 | 743 | |
---|
| 744 | +static const struct sun8i_codec_quirks sun8i_a33_quirks = { |
---|
| 745 | + .legacy_widgets = true, |
---|
| 746 | + .lrck_inversion = true, |
---|
| 747 | +}; |
---|
| 748 | + |
---|
| 749 | +static const struct sun8i_codec_quirks sun50i_a64_quirks = { |
---|
| 750 | +}; |
---|
| 751 | + |
---|
604 | 752 | static const struct of_device_id sun8i_codec_of_match[] = { |
---|
605 | | - { .compatible = "allwinner,sun8i-a33-codec" }, |
---|
| 753 | + { .compatible = "allwinner,sun8i-a33-codec", .data = &sun8i_a33_quirks }, |
---|
| 754 | + { .compatible = "allwinner,sun50i-a64-codec", .data = &sun50i_a64_quirks }, |
---|
606 | 755 | {} |
---|
607 | 756 | }; |
---|
608 | 757 | MODULE_DEVICE_TABLE(of, sun8i_codec_of_match); |
---|