xref: /openbmc/linux/sound/soc/codecs/jz4725b.c (revision 519b58bb)
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 
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_clear_bits(map, JZ4725B_CODEC_REG_IFR,
205 					 BIT(REG_IFR_RAMP_UP_DONE_OFFSET));
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_clear_bits(map, JZ4725B_CODEC_REG_IFR,
212 				BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET));
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 
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_clear_bits(map, JZ4725B_CODEC_REG_PMR2,
311 				  BIT(REG_PMR2_SB_SLEEP_OFFSET));
312 		break;
313 	case SND_SOC_BIAS_PREPARE:
314 		/* Enable sound hardware */
315 		regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2,
316 				  BIT(REG_PMR2_SB_OFFSET));
317 		msleep(224);
318 		break;
319 	case SND_SOC_BIAS_STANDBY:
320 		regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2,
321 				BIT(REG_PMR2_SB_SLEEP_OFFSET));
322 		break;
323 	case SND_SOC_BIAS_OFF:
324 		regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2,
325 				BIT(REG_PMR2_SB_OFFSET));
326 		break;
327 	}
328 
329 	return 0;
330 }
331 
332 static int jz4725b_codec_dev_probe(struct snd_soc_component *component)
333 {
334 	struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
335 	struct regmap *map = icdc->regmap;
336 
337 	clk_prepare_enable(icdc->clk);
338 
339 	/* Write CONFIGn (n=1 to 8) bits.
340 	 * The value 0x0f is specified in the datasheet as a requirement.
341 	 */
342 	regmap_write(map, JZ4725B_CODEC_REG_AICR,
343 		     0xf << REG_AICR_CONFIG1_OFFSET);
344 	regmap_write(map, JZ4725B_CODEC_REG_CCR1,
345 		     0x0 << REG_CCR1_CONFIG4_OFFSET);
346 
347 	return 0;
348 }
349 
350 static void jz4725b_codec_dev_remove(struct snd_soc_component *component)
351 {
352 	struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
353 
354 	clk_disable_unprepare(icdc->clk);
355 }
356 
357 static const struct snd_soc_component_driver jz4725b_codec = {
358 	.probe			= jz4725b_codec_dev_probe,
359 	.remove			= jz4725b_codec_dev_remove,
360 	.set_bias_level		= jz4725b_codec_set_bias_level,
361 	.controls		= jz4725b_codec_controls,
362 	.num_controls		= ARRAY_SIZE(jz4725b_codec_controls),
363 	.dapm_widgets		= jz4725b_codec_dapm_widgets,
364 	.num_dapm_widgets	= ARRAY_SIZE(jz4725b_codec_dapm_widgets),
365 	.dapm_routes		= jz4725b_codec_dapm_routes,
366 	.num_dapm_routes	= ARRAY_SIZE(jz4725b_codec_dapm_routes),
367 	.suspend_bias_off	= 1,
368 	.use_pmdown_time	= 1,
369 };
370 
371 static const unsigned int jz4725b_codec_sample_rates[] = {
372 	96000, 48000, 44100, 32000,
373 	24000, 22050, 16000, 12000,
374 	11025, 9600, 8000,
375 };
376 
377 static int jz4725b_codec_hw_params(struct snd_pcm_substream *substream,
378 	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
379 {
380 	struct jz_icdc *icdc = snd_soc_component_get_drvdata(dai->component);
381 	unsigned int rate, bit_width;
382 
383 	switch (params_format(params)) {
384 	case SNDRV_PCM_FORMAT_S16_LE:
385 		bit_width = 0;
386 		break;
387 	case SNDRV_PCM_FORMAT_S18_3LE:
388 		bit_width = 1;
389 		break;
390 	case SNDRV_PCM_FORMAT_S20_3LE:
391 		bit_width = 2;
392 		break;
393 	case SNDRV_PCM_FORMAT_S24_3LE:
394 		bit_width = 3;
395 		break;
396 	default:
397 		return -EINVAL;
398 	}
399 
400 	for (rate = 0; rate < ARRAY_SIZE(jz4725b_codec_sample_rates); rate++) {
401 		if (jz4725b_codec_sample_rates[rate] == params_rate(params))
402 			break;
403 	}
404 
405 	if (rate == ARRAY_SIZE(jz4725b_codec_sample_rates))
406 		return -EINVAL;
407 
408 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
409 		regmap_update_bits(icdc->regmap,
410 				   JZ4725B_CODEC_REG_CR2,
411 				   REG_CR2_DAC_ADWL_MASK,
412 				   bit_width << REG_CR2_DAC_ADWL_OFFSET);
413 
414 		regmap_update_bits(icdc->regmap,
415 				   JZ4725B_CODEC_REG_CCR2,
416 				   REG_CCR2_DFREQ_MASK,
417 				   rate << REG_CCR2_DFREQ_OFFSET);
418 	} else {
419 		regmap_update_bits(icdc->regmap,
420 				   JZ4725B_CODEC_REG_CR2,
421 				   REG_CR2_ADC_ADWL_MASK,
422 				   bit_width << REG_CR2_ADC_ADWL_OFFSET);
423 
424 		regmap_update_bits(icdc->regmap,
425 				   JZ4725B_CODEC_REG_CCR2,
426 				   REG_CCR2_AFREQ_MASK,
427 				   rate << REG_CCR2_AFREQ_OFFSET);
428 	}
429 
430 	return 0;
431 }
432 
433 static const struct snd_soc_dai_ops jz4725b_codec_dai_ops = {
434 	.hw_params = jz4725b_codec_hw_params,
435 };
436 
437 #define JZ_ICDC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_S18_3LE | \
438 			 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE)
439 
440 static struct snd_soc_dai_driver jz4725b_codec_dai = {
441 	.name = "jz4725b-hifi",
442 	.playback = {
443 		.stream_name = "Playback",
444 		.channels_min = 2,
445 		.channels_max = 2,
446 		.rates = SNDRV_PCM_RATE_8000_96000,
447 		.formats = JZ_ICDC_FORMATS,
448 	},
449 	.capture = {
450 		.stream_name = "Capture",
451 		.channels_min = 2,
452 		.channels_max = 2,
453 		.rates = SNDRV_PCM_RATE_8000_96000,
454 		.formats = JZ_ICDC_FORMATS,
455 	},
456 	.ops = &jz4725b_codec_dai_ops,
457 };
458 
459 static bool jz4725b_codec_volatile(struct device *dev, unsigned int reg)
460 {
461 	return reg == JZ4725B_CODEC_REG_IFR;
462 }
463 
464 static bool jz4725b_codec_can_access_reg(struct device *dev, unsigned int reg)
465 {
466 	return (reg != JZ4725B_CODEC_REG_TR1) && (reg != JZ4725B_CODEC_REG_TR2);
467 }
468 
469 static int jz4725b_codec_io_wait(struct jz_icdc *icdc)
470 {
471 	u32 reg;
472 
473 	return readl_poll_timeout(icdc->base + ICDC_RGADW_OFFSET, reg,
474 				  !(reg & ICDC_RGADW_RGWR), 1000, 10000);
475 }
476 
477 static int jz4725b_codec_reg_read(void *context, unsigned int reg,
478 				  unsigned int *val)
479 {
480 	struct jz_icdc *icdc = context;
481 	unsigned int i;
482 	u32 tmp;
483 	int ret;
484 
485 	ret = jz4725b_codec_io_wait(icdc);
486 	if (ret)
487 		return ret;
488 
489 	tmp = readl(icdc->base + ICDC_RGADW_OFFSET);
490 	tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
491 	    | (reg << ICDC_RGADW_RGADDR_OFFSET);
492 	writel(tmp, icdc->base + ICDC_RGADW_OFFSET);
493 
494 	/* wait 6+ cycles */
495 	for (i = 0; i < 6; i++)
496 		*val = readl(icdc->base + ICDC_RGDATA_OFFSET) &
497 			ICDC_RGDATA_RGDOUT_MASK;
498 
499 	return 0;
500 }
501 
502 static int jz4725b_codec_reg_write(void *context, unsigned int reg,
503 				   unsigned int val)
504 {
505 	struct jz_icdc *icdc = context;
506 	int ret;
507 
508 	ret = jz4725b_codec_io_wait(icdc);
509 	if (ret)
510 		return ret;
511 
512 	writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
513 			icdc->base + ICDC_RGADW_OFFSET);
514 
515 	ret = jz4725b_codec_io_wait(icdc);
516 	if (ret)
517 		return ret;
518 
519 	return 0;
520 }
521 
522 static const u8 jz4725b_codec_reg_defaults[] = {
523 	0x0c, 0xaa, 0x78, 0x00, 0x00, 0xff, 0x03, 0x51,
524 	0x3f, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
525 	0x04, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0x34,
526 	0x07, 0x44, 0x1f, 0x00,
527 };
528 
529 static const struct regmap_config jz4725b_codec_regmap_config = {
530 	.reg_bits = 7,
531 	.val_bits = 8,
532 
533 	.max_register = JZ4725B_CODEC_REG_AGC5,
534 	.volatile_reg = jz4725b_codec_volatile,
535 	.readable_reg = jz4725b_codec_can_access_reg,
536 	.writeable_reg = jz4725b_codec_can_access_reg,
537 
538 	.reg_read = jz4725b_codec_reg_read,
539 	.reg_write = jz4725b_codec_reg_write,
540 
541 	.reg_defaults_raw = jz4725b_codec_reg_defaults,
542 	.num_reg_defaults_raw = ARRAY_SIZE(jz4725b_codec_reg_defaults),
543 	.cache_type = REGCACHE_FLAT,
544 };
545 
546 static int jz4725b_codec_probe(struct platform_device *pdev)
547 {
548 	struct device *dev = &pdev->dev;
549 	struct jz_icdc *icdc;
550 	int ret;
551 
552 	icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL);
553 	if (!icdc)
554 		return -ENOMEM;
555 
556 	icdc->base = devm_platform_ioremap_resource(pdev, 0);
557 	if (IS_ERR(icdc->base))
558 		return PTR_ERR(icdc->base);
559 
560 	icdc->regmap = devm_regmap_init(dev, NULL, icdc,
561 					&jz4725b_codec_regmap_config);
562 	if (IS_ERR(icdc->regmap))
563 		return PTR_ERR(icdc->regmap);
564 
565 	icdc->clk = devm_clk_get(&pdev->dev, "aic");
566 	if (IS_ERR(icdc->clk))
567 		return PTR_ERR(icdc->clk);
568 
569 	platform_set_drvdata(pdev, icdc);
570 
571 	ret = devm_snd_soc_register_component(dev, &jz4725b_codec,
572 					      &jz4725b_codec_dai, 1);
573 	if (ret)
574 		dev_err(dev, "Failed to register codec\n");
575 
576 	return ret;
577 }
578 
579 static const struct of_device_id jz4725b_codec_of_matches[] = {
580 	{ .compatible = "ingenic,jz4725b-codec", },
581 	{ }
582 };
583 MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches);
584 
585 static struct platform_driver jz4725b_codec_driver = {
586 	.probe = jz4725b_codec_probe,
587 	.driver = {
588 		.name = "jz4725b-codec",
589 		.of_match_table = jz4725b_codec_of_matches,
590 	},
591 };
592 module_platform_driver(jz4725b_codec_driver);
593 
594 MODULE_DESCRIPTION("JZ4725B SoC internal codec driver");
595 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
596 MODULE_LICENSE("GPL v2");
597