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 6b0bc040c3b1..e66672317e57 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -209,6 +209,7 @@ struct sigmatel_spec { | |||
209 | unsigned int gpio_data; | 209 | unsigned int gpio_data; |
210 | unsigned int gpio_mute; | 210 | unsigned int gpio_mute; |
211 | unsigned int gpio_led; | 211 | unsigned int gpio_led; |
212 | unsigned int gpio_led_polarity; | ||
212 | 213 | ||
213 | /* stream */ | 214 | /* stream */ |
214 | unsigned int stream_delay; | 215 | unsigned int stream_delay; |
@@ -4724,13 +4725,61 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
4724 | } | 4725 | } |
4725 | } | 4726 | } |
4726 | 4727 | ||
4727 | static int hp_bseries_system(u32 subsystem_id) | 4728 | /* |
4729 | * This method searches for the mute LED GPIO configuration | ||
4730 | * provided as OEM string in SMBIOS. The format of that string | ||
4731 | * is HP_Mute_LED_P_G or HP_Mute_LED_P | ||
4732 | * where P can be 0 or 1 and defines mute LED GPIO control state (low/high) | ||
4733 | * that corresponds to the NOT muted state of the master volume | ||
4734 | * and G is the index of the GPIO to use as the mute LED control (0..9) | ||
4735 | * If _G portion is missing it is assigned based on the codec ID | ||
4736 | * | ||
4737 | * So, HP B-series like systems may have HP_Mute_LED_0 (current models) | ||
4738 | * or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings | ||
4739 | */ | ||
4740 | static int find_mute_led_gpio(struct hda_codec *codec) | ||
4741 | { | ||
4742 | struct sigmatel_spec *spec = codec->spec; | ||
4743 | const struct dmi_device *dev = NULL; | ||
4744 | |||
4745 | if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { | ||
4746 | while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, | ||
4747 | NULL, dev))) { | ||
4748 | if (sscanf(dev->name, "HP_Mute_LED_%d_%d", | ||
4749 | &spec->gpio_led_polarity, | ||
4750 | &spec->gpio_led) == 2) { | ||
4751 | spec->gpio_led = 1 << spec->gpio_led; | ||
4752 | return 1; | ||
4753 | } | ||
4754 | if (sscanf(dev->name, "HP_Mute_LED_%d", | ||
4755 | &spec->gpio_led_polarity) == 1) { | ||
4756 | switch (codec->vendor_id) { | ||
4757 | case 0x111d7608: | ||
4758 | /* GPIO 0 */ | ||
4759 | spec->gpio_led = 0x01; | ||
4760 | return 1; | ||
4761 | case 0x111d7600: | ||
4762 | case 0x111d7601: | ||
4763 | case 0x111d7602: | ||
4764 | case 0x111d7603: | ||
4765 | /* GPIO 3 */ | ||
4766 | spec->gpio_led = 0x08; | ||
4767 | return 1; | ||
4768 | } | ||
4769 | } | ||
4770 | } | ||
4771 | } | ||
4772 | return 0; | ||
4773 | } | ||
4774 | |||
4775 | static int hp_blike_system(u32 subsystem_id) | ||
4728 | { | 4776 | { |
4729 | switch (subsystem_id) { | 4777 | switch (subsystem_id) { |
4730 | case 0x103c307e: | 4778 | case 0x103c1520: |
4731 | case 0x103c307f: | 4779 | case 0x103c1521: |
4732 | case 0x103c3080: | 4780 | case 0x103c1523: |
4733 | case 0x103c3081: | 4781 | case 0x103c1524: |
4782 | case 0x103c1525: | ||
4734 | case 0x103c1722: | 4783 | case 0x103c1722: |
4735 | case 0x103c1723: | 4784 | case 0x103c1723: |
4736 | case 0x103c1724: | 4785 | case 0x103c1724: |
@@ -4739,6 +4788,14 @@ static int hp_bseries_system(u32 subsystem_id) | |||
4739 | case 0x103c1727: | 4788 | case 0x103c1727: |
4740 | case 0x103c1728: | 4789 | case 0x103c1728: |
4741 | case 0x103c1729: | 4790 | case 0x103c1729: |
4791 | case 0x103c172a: | ||
4792 | case 0x103c172b: | ||
4793 | case 0x103c307e: | ||
4794 | case 0x103c307f: | ||
4795 | case 0x103c3080: | ||
4796 | case 0x103c3081: | ||
4797 | case 0x103c7007: | ||
4798 | case 0x103c7008: | ||
4742 | return 1; | 4799 | return 1; |
4743 | } | 4800 | } |
4744 | return 0; | 4801 | return 0; |
@@ -4833,7 +4890,7 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, | |||
4833 | else | 4890 | else |
4834 | spec->gpio_data |= spec->gpio_led; /* white */ | 4891 | spec->gpio_data |= spec->gpio_led; /* white */ |
4835 | 4892 | ||
4836 | if (hp_bseries_system(codec->subsystem_id)) { | 4893 | if (!spec->gpio_led_polarity) { |
4837 | /* LED state is inverted on these systems */ | 4894 | /* LED state is inverted on these systems */ |
4838 | spec->gpio_data ^= spec->gpio_led; | 4895 | spec->gpio_data ^= spec->gpio_led; |
4839 | } | 4896 | } |
@@ -5526,7 +5583,7 @@ again: | |||
5526 | break; | 5583 | break; |
5527 | } | 5584 | } |
5528 | 5585 | ||
5529 | if (hp_bseries_system(codec->subsystem_id)) { | 5586 | if (hp_blike_system(codec->subsystem_id)) { |
5530 | pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f); | 5587 | pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f); |
5531 | if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT || | 5588 | if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT || |
5532 | get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER || | 5589 | get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER || |
@@ -5544,26 +5601,10 @@ again: | |||
5544 | } | 5601 | } |
5545 | } | 5602 | } |
5546 | 5603 | ||
5547 | if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { | 5604 | if (find_mute_led_gpio(codec)) |
5548 | const struct dmi_device *dev = NULL; | 5605 | snd_printd("mute LED gpio %d polarity %d\n", |
5549 | while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, | 5606 | spec->gpio_led, |
5550 | NULL, dev))) { | 5607 | spec->gpio_led_polarity); |
5551 | if (strcmp(dev->name, "HP_Mute_LED_1")) { | ||
5552 | switch (codec->vendor_id) { | ||
5553 | case 0x111d7608: | ||
5554 | spec->gpio_led = 0x01; | ||
5555 | break; | ||
5556 | case 0x111d7600: | ||
5557 | case 0x111d7601: | ||
5558 | case 0x111d7602: | ||
5559 | case 0x111d7603: | ||
5560 | spec->gpio_led = 0x08; | ||
5561 | break; | ||
5562 | } | ||
5563 | break; | ||
5564 | } | ||
5565 | } | ||
5566 | } | ||
5567 | 5608 | ||
5568 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5609 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
5569 | if (spec->gpio_led) { | 5610 | if (spec->gpio_led) { |