1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright(c) 2019-2020 Intel Corporation.
3
4 /*
5 * Intel SOF Machine Driver with Realtek rt5682 Codec
6 * and speaker codec MAX98357A or RT1015.
7 */
8 #include <linux/i2c.h>
9 #include <linux/input.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/clk.h>
13 #include <linux/dmi.h>
14 #include <sound/core.h>
15 #include <sound/jack.h>
16 #include <sound/pcm.h>
17 #include <sound/pcm_params.h>
18 #include <sound/soc.h>
19 #include <sound/sof.h>
20 #include <sound/rt5682.h>
21 #include <sound/rt5682s.h>
22 #include <sound/soc-acpi.h>
23 #include "../../codecs/rt5682.h"
24 #include "../../codecs/rt5682s.h"
25 #include "../../codecs/hdac_hdmi.h"
26 #include "../common/soc-intel-quirks.h"
27 #include "hda_dsp_common.h"
28 #include "sof_maxim_common.h"
29 #include "sof_realtek_common.h"
30
31 #define NAME_SIZE 32
32
33 #define SOF_RT5682_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0))
34 #define SOF_RT5682_SSP_CODEC_MASK (GENMASK(2, 0))
35 #define SOF_RT5682_MCLK_EN BIT(3)
36 #define SOF_RT5682_MCLK_24MHZ BIT(4)
37 #define SOF_SPEAKER_AMP_PRESENT BIT(5)
38 #define SOF_RT5682_SSP_AMP_SHIFT 6
39 #define SOF_RT5682_SSP_AMP_MASK (GENMASK(8, 6))
40 #define SOF_RT5682_SSP_AMP(quirk) \
41 (((quirk) << SOF_RT5682_SSP_AMP_SHIFT) & SOF_RT5682_SSP_AMP_MASK)
42 #define SOF_RT5682_MCLK_BYTCHT_EN BIT(9)
43 #define SOF_RT5682_NUM_HDMIDEV_SHIFT 10
44 #define SOF_RT5682_NUM_HDMIDEV_MASK (GENMASK(12, 10))
45 #define SOF_RT5682_NUM_HDMIDEV(quirk) \
46 ((quirk << SOF_RT5682_NUM_HDMIDEV_SHIFT) & SOF_RT5682_NUM_HDMIDEV_MASK)
47 #define SOF_RT1011_SPEAKER_AMP_PRESENT BIT(13)
48 #define SOF_RT1015_SPEAKER_AMP_PRESENT BIT(14)
49 #define SOF_RT1015_SPEAKER_AMP_100FS BIT(15)
50 #define SOF_RT1015P_SPEAKER_AMP_PRESENT BIT(16)
51 #define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(17)
52 #define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(18)
53
54 /* BT audio offload: reserve 3 bits for future */
55 #define SOF_BT_OFFLOAD_SSP_SHIFT 19
56 #define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(21, 19))
57 #define SOF_BT_OFFLOAD_SSP(quirk) \
58 (((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
59 #define SOF_SSP_BT_OFFLOAD_PRESENT BIT(22)
60 #define SOF_RT5682S_HEADPHONE_CODEC_PRESENT BIT(23)
61 #define SOF_MAX98390_SPEAKER_AMP_PRESENT BIT(24)
62 #define SOF_MAX98390_TWEETER_SPEAKER_PRESENT BIT(25)
63 #define SOF_RT1019_SPEAKER_AMP_PRESENT BIT(26)
64
65
66 /* Default: MCLK on, MCLK 19.2M, SSP0 */
67 static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
68 SOF_RT5682_SSP_CODEC(0);
69
70 static int is_legacy_cpu;
71
72 struct sof_hdmi_pcm {
73 struct list_head head;
74 struct snd_soc_dai *codec_dai;
75 struct snd_soc_jack hdmi_jack;
76 int device;
77 };
78
79 struct sof_card_private {
80 struct clk *mclk;
81 struct snd_soc_jack sof_headset;
82 struct list_head hdmi_pcm_list;
83 bool common_hdmi_codec_drv;
84 bool idisp_codec;
85 };
86
sof_rt5682_quirk_cb(const struct dmi_system_id * id)87 static int sof_rt5682_quirk_cb(const struct dmi_system_id *id)
88 {
89 sof_rt5682_quirk = (unsigned long)id->driver_data;
90 return 1;
91 }
92
93 static const struct dmi_system_id sof_rt5682_quirk_table[] = {
94 {
95 .callback = sof_rt5682_quirk_cb,
96 .matches = {
97 DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
98 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max"),
99 },
100 .driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)),
101 },
102 {
103 .callback = sof_rt5682_quirk_cb,
104 .matches = {
105 DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
106 DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"),
107 },
108 .driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)),
109 },
110 {
111 .callback = sof_rt5682_quirk_cb,
112 .matches = {
113 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
114 DMI_MATCH(DMI_PRODUCT_NAME, "WhiskeyLake Client"),
115 },
116 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
117 SOF_RT5682_MCLK_24MHZ |
118 SOF_RT5682_SSP_CODEC(1)),
119 },
120 {
121 /*
122 * Dooly is hatch family but using rt1015 amp so it
123 * requires a quirk before "Google_Hatch".
124 */
125 .callback = sof_rt5682_quirk_cb,
126 .matches = {
127 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
128 DMI_MATCH(DMI_PRODUCT_NAME, "Dooly"),
129 },
130 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
131 SOF_RT5682_MCLK_24MHZ |
132 SOF_RT5682_SSP_CODEC(0) |
133 SOF_SPEAKER_AMP_PRESENT |
134 SOF_RT1015_SPEAKER_AMP_PRESENT |
135 SOF_RT1015_SPEAKER_AMP_100FS |
136 SOF_RT5682_SSP_AMP(1)),
137 },
138 {
139 .callback = sof_rt5682_quirk_cb,
140 .matches = {
141 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"),
142 },
143 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
144 SOF_RT5682_MCLK_24MHZ |
145 SOF_RT5682_SSP_CODEC(0) |
146 SOF_SPEAKER_AMP_PRESENT |
147 SOF_RT5682_SSP_AMP(1)),
148 },
149 {
150 .callback = sof_rt5682_quirk_cb,
151 .matches = {
152 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
153 DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
154 },
155 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
156 SOF_RT5682_SSP_CODEC(0)),
157 },
158 {
159 .callback = sof_rt5682_quirk_cb,
160 .matches = {
161 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Volteer"),
162 DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98373_ALC5682I_I2S_UP4"),
163 },
164 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
165 SOF_RT5682_SSP_CODEC(0) |
166 SOF_SPEAKER_AMP_PRESENT |
167 SOF_MAX98373_SPEAKER_AMP_PRESENT |
168 SOF_RT5682_SSP_AMP(2) |
169 SOF_RT5682_NUM_HDMIDEV(4)),
170 },
171 {
172 .callback = sof_rt5682_quirk_cb,
173 .matches = {
174 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
175 DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
176 DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"),
177 },
178 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
179 SOF_RT5682_SSP_CODEC(0) |
180 SOF_SPEAKER_AMP_PRESENT |
181 SOF_MAX98373_SPEAKER_AMP_PRESENT |
182 SOF_RT5682_SSP_AMP(2) |
183 SOF_RT5682_NUM_HDMIDEV(4)),
184 },
185 {
186 .callback = sof_rt5682_quirk_cb,
187 .matches = {
188 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
189 DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98390_ALC5682I_I2S"),
190 },
191 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
192 SOF_RT5682_SSP_CODEC(0) |
193 SOF_SPEAKER_AMP_PRESENT |
194 SOF_MAX98390_SPEAKER_AMP_PRESENT |
195 SOF_RT5682_SSP_AMP(2) |
196 SOF_RT5682_NUM_HDMIDEV(4)),
197 },
198 {
199 .callback = sof_rt5682_quirk_cb,
200 .matches = {
201 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
202 DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98390_ALC5682I_I2S_4SPK"),
203 },
204 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
205 SOF_RT5682_SSP_CODEC(0) |
206 SOF_SPEAKER_AMP_PRESENT |
207 SOF_MAX98390_SPEAKER_AMP_PRESENT |
208 SOF_MAX98390_TWEETER_SPEAKER_PRESENT |
209 SOF_RT5682_SSP_AMP(1) |
210 SOF_RT5682_NUM_HDMIDEV(4) |
211 SOF_BT_OFFLOAD_SSP(2) |
212 SOF_SSP_BT_OFFLOAD_PRESENT),
213
214 },
215 {
216 .callback = sof_rt5682_quirk_cb,
217 .matches = {
218 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
219 DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S_AMP_SSP2"),
220 },
221 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
222 SOF_RT5682_SSP_CODEC(0) |
223 SOF_SPEAKER_AMP_PRESENT |
224 SOF_MAX98360A_SPEAKER_AMP_PRESENT |
225 SOF_RT5682_SSP_AMP(2) |
226 SOF_RT5682_NUM_HDMIDEV(4)),
227 },
228 {}
229 };
230
sof_hdmi_init(struct snd_soc_pcm_runtime * rtd)231 static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
232 {
233 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
234 struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
235 struct sof_hdmi_pcm *pcm;
236
237 pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
238 if (!pcm)
239 return -ENOMEM;
240
241 /* dai_link id is 1:1 mapped to the PCM device */
242 pcm->device = rtd->dai_link->id;
243 pcm->codec_dai = dai;
244
245 list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
246
247 return 0;
248 }
249
sof_rt5682_codec_init(struct snd_soc_pcm_runtime * rtd)250 static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
251 {
252 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
253 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
254 struct snd_soc_jack *jack;
255 int ret;
256
257 /* need to enable ASRC function for 24MHz mclk rate */
258 if ((sof_rt5682_quirk & SOF_RT5682_MCLK_EN) &&
259 (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ)) {
260 if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT)
261 rt5682s_sel_asrc_clk_src(component,
262 RT5682S_DA_STEREO1_FILTER |
263 RT5682S_AD_STEREO1_FILTER,
264 RT5682S_CLK_SEL_I2S1_ASRC);
265 else
266 rt5682_sel_asrc_clk_src(component,
267 RT5682_DA_STEREO1_FILTER |
268 RT5682_AD_STEREO1_FILTER,
269 RT5682_CLK_SEL_I2S1_ASRC);
270 }
271
272 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
273 /*
274 * The firmware might enable the clock at
275 * boot (this information may or may not
276 * be reflected in the enable clock register).
277 * To change the rate we must disable the clock
278 * first to cover these cases. Due to common
279 * clock framework restrictions that do not allow
280 * to disable a clock that has not been enabled,
281 * we need to enable the clock first.
282 */
283 ret = clk_prepare_enable(ctx->mclk);
284 if (!ret)
285 clk_disable_unprepare(ctx->mclk);
286
287 ret = clk_set_rate(ctx->mclk, 19200000);
288
289 if (ret)
290 dev_err(rtd->dev, "unable to set MCLK rate\n");
291 }
292
293 /*
294 * Headset buttons map to the google Reference headset.
295 * These can be configured by userspace.
296 */
297 ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
298 SND_JACK_HEADSET | SND_JACK_BTN_0 |
299 SND_JACK_BTN_1 | SND_JACK_BTN_2 |
300 SND_JACK_BTN_3,
301 &ctx->sof_headset);
302 if (ret) {
303 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
304 return ret;
305 }
306
307 jack = &ctx->sof_headset;
308
309 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
310 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
311 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
312 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
313 ret = snd_soc_component_set_jack(component, jack, NULL);
314
315 if (ret) {
316 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
317 return ret;
318 }
319
320 return ret;
321 };
322
sof_rt5682_codec_exit(struct snd_soc_pcm_runtime * rtd)323 static void sof_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd)
324 {
325 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
326
327 snd_soc_component_set_jack(component, NULL, NULL);
328 }
329
sof_rt5682_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)330 static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,
331 struct snd_pcm_hw_params *params)
332 {
333 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
334 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
335 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
336 int pll_id, pll_source, pll_in, pll_out, clk_id, ret;
337
338 if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
339 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
340 ret = clk_prepare_enable(ctx->mclk);
341 if (ret < 0) {
342 dev_err(rtd->dev,
343 "could not configure MCLK state");
344 return ret;
345 }
346 }
347
348 if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT)
349 pll_source = RT5682S_PLL_S_MCLK;
350 else
351 pll_source = RT5682_PLL1_S_MCLK;
352
353 /* get the tplg configured mclk. */
354 pll_in = sof_dai_get_mclk(rtd);
355
356 /* mclk from the quirk is the first choice */
357 if (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ) {
358 if (pll_in != 24000000)
359 dev_warn(rtd->dev, "configure wrong mclk in tplg, please use 24MHz.\n");
360 pll_in = 24000000;
361 } else if (pll_in == 0) {
362 /* use default mclk if not specified correct in topology */
363 pll_in = 19200000;
364 } else if (pll_in < 0) {
365 return pll_in;
366 }
367 } else {
368 if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT)
369 pll_source = RT5682S_PLL_S_BCLK1;
370 else
371 pll_source = RT5682_PLL1_S_BCLK1;
372
373 pll_in = params_rate(params) * 50;
374 }
375
376 if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) {
377 pll_id = RT5682S_PLL2;
378 clk_id = RT5682S_SCLK_S_PLL2;
379 } else {
380 pll_id = RT5682_PLL1;
381 clk_id = RT5682_SCLK_S_PLL1;
382 }
383
384 pll_out = params_rate(params) * 512;
385
386 /* when MCLK is 512FS, no need to set PLL configuration additionally. */
387 if (pll_in == pll_out)
388 clk_id = RT5682S_SCLK_S_MCLK;
389 else {
390 /* Configure pll for codec */
391 ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, pll_in,
392 pll_out);
393 if (ret < 0)
394 dev_err(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret);
395 }
396
397 /* Configure sysclk for codec */
398 ret = snd_soc_dai_set_sysclk(codec_dai, clk_id,
399 pll_out, SND_SOC_CLOCK_IN);
400 if (ret < 0)
401 dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
402
403 /*
404 * slot_width should equal or large than data length, set them
405 * be the same
406 */
407 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2,
408 params_width(params));
409 if (ret < 0) {
410 dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
411 return ret;
412 }
413
414 return ret;
415 }
416
417 static struct snd_soc_ops sof_rt5682_ops = {
418 .hw_params = sof_rt5682_hw_params,
419 };
420
421 static struct snd_soc_dai_link_component platform_component[] = {
422 {
423 /* name might be overridden during probe */
424 .name = "0000:00:1f.3"
425 }
426 };
427
sof_card_late_probe(struct snd_soc_card * card)428 static int sof_card_late_probe(struct snd_soc_card *card)
429 {
430 struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
431 struct snd_soc_component *component = NULL;
432 struct snd_soc_dapm_context *dapm = &card->dapm;
433 char jack_name[NAME_SIZE];
434 struct sof_hdmi_pcm *pcm;
435 int err;
436
437 if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
438 /* Disable Left and Right Spk pin after boot */
439 snd_soc_dapm_disable_pin(dapm, "Left Spk");
440 snd_soc_dapm_disable_pin(dapm, "Right Spk");
441 err = snd_soc_dapm_sync(dapm);
442 if (err < 0)
443 return err;
444 }
445
446 /* HDMI is not supported by SOF on Baytrail/CherryTrail */
447 if (is_legacy_cpu || !ctx->idisp_codec)
448 return 0;
449
450 if (list_empty(&ctx->hdmi_pcm_list))
451 return -EINVAL;
452
453 if (ctx->common_hdmi_codec_drv) {
454 pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm,
455 head);
456 component = pcm->codec_dai->component;
457 return hda_dsp_hdmi_build_controls(card, component);
458 }
459
460 list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
461 component = pcm->codec_dai->component;
462 snprintf(jack_name, sizeof(jack_name),
463 "HDMI/DP, pcm=%d Jack", pcm->device);
464 err = snd_soc_card_jack_new(card, jack_name,
465 SND_JACK_AVOUT, &pcm->hdmi_jack);
466
467 if (err)
468 return err;
469
470 err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
471 &pcm->hdmi_jack);
472 if (err < 0)
473 return err;
474 }
475
476 return hdac_hdmi_jack_port_init(component, &card->dapm);
477 }
478
479 static const struct snd_kcontrol_new sof_controls[] = {
480 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
481 SOC_DAPM_PIN_SWITCH("Headset Mic"),
482 SOC_DAPM_PIN_SWITCH("Left Spk"),
483 SOC_DAPM_PIN_SWITCH("Right Spk"),
484
485 };
486
487 static const struct snd_soc_dapm_widget sof_widgets[] = {
488 SND_SOC_DAPM_HP("Headphone Jack", NULL),
489 SND_SOC_DAPM_MIC("Headset Mic", NULL),
490 SND_SOC_DAPM_SPK("Left Spk", NULL),
491 SND_SOC_DAPM_SPK("Right Spk", NULL),
492 };
493
494 static const struct snd_soc_dapm_widget dmic_widgets[] = {
495 SND_SOC_DAPM_MIC("SoC DMIC", NULL),
496 };
497
498 static const struct snd_soc_dapm_route sof_map[] = {
499 /* HP jack connectors - unknown if we have jack detection */
500 { "Headphone Jack", NULL, "HPOL" },
501 { "Headphone Jack", NULL, "HPOR" },
502
503 /* other jacks */
504 { "IN1P", NULL, "Headset Mic" },
505 };
506
507 static const struct snd_soc_dapm_route dmic_map[] = {
508 /* digital mics */
509 {"DMic", NULL, "SoC DMIC"},
510 };
511
dmic_init(struct snd_soc_pcm_runtime * rtd)512 static int dmic_init(struct snd_soc_pcm_runtime *rtd)
513 {
514 struct snd_soc_card *card = rtd->card;
515 int ret;
516
517 ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
518 ARRAY_SIZE(dmic_widgets));
519 if (ret) {
520 dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
521 /* Don't need to add routes if widget addition failed */
522 return ret;
523 }
524
525 ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
526 ARRAY_SIZE(dmic_map));
527
528 if (ret)
529 dev_err(card->dev, "DMic map addition failed: %d\n", ret);
530
531 return ret;
532 }
533
534 /* sof audio machine driver for rt5682 codec */
535 static struct snd_soc_card sof_audio_card_rt5682 = {
536 .name = "rt5682", /* the sof- prefix is added by the core */
537 .owner = THIS_MODULE,
538 .controls = sof_controls,
539 .num_controls = ARRAY_SIZE(sof_controls),
540 .dapm_widgets = sof_widgets,
541 .num_dapm_widgets = ARRAY_SIZE(sof_widgets),
542 .dapm_routes = sof_map,
543 .num_dapm_routes = ARRAY_SIZE(sof_map),
544 .fully_routed = true,
545 .late_probe = sof_card_late_probe,
546 };
547
548 static struct snd_soc_dai_link_component rt5682_component[] = {
549 {
550 .name = "i2c-10EC5682:00",
551 .dai_name = "rt5682-aif1",
552 }
553 };
554
555 static struct snd_soc_dai_link_component rt5682s_component[] = {
556 {
557 .name = "i2c-RTL5682:00",
558 .dai_name = "rt5682s-aif1",
559 }
560 };
561
562 static struct snd_soc_dai_link_component dmic_component[] = {
563 {
564 .name = "dmic-codec",
565 .dai_name = "dmic-hifi",
566 }
567 };
568
569 static struct snd_soc_dai_link_component dummy_component[] = {
570 {
571 .name = "snd-soc-dummy",
572 .dai_name = "snd-soc-dummy-dai",
573 }
574 };
575
576 #define IDISP_CODEC_MASK 0x4
577
sof_card_dai_links_create(struct device * dev,int ssp_codec,int ssp_amp,int dmic_be_num,int hdmi_num,bool idisp_codec)578 static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
579 int ssp_codec,
580 int ssp_amp,
581 int dmic_be_num,
582 int hdmi_num,
583 bool idisp_codec)
584 {
585 struct snd_soc_dai_link_component *idisp_components;
586 struct snd_soc_dai_link_component *cpus;
587 struct snd_soc_dai_link *links;
588 int i, id = 0;
589
590 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
591 sof_audio_card_rt5682.num_links, GFP_KERNEL);
592 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
593 sof_audio_card_rt5682.num_links, GFP_KERNEL);
594 if (!links || !cpus)
595 goto devm_err;
596
597 /* codec SSP */
598 links[id].name = devm_kasprintf(dev, GFP_KERNEL,
599 "SSP%d-Codec", ssp_codec);
600 if (!links[id].name)
601 goto devm_err;
602
603 links[id].id = id;
604 if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) {
605 links[id].codecs = rt5682s_component;
606 links[id].num_codecs = ARRAY_SIZE(rt5682s_component);
607 } else {
608 links[id].codecs = rt5682_component;
609 links[id].num_codecs = ARRAY_SIZE(rt5682_component);
610 }
611 links[id].platforms = platform_component;
612 links[id].num_platforms = ARRAY_SIZE(platform_component);
613 links[id].init = sof_rt5682_codec_init;
614 links[id].exit = sof_rt5682_codec_exit;
615 links[id].ops = &sof_rt5682_ops;
616 links[id].dpcm_playback = 1;
617 links[id].dpcm_capture = 1;
618 links[id].no_pcm = 1;
619 links[id].cpus = &cpus[id];
620 links[id].num_cpus = 1;
621 if (is_legacy_cpu) {
622 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
623 "ssp%d-port",
624 ssp_codec);
625 if (!links[id].cpus->dai_name)
626 goto devm_err;
627 } else {
628 /*
629 * Currently, On SKL+ platforms MCLK will be turned off in sof
630 * runtime suspended, and it will go into runtime suspended
631 * right after playback is stop. However, rt5682 will output
632 * static noise if sysclk turns off during playback. Set
633 * ignore_pmdown_time to power down rt5682 immediately and
634 * avoid the noise.
635 * It can be removed once we can control MCLK by driver.
636 */
637 links[id].ignore_pmdown_time = 1;
638 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
639 "SSP%d Pin",
640 ssp_codec);
641 if (!links[id].cpus->dai_name)
642 goto devm_err;
643 }
644 id++;
645
646 /* dmic */
647 if (dmic_be_num > 0) {
648 /* at least we have dmic01 */
649 links[id].name = "dmic01";
650 links[id].cpus = &cpus[id];
651 links[id].cpus->dai_name = "DMIC01 Pin";
652 links[id].init = dmic_init;
653 if (dmic_be_num > 1) {
654 /* set up 2 BE links at most */
655 links[id + 1].name = "dmic16k";
656 links[id + 1].cpus = &cpus[id + 1];
657 links[id + 1].cpus->dai_name = "DMIC16k Pin";
658 dmic_be_num = 2;
659 }
660 }
661
662 for (i = 0; i < dmic_be_num; i++) {
663 links[id].id = id;
664 links[id].num_cpus = 1;
665 links[id].codecs = dmic_component;
666 links[id].num_codecs = ARRAY_SIZE(dmic_component);
667 links[id].platforms = platform_component;
668 links[id].num_platforms = ARRAY_SIZE(platform_component);
669 links[id].ignore_suspend = 1;
670 links[id].dpcm_capture = 1;
671 links[id].no_pcm = 1;
672 id++;
673 }
674
675 /* HDMI */
676 if (hdmi_num > 0) {
677 idisp_components = devm_kzalloc(dev,
678 sizeof(struct snd_soc_dai_link_component) *
679 hdmi_num, GFP_KERNEL);
680 if (!idisp_components)
681 goto devm_err;
682 }
683 for (i = 1; i <= hdmi_num; i++) {
684 links[id].name = devm_kasprintf(dev, GFP_KERNEL,
685 "iDisp%d", i);
686 if (!links[id].name)
687 goto devm_err;
688
689 links[id].id = id;
690 links[id].cpus = &cpus[id];
691 links[id].num_cpus = 1;
692 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
693 "iDisp%d Pin", i);
694 if (!links[id].cpus->dai_name)
695 goto devm_err;
696
697 if (idisp_codec) {
698 idisp_components[i - 1].name = "ehdaudio0D2";
699 idisp_components[i - 1].dai_name = devm_kasprintf(dev,
700 GFP_KERNEL,
701 "intel-hdmi-hifi%d",
702 i);
703 if (!idisp_components[i - 1].dai_name)
704 goto devm_err;
705 } else {
706 idisp_components[i - 1].name = "snd-soc-dummy";
707 idisp_components[i - 1].dai_name = "snd-soc-dummy-dai";
708 }
709
710 links[id].codecs = &idisp_components[i - 1];
711 links[id].num_codecs = 1;
712 links[id].platforms = platform_component;
713 links[id].num_platforms = ARRAY_SIZE(platform_component);
714 links[id].init = sof_hdmi_init;
715 links[id].dpcm_playback = 1;
716 links[id].no_pcm = 1;
717 id++;
718 }
719
720 /* speaker amp */
721 if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) {
722 links[id].name = devm_kasprintf(dev, GFP_KERNEL,
723 "SSP%d-Codec", ssp_amp);
724 if (!links[id].name)
725 goto devm_err;
726
727 links[id].id = id;
728 if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT) {
729 sof_rt1015_dai_link(&links[id], (sof_rt5682_quirk &
730 SOF_RT1015_SPEAKER_AMP_100FS) ? 100 : 64);
731 } else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) {
732 sof_rt1015p_dai_link(&links[id]);
733 } else if (sof_rt5682_quirk & SOF_RT1019_SPEAKER_AMP_PRESENT) {
734 sof_rt1019_dai_link(&links[id]);
735 } else if (sof_rt5682_quirk &
736 SOF_MAX98373_SPEAKER_AMP_PRESENT) {
737 links[id].codecs = max_98373_components;
738 links[id].num_codecs = ARRAY_SIZE(max_98373_components);
739 links[id].init = max_98373_spk_codec_init;
740 links[id].ops = &max_98373_ops;
741 /* feedback stream */
742 links[id].dpcm_capture = 1;
743 } else if (sof_rt5682_quirk &
744 SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
745 max_98360a_dai_link(&links[id]);
746 } else if (sof_rt5682_quirk &
747 SOF_RT1011_SPEAKER_AMP_PRESENT) {
748 sof_rt1011_dai_link(&links[id]);
749 } else if (sof_rt5682_quirk &
750 SOF_MAX98390_SPEAKER_AMP_PRESENT) {
751 if (sof_rt5682_quirk &
752 SOF_MAX98390_TWEETER_SPEAKER_PRESENT) {
753 links[id].codecs = max_98390_4spk_components;
754 links[id].num_codecs = ARRAY_SIZE(max_98390_4spk_components);
755 } else {
756 links[id].codecs = max_98390_components;
757 links[id].num_codecs = ARRAY_SIZE(max_98390_components);
758 }
759 links[id].init = max_98390_spk_codec_init;
760 links[id].ops = &max_98390_ops;
761 links[id].dpcm_capture = 1;
762
763 } else {
764 max_98357a_dai_link(&links[id]);
765 }
766 links[id].platforms = platform_component;
767 links[id].num_platforms = ARRAY_SIZE(platform_component);
768 links[id].dpcm_playback = 1;
769 links[id].no_pcm = 1;
770 links[id].cpus = &cpus[id];
771 links[id].num_cpus = 1;
772 if (is_legacy_cpu) {
773 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
774 "ssp%d-port",
775 ssp_amp);
776 if (!links[id].cpus->dai_name)
777 goto devm_err;
778
779 } else {
780 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
781 "SSP%d Pin",
782 ssp_amp);
783 if (!links[id].cpus->dai_name)
784 goto devm_err;
785 }
786 id++;
787 }
788
789 /* BT audio offload */
790 if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
791 int port = (sof_rt5682_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
792 SOF_BT_OFFLOAD_SSP_SHIFT;
793
794 links[id].id = id;
795 links[id].cpus = &cpus[id];
796 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
797 "SSP%d Pin", port);
798 if (!links[id].cpus->dai_name)
799 goto devm_err;
800 links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
801 if (!links[id].name)
802 goto devm_err;
803 links[id].codecs = dummy_component;
804 links[id].num_codecs = ARRAY_SIZE(dummy_component);
805 links[id].platforms = platform_component;
806 links[id].num_platforms = ARRAY_SIZE(platform_component);
807 links[id].dpcm_playback = 1;
808 links[id].dpcm_capture = 1;
809 links[id].no_pcm = 1;
810 links[id].num_cpus = 1;
811 }
812
813 return links;
814 devm_err:
815 return NULL;
816 }
817
sof_audio_probe(struct platform_device * pdev)818 static int sof_audio_probe(struct platform_device *pdev)
819 {
820 struct snd_soc_dai_link *dai_links;
821 struct snd_soc_acpi_mach *mach;
822 struct sof_card_private *ctx;
823 int dmic_be_num, hdmi_num;
824 int ret, ssp_amp, ssp_codec;
825
826 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
827 if (!ctx)
828 return -ENOMEM;
829
830 if (pdev->id_entry && pdev->id_entry->driver_data)
831 sof_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data;
832
833 dmi_check_system(sof_rt5682_quirk_table);
834
835 mach = pdev->dev.platform_data;
836
837 /* A speaker amp might not be present when the quirk claims one is.
838 * Detect this via whether the machine driver match includes quirk_data.
839 */
840 if ((sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) && !mach->quirk_data)
841 sof_rt5682_quirk &= ~SOF_SPEAKER_AMP_PRESENT;
842
843 /* Detect the headset codec variant */
844 if (acpi_dev_present("RTL5682", NULL, -1))
845 sof_rt5682_quirk |= SOF_RT5682S_HEADPHONE_CODEC_PRESENT;
846
847 /* Detect the headset codec variant to support machines in DMI quirk */
848 if (acpi_dev_present("RTL5682", NULL, -1))
849 sof_rt5682_quirk |= SOF_RT5682S_HEADPHONE_CODEC_PRESENT;
850
851 if (soc_intel_is_byt() || soc_intel_is_cht()) {
852 is_legacy_cpu = 1;
853 dmic_be_num = 0;
854 hdmi_num = 0;
855 /* default quirk for legacy cpu */
856 sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
857 SOF_RT5682_MCLK_BYTCHT_EN |
858 SOF_RT5682_SSP_CODEC(2);
859 } else {
860 dmic_be_num = 2;
861 hdmi_num = (sof_rt5682_quirk & SOF_RT5682_NUM_HDMIDEV_MASK) >>
862 SOF_RT5682_NUM_HDMIDEV_SHIFT;
863 /* default number of HDMI DAI's */
864 if (!hdmi_num)
865 hdmi_num = 3;
866
867 if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
868 ctx->idisp_codec = true;
869 }
870
871 /* need to get main clock from pmc */
872 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
873 ctx->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
874 if (IS_ERR(ctx->mclk)) {
875 ret = PTR_ERR(ctx->mclk);
876
877 dev_err(&pdev->dev,
878 "Failed to get MCLK from pmc_plt_clk_3: %d\n",
879 ret);
880 return ret;
881 }
882
883 ret = clk_prepare_enable(ctx->mclk);
884 if (ret < 0) {
885 dev_err(&pdev->dev,
886 "could not configure MCLK state");
887 return ret;
888 }
889 }
890
891 dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk);
892
893 ssp_amp = (sof_rt5682_quirk & SOF_RT5682_SSP_AMP_MASK) >>
894 SOF_RT5682_SSP_AMP_SHIFT;
895
896 ssp_codec = sof_rt5682_quirk & SOF_RT5682_SSP_CODEC_MASK;
897
898 /* compute number of dai links */
899 sof_audio_card_rt5682.num_links = 1 + dmic_be_num + hdmi_num;
900
901 if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT)
902 sof_audio_card_rt5682.num_links++;
903
904 if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT)
905 max_98373_set_codec_conf(&sof_audio_card_rt5682);
906 else if (sof_rt5682_quirk & SOF_RT1011_SPEAKER_AMP_PRESENT)
907 sof_rt1011_codec_conf(&sof_audio_card_rt5682);
908 else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT)
909 sof_rt1015p_codec_conf(&sof_audio_card_rt5682);
910 else if (sof_rt5682_quirk & SOF_MAX98390_SPEAKER_AMP_PRESENT) {
911 if (sof_rt5682_quirk & SOF_MAX98390_TWEETER_SPEAKER_PRESENT)
912 max_98390_set_codec_conf(&sof_audio_card_rt5682,
913 ARRAY_SIZE(max_98390_4spk_components));
914 else
915 max_98390_set_codec_conf(&sof_audio_card_rt5682,
916 ARRAY_SIZE(max_98390_components));
917 }
918
919 if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
920 sof_audio_card_rt5682.num_links++;
921
922 dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,
923 dmic_be_num, hdmi_num, ctx->idisp_codec);
924 if (!dai_links)
925 return -ENOMEM;
926
927 sof_audio_card_rt5682.dai_link = dai_links;
928
929 if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT)
930 sof_rt1015_codec_conf(&sof_audio_card_rt5682);
931
932 INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
933
934 sof_audio_card_rt5682.dev = &pdev->dev;
935
936 /* set platform name for each dailink */
937 ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_rt5682,
938 mach->mach_params.platform);
939 if (ret)
940 return ret;
941
942 ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
943
944 snd_soc_card_set_drvdata(&sof_audio_card_rt5682, ctx);
945
946 return devm_snd_soc_register_card(&pdev->dev,
947 &sof_audio_card_rt5682);
948 }
949
950 static const struct platform_device_id board_ids[] = {
951 {
952 .name = "sof_rt5682",
953 },
954 {
955 .name = "tgl_mx98357_rt5682",
956 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
957 SOF_RT5682_SSP_CODEC(0) |
958 SOF_SPEAKER_AMP_PRESENT |
959 SOF_RT5682_SSP_AMP(1) |
960 SOF_RT5682_NUM_HDMIDEV(4) |
961 SOF_BT_OFFLOAD_SSP(2) |
962 SOF_SSP_BT_OFFLOAD_PRESENT),
963 },
964 {
965 .name = "jsl_rt5682_rt1015",
966 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
967 SOF_RT5682_MCLK_24MHZ |
968 SOF_RT5682_SSP_CODEC(0) |
969 SOF_SPEAKER_AMP_PRESENT |
970 SOF_RT1015_SPEAKER_AMP_PRESENT |
971 SOF_RT5682_SSP_AMP(1)),
972 },
973 {
974 .name = "tgl_mx98373_rt5682",
975 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
976 SOF_RT5682_SSP_CODEC(0) |
977 SOF_SPEAKER_AMP_PRESENT |
978 SOF_MAX98373_SPEAKER_AMP_PRESENT |
979 SOF_RT5682_SSP_AMP(1) |
980 SOF_RT5682_NUM_HDMIDEV(4) |
981 SOF_BT_OFFLOAD_SSP(2) |
982 SOF_SSP_BT_OFFLOAD_PRESENT),
983 },
984 {
985 .name = "jsl_rt5682_mx98360",
986 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
987 SOF_RT5682_MCLK_24MHZ |
988 SOF_RT5682_SSP_CODEC(0) |
989 SOF_SPEAKER_AMP_PRESENT |
990 SOF_MAX98360A_SPEAKER_AMP_PRESENT |
991 SOF_RT5682_SSP_AMP(1)),
992 },
993 {
994 .name = "cml_rt1015_rt5682",
995 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
996 SOF_RT5682_MCLK_24MHZ |
997 SOF_RT5682_SSP_CODEC(0) |
998 SOF_SPEAKER_AMP_PRESENT |
999 SOF_RT1015_SPEAKER_AMP_PRESENT |
1000 SOF_RT1015_SPEAKER_AMP_100FS |
1001 SOF_RT5682_SSP_AMP(1)),
1002 },
1003 {
1004 .name = "tgl_rt1011_rt5682",
1005 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1006 SOF_RT5682_SSP_CODEC(0) |
1007 SOF_SPEAKER_AMP_PRESENT |
1008 SOF_RT1011_SPEAKER_AMP_PRESENT |
1009 SOF_RT5682_SSP_AMP(1) |
1010 SOF_RT5682_NUM_HDMIDEV(4) |
1011 SOF_BT_OFFLOAD_SSP(2) |
1012 SOF_SSP_BT_OFFLOAD_PRESENT),
1013 },
1014 {
1015 .name = "jsl_rt5682_rt1015p",
1016 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1017 SOF_RT5682_MCLK_24MHZ |
1018 SOF_RT5682_SSP_CODEC(0) |
1019 SOF_SPEAKER_AMP_PRESENT |
1020 SOF_RT1015P_SPEAKER_AMP_PRESENT |
1021 SOF_RT5682_SSP_AMP(1)),
1022 },
1023 {
1024 .name = "adl_mx98373_rt5682",
1025 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1026 SOF_RT5682_SSP_CODEC(0) |
1027 SOF_SPEAKER_AMP_PRESENT |
1028 SOF_MAX98373_SPEAKER_AMP_PRESENT |
1029 SOF_RT5682_SSP_AMP(1) |
1030 SOF_RT5682_NUM_HDMIDEV(4) |
1031 SOF_BT_OFFLOAD_SSP(2) |
1032 SOF_SSP_BT_OFFLOAD_PRESENT),
1033 },
1034 {
1035 .name = "adl_mx98357_rt5682",
1036 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1037 SOF_RT5682_SSP_CODEC(0) |
1038 SOF_SPEAKER_AMP_PRESENT |
1039 SOF_RT5682_SSP_AMP(2) |
1040 SOF_RT5682_NUM_HDMIDEV(4)),
1041 },
1042 {
1043 .name = "adl_max98390_rt5682",
1044 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1045 SOF_RT5682_SSP_CODEC(0) |
1046 SOF_SPEAKER_AMP_PRESENT |
1047 SOF_MAX98390_SPEAKER_AMP_PRESENT |
1048 SOF_RT5682_SSP_AMP(1) |
1049 SOF_RT5682_NUM_HDMIDEV(4) |
1050 SOF_BT_OFFLOAD_SSP(2) |
1051 SOF_SSP_BT_OFFLOAD_PRESENT),
1052 },
1053 {
1054 .name = "adl_mx98360_rt5682",
1055 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1056 SOF_RT5682_SSP_CODEC(0) |
1057 SOF_SPEAKER_AMP_PRESENT |
1058 SOF_MAX98360A_SPEAKER_AMP_PRESENT |
1059 SOF_RT5682_SSP_AMP(1) |
1060 SOF_RT5682_NUM_HDMIDEV(4) |
1061 SOF_BT_OFFLOAD_SSP(2) |
1062 SOF_SSP_BT_OFFLOAD_PRESENT),
1063 },
1064 {
1065 .name = "adl_rt5682",
1066 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1067 SOF_RT5682_SSP_CODEC(0) |
1068 SOF_RT5682_NUM_HDMIDEV(4) |
1069 SOF_BT_OFFLOAD_SSP(2) |
1070 SOF_SSP_BT_OFFLOAD_PRESENT),
1071 },
1072 {
1073 .name = "adl_rt1019_rt5682s",
1074 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1075 SOF_RT5682_SSP_CODEC(0) |
1076 SOF_RT5682S_HEADPHONE_CODEC_PRESENT |
1077 SOF_SPEAKER_AMP_PRESENT |
1078 SOF_RT1019_SPEAKER_AMP_PRESENT |
1079 SOF_RT5682_SSP_AMP(1) |
1080 SOF_RT5682_NUM_HDMIDEV(4)),
1081 },
1082 { }
1083 };
1084 MODULE_DEVICE_TABLE(platform, board_ids);
1085
1086 static struct platform_driver sof_audio = {
1087 .probe = sof_audio_probe,
1088 .driver = {
1089 .name = "sof_rt5682",
1090 .pm = &snd_soc_pm_ops,
1091 },
1092 .id_table = board_ids,
1093 };
1094 module_platform_driver(sof_audio)
1095
1096 /* Module information */
1097 MODULE_DESCRIPTION("SOF Audio Machine driver");
1098 MODULE_AUTHOR("Bard Liao <bard.liao@intel.com>");
1099 MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
1100 MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
1101 MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
1102 MODULE_LICENSE("GPL v2");
1103 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
1104 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
1105 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
1106