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