Commit c556d202 authored by Hans de Goede's avatar Hans de Goede Committed by Mark Brown

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: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20231025143513.291753-4-hdegoede@redhat.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent bce4b014
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -37,10 +38,17 @@ struct byt_wm5102_private { ...@@ -37,10 +38,17 @@ struct byt_wm5102_private {
int mclk_freq; int mclk_freq;
}; };
/* Bits 0-15 are reserved for things like an input-map */ /* Bits 0-3 are reserved for the input-map */
#define BYT_WM5102_OUT_MAP GENMASK(7, 4)
#define BYT_WM5102_SSP2 BIT(16) #define BYT_WM5102_SSP2 BIT(16)
#define BYT_WM5102_MCLK_19_2MHZ BIT(17) #define BYT_WM5102_MCLK_19_2MHZ BIT(17)
/* Note these values are pre-shifted for easy use of setting quirks */
enum {
BYT_WM5102_SPK_SPK_MAP = FIELD_PREP_CONST(BYT_WM5102_OUT_MAP, 0),
BYT_WM5102_SPK_HPOUT2_MAP = FIELD_PREP_CONST(BYT_WM5102_OUT_MAP, 1),
};
static unsigned long quirk; static unsigned long quirk;
static int quirk_override = -1; static int quirk_override = -1;
...@@ -49,6 +57,20 @@ MODULE_PARM_DESC(quirk, "Board-specific quirk override"); ...@@ -49,6 +57,20 @@ MODULE_PARM_DESC(quirk, "Board-specific quirk override");
static void log_quirks(struct device *dev) static void log_quirks(struct device *dev)
{ {
switch (quirk & BYT_WM5102_OUT_MAP) {
case BYT_WM5102_SPK_SPK_MAP:
dev_info_once(dev, "quirk SPK_SPK_MAP enabled\n");
break;
case BYT_WM5102_SPK_HPOUT2_MAP:
dev_info_once(dev, "quirk SPK_HPOUT2_MAP enabled\n");
break;
default:
dev_warn_once(dev, "quirk sets invalid output map: 0x%lx, defaulting to SPK_SPK_MAP\n",
quirk & BYT_WM5102_OUT_MAP);
quirk &= ~BYT_WM5102_OUT_MAP;
quirk |= BYT_WM5102_SPK_SPK_MAP;
break;
}
if (quirk & BYT_WM5102_SSP2) if (quirk & BYT_WM5102_SSP2)
dev_info_once(dev, "quirk SSP2 enabled"); dev_info_once(dev, "quirk SSP2 enabled");
if (quirk & BYT_WM5102_MCLK_19_2MHZ) if (quirk & BYT_WM5102_MCLK_19_2MHZ)
...@@ -164,12 +186,6 @@ static const struct snd_soc_dapm_route byt_wm5102_audio_map[] = { ...@@ -164,12 +186,6 @@ static const struct snd_soc_dapm_route byt_wm5102_audio_map[] = {
{"Headset Mic", NULL, "Platform Clock"}, {"Headset Mic", NULL, "Platform Clock"},
{"Internal Mic", NULL, "Platform Clock"}, {"Internal Mic", NULL, "Platform Clock"},
{"Speaker", NULL, "Platform Clock"}, {"Speaker", NULL, "Platform Clock"},
{"Line Out", NULL, "Platform Clock"},
{"Speaker", NULL, "SPKOUTLP"},
{"Speaker", NULL, "SPKOUTLN"},
{"Speaker", NULL, "SPKOUTRP"},
{"Speaker", NULL, "SPKOUTRN"},
{"Speaker", NULL, "Speaker VDD"}, {"Speaker", NULL, "Speaker VDD"},
{"Headphone", NULL, "HPOUT1L"}, {"Headphone", NULL, "HPOUT1L"},
...@@ -203,6 +219,18 @@ static const struct snd_soc_dapm_route bytcr_wm5102_ssp2_map[] = { ...@@ -203,6 +219,18 @@ static const struct snd_soc_dapm_route bytcr_wm5102_ssp2_map[] = {
{"ssp2 Rx", NULL, "AIF1 Capture"}, {"ssp2 Rx", NULL, "AIF1 Capture"},
}; };
static const struct snd_soc_dapm_route byt_wm5102_spk_spk_map[] = {
{"Speaker", NULL, "SPKOUTLP"},
{"Speaker", NULL, "SPKOUTLN"},
{"Speaker", NULL, "SPKOUTRP"},
{"Speaker", NULL, "SPKOUTRN"},
};
static const struct snd_soc_dapm_route byt_wm5102_spk_hpout2_map[] = {
{"Speaker", NULL, "HPOUT2L"},
{"Speaker", NULL, "HPOUT2R"},
};
static const struct snd_kcontrol_new byt_wm5102_controls[] = { static const struct snd_kcontrol_new byt_wm5102_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone"), SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Headset Mic"), SOC_DAPM_PIN_SWITCH("Headset Mic"),
...@@ -243,6 +271,20 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime) ...@@ -243,6 +271,20 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime)
return ret; return ret;
} }
switch (quirk & BYT_WM5102_OUT_MAP) {
case BYT_WM5102_SPK_SPK_MAP:
custom_map = byt_wm5102_spk_spk_map;
num_routes = ARRAY_SIZE(byt_wm5102_spk_spk_map);
break;
case BYT_WM5102_SPK_HPOUT2_MAP:
custom_map = byt_wm5102_spk_hpout2_map;
num_routes = ARRAY_SIZE(byt_wm5102_spk_hpout2_map);
break;
}
ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
if (ret)
return ret;
if (quirk & BYT_WM5102_SSP2) { if (quirk & BYT_WM5102_SSP2) {
custom_map = bytcr_wm5102_ssp2_map; custom_map = bytcr_wm5102_ssp2_map;
num_routes = ARRAY_SIZE(bytcr_wm5102_ssp2_map); num_routes = ARRAY_SIZE(bytcr_wm5102_ssp2_map);
...@@ -434,8 +476,11 @@ static struct snd_soc_card byt_wm5102_card = { ...@@ -434,8 +476,11 @@ static struct snd_soc_card byt_wm5102_card = {
.fully_routed = true, .fully_routed = true,
}; };
static char byt_wm5102_components[64]; /* = "cfg-spk:* cfg-int-mic:* cfg-hs-mic:* ..." */
static int snd_byt_wm5102_mc_probe(struct platform_device *pdev) static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
{ {
static const char * const out_map_name[] = { "spk", "hpout2" };
char codec_name[SND_ACPI_I2C_ID_LEN]; char codec_name[SND_ACPI_I2C_ID_LEN];
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct byt_wm5102_private *priv; struct byt_wm5102_private *priv;
...@@ -493,8 +538,13 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev) ...@@ -493,8 +538,13 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
} }
if (soc_intel_is_cht()) { if (soc_intel_is_cht()) {
/* On CHT default to SSP2 */ /*
quirk = BYT_WM5102_SSP2 | BYT_WM5102_MCLK_19_2MHZ; * CHT always uses SSP2 and 19.2 MHz; and
* the one currently supported CHT design uses HPOUT2 as
* speaker output.
*/
quirk = BYT_WM5102_SSP2 | BYT_WM5102_MCLK_19_2MHZ |
BYT_WM5102_SPK_HPOUT2_MAP;
} }
if (quirk_override != -1) { if (quirk_override != -1) {
dev_info_once(dev, "Overriding quirk 0x%lx => 0x%x\n", 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) ...@@ -503,6 +553,10 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
} }
log_quirks(dev); log_quirks(dev);
snprintf(byt_wm5102_components, sizeof(byt_wm5102_components),
"cfg-spk:%s", out_map_name[FIELD_GET(BYT_WM5102_OUT_MAP, quirk)]);
byt_wm5102_card.components = byt_wm5102_components;
/* find index of codec dai */ /* find index of codec dai */
for (i = 0; i < ARRAY_SIZE(byt_wm5102_dais); i++) { for (i = 0; i < ARRAY_SIZE(byt_wm5102_dais); i++) {
if (!strcmp(byt_wm5102_dais[i].codecs->name, if (!strcmp(byt_wm5102_dais[i].codecs->name,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment