1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Rockchip machine ASoC driver for boards using MAX98357A/RT5514/DA7219
4 *
5 * Copyright (c) 2016, ROCKCHIP CORPORATION.  All rights reserved.
6 */
7
8#include <linux/module.h>
9#include <linux/platform_device.h>
10#include <linux/slab.h>
11#include <linux/gpio.h>
12#include <linux/of_gpio.h>
13#include <linux/delay.h>
14#include <linux/spi/spi.h>
15#include <linux/i2c.h>
16#include <linux/input.h>
17#include <sound/core.h>
18#include <sound/jack.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/soc.h>
22#include "rockchip_i2s.h"
23#include "../codecs/da7219.h"
24#include "../codecs/da7219-aad.h"
25#include "../codecs/rt5514.h"
26
27#define DRV_NAME "rk3399-gru-sound"
28
29#define SOUND_FS	256
30
31static unsigned int dmic_wakeup_delay;
32
33static struct snd_soc_jack rockchip_sound_jack;
34
35/* Headset jack detection DAPM pins */
36static struct snd_soc_jack_pin rockchip_sound_jack_pins[] = {
37	{
38		.pin = "Headphones",
39		.mask = SND_JACK_HEADPHONE,
40	},
41	{
42		.pin = "Headset Mic",
43		.mask = SND_JACK_MICROPHONE,
44	},
45
46};
47
48static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
49	SND_SOC_DAPM_HP("Headphones", NULL),
50	SND_SOC_DAPM_SPK("Speakers", NULL),
51	SND_SOC_DAPM_MIC("Headset Mic", NULL),
52	SND_SOC_DAPM_MIC("Int Mic", NULL),
53	SND_SOC_DAPM_LINE("HDMI", NULL),
54};
55
56static const struct snd_kcontrol_new rockchip_controls[] = {
57	SOC_DAPM_PIN_SWITCH("Headphones"),
58	SOC_DAPM_PIN_SWITCH("Speakers"),
59	SOC_DAPM_PIN_SWITCH("Headset Mic"),
60	SOC_DAPM_PIN_SWITCH("Int Mic"),
61	SOC_DAPM_PIN_SWITCH("HDMI"),
62};
63
64static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substream,
65			     struct snd_pcm_hw_params *params)
66{
67	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
68	unsigned int mclk;
69	int ret;
70
71	mclk = params_rate(params) * SOUND_FS;
72
73	ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0, mclk, 0);
74	if (ret) {
75		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
76				__func__, mclk, ret);
77		return ret;
78	}
79
80	return 0;
81}
82
83static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream,
84			     struct snd_pcm_hw_params *params)
85{
86	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
87	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
88	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
89	unsigned int mclk;
90	int ret;
91
92	mclk = params_rate(params) * SOUND_FS;
93
94	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
95				     SND_SOC_CLOCK_OUT);
96	if (ret < 0) {
97		dev_err(rtd->card->dev, "Can't set cpu clock out %d\n", ret);
98		return ret;
99	}
100
101	ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK,
102				     mclk, SND_SOC_CLOCK_IN);
103	if (ret) {
104		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
105				__func__, params_rate(params) * 512, ret);
106		return ret;
107	}
108
109	/* Wait for DMIC stable */
110	msleep(dmic_wakeup_delay);
111
112	return 0;
113}
114
115static int rockchip_sound_da7219_hw_params(struct snd_pcm_substream *substream,
116			     struct snd_pcm_hw_params *params)
117{
118	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
119	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
120	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
121	int mclk, ret;
122
123	/* in bypass mode, the mclk has to be one of the frequencies below */
124	switch (params_rate(params)) {
125	case 8000:
126	case 16000:
127	case 24000:
128	case 32000:
129	case 48000:
130	case 64000:
131	case 96000:
132		mclk = 12288000;
133		break;
134	case 11025:
135	case 22050:
136	case 44100:
137	case 88200:
138		mclk = 11289600;
139		break;
140	default:
141		return -EINVAL;
142	}
143
144	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
145				     SND_SOC_CLOCK_OUT);
146	if (ret < 0) {
147		dev_err(codec_dai->dev, "Can't set cpu clock out %d\n", ret);
148		return ret;
149	}
150
151	ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
152				     SND_SOC_CLOCK_IN);
153	if (ret < 0) {
154		dev_err(codec_dai->dev, "Can't set codec clock in %d\n", ret);
155		return ret;
156	}
157
158	ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
159	if (ret < 0) {
160		dev_err(codec_dai->dev, "Can't set pll sysclk mclk %d\n", ret);
161		return ret;
162	}
163
164	return 0;
165}
166
167static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
168{
169	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
170	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
171	int ret;
172
173	/* We need default MCLK and PLL settings for the accessory detection */
174	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 12288000,
175				     SND_SOC_CLOCK_IN);
176	if (ret < 0) {
177		dev_err(codec_dai->dev, "Init can't set codec clock in %d\n", ret);
178		return ret;
179	}
180
181	ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
182	if (ret < 0) {
183		dev_err(codec_dai->dev, "Init can't set pll sysclk mclk %d\n", ret);
184		return ret;
185	}
186
187	/* Enable Headset and 4 Buttons Jack detection */
188	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
189				    SND_JACK_HEADSET | SND_JACK_LINEOUT |
190				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
191				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
192				    &rockchip_sound_jack,
193				    rockchip_sound_jack_pins,
194				    ARRAY_SIZE(rockchip_sound_jack_pins));
195
196	if (ret) {
197		dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
198		return ret;
199	}
200
201	snd_jack_set_key(
202		rockchip_sound_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
203	snd_jack_set_key(
204		rockchip_sound_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
205	snd_jack_set_key(
206		rockchip_sound_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
207	snd_jack_set_key(
208		rockchip_sound_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
209
210	da7219_aad_jack_det(component, &rockchip_sound_jack);
211
212	return 0;
213}
214
215static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream,
216			     struct snd_pcm_hw_params *params)
217{
218	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
219	unsigned int mclk;
220	int ret;
221
222	mclk = params_rate(params) * SOUND_FS;
223
224	ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0, mclk, 0);
225	if (ret) {
226		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
227				__func__, mclk, ret);
228		return ret;
229	}
230
231	/* Wait for DMIC stable */
232	msleep(dmic_wakeup_delay);
233
234	return 0;
235}
236
237static int rockchip_sound_startup(struct snd_pcm_substream *substream)
238{
239	struct snd_pcm_runtime *runtime = substream->runtime;
240
241	runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
242	return snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
243			8000, 96000);
244}
245
246static const struct snd_soc_ops rockchip_sound_max98357a_ops = {
247	.startup = rockchip_sound_startup,
248	.hw_params = rockchip_sound_max98357a_hw_params,
249};
250
251static const struct snd_soc_ops rockchip_sound_rt5514_ops = {
252	.startup = rockchip_sound_startup,
253	.hw_params = rockchip_sound_rt5514_hw_params,
254};
255
256static const struct snd_soc_ops rockchip_sound_da7219_ops = {
257	.startup = rockchip_sound_startup,
258	.hw_params = rockchip_sound_da7219_hw_params,
259};
260
261static const struct snd_soc_ops rockchip_sound_dmic_ops = {
262	.startup = rockchip_sound_startup,
263	.hw_params = rockchip_sound_dmic_hw_params,
264};
265
266static struct snd_soc_card rockchip_sound_card = {
267	.name = "rk3399-gru-sound",
268	.owner = THIS_MODULE,
269	.dapm_widgets = rockchip_dapm_widgets,
270	.num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
271	.controls = rockchip_controls,
272	.num_controls = ARRAY_SIZE(rockchip_controls),
273};
274
275enum {
276	DAILINK_CDNDP,
277	DAILINK_DA7219,
278	DAILINK_DMIC,
279	DAILINK_MAX98357A,
280	DAILINK_RT5514,
281	DAILINK_RT5514_DSP,
282};
283
284SND_SOC_DAILINK_DEFS(cdndp,
285	DAILINK_COMP_ARRAY(COMP_EMPTY()),
286	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "spdif-hifi")),
287	DAILINK_COMP_ARRAY(COMP_EMPTY()));
288
289SND_SOC_DAILINK_DEFS(da7219,
290	DAILINK_COMP_ARRAY(COMP_EMPTY()),
291	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "da7219-hifi")),
292	DAILINK_COMP_ARRAY(COMP_EMPTY()));
293
294SND_SOC_DAILINK_DEFS(dmic,
295	DAILINK_COMP_ARRAY(COMP_EMPTY()),
296	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dmic-hifi")),
297	DAILINK_COMP_ARRAY(COMP_EMPTY()));
298
299SND_SOC_DAILINK_DEFS(max98357a,
300	DAILINK_COMP_ARRAY(COMP_EMPTY()),
301	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
302	DAILINK_COMP_ARRAY(COMP_EMPTY()));
303
304SND_SOC_DAILINK_DEFS(rt5514,
305	DAILINK_COMP_ARRAY(COMP_EMPTY()),
306	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5514-aif1")),
307	DAILINK_COMP_ARRAY(COMP_EMPTY()));
308
309SND_SOC_DAILINK_DEFS(rt5514_dsp,
310	DAILINK_COMP_ARRAY(COMP_EMPTY()),
311	DAILINK_COMP_ARRAY(COMP_DUMMY()),
312	DAILINK_COMP_ARRAY(COMP_EMPTY()));
313
314static const struct snd_soc_dai_link rockchip_dais[] = {
315	[DAILINK_CDNDP] = {
316		.name = "DP",
317		.stream_name = "DP PCM",
318		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
319			SND_SOC_DAIFMT_CBS_CFS,
320		SND_SOC_DAILINK_REG(cdndp),
321	},
322	[DAILINK_DA7219] = {
323		.name = "DA7219",
324		.stream_name = "DA7219 PCM",
325		.init = rockchip_sound_da7219_init,
326		.ops = &rockchip_sound_da7219_ops,
327		/* set da7219 as slave */
328		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
329			SND_SOC_DAIFMT_CBS_CFS,
330		SND_SOC_DAILINK_REG(da7219),
331	},
332	[DAILINK_DMIC] = {
333		.name = "DMIC",
334		.stream_name = "DMIC PCM",
335		.ops = &rockchip_sound_dmic_ops,
336		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
337			SND_SOC_DAIFMT_CBS_CFS,
338		SND_SOC_DAILINK_REG(dmic),
339	},
340	[DAILINK_MAX98357A] = {
341		.name = "MAX98357A",
342		.stream_name = "MAX98357A PCM",
343		.ops = &rockchip_sound_max98357a_ops,
344		/* set max98357a as slave */
345		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
346			SND_SOC_DAIFMT_CBS_CFS,
347		SND_SOC_DAILINK_REG(max98357a),
348	},
349	[DAILINK_RT5514] = {
350		.name = "RT5514",
351		.stream_name = "RT5514 PCM",
352		.ops = &rockchip_sound_rt5514_ops,
353		/* set rt5514 as slave */
354		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
355			SND_SOC_DAIFMT_CBS_CFS,
356		SND_SOC_DAILINK_REG(rt5514),
357	},
358	/* RT5514 DSP for voice wakeup via spi bus */
359	[DAILINK_RT5514_DSP] = {
360		.name = "RT5514 DSP",
361		.stream_name = "Wake on Voice",
362		SND_SOC_DAILINK_REG(rt5514_dsp),
363	},
364};
365
366static const struct snd_soc_dapm_route rockchip_sound_cdndp_routes[] = {
367	/* Output */
368	{"HDMI", NULL, "TX"},
369};
370
371static const struct snd_soc_dapm_route rockchip_sound_da7219_routes[] = {
372	/* Output */
373	{"Headphones", NULL, "HPL"},
374	{"Headphones", NULL, "HPR"},
375
376	/* Input */
377	{"MIC", NULL, "Headset Mic"},
378};
379
380static const struct snd_soc_dapm_route rockchip_sound_dmic_routes[] = {
381	/* Input */
382	{"DMic", NULL, "Int Mic"},
383};
384
385static const struct snd_soc_dapm_route rockchip_sound_max98357a_routes[] = {
386	/* Output */
387	{"Speakers", NULL, "Speaker"},
388};
389
390static const struct snd_soc_dapm_route rockchip_sound_rt5514_routes[] = {
391	/* Input */
392	{"DMIC1L", NULL, "Int Mic"},
393	{"DMIC1R", NULL, "Int Mic"},
394};
395
396struct rockchip_sound_route {
397	const struct snd_soc_dapm_route *routes;
398	int num_routes;
399};
400
401static const struct rockchip_sound_route rockchip_routes[] = {
402	[DAILINK_CDNDP] = {
403		.routes = rockchip_sound_cdndp_routes,
404		.num_routes = ARRAY_SIZE(rockchip_sound_cdndp_routes),
405	},
406	[DAILINK_DA7219] = {
407		.routes = rockchip_sound_da7219_routes,
408		.num_routes = ARRAY_SIZE(rockchip_sound_da7219_routes),
409	},
410	[DAILINK_DMIC] = {
411		.routes = rockchip_sound_dmic_routes,
412		.num_routes = ARRAY_SIZE(rockchip_sound_dmic_routes),
413	},
414	[DAILINK_MAX98357A] = {
415		.routes = rockchip_sound_max98357a_routes,
416		.num_routes = ARRAY_SIZE(rockchip_sound_max98357a_routes),
417	},
418	[DAILINK_RT5514] = {
419		.routes = rockchip_sound_rt5514_routes,
420		.num_routes = ARRAY_SIZE(rockchip_sound_rt5514_routes),
421	},
422	[DAILINK_RT5514_DSP] = {},
423};
424
425struct dailink_match_data {
426	const char *compatible;
427	struct bus_type *bus_type;
428};
429
430static const struct dailink_match_data dailink_match[] = {
431	[DAILINK_CDNDP] = {
432		.compatible = "rockchip,rk3399-cdn-dp",
433	},
434	[DAILINK_DA7219] = {
435		.compatible = "dlg,da7219",
436	},
437	[DAILINK_DMIC] = {
438		.compatible = "dmic-codec",
439	},
440	[DAILINK_MAX98357A] = {
441		.compatible = "maxim,max98357a",
442	},
443	[DAILINK_RT5514] = {
444		.compatible = "realtek,rt5514",
445		.bus_type = &i2c_bus_type,
446	},
447	[DAILINK_RT5514_DSP] = {
448		.compatible = "realtek,rt5514",
449		.bus_type = &spi_bus_type,
450	},
451};
452
453static int rockchip_sound_codec_node_match(struct device_node *np_codec)
454{
455	struct device *dev;
456	int i;
457
458	for (i = 0; i < ARRAY_SIZE(dailink_match); i++) {
459		if (!of_device_is_compatible(np_codec,
460					     dailink_match[i].compatible))
461			continue;
462
463		if (dailink_match[i].bus_type) {
464			dev = bus_find_device_by_of_node(dailink_match[i].bus_type,
465							 np_codec);
466			if (!dev)
467				continue;
468			put_device(dev);
469		}
470
471		return i;
472	}
473	return -1;
474}
475
476static int rockchip_sound_of_parse_dais(struct device *dev,
477					struct snd_soc_card *card)
478{
479	struct device_node *np_cpu, *np_cpu0, *np_cpu1;
480	struct device_node *np_codec;
481	struct snd_soc_dai_link *dai;
482	struct snd_soc_dapm_route *routes;
483	int i, index;
484	int num_routes;
485
486	card->dai_link = devm_kzalloc(dev, sizeof(rockchip_dais),
487				      GFP_KERNEL);
488	if (!card->dai_link)
489		return -ENOMEM;
490
491	num_routes = 0;
492	for (i = 0; i < ARRAY_SIZE(rockchip_routes); i++)
493		num_routes += rockchip_routes[i].num_routes;
494	routes = devm_kcalloc(dev, num_routes, sizeof(*routes),
495			      GFP_KERNEL);
496	if (!routes)
497		return -ENOMEM;
498	card->dapm_routes = routes;
499
500	np_cpu0 = of_parse_phandle(dev->of_node, "rockchip,cpu", 0);
501	np_cpu1 = of_parse_phandle(dev->of_node, "rockchip,cpu", 1);
502
503	card->num_dapm_routes = 0;
504	card->num_links = 0;
505	for (i = 0; i < ARRAY_SIZE(rockchip_dais); i++) {
506		np_codec = of_parse_phandle(dev->of_node,
507					    "rockchip,codec", i);
508		if (!np_codec)
509			break;
510
511		if (!of_device_is_available(np_codec))
512			continue;
513
514		index = rockchip_sound_codec_node_match(np_codec);
515		if (index < 0)
516			continue;
517
518		switch (index) {
519		case DAILINK_CDNDP:
520			np_cpu = np_cpu1;
521			break;
522		case DAILINK_RT5514_DSP:
523			np_cpu = np_codec;
524			break;
525		default:
526			np_cpu = np_cpu0;
527			break;
528		}
529
530		if (!np_cpu) {
531			dev_err(dev, "Missing 'rockchip,cpu' for %s\n",
532				rockchip_dais[index].name);
533			return -EINVAL;
534		}
535
536		dai = &card->dai_link[card->num_links++];
537		*dai = rockchip_dais[index];
538
539		if (!dai->codecs->name)
540			dai->codecs->of_node = np_codec;
541		dai->platforms->of_node = np_cpu;
542		dai->cpus->of_node = np_cpu;
543
544		if (card->num_dapm_routes + rockchip_routes[index].num_routes >
545		    num_routes) {
546			dev_err(dev, "Too many routes\n");
547			return -EINVAL;
548		}
549
550		memcpy(routes + card->num_dapm_routes,
551		       rockchip_routes[index].routes,
552		       rockchip_routes[index].num_routes * sizeof(*routes));
553		card->num_dapm_routes += rockchip_routes[index].num_routes;
554	}
555
556	return 0;
557}
558
559static int rockchip_sound_probe(struct platform_device *pdev)
560{
561	struct snd_soc_card *card = &rockchip_sound_card;
562	int ret;
563
564	ret = rockchip_sound_of_parse_dais(&pdev->dev, card);
565	if (ret < 0) {
566		dev_err(&pdev->dev, "Failed to parse dais: %d\n", ret);
567		return ret;
568	}
569
570	/* Set DMIC wakeup delay */
571	ret = device_property_read_u32(&pdev->dev, "dmic-wakeup-delay-ms",
572					&dmic_wakeup_delay);
573	if (ret) {
574		dmic_wakeup_delay = 0;
575		dev_dbg(&pdev->dev,
576			"no optional property 'dmic-wakeup-delay-ms' found, default: no delay\n");
577	}
578
579	card->dev = &pdev->dev;
580	return devm_snd_soc_register_card(&pdev->dev, card);
581}
582
583static const struct of_device_id rockchip_sound_of_match[] = {
584	{ .compatible = "rockchip,rk3399-gru-sound", },
585	{},
586};
587
588static struct platform_driver rockchip_sound_driver = {
589	.probe = rockchip_sound_probe,
590	.driver = {
591		.name = DRV_NAME,
592		.of_match_table = rockchip_sound_of_match,
593#ifdef CONFIG_PM
594		.pm = &snd_soc_pm_ops,
595#endif
596	},
597};
598
599module_platform_driver(rockchip_sound_driver);
600
601MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>");
602MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
603MODULE_LICENSE("GPL v2");
604MODULE_ALIAS("platform:" DRV_NAME);
605MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);
606