treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / sound / soc / codecs / rk3328_codec.c
blob287c962ba00d7126ef5320682f2501cf7add1b53
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.
7 #include <linux/clk.h>
8 #include <linux/delay.h>
9 #include <linux/device.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/platform_device.h>
13 #include <linux/pm_runtime.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"
21 * volume setting
22 * 0: -39dB
23 * 26: 0dB
24 * 31: 6dB
25 * Step: 1.5dB
27 #define OUT_VOLUME (0x18)
28 #define RK3328_GRF_SOC_CON2 (0x0408)
29 #define RK3328_GRF_SOC_CON10 (0x0428)
30 #define INITIAL_FREQ (11289600)
32 struct rk3328_codec_priv {
33 struct regmap *regmap;
34 struct regmap *grf;
35 struct clk *mclk;
36 struct clk *pclk;
37 unsigned int sclk;
38 int spk_depop_time; /* msec */
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 },
56 static int rk3328_codec_reset(struct rk3328_codec_priv *rk3328)
58 regmap_write(rk3328->regmap, CODEC_RESET, 0x00);
59 mdelay(10);
60 regmap_write(rk3328->regmap, CODEC_RESET, 0x03);
62 return 0;
65 static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
67 struct rk3328_codec_priv *rk3328 =
68 snd_soc_component_get_drvdata(dai->component);
69 unsigned int val;
71 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
72 case SND_SOC_DAIFMT_CBS_CFS:
73 val = PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE;
74 break;
75 case SND_SOC_DAIFMT_CBM_CFM:
76 val = PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER;
77 break;
78 default:
79 return -EINVAL;
82 regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL1,
83 PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val);
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;
103 regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2,
104 DAC_MODE_MASK, val);
106 return 0;
109 static void rk3328_analog_output(struct rk3328_codec_priv *rk3328, int mute)
111 unsigned int val = BIT(17);
113 if (mute)
114 val |= BIT(1);
116 regmap_write(rk3328->grf, RK3328_GRF_SOC_CON10, val);
119 static int rk3328_digital_mute(struct snd_soc_dai *dai, int mute)
121 struct rk3328_codec_priv *rk3328 =
122 snd_soc_component_get_drvdata(dai->component);
123 unsigned int val;
125 if (mute)
126 val = HPOUTL_MUTE | HPOUTR_MUTE;
127 else
128 val = HPOUTL_UNMUTE | HPOUTR_UNMUTE;
130 regmap_update_bits(rk3328->regmap, HPOUT_CTRL,
131 HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val);
133 return 0;
136 static int rk3328_codec_power_on(struct rk3328_codec_priv *rk3328, int wait_ms)
138 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
139 DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE);
140 mdelay(10);
141 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
142 DAC_CHARGE_CURRENT_ALL_MASK,
143 DAC_CHARGE_CURRENT_ALL_ON);
144 mdelay(wait_ms);
146 return 0;
149 static int rk3328_codec_power_off(struct rk3328_codec_priv *rk3328, int wait_ms)
151 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
152 DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE);
153 mdelay(10);
154 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
155 DAC_CHARGE_CURRENT_ALL_MASK,
156 DAC_CHARGE_CURRENT_ALL_ON);
157 mdelay(wait_ms);
159 return 0;
162 static const struct rk3328_reg_msk_val playback_open_list[] = {
163 { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON },
164 { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
165 DACL_PATH_REFV_ON | DACR_PATH_REFV_ON },
166 { DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_MASK | HPOUTR_ZERO_CROSSING_MASK,
167 HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON },
168 { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
169 HPOUTR_POP_WORK | HPOUTL_POP_WORK },
170 { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_EN | HPMIXR_EN },
171 { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
172 HPMIXL_INIT_EN | HPMIXR_INIT_EN },
173 { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_EN | HPOUTR_EN },
174 { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
175 HPOUTL_INIT_EN | HPOUTR_INIT_EN },
176 { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
177 DACL_REFV_ON | DACR_REFV_ON },
178 { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
179 DACL_CLK_ON | DACR_CLK_ON },
180 { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_ON | DACR_ON },
181 { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
182 DACL_INIT_ON | DACR_INIT_ON },
183 { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
184 DACL_SELECT | DACR_SELECT },
185 { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
186 HPMIXL_INIT2_EN | HPMIXR_INIT2_EN },
187 { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
188 HPOUTL_UNMUTE | HPOUTR_UNMUTE },
191 static int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328)
193 int i;
195 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
196 DAC_CHARGE_CURRENT_ALL_MASK,
197 DAC_CHARGE_CURRENT_I);
199 for (i = 0; i < ARRAY_SIZE(playback_open_list); i++) {
200 regmap_update_bits(rk3328->regmap,
201 playback_open_list[i].reg,
202 playback_open_list[i].msk,
203 playback_open_list[i].val);
204 mdelay(1);
207 msleep(rk3328->spk_depop_time);
208 rk3328_analog_output(rk3328, 1);
210 regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
211 HPOUTL_GAIN_MASK, OUT_VOLUME);
212 regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
213 HPOUTR_GAIN_MASK, OUT_VOLUME);
215 return 0;
218 static const struct rk3328_reg_msk_val playback_close_list[] = {
219 { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
220 HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS },
221 { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
222 DACL_UNSELECT | DACR_UNSELECT },
223 { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
224 HPOUTL_MUTE | HPOUTR_MUTE },
225 { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
226 HPOUTL_INIT_DIS | HPOUTR_INIT_DIS },
227 { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_DIS | HPOUTR_DIS },
228 { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_DIS | HPMIXR_DIS },
229 { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_OFF | DACR_OFF },
230 { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
231 DACL_CLK_OFF | DACR_CLK_OFF },
232 { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
233 DACL_REFV_OFF | DACR_REFV_OFF },
234 { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
235 HPOUTR_POP_XCHARGE | HPOUTL_POP_XCHARGE },
236 { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
237 DACL_PATH_REFV_OFF | DACR_PATH_REFV_OFF },
238 { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_OFF },
239 { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
240 HPMIXL_INIT_DIS | HPMIXR_INIT_DIS },
241 { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
242 DACL_INIT_OFF | DACR_INIT_OFF },
245 static int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328)
247 size_t i;
249 rk3328_analog_output(rk3328, 0);
251 regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
252 HPOUTL_GAIN_MASK, 0);
253 regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
254 HPOUTR_GAIN_MASK, 0);
256 for (i = 0; i < ARRAY_SIZE(playback_close_list); i++) {
257 regmap_update_bits(rk3328->regmap,
258 playback_close_list[i].reg,
259 playback_close_list[i].msk,
260 playback_close_list[i].val);
261 mdelay(1);
264 /* Workaround for silence when changed Fs 48 -> 44.1kHz */
265 rk3328_codec_reset(rk3328);
267 regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
268 DAC_CHARGE_CURRENT_ALL_MASK,
269 DAC_CHARGE_CURRENT_ALL_ON);
271 return 0;
274 static int rk3328_hw_params(struct snd_pcm_substream *substream,
275 struct snd_pcm_hw_params *params,
276 struct snd_soc_dai *dai)
278 struct rk3328_codec_priv *rk3328 =
279 snd_soc_component_get_drvdata(dai->component);
280 unsigned int val = 0;
282 switch (params_format(params)) {
283 case SNDRV_PCM_FORMAT_S16_LE:
284 val = DAC_VDL_16BITS;
285 break;
286 case SNDRV_PCM_FORMAT_S20_3LE:
287 val = DAC_VDL_20BITS;
288 break;
289 case SNDRV_PCM_FORMAT_S24_LE:
290 val = DAC_VDL_24BITS;
291 break;
292 case SNDRV_PCM_FORMAT_S32_LE:
293 val = DAC_VDL_32BITS;
294 break;
295 default:
296 return -EINVAL;
298 regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val);
300 val = DAC_WL_32BITS | DAC_RST_DIS;
301 regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL3,
302 DAC_WL_MASK | DAC_RST_MASK, val);
304 return 0;
307 static int rk3328_pcm_startup(struct snd_pcm_substream *substream,
308 struct snd_soc_dai *dai)
310 struct rk3328_codec_priv *rk3328 =
311 snd_soc_component_get_drvdata(dai->component);
313 return rk3328_codec_open_playback(rk3328);
316 static void rk3328_pcm_shutdown(struct snd_pcm_substream *substream,
317 struct snd_soc_dai *dai)
319 struct rk3328_codec_priv *rk3328 =
320 snd_soc_component_get_drvdata(dai->component);
322 rk3328_codec_close_playback(rk3328);
325 static const struct snd_soc_dai_ops rk3328_dai_ops = {
326 .hw_params = rk3328_hw_params,
327 .set_fmt = rk3328_set_dai_fmt,
328 .digital_mute = rk3328_digital_mute,
329 .startup = rk3328_pcm_startup,
330 .shutdown = rk3328_pcm_shutdown,
333 static struct snd_soc_dai_driver rk3328_dai[] = {
335 .name = "rk3328-hifi",
336 .id = RK3328_HIFI,
337 .playback = {
338 .stream_name = "HIFI Playback",
339 .channels_min = 1,
340 .channels_max = 2,
341 .rates = SNDRV_PCM_RATE_8000_96000,
342 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
343 SNDRV_PCM_FMTBIT_S20_3LE |
344 SNDRV_PCM_FMTBIT_S24_LE |
345 SNDRV_PCM_FMTBIT_S32_LE),
347 .capture = {
348 .stream_name = "HIFI Capture",
349 .channels_min = 2,
350 .channels_max = 8,
351 .rates = SNDRV_PCM_RATE_8000_96000,
352 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
353 SNDRV_PCM_FMTBIT_S20_3LE |
354 SNDRV_PCM_FMTBIT_S24_LE |
355 SNDRV_PCM_FMTBIT_S32_LE),
357 .ops = &rk3328_dai_ops,
361 static int rk3328_codec_probe(struct snd_soc_component *component)
363 struct rk3328_codec_priv *rk3328 =
364 snd_soc_component_get_drvdata(component);
366 rk3328_codec_reset(rk3328);
367 rk3328_codec_power_on(rk3328, 0);
369 return 0;
372 static void rk3328_codec_remove(struct snd_soc_component *component)
374 struct rk3328_codec_priv *rk3328 =
375 snd_soc_component_get_drvdata(component);
377 rk3328_codec_close_playback(rk3328);
378 rk3328_codec_power_off(rk3328, 0);
381 static const struct snd_soc_component_driver soc_codec_rk3328 = {
382 .probe = rk3328_codec_probe,
383 .remove = rk3328_codec_remove,
386 static bool rk3328_codec_write_read_reg(struct device *dev, unsigned int reg)
388 switch (reg) {
389 case CODEC_RESET:
390 case DAC_INIT_CTRL1:
391 case DAC_INIT_CTRL2:
392 case DAC_INIT_CTRL3:
393 case DAC_PRECHARGE_CTRL:
394 case DAC_PWR_CTRL:
395 case DAC_CLK_CTRL:
396 case HPMIX_CTRL:
397 case DAC_SELECT:
398 case HPOUT_CTRL:
399 case HPOUTL_GAIN_CTRL:
400 case HPOUTR_GAIN_CTRL:
401 case HPOUT_POP_CTRL:
402 return true;
403 default:
404 return false;
408 static bool rk3328_codec_volatile_reg(struct device *dev, unsigned int reg)
410 switch (reg) {
411 case CODEC_RESET:
412 return true;
413 default:
414 return false;
418 static const struct regmap_config rk3328_codec_regmap_config = {
419 .reg_bits = 32,
420 .reg_stride = 4,
421 .val_bits = 32,
422 .max_register = HPOUT_POP_CTRL,
423 .writeable_reg = rk3328_codec_write_read_reg,
424 .readable_reg = rk3328_codec_write_read_reg,
425 .volatile_reg = rk3328_codec_volatile_reg,
426 .reg_defaults = rk3328_codec_reg_defaults,
427 .num_reg_defaults = ARRAY_SIZE(rk3328_codec_reg_defaults),
428 .cache_type = REGCACHE_FLAT,
431 static int rk3328_platform_probe(struct platform_device *pdev)
433 struct device_node *rk3328_np = pdev->dev.of_node;
434 struct rk3328_codec_priv *rk3328;
435 struct regmap *grf;
436 void __iomem *base;
437 int ret = 0;
439 rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL);
440 if (!rk3328)
441 return -ENOMEM;
443 grf = syscon_regmap_lookup_by_phandle(rk3328_np,
444 "rockchip,grf");
445 if (IS_ERR(grf)) {
446 dev_err(&pdev->dev, "missing 'rockchip,grf'\n");
447 return PTR_ERR(grf);
449 rk3328->grf = grf;
450 /* enable i2s_acodec_en */
451 regmap_write(grf, RK3328_GRF_SOC_CON2,
452 (BIT(14) << 16 | BIT(14)));
454 ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms",
455 &rk3328->spk_depop_time);
456 if (ret < 0) {
457 dev_info(&pdev->dev, "spk_depop_time use default value.\n");
458 rk3328->spk_depop_time = 200;
461 rk3328_analog_output(rk3328, 0);
463 rk3328->mclk = devm_clk_get(&pdev->dev, "mclk");
464 if (IS_ERR(rk3328->mclk))
465 return PTR_ERR(rk3328->mclk);
467 ret = clk_prepare_enable(rk3328->mclk);
468 if (ret)
469 return ret;
470 clk_set_rate(rk3328->mclk, INITIAL_FREQ);
472 rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");
473 if (IS_ERR(rk3328->pclk)) {
474 dev_err(&pdev->dev, "can't get acodec pclk\n");
475 return PTR_ERR(rk3328->pclk);
478 ret = clk_prepare_enable(rk3328->pclk);
479 if (ret < 0) {
480 dev_err(&pdev->dev, "failed to enable acodec pclk\n");
481 return ret;
484 base = devm_platform_ioremap_resource(pdev, 0);
485 if (IS_ERR(base))
486 return PTR_ERR(base);
488 rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
489 &rk3328_codec_regmap_config);
490 if (IS_ERR(rk3328->regmap))
491 return PTR_ERR(rk3328->regmap);
493 platform_set_drvdata(pdev, rk3328);
495 return devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
496 rk3328_dai,
497 ARRAY_SIZE(rk3328_dai));
500 static const struct of_device_id rk3328_codec_of_match[] = {
501 { .compatible = "rockchip,rk3328-codec", },
504 MODULE_DEVICE_TABLE(of, rk3328_codec_of_match);
506 static struct platform_driver rk3328_codec_driver = {
507 .driver = {
508 .name = "rk3328-codec",
509 .of_match_table = of_match_ptr(rk3328_codec_of_match),
511 .probe = rk3328_platform_probe,
513 module_platform_driver(rk3328_codec_driver);
515 MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
516 MODULE_DESCRIPTION("ASoC rk3328 codec driver");
517 MODULE_LICENSE("GPL v2");