cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rk3399_gru_sound.c (16052B)


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