]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - sound/soc/intel/boards/sof_rt5682.c
Merge tag 'asoc-v5.7' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[mirror_ubuntu-hirsute-kernel.git] / sound / soc / intel / boards / sof_rt5682.c
CommitLineData
f70abd75 1// SPDX-License-Identifier: GPL-2.0
a79ae0f6 2// Copyright(c) 2019-2020 Intel Corporation.
f70abd75
B
3
4/*
5 * Intel SOF Machine Driver with Realtek rt5682 Codec
a79ae0f6 6 * and speaker codec MAX98357A or RT1015.
f70abd75
B
7 */
8#include <linux/i2c.h>
9#include <linux/input.h>
10#include <linux/module.h>
11#include <linux/platform_device.h>
1eed6bc0 12#include <linux/clk.h>
f70abd75 13#include <linux/dmi.h>
f70abd75
B
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/rt5682.h>
20#include <sound/soc-acpi.h>
a79ae0f6 21#include "../../codecs/rt1015.h"
f70abd75
B
22#include "../../codecs/rt5682.h"
23#include "../../codecs/hdac_hdmi.h"
536cfd2f 24#include "../common/soc-intel-quirks.h"
59bbd703 25#include "hda_dsp_common.h"
e2e404a6 26#include "sof_maxim_common.h"
f70abd75
B
27
28#define NAME_SIZE 32
29
30#define SOF_RT5682_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0))
31#define SOF_RT5682_SSP_CODEC_MASK (GENMASK(2, 0))
32#define SOF_RT5682_MCLK_EN BIT(3)
33#define SOF_RT5682_MCLK_24MHZ BIT(4)
34#define SOF_SPEAKER_AMP_PRESENT BIT(5)
f70abd75 35#define SOF_RT5682_SSP_AMP_SHIFT 6
df936613
SP
36#define SOF_RT5682_SSP_AMP_MASK (GENMASK(8, 6))
37#define SOF_RT5682_SSP_AMP(quirk) \
38 (((quirk) << SOF_RT5682_SSP_AMP_SHIFT) & SOF_RT5682_SSP_AMP_MASK)
1eed6bc0 39#define SOF_RT5682_MCLK_BYTCHT_EN BIT(9)
c68e0797
SN
40#define SOF_RT5682_NUM_HDMIDEV_SHIFT 10
41#define SOF_RT5682_NUM_HDMIDEV_MASK (GENMASK(12, 10))
42#define SOF_RT5682_NUM_HDMIDEV(quirk) \
43 ((quirk << SOF_RT5682_NUM_HDMIDEV_SHIFT) & SOF_RT5682_NUM_HDMIDEV_MASK)
a79ae0f6 44#define SOF_RT1015_SPEAKER_AMP_PRESENT BIT(13)
e2e404a6 45#define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(14)
f70abd75
B
46
47/* Default: MCLK on, MCLK 19.2M, SSP0 */
48static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
49 SOF_RT5682_SSP_CODEC(0);
50
51static int is_legacy_cpu;
52
53static struct snd_soc_jack sof_hdmi[3];
54
55struct sof_hdmi_pcm {
56 struct list_head head;
57 struct snd_soc_dai *codec_dai;
58 int device;
59};
60
61struct sof_card_private {
1eed6bc0 62 struct clk *mclk;
f70abd75
B
63 struct snd_soc_jack sof_headset;
64 struct list_head hdmi_pcm_list;
59bbd703 65 bool common_hdmi_codec_drv;
f70abd75
B
66};
67
68static int sof_rt5682_quirk_cb(const struct dmi_system_id *id)
69{
70 sof_rt5682_quirk = (unsigned long)id->driver_data;
71 return 1;
72}
73
74static const struct dmi_system_id sof_rt5682_quirk_table[] = {
1eed6bc0
XZ
75 {
76 .callback = sof_rt5682_quirk_cb,
77 .matches = {
78 DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
79 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max"),
80 },
81 .driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)),
82 },
83 {
84 .callback = sof_rt5682_quirk_cb,
85 .matches = {
86 DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
87 DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"),
88 },
89 .driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)),
90 },
f70abd75
B
91 {
92 .callback = sof_rt5682_quirk_cb,
93 .matches = {
94 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
95 DMI_MATCH(DMI_PRODUCT_NAME, "WhiskeyLake Client"),
96 },
97 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
98 SOF_RT5682_MCLK_24MHZ |
99 SOF_RT5682_SSP_CODEC(1)),
100 },
101 {
102 .callback = sof_rt5682_quirk_cb,
103 .matches = {
1a3fb5d3 104 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"),
f70abd75
B
105 },
106 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
107 SOF_RT5682_MCLK_24MHZ |
108 SOF_RT5682_SSP_CODEC(0) |
109 SOF_SPEAKER_AMP_PRESENT |
110 SOF_RT5682_SSP_AMP(1)),
111 },
112 {
113 .callback = sof_rt5682_quirk_cb,
114 .matches = {
115 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
116 DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
117 },
118 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
119 SOF_RT5682_SSP_CODEC(0)),
120 },
121 {}
122};
123
124static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
125{
126 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
0d1571c1 127 struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
f70abd75
B
128 struct sof_hdmi_pcm *pcm;
129
130 pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
131 if (!pcm)
132 return -ENOMEM;
133
134 /* dai_link id is 1:1 mapped to the PCM device */
135 pcm->device = rtd->dai_link->id;
136 pcm->codec_dai = dai;
137
138 list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
139
140 return 0;
141}
142
143static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
144{
145 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
0d1571c1 146 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
f70abd75
B
147 struct snd_soc_jack *jack;
148 int ret;
149
150 /* need to enable ASRC function for 24MHz mclk rate */
151 if ((sof_rt5682_quirk & SOF_RT5682_MCLK_EN) &&
152 (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ)) {
153 rt5682_sel_asrc_clk_src(component, RT5682_DA_STEREO1_FILTER |
154 RT5682_AD_STEREO1_FILTER,
155 RT5682_CLK_SEL_I2S1_ASRC);
156 }
157
1eed6bc0
XZ
158 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
159 /*
160 * The firmware might enable the clock at
161 * boot (this information may or may not
162 * be reflected in the enable clock register).
163 * To change the rate we must disable the clock
164 * first to cover these cases. Due to common
165 * clock framework restrictions that do not allow
166 * to disable a clock that has not been enabled,
167 * we need to enable the clock first.
168 */
169 ret = clk_prepare_enable(ctx->mclk);
170 if (!ret)
171 clk_disable_unprepare(ctx->mclk);
172
173 ret = clk_set_rate(ctx->mclk, 19200000);
174
175 if (ret)
176 dev_err(rtd->dev, "unable to set MCLK rate\n");
177 }
178
f70abd75
B
179 /*
180 * Headset buttons map to the google Reference headset.
181 * These can be configured by userspace.
182 */
183 ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
184 SND_JACK_HEADSET | SND_JACK_BTN_0 |
185 SND_JACK_BTN_1 | SND_JACK_BTN_2 |
186 SND_JACK_BTN_3,
187 &ctx->sof_headset, NULL, 0);
188 if (ret) {
189 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
190 return ret;
191 }
192
193 jack = &ctx->sof_headset;
194
195 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
d5952f34
SP
196 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
197 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
198 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
f70abd75
B
199 ret = snd_soc_component_set_jack(component, jack, NULL);
200
201 if (ret) {
202 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
203 return ret;
204 }
205
206 return ret;
207};
208
209static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,
210 struct snd_pcm_hw_params *params)
211{
212 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1eed6bc0 213 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
0d1571c1 214 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
f70abd75
B
215 int clk_id, clk_freq, pll_out, ret;
216
217 if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
1eed6bc0
XZ
218 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
219 ret = clk_prepare_enable(ctx->mclk);
220 if (ret < 0) {
221 dev_err(rtd->dev,
222 "could not configure MCLK state");
223 return ret;
224 }
225 }
226
f70abd75
B
227 clk_id = RT5682_PLL1_S_MCLK;
228 if (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ)
229 clk_freq = 24000000;
230 else
231 clk_freq = 19200000;
232 } else {
233 clk_id = RT5682_PLL1_S_BCLK1;
234 clk_freq = params_rate(params) * 50;
235 }
236
237 pll_out = params_rate(params) * 512;
238
239 ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out);
240 if (ret < 0)
241 dev_err(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret);
242
243 /* Configure sysclk for codec */
244 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
245 pll_out, SND_SOC_CLOCK_IN);
246 if (ret < 0)
247 dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
248
249 /*
250 * slot_width should equal or large than data length, set them
251 * be the same
252 */
253 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2,
254 params_width(params));
255 if (ret < 0) {
256 dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
257 return ret;
258 }
259
260 return ret;
261}
262
263static struct snd_soc_ops sof_rt5682_ops = {
264 .hw_params = sof_rt5682_hw_params,
265};
266
a79ae0f6
YZ
267static int sof_rt1015_hw_params(struct snd_pcm_substream *substream,
268 struct snd_pcm_hw_params *params)
269{
270 struct snd_soc_pcm_runtime *rtd = substream->private_data;
271 struct snd_soc_card *card = rtd->card;
272 struct snd_soc_dai *codec_dai;
273 int i, ret;
274
275 if (!snd_soc_card_get_codec_dai(card, "rt1015-aif"))
276 return 0;
277
278 for_each_rtd_codec_dais(rtd, i, codec_dai) {
279 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
280 params_rate(params) * 50,
281 params_rate(params) * 256);
282 if (ret < 0) {
283 dev_err(card->dev, "failed to set pll\n");
284 return ret;
285 }
286 /* Configure sysclk for codec */
287 ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL,
288 params_rate(params) * 256,
289 SND_SOC_CLOCK_IN);
290 if (ret < 0) {
291 dev_err(card->dev, "failed to set sysclk\n");
292 return ret;
293 }
294 }
295
296 return 0;
297}
298
299static struct snd_soc_ops sof_rt1015_ops = {
300 .hw_params = sof_rt1015_hw_params,
301};
302
f70abd75
B
303static struct snd_soc_dai_link_component platform_component[] = {
304 {
305 /* name might be overridden during probe */
306 .name = "0000:00:1f.3"
307 }
308};
309
310static int sof_card_late_probe(struct snd_soc_card *card)
311{
312 struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
313 struct snd_soc_component *component = NULL;
314 char jack_name[NAME_SIZE];
315 struct sof_hdmi_pcm *pcm;
98ff5c26 316 int err;
f70abd75
B
317 int i = 0;
318
319 /* HDMI is not supported by SOF on Baytrail/CherryTrail */
320 if (is_legacy_cpu)
321 return 0;
322
98ff5c26
GL
323 if (list_empty(&ctx->hdmi_pcm_list))
324 return -EINVAL;
59bbd703 325
98ff5c26
GL
326 if (ctx->common_hdmi_codec_drv) {
327 pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm,
328 head);
329 component = pcm->codec_dai->component;
59bbd703 330 return hda_dsp_hdmi_build_controls(card, component);
98ff5c26 331 }
59bbd703 332
f70abd75
B
333 list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
334 component = pcm->codec_dai->component;
335 snprintf(jack_name, sizeof(jack_name),
336 "HDMI/DP, pcm=%d Jack", pcm->device);
337 err = snd_soc_card_jack_new(card, jack_name,
338 SND_JACK_AVOUT, &sof_hdmi[i],
339 NULL, 0);
340
341 if (err)
342 return err;
343
344 err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
345 &sof_hdmi[i]);
346 if (err < 0)
347 return err;
348
349 i++;
350 }
f70abd75
B
351
352 return hdac_hdmi_jack_port_init(component, &card->dapm);
353}
354
355static const struct snd_kcontrol_new sof_controls[] = {
356 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
357 SOC_DAPM_PIN_SWITCH("Headset Mic"),
358 SOC_DAPM_PIN_SWITCH("Spk"),
a79ae0f6
YZ
359 SOC_DAPM_PIN_SWITCH("Left Spk"),
360 SOC_DAPM_PIN_SWITCH("Right Spk"),
361
f70abd75
B
362};
363
364static const struct snd_soc_dapm_widget sof_widgets[] = {
365 SND_SOC_DAPM_HP("Headphone Jack", NULL),
366 SND_SOC_DAPM_MIC("Headset Mic", NULL),
367 SND_SOC_DAPM_SPK("Spk", NULL),
a79ae0f6
YZ
368 SND_SOC_DAPM_SPK("Left Spk", NULL),
369 SND_SOC_DAPM_SPK("Right Spk", NULL),
4413adc4
BL
370};
371
372static const struct snd_soc_dapm_widget dmic_widgets[] = {
8afd1a99 373 SND_SOC_DAPM_MIC("SoC DMIC", NULL),
f70abd75
B
374};
375
376static const struct snd_soc_dapm_route sof_map[] = {
377 /* HP jack connectors - unknown if we have jack detection */
378 { "Headphone Jack", NULL, "HPOL" },
379 { "Headphone Jack", NULL, "HPOR" },
380
381 /* other jacks */
382 { "IN1P", NULL, "Headset Mic" },
f70abd75
B
383};
384
385static const struct snd_soc_dapm_route speaker_map[] = {
386 /* speaker */
387 { "Spk", NULL, "Speaker" },
388};
389
a79ae0f6
YZ
390static const struct snd_soc_dapm_route speaker_map_lr[] = {
391 { "Left Spk", NULL, "Left SPO" },
392 { "Right Spk", NULL, "Right SPO" },
393};
394
4413adc4
BL
395static const struct snd_soc_dapm_route dmic_map[] = {
396 /* digital mics */
397 {"DMic", NULL, "SoC DMIC"},
398};
399
a79ae0f6
YZ
400static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd)
401{
402 return snd_soc_dapm_add_routes(&rtd->card->dapm, speaker_map_lr,
403 ARRAY_SIZE(speaker_map_lr));
404}
405
f70abd75
B
406static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
407{
408 struct snd_soc_card *card = rtd->card;
409 int ret;
410
411 ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map,
412 ARRAY_SIZE(speaker_map));
413
414 if (ret)
415 dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
416 return ret;
417}
418
4413adc4
BL
419static int dmic_init(struct snd_soc_pcm_runtime *rtd)
420{
421 struct snd_soc_card *card = rtd->card;
422 int ret;
423
424 ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
425 ARRAY_SIZE(dmic_widgets));
426 if (ret) {
427 dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
428 /* Don't need to add routes if widget addition failed */
429 return ret;
430 }
431
432 ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
433 ARRAY_SIZE(dmic_map));
434
435 if (ret)
436 dev_err(card->dev, "DMic map addition failed: %d\n", ret);
437
438 return ret;
439}
440
a79ae0f6
YZ
441static struct snd_soc_codec_conf rt1015_amp_conf[] = {
442 {
443 .dlc = COMP_CODEC_CONF("i2c-10EC1015:00"),
444 .name_prefix = "Left",
445 },
446 {
447 .dlc = COMP_CODEC_CONF("i2c-10EC1015:01"),
448 .name_prefix = "Right",
449 },
450};
451
f70abd75
B
452/* sof audio machine driver for rt5682 codec */
453static struct snd_soc_card sof_audio_card_rt5682 = {
d745cc1a 454 .name = "rt5682", /* the sof- prefix is added by the core */
f70abd75
B
455 .owner = THIS_MODULE,
456 .controls = sof_controls,
457 .num_controls = ARRAY_SIZE(sof_controls),
458 .dapm_widgets = sof_widgets,
459 .num_dapm_widgets = ARRAY_SIZE(sof_widgets),
460 .dapm_routes = sof_map,
461 .num_dapm_routes = ARRAY_SIZE(sof_map),
462 .fully_routed = true,
463 .late_probe = sof_card_late_probe,
464};
465
f70abd75
B
466static struct snd_soc_dai_link_component rt5682_component[] = {
467 {
468 .name = "i2c-10EC5682:00",
469 .dai_name = "rt5682-aif1",
470 }
471};
472
473static struct snd_soc_dai_link_component dmic_component[] = {
474 {
475 .name = "dmic-codec",
476 .dai_name = "dmic-hifi",
477 }
478};
479
480static struct snd_soc_dai_link_component max98357a_component[] = {
481 {
482 .name = "MX98357A:00",
483 .dai_name = "HiFi",
484 }
485};
486
a79ae0f6
YZ
487static struct snd_soc_dai_link_component rt1015_components[] = {
488 {
489 .name = "i2c-10EC1015:00",
490 .dai_name = "rt1015-aif",
491 },
492 {
493 .name = "i2c-10EC1015:01",
494 .dai_name = "rt1015-aif",
495 },
496};
497
f70abd75
B
498static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
499 int ssp_codec,
500 int ssp_amp,
e711223a 501 int dmic_be_num,
f70abd75
B
502 int hdmi_num)
503{
504 struct snd_soc_dai_link_component *idisp_components;
e1684073 505 struct snd_soc_dai_link_component *cpus;
f70abd75
B
506 struct snd_soc_dai_link *links;
507 int i, id = 0;
508
509 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
510 sof_audio_card_rt5682.num_links, GFP_KERNEL);
e1684073
KM
511 cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
512 sof_audio_card_rt5682.num_links, GFP_KERNEL);
513 if (!links || !cpus)
f70abd75
B
514 goto devm_err;
515
516 /* codec SSP */
517 links[id].name = devm_kasprintf(dev, GFP_KERNEL,
518 "SSP%d-Codec", ssp_codec);
519 if (!links[id].name)
520 goto devm_err;
521
522 links[id].id = id;
523 links[id].codecs = rt5682_component;
524 links[id].num_codecs = ARRAY_SIZE(rt5682_component);
525 links[id].platforms = platform_component;
526 links[id].num_platforms = ARRAY_SIZE(platform_component);
527 links[id].init = sof_rt5682_codec_init;
528 links[id].ops = &sof_rt5682_ops;
529 links[id].nonatomic = true;
530 links[id].dpcm_playback = 1;
531 links[id].dpcm_capture = 1;
532 links[id].no_pcm = 1;
e1684073
KM
533 links[id].cpus = &cpus[id];
534 links[id].num_cpus = 1;
f70abd75 535 if (is_legacy_cpu) {
e1684073
KM
536 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
537 "ssp%d-port",
538 ssp_codec);
539 if (!links[id].cpus->dai_name)
f70abd75
B
540 goto devm_err;
541 } else {
542 /*
543 * Currently, On SKL+ platforms MCLK will be turned off in sof
544 * runtime suspended, and it will go into runtime suspended
545 * right after playback is stop. However, rt5682 will output
546 * static noise if sysclk turns off during playback. Set
547 * ignore_pmdown_time to power down rt5682 immediately and
548 * avoid the noise.
549 * It can be removed once we can control MCLK by driver.
550 */
551 links[id].ignore_pmdown_time = 1;
e1684073
KM
552 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
553 "SSP%d Pin",
554 ssp_codec);
555 if (!links[id].cpus->dai_name)
f70abd75
B
556 goto devm_err;
557 }
558 id++;
559
560 /* dmic */
e711223a
KJ
561 if (dmic_be_num > 0) {
562 /* at least we have dmic01 */
563 links[id].name = "dmic01";
564 links[id].cpus = &cpus[id];
565 links[id].cpus->dai_name = "DMIC01 Pin";
4413adc4 566 links[id].init = dmic_init;
e711223a
KJ
567 if (dmic_be_num > 1) {
568 /* set up 2 BE links at most */
569 links[id + 1].name = "dmic16k";
570 links[id + 1].cpus = &cpus[id + 1];
571 links[id + 1].cpus->dai_name = "DMIC16k Pin";
572 dmic_be_num = 2;
573 }
574 }
f70abd75 575
e711223a 576 for (i = 0; i < dmic_be_num; i++) {
f70abd75 577 links[id].id = id;
e1684073 578 links[id].num_cpus = 1;
f70abd75
B
579 links[id].codecs = dmic_component;
580 links[id].num_codecs = ARRAY_SIZE(dmic_component);
581 links[id].platforms = platform_component;
582 links[id].num_platforms = ARRAY_SIZE(platform_component);
583 links[id].ignore_suspend = 1;
584 links[id].dpcm_capture = 1;
585 links[id].no_pcm = 1;
586 id++;
587 }
588
589 /* HDMI */
590 if (hdmi_num > 0) {
591 idisp_components = devm_kzalloc(dev,
592 sizeof(struct snd_soc_dai_link_component) *
593 hdmi_num, GFP_KERNEL);
594 if (!idisp_components)
595 goto devm_err;
596 }
597 for (i = 1; i <= hdmi_num; i++) {
598 links[id].name = devm_kasprintf(dev, GFP_KERNEL,
599 "iDisp%d", i);
600 if (!links[id].name)
601 goto devm_err;
602
603 links[id].id = id;
e1684073
KM
604 links[id].cpus = &cpus[id];
605 links[id].num_cpus = 1;
606 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
607 "iDisp%d Pin", i);
608 if (!links[id].cpus->dai_name)
f70abd75
B
609 goto devm_err;
610
611 idisp_components[i - 1].name = "ehdaudio0D2";
612 idisp_components[i - 1].dai_name = devm_kasprintf(dev,
613 GFP_KERNEL,
614 "intel-hdmi-hifi%d",
615 i);
616 if (!idisp_components[i - 1].dai_name)
617 goto devm_err;
618
619 links[id].codecs = &idisp_components[i - 1];
620 links[id].num_codecs = 1;
621 links[id].platforms = platform_component;
622 links[id].num_platforms = ARRAY_SIZE(platform_component);
623 links[id].init = sof_hdmi_init;
624 links[id].dpcm_playback = 1;
625 links[id].no_pcm = 1;
626 id++;
627 }
628
629 /* speaker amp */
630 if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) {
631 links[id].name = devm_kasprintf(dev, GFP_KERNEL,
632 "SSP%d-Codec", ssp_amp);
633 if (!links[id].name)
634 goto devm_err;
635
636 links[id].id = id;
a79ae0f6
YZ
637 if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT) {
638 links[id].codecs = rt1015_components;
639 links[id].num_codecs = ARRAY_SIZE(rt1015_components);
640 links[id].init = speaker_codec_init_lr;
641 links[id].ops = &sof_rt1015_ops;
e2e404a6
SN
642 } else if (sof_rt5682_quirk &
643 SOF_MAX98373_SPEAKER_AMP_PRESENT) {
644 links[id].codecs = max_98373_components;
645 links[id].num_codecs = ARRAY_SIZE(max_98373_components);
646 links[id].init = max98373_spk_codec_init;
647 links[id].ops = &max_98373_ops;
a79ae0f6
YZ
648 } else {
649 links[id].codecs = max98357a_component;
650 links[id].num_codecs = ARRAY_SIZE(max98357a_component);
651 links[id].init = speaker_codec_init;
652 }
f70abd75
B
653 links[id].platforms = platform_component;
654 links[id].num_platforms = ARRAY_SIZE(platform_component);
f70abd75
B
655 links[id].nonatomic = true;
656 links[id].dpcm_playback = 1;
657 links[id].no_pcm = 1;
e1684073
KM
658 links[id].cpus = &cpus[id];
659 links[id].num_cpus = 1;
f70abd75 660 if (is_legacy_cpu) {
e1684073
KM
661 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
662 "ssp%d-port",
663 ssp_amp);
664 if (!links[id].cpus->dai_name)
f70abd75
B
665 goto devm_err;
666
667 } else {
e1684073
KM
668 links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
669 "SSP%d Pin",
670 ssp_amp);
671 if (!links[id].cpus->dai_name)
f70abd75
B
672 goto devm_err;
673 }
674 }
675
676 return links;
677devm_err:
678 return NULL;
679}
680
681static int sof_audio_probe(struct platform_device *pdev)
682{
683 struct snd_soc_dai_link *dai_links;
684 struct snd_soc_acpi_mach *mach;
685 struct sof_card_private *ctx;
e711223a 686 int dmic_be_num, hdmi_num;
f70abd75
B
687 int ret, ssp_amp, ssp_codec;
688
281c443f 689 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
f70abd75
B
690 if (!ctx)
691 return -ENOMEM;
692
6605f0ca
SN
693 if (pdev->id_entry && pdev->id_entry->driver_data)
694 sof_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data;
695
c68e0797
SN
696 dmi_check_system(sof_rt5682_quirk_table);
697
42432196 698 mach = pdev->dev.platform_data;
d4b74e21
SM
699
700 /* A speaker amp might not be present when the quirk claims one is.
701 * Detect this via whether the machine driver match includes quirk_data.
702 */
703 if ((sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) && !mach->quirk_data)
704 sof_rt5682_quirk &= ~SOF_SPEAKER_AMP_PRESENT;
705
536cfd2f 706 if (soc_intel_is_byt() || soc_intel_is_cht()) {
f70abd75 707 is_legacy_cpu = 1;
e711223a 708 dmic_be_num = 0;
f70abd75
B
709 hdmi_num = 0;
710 /* default quirk for legacy cpu */
1eed6bc0
XZ
711 sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
712 SOF_RT5682_MCLK_BYTCHT_EN |
713 SOF_RT5682_SSP_CODEC(2);
f70abd75 714 } else {
e711223a 715 dmic_be_num = 2;
c68e0797
SN
716 hdmi_num = (sof_rt5682_quirk & SOF_RT5682_NUM_HDMIDEV_MASK) >>
717 SOF_RT5682_NUM_HDMIDEV_SHIFT;
718 /* default number of HDMI DAI's */
719 if (!hdmi_num)
720 hdmi_num = 3;
f70abd75
B
721 }
722
1eed6bc0
XZ
723 /* need to get main clock from pmc */
724 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
725 ctx->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
e5f0d490
CY
726 if (IS_ERR(ctx->mclk)) {
727 ret = PTR_ERR(ctx->mclk);
728
729 dev_err(&pdev->dev,
730 "Failed to get MCLK from pmc_plt_clk_3: %d\n",
731 ret);
732 return ret;
733 }
734
1eed6bc0
XZ
735 ret = clk_prepare_enable(ctx->mclk);
736 if (ret < 0) {
737 dev_err(&pdev->dev,
738 "could not configure MCLK state");
739 return ret;
740 }
741 }
742
f70abd75
B
743 dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk);
744
745 ssp_amp = (sof_rt5682_quirk & SOF_RT5682_SSP_AMP_MASK) >>
746 SOF_RT5682_SSP_AMP_SHIFT;
747
748 ssp_codec = sof_rt5682_quirk & SOF_RT5682_SSP_CODEC_MASK;
749
750 /* compute number of dai links */
e711223a 751 sof_audio_card_rt5682.num_links = 1 + dmic_be_num + hdmi_num;
b385256e 752
f70abd75
B
753 if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT)
754 sof_audio_card_rt5682.num_links++;
755
e2e404a6
SN
756 if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT)
757 sof_max98373_codec_conf(&sof_audio_card_rt5682);
758
f70abd75 759 dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,
e711223a 760 dmic_be_num, hdmi_num);
f70abd75
B
761 if (!dai_links)
762 return -ENOMEM;
763
764 sof_audio_card_rt5682.dai_link = dai_links;
765
a79ae0f6
YZ
766 if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT) {
767 sof_audio_card_rt5682.codec_conf = rt1015_amp_conf;
768 sof_audio_card_rt5682.num_configs = ARRAY_SIZE(rt1015_amp_conf);
769 }
770
f70abd75
B
771 INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
772
773 sof_audio_card_rt5682.dev = &pdev->dev;
f70abd75
B
774
775 /* set platform name for each dailink */
776 ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_rt5682,
777 mach->mach_params.platform);
778 if (ret)
779 return ret;
780
59bbd703
KV
781 ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
782
f70abd75
B
783 snd_soc_card_set_drvdata(&sof_audio_card_rt5682, ctx);
784
785 return devm_snd_soc_register_card(&pdev->dev,
786 &sof_audio_card_rt5682);
787}
788
6ba5041c
JU
789static int sof_rt5682_remove(struct platform_device *pdev)
790{
791 struct snd_soc_card *card = platform_get_drvdata(pdev);
792 struct snd_soc_component *component = NULL;
793
794 for_each_card_components(card, component) {
795 if (!strcmp(component->name, rt5682_component[0].name)) {
796 snd_soc_component_set_jack(component, NULL, NULL);
797 break;
798 }
799 }
800
801 return 0;
802}
803
6605f0ca
SN
804static const struct platform_device_id board_ids[] = {
805 {
806 .name = "sof_rt5682",
807 },
808 {
809 .name = "tgl_max98357a_rt5682",
810 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
811 SOF_RT5682_SSP_CODEC(0) |
812 SOF_SPEAKER_AMP_PRESENT |
813 SOF_RT5682_SSP_AMP(1) |
814 SOF_RT5682_NUM_HDMIDEV(4)),
815 },
a79ae0f6
YZ
816 {
817 .name = "jsl_rt5682_rt1015",
818 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
819 SOF_RT5682_MCLK_24MHZ |
820 SOF_RT5682_SSP_CODEC(0) |
821 SOF_SPEAKER_AMP_PRESENT |
822 SOF_RT1015_SPEAKER_AMP_PRESENT |
823 SOF_RT5682_SSP_AMP(1)),
824 },
e2e404a6
SN
825 {
826 .name = "tgl_max98373_rt5682",
827 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
828 SOF_RT5682_SSP_CODEC(0) |
829 SOF_SPEAKER_AMP_PRESENT |
830 SOF_MAX98373_SPEAKER_AMP_PRESENT |
831 SOF_RT5682_SSP_AMP(1) |
832 SOF_RT5682_NUM_HDMIDEV(4)),
833 },
6605f0ca
SN
834 { }
835};
836
f70abd75
B
837static struct platform_driver sof_audio = {
838 .probe = sof_audio_probe,
6ba5041c 839 .remove = sof_rt5682_remove,
f70abd75
B
840 .driver = {
841 .name = "sof_rt5682",
842 .pm = &snd_soc_pm_ops,
843 },
6605f0ca 844 .id_table = board_ids,
f70abd75
B
845};
846module_platform_driver(sof_audio)
847
848/* Module information */
849MODULE_DESCRIPTION("SOF Audio Machine driver");
850MODULE_AUTHOR("Bard Liao <bard.liao@intel.com>");
851MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
852MODULE_LICENSE("GPL v2");
853MODULE_ALIAS("platform:sof_rt5682");
6605f0ca 854MODULE_ALIAS("platform:tgl_max98357a_rt5682");
a79ae0f6 855MODULE_ALIAS("platform:jsl_rt5682_rt1015");
e2e404a6 856MODULE_ALIAS("platform:tgl_max98373_rt5682");