0001
0002
0003
0004
0005
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
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
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
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
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
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
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
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
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
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
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
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
0388 {"HDMI", NULL, "TX"},
0389 };
0390
0391 static const struct snd_soc_dapm_route rockchip_sound_da7219_routes[] = {
0392
0393 {"Headphones", NULL, "HPL"},
0394 {"Headphones", NULL, "HPR"},
0395
0396
0397 {"MIC", NULL, "Headset Mic"},
0398 };
0399
0400 static const struct snd_soc_dapm_route rockchip_sound_dmic_routes[] = {
0401
0402 {"DMic", NULL, "Int Mic"},
0403 };
0404
0405 static const struct snd_soc_dapm_route rockchip_sound_max98357a_routes[] = {
0406
0407 {"Speakers", NULL, "Speaker"},
0408 };
0409
0410 static const struct snd_soc_dapm_route rockchip_sound_rt5514_routes[] = {
0411
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
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);