Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  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");