Merge branch 'fix/hda' into topic/hda
[pandora-kernel.git] / sound / pci / hda / patch_sigmatel.c
index abc44db..b3c53f7 100644 (file)
@@ -40,6 +40,7 @@ enum {
        STAC_INSERT_EVENT,
        STAC_PWR_EVENT,
        STAC_HP_EVENT,
+       STAC_LO_EVENT,
        STAC_MIC_EVENT,
 };
 
@@ -1793,6 +1794,8 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
                                "Dell Studio 1537", STAC_DELL_M6_DMIC),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a0,
                                "Dell Studio 17", STAC_DELL_M6_DMIC),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02be,
+                               "Dell Studio 1555", STAC_DELL_M6_DMIC),
        {} /* terminator */
 };
 
@@ -2248,7 +2251,7 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0227, "Dell Vostro 1400  ", STAC_DELL_BIOS),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022e, "Dell     ", STAC_DELL_BIOS),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022f, "Dell Inspiron 1525", STAC_DELL_3ST),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022f, "Dell Inspiron 1525", STAC_DELL_BIOS),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0242, "Dell     ", STAC_DELL_BIOS),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0243, "Dell     ", STAC_DELL_BIOS),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x02ff, "Dell     ", STAC_DELL_BIOS),
@@ -3307,11 +3310,11 @@ static int stac92xx_add_capvol_ctls(struct hda_codec *codec, unsigned long vol,
 {
        int err;
        err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx,
-                                      "Captuer Volume", vol);
+                                      "Capture Volume", vol);
        if (err < 0)
                return err;
        err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_MUTE, idx,
-                                      "Captuer Switch", sw);
+                                      "Capture Switch", sw);
        if (err < 0)
                return err;
        return 0;
@@ -4345,6 +4348,14 @@ static int stac92xx_init(struct hda_codec *codec)
                        hda_nid_t nid = cfg->hp_pins[i];
                        enable_pin_detect(codec, nid, STAC_HP_EVENT);
                }
+               if (cfg->line_out_type == AUTO_PIN_LINE_OUT) {
+                       /* enable pin-detect for line-outs as well */
+                       for (i = 0; i < cfg->hp_outs; i++) {
+                               hda_nid_t nid = cfg->hp_pins[i];
+                               enable_pin_detect(codec, nid, STAC_LO_EVENT);
+                       }
+               }
+
                /* force to enable the first line-out; the others are set up
                 * in unsol_event
                 */
@@ -4359,6 +4370,9 @@ static int stac92xx_init(struct hda_codec *codec)
                        stac_toggle_power_map(codec, cfg->hp_pins[i], 1);
        }
        if (spec->auto_mic) {
+               /* initialize connection to analog input */
+               snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0,
+                                         AC_VERB_SET_CONNECT_SEL, 0);
                if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT))
                        stac_issue_unsol_event(codec, spec->ext_mic.pin);
        }
@@ -4540,6 +4554,48 @@ static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
        return 0;
 }
 
+static void stac92xx_line_out_detect(struct hda_codec *codec,
+                                    int presence)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       int i;
+
+       for (i = 0; i < cfg->line_outs; i++) {
+               if (presence)
+                       break;
+               presence = get_pin_presence(codec, cfg->line_out_pins[i]);
+               if (presence) {
+                       unsigned int pinctl;
+                       pinctl = snd_hda_codec_read(codec,
+                                                   cfg->line_out_pins[i], 0,
+                                           AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+                       if (pinctl & AC_PINCTL_IN_EN)
+                               presence = 0; /* mic- or line-input */
+               }
+       }
+
+       if (presence) {
+               /* disable speakers */
+               for (i = 0; i < cfg->speaker_outs; i++)
+                       stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
+                                               AC_PINCTL_OUT_EN);
+               if (spec->eapd_mask && spec->eapd_switch)
+                       stac_gpio_set(codec, spec->gpio_mask,
+                               spec->gpio_dir, spec->gpio_data &
+                               ~spec->eapd_mask);
+       } else {
+               /* enable speakers */
+               for (i = 0; i < cfg->speaker_outs; i++)
+                       stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
+                                               AC_PINCTL_OUT_EN);
+               if (spec->eapd_mask && spec->eapd_switch)
+                       stac_gpio_set(codec, spec->gpio_mask,
+                               spec->gpio_dir, spec->gpio_data |
+                               spec->eapd_mask);
+       }
+} 
+
 /* return non-zero if the hp-pin of the given array index isn't
  * a jack-detection target
  */
@@ -4592,13 +4648,6 @@ static void stac92xx_hp_detect(struct hda_codec *codec)
                for (i = 0; i < cfg->line_outs; i++)
                        stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
                                                AC_PINCTL_OUT_EN);
-               for (i = 0; i < cfg->speaker_outs; i++)
-                       stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
-                                               AC_PINCTL_OUT_EN);
-               if (spec->eapd_mask && spec->eapd_switch)
-                       stac_gpio_set(codec, spec->gpio_mask,
-                               spec->gpio_dir, spec->gpio_data &
-                               ~spec->eapd_mask);
        } else {
                /* enable lineouts */
                if (spec->hp_switch)
@@ -4607,14 +4656,8 @@ static void stac92xx_hp_detect(struct hda_codec *codec)
                for (i = 0; i < cfg->line_outs; i++)
                        stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
                                                AC_PINCTL_OUT_EN);
-               for (i = 0; i < cfg->speaker_outs; i++)
-                       stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
-                                               AC_PINCTL_OUT_EN);
-               if (spec->eapd_mask && spec->eapd_switch)
-                       stac_gpio_set(codec, spec->gpio_mask,
-                               spec->gpio_dir, spec->gpio_data |
-                               spec->eapd_mask);
        }
+       stac92xx_line_out_detect(codec, presence);
        /* toggle hp outs */
        for (i = 0; i < cfg->hp_outs; i++) {
                unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN;
@@ -4741,6 +4784,9 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
        case STAC_HP_EVENT:
                stac92xx_hp_detect(codec);
                break;
+       case STAC_LO_EVENT:
+               stac92xx_line_out_detect(codec, 0);
+               break;
        case STAC_MIC_EVENT:
                stac92xx_mic_detect(codec);
                break;
@@ -4748,6 +4794,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
 
        switch (event->type) {
        case STAC_HP_EVENT:
+       case STAC_LO_EVENT:
        case STAC_MIC_EVENT:
        case STAC_INSERT_EVENT:
        case STAC_PWR_EVENT:
@@ -5478,8 +5525,6 @@ again:
                }
                break;
        case 0x111d7608: /* 5 Port with Analog Mixer */
-               memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
-                      sizeof(stac92hd71bxx_dmux_amixer));
                spec->private_dimux.num_items--;
                switch (spec->board_config) {
                case STAC_HP_M4:
@@ -5502,9 +5547,15 @@ again:
 
                /* no output amps */
                spec->num_pwrs = 0;
-               if (snd_hda_get_bool_hint(codec, "analog_mixer") == 1)
+               if (snd_hda_get_bool_hint(codec, "analog_mixer") == 1) {
                        spec->mixer = stac92hd71bxx_analog_mixer;
-
+                       memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
+                              sizeof(stac92hd71bxx_dmux_amixer));
+               } else {
+                       memcpy(&spec->private_dimux,
+                              &stac92hd71bxx_dmux_nomixer,
+                              sizeof(stac92hd71bxx_dmux_nomixer));
+               }
                /* disable VSW */
                spec->init = stac92hd71bxx_core_init;
                unmute_init++;
@@ -5528,10 +5579,15 @@ again:
                spec->num_pwrs = 0;
                /* fallthru */
        default:
-               memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
-                      sizeof(stac92hd71bxx_dmux_amixer));
-               if (snd_hda_get_bool_hint(codec, "analog_mixer") == 1)
+               if (snd_hda_get_bool_hint(codec, "analog_mixer") == 1) {
                        spec->mixer = stac92hd71bxx_analog_mixer;
+                       memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
+                              sizeof(stac92hd71bxx_dmux_amixer));
+               } else {
+                       memcpy(&spec->private_dimux,
+                              &stac92hd71bxx_dmux_nomixer,
+                              sizeof(stac92hd71bxx_dmux_nomixer));
+               }
                spec->init = stac92hd71bxx_core_init;
                codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
                spec->num_dmics = stac92hd71bxx_connected_ports(codec,
@@ -5814,6 +5870,13 @@ static int patch_stac927x(struct hda_codec *codec)
                /* GPIO2 High = Enable EAPD */
                spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x04;
                spec->gpio_data = 0x04;
+               switch (codec->subsystem_id) {
+               case 0x1028022f:
+                       /* correct EAPD to be GPIO0 */
+                       spec->eapd_mask = spec->gpio_mask = 0x01;
+                       spec->gpio_dir = spec->gpio_data = 0x01;
+                       break;
+               };
                spec->dmic_nids = stac927x_dmic_nids;
                spec->num_dmics = STAC927X_NUM_DMICS;