ASoC: Intel: sof_rt5682: Fix uninitialized variable in probe
[linux-2.6-block.git] / sound / soc / intel / boards / sof_rt5682.c
CommitLineData
e149ca29 1// SPDX-License-Identifier: GPL-2.0-only
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>
bf939446 19#include <sound/sof.h>
f70abd75 20#include <sound/rt5682.h>
9a50d609 21#include <sound/rt5682s.h>
f70abd75
B
22#include <sound/soc-acpi.h>
23#include "../../codecs/rt5682.h"
9a50d609 24#include "../../codecs/rt5682s.h"
6657fcc9 25#include "../../codecs/rt5645.h"
536cfd2f 26#include "../common/soc-intel-quirks.h"
89cadbd8 27#include "sof_board_helpers.h"
e2e404a6 28#include "sof_maxim_common.h"
aa6cc97c 29#include "sof_realtek_common.h"
8efcd486
BL
30
31/* Driver-specific board quirks: from bit 0 to 7 */
32#define SOF_RT5682_MCLK_EN BIT(0)
33#define SOF_RT5682_MCLK_BYTCHT_EN BIT(1)
37897bab 34
f70abd75
B
35/* Default: MCLK on, MCLK 19.2M, SSP0 */
36static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
8efcd486 37 SOF_SSP_PORT_CODEC(0);
f70abd75 38
f70abd75
B
39static int sof_rt5682_quirk_cb(const struct dmi_system_id *id)
40{
41 sof_rt5682_quirk = (unsigned long)id->driver_data;
42 return 1;
43}
44
45static const struct dmi_system_id sof_rt5682_quirk_table[] = {
1eed6bc0
XZ
46 {
47 .callback = sof_rt5682_quirk_cb,
48 .matches = {
49 DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
50 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max"),
51 },
8efcd486 52 .driver_data = (void *)(SOF_SSP_PORT_CODEC(2)),
1eed6bc0
XZ
53 },
54 {
55 .callback = sof_rt5682_quirk_cb,
56 .matches = {
57 DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
58 DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"),
59 },
8efcd486 60 .driver_data = (void *)(SOF_SSP_PORT_CODEC(2)),
1eed6bc0 61 },
f70abd75
B
62 {
63 .callback = sof_rt5682_quirk_cb,
64 .matches = {
65 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
66 DMI_MATCH(DMI_PRODUCT_NAME, "WhiskeyLake Client"),
67 },
68 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
8efcd486 69 SOF_SSP_PORT_CODEC(1)),
f70abd75
B
70 },
71 {
72 .callback = sof_rt5682_quirk_cb,
73 .matches = {
1a3fb5d3 74 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"),
f70abd75
B
75 },
76 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
8efcd486
BL
77 SOF_SSP_PORT_CODEC(0) |
78 SOF_SSP_PORT_AMP(1)),
f70abd75
B
79 },
80 {
81 .callback = sof_rt5682_quirk_cb,
82 .matches = {
83 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
84 DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
85 },
86 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
8efcd486 87 SOF_SSP_PORT_CODEC(0)),
f70abd75 88 },
3e1734b6
SN
89 {
90 .callback = sof_rt5682_quirk_cb,
91 .matches = {
92 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Volteer"),
2a4b91a2 93 DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98373_ALC5682I_I2S_UP4"),
3e1734b6
SN
94 },
95 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
8efcd486
BL
96 SOF_SSP_PORT_CODEC(0) |
97 SOF_SSP_PORT_AMP(2) |
98 SOF_NUM_IDISP_HDMI(4)),
3e1734b6 99 },
46fa9a15 100 {
101 .callback = sof_rt5682_quirk_cb,
102 .matches = {
103 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
104 DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
105 DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"),
106 },
107 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
8efcd486
BL
108 SOF_SSP_PORT_CODEC(0) |
109 SOF_SSP_PORT_AMP(2) |
110 SOF_NUM_IDISP_HDMI(4)),
46fa9a15 111 },
f316c9d9
MC
112 {
113 .callback = sof_rt5682_quirk_cb,
114 .matches = {
115 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
116 DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98390_ALC5682I_I2S"),
117 },
118 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
8efcd486
BL
119 SOF_SSP_PORT_CODEC(0) |
120 SOF_SSP_PORT_AMP(2) |
121 SOF_NUM_IDISP_HDMI(4)),
f316c9d9 122 },
fcd1e39c
AH
123 {
124 .callback = sof_rt5682_quirk_cb,
125 .matches = {
126 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
127 DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S_AMP_SSP2"),
128 },
129 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
8efcd486
BL
130 SOF_SSP_PORT_CODEC(0) |
131 SOF_SSP_PORT_AMP(2) |
132 SOF_NUM_IDISP_HDMI(4)),
fcd1e39c 133 },
b4dd2e37
YZ
134 {
135 .callback = sof_rt5682_quirk_cb,
136 .matches = {
137 DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
138 },
139 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
8efcd486
BL
140 SOF_SSP_PORT_CODEC(2) |
141 SOF_SSP_PORT_AMP(0) |
8efcd486
BL
142 SOF_SSP_PORT_BT_OFFLOAD(1) |
143 SOF_BT_OFFLOAD_PRESENT
b4dd2e37
YZ
144 ),
145 },
f70abd75
B
146 {}
147};
148
c3ce12b2
PLB
149static struct snd_soc_jack_pin jack_pins[] = {
150 {
151 .pin = "Headphone Jack",
152 .mask = SND_JACK_HEADPHONE,
153 },
154 {
155 .pin = "Headset Mic",
156 .mask = SND_JACK_MICROPHONE,
157 },
158};
159
f70abd75
B
160static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
161{
162 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
a2c1125e 163 struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
89cadbd8 164 struct snd_soc_jack *jack = &ctx->headset_jack;
6657fcc9 165 int extra_jack_data;
95409545 166 int ret, mclk_freq;
f70abd75 167
95409545
BL
168 if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
169 mclk_freq = sof_dai_get_mclk(rtd);
170 if (mclk_freq <= 0) {
171 dev_err(rtd->dev, "invalid mclk freq %d\n", mclk_freq);
172 return -EINVAL;
173 }
f70abd75 174
95409545
BL
175 /* need to enable ASRC function for 24MHz mclk rate */
176 if (mclk_freq == 24000000) {
177 dev_info(rtd->dev, "enable ASRC\n");
178
5f706c5e
BL
179 switch (ctx->codec_type) {
180 case CODEC_RT5650:
95409545
BL
181 rt5645_sel_asrc_clk_src(component,
182 RT5645_DA_STEREO_FILTER |
183 RT5645_AD_STEREO_FILTER,
184 RT5645_CLK_SEL_I2S1_ASRC);
185 rt5645_sel_asrc_clk_src(component,
186 RT5645_DA_MONO_L_FILTER |
187 RT5645_DA_MONO_R_FILTER,
188 RT5645_CLK_SEL_I2S2_ASRC);
5f706c5e
BL
189 break;
190 case CODEC_RT5682:
95409545
BL
191 rt5682_sel_asrc_clk_src(component,
192 RT5682_DA_STEREO1_FILTER |
193 RT5682_AD_STEREO1_FILTER,
194 RT5682_CLK_SEL_I2S1_ASRC);
5f706c5e
BL
195 break;
196 case CODEC_RT5682S:
197 rt5682s_sel_asrc_clk_src(component,
198 RT5682S_DA_STEREO1_FILTER |
199 RT5682S_AD_STEREO1_FILTER,
200 RT5682S_CLK_SEL_I2S1_ASRC);
201 break;
202 default:
203 dev_err(rtd->dev, "invalid codec type %d\n",
204 ctx->codec_type);
205 return -EINVAL;
206 }
95409545 207 }
1eed6bc0 208
95409545
BL
209 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
210 /*
211 * The firmware might enable the clock at
212 * boot (this information may or may not
213 * be reflected in the enable clock register).
214 * To change the rate we must disable the clock
215 * first to cover these cases. Due to common
216 * clock framework restrictions that do not allow
217 * to disable a clock that has not been enabled,
218 * we need to enable the clock first.
219 */
89cadbd8 220 ret = clk_prepare_enable(ctx->rt5682.mclk);
95409545 221 if (!ret)
89cadbd8 222 clk_disable_unprepare(ctx->rt5682.mclk);
1eed6bc0 223
89cadbd8 224 ret = clk_set_rate(ctx->rt5682.mclk, 19200000);
95409545
BL
225
226 if (ret)
227 dev_err(rtd->dev, "unable to set MCLK rate\n");
228 }
1eed6bc0
XZ
229 }
230
f70abd75
B
231 /*
232 * Headset buttons map to the google Reference headset.
233 * These can be configured by userspace.
234 */
c3ce12b2
PLB
235 ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
236 SND_JACK_HEADSET | SND_JACK_BTN_0 |
237 SND_JACK_BTN_1 | SND_JACK_BTN_2 |
238 SND_JACK_BTN_3,
89cadbd8 239 jack,
c3ce12b2
PLB
240 jack_pins,
241 ARRAY_SIZE(jack_pins));
f70abd75
B
242 if (ret) {
243 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
244 return ret;
245 }
246
f70abd75 247 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
d5952f34
SP
248 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
249 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
250 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
6657fcc9 251
5f706c5e 252 if (ctx->codec_type == CODEC_RT5650) {
6657fcc9
BL
253 extra_jack_data = SND_JACK_MICROPHONE | SND_JACK_BTN_0;
254 ret = snd_soc_component_set_jack(component, jack, &extra_jack_data);
255 } else
256 ret = snd_soc_component_set_jack(component, jack, NULL);
f70abd75
B
257
258 if (ret) {
259 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
260 return ret;
261 }
262
263 return ret;
264};
265
b0c96fc1
FO
266static void sof_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd)
267{
a2c1125e 268 struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
b0c96fc1
FO
269
270 snd_soc_component_set_jack(component, NULL, NULL);
271}
272
f70abd75
B
273static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,
274 struct snd_pcm_hw_params *params)
275{
a2c1125e 276 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
1eed6bc0 277 struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
a2c1125e 278 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
9a50d609 279 int pll_id, pll_source, pll_in, pll_out, clk_id, ret;
f70abd75
B
280
281 if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
1eed6bc0 282 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
89cadbd8 283 ret = clk_prepare_enable(ctx->rt5682.mclk);
1eed6bc0
XZ
284 if (ret < 0) {
285 dev_err(rtd->dev,
286 "could not configure MCLK state");
287 return ret;
288 }
289 }
290
5f706c5e
BL
291 switch (ctx->codec_type) {
292 case CODEC_RT5650:
6657fcc9 293 pll_source = RT5645_PLL1_S_MCLK;
5f706c5e
BL
294 break;
295 case CODEC_RT5682:
9a50d609 296 pll_source = RT5682_PLL1_S_MCLK;
5f706c5e
BL
297 break;
298 case CODEC_RT5682S:
299 pll_source = RT5682S_PLL_S_MCLK;
300 break;
301 default:
302 dev_err(rtd->dev, "invalid codec type %d\n",
303 ctx->codec_type);
304 return -EINVAL;
305 }
bf939446
KJ
306
307 /* get the tplg configured mclk. */
9a50d609 308 pll_in = sof_dai_get_mclk(rtd);
95409545
BL
309 if (pll_in <= 0) {
310 dev_err(rtd->dev, "invalid mclk freq %d\n", pll_in);
311 return -EINVAL;
bf939446 312 }
f70abd75 313 } else {
5f706c5e
BL
314 switch (ctx->codec_type) {
315 case CODEC_RT5650:
6657fcc9 316 pll_source = RT5645_PLL1_S_BCLK1;
5f706c5e
BL
317 break;
318 case CODEC_RT5682:
9a50d609 319 pll_source = RT5682_PLL1_S_BCLK1;
5f706c5e
BL
320 break;
321 case CODEC_RT5682S:
322 pll_source = RT5682S_PLL_S_BCLK1;
323 break;
324 default:
325 dev_err(rtd->dev, "invalid codec type %d\n",
326 ctx->codec_type);
327 return -EINVAL;
328 }
9a50d609
BL
329
330 pll_in = params_rate(params) * 50;
331 }
332
5f706c5e
BL
333 switch (ctx->codec_type) {
334 case CODEC_RT5650:
6657fcc9
BL
335 pll_id = 0; /* not used in codec driver */
336 clk_id = RT5645_SCLK_S_PLL1;
5f706c5e
BL
337 break;
338 case CODEC_RT5682:
9a50d609
BL
339 pll_id = RT5682_PLL1;
340 clk_id = RT5682_SCLK_S_PLL1;
5f706c5e
BL
341 break;
342 case CODEC_RT5682S:
343 pll_id = RT5682S_PLL2;
344 clk_id = RT5682S_SCLK_S_PLL2;
345 break;
346 default:
347 dev_err(rtd->dev, "invalid codec type %d\n", ctx->codec_type);
348 return -EINVAL;
f70abd75
B
349 }
350
351 pll_out = params_rate(params) * 512;
352
dbf2f8e3 353 /* when MCLK is 512FS, no need to set PLL configuration additionally. */
5f706c5e
BL
354 if (pll_in == pll_out) {
355 switch (ctx->codec_type) {
356 case CODEC_RT5650:
95409545 357 clk_id = RT5645_SCLK_S_MCLK;
5f706c5e
BL
358 break;
359 case CODEC_RT5682:
95409545 360 clk_id = RT5682_SCLK_S_MCLK;
5f706c5e
BL
361 break;
362 case CODEC_RT5682S:
363 clk_id = RT5682S_SCLK_S_MCLK;
364 break;
365 default:
366 dev_err(rtd->dev, "invalid codec type %d\n",
367 ctx->codec_type);
368 return -EINVAL;
369 }
370 } else {
dbf2f8e3
MC
371 /* Configure pll for codec */
372 ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, pll_in,
373 pll_out);
374 if (ret < 0)
375 dev_err(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret);
376 }
f70abd75
B
377
378 /* Configure sysclk for codec */
9a50d609 379 ret = snd_soc_dai_set_sysclk(codec_dai, clk_id,
f70abd75
B
380 pll_out, SND_SOC_CLOCK_IN);
381 if (ret < 0)
382 dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
383
384 /*
385 * slot_width should equal or large than data length, set them
386 * be the same
387 */
388 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2,
389 params_width(params));
390 if (ret < 0) {
391 dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
392 return ret;
393 }
394
395 return ret;
396}
397
398static struct snd_soc_ops sof_rt5682_ops = {
399 .hw_params = sof_rt5682_hw_params,
400};
401
f70abd75
B
402static int sof_card_late_probe(struct snd_soc_card *card)
403{
404 struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
94d2d089 405 struct snd_soc_dapm_context *dapm = &card->dapm;
98ff5c26 406 int err;
f70abd75 407
5f706c5e 408 if (ctx->amp_type == CODEC_MAX98373) {
371a3f01
YZ
409 /* Disable Left and Right Spk pin after boot */
410 snd_soc_dapm_disable_pin(dapm, "Left Spk");
411 snd_soc_dapm_disable_pin(dapm, "Right Spk");
412 err = snd_soc_dapm_sync(dapm);
413 if (err < 0)
414 return err;
415 }
416
89cadbd8 417 return sof_intel_board_card_late_probe(card);
f70abd75
B
418}
419
420static const struct snd_kcontrol_new sof_controls[] = {
421 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
422 SOC_DAPM_PIN_SWITCH("Headset Mic"),
a79ae0f6
YZ
423 SOC_DAPM_PIN_SWITCH("Left Spk"),
424 SOC_DAPM_PIN_SWITCH("Right Spk"),
425
f70abd75
B
426};
427
428static const struct snd_soc_dapm_widget sof_widgets[] = {
429 SND_SOC_DAPM_HP("Headphone Jack", NULL),
430 SND_SOC_DAPM_MIC("Headset Mic", NULL),
a79ae0f6
YZ
431 SND_SOC_DAPM_SPK("Left Spk", NULL),
432 SND_SOC_DAPM_SPK("Right Spk", NULL),
4413adc4
BL
433};
434
f70abd75
B
435static const struct snd_soc_dapm_route sof_map[] = {
436 /* HP jack connectors - unknown if we have jack detection */
437 { "Headphone Jack", NULL, "HPOL" },
438 { "Headphone Jack", NULL, "HPOR" },
439
440 /* other jacks */
441 { "IN1P", NULL, "Headset Mic" },
f70abd75
B
442};
443
6657fcc9
BL
444static const struct snd_soc_dapm_route rt5650_spk_dapm_routes[] = {
445 /* speaker */
446 { "Left Spk", NULL, "SPOL" },
447 { "Right Spk", NULL, "SPOR" },
448};
449
6657fcc9
BL
450static int rt5650_spk_init(struct snd_soc_pcm_runtime *rtd)
451{
452 struct snd_soc_card *card = rtd->card;
453 int ret;
454
455 ret = snd_soc_dapm_add_routes(&card->dapm, rt5650_spk_dapm_routes,
456 ARRAY_SIZE(rt5650_spk_dapm_routes));
457 if (ret)
458 dev_err(rtd->dev, "fail to add dapm routes, ret=%d\n", ret);
459
460 return ret;
461}
462
f70abd75
B
463/* sof audio machine driver for rt5682 codec */
464static struct snd_soc_card sof_audio_card_rt5682 = {
d745cc1a 465 .name = "rt5682", /* the sof- prefix is added by the core */
f70abd75
B
466 .owner = THIS_MODULE,
467 .controls = sof_controls,
468 .num_controls = ARRAY_SIZE(sof_controls),
469 .dapm_widgets = sof_widgets,
470 .num_dapm_widgets = ARRAY_SIZE(sof_widgets),
471 .dapm_routes = sof_map,
472 .num_dapm_routes = ARRAY_SIZE(sof_map),
473 .fully_routed = true,
474 .late_probe = sof_card_late_probe,
475};
476
f70abd75
B
477static struct snd_soc_dai_link_component rt5682_component[] = {
478 {
479 .name = "i2c-10EC5682:00",
480 .dai_name = "rt5682-aif1",
481 }
482};
483
9a50d609
BL
484static struct snd_soc_dai_link_component rt5682s_component[] = {
485 {
486 .name = "i2c-RTL5682:00",
487 .dai_name = "rt5682s-aif1",
488 }
489};
490
6657fcc9
BL
491static struct snd_soc_dai_link_component rt5650_components[] = {
492 {
493 .name = "i2c-10EC5650:00",
494 .dai_name = "rt5645-aif1",
495 },
496 {
497 .name = "i2c-10EC5650:00",
498 .dai_name = "rt5645-aif2",
499 }
500};
501
8fa1116e
BL
502static int
503sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card,
504 struct sof_card_private *ctx)
f70abd75 505{
89cadbd8 506 int ret;
f70abd75 507
8fa1116e 508 ret = sof_intel_board_set_dai_link(dev, card, ctx);
84c280af 509 if (ret)
8fa1116e
BL
510 return ret;
511
512 if (!ctx->codec_link) {
513 dev_err(dev, "codec link not available");
514 return -EINVAL;
515 }
5f706c5e 516
8fa1116e
BL
517 /* codec-specific fields for headphone codec */
518 switch (ctx->codec_type) {
5f706c5e 519 case CODEC_RT5650:
8fa1116e
BL
520 ctx->codec_link->codecs = &rt5650_components[0];
521 ctx->codec_link->num_codecs = 1;
5f706c5e
BL
522 break;
523 case CODEC_RT5682:
8fa1116e
BL
524 ctx->codec_link->codecs = rt5682_component;
525 ctx->codec_link->num_codecs = ARRAY_SIZE(rt5682_component);
5f706c5e
BL
526 break;
527 case CODEC_RT5682S:
8fa1116e
BL
528 ctx->codec_link->codecs = rt5682s_component;
529 ctx->codec_link->num_codecs = ARRAY_SIZE(rt5682s_component);
5f706c5e
BL
530 break;
531 default:
8fa1116e
BL
532 dev_err(dev, "invalid codec type %d\n", ctx->codec_type);
533 return -EINVAL;
9a50d609 534 }
5f706c5e 535
8fa1116e
BL
536 ctx->codec_link->init = sof_rt5682_codec_init;
537 ctx->codec_link->exit = sof_rt5682_codec_exit;
538 ctx->codec_link->ops = &sof_rt5682_ops;
84c280af 539
8fa1116e 540 if (!ctx->rt5682.is_legacy_cpu) {
f70abd75
B
541 /*
542 * Currently, On SKL+ platforms MCLK will be turned off in sof
543 * runtime suspended, and it will go into runtime suspended
544 * right after playback is stop. However, rt5682 will output
545 * static noise if sysclk turns off during playback. Set
546 * ignore_pmdown_time to power down rt5682 immediately and
547 * avoid the noise.
548 * It can be removed once we can control MCLK by driver.
549 */
8fa1116e 550 ctx->codec_link->ignore_pmdown_time = 1;
37897bab
YZ
551 }
552
8fa1116e
BL
553 if (ctx->amp_type == CODEC_NONE)
554 return 0;
37897bab 555
8fa1116e
BL
556 if (!ctx->amp_link) {
557 dev_err(dev, "amp link not available");
558 return -EINVAL;
f70abd75
B
559 }
560
8fa1116e
BL
561 /* codec-specific fields for speaker amplifier */
562 switch (ctx->amp_type) {
563 case CODEC_MAX98357A:
564 max_98357a_dai_link(ctx->amp_link);
565 break;
566 case CODEC_MAX98360A:
567 max_98360a_dai_link(ctx->amp_link);
568 break;
569 case CODEC_MAX98373:
570 ctx->amp_link->codecs = max_98373_components;
571 ctx->amp_link->num_codecs = ARRAY_SIZE(max_98373_components);
572 ctx->amp_link->init = max_98373_spk_codec_init;
573 ctx->amp_link->ops = &max_98373_ops;
574 break;
575 case CODEC_MAX98390:
576 max_98390_dai_link(dev, ctx->amp_link);
577 break;
578 case CODEC_RT1011:
579 sof_rt1011_dai_link(ctx->amp_link);
580 break;
581 case CODEC_RT1015:
582 sof_rt1015_dai_link(ctx->amp_link);
583 break;
584 case CODEC_RT1015P:
585 sof_rt1015p_dai_link(ctx->amp_link);
586 break;
587 case CODEC_RT1019P:
588 sof_rt1019p_dai_link(ctx->amp_link);
589 break;
590 case CODEC_RT5650:
591 /* use AIF2 to support speaker pipeline */
592 ctx->amp_link->codecs = &rt5650_components[1];
593 ctx->amp_link->num_codecs = 1;
594 ctx->amp_link->init = rt5650_spk_init;
595 ctx->amp_link->ops = &sof_rt5682_ops;
596 break;
597 default:
598 dev_err(dev, "invalid amp type %d\n", ctx->amp_type);
599 return -EINVAL;
f3c37847 600 }
601
8fa1116e 602 return 0;
f70abd75
B
603}
604
605static int sof_audio_probe(struct platform_device *pdev)
606{
3de206a4 607 struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
f70abd75 608 struct sof_card_private *ctx;
9cb83ed1 609 bool is_legacy_cpu = false;
e45cd972 610 int ret;
f70abd75 611
6605f0ca
SN
612 if (pdev->id_entry && pdev->id_entry->driver_data)
613 sof_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data;
614
c68e0797
SN
615 dmi_check_system(sof_rt5682_quirk_table);
616
8efcd486
BL
617 if (soc_intel_is_byt() || soc_intel_is_cht()) {
618 is_legacy_cpu = true;
619
620 /* default quirk for legacy cpu */
621 sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
622 SOF_RT5682_MCLK_BYTCHT_EN |
623 SOF_SSP_PORT_CODEC(2);
624 }
625
626 dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk);
627
628 /* initialize ctx with board quirk */
629 ctx = sof_intel_board_get_ctx(&pdev->dev, sof_rt5682_quirk);
630 if (!ctx)
631 return -ENOMEM;
6657fcc9 632
5f706c5e 633 if (ctx->codec_type == CODEC_RT5650) {
6657fcc9
BL
634 sof_audio_card_rt5682.name = devm_kstrdup(&pdev->dev, "rt5650",
635 GFP_KERNEL);
5f706c5e
BL
636
637 /* create speaker dai link also */
638 if (ctx->amp_type == CODEC_NONE)
639 ctx->amp_type = CODEC_RT5650;
6657fcc9 640 }
8fe6ec03 641
8efcd486 642 if (is_legacy_cpu) {
89cadbd8 643 ctx->rt5682.is_legacy_cpu = true;
c51fc25d 644 ctx->dmic_be_num = 0;
89cadbd8
BL
645 /* HDMI is not supported by SOF on Baytrail/CherryTrail */
646 ctx->hdmi_num = 0;
f70abd75 647 } else {
22cefca3 648 if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
d8fc8176 649 ctx->hdmi.idisp_codec = true;
f70abd75
B
650 }
651
1eed6bc0
XZ
652 /* need to get main clock from pmc */
653 if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
89cadbd8
BL
654 ctx->rt5682.mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
655 if (IS_ERR(ctx->rt5682.mclk)) {
656 ret = PTR_ERR(ctx->rt5682.mclk);
e5f0d490
CY
657
658 dev_err(&pdev->dev,
659 "Failed to get MCLK from pmc_plt_clk_3: %d\n",
660 ret);
661 return ret;
662 }
663
89cadbd8 664 ret = clk_prepare_enable(ctx->rt5682.mclk);
1eed6bc0
XZ
665 if (ret < 0) {
666 dev_err(&pdev->dev,
667 "could not configure MCLK state");
668 return ret;
669 }
670 }
671
8fa1116e
BL
672 /* update dai_link */
673 ret = sof_card_dai_links_create(&pdev->dev, &sof_audio_card_rt5682, ctx);
674 if (ret)
675 return ret;
f70abd75 676
5f706c5e
BL
677 /* update codec_conf */
678 switch (ctx->amp_type) {
679 case CODEC_MAX98373:
680 max_98373_set_codec_conf(&sof_audio_card_rt5682);
681 break;
682 case CODEC_MAX98390:
683 max_98390_set_codec_conf(&pdev->dev, &sof_audio_card_rt5682);
684 break;
685 case CODEC_RT1011:
686 sof_rt1011_codec_conf(&sof_audio_card_rt5682);
687 break;
688 case CODEC_RT1015:
77659872 689 sof_rt1015_codec_conf(&sof_audio_card_rt5682);
5f706c5e
BL
690 break;
691 case CODEC_RT1015P:
692 sof_rt1015p_codec_conf(&sof_audio_card_rt5682);
693 break;
5f706c5e
BL
694 case CODEC_MAX98357A:
695 case CODEC_MAX98360A:
696 case CODEC_RT1019P:
697 case CODEC_RT5650:
b497654f 698 case CODEC_NONE:
5f706c5e
BL
699 /* no codec conf required */
700 break;
701 default:
702 dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type);
703 return -EINVAL;
704 }
a79ae0f6 705
f70abd75 706 sof_audio_card_rt5682.dev = &pdev->dev;
f70abd75
B
707
708 /* set platform name for each dailink */
709 ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_rt5682,
710 mach->mach_params.platform);
711 if (ret)
712 return ret;
713
714 snd_soc_card_set_drvdata(&sof_audio_card_rt5682, ctx);
715
716 return devm_snd_soc_register_card(&pdev->dev,
717 &sof_audio_card_rt5682);
718}
719
6605f0ca
SN
720static const struct platform_device_id board_ids[] = {
721 {
722 .name = "sof_rt5682",
723 },
724 {
61cafaea 725 .name = "cml_rt5682_def",
6605f0ca 726 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8efcd486
BL
727 SOF_SSP_PORT_CODEC(0) |
728 SOF_SSP_PORT_AMP(1)),
6605f0ca 729 },
a79ae0f6 730 {
9be229ff 731 .name = "jsl_rt5682_def",
db31e3a1 732 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8efcd486
BL
733 SOF_SSP_PORT_CODEC(0) |
734 SOF_SSP_PORT_AMP(1)),
db31e3a1 735 },
1f583cbd 736 {
dbda8647 737 .name = "tgl_rt5682_def",
ad83b1ad 738 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8efcd486
BL
739 SOF_SSP_PORT_CODEC(0) |
740 SOF_SSP_PORT_AMP(1) |
741 SOF_NUM_IDISP_HDMI(4) |
742 SOF_SSP_PORT_BT_OFFLOAD(2) |
743 SOF_BT_OFFLOAD_PRESENT),
ad83b1ad 744 },
2e4dba57 745 {
41333c35 746 .name = "adl_rt5682_def",
2e4dba57 747 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8efcd486
BL
748 SOF_SSP_PORT_CODEC(0) |
749 SOF_SSP_PORT_AMP(1) |
750 SOF_NUM_IDISP_HDMI(4) |
751 SOF_SSP_PORT_BT_OFFLOAD(2) |
752 SOF_BT_OFFLOAD_PRESENT),
2e4dba57
VKG
753 },
754 {
3c561a09 755 .name = "adl_mx98357_rt5682",
2e4dba57 756 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8efcd486
BL
757 SOF_SSP_PORT_CODEC(0) |
758 SOF_SSP_PORT_AMP(2) |
759 SOF_NUM_IDISP_HDMI(4)),
2e4dba57 760 },
f3c37847 761 {
762 .name = "adl_rt5682_c1_h02",
763 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8efcd486 764 SOF_SSP_PORT_CODEC(1) |
f3c37847 765 /* SSP 0 and SSP 2 are used for HDMI IN */
8efcd486 766 SOF_SSP_MASK_HDMI_CAPTURE(0x5)),
f3c37847 767 },
26d9726f
TC
768 {
769 .name = "rpl_mx98357_rt5682",
770 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8efcd486
BL
771 SOF_SSP_PORT_CODEC(0) |
772 SOF_SSP_PORT_AMP(2) |
773 SOF_NUM_IDISP_HDMI(4)),
26d9726f 774 },
a7fe7e24 775 {
19ec6b2e 776 .name = "rpl_rt5682_def",
5dc51e50 777 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8efcd486
BL
778 SOF_SSP_PORT_CODEC(0) |
779 SOF_SSP_PORT_AMP(1) |
780 SOF_NUM_IDISP_HDMI(4) |
781 SOF_SSP_PORT_BT_OFFLOAD(2) |
782 SOF_BT_OFFLOAD_PRESENT),
5dc51e50 783 },
14b7ed66
B
784 {
785 .name = "rpl_rt5682_c1_h02",
786 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8efcd486 787 SOF_SSP_PORT_CODEC(1) |
14b7ed66 788 /* SSP 0 and SSP 2 are used for HDMI IN */
8efcd486 789 SOF_SSP_MASK_HDMI_CAPTURE(0x5)),
14b7ed66 790 },
1f6645b1
YZ
791 {
792 .name = "mtl_mx98357_rt5682",
793 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8efcd486
BL
794 SOF_SSP_PORT_CODEC(0) |
795 SOF_SSP_PORT_AMP(1) |
8efcd486
BL
796 SOF_SSP_PORT_BT_OFFLOAD(2) |
797 SOF_BT_OFFLOAD_PRESENT),
1f6645b1 798 },
7e43b75d
D
799 {
800 .name = "mtl_mx98360_rt5682",
801 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8efcd486 802 SOF_SSP_PORT_CODEC(0) |
b497654f 803 SOF_SSP_PORT_AMP(1)),
7e43b75d 804 },
b20c8137 805 {
922edacf 806 .name = "mtl_rt5682_def",
a55ea47b 807 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8efcd486
BL
808 SOF_SSP_PORT_CODEC(2) |
809 SOF_SSP_PORT_AMP(0) |
8efcd486
BL
810 SOF_SSP_PORT_BT_OFFLOAD(1) |
811 SOF_BT_OFFLOAD_PRESENT),
a55ea47b 812 },
6605f0ca
SN
813 { }
814};
a75e5cdf 815MODULE_DEVICE_TABLE(platform, board_ids);
6605f0ca 816
f70abd75
B
817static struct platform_driver sof_audio = {
818 .probe = sof_audio_probe,
819 .driver = {
820 .name = "sof_rt5682",
821 .pm = &snd_soc_pm_ops,
822 },
6605f0ca 823 .id_table = board_ids,
f70abd75
B
824};
825module_platform_driver(sof_audio)
826
827/* Module information */
828MODULE_DESCRIPTION("SOF Audio Machine driver");
829MODULE_AUTHOR("Bard Liao <bard.liao@intel.com>");
830MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
aa6cc97c 831MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
f316c9d9 832MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
f70abd75 833MODULE_LICENSE("GPL v2");
89cadbd8 834MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
9c5046e4 835MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
e1d5e133 836MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);