ALSA: hda - Overwrite pin config on intel DG45ID board.
[safe/jmp/linux-2.6] / sound / pci / hda / patch_sigmatel.c
index 2a45375..3d59f83 100644 (file)
@@ -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;
@@ -1538,6 +1539,13 @@ static unsigned int alienware_m17x_pin_configs[13] = {
        0x904601b0,
 };
 
+static unsigned int intel_dg45id_pin_configs[14] = {
+       0x02214230, 0x02A19240, 0x01013214, 0x01014210,
+       0x01A19250, 0x01011212, 0x01016211, 0x40f000f0,
+       0x40f000f0, 0x40f000f0, 0x40f000f0, 0x014510A0,
+       0x074510B0, 0x40f000f0
+};
+
 static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
        [STAC_92HD73XX_REF]     = ref92hd73xx_pin_configs,
        [STAC_DELL_M6_AMIC]     = dell_m6_pin_configs,
@@ -1545,6 +1553,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
        [STAC_DELL_M6_BOTH]     = dell_m6_pin_configs,
        [STAC_DELL_EQ]  = dell_m6_pin_configs,
        [STAC_ALIENWARE_M17X]   = alienware_m17x_pin_configs,
+       [STAC_92HD73XX_INTEL]   = intel_dg45id_pin_configs,
 };
 
 static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
@@ -4440,7 +4449,14 @@ static inline int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
 {
        if (!nid)
                return 0;
-       return snd_hda_jack_detect(codec, nid);
+       /* NOTE: we can't use snd_hda_jack_detect() here because STAC/IDT
+        * codecs behave wrongly when SET_PIN_SENSE is triggered, although
+        * the pincap gives TRIG_REQ bit.
+        */
+       if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0) &
+           AC_PINSENSE_PRESENCE)
+               return 1;
+       return 0;
 }
 
 static void stac92xx_line_out_detect(struct hda_codec *codec,
@@ -4717,13 +4733,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:
@@ -4732,6 +4796,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;
@@ -4826,7 +4898,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;
                }
@@ -5519,7 +5591,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  ||
@@ -5537,26 +5609,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) {