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 
31 static unsigned int dmic_wakeup_delay;
32 
33 static struct snd_soc_jack rockchip_sound_jack;
34 
35 /* Headset jack detection DAPM pins */
36 static 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 
48 static 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 
56 static 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 
64 static 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 
83 static 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 
115 static 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 
167 static struct snd_soc_jack cdn_dp_card_jack;
168 
169 static int rockchip_sound_cdndp_init(struct snd_soc_pcm_runtime *rtd)
170 {
171 	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
172 	struct snd_soc_card *card = rtd->card;
173 	int ret;
174 
175 	/* Enable jack detection. */
176 	ret = snd_soc_card_jack_new(card, "DP Jack", SND_JACK_LINEOUT,
177 				    &cdn_dp_card_jack, NULL, 0);
178 	if (ret) {
179 		dev_err(card->dev, "Can't create DP Jack %d\n", ret);
180 		return ret;
181 	}
182 
183 	return snd_soc_component_set_jack(component, &cdn_dp_card_jack, NULL);
184 }
185 
186 static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
187 {
188 	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
189 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
190 	int ret;
191 
192 	/* We need default MCLK and PLL settings for the accessory detection */
193 	ret = snd_soc_dai_set_sysclk(codec_dai, 0, 12288000,
194 				     SND_SOC_CLOCK_IN);
195 	if (ret < 0) {
196 		dev_err(codec_dai->dev, "Init can't set codec clock in %d\n", ret);
197 		return ret;
198 	}
199 
200 	ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
201 	if (ret < 0) {
202 		dev_err(codec_dai->dev, "Init can't set pll sysclk mclk %d\n", ret);
203 		return ret;
204 	}
205 
206 	/* Enable Headset and 4 Buttons Jack detection */
207 	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
208 				    SND_JACK_HEADSET | SND_JACK_LINEOUT |
209 				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
210 				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
211 				    &rockchip_sound_jack,
212 				    rockchip_sound_jack_pins,
213 				    ARRAY_SIZE(rockchip_sound_jack_pins));
214 
215 	if (ret) {
216 		dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
217 		return ret;
218 	}
219 
220 	snd_jack_set_key(
221 		rockchip_sound_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
222 	snd_jack_set_key(
223 		rockchip_sound_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
224 	snd_jack_set_key(
225 		rockchip_sound_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
226 	snd_jack_set_key(
227 		rockchip_sound_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
228 
229 	da7219_aad_jack_det(component, &rockchip_sound_jack);
230 
231 	return 0;
232 }
233 
234 static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream,
235 			     struct snd_pcm_hw_params *params)
236 {
237 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
238 	unsigned int mclk;
239 	int ret;
240 
241 	mclk = params_rate(params) * SOUND_FS;
242 
243 	ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0, mclk, 0);
244 	if (ret) {
245 		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
246 				__func__, mclk, ret);
247 		return ret;
248 	}
249 
250 	/* Wait for DMIC stable */
251 	msleep(dmic_wakeup_delay);
252 
253 	return 0;
254 }
255 
256 static int rockchip_sound_startup(struct snd_pcm_substream *substream)
257 {
258 	struct snd_pcm_runtime *runtime = substream->runtime;
259 
260 	runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
261 	return snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
262 			8000, 96000);
263 }
264 
265 static const struct snd_soc_ops rockchip_sound_max98357a_ops = {
266 	.startup = rockchip_sound_startup,
267 	.hw_params = rockchip_sound_max98357a_hw_params,
268 };
269 
270 static const struct snd_soc_ops rockchip_sound_rt5514_ops = {
271 	.startup = rockchip_sound_startup,
272 	.hw_params = rockchip_sound_rt5514_hw_params,
273 };
274 
275 static const struct snd_soc_ops rockchip_sound_da7219_ops = {
276 	.startup = rockchip_sound_startup,
277 	.hw_params = rockchip_sound_da7219_hw_params,
278 };
279 
280 static const struct snd_soc_ops rockchip_sound_dmic_ops = {
281 	.startup = rockchip_sound_startup,
282 	.hw_params = rockchip_sound_dmic_hw_params,
283 };
284 
285 static struct snd_soc_card rockchip_sound_card = {
286 	.name = "rk3399-gru-sound",
287 	.owner = THIS_MODULE,
288 	.dapm_widgets = rockchip_dapm_widgets,
289 	.num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
290 	.controls = rockchip_controls,
291 	.num_controls = ARRAY_SIZE(rockchip_controls),
292 };
293 
294 enum {
295 	DAILINK_CDNDP,
296 	DAILINK_DA7219,
297 	DAILINK_DMIC,
298 	DAILINK_MAX98357A,
299 	DAILINK_RT5514,
300 	DAILINK_RT5514_DSP,
301 };
302 
303 SND_SOC_DAILINK_DEFS(cdndp,
304 	DAILINK_COMP_ARRAY(COMP_EMPTY()),
305 	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "spdif-hifi")),
306 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
307 
308 SND_SOC_DAILINK_DEFS(da7219,
309 	DAILINK_COMP_ARRAY(COMP_EMPTY()),
310 	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "da7219-hifi")),
311 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
312 
313 SND_SOC_DAILINK_DEFS(dmic,
314 	DAILINK_COMP_ARRAY(COMP_EMPTY()),
315 	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dmic-hifi")),
316 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
317 
318 SND_SOC_DAILINK_DEFS(max98357a,
319 	DAILINK_COMP_ARRAY(COMP_EMPTY()),
320 	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
321 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
322 
323 SND_SOC_DAILINK_DEFS(rt5514,
324 	DAILINK_COMP_ARRAY(COMP_EMPTY()),
325 	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5514-aif1")),
326 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
327 
328 SND_SOC_DAILINK_DEFS(rt5514_dsp,
329 	DAILINK_COMP_ARRAY(COMP_EMPTY()),
330 	DAILINK_COMP_ARRAY(COMP_DUMMY()),
331 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
332 
333 static const struct snd_soc_dai_link rockchip_dais[] = {
334 	[DAILINK_CDNDP] = {
335 		.name = "DP",
336 		.stream_name = "DP PCM",
337 		.init = rockchip_sound_cdndp_init,
338 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
339 			SND_SOC_DAIFMT_CBS_CFS,
340 		SND_SOC_DAILINK_REG(cdndp),
341 	},
342 	[DAILINK_DA7219] = {
343 		.name = "DA7219",
344 		.stream_name = "DA7219 PCM",
345 		.init = rockchip_sound_da7219_init,
346 		.ops = &rockchip_sound_da7219_ops,
347 		/* set da7219 as slave */
348 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
349 			SND_SOC_DAIFMT_CBS_CFS,
350 		SND_SOC_DAILINK_REG(da7219),
351 	},
352 	[DAILINK_DMIC] = {
353 		.name = "DMIC",
354 		.stream_name = "DMIC PCM",
355 		.ops = &rockchip_sound_dmic_ops,
356 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
357 			SND_SOC_DAIFMT_CBS_CFS,
358 		SND_SOC_DAILINK_REG(dmic),
359 	},
360 	[DAILINK_MAX98357A] = {
361 		.name = "MAX98357A",
362 		.stream_name = "MAX98357A PCM",
363 		.ops = &rockchip_sound_max98357a_ops,
364 		/* set max98357a as slave */
365 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
366 			SND_SOC_DAIFMT_CBS_CFS,
367 		SND_SOC_DAILINK_REG(max98357a),
368 	},
369 	[DAILINK_RT5514] = {
370 		.name = "RT5514",
371 		.stream_name = "RT5514 PCM",
372 		.ops = &rockchip_sound_rt5514_ops,
373 		/* set rt5514 as slave */
374 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
375 			SND_SOC_DAIFMT_CBS_CFS,
376 		SND_SOC_DAILINK_REG(rt5514),
377 	},
378 	/* RT5514 DSP for voice wakeup via spi bus */
379 	[DAILINK_RT5514_DSP] = {
380 		.name = "RT5514 DSP",
381 		.stream_name = "Wake on Voice",
382 		SND_SOC_DAILINK_REG(rt5514_dsp),
383 	},
384 };
385 
386 static const struct snd_soc_dapm_route rockchip_sound_cdndp_routes[] = {
387 	/* Output */
388 	{"HDMI", NULL, "TX"},
389 };
390 
391 static const struct snd_soc_dapm_route rockchip_sound_da7219_routes[] = {
392 	/* Output */
393 	{"Headphones", NULL, "HPL"},
394 	{"Headphones", NULL, "HPR"},
395 
396 	/* Input */
397 	{"MIC", NULL, "Headset Mic"},
398 };
399 
400 static const struct snd_soc_dapm_route rockchip_sound_dmic_routes[] = {
401 	/* Input */
402 	{"DMic", NULL, "Int Mic"},
403 };
404 
405 static const struct snd_soc_dapm_route rockchip_sound_max98357a_routes[] = {
406 	/* Output */
407 	{"Speakers", NULL, "Speaker"},
408 };
409 
410 static const struct snd_soc_dapm_route rockchip_sound_rt5514_routes[] = {
411 	/* Input */
412 	{"DMIC1L", NULL, "Int Mic"},
413 	{"DMIC1R", NULL, "Int Mic"},
414 };
415 
416 struct rockchip_sound_route {
417 	const struct snd_soc_dapm_route *routes;
418 	int num_routes;
419 };
420 
421 static const struct rockchip_sound_route rockchip_routes[] = {
422 	[DAILINK_CDNDP] = {
423 		.routes = rockchip_sound_cdndp_routes,
424 		.num_routes = ARRAY_SIZE(rockchip_sound_cdndp_routes),
425 	},
426 	[DAILINK_DA7219] = {
427 		.routes = rockchip_sound_da7219_routes,
428 		.num_routes = ARRAY_SIZE(rockchip_sound_da7219_routes),
429 	},
430 	[DAILINK_DMIC] = {
431 		.routes = rockchip_sound_dmic_routes,
432 		.num_routes = ARRAY_SIZE(rockchip_sound_dmic_routes),
433 	},
434 	[DAILINK_MAX98357A] = {
435 		.routes = rockchip_sound_max98357a_routes,
436 		.num_routes = ARRAY_SIZE(rockchip_sound_max98357a_routes),
437 	},
438 	[DAILINK_RT5514] = {
439 		.routes = rockchip_sound_rt5514_routes,
440 		.num_routes = ARRAY_SIZE(rockchip_sound_rt5514_routes),
441 	},
442 	[DAILINK_RT5514_DSP] = {},
443 };
444 
445 struct dailink_match_data {
446 	const char *compatible;
447 	struct bus_type *bus_type;
448 };
449 
450 static const struct dailink_match_data dailink_match[] = {
451 	[DAILINK_CDNDP] = {
452 		.compatible = "rockchip,rk3399-cdn-dp",
453 	},
454 	[DAILINK_DA7219] = {
455 		.compatible = "dlg,da7219",
456 	},
457 	[DAILINK_DMIC] = {
458 		.compatible = "dmic-codec",
459 	},
460 	[DAILINK_MAX98357A] = {
461 		.compatible = "maxim,max98357a",
462 	},
463 	[DAILINK_RT5514] = {
464 		.compatible = "realtek,rt5514",
465 		.bus_type = &i2c_bus_type,
466 	},
467 	[DAILINK_RT5514_DSP] = {
468 		.compatible = "realtek,rt5514",
469 		.bus_type = &spi_bus_type,
470 	},
471 };
472 
473 static int rockchip_sound_codec_node_match(struct device_node *np_codec)
474 {
475 	struct device *dev;
476 	int i;
477 
478 	for (i = 0; i < ARRAY_SIZE(dailink_match); i++) {
479 		if (!of_device_is_compatible(np_codec,
480 					     dailink_match[i].compatible))
481 			continue;
482 
483 		if (dailink_match[i].bus_type) {
484 			dev = bus_find_device_by_of_node(dailink_match[i].bus_type,
485 							 np_codec);
486 			if (!dev)
487 				continue;
488 			put_device(dev);
489 		}
490 
491 		return i;
492 	}
493 	return -1;
494 }
495 
496 static int rockchip_sound_of_parse_dais(struct device *dev,
497 					struct snd_soc_card *card)
498 {
499 	struct device_node *np_cpu, *np_cpu0, *np_cpu1;
500 	struct device_node *np_codec;
501 	struct snd_soc_dai_link *dai;
502 	struct snd_soc_dapm_route *routes;
503 	int i, index;
504 	int num_routes;
505 
506 	card->dai_link = devm_kzalloc(dev, sizeof(rockchip_dais),
507 				      GFP_KERNEL);
508 	if (!card->dai_link)
509 		return -ENOMEM;
510 
511 	num_routes = 0;
512 	for (i = 0; i < ARRAY_SIZE(rockchip_routes); i++)
513 		num_routes += rockchip_routes[i].num_routes;
514 	routes = devm_kcalloc(dev, num_routes, sizeof(*routes),
515 			      GFP_KERNEL);
516 	if (!routes)
517 		return -ENOMEM;
518 	card->dapm_routes = routes;
519 
520 	np_cpu0 = of_parse_phandle(dev->of_node, "rockchip,cpu", 0);
521 	np_cpu1 = of_parse_phandle(dev->of_node, "rockchip,cpu", 1);
522 
523 	card->num_dapm_routes = 0;
524 	card->num_links = 0;
525 	for (i = 0; i < ARRAY_SIZE(rockchip_dais); i++) {
526 		np_codec = of_parse_phandle(dev->of_node,
527 					    "rockchip,codec", i);
528 		if (!np_codec)
529 			break;
530 
531 		if (!of_device_is_available(np_codec))
532 			continue;
533 
534 		index = rockchip_sound_codec_node_match(np_codec);
535 		if (index < 0)
536 			continue;
537 
538 		switch (index) {
539 		case DAILINK_CDNDP:
540 			np_cpu = np_cpu1;
541 			break;
542 		case DAILINK_RT5514_DSP:
543 			np_cpu = np_codec;
544 			break;
545 		default:
546 			np_cpu = np_cpu0;
547 			break;
548 		}
549 
550 		if (!np_cpu) {
551 			dev_err(dev, "Missing 'rockchip,cpu' for %s\n",
552 				rockchip_dais[index].name);
553 			return -EINVAL;
554 		}
555 
556 		dai = &card->dai_link[card->num_links++];
557 		*dai = rockchip_dais[index];
558 
559 		if (!dai->codecs->name)
560 			dai->codecs->of_node = np_codec;
561 		dai->platforms->of_node = np_cpu;
562 		dai->cpus->of_node = np_cpu;
563 
564 		if (card->num_dapm_routes + rockchip_routes[index].num_routes >
565 		    num_routes) {
566 			dev_err(dev, "Too many routes\n");
567 			return -EINVAL;
568 		}
569 
570 		memcpy(routes + card->num_dapm_routes,
571 		       rockchip_routes[index].routes,
572 		       rockchip_routes[index].num_routes * sizeof(*routes));
573 		card->num_dapm_routes += rockchip_routes[index].num_routes;
574 	}
575 
576 	return 0;
577 }
578 
579 static int rockchip_sound_probe(struct platform_device *pdev)
580 {
581 	struct snd_soc_card *card = &rockchip_sound_card;
582 	int ret;
583 
584 	ret = rockchip_sound_of_parse_dais(&pdev->dev, card);
585 	if (ret < 0) {
586 		dev_err(&pdev->dev, "Failed to parse dais: %d\n", ret);
587 		return ret;
588 	}
589 
590 	/* Set DMIC wakeup delay */
591 	ret = device_property_read_u32(&pdev->dev, "dmic-wakeup-delay-ms",
592 					&dmic_wakeup_delay);
593 	if (ret) {
594 		dmic_wakeup_delay = 0;
595 		dev_dbg(&pdev->dev,
596 			"no optional property 'dmic-wakeup-delay-ms' found, default: no delay\n");
597 	}
598 
599 	card->dev = &pdev->dev;
600 	return devm_snd_soc_register_card(&pdev->dev, card);
601 }
602 
603 static const struct of_device_id rockchip_sound_of_match[] = {
604 	{ .compatible = "rockchip,rk3399-gru-sound", },
605 	{},
606 };
607 
608 static struct platform_driver rockchip_sound_driver = {
609 	.probe = rockchip_sound_probe,
610 	.driver = {
611 		.name = DRV_NAME,
612 		.of_match_table = rockchip_sound_of_match,
613 #ifdef CONFIG_PM
614 		.pm = &snd_soc_pm_ops,
615 #endif
616 	},
617 };
618 
619 module_platform_driver(rockchip_sound_driver);
620 
621 MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>");
622 MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
623 MODULE_LICENSE("GPL v2");
624 MODULE_ALIAS("platform:" DRV_NAME);
625 MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);
626