diff options
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 318 |
1 files changed, 245 insertions, 73 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 7f81cc2274f..aa376b59c00 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -95,6 +95,7 @@ enum { | |||
95 | STAC_92HD83XXX_PWR_REF, | 95 | STAC_92HD83XXX_PWR_REF, |
96 | STAC_DELL_S14, | 96 | STAC_DELL_S14, |
97 | STAC_92HD83XXX_HP, | 97 | STAC_92HD83XXX_HP, |
98 | STAC_92HD83XXX_HP_cNB11_INTQUAD, | ||
98 | STAC_HP_DV7_4000, | 99 | STAC_HP_DV7_4000, |
99 | STAC_92HD83XXX_MODELS | 100 | STAC_92HD83XXX_MODELS |
100 | }; | 101 | }; |
@@ -212,6 +213,7 @@ struct sigmatel_spec { | |||
212 | unsigned int gpio_mute; | 213 | unsigned int gpio_mute; |
213 | unsigned int gpio_led; | 214 | unsigned int gpio_led; |
214 | unsigned int gpio_led_polarity; | 215 | unsigned int gpio_led_polarity; |
216 | unsigned int vref_led; | ||
215 | 217 | ||
216 | /* stream */ | 218 | /* stream */ |
217 | unsigned int stream_delay; | 219 | unsigned int stream_delay; |
@@ -671,6 +673,30 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, | |||
671 | return 0; | 673 | return 0; |
672 | } | 674 | } |
673 | 675 | ||
676 | static int stac_vrefout_set(struct hda_codec *codec, | ||
677 | hda_nid_t nid, unsigned int new_vref) | ||
678 | { | ||
679 | int error, pinctl; | ||
680 | |||
681 | snd_printdd("%s, nid %x ctl %x\n", __func__, nid, new_vref); | ||
682 | pinctl = snd_hda_codec_read(codec, nid, 0, | ||
683 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
684 | |||
685 | if (pinctl < 0) | ||
686 | return pinctl; | ||
687 | |||
688 | pinctl &= 0xff; | ||
689 | pinctl &= ~AC_PINCTL_VREFEN; | ||
690 | pinctl |= (new_vref & AC_PINCTL_VREFEN); | ||
691 | |||
692 | error = snd_hda_codec_write_cache(codec, nid, 0, | ||
693 | AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); | ||
694 | if (error < 0) | ||
695 | return error; | ||
696 | |||
697 | return 1; | ||
698 | } | ||
699 | |||
674 | static unsigned int stac92xx_vref_set(struct hda_codec *codec, | 700 | static unsigned int stac92xx_vref_set(struct hda_codec *codec, |
675 | hda_nid_t nid, unsigned int new_vref) | 701 | hda_nid_t nid, unsigned int new_vref) |
676 | { | 702 | { |
@@ -1112,7 +1138,9 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1112 | } | 1138 | } |
1113 | 1139 | ||
1114 | if (spec->multiout.dig_out_nid) { | 1140 | if (spec->multiout.dig_out_nid) { |
1115 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | 1141 | err = snd_hda_create_spdif_out_ctls(codec, |
1142 | spec->multiout.dig_out_nid, | ||
1143 | spec->multiout.dig_out_nid); | ||
1116 | if (err < 0) | 1144 | if (err < 0) |
1117 | return err; | 1145 | return err; |
1118 | err = snd_hda_create_spdif_share_sw(codec, | 1146 | err = snd_hda_create_spdif_share_sw(codec, |
@@ -1634,10 +1662,17 @@ static const unsigned int hp_dv7_4000_pin_configs[10] = { | |||
1634 | 0x40f000f0, 0x40f000f0, | 1662 | 0x40f000f0, 0x40f000f0, |
1635 | }; | 1663 | }; |
1636 | 1664 | ||
1665 | static const unsigned int hp_cNB11_intquad_pin_configs[10] = { | ||
1666 | 0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110, | ||
1667 | 0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130, | ||
1668 | 0x40f000f0, 0x40f000f0, | ||
1669 | }; | ||
1670 | |||
1637 | static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { | 1671 | static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { |
1638 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, | 1672 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, |
1639 | [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, | 1673 | [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, |
1640 | [STAC_DELL_S14] = dell_s14_pin_configs, | 1674 | [STAC_DELL_S14] = dell_s14_pin_configs, |
1675 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs, | ||
1641 | [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, | 1676 | [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, |
1642 | }; | 1677 | }; |
1643 | 1678 | ||
@@ -1647,6 +1682,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | |||
1647 | [STAC_92HD83XXX_PWR_REF] = "mic-ref", | 1682 | [STAC_92HD83XXX_PWR_REF] = "mic-ref", |
1648 | [STAC_DELL_S14] = "dell-s14", | 1683 | [STAC_DELL_S14] = "dell-s14", |
1649 | [STAC_92HD83XXX_HP] = "hp", | 1684 | [STAC_92HD83XXX_HP] = "hp", |
1685 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", | ||
1650 | [STAC_HP_DV7_4000] = "hp-dv7-4000", | 1686 | [STAC_HP_DV7_4000] = "hp-dv7-4000", |
1651 | }; | 1687 | }; |
1652 | 1688 | ||
@@ -1659,7 +1695,47 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | |||
1659 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, | 1695 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, |
1660 | "unknown Dell", STAC_DELL_S14), | 1696 | "unknown Dell", STAC_DELL_S14), |
1661 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600, | 1697 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600, |
1662 | "HP", STAC_92HD83XXX_HP), | 1698 | "HP", STAC_92HD83XXX_HP), |
1699 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656, | ||
1700 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1701 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1657, | ||
1702 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1703 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1658, | ||
1704 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1705 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1659, | ||
1706 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1707 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165A, | ||
1708 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1709 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165B, | ||
1710 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1711 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388, | ||
1712 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1713 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389, | ||
1714 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1715 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355B, | ||
1716 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1717 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355C, | ||
1718 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1719 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355D, | ||
1720 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1721 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355E, | ||
1722 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1723 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355F, | ||
1724 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1725 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3560, | ||
1726 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1727 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358B, | ||
1728 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1729 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358C, | ||
1730 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1731 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358D, | ||
1732 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1733 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3591, | ||
1734 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1735 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3592, | ||
1736 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1737 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593, | ||
1738 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | ||
1663 | {} /* terminator */ | 1739 | {} /* terminator */ |
1664 | }; | 1740 | }; |
1665 | 1741 | ||
@@ -3406,30 +3482,9 @@ static hda_nid_t get_connected_node(struct hda_codec *codec, hda_nid_t mux, | |||
3406 | return 0; | 3482 | return 0; |
3407 | } | 3483 | } |
3408 | 3484 | ||
3409 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | 3485 | /* look for NID recursively */ |
3410 | hda_nid_t nid) | 3486 | #define get_connection_index(codec, mux, nid) \ |
3411 | { | 3487 | snd_hda_get_conn_index(codec, mux, nid, 1) |
3412 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; | ||
3413 | int i, nums; | ||
3414 | |||
3415 | if (!(get_wcaps(codec, mux) & AC_WCAP_CONN_LIST)) | ||
3416 | return -1; | ||
3417 | |||
3418 | nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); | ||
3419 | for (i = 0; i < nums; i++) | ||
3420 | if (conn[i] == nid) | ||
3421 | return i; | ||
3422 | |||
3423 | for (i = 0; i < nums; i++) { | ||
3424 | unsigned int wid_caps = get_wcaps(codec, conn[i]); | ||
3425 | unsigned int wid_type = get_wcaps_type(wid_caps); | ||
3426 | |||
3427 | if (wid_type != AC_WID_PIN && wid_type != AC_WID_AUD_MIX) | ||
3428 | if (get_connection_index(codec, conn[i], nid) >= 0) | ||
3429 | return i; | ||
3430 | } | ||
3431 | return -1; | ||
3432 | } | ||
3433 | 3488 | ||
3434 | /* create a volume assigned to the given pin (only if supported) */ | 3489 | /* create a volume assigned to the given pin (only if supported) */ |
3435 | /* return 1 if the volume control is created */ | 3490 | /* return 1 if the volume control is created */ |
@@ -4039,6 +4094,8 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | |||
4039 | { | 4094 | { |
4040 | unsigned int gpiostate, gpiomask, gpiodir; | 4095 | unsigned int gpiostate, gpiomask, gpiodir; |
4041 | 4096 | ||
4097 | snd_printdd("%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data); | ||
4098 | |||
4042 | gpiostate = snd_hda_codec_read(codec, codec->afg, 0, | 4099 | gpiostate = snd_hda_codec_read(codec, codec->afg, 0, |
4043 | AC_VERB_GET_GPIO_DATA, 0); | 4100 | AC_VERB_GET_GPIO_DATA, 0); |
4044 | gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask); | 4101 | gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask); |
@@ -4228,10 +4285,12 @@ static void stac_store_hints(struct hda_codec *codec) | |||
4228 | spec->eapd_switch = val; | 4285 | spec->eapd_switch = val; |
4229 | get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); | 4286 | get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); |
4230 | if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { | 4287 | if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { |
4231 | spec->gpio_mask |= spec->gpio_led; | 4288 | if (spec->gpio_led <= 8) { |
4232 | spec->gpio_dir |= spec->gpio_led; | 4289 | spec->gpio_mask |= spec->gpio_led; |
4233 | if (spec->gpio_led_polarity) | 4290 | spec->gpio_dir |= spec->gpio_led; |
4234 | spec->gpio_data |= spec->gpio_led; | 4291 | if (spec->gpio_led_polarity) |
4292 | spec->gpio_data |= spec->gpio_led; | ||
4293 | } | ||
4235 | } | 4294 | } |
4236 | } | 4295 | } |
4237 | 4296 | ||
@@ -4401,11 +4460,26 @@ static void stac92xx_free_kctls(struct hda_codec *codec) | |||
4401 | snd_array_free(&spec->kctls); | 4460 | snd_array_free(&spec->kctls); |
4402 | } | 4461 | } |
4403 | 4462 | ||
4463 | static void stac92xx_shutup_pins(struct hda_codec *codec) | ||
4464 | { | ||
4465 | unsigned int i, def_conf; | ||
4466 | |||
4467 | if (codec->bus->shutdown) | ||
4468 | return; | ||
4469 | for (i = 0; i < codec->init_pins.used; i++) { | ||
4470 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | ||
4471 | def_conf = snd_hda_codec_get_pincfg(codec, pin->nid); | ||
4472 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) | ||
4473 | snd_hda_codec_write(codec, pin->nid, 0, | ||
4474 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | ||
4475 | } | ||
4476 | } | ||
4477 | |||
4404 | static void stac92xx_shutup(struct hda_codec *codec) | 4478 | static void stac92xx_shutup(struct hda_codec *codec) |
4405 | { | 4479 | { |
4406 | struct sigmatel_spec *spec = codec->spec; | 4480 | struct sigmatel_spec *spec = codec->spec; |
4407 | 4481 | ||
4408 | snd_hda_shutup_pins(codec); | 4482 | stac92xx_shutup_pins(codec); |
4409 | 4483 | ||
4410 | if (spec->eapd_mask) | 4484 | if (spec->eapd_mask) |
4411 | stac_gpio_set(codec, spec->gpio_mask, | 4485 | stac_gpio_set(codec, spec->gpio_mask, |
@@ -4803,10 +4877,11 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) | |||
4803 | if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { | 4877 | if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { |
4804 | while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, | 4878 | while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, |
4805 | NULL, dev))) { | 4879 | NULL, dev))) { |
4806 | if (sscanf(dev->name, "HP_Mute_LED_%d_%d", | 4880 | if (sscanf(dev->name, "HP_Mute_LED_%d_%x", |
4807 | &spec->gpio_led_polarity, | 4881 | &spec->gpio_led_polarity, |
4808 | &spec->gpio_led) == 2) { | 4882 | &spec->gpio_led) == 2) { |
4809 | spec->gpio_led = 1 << spec->gpio_led; | 4883 | if (spec->gpio_led < 4) |
4884 | spec->gpio_led = 1 << spec->gpio_led; | ||
4810 | return 1; | 4885 | return 1; |
4811 | } | 4886 | } |
4812 | if (sscanf(dev->name, "HP_Mute_LED_%d", | 4887 | if (sscanf(dev->name, "HP_Mute_LED_%d", |
@@ -4904,7 +4979,7 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer, | |||
4904 | #define stac927x_proc_hook NULL | 4979 | #define stac927x_proc_hook NULL |
4905 | #endif | 4980 | #endif |
4906 | 4981 | ||
4907 | #ifdef SND_HDA_NEEDS_RESUME | 4982 | #ifdef CONFIG_PM |
4908 | static int stac92xx_resume(struct hda_codec *codec) | 4983 | static int stac92xx_resume(struct hda_codec *codec) |
4909 | { | 4984 | { |
4910 | struct sigmatel_spec *spec = codec->spec; | 4985 | struct sigmatel_spec *spec = codec->spec; |
@@ -4920,29 +4995,81 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
4920 | stac_issue_unsol_event(codec, | 4995 | stac_issue_unsol_event(codec, |
4921 | spec->autocfg.line_out_pins[0]); | 4996 | spec->autocfg.line_out_pins[0]); |
4922 | } | 4997 | } |
4998 | return 0; | ||
4999 | } | ||
5000 | |||
5001 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | ||
5002 | { | ||
5003 | stac92xx_shutup(codec); | ||
5004 | return 0; | ||
5005 | } | ||
5006 | |||
5007 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5008 | static int stac92xx_pre_resume(struct hda_codec *codec) | ||
5009 | { | ||
5010 | struct sigmatel_spec *spec = codec->spec; | ||
5011 | |||
4923 | /* sync mute LED */ | 5012 | /* sync mute LED */ |
4924 | if (spec->gpio_led) | 5013 | if (spec->gpio_led) { |
4925 | hda_call_check_power_status(codec, 0x01); | 5014 | if (spec->gpio_led <= 8) { |
5015 | stac_gpio_set(codec, spec->gpio_mask, | ||
5016 | spec->gpio_dir, spec->gpio_data); | ||
5017 | } else { | ||
5018 | stac_vrefout_set(codec, | ||
5019 | spec->gpio_led, spec->vref_led); | ||
5020 | } | ||
5021 | } | ||
5022 | return 0; | ||
5023 | } | ||
5024 | |||
5025 | static int stac92xx_post_suspend(struct hda_codec *codec) | ||
5026 | { | ||
5027 | struct sigmatel_spec *spec = codec->spec; | ||
5028 | if (spec->gpio_led > 8) { | ||
5029 | /* with vref-out pin used for mute led control | ||
5030 | * codec AFG is prevented from D3 state, but on | ||
5031 | * system suspend it can (and should) be used | ||
5032 | */ | ||
5033 | snd_hda_codec_read(codec, codec->afg, 0, | ||
5034 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
5035 | } | ||
4926 | return 0; | 5036 | return 0; |
4927 | } | 5037 | } |
4928 | 5038 | ||
5039 | static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, | ||
5040 | unsigned int power_state) | ||
5041 | { | ||
5042 | unsigned int afg_power_state = power_state; | ||
5043 | struct sigmatel_spec *spec = codec->spec; | ||
5044 | |||
5045 | if (power_state == AC_PWRST_D3) { | ||
5046 | if (spec->gpio_led > 8) { | ||
5047 | /* with vref-out pin used for mute led control | ||
5048 | * codec AFG is prevented from D3 state | ||
5049 | */ | ||
5050 | afg_power_state = AC_PWRST_D1; | ||
5051 | } | ||
5052 | /* this delay seems necessary to avoid click noise at power-down */ | ||
5053 | msleep(100); | ||
5054 | } | ||
5055 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | ||
5056 | afg_power_state); | ||
5057 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | ||
5058 | } | ||
5059 | |||
4929 | /* | 5060 | /* |
4930 | * using power check for controlling mute led of HP notebooks | 5061 | * For this feature CONFIG_SND_HDA_POWER_SAVE is needed |
4931 | * check for mute state only on Speakers (nid = 0x10) | 5062 | * as mute LED state is updated in check_power_status hook |
4932 | * | ||
4933 | * For this feature CONFIG_SND_HDA_POWER_SAVE is needed, otherwise | ||
4934 | * the LED is NOT working properly ! | ||
4935 | * | ||
4936 | * Changed name to reflect that it now works for any designated | ||
4937 | * model, not just HP HDX. | ||
4938 | */ | 5063 | */ |
4939 | 5064 | static int stac92xx_update_led_status(struct hda_codec *codec) | |
4940 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4941 | static int stac92xx_hp_check_power_status(struct hda_codec *codec, | ||
4942 | hda_nid_t nid) | ||
4943 | { | 5065 | { |
4944 | struct sigmatel_spec *spec = codec->spec; | 5066 | struct sigmatel_spec *spec = codec->spec; |
4945 | int i, muted = 1; | 5067 | int i, num_ext_dacs, muted = 1; |
5068 | unsigned int muted_lvl, notmtd_lvl; | ||
5069 | hda_nid_t nid; | ||
5070 | |||
5071 | if (!spec->gpio_led) | ||
5072 | return 0; | ||
4946 | 5073 | ||
4947 | for (i = 0; i < spec->multiout.num_dacs; i++) { | 5074 | for (i = 0; i < spec->multiout.num_dacs; i++) { |
4948 | nid = spec->multiout.dac_nids[i]; | 5075 | nid = spec->multiout.dac_nids[i]; |
@@ -4952,27 +5079,58 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, | |||
4952 | break; | 5079 | break; |
4953 | } | 5080 | } |
4954 | } | 5081 | } |
4955 | if (muted) | 5082 | if (muted && spec->multiout.hp_nid) |
4956 | spec->gpio_data &= ~spec->gpio_led; /* orange */ | 5083 | if (!(snd_hda_codec_amp_read(codec, |
4957 | else | 5084 | spec->multiout.hp_nid, 0, HDA_OUTPUT, 0) & |
4958 | spec->gpio_data |= spec->gpio_led; /* white */ | 5085 | HDA_AMP_MUTE)) { |
4959 | 5086 | muted = 0; /* HP is not muted */ | |
4960 | if (!spec->gpio_led_polarity) { | 5087 | } |
4961 | /* LED state is inverted on these systems */ | 5088 | num_ext_dacs = ARRAY_SIZE(spec->multiout.extra_out_nid); |
4962 | spec->gpio_data ^= spec->gpio_led; | 5089 | for (i = 0; muted && i < num_ext_dacs; i++) { |
5090 | nid = spec->multiout.extra_out_nid[i]; | ||
5091 | if (nid == 0) | ||
5092 | break; | ||
5093 | if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & | ||
5094 | HDA_AMP_MUTE)) { | ||
5095 | muted = 0; /* extra output is not muted */ | ||
5096 | } | ||
4963 | } | 5097 | } |
5098 | /*polarity defines *not* muted state level*/ | ||
5099 | if (spec->gpio_led <= 8) { | ||
5100 | if (muted) | ||
5101 | spec->gpio_data &= ~spec->gpio_led; /* orange */ | ||
5102 | else | ||
5103 | spec->gpio_data |= spec->gpio_led; /* white */ | ||
4964 | 5104 | ||
4965 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); | 5105 | if (!spec->gpio_led_polarity) { |
5106 | /* LED state is inverted on these systems */ | ||
5107 | spec->gpio_data ^= spec->gpio_led; | ||
5108 | } | ||
5109 | stac_gpio_set(codec, spec->gpio_mask, | ||
5110 | spec->gpio_dir, spec->gpio_data); | ||
5111 | } else { | ||
5112 | notmtd_lvl = spec->gpio_led_polarity ? | ||
5113 | AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_GRD; | ||
5114 | muted_lvl = spec->gpio_led_polarity ? | ||
5115 | AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; | ||
5116 | spec->vref_led = muted ? muted_lvl : notmtd_lvl; | ||
5117 | stac_vrefout_set(codec, spec->gpio_led, spec->vref_led); | ||
5118 | } | ||
4966 | return 0; | 5119 | return 0; |
4967 | } | 5120 | } |
4968 | #endif | ||
4969 | 5121 | ||
4970 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | 5122 | /* |
5123 | * use power check for controlling mute led of HP notebooks | ||
5124 | */ | ||
5125 | static int stac92xx_check_power_status(struct hda_codec *codec, | ||
5126 | hda_nid_t nid) | ||
4971 | { | 5127 | { |
4972 | stac92xx_shutup(codec); | 5128 | stac92xx_update_led_status(codec); |
5129 | |||
4973 | return 0; | 5130 | return 0; |
4974 | } | 5131 | } |
4975 | #endif | 5132 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ |
5133 | #endif /* CONFIG_PM */ | ||
4976 | 5134 | ||
4977 | static const struct hda_codec_ops stac92xx_patch_ops = { | 5135 | static const struct hda_codec_ops stac92xx_patch_ops = { |
4978 | .build_controls = stac92xx_build_controls, | 5136 | .build_controls = stac92xx_build_controls, |
@@ -4980,7 +5138,7 @@ static const struct hda_codec_ops stac92xx_patch_ops = { | |||
4980 | .init = stac92xx_init, | 5138 | .init = stac92xx_init, |
4981 | .free = stac92xx_free, | 5139 | .free = stac92xx_free, |
4982 | .unsol_event = stac92xx_unsol_event, | 5140 | .unsol_event = stac92xx_unsol_event, |
4983 | #ifdef SND_HDA_NEEDS_RESUME | 5141 | #ifdef CONFIG_PM |
4984 | .suspend = stac92xx_suspend, | 5142 | .suspend = stac92xx_suspend, |
4985 | .resume = stac92xx_resume, | 5143 | .resume = stac92xx_resume, |
4986 | #endif | 5144 | #endif |
@@ -5496,12 +5654,19 @@ again: | |||
5496 | 5654 | ||
5497 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5655 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
5498 | if (spec->gpio_led) { | 5656 | if (spec->gpio_led) { |
5499 | spec->gpio_mask |= spec->gpio_led; | 5657 | if (spec->gpio_led <= 8) { |
5500 | spec->gpio_dir |= spec->gpio_led; | 5658 | spec->gpio_mask |= spec->gpio_led; |
5501 | spec->gpio_data |= spec->gpio_led; | 5659 | spec->gpio_dir |= spec->gpio_led; |
5502 | /* register check_power_status callback. */ | 5660 | spec->gpio_data |= spec->gpio_led; |
5661 | } else { | ||
5662 | codec->patch_ops.set_power_state = | ||
5663 | stac92xx_set_power_state; | ||
5664 | codec->patch_ops.post_suspend = | ||
5665 | stac92xx_post_suspend; | ||
5666 | } | ||
5667 | codec->patch_ops.pre_resume = stac92xx_pre_resume; | ||
5503 | codec->patch_ops.check_power_status = | 5668 | codec->patch_ops.check_power_status = |
5504 | stac92xx_hp_check_power_status; | 5669 | stac92xx_check_power_status; |
5505 | } | 5670 | } |
5506 | #endif | 5671 | #endif |
5507 | 5672 | ||
@@ -5824,12 +5989,19 @@ again: | |||
5824 | 5989 | ||
5825 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5990 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
5826 | if (spec->gpio_led) { | 5991 | if (spec->gpio_led) { |
5827 | spec->gpio_mask |= spec->gpio_led; | 5992 | if (spec->gpio_led <= 8) { |
5828 | spec->gpio_dir |= spec->gpio_led; | 5993 | spec->gpio_mask |= spec->gpio_led; |
5829 | spec->gpio_data |= spec->gpio_led; | 5994 | spec->gpio_dir |= spec->gpio_led; |
5830 | /* register check_power_status callback. */ | 5995 | spec->gpio_data |= spec->gpio_led; |
5996 | } else { | ||
5997 | codec->patch_ops.set_power_state = | ||
5998 | stac92xx_set_power_state; | ||
5999 | codec->patch_ops.post_suspend = | ||
6000 | stac92xx_post_suspend; | ||
6001 | } | ||
6002 | codec->patch_ops.pre_resume = stac92xx_pre_resume; | ||
5831 | codec->patch_ops.check_power_status = | 6003 | codec->patch_ops.check_power_status = |
5832 | stac92xx_hp_check_power_status; | 6004 | stac92xx_check_power_status; |
5833 | } | 6005 | } |
5834 | #endif | 6006 | #endif |
5835 | 6007 | ||