]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.drivers/alsa-post-ga-hda-sigmatel-update3
Imported linux-2.6.27.39 suse/xen patches.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / alsa-post-ga-hda-sigmatel-update3
CommitLineData
2cb7cef9
BS
1From dc04d1b4d2043e2fca2d94d6d5542b930f2bc5b3 Mon Sep 17 00:00:00 2001
2From: Takashi Iwai <tiwai@suse.de>
3Date: Fri, 6 Mar 2009 10:00:05 +0100
4Subject: ALSA: hda - Create output controls according to pin types for IDT/STAC
5Patch-mainline:
6References: bnc#479558, bnc#482052
7
8Improve the parser to pick up more intuitive control names for the
9outputs judging from the pin type, instead of fixed names assigned
10to channels.
11
12Also, revive the multi-HP workaround since this change fixes the
13problem with the multi-HP detection.
14
15Signed-off-by: Takashi Iwai <tiwai@suse.de>
16
17---
18 sound/pci/hda/patch_sigmatel.c | 141 ++++++++++++++++++++---------------------
19 1 file changed, 72 insertions(+), 69 deletions(-)
20
21--- a/sound/pci/hda/patch_sigmatel.c
22+++ b/sound/pci/hda/patch_sigmatel.c
23@@ -2998,35 +2998,33 @@ static int add_spec_extra_dacs(struct si
24 return 1;
25 }
26
27-static int is_unique_dac(struct sigmatel_spec *spec, hda_nid_t nid)
28-{
29- int i;
30-
31- if (spec->autocfg.line_outs != 1)
32- return 0;
33- if (spec->multiout.hp_nid == nid)
34- return 0;
35- for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++)
36- if (spec->multiout.extra_out_nid[i] == nid)
37- return 0;
38- return 1;
39-}
40-
41-/* add playback controls from the parsed DAC table */
42-static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
43- const struct auto_pin_cfg *cfg)
44+/* Create output controls
45+ * The mixer elements are named depending on the given type (AUTO_PIN_XXX_OUT)
46+ */
47+static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
48+ const hda_nid_t *pins,
49+ const hda_nid_t *dac_nids,
50+ int type)
51 {
52 struct sigmatel_spec *spec = codec->spec;
53 static const char *chname[4] = {
54 "Front", "Surround", NULL /*CLFE*/, "Side"
55 };
56- hda_nid_t nid = 0;
57+ static const char *hp_pfxs[] = {
58+ "Headphone", "Headphone2", "Headphone3", "Headphone4"
59+ };
60+ static const char *speaker_pfxs[] = {
61+ "Speaker", "External Speaker", "Speaker2", "Speaker3"
62+ };
63+ hda_nid_t nid;
64 int i, err;
65 unsigned int wid_caps;
66
67- for (i = 0; i < cfg->line_outs && spec->multiout.dac_nids[i]; i++) {
68- nid = spec->multiout.dac_nids[i];
69- if (i == 2) {
70+ for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) {
71+ nid = dac_nids[i];
72+ if (!nid)
73+ continue;
74+ if (type != AUTO_PIN_HP_OUT && i == 2) {
75 /* Center/LFE */
76 err = create_controls(codec, "Center", nid, 1);
77 if (err < 0)
78@@ -3047,23 +3045,43 @@ static int stac92xx_auto_create_multi_ou
79 }
80
81 } else {
82- const char *name = chname[i];
83- /* if it's a single DAC, assign a better name */
84- if (!i && is_unique_dac(spec, nid)) {
85- switch (cfg->line_out_type) {
86- case AUTO_PIN_HP_OUT:
87- name = "Headphone";
88- break;
89- case AUTO_PIN_SPEAKER_OUT:
90- name = "Speaker";
91- break;
92- }
93+ const char *name;
94+ switch (type) {
95+ case AUTO_PIN_HP_OUT:
96+ name = hp_pfxs[i];
97+ break;
98+ case AUTO_PIN_SPEAKER_OUT:
99+ name = speaker_pfxs[i];
100+ break;
101+ default:
102+ name = chname[i];
103+ break;
104 }
105 err = create_controls(codec, name, nid, 3);
106 if (err < 0)
107 return err;
108+ if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) {
109+ wid_caps = get_wcaps(codec, pins[i]);
110+ if (wid_caps & AC_WCAP_UNSOL_CAP)
111+ spec->hp_detect = 1;
112+ }
113 }
114 }
115+ return 0;
116+}
117+
118+/* add playback controls from the parsed DAC table */
119+static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
120+ const struct auto_pin_cfg *cfg)
121+{
122+ struct sigmatel_spec *spec = codec->spec;
123+ int err;
124+
125+ err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins,
126+ spec->multiout.dac_nids,
127+ cfg->line_out_type);
128+ if (err < 0)
129+ return err;
130
131 if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) {
132 err = stac92xx_add_control(spec,
133@@ -3098,40 +3116,18 @@ static int stac92xx_auto_create_hp_ctls(
134 struct auto_pin_cfg *cfg)
135 {
136 struct sigmatel_spec *spec = codec->spec;
137- hda_nid_t nid;
138- int i, err, nums;
139+ int err;
140+
141+ err = create_multi_out_ctls(codec, cfg->hp_outs, cfg->hp_pins,
142+ spec->hp_dacs, AUTO_PIN_HP_OUT);
143+ if (err < 0)
144+ return err;
145+
146+ err = create_multi_out_ctls(codec, cfg->speaker_outs, cfg->speaker_pins,
147+ spec->speaker_dacs, AUTO_PIN_SPEAKER_OUT);
148+ if (err < 0)
149+ return err;
150
151- nums = 0;
152- for (i = 0; i < cfg->hp_outs; i++) {
153- static const char *pfxs[] = {
154- "Headphone", "Headphone2", "Headphone3",
155- };
156- unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]);
157- if (wid_caps & AC_WCAP_UNSOL_CAP)
158- spec->hp_detect = 1;
159- if (nums >= ARRAY_SIZE(pfxs))
160- continue;
161- nid = spec->hp_dacs[i];
162- if (!nid)
163- continue;
164- err = create_controls(codec, pfxs[nums++], nid, 3);
165- if (err < 0)
166- return err;
167- }
168- nums = 0;
169- for (i = 0; i < cfg->speaker_outs; i++) {
170- static const char *pfxs[] = {
171- "Speaker", "External Speaker", "Speaker2",
172- };
173- if (nums >= ARRAY_SIZE(pfxs))
174- continue;
175- nid = spec->speaker_dacs[i];
176- if (!nid)
177- continue;
178- err = create_controls(codec, pfxs[nums++], nid, 3);
179- if (err < 0)
180- return err;
181- }
182 return 0;
183 }
184
185@@ -3468,6 +3464,7 @@ static void stac92xx_auto_init_hp_out(st
186 static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)
187 {
188 struct sigmatel_spec *spec = codec->spec;
189+ int hp_swap = 0;
190 int err;
191
192 if ((err = snd_hda_parse_pin_def_config(codec,
193@@ -3477,7 +3474,6 @@ static int stac92xx_parse_auto_config(st
194 if (! spec->autocfg.line_outs)
195 return 0; /* can't find valid pin config */
196
197-#if 0 /* FIXME: temporarily disabled */
198 /* If we have no real line-out pin and multiple hp-outs, HPs should
199 * be set up as multi-channel outputs.
200 */
201@@ -3496,8 +3492,8 @@ static int stac92xx_parse_auto_config(st
202 spec->autocfg.line_outs = spec->autocfg.hp_outs;
203 spec->autocfg.line_out_type = AUTO_PIN_HP_OUT;
204 spec->autocfg.hp_outs = 0;
205+ hp_swap = 1;
206 }
207-#endif /* FIXME: temporarily disabled */
208 if (spec->autocfg.mono_out_pin) {
209 int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) &
210 (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP);
211@@ -3590,12 +3586,19 @@ static int stac92xx_parse_auto_config(st
212 #endif
213
214 err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg);
215-
216 if (err < 0)
217 return err;
218
219- err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
220+ /* All output parsing done, now restore the swapped hp pins */
221+ if (hp_swap) {
222+ memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins,
223+ sizeof(spec->autocfg.hp_pins));
224+ spec->autocfg.hp_outs = spec->autocfg.line_outs;
225+ spec->autocfg.line_out_type = AUTO_PIN_HP_OUT;
226+ spec->autocfg.line_outs = 0;
227+ }
228
229+ err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
230 if (err < 0)
231 return err;
232