Skip to content

Commit aa70527

Browse files
committed
Make headphone work on Huawei Matebook D15
Merge series from Mauro Carvalho Chehab <mchehab@kernel.org>: Huawei Matebook D15 uses two different GPIOs are used to control the output: - gpio0 controls the speaker output; - gpio1 controls the headphone output. Changing both at the same time cause spurious events that are mis-interpreted as input events, causing troubles on apps. So, a delay is needed before turning on such gpios. Also, the headset microphone is connected to MIC1, instead of MIC2 port. With this patch, plugging a headphone causes a jack event to trigger the speaker supply, powering down the speaker and powering up the headphone output. Removing the headphone also triggers the power supply, powering up the speaker and powering down the headphone. The headset microphone also works.
2 parents 92ccbf1 + c7cb471 commit aa70527

1 file changed

Lines changed: 89 additions & 28 deletions

File tree

sound/soc/intel/boards/sof_es8336.c

Lines changed: 89 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@
2727
#define SOF_ES8336_SSP_CODEC(quirk) ((quirk) & GENMASK(3, 0))
2828
#define SOF_ES8336_SSP_CODEC_MASK (GENMASK(3, 0))
2929

30-
#define SOF_ES8336_TGL_GPIO_QUIRK BIT(4)
30+
#define SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK BIT(4)
3131
#define SOF_ES8336_ENABLE_DMIC BIT(5)
3232
#define SOF_ES8336_JD_INVERTED BIT(6)
33+
#define SOF_ES8336_HEADPHONE_GPIO BIT(7)
34+
#define SOC_ES8336_HEADSET_MIC1 BIT(8)
3335

3436
static unsigned long quirk;
3537

@@ -39,7 +41,7 @@ MODULE_PARM_DESC(quirk, "Board-specific quirk override");
3941

4042
struct sof_es8336_private {
4143
struct device *codec_dev;
42-
struct gpio_desc *gpio_pa;
44+
struct gpio_desc *gpio_speakers, *gpio_headphone;
4345
struct snd_soc_jack jack;
4446
struct list_head hdmi_pcm_list;
4547
bool speaker_en;
@@ -51,30 +53,46 @@ struct sof_hdmi_pcm {
5153
int device;
5254
};
5355

54-
static const struct acpi_gpio_params pa_enable_gpio = { 0, 0, true };
55-
static const struct acpi_gpio_mapping acpi_es8336_gpios[] = {
56-
{ "pa-enable-gpios", &pa_enable_gpio, 1 },
56+
static const struct acpi_gpio_params enable_gpio0 = { 0, 0, true };
57+
static const struct acpi_gpio_params enable_gpio1 = { 1, 0, true };
58+
59+
static const struct acpi_gpio_mapping acpi_speakers_enable_gpio0[] = {
60+
{ "speakers-enable-gpios", &enable_gpio0, 1 },
5761
{ }
5862
};
5963

60-
static const struct acpi_gpio_params quirk_pa_enable_gpio = { 1, 0, true };
61-
static const struct acpi_gpio_mapping quirk_acpi_es8336_gpios[] = {
62-
{ "pa-enable-gpios", &quirk_pa_enable_gpio, 1 },
64+
static const struct acpi_gpio_mapping acpi_speakers_enable_gpio1[] = {
65+
{ "speakers-enable-gpios", &enable_gpio1, 1 },
66+
};
67+
68+
static const struct acpi_gpio_mapping acpi_enable_both_gpios[] = {
69+
{ "speakers-enable-gpios", &enable_gpio0, 1 },
70+
{ "headphone-enable-gpios", &enable_gpio1, 1 },
6371
{ }
6472
};
6573

66-
static const struct acpi_gpio_mapping *gpio_mapping = acpi_es8336_gpios;
74+
static const struct acpi_gpio_mapping acpi_enable_both_gpios_rev_order[] = {
75+
{ "speakers-enable-gpios", &enable_gpio1, 1 },
76+
{ "headphone-enable-gpios", &enable_gpio0, 1 },
77+
{ }
78+
};
79+
80+
static const struct acpi_gpio_mapping *gpio_mapping = acpi_speakers_enable_gpio0;
6781

6882
static void log_quirks(struct device *dev)
6983
{
7084
dev_info(dev, "quirk mask %#lx\n", quirk);
7185
dev_info(dev, "quirk SSP%ld\n", SOF_ES8336_SSP_CODEC(quirk));
7286
if (quirk & SOF_ES8336_ENABLE_DMIC)
7387
dev_info(dev, "quirk DMIC enabled\n");
74-
if (quirk & SOF_ES8336_TGL_GPIO_QUIRK)
75-
dev_info(dev, "quirk TGL GPIO enabled\n");
88+
if (quirk & SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK)
89+
dev_info(dev, "Speakers GPIO1 quirk enabled\n");
90+
if (quirk & SOF_ES8336_HEADPHONE_GPIO)
91+
dev_info(dev, "quirk headphone GPIO enabled\n");
7692
if (quirk & SOF_ES8336_JD_INVERTED)
7793
dev_info(dev, "quirk JD inverted enabled\n");
94+
if (quirk & SOC_ES8336_HEADSET_MIC1)
95+
dev_info(dev, "quirk headset at mic1 port enabled\n");
7896
}
7997

8098
static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
@@ -83,12 +101,23 @@ static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
83101
struct snd_soc_card *card = w->dapm->card;
84102
struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
85103

104+
if (priv->speaker_en == !SND_SOC_DAPM_EVENT_ON(event))
105+
return 0;
106+
107+
priv->speaker_en = !SND_SOC_DAPM_EVENT_ON(event);
108+
109+
if (SND_SOC_DAPM_EVENT_ON(event))
110+
msleep(70);
111+
112+
gpiod_set_value_cansleep(priv->gpio_speakers, priv->speaker_en);
113+
114+
if (!(quirk & SOF_ES8336_HEADPHONE_GPIO))
115+
return 0;
116+
86117
if (SND_SOC_DAPM_EVENT_ON(event))
87-
priv->speaker_en = false;
88-
else
89-
priv->speaker_en = true;
118+
msleep(70);
90119

91-
gpiod_set_value_cansleep(priv->gpio_pa, priv->speaker_en);
120+
gpiod_set_value_cansleep(priv->gpio_headphone, priv->speaker_en);
92121

93122
return 0;
94123
}
@@ -114,18 +143,23 @@ static const struct snd_soc_dapm_route sof_es8316_audio_map[] = {
114143

115144
/*
116145
* There is no separate speaker output instead the speakers are muxed to
117-
* the HP outputs. The mux is controlled by the "Speaker Power" supply.
146+
* the HP outputs. The mux is controlled Speaker and/or headphone switch.
118147
*/
119148
{"Speaker", NULL, "HPOL"},
120149
{"Speaker", NULL, "HPOR"},
121150
{"Speaker", NULL, "Speaker Power"},
122151
};
123152

124-
static const struct snd_soc_dapm_route sof_es8316_intmic_in1_map[] = {
153+
static const struct snd_soc_dapm_route sof_es8316_headset_mic2_map[] = {
125154
{"MIC1", NULL, "Internal Mic"},
126155
{"MIC2", NULL, "Headset Mic"},
127156
};
128157

158+
static const struct snd_soc_dapm_route sof_es8316_headset_mic1_map[] = {
159+
{"MIC2", NULL, "Internal Mic"},
160+
{"MIC1", NULL, "Headset Mic"},
161+
};
162+
129163
static const struct snd_soc_dapm_route dmic_map[] = {
130164
/* digital mics */
131165
{"DMic", NULL, "SoC DMIC"},
@@ -199,8 +233,13 @@ static int sof_es8316_init(struct snd_soc_pcm_runtime *runtime)
199233

200234
card->dapm.idle_bias_off = true;
201235

202-
custom_map = sof_es8316_intmic_in1_map;
203-
num_routes = ARRAY_SIZE(sof_es8316_intmic_in1_map);
236+
if (quirk & SOC_ES8336_HEADSET_MIC1) {
237+
custom_map = sof_es8316_headset_mic1_map;
238+
num_routes = ARRAY_SIZE(sof_es8316_headset_mic1_map);
239+
} else {
240+
custom_map = sof_es8316_headset_mic2_map;
241+
num_routes = ARRAY_SIZE(sof_es8316_headset_mic2_map);
242+
}
204243

205244
ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
206245
if (ret)
@@ -233,8 +272,14 @@ static int sof_es8336_quirk_cb(const struct dmi_system_id *id)
233272
{
234273
quirk = (unsigned long)id->driver_data;
235274

236-
if (quirk & SOF_ES8336_TGL_GPIO_QUIRK)
237-
gpio_mapping = quirk_acpi_es8336_gpios;
275+
if (quirk & SOF_ES8336_HEADPHONE_GPIO) {
276+
if (quirk & SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK)
277+
gpio_mapping = acpi_enable_both_gpios;
278+
else
279+
gpio_mapping = acpi_enable_both_gpios_rev_order;
280+
} else if (quirk & SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK) {
281+
gpio_mapping = acpi_speakers_enable_gpio1;
282+
}
238283

239284
return 1;
240285
}
@@ -257,7 +302,16 @@ static const struct dmi_system_id sof_es8336_quirk_table[] = {
257302
DMI_MATCH(DMI_SYS_VENDOR, "IP3 tech"),
258303
DMI_MATCH(DMI_BOARD_NAME, "WN1"),
259304
},
260-
.driver_data = (void *)(SOF_ES8336_TGL_GPIO_QUIRK)
305+
.driver_data = (void *)(SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK)
306+
},
307+
{
308+
.callback = sof_es8336_quirk_cb,
309+
.matches = {
310+
DMI_MATCH(DMI_SYS_VENDOR, "HUAWEI"),
311+
DMI_MATCH(DMI_BOARD_NAME, "BOHB-WAX9-PCB-B2"),
312+
},
313+
.driver_data = (void *)(SOF_ES8336_HEADPHONE_GPIO |
314+
SOC_ES8336_HEADSET_MIC1)
261315
},
262316
{}
263317
};
@@ -585,10 +639,17 @@ static int sof_es8336_probe(struct platform_device *pdev)
585639
if (ret)
586640
dev_warn(codec_dev, "unable to add GPIO mapping table\n");
587641

588-
priv->gpio_pa = gpiod_get_optional(codec_dev, "pa-enable", GPIOD_OUT_LOW);
589-
if (IS_ERR(priv->gpio_pa)) {
590-
ret = dev_err_probe(dev, PTR_ERR(priv->gpio_pa),
591-
"could not get pa-enable GPIO\n");
642+
priv->gpio_speakers = gpiod_get_optional(codec_dev, "speakers-enable", GPIOD_OUT_LOW);
643+
if (IS_ERR(priv->gpio_speakers)) {
644+
ret = dev_err_probe(dev, PTR_ERR(priv->gpio_speakers),
645+
"could not get speakers-enable GPIO\n");
646+
goto err_put_codec;
647+
}
648+
649+
priv->gpio_headphone = gpiod_get_optional(codec_dev, "headphone-enable", GPIOD_OUT_LOW);
650+
if (IS_ERR(priv->gpio_headphone)) {
651+
ret = dev_err_probe(dev, PTR_ERR(priv->gpio_headphone),
652+
"could not get headphone-enable GPIO\n");
592653
goto err_put_codec;
593654
}
594655

@@ -604,7 +665,7 @@ static int sof_es8336_probe(struct platform_device *pdev)
604665

605666
ret = devm_snd_soc_register_card(dev, card);
606667
if (ret) {
607-
gpiod_put(priv->gpio_pa);
668+
gpiod_put(priv->gpio_speakers);
608669
dev_err(dev, "snd_soc_register_card failed: %d\n", ret);
609670
goto err_put_codec;
610671
}
@@ -622,7 +683,7 @@ static int sof_es8336_remove(struct platform_device *pdev)
622683
struct snd_soc_card *card = platform_get_drvdata(pdev);
623684
struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card);
624685

625-
gpiod_put(priv->gpio_pa);
686+
gpiod_put(priv->gpio_speakers);
626687
device_remove_software_node(priv->codec_dev);
627688
put_device(priv->codec_dev);
628689

0 commit comments

Comments
 (0)