diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index a447013..b8d19d8 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2931,74 +2931,191 @@ static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
 	return 0;
 }
 
-/* return 0 if no possible DAC is found, 1 if one or more found */
+/* mark up volume and mute control NIDs: used during badness parsing and
+ * at creating actual controls
+ */
+static inline unsigned int get_ctl_pos(unsigned int data)
+{
+	hda_nid_t nid = get_amp_nid_(data);
+	unsigned int dir;
+	if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
+		return 0;
+	dir = get_amp_direction_(data);
+	return (nid << 1) | dir;
+}
+
+#define is_ctl_used(bits, data) \
+	test_bit(get_ctl_pos(data), bits)
+#define mark_ctl_usage(bits, data) \
+	set_bit(get_ctl_pos(data), bits)
+
+static void clear_vol_marks(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	memset(spec->vol_ctls, 0, sizeof(spec->vol_ctls));
+	memset(spec->sw_ctls, 0, sizeof(spec->sw_ctls));
+}
+
+/* badness definition */
+enum {
+	/* No primary DAC is found for the main output */
+	BAD_NO_PRIMARY_DAC = 0x10000,
+	/* No DAC is found for the extra output */
+	BAD_NO_DAC = 0x4000,
+	/* No individual DAC for extra output */
+	BAD_NO_EXTRA_DAC = 0x1000,
+	/* No individual DAC for extra surrounds */
+	BAD_NO_EXTRA_SURR_DAC = 0x200,
+	/* Primary DAC shared with main surrounds */
+	BAD_SHARED_SURROUND = 0x100,
+	/* Volume widget is shared */
+	BAD_SHARED_VOL = 0x10,
+	/* Primary DAC shared with main CLFE */
+	BAD_SHARED_CLFE = 0x10,
+	/* Primary DAC shared with extra surrounds */
+	BAD_SHARED_EXTRA_SURROUND = 0x10,
+	/* No possible multi-ios */
+	BAD_MULTI_IO = 0x1,
+};
+
+static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
+					   hda_nid_t pin, hda_nid_t dac);
+static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
+					  hda_nid_t pin, hda_nid_t dac);
+
+static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin,
+				   hda_nid_t dac)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t nid;
+	unsigned int val;
+	int badness = 0;
+
+	nid = alc_look_for_out_vol_nid(codec, pin, dac);
+	if (nid) {
+		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+		if (is_ctl_used(spec->vol_ctls, nid))
+			badness += BAD_SHARED_VOL;
+		else
+			mark_ctl_usage(spec->vol_ctls, val);
+	} else
+		badness += BAD_SHARED_VOL;
+	nid = alc_look_for_out_mute_nid(codec, pin, dac);
+	if (nid) {
+		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
+		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT)
+			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+		else
+			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
+		if (is_ctl_used(spec->sw_ctls, val))
+			badness += BAD_SHARED_VOL;
+		else
+			mark_ctl_usage(spec->sw_ctls, val);
+	} else
+		badness += BAD_SHARED_VOL;
+	return badness;
+}
+
+/* try to assign DACs to extra pins and return the resultant badness */
 static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
 				    const hda_nid_t *pins, hda_nid_t *dacs)
 {
+	struct alc_spec *spec = codec->spec;
 	int i;
+	int badness = 0;
+	hda_nid_t dac;
 
 	if (num_outs && !dacs[0]) {
-		dacs[0] = alc_auto_look_for_dac(codec, pins[0]);
-		if (!dacs[0])
-			return 0;
+		dac = dacs[0] = alc_auto_look_for_dac(codec, pins[0]);
+		if (!dacs[0]) {
+			dac = spec->private_dac_nids[0];
+			if (!alc_auto_is_dac_reachable(codec, pins[0], dac))
+				return BAD_NO_DAC;
+			badness += BAD_NO_EXTRA_DAC;
+		}
+		badness += eval_shared_vol_badness(codec, pins[0], dac);
 	}
 
 	for (i = 1; i < num_outs; i++)
 		dacs[i] = get_dac_if_single(codec, pins[i]);
 	for (i = 1; i < num_outs; i++) {
-		if (!dacs[i])
-			dacs[i] = alc_auto_look_for_dac(codec, pins[i]);
+		dac = dacs[i];
+		if (!dac)
+			dac = dacs[i] = alc_auto_look_for_dac(codec, pins[i]);
+		if (!dac) {
+			if (alc_auto_is_dac_reachable(codec, pins[i], dacs[0])) {
+				dac = dacs[0];
+				badness += BAD_SHARED_EXTRA_SURROUND;
+			} else if (alc_auto_is_dac_reachable(codec, pins[i],
+					spec->private_dac_nids[0])) {
+				dac = spec->private_dac_nids[0];
+				badness += BAD_NO_EXTRA_SURR_DAC;
+			} else
+				badness += BAD_NO_DAC;
+		}
+		if (dac)
+			badness += eval_shared_vol_badness(codec, pins[i], dac);
 	}
-	return 1;
+	return badness;
 }
 
 static int alc_auto_fill_multi_ios(struct hda_codec *codec,
 				   unsigned int location, int offset);
 
 /* fill in the dac_nids table from the parsed pin configuration */
-static int alc_auto_fill_dac_nids(struct hda_codec *codec)
+static int fill_and_eval_dacs(struct hda_codec *codec,
+			      bool fill_hardwired)
 {
 	struct alc_spec *spec = codec->spec;
 	const struct auto_pin_cfg *cfg = &spec->autocfg;
 	unsigned int location, defcfg;
-	int num_pins;
-	bool redone = false;
-	int i;
+	int i, err, badness;
 
- again:
 	/* set num_dacs once to full for alc_auto_look_for_dac() */
 	spec->multiout.num_dacs = cfg->line_outs;
-	spec->multiout.hp_out_nid[0] = 0;
-	spec->multiout.extra_out_nid[0] = 0;
-	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
 	spec->multiout.dac_nids = spec->private_dac_nids;
+	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
+	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
+	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
 	spec->multi_ios = 0;
+	clear_vol_marks(codec);
+	badness = 0;
 
 	/* fill hard-wired DACs first */
-	if (!redone) {
+	if (fill_hardwired) {
 		for (i = 0; i < cfg->line_outs; i++)
 			spec->private_dac_nids[i] =
 				get_dac_if_single(codec, cfg->line_out_pins[i]);
-		if (cfg->hp_outs)
-			spec->multiout.hp_out_nid[0] =
-				get_dac_if_single(codec, cfg->hp_pins[0]);
-		if (cfg->speaker_outs)
-			spec->multiout.extra_out_nid[0] =
-				get_dac_if_single(codec, cfg->speaker_pins[0]);
+		for (i = 0; i < cfg->hp_outs; i++)
+			spec->multiout.hp_out_nid[i] =
+				get_dac_if_single(codec, cfg->hp_pins[i]);
+		for (i = 0; i < cfg->speaker_outs; i++)
+			spec->multiout.extra_out_nid[i] =
+				get_dac_if_single(codec, cfg->speaker_pins[i]);
 	}
 
 	for (i = 0; i < cfg->line_outs; i++) {
 		hda_nid_t pin = cfg->line_out_pins[i];
-		if (spec->private_dac_nids[i])
-			continue;
-		spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
-		if (!spec->private_dac_nids[i] && !redone) {
-			/* if we can't find primary DACs, re-probe without
-			 * checking the hard-wired DACs
-			 */
-			redone = true;
-			goto again;
+		hda_nid_t dac;
+		if (!spec->private_dac_nids[i])
+			spec->private_dac_nids[i] =
+				alc_auto_look_for_dac(codec, pin);
+		dac = spec->private_dac_nids[i];
+		if (!dac) {
+			if (!i)
+				badness += BAD_NO_PRIMARY_DAC;
+			else if (alc_auto_is_dac_reachable(codec, pin,
+					spec->private_dac_nids[0])) {
+				if (i == 1)
+					badness += BAD_SHARED_SURROUND;
+				else
+					badness += BAD_SHARED_CLFE;
+				dac = spec->private_dac_nids[0];
+			} else
+				badness += BAD_NO_DAC;
 		}
+		if (dac)
+			badness += eval_shared_vol_badness(codec, pin, dac);
 	}
 
 	/* re-count num_dacs and squash invalid entries */
@@ -3018,26 +3135,114 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
 		/* try to fill multi-io first */
 		defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
 		location = get_defcfg_location(defcfg);
-
-		num_pins = alc_auto_fill_multi_ios(codec, location, 0);
-		if (num_pins > 0) {
-			spec->multi_ios = num_pins;
-			spec->ext_channel_count = 2;
-			spec->multiout.num_dacs = num_pins + 1;
-		}
+		err = alc_auto_fill_multi_ios(codec, location, 0);
+		if (err < 0)
+			return err;
+		badness += err;
 	}
 
-	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
-		alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins,
-				 spec->multiout.hp_out_nid);
+	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
+		err = alc_auto_fill_extra_dacs(codec, cfg->hp_outs,
+					       cfg->hp_pins,
+					       spec->multiout.hp_out_nid);
+		if (err < 0)
+			return err;
+		badness += err;
+	}
 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
-		int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs,
-					cfg->speaker_pins,
-					spec->multiout.extra_out_nid);
-		/* if no speaker volume is assigned, try again as the primary
-		 * output
-		 */
-		if (!err && cfg->speaker_outs > 0 &&
+		err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs,
+					       cfg->speaker_pins,
+					       spec->multiout.extra_out_nid);
+		if (err < 0)
+			return err;
+		badness += err;
+	}
+	if (!spec->multi_ios &&
+	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
+	    cfg->hp_outs) {
+		/* try multi-ios with HP + inputs */
+		defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]);
+		location = get_defcfg_location(defcfg);
+		err = alc_auto_fill_multi_ios(codec, location, 1);
+		if (err < 0)
+			return err;
+		badness += err;
+	}
+
+	return badness;
+}
+
+#define DEBUG_BADNESS
+
+#ifdef DEBUG_BADNESS
+#define debug_badness	snd_printdd
+#else
+#define debug_badness(...)
+#endif
+
+static void debug_show_configs(struct alc_spec *spec, struct auto_pin_cfg *cfg)
+{
+	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
+		      cfg->line_out_pins[0], cfg->line_out_pins[1],
+		      cfg->line_out_pins[2], cfg->line_out_pins[2],
+		      spec->multiout.dac_nids[0],
+		      spec->multiout.dac_nids[1],
+		      spec->multiout.dac_nids[2],
+		      spec->multiout.dac_nids[3]);
+	debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
+		      cfg->hp_pins[0], cfg->hp_pins[1],
+		      cfg->hp_pins[2], cfg->hp_pins[2],
+		      spec->multiout.hp_out_nid[0],
+		      spec->multiout.hp_out_nid[1],
+		      spec->multiout.hp_out_nid[2],
+		      spec->multiout.hp_out_nid[3]);
+	debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
+		      cfg->speaker_pins[0], cfg->speaker_pins[1],
+		      cfg->speaker_pins[2], cfg->speaker_pins[3],
+		      spec->multiout.extra_out_nid[0],
+		      spec->multiout.extra_out_nid[1],
+		      spec->multiout.extra_out_nid[2],
+		      spec->multiout.extra_out_nid[3]);
+}
+
+static int alc_auto_fill_dac_nids(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	struct auto_pin_cfg *best_cfg;
+	int best_badness = INT_MAX;
+	int badness;
+	bool fill_hardwired = true;
+	bool best_wired = true;
+	bool hp_spk_swapped = false;
+
+	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
+	if (!best_cfg)
+		return -ENOMEM;
+	*best_cfg = *cfg;
+
+	for (;;) {
+		badness = fill_and_eval_dacs(codec, fill_hardwired);
+		if (badness < 0)
+			return badness;
+		debug_badness("==> lo_type=%d, wired=%d, badness=0x%x\n",
+			      cfg->line_out_type, fill_hardwired, badness);
+		debug_show_configs(spec, cfg);
+		if (badness < best_badness) {
+			best_badness = badness;
+			*best_cfg = *cfg;
+			best_wired = fill_hardwired;
+		}
+		if (!badness)
+			break;
+		if (fill_hardwired) {
+			fill_hardwired = false;
+			continue;
+		}
+		if (hp_spk_swapped)
+			break;
+		hp_spk_swapped = true;
+		if (cfg->speaker_outs > 0 &&
 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
 			cfg->hp_outs = cfg->line_outs;
 			memcpy(cfg->hp_pins, cfg->line_out_pins,
@@ -3048,49 +3253,46 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
 			cfg->speaker_outs = 0;
 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
-			redone = false;
-			goto again;
-		}
+			fill_hardwired = true;
+			continue;
+		} 
+		if (cfg->hp_outs > 0 &&
+		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
+			cfg->speaker_outs = cfg->line_outs;
+			memcpy(cfg->speaker_pins, cfg->line_out_pins,
+			       sizeof(cfg->speaker_pins));
+			cfg->line_outs = cfg->hp_outs;
+			memcpy(cfg->line_out_pins, cfg->hp_pins,
+			       sizeof(cfg->hp_pins));
+			cfg->hp_outs = 0;
+			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
+			cfg->line_out_type = AUTO_PIN_HP_OUT;
+			fill_hardwired = true;
+			continue;
+		} 
+		break;
 	}
 
-	if (cfg->line_out_pins[0])
+
+	if (badness) {
+		*cfg = *best_cfg;
+		fill_and_eval_dacs(codec, best_wired);
+	}
+	debug_badness("==> Best config: lo_type=%d, wired=%d\n",
+		      cfg->line_out_type, best_wired);
+	debug_show_configs(spec, cfg);
+	
+if (cfg->line_out_pins[0])
 		spec->vmaster_nid =
 			alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0],
 						 spec->multiout.dac_nids[0]);
 
-	if (!spec->multi_ios &&
-	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
-	    cfg->hp_outs) {
-		/* try multi-ios with HP + inputs */
-		defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]);
-		location = get_defcfg_location(defcfg);
-
-		num_pins = alc_auto_fill_multi_ios(codec, location, 1);
-		if (num_pins > 0) {
-			spec->multi_ios = num_pins;
-			spec->ext_channel_count = 2;
-			spec->multiout.num_dacs = num_pins + 1;
-		}
-	}
-
+	/* clear the bitmap flags for creating controls */
+	clear_vol_marks(codec);
+	kfree(best_cfg);
 	return 0;
 }
 
-static inline unsigned int get_ctl_pos(unsigned int data)
-{
-	hda_nid_t nid = get_amp_nid_(data);
-	unsigned int dir;
-	if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
-		return 0;
-	dir = get_amp_direction_(data);
-	return (nid << 1) | dir;
-}
-
-#define is_ctl_used(bits, data) \
-	test_bit(get_ctl_pos(data), bits)
-#define mark_ctl_usage(bits, data) \
-	set_bit(get_ctl_pos(data), bits)
-
 static int alc_auto_add_vol_ctl(struct hda_codec *codec,
 			      const char *pfx, int cidx,
 			      hda_nid_t nid, unsigned int chs)
@@ -3474,6 +3676,7 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec,
 	struct auto_pin_cfg *cfg = &spec->autocfg;
 	hda_nid_t prime_dac = spec->private_dac_nids[0];
 	int type, i, dacs, num_pins = 0;
+	int badness = 0;
 
 	dacs = spec->multiout.num_dacs;
 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
@@ -3498,12 +3701,16 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec,
 			}
 			if (!dac)
 				dac = alc_auto_look_for_dac(codec, nid);
-			if (!dac)
+			if (!dac) {
+				badness += BAD_MULTI_IO;
 				continue;
+			}
 			spec->multi_io[num_pins].pin = nid;
 			spec->multi_io[num_pins].dac = dac;
 			num_pins++;
 			spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
+			if (num_pins >= 2)
+				break;
 		}
 	}
 	spec->multiout.num_dacs = dacs;
@@ -3512,9 +3719,13 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec,
 		memset(spec->private_dac_nids + dacs, 0,
 		       sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - dacs));
 		spec->private_dac_nids[0] = prime_dac;
-		return 0;
+		return badness;
 	}
-	return num_pins;
+
+	spec->multi_ios = num_pins;
+	spec->ext_channel_count = 2;
+	spec->multiout.num_dacs = num_pins + 1;
+	return 0;
 }
 
 static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
