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