1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/module.h> 7 #include <linux/platform_device.h> 8 #include <linux/of_device.h> 9 #include <sound/core.h> 10 #include <sound/pcm.h> 11 #include <sound/pcm_params.h> 12 #include <sound/jack.h> 13 #include <sound/soc.h> 14 #include <linux/soundwire/sdw.h> 15 #include <uapi/linux/input-event-codes.h> 16 #include "common.h" 17 #include "qdsp6/q6afe.h" 18 #include "../codecs/rt5663.h" 19 20 #define DRIVER_NAME "sdm845" 21 #define DEFAULT_SAMPLE_RATE_48K 48000 22 #define DEFAULT_MCLK_RATE 24576000 23 #define TDM_BCLK_RATE 6144000 24 #define MI2S_BCLK_RATE 1536000 25 #define LEFT_SPK_TDM_TX_MASK 0x30 26 #define RIGHT_SPK_TDM_TX_MASK 0xC0 27 #define SPK_TDM_RX_MASK 0x03 28 #define NUM_TDM_SLOTS 8 29 #define SLIM_MAX_TX_PORTS 16 30 #define SLIM_MAX_RX_PORTS 13 31 #define WCD934X_DEFAULT_MCLK_RATE 9600000 32 33 struct sdm845_snd_data { 34 struct snd_soc_jack jack; 35 bool jack_setup; 36 bool slim_port_setup; 37 bool stream_prepared[AFE_PORT_MAX]; 38 struct snd_soc_card *card; 39 uint32_t pri_mi2s_clk_count; 40 uint32_t sec_mi2s_clk_count; 41 uint32_t quat_tdm_clk_count; 42 struct sdw_stream_runtime *sruntime[AFE_PORT_MAX]; 43 }; 44 45 static unsigned int tdm_slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28}; 46 47 static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream, 48 struct snd_pcm_hw_params *params) 49 { 50 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 51 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 52 struct snd_soc_dai *codec_dai; 53 struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); 54 u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS]; 55 struct sdw_stream_runtime *sruntime; 56 u32 rx_ch_cnt = 0, tx_ch_cnt = 0; 57 int ret = 0, i; 58 59 for_each_rtd_codec_dais(rtd, i, codec_dai) { 60 sruntime = snd_soc_dai_get_stream(codec_dai, 61 substream->stream); 62 if (sruntime != ERR_PTR(-ENOTSUPP)) 63 pdata->sruntime[cpu_dai->id] = sruntime; 64 65 ret = snd_soc_dai_get_channel_map(codec_dai, 66 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch); 67 68 if (ret != 0 && ret != -ENOTSUPP) { 69 pr_err("failed to get codec chan map, err:%d\n", ret); 70 return ret; 71 } else if (ret == -ENOTSUPP) { 72 /* Ignore unsupported */ 73 continue; 74 } 75 76 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 77 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL, 78 rx_ch_cnt, rx_ch); 79 else 80 ret = snd_soc_dai_set_channel_map(cpu_dai, tx_ch_cnt, 81 tx_ch, 0, NULL); 82 } 83 84 return 0; 85 } 86 87 static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream, 88 struct snd_pcm_hw_params *params) 89 { 90 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 91 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 92 struct snd_soc_dai *codec_dai; 93 int ret = 0, j; 94 int channels, slot_width; 95 96 switch (params_format(params)) { 97 case SNDRV_PCM_FORMAT_S16_LE: 98 slot_width = 16; 99 break; 100 default: 101 dev_err(rtd->dev, "%s: invalid param format 0x%x\n", 102 __func__, params_format(params)); 103 return -EINVAL; 104 } 105 106 channels = params_channels(params); 107 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 108 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0x3, 109 8, slot_width); 110 if (ret < 0) { 111 dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n", 112 __func__, ret); 113 goto end; 114 } 115 116 ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL, 117 channels, tdm_slot_offset); 118 if (ret < 0) { 119 dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n", 120 __func__, ret); 121 goto end; 122 } 123 } else { 124 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0, 125 8, slot_width); 126 if (ret < 0) { 127 dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n", 128 __func__, ret); 129 goto end; 130 } 131 132 ret = snd_soc_dai_set_channel_map(cpu_dai, channels, 133 tdm_slot_offset, 0, NULL); 134 if (ret < 0) { 135 dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n", 136 __func__, ret); 137 goto end; 138 } 139 } 140 141 for_each_rtd_codec_dais(rtd, j, codec_dai) { 142 143 if (!strcmp(codec_dai->component->name_prefix, "Left")) { 144 ret = snd_soc_dai_set_tdm_slot( 145 codec_dai, LEFT_SPK_TDM_TX_MASK, 146 SPK_TDM_RX_MASK, NUM_TDM_SLOTS, 147 slot_width); 148 if (ret < 0) { 149 dev_err(rtd->dev, 150 "DEV0 TDM slot err:%d\n", ret); 151 return ret; 152 } 153 } 154 155 if (!strcmp(codec_dai->component->name_prefix, "Right")) { 156 ret = snd_soc_dai_set_tdm_slot( 157 codec_dai, RIGHT_SPK_TDM_TX_MASK, 158 SPK_TDM_RX_MASK, NUM_TDM_SLOTS, 159 slot_width); 160 if (ret < 0) { 161 dev_err(rtd->dev, 162 "DEV1 TDM slot err:%d\n", ret); 163 return ret; 164 } 165 } 166 } 167 168 end: 169 return ret; 170 } 171 172 static int sdm845_snd_hw_params(struct snd_pcm_substream *substream, 173 struct snd_pcm_hw_params *params) 174 { 175 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 176 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 177 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 178 int ret = 0; 179 180 switch (cpu_dai->id) { 181 case PRIMARY_MI2S_RX: 182 case PRIMARY_MI2S_TX: 183 /* 184 * Use ASRC for internal clocks, as PLL rate isn't multiple 185 * of BCLK. 186 */ 187 rt5663_sel_asrc_clk_src( 188 codec_dai->component, 189 RT5663_DA_STEREO_FILTER | RT5663_AD_STEREO_FILTER, 190 RT5663_CLK_SEL_I2S1_ASRC); 191 ret = snd_soc_dai_set_sysclk( 192 codec_dai, RT5663_SCLK_S_MCLK, DEFAULT_MCLK_RATE, 193 SND_SOC_CLOCK_IN); 194 if (ret < 0) 195 dev_err(rtd->dev, 196 "snd_soc_dai_set_sysclk err = %d\n", ret); 197 break; 198 case QUATERNARY_TDM_RX_0: 199 case QUATERNARY_TDM_TX_0: 200 ret = sdm845_tdm_snd_hw_params(substream, params); 201 break; 202 case SLIMBUS_0_RX...SLIMBUS_6_TX: 203 ret = sdm845_slim_snd_hw_params(substream, params); 204 break; 205 case QUATERNARY_MI2S_RX: 206 break; 207 default: 208 pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id); 209 break; 210 } 211 return ret; 212 } 213 214 static void sdm845_jack_free(struct snd_jack *jack) 215 { 216 struct snd_soc_component *component = jack->private_data; 217 218 snd_soc_component_set_jack(component, NULL, NULL); 219 } 220 221 static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd) 222 { 223 struct snd_soc_component *component; 224 struct snd_soc_card *card = rtd->card; 225 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 226 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 227 struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(card); 228 struct snd_soc_dai_link *link = rtd->dai_link; 229 struct snd_jack *jack; 230 /* 231 * Codec SLIMBUS configuration 232 * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13 233 * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13 234 * TX14, TX15, TX16 235 */ 236 unsigned int rx_ch[SLIM_MAX_RX_PORTS] = {144, 145, 146, 147, 148, 149, 237 150, 151, 152, 153, 154, 155, 156}; 238 unsigned int tx_ch[SLIM_MAX_TX_PORTS] = {128, 129, 130, 131, 132, 133, 239 134, 135, 136, 137, 138, 139, 240 140, 141, 142, 143}; 241 int rval, i; 242 243 244 if (!pdata->jack_setup) { 245 rval = snd_soc_card_jack_new(card, "Headset Jack", 246 SND_JACK_HEADSET | 247 SND_JACK_HEADPHONE | 248 SND_JACK_BTN_0 | SND_JACK_BTN_1 | 249 SND_JACK_BTN_2 | SND_JACK_BTN_3, 250 &pdata->jack, NULL, 0); 251 252 if (rval < 0) { 253 dev_err(card->dev, "Unable to add Headphone Jack\n"); 254 return rval; 255 } 256 257 jack = pdata->jack.jack; 258 259 snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 260 snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 261 snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 262 snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 263 pdata->jack_setup = true; 264 } 265 266 switch (cpu_dai->id) { 267 case PRIMARY_MI2S_RX: 268 jack = pdata->jack.jack; 269 component = codec_dai->component; 270 271 jack->private_data = component; 272 jack->private_free = sdm845_jack_free; 273 rval = snd_soc_component_set_jack(component, 274 &pdata->jack, NULL); 275 if (rval != 0 && rval != -ENOTSUPP) { 276 dev_warn(card->dev, "Failed to set jack: %d\n", rval); 277 return rval; 278 } 279 break; 280 case SLIMBUS_0_RX...SLIMBUS_6_TX: 281 /* setting up wcd multiple times for slim port is redundant */ 282 if (pdata->slim_port_setup || !link->no_pcm) 283 return 0; 284 285 for_each_rtd_codec_dais(rtd, i, codec_dai) { 286 rval = snd_soc_dai_set_channel_map(codec_dai, 287 ARRAY_SIZE(tx_ch), 288 tx_ch, 289 ARRAY_SIZE(rx_ch), 290 rx_ch); 291 if (rval != 0 && rval != -ENOTSUPP) 292 return rval; 293 294 snd_soc_dai_set_sysclk(codec_dai, 0, 295 WCD934X_DEFAULT_MCLK_RATE, 296 SNDRV_PCM_STREAM_PLAYBACK); 297 298 rval = snd_soc_component_set_jack(codec_dai->component, 299 &pdata->jack, NULL); 300 if (rval != 0 && rval != -ENOTSUPP) { 301 dev_warn(card->dev, "Failed to set jack: %d\n", rval); 302 return rval; 303 } 304 } 305 306 pdata->slim_port_setup = true; 307 308 break; 309 default: 310 break; 311 } 312 313 return 0; 314 } 315 316 317 static int sdm845_snd_startup(struct snd_pcm_substream *substream) 318 { 319 unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; 320 unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS; 321 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 322 struct snd_soc_card *card = rtd->card; 323 struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card); 324 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 325 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 326 int j; 327 int ret; 328 329 switch (cpu_dai->id) { 330 case PRIMARY_MI2S_RX: 331 case PRIMARY_MI2S_TX: 332 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF; 333 if (++(data->pri_mi2s_clk_count) == 1) { 334 snd_soc_dai_set_sysclk(cpu_dai, 335 Q6AFE_LPASS_CLK_ID_MCLK_1, 336 DEFAULT_MCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); 337 snd_soc_dai_set_sysclk(cpu_dai, 338 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT, 339 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); 340 } 341 snd_soc_dai_set_fmt(cpu_dai, fmt); 342 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); 343 break; 344 345 case SECONDARY_MI2S_TX: 346 codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; 347 if (++(data->sec_mi2s_clk_count) == 1) { 348 snd_soc_dai_set_sysclk(cpu_dai, 349 Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT, 350 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_CAPTURE); 351 } 352 snd_soc_dai_set_fmt(cpu_dai, fmt); 353 snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); 354 break; 355 case QUATERNARY_MI2S_RX: 356 snd_soc_dai_set_sysclk(cpu_dai, 357 Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT, 358 MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); 359 snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS); 360 361 362 break; 363 364 case QUATERNARY_TDM_RX_0: 365 case QUATERNARY_TDM_TX_0: 366 if (++(data->quat_tdm_clk_count) == 1) { 367 snd_soc_dai_set_sysclk(cpu_dai, 368 Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT, 369 TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); 370 } 371 372 codec_dai_fmt |= SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_DSP_B; 373 374 for_each_rtd_codec_dais(rtd, j, codec_dai) { 375 376 if (!strcmp(codec_dai->component->name_prefix, 377 "Left")) { 378 ret = snd_soc_dai_set_fmt( 379 codec_dai, codec_dai_fmt); 380 if (ret < 0) { 381 dev_err(rtd->dev, 382 "Left TDM fmt err:%d\n", ret); 383 return ret; 384 } 385 } 386 387 if (!strcmp(codec_dai->component->name_prefix, 388 "Right")) { 389 ret = snd_soc_dai_set_fmt( 390 codec_dai, codec_dai_fmt); 391 if (ret < 0) { 392 dev_err(rtd->dev, 393 "Right TDM slot err:%d\n", ret); 394 return ret; 395 } 396 } 397 } 398 break; 399 case SLIMBUS_0_RX...SLIMBUS_6_TX: 400 break; 401 402 default: 403 pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id); 404 break; 405 } 406 return 0; 407 } 408 409 static void sdm845_snd_shutdown(struct snd_pcm_substream *substream) 410 { 411 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 412 struct snd_soc_card *card = rtd->card; 413 struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card); 414 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 415 416 switch (cpu_dai->id) { 417 case PRIMARY_MI2S_RX: 418 case PRIMARY_MI2S_TX: 419 if (--(data->pri_mi2s_clk_count) == 0) { 420 snd_soc_dai_set_sysclk(cpu_dai, 421 Q6AFE_LPASS_CLK_ID_MCLK_1, 422 0, SNDRV_PCM_STREAM_PLAYBACK); 423 snd_soc_dai_set_sysclk(cpu_dai, 424 Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT, 425 0, SNDRV_PCM_STREAM_PLAYBACK); 426 } 427 break; 428 429 case SECONDARY_MI2S_TX: 430 if (--(data->sec_mi2s_clk_count) == 0) { 431 snd_soc_dai_set_sysclk(cpu_dai, 432 Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT, 433 0, SNDRV_PCM_STREAM_CAPTURE); 434 } 435 break; 436 437 case QUATERNARY_TDM_RX_0: 438 case QUATERNARY_TDM_TX_0: 439 if (--(data->quat_tdm_clk_count) == 0) { 440 snd_soc_dai_set_sysclk(cpu_dai, 441 Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT, 442 0, SNDRV_PCM_STREAM_PLAYBACK); 443 } 444 break; 445 case SLIMBUS_0_RX...SLIMBUS_6_TX: 446 case QUATERNARY_MI2S_RX: 447 break; 448 449 default: 450 pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id); 451 break; 452 } 453 } 454 455 static int sdm845_snd_prepare(struct snd_pcm_substream *substream) 456 { 457 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 458 struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 459 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 460 struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; 461 int ret; 462 463 if (!sruntime) 464 return 0; 465 466 if (data->stream_prepared[cpu_dai->id]) { 467 sdw_disable_stream(sruntime); 468 sdw_deprepare_stream(sruntime); 469 data->stream_prepared[cpu_dai->id] = false; 470 } 471 472 ret = sdw_prepare_stream(sruntime); 473 if (ret) 474 return ret; 475 476 /** 477 * NOTE: there is a strict hw requirement about the ordering of port 478 * enables and actual WSA881x PA enable. PA enable should only happen 479 * after soundwire ports are enabled if not DC on the line is 480 * accumulated resulting in Click/Pop Noise 481 * PA enable/mute are handled as part of codec DAPM and digital mute. 482 */ 483 484 ret = sdw_enable_stream(sruntime); 485 if (ret) { 486 sdw_deprepare_stream(sruntime); 487 return ret; 488 } 489 data->stream_prepared[cpu_dai->id] = true; 490 491 return ret; 492 } 493 494 static int sdm845_snd_hw_free(struct snd_pcm_substream *substream) 495 { 496 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 497 struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 498 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 499 struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; 500 501 if (sruntime && data->stream_prepared[cpu_dai->id]) { 502 sdw_disable_stream(sruntime); 503 sdw_deprepare_stream(sruntime); 504 data->stream_prepared[cpu_dai->id] = false; 505 } 506 507 return 0; 508 } 509 510 static const struct snd_soc_ops sdm845_be_ops = { 511 .hw_params = sdm845_snd_hw_params, 512 .hw_free = sdm845_snd_hw_free, 513 .prepare = sdm845_snd_prepare, 514 .startup = sdm845_snd_startup, 515 .shutdown = sdm845_snd_shutdown, 516 }; 517 518 static int sdm845_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 519 struct snd_pcm_hw_params *params) 520 { 521 struct snd_interval *rate = hw_param_interval(params, 522 SNDRV_PCM_HW_PARAM_RATE); 523 struct snd_interval *channels = hw_param_interval(params, 524 SNDRV_PCM_HW_PARAM_CHANNELS); 525 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 526 527 rate->min = rate->max = DEFAULT_SAMPLE_RATE_48K; 528 channels->min = channels->max = 2; 529 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); 530 531 return 0; 532 } 533 534 static const struct snd_soc_dapm_widget sdm845_snd_widgets[] = { 535 SND_SOC_DAPM_HP("Headphone Jack", NULL), 536 SND_SOC_DAPM_MIC("Headset Mic", NULL), 537 SND_SOC_DAPM_SPK("Left Spk", NULL), 538 SND_SOC_DAPM_SPK("Right Spk", NULL), 539 SND_SOC_DAPM_MIC("Int Mic", NULL), 540 }; 541 542 static void sdm845_add_ops(struct snd_soc_card *card) 543 { 544 struct snd_soc_dai_link *link; 545 int i; 546 547 for_each_card_prelinks(card, i, link) { 548 if (link->no_pcm == 1) { 549 link->ops = &sdm845_be_ops; 550 link->be_hw_params_fixup = sdm845_be_hw_params_fixup; 551 } 552 link->init = sdm845_dai_init; 553 } 554 } 555 556 static int sdm845_snd_platform_probe(struct platform_device *pdev) 557 { 558 struct snd_soc_card *card; 559 struct sdm845_snd_data *data; 560 struct device *dev = &pdev->dev; 561 int ret; 562 563 card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); 564 if (!card) 565 return -ENOMEM; 566 567 /* Allocate the private data */ 568 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 569 if (!data) 570 return -ENOMEM; 571 572 card->driver_name = DRIVER_NAME; 573 card->dapm_widgets = sdm845_snd_widgets; 574 card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets); 575 card->dev = dev; 576 card->owner = THIS_MODULE; 577 dev_set_drvdata(dev, card); 578 ret = qcom_snd_parse_of(card); 579 if (ret) 580 return ret; 581 582 data->card = card; 583 snd_soc_card_set_drvdata(card, data); 584 585 sdm845_add_ops(card); 586 return devm_snd_soc_register_card(dev, card); 587 } 588 589 static const struct of_device_id sdm845_snd_device_id[] = { 590 { .compatible = "qcom,sdm845-sndcard" }, 591 { .compatible = "qcom,db845c-sndcard" }, 592 { .compatible = "lenovo,yoga-c630-sndcard" }, 593 {}, 594 }; 595 MODULE_DEVICE_TABLE(of, sdm845_snd_device_id); 596 597 static struct platform_driver sdm845_snd_driver = { 598 .probe = sdm845_snd_platform_probe, 599 .driver = { 600 .name = "msm-snd-sdm845", 601 .of_match_table = sdm845_snd_device_id, 602 }, 603 }; 604 module_platform_driver(sdm845_snd_driver); 605 606 MODULE_DESCRIPTION("sdm845 ASoC Machine Driver"); 607 MODULE_LICENSE("GPL v2"); 608