Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Rockchip machine ASoC driver for boards using MAX98357A/RT5514/DA7219
0004  *
0005  * Copyright (c) 2016, ROCKCHIP CORPORATION.  All rights reserved.
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/platform_device.h>
0010 #include <linux/slab.h>
0011 #include <linux/gpio.h>
0012 #include <linux/of_gpio.h>
0013 #include <linux/delay.h>
0014 #include <linux/spi/spi.h>
0015 #include <linux/i2c.h>
0016 #include <linux/input.h>
0017 #include <sound/core.h>
0018 #include <sound/jack.h>
0019 #include <sound/pcm.h>
0020 #include <sound/pcm_params.h>
0021 #include <sound/soc.h>
0022 #include "rockchip_i2s.h"
0023 #include "../codecs/da7219.h"
0024 #include "../codecs/da7219-aad.h"
0025 #include "../codecs/rt5514.h"
0026 
0027 #define DRV_NAME "rk3399-gru-sound"
0028 
0029 #define SOUND_FS    256
0030 
0031 static unsigned int dmic_wakeup_delay;
0032 
0033 static struct snd_soc_jack rockchip_sound_jack;
0034 
0035 /* Headset jack detection DAPM pins */
0036 static struct snd_soc_jack_pin rockchip_sound_jack_pins[] = {
0037     {
0038         .pin = "Headphones",
0039         .mask = SND_JACK_HEADPHONE,
0040     },
0041     {
0042         .pin = "Headset Mic",
0043         .mask = SND_JACK_MICROPHONE,
0044     },
0045 
0046 };
0047 
0048 static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
0049     SND_SOC_DAPM_HP("Headphones", NULL),
0050     SND_SOC_DAPM_SPK("Speakers", NULL),
0051     SND_SOC_DAPM_MIC("Headset Mic", NULL),
0052     SND_SOC_DAPM_MIC("Int Mic", NULL),
0053     SND_SOC_DAPM_LINE("HDMI", NULL),
0054 };
0055 
0056 static const struct snd_kcontrol_new rockchip_controls[] = {
0057     SOC_DAPM_PIN_SWITCH("Headphones"),
0058     SOC_DAPM_PIN_SWITCH("Speakers"),
0059     SOC_DAPM_PIN_SWITCH("Headset Mic"),
0060     SOC_DAPM_PIN_SWITCH("Int Mic"),
0061     SOC_DAPM_PIN_SWITCH("HDMI"),
0062 };
0063 
0064 static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substream,
0065                  struct snd_pcm_hw_params *params)
0066 {
0067     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0068     unsigned int mclk;
0069     int ret;
0070 
0071     mclk = params_rate(params) * SOUND_FS;
0072 
0073     ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0, mclk, 0);
0074     if (ret) {
0075         dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
0076                 __func__, mclk, ret);
0077         return ret;
0078     }
0079 
0080     return 0;
0081 }
0082 
0083 static int rockchip_sound_rt5514_hw_params(struct snd_pcm_substream *substream,
0084                  struct snd_pcm_hw_params *params)
0085 {
0086     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0087     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0088     struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0089     unsigned int mclk;
0090     int ret;
0091 
0092     mclk = params_rate(params) * SOUND_FS;
0093 
0094     ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
0095                      SND_SOC_CLOCK_OUT);
0096     if (ret < 0) {
0097         dev_err(rtd->card->dev, "Can't set cpu clock out %d\n", ret);
0098         return ret;
0099     }
0100 
0101     ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK,
0102                      mclk, SND_SOC_CLOCK_IN);
0103     if (ret) {
0104         dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
0105                 __func__, params_rate(params) * 512, ret);
0106         return ret;
0107     }
0108 
0109     /* Wait for DMIC stable */
0110     msleep(dmic_wakeup_delay);
0111 
0112     return 0;
0113 }
0114 
0115 static int rockchip_sound_da7219_hw_params(struct snd_pcm_substream *substream,
0116                  struct snd_pcm_hw_params *params)
0117 {
0118     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0119     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0120     struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0121     int mclk, ret;
0122 
0123     /* in bypass mode, the mclk has to be one of the frequencies below */
0124     switch (params_rate(params)) {
0125     case 8000:
0126     case 16000:
0127     case 24000:
0128     case 32000:
0129     case 48000:
0130     case 64000:
0131     case 96000:
0132         mclk = 12288000;
0133         break;
0134     case 11025:
0135     case 22050:
0136     case 44100:
0137     case 88200:
0138         mclk = 11289600;
0139         break;
0140     default:
0141         return -EINVAL;
0142     }
0143 
0144     ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
0145                      SND_SOC_CLOCK_OUT);
0146     if (ret < 0) {
0147         dev_err(codec_dai->dev, "Can't set cpu clock out %d\n", ret);
0148         return ret;
0149     }
0150 
0151     ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
0152                      SND_SOC_CLOCK_IN);
0153     if (ret < 0) {
0154         dev_err(codec_dai->dev, "Can't set codec clock in %d\n", ret);
0155         return ret;
0156     }
0157 
0158     ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
0159     if (ret < 0) {
0160         dev_err(codec_dai->dev, "Can't set pll sysclk mclk %d\n", ret);
0161         return ret;
0162     }
0163 
0164     return 0;
0165 }
0166 
0167 static struct snd_soc_jack cdn_dp_card_jack;
0168 
0169 static int rockchip_sound_cdndp_init(struct snd_soc_pcm_runtime *rtd)
0170 {
0171     struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
0172     struct snd_soc_card *card = rtd->card;
0173     int ret;
0174 
0175     /* Enable jack detection. */
0176     ret = snd_soc_card_jack_new(card, "DP Jack", SND_JACK_LINEOUT,
0177                     &cdn_dp_card_jack);
0178     if (ret) {
0179         dev_err(card->dev, "Can't create DP Jack %d\n", ret);
0180         return ret;
0181     }
0182 
0183     return snd_soc_component_set_jack(component, &cdn_dp_card_jack, NULL);
0184 }
0185 
0186 static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
0187 {
0188     struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
0189     struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0190     int ret;
0191 
0192     /* We need default MCLK and PLL settings for the accessory detection */
0193     ret = snd_soc_dai_set_sysclk(codec_dai, 0, 12288000,
0194                      SND_SOC_CLOCK_IN);
0195     if (ret < 0) {
0196         dev_err(codec_dai->dev, "Init can't set codec clock in %d\n", ret);
0197         return ret;
0198     }
0199 
0200     ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
0201     if (ret < 0) {
0202         dev_err(codec_dai->dev, "Init can't set pll sysclk mclk %d\n", ret);
0203         return ret;
0204     }
0205 
0206     /* Enable Headset and 4 Buttons Jack detection */
0207     ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
0208                      SND_JACK_HEADSET | SND_JACK_LINEOUT |
0209                      SND_JACK_BTN_0 | SND_JACK_BTN_1 |
0210                      SND_JACK_BTN_2 | SND_JACK_BTN_3,
0211                      &rockchip_sound_jack,
0212                      rockchip_sound_jack_pins,
0213                      ARRAY_SIZE(rockchip_sound_jack_pins));
0214 
0215     if (ret) {
0216         dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
0217         return ret;
0218     }
0219 
0220     snd_jack_set_key(
0221         rockchip_sound_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
0222     snd_jack_set_key(
0223         rockchip_sound_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
0224     snd_jack_set_key(
0225         rockchip_sound_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
0226     snd_jack_set_key(
0227         rockchip_sound_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
0228 
0229     da7219_aad_jack_det(component, &rockchip_sound_jack);
0230 
0231     return 0;
0232 }
0233 
0234 static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream,
0235                  struct snd_pcm_hw_params *params)
0236 {
0237     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0238     unsigned int mclk;
0239     int ret;
0240 
0241     mclk = params_rate(params) * SOUND_FS;
0242 
0243     ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0, mclk, 0);
0244     if (ret) {
0245         dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
0246                 __func__, mclk, ret);
0247         return ret;
0248     }
0249 
0250     /* Wait for DMIC stable */
0251     msleep(dmic_wakeup_delay);
0252 
0253     return 0;
0254 }
0255 
0256 static int rockchip_sound_startup(struct snd_pcm_substream *substream)
0257 {
0258     struct snd_pcm_runtime *runtime = substream->runtime;
0259 
0260     runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
0261     return snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
0262             8000, 96000);
0263 }
0264 
0265 static const struct snd_soc_ops rockchip_sound_max98357a_ops = {
0266     .startup = rockchip_sound_startup,
0267     .hw_params = rockchip_sound_max98357a_hw_params,
0268 };
0269 
0270 static const struct snd_soc_ops rockchip_sound_rt5514_ops = {
0271     .startup = rockchip_sound_startup,
0272     .hw_params = rockchip_sound_rt5514_hw_params,
0273 };
0274 
0275 static const struct snd_soc_ops rockchip_sound_da7219_ops = {
0276     .startup = rockchip_sound_startup,
0277     .hw_params = rockchip_sound_da7219_hw_params,
0278 };
0279 
0280 static const struct snd_soc_ops rockchip_sound_dmic_ops = {
0281     .startup = rockchip_sound_startup,
0282     .hw_params = rockchip_sound_dmic_hw_params,
0283 };
0284 
0285 static struct snd_soc_card rockchip_sound_card = {
0286     .name = "rk3399-gru-sound",
0287     .owner = THIS_MODULE,
0288     .dapm_widgets = rockchip_dapm_widgets,
0289     .num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
0290     .controls = rockchip_controls,
0291     .num_controls = ARRAY_SIZE(rockchip_controls),
0292 };
0293 
0294 enum {
0295     DAILINK_CDNDP,
0296     DAILINK_DA7219,
0297     DAILINK_DMIC,
0298     DAILINK_MAX98357A,
0299     DAILINK_RT5514,
0300     DAILINK_RT5514_DSP,
0301 };
0302 
0303 SND_SOC_DAILINK_DEFS(cdndp,
0304     DAILINK_COMP_ARRAY(COMP_EMPTY()),
0305     DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "spdif-hifi")),
0306     DAILINK_COMP_ARRAY(COMP_EMPTY()));
0307 
0308 SND_SOC_DAILINK_DEFS(da7219,
0309     DAILINK_COMP_ARRAY(COMP_EMPTY()),
0310     DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "da7219-hifi")),
0311     DAILINK_COMP_ARRAY(COMP_EMPTY()));
0312 
0313 SND_SOC_DAILINK_DEFS(dmic,
0314     DAILINK_COMP_ARRAY(COMP_EMPTY()),
0315     DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dmic-hifi")),
0316     DAILINK_COMP_ARRAY(COMP_EMPTY()));
0317 
0318 SND_SOC_DAILINK_DEFS(max98357a,
0319     DAILINK_COMP_ARRAY(COMP_EMPTY()),
0320     DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
0321     DAILINK_COMP_ARRAY(COMP_EMPTY()));
0322 
0323 SND_SOC_DAILINK_DEFS(rt5514,
0324     DAILINK_COMP_ARRAY(COMP_EMPTY()),
0325     DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5514-aif1")),
0326     DAILINK_COMP_ARRAY(COMP_EMPTY()));
0327 
0328 SND_SOC_DAILINK_DEFS(rt5514_dsp,
0329     DAILINK_COMP_ARRAY(COMP_EMPTY()),
0330     DAILINK_COMP_ARRAY(COMP_DUMMY()),
0331     DAILINK_COMP_ARRAY(COMP_EMPTY()));
0332 
0333 static const struct snd_soc_dai_link rockchip_dais[] = {
0334     [DAILINK_CDNDP] = {
0335         .name = "DP",
0336         .stream_name = "DP PCM",
0337         .init = rockchip_sound_cdndp_init,
0338         .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
0339             SND_SOC_DAIFMT_CBS_CFS,
0340         SND_SOC_DAILINK_REG(cdndp),
0341     },
0342     [DAILINK_DA7219] = {
0343         .name = "DA7219",
0344         .stream_name = "DA7219 PCM",
0345         .init = rockchip_sound_da7219_init,
0346         .ops = &rockchip_sound_da7219_ops,
0347         /* set da7219 as slave */
0348         .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
0349             SND_SOC_DAIFMT_CBS_CFS,
0350         SND_SOC_DAILINK_REG(da7219),
0351     },
0352     [DAILINK_DMIC] = {
0353         .name = "DMIC",
0354         .stream_name = "DMIC PCM",
0355         .ops = &rockchip_sound_dmic_ops,
0356         .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
0357             SND_SOC_DAIFMT_CBS_CFS,
0358         SND_SOC_DAILINK_REG(dmic),
0359     },
0360     [DAILINK_MAX98357A] = {
0361         .name = "MAX98357A",
0362         .stream_name = "MAX98357A PCM",
0363         .ops = &rockchip_sound_max98357a_ops,
0364         /* set max98357a as slave */
0365         .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
0366             SND_SOC_DAIFMT_CBS_CFS,
0367         SND_SOC_DAILINK_REG(max98357a),
0368     },
0369     [DAILINK_RT5514] = {
0370         .name = "RT5514",
0371         .stream_name = "RT5514 PCM",
0372         .ops = &rockchip_sound_rt5514_ops,
0373         /* set rt5514 as slave */
0374         .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
0375             SND_SOC_DAIFMT_CBS_CFS,
0376         SND_SOC_DAILINK_REG(rt5514),
0377     },
0378     /* RT5514 DSP for voice wakeup via spi bus */
0379     [DAILINK_RT5514_DSP] = {
0380         .name = "RT5514 DSP",
0381         .stream_name = "Wake on Voice",
0382         SND_SOC_DAILINK_REG(rt5514_dsp),
0383     },
0384 };
0385 
0386 static const struct snd_soc_dapm_route rockchip_sound_cdndp_routes[] = {
0387     /* Output */
0388     {"HDMI", NULL, "TX"},
0389 };
0390 
0391 static const struct snd_soc_dapm_route rockchip_sound_da7219_routes[] = {
0392     /* Output */
0393     {"Headphones", NULL, "HPL"},
0394     {"Headphones", NULL, "HPR"},
0395 
0396     /* Input */
0397     {"MIC", NULL, "Headset Mic"},
0398 };
0399 
0400 static const struct snd_soc_dapm_route rockchip_sound_dmic_routes[] = {
0401     /* Input */
0402     {"DMic", NULL, "Int Mic"},
0403 };
0404 
0405 static const struct snd_soc_dapm_route rockchip_sound_max98357a_routes[] = {
0406     /* Output */
0407     {"Speakers", NULL, "Speaker"},
0408 };
0409 
0410 static const struct snd_soc_dapm_route rockchip_sound_rt5514_routes[] = {
0411     /* Input */
0412     {"DMIC1L", NULL, "Int Mic"},
0413     {"DMIC1R", NULL, "Int Mic"},
0414 };
0415 
0416 struct rockchip_sound_route {
0417     const struct snd_soc_dapm_route *routes;
0418     int num_routes;
0419 };
0420 
0421 static const struct rockchip_sound_route rockchip_routes[] = {
0422     [DAILINK_CDNDP] = {
0423         .routes = rockchip_sound_cdndp_routes,
0424         .num_routes = ARRAY_SIZE(rockchip_sound_cdndp_routes),
0425     },
0426     [DAILINK_DA7219] = {
0427         .routes = rockchip_sound_da7219_routes,
0428         .num_routes = ARRAY_SIZE(rockchip_sound_da7219_routes),
0429     },
0430     [DAILINK_DMIC] = {
0431         .routes = rockchip_sound_dmic_routes,
0432         .num_routes = ARRAY_SIZE(rockchip_sound_dmic_routes),
0433     },
0434     [DAILINK_MAX98357A] = {
0435         .routes = rockchip_sound_max98357a_routes,
0436         .num_routes = ARRAY_SIZE(rockchip_sound_max98357a_routes),
0437     },
0438     [DAILINK_RT5514] = {
0439         .routes = rockchip_sound_rt5514_routes,
0440         .num_routes = ARRAY_SIZE(rockchip_sound_rt5514_routes),
0441     },
0442     [DAILINK_RT5514_DSP] = {},
0443 };
0444 
0445 struct dailink_match_data {
0446     const char *compatible;
0447     struct bus_type *bus_type;
0448 };
0449 
0450 static const struct dailink_match_data dailink_match[] = {
0451     [DAILINK_CDNDP] = {
0452         .compatible = "rockchip,rk3399-cdn-dp",
0453     },
0454     [DAILINK_DA7219] = {
0455         .compatible = "dlg,da7219",
0456     },
0457     [DAILINK_DMIC] = {
0458         .compatible = "dmic-codec",
0459     },
0460     [DAILINK_MAX98357A] = {
0461         .compatible = "maxim,max98357a",
0462     },
0463     [DAILINK_RT5514] = {
0464         .compatible = "realtek,rt5514",
0465         .bus_type = &i2c_bus_type,
0466     },
0467     [DAILINK_RT5514_DSP] = {
0468         .compatible = "realtek,rt5514",
0469         .bus_type = &spi_bus_type,
0470     },
0471 };
0472 
0473 static int rockchip_sound_codec_node_match(struct device_node *np_codec)
0474 {
0475     struct device *dev;
0476     int i;
0477 
0478     for (i = 0; i < ARRAY_SIZE(dailink_match); i++) {
0479         if (!of_device_is_compatible(np_codec,
0480                          dailink_match[i].compatible))
0481             continue;
0482 
0483         if (dailink_match[i].bus_type) {
0484             dev = bus_find_device_by_of_node(dailink_match[i].bus_type,
0485                              np_codec);
0486             if (!dev)
0487                 continue;
0488             put_device(dev);
0489         }
0490 
0491         return i;
0492     }
0493     return -1;
0494 }
0495 
0496 static int rockchip_sound_of_parse_dais(struct device *dev,
0497                     struct snd_soc_card *card)
0498 {
0499     struct device_node *np_cpu, *np_cpu0, *np_cpu1;
0500     struct device_node *np_codec;
0501     struct snd_soc_dai_link *dai;
0502     struct snd_soc_dapm_route *routes;
0503     int i, index;
0504     int num_routes;
0505 
0506     card->dai_link = devm_kzalloc(dev, sizeof(rockchip_dais),
0507                       GFP_KERNEL);
0508     if (!card->dai_link)
0509         return -ENOMEM;
0510 
0511     num_routes = 0;
0512     for (i = 0; i < ARRAY_SIZE(rockchip_routes); i++)
0513         num_routes += rockchip_routes[i].num_routes;
0514     routes = devm_kcalloc(dev, num_routes, sizeof(*routes),
0515                   GFP_KERNEL);
0516     if (!routes)
0517         return -ENOMEM;
0518     card->dapm_routes = routes;
0519 
0520     np_cpu0 = of_parse_phandle(dev->of_node, "rockchip,cpu", 0);
0521     np_cpu1 = of_parse_phandle(dev->of_node, "rockchip,cpu", 1);
0522 
0523     card->num_dapm_routes = 0;
0524     card->num_links = 0;
0525     for (i = 0; i < ARRAY_SIZE(rockchip_dais); i++) {
0526         np_codec = of_parse_phandle(dev->of_node,
0527                         "rockchip,codec", i);
0528         if (!np_codec)
0529             break;
0530 
0531         if (!of_device_is_available(np_codec))
0532             continue;
0533 
0534         index = rockchip_sound_codec_node_match(np_codec);
0535         if (index < 0)
0536             continue;
0537 
0538         switch (index) {
0539         case DAILINK_CDNDP:
0540             np_cpu = np_cpu1;
0541             break;
0542         case DAILINK_RT5514_DSP:
0543             np_cpu = np_codec;
0544             break;
0545         default:
0546             np_cpu = np_cpu0;
0547             break;
0548         }
0549 
0550         if (!np_cpu) {
0551             dev_err(dev, "Missing 'rockchip,cpu' for %s\n",
0552                 rockchip_dais[index].name);
0553             return -EINVAL;
0554         }
0555 
0556         dai = &card->dai_link[card->num_links++];
0557         *dai = rockchip_dais[index];
0558 
0559         if (!dai->codecs->name)
0560             dai->codecs->of_node = np_codec;
0561         dai->platforms->of_node = np_cpu;
0562         dai->cpus->of_node = np_cpu;
0563 
0564         if (card->num_dapm_routes + rockchip_routes[index].num_routes >
0565             num_routes) {
0566             dev_err(dev, "Too many routes\n");
0567             return -EINVAL;
0568         }
0569 
0570         memcpy(routes + card->num_dapm_routes,
0571                rockchip_routes[index].routes,
0572                rockchip_routes[index].num_routes * sizeof(*routes));
0573         card->num_dapm_routes += rockchip_routes[index].num_routes;
0574     }
0575 
0576     return 0;
0577 }
0578 
0579 static int rockchip_sound_probe(struct platform_device *pdev)
0580 {
0581     struct snd_soc_card *card = &rockchip_sound_card;
0582     int ret;
0583 
0584     ret = rockchip_sound_of_parse_dais(&pdev->dev, card);
0585     if (ret < 0) {
0586         dev_err(&pdev->dev, "Failed to parse dais: %d\n", ret);
0587         return ret;
0588     }
0589 
0590     /* Set DMIC wakeup delay */
0591     ret = device_property_read_u32(&pdev->dev, "dmic-wakeup-delay-ms",
0592                     &dmic_wakeup_delay);
0593     if (ret) {
0594         dmic_wakeup_delay = 0;
0595         dev_dbg(&pdev->dev,
0596             "no optional property 'dmic-wakeup-delay-ms' found, default: no delay\n");
0597     }
0598 
0599     card->dev = &pdev->dev;
0600     return devm_snd_soc_register_card(&pdev->dev, card);
0601 }
0602 
0603 static const struct of_device_id rockchip_sound_of_match[] = {
0604     { .compatible = "rockchip,rk3399-gru-sound", },
0605     {},
0606 };
0607 
0608 static struct platform_driver rockchip_sound_driver = {
0609     .probe = rockchip_sound_probe,
0610     .driver = {
0611         .name = DRV_NAME,
0612         .of_match_table = rockchip_sound_of_match,
0613 #ifdef CONFIG_PM
0614         .pm = &snd_soc_pm_ops,
0615 #endif
0616     },
0617 };
0618 
0619 module_platform_driver(rockchip_sound_driver);
0620 
0621 MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>");
0622 MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
0623 MODULE_LICENSE("GPL v2");
0624 MODULE_ALIAS("platform:" DRV_NAME);
0625 MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);