aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r--sound/pci/hda/patch_sigmatel.c96
1 files changed, 62 insertions, 34 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 088a5afbd1b9..3bc29c9b2529 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -83,6 +83,7 @@ enum {
83 STAC_DELL_M6_BOTH, 83 STAC_DELL_M6_BOTH,
84 STAC_DELL_EQ, 84 STAC_DELL_EQ,
85 STAC_ALIENWARE_M17X, 85 STAC_ALIENWARE_M17X,
86 STAC_92HD89XX_HP_FRONT_JACK,
86 STAC_92HD73XX_MODELS 87 STAC_92HD73XX_MODELS
87}; 88};
88 89
@@ -97,6 +98,7 @@ enum {
97 STAC_92HD83XXX_HP_LED, 98 STAC_92HD83XXX_HP_LED,
98 STAC_92HD83XXX_HP_INV_LED, 99 STAC_92HD83XXX_HP_INV_LED,
99 STAC_92HD83XXX_HP_MIC_LED, 100 STAC_92HD83XXX_HP_MIC_LED,
101 STAC_HP_LED_GPIO10,
100 STAC_92HD83XXX_HEADSET_JACK, 102 STAC_92HD83XXX_HEADSET_JACK,
101 STAC_92HD83XXX_HP, 103 STAC_92HD83XXX_HP,
102 STAC_HP_ENVY_BASS, 104 STAC_HP_ENVY_BASS,
@@ -194,7 +196,7 @@ struct sigmatel_spec {
194 int default_polarity; 196 int default_polarity;
195 197
196 unsigned int mic_mute_led_gpio; /* capture mute LED GPIO */ 198 unsigned int mic_mute_led_gpio; /* capture mute LED GPIO */
197 bool mic_mute_led_on; /* current mic mute state */ 199 unsigned int mic_enabled; /* current mic mute state (bitmask) */
198 200
199 /* stream */ 201 /* stream */
200 unsigned int stream_delay; 202 unsigned int stream_delay;
@@ -324,19 +326,26 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
324 326
325/* hook for controlling mic-mute LED GPIO */ 327/* hook for controlling mic-mute LED GPIO */
326static void stac_capture_led_hook(struct hda_codec *codec, 328static void stac_capture_led_hook(struct hda_codec *codec,
327 struct snd_ctl_elem_value *ucontrol) 329 struct snd_kcontrol *kcontrol,
330 struct snd_ctl_elem_value *ucontrol)
328{ 331{
329 struct sigmatel_spec *spec = codec->spec; 332 struct sigmatel_spec *spec = codec->spec;
330 bool mute; 333 unsigned int mask;
334 bool cur_mute, prev_mute;
331 335
332 if (!ucontrol) 336 if (!kcontrol || !ucontrol)
333 return; 337 return;
334 338
335 mute = !(ucontrol->value.integer.value[0] || 339 mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
336 ucontrol->value.integer.value[1]); 340 prev_mute = !spec->mic_enabled;
337 if (spec->mic_mute_led_on != mute) { 341 if (ucontrol->value.integer.value[0] ||
338 spec->mic_mute_led_on = mute; 342 ucontrol->value.integer.value[1])
339 if (mute) 343 spec->mic_enabled |= mask;
344 else
345 spec->mic_enabled &= ~mask;
346 cur_mute = !spec->mic_enabled;
347 if (cur_mute != prev_mute) {
348 if (cur_mute)
340 spec->gpio_data |= spec->mic_mute_led_gpio; 349 spec->gpio_data |= spec->mic_mute_led_gpio;
341 else 350 else
342 spec->gpio_data &= ~spec->mic_mute_led_gpio; 351 spec->gpio_data &= ~spec->mic_mute_led_gpio;
@@ -368,6 +377,17 @@ static int stac_vrefout_set(struct hda_codec *codec,
368 return 1; 377 return 1;
369} 378}
370 379
380/* prevent codec AFG to D3 state when vref-out pin is used for mute LED */
381/* this hook is set in stac_setup_gpio() */
382static unsigned int stac_vref_led_power_filter(struct hda_codec *codec,
383 hda_nid_t nid,
384 unsigned int power_state)
385{
386 if (nid == codec->afg && power_state == AC_PWRST_D3)
387 return AC_PWRST_D1;
388 return snd_hda_gen_path_power_filter(codec, nid, power_state);
389}
390
371/* update mute-LED accoring to the master switch */ 391/* update mute-LED accoring to the master switch */
372static void stac_update_led_status(struct hda_codec *codec, int enabled) 392static void stac_update_led_status(struct hda_codec *codec, int enabled)
373{ 393{
@@ -1777,6 +1797,12 @@ static const struct hda_pintbl intel_dg45id_pin_configs[] = {
1777 {} 1797 {}
1778}; 1798};
1779 1799
1800static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = {
1801 { 0x0a, 0x02214030 },
1802 { 0x0b, 0x02A19010 },
1803 {}
1804};
1805
1780static void stac92hd73xx_fixup_ref(struct hda_codec *codec, 1806static void stac92hd73xx_fixup_ref(struct hda_codec *codec,
1781 const struct hda_fixup *fix, int action) 1807 const struct hda_fixup *fix, int action)
1782{ 1808{
@@ -1895,6 +1921,10 @@ static const struct hda_fixup stac92hd73xx_fixups[] = {
1895 [STAC_92HD73XX_NO_JD] = { 1921 [STAC_92HD73XX_NO_JD] = {
1896 .type = HDA_FIXUP_FUNC, 1922 .type = HDA_FIXUP_FUNC,
1897 .v.func = stac92hd73xx_fixup_no_jd, 1923 .v.func = stac92hd73xx_fixup_no_jd,
1924 },
1925 [STAC_92HD89XX_HP_FRONT_JACK] = {
1926 .type = HDA_FIXUP_PINS,
1927 .v.pins = stac92hd89xx_hp_front_jack_pin_configs,
1898 } 1928 }
1899}; 1929};
1900 1930
@@ -1955,6 +1985,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = {
1955 "Alienware M17x", STAC_ALIENWARE_M17X), 1985 "Alienware M17x", STAC_ALIENWARE_M17X),
1956 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, 1986 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490,
1957 "Alienware M17x R3", STAC_DELL_EQ), 1987 "Alienware M17x R3", STAC_DELL_EQ),
1988 SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17,
1989 "unknown HP", STAC_92HD89XX_HP_FRONT_JACK),
1958 {} /* terminator */ 1990 {} /* terminator */
1959}; 1991};
1960 1992
@@ -2099,6 +2131,17 @@ static void stac92hd83xxx_fixup_hp_mic_led(struct hda_codec *codec,
2099 } 2131 }
2100} 2132}
2101 2133
2134static void stac92hd83xxx_fixup_hp_led_gpio10(struct hda_codec *codec,
2135 const struct hda_fixup *fix, int action)
2136{
2137 struct sigmatel_spec *spec = codec->spec;
2138
2139 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
2140 spec->gpio_led = 0x10; /* GPIO4 */
2141 spec->default_polarity = 0;
2142 }
2143}
2144
2102static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec, 2145static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec,
2103 const struct hda_fixup *fix, int action) 2146 const struct hda_fixup *fix, int action)
2104{ 2147{
@@ -2593,6 +2636,12 @@ static const struct hda_fixup stac92hd83xxx_fixups[] = {
2593 .chained = true, 2636 .chained = true,
2594 .chain_id = STAC_92HD83XXX_HP, 2637 .chain_id = STAC_92HD83XXX_HP,
2595 }, 2638 },
2639 [STAC_HP_LED_GPIO10] = {
2640 .type = HDA_FIXUP_FUNC,
2641 .v.func = stac92hd83xxx_fixup_hp_led_gpio10,
2642 .chained = true,
2643 .chain_id = STAC_92HD83XXX_HP,
2644 },
2596 [STAC_92HD83XXX_HEADSET_JACK] = { 2645 [STAC_92HD83XXX_HEADSET_JACK] = {
2597 .type = HDA_FIXUP_FUNC, 2646 .type = HDA_FIXUP_FUNC,
2598 .v.func = stac92hd83xxx_fixup_headset_jack, 2647 .v.func = stac92hd83xxx_fixup_headset_jack,
@@ -2671,6 +2720,8 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = {
2671 "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), 2720 "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
2672 SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1888, 2721 SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1888,
2673 "HP Envy Spectre", STAC_HP_ENVY_BASS), 2722 "HP Envy Spectre", STAC_HP_ENVY_BASS),
2723 SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1899,
2724 "HP Folio 13", STAC_HP_LED_GPIO10),
2674 SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18df, 2725 SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18df,
2675 "HP Folio", STAC_HP_BNB13_EQ), 2726 "HP Folio", STAC_HP_BNB13_EQ),
2676 SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18F8, 2727 SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18F8,
@@ -4260,30 +4311,8 @@ static int stac_suspend(struct hda_codec *codec)
4260 stac_shutup(codec); 4311 stac_shutup(codec);
4261 return 0; 4312 return 0;
4262} 4313}
4263
4264static void stac_set_power_state(struct hda_codec *codec, hda_nid_t fg,
4265 unsigned int power_state)
4266{
4267 unsigned int afg_power_state = power_state;
4268 struct sigmatel_spec *spec = codec->spec;
4269
4270 if (power_state == AC_PWRST_D3) {
4271 if (spec->vref_mute_led_nid) {
4272 /* with vref-out pin used for mute led control
4273 * codec AFG is prevented from D3 state
4274 */
4275 afg_power_state = AC_PWRST_D1;
4276 }
4277 /* this delay seems necessary to avoid click noise at power-down */
4278 msleep(100);
4279 }
4280 snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
4281 afg_power_state);
4282 snd_hda_codec_set_power_to_all(codec, fg, power_state);
4283}
4284#else 4314#else
4285#define stac_suspend NULL 4315#define stac_suspend NULL
4286#define stac_set_power_state NULL
4287#endif /* CONFIG_PM */ 4316#endif /* CONFIG_PM */
4288 4317
4289static const struct hda_codec_ops stac_patch_ops = { 4318static const struct hda_codec_ops stac_patch_ops = {
@@ -4466,15 +4495,14 @@ static void stac_setup_gpio(struct hda_codec *codec)
4466 spec->gpio_dir |= spec->gpio_led; 4495 spec->gpio_dir |= spec->gpio_led;
4467 spec->gpio_data |= spec->gpio_led; 4496 spec->gpio_data |= spec->gpio_led;
4468 } else { 4497 } else {
4469 codec->patch_ops.set_power_state = 4498 codec->power_filter = stac_vref_led_power_filter;
4470 stac_set_power_state;
4471 } 4499 }
4472 } 4500 }
4473 4501
4474 if (spec->mic_mute_led_gpio) { 4502 if (spec->mic_mute_led_gpio) {
4475 spec->gpio_mask |= spec->mic_mute_led_gpio; 4503 spec->gpio_mask |= spec->mic_mute_led_gpio;
4476 spec->gpio_dir |= spec->mic_mute_led_gpio; 4504 spec->gpio_dir |= spec->mic_mute_led_gpio;
4477 spec->mic_mute_led_on = true; 4505 spec->mic_enabled = 0;
4478 spec->gpio_data |= spec->mic_mute_led_gpio; 4506 spec->gpio_data |= spec->mic_mute_led_gpio;
4479 4507
4480 spec->gen.cap_sync_hook = stac_capture_led_hook; 4508 spec->gen.cap_sync_hook = stac_capture_led_hook;