1
2
3
4
5
6
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
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
64
65
66static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
67 SOF_RT5682_SSP_CODEC(0);
68
69static int is_legacy_cpu;
70
71static struct snd_soc_jack sof_hdmi[3];
72
73struct sof_hdmi_pcm {
74 struct list_head head;
75 struct snd_soc_dai *codec_dai;
76 int device;
77};
78
79struct 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
87static 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
93static 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
123
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
231static 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
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
250static 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
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
275
276
277
278
279
280
281
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
295
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, NULL, 0);
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
323static 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
330static 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
354 pll_in = sof_dai_get_mclk(rtd);
355
356
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
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
387 if (pll_in == pll_out)
388 clk_id = RT5682S_SCLK_S_MCLK;
389 else {
390
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
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
405
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
417static struct snd_soc_ops sof_rt5682_ops = {
418 .hw_params = sof_rt5682_hw_params,
419};
420
421static struct snd_soc_dai_link_component platform_component[] = {
422 {
423
424 .name = "0000:00:1f.3"
425 }
426};
427
428static 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 int i = 0;
437
438
439 if (is_legacy_cpu || !ctx->idisp_codec)
440 return 0;
441
442 if (list_empty(&ctx->hdmi_pcm_list))
443 return -EINVAL;
444
445 if (ctx->common_hdmi_codec_drv) {
446 pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm,
447 head);
448 component = pcm->codec_dai->component;
449 return hda_dsp_hdmi_build_controls(card, component);
450 }
451
452 list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
453 component = pcm->codec_dai->component;
454 snprintf(jack_name, sizeof(jack_name),
455 "HDMI/DP, pcm=%d Jack", pcm->device);
456 err = snd_soc_card_jack_new(card, jack_name,
457 SND_JACK_AVOUT, &sof_hdmi[i],
458 NULL, 0);
459
460 if (err)
461 return err;
462
463 err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
464 &sof_hdmi[i]);
465 if (err < 0)
466 return err;
467
468 i++;
469 }
470
471 if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
472
473 snd_soc_dapm_disable_pin(dapm, "Left Spk");
474 snd_soc_dapm_disable_pin(dapm, "Right Spk");
475 err = snd_soc_dapm_sync(dapm);
476 if (err < 0)
477 return err;
478 }
479
480 return hdac_hdmi_jack_port_init(component, &card->dapm);
481}
482
483static const struct snd_kcontrol_new sof_controls[] = {
484 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
485 SOC_DAPM_PIN_SWITCH("Headset Mic"),
486 SOC_DAPM_PIN_SWITCH("Left Spk"),
487 SOC_DAPM_PIN_SWITCH("Right Spk"),
488
489};
490
491static const struct snd_soc_dapm_widget sof_widgets[] = {
492 SND_SOC_DAPM_HP("Headphone Jack", NULL),
493 SND_SOC_DAPM_MIC("Headset Mic", NULL),
494 SND_SOC_DAPM_SPK("Left Spk", NULL),
495 SND_SOC_DAPM_SPK("Right Spk", NULL),
496};
497
498static const struct snd_soc_dapm_widget dmic_widgets[] = {
499 SND_SOC_DAPM_MIC("SoC DMIC", NULL),
500};
501
502static const struct snd_soc_dapm_route sof_map[] = {
503
504 { "Headphone Jack", NULL, "HPOL" },
505 { "Headphone Jack", NULL, "HPOR" },
506
507
508 { "IN1P", NULL, "Headset Mic" },
509};
510
511static const struct snd_soc_dapm_route dmic_map[] = {
512
513 {"DMic", NULL, "SoC DMIC"},
514};
515
516static int dmic_init(struct snd_soc_pcm_runtime *rtd)
517{
518 struct snd_soc_card *card = rtd->card;
519 int ret;
520
521 ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
522 ARRAY_SIZE(dmic_widgets));
523 if (ret) {
524 dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
525
526 return ret;
527 }
528
529 ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
530 ARRAY_SIZE(dmic_map));
531
532 if (ret)
533 dev_err(card->dev, "DMic map addition failed: %d\n", ret);
534
535 return ret;
536}
537
538
539static struct snd_soc_card sof_audio_card_rt5682 = {
540 .name = "rt5682",
541 .owner = THIS_MODULE,
542 .controls = sof_controls,
543 .num_controls = ARRAY_SIZE(sof_controls),
544 .dapm_widgets = sof_widgets,
545 .num_dapm_widgets = ARRAY_SIZE(sof_widgets),
546 .dapm_routes = sof_map,
547 .num_dapm_routes = ARRAY_SIZE(sof_map),
548 .fully_routed = true,
549 .late_probe = sof_card_late_probe,
550};
551
552static struct snd_soc_dai_link_component rt5682_component[] = {
553 {
554 .name = "i2c-10EC5682:00",
555 .dai_name = "rt5682-aif1",
556 }
557};
558
559static struct snd_soc_dai_link_component rt5682s_component[] = {
560 {
561 .name = "i2c-RTL5682:00",
562 .dai_name = "rt5682s-aif1",
563 }
564};
565
566static struct snd_soc_dai_link_component dmic_component[] = {
567 {
568 .name = "dmic-codec",
569 .dai_name = "dmic-hifi",
570 }
571};
572
573static struct snd_soc_dai_link_component dummy_component[] = {
574 {
575 .name = "snd-soc-dummy",
576 .dai_name = "snd-soc-dummy-dai",
577 }
578};
579
580#define IDISP_CODEC_MASK 0x4
581
582static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
583 int ssp_codec,
584 int ssp_amp,
585 int dmic_be_num,
586 int hdmi_num,
587 bool idisp_codec)
588{
589 struct snd_soc_dai_link_component *idisp_components;
590 struct snd_soc_dai_link_component *cpus;
591 struct snd_soc_dai_link *links;
592 int i, id = 0;
593
594 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
595 sof_audio_card_rt5682.num_links, GFP_KERNEL);
596 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
597 sof_audio_card_rt5682.num_links, GFP_KERNEL);
598 if (!links || !cpus)
599 goto devm_err;
600
601
602 links[id].name = devm_kasprintf(dev, GFP_KERNEL,
603 "SSP%d-Codec", ssp_codec);
604 if (!links[id].name)
605 goto devm_err;
606
607 links[id].id = id;
608 if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) {
609 links[id].codecs = rt5682s_component;
610 links[id].num_codecs = ARRAY_SIZE(rt5682s_component);
611 } else {
612 links[id].codecs = rt5682_component;
613 links[id].num_codecs = ARRAY_SIZE(rt5682_component);
614 }
615 links[id].platforms = platform_component;
616 links[id].num_platforms = ARRAY_SIZE(platform_component);
617 links[id].init = sof_rt5682_codec_init;
618 links[id].exit = sof_rt5682_codec_exit;
619 links[id].ops = &sof_rt5682_ops;
620 links[id].dpcm_playback = 1;
621 links[id].dpcm_capture = 1;
622 links[id].no_pcm = 1;
623 links[id].cpus = &cpus[id];
624 links[id].num_cpus = 1;
625 if (is_legacy_cpu) {
626 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
627 "ssp%d-port",
628 ssp_codec);
629 if (!links[id].cpus->dai_name)
630 goto devm_err;
631 } else {
632
633
634
635
636
637
638
639
640
641 links[id].ignore_pmdown_time = 1;
642 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
643 "SSP%d Pin",
644 ssp_codec);
645 if (!links[id].cpus->dai_name)
646 goto devm_err;
647 }
648 id++;
649
650
651 if (dmic_be_num > 0) {
652
653 links[id].name = "dmic01";
654 links[id].cpus = &cpus[id];
655 links[id].cpus->dai_name = "DMIC01 Pin";
656 links[id].init = dmic_init;
657 if (dmic_be_num > 1) {
658
659 links[id + 1].name = "dmic16k";
660 links[id + 1].cpus = &cpus[id + 1];
661 links[id + 1].cpus->dai_name = "DMIC16k Pin";
662 dmic_be_num = 2;
663 }
664 }
665
666 for (i = 0; i < dmic_be_num; i++) {
667 links[id].id = id;
668 links[id].num_cpus = 1;
669 links[id].codecs = dmic_component;
670 links[id].num_codecs = ARRAY_SIZE(dmic_component);
671 links[id].platforms = platform_component;
672 links[id].num_platforms = ARRAY_SIZE(platform_component);
673 links[id].ignore_suspend = 1;
674 links[id].dpcm_capture = 1;
675 links[id].no_pcm = 1;
676 id++;
677 }
678
679
680 if (hdmi_num > 0) {
681 idisp_components = devm_kzalloc(dev,
682 sizeof(struct snd_soc_dai_link_component) *
683 hdmi_num, GFP_KERNEL);
684 if (!idisp_components)
685 goto devm_err;
686 }
687 for (i = 1; i <= hdmi_num; i++) {
688 links[id].name = devm_kasprintf(dev, GFP_KERNEL,
689 "iDisp%d", i);
690 if (!links[id].name)
691 goto devm_err;
692
693 links[id].id = id;
694 links[id].cpus = &cpus[id];
695 links[id].num_cpus = 1;
696 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
697 "iDisp%d Pin", i);
698 if (!links[id].cpus->dai_name)
699 goto devm_err;
700
701 if (idisp_codec) {
702 idisp_components[i - 1].name = "ehdaudio0D2";
703 idisp_components[i - 1].dai_name = devm_kasprintf(dev,
704 GFP_KERNEL,
705 "intel-hdmi-hifi%d",
706 i);
707 if (!idisp_components[i - 1].dai_name)
708 goto devm_err;
709 } else {
710 idisp_components[i - 1].name = "snd-soc-dummy";
711 idisp_components[i - 1].dai_name = "snd-soc-dummy-dai";
712 }
713
714 links[id].codecs = &idisp_components[i - 1];
715 links[id].num_codecs = 1;
716 links[id].platforms = platform_component;
717 links[id].num_platforms = ARRAY_SIZE(platform_component);
718 links[id].init = sof_hdmi_init;
719 links[id].dpcm_playback = 1;
720 links[id].no_pcm = 1;
721 id++;
722 }
723
724
725 if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) {
726 links[id].name = devm_kasprintf(dev, GFP_KERNEL,
727 "SSP%d-Codec", ssp_amp);
728 if (!links[id].name)
729 goto devm_err;
730
731 links[id].id = id;
732 if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT) {
733 sof_rt1015_dai_link(&links[id], (sof_rt5682_quirk &
734 SOF_RT1015_SPEAKER_AMP_100FS) ? 100 : 64);
735 } else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) {
736 sof_rt1015p_dai_link(&links[id]);
737 } else if (sof_rt5682_quirk &
738 SOF_MAX98373_SPEAKER_AMP_PRESENT) {
739 links[id].codecs = max_98373_components;
740 links[id].num_codecs = ARRAY_SIZE(max_98373_components);
741 links[id].init = max_98373_spk_codec_init;
742 links[id].ops = &max_98373_ops;
743
744 links[id].dpcm_capture = 1;
745 } else if (sof_rt5682_quirk &
746 SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
747 max_98360a_dai_link(&links[id]);
748 } else if (sof_rt5682_quirk &
749 SOF_RT1011_SPEAKER_AMP_PRESENT) {
750 sof_rt1011_dai_link(&links[id]);
751 } else if (sof_rt5682_quirk &
752 SOF_MAX98390_SPEAKER_AMP_PRESENT) {
753 if (sof_rt5682_quirk &
754 SOF_MAX98390_TWEETER_SPEAKER_PRESENT) {
755 links[id].codecs = max_98390_4spk_components;
756 links[id].num_codecs = ARRAY_SIZE(max_98390_4spk_components);
757 } else {
758 links[id].codecs = max_98390_components;
759 links[id].num_codecs = ARRAY_SIZE(max_98390_components);
760 }
761 links[id].init = max_98390_spk_codec_init;
762 links[id].ops = &max_98390_ops;
763 links[id].dpcm_capture = 1;
764
765 } else {
766 max_98357a_dai_link(&links[id]);
767 }
768 links[id].platforms = platform_component;
769 links[id].num_platforms = ARRAY_SIZE(platform_component);
770 links[id].dpcm_playback = 1;
771 links[id].no_pcm = 1;
772 links[id].cpus = &cpus[id];
773 links[id].num_cpus = 1;
774 if (is_legacy_cpu) {
775 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
776 "ssp%d-port",
777 ssp_amp);
778 if (!links[id].cpus->dai_name)
779 goto devm_err;
780
781 } else {
782 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
783 "SSP%d Pin",
784 ssp_amp);
785 if (!links[id].cpus->dai_name)
786 goto devm_err;
787 }
788 id++;
789 }
790
791
792 if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
793 int port = (sof_rt5682_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
794 SOF_BT_OFFLOAD_SSP_SHIFT;
795
796 links[id].id = id;
797 links[id].cpus = &cpus[id];
798 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
799 "SSP%d Pin", port);
800 if (!links[id].cpus->dai_name)
801 goto devm_err;
802 links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
803 if (!links[id].name)
804 goto devm_err;
805 links[id].codecs = dummy_component;
806 links[id].num_codecs = ARRAY_SIZE(dummy_component);
807 links[id].platforms = platform_component;
808 links[id].num_platforms = ARRAY_SIZE(platform_component);
809 links[id].dpcm_playback = 1;
810 links[id].dpcm_capture = 1;
811 links[id].no_pcm = 1;
812 links[id].num_cpus = 1;
813 }
814
815 return links;
816devm_err:
817 return NULL;
818}
819
820static int sof_audio_probe(struct platform_device *pdev)
821{
822 struct snd_soc_dai_link *dai_links;
823 struct snd_soc_acpi_mach *mach;
824 struct sof_card_private *ctx;
825 int dmic_be_num, hdmi_num;
826 int ret, ssp_amp, ssp_codec;
827
828 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
829 if (!ctx)
830 return -ENOMEM;
831
832 if (pdev->id_entry && pdev->id_entry->driver_data)
833 sof_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data;
834
835 dmi_check_system(sof_rt5682_quirk_table);
836
837 mach = pdev->dev.platform_data;
838
839
840
841
842 if ((sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) && !mach->quirk_data)
843 sof_rt5682_quirk &= ~SOF_SPEAKER_AMP_PRESENT;
844
845
846 if (acpi_dev_present("RTL5682", NULL, -1))
847 sof_rt5682_quirk |= SOF_RT5682S_HEADPHONE_CODEC_PRESENT;
848
849
850 if (acpi_dev_present("RTL5682", NULL, -1))
851 sof_rt5682_quirk |= SOF_RT5682S_HEADPHONE_CODEC_PRESENT;
852
853 if (soc_intel_is_byt() || soc_intel_is_cht()) {
854 is_legacy_cpu = 1;
855 dmic_be_num = 0;
856 hdmi_num = 0;
857
858 sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
859 SOF_RT5682_MCLK_BYTCHT_EN |
860 SOF_RT5682_SSP_CODEC(2);
861 } else {
862 dmic_be_num = 2;
863 hdmi_num = (sof_rt5682_quirk & SOF_RT5682_NUM_HDMIDEV_MASK) >>
864 SOF_RT5682_NUM_HDMIDEV_SHIFT;
865
866 if (!hdmi_num)
867 hdmi_num = 3;
868
869 if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
870 ctx->idisp_codec = true;
871 }
872
873
874 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
875 ctx->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
876 if (IS_ERR(ctx->mclk)) {
877 ret = PTR_ERR(ctx->mclk);
878
879 dev_err(&pdev->dev,
880 "Failed to get MCLK from pmc_plt_clk_3: %d\n",
881 ret);
882 return ret;
883 }
884
885 ret = clk_prepare_enable(ctx->mclk);
886 if (ret < 0) {
887 dev_err(&pdev->dev,
888 "could not configure MCLK state");
889 return ret;
890 }
891 }
892
893 dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk);
894
895 ssp_amp = (sof_rt5682_quirk & SOF_RT5682_SSP_AMP_MASK) >>
896 SOF_RT5682_SSP_AMP_SHIFT;
897
898 ssp_codec = sof_rt5682_quirk & SOF_RT5682_SSP_CODEC_MASK;
899
900
901 sof_audio_card_rt5682.num_links = 1 + dmic_be_num + hdmi_num;
902
903 if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT)
904 sof_audio_card_rt5682.num_links++;
905
906 if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT)
907 max_98373_set_codec_conf(&sof_audio_card_rt5682);
908 else if (sof_rt5682_quirk & SOF_RT1011_SPEAKER_AMP_PRESENT)
909 sof_rt1011_codec_conf(&sof_audio_card_rt5682);
910 else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT)
911 sof_rt1015p_codec_conf(&sof_audio_card_rt5682);
912 else if (sof_rt5682_quirk & SOF_MAX98390_SPEAKER_AMP_PRESENT) {
913 if (sof_rt5682_quirk & SOF_MAX98390_TWEETER_SPEAKER_PRESENT)
914 max_98390_set_codec_conf(&sof_audio_card_rt5682,
915 ARRAY_SIZE(max_98390_4spk_components));
916 else
917 max_98390_set_codec_conf(&sof_audio_card_rt5682,
918 ARRAY_SIZE(max_98390_components));
919 }
920
921 if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
922 sof_audio_card_rt5682.num_links++;
923
924 dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,
925 dmic_be_num, hdmi_num, ctx->idisp_codec);
926 if (!dai_links)
927 return -ENOMEM;
928
929 sof_audio_card_rt5682.dai_link = dai_links;
930
931 if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT)
932 sof_rt1015_codec_conf(&sof_audio_card_rt5682);
933
934 INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
935
936 sof_audio_card_rt5682.dev = &pdev->dev;
937
938
939 ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_rt5682,
940 mach->mach_params.platform);
941 if (ret)
942 return ret;
943
944 ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
945
946 snd_soc_card_set_drvdata(&sof_audio_card_rt5682, ctx);
947
948 return devm_snd_soc_register_card(&pdev->dev,
949 &sof_audio_card_rt5682);
950}
951
952static const struct platform_device_id board_ids[] = {
953 {
954 .name = "sof_rt5682",
955 },
956 {
957 .name = "tgl_mx98357_rt5682",
958 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
959 SOF_RT5682_SSP_CODEC(0) |
960 SOF_SPEAKER_AMP_PRESENT |
961 SOF_RT5682_SSP_AMP(1) |
962 SOF_RT5682_NUM_HDMIDEV(4) |
963 SOF_BT_OFFLOAD_SSP(2) |
964 SOF_SSP_BT_OFFLOAD_PRESENT),
965 },
966 {
967 .name = "jsl_rt5682_rt1015",
968 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
969 SOF_RT5682_MCLK_24MHZ |
970 SOF_RT5682_SSP_CODEC(0) |
971 SOF_SPEAKER_AMP_PRESENT |
972 SOF_RT1015_SPEAKER_AMP_PRESENT |
973 SOF_RT5682_SSP_AMP(1)),
974 },
975 {
976 .name = "tgl_mx98373_rt5682",
977 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
978 SOF_RT5682_SSP_CODEC(0) |
979 SOF_SPEAKER_AMP_PRESENT |
980 SOF_MAX98373_SPEAKER_AMP_PRESENT |
981 SOF_RT5682_SSP_AMP(1) |
982 SOF_RT5682_NUM_HDMIDEV(4) |
983 SOF_BT_OFFLOAD_SSP(2) |
984 SOF_SSP_BT_OFFLOAD_PRESENT),
985 },
986 {
987 .name = "jsl_rt5682_mx98360",
988 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
989 SOF_RT5682_MCLK_24MHZ |
990 SOF_RT5682_SSP_CODEC(0) |
991 SOF_SPEAKER_AMP_PRESENT |
992 SOF_MAX98360A_SPEAKER_AMP_PRESENT |
993 SOF_RT5682_SSP_AMP(1)),
994 },
995 {
996 .name = "cml_rt1015_rt5682",
997 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
998 SOF_RT5682_MCLK_24MHZ |
999 SOF_RT5682_SSP_CODEC(0) |
1000 SOF_SPEAKER_AMP_PRESENT |
1001 SOF_RT1015_SPEAKER_AMP_PRESENT |
1002 SOF_RT1015_SPEAKER_AMP_100FS |
1003 SOF_RT5682_SSP_AMP(1)),
1004 },
1005 {
1006 .name = "tgl_rt1011_rt5682",
1007 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1008 SOF_RT5682_SSP_CODEC(0) |
1009 SOF_SPEAKER_AMP_PRESENT |
1010 SOF_RT1011_SPEAKER_AMP_PRESENT |
1011 SOF_RT5682_SSP_AMP(1) |
1012 SOF_RT5682_NUM_HDMIDEV(4) |
1013 SOF_BT_OFFLOAD_SSP(2) |
1014 SOF_SSP_BT_OFFLOAD_PRESENT),
1015 },
1016 {
1017 .name = "jsl_rt5682_rt1015p",
1018 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1019 SOF_RT5682_MCLK_24MHZ |
1020 SOF_RT5682_SSP_CODEC(0) |
1021 SOF_SPEAKER_AMP_PRESENT |
1022 SOF_RT1015P_SPEAKER_AMP_PRESENT |
1023 SOF_RT5682_SSP_AMP(1)),
1024 },
1025 {
1026 .name = "adl_mx98373_rt5682",
1027 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1028 SOF_RT5682_SSP_CODEC(0) |
1029 SOF_SPEAKER_AMP_PRESENT |
1030 SOF_MAX98373_SPEAKER_AMP_PRESENT |
1031 SOF_RT5682_SSP_AMP(1) |
1032 SOF_RT5682_NUM_HDMIDEV(4) |
1033 SOF_BT_OFFLOAD_SSP(2) |
1034 SOF_SSP_BT_OFFLOAD_PRESENT),
1035 },
1036 {
1037 .name = "adl_mx98357_rt5682",
1038 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1039 SOF_RT5682_SSP_CODEC(0) |
1040 SOF_SPEAKER_AMP_PRESENT |
1041 SOF_RT5682_SSP_AMP(2) |
1042 SOF_RT5682_NUM_HDMIDEV(4)),
1043 },
1044 {
1045 .name = "adl_max98390_rt5682",
1046 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1047 SOF_RT5682_SSP_CODEC(0) |
1048 SOF_SPEAKER_AMP_PRESENT |
1049 SOF_MAX98390_SPEAKER_AMP_PRESENT |
1050 SOF_RT5682_SSP_AMP(1) |
1051 SOF_RT5682_NUM_HDMIDEV(4) |
1052 SOF_BT_OFFLOAD_SSP(2) |
1053 SOF_SSP_BT_OFFLOAD_PRESENT),
1054 },
1055 {
1056 .name = "adl_mx98360_rt5682",
1057 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1058 SOF_RT5682_SSP_CODEC(0) |
1059 SOF_SPEAKER_AMP_PRESENT |
1060 SOF_MAX98360A_SPEAKER_AMP_PRESENT |
1061 SOF_RT5682_SSP_AMP(1) |
1062 SOF_RT5682_NUM_HDMIDEV(4) |
1063 SOF_BT_OFFLOAD_SSP(2) |
1064 SOF_SSP_BT_OFFLOAD_PRESENT),
1065 },
1066 {
1067 .name = "adl_rt5682",
1068 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1069 SOF_RT5682_SSP_CODEC(0) |
1070 SOF_RT5682_NUM_HDMIDEV(4) |
1071 SOF_BT_OFFLOAD_SSP(2) |
1072 SOF_SSP_BT_OFFLOAD_PRESENT),
1073 },
1074 { }
1075};
1076MODULE_DEVICE_TABLE(platform, board_ids);
1077
1078static struct platform_driver sof_audio = {
1079 .probe = sof_audio_probe,
1080 .driver = {
1081 .name = "sof_rt5682",
1082 .pm = &snd_soc_pm_ops,
1083 },
1084 .id_table = board_ids,
1085};
1086module_platform_driver(sof_audio)
1087
1088
1089MODULE_DESCRIPTION("SOF Audio Machine driver");
1090MODULE_AUTHOR("Bard Liao <bard.liao@intel.com>");
1091MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
1092MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
1093MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
1094MODULE_LICENSE("GPL v2");
1095MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
1096MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
1097MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
1098