int invert = (kcontrol->private_value >> 8) & 1;
        hda_nid_t nid = kcontrol->private_value & 0xff;
        unsigned int eapd;
-       eapd = ucontrol->value.integer.value[0];
+       eapd = !!ucontrol->value.integer.value[0];
        if (invert)
                eapd = !eapd;
        if (eapd == spec->cur_eapd)
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct ad198x_spec *spec = codec->spec;
 
+       if (ucontrol->value.enumerated.item[0] > 1)
+               return -EINVAL;
        if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
                spec->spdif_route = ucontrol->value.enumerated.item[0];
                snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
        int change;
 
        val = ucontrol->value.enumerated.item[0];
+       if (val > 3)
+               return -EINVAL;
        if (!val) {
                sel = snd_hda_codec_read(codec, 0x1d, 0,
                                         AC_VERB_GET_AMP_GAIN_MUTE,
 
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct sigmatel_spec *spec = codec->spec;
        unsigned int dac_mode;
+       unsigned int val;
 
-       if (spec->aloopback == ucontrol->value.integer.value[0])
+       val = !!ucontrol->value.integer.value[0];
+       if (spec->aloopback == val)
                return 0;
 
-       spec->aloopback = ucontrol->value.integer.value[0];
-
+       spec->aloopback = val;
 
        dac_mode = snd_hda_codec_read(codec, codec->afg, 0,
                kcontrol->private_value & 0xFFFF, 0x0);
        return 1;
 }
 
+static int stac92xx_volknob_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 127;
+       return 0;
+}
+
+static int stac92xx_volknob_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.integer.value[0] = kcontrol->private_value & 0xff;
+       return 0;
+}
+
+static int stac92xx_volknob_put(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       unsigned int oval = kcontrol->private_value & 0xff;
+       unsigned int val;
+
+       val = ucontrol->value.integer.value[0] & 0xff;
+       if (val == oval)
+               return 0;
+
+       kcontrol->private_value &= ~0xff;
+       kcontrol->private_value |= val;
+
+       snd_hda_codec_write_cache(codec, kcontrol->private_value >> 16, 0,
+               AC_VERB_SET_VOLUME_KNOB_CONTROL, val | 0x80);
+       return 1;
+}
+
 static struct hda_verb stac9200_core_init[] = {
        /* set dac0mux for dac converter */
        { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
        struct sigmatel_spec *spec = codec->spec;
         hda_nid_t nid = kcontrol->private_value >> 8;
        int io_idx = kcontrol-> private_value & 0xff;
-        unsigned short val = ucontrol->value.integer.value[0];
+       unsigned short val = !!ucontrol->value.integer.value[0];
 
        spec->io_switch[io_idx] = val;
 
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct sigmatel_spec *spec = codec->spec;
        hda_nid_t nid = kcontrol->private_value & 0xff;
+       unsigned int val = !!ucontrol->value.integer.value[0];
 
-       if (spec->clfe_swap == ucontrol->value.integer.value[0])
+       if (spec->clfe_swap == val)
                return 0;
 
-       spec->clfe_swap = ucontrol->value.integer.value[0];
+       spec->clfe_swap = val;
 
        snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
                spec->clfe_swap ? 0x4 : 0x0);