Skip to content

Commit c556d20

Browse files
jwrdegoedebroonie
authored andcommitted
ASoC: Intel: bytcr_wm5102: Add BYT_WM5102_OUT_MAP quirk
Some x86 WM5102 designs don't use the SPK pins for speaker output instead they use the HPOUT2L + HPOUT2R for the speakers. Add an BYT_WM5102_OUT_MAP quirk mechanism to allow selecting between 2 output maps, one for the speakers on the SPK output pins and one for the speakers on the HPOUT2 pins. The new HPOUT2 map is enabled by default on CHT because this is used on the Lenovo Yoga Tab 3 YT3-X90 model which is the only Cherry Trail design currently supported. If different CHT designs turn up which need different output maps we can add DMI quirks to select a different map later. The userspace UCM profile also needs to know about this so setup a components string with this info too. While at it also drop the unused "Line Out" route. Acked-by: Pierre-Louis Bossart <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent bce4b01 commit c556d20

File tree

1 file changed

+63
-9
lines changed

1 file changed

+63
-9
lines changed

sound/soc/intel/boards/bytcr_wm5102.c

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111

1212
#include <linux/acpi.h>
13+
#include <linux/bitfield.h>
1314
#include <linux/clk.h>
1415
#include <linux/device.h>
1516
#include <linux/init.h>
@@ -37,10 +38,17 @@ struct byt_wm5102_private {
3738
int mclk_freq;
3839
};
3940

40-
/* Bits 0-15 are reserved for things like an input-map */
41+
/* Bits 0-3 are reserved for the input-map */
42+
#define BYT_WM5102_OUT_MAP GENMASK(7, 4)
4143
#define BYT_WM5102_SSP2 BIT(16)
4244
#define BYT_WM5102_MCLK_19_2MHZ BIT(17)
4345

46+
/* Note these values are pre-shifted for easy use of setting quirks */
47+
enum {
48+
BYT_WM5102_SPK_SPK_MAP = FIELD_PREP_CONST(BYT_WM5102_OUT_MAP, 0),
49+
BYT_WM5102_SPK_HPOUT2_MAP = FIELD_PREP_CONST(BYT_WM5102_OUT_MAP, 1),
50+
};
51+
4452
static unsigned long quirk;
4553

4654
static int quirk_override = -1;
@@ -49,6 +57,20 @@ MODULE_PARM_DESC(quirk, "Board-specific quirk override");
4957

5058
static void log_quirks(struct device *dev)
5159
{
60+
switch (quirk & BYT_WM5102_OUT_MAP) {
61+
case BYT_WM5102_SPK_SPK_MAP:
62+
dev_info_once(dev, "quirk SPK_SPK_MAP enabled\n");
63+
break;
64+
case BYT_WM5102_SPK_HPOUT2_MAP:
65+
dev_info_once(dev, "quirk SPK_HPOUT2_MAP enabled\n");
66+
break;
67+
default:
68+
dev_warn_once(dev, "quirk sets invalid output map: 0x%lx, defaulting to SPK_SPK_MAP\n",
69+
quirk & BYT_WM5102_OUT_MAP);
70+
quirk &= ~BYT_WM5102_OUT_MAP;
71+
quirk |= BYT_WM5102_SPK_SPK_MAP;
72+
break;
73+
}
5274
if (quirk & BYT_WM5102_SSP2)
5375
dev_info_once(dev, "quirk SSP2 enabled");
5476
if (quirk & BYT_WM5102_MCLK_19_2MHZ)
@@ -164,12 +186,6 @@ static const struct snd_soc_dapm_route byt_wm5102_audio_map[] = {
164186
{"Headset Mic", NULL, "Platform Clock"},
165187
{"Internal Mic", NULL, "Platform Clock"},
166188
{"Speaker", NULL, "Platform Clock"},
167-
{"Line Out", NULL, "Platform Clock"},
168-
169-
{"Speaker", NULL, "SPKOUTLP"},
170-
{"Speaker", NULL, "SPKOUTLN"},
171-
{"Speaker", NULL, "SPKOUTRP"},
172-
{"Speaker", NULL, "SPKOUTRN"},
173189
{"Speaker", NULL, "Speaker VDD"},
174190

175191
{"Headphone", NULL, "HPOUT1L"},
@@ -203,6 +219,18 @@ static const struct snd_soc_dapm_route bytcr_wm5102_ssp2_map[] = {
203219
{"ssp2 Rx", NULL, "AIF1 Capture"},
204220
};
205221

222+
static const struct snd_soc_dapm_route byt_wm5102_spk_spk_map[] = {
223+
{"Speaker", NULL, "SPKOUTLP"},
224+
{"Speaker", NULL, "SPKOUTLN"},
225+
{"Speaker", NULL, "SPKOUTRP"},
226+
{"Speaker", NULL, "SPKOUTRN"},
227+
};
228+
229+
static const struct snd_soc_dapm_route byt_wm5102_spk_hpout2_map[] = {
230+
{"Speaker", NULL, "HPOUT2L"},
231+
{"Speaker", NULL, "HPOUT2R"},
232+
};
233+
206234
static const struct snd_kcontrol_new byt_wm5102_controls[] = {
207235
SOC_DAPM_PIN_SWITCH("Headphone"),
208236
SOC_DAPM_PIN_SWITCH("Headset Mic"),
@@ -243,6 +271,20 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime)
243271
return ret;
244272
}
245273

274+
switch (quirk & BYT_WM5102_OUT_MAP) {
275+
case BYT_WM5102_SPK_SPK_MAP:
276+
custom_map = byt_wm5102_spk_spk_map;
277+
num_routes = ARRAY_SIZE(byt_wm5102_spk_spk_map);
278+
break;
279+
case BYT_WM5102_SPK_HPOUT2_MAP:
280+
custom_map = byt_wm5102_spk_hpout2_map;
281+
num_routes = ARRAY_SIZE(byt_wm5102_spk_hpout2_map);
282+
break;
283+
}
284+
ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
285+
if (ret)
286+
return ret;
287+
246288
if (quirk & BYT_WM5102_SSP2) {
247289
custom_map = bytcr_wm5102_ssp2_map;
248290
num_routes = ARRAY_SIZE(bytcr_wm5102_ssp2_map);
@@ -434,8 +476,11 @@ static struct snd_soc_card byt_wm5102_card = {
434476
.fully_routed = true,
435477
};
436478

479+
static char byt_wm5102_components[64]; /* = "cfg-spk:* cfg-int-mic:* cfg-hs-mic:* ..." */
480+
437481
static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
438482
{
483+
static const char * const out_map_name[] = { "spk", "hpout2" };
439484
char codec_name[SND_ACPI_I2C_ID_LEN];
440485
struct device *dev = &pdev->dev;
441486
struct byt_wm5102_private *priv;
@@ -493,8 +538,13 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
493538
}
494539

495540
if (soc_intel_is_cht()) {
496-
/* On CHT default to SSP2 */
497-
quirk = BYT_WM5102_SSP2 | BYT_WM5102_MCLK_19_2MHZ;
541+
/*
542+
* CHT always uses SSP2 and 19.2 MHz; and
543+
* the one currently supported CHT design uses HPOUT2 as
544+
* speaker output.
545+
*/
546+
quirk = BYT_WM5102_SSP2 | BYT_WM5102_MCLK_19_2MHZ |
547+
BYT_WM5102_SPK_HPOUT2_MAP;
498548
}
499549
if (quirk_override != -1) {
500550
dev_info_once(dev, "Overriding quirk 0x%lx => 0x%x\n",
@@ -503,6 +553,10 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
503553
}
504554
log_quirks(dev);
505555

556+
snprintf(byt_wm5102_components, sizeof(byt_wm5102_components),
557+
"cfg-spk:%s", out_map_name[FIELD_GET(BYT_WM5102_OUT_MAP, quirk)]);
558+
byt_wm5102_card.components = byt_wm5102_components;
559+
506560
/* find index of codec dai */
507561
for (i = 0; i < ARRAY_SIZE(byt_wm5102_dais); i++) {
508562
if (!strcmp(byt_wm5102_dais[i].codecs->name,

0 commit comments

Comments
 (0)