~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/rockchip/rk3399_gru_sound.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php