1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * bytcr_rt5651.c - ASoc Machine driver for Intel Byt CR platform
4 * (derived from bytcr_rt5640.c)
5 *
6 * Copyright (C) 2015 Intel Corp
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 */
11
12#include <linux/init.h>
13#include <linux/i2c.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/property.h>
17#include <linux/acpi.h>
18#include <linux/clk.h>
19#include <linux/device.h>
20#include <linux/dmi.h>
21#include <linux/input.h>
22#include <linux/gpio/consumer.h>
23#include <linux/gpio/machine.h>
24#include <linux/slab.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/soc.h>
28#include <sound/jack.h>
29#include <sound/soc-acpi.h>
30#include "../../codecs/rt5651.h"
31#include "../atom/sst-atom-controls.h"
32#include "../common/soc-intel-quirks.h"
33
34enum {
35 BYT_RT5651_DMIC_MAP,
36 BYT_RT5651_IN1_MAP,
37 BYT_RT5651_IN2_MAP,
38 BYT_RT5651_IN1_IN2_MAP,
39};
40
41enum {
42 BYT_RT5651_JD_NULL = (RT5651_JD_NULL << 4),
43 BYT_RT5651_JD1_1 = (RT5651_JD1_1 << 4),
44 BYT_RT5651_JD1_2 = (RT5651_JD1_2 << 4),
45 BYT_RT5651_JD2 = (RT5651_JD2 << 4),
46};
47
48enum {
49 BYT_RT5651_OVCD_TH_600UA = (6 << 8),
50 BYT_RT5651_OVCD_TH_1500UA = (15 << 8),
51 BYT_RT5651_OVCD_TH_2000UA = (20 << 8),
52};
53
54enum {
55 BYT_RT5651_OVCD_SF_0P5 = (RT5651_OVCD_SF_0P5 << 13),
56 BYT_RT5651_OVCD_SF_0P75 = (RT5651_OVCD_SF_0P75 << 13),
57 BYT_RT5651_OVCD_SF_1P0 = (RT5651_OVCD_SF_1P0 << 13),
58 BYT_RT5651_OVCD_SF_1P5 = (RT5651_OVCD_SF_1P5 << 13),
59};
60
61#define BYT_RT5651_MAP_MASK GENMASK(3, 0)
62#define BYT_RT5651_MAP(quirk) ((quirk) & BYT_RT5651_MAP_MASK)
63#define BYT_RT5651_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4)
64#define BYT_RT5651_OVCD_TH(quirk) (((quirk) & GENMASK(12, 8)) >> 8)
65#define BYT_RT5651_OVCD_SF(quirk) (((quirk) & GENMASK(14, 13)) >> 13)
66#define BYT_RT5651_DMIC_EN BIT(16)
67#define BYT_RT5651_MCLK_EN BIT(17)
68#define BYT_RT5651_MCLK_25MHZ BIT(18)
69#define BYT_RT5651_SSP2_AIF2 BIT(19) /* default is using AIF1 */
70#define BYT_RT5651_SSP0_AIF1 BIT(20)
71#define BYT_RT5651_SSP0_AIF2 BIT(21)
72#define BYT_RT5651_HP_LR_SWAPPED BIT(22)
73#define BYT_RT5651_MONO_SPEAKER BIT(23)
74#define BYT_RT5651_JD_NOT_INV BIT(24)
75
76#define BYT_RT5651_DEFAULT_QUIRKS (BYT_RT5651_MCLK_EN | \
77 BYT_RT5651_JD1_1 | \
78 BYT_RT5651_OVCD_TH_2000UA | \
79 BYT_RT5651_OVCD_SF_0P75)
80
81/* jack-detect-source + inv + dmic-en + ovcd-th + -sf + terminating entry */
82#define MAX_NO_PROPS 6
83
84struct byt_rt5651_private {
85 struct clk *mclk;
86 struct gpio_desc *ext_amp_gpio;
87 struct gpio_desc *hp_detect;
88 struct snd_soc_jack jack;
89 struct device *codec_dev;
90};
91
92static const struct acpi_gpio_mapping *byt_rt5651_gpios;
93
94/* Default: jack-detect on JD1_1, internal mic on in2, headsetmic on in3 */
95static unsigned long byt_rt5651_quirk = BYT_RT5651_DEFAULT_QUIRKS |
96 BYT_RT5651_IN2_MAP;
97
98static int quirk_override = -1;
99module_param_named(quirk, quirk_override, int, 0444);
100MODULE_PARM_DESC(quirk, "Board-specific quirk override");
101
102static void log_quirks(struct device *dev)
103{
104 int map;
105
106 map = BYT_RT5651_MAP(byt_rt5651_quirk);
107 switch (map) {
108 case BYT_RT5651_DMIC_MAP:
109 dev_info(dev, "quirk DMIC_MAP enabled");
110 break;
111 case BYT_RT5651_IN1_MAP:
112 dev_info(dev, "quirk IN1_MAP enabled");
113 break;
114 case BYT_RT5651_IN2_MAP:
115 dev_info(dev, "quirk IN2_MAP enabled");
116 break;
117 case BYT_RT5651_IN1_IN2_MAP:
118 dev_info(dev, "quirk IN1_IN2_MAP enabled");
119 break;
120 default:
121 dev_warn_once(dev, "quirk sets invalid input map: 0x%x, default to DMIC_MAP\n", map);
122 byt_rt5651_quirk &= ~BYT_RT5651_MAP_MASK;
123 byt_rt5651_quirk |= BYT_RT5651_DMIC_MAP;
124 break;
125 }
126
127 if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) {
128 dev_info(dev, "quirk realtek,jack-detect-source %ld\n",
129 BYT_RT5651_JDSRC(byt_rt5651_quirk));
130 dev_info(dev, "quirk realtek,over-current-threshold-microamp %ld\n",
131 BYT_RT5651_OVCD_TH(byt_rt5651_quirk) * 100);
132 dev_info(dev, "quirk realtek,over-current-scale-factor %ld\n",
133 BYT_RT5651_OVCD_SF(byt_rt5651_quirk));
134 }
135 if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
136 dev_info(dev, "quirk DMIC enabled");
137 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
138 dev_info(dev, "quirk MCLK_EN enabled");
139 if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
140 dev_info(dev, "quirk MCLK_25MHZ enabled");
141 if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2)
142 dev_info(dev, "quirk SSP2_AIF2 enabled\n");
143 if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1)
144 dev_info(dev, "quirk SSP0_AIF1 enabled\n");
145 if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)
146 dev_info(dev, "quirk SSP0_AIF2 enabled\n");
147 if (byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER)
148 dev_info(dev, "quirk MONO_SPEAKER enabled\n");
149 if (byt_rt5651_quirk & BYT_RT5651_JD_NOT_INV)
150 dev_info(dev, "quirk JD_NOT_INV enabled\n");
151}
152
153#define BYT_CODEC_DAI1 "rt5651-aif1"
154#define BYT_CODEC_DAI2 "rt5651-aif2"
155
156static int byt_rt5651_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
157 int rate, int bclk_ratio)
158{
159 int clk_id, clk_freq, ret;
160
161 /* Configure the PLL before selecting it */
162 if (!(byt_rt5651_quirk & BYT_RT5651_MCLK_EN)) {
163 clk_id = RT5651_PLL1_S_BCLK1;
164 clk_freq = rate * bclk_ratio;
165 } else {
166 clk_id = RT5651_PLL1_S_MCLK;
167 if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
168 clk_freq = 25000000;
169 else
170 clk_freq = 19200000;
171 }
172 ret = snd_soc_dai_set_pll(dai: codec_dai, pll_id: 0, source: clk_id, freq_in: clk_freq, freq_out: rate * 512);
173 if (ret < 0) {
174 dev_err(codec_dai->component->dev, "can't set pll: %d\n", ret);
175 return ret;
176 }
177
178 ret = snd_soc_dai_set_sysclk(dai: codec_dai, clk_id: RT5651_SCLK_S_PLL1,
179 freq: rate * 512, SND_SOC_CLOCK_IN);
180 if (ret < 0) {
181 dev_err(codec_dai->component->dev, "can't set clock %d\n", ret);
182 return ret;
183 }
184
185 return 0;
186}
187
188static int platform_clock_control(struct snd_soc_dapm_widget *w,
189 struct snd_kcontrol *k, int event)
190{
191 struct snd_soc_card *card = snd_soc_dapm_to_card(dapm: w->dapm);
192 struct snd_soc_dai *codec_dai;
193 struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
194 int ret;
195
196 codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
197 if (!codec_dai)
198 codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
199 if (!codec_dai) {
200 dev_err(card->dev,
201 "Codec dai not found; Unable to set platform clock\n");
202 return -EIO;
203 }
204
205 if (SND_SOC_DAPM_EVENT_ON(event)) {
206 ret = clk_prepare_enable(clk: priv->mclk);
207 if (ret < 0) {
208 dev_err(card->dev, "could not configure MCLK state");
209 return ret;
210 }
211 ret = byt_rt5651_prepare_and_enable_pll1(codec_dai, rate: 48000, bclk_ratio: 50);
212 } else {
213 /*
214 * Set codec clock source to internal clock before
215 * turning off the platform clock. Codec needs clock
216 * for Jack detection and button press
217 */
218 ret = snd_soc_dai_set_sysclk(dai: codec_dai, clk_id: RT5651_SCLK_S_RCCLK,
219 freq: 48000 * 512,
220 SND_SOC_CLOCK_IN);
221 if (!ret)
222 clk_disable_unprepare(clk: priv->mclk);
223 }
224
225 if (ret < 0) {
226 dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
227 return ret;
228 }
229
230 return 0;
231}
232
233static int rt5651_ext_amp_power_event(struct snd_soc_dapm_widget *w,
234 struct snd_kcontrol *kcontrol, int event)
235{
236 struct snd_soc_card *card = snd_soc_dapm_to_card(dapm: w->dapm);
237 struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
238
239 if (SND_SOC_DAPM_EVENT_ON(event))
240 gpiod_set_value_cansleep(desc: priv->ext_amp_gpio, value: 1);
241 else
242 gpiod_set_value_cansleep(desc: priv->ext_amp_gpio, value: 0);
243
244 return 0;
245}
246
247static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = {
248 SND_SOC_DAPM_HP("Headphone", NULL),
249 SND_SOC_DAPM_MIC("Headset Mic", NULL),
250 SND_SOC_DAPM_MIC("Internal Mic", NULL),
251 SND_SOC_DAPM_SPK("Speaker", NULL),
252 SND_SOC_DAPM_LINE("Line In", NULL),
253 SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
254 platform_clock_control, SND_SOC_DAPM_PRE_PMU |
255 SND_SOC_DAPM_POST_PMD),
256 SND_SOC_DAPM_SUPPLY("Ext Amp Power", SND_SOC_NOPM, 0, 0,
257 rt5651_ext_amp_power_event,
258 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
259};
260
261static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
262 {"Headphone", NULL, "Platform Clock"},
263 {"Headset Mic", NULL, "Platform Clock"},
264 {"Internal Mic", NULL, "Platform Clock"},
265 {"Speaker", NULL, "Platform Clock"},
266 {"Speaker", NULL, "Ext Amp Power"},
267 {"Line In", NULL, "Platform Clock"},
268
269 {"Headset Mic", NULL, "micbias1"}, /* lowercase for rt5651 */
270 {"Headphone", NULL, "HPOL"},
271 {"Headphone", NULL, "HPOR"},
272 {"Speaker", NULL, "LOUTL"},
273 {"Speaker", NULL, "LOUTR"},
274 {"IN2P", NULL, "Line In"},
275 {"IN2N", NULL, "Line In"},
276
277};
278
279static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic_map[] = {
280 {"DMIC L1", NULL, "Internal Mic"},
281 {"DMIC R1", NULL, "Internal Mic"},
282 {"IN2P", NULL, "Headset Mic"},
283};
284
285static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_map[] = {
286 {"Internal Mic", NULL, "micbias1"},
287 {"IN1P", NULL, "Internal Mic"},
288 {"IN3P", NULL, "Headset Mic"},
289};
290
291static const struct snd_soc_dapm_route byt_rt5651_intmic_in2_map[] = {
292 {"Internal Mic", NULL, "micbias1"},
293 {"IN2P", NULL, "Internal Mic"},
294 {"IN3P", NULL, "Headset Mic"},
295};
296
297static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_in2_map[] = {
298 {"Internal Mic", NULL, "micbias1"},
299 {"IN1P", NULL, "Internal Mic"},
300 {"IN2P", NULL, "Internal Mic"},
301 {"IN3P", NULL, "Headset Mic"},
302};
303
304static const struct snd_soc_dapm_route byt_rt5651_ssp0_aif1_map[] = {
305 {"ssp0 Tx", NULL, "modem_out"},
306 {"modem_in", NULL, "ssp0 Rx"},
307
308 {"AIF1 Playback", NULL, "ssp0 Tx"},
309 {"ssp0 Rx", NULL, "AIF1 Capture"},
310};
311
312static const struct snd_soc_dapm_route byt_rt5651_ssp0_aif2_map[] = {
313 {"ssp0 Tx", NULL, "modem_out"},
314 {"modem_in", NULL, "ssp0 Rx"},
315
316 {"AIF2 Playback", NULL, "ssp0 Tx"},
317 {"ssp0 Rx", NULL, "AIF2 Capture"},
318};
319
320static const struct snd_soc_dapm_route byt_rt5651_ssp2_aif1_map[] = {
321 {"ssp2 Tx", NULL, "codec_out0"},
322 {"ssp2 Tx", NULL, "codec_out1"},
323 {"codec_in0", NULL, "ssp2 Rx"},
324 {"codec_in1", NULL, "ssp2 Rx"},
325
326 {"AIF1 Playback", NULL, "ssp2 Tx"},
327 {"ssp2 Rx", NULL, "AIF1 Capture"},
328};
329
330static const struct snd_soc_dapm_route byt_rt5651_ssp2_aif2_map[] = {
331 {"ssp2 Tx", NULL, "codec_out0"},
332 {"ssp2 Tx", NULL, "codec_out1"},
333 {"codec_in0", NULL, "ssp2 Rx"},
334 {"codec_in1", NULL, "ssp2 Rx"},
335
336 {"AIF2 Playback", NULL, "ssp2 Tx"},
337 {"ssp2 Rx", NULL, "AIF2 Capture"},
338};
339
340static const struct snd_kcontrol_new byt_rt5651_controls[] = {
341 SOC_DAPM_PIN_SWITCH("Headphone"),
342 SOC_DAPM_PIN_SWITCH("Headset Mic"),
343 SOC_DAPM_PIN_SWITCH("Internal Mic"),
344 SOC_DAPM_PIN_SWITCH("Speaker"),
345 SOC_DAPM_PIN_SWITCH("Line In"),
346};
347
348static struct snd_soc_jack_pin bytcr_jack_pins[] = {
349 {
350 .pin = "Headphone",
351 .mask = SND_JACK_HEADPHONE,
352 },
353 {
354 .pin = "Headset Mic",
355 .mask = SND_JACK_MICROPHONE,
356 },
357};
358
359static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
360 struct snd_pcm_hw_params *params)
361{
362 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
363 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
364 snd_pcm_format_t format = params_format(p: params);
365 int rate = params_rate(p: params);
366 int bclk_ratio;
367
368 if (format == SNDRV_PCM_FORMAT_S16_LE)
369 bclk_ratio = 32;
370 else
371 bclk_ratio = 50;
372
373 return byt_rt5651_prepare_and_enable_pll1(codec_dai, rate, bclk_ratio);
374}
375
376static const struct acpi_gpio_params pov_p1006w_hp_detect = { 1, 0, false };
377static const struct acpi_gpio_params pov_p1006w_ext_amp_en = { 2, 0, true };
378
379static const struct acpi_gpio_mapping byt_rt5651_pov_p1006w_gpios[] = {
380 { "hp-detect-gpios", &pov_p1006w_hp_detect, 1, },
381 { "ext-amp-enable-gpios", &pov_p1006w_ext_amp_en, 1, },
382 { },
383};
384
385static int byt_rt5651_pov_p1006w_quirk_cb(const struct dmi_system_id *id)
386{
387 byt_rt5651_quirk = (unsigned long)id->driver_data;
388 byt_rt5651_gpios = byt_rt5651_pov_p1006w_gpios;
389 return 1;
390}
391
392static int byt_rt5651_quirk_cb(const struct dmi_system_id *id)
393{
394 byt_rt5651_quirk = (unsigned long)id->driver_data;
395 return 1;
396}
397
398static const struct dmi_system_id byt_rt5651_quirk_table[] = {
399 {
400 /* Chuwi Hi8 Pro (CWI513) */
401 .callback = byt_rt5651_quirk_cb,
402 .matches = {
403 DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
404 DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"),
405 },
406 .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
407 BYT_RT5651_IN2_MAP |
408 BYT_RT5651_HP_LR_SWAPPED |
409 BYT_RT5651_MONO_SPEAKER),
410 },
411 {
412 /* Chuwi Vi8 Plus (CWI519) */
413 .callback = byt_rt5651_quirk_cb,
414 .matches = {
415 DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
416 DMI_MATCH(DMI_PRODUCT_NAME, "D2D3_Vi8A1"),
417 },
418 .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
419 BYT_RT5651_IN2_MAP |
420 BYT_RT5651_HP_LR_SWAPPED |
421 BYT_RT5651_MONO_SPEAKER),
422 },
423 {
424 /* Complet Electro Serv MY8307 */
425 .callback = byt_rt5651_quirk_cb,
426 .matches = {
427 DMI_MATCH(DMI_SYS_VENDOR, "Complet Electro Serv"),
428 DMI_MATCH(DMI_PRODUCT_NAME, "MY8307"),
429 },
430 .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
431 BYT_RT5651_IN2_MAP |
432 BYT_RT5651_MONO_SPEAKER |
433 BYT_RT5651_JD_NOT_INV),
434 },
435 {
436 /* I.T.Works TW701, Ployer Momo7w and Trekstor ST70416-6
437 * (these all use the same mainboard) */
438 .callback = byt_rt5651_quirk_cb,
439 .matches = {
440 DMI_MATCH(DMI_BIOS_VENDOR, "INSYDE Corp."),
441 /* Partial match for all of itWORKS.G.WI71C.JGBMRBA,
442 * TREK.G.WI71C.JGBMRBA0x and MOMO.G.WI71C.MABMRBA02 */
443 DMI_MATCH(DMI_BIOS_VERSION, ".G.WI71C."),
444 },
445 .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
446 BYT_RT5651_IN2_MAP |
447 BYT_RT5651_SSP0_AIF1 |
448 BYT_RT5651_MONO_SPEAKER),
449 },
450 {
451 /* Jumper EZpad 7 */
452 .callback = byt_rt5651_quirk_cb,
453 .matches = {
454 DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
455 DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
456 /* Jumper12x.WJ2012.bsBKRCP05 with the version dropped */
457 DMI_MATCH(DMI_BIOS_VERSION, "Jumper12x.WJ2012.bsBKRCP"),
458 },
459 .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
460 BYT_RT5651_IN2_MAP |
461 BYT_RT5651_JD_NOT_INV),
462 },
463 {
464 /* KIANO SlimNote 14.2 */
465 .callback = byt_rt5651_quirk_cb,
466 .matches = {
467 DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
468 DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
469 },
470 .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
471 BYT_RT5651_IN1_IN2_MAP),
472 },
473 {
474 /* Minnowboard Max B3 */
475 .callback = byt_rt5651_quirk_cb,
476 .matches = {
477 DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
478 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
479 },
480 .driver_data = (void *)(BYT_RT5651_IN1_MAP),
481 },
482 {
483 /* Minnowboard Turbot */
484 .callback = byt_rt5651_quirk_cb,
485 .matches = {
486 DMI_MATCH(DMI_SYS_VENDOR, "ADI"),
487 DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Turbot"),
488 },
489 .driver_data = (void *)(BYT_RT5651_MCLK_EN |
490 BYT_RT5651_IN1_MAP),
491 },
492 {
493 /* Point of View mobii wintab p1006w (v1.0) */
494 .callback = byt_rt5651_pov_p1006w_quirk_cb,
495 .matches = {
496 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),
497 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
498 /* Note 105b is Foxcon's USB/PCI vendor id */
499 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "105B"),
500 DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"),
501 },
502 .driver_data = (void *)(BYT_RT5651_DMIC_MAP |
503 BYT_RT5651_OVCD_TH_2000UA |
504 BYT_RT5651_OVCD_SF_0P75 |
505 BYT_RT5651_DMIC_EN |
506 BYT_RT5651_MCLK_EN |
507 BYT_RT5651_SSP0_AIF1),
508 },
509 {
510 /* VIOS LTH17 */
511 .callback = byt_rt5651_quirk_cb,
512 .matches = {
513 DMI_MATCH(DMI_SYS_VENDOR, "VIOS"),
514 DMI_MATCH(DMI_PRODUCT_NAME, "LTH17"),
515 },
516 .driver_data = (void *)(BYT_RT5651_IN1_IN2_MAP |
517 BYT_RT5651_JD1_1 |
518 BYT_RT5651_OVCD_TH_2000UA |
519 BYT_RT5651_OVCD_SF_1P0 |
520 BYT_RT5651_MCLK_EN),
521 },
522 {
523 /* Yours Y8W81 (and others using the same mainboard) */
524 .callback = byt_rt5651_quirk_cb,
525 .matches = {
526 DMI_MATCH(DMI_BIOS_VENDOR, "INSYDE Corp."),
527 /* Partial match for all devs with a W86C mainboard */
528 DMI_MATCH(DMI_BIOS_VERSION, ".F.W86C."),
529 },
530 .driver_data = (void *)(BYT_RT5651_DEFAULT_QUIRKS |
531 BYT_RT5651_IN2_MAP |
532 BYT_RT5651_SSP0_AIF1 |
533 BYT_RT5651_MONO_SPEAKER),
534 },
535 {}
536};
537
538/*
539 * Note this MUST be called before snd_soc_register_card(), so that the props
540 * are in place before the codec component driver's probe function parses them.
541 */
542static int byt_rt5651_add_codec_device_props(struct device *i2c_dev,
543 struct byt_rt5651_private *priv)
544{
545 struct property_entry props[MAX_NO_PROPS] = {};
546 struct fwnode_handle *fwnode;
547 int cnt = 0;
548 int ret;
549
550 props[cnt++] = PROPERTY_ENTRY_U32("realtek,jack-detect-source",
551 BYT_RT5651_JDSRC(byt_rt5651_quirk));
552
553 props[cnt++] = PROPERTY_ENTRY_U32("realtek,over-current-threshold-microamp",
554 BYT_RT5651_OVCD_TH(byt_rt5651_quirk) * 100);
555
556 props[cnt++] = PROPERTY_ENTRY_U32("realtek,over-current-scale-factor",
557 BYT_RT5651_OVCD_SF(byt_rt5651_quirk));
558
559 if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
560 props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,dmic-en");
561
562 if (byt_rt5651_quirk & BYT_RT5651_JD_NOT_INV)
563 props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
564
565 fwnode = fwnode_create_software_node(properties: props, NULL);
566 if (IS_ERR(ptr: fwnode)) {
567 /* put_device(i2c_dev) is handled in caller */
568 return PTR_ERR(ptr: fwnode);
569 }
570
571 ret = device_add_software_node(dev: i2c_dev, node: to_software_node(fwnode));
572
573 fwnode_handle_put(fwnode);
574
575 return ret;
576}
577
578static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
579{
580 struct snd_soc_card *card = runtime->card;
581 struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
582 struct snd_soc_component *codec = snd_soc_rtd_to_codec(runtime, 0)->component;
583 struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
584 const struct snd_soc_dapm_route *custom_map;
585 int num_routes;
586 int report;
587 int ret;
588
589 snd_soc_dapm_set_idle_bias(dapm, on: false);
590
591 /* Start with RC clk for jack-detect (we disable MCLK below) */
592 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
593 snd_soc_component_update_bits(component: codec, RT5651_GLB_CLK,
594 RT5651_SCLK_SRC_MASK, RT5651_SCLK_SRC_RCCLK);
595
596 switch (BYT_RT5651_MAP(byt_rt5651_quirk)) {
597 case BYT_RT5651_IN1_MAP:
598 custom_map = byt_rt5651_intmic_in1_map;
599 num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_map);
600 break;
601 case BYT_RT5651_IN2_MAP:
602 custom_map = byt_rt5651_intmic_in2_map;
603 num_routes = ARRAY_SIZE(byt_rt5651_intmic_in2_map);
604 break;
605 case BYT_RT5651_IN1_IN2_MAP:
606 custom_map = byt_rt5651_intmic_in1_in2_map;
607 num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_in2_map);
608 break;
609 default:
610 custom_map = byt_rt5651_intmic_dmic_map;
611 num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic_map);
612 }
613 ret = snd_soc_dapm_add_routes(dapm, route: custom_map, num: num_routes);
614 if (ret)
615 return ret;
616
617 if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) {
618 ret = snd_soc_dapm_add_routes(dapm,
619 route: byt_rt5651_ssp2_aif2_map,
620 ARRAY_SIZE(byt_rt5651_ssp2_aif2_map));
621 } else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) {
622 ret = snd_soc_dapm_add_routes(dapm,
623 route: byt_rt5651_ssp0_aif1_map,
624 ARRAY_SIZE(byt_rt5651_ssp0_aif1_map));
625 } else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2) {
626 ret = snd_soc_dapm_add_routes(dapm,
627 route: byt_rt5651_ssp0_aif2_map,
628 ARRAY_SIZE(byt_rt5651_ssp0_aif2_map));
629 } else {
630 ret = snd_soc_dapm_add_routes(dapm,
631 route: byt_rt5651_ssp2_aif1_map,
632 ARRAY_SIZE(byt_rt5651_ssp2_aif1_map));
633 }
634 if (ret)
635 return ret;
636
637 ret = snd_soc_add_card_controls(soc_card: card, controls: byt_rt5651_controls,
638 ARRAY_SIZE(byt_rt5651_controls));
639 if (ret) {
640 dev_err(card->dev, "unable to add card controls\n");
641 return ret;
642 }
643
644 /*
645 * The firmware might enable the clock at boot (this information
646 * may or may not be reflected in the enable clock register).
647 * To change the rate we must disable the clock first to cover
648 * these cases. Due to common clock framework restrictions that
649 * do not allow to disable a clock that has not been enabled,
650 * we need to enable the clock first.
651 */
652 ret = clk_prepare_enable(clk: priv->mclk);
653 if (!ret)
654 clk_disable_unprepare(clk: priv->mclk);
655
656 if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
657 ret = clk_set_rate(clk: priv->mclk, rate: 25000000);
658 else
659 ret = clk_set_rate(clk: priv->mclk, rate: 19200000);
660
661 if (ret)
662 dev_err(card->dev, "unable to set MCLK rate\n");
663
664 report = 0;
665 if (BYT_RT5651_JDSRC(byt_rt5651_quirk))
666 report = SND_JACK_HEADSET | SND_JACK_BTN_0;
667 else if (priv->hp_detect)
668 report = SND_JACK_HEADSET;
669
670 if (report) {
671 ret = snd_soc_card_jack_new_pins(card: runtime->card, id: "Headset",
672 type: report, jack: &priv->jack,
673 pins: bytcr_jack_pins,
674 ARRAY_SIZE(bytcr_jack_pins));
675 if (ret) {
676 dev_err(runtime->dev, "jack creation failed %d\n", ret);
677 return ret;
678 }
679
680 if (report & SND_JACK_BTN_0)
681 snd_jack_set_key(jack: priv->jack.jack, type: SND_JACK_BTN_0,
682 KEY_PLAYPAUSE);
683
684 ret = snd_soc_component_set_jack(component: codec, jack: &priv->jack,
685 data: priv->hp_detect);
686 if (ret)
687 return ret;
688 }
689
690 return 0;
691}
692
693static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
694 struct snd_pcm_hw_params *params)
695{
696 struct snd_interval *rate = hw_param_interval(params,
697 SNDRV_PCM_HW_PARAM_RATE);
698 struct snd_interval *channels = hw_param_interval(params,
699 SNDRV_PCM_HW_PARAM_CHANNELS);
700 int ret, bits;
701
702 /* The DSP will convert the FE rate to 48k, stereo */
703 rate->min = rate->max = 48000;
704 channels->min = channels->max = 2;
705
706 if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
707 (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
708 /* set SSP0 to 16-bit */
709 params_set_format(p: params, SNDRV_PCM_FORMAT_S16_LE);
710 bits = 16;
711 } else {
712 /* set SSP2 to 24-bit */
713 params_set_format(p: params, SNDRV_PCM_FORMAT_S24_LE);
714 bits = 24;
715 }
716
717 /*
718 * Default mode for SSP configuration is TDM 4 slot, override config
719 * with explicit setting to I2S 2ch. The word length is set with
720 * dai_set_tdm_slot() since there is no other API exposed
721 */
722 ret = snd_soc_dai_set_fmt(snd_soc_rtd_to_cpu(rtd, 0),
723 SND_SOC_DAIFMT_I2S |
724 SND_SOC_DAIFMT_NB_NF |
725 SND_SOC_DAIFMT_BP_FP
726 );
727
728 if (ret < 0) {
729 dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
730 return ret;
731 }
732
733 ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_cpu(rtd, 0), tx_mask: 0x3, rx_mask: 0x3, slots: 2, slot_width: bits);
734 if (ret < 0) {
735 dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
736 return ret;
737 }
738
739 return 0;
740}
741
742static const unsigned int rates_48000[] = {
743 48000,
744};
745
746static const struct snd_pcm_hw_constraint_list constraints_48000 = {
747 .count = ARRAY_SIZE(rates_48000),
748 .list = rates_48000,
749};
750
751static int byt_rt5651_aif1_startup(struct snd_pcm_substream *substream)
752{
753 return snd_pcm_hw_constraint_list(runtime: substream->runtime, cond: 0,
754 SNDRV_PCM_HW_PARAM_RATE,
755 l: &constraints_48000);
756}
757
758static const struct snd_soc_ops byt_rt5651_aif1_ops = {
759 .startup = byt_rt5651_aif1_startup,
760};
761
762static const struct snd_soc_ops byt_rt5651_be_ssp2_ops = {
763 .hw_params = byt_rt5651_aif1_hw_params,
764};
765
766SND_SOC_DAILINK_DEF(dummy,
767 DAILINK_COMP_ARRAY(COMP_DUMMY()));
768
769SND_SOC_DAILINK_DEF(media,
770 DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
771
772SND_SOC_DAILINK_DEF(deepbuffer,
773 DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
774
775SND_SOC_DAILINK_DEF(ssp2_port,
776 DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
777SND_SOC_DAILINK_DEF(ssp2_codec,
778 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5651:00", "rt5651-aif1")));
779
780SND_SOC_DAILINK_DEF(platform,
781 DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
782
783static struct snd_soc_dai_link byt_rt5651_dais[] = {
784 [MERR_DPCM_AUDIO] = {
785 .name = "Audio Port",
786 .stream_name = "Audio",
787 .nonatomic = true,
788 .dynamic = 1,
789 .ops = &byt_rt5651_aif1_ops,
790 SND_SOC_DAILINK_REG(media, dummy, platform),
791 },
792 [MERR_DPCM_DEEP_BUFFER] = {
793 .name = "Deep-Buffer Audio Port",
794 .stream_name = "Deep-Buffer Audio",
795 .nonatomic = true,
796 .dynamic = 1,
797 .playback_only = 1,
798 .ops = &byt_rt5651_aif1_ops,
799 SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
800 },
801 /* CODEC<->CODEC link */
802 /* back ends */
803 {
804 .name = "SSP2-Codec",
805 .id = 0,
806 .no_pcm = 1,
807 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
808 | SND_SOC_DAIFMT_CBC_CFC,
809 .be_hw_params_fixup = byt_rt5651_codec_fixup,
810 .init = byt_rt5651_init,
811 .ops = &byt_rt5651_be_ssp2_ops,
812 SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
813 },
814};
815
816/* SoC card */
817static char byt_rt5651_codec_name[SND_ACPI_I2C_ID_LEN];
818#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
819static char byt_rt5651_long_name[50]; /* = "bytcr-rt5651-*-spk-*-mic[-swapped-hp]" */
820#endif
821static char byt_rt5651_components[50]; /* = "cfg-spk:* cfg-mic:*" */
822
823static int byt_rt5651_suspend(struct snd_soc_card *card)
824{
825 struct snd_soc_component *component;
826
827 if (!BYT_RT5651_JDSRC(byt_rt5651_quirk))
828 return 0;
829
830 for_each_card_components(card, component) {
831 if (!strcmp(component->name, byt_rt5651_codec_name)) {
832 dev_dbg(component->dev, "disabling jack detect before suspend\n");
833 snd_soc_component_set_jack(component, NULL, NULL);
834 break;
835 }
836 }
837
838 return 0;
839}
840
841static int byt_rt5651_resume(struct snd_soc_card *card)
842{
843 struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
844 struct snd_soc_component *component;
845
846 if (!BYT_RT5651_JDSRC(byt_rt5651_quirk))
847 return 0;
848
849 for_each_card_components(card, component) {
850 if (!strcmp(component->name, byt_rt5651_codec_name)) {
851 dev_dbg(component->dev, "re-enabling jack detect after resume\n");
852 snd_soc_component_set_jack(component, jack: &priv->jack,
853 data: priv->hp_detect);
854 break;
855 }
856 }
857
858 return 0;
859}
860
861/* use space before codec name to simplify card ID, and simplify driver name */
862#define SOF_CARD_NAME "bytcht rt5651" /* card name will be 'sof-bytcht rt5651' */
863#define SOF_DRIVER_NAME "SOF"
864
865#define CARD_NAME "bytcr-rt5651"
866#define DRIVER_NAME NULL /* card name will be used for driver name */
867
868static struct snd_soc_card byt_rt5651_card = {
869 .name = CARD_NAME,
870 .driver_name = DRIVER_NAME,
871 .owner = THIS_MODULE,
872 .dai_link = byt_rt5651_dais,
873 .num_links = ARRAY_SIZE(byt_rt5651_dais),
874 .dapm_widgets = byt_rt5651_widgets,
875 .num_dapm_widgets = ARRAY_SIZE(byt_rt5651_widgets),
876 .dapm_routes = byt_rt5651_audio_map,
877 .num_dapm_routes = ARRAY_SIZE(byt_rt5651_audio_map),
878 .fully_routed = true,
879 .suspend_pre = byt_rt5651_suspend,
880 .resume_post = byt_rt5651_resume,
881};
882
883static const struct acpi_gpio_params ext_amp_enable_gpios = { 0, 0, false };
884
885static const struct acpi_gpio_mapping cht_rt5651_gpios[] = {
886 /*
887 * Some boards have I2cSerialBusV2, GpioIo, GpioInt as ACPI resources,
888 * other boards may have I2cSerialBusV2, GpioInt, GpioIo instead.
889 * We want the GpioIo one for the ext-amp-enable-gpio.
890 */
891 { "ext-amp-enable-gpios", &ext_amp_enable_gpios, 1, ACPI_GPIO_QUIRK_ONLY_GPIOIO },
892 { },
893};
894
895struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */
896 u64 aif_value; /* 1: AIF1, 2: AIF2 */
897 u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */
898};
899
900static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
901{
902 struct device *dev = &pdev->dev;
903 static const char * const mic_name[] = { "dmic", "in1", "in2", "in12" };
904 struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
905 struct byt_rt5651_private *priv;
906 const char *platform_name;
907 struct acpi_device *adev;
908 struct device *codec_dev;
909 bool sof_parent;
910 bool is_bytcr = false;
911 int ret_val = 0;
912 int dai_index = 0;
913 int i;
914
915 priv = devm_kzalloc(dev, size: sizeof(*priv), GFP_KERNEL);
916 if (!priv)
917 return -ENOMEM;
918
919 /* register the soc card */
920 byt_rt5651_card.dev = dev;
921 snd_soc_card_set_drvdata(card: &byt_rt5651_card, data: priv);
922
923 /* fix index of codec dai */
924 for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) {
925 if (byt_rt5651_dais[i].num_codecs &&
926 !strcmp(byt_rt5651_dais[i].codecs->name,
927 "i2c-10EC5651:00")) {
928 dai_index = i;
929 break;
930 }
931 }
932
933 /* fixup codec name based on HID */
934 adev = acpi_dev_get_first_match_dev(hid: mach->id, NULL, hrv: -1);
935 if (adev) {
936 snprintf(buf: byt_rt5651_codec_name, size: sizeof(byt_rt5651_codec_name),
937 fmt: "i2c-%s", acpi_dev_name(adev));
938 byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name;
939 } else {
940 dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
941 return -ENOENT;
942 }
943
944 codec_dev = acpi_get_first_physical_node(adev);
945 acpi_dev_put(adev);
946 if (!codec_dev)
947 return -EPROBE_DEFER;
948 priv->codec_dev = get_device(dev: codec_dev);
949
950 /*
951 * swap SSP0 if bytcr is detected
952 * (will be overridden if DMI quirk is detected)
953 */
954 if (soc_intel_is_byt()) {
955 if (mach->mach_params.acpi_ipc_irq_index == 0)
956 is_bytcr = true;
957 }
958
959 if (is_bytcr) {
960 /*
961 * Baytrail CR platforms may have CHAN package in BIOS, try
962 * to find relevant routing quirk based as done on Windows
963 * platforms. We have to read the information directly from the
964 * BIOS, at this stage the card is not created and the links
965 * with the codec driver/pdata are non-existent
966 */
967
968 struct acpi_chan_package chan_package = { 0 };
969
970 /* format specified: 2 64-bit integers */
971 struct acpi_buffer format = {sizeof("NN"), "NN"};
972 struct acpi_buffer state = {0, NULL};
973 struct snd_soc_acpi_package_context pkg_ctx;
974 bool pkg_found = false;
975
976 state.length = sizeof(chan_package);
977 state.pointer = &chan_package;
978
979 pkg_ctx.name = "CHAN";
980 pkg_ctx.length = 2;
981 pkg_ctx.format = &format;
982 pkg_ctx.state = &state;
983 pkg_ctx.data_valid = false;
984
985 pkg_found = snd_soc_acpi_find_package_from_hid(hid: mach->id,
986 ctx: &pkg_ctx);
987 if (pkg_found) {
988 if (chan_package.aif_value == 1) {
989 dev_info(dev, "BIOS Routing: AIF1 connected\n");
990 byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF1;
991 } else if (chan_package.aif_value == 2) {
992 dev_info(dev, "BIOS Routing: AIF2 connected\n");
993 byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
994 } else {
995 dev_info(dev, "BIOS Routing isn't valid, ignored\n");
996 pkg_found = false;
997 }
998 }
999
1000 if (!pkg_found) {
1001 /* no BIOS indications, assume SSP0-AIF2 connection */
1002 byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
1003 }
1004 }
1005
1006 /* check quirks before creating card */
1007 dmi_check_system(list: byt_rt5651_quirk_table);
1008
1009 if (quirk_override != -1) {
1010 dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n",
1011 byt_rt5651_quirk, quirk_override);
1012 byt_rt5651_quirk = quirk_override;
1013 }
1014
1015 /* Must be called before register_card, also see declaration comment. */
1016 ret_val = byt_rt5651_add_codec_device_props(i2c_dev: codec_dev, priv);
1017 if (ret_val)
1018 goto err_device;
1019
1020 /* Cherry Trail devices use an external amplifier enable gpio */
1021 if (soc_intel_is_cht() && !byt_rt5651_gpios)
1022 byt_rt5651_gpios = cht_rt5651_gpios;
1023
1024 if (byt_rt5651_gpios) {
1025 devm_acpi_dev_add_driver_gpios(dev: codec_dev, gpios: byt_rt5651_gpios);
1026 priv->ext_amp_gpio = devm_fwnode_gpiod_get(dev, fwnode: codec_dev->fwnode,
1027 con_id: "ext-amp-enable",
1028 flags: GPIOD_OUT_LOW,
1029 label: "speaker-amp");
1030 if (IS_ERR(ptr: priv->ext_amp_gpio)) {
1031 ret_val = PTR_ERR(ptr: priv->ext_amp_gpio);
1032 switch (ret_val) {
1033 case -ENOENT:
1034 priv->ext_amp_gpio = NULL;
1035 break;
1036 default:
1037 dev_err(dev, "Failed to get ext-amp-enable GPIO: %d\n", ret_val);
1038 fallthrough;
1039 case -EPROBE_DEFER:
1040 goto err;
1041 }
1042 }
1043 priv->hp_detect = devm_fwnode_gpiod_get(dev, fwnode: codec_dev->fwnode,
1044 con_id: "hp-detect",
1045 flags: GPIOD_IN,
1046 label: "hp-detect");
1047 if (IS_ERR(ptr: priv->hp_detect)) {
1048 ret_val = PTR_ERR(ptr: priv->hp_detect);
1049 switch (ret_val) {
1050 case -ENOENT:
1051 priv->hp_detect = NULL;
1052 break;
1053 default:
1054 dev_err(dev, "Failed to get hp-detect GPIO: %d\n", ret_val);
1055 fallthrough;
1056 case -EPROBE_DEFER:
1057 goto err;
1058 }
1059 }
1060 }
1061
1062 log_quirks(dev);
1063
1064 if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) ||
1065 (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2))
1066 byt_rt5651_dais[dai_index].codecs->dai_name = "rt5651-aif2";
1067
1068 if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
1069 (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2))
1070 byt_rt5651_dais[dai_index].cpus->dai_name = "ssp0-port";
1071
1072 if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
1073 priv->mclk = devm_clk_get_optional(dev, id: "pmc_plt_clk_3");
1074 if (IS_ERR(ptr: priv->mclk)) {
1075 ret_val = dev_err_probe(dev, err: PTR_ERR(ptr: priv->mclk),
1076 fmt: "Failed to get MCLK from pmc_plt_clk_3\n");
1077 goto err;
1078 }
1079 /*
1080 * Fall back to bit clock usage when clock is not
1081 * available likely due to missing dependencies.
1082 */
1083 if (!priv->mclk)
1084 byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN;
1085 }
1086
1087 snprintf(buf: byt_rt5651_components, size: sizeof(byt_rt5651_components),
1088 fmt: "cfg-spk:%s cfg-mic:%s%s",
1089 (byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER) ? "1" : "2",
1090 mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)],
1091 (byt_rt5651_quirk & BYT_RT5651_HP_LR_SWAPPED) ?
1092 " cfg-hp:lrswap" : "");
1093 byt_rt5651_card.components = byt_rt5651_components;
1094#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
1095 snprintf(byt_rt5651_long_name, sizeof(byt_rt5651_long_name),
1096 "bytcr-rt5651-%s-spk-%s-mic%s",
1097 (byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER) ?
1098 "mono" : "stereo",
1099 mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)],
1100 (byt_rt5651_quirk & BYT_RT5651_HP_LR_SWAPPED) ?
1101 "-hp-swapped" : "");
1102 byt_rt5651_card.long_name = byt_rt5651_long_name;
1103#endif
1104
1105 /* override platform name, if required */
1106 platform_name = mach->mach_params.platform;
1107
1108 ret_val = snd_soc_fixup_dai_links_platform_name(card: &byt_rt5651_card,
1109 platform_name);
1110 if (ret_val)
1111 goto err;
1112
1113 sof_parent = snd_soc_acpi_sof_parent(dev);
1114
1115 /* set card and driver name */
1116 if (sof_parent) {
1117 byt_rt5651_card.name = SOF_CARD_NAME;
1118 byt_rt5651_card.driver_name = SOF_DRIVER_NAME;
1119 } else {
1120 byt_rt5651_card.name = CARD_NAME;
1121 byt_rt5651_card.driver_name = DRIVER_NAME;
1122 }
1123
1124 /* set pm ops */
1125 if (sof_parent)
1126 dev->driver->pm = &snd_soc_pm_ops;
1127
1128 ret_val = devm_snd_soc_register_card(dev, card: &byt_rt5651_card);
1129 if (ret_val) {
1130 dev_err(dev, "devm_snd_soc_register_card failed %d\n", ret_val);
1131 goto err;
1132 }
1133 platform_set_drvdata(pdev, data: &byt_rt5651_card);
1134 return ret_val;
1135
1136err:
1137 device_remove_software_node(dev: priv->codec_dev);
1138err_device:
1139 put_device(dev: priv->codec_dev);
1140 return ret_val;
1141}
1142
1143static void snd_byt_rt5651_mc_remove(struct platform_device *pdev)
1144{
1145 struct snd_soc_card *card = platform_get_drvdata(pdev);
1146 struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
1147
1148 device_remove_software_node(dev: priv->codec_dev);
1149 put_device(dev: priv->codec_dev);
1150}
1151
1152static struct platform_driver snd_byt_rt5651_mc_driver = {
1153 .driver = {
1154 .name = "bytcr_rt5651",
1155 },
1156 .probe = snd_byt_rt5651_mc_probe,
1157 .remove = snd_byt_rt5651_mc_remove,
1158};
1159
1160module_platform_driver(snd_byt_rt5651_mc_driver);
1161
1162MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver for RT5651");
1163MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
1164MODULE_LICENSE("GPL v2");
1165MODULE_ALIAS("platform:bytcr_rt5651");
1166

source code of linux/sound/soc/intel/boards/bytcr_rt5651.c