+++ /dev/null
-From dc04d1b4d2043e2fca2d94d6d5542b930f2bc5b3 Mon Sep 17 00:00:00 2001
-From: Takashi Iwai <tiwai@suse.de>
-Date: Fri, 6 Mar 2009 10:00:05 +0100
-Subject: ALSA: hda - Create output controls according to pin types for IDT/STAC
-Patch-mainline:
-References: bnc#479558, bnc#482052
-
-Improve the parser to pick up more intuitive control names for the
-outputs judging from the pin type, instead of fixed names assigned
-to channels.
-
-Also, revive the multi-HP workaround since this change fixes the
-problem with the multi-HP detection.
-
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-
----
- sound/pci/hda/patch_sigmatel.c | 141 ++++++++++++++++++++---------------------
- 1 file changed, 72 insertions(+), 69 deletions(-)
-
---- a/sound/pci/hda/patch_sigmatel.c
-+++ b/sound/pci/hda/patch_sigmatel.c
-@@ -2998,35 +2998,33 @@ static int add_spec_extra_dacs(struct si
- return 1;
- }
-
--static int is_unique_dac(struct sigmatel_spec *spec, hda_nid_t nid)
--{
-- int i;
--
-- if (spec->autocfg.line_outs != 1)
-- return 0;
-- if (spec->multiout.hp_nid == nid)
-- return 0;
-- for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++)
-- if (spec->multiout.extra_out_nid[i] == nid)
-- return 0;
-- return 1;
--}
--
--/* add playback controls from the parsed DAC table */
--static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
-- const struct auto_pin_cfg *cfg)
-+/* Create output controls
-+ * The mixer elements are named depending on the given type (AUTO_PIN_XXX_OUT)
-+ */
-+static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
-+ const hda_nid_t *pins,
-+ const hda_nid_t *dac_nids,
-+ int type)
- {
- struct sigmatel_spec *spec = codec->spec;
- static const char *chname[4] = {
- "Front", "Surround", NULL /*CLFE*/, "Side"
- };
-- hda_nid_t nid = 0;
-+ static const char *hp_pfxs[] = {
-+ "Headphone", "Headphone2", "Headphone3", "Headphone4"
-+ };
-+ static const char *speaker_pfxs[] = {
-+ "Speaker", "External Speaker", "Speaker2", "Speaker3"
-+ };
-+ hda_nid_t nid;
- int i, err;
- unsigned int wid_caps;
-
-- for (i = 0; i < cfg->line_outs && spec->multiout.dac_nids[i]; i++) {
-- nid = spec->multiout.dac_nids[i];
-- if (i == 2) {
-+ for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) {
-+ nid = dac_nids[i];
-+ if (!nid)
-+ continue;
-+ if (type != AUTO_PIN_HP_OUT && i == 2) {
- /* Center/LFE */
- err = create_controls(codec, "Center", nid, 1);
- if (err < 0)
-@@ -3047,23 +3045,43 @@ static int stac92xx_auto_create_multi_ou
- }
-
- } else {
-- const char *name = chname[i];
-- /* if it's a single DAC, assign a better name */
-- if (!i && is_unique_dac(spec, nid)) {
-- switch (cfg->line_out_type) {
-- case AUTO_PIN_HP_OUT:
-- name = "Headphone";
-- break;
-- case AUTO_PIN_SPEAKER_OUT:
-- name = "Speaker";
-- break;
-- }
-+ const char *name;
-+ switch (type) {
-+ case AUTO_PIN_HP_OUT:
-+ name = hp_pfxs[i];
-+ break;
-+ case AUTO_PIN_SPEAKER_OUT:
-+ name = speaker_pfxs[i];
-+ break;
-+ default:
-+ name = chname[i];
-+ break;
- }
- err = create_controls(codec, name, nid, 3);
- if (err < 0)
- return err;
-+ if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) {
-+ wid_caps = get_wcaps(codec, pins[i]);
-+ if (wid_caps & AC_WCAP_UNSOL_CAP)
-+ spec->hp_detect = 1;
-+ }
- }
- }
-+ return 0;
-+}
-+
-+/* add playback controls from the parsed DAC table */
-+static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
-+ const struct auto_pin_cfg *cfg)
-+{
-+ struct sigmatel_spec *spec = codec->spec;
-+ int err;
-+
-+ err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins,
-+ spec->multiout.dac_nids,
-+ cfg->line_out_type);
-+ if (err < 0)
-+ return err;
-
- if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) {
- err = stac92xx_add_control(spec,
-@@ -3098,40 +3116,18 @@ static int stac92xx_auto_create_hp_ctls(
- struct auto_pin_cfg *cfg)
- {
- struct sigmatel_spec *spec = codec->spec;
-- hda_nid_t nid;
-- int i, err, nums;
-+ int err;
-+
-+ err = create_multi_out_ctls(codec, cfg->hp_outs, cfg->hp_pins,
-+ spec->hp_dacs, AUTO_PIN_HP_OUT);
-+ if (err < 0)
-+ return err;
-+
-+ err = create_multi_out_ctls(codec, cfg->speaker_outs, cfg->speaker_pins,
-+ spec->speaker_dacs, AUTO_PIN_SPEAKER_OUT);
-+ if (err < 0)
-+ return err;
-
-- nums = 0;
-- for (i = 0; i < cfg->hp_outs; i++) {
-- static const char *pfxs[] = {
-- "Headphone", "Headphone2", "Headphone3",
-- };
-- unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]);
-- if (wid_caps & AC_WCAP_UNSOL_CAP)
-- spec->hp_detect = 1;
-- if (nums >= ARRAY_SIZE(pfxs))
-- continue;
-- nid = spec->hp_dacs[i];
-- if (!nid)
-- continue;
-- err = create_controls(codec, pfxs[nums++], nid, 3);
-- if (err < 0)
-- return err;
-- }
-- nums = 0;
-- for (i = 0; i < cfg->speaker_outs; i++) {
-- static const char *pfxs[] = {
-- "Speaker", "External Speaker", "Speaker2",
-- };
-- if (nums >= ARRAY_SIZE(pfxs))
-- continue;
-- nid = spec->speaker_dacs[i];
-- if (!nid)
-- continue;
-- err = create_controls(codec, pfxs[nums++], nid, 3);
-- if (err < 0)
-- return err;
-- }
- return 0;
- }
-
-@@ -3468,6 +3464,7 @@ static void stac92xx_auto_init_hp_out(st
- static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)
- {
- struct sigmatel_spec *spec = codec->spec;
-+ int hp_swap = 0;
- int err;
-
- if ((err = snd_hda_parse_pin_def_config(codec,
-@@ -3477,7 +3474,6 @@ static int stac92xx_parse_auto_config(st
- if (! spec->autocfg.line_outs)
- return 0; /* can't find valid pin config */
-
--#if 0 /* FIXME: temporarily disabled */
- /* If we have no real line-out pin and multiple hp-outs, HPs should
- * be set up as multi-channel outputs.
- */
-@@ -3496,8 +3492,8 @@ static int stac92xx_parse_auto_config(st
- spec->autocfg.line_outs = spec->autocfg.hp_outs;
- spec->autocfg.line_out_type = AUTO_PIN_HP_OUT;
- spec->autocfg.hp_outs = 0;
-+ hp_swap = 1;
- }
--#endif /* FIXME: temporarily disabled */
- if (spec->autocfg.mono_out_pin) {
- int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) &
- (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP);
-@@ -3590,12 +3586,19 @@ static int stac92xx_parse_auto_config(st
- #endif
-
- err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg);
--
- if (err < 0)
- return err;
-
-- err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
-+ /* All output parsing done, now restore the swapped hp pins */
-+ if (hp_swap) {
-+ memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins,
-+ sizeof(spec->autocfg.hp_pins));
-+ spec->autocfg.hp_outs = spec->autocfg.line_outs;
-+ spec->autocfg.line_out_type = AUTO_PIN_HP_OUT;
-+ spec->autocfg.line_outs = 0;
-+ }
-
-+ err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
- if (err < 0)
- return err;
-