ALSA: hda - fix DG45ID SPDIF output
[safe/jmp/linux-2.6] / sound / pci / hda / patch_sigmatel.c
index 693dd14..12825aa 100644 (file)
@@ -1544,11 +1544,9 @@ static unsigned int alienware_m17x_pin_configs[13] = {
        0x904601b0,
 };
 
-static unsigned int intel_dg45id_pin_configs[14] = {
+static unsigned int intel_dg45id_pin_configs[13] = {
        0x02214230, 0x02A19240, 0x01013214, 0x01014210,
-       0x01A19250, 0x01011212, 0x01016211, 0x40f000f0,
-       0x40f000f0, 0x40f000f0, 0x40f000f0, 0x014510A0,
-       0x074510B0, 0x40f000f0
+       0x01A19250, 0x01011212, 0x01016211
 };
 
 static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
@@ -1607,6 +1605,10 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
                                "Dell Studio 1555", STAC_DELL_M6_DMIC),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd,
                                "Dell Studio 1557", STAC_DELL_M6_DMIC),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe,
+                               "Dell Studio XPS 1645", STAC_DELL_M6_BOTH),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413,
+                               "Dell Studio 1558", STAC_DELL_M6_BOTH),
        {} /* terminator */
 };
 
@@ -1730,6 +1732,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
                      "HP HDX", STAC_HP_HDX),  /* HDX16 */
        SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3620,
                      "HP dv6", STAC_HP_DV5),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061,
+                     "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */
        SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010,
                      "HP", STAC_HP_DV5),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
@@ -4363,6 +4367,12 @@ static int stac92xx_init(struct hda_codec *codec)
                if (enable_pin_detect(codec, nid, STAC_PWR_EVENT))
                        stac_issue_unsol_event(codec, nid);
        }
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       /* sync mute LED */
+       if (spec->gpio_led && codec->patch_ops.check_power_status)
+               codec->patch_ops.check_power_status(codec, 0x01);
+#endif 
        if (spec->dac_list)
                stac92xx_power_down(codec);
        return 0;
@@ -4754,19 +4764,14 @@ static int hp_blike_system(u32 subsystem_id);
 static void set_hp_led_gpio(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
-       switch (codec->vendor_id) {
-       case 0x111d7608:
-               /* GPIO 0 */
-               spec->gpio_led = 0x01;
-               break;
-       case 0x111d7600:
-       case 0x111d7601:
-       case 0x111d7602:
-       case 0x111d7603:
-               /* GPIO 3 */
-               spec->gpio_led = 0x08;
-               break;
-       }
+       unsigned int gpio;
+
+       gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP);
+       gpio &= AC_GPIO_IO_COUNT;
+       if (gpio > 3)
+               spec->gpio_led = 0x08; /* GPIO 3 */
+       else
+               spec->gpio_led = 0x01; /* GPIO 0 */
 }
 
 /*
@@ -4789,7 +4794,7 @@ static void set_hp_led_gpio(struct hda_codec *codec)
  * Need more information on whether it is true across the entire series.
  * -- kunal
  */
-static int find_mute_led_gpio(struct hda_codec *codec)
+static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity)
 {
        struct sigmatel_spec *spec = codec->spec;
        const struct dmi_device *dev = NULL;
@@ -4816,7 +4821,7 @@ static int find_mute_led_gpio(struct hda_codec *codec)
                 */
                if (!hp_blike_system(codec->subsystem_id)) {
                        set_hp_led_gpio(codec);
-                       spec->gpio_led_polarity = 1;
+                       spec->gpio_led_polarity = default_polarity;
                        return 1;
                }
        }
@@ -4914,6 +4919,11 @@ static int stac92xx_resume(struct hda_codec *codec)
                        stac_issue_unsol_event(codec,
                                               spec->autocfg.line_out_pins[0]);
        }
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       /* sync mute LED */
+       if (spec->gpio_led && codec->patch_ops.check_power_status)
+               codec->patch_ops.check_power_status(codec, 0x01);
+#endif 
        return 0;
 }
 
@@ -4933,43 +4943,29 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec,
                                              hda_nid_t nid)
 {
        struct sigmatel_spec *spec = codec->spec;
+       int i, muted = 1;
 
-       if (nid == 0x10) {
-               if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
-                   HDA_AMP_MUTE)
-                       spec->gpio_data &= ~spec->gpio_led; /* orange */
-               else
-                       spec->gpio_data |= spec->gpio_led; /* white */
-
-               if (!spec->gpio_led_polarity) {
-                       /* LED state is inverted on these systems */
-                       spec->gpio_data ^= spec->gpio_led;
+       for (i = 0; i < spec->multiout.num_dacs; i++) {
+               nid = spec->multiout.dac_nids[i];
+               if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
+                     HDA_AMP_MUTE)) {
+                       muted = 0; /* something heard */
+                       break;
                }
-
-               stac_gpio_set(codec, spec->gpio_mask,
-                             spec->gpio_dir,
-                             spec->gpio_data);
        }
+       if (muted)
+               spec->gpio_data &= ~spec->gpio_led; /* orange */
+       else
+               spec->gpio_data |= spec->gpio_led; /* white */
 
-       return 0;
-}
-
-static int idt92hd83xxx_hp_check_power_status(struct hda_codec *codec,
-                                             hda_nid_t nid)
-{
-       struct sigmatel_spec *spec = codec->spec;
+       if (!spec->gpio_led_polarity) {
+               /* LED state is inverted on these systems */
+               spec->gpio_data ^= spec->gpio_led;
+       }
 
-       if (nid != 0x13)
-               return 0;
-       if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & HDA_AMP_MUTE)
-               spec->gpio_data |= spec->gpio_led; /* mute LED on */
-       else
-               spec->gpio_data &= ~spec->gpio_led; /* mute LED off */
        stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
-
        return 0;
 }
-
 #endif
 
 static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
@@ -5291,7 +5287,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
        hda_nid_t conn[STAC92HD83_DAC_COUNT + 1];
        int err;
        int num_dacs;
-       hda_nid_t nid;
 
        spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
@@ -5352,10 +5347,7 @@ again:
 
        codec->patch_ops = stac92xx_patch_ops;
 
-       if (spec->board_config == STAC_92HD83XXX_HP)
-               spec->gpio_led = 0x01;
-
-       if (find_mute_led_gpio(codec))
+       if (find_mute_led_gpio(codec, 0))
                snd_printd("mute LED gpio %d polarity %d\n",
                                spec->gpio_led,
                                spec->gpio_led_polarity);
@@ -5367,7 +5359,7 @@ again:
                spec->gpio_data |= spec->gpio_led;
                /* register check_power_status callback. */
                codec->patch_ops.check_power_status =
-                       idt92hd83xxx_hp_check_power_status;
+                       stac92xx_hp_check_power_status;
        }
 #endif 
 
@@ -5387,24 +5379,21 @@ again:
                return err;
        }
 
-       switch (spec->board_config) {
-       case STAC_DELL_S14:
-               nid = 0xf;
-               break;
-       default:
-               nid = 0xe;
-               break;
-       }
-
-       num_dacs = snd_hda_get_connections(codec, nid,
+       /* docking output support */
+       num_dacs = snd_hda_get_connections(codec, 0xF,
                                conn, STAC92HD83_DAC_COUNT + 1) - 1;
-       if (num_dacs < 0)
-               num_dacs = STAC92HD83_DAC_COUNT;
-
-       /* set port X to select the last DAC
-        */
-       snd_hda_codec_write_cache(codec, nid, 0,
+       /* skip non-DAC connections */
+       while (num_dacs >= 0 &&
+                       (get_wcaps_type(get_wcaps(codec, conn[num_dacs]))
+                                       != AC_WID_AUD_OUT))
+               num_dacs--;
+       /* set port E and F to select the last DAC */
+       if (num_dacs >= 0) {
+               snd_hda_codec_write_cache(codec, 0xE, 0,
                        AC_VERB_SET_CONNECT_SEL, num_dacs);
+               snd_hda_codec_write_cache(codec, 0xF, 0,
+                       AC_VERB_SET_CONNECT_SEL, num_dacs);
+       }
 
        codec->proc_widget_hook = stac92hd_proc_hook;
 
@@ -5685,7 +5674,6 @@ again:
                 */
                spec->num_smuxes = 1;
                spec->num_dmuxes = 1;
-               spec->gpio_led = 0x01;
                /* fallthrough */
        case STAC_HP_DV5:
                snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010);
@@ -5700,8 +5688,6 @@ again:
                spec->num_dmics = 1;
                spec->num_dmuxes = 1;
                spec->num_smuxes = 1;
-               /* orange/white mute led on GPIO3, orange=0, white=1 */
-               spec->gpio_led = 0x08;
                break;
        }
 
@@ -5723,7 +5709,7 @@ again:
                }
        }
 
-       if (find_mute_led_gpio(codec))
+       if (find_mute_led_gpio(codec, 1))
                snd_printd("mute LED gpio %d polarity %d\n",
                                spec->gpio_led,
                                spec->gpio_led_polarity);