diff options
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 95 |
1 files changed, 68 insertions, 27 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 6b0bc040c3b..e66672317e5 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -209,6 +209,7 @@ struct sigmatel_spec { unsigned int gpio_data; unsigned int gpio_mute; unsigned int gpio_led; + unsigned int gpio_led_polarity; /* stream */ unsigned int stream_delay; @@ -4724,13 +4725,61 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) } } -static int hp_bseries_system(u32 subsystem_id) +/* + * This method searches for the mute LED GPIO configuration + * provided as OEM string in SMBIOS. The format of that string + * is HP_Mute_LED_P_G or HP_Mute_LED_P + * where P can be 0 or 1 and defines mute LED GPIO control state (low/high) + * that corresponds to the NOT muted state of the master volume + * and G is the index of the GPIO to use as the mute LED control (0..9) + * If _G portion is missing it is assigned based on the codec ID + * + * So, HP B-series like systems may have HP_Mute_LED_0 (current models) + * or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings + */ +static int find_mute_led_gpio(struct hda_codec *codec) +{ + struct sigmatel_spec *spec = codec->spec; + const struct dmi_device *dev = NULL; + + if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { + while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, + NULL, dev))) { + if (sscanf(dev->name, "HP_Mute_LED_%d_%d", + &spec->gpio_led_polarity, + &spec->gpio_led) == 2) { + spec->gpio_led = 1 << spec->gpio_led; + return 1; + } + if (sscanf(dev->name, "HP_Mute_LED_%d", + &spec->gpio_led_polarity) == 1) { + switch (codec->vendor_id) { + case 0x111d7608: + /* GPIO 0 */ + spec->gpio_led = 0x01; + return 1; + case 0x111d7600: + case 0x111d7601: + case 0x111d7602: + case 0x111d7603: + /* GPIO 3 */ + spec->gpio_led = 0x08; + return 1; + } + } + } + } + return 0; +} + +static int hp_blike_system(u32 subsystem_id) { switch (subsystem_id) { - case 0x103c307e: - case 0x103c307f: - case 0x103c3080: - case 0x103c3081: + case 0x103c1520: + case 0x103c1521: + case 0x103c1523: + case 0x103c1524: + case 0x103c1525: case 0x103c1722: case 0x103c1723: case 0x103c1724: @@ -4739,6 +4788,14 @@ static int hp_bseries_system(u32 subsystem_id) case 0x103c1727: case 0x103c1728: case 0x103c1729: + case 0x103c172a: + case 0x103c172b: + case 0x103c307e: + case 0x103c307f: + case 0x103c3080: + case 0x103c3081: + case 0x103c7007: + case 0x103c7008: return 1; } return 0; @@ -4833,7 +4890,7 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, else spec->gpio_data |= spec->gpio_led; /* white */ - if (hp_bseries_system(codec->subsystem_id)) { + if (!spec->gpio_led_polarity) { /* LED state is inverted on these systems */ spec->gpio_data ^= spec->gpio_led; } @@ -5526,7 +5583,7 @@ again: break; } - if (hp_bseries_system(codec->subsystem_id)) { + if (hp_blike_system(codec->subsystem_id)) { pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f); if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT || get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER || @@ -5544,26 +5601,10 @@ again: } } - if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { - const struct dmi_device *dev = NULL; - while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, - NULL, dev))) { - if (strcmp(dev->name, "HP_Mute_LED_1")) { - switch (codec->vendor_id) { - case 0x111d7608: - spec->gpio_led = 0x01; - break; - case 0x111d7600: - case 0x111d7601: - case 0x111d7602: - case 0x111d7603: - spec->gpio_led = 0x08; - break; - } - break; - } - } - } + if (find_mute_led_gpio(codec)) + snd_printd("mute LED gpio %d polarity %d\n", + spec->gpio_led, + spec->gpio_led_polarity); #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { |