~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/codecs/jz4725b.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 //
  3 // JZ4725B CODEC driver
  4 //
  5 // Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net>
  6 
  7 #include <linux/kernel.h>
  8 #include <linux/module.h>
  9 #include <linux/platform_device.h>
 10 #include <linux/slab.h>
 11 #include <linux/io.h>
 12 #include <linux/iopoll.h>
 13 #include <linux/regmap.h>
 14 #include <linux/clk.h>
 15 
 16 #include <linux/delay.h>
 17 
 18 #include <sound/core.h>
 19 #include <sound/pcm.h>
 20 #include <sound/pcm_params.h>
 21 #include <sound/initval.h>
 22 #include <sound/soc.h>
 23 #include <sound/tlv.h>
 24 
 25 #define ICDC_RGADW_OFFSET               0x00
 26 #define ICDC_RGDATA_OFFSET              0x04
 27 
 28 /* ICDC internal register access control register(RGADW) */
 29 #define ICDC_RGADW_RGWR                 BIT(16)
 30 
 31 #define ICDC_RGADW_RGADDR_OFFSET        8
 32 #define ICDC_RGADW_RGADDR_MASK          GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
 33 
 34 #define ICDC_RGADW_RGDIN_OFFSET         0
 35 #define ICDC_RGADW_RGDIN_MASK           GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
 36 
 37 /* ICDC internal register data output register (RGDATA)*/
 38 #define ICDC_RGDATA_IRQ                 BIT(8)
 39 
 40 #define ICDC_RGDATA_RGDOUT_OFFSET       0
 41 #define ICDC_RGDATA_RGDOUT_MASK         GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
 42 
 43 /* JZ internal register space */
 44 enum {
 45         JZ4725B_CODEC_REG_AICR,
 46         JZ4725B_CODEC_REG_CR1,
 47         JZ4725B_CODEC_REG_CR2,
 48         JZ4725B_CODEC_REG_CCR1,
 49         JZ4725B_CODEC_REG_CCR2,
 50         JZ4725B_CODEC_REG_PMR1,
 51         JZ4725B_CODEC_REG_PMR2,
 52         JZ4725B_CODEC_REG_CRR,
 53         JZ4725B_CODEC_REG_ICR,
 54         JZ4725B_CODEC_REG_IFR,
 55         JZ4725B_CODEC_REG_CGR1,
 56         JZ4725B_CODEC_REG_CGR2,
 57         JZ4725B_CODEC_REG_CGR3,
 58         JZ4725B_CODEC_REG_CGR4,
 59         JZ4725B_CODEC_REG_CGR5,
 60         JZ4725B_CODEC_REG_CGR6,
 61         JZ4725B_CODEC_REG_CGR7,
 62         JZ4725B_CODEC_REG_CGR8,
 63         JZ4725B_CODEC_REG_CGR9,
 64         JZ4725B_CODEC_REG_CGR10,
 65         JZ4725B_CODEC_REG_TR1,
 66         JZ4725B_CODEC_REG_TR2,
 67         JZ4725B_CODEC_REG_CR3,
 68         JZ4725B_CODEC_REG_AGC1,
 69         JZ4725B_CODEC_REG_AGC2,
 70         JZ4725B_CODEC_REG_AGC3,
 71         JZ4725B_CODEC_REG_AGC4,
 72         JZ4725B_CODEC_REG_AGC5,
 73 };
 74 
 75 #define REG_AICR_CONFIG1_OFFSET         0
 76 #define REG_AICR_CONFIG1_MASK           (0xf << REG_AICR_CONFIG1_OFFSET)
 77 
 78 #define REG_CR1_SB_MICBIAS_OFFSET       7
 79 #define REG_CR1_MONO_OFFSET             6
 80 #define REG_CR1_DAC_MUTE_OFFSET         5
 81 #define REG_CR1_HP_DIS_OFFSET           4
 82 #define REG_CR1_DACSEL_OFFSET           3
 83 #define REG_CR1_BYPASS_OFFSET           2
 84 
 85 #define REG_CR2_DAC_DEEMP_OFFSET        7
 86 #define REG_CR2_DAC_ADWL_OFFSET         5
 87 #define REG_CR2_DAC_ADWL_MASK           (0x3 << REG_CR2_DAC_ADWL_OFFSET)
 88 #define REG_CR2_ADC_ADWL_OFFSET         3
 89 #define REG_CR2_ADC_ADWL_MASK           (0x3 << REG_CR2_ADC_ADWL_OFFSET)
 90 #define REG_CR2_ADC_HPF_OFFSET          2
 91 
 92 #define REG_CR3_SB_MIC1_OFFSET          7
 93 #define REG_CR3_SB_MIC2_OFFSET          6
 94 #define REG_CR3_SIDETONE1_OFFSET        5
 95 #define REG_CR3_SIDETONE2_OFFSET        4
 96 #define REG_CR3_MICDIFF_OFFSET          3
 97 #define REG_CR3_MICSTEREO_OFFSET        2
 98 #define REG_CR3_INSEL_OFFSET            0
 99 #define REG_CR3_INSEL_MASK              (0x3 << REG_CR3_INSEL_OFFSET)
100 
101 #define REG_CCR1_CONFIG4_OFFSET         0
102 #define REG_CCR1_CONFIG4_MASK           (0xf << REG_CCR1_CONFIG4_OFFSET)
103 
104 #define REG_CCR2_DFREQ_OFFSET           4
105 #define REG_CCR2_DFREQ_MASK             (0xf << REG_CCR2_DFREQ_OFFSET)
106 #define REG_CCR2_AFREQ_OFFSET           0
107 #define REG_CCR2_AFREQ_MASK             (0xf << REG_CCR2_AFREQ_OFFSET)
108 
109 #define REG_PMR1_SB_DAC_OFFSET          7
110 #define REG_PMR1_SB_OUT_OFFSET          6
111 #define REG_PMR1_SB_MIX_OFFSET          5
112 #define REG_PMR1_SB_ADC_OFFSET          4
113 #define REG_PMR1_SB_LIN_OFFSET          3
114 #define REG_PMR1_SB_IND_OFFSET          0
115 
116 #define REG_PMR2_LRGI_OFFSET            7
117 #define REG_PMR2_RLGI_OFFSET            6
118 #define REG_PMR2_LRGOD_OFFSET           5
119 #define REG_PMR2_RLGOD_OFFSET           4
120 #define REG_PMR2_GIM_OFFSET             3
121 #define REG_PMR2_SB_MC_OFFSET           2
122 #define REG_PMR2_SB_OFFSET              1
123 #define REG_PMR2_SB_SLEEP_OFFSET        0
124 
125 #define REG_IFR_RAMP_UP_DONE_OFFSET     3
126 #define REG_IFR_RAMP_DOWN_DONE_OFFSET   2
127 
128 #define REG_CGR1_GODL_OFFSET            4
129 #define REG_CGR1_GODL_MASK              (0xf << REG_CGR1_GODL_OFFSET)
130 #define REG_CGR1_GODR_OFFSET            0
131 #define REG_CGR1_GODR_MASK              (0xf << REG_CGR1_GODR_OFFSET)
132 
133 #define REG_CGR2_GO1R_OFFSET            0
134 #define REG_CGR2_GO1R_MASK              (0x1f << REG_CGR2_GO1R_OFFSET)
135 
136 #define REG_CGR3_GO1L_OFFSET            0
137 #define REG_CGR3_GO1L_MASK              (0x1f << REG_CGR3_GO1L_OFFSET)
138 
139 #define REG_CGR4_GO2R_OFFSET            0
140 #define REG_CGR4_GO2R_MASK              (0x1f << REG_CGR4_GO2R_OFFSET)
141 
142 #define REG_CGR5_GO2L_OFFSET            0
143 #define REG_CGR5_GO2L_MASK              (0x1f << REG_CGR5_GO2L_OFFSET)
144 
145 #define REG_CGR6_GO3R_OFFSET            0
146 #define REG_CGR6_GO3R_MASK              (0x1f << REG_CGR6_GO3R_OFFSET)
147 
148 #define REG_CGR7_GO3L_OFFSET            0
149 #define REG_CGR7_GO3L_MASK              (0x1f << REG_CGR7_GO3L_OFFSET)
150 
151 #define REG_CGR8_GOR_OFFSET             0
152 #define REG_CGR8_GOR_MASK               (0x1f << REG_CGR8_GOR_OFFSET)
153 
154 #define REG_CGR9_GOL_OFFSET             0
155 #define REG_CGR9_GOL_MASK               (0x1f << REG_CGR9_GOL_OFFSET)
156 
157 #define REG_CGR10_GIL_OFFSET            0
158 #define REG_CGR10_GIR_OFFSET            4
159 
160 struct jz_icdc {
161         struct regmap *regmap;
162         void __iomem *base;
163         struct clk *clk;
164 };
165 
166 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_adc_tlv,     0, 150, 0);
167 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_dac_tlv, -2250, 150, 0);
168 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(jz4725b_mix_tlv,
169          0, 11, TLV_DB_SCALE_ITEM(-2250,   0, 0),
170         12, 31, TLV_DB_SCALE_ITEM(-2250, 150, 0),
171 );
172 
173 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(jz4725b_out_tlv,
174          0, 11, TLV_DB_SCALE_ITEM(-3350, 200, 0),
175         12, 23, TLV_DB_SCALE_ITEM(-1050, 100, 0),
176         24, 31, TLV_DB_SCALE_ITEM(  100,  50, 0),
177 );
178 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_mic_boost_tlv, 0, 2000, 0);
179 
180 static const char * const jz4725b_mic_mode_texts[] = {
181         "Single Ended", "Differential",
182 };
183 
184 static const struct soc_enum jz4725b_mic_mode_enum =
185         SOC_ENUM_SINGLE(JZ4725B_CODEC_REG_CR3, REG_CR3_MICDIFF_OFFSET,
186                         2, jz4725b_mic_mode_texts);
187 
188 static const struct snd_kcontrol_new jz4725b_codec_controls[] = {
189         SOC_DOUBLE_TLV("DAC Playback Volume",
190                        JZ4725B_CODEC_REG_CGR1,
191                        REG_CGR1_GODL_OFFSET,
192                        REG_CGR1_GODR_OFFSET,
193                        0xf, 1, jz4725b_dac_tlv),
194         SOC_DOUBLE_TLV("Master Capture Volume",
195                        JZ4725B_CODEC_REG_CGR10,
196                        REG_CGR10_GIL_OFFSET,
197                        REG_CGR10_GIR_OFFSET,
198                        0xf, 0, jz4725b_adc_tlv),
199         SOC_DOUBLE_R_TLV("Mixer Line In Bypass Playback Volume",
200                          JZ4725B_CODEC_REG_CGR3,
201                          JZ4725B_CODEC_REG_CGR2,
202                          REG_CGR2_GO1R_OFFSET,
203                          0x1f, 1, jz4725b_mix_tlv),
204         SOC_DOUBLE_R_TLV("Mixer Mic 1 Bypass Playback Volume",
205                          JZ4725B_CODEC_REG_CGR5,
206                          JZ4725B_CODEC_REG_CGR4,
207                          REG_CGR4_GO2R_OFFSET,
208                          0x1f, 1, jz4725b_mix_tlv),
209         SOC_DOUBLE_R_TLV("Mixer Mic 2 Bypass Playback Volume",
210                          JZ4725B_CODEC_REG_CGR7,
211                          JZ4725B_CODEC_REG_CGR6,
212                          REG_CGR6_GO3R_OFFSET,
213                          0x1f, 1, jz4725b_mix_tlv),
214 
215         SOC_DOUBLE_R_TLV("Master Playback Volume",
216                          JZ4725B_CODEC_REG_CGR9,
217                          JZ4725B_CODEC_REG_CGR8,
218                          REG_CGR8_GOR_OFFSET,
219                          0x1f, 1, jz4725b_out_tlv),
220 
221         SOC_SINGLE("DAC Playback Switch", JZ4725B_CODEC_REG_CR1,
222                    REG_CR1_DAC_MUTE_OFFSET, 1, 1),
223 
224         SOC_SINGLE("Deemphasize Filter Playback Switch",
225                    JZ4725B_CODEC_REG_CR2,
226                    REG_CR2_DAC_DEEMP_OFFSET, 1, 0),
227 
228         SOC_SINGLE("High-Pass Filter Capture Switch",
229                    JZ4725B_CODEC_REG_CR2,
230                    REG_CR2_ADC_HPF_OFFSET, 1, 0),
231 
232         SOC_ENUM("Mic Mode Capture Switch", jz4725b_mic_mode_enum),
233 
234         SOC_SINGLE_TLV("Mic1 Boost Capture Volume",
235                        JZ4725B_CODEC_REG_PMR2,
236                        REG_PMR2_GIM_OFFSET,
237                        1, 0, jz4725b_mic_boost_tlv),
238 };
239 
240 static const char * const jz4725b_codec_adc_src_texts[] = {
241         "Mic 1", "Mic 2", "Line In", "Mixer",
242 };
243 static const unsigned int jz4725b_codec_adc_src_values[] = { 0, 1, 2, 3, };
244 static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum,
245                                   JZ4725B_CODEC_REG_CR3,
246                                   REG_CR3_INSEL_OFFSET,
247                                   REG_CR3_INSEL_MASK,
248                                   jz4725b_codec_adc_src_texts,
249                                   jz4725b_codec_adc_src_values);
250 static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl =
251         SOC_DAPM_ENUM("ADC Source Capture Route", jz4725b_codec_adc_src_enum);
252 
253 static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = {
254         SOC_DAPM_SINGLE("Line In Bypass Playback Switch", JZ4725B_CODEC_REG_CR1,
255                         REG_CR1_BYPASS_OFFSET, 1, 0),
256         SOC_DAPM_SINGLE("Mic 1 Bypass Playback Switch", JZ4725B_CODEC_REG_CR3,
257                         REG_CR3_SIDETONE1_OFFSET, 1, 0),
258         SOC_DAPM_SINGLE("Mic 2 Bypass Playback Switch", JZ4725B_CODEC_REG_CR3,
259                         REG_CR3_SIDETONE2_OFFSET, 1, 0),
260 };
261 
262 static int jz4725b_out_stage_enable(struct snd_soc_dapm_widget *w,
263                                     struct snd_kcontrol *kcontrol,
264                                     int event)
265 {
266         struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
267         struct jz_icdc *icdc = snd_soc_component_get_drvdata(codec);
268         struct regmap *map = icdc->regmap;
269         unsigned int val;
270 
271         switch (event) {
272         case SND_SOC_DAPM_PRE_PMU:
273                 return regmap_clear_bits(map, JZ4725B_CODEC_REG_IFR,
274                                          BIT(REG_IFR_RAMP_UP_DONE_OFFSET));
275         case SND_SOC_DAPM_POST_PMU:
276                 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
277                                val, val & BIT(REG_IFR_RAMP_UP_DONE_OFFSET),
278                                100000, 500000);
279         case SND_SOC_DAPM_PRE_PMD:
280                 return regmap_clear_bits(map, JZ4725B_CODEC_REG_IFR,
281                                 BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET));
282         case SND_SOC_DAPM_POST_PMD:
283                 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
284                                val, val & BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET),
285                                100000, 500000);
286         default:
287                 return -EINVAL;
288         }
289 }
290 
291 static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = {
292         /* DAC */
293         SND_SOC_DAPM_DAC("DAC", "Playback",
294                          JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_DAC_OFFSET, 1),
295 
296         /* ADC */
297         SND_SOC_DAPM_ADC("ADC", "Capture",
298                          JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1),
299 
300         SND_SOC_DAPM_MUX("ADC Source Capture Route", SND_SOC_NOPM, 0, 0,
301                          &jz4725b_codec_adc_src_ctrl),
302 
303         /* Mixer */
304         SND_SOC_DAPM_MIXER("Mixer", JZ4725B_CODEC_REG_PMR1,
305                            REG_PMR1_SB_MIX_OFFSET, 1,
306                            jz4725b_codec_mixer_controls,
307                            ARRAY_SIZE(jz4725b_codec_mixer_controls)),
308         SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1,
309                            REG_CR1_DACSEL_OFFSET, 0, NULL, 0),
310 
311         SND_SOC_DAPM_MIXER("Line In", JZ4725B_CODEC_REG_PMR1,
312                            REG_PMR1_SB_LIN_OFFSET, 1, NULL, 0),
313         SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1,
314                            REG_CR1_HP_DIS_OFFSET, 1, NULL, 0),
315 
316         SND_SOC_DAPM_MIXER("Mic 1", JZ4725B_CODEC_REG_CR3,
317                            REG_CR3_SB_MIC1_OFFSET, 1, NULL, 0),
318         SND_SOC_DAPM_MIXER("Mic 2", JZ4725B_CODEC_REG_CR3,
319                            REG_CR3_SB_MIC2_OFFSET, 1, NULL, 0),
320 
321         SND_SOC_DAPM_MIXER_E("Out Stage", JZ4725B_CODEC_REG_PMR1,
322                              REG_PMR1_SB_OUT_OFFSET, 1, NULL, 0,
323                              jz4725b_out_stage_enable,
324                              SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
325                              SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
326         SND_SOC_DAPM_MIXER("Mixer to ADC", JZ4725B_CODEC_REG_PMR1,
327                            REG_PMR1_SB_IND_OFFSET, 1, NULL, 0),
328 
329         SND_SOC_DAPM_SUPPLY("Mic Bias", JZ4725B_CODEC_REG_CR1,
330                             REG_CR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
331 
332         /* Pins */
333         SND_SOC_DAPM_INPUT("MIC1P"),
334         SND_SOC_DAPM_INPUT("MIC1N"),
335         SND_SOC_DAPM_INPUT("MIC2P"),
336         SND_SOC_DAPM_INPUT("MIC2N"),
337 
338         SND_SOC_DAPM_INPUT("LLINEIN"),
339         SND_SOC_DAPM_INPUT("RLINEIN"),
340 
341         SND_SOC_DAPM_OUTPUT("LHPOUT"),
342         SND_SOC_DAPM_OUTPUT("RHPOUT"),
343 };
344 
345 static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = {
346         {"Mic 1", NULL, "MIC1P"},
347         {"Mic 1", NULL, "MIC1N"},
348         {"Mic 2", NULL, "MIC2P"},
349         {"Mic 2", NULL, "MIC2N"},
350 
351         {"Line In", NULL, "LLINEIN"},
352         {"Line In", NULL, "RLINEIN"},
353 
354         {"Mixer", "Mic 1 Bypass Playback Switch", "Mic 1"},
355         {"Mixer", "Mic 2 Bypass Playback Switch", "Mic 2"},
356         {"Mixer", "Line In Bypass Playback Switch", "Line In"},
357         {"DAC to Mixer", NULL, "DAC"},
358         {"Mixer", NULL, "DAC to Mixer"},
359 
360         {"Mixer to ADC", NULL, "Mixer"},
361         {"ADC Source Capture Route", "Mixer", "Mixer to ADC"},
362         {"ADC Source Capture Route", "Line In", "Line In"},
363         {"ADC Source Capture Route", "Mic 1", "Mic 1"},
364         {"ADC Source Capture Route", "Mic 2", "Mic 2"},
365         {"ADC", NULL, "ADC Source Capture Route"},
366 
367         {"Out Stage", NULL, "Mixer"},
368         {"HP Out", NULL, "Out Stage"},
369         {"LHPOUT", NULL, "HP Out"},
370         {"RHPOUT", NULL, "HP Out"},
371 };
372 
373 static int jz4725b_codec_set_bias_level(struct snd_soc_component *component,
374                                         enum snd_soc_bias_level level)
375 {
376         struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
377         struct regmap *map = icdc->regmap;
378 
379         switch (level) {
380         case SND_SOC_BIAS_ON:
381                 regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2,
382                                   BIT(REG_PMR2_SB_SLEEP_OFFSET));
383                 break;
384         case SND_SOC_BIAS_PREPARE:
385                 /* Enable sound hardware */
386                 regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2,
387                                   BIT(REG_PMR2_SB_OFFSET));
388                 msleep(224);
389                 break;
390         case SND_SOC_BIAS_STANDBY:
391                 regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2,
392                                 BIT(REG_PMR2_SB_SLEEP_OFFSET));
393                 break;
394         case SND_SOC_BIAS_OFF:
395                 regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2,
396                                 BIT(REG_PMR2_SB_OFFSET));
397                 break;
398         }
399 
400         return 0;
401 }
402 
403 static int jz4725b_codec_dev_probe(struct snd_soc_component *component)
404 {
405         struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
406         struct regmap *map = icdc->regmap;
407 
408         clk_prepare_enable(icdc->clk);
409 
410         /* Write CONFIGn (n=1 to 8) bits.
411          * The value 0x0f is specified in the datasheet as a requirement.
412          */
413         regmap_write(map, JZ4725B_CODEC_REG_AICR,
414                      0xf << REG_AICR_CONFIG1_OFFSET);
415         regmap_write(map, JZ4725B_CODEC_REG_CCR1,
416                      0x0 << REG_CCR1_CONFIG4_OFFSET);
417 
418         return 0;
419 }
420 
421 static void jz4725b_codec_dev_remove(struct snd_soc_component *component)
422 {
423         struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
424 
425         clk_disable_unprepare(icdc->clk);
426 }
427 
428 static const struct snd_soc_component_driver jz4725b_codec = {
429         .probe                  = jz4725b_codec_dev_probe,
430         .remove                 = jz4725b_codec_dev_remove,
431         .set_bias_level         = jz4725b_codec_set_bias_level,
432         .controls               = jz4725b_codec_controls,
433         .num_controls           = ARRAY_SIZE(jz4725b_codec_controls),
434         .dapm_widgets           = jz4725b_codec_dapm_widgets,
435         .num_dapm_widgets       = ARRAY_SIZE(jz4725b_codec_dapm_widgets),
436         .dapm_routes            = jz4725b_codec_dapm_routes,
437         .num_dapm_routes        = ARRAY_SIZE(jz4725b_codec_dapm_routes),
438         .suspend_bias_off       = 1,
439         .use_pmdown_time        = 1,
440 };
441 
442 static const unsigned int jz4725b_codec_sample_rates[] = {
443         96000, 48000, 44100, 32000,
444         24000, 22050, 16000, 12000,
445         11025, 9600, 8000,
446 };
447 
448 static int jz4725b_codec_hw_params(struct snd_pcm_substream *substream,
449         struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
450 {
451         struct jz_icdc *icdc = snd_soc_component_get_drvdata(dai->component);
452         unsigned int rate, bit_width;
453 
454         switch (params_format(params)) {
455         case SNDRV_PCM_FORMAT_S16_LE:
456                 bit_width = 0;
457                 break;
458         case SNDRV_PCM_FORMAT_S18_3LE:
459                 bit_width = 1;
460                 break;
461         case SNDRV_PCM_FORMAT_S20_3LE:
462                 bit_width = 2;
463                 break;
464         case SNDRV_PCM_FORMAT_S24_3LE:
465                 bit_width = 3;
466                 break;
467         default:
468                 return -EINVAL;
469         }
470 
471         for (rate = 0; rate < ARRAY_SIZE(jz4725b_codec_sample_rates); rate++) {
472                 if (jz4725b_codec_sample_rates[rate] == params_rate(params))
473                         break;
474         }
475 
476         if (rate == ARRAY_SIZE(jz4725b_codec_sample_rates))
477                 return -EINVAL;
478 
479         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
480                 regmap_update_bits(icdc->regmap,
481                                    JZ4725B_CODEC_REG_CR2,
482                                    REG_CR2_DAC_ADWL_MASK,
483                                    bit_width << REG_CR2_DAC_ADWL_OFFSET);
484 
485                 regmap_update_bits(icdc->regmap,
486                                    JZ4725B_CODEC_REG_CCR2,
487                                    REG_CCR2_DFREQ_MASK,
488                                    rate << REG_CCR2_DFREQ_OFFSET);
489         } else {
490                 regmap_update_bits(icdc->regmap,
491                                    JZ4725B_CODEC_REG_CR2,
492                                    REG_CR2_ADC_ADWL_MASK,
493                                    bit_width << REG_CR2_ADC_ADWL_OFFSET);
494 
495                 regmap_update_bits(icdc->regmap,
496                                    JZ4725B_CODEC_REG_CCR2,
497                                    REG_CCR2_AFREQ_MASK,
498                                    rate << REG_CCR2_AFREQ_OFFSET);
499         }
500 
501         return 0;
502 }
503 
504 static const struct snd_soc_dai_ops jz4725b_codec_dai_ops = {
505         .hw_params = jz4725b_codec_hw_params,
506 };
507 
508 #define JZ_ICDC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_S18_3LE | \
509                          SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE)
510 
511 static struct snd_soc_dai_driver jz4725b_codec_dai = {
512         .name = "jz4725b-hifi",
513         .playback = {
514                 .stream_name = "Playback",
515                 .channels_min = 2,
516                 .channels_max = 2,
517                 .rates = SNDRV_PCM_RATE_8000_96000,
518                 .formats = JZ_ICDC_FORMATS,
519         },
520         .capture = {
521                 .stream_name = "Capture",
522                 .channels_min = 2,
523                 .channels_max = 2,
524                 .rates = SNDRV_PCM_RATE_8000_96000,
525                 .formats = JZ_ICDC_FORMATS,
526         },
527         .ops = &jz4725b_codec_dai_ops,
528 };
529 
530 static bool jz4725b_codec_volatile(struct device *dev, unsigned int reg)
531 {
532         return reg == JZ4725B_CODEC_REG_IFR;
533 }
534 
535 static bool jz4725b_codec_can_access_reg(struct device *dev, unsigned int reg)
536 {
537         return (reg != JZ4725B_CODEC_REG_TR1) && (reg != JZ4725B_CODEC_REG_TR2);
538 }
539 
540 static int jz4725b_codec_io_wait(struct jz_icdc *icdc)
541 {
542         u32 reg;
543 
544         return readl_poll_timeout(icdc->base + ICDC_RGADW_OFFSET, reg,
545                                   !(reg & ICDC_RGADW_RGWR), 1000, 10000);
546 }
547 
548 static int jz4725b_codec_reg_read(void *context, unsigned int reg,
549                                   unsigned int *val)
550 {
551         struct jz_icdc *icdc = context;
552         unsigned int i;
553         u32 tmp;
554         int ret;
555 
556         ret = jz4725b_codec_io_wait(icdc);
557         if (ret)
558                 return ret;
559 
560         tmp = readl(icdc->base + ICDC_RGADW_OFFSET);
561         tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
562             | (reg << ICDC_RGADW_RGADDR_OFFSET);
563         writel(tmp, icdc->base + ICDC_RGADW_OFFSET);
564 
565         /* wait 6+ cycles */
566         for (i = 0; i < 6; i++)
567                 *val = readl(icdc->base + ICDC_RGDATA_OFFSET) &
568                         ICDC_RGDATA_RGDOUT_MASK;
569 
570         return 0;
571 }
572 
573 static int jz4725b_codec_reg_write(void *context, unsigned int reg,
574                                    unsigned int val)
575 {
576         struct jz_icdc *icdc = context;
577         int ret;
578 
579         ret = jz4725b_codec_io_wait(icdc);
580         if (ret)
581                 return ret;
582 
583         writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
584                         icdc->base + ICDC_RGADW_OFFSET);
585 
586         ret = jz4725b_codec_io_wait(icdc);
587         if (ret)
588                 return ret;
589 
590         return 0;
591 }
592 
593 static const u8 jz4725b_codec_reg_defaults[] = {
594         0x0c, 0xaa, 0x78, 0x00, 0x00, 0xff, 0x03, 0x51,
595         0x3f, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
596         0x04, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0x34,
597         0x07, 0x44, 0x1f, 0x00,
598 };
599 
600 static const struct regmap_config jz4725b_codec_regmap_config = {
601         .reg_bits = 7,
602         .val_bits = 8,
603 
604         .max_register = JZ4725B_CODEC_REG_AGC5,
605         .volatile_reg = jz4725b_codec_volatile,
606         .readable_reg = jz4725b_codec_can_access_reg,
607         .writeable_reg = jz4725b_codec_can_access_reg,
608 
609         .reg_read = jz4725b_codec_reg_read,
610         .reg_write = jz4725b_codec_reg_write,
611 
612         .reg_defaults_raw = jz4725b_codec_reg_defaults,
613         .num_reg_defaults_raw = ARRAY_SIZE(jz4725b_codec_reg_defaults),
614         .cache_type = REGCACHE_FLAT,
615 };
616 
617 static int jz4725b_codec_probe(struct platform_device *pdev)
618 {
619         struct device *dev = &pdev->dev;
620         struct jz_icdc *icdc;
621         int ret;
622 
623         icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL);
624         if (!icdc)
625                 return -ENOMEM;
626 
627         icdc->base = devm_platform_ioremap_resource(pdev, 0);
628         if (IS_ERR(icdc->base))
629                 return PTR_ERR(icdc->base);
630 
631         icdc->regmap = devm_regmap_init(dev, NULL, icdc,
632                                         &jz4725b_codec_regmap_config);
633         if (IS_ERR(icdc->regmap))
634                 return PTR_ERR(icdc->regmap);
635 
636         icdc->clk = devm_clk_get(&pdev->dev, "aic");
637         if (IS_ERR(icdc->clk))
638                 return PTR_ERR(icdc->clk);
639 
640         platform_set_drvdata(pdev, icdc);
641 
642         ret = devm_snd_soc_register_component(dev, &jz4725b_codec,
643                                               &jz4725b_codec_dai, 1);
644         if (ret)
645                 dev_err(dev, "Failed to register codec\n");
646 
647         return ret;
648 }
649 
650 static const struct of_device_id jz4725b_codec_of_matches[] = {
651         { .compatible = "ingenic,jz4725b-codec", },
652         { }
653 };
654 MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches);
655 
656 static struct platform_driver jz4725b_codec_driver = {
657         .probe = jz4725b_codec_probe,
658         .driver = {
659                 .name = "jz4725b-codec",
660                 .of_match_table = jz4725b_codec_of_matches,
661         },
662 };
663 module_platform_driver(jz4725b_codec_driver);
664 
665 MODULE_DESCRIPTION("JZ4725B SoC internal codec driver");
666 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
667 MODULE_LICENSE("GPL v2");
668 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php