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