blob: 3d0cc6e90d7b3bcc248b8f321792aab2a4d0155a [file] [log] [blame]
Thomas Gleixner9952f692019-05-28 10:10:04 -07001// SPDX-License-Identifier: GPL-2.0-only
Xing Zhengc6eac8a2016-08-03 16:10:00 +08002/*
3 * Rockchip machine ASoC driver for boards using MAX98357A/RT5514/DA7219
4 *
5 * Copyright (c) 2016, ROCKCHIP CORPORATION. All rights reserved.
Xing Zhengc6eac8a2016-08-03 16:10:00 +08006 */
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>
Jeffy Chen7e0dc9a2017-09-19 20:57:59 +080015#include <linux/i2c.h>
Cheng-Yi Chiang22b93ea2016-09-16 07:10:06 +080016#include <linux/input.h>
Xing Zhengc6eac8a2016-08-03 16:10:00 +080017#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
Jeffy Chenf628c4e2017-08-22 23:35:48 +080031static unsigned int dmic_wakeup_delay;
Wonjoon Lee3a6f9dc2016-09-22 21:50:06 +080032
Xing Zhengc6eac8a2016-08-03 16:10:00 +080033static struct snd_soc_jack rockchip_sound_jack;
34
35static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
36 SND_SOC_DAPM_HP("Headphones", NULL),
37 SND_SOC_DAPM_SPK("Speakers", NULL),
38 SND_SOC_DAPM_MIC("Headset Mic", NULL),
39 SND_SOC_DAPM_MIC("Int Mic", NULL),
Jeffy Chene7251482017-09-18 19:17:59 +080040 SND_SOC_DAPM_LINE("HDMI", NULL),
Xing Zhengc6eac8a2016-08-03 16:10:00 +080041};
42
Xing Zhengc6eac8a2016-08-03 16:10:00 +080043static const struct snd_kcontrol_new rockchip_controls[] = {
44 SOC_DAPM_PIN_SWITCH("Headphones"),
45 SOC_DAPM_PIN_SWITCH("Speakers"),
46 SOC_DAPM_PIN_SWITCH("Headset Mic"),
47 SOC_DAPM_PIN_SWITCH("Int Mic"),
Jeffy Chene7251482017-09-18 19:17:59 +080048 SOC_DAPM_PIN_SWITCH("HDMI"),
Xing Zhengc6eac8a2016-08-03 16:10:00 +080049};
50
51static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substream,
52 struct snd_pcm_hw_params *params)
53{
54 struct snd_soc_pcm_runtime *rtd = substream->private_data;
55 unsigned int mclk;
56 int ret;
57
58 /* max98357a supports these sample rates */
59 switch (params_rate(params)) {
60 case 8000:
61 case 16000:
62 case 48000:
63 case 96000:
64 mclk = params_rate(params) * SOUND_FS;
65 break;
66 default:
67 dev_err(rtd->card->dev, "%s() doesn't support this sample rate: %d\n",
68 __func__, params_rate(params));
69 return -EINVAL;
70 }
71
72 ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 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
82static 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 = substream->private_data;
86 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
87 struct snd_soc_dai *codec_dai = rtd->codec_dai;
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
Wonjoon Lee3a6f9dc2016-09-22 21:50:06 +0800108 /* Wait for DMIC stable */
Jeffy Chenf628c4e2017-08-22 23:35:48 +0800109 msleep(dmic_wakeup_delay);
Wonjoon Lee3a6f9dc2016-09-22 21:50:06 +0800110
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800111 return 0;
112}
113
114static 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 = substream->private_data;
118 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
119 struct snd_soc_dai *codec_dai = rtd->codec_dai;
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
166static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
167{
Kuninori Morimoto45101122018-01-29 04:36:54 +0000168 struct snd_soc_component *component = rtd->codec_dais[0]->component;
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800169 struct snd_soc_dai *codec_dai = rtd->codec_dai;
170 int ret;
171
172 /* We need default MCLK and PLL settings for the accessory detection */
173 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 12288000,
174 SND_SOC_CLOCK_IN);
175 if (ret < 0) {
176 dev_err(codec_dai->dev, "Init can't set codec clock in %d\n", ret);
177 return ret;
178 }
179
180 ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
181 if (ret < 0) {
182 dev_err(codec_dai->dev, "Init can't set pll sysclk mclk %d\n", ret);
183 return ret;
184 }
185
186 /* Enable Headset and 4 Buttons Jack detection */
187 ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
188 SND_JACK_HEADSET | SND_JACK_LINEOUT |
189 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
190 SND_JACK_BTN_2 | SND_JACK_BTN_3,
191 &rockchip_sound_jack, NULL, 0);
192
193 if (ret) {
194 dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
195 return ret;
196 }
197
Benson Leungaf1b1ce2017-11-22 12:56:42 -0800198 snd_jack_set_key(
199 rockchip_sound_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
Cheng-Yi Chiang22b93ea2016-09-16 07:10:06 +0800200 snd_jack_set_key(
201 rockchip_sound_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
202 snd_jack_set_key(
203 rockchip_sound_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
204 snd_jack_set_key(
205 rockchip_sound_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
206
Kuninori Morimoto45101122018-01-29 04:36:54 +0000207 da7219_aad_jack_det(component, &rockchip_sound_jack);
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800208
209 return 0;
210}
211
Jeffy Chen626d84d2017-08-24 12:52:26 +0800212static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream,
213 struct snd_pcm_hw_params *params)
214{
215 struct snd_soc_pcm_runtime *rtd = substream->private_data;
216 unsigned int mclk;
217 int ret;
218
219 mclk = params_rate(params) * SOUND_FS;
220
221 ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0);
222 if (ret) {
223 dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
224 __func__, mclk, ret);
225 return ret;
226 }
227
228 /* Wait for DMIC stable */
229 msleep(dmic_wakeup_delay);
230
231 return 0;
232}
233
Julia Lawall705e9992016-10-15 16:55:47 +0200234static const struct snd_soc_ops rockchip_sound_max98357a_ops = {
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800235 .hw_params = rockchip_sound_max98357a_hw_params,
236};
237
Julia Lawall705e9992016-10-15 16:55:47 +0200238static const struct snd_soc_ops rockchip_sound_rt5514_ops = {
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800239 .hw_params = rockchip_sound_rt5514_hw_params,
240};
241
Julia Lawall705e9992016-10-15 16:55:47 +0200242static const struct snd_soc_ops rockchip_sound_da7219_ops = {
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800243 .hw_params = rockchip_sound_da7219_hw_params,
244};
245
Jeffy Chen1fe165b2017-08-30 17:58:14 +0800246static const struct snd_soc_ops rockchip_sound_dmic_ops = {
Jeffy Chen626d84d2017-08-24 12:52:26 +0800247 .hw_params = rockchip_sound_dmic_hw_params,
248};
249
Jeffy Chen0d529542017-08-24 12:52:24 +0800250static struct snd_soc_card rockchip_sound_card = {
251 .name = "rk3399-gru-sound",
252 .owner = THIS_MODULE,
253 .dapm_widgets = rockchip_dapm_widgets,
254 .num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
Jeffy Chen0d529542017-08-24 12:52:24 +0800255 .controls = rockchip_controls,
256 .num_controls = ARRAY_SIZE(rockchip_controls),
257};
258
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800259enum {
Jeffy Chen3313faf2017-08-24 12:52:25 +0800260 DAILINK_CDNDP,
Jeffy Chen0d529542017-08-24 12:52:24 +0800261 DAILINK_DA7219,
Jeffy Chen626d84d2017-08-24 12:52:26 +0800262 DAILINK_DMIC,
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800263 DAILINK_MAX98357A,
264 DAILINK_RT5514,
Xing Zhenge5abe952016-08-19 21:56:12 +0800265 DAILINK_RT5514_DSP,
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800266};
267
Jeffy Chen0d529542017-08-24 12:52:24 +0800268static const struct snd_soc_dai_link rockchip_dais[] = {
Jeffy Chen3313faf2017-08-24 12:52:25 +0800269 [DAILINK_CDNDP] = {
270 .name = "DP",
271 .stream_name = "DP PCM",
Lin Huangb18c6c32018-05-22 16:53:42 +0800272 .codec_dai_name = "spdif-hifi",
Jeffy Chen3313faf2017-08-24 12:52:25 +0800273 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
274 SND_SOC_DAIFMT_CBS_CFS,
275 },
Jeffy Chen0d529542017-08-24 12:52:24 +0800276 [DAILINK_DA7219] = {
277 .name = "DA7219",
278 .stream_name = "DA7219 PCM",
279 .codec_dai_name = "da7219-hifi",
280 .init = rockchip_sound_da7219_init,
281 .ops = &rockchip_sound_da7219_ops,
282 /* set da7219 as slave */
283 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
284 SND_SOC_DAIFMT_CBS_CFS,
285 },
Jeffy Chen626d84d2017-08-24 12:52:26 +0800286 [DAILINK_DMIC] = {
287 .name = "DMIC",
288 .stream_name = "DMIC PCM",
289 .codec_dai_name = "dmic-hifi",
290 .ops = &rockchip_sound_dmic_ops,
291 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
292 SND_SOC_DAIFMT_CBS_CFS,
293 },
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800294 [DAILINK_MAX98357A] = {
295 .name = "MAX98357A",
296 .stream_name = "MAX98357A PCM",
297 .codec_dai_name = "HiFi",
298 .ops = &rockchip_sound_max98357a_ops,
299 /* set max98357a as slave */
300 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
301 SND_SOC_DAIFMT_CBS_CFS,
302 },
303 [DAILINK_RT5514] = {
304 .name = "RT5514",
305 .stream_name = "RT5514 PCM",
306 .codec_dai_name = "rt5514-aif1",
307 .ops = &rockchip_sound_rt5514_ops,
308 /* set rt5514 as slave */
309 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
310 SND_SOC_DAIFMT_CBS_CFS,
311 },
Xing Zhenge5abe952016-08-19 21:56:12 +0800312 /* RT5514 DSP for voice wakeup via spi bus */
313 [DAILINK_RT5514_DSP] = {
314 .name = "RT5514 DSP",
315 .stream_name = "Wake on Voice",
Jeffy Chenfde7f9d2017-11-21 16:25:17 +0800316 .codec_name = "snd-soc-dummy",
317 .codec_dai_name = "snd-soc-dummy-dai",
Xing Zhenge5abe952016-08-19 21:56:12 +0800318 },
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800319};
320
Jeffy Chend9f9c162017-09-19 20:57:58 +0800321static const struct snd_soc_dapm_route rockchip_sound_cdndp_routes[] = {
322 /* Output */
323 {"HDMI", NULL, "TX"},
324};
325
326static const struct snd_soc_dapm_route rockchip_sound_da7219_routes[] = {
327 /* Output */
328 {"Headphones", NULL, "HPL"},
329 {"Headphones", NULL, "HPR"},
330
331 /* Input */
332 {"MIC", NULL, "Headset Mic"},
333};
334
335static const struct snd_soc_dapm_route rockchip_sound_dmic_routes[] = {
336 /* Input */
337 {"DMic", NULL, "Int Mic"},
338};
339
340static const struct snd_soc_dapm_route rockchip_sound_max98357a_routes[] = {
341 /* Output */
342 {"Speakers", NULL, "Speaker"},
343};
344
345static const struct snd_soc_dapm_route rockchip_sound_rt5514_routes[] = {
346 /* Input */
347 {"DMIC1L", NULL, "Int Mic"},
348 {"DMIC1R", NULL, "Int Mic"},
349};
350
351struct rockchip_sound_route {
352 const struct snd_soc_dapm_route *routes;
353 int num_routes;
354};
355
356static const struct rockchip_sound_route rockchip_routes[] = {
357 [DAILINK_CDNDP] = {
358 .routes = rockchip_sound_cdndp_routes,
359 .num_routes = ARRAY_SIZE(rockchip_sound_cdndp_routes),
360 },
361 [DAILINK_DA7219] = {
362 .routes = rockchip_sound_da7219_routes,
363 .num_routes = ARRAY_SIZE(rockchip_sound_da7219_routes),
364 },
365 [DAILINK_DMIC] = {
366 .routes = rockchip_sound_dmic_routes,
367 .num_routes = ARRAY_SIZE(rockchip_sound_dmic_routes),
368 },
369 [DAILINK_MAX98357A] = {
370 .routes = rockchip_sound_max98357a_routes,
371 .num_routes = ARRAY_SIZE(rockchip_sound_max98357a_routes),
372 },
373 [DAILINK_RT5514] = {
374 .routes = rockchip_sound_rt5514_routes,
375 .num_routes = ARRAY_SIZE(rockchip_sound_rt5514_routes),
376 },
377 [DAILINK_RT5514_DSP] = {},
378};
379
Jeffy Chen7e0dc9a2017-09-19 20:57:59 +0800380struct dailink_match_data {
381 const char *compatible;
382 struct bus_type *bus_type;
383};
384
385static const struct dailink_match_data dailink_match[] = {
386 [DAILINK_CDNDP] = {
387 .compatible = "rockchip,rk3399-cdn-dp",
388 },
389 [DAILINK_DA7219] = {
390 .compatible = "dlg,da7219",
391 },
392 [DAILINK_DMIC] = {
393 .compatible = "dmic-codec",
394 },
395 [DAILINK_MAX98357A] = {
396 .compatible = "maxim,max98357a",
397 },
398 [DAILINK_RT5514] = {
399 .compatible = "realtek,rt5514",
400 .bus_type = &i2c_bus_type,
401 },
402 [DAILINK_RT5514_DSP] = {
403 .compatible = "realtek,rt5514",
404 .bus_type = &spi_bus_type,
405 },
406};
407
408static int of_dev_node_match(struct device *dev, void *data)
409{
410 return dev->of_node == data;
411}
412
Jeffy Chen0d529542017-08-24 12:52:24 +0800413static int rockchip_sound_codec_node_match(struct device_node *np_codec)
Xing Zhenge5abe952016-08-19 21:56:12 +0800414{
Jeffy Chen7e0dc9a2017-09-19 20:57:59 +0800415 struct device *dev;
Jeffy Chen0d529542017-08-24 12:52:24 +0800416 int i;
417
Jeffy Chen7e0dc9a2017-09-19 20:57:59 +0800418 for (i = 0; i < ARRAY_SIZE(dailink_match); i++) {
419 if (!of_device_is_compatible(np_codec,
420 dailink_match[i].compatible))
421 continue;
422
423 if (dailink_match[i].bus_type) {
424 dev = bus_find_device(dailink_match[i].bus_type, NULL,
425 np_codec, of_dev_node_match);
426 if (!dev)
427 continue;
428 put_device(dev);
429 }
430
431 return i;
Jeffy Chen0d529542017-08-24 12:52:24 +0800432 }
433 return -1;
434}
435
436static int rockchip_sound_of_parse_dais(struct device *dev,
437 struct snd_soc_card *card)
438{
Jeffy Chen3313faf2017-08-24 12:52:25 +0800439 struct device_node *np_cpu, *np_cpu0, *np_cpu1;
Jeffy Chen0d529542017-08-24 12:52:24 +0800440 struct device_node *np_codec;
441 struct snd_soc_dai_link *dai;
Jeffy Chend9f9c162017-09-19 20:57:58 +0800442 struct snd_soc_dapm_route *routes;
Jeffy Chen0d529542017-08-24 12:52:24 +0800443 int i, index;
Douglas Anderson8eae6c22017-09-29 15:03:24 -0700444 int num_routes;
Jeffy Chen0d529542017-08-24 12:52:24 +0800445
446 card->dai_link = devm_kzalloc(dev, sizeof(rockchip_dais),
447 GFP_KERNEL);
448 if (!card->dai_link)
449 return -ENOMEM;
450
Douglas Anderson8eae6c22017-09-29 15:03:24 -0700451 num_routes = 0;
452 for (i = 0; i < ARRAY_SIZE(rockchip_routes); i++)
453 num_routes += rockchip_routes[i].num_routes;
Kees Cooka86854d2018-06-12 14:07:58 -0700454 routes = devm_kcalloc(dev, num_routes, sizeof(*routes),
Jeffy Chend9f9c162017-09-19 20:57:58 +0800455 GFP_KERNEL);
456 if (!routes)
457 return -ENOMEM;
458 card->dapm_routes = routes;
459
Jeffy Chen3313faf2017-08-24 12:52:25 +0800460 np_cpu0 = of_parse_phandle(dev->of_node, "rockchip,cpu", 0);
461 np_cpu1 = of_parse_phandle(dev->of_node, "rockchip,cpu", 1);
Jeffy Chen0d529542017-08-24 12:52:24 +0800462
Jeffy Chend9f9c162017-09-19 20:57:58 +0800463 card->num_dapm_routes = 0;
Jeffy Chen0d529542017-08-24 12:52:24 +0800464 card->num_links = 0;
465 for (i = 0; i < ARRAY_SIZE(rockchip_dais); i++) {
466 np_codec = of_parse_phandle(dev->of_node,
467 "rockchip,codec", i);
468 if (!np_codec)
469 break;
470
471 if (!of_device_is_available(np_codec))
472 continue;
473
474 index = rockchip_sound_codec_node_match(np_codec);
475 if (index < 0)
476 continue;
477
Jeffy Chenfde7f9d2017-11-21 16:25:17 +0800478 switch (index) {
479 case DAILINK_CDNDP:
480 np_cpu = np_cpu1;
481 break;
482 case DAILINK_RT5514_DSP:
483 np_cpu = np_codec;
484 break;
485 default:
486 np_cpu = np_cpu0;
487 break;
488 }
489
Jeffy Chen0d529542017-08-24 12:52:24 +0800490 if (!np_cpu) {
491 dev_err(dev, "Missing 'rockchip,cpu' for %s\n",
492 rockchip_dais[index].name);
493 return -EINVAL;
494 }
495
496 dai = &card->dai_link[card->num_links++];
497 *dai = rockchip_dais[index];
498
Jeffy Chenfde7f9d2017-11-21 16:25:17 +0800499 if (!dai->codec_name)
500 dai->codec_of_node = np_codec;
Jeffy Chen0d529542017-08-24 12:52:24 +0800501 dai->platform_of_node = np_cpu;
502 dai->cpu_of_node = np_cpu;
Jeffy Chend9f9c162017-09-19 20:57:58 +0800503
Douglas Anderson8eae6c22017-09-29 15:03:24 -0700504 if (card->num_dapm_routes + rockchip_routes[index].num_routes >
505 num_routes) {
506 dev_err(dev, "Too many routes\n");
507 return -EINVAL;
508 }
509
Jeffy Chend9f9c162017-09-19 20:57:58 +0800510 memcpy(routes + card->num_dapm_routes,
511 rockchip_routes[index].routes,
512 rockchip_routes[index].num_routes * sizeof(*routes));
513 card->num_dapm_routes += rockchip_routes[index].num_routes;
Jeffy Chen0d529542017-08-24 12:52:24 +0800514 }
515
516 return 0;
Xing Zhenge5abe952016-08-19 21:56:12 +0800517}
518
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800519static int rockchip_sound_probe(struct platform_device *pdev)
520{
521 struct snd_soc_card *card = &rockchip_sound_card;
Jeffy Chen0d529542017-08-24 12:52:24 +0800522 int ret;
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800523
Jeffy Chen0d529542017-08-24 12:52:24 +0800524 ret = rockchip_sound_of_parse_dais(&pdev->dev, card);
525 if (ret < 0) {
526 dev_err(&pdev->dev, "Failed to parse dais: %d\n", ret);
527 return ret;
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800528 }
529
Jeffy Chenf628c4e2017-08-22 23:35:48 +0800530 /* Set DMIC wakeup delay */
531 ret = device_property_read_u32(&pdev->dev, "dmic-wakeup-delay-ms",
532 &dmic_wakeup_delay);
Wonjoon Lee3a6f9dc2016-09-22 21:50:06 +0800533 if (ret) {
Jeffy Chenf628c4e2017-08-22 23:35:48 +0800534 dmic_wakeup_delay = 0;
Wonjoon Lee3a6f9dc2016-09-22 21:50:06 +0800535 dev_dbg(&pdev->dev,
Jeffy Chenf628c4e2017-08-22 23:35:48 +0800536 "no optional property 'dmic-wakeup-delay-ms' found, default: no delay\n");
Wonjoon Lee3a6f9dc2016-09-22 21:50:06 +0800537 }
538
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800539 card->dev = &pdev->dev;
Jeffy Chen0d529542017-08-24 12:52:24 +0800540 return devm_snd_soc_register_card(&pdev->dev, card);
Xing Zhengc6eac8a2016-08-03 16:10:00 +0800541}
542
543static const struct of_device_id rockchip_sound_of_match[] = {
544 { .compatible = "rockchip,rk3399-gru-sound", },
545 {},
546};
547
548static struct platform_driver rockchip_sound_driver = {
549 .probe = rockchip_sound_probe,
550 .driver = {
551 .name = DRV_NAME,
552 .of_match_table = rockchip_sound_of_match,
553#ifdef CONFIG_PM
554 .pm = &snd_soc_pm_ops,
555#endif
556 },
557};
558
559module_platform_driver(rockchip_sound_driver);
560
561MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>");
562MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
563MODULE_LICENSE("GPL v2");
564MODULE_ALIAS("platform:" DRV_NAME);
565MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);