ALSA: hda - Improve auto-cfg mixer name for ALC262
[safe/jmp/linux-2.6] / sound / pci / hda / patch_realtek.c
index 00ed126..4074759 100644 (file)
@@ -10790,80 +10790,106 @@ static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
        { } /* end */
 };
 
+/* We use two mixers depending on the output pin; 0x16 is a mono output
+ * and thus it's bound with a different mixer.
+ * This function returns which mixer amp should be used.
+ */
+static int alc262_check_volbit(hda_nid_t nid)
+{
+       if (!nid)
+               return 0;
+       else if (nid == 0x16)
+               return 2;
+       else
+               return 1;
+}
+
+static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
+                                 const char *pfx, int *vbits)
+{
+       char name[32];
+       unsigned long val;
+       int vbit;
+
+       vbit = alc262_check_volbit(nid);
+       if (!vbit)
+               return 0;
+       if (*vbits & vbit) /* a volume control for this mixer already there */
+               return 0;
+       *vbits |= vbit;
+       snprintf(name, sizeof(name), "%s Playback Volume", pfx);
+       if (vbit == 2)
+               val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
+       else
+               val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
+       return add_control(spec, ALC_CTL_WIDGET_VOL, name, val);
+}
+
+static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
+                                const char *pfx)
+{
+       char name[32];
+       unsigned long val;
+
+       if (!nid)
+               return 0;
+       snprintf(name, sizeof(name), "%s Playback Switch", pfx);
+       if (nid == 0x16)
+               val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
+       else
+               val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+       return add_control(spec, ALC_CTL_WIDGET_MUTE, name, val);
+}
+
 /* add playback controls from the parsed DAC table */
 static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
                                             const struct auto_pin_cfg *cfg)
 {
-       hda_nid_t nid;
+       const char *pfx;
+       int vbits;
        int err;
 
        spec->multiout.num_dacs = 1;    /* only use one dac */
        spec->multiout.dac_nids = spec->private_dac_nids;
        spec->multiout.dac_nids[0] = 2;
 
-       nid = cfg->line_out_pins[0];
-       if (nid) {
-               err = add_control(spec, ALC_CTL_WIDGET_VOL,
-                                 "Front Playback Volume",
-                                 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT));
-               if (err < 0)
-                       return err;
-               err = add_control(spec, ALC_CTL_WIDGET_MUTE,
-                                 "Front Playback Switch",
-                                 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
-               if (err < 0)
-                       return err;
-       }
+       if (!cfg->speaker_pins[0] && !cfg->hp_pins[0])
+               pfx = "Master";
+       else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
+               pfx = "Speaker";
+       else
+               pfx = "Front";
+       err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[0], pfx);
+       if (err < 0)
+               return err;
+       err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[0], "Speaker");
+       if (err < 0)
+               return err;
+       err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[0], "Headphone");
+       if (err < 0)
+               return err;
 
-       nid = cfg->speaker_pins[0];
-       if (nid) {
-               if (nid == 0x16) {
-                       err = add_control(spec, ALC_CTL_WIDGET_VOL,
-                                         "Speaker Playback Volume",
-                                         HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
-                                                             HDA_OUTPUT));
-                       if (err < 0)
-                               return err;
-                       err = add_control(spec, ALC_CTL_WIDGET_MUTE,
-                                         "Speaker Playback Switch",
-                                         HDA_COMPOSE_AMP_VAL(nid, 2, 0,
-                                                             HDA_OUTPUT));
-                       if (err < 0)
-                               return err;
-               } else {
-                       err = add_control(spec, ALC_CTL_WIDGET_MUTE,
-                                         "Speaker Playback Switch",
-                                         HDA_COMPOSE_AMP_VAL(nid, 3, 0,
-                                                             HDA_OUTPUT));
-                       if (err < 0)
-                               return err;
-               }
-       }
-       nid = cfg->hp_pins[0];
-       if (nid) {
-               /* spec->multiout.hp_nid = 2; */
-               if (nid == 0x16) {
-                       err = add_control(spec, ALC_CTL_WIDGET_VOL,
-                                         "Headphone Playback Volume",
-                                         HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
-                                                             HDA_OUTPUT));
-                       if (err < 0)
-                               return err;
-                       err = add_control(spec, ALC_CTL_WIDGET_MUTE,
-                                         "Headphone Playback Switch",
-                                         HDA_COMPOSE_AMP_VAL(nid, 2, 0,
-                                                             HDA_OUTPUT));
-                       if (err < 0)
-                               return err;
-               } else {
-                       err = add_control(spec, ALC_CTL_WIDGET_MUTE,
-                                         "Headphone Playback Switch",
-                                         HDA_COMPOSE_AMP_VAL(nid, 3, 0,
-                                                             HDA_OUTPUT));
-                       if (err < 0)
-                               return err;
-               }
-       }
+       vbits = alc262_check_volbit(cfg->line_out_pins[0]) |
+               alc262_check_volbit(cfg->speaker_pins[0]) |
+               alc262_check_volbit(cfg->hp_pins[0]);
+       if (vbits == 1 || vbits == 2)
+               pfx = "Master"; /* only one mixer is used */
+       else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
+               pfx = "Speaker";
+       else
+               pfx = "Front";
+       vbits = 0;
+       err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[0], pfx, &vbits);
+       if (err < 0)
+               return err;
+       err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[0], "Speaker",
+                                    &vbits);
+       if (err < 0)
+               return err;
+       err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[0], "Headphone",
+                                    &vbits);
+       if (err < 0)
+               return err;
        return 0;
 }