1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // rk3328 ALSA SoC Audio driver
4 //
5 // Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
6
7 #include <linux/clk.h>
8 #include <linux/delay.h>
9 #include <linux/device.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/platform_device.h>
14 #include <linux/regmap.h>
15 #include <linux/mfd/syscon.h>
16 #include <sound/dmaengine_pcm.h>
17 #include <sound/pcm_params.h>
18 #include "rk3328_codec.h"
19
20 /*
21 * volume setting
22 * 0: -39dB
23 * 26: 0dB
24 * 31: 6dB
25 * Step: 1.5dB
26 */
27 #define OUT_VOLUME (0x18)
28 #define RK3328_GRF_SOC_CON2 (0x0408)
29 #define RK3328_GRF_SOC_CON10 (0x0428)
30 #define INITIAL_FREQ (11289600)
31
32 struct rk3328_codec_priv {
33 struct regmap *regmap;
34 struct gpio_desc *mute;
35 struct clk *mclk;
36 struct clk *pclk;
37 unsigned int sclk;
38 int spk_depop_time; /* msec */
39 };
40
41 static const struct reg_default rk3328_codec_reg_defaults[] = {
42 { CODEC_RESET, 0x03 },
43 { DAC_INIT_CTRL1, 0x00 },
44 { DAC_INIT_CTRL2, 0x50 },
45 { DAC_INIT_CTRL3, 0x0e },
46 { DAC_PRECHARGE_CTRL, 0x01 },
47 { DAC_PWR_CTRL, 0x00 },
48 { DAC_CLK_CTRL, 0x00 },
49 { HPMIX_CTRL, 0x00 },
50 { HPOUT_CTRL, 0x00 },
51 { HPOUTL_GAIN_CTRL, 0x00 },
52 { HPOUTR_GAIN_CTRL, 0x00 },
53 { HPOUT_POP_CTRL, 0x11 },
54 };
55
rk3328_codec_reset(struct rk3328_codec_priv * rk3328)56 static int rk3328_codec_reset(struct rk3328_codec_priv *rk3328)
57 {
58 regmap_write(rk3328->regmap, CODEC_RESET, 0x00);
59 mdelay(10);
60 regmap_write(rk3328->regmap, CODEC_RESET, 0x03);
61
62 return 0;
63 }
64
rk3328_set_dai_fmt(struct snd_soc_dai * dai,unsigned int fmt)65 static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
66 {
67 struct rk3328_codec_priv *rk3328 =
68 snd_soc_component_get_drvdata(dai->component);
69 unsigned int val;
70
71 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
72 case SND_SOC_DAIFMT_CBC_CFC:
73 val = PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE;
74 break;
75 case SND_SOC_DAIFMT_CBP_CFP:
76 val = PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER;
77 break;
78 default:
79 return -EINVAL;
80 }
81
82 regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL1,
83 PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val);
84
85 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
86 case SND_SOC_DAIFMT_DSP_A:
87 case SND_SOC_DAIFMT_DSP_B:
88 val = DAC_MODE_PCM;
89 break;
90 case SND_SOC_DAIFMT_I2S:
91 val = DAC_MODE_I2S;
92 break;
93 case SND_SOC_DAIFMT_RIGHT_J:
94 val = DAC_MODE_RJM;
95 break;
96 case SND_SOC_DAIFMT_LEFT_J:
97 val = DAC_MODE_LJM;
98 break;
99 default:
100 return -EINVAL;
101 }
102
103 regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2,
104 DAC_MODE_MASK, val);
105
106 return 0;
107 }
108
rk3328_mute_stream(struct snd_soc_dai * dai,int mute,int direction)109 static int rk3328_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
110 {
111 struct rk3328_codec_priv *rk3328 =
112 snd_soc_component_get_drvdata(dai->component);
113 unsigned int val;
114
115 if (mute)
116 val = HPOUTL_MUTE | HPOUTR_MUTE;
117 else
118 val = HPOUTL_UNMUTE | HPOUTR_UNMUTE;
119
120 regmap_update_bits(rk3328->regmap, HPOUT_CTRL,
121 HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val);
122
123 return 0;
124 }
125
rk3328_codec_power_on(struct rk3328_codec_priv * rk3328,int wait_ms)126 static int rk3328_codec_power_on(struct rk3328_codec_priv *rk3328, int wait_ms)
127 {
128 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
129 DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE);
130 mdelay(10);
131 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
132 DAC_CHARGE_CURRENT_ALL_MASK,
133 DAC_CHARGE_CURRENT_ALL_ON);
134 mdelay(wait_ms);
135
136 return 0;
137 }
138
rk3328_codec_power_off(struct rk3328_codec_priv * rk3328,int wait_ms)139 static int rk3328_codec_power_off(struct rk3328_codec_priv *rk3328, int wait_ms)
140 {
141 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
142 DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE);
143 mdelay(10);
144 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
145 DAC_CHARGE_CURRENT_ALL_MASK,
146 DAC_CHARGE_CURRENT_ALL_ON);
147 mdelay(wait_ms);
148
149 return 0;
150 }
151
152 static const struct rk3328_reg_msk_val playback_open_list[] = {
153 { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON },
154 { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
155 DACL_PATH_REFV_ON | DACR_PATH_REFV_ON },
156 { DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_MASK | HPOUTR_ZERO_CROSSING_MASK,
157 HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON },
158 { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
159 HPOUTR_POP_WORK | HPOUTL_POP_WORK },
160 { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_EN | HPMIXR_EN },
161 { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
162 HPMIXL_INIT_EN | HPMIXR_INIT_EN },
163 { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_EN | HPOUTR_EN },
164 { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
165 HPOUTL_INIT_EN | HPOUTR_INIT_EN },
166 { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
167 DACL_REFV_ON | DACR_REFV_ON },
168 { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
169 DACL_CLK_ON | DACR_CLK_ON },
170 { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_ON | DACR_ON },
171 { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
172 DACL_INIT_ON | DACR_INIT_ON },
173 { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
174 DACL_SELECT | DACR_SELECT },
175 { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
176 HPMIXL_INIT2_EN | HPMIXR_INIT2_EN },
177 { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
178 HPOUTL_UNMUTE | HPOUTR_UNMUTE },
179 };
180
rk3328_codec_open_playback(struct rk3328_codec_priv * rk3328)181 static int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328)
182 {
183 int i;
184
185 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
186 DAC_CHARGE_CURRENT_ALL_MASK,
187 DAC_CHARGE_CURRENT_I);
188
189 for (i = 0; i < ARRAY_SIZE(playback_open_list); i++) {
190 regmap_update_bits(rk3328->regmap,
191 playback_open_list[i].reg,
192 playback_open_list[i].msk,
193 playback_open_list[i].val);
194 mdelay(1);
195 }
196
197 msleep(rk3328->spk_depop_time);
198 gpiod_set_value(rk3328->mute, 0);
199
200 regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
201 HPOUTL_GAIN_MASK, OUT_VOLUME);
202 regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
203 HPOUTR_GAIN_MASK, OUT_VOLUME);
204
205 return 0;
206 }
207
208 static const struct rk3328_reg_msk_val playback_close_list[] = {
209 { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
210 HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS },
211 { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
212 DACL_UNSELECT | DACR_UNSELECT },
213 { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
214 HPOUTL_MUTE | HPOUTR_MUTE },
215 { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
216 HPOUTL_INIT_DIS | HPOUTR_INIT_DIS },
217 { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_DIS | HPOUTR_DIS },
218 { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_DIS | HPMIXR_DIS },
219 { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_OFF | DACR_OFF },
220 { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
221 DACL_CLK_OFF | DACR_CLK_OFF },
222 { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
223 DACL_REFV_OFF | DACR_REFV_OFF },
224 { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
225 HPOUTR_POP_XCHARGE | HPOUTL_POP_XCHARGE },
226 { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
227 DACL_PATH_REFV_OFF | DACR_PATH_REFV_OFF },
228 { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_OFF },
229 { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
230 HPMIXL_INIT_DIS | HPMIXR_INIT_DIS },
231 { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
232 DACL_INIT_OFF | DACR_INIT_OFF },
233 };
234
rk3328_codec_close_playback(struct rk3328_codec_priv * rk3328)235 static int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328)
236 {
237 size_t i;
238
239 gpiod_set_value(rk3328->mute, 1);
240
241 regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
242 HPOUTL_GAIN_MASK, 0);
243 regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
244 HPOUTR_GAIN_MASK, 0);
245
246 for (i = 0; i < ARRAY_SIZE(playback_close_list); i++) {
247 regmap_update_bits(rk3328->regmap,
248 playback_close_list[i].reg,
249 playback_close_list[i].msk,
250 playback_close_list[i].val);
251 mdelay(1);
252 }
253
254 /* Workaround for silence when changed Fs 48 -> 44.1kHz */
255 rk3328_codec_reset(rk3328);
256
257 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
258 DAC_CHARGE_CURRENT_ALL_MASK,
259 DAC_CHARGE_CURRENT_ALL_ON);
260
261 return 0;
262 }
263
rk3328_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)264 static int rk3328_hw_params(struct snd_pcm_substream *substream,
265 struct snd_pcm_hw_params *params,
266 struct snd_soc_dai *dai)
267 {
268 struct rk3328_codec_priv *rk3328 =
269 snd_soc_component_get_drvdata(dai->component);
270 unsigned int val = 0;
271
272 switch (params_format(params)) {
273 case SNDRV_PCM_FORMAT_S16_LE:
274 val = DAC_VDL_16BITS;
275 break;
276 case SNDRV_PCM_FORMAT_S20_3LE:
277 val = DAC_VDL_20BITS;
278 break;
279 case SNDRV_PCM_FORMAT_S24_LE:
280 val = DAC_VDL_24BITS;
281 break;
282 case SNDRV_PCM_FORMAT_S32_LE:
283 val = DAC_VDL_32BITS;
284 break;
285 default:
286 return -EINVAL;
287 }
288 regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val);
289
290 val = DAC_WL_32BITS | DAC_RST_DIS;
291 regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL3,
292 DAC_WL_MASK | DAC_RST_MASK, val);
293
294 return 0;
295 }
296
rk3328_pcm_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)297 static int rk3328_pcm_startup(struct snd_pcm_substream *substream,
298 struct snd_soc_dai *dai)
299 {
300 struct rk3328_codec_priv *rk3328 =
301 snd_soc_component_get_drvdata(dai->component);
302
303 return rk3328_codec_open_playback(rk3328);
304 }
305
rk3328_pcm_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)306 static void rk3328_pcm_shutdown(struct snd_pcm_substream *substream,
307 struct snd_soc_dai *dai)
308 {
309 struct rk3328_codec_priv *rk3328 =
310 snd_soc_component_get_drvdata(dai->component);
311
312 rk3328_codec_close_playback(rk3328);
313 }
314
315 static const struct snd_soc_dai_ops rk3328_dai_ops = {
316 .hw_params = rk3328_hw_params,
317 .set_fmt = rk3328_set_dai_fmt,
318 .mute_stream = rk3328_mute_stream,
319 .startup = rk3328_pcm_startup,
320 .shutdown = rk3328_pcm_shutdown,
321 .no_capture_mute = 1,
322 };
323
324 static struct snd_soc_dai_driver rk3328_dai[] = {
325 {
326 .name = "rk3328-hifi",
327 .id = RK3328_HIFI,
328 .playback = {
329 .stream_name = "HIFI Playback",
330 .channels_min = 1,
331 .channels_max = 2,
332 .rates = SNDRV_PCM_RATE_8000_96000,
333 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
334 SNDRV_PCM_FMTBIT_S20_3LE |
335 SNDRV_PCM_FMTBIT_S24_LE |
336 SNDRV_PCM_FMTBIT_S32_LE),
337 },
338 .capture = {
339 .stream_name = "HIFI Capture",
340 .channels_min = 2,
341 .channels_max = 8,
342 .rates = SNDRV_PCM_RATE_8000_96000,
343 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
344 SNDRV_PCM_FMTBIT_S20_3LE |
345 SNDRV_PCM_FMTBIT_S24_LE |
346 SNDRV_PCM_FMTBIT_S32_LE),
347 },
348 .ops = &rk3328_dai_ops,
349 },
350 };
351
rk3328_codec_probe(struct snd_soc_component * component)352 static int rk3328_codec_probe(struct snd_soc_component *component)
353 {
354 struct rk3328_codec_priv *rk3328 =
355 snd_soc_component_get_drvdata(component);
356
357 rk3328_codec_reset(rk3328);
358 rk3328_codec_power_on(rk3328, 0);
359
360 return 0;
361 }
362
rk3328_codec_remove(struct snd_soc_component * component)363 static void rk3328_codec_remove(struct snd_soc_component *component)
364 {
365 struct rk3328_codec_priv *rk3328 =
366 snd_soc_component_get_drvdata(component);
367
368 rk3328_codec_close_playback(rk3328);
369 rk3328_codec_power_off(rk3328, 0);
370 }
371
372 static const struct snd_soc_component_driver soc_codec_rk3328 = {
373 .probe = rk3328_codec_probe,
374 .remove = rk3328_codec_remove,
375 };
376
rk3328_codec_write_read_reg(struct device * dev,unsigned int reg)377 static bool rk3328_codec_write_read_reg(struct device *dev, unsigned int reg)
378 {
379 switch (reg) {
380 case CODEC_RESET:
381 case DAC_INIT_CTRL1:
382 case DAC_INIT_CTRL2:
383 case DAC_INIT_CTRL3:
384 case DAC_PRECHARGE_CTRL:
385 case DAC_PWR_CTRL:
386 case DAC_CLK_CTRL:
387 case HPMIX_CTRL:
388 case DAC_SELECT:
389 case HPOUT_CTRL:
390 case HPOUTL_GAIN_CTRL:
391 case HPOUTR_GAIN_CTRL:
392 case HPOUT_POP_CTRL:
393 return true;
394 default:
395 return false;
396 }
397 }
398
rk3328_codec_volatile_reg(struct device * dev,unsigned int reg)399 static bool rk3328_codec_volatile_reg(struct device *dev, unsigned int reg)
400 {
401 switch (reg) {
402 case CODEC_RESET:
403 return true;
404 default:
405 return false;
406 }
407 }
408
409 static const struct regmap_config rk3328_codec_regmap_config = {
410 .reg_bits = 32,
411 .reg_stride = 4,
412 .val_bits = 32,
413 .max_register = HPOUT_POP_CTRL,
414 .writeable_reg = rk3328_codec_write_read_reg,
415 .readable_reg = rk3328_codec_write_read_reg,
416 .volatile_reg = rk3328_codec_volatile_reg,
417 .reg_defaults = rk3328_codec_reg_defaults,
418 .num_reg_defaults = ARRAY_SIZE(rk3328_codec_reg_defaults),
419 .cache_type = REGCACHE_FLAT,
420 };
421
rk3328_platform_probe(struct platform_device * pdev)422 static int rk3328_platform_probe(struct platform_device *pdev)
423 {
424 struct device_node *rk3328_np = pdev->dev.of_node;
425 struct rk3328_codec_priv *rk3328;
426 struct regmap *grf;
427 void __iomem *base;
428 int ret = 0;
429
430 rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL);
431 if (!rk3328)
432 return -ENOMEM;
433
434 grf = syscon_regmap_lookup_by_phandle(rk3328_np,
435 "rockchip,grf");
436 if (IS_ERR(grf)) {
437 dev_err(&pdev->dev, "missing 'rockchip,grf'\n");
438 return PTR_ERR(grf);
439 }
440 /* enable i2s_acodec_en */
441 regmap_write(grf, RK3328_GRF_SOC_CON2,
442 (BIT(14) << 16 | BIT(14)));
443
444 ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms",
445 &rk3328->spk_depop_time);
446 if (ret < 0) {
447 dev_info(&pdev->dev, "spk_depop_time use default value.\n");
448 rk3328->spk_depop_time = 200;
449 }
450
451 rk3328->mute = gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_HIGH);
452 if (IS_ERR(rk3328->mute))
453 return PTR_ERR(rk3328->mute);
454 /*
455 * Rock64 is the only supported platform to have widely relied on
456 * this; if we do happen to come across an old DTB, just leave the
457 * external mute forced off.
458 */
459 if (!rk3328->mute && of_machine_is_compatible("pine64,rock64")) {
460 dev_warn(&pdev->dev, "assuming implicit control of GPIO_MUTE; update devicetree if possible\n");
461 regmap_write(grf, RK3328_GRF_SOC_CON10, BIT(17) | BIT(1));
462 }
463
464 rk3328->mclk = devm_clk_get(&pdev->dev, "mclk");
465 if (IS_ERR(rk3328->mclk))
466 return PTR_ERR(rk3328->mclk);
467
468 ret = clk_prepare_enable(rk3328->mclk);
469 if (ret)
470 return ret;
471 clk_set_rate(rk3328->mclk, INITIAL_FREQ);
472
473 rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");
474 if (IS_ERR(rk3328->pclk)) {
475 dev_err(&pdev->dev, "can't get acodec pclk\n");
476 ret = PTR_ERR(rk3328->pclk);
477 goto err_unprepare_mclk;
478 }
479
480 ret = clk_prepare_enable(rk3328->pclk);
481 if (ret < 0) {
482 dev_err(&pdev->dev, "failed to enable acodec pclk\n");
483 goto err_unprepare_mclk;
484 }
485
486 base = devm_platform_ioremap_resource(pdev, 0);
487 if (IS_ERR(base)) {
488 ret = PTR_ERR(base);
489 goto err_unprepare_pclk;
490 }
491
492 rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
493 &rk3328_codec_regmap_config);
494 if (IS_ERR(rk3328->regmap)) {
495 ret = PTR_ERR(rk3328->regmap);
496 goto err_unprepare_pclk;
497 }
498
499 platform_set_drvdata(pdev, rk3328);
500
501 ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
502 rk3328_dai,
503 ARRAY_SIZE(rk3328_dai));
504 if (ret)
505 goto err_unprepare_pclk;
506
507 return 0;
508
509 err_unprepare_pclk:
510 clk_disable_unprepare(rk3328->pclk);
511
512 err_unprepare_mclk:
513 clk_disable_unprepare(rk3328->mclk);
514 return ret;
515 }
516
517 static const struct of_device_id rk3328_codec_of_match[] __maybe_unused = {
518 { .compatible = "rockchip,rk3328-codec", },
519 {},
520 };
521 MODULE_DEVICE_TABLE(of, rk3328_codec_of_match);
522
523 static struct platform_driver rk3328_codec_driver = {
524 .driver = {
525 .name = "rk3328-codec",
526 .of_match_table = of_match_ptr(rk3328_codec_of_match),
527 },
528 .probe = rk3328_platform_probe,
529 };
530 module_platform_driver(rk3328_codec_driver);
531
532 MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
533 MODULE_DESCRIPTION("ASoC rk3328 codec driver");
534 MODULE_LICENSE("GPL v2");
535