]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.drivers/alsa-post-ga-hda-sigmatel-update3
Disable build of xen kernel.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.drivers / alsa-post-ga-hda-sigmatel-update3
1 From dc04d1b4d2043e2fca2d94d6d5542b930f2bc5b3 Mon Sep 17 00:00:00 2001
2 From: Takashi Iwai <tiwai@suse.de>
3 Date: Fri, 6 Mar 2009 10:00:05 +0100
4 Subject: ALSA: hda - Create output controls according to pin types for IDT/STAC
5 Patch-mainline:
6 References: bnc#479558, bnc#482052
7
8 Improve the parser to pick up more intuitive control names for the
9 outputs judging from the pin type, instead of fixed names assigned
10 to channels.
11
12 Also, revive the multi-HP workaround since this change fixes the
13 problem with the multi-HP detection.
14
15 Signed-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