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/soc-acpi.h>
22#include "../../codecs/rt1015.h"
23#include "../../codecs/rt5682.h"
24#include "../../codecs/hdac_hdmi.h"
25#include "../common/soc-intel-quirks.h"
26#include "hda_dsp_common.h"
27#include "sof_maxim_common.h"
28#include "sof_realtek_common.h"
29
30#define NAME_SIZE 32
31
32#define SOF_RT5682_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0))
33#define SOF_RT5682_SSP_CODEC_MASK (GENMASK(2, 0))
34#define SOF_RT5682_MCLK_EN BIT(3)
35#define SOF_RT5682_MCLK_24MHZ BIT(4)
36#define SOF_SPEAKER_AMP_PRESENT BIT(5)
37#define SOF_RT5682_SSP_AMP_SHIFT 6
38#define SOF_RT5682_SSP_AMP_MASK (GENMASK(8, 6))
39#define SOF_RT5682_SSP_AMP(quirk) \
40 (((quirk) << SOF_RT5682_SSP_AMP_SHIFT) & SOF_RT5682_SSP_AMP_MASK)
41#define SOF_RT5682_MCLK_BYTCHT_EN BIT(9)
42#define SOF_RT5682_NUM_HDMIDEV_SHIFT 10
43#define SOF_RT5682_NUM_HDMIDEV_MASK (GENMASK(12, 10))
44#define SOF_RT5682_NUM_HDMIDEV(quirk) \
45 ((quirk << SOF_RT5682_NUM_HDMIDEV_SHIFT) & SOF_RT5682_NUM_HDMIDEV_MASK)
46#define SOF_RT1011_SPEAKER_AMP_PRESENT BIT(13)
47#define SOF_RT1015_SPEAKER_AMP_PRESENT BIT(14)
48#define SOF_RT1015_SPEAKER_AMP_100FS BIT(15)
49#define SOF_RT1015P_SPEAKER_AMP_PRESENT BIT(16)
50#define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(17)
51#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(18)
52
53
54#define SOF_BT_OFFLOAD_SSP_SHIFT 19
55#define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(21, 19))
56#define SOF_BT_OFFLOAD_SSP(quirk) \
57 (((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
58#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(22)
59
60
61static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
62 SOF_RT5682_SSP_CODEC(0);
63
64static int is_legacy_cpu;
65
66static struct snd_soc_jack sof_hdmi[3];
67
68struct sof_hdmi_pcm {
69 struct list_head head;
70 struct snd_soc_dai *codec_dai;
71 int device;
72};
73
74struct sof_card_private {
75 struct clk *mclk;
76 struct snd_soc_jack sof_headset;
77 struct list_head hdmi_pcm_list;
78 bool common_hdmi_codec_drv;
79};
80
81static int sof_rt5682_quirk_cb(const struct dmi_system_id *id)
82{
83 sof_rt5682_quirk = (unsigned long)id->driver_data;
84 return 1;
85}
86
87static const struct dmi_system_id sof_rt5682_quirk_table[] = {
88 {
89 .callback = sof_rt5682_quirk_cb,
90 .matches = {
91 DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
92 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max"),
93 },
94 .driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)),
95 },
96 {
97 .callback = sof_rt5682_quirk_cb,
98 .matches = {
99 DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
100 DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"),
101 },
102 .driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)),
103 },
104 {
105 .callback = sof_rt5682_quirk_cb,
106 .matches = {
107 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
108 DMI_MATCH(DMI_PRODUCT_NAME, "WhiskeyLake Client"),
109 },
110 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
111 SOF_RT5682_MCLK_24MHZ |
112 SOF_RT5682_SSP_CODEC(1)),
113 },
114 {
115
116
117
118
119 .callback = sof_rt5682_quirk_cb,
120 .matches = {
121 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
122 DMI_MATCH(DMI_PRODUCT_NAME, "Dooly"),
123 },
124 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
125 SOF_RT5682_MCLK_24MHZ |
126 SOF_RT5682_SSP_CODEC(0) |
127 SOF_SPEAKER_AMP_PRESENT |
128 SOF_RT1015_SPEAKER_AMP_PRESENT |
129 SOF_RT1015_SPEAKER_AMP_100FS |
130 SOF_RT5682_SSP_AMP(1)),
131 },
132 {
133 .callback = sof_rt5682_quirk_cb,
134 .matches = {
135 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"),
136 },
137 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
138 SOF_RT5682_MCLK_24MHZ |
139 SOF_RT5682_SSP_CODEC(0) |
140 SOF_SPEAKER_AMP_PRESENT |
141 SOF_RT5682_SSP_AMP(1)),
142 },
143 {
144 .callback = sof_rt5682_quirk_cb,
145 .matches = {
146 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
147 DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
148 },
149 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
150 SOF_RT5682_SSP_CODEC(0)),
151 },
152 {
153 .callback = sof_rt5682_quirk_cb,
154 .matches = {
155 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Volteer"),
156 DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98373_ALC5682I_I2S_UP4"),
157 },
158 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
159 SOF_RT5682_SSP_CODEC(0) |
160 SOF_SPEAKER_AMP_PRESENT |
161 SOF_MAX98373_SPEAKER_AMP_PRESENT |
162 SOF_RT5682_SSP_AMP(2) |
163 SOF_RT5682_NUM_HDMIDEV(4)),
164 },
165 {
166 .callback = sof_rt5682_quirk_cb,
167 .matches = {
168 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
169 DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
170 DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"),
171 },
172 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
173 SOF_RT5682_SSP_CODEC(0) |
174 SOF_SPEAKER_AMP_PRESENT |
175 SOF_MAX98373_SPEAKER_AMP_PRESENT |
176 SOF_RT5682_SSP_AMP(2) |
177 SOF_RT5682_NUM_HDMIDEV(4)),
178 },
179 {}
180};
181
182static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
183{
184 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
185 struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
186 struct sof_hdmi_pcm *pcm;
187
188 pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
189 if (!pcm)
190 return -ENOMEM;
191
192
193 pcm->device = rtd->dai_link->id;
194 pcm->codec_dai = dai;
195
196 list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
197
198 return 0;
199}
200
201static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
202{
203 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
204 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
205 struct snd_soc_jack *jack;
206 int ret;
207
208
209 if ((sof_rt5682_quirk & SOF_RT5682_MCLK_EN) &&
210 (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ)) {
211 rt5682_sel_asrc_clk_src(component, RT5682_DA_STEREO1_FILTER |
212 RT5682_AD_STEREO1_FILTER,
213 RT5682_CLK_SEL_I2S1_ASRC);
214 }
215
216 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
217
218
219
220
221
222
223
224
225
226
227 ret = clk_prepare_enable(ctx->mclk);
228 if (!ret)
229 clk_disable_unprepare(ctx->mclk);
230
231 ret = clk_set_rate(ctx->mclk, 19200000);
232
233 if (ret)
234 dev_err(rtd->dev, "unable to set MCLK rate\n");
235 }
236
237
238
239
240
241 ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
242 SND_JACK_HEADSET | SND_JACK_BTN_0 |
243 SND_JACK_BTN_1 | SND_JACK_BTN_2 |
244 SND_JACK_BTN_3,
245 &ctx->sof_headset, NULL, 0);
246 if (ret) {
247 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
248 return ret;
249 }
250
251 jack = &ctx->sof_headset;
252
253 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
254 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
255 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
256 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
257 ret = snd_soc_component_set_jack(component, jack, NULL);
258
259 if (ret) {
260 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
261 return ret;
262 }
263
264 return ret;
265};
266
267static void sof_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd)
268{
269 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
270
271 snd_soc_component_set_jack(component, NULL, NULL);
272}
273
274static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,
275 struct snd_pcm_hw_params *params)
276{
277 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
278 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
279 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
280 int clk_id, clk_freq, pll_out, ret;
281
282 if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
283 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
284 ret = clk_prepare_enable(ctx->mclk);
285 if (ret < 0) {
286 dev_err(rtd->dev,
287 "could not configure MCLK state");
288 return ret;
289 }
290 }
291
292 clk_id = RT5682_PLL1_S_MCLK;
293
294
295 clk_freq = sof_dai_get_mclk(rtd);
296
297
298 if (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ) {
299 if (clk_freq != 24000000)
300 dev_warn(rtd->dev, "configure wrong mclk in tplg, please use 24MHz.\n");
301 clk_freq = 24000000;
302 } else if (clk_freq == 0) {
303
304 clk_freq = 19200000;
305 } else if (clk_freq < 0) {
306 return clk_freq;
307 }
308 } else {
309 clk_id = RT5682_PLL1_S_BCLK1;
310 clk_freq = params_rate(params) * 50;
311 }
312
313 pll_out = params_rate(params) * 512;
314
315 ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out);
316 if (ret < 0)
317 dev_err(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret);
318
319
320 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
321 pll_out, SND_SOC_CLOCK_IN);
322 if (ret < 0)
323 dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
324
325
326
327
328
329 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2,
330 params_width(params));
331 if (ret < 0) {
332 dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
333 return ret;
334 }
335
336 return ret;
337}
338
339static struct snd_soc_ops sof_rt5682_ops = {
340 .hw_params = sof_rt5682_hw_params,
341};
342
343static int sof_rt1015_hw_params(struct snd_pcm_substream *substream,
344 struct snd_pcm_hw_params *params)
345{
346 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
347 struct snd_soc_card *card = rtd->card;
348 struct snd_soc_dai *codec_dai;
349 int i, fs, ret;
350
351 if (!snd_soc_card_get_codec_dai(card, "rt1015-aif"))
352 return 0;
353
354 if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_100FS)
355 fs = 100;
356 else
357 fs = 64;
358
359 for_each_rtd_codec_dais(rtd, i, codec_dai) {
360 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
361 params_rate(params) * fs,
362 params_rate(params) * 256);
363 if (ret < 0) {
364 dev_err(card->dev, "failed to set pll\n");
365 return ret;
366 }
367
368 ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL,
369 params_rate(params) * 256,
370 SND_SOC_CLOCK_IN);
371 if (ret < 0) {
372 dev_err(card->dev, "failed to set sysclk\n");
373 return ret;
374 }
375
376 if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_100FS) {
377 if (!strcmp(codec_dai->component->name, "i2c-10EC1015:00")) {
378 ret = snd_soc_dai_set_tdm_slot(codec_dai,
379 0x0, 0x1, 4, 24);
380 if (ret < 0) {
381 dev_err(card->dev, "failed to set tdm slot\n");
382 return ret;
383 }
384 }
385
386 if (!strcmp(codec_dai->component->name, "i2c-10EC1015:01")) {
387 ret = snd_soc_dai_set_tdm_slot(codec_dai,
388 0x0, 0x2, 4, 24);
389 if (ret < 0) {
390 dev_err(card->dev, "failed to set tdm slot\n");
391 return ret;
392 }
393 }
394 }
395 }
396
397 return 0;
398}
399
400static struct snd_soc_ops sof_rt1015_ops = {
401 .hw_params = sof_rt1015_hw_params,
402};
403
404static struct snd_soc_dai_link_component platform_component[] = {
405 {
406
407 .name = "0000:00:1f.3"
408 }
409};
410
411static int sof_card_late_probe(struct snd_soc_card *card)
412{
413 struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
414 struct snd_soc_component *component = NULL;
415 struct snd_soc_dapm_context *dapm = &card->dapm;
416 char jack_name[NAME_SIZE];
417 struct sof_hdmi_pcm *pcm;
418 int err;
419 int i = 0;
420
421
422 if (is_legacy_cpu)
423 return 0;
424
425 if (list_empty(&ctx->hdmi_pcm_list))
426 return -EINVAL;
427
428 if (ctx->common_hdmi_codec_drv) {
429 pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm,
430 head);
431 component = pcm->codec_dai->component;
432 return hda_dsp_hdmi_build_controls(card, component);
433 }
434
435 list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
436 component = pcm->codec_dai->component;
437 snprintf(jack_name, sizeof(jack_name),
438 "HDMI/DP, pcm=%d Jack", pcm->device);
439 err = snd_soc_card_jack_new(card, jack_name,
440 SND_JACK_AVOUT, &sof_hdmi[i],
441 NULL, 0);
442
443 if (err)
444 return err;
445
446 err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
447 &sof_hdmi[i]);
448 if (err < 0)
449 return err;
450
451 i++;
452 }
453
454 if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
455
456 snd_soc_dapm_disable_pin(dapm, "Left Spk");
457 snd_soc_dapm_disable_pin(dapm, "Right Spk");
458 err = snd_soc_dapm_sync(dapm);
459 if (err < 0)
460 return err;
461 }
462 return hdac_hdmi_jack_port_init(component, &card->dapm);
463}
464
465static const struct snd_kcontrol_new sof_controls[] = {
466 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
467 SOC_DAPM_PIN_SWITCH("Headset Mic"),
468 SOC_DAPM_PIN_SWITCH("Left Spk"),
469 SOC_DAPM_PIN_SWITCH("Right Spk"),
470
471};
472
473static const struct snd_soc_dapm_widget sof_widgets[] = {
474 SND_SOC_DAPM_HP("Headphone Jack", NULL),
475 SND_SOC_DAPM_MIC("Headset Mic", NULL),
476 SND_SOC_DAPM_SPK("Left Spk", NULL),
477 SND_SOC_DAPM_SPK("Right Spk", NULL),
478};
479
480static const struct snd_soc_dapm_widget dmic_widgets[] = {
481 SND_SOC_DAPM_MIC("SoC DMIC", NULL),
482};
483
484static const struct snd_soc_dapm_route sof_map[] = {
485
486 { "Headphone Jack", NULL, "HPOL" },
487 { "Headphone Jack", NULL, "HPOR" },
488
489
490 { "IN1P", NULL, "Headset Mic" },
491};
492
493static const struct snd_soc_dapm_route speaker_map_lr[] = {
494 { "Left Spk", NULL, "Left SPO" },
495 { "Right Spk", NULL, "Right SPO" },
496};
497
498static const struct snd_soc_dapm_route dmic_map[] = {
499
500 {"DMic", NULL, "SoC DMIC"},
501};
502
503static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd)
504{
505 return snd_soc_dapm_add_routes(&rtd->card->dapm, speaker_map_lr,
506 ARRAY_SIZE(speaker_map_lr));
507}
508
509static int dmic_init(struct snd_soc_pcm_runtime *rtd)
510{
511 struct snd_soc_card *card = rtd->card;
512 int ret;
513
514 ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
515 ARRAY_SIZE(dmic_widgets));
516 if (ret) {
517 dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
518
519 return ret;
520 }
521
522 ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
523 ARRAY_SIZE(dmic_map));
524
525 if (ret)
526 dev_err(card->dev, "DMic map addition failed: %d\n", ret);
527
528 return ret;
529}
530
531static struct snd_soc_codec_conf rt1015_amp_conf[] = {
532 {
533 .dlc = COMP_CODEC_CONF("i2c-10EC1015:00"),
534 .name_prefix = "Left",
535 },
536 {
537 .dlc = COMP_CODEC_CONF("i2c-10EC1015:01"),
538 .name_prefix = "Right",
539 },
540};
541
542
543static struct snd_soc_card sof_audio_card_rt5682 = {
544 .name = "rt5682",
545 .owner = THIS_MODULE,
546 .controls = sof_controls,
547 .num_controls = ARRAY_SIZE(sof_controls),
548 .dapm_widgets = sof_widgets,
549 .num_dapm_widgets = ARRAY_SIZE(sof_widgets),
550 .dapm_routes = sof_map,
551 .num_dapm_routes = ARRAY_SIZE(sof_map),
552 .fully_routed = true,
553 .late_probe = sof_card_late_probe,
554};
555
556static struct snd_soc_dai_link_component rt5682_component[] = {
557 {
558 .name = "i2c-10EC5682:00",
559 .dai_name = "rt5682-aif1",
560 }
561};
562
563static struct snd_soc_dai_link_component dmic_component[] = {
564 {
565 .name = "dmic-codec",
566 .dai_name = "dmic-hifi",
567 }
568};
569
570static struct snd_soc_dai_link_component rt1015_components[] = {
571 {
572 .name = "i2c-10EC1015:00",
573 .dai_name = "rt1015-aif",
574 },
575 {
576 .name = "i2c-10EC1015:01",
577 .dai_name = "rt1015-aif",
578 },
579};
580
581static struct snd_soc_dai_link_component dummy_component[] = {
582 {
583 .name = "snd-soc-dummy",
584 .dai_name = "snd-soc-dummy-dai",
585 }
586};
587
588static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
589 int ssp_codec,
590 int ssp_amp,
591 int dmic_be_num,
592 int hdmi_num)
593{
594 struct snd_soc_dai_link_component *idisp_components;
595 struct snd_soc_dai_link_component *cpus;
596 struct snd_soc_dai_link *links;
597 int i, id = 0;
598
599 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
600 sof_audio_card_rt5682.num_links, GFP_KERNEL);
601 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
602 sof_audio_card_rt5682.num_links, GFP_KERNEL);
603 if (!links || !cpus)
604 goto devm_err;
605
606
607 links[id].name = devm_kasprintf(dev, GFP_KERNEL,
608 "SSP%d-Codec", ssp_codec);
609 if (!links[id].name)
610 goto devm_err;
611
612 links[id].id = id;
613 links[id].codecs = rt5682_component;
614 links[id].num_codecs = ARRAY_SIZE(rt5682_component);
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 idisp_components[i - 1].name = "ehdaudio0D2";
702 idisp_components[i - 1].dai_name = devm_kasprintf(dev,
703 GFP_KERNEL,
704 "intel-hdmi-hifi%d",
705 i);
706 if (!idisp_components[i - 1].dai_name)
707 goto devm_err;
708
709 links[id].codecs = &idisp_components[i - 1];
710 links[id].num_codecs = 1;
711 links[id].platforms = platform_component;
712 links[id].num_platforms = ARRAY_SIZE(platform_component);
713 links[id].init = sof_hdmi_init;
714 links[id].dpcm_playback = 1;
715 links[id].no_pcm = 1;
716 id++;
717 }
718
719
720 if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) {
721 links[id].name = devm_kasprintf(dev, GFP_KERNEL,
722 "SSP%d-Codec", ssp_amp);
723 if (!links[id].name)
724 goto devm_err;
725
726 links[id].id = id;
727 if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT) {
728 links[id].codecs = rt1015_components;
729 links[id].num_codecs = ARRAY_SIZE(rt1015_components);
730 links[id].init = speaker_codec_init_lr;
731 links[id].ops = &sof_rt1015_ops;
732 } else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) {
733 sof_rt1015p_dai_link(&links[id]);
734 } else if (sof_rt5682_quirk &
735 SOF_MAX98373_SPEAKER_AMP_PRESENT) {
736 links[id].codecs = max_98373_components;
737 links[id].num_codecs = ARRAY_SIZE(max_98373_components);
738 links[id].init = max_98373_spk_codec_init;
739 links[id].ops = &max_98373_ops;
740
741 links[id].dpcm_capture = 1;
742 } else if (sof_rt5682_quirk &
743 SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
744 max_98360a_dai_link(&links[id]);
745 } else if (sof_rt5682_quirk &
746 SOF_RT1011_SPEAKER_AMP_PRESENT) {
747 sof_rt1011_dai_link(&links[id]);
748 } else {
749 max_98357a_dai_link(&links[id]);
750 }
751 links[id].platforms = platform_component;
752 links[id].num_platforms = ARRAY_SIZE(platform_component);
753 links[id].dpcm_playback = 1;
754 links[id].no_pcm = 1;
755 links[id].cpus = &cpus[id];
756 links[id].num_cpus = 1;
757 if (is_legacy_cpu) {
758 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
759 "ssp%d-port",
760 ssp_amp);
761 if (!links[id].cpus->dai_name)
762 goto devm_err;
763
764 } else {
765 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
766 "SSP%d Pin",
767 ssp_amp);
768 if (!links[id].cpus->dai_name)
769 goto devm_err;
770 }
771 id++;
772 }
773
774
775 if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
776 int port = (sof_rt5682_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
777 SOF_BT_OFFLOAD_SSP_SHIFT;
778
779 links[id].id = id;
780 links[id].cpus = &cpus[id];
781 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
782 "SSP%d Pin", port);
783 if (!links[id].cpus->dai_name)
784 goto devm_err;
785 links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
786 if (!links[id].name)
787 goto devm_err;
788 links[id].codecs = dummy_component;
789 links[id].num_codecs = ARRAY_SIZE(dummy_component);
790 links[id].platforms = platform_component;
791 links[id].num_platforms = ARRAY_SIZE(platform_component);
792 links[id].dpcm_playback = 1;
793 links[id].dpcm_capture = 1;
794 links[id].no_pcm = 1;
795 links[id].num_cpus = 1;
796 }
797
798 return links;
799devm_err:
800 return NULL;
801}
802
803static int sof_audio_probe(struct platform_device *pdev)
804{
805 struct snd_soc_dai_link *dai_links;
806 struct snd_soc_acpi_mach *mach;
807 struct sof_card_private *ctx;
808 int dmic_be_num, hdmi_num;
809 int ret, ssp_amp, ssp_codec;
810
811 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
812 if (!ctx)
813 return -ENOMEM;
814
815 if (pdev->id_entry && pdev->id_entry->driver_data)
816 sof_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data;
817
818 dmi_check_system(sof_rt5682_quirk_table);
819
820 mach = pdev->dev.platform_data;
821
822
823
824
825 if ((sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) && !mach->quirk_data)
826 sof_rt5682_quirk &= ~SOF_SPEAKER_AMP_PRESENT;
827
828 if (soc_intel_is_byt() || soc_intel_is_cht()) {
829 is_legacy_cpu = 1;
830 dmic_be_num = 0;
831 hdmi_num = 0;
832
833 sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
834 SOF_RT5682_MCLK_BYTCHT_EN |
835 SOF_RT5682_SSP_CODEC(2);
836 } else {
837 dmic_be_num = 2;
838 hdmi_num = (sof_rt5682_quirk & SOF_RT5682_NUM_HDMIDEV_MASK) >>
839 SOF_RT5682_NUM_HDMIDEV_SHIFT;
840
841 if (!hdmi_num)
842 hdmi_num = 3;
843 }
844
845
846 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
847 ctx->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
848 if (IS_ERR(ctx->mclk)) {
849 ret = PTR_ERR(ctx->mclk);
850
851 dev_err(&pdev->dev,
852 "Failed to get MCLK from pmc_plt_clk_3: %d\n",
853 ret);
854 return ret;
855 }
856
857 ret = clk_prepare_enable(ctx->mclk);
858 if (ret < 0) {
859 dev_err(&pdev->dev,
860 "could not configure MCLK state");
861 return ret;
862 }
863 }
864
865 dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk);
866
867 ssp_amp = (sof_rt5682_quirk & SOF_RT5682_SSP_AMP_MASK) >>
868 SOF_RT5682_SSP_AMP_SHIFT;
869
870 ssp_codec = sof_rt5682_quirk & SOF_RT5682_SSP_CODEC_MASK;
871
872
873 sof_audio_card_rt5682.num_links = 1 + dmic_be_num + hdmi_num;
874
875 if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT)
876 sof_audio_card_rt5682.num_links++;
877
878 if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT)
879 max_98373_set_codec_conf(&sof_audio_card_rt5682);
880 else if (sof_rt5682_quirk & SOF_RT1011_SPEAKER_AMP_PRESENT)
881 sof_rt1011_codec_conf(&sof_audio_card_rt5682);
882 else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT)
883 sof_rt1015p_codec_conf(&sof_audio_card_rt5682);
884
885 if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
886 sof_audio_card_rt5682.num_links++;
887
888 dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,
889 dmic_be_num, hdmi_num);
890 if (!dai_links)
891 return -ENOMEM;
892
893 sof_audio_card_rt5682.dai_link = dai_links;
894
895 if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT) {
896 sof_audio_card_rt5682.codec_conf = rt1015_amp_conf;
897 sof_audio_card_rt5682.num_configs = ARRAY_SIZE(rt1015_amp_conf);
898 }
899
900 INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
901
902 sof_audio_card_rt5682.dev = &pdev->dev;
903
904
905 ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_rt5682,
906 mach->mach_params.platform);
907 if (ret)
908 return ret;
909
910 ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
911
912 snd_soc_card_set_drvdata(&sof_audio_card_rt5682, ctx);
913
914 return devm_snd_soc_register_card(&pdev->dev,
915 &sof_audio_card_rt5682);
916}
917
918static const struct platform_device_id board_ids[] = {
919 {
920 .name = "sof_rt5682",
921 },
922 {
923 .name = "tgl_mx98357a_rt5682",
924 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
925 SOF_RT5682_SSP_CODEC(0) |
926 SOF_SPEAKER_AMP_PRESENT |
927 SOF_RT5682_SSP_AMP(1) |
928 SOF_RT5682_NUM_HDMIDEV(4) |
929 SOF_BT_OFFLOAD_SSP(2) |
930 SOF_SSP_BT_OFFLOAD_PRESENT),
931 },
932 {
933 .name = "jsl_rt5682_rt1015",
934 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
935 SOF_RT5682_MCLK_24MHZ |
936 SOF_RT5682_SSP_CODEC(0) |
937 SOF_SPEAKER_AMP_PRESENT |
938 SOF_RT1015_SPEAKER_AMP_PRESENT |
939 SOF_RT5682_SSP_AMP(1)),
940 },
941 {
942 .name = "tgl_mx98373_rt5682",
943 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
944 SOF_RT5682_SSP_CODEC(0) |
945 SOF_SPEAKER_AMP_PRESENT |
946 SOF_MAX98373_SPEAKER_AMP_PRESENT |
947 SOF_RT5682_SSP_AMP(1) |
948 SOF_RT5682_NUM_HDMIDEV(4) |
949 SOF_BT_OFFLOAD_SSP(2) |
950 SOF_SSP_BT_OFFLOAD_PRESENT),
951 },
952 {
953 .name = "jsl_rt5682_mx98360a",
954 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
955 SOF_RT5682_MCLK_24MHZ |
956 SOF_RT5682_SSP_CODEC(0) |
957 SOF_SPEAKER_AMP_PRESENT |
958 SOF_MAX98360A_SPEAKER_AMP_PRESENT |
959 SOF_RT5682_SSP_AMP(1)),
960 },
961 {
962 .name = "cml_rt1015_rt5682",
963 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
964 SOF_RT5682_MCLK_24MHZ |
965 SOF_RT5682_SSP_CODEC(0) |
966 SOF_SPEAKER_AMP_PRESENT |
967 SOF_RT1015_SPEAKER_AMP_PRESENT |
968 SOF_RT1015_SPEAKER_AMP_100FS |
969 SOF_RT5682_SSP_AMP(1)),
970 },
971 {
972 .name = "tgl_rt1011_rt5682",
973 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
974 SOF_RT5682_SSP_CODEC(0) |
975 SOF_SPEAKER_AMP_PRESENT |
976 SOF_RT1011_SPEAKER_AMP_PRESENT |
977 SOF_RT5682_SSP_AMP(1) |
978 SOF_RT5682_NUM_HDMIDEV(4) |
979 SOF_BT_OFFLOAD_SSP(2) |
980 SOF_SSP_BT_OFFLOAD_PRESENT),
981 },
982 {
983 .name = "jsl_rt5682_rt1015p",
984 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
985 SOF_RT5682_MCLK_24MHZ |
986 SOF_RT5682_SSP_CODEC(0) |
987 SOF_SPEAKER_AMP_PRESENT |
988 SOF_RT1015P_SPEAKER_AMP_PRESENT |
989 SOF_RT5682_SSP_AMP(1)),
990 },
991 {
992 .name = "adl_mx98373_rt5682",
993 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
994 SOF_RT5682_SSP_CODEC(0) |
995 SOF_SPEAKER_AMP_PRESENT |
996 SOF_MAX98373_SPEAKER_AMP_PRESENT |
997 SOF_RT5682_SSP_AMP(1) |
998 SOF_RT5682_NUM_HDMIDEV(4) |
999 SOF_BT_OFFLOAD_SSP(2) |
1000 SOF_SSP_BT_OFFLOAD_PRESENT),
1001 },
1002 {
1003 .name = "adl_mx98357a_rt5682",
1004 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1005 SOF_RT5682_SSP_CODEC(0) |
1006 SOF_SPEAKER_AMP_PRESENT |
1007 SOF_RT5682_SSP_AMP(2) |
1008 SOF_RT5682_NUM_HDMIDEV(4)),
1009 },
1010 { }
1011};
1012MODULE_DEVICE_TABLE(platform, board_ids);
1013
1014static struct platform_driver sof_audio = {
1015 .probe = sof_audio_probe,
1016 .driver = {
1017 .name = "sof_rt5682",
1018 .pm = &snd_soc_pm_ops,
1019 },
1020 .id_table = board_ids,
1021};
1022module_platform_driver(sof_audio)
1023
1024
1025MODULE_DESCRIPTION("SOF Audio Machine driver");
1026MODULE_AUTHOR("Bard Liao <bard.liao@intel.com>");
1027MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
1028MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
1029MODULE_LICENSE("GPL v2");
1030MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
1031MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
1032