]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - sound/pci/hda/patch_via.c
Merge branch 'master' into tk71
[mv-sheeva.git] / sound / pci / hda / patch_via.c
index ae3acb2b42d11366a2d24bd768d823dbc61853b4..63b0054200a878e3d879f259f3ad5134ba7e7682 100644 (file)
@@ -263,8 +263,7 @@ static void vt1708_stop_hp_work(struct via_spec *spec)
                return;
        snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
                            !spec->vt1708_jack_detectect);
-       cancel_delayed_work(&spec->vt1708_hp_work);
-       flush_scheduled_work();
+       cancel_delayed_work_sync(&spec->vt1708_hp_work);
 }
 
 
@@ -444,8 +443,8 @@ static hda_nid_t vt1812_adc_nids[2] = {
 
 
 /* add dynamic controls */
-static int via_add_control(struct via_spec *spec, int type, const char *name,
-                          unsigned long val)
+static int __via_add_control(struct via_spec *spec, int type, const char *name,
+                            int idx, unsigned long val)
 {
        struct snd_kcontrol_new *knew;
 
@@ -463,6 +462,9 @@ static int via_add_control(struct via_spec *spec, int type, const char *name,
        return 0;
 }
 
+#define via_add_control(spec, type, name, val) \
+       __via_add_control(spec, type, name, 0, val)
+
 static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec,
                                                struct snd_kcontrol_new *tmpl)
 {
@@ -494,18 +496,18 @@ static void via_free_kctls(struct hda_codec *codec)
 
 /* create input playback/capture controls for the given pin */
 static int via_new_analog_input(struct via_spec *spec, const char *ctlname,
-                               int idx, int mix_nid)
+                               int type_idx, int idx, int mix_nid)
 {
        char name[32];
        int err;
 
        sprintf(name, "%s Playback Volume", ctlname);
-       err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+       err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx,
                              HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
        if (err < 0)
                return err;
        sprintf(name, "%s Playback Switch", ctlname);
-       err = via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name,
+       err = __via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, type_idx,
                              HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
        if (err < 0)
                return err;
@@ -557,17 +559,15 @@ static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin);
 static void via_auto_init_analog_input(struct hda_codec *codec)
 {
        struct via_spec *spec = codec->spec;
+       const struct auto_pin_cfg *cfg = &spec->autocfg;
        unsigned int ctl;
        int i;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[i];
-               if (!nid)
-                       continue;
-
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
                if (spec->smart51_enabled && is_smart51_pins(spec, nid))
                        ctl = PIN_OUT;
-               else if (i <= AUTO_PIN_FRONT_MIC)
+               else if (cfg->inputs[i].type == AUTO_PIN_MIC)
                        ctl = PIN_VREF50;
                else
                        ctl = PIN_IN;
@@ -1322,15 +1322,14 @@ static void mute_aa_path(struct hda_codec *codec, int mute)
 }
 static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin)
 {
-       int res = 0;
-       int index;
-       for (index = AUTO_PIN_MIC; index < AUTO_PIN_FRONT_LINE; index++) {
-               if (pin == spec->autocfg.input_pins[index]) {
-                       res = 1;
-                       break;
-               }
+       const struct auto_pin_cfg *cfg = &spec->autocfg;
+       int i;
+
+       for (i = 0; i < cfg->num_inputs; i++) {
+               if (pin == cfg->inputs[i].pin)
+                       return cfg->inputs[i].type <= AUTO_PIN_LINE_IN;
        }
-       return res;
+       return 0;
 }
 
 static int via_smart51_info(struct snd_kcontrol *kcontrol,
@@ -1348,25 +1347,21 @@ static int via_smart51_get(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct via_spec *spec = codec->spec;
-       int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE };
+       const struct auto_pin_cfg *cfg = &spec->autocfg;
        int on = 1;
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(index); i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[index[i]];
-               if (nid) {
-                       int ctl =
-                           snd_hda_codec_read(codec, nid, 0,
-                                              AC_VERB_GET_PIN_WIDGET_CONTROL,
-                                              0);
-                       if (i == AUTO_PIN_FRONT_MIC
-                           && spec->hp_independent_mode
-                           && spec->codec_type != VT1718S)
-                               continue; /* ignore FMic for independent HP */
-                       if (ctl & AC_PINCTL_IN_EN
-                           && !(ctl & AC_PINCTL_OUT_EN))
-                               on = 0;
-               }
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
+               int ctl = snd_hda_codec_read(codec, nid, 0,
+                                            AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+               if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
+                       continue;
+               if (cfg->inputs[i].type == AUTO_PIN_MIC &&
+                   spec->hp_independent_mode && spec->codec_type != VT1718S)
+                       continue; /* ignore FMic for independent HP */
+               if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN))
+                       on = 0;
        }
        *ucontrol->value.integer.value = on;
        return 0;
@@ -1377,36 +1372,38 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct via_spec *spec = codec->spec;
+       const struct auto_pin_cfg *cfg = &spec->autocfg;
        int out_in = *ucontrol->value.integer.value
                ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN;
-       int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE };
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(index); i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[index[i]];
-               if (i == AUTO_PIN_FRONT_MIC
-                   && spec->hp_independent_mode
-                   && spec->codec_type != VT1718S)
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
+               unsigned int parm;
+
+               if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
+                       continue;
+               if (cfg->inputs[i].type == AUTO_PIN_MIC &&
+                   spec->hp_independent_mode && spec->codec_type != VT1718S)
                        continue; /* don't retask FMic for independent HP */
-               if (nid) {
-                       unsigned int parm = snd_hda_codec_read(
-                               codec, nid, 0,
-                               AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-                       parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
-                       parm |= out_in;
-                       snd_hda_codec_write(codec, nid, 0,
-                                           AC_VERB_SET_PIN_WIDGET_CONTROL,
-                                           parm);
-                       if (out_in == AC_PINCTL_OUT_EN) {
-                               mute_aa_path(codec, 1);
-                               notify_aa_path_ctls(codec);
-                       }
-                       if (spec->codec_type == VT1718S)
-                               snd_hda_codec_amp_stereo(
+
+               parm = snd_hda_codec_read(codec, nid, 0,
+                                         AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+               parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
+               parm |= out_in;
+               snd_hda_codec_write(codec, nid, 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                   parm);
+               if (out_in == AC_PINCTL_OUT_EN) {
+                       mute_aa_path(codec, 1);
+                       notify_aa_path_ctls(codec);
+               }
+               if (spec->codec_type == VT1718S) {
+                       snd_hda_codec_amp_stereo(
                                        codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE,
                                        HDA_AMP_UNMUTE);
                }
-               if (i == AUTO_PIN_FRONT_MIC) {
+               if (cfg->inputs[i].type == AUTO_PIN_MIC) {
                        if (spec->codec_type == VT1708S
                            || spec->codec_type == VT1716S) {
                                /* input = index 1 (AOW3) */
@@ -1442,7 +1439,7 @@ static struct snd_kcontrol_new via_smart51_mixer[2] = {
 static int via_smart51_build(struct via_spec *spec)
 {
        struct snd_kcontrol_new *knew;
-       int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE };
+       const struct auto_pin_cfg *cfg = &spec->autocfg;
        hda_nid_t nid;
        int i;
 
@@ -1450,13 +1447,14 @@ static int via_smart51_build(struct via_spec *spec)
        if (knew == NULL)
                return -ENOMEM;
 
-       for (i = 0; i < ARRAY_SIZE(index); i++) {
-               nid = spec->autocfg.input_pins[index[i]];
-               if (nid) {
+       for (i = 0; i < cfg->num_inputs; i++) {
+               nid = cfg->inputs[i].pin;
+               if (cfg->inputs[i].type <= AUTO_PIN_LINE_IN) {
                        knew = via_clone_control(spec, &via_smart51_mixer[1]);
                        if (knew == NULL)
                                return -ENOMEM;
                        knew->subdevice = nid;
+                       break;
                }
        }
 
@@ -2283,7 +2281,9 @@ static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
                                             const struct auto_pin_cfg *cfg)
 {
        char name[32];
-       static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
+       static const char * const chname[4] = {
+               "Front", "Surround", "C/LFE", "Side"
+       };
        hda_nid_t nid, nid_vol, nid_vols[] = {0x17, 0x19, 0x1a, 0x1b};
        int i, err;
 
@@ -2372,16 +2372,11 @@ static void create_hp_imux(struct via_spec *spec)
 {
        int i;
        struct hda_input_mux *imux = &spec->private_imux[1];
-       static const char *texts[] = { "OFF", "ON", NULL};
+       static const char * const texts[] = { "OFF", "ON", NULL};
 
        /* for hp mode select */
-       i = 0;
-       while (texts[i] != NULL) {
-               imux->items[imux->num_items].label =  texts[i];
-               imux->items[imux->num_items].index = i;
-               imux->num_items++;
-               i++;
-       }
+       for (i = 0; texts[i]; i++)
+               snd_hda_add_imux_item(imux, texts[i], i, NULL);
 
        spec->hp_mux = &spec->private_imux[1];
 }
@@ -2413,51 +2408,53 @@ static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
-                                               const struct auto_pin_cfg *cfg)
+static int vt_auto_create_analog_input_ctls(struct hda_codec *codec,
+                                           const struct auto_pin_cfg *cfg,
+                                           hda_nid_t cap_nid,
+                                           hda_nid_t pin_idxs[], int num_idxs)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
+       struct via_spec *spec = codec->spec;
        struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
+       int i, err, idx, type, type_idx = 0;
 
        /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = idx;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x1d: /* Mic */
-                       idx = 2;
-                       break;
-
-               case 0x1e: /* Line In */
-                       idx = 3;
-                       break;
-
-               case 0x21: /* Front Mic */
-                       idx = 4;
-                       break;
-
-               case 0x24: /* CD */
-                       idx = 1;
+       for (idx = 0; idx < num_idxs; idx++) {
+               if (pin_idxs[idx] == 0xff) {
+                       snd_hda_add_imux_item(imux, "Stereo Mixer", idx, NULL);
                        break;
                }
-               err = via_new_analog_input(spec, labels[i], idx, 0x17);
+       }
+
+       for (i = 0; i < cfg->num_inputs; i++) {
+               const char *label;
+               type = cfg->inputs[i].type;
+               for (idx = 0; idx < num_idxs; idx++)
+                       if (pin_idxs[idx] == cfg->inputs[i].pin)
+                               break;
+               if (idx >= num_idxs)
+                       continue;
+               if (i > 0 && type == cfg->inputs[i - 1].type)
+                       type_idx++;
+               else
+                       type_idx = 0;
+               label = hda_get_autocfg_input_label(codec, cfg, i);
+               err = via_new_analog_input(spec, label, type_idx, idx, cap_nid);
                if (err < 0)
                        return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx;
-               imux->num_items++;
+               snd_hda_add_imux_item(imux, label, idx, NULL);
        }
        return 0;
 }
 
+/* create playback/capture controls for input pins */
+static int vt1708_auto_create_analog_input_ctls(struct hda_codec *codec,
+                                               const struct auto_pin_cfg *cfg)
+{
+       static hda_nid_t pin_idxs[] = { 0xff, 0x24, 0x1d, 0x1e, 0x21 };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x17, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
+}
+
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 static struct hda_amp_list vt1708_loopbacks[] = {
        { 0x17, HDA_INPUT, 1 },
@@ -2554,7 +2551,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec)
        err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1708_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
        /* add jack detect on/off control */
@@ -2895,7 +2892,9 @@ static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
                                             const struct auto_pin_cfg *cfg)
 {
        char name[32];
-       static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
+       static const char * const chname[4] = {
+               "Front", "Surround", "C/LFE", "Side"
+       };
        hda_nid_t nid, nid_vol, nid_vols[] = {0x18, 0x1a, 0x1b, 0x29};
        int i, err;
 
@@ -3021,49 +3020,12 @@ static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1709_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = idx;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x1d: /* Mic */
-                       idx = 2;
-                       break;
-
-               case 0x1e: /* Line In */
-                       idx = 3;
-                       break;
-
-               case 0x21: /* Front Mic */
-                       idx = 4;
-                       break;
-
-               case 0x23: /* CD */
-                       idx = 1;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x18);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx;
-               imux->num_items++;
-       }
-       return 0;
+       static hda_nid_t pin_idxs[] = { 0xff, 0x23, 0x1d, 0x1e, 0x21 };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x18, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
 }
 
 static int vt1709_parse_auto_config(struct hda_codec *codec)
@@ -3086,7 +3048,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
        err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1709_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -3475,7 +3437,9 @@ static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec,
                                             const struct auto_pin_cfg *cfg)
 {
        char name[32];
-       static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
+       static const char * const chname[4] = {
+               "Front", "Surround", "C/LFE", "Side"
+       };
        hda_nid_t nid_vols[] = {0x16, 0x18, 0x26, 0x27};
        hda_nid_t nid, nid_vol = 0;
        int i, err;
@@ -3588,49 +3552,12 @@ static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1708B_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = idx;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x1a: /* Mic */
-                       idx = 2;
-                       break;
-
-               case 0x1b: /* Line In */
-                       idx = 3;
-                       break;
-
-               case 0x1e: /* Front Mic */
-                       idx = 4;
-                       break;
-
-               case 0x1f: /* CD */
-                       idx = 1;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x16);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx;
-               imux->num_items++;
-       }
-       return 0;
+       static hda_nid_t pin_idxs[] = { 0xff, 0x1f, 0x1a, 0x1b, 0x1e };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
 }
 
 static int vt1708B_parse_auto_config(struct hda_codec *codec)
@@ -3653,7 +3580,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec)
        err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1708B_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -3940,7 +3867,9 @@ static int vt1708S_auto_create_multi_out_ctls(struct via_spec *spec,
                                             const struct auto_pin_cfg *cfg)
 {
        char name[32];
-       static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
+       static const char * const chname[4] = {
+               "Front", "Surround", "C/LFE", "Side"
+       };
        hda_nid_t nid_vols[] = {0x10, 0x11, 0x24, 0x25};
        hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x26, 0x27};
        hda_nid_t nid, nid_vol, nid_mute;
@@ -4061,49 +3990,12 @@ static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1708S_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = 5;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x1a: /* Mic */
-                       idx = 2;
-                       break;
-
-               case 0x1b: /* Line In */
-                       idx = 3;
-                       break;
-
-               case 0x1e: /* Front Mic */
-                       idx = 4;
-                       break;
-
-               case 0x1f: /* CD */
-                       idx = 1;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x16);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx-1;
-               imux->num_items++;
-       }
-       return 0;
+       static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
 }
 
 /* fill out digital output widgets; one for master and one for slave outputs */
@@ -4151,7 +4043,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
        err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1708S_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1708S_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -4420,7 +4312,7 @@ static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 {
        int err, i;
        struct hda_input_mux *imux;
-       static const char *texts[] = { "ON", "OFF", NULL};
+       static const char * const texts[] = { "ON", "OFF", NULL};
        if (!pin)
                return 0;
        spec->multiout.hp_nid = 0x1D;
@@ -4441,58 +4333,20 @@ static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
        imux = &spec->private_imux[1];
 
        /* for hp mode select */
-       i = 0;
-       while (texts[i] != NULL)        {
-               imux->items[imux->num_items].label =  texts[i];
-               imux->items[imux->num_items].index = i;
-               imux->num_items++;
-               i++;
-       }
+       for (i = 0; texts[i]; i++)
+               snd_hda_add_imux_item(imux, texts[i], i, NULL);
 
        spec->hp_mux = &spec->private_imux[1];
        return 0;
 }
 
 /* create playback/capture controls for input pins */
-static int vt1702_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1702_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = 3;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x14: /* Mic */
-                       idx = 1;
-                       break;
-
-               case 0x15: /* Line In */
-                       idx = 2;
-                       break;
-
-               case 0x18: /* Front Mic */
-                       idx = 3;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x1A);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx-1;
-               imux->num_items++;
-       }
-       return 0;
+       static hda_nid_t pin_idxs[] = { 0x14, 0x15, 0x18, 0xff };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x1a, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
 }
 
 static int vt1702_parse_auto_config(struct hda_codec *codec)
@@ -4521,7 +4375,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
                                  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
                                  (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
                                  (1 << AC_AMPCAP_MUTE_SHIFT));
-       err = vt1702_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1702_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -4769,7 +4623,9 @@ static int vt1718S_auto_create_multi_out_ctls(struct via_spec *spec,
                                             const struct auto_pin_cfg *cfg)
 {
        char name[32];
-       static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
+       static const char * const chname[4] = {
+               "Front", "Surround", "C/LFE", "Side"
+       };
        hda_nid_t nid_vols[] = {0x8, 0x9, 0xa, 0xb};
        hda_nid_t nid_mutes[] = {0x24, 0x25, 0x26, 0x27};
        hda_nid_t nid, nid_vol, nid_mute = 0;
@@ -4872,49 +4728,12 @@ static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1718S_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1718S_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = 5;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x2b: /* Mic */
-                       idx = 1;
-                       break;
-
-               case 0x2a: /* Line In */
-                       idx = 2;
-                       break;
-
-               case 0x29: /* Front Mic */
-                       idx = 3;
-                       break;
-
-               case 0x2c: /* CD */
-                       idx = 0;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x21);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx;
-               imux->num_items++;
-       }
-       return 0;
+       static hda_nid_t pin_idxs[] = { 0x2c, 0x2b, 0x2a, 0x29, 0, 0xff };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
 }
 
 static int vt1718S_parse_auto_config(struct hda_codec *codec)
@@ -4938,7 +4757,7 @@ static int vt1718S_parse_auto_config(struct hda_codec *codec)
        err = vt1718S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1718S_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1718S_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -5255,7 +5074,9 @@ static int vt1716S_auto_create_multi_out_ctls(struct via_spec *spec,
                                              const struct auto_pin_cfg *cfg)
 {
        char name[32];
-       static const char *chname[3] = { "Front", "Surround", "C/LFE" };
+       static const char * const chname[3] = {
+               "Front", "Surround", "C/LFE"
+       };
        hda_nid_t nid_vols[] = {0x10, 0x11, 0x25};
        hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x27};
        hda_nid_t nid, nid_vol, nid_mute;
@@ -5371,49 +5192,12 @@ static int vt1716S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1716S_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1716S_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = 5;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x1a: /* Mic */
-                       idx = 2;
-                       break;
-
-               case 0x1b: /* Line In */
-                       idx = 3;
-                       break;
-
-               case 0x1e: /* Front Mic */
-                       idx = 4;
-                       break;
-
-               case 0x1f: /* CD */
-                       idx = 1;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x16);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx-1;
-               imux->num_items++;
-       }
-       return 0;
+       static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
 }
 
 static int vt1716S_parse_auto_config(struct hda_codec *codec)
@@ -5436,7 +5220,7 @@ static int vt1716S_parse_auto_config(struct hda_codec *codec)
        err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1716S_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1716S_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -5717,54 +5501,25 @@ static int vt2002P_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt2002P_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt2002P_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
+       struct via_spec *spec = codec->spec;
        struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x2b: /* Mic */
-                       idx = 0;
-                       break;
-
-               case 0x2a: /* Line In */
-                       idx = 1;
-                       break;
-
-               case 0x29: /* Front Mic */
-                       idx = 2;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x21);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx;
-               imux->num_items++;
-       }
+       static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0xff };
+       int err;
 
+       err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
+                                              ARRAY_SIZE(pin_idxs));
+       if (err < 0)
+               return err;
        /* build volume/mute control of loopback */
-       err = via_new_analog_input(spec, "Stereo Mixer", 3, 0x21);
+       err = via_new_analog_input(spec, "Stereo Mixer", 0, 3, 0x21);
        if (err < 0)
                return err;
 
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = 3;
-       imux->num_items++;
-
        /* for digital mic select */
-       imux->items[imux->num_items].label = "Digital Mic";
-       imux->items[imux->num_items].index = 4;
-       imux->num_items++;
+       snd_hda_add_imux_item(imux, "Digital Mic", 4, NULL);
 
        return 0;
 }
@@ -5792,7 +5547,7 @@ static int vt2002P_parse_auto_config(struct hda_codec *codec)
        err = vt2002P_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt2002P_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt2002P_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -6067,53 +5822,26 @@ static int vt1812_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1812_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1812_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
+       struct via_spec *spec = codec->spec;
        struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x2b: /* Mic */
-                       idx = 0;
-                       break;
+       static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0, 0, 0xff };
+       int err;
 
-               case 0x2a: /* Line In */
-                       idx = 1;
-                       break;
+       err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
+                                              ARRAY_SIZE(pin_idxs));
+       if (err < 0)
+               return err;
 
-               case 0x29: /* Front Mic */
-                       idx = 2;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x21);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx;
-               imux->num_items++;
-       }
        /* build volume/mute control of loopback */
-       err = via_new_analog_input(spec, "Stereo Mixer", 5, 0x21);
+       err = via_new_analog_input(spec, "Stereo Mixer", 0, 5, 0x21);
        if (err < 0)
                return err;
 
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = 5;
-       imux->num_items++;
-
        /* for digital mic select */
-       imux->items[imux->num_items].label = "Digital Mic";
-       imux->items[imux->num_items].index = 6;
-       imux->num_items++;
+       snd_hda_add_imux_item(imux, "Digital Mic", 6, NULL);
 
        return 0;
 }
@@ -6141,7 +5869,7 @@ static int vt1812_parse_auto_config(struct hda_codec *codec)
        err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1812_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1812_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;