[ALSA] hda-codec - Add auto-mute function to Sony VAIO with STAC9872
[pandora-kernel.git] / sound / pci / hda / patch_sigmatel.c
index 3f25de7..76ec32a 100644 (file)
@@ -44,7 +44,9 @@ enum {
 
 enum {
        STAC_9205_REF,
-       STAC_M43xx,
+       STAC_9205_DELL_M43,
+       STAC_9205_DELL_M44,
+       STAC_9205_M43xx,
        STAC_9205_MODELS
 };
 
@@ -80,6 +82,7 @@ enum {
        STAC_D965_REF,
        STAC_D965_3ST,
        STAC_D965_5ST,
+       STAC_DELL_3ST,
        STAC_927X_MODELS
 };
 
@@ -95,6 +98,8 @@ struct sigmatel_spec {
        unsigned int hp_detect: 1;
        unsigned int gpio_mute: 1;
 
+       unsigned int gpio_mask, gpio_data;
+
        /* playback */
        struct hda_multi_out multiout;
        hda_nid_t dac_nids[5];
@@ -717,16 +722,25 @@ static unsigned int d965_5st_pin_configs[14] = {
        0x40000100, 0x40000100
 };
 
+static unsigned int dell_3st_pin_configs[14] = {
+       0x02211230, 0x02a11220, 0x01a19040, 0x01114210,
+       0x01111212, 0x01116211, 0x01813050, 0x01112214,
+       0x403003fa, 0x40000100, 0x40000100, 0x404003fb,
+       0x40c003fc, 0x40000100
+};
+
 static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {
        [STAC_D965_REF] = ref927x_pin_configs,
        [STAC_D965_3ST] = d965_3st_pin_configs,
        [STAC_D965_5ST] = d965_5st_pin_configs,
+       [STAC_DELL_3ST] = dell_3st_pin_configs,
 };
 
 static const char *stac927x_models[STAC_927X_MODELS] = {
        [STAC_D965_REF] = "ref",
        [STAC_D965_3ST] = "3stack",
        [STAC_D965_5ST] = "5stack",
+       [STAC_DELL_3ST] = "dell-3stack",
 };
 
 static struct snd_pci_quirk stac927x_cfg_tbl[] = {
@@ -753,6 +767,10 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST),
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST),
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST),
+       /* Dell 3 stack systems */
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01dd, "Dell E520", STAC_DELL_3ST),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01ed, "Dell     ", STAC_DELL_3ST),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f4, "Dell     ", STAC_DELL_3ST),
        /* 965 based 5 stack systems */
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST),
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST),
@@ -772,23 +790,58 @@ static unsigned int ref9205_pin_configs[12] = {
        0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030
 };
 
+static unsigned int dell_m43_9205_pin_configs[12] = {
+       0x0321101f, 0x03a11020, 0x90a70330, 0x90170310,
+       0x400000fe, 0x400000ff, 0x400000fd, 0x40f000f9,
+       0x400000fa, 0x400000fc, 0x0144131f, 0x40c003f8,
+};
+
+static unsigned int dell_m44_9205_pin_configs[12] = {
+       0x0421101f, 0x04a11020, 0x400003fa, 0x90170310,
+       0x400003fb, 0x400003fc, 0x400003fd, 0x400003f9,
+       0x90a60330, 0x400003ff, 0x01441340, 0x40c003fe,
+};
+
+
 static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
-       [STAC_REF] = ref9205_pin_configs,
-       [STAC_M43xx] = NULL,
+       [STAC_9205_REF] = ref9205_pin_configs,
+       [STAC_9205_DELL_M43] = dell_m43_9205_pin_configs,
+       [STAC_9205_DELL_M44] = dell_m44_9205_pin_configs,
+       [STAC_9205_M43xx] = NULL,
 };
 
 static const char *stac9205_models[STAC_9205_MODELS] = {
        [STAC_9205_REF] = "ref",
+       [STAC_9205_DELL_M43] = "dell-m43",
+       [STAC_9205_DELL_M44] = "dell-m44",
 };
 
 static struct snd_pci_quirk stac9205_cfg_tbl[] = {
        /* SigmaTel reference board */
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
                      "DFI LanParty", STAC_9205_REF),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01f8,
-                     "Dell Precision", STAC_M43xx),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01ff,
-                     "Dell Precision", STAC_M43xx),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f8,
+                     "Dell Precision", STAC_9205_M43xx),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f9,
+                     "Dell Precision", STAC_9205_DELL_M43),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fa,
+                     "Dell Precision", STAC_9205_DELL_M43),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fe,
+                     "Dell Precision", STAC_9205_DELL_M43),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ff,
+                     "Dell Precision", STAC_9205_DELL_M43),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206,
+                     "Dell Precision", STAC_9205_DELL_M43),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1,
+                     "Dell Inspiron", STAC_9205_DELL_M44),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2,
+                     "Dell Inspiron", STAC_9205_DELL_M44),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc,
+                     "Dell Inspiron", STAC_9205_DELL_M44),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd,
+                     "Dell Inspiron", STAC_9205_DELL_M44),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f,
+                     "Dell Inspiron", STAC_9205_DELL_M44),
        {} /* terminator */
 };
 
@@ -854,20 +907,20 @@ static void stac92xx_set_config_regs(struct hda_codec *codec)
                                        spec->pin_configs[i]);
 }
 
-static void stac92xx_enable_gpio_mask(struct hda_codec *codec,
-                                     int gpio_mask, int gpio_data)
+static void stac92xx_enable_gpio_mask(struct hda_codec *codec)
 {
+       struct sigmatel_spec *spec = codec->spec;
        /* Configure GPIOx as output */
-       snd_hda_codec_write(codec, codec->afg, 0,
-                           AC_VERB_SET_GPIO_DIRECTION, gpio_mask);
+       snd_hda_codec_write_cache(codec, codec->afg, 0,
+                                 AC_VERB_SET_GPIO_DIRECTION, spec->gpio_mask);
        /* Configure GPIOx as CMOS */
-       snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000);
+       snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7e7, 0x00000000);
        /* Assert GPIOx */
-       snd_hda_codec_write(codec, codec->afg, 0,
-                           AC_VERB_SET_GPIO_DATA, gpio_data);
+       snd_hda_codec_write_cache(codec, codec->afg, 0,
+                                 AC_VERB_SET_GPIO_DATA, spec->gpio_data);
        /* Enable GPIOx */
-       snd_hda_codec_write(codec, codec->afg, 0,
-                           AC_VERB_SET_GPIO_MASK, gpio_mask);
+       snd_hda_codec_write_cache(codec, codec->afg, 0,
+                                 AC_VERB_SET_GPIO_MASK, spec->gpio_mask);
 }
 
 /*
@@ -1066,17 +1119,11 @@ static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid)
 static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type)
 
 {
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+       snd_hda_codec_write_cache(codec, nid, 0,
+                                 AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
 }
 
-static int stac92xx_io_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       uinfo->count = 1;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 1;
-       return 0;
-}
+#define stac92xx_io_switch_info                snd_ctl_boolean_mono_info
 
 static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
@@ -1282,8 +1329,8 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
                spec->multiout.num_dacs++;
                if (conn_len > 1) {
                        /* select this DAC in the pin's input mux */
-                       snd_hda_codec_write(codec, nid, 0,
-                                           AC_VERB_SET_CONNECT_SEL, j);
+                       snd_hda_codec_write_cache(codec, nid, 0,
+                                                 AC_VERB_SET_CONNECT_SEL, j);
 
                }
        }
@@ -1536,9 +1583,9 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
                 * NID lists.  Hopefully this won't get confused.
                 */
                for (i = 0; i < spec->num_muxes; i++) {
-                       snd_hda_codec_write(codec, spec->mux_nids[i], 0,
-                                           AC_VERB_SET_CONNECT_SEL,
-                                           imux->items[0].index);
+                       snd_hda_codec_write_cache(codec, spec->mux_nids[i], 0,
+                                                 AC_VERB_SET_CONNECT_SEL,
+                                                 imux->items[0].index);
                }
        }
 
@@ -1870,7 +1917,7 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
        if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))
                pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
        
-       snd_hda_codec_write(codec, nid, 0,
+       snd_hda_codec_write_cache(codec, nid, 0,
                        AC_VERB_SET_PIN_WIDGET_CONTROL,
                        pin_ctl | flag);
 }
@@ -1880,7 +1927,7 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
 {
        unsigned int pin_ctl = snd_hda_codec_read(codec, nid,
                        0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
-       snd_hda_codec_write(codec, nid, 0,
+       snd_hda_codec_write_cache(codec, nid, 0,
                        AC_VERB_SET_PIN_WIDGET_CONTROL,
                        pin_ctl & ~flag);
 }
@@ -1936,22 +1983,13 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
        }
 }
 
-#ifdef CONFIG_PM
+#ifdef SND_HDA_NEEDS_RESUME
 static int stac92xx_resume(struct hda_codec *codec)
 {
-       struct sigmatel_spec *spec = codec->spec;
-       int i;
-
-       stac92xx_init(codec);
        stac92xx_set_config_regs(codec);
-       snd_hda_resume_ctls(codec, spec->mixer);
-       for (i = 0; i < spec->num_mixers; i++)
-               snd_hda_resume_ctls(codec, spec->mixers[i]);
-       if (spec->multiout.dig_out_nid)
-               snd_hda_resume_spdif_out(codec);
-       if (spec->dig_in_nid)
-               snd_hda_resume_spdif_in(codec);
-
+       stac92xx_init(codec);
+       snd_hda_codec_resume_amp(codec);
+       snd_hda_codec_resume_cache(codec);
        return 0;
 }
 #endif
@@ -1962,7 +2000,7 @@ static struct hda_codec_ops stac92xx_patch_ops = {
        .init = stac92xx_init,
        .free = stac92xx_free,
        .unsol_event = stac92xx_unsol_event,
-#ifdef CONFIG_PM
+#ifdef SND_HDA_NEEDS_RESUME
        .resume = stac92xx_resume,
 #endif
 };
@@ -2247,7 +2285,8 @@ static int patch_stac927x(struct hda_codec *codec)
 
        spec->multiout.dac_nids = spec->dac_nids;
        /* GPIO0 High = Enable EAPD */
-       stac92xx_enable_gpio_mask(codec, 0x00000001, 0x00000001);
+       spec->gpio_mask = spec->gpio_data = 0x00000001;
+       stac92xx_enable_gpio_mask(codec); 
        
        err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);
        if (!err) {
@@ -2272,7 +2311,7 @@ static int patch_stac927x(struct hda_codec *codec)
 static int patch_stac9205(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec;
-       int err, gpio_mask, gpio_data;
+       int err;
 
        spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
@@ -2310,20 +2349,26 @@ static int patch_stac9205(struct hda_codec *codec)
 
        spec->multiout.dac_nids = spec->dac_nids;
        
-       if (spec->board_config == STAC_M43xx) {
+       switch (spec->board_config){
+       case STAC_9205_M43xx:
+       case STAC_9205_DELL_M43:
                /* Enable SPDIF in/out */
                stac92xx_set_config_reg(codec, 0x1f, 0x01441030);
                stac92xx_set_config_reg(codec, 0x20, 0x1c410030);
 
-               gpio_mask = 0x00000007; /* GPIO0-2 */
+               spec->gpio_mask = 0x00000007; /* GPIO0-2 */
                /* GPIO0 High = EAPD, GPIO1 Low = DRM,
                 * GPIO2 High = Headphone Mute
                 */
-               gpio_data = 0x00000005;
-       } else
-               gpio_mask = gpio_data = 0x00000001; /* GPIO0 High = EAPD */
+               spec->gpio_data = 0x00000005;
+               break;
+       default:
+               /* GPIO0 High = EAPD */
+               spec->gpio_mask = spec->gpio_data = 0x00000001;
+               break;
+       }
 
-       stac92xx_enable_gpio_mask(codec, gpio_mask, gpio_data);
+       stac92xx_enable_gpio_mask(codec);
        err = stac92xx_parse_auto_config(codec, 0x1f, 0x20);
        if (!err) {
                if (spec->board_config < 0) {
@@ -2366,6 +2411,7 @@ static struct hda_input_mux vaio_mux = {
 
 static struct hda_verb vaio_init[] = {
        {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */
+       {0x0a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | STAC_HP_EVENT},
        {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */
        {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */
        {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
@@ -2397,61 +2443,28 @@ static struct hda_verb vaio_ar_init[] = {
 };
 
 /* bind volumes of both NID 0x02 and 0x05 */
-static int vaio_master_vol_put(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       long *valp = ucontrol->value.integer.value;
-       int change;
-
-       change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0,
-                                         0x7f, valp[0] & 0x7f);
-       change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0,
-                                          0x7f, valp[1] & 0x7f);
-       snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,
-                                0x7f, valp[0] & 0x7f);
-       snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,
-                                0x7f, valp[1] & 0x7f);
-       return change;
-}
+static struct hda_bind_ctls vaio_bind_master_vol = {
+       .ops = &snd_hda_bind_vol,
+       .values = {
+               HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
+               0
+       },
+};
 
 /* bind volumes of both NID 0x02 and 0x05 */
-static int vaio_master_sw_put(struct snd_kcontrol *kcontrol,
-                             struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       long *valp = ucontrol->value.integer.value;
-       int change;
-
-       change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0,
-                                         0x80, (valp[0] ? 0 : 0x80));
-       change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0,
-                                          0x80, (valp[1] ? 0 : 0x80));
-       snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,
-                                0x80, (valp[0] ? 0 : 0x80));
-       snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,
-                                0x80, (valp[1] ? 0 : 0x80));
-       return change;
-}
+static struct hda_bind_ctls vaio_bind_master_sw = {
+       .ops = &snd_hda_bind_sw,
+       .values = {
+               HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
+               HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
+               0,
+       },
+};
 
 static struct snd_kcontrol_new vaio_mixer[] = {
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Master Playback Volume",
-               .info = snd_hda_mixer_amp_volume_info,
-               .get = snd_hda_mixer_amp_volume_get,
-               .put = vaio_master_vol_put,
-               .tlv = { .c = snd_hda_mixer_amp_tlv },
-               .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
-       },
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Master Playback Switch",
-               .info = snd_hda_mixer_amp_switch_info,
-               .get = snd_hda_mixer_amp_switch_get,
-               .put = vaio_master_sw_put,
-               .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
-       },
+       HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol),
+       HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw),
        /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
        HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
        HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
@@ -2467,22 +2480,8 @@ static struct snd_kcontrol_new vaio_mixer[] = {
 };
 
 static struct snd_kcontrol_new vaio_ar_mixer[] = {
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Master Playback Volume",
-               .info = snd_hda_mixer_amp_volume_info,
-               .get = snd_hda_mixer_amp_volume_get,
-               .put = vaio_master_vol_put,
-               .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
-       },
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Master Playback Switch",
-               .info = snd_hda_mixer_amp_switch_info,
-               .get = snd_hda_mixer_amp_switch_get,
-               .put = vaio_master_sw_put,
-               .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
-       },
+       HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol),
+       HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw),
        /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
        HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
        HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
@@ -2504,6 +2503,49 @@ static struct hda_codec_ops stac9872_patch_ops = {
        .build_pcms = stac92xx_build_pcms,
        .init = stac92xx_init,
        .free = stac92xx_free,
+#ifdef SND_HDA_NEEDS_RESUME
+       .resume = stac92xx_resume,
+#endif
+};
+
+static int stac9872_vaio_init(struct hda_codec *codec)
+{
+       int err;
+
+       err = stac92xx_init(codec);
+       if (err < 0)
+               return err;
+       if (codec->patch_ops.unsol_event)
+               codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+       return 0;
+}
+
+static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res)
+{
+       if (get_pin_presence(codec, 0x0a)) {
+               stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
+               stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
+       } else {
+               stac92xx_reset_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
+               stac92xx_set_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
+       }
+} 
+
+static void stac9872_vaio_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+       switch (res >> 26) {
+       case STAC_HP_EVENT:
+               stac9872_vaio_hp_detect(codec, res);
+               break;
+       }
+}
+
+static struct hda_codec_ops stac9872_vaio_patch_ops = {
+       .build_controls = stac92xx_build_controls,
+       .build_pcms = stac92xx_build_pcms,
+       .init = stac9872_vaio_init,
+       .free = stac92xx_free,
+       .unsol_event = stac9872_vaio_unsol_event,
 #ifdef CONFIG_PM
        .resume = stac92xx_resume,
 #endif
@@ -2564,6 +2606,7 @@ static int patch_stac9872(struct hda_codec *codec)
                spec->adc_nids = vaio_adcs;
                spec->input_mux = &vaio_mux;
                spec->mux_nids = vaio_mux_nids;
+               codec->patch_ops = stac9872_vaio_patch_ops;
                break;
        
        case CXD9872AKD_VAIO:
@@ -2577,10 +2620,10 @@ static int patch_stac9872(struct hda_codec *codec)
                spec->adc_nids = vaio_adcs;
                spec->input_mux = &vaio_mux;
                spec->mux_nids = vaio_mux_nids;
+               codec->patch_ops = stac9872_patch_ops;
                break;
        }
 
-       codec->patch_ops = stac9872_patch_ops;
        return 0;
 }