linux/sound/soc/rockchip/rk3399_gru_sound.c
<<
>>
Prefs
   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
  28static unsigned int dmic_wakeup_delay;
  29
  30static struct snd_soc_jack rockchip_sound_jack;
  31
  32/* Headset jack detection DAPM pins */
  33static 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
  48static 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
  57static 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
  66static 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
  85static 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
 117static 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
 169static struct snd_soc_jack cdn_dp_card_jack;
 170
 171static 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
 188static 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
 236static 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
 258static 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
 267static const struct snd_soc_ops rockchip_sound_max98357a_ops = {
 268        .startup = rockchip_sound_startup,
 269        .hw_params = rockchip_sound_max98357a_hw_params,
 270};
 271
 272static const struct snd_soc_ops rockchip_sound_rt5514_ops = {
 273        .startup = rockchip_sound_startup,
 274        .hw_params = rockchip_sound_rt5514_hw_params,
 275};
 276
 277static const struct snd_soc_ops rockchip_sound_da7219_ops = {
 278        .startup = rockchip_sound_startup,
 279        .hw_params = rockchip_sound_da7219_hw_params,
 280};
 281
 282static const struct snd_soc_ops rockchip_sound_dmic_ops = {
 283        .startup = rockchip_sound_startup,
 284        .hw_params = rockchip_sound_dmic_hw_params,
 285};
 286
 287static 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
 296enum {
 297        DAILINK_CDNDP,
 298        DAILINK_DA7219,
 299        DAILINK_DMIC,
 300        DAILINK_MAX98357A,
 301        DAILINK_RT5514,
 302        DAILINK_RT5514_DSP,
 303};
 304
 305SND_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
 310SND_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
 315SND_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
 320SND_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
 325SND_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
 330SND_SOC_DAILINK_DEFS(rt5514_dsp,
 331        DAILINK_COMP_ARRAY(COMP_EMPTY()),
 332        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 333        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 334
 335static 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_CBC_CFC,
 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_CBC_CFC,
 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_CBC_CFC,
 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_CBC_CFC,
 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_CBC_CFC,
 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
 388static const struct snd_soc_dapm_route rockchip_sound_cdndp_routes[] = {
 389        /* Output */
 390        {"HDMI", NULL, "TX"},
 391};
 392
 393static 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
 402static const struct snd_soc_dapm_route rockchip_sound_dmic_routes[] = {
 403        /* Input */
 404        {"DMic", NULL, "Int Mic"},
 405};
 406
 407static const struct snd_soc_dapm_route rockchip_sound_max98357a_routes[] = {
 408        /* Output */
 409        {"Speakers", NULL, "Speaker"},
 410};
 411
 412static const struct snd_soc_dapm_route rockchip_sound_rt5514_routes[] = {
 413        /* Input */
 414        {"DMIC1L", NULL, "Int Mic"},
 415        {"DMIC1R", NULL, "Int Mic"},
 416};
 417
 418struct rockchip_sound_route {
 419        const struct snd_soc_dapm_route *routes;
 420        int num_routes;
 421};
 422
 423static 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
 447struct dailink_match_data {
 448        const char *compatible;
 449        const struct bus_type *bus_type;
 450};
 451
 452static 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
 475static 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
 498static 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
 581static 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
 605static const struct of_device_id rockchip_sound_of_match[] = {
 606        { .compatible = "rockchip,rk3399-gru-sound", },
 607        {},
 608};
 609
 610static 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
 621module_platform_driver(rockchip_sound_driver);
 622
 623MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>");
 624MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
 625MODULE_LICENSE("GPL v2");
 626MODULE_ALIAS("platform:" DRV_NAME);
 627MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);
 628