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_CGR10_GIL_OFFSET 0
140 #define REG_CGR10_GIR_OFFSET 4
141
142 struct jz_icdc {
143 struct regmap *regmap;
144 void __iomem *base;
145 struct clk *clk;
146 };
147
148 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_adc_tlv, 0, 150, 0);
149 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_dac_tlv, -2250, 150, 0);
150
151 static const struct snd_kcontrol_new jz4725b_codec_controls[] = {
152 SOC_DOUBLE_TLV("Master Playback Volume",
153 JZ4725B_CODEC_REG_CGR1,
154 REG_CGR1_GODL_OFFSET,
155 REG_CGR1_GODR_OFFSET,
156 0xf, 1, jz4725b_dac_tlv),
157 SOC_DOUBLE_TLV("Master Capture Volume",
158 JZ4725B_CODEC_REG_CGR10,
159 REG_CGR10_GIL_OFFSET,
160 REG_CGR10_GIR_OFFSET,
161 0xf, 0, jz4725b_adc_tlv),
162
163 SOC_SINGLE("Master Playback Switch", JZ4725B_CODEC_REG_CR1,
164 REG_CR1_DAC_MUTE_OFFSET, 1, 1),
165
166 SOC_SINGLE("Deemphasize Filter Playback Switch",
167 JZ4725B_CODEC_REG_CR2,
168 REG_CR2_DAC_DEEMP_OFFSET, 1, 0),
169
170 SOC_SINGLE("High-Pass Filter Capture Switch",
171 JZ4725B_CODEC_REG_CR2,
172 REG_CR2_ADC_HPF_OFFSET, 1, 0),
173 };
174
175 static const char * const jz4725b_codec_adc_src_texts[] = {
176 "Mic 1", "Mic 2", "Line In", "Mixer",
177 };
178 static const unsigned int jz4725b_codec_adc_src_values[] = { 0, 1, 2, 3, };
179 static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum,
180 JZ4725B_CODEC_REG_CR3,
181 REG_CR3_INSEL_OFFSET,
182 REG_CR3_INSEL_MASK,
183 jz4725b_codec_adc_src_texts,
184 jz4725b_codec_adc_src_values);
185 static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl =
186 SOC_DAPM_ENUM("ADC Source Capture Route", jz4725b_codec_adc_src_enum);
187
188 static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = {
189 SOC_DAPM_SINGLE("Line In Bypass", JZ4725B_CODEC_REG_CR1,
190 REG_CR1_BYPASS_OFFSET, 1, 0),
191 };
192
jz4725b_out_stage_enable(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)193 static int jz4725b_out_stage_enable(struct snd_soc_dapm_widget *w,
194 struct snd_kcontrol *kcontrol,
195 int event)
196 {
197 struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
198 struct jz_icdc *icdc = snd_soc_component_get_drvdata(codec);
199 struct regmap *map = icdc->regmap;
200 unsigned int val;
201
202 switch (event) {
203 case SND_SOC_DAPM_PRE_PMU:
204 return regmap_update_bits(map, JZ4725B_CODEC_REG_IFR,
205 BIT(REG_IFR_RAMP_UP_DONE_OFFSET), 0);
206 case SND_SOC_DAPM_POST_PMU:
207 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
208 val, val & BIT(REG_IFR_RAMP_UP_DONE_OFFSET),
209 100000, 500000);
210 case SND_SOC_DAPM_PRE_PMD:
211 return regmap_update_bits(map, JZ4725B_CODEC_REG_IFR,
212 BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET), 0);
213 case SND_SOC_DAPM_POST_PMD:
214 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
215 val, val & BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET),
216 100000, 500000);
217 default:
218 return -EINVAL;
219 }
220 }
221
222 static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = {
223 /* DAC */
224 SND_SOC_DAPM_DAC("DAC", "Playback",
225 JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_DAC_OFFSET, 1),
226
227 /* ADC */
228 SND_SOC_DAPM_ADC("ADC", "Capture",
229 JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1),
230
231 SND_SOC_DAPM_MUX("ADC Source Capture Route", SND_SOC_NOPM, 0, 0,
232 &jz4725b_codec_adc_src_ctrl),
233
234 /* Mixer */
235 SND_SOC_DAPM_MIXER("Mixer", JZ4725B_CODEC_REG_PMR1,
236 REG_PMR1_SB_MIX_OFFSET, 1,
237 jz4725b_codec_mixer_controls,
238 ARRAY_SIZE(jz4725b_codec_mixer_controls)),
239 SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1,
240 REG_CR1_DACSEL_OFFSET, 0, NULL, 0),
241
242 SND_SOC_DAPM_MIXER("Line In", JZ4725B_CODEC_REG_PMR1,
243 REG_PMR1_SB_LIN_OFFSET, 1, NULL, 0),
244 SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1,
245 REG_CR1_HP_DIS_OFFSET, 1, NULL, 0),
246
247 SND_SOC_DAPM_MIXER("Mic 1", JZ4725B_CODEC_REG_CR3,
248 REG_CR3_SB_MIC1_OFFSET, 1, NULL, 0),
249 SND_SOC_DAPM_MIXER("Mic 2", JZ4725B_CODEC_REG_CR3,
250 REG_CR3_SB_MIC2_OFFSET, 1, NULL, 0),
251
252 SND_SOC_DAPM_MIXER_E("Out Stage", JZ4725B_CODEC_REG_PMR1,
253 REG_PMR1_SB_OUT_OFFSET, 1, NULL, 0,
254 jz4725b_out_stage_enable,
255 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
256 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
257 SND_SOC_DAPM_MIXER("Mixer to ADC", JZ4725B_CODEC_REG_PMR1,
258 REG_PMR1_SB_IND_OFFSET, 1, NULL, 0),
259
260 SND_SOC_DAPM_SUPPLY("Mic Bias", JZ4725B_CODEC_REG_CR1,
261 REG_CR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
262
263 /* Pins */
264 SND_SOC_DAPM_INPUT("MIC1P"),
265 SND_SOC_DAPM_INPUT("MIC1N"),
266 SND_SOC_DAPM_INPUT("MIC2P"),
267 SND_SOC_DAPM_INPUT("MIC2N"),
268
269 SND_SOC_DAPM_INPUT("LLINEIN"),
270 SND_SOC_DAPM_INPUT("RLINEIN"),
271
272 SND_SOC_DAPM_OUTPUT("LHPOUT"),
273 SND_SOC_DAPM_OUTPUT("RHPOUT"),
274 };
275
276 static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = {
277 {"Mic 1", NULL, "MIC1P"},
278 {"Mic 1", NULL, "MIC1N"},
279 {"Mic 2", NULL, "MIC2P"},
280 {"Mic 2", NULL, "MIC2N"},
281
282 {"Line In", NULL, "LLINEIN"},
283 {"Line In", NULL, "RLINEIN"},
284
285 {"Mixer", "Line In Bypass", "Line In"},
286 {"DAC to Mixer", NULL, "DAC"},
287 {"Mixer", NULL, "DAC to Mixer"},
288
289 {"Mixer to ADC", NULL, "Mixer"},
290 {"ADC Source Capture Route", "Mixer", "Mixer to ADC"},
291 {"ADC Source Capture Route", "Line In", "Line In"},
292 {"ADC Source Capture Route", "Mic 1", "Mic 1"},
293 {"ADC Source Capture Route", "Mic 2", "Mic 2"},
294 {"ADC", NULL, "ADC Source Capture Route"},
295
296 {"Out Stage", NULL, "Mixer"},
297 {"HP Out", NULL, "Out Stage"},
298 {"LHPOUT", NULL, "HP Out"},
299 {"RHPOUT", NULL, "HP Out"},
300 };
301
jz4725b_codec_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)302 static int jz4725b_codec_set_bias_level(struct snd_soc_component *component,
303 enum snd_soc_bias_level level)
304 {
305 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
306 struct regmap *map = icdc->regmap;
307
308 switch (level) {
309 case SND_SOC_BIAS_ON:
310 regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
311 BIT(REG_PMR2_SB_SLEEP_OFFSET), 0);
312 break;
313 case SND_SOC_BIAS_PREPARE:
314 /* Enable sound hardware */
315 regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
316 BIT(REG_PMR2_SB_OFFSET), 0);
317 msleep(224);
318 break;
319 case SND_SOC_BIAS_STANDBY:
320 regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
321 BIT(REG_PMR2_SB_SLEEP_OFFSET),
322 BIT(REG_PMR2_SB_SLEEP_OFFSET));
323 break;
324 case SND_SOC_BIAS_OFF:
325 regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
326 BIT(REG_PMR2_SB_OFFSET),
327 BIT(REG_PMR2_SB_OFFSET));
328 break;
329 }
330
331 return 0;
332 }
333
jz4725b_codec_dev_probe(struct snd_soc_component * component)334 static int jz4725b_codec_dev_probe(struct snd_soc_component *component)
335 {
336 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
337 struct regmap *map = icdc->regmap;
338
339 clk_prepare_enable(icdc->clk);
340
341 /* Write CONFIGn (n=1 to 8) bits.
342 * The value 0x0f is specified in the datasheet as a requirement.
343 */
344 regmap_write(map, JZ4725B_CODEC_REG_AICR,
345 0xf << REG_AICR_CONFIG1_OFFSET);
346 regmap_write(map, JZ4725B_CODEC_REG_CCR1,
347 0x0 << REG_CCR1_CONFIG4_OFFSET);
348
349 return 0;
350 }
351
jz4725b_codec_dev_remove(struct snd_soc_component * component)352 static void jz4725b_codec_dev_remove(struct snd_soc_component *component)
353 {
354 struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
355
356 clk_disable_unprepare(icdc->clk);
357 }
358
359 static const struct snd_soc_component_driver jz4725b_codec = {
360 .probe = jz4725b_codec_dev_probe,
361 .remove = jz4725b_codec_dev_remove,
362 .set_bias_level = jz4725b_codec_set_bias_level,
363 .controls = jz4725b_codec_controls,
364 .num_controls = ARRAY_SIZE(jz4725b_codec_controls),
365 .dapm_widgets = jz4725b_codec_dapm_widgets,
366 .num_dapm_widgets = ARRAY_SIZE(jz4725b_codec_dapm_widgets),
367 .dapm_routes = jz4725b_codec_dapm_routes,
368 .num_dapm_routes = ARRAY_SIZE(jz4725b_codec_dapm_routes),
369 .suspend_bias_off = 1,
370 .use_pmdown_time = 1,
371 };
372
373 static const unsigned int jz4725b_codec_sample_rates[] = {
374 96000, 48000, 44100, 32000,
375 24000, 22050, 16000, 12000,
376 11025, 9600, 8000,
377 };
378
jz4725b_codec_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)379 static int jz4725b_codec_hw_params(struct snd_pcm_substream *substream,
380 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
381 {
382 struct jz_icdc *icdc = snd_soc_component_get_drvdata(dai->component);
383 unsigned int rate, bit_width;
384
385 switch (params_format(params)) {
386 case SNDRV_PCM_FORMAT_S16_LE:
387 bit_width = 0;
388 break;
389 case SNDRV_PCM_FORMAT_S18_3LE:
390 bit_width = 1;
391 break;
392 case SNDRV_PCM_FORMAT_S20_3LE:
393 bit_width = 2;
394 break;
395 case SNDRV_PCM_FORMAT_S24_3LE:
396 bit_width = 3;
397 break;
398 default:
399 return -EINVAL;
400 }
401
402 for (rate = 0; rate < ARRAY_SIZE(jz4725b_codec_sample_rates); rate++) {
403 if (jz4725b_codec_sample_rates[rate] == params_rate(params))
404 break;
405 }
406
407 if (rate == ARRAY_SIZE(jz4725b_codec_sample_rates))
408 return -EINVAL;
409
410 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
411 regmap_update_bits(icdc->regmap,
412 JZ4725B_CODEC_REG_CR2,
413 REG_CR2_DAC_ADWL_MASK,
414 bit_width << REG_CR2_DAC_ADWL_OFFSET);
415
416 regmap_update_bits(icdc->regmap,
417 JZ4725B_CODEC_REG_CCR2,
418 REG_CCR2_DFREQ_MASK,
419 rate << REG_CCR2_DFREQ_OFFSET);
420 } else {
421 regmap_update_bits(icdc->regmap,
422 JZ4725B_CODEC_REG_CR2,
423 REG_CR2_ADC_ADWL_MASK,
424 bit_width << REG_CR2_ADC_ADWL_OFFSET);
425
426 regmap_update_bits(icdc->regmap,
427 JZ4725B_CODEC_REG_CCR2,
428 REG_CCR2_AFREQ_MASK,
429 rate << REG_CCR2_AFREQ_OFFSET);
430 }
431
432 return 0;
433 }
434
435 static const struct snd_soc_dai_ops jz4725b_codec_dai_ops = {
436 .hw_params = jz4725b_codec_hw_params,
437 };
438
439 #define JZ_ICDC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
440 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE)
441
442 static struct snd_soc_dai_driver jz4725b_codec_dai = {
443 .name = "jz4725b-hifi",
444 .playback = {
445 .stream_name = "Playback",
446 .channels_min = 2,
447 .channels_max = 2,
448 .rates = SNDRV_PCM_RATE_8000_96000,
449 .formats = JZ_ICDC_FORMATS,
450 },
451 .capture = {
452 .stream_name = "Capture",
453 .channels_min = 2,
454 .channels_max = 2,
455 .rates = SNDRV_PCM_RATE_8000_96000,
456 .formats = JZ_ICDC_FORMATS,
457 },
458 .ops = &jz4725b_codec_dai_ops,
459 };
460
jz4725b_codec_volatile(struct device * dev,unsigned int reg)461 static bool jz4725b_codec_volatile(struct device *dev, unsigned int reg)
462 {
463 return reg == JZ4725B_CODEC_REG_IFR;
464 }
465
jz4725b_codec_can_access_reg(struct device * dev,unsigned int reg)466 static bool jz4725b_codec_can_access_reg(struct device *dev, unsigned int reg)
467 {
468 return (reg != JZ4725B_CODEC_REG_TR1) && (reg != JZ4725B_CODEC_REG_TR2);
469 }
470
jz4725b_codec_io_wait(struct jz_icdc * icdc)471 static int jz4725b_codec_io_wait(struct jz_icdc *icdc)
472 {
473 u32 reg;
474
475 return readl_poll_timeout(icdc->base + ICDC_RGADW_OFFSET, reg,
476 !(reg & ICDC_RGADW_RGWR), 1000, 10000);
477 }
478
jz4725b_codec_reg_read(void * context,unsigned int reg,unsigned int * val)479 static int jz4725b_codec_reg_read(void *context, unsigned int reg,
480 unsigned int *val)
481 {
482 struct jz_icdc *icdc = context;
483 unsigned int i;
484 u32 tmp;
485 int ret;
486
487 ret = jz4725b_codec_io_wait(icdc);
488 if (ret)
489 return ret;
490
491 tmp = readl(icdc->base + ICDC_RGADW_OFFSET);
492 tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
493 | (reg << ICDC_RGADW_RGADDR_OFFSET);
494 writel(tmp, icdc->base + ICDC_RGADW_OFFSET);
495
496 /* wait 6+ cycles */
497 for (i = 0; i < 6; i++)
498 *val = readl(icdc->base + ICDC_RGDATA_OFFSET) &
499 ICDC_RGDATA_RGDOUT_MASK;
500
501 return 0;
502 }
503
jz4725b_codec_reg_write(void * context,unsigned int reg,unsigned int val)504 static int jz4725b_codec_reg_write(void *context, unsigned int reg,
505 unsigned int val)
506 {
507 struct jz_icdc *icdc = context;
508 int ret;
509
510 ret = jz4725b_codec_io_wait(icdc);
511 if (ret)
512 return ret;
513
514 writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
515 icdc->base + ICDC_RGADW_OFFSET);
516
517 ret = jz4725b_codec_io_wait(icdc);
518 if (ret)
519 return ret;
520
521 return 0;
522 }
523
524 static const u8 jz4725b_codec_reg_defaults[] = {
525 0x0c, 0xaa, 0x78, 0x00, 0x00, 0xff, 0x03, 0x51,
526 0x3f, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
527 0x04, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0x34,
528 0x07, 0x44, 0x1f, 0x00,
529 };
530
531 static const struct regmap_config jz4725b_codec_regmap_config = {
532 .reg_bits = 7,
533 .val_bits = 8,
534
535 .max_register = JZ4725B_CODEC_REG_AGC5,
536 .volatile_reg = jz4725b_codec_volatile,
537 .readable_reg = jz4725b_codec_can_access_reg,
538 .writeable_reg = jz4725b_codec_can_access_reg,
539
540 .reg_read = jz4725b_codec_reg_read,
541 .reg_write = jz4725b_codec_reg_write,
542
543 .reg_defaults_raw = jz4725b_codec_reg_defaults,
544 .num_reg_defaults_raw = ARRAY_SIZE(jz4725b_codec_reg_defaults),
545 .cache_type = REGCACHE_FLAT,
546 };
547
jz4725b_codec_probe(struct platform_device * pdev)548 static int jz4725b_codec_probe(struct platform_device *pdev)
549 {
550 struct device *dev = &pdev->dev;
551 struct jz_icdc *icdc;
552 int ret;
553
554 icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL);
555 if (!icdc)
556 return -ENOMEM;
557
558 icdc->base = devm_platform_ioremap_resource(pdev, 0);
559 if (IS_ERR(icdc->base))
560 return PTR_ERR(icdc->base);
561
562 icdc->regmap = devm_regmap_init(dev, NULL, icdc,
563 &jz4725b_codec_regmap_config);
564 if (IS_ERR(icdc->regmap))
565 return PTR_ERR(icdc->regmap);
566
567 icdc->clk = devm_clk_get(&pdev->dev, "aic");
568 if (IS_ERR(icdc->clk))
569 return PTR_ERR(icdc->clk);
570
571 platform_set_drvdata(pdev, icdc);
572
573 ret = devm_snd_soc_register_component(dev, &jz4725b_codec,
574 &jz4725b_codec_dai, 1);
575 if (ret)
576 dev_err(dev, "Failed to register codec\n");
577
578 return ret;
579 }
580
581 static const struct of_device_id jz4725b_codec_of_matches[] = {
582 { .compatible = "ingenic,jz4725b-codec", },
583 { }
584 };
585 MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches);
586
587 static struct platform_driver jz4725b_codec_driver = {
588 .probe = jz4725b_codec_probe,
589 .driver = {
590 .name = "jz4725b-codec",
591 .of_match_table = jz4725b_codec_of_matches,
592 },
593 };
594 module_platform_driver(jz4725b_codec_driver);
595
596 MODULE_DESCRIPTION("JZ4725B SoC internal codec driver");
597 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
598 MODULE_LICENSE("GPL v2");
599