diff options
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 96 |
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 */ |
326 | static void stac_capture_led_hook(struct hda_codec *codec, | 328 | static 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() */ | ||
382 | static 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 */ |
372 | static void stac_update_led_status(struct hda_codec *codec, int enabled) | 392 | static 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 | ||
1800 | static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = { | ||
1801 | { 0x0a, 0x02214030 }, | ||
1802 | { 0x0b, 0x02A19010 }, | ||
1803 | {} | ||
1804 | }; | ||
1805 | |||
1780 | static void stac92hd73xx_fixup_ref(struct hda_codec *codec, | 1806 | static 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 | ||
2134 | static 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 | |||
2102 | static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec, | 2145 | static 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 | |||
4264 | static 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 | ||
4289 | static const struct hda_codec_ops stac_patch_ops = { | 4318 | static 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; |