Linux Audio

Check our new training course

Loading...
v6.13.7
  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
 32struct 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
 41static 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
 56static 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
 65static 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
109static 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
126static 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
139static 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
152static 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
181static 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
208static 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
235static 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
264static 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
297static 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
306static 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
315static 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
324static 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
352static 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
363static 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
372static const struct snd_soc_component_driver soc_codec_rk3328 = {
373	.probe = rk3328_codec_probe,
374	.remove = rk3328_codec_remove,
375};
376
377static 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
399static 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
409static 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
422static 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
509err_unprepare_pclk:
510	clk_disable_unprepare(rk3328->pclk);
511
512err_unprepare_mclk:
513	clk_disable_unprepare(rk3328->mclk);
514	return ret;
515}
516
517static const struct of_device_id rk3328_codec_of_match[] __maybe_unused = {
518		{ .compatible = "rockchip,rk3328-codec", },
519		{},
520};
521MODULE_DEVICE_TABLE(of, rk3328_codec_of_match);
522
523static 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};
530module_platform_driver(rk3328_codec_driver);
531
532MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
533MODULE_DESCRIPTION("ASoC rk3328 codec driver");
534MODULE_LICENSE("GPL v2");
v5.4
  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/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"
 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
 32struct 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 */
 39};
 40
 41static 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
 56static 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
 65static 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_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;
 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
109static void rk3328_analog_output(struct rk3328_codec_priv *rk3328, int mute)
110{
111	unsigned int val = BIT(17);
112
113	if (mute)
114		val |= BIT(1);
115
116	regmap_write(rk3328->grf, RK3328_GRF_SOC_CON10, val);
117}
118
119static int rk3328_digital_mute(struct snd_soc_dai *dai, int mute)
120{
121	struct rk3328_codec_priv *rk3328 =
122		snd_soc_component_get_drvdata(dai->component);
123	unsigned int val;
124
125	if (mute)
126		val = HPOUTL_MUTE | HPOUTR_MUTE;
127	else
128		val = HPOUTL_UNMUTE | HPOUTR_UNMUTE;
129
130	regmap_update_bits(rk3328->regmap, HPOUT_CTRL,
131			   HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val);
132
133	return 0;
134}
135
136static int rk3328_codec_power_on(struct rk3328_codec_priv *rk3328, int wait_ms)
137{
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);
145
146	return 0;
147}
148
149static int rk3328_codec_power_off(struct rk3328_codec_priv *rk3328, int wait_ms)
150{
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);
158
159	return 0;
160}
161
162static 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 },
189};
190
191static int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328)
192{
193	int i;
194
195	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
196			   DAC_CHARGE_CURRENT_ALL_MASK,
197			   DAC_CHARGE_CURRENT_I);
198
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);
205	}
206
207	msleep(rk3328->spk_depop_time);
208	rk3328_analog_output(rk3328, 1);
209
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);
214
215	return 0;
216}
217
218static 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 },
243};
244
245static int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328)
246{
247	size_t i;
248
249	rk3328_analog_output(rk3328, 0);
250
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);
255
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);
262	}
263
264	/* Workaround for silence when changed Fs 48 -> 44.1kHz */
265	rk3328_codec_reset(rk3328);
266
267	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
268			   DAC_CHARGE_CURRENT_ALL_MASK,
269			   DAC_CHARGE_CURRENT_ALL_ON);
270
271	return 0;
272}
273
274static int rk3328_hw_params(struct snd_pcm_substream *substream,
275			    struct snd_pcm_hw_params *params,
276			    struct snd_soc_dai *dai)
277{
278	struct rk3328_codec_priv *rk3328 =
279		snd_soc_component_get_drvdata(dai->component);
280	unsigned int val = 0;
281
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;
297	}
298	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val);
299
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);
303
304	return 0;
305}
306
307static int rk3328_pcm_startup(struct snd_pcm_substream *substream,
308			      struct snd_soc_dai *dai)
309{
310	struct rk3328_codec_priv *rk3328 =
311		snd_soc_component_get_drvdata(dai->component);
312
313	return rk3328_codec_open_playback(rk3328);
314}
315
316static void rk3328_pcm_shutdown(struct snd_pcm_substream *substream,
317				struct snd_soc_dai *dai)
318{
319	struct rk3328_codec_priv *rk3328 =
320		snd_soc_component_get_drvdata(dai->component);
321
322	rk3328_codec_close_playback(rk3328);
323}
324
325static 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,
 
331};
332
333static struct snd_soc_dai_driver rk3328_dai[] = {
334	{
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),
346		},
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),
356		},
357		.ops = &rk3328_dai_ops,
358	},
359};
360
361static int rk3328_codec_probe(struct snd_soc_component *component)
362{
363	struct rk3328_codec_priv *rk3328 =
364		snd_soc_component_get_drvdata(component);
365
366	rk3328_codec_reset(rk3328);
367	rk3328_codec_power_on(rk3328, 0);
368
369	return 0;
370}
371
372static void rk3328_codec_remove(struct snd_soc_component *component)
373{
374	struct rk3328_codec_priv *rk3328 =
375		snd_soc_component_get_drvdata(component);
376
377	rk3328_codec_close_playback(rk3328);
378	rk3328_codec_power_off(rk3328, 0);
379}
380
381static const struct snd_soc_component_driver soc_codec_rk3328 = {
382	.probe = rk3328_codec_probe,
383	.remove = rk3328_codec_remove,
384};
385
386static bool rk3328_codec_write_read_reg(struct device *dev, unsigned int reg)
387{
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;
405	}
406}
407
408static bool rk3328_codec_volatile_reg(struct device *dev, unsigned int reg)
409{
410	switch (reg) {
411	case CODEC_RESET:
412		return true;
413	default:
414		return false;
415	}
416}
417
418static 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,
429};
430
431static int rk3328_platform_probe(struct platform_device *pdev)
432{
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;
438
439	rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL);
440	if (!rk3328)
441		return -ENOMEM;
442
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);
448	}
449	rk3328->grf = grf;
450	/* enable i2s_acodec_en */
451	regmap_write(grf, RK3328_GRF_SOC_CON2,
452		     (BIT(14) << 16 | BIT(14)));
453
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;
459	}
460
461	rk3328_analog_output(rk3328, 0);
 
 
 
 
 
 
 
 
 
 
 
462
463	rk3328->mclk = devm_clk_get(&pdev->dev, "mclk");
464	if (IS_ERR(rk3328->mclk))
465		return PTR_ERR(rk3328->mclk);
466
467	ret = clk_prepare_enable(rk3328->mclk);
468	if (ret)
469		return ret;
470	clk_set_rate(rk3328->mclk, INITIAL_FREQ);
471
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);
 
476	}
477
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;
482	}
483
484	base = devm_platform_ioremap_resource(pdev, 0);
485	if (IS_ERR(base))
486		return PTR_ERR(base);
 
 
487
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);
 
 
492
493	platform_set_drvdata(pdev, rk3328);
494
495	return devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
496					       rk3328_dai,
497					       ARRAY_SIZE(rk3328_dai));
 
 
 
 
 
 
 
 
 
 
 
498}
499
500static const struct of_device_id rk3328_codec_of_match[] = {
501		{ .compatible = "rockchip,rk3328-codec", },
502		{},
503};
504MODULE_DEVICE_TABLE(of, rk3328_codec_of_match);
505
506static struct platform_driver rk3328_codec_driver = {
507	.driver = {
508		   .name = "rk3328-codec",
509		   .of_match_table = of_match_ptr(rk3328_codec_of_match),
510	},
511	.probe = rk3328_platform_probe,
512};
513module_platform_driver(rk3328_codec_driver);
514
515MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
516MODULE_DESCRIPTION("ASoC rk3328 codec driver");
517MODULE_LICENSE("GPL v2");