diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/vmaster.c | 46 | ||||
-rw-r--r-- | sound/pci/hda/alc260_quirks.c | 968 | ||||
-rw-r--r-- | sound/pci/hda/alc880_quirks.c | 1707 | ||||
-rw-r--r-- | sound/pci/hda/alc882_quirks.c | 866 | ||||
-rw-r--r-- | sound/pci/hda/alc_quirks.c | 480 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 192 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 52 | ||||
-rw-r--r-- | sound/pci/hda/hda_jack.c | 16 | ||||
-rw-r--r-- | sound/pci/hda/hda_jack.h | 13 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 30 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 72 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 122 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 1840 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 203 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 48 |
17 files changed, 1766 insertions, 4892 deletions
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 130cfe677d60..14a286a7bf2b 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c | |||
@@ -37,6 +37,8 @@ struct link_master { | |||
37 | struct link_ctl_info info; | 37 | struct link_ctl_info info; |
38 | int val; /* the master value */ | 38 | int val; /* the master value */ |
39 | unsigned int tlv[4]; | 39 | unsigned int tlv[4]; |
40 | void (*hook)(void *private_data, int); | ||
41 | void *hook_private_data; | ||
40 | }; | 42 | }; |
41 | 43 | ||
42 | /* | 44 | /* |
@@ -126,7 +128,9 @@ static int master_init(struct link_master *master) | |||
126 | master->info.count = 1; /* always mono */ | 128 | master->info.count = 1; /* always mono */ |
127 | /* set full volume as default (= no attenuation) */ | 129 | /* set full volume as default (= no attenuation) */ |
128 | master->val = master->info.max_val; | 130 | master->val = master->info.max_val; |
129 | return 0; | 131 | if (master->hook) |
132 | master->hook(master->hook_private_data, master->val); | ||
133 | return 1; | ||
130 | } | 134 | } |
131 | return -ENOENT; | 135 | return -ENOENT; |
132 | } | 136 | } |
@@ -329,6 +333,8 @@ static int master_put(struct snd_kcontrol *kcontrol, | |||
329 | slave_put_val(slave, uval); | 333 | slave_put_val(slave, uval); |
330 | } | 334 | } |
331 | kfree(uval); | 335 | kfree(uval); |
336 | if (master->hook && !err) | ||
337 | master->hook(master->hook_private_data, master->val); | ||
332 | return 1; | 338 | return 1; |
333 | } | 339 | } |
334 | 340 | ||
@@ -408,3 +414,41 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, | |||
408 | return kctl; | 414 | return kctl; |
409 | } | 415 | } |
410 | EXPORT_SYMBOL(snd_ctl_make_virtual_master); | 416 | EXPORT_SYMBOL(snd_ctl_make_virtual_master); |
417 | |||
418 | /** | ||
419 | * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control | ||
420 | * @kcontrol: vmaster kctl element | ||
421 | * @hook: the hook function | ||
422 | * | ||
423 | * Adds the given hook to the vmaster control element so that it's called | ||
424 | * at each time when the value is changed. | ||
425 | */ | ||
426 | int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol, | ||
427 | void (*hook)(void *private_data, int), | ||
428 | void *private_data) | ||
429 | { | ||
430 | struct link_master *master = snd_kcontrol_chip(kcontrol); | ||
431 | master->hook = hook; | ||
432 | master->hook_private_data = private_data; | ||
433 | return 0; | ||
434 | } | ||
435 | EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook); | ||
436 | |||
437 | /** | ||
438 | * snd_ctl_sync_vmaster_hook - Sync the vmaster hook | ||
439 | * @kcontrol: vmaster kctl element | ||
440 | * | ||
441 | * Call the hook function to synchronize with the current value of the given | ||
442 | * vmaster element. NOP when NULL is passed to @kcontrol or the hook doesn't | ||
443 | * exist. | ||
444 | */ | ||
445 | void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol) | ||
446 | { | ||
447 | struct link_master *master; | ||
448 | if (!kcontrol) | ||
449 | return; | ||
450 | master = snd_kcontrol_chip(kcontrol); | ||
451 | if (master->hook) | ||
452 | master->hook(master->hook_private_data, master->val); | ||
453 | } | ||
454 | EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook); | ||
diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c deleted file mode 100644 index 3b5170b9700f..000000000000 --- a/sound/pci/hda/alc260_quirks.c +++ /dev/null | |||
@@ -1,968 +0,0 @@ | |||
1 | /* | ||
2 | * ALC260 quirk models | ||
3 | * included by patch_realtek.c | ||
4 | */ | ||
5 | |||
6 | /* ALC260 models */ | ||
7 | enum { | ||
8 | ALC260_AUTO, | ||
9 | ALC260_BASIC, | ||
10 | ALC260_FUJITSU_S702X, | ||
11 | ALC260_ACER, | ||
12 | ALC260_WILL, | ||
13 | ALC260_REPLACER_672V, | ||
14 | ALC260_FAVORIT100, | ||
15 | #ifdef CONFIG_SND_DEBUG | ||
16 | ALC260_TEST, | ||
17 | #endif | ||
18 | ALC260_MODEL_LAST /* last tag */ | ||
19 | }; | ||
20 | |||
21 | static const hda_nid_t alc260_dac_nids[1] = { | ||
22 | /* front */ | ||
23 | 0x02, | ||
24 | }; | ||
25 | |||
26 | static const hda_nid_t alc260_adc_nids[1] = { | ||
27 | /* ADC0 */ | ||
28 | 0x04, | ||
29 | }; | ||
30 | |||
31 | static const hda_nid_t alc260_adc_nids_alt[1] = { | ||
32 | /* ADC1 */ | ||
33 | 0x05, | ||
34 | }; | ||
35 | |||
36 | /* NIDs used when simultaneous access to both ADCs makes sense. Note that | ||
37 | * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC. | ||
38 | */ | ||
39 | static const hda_nid_t alc260_dual_adc_nids[2] = { | ||
40 | /* ADC0, ADC1 */ | ||
41 | 0x04, 0x05 | ||
42 | }; | ||
43 | |||
44 | #define ALC260_DIGOUT_NID 0x03 | ||
45 | #define ALC260_DIGIN_NID 0x06 | ||
46 | |||
47 | static const struct hda_input_mux alc260_capture_source = { | ||
48 | .num_items = 4, | ||
49 | .items = { | ||
50 | { "Mic", 0x0 }, | ||
51 | { "Front Mic", 0x1 }, | ||
52 | { "Line", 0x2 }, | ||
53 | { "CD", 0x4 }, | ||
54 | }, | ||
55 | }; | ||
56 | |||
57 | /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack, | ||
58 | * headphone jack and the internal CD lines since these are the only pins at | ||
59 | * which audio can appear. For flexibility, also allow the option of | ||
60 | * recording the mixer output on the second ADC (ADC0 doesn't have a | ||
61 | * connection to the mixer output). | ||
62 | */ | ||
63 | static const struct hda_input_mux alc260_fujitsu_capture_sources[2] = { | ||
64 | { | ||
65 | .num_items = 3, | ||
66 | .items = { | ||
67 | { "Mic/Line", 0x0 }, | ||
68 | { "CD", 0x4 }, | ||
69 | { "Headphone", 0x2 }, | ||
70 | }, | ||
71 | }, | ||
72 | { | ||
73 | .num_items = 4, | ||
74 | .items = { | ||
75 | { "Mic/Line", 0x0 }, | ||
76 | { "CD", 0x4 }, | ||
77 | { "Headphone", 0x2 }, | ||
78 | { "Mixer", 0x5 }, | ||
79 | }, | ||
80 | }, | ||
81 | |||
82 | }; | ||
83 | |||
84 | /* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to | ||
85 | * the Fujitsu S702x, but jacks are marked differently. | ||
86 | */ | ||
87 | static const struct hda_input_mux alc260_acer_capture_sources[2] = { | ||
88 | { | ||
89 | .num_items = 4, | ||
90 | .items = { | ||
91 | { "Mic", 0x0 }, | ||
92 | { "Line", 0x2 }, | ||
93 | { "CD", 0x4 }, | ||
94 | { "Headphone", 0x5 }, | ||
95 | }, | ||
96 | }, | ||
97 | { | ||
98 | .num_items = 5, | ||
99 | .items = { | ||
100 | { "Mic", 0x0 }, | ||
101 | { "Line", 0x2 }, | ||
102 | { "CD", 0x4 }, | ||
103 | { "Headphone", 0x6 }, | ||
104 | { "Mixer", 0x5 }, | ||
105 | }, | ||
106 | }, | ||
107 | }; | ||
108 | |||
109 | /* Maxdata Favorit 100XS */ | ||
110 | static const struct hda_input_mux alc260_favorit100_capture_sources[2] = { | ||
111 | { | ||
112 | .num_items = 2, | ||
113 | .items = { | ||
114 | { "Line/Mic", 0x0 }, | ||
115 | { "CD", 0x4 }, | ||
116 | }, | ||
117 | }, | ||
118 | { | ||
119 | .num_items = 3, | ||
120 | .items = { | ||
121 | { "Line/Mic", 0x0 }, | ||
122 | { "CD", 0x4 }, | ||
123 | { "Mixer", 0x5 }, | ||
124 | }, | ||
125 | }, | ||
126 | }; | ||
127 | |||
128 | /* | ||
129 | * This is just place-holder, so there's something for alc_build_pcms to look | ||
130 | * at when it calculates the maximum number of channels. ALC260 has no mixer | ||
131 | * element which allows changing the channel mode, so the verb list is | ||
132 | * never used. | ||
133 | */ | ||
134 | static const struct hda_channel_mode alc260_modes[1] = { | ||
135 | { 2, NULL }, | ||
136 | }; | ||
137 | |||
138 | |||
139 | /* Mixer combinations | ||
140 | * | ||
141 | * basic: base_output + input + pc_beep + capture | ||
142 | * fujitsu: fujitsu + capture | ||
143 | * acer: acer + capture | ||
144 | */ | ||
145 | |||
146 | static const struct snd_kcontrol_new alc260_base_output_mixer[] = { | ||
147 | HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
148 | HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), | ||
149 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), | ||
150 | HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), | ||
151 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), | ||
152 | HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), | ||
153 | { } /* end */ | ||
154 | }; | ||
155 | |||
156 | static const struct snd_kcontrol_new alc260_input_mixer[] = { | ||
157 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
158 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
159 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
160 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
161 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
162 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
163 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), | ||
164 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), | ||
165 | { } /* end */ | ||
166 | }; | ||
167 | |||
168 | /* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12, | ||
169 | * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10. | ||
170 | */ | ||
171 | static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = { | ||
172 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
173 | HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), | ||
174 | ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | ||
175 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
176 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
177 | HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
178 | HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
179 | ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
180 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), | ||
181 | HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT), | ||
182 | { } /* end */ | ||
183 | }; | ||
184 | |||
185 | /* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current | ||
186 | * versions of the ALC260 don't act on requests to enable mic bias from NID | ||
187 | * 0x0f (used to drive the headphone jack in these laptops). The ALC260 | ||
188 | * datasheet doesn't mention this restriction. At this stage it's not clear | ||
189 | * whether this behaviour is intentional or is a hardware bug in chip | ||
190 | * revisions available in early 2006. Therefore for now allow the | ||
191 | * "Headphone Jack Mode" control to span all choices, but if it turns out | ||
192 | * that the lack of mic bias for this NID is intentional we could change the | ||
193 | * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. | ||
194 | * | ||
195 | * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006 | ||
196 | * don't appear to make the mic bias available from the "line" jack, even | ||
197 | * though the NID used for this jack (0x14) can supply it. The theory is | ||
198 | * that perhaps Acer have included blocking capacitors between the ALC260 | ||
199 | * and the output jack. If this turns out to be the case for all such | ||
200 | * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT | ||
201 | * to ALC_PIN_DIR_INOUT_NOMICBIAS. | ||
202 | * | ||
203 | * The C20x Tablet series have a mono internal speaker which is controlled | ||
204 | * via the chip's Mono sum widget and pin complex, so include the necessary | ||
205 | * controls for such models. On models without a "mono speaker" the control | ||
206 | * won't do anything. | ||
207 | */ | ||
208 | static const struct snd_kcontrol_new alc260_acer_mixer[] = { | ||
209 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
210 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), | ||
211 | ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), | ||
212 | HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, | ||
213 | HDA_OUTPUT), | ||
214 | HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, | ||
215 | HDA_INPUT), | ||
216 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
217 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
218 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
219 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
220 | ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
221 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
222 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
223 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | ||
224 | { } /* end */ | ||
225 | }; | ||
226 | |||
227 | /* Maxdata Favorit 100XS: one output and one input (0x12) jack | ||
228 | */ | ||
229 | static const struct snd_kcontrol_new alc260_favorit100_mixer[] = { | ||
230 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
231 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), | ||
232 | ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), | ||
233 | HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
234 | HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
235 | ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
236 | { } /* end */ | ||
237 | }; | ||
238 | |||
239 | /* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12, | ||
240 | * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17. | ||
241 | */ | ||
242 | static const struct snd_kcontrol_new alc260_will_mixer[] = { | ||
243 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
244 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), | ||
245 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
246 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
247 | ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
248 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
249 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
250 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | ||
251 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
252 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
253 | { } /* end */ | ||
254 | }; | ||
255 | |||
256 | /* Replacer 672V ALC260 pin usage: Mic jack = 0x12, | ||
257 | * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f. | ||
258 | */ | ||
259 | static const struct snd_kcontrol_new alc260_replacer_672v_mixer[] = { | ||
260 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
261 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT), | ||
262 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
263 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
264 | ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
265 | HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT), | ||
266 | HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT), | ||
267 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
268 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
269 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | ||
270 | { } /* end */ | ||
271 | }; | ||
272 | |||
273 | /* | ||
274 | * initialization verbs | ||
275 | */ | ||
276 | static const struct hda_verb alc260_init_verbs[] = { | ||
277 | /* Line In pin widget for input */ | ||
278 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
279 | /* CD pin widget for input */ | ||
280 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
281 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | ||
282 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
283 | /* Mic2 (front panel) pin widget for input and vref at 80% */ | ||
284 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
285 | /* LINE-2 is used for line-out in rear */ | ||
286 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
287 | /* select line-out */ | ||
288 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
289 | /* LINE-OUT pin */ | ||
290 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
291 | /* enable HP */ | ||
292 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
293 | /* enable Mono */ | ||
294 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
295 | /* mute capture amp left and right */ | ||
296 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
297 | /* set connection select to line in (default select for this ADC) */ | ||
298 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
299 | /* mute capture amp left and right */ | ||
300 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
301 | /* set connection select to line in (default select for this ADC) */ | ||
302 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
303 | /* set vol=0 Line-Out mixer amp left and right */ | ||
304 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
305 | /* unmute pin widget amp left and right (no gain on this amp) */ | ||
306 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
307 | /* set vol=0 HP mixer amp left and right */ | ||
308 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
309 | /* unmute pin widget amp left and right (no gain on this amp) */ | ||
310 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
311 | /* set vol=0 Mono mixer amp left and right */ | ||
312 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
313 | /* unmute pin widget amp left and right (no gain on this amp) */ | ||
314 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
315 | /* unmute LINE-2 out pin */ | ||
316 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
317 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & | ||
318 | * Line In 2 = 0x03 | ||
319 | */ | ||
320 | /* mute analog inputs */ | ||
321 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
322 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
323 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
324 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
325 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
326 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | ||
327 | /* mute Front out path */ | ||
328 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
329 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
330 | /* mute Headphone out path */ | ||
331 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
332 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
333 | /* mute Mono out path */ | ||
334 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
335 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
336 | { } | ||
337 | }; | ||
338 | |||
339 | /* Initialisation sequence for ALC260 as configured in Fujitsu S702x | ||
340 | * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD | ||
341 | * audio = 0x16, internal speaker = 0x10. | ||
342 | */ | ||
343 | static const struct hda_verb alc260_fujitsu_init_verbs[] = { | ||
344 | /* Disable all GPIOs */ | ||
345 | {0x01, AC_VERB_SET_GPIO_MASK, 0}, | ||
346 | /* Internal speaker is connected to headphone pin */ | ||
347 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
348 | /* Headphone/Line-out jack connects to Line1 pin; make it an output */ | ||
349 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
350 | /* Mic/Line-in jack is connected to mic1 pin, so make it an input */ | ||
351 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
352 | /* Ensure all other unused pins are disabled and muted. */ | ||
353 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
354 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
355 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
356 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
357 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
358 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
359 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
360 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
361 | |||
362 | /* Disable digital (SPDIF) pins */ | ||
363 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
364 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
365 | |||
366 | /* Ensure Line1 pin widget takes its input from the OUT1 sum bus | ||
367 | * when acting as an output. | ||
368 | */ | ||
369 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, | ||
370 | |||
371 | /* Start with output sum widgets muted and their output gains at min */ | ||
372 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
373 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
374 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
375 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
376 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
377 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
378 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
379 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
380 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
381 | |||
382 | /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */ | ||
383 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
384 | /* Unmute Line1 pin widget output buffer since it starts as an output. | ||
385 | * If the pin mode is changed by the user the pin mode control will | ||
386 | * take care of enabling the pin's input/output buffers as needed. | ||
387 | * Therefore there's no need to enable the input buffer at this | ||
388 | * stage. | ||
389 | */ | ||
390 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
391 | /* Unmute input buffer of pin widget used for Line-in (no equiv | ||
392 | * mixer ctrl) | ||
393 | */ | ||
394 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
395 | |||
396 | /* Mute capture amp left and right */ | ||
397 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
398 | /* Set ADC connection select to match default mixer setting - line | ||
399 | * in (on mic1 pin) | ||
400 | */ | ||
401 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
402 | |||
403 | /* Do the same for the second ADC: mute capture input amp and | ||
404 | * set ADC connection to line in (on mic1 pin) | ||
405 | */ | ||
406 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
407 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
408 | |||
409 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
410 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
411 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
412 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
413 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
414 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
415 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
416 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
417 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
418 | |||
419 | { } | ||
420 | }; | ||
421 | |||
422 | /* Initialisation sequence for ALC260 as configured in Acer TravelMate and | ||
423 | * similar laptops (adapted from Fujitsu init verbs). | ||
424 | */ | ||
425 | static const struct hda_verb alc260_acer_init_verbs[] = { | ||
426 | /* On TravelMate laptops, GPIO 0 enables the internal speaker and | ||
427 | * the headphone jack. Turn this on and rely on the standard mute | ||
428 | * methods whenever the user wants to turn these outputs off. | ||
429 | */ | ||
430 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
431 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
432 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
433 | /* Internal speaker/Headphone jack is connected to Line-out pin */ | ||
434 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
435 | /* Internal microphone/Mic jack is connected to Mic1 pin */ | ||
436 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, | ||
437 | /* Line In jack is connected to Line1 pin */ | ||
438 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
439 | /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */ | ||
440 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
441 | /* Ensure all other unused pins are disabled and muted. */ | ||
442 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
443 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
444 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
445 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
446 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
447 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
448 | /* Disable digital (SPDIF) pins */ | ||
449 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
450 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
451 | |||
452 | /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum | ||
453 | * bus when acting as outputs. | ||
454 | */ | ||
455 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, | ||
456 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, | ||
457 | |||
458 | /* Start with output sum widgets muted and their output gains at min */ | ||
459 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
460 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
461 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
462 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
463 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
464 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
465 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
466 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
467 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
468 | |||
469 | /* Unmute Line-out pin widget amp left and right | ||
470 | * (no equiv mixer ctrl) | ||
471 | */ | ||
472 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
473 | /* Unmute mono pin widget amp output (no equiv mixer ctrl) */ | ||
474 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
475 | /* Unmute Mic1 and Line1 pin widget input buffers since they start as | ||
476 | * inputs. If the pin mode is changed by the user the pin mode control | ||
477 | * will take care of enabling the pin's input/output buffers as needed. | ||
478 | * Therefore there's no need to enable the input buffer at this | ||
479 | * stage. | ||
480 | */ | ||
481 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
482 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
483 | |||
484 | /* Mute capture amp left and right */ | ||
485 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
486 | /* Set ADC connection select to match default mixer setting - mic | ||
487 | * (on mic1 pin) | ||
488 | */ | ||
489 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
490 | |||
491 | /* Do similar with the second ADC: mute capture input amp and | ||
492 | * set ADC connection to mic to match ALSA's default state. | ||
493 | */ | ||
494 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
495 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
496 | |||
497 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
498 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
499 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
500 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
501 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
502 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
503 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
504 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
505 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
506 | |||
507 | { } | ||
508 | }; | ||
509 | |||
510 | /* Initialisation sequence for Maxdata Favorit 100XS | ||
511 | * (adapted from Acer init verbs). | ||
512 | */ | ||
513 | static const struct hda_verb alc260_favorit100_init_verbs[] = { | ||
514 | /* GPIO 0 enables the output jack. | ||
515 | * Turn this on and rely on the standard mute | ||
516 | * methods whenever the user wants to turn these outputs off. | ||
517 | */ | ||
518 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
519 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
520 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
521 | /* Line/Mic input jack is connected to Mic1 pin */ | ||
522 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, | ||
523 | /* Ensure all other unused pins are disabled and muted. */ | ||
524 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
525 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
526 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
527 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
528 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
529 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
530 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
531 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
532 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
533 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
534 | /* Disable digital (SPDIF) pins */ | ||
535 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
536 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
537 | |||
538 | /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum | ||
539 | * bus when acting as outputs. | ||
540 | */ | ||
541 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, | ||
542 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, | ||
543 | |||
544 | /* Start with output sum widgets muted and their output gains at min */ | ||
545 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
546 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
547 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
548 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
549 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
550 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
551 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
552 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
553 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
554 | |||
555 | /* Unmute Line-out pin widget amp left and right | ||
556 | * (no equiv mixer ctrl) | ||
557 | */ | ||
558 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
559 | /* Unmute Mic1 and Line1 pin widget input buffers since they start as | ||
560 | * inputs. If the pin mode is changed by the user the pin mode control | ||
561 | * will take care of enabling the pin's input/output buffers as needed. | ||
562 | * Therefore there's no need to enable the input buffer at this | ||
563 | * stage. | ||
564 | */ | ||
565 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
566 | |||
567 | /* Mute capture amp left and right */ | ||
568 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
569 | /* Set ADC connection select to match default mixer setting - mic | ||
570 | * (on mic1 pin) | ||
571 | */ | ||
572 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
573 | |||
574 | /* Do similar with the second ADC: mute capture input amp and | ||
575 | * set ADC connection to mic to match ALSA's default state. | ||
576 | */ | ||
577 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
578 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
579 | |||
580 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
581 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
582 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
583 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
584 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
585 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
586 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
587 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
588 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
589 | |||
590 | { } | ||
591 | }; | ||
592 | |||
593 | static const struct hda_verb alc260_will_verbs[] = { | ||
594 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
595 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
596 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
597 | {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | ||
598 | {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
599 | {0x1a, AC_VERB_SET_PROC_COEF, 0x3040}, | ||
600 | {} | ||
601 | }; | ||
602 | |||
603 | static const struct hda_verb alc260_replacer_672v_verbs[] = { | ||
604 | {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | ||
605 | {0x1a, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
606 | {0x1a, AC_VERB_SET_PROC_COEF, 0x3050}, | ||
607 | |||
608 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
609 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
610 | {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, | ||
611 | |||
612 | {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
613 | {} | ||
614 | }; | ||
615 | |||
616 | /* toggle speaker-output according to the hp-jack state */ | ||
617 | static void alc260_replacer_672v_automute(struct hda_codec *codec) | ||
618 | { | ||
619 | unsigned int present; | ||
620 | |||
621 | /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */ | ||
622 | present = snd_hda_jack_detect(codec, 0x0f); | ||
623 | if (present) { | ||
624 | snd_hda_codec_write_cache(codec, 0x01, 0, | ||
625 | AC_VERB_SET_GPIO_DATA, 1); | ||
626 | snd_hda_codec_write_cache(codec, 0x0f, 0, | ||
627 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
628 | PIN_HP); | ||
629 | } else { | ||
630 | snd_hda_codec_write_cache(codec, 0x01, 0, | ||
631 | AC_VERB_SET_GPIO_DATA, 0); | ||
632 | snd_hda_codec_write_cache(codec, 0x0f, 0, | ||
633 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
634 | PIN_OUT); | ||
635 | } | ||
636 | } | ||
637 | |||
638 | static void alc260_replacer_672v_unsol_event(struct hda_codec *codec, | ||
639 | unsigned int res) | ||
640 | { | ||
641 | if ((res >> 26) == ALC_HP_EVENT) | ||
642 | alc260_replacer_672v_automute(codec); | ||
643 | } | ||
644 | |||
645 | static const struct hda_verb alc260_hp_dc7600_verbs[] = { | ||
646 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
647 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
648 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
649 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
650 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
651 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
652 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
653 | {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
654 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
655 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
656 | {} | ||
657 | }; | ||
658 | |||
659 | /* Test configuration for debugging, modelled after the ALC880 test | ||
660 | * configuration. | ||
661 | */ | ||
662 | #ifdef CONFIG_SND_DEBUG | ||
663 | static const hda_nid_t alc260_test_dac_nids[1] = { | ||
664 | 0x02, | ||
665 | }; | ||
666 | static const hda_nid_t alc260_test_adc_nids[2] = { | ||
667 | 0x04, 0x05, | ||
668 | }; | ||
669 | /* For testing the ALC260, each input MUX needs its own definition since | ||
670 | * the signal assignments are different. This assumes that the first ADC | ||
671 | * is NID 0x04. | ||
672 | */ | ||
673 | static const struct hda_input_mux alc260_test_capture_sources[2] = { | ||
674 | { | ||
675 | .num_items = 7, | ||
676 | .items = { | ||
677 | { "MIC1 pin", 0x0 }, | ||
678 | { "MIC2 pin", 0x1 }, | ||
679 | { "LINE1 pin", 0x2 }, | ||
680 | { "LINE2 pin", 0x3 }, | ||
681 | { "CD pin", 0x4 }, | ||
682 | { "LINE-OUT pin", 0x5 }, | ||
683 | { "HP-OUT pin", 0x6 }, | ||
684 | }, | ||
685 | }, | ||
686 | { | ||
687 | .num_items = 8, | ||
688 | .items = { | ||
689 | { "MIC1 pin", 0x0 }, | ||
690 | { "MIC2 pin", 0x1 }, | ||
691 | { "LINE1 pin", 0x2 }, | ||
692 | { "LINE2 pin", 0x3 }, | ||
693 | { "CD pin", 0x4 }, | ||
694 | { "Mixer", 0x5 }, | ||
695 | { "LINE-OUT pin", 0x6 }, | ||
696 | { "HP-OUT pin", 0x7 }, | ||
697 | }, | ||
698 | }, | ||
699 | }; | ||
700 | static const struct snd_kcontrol_new alc260_test_mixer[] = { | ||
701 | /* Output driver widgets */ | ||
702 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), | ||
703 | HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), | ||
704 | HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT), | ||
705 | HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT), | ||
706 | HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
707 | HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT), | ||
708 | |||
709 | /* Modes for retasking pin widgets | ||
710 | * Note: the ALC260 doesn't seem to act on requests to enable mic | ||
711 | * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't | ||
712 | * mention this restriction. At this stage it's not clear whether | ||
713 | * this behaviour is intentional or is a hardware bug in chip | ||
714 | * revisions available at least up until early 2006. Therefore for | ||
715 | * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all | ||
716 | * choices, but if it turns out that the lack of mic bias for these | ||
717 | * NIDs is intentional we could change their modes from | ||
718 | * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. | ||
719 | */ | ||
720 | ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT), | ||
721 | ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT), | ||
722 | ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT), | ||
723 | ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT), | ||
724 | ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT), | ||
725 | ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT), | ||
726 | |||
727 | /* Loopback mixer controls */ | ||
728 | HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT), | ||
729 | HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT), | ||
730 | HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT), | ||
731 | HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT), | ||
732 | HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
733 | HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
734 | HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT), | ||
735 | HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT), | ||
736 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
737 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
738 | HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT), | ||
739 | HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), | ||
740 | HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), | ||
741 | HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT), | ||
742 | |||
743 | /* Controls for GPIO pins, assuming they are configured as outputs */ | ||
744 | ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01), | ||
745 | ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02), | ||
746 | ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04), | ||
747 | ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08), | ||
748 | |||
749 | /* Switches to allow the digital IO pins to be enabled. The datasheet | ||
750 | * is ambigious as to which NID is which; testing on laptops which | ||
751 | * make this output available should provide clarification. | ||
752 | */ | ||
753 | ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01), | ||
754 | ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01), | ||
755 | |||
756 | /* A switch allowing EAPD to be enabled. Some laptops seem to use | ||
757 | * this output to turn on an external amplifier. | ||
758 | */ | ||
759 | ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02), | ||
760 | ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02), | ||
761 | |||
762 | { } /* end */ | ||
763 | }; | ||
764 | static const struct hda_verb alc260_test_init_verbs[] = { | ||
765 | /* Enable all GPIOs as outputs with an initial value of 0 */ | ||
766 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f}, | ||
767 | {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, | ||
768 | {0x01, AC_VERB_SET_GPIO_MASK, 0x0f}, | ||
769 | |||
770 | /* Enable retasking pins as output, initially without power amp */ | ||
771 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
772 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
773 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
774 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
775 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
776 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
777 | |||
778 | /* Disable digital (SPDIF) pins initially, but users can enable | ||
779 | * them via a mixer switch. In the case of SPDIF-out, this initverb | ||
780 | * payload also sets the generation to 0, output to be in "consumer" | ||
781 | * PCM format, copyright asserted, no pre-emphasis and no validity | ||
782 | * control. | ||
783 | */ | ||
784 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
785 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
786 | |||
787 | /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the | ||
788 | * OUT1 sum bus when acting as an output. | ||
789 | */ | ||
790 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, | ||
791 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0}, | ||
792 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, | ||
793 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0}, | ||
794 | |||
795 | /* Start with output sum widgets muted and their output gains at min */ | ||
796 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
797 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
798 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
799 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
800 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
801 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
802 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
803 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
804 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
805 | |||
806 | /* Unmute retasking pin widget output buffers since the default | ||
807 | * state appears to be output. As the pin mode is changed by the | ||
808 | * user the pin mode control will take care of enabling the pin's | ||
809 | * input/output buffers as needed. | ||
810 | */ | ||
811 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
812 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
813 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
814 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
815 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
816 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
817 | /* Also unmute the mono-out pin widget */ | ||
818 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
819 | |||
820 | /* Mute capture amp left and right */ | ||
821 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
822 | /* Set ADC connection select to match default mixer setting (mic1 | ||
823 | * pin) | ||
824 | */ | ||
825 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
826 | |||
827 | /* Do the same for the second ADC: mute capture input amp and | ||
828 | * set ADC connection to mic1 pin | ||
829 | */ | ||
830 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
831 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
832 | |||
833 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
834 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
835 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
836 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
837 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
838 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
839 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
840 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
841 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
842 | |||
843 | { } | ||
844 | }; | ||
845 | #endif | ||
846 | |||
847 | /* | ||
848 | * ALC260 configurations | ||
849 | */ | ||
850 | static const char * const alc260_models[ALC260_MODEL_LAST] = { | ||
851 | [ALC260_BASIC] = "basic", | ||
852 | [ALC260_FUJITSU_S702X] = "fujitsu", | ||
853 | [ALC260_ACER] = "acer", | ||
854 | [ALC260_WILL] = "will", | ||
855 | [ALC260_REPLACER_672V] = "replacer", | ||
856 | [ALC260_FAVORIT100] = "favorit100", | ||
857 | #ifdef CONFIG_SND_DEBUG | ||
858 | [ALC260_TEST] = "test", | ||
859 | #endif | ||
860 | [ALC260_AUTO] = "auto", | ||
861 | }; | ||
862 | |||
863 | static const struct snd_pci_quirk alc260_cfg_tbl[] = { | ||
864 | SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER), | ||
865 | SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL), | ||
866 | SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER), | ||
867 | SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100), | ||
868 | SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC), | ||
869 | SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC), | ||
870 | SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC), | ||
871 | SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X), | ||
872 | SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC), | ||
873 | SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V), | ||
874 | SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL), | ||
875 | {} | ||
876 | }; | ||
877 | |||
878 | static const struct alc_config_preset alc260_presets[] = { | ||
879 | [ALC260_BASIC] = { | ||
880 | .mixers = { alc260_base_output_mixer, | ||
881 | alc260_input_mixer }, | ||
882 | .init_verbs = { alc260_init_verbs }, | ||
883 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
884 | .dac_nids = alc260_dac_nids, | ||
885 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), | ||
886 | .adc_nids = alc260_dual_adc_nids, | ||
887 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
888 | .channel_mode = alc260_modes, | ||
889 | .input_mux = &alc260_capture_source, | ||
890 | }, | ||
891 | [ALC260_FUJITSU_S702X] = { | ||
892 | .mixers = { alc260_fujitsu_mixer }, | ||
893 | .init_verbs = { alc260_fujitsu_init_verbs }, | ||
894 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
895 | .dac_nids = alc260_dac_nids, | ||
896 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), | ||
897 | .adc_nids = alc260_dual_adc_nids, | ||
898 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
899 | .channel_mode = alc260_modes, | ||
900 | .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources), | ||
901 | .input_mux = alc260_fujitsu_capture_sources, | ||
902 | }, | ||
903 | [ALC260_ACER] = { | ||
904 | .mixers = { alc260_acer_mixer }, | ||
905 | .init_verbs = { alc260_acer_init_verbs }, | ||
906 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
907 | .dac_nids = alc260_dac_nids, | ||
908 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), | ||
909 | .adc_nids = alc260_dual_adc_nids, | ||
910 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
911 | .channel_mode = alc260_modes, | ||
912 | .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), | ||
913 | .input_mux = alc260_acer_capture_sources, | ||
914 | }, | ||
915 | [ALC260_FAVORIT100] = { | ||
916 | .mixers = { alc260_favorit100_mixer }, | ||
917 | .init_verbs = { alc260_favorit100_init_verbs }, | ||
918 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
919 | .dac_nids = alc260_dac_nids, | ||
920 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), | ||
921 | .adc_nids = alc260_dual_adc_nids, | ||
922 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
923 | .channel_mode = alc260_modes, | ||
924 | .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources), | ||
925 | .input_mux = alc260_favorit100_capture_sources, | ||
926 | }, | ||
927 | [ALC260_WILL] = { | ||
928 | .mixers = { alc260_will_mixer }, | ||
929 | .init_verbs = { alc260_init_verbs, alc260_will_verbs }, | ||
930 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
931 | .dac_nids = alc260_dac_nids, | ||
932 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), | ||
933 | .adc_nids = alc260_adc_nids, | ||
934 | .dig_out_nid = ALC260_DIGOUT_NID, | ||
935 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
936 | .channel_mode = alc260_modes, | ||
937 | .input_mux = &alc260_capture_source, | ||
938 | }, | ||
939 | [ALC260_REPLACER_672V] = { | ||
940 | .mixers = { alc260_replacer_672v_mixer }, | ||
941 | .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs }, | ||
942 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
943 | .dac_nids = alc260_dac_nids, | ||
944 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), | ||
945 | .adc_nids = alc260_adc_nids, | ||
946 | .dig_out_nid = ALC260_DIGOUT_NID, | ||
947 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
948 | .channel_mode = alc260_modes, | ||
949 | .input_mux = &alc260_capture_source, | ||
950 | .unsol_event = alc260_replacer_672v_unsol_event, | ||
951 | .init_hook = alc260_replacer_672v_automute, | ||
952 | }, | ||
953 | #ifdef CONFIG_SND_DEBUG | ||
954 | [ALC260_TEST] = { | ||
955 | .mixers = { alc260_test_mixer }, | ||
956 | .init_verbs = { alc260_test_init_verbs }, | ||
957 | .num_dacs = ARRAY_SIZE(alc260_test_dac_nids), | ||
958 | .dac_nids = alc260_test_dac_nids, | ||
959 | .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids), | ||
960 | .adc_nids = alc260_test_adc_nids, | ||
961 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
962 | .channel_mode = alc260_modes, | ||
963 | .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources), | ||
964 | .input_mux = alc260_test_capture_sources, | ||
965 | }, | ||
966 | #endif | ||
967 | }; | ||
968 | |||
diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c deleted file mode 100644 index 501501ef36a9..000000000000 --- a/sound/pci/hda/alc880_quirks.c +++ /dev/null | |||
@@ -1,1707 +0,0 @@ | |||
1 | /* | ||
2 | * ALC880 quirk models | ||
3 | * included by patch_realtek.c | ||
4 | */ | ||
5 | |||
6 | /* ALC880 board config type */ | ||
7 | enum { | ||
8 | ALC880_AUTO, | ||
9 | ALC880_3ST, | ||
10 | ALC880_3ST_DIG, | ||
11 | ALC880_5ST, | ||
12 | ALC880_5ST_DIG, | ||
13 | ALC880_W810, | ||
14 | ALC880_Z71V, | ||
15 | ALC880_6ST, | ||
16 | ALC880_6ST_DIG, | ||
17 | ALC880_F1734, | ||
18 | ALC880_ASUS, | ||
19 | ALC880_ASUS_DIG, | ||
20 | ALC880_ASUS_W1V, | ||
21 | ALC880_ASUS_DIG2, | ||
22 | ALC880_FUJITSU, | ||
23 | ALC880_UNIWILL_DIG, | ||
24 | ALC880_UNIWILL, | ||
25 | ALC880_UNIWILL_P53, | ||
26 | ALC880_CLEVO, | ||
27 | ALC880_TCL_S700, | ||
28 | ALC880_LG, | ||
29 | #ifdef CONFIG_SND_DEBUG | ||
30 | ALC880_TEST, | ||
31 | #endif | ||
32 | ALC880_MODEL_LAST /* last tag */ | ||
33 | }; | ||
34 | |||
35 | /* | ||
36 | * ALC880 3-stack model | ||
37 | * | ||
38 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) | ||
39 | * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, | ||
40 | * F-Mic = 0x1b, HP = 0x19 | ||
41 | */ | ||
42 | |||
43 | static const hda_nid_t alc880_dac_nids[4] = { | ||
44 | /* front, rear, clfe, rear_surr */ | ||
45 | 0x02, 0x05, 0x04, 0x03 | ||
46 | }; | ||
47 | |||
48 | static const hda_nid_t alc880_adc_nids[3] = { | ||
49 | /* ADC0-2 */ | ||
50 | 0x07, 0x08, 0x09, | ||
51 | }; | ||
52 | |||
53 | /* The datasheet says the node 0x07 is connected from inputs, | ||
54 | * but it shows zero connection in the real implementation on some devices. | ||
55 | * Note: this is a 915GAV bug, fixed on 915GLV | ||
56 | */ | ||
57 | static const hda_nid_t alc880_adc_nids_alt[2] = { | ||
58 | /* ADC1-2 */ | ||
59 | 0x08, 0x09, | ||
60 | }; | ||
61 | |||
62 | #define ALC880_DIGOUT_NID 0x06 | ||
63 | #define ALC880_DIGIN_NID 0x0a | ||
64 | #define ALC880_PIN_CD_NID 0x1c | ||
65 | |||
66 | static const struct hda_input_mux alc880_capture_source = { | ||
67 | .num_items = 4, | ||
68 | .items = { | ||
69 | { "Mic", 0x0 }, | ||
70 | { "Front Mic", 0x3 }, | ||
71 | { "Line", 0x2 }, | ||
72 | { "CD", 0x4 }, | ||
73 | }, | ||
74 | }; | ||
75 | |||
76 | /* channel source setting (2/6 channel selection for 3-stack) */ | ||
77 | /* 2ch mode */ | ||
78 | static const struct hda_verb alc880_threestack_ch2_init[] = { | ||
79 | /* set line-in to input, mute it */ | ||
80 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
81 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
82 | /* set mic-in to input vref 80%, mute it */ | ||
83 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
84 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
85 | { } /* end */ | ||
86 | }; | ||
87 | |||
88 | /* 6ch mode */ | ||
89 | static const struct hda_verb alc880_threestack_ch6_init[] = { | ||
90 | /* set line-in to output, unmute it */ | ||
91 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
92 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
93 | /* set mic-in to output, unmute it */ | ||
94 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
95 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
96 | { } /* end */ | ||
97 | }; | ||
98 | |||
99 | static const struct hda_channel_mode alc880_threestack_modes[2] = { | ||
100 | { 2, alc880_threestack_ch2_init }, | ||
101 | { 6, alc880_threestack_ch6_init }, | ||
102 | }; | ||
103 | |||
104 | static const struct snd_kcontrol_new alc880_three_stack_mixer[] = { | ||
105 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
106 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
107 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
108 | HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), | ||
109 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
110 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
111 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
112 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
113 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
114 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
115 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
116 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
117 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
118 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
119 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), | ||
120 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), | ||
121 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), | ||
122 | { | ||
123 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
124 | .name = "Channel Mode", | ||
125 | .info = alc_ch_mode_info, | ||
126 | .get = alc_ch_mode_get, | ||
127 | .put = alc_ch_mode_put, | ||
128 | }, | ||
129 | { } /* end */ | ||
130 | }; | ||
131 | |||
132 | /* | ||
133 | * ALC880 5-stack model | ||
134 | * | ||
135 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), | ||
136 | * Side = 0x02 (0xd) | ||
137 | * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 | ||
138 | * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 | ||
139 | */ | ||
140 | |||
141 | /* additional mixers to alc880_three_stack_mixer */ | ||
142 | static const struct snd_kcontrol_new alc880_five_stack_mixer[] = { | ||
143 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
144 | HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT), | ||
145 | { } /* end */ | ||
146 | }; | ||
147 | |||
148 | /* channel source setting (6/8 channel selection for 5-stack) */ | ||
149 | /* 6ch mode */ | ||
150 | static const struct hda_verb alc880_fivestack_ch6_init[] = { | ||
151 | /* set line-in to input, mute it */ | ||
152 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
153 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
154 | { } /* end */ | ||
155 | }; | ||
156 | |||
157 | /* 8ch mode */ | ||
158 | static const struct hda_verb alc880_fivestack_ch8_init[] = { | ||
159 | /* set line-in to output, unmute it */ | ||
160 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
161 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
162 | { } /* end */ | ||
163 | }; | ||
164 | |||
165 | static const struct hda_channel_mode alc880_fivestack_modes[2] = { | ||
166 | { 6, alc880_fivestack_ch6_init }, | ||
167 | { 8, alc880_fivestack_ch8_init }, | ||
168 | }; | ||
169 | |||
170 | |||
171 | /* | ||
172 | * ALC880 6-stack model | ||
173 | * | ||
174 | * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), | ||
175 | * Side = 0x05 (0x0f) | ||
176 | * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, | ||
177 | * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b | ||
178 | */ | ||
179 | |||
180 | static const hda_nid_t alc880_6st_dac_nids[4] = { | ||
181 | /* front, rear, clfe, rear_surr */ | ||
182 | 0x02, 0x03, 0x04, 0x05 | ||
183 | }; | ||
184 | |||
185 | static const struct hda_input_mux alc880_6stack_capture_source = { | ||
186 | .num_items = 4, | ||
187 | .items = { | ||
188 | { "Mic", 0x0 }, | ||
189 | { "Front Mic", 0x1 }, | ||
190 | { "Line", 0x2 }, | ||
191 | { "CD", 0x4 }, | ||
192 | }, | ||
193 | }; | ||
194 | |||
195 | /* fixed 8-channels */ | ||
196 | static const struct hda_channel_mode alc880_sixstack_modes[1] = { | ||
197 | { 8, NULL }, | ||
198 | }; | ||
199 | |||
200 | static const struct snd_kcontrol_new alc880_six_stack_mixer[] = { | ||
201 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
202 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
203 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
204 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
205 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
206 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
207 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
208 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
209 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
210 | HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), | ||
211 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
212 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
213 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
214 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
215 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
216 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
217 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
218 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
219 | { | ||
220 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
221 | .name = "Channel Mode", | ||
222 | .info = alc_ch_mode_info, | ||
223 | .get = alc_ch_mode_get, | ||
224 | .put = alc_ch_mode_put, | ||
225 | }, | ||
226 | { } /* end */ | ||
227 | }; | ||
228 | |||
229 | |||
230 | /* | ||
231 | * ALC880 W810 model | ||
232 | * | ||
233 | * W810 has rear IO for: | ||
234 | * Front (DAC 02) | ||
235 | * Surround (DAC 03) | ||
236 | * Center/LFE (DAC 04) | ||
237 | * Digital out (06) | ||
238 | * | ||
239 | * The system also has a pair of internal speakers, and a headphone jack. | ||
240 | * These are both connected to Line2 on the codec, hence to DAC 02. | ||
241 | * | ||
242 | * There is a variable resistor to control the speaker or headphone | ||
243 | * volume. This is a hardware-only device without a software API. | ||
244 | * | ||
245 | * Plugging headphones in will disable the internal speakers. This is | ||
246 | * implemented in hardware, not via the driver using jack sense. In | ||
247 | * a similar fashion, plugging into the rear socket marked "front" will | ||
248 | * disable both the speakers and headphones. | ||
249 | * | ||
250 | * For input, there's a microphone jack, and an "audio in" jack. | ||
251 | * These may not do anything useful with this driver yet, because I | ||
252 | * haven't setup any initialization verbs for these yet... | ||
253 | */ | ||
254 | |||
255 | static const hda_nid_t alc880_w810_dac_nids[3] = { | ||
256 | /* front, rear/surround, clfe */ | ||
257 | 0x02, 0x03, 0x04 | ||
258 | }; | ||
259 | |||
260 | /* fixed 6 channels */ | ||
261 | static const struct hda_channel_mode alc880_w810_modes[1] = { | ||
262 | { 6, NULL } | ||
263 | }; | ||
264 | |||
265 | /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */ | ||
266 | static const struct snd_kcontrol_new alc880_w810_base_mixer[] = { | ||
267 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
268 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
269 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
270 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
271 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
272 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
273 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
274 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
275 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
276 | { } /* end */ | ||
277 | }; | ||
278 | |||
279 | |||
280 | /* | ||
281 | * Z710V model | ||
282 | * | ||
283 | * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) | ||
284 | * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), | ||
285 | * Line = 0x1a | ||
286 | */ | ||
287 | |||
288 | static const hda_nid_t alc880_z71v_dac_nids[1] = { | ||
289 | 0x02 | ||
290 | }; | ||
291 | #define ALC880_Z71V_HP_DAC 0x03 | ||
292 | |||
293 | /* fixed 2 channels */ | ||
294 | static const struct hda_channel_mode alc880_2_jack_modes[1] = { | ||
295 | { 2, NULL } | ||
296 | }; | ||
297 | |||
298 | static const struct snd_kcontrol_new alc880_z71v_mixer[] = { | ||
299 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
300 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
301 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
302 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), | ||
303 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
304 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
305 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
306 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
307 | { } /* end */ | ||
308 | }; | ||
309 | |||
310 | |||
311 | /* | ||
312 | * ALC880 F1734 model | ||
313 | * | ||
314 | * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d) | ||
315 | * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18 | ||
316 | */ | ||
317 | |||
318 | static const hda_nid_t alc880_f1734_dac_nids[1] = { | ||
319 | 0x03 | ||
320 | }; | ||
321 | #define ALC880_F1734_HP_DAC 0x02 | ||
322 | |||
323 | static const struct snd_kcontrol_new alc880_f1734_mixer[] = { | ||
324 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
325 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), | ||
326 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
327 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | ||
328 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
329 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
330 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
331 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
332 | { } /* end */ | ||
333 | }; | ||
334 | |||
335 | static const struct hda_input_mux alc880_f1734_capture_source = { | ||
336 | .num_items = 2, | ||
337 | .items = { | ||
338 | { "Mic", 0x1 }, | ||
339 | { "CD", 0x4 }, | ||
340 | }, | ||
341 | }; | ||
342 | |||
343 | |||
344 | /* | ||
345 | * ALC880 ASUS model | ||
346 | * | ||
347 | * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) | ||
348 | * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, | ||
349 | * Mic = 0x18, Line = 0x1a | ||
350 | */ | ||
351 | |||
352 | #define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */ | ||
353 | #define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */ | ||
354 | |||
355 | static const struct snd_kcontrol_new alc880_asus_mixer[] = { | ||
356 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
357 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
358 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
359 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
360 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
361 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
362 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
363 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
364 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
365 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
366 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
367 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
368 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
369 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
370 | { | ||
371 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
372 | .name = "Channel Mode", | ||
373 | .info = alc_ch_mode_info, | ||
374 | .get = alc_ch_mode_get, | ||
375 | .put = alc_ch_mode_put, | ||
376 | }, | ||
377 | { } /* end */ | ||
378 | }; | ||
379 | |||
380 | /* | ||
381 | * ALC880 ASUS W1V model | ||
382 | * | ||
383 | * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) | ||
384 | * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, | ||
385 | * Mic = 0x18, Line = 0x1a, Line2 = 0x1b | ||
386 | */ | ||
387 | |||
388 | /* additional mixers to alc880_asus_mixer */ | ||
389 | static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = { | ||
390 | HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT), | ||
391 | HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT), | ||
392 | { } /* end */ | ||
393 | }; | ||
394 | |||
395 | /* TCL S700 */ | ||
396 | static const struct snd_kcontrol_new alc880_tcl_s700_mixer[] = { | ||
397 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
398 | HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
399 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
400 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT), | ||
401 | HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT), | ||
402 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT), | ||
403 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT), | ||
404 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
405 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
406 | { } /* end */ | ||
407 | }; | ||
408 | |||
409 | /* Uniwill */ | ||
410 | static const struct snd_kcontrol_new alc880_uniwill_mixer[] = { | ||
411 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
412 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), | ||
413 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
414 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | ||
415 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
416 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
417 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
418 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
419 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
420 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
421 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
422 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
423 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
424 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
425 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
426 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
427 | { | ||
428 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
429 | .name = "Channel Mode", | ||
430 | .info = alc_ch_mode_info, | ||
431 | .get = alc_ch_mode_get, | ||
432 | .put = alc_ch_mode_put, | ||
433 | }, | ||
434 | { } /* end */ | ||
435 | }; | ||
436 | |||
437 | static const struct snd_kcontrol_new alc880_fujitsu_mixer[] = { | ||
438 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
439 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), | ||
440 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
441 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | ||
442 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
443 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
444 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
445 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
446 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
447 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
448 | { } /* end */ | ||
449 | }; | ||
450 | |||
451 | static const struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = { | ||
452 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
453 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), | ||
454 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
455 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | ||
456 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
457 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
458 | { } /* end */ | ||
459 | }; | ||
460 | |||
461 | /* | ||
462 | * initialize the codec volumes, etc | ||
463 | */ | ||
464 | |||
465 | /* | ||
466 | * generic initialization of ADC, input mixers and output mixers | ||
467 | */ | ||
468 | static const struct hda_verb alc880_volume_init_verbs[] = { | ||
469 | /* | ||
470 | * Unmute ADC0-2 and set the default input to mic-in | ||
471 | */ | ||
472 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
473 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
474 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
475 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
476 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
477 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
478 | |||
479 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | ||
480 | * mixer widget | ||
481 | * Note: PASD motherboards uses the Line In 2 as the input for front | ||
482 | * panel mic (mic 2) | ||
483 | */ | ||
484 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | ||
485 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
486 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
487 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
488 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
489 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
490 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, | ||
491 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, | ||
492 | |||
493 | /* | ||
494 | * Set up output mixers (0x0c - 0x0f) | ||
495 | */ | ||
496 | /* set vol=0 to output mixers */ | ||
497 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
498 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
499 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
500 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
501 | /* set up input amps for analog loopback */ | ||
502 | /* Amp Indices: DAC = 0, mixer = 1 */ | ||
503 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
504 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
505 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
506 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
507 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
508 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
509 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
510 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
511 | |||
512 | { } | ||
513 | }; | ||
514 | |||
515 | /* | ||
516 | * 3-stack pin configuration: | ||
517 | * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b | ||
518 | */ | ||
519 | static const struct hda_verb alc880_pin_3stack_init_verbs[] = { | ||
520 | /* | ||
521 | * preset connection lists of input pins | ||
522 | * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround | ||
523 | */ | ||
524 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ | ||
525 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
526 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ | ||
527 | |||
528 | /* | ||
529 | * Set pin mode and muting | ||
530 | */ | ||
531 | /* set front pin widgets 0x14 for output */ | ||
532 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
533 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
534 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | ||
535 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
536 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
537 | /* Mic2 (as headphone out) for HP output */ | ||
538 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
539 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
540 | /* Line In pin widget for input */ | ||
541 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
542 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
543 | /* Line2 (as front mic) pin widget for input and vref at 80% */ | ||
544 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
545 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
546 | /* CD pin widget for input */ | ||
547 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
548 | |||
549 | { } | ||
550 | }; | ||
551 | |||
552 | /* | ||
553 | * 5-stack pin configuration: | ||
554 | * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19, | ||
555 | * line-in/side = 0x1a, f-mic = 0x1b | ||
556 | */ | ||
557 | static const struct hda_verb alc880_pin_5stack_init_verbs[] = { | ||
558 | /* | ||
559 | * preset connection lists of input pins | ||
560 | * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround | ||
561 | */ | ||
562 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
563 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */ | ||
564 | |||
565 | /* | ||
566 | * Set pin mode and muting | ||
567 | */ | ||
568 | /* set pin widgets 0x14-0x17 for output */ | ||
569 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
570 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
571 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
572 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
573 | /* unmute pins for output (no gain on this amp) */ | ||
574 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
575 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
576 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
577 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
578 | |||
579 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | ||
580 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
581 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
582 | /* Mic2 (as headphone out) for HP output */ | ||
583 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
584 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
585 | /* Line In pin widget for input */ | ||
586 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
587 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
588 | /* Line2 (as front mic) pin widget for input and vref at 80% */ | ||
589 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
590 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
591 | /* CD pin widget for input */ | ||
592 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
593 | |||
594 | { } | ||
595 | }; | ||
596 | |||
597 | /* | ||
598 | * W810 pin configuration: | ||
599 | * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b | ||
600 | */ | ||
601 | static const struct hda_verb alc880_pin_w810_init_verbs[] = { | ||
602 | /* hphone/speaker input selector: front DAC */ | ||
603 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
604 | |||
605 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
606 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
607 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
608 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
609 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
610 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
611 | |||
612 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
613 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
614 | |||
615 | { } | ||
616 | }; | ||
617 | |||
618 | /* | ||
619 | * Z71V pin configuration: | ||
620 | * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?) | ||
621 | */ | ||
622 | static const struct hda_verb alc880_pin_z71v_init_verbs[] = { | ||
623 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
624 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
625 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
626 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
627 | |||
628 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
629 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
630 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
631 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
632 | |||
633 | { } | ||
634 | }; | ||
635 | |||
636 | /* | ||
637 | * 6-stack pin configuration: | ||
638 | * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, | ||
639 | * f-mic = 0x19, line = 0x1a, HP = 0x1b | ||
640 | */ | ||
641 | static const struct hda_verb alc880_pin_6stack_init_verbs[] = { | ||
642 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
643 | |||
644 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
645 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
646 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
647 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
648 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
649 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
650 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
651 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
652 | |||
653 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
654 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
655 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
656 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
657 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
658 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
659 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
660 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
661 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
662 | |||
663 | { } | ||
664 | }; | ||
665 | |||
666 | /* | ||
667 | * Uniwill pin configuration: | ||
668 | * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19, | ||
669 | * line = 0x1a | ||
670 | */ | ||
671 | static const struct hda_verb alc880_uniwill_init_verbs[] = { | ||
672 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
673 | |||
674 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
675 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
676 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
677 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
678 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
679 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
680 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
681 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
682 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
683 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
684 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
685 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
686 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
687 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
688 | |||
689 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
690 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
691 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
692 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
693 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
694 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
695 | /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */ | ||
696 | /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */ | ||
697 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
698 | |||
699 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
700 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT}, | ||
701 | |||
702 | { } | ||
703 | }; | ||
704 | |||
705 | /* | ||
706 | * Uniwill P53 | ||
707 | * HP = 0x14, InternalSpeaker = 0x15, mic = 0x19, | ||
708 | */ | ||
709 | static const struct hda_verb alc880_uniwill_p53_init_verbs[] = { | ||
710 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
711 | |||
712 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
713 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
714 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
715 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
716 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
717 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
718 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
719 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
720 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
721 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
722 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
723 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
724 | |||
725 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
726 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
727 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
728 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
729 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
730 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
731 | |||
732 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
733 | {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_DCVOL_EVENT}, | ||
734 | |||
735 | { } | ||
736 | }; | ||
737 | |||
738 | static const struct hda_verb alc880_beep_init_verbs[] = { | ||
739 | { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) }, | ||
740 | { } | ||
741 | }; | ||
742 | |||
743 | static void alc880_uniwill_setup(struct hda_codec *codec) | ||
744 | { | ||
745 | struct alc_spec *spec = codec->spec; | ||
746 | |||
747 | spec->autocfg.hp_pins[0] = 0x14; | ||
748 | spec->autocfg.speaker_pins[0] = 0x15; | ||
749 | spec->autocfg.speaker_pins[0] = 0x16; | ||
750 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
751 | } | ||
752 | |||
753 | static void alc880_uniwill_init_hook(struct hda_codec *codec) | ||
754 | { | ||
755 | alc_hp_automute(codec); | ||
756 | alc88x_simple_mic_automute(codec); | ||
757 | } | ||
758 | |||
759 | static void alc880_uniwill_unsol_event(struct hda_codec *codec, | ||
760 | unsigned int res) | ||
761 | { | ||
762 | /* Looks like the unsol event is incompatible with the standard | ||
763 | * definition. 4bit tag is placed at 28 bit! | ||
764 | */ | ||
765 | res >>= 28; | ||
766 | switch (res) { | ||
767 | case ALC_MIC_EVENT: | ||
768 | alc88x_simple_mic_automute(codec); | ||
769 | break; | ||
770 | default: | ||
771 | alc_exec_unsol_event(codec, res); | ||
772 | break; | ||
773 | } | ||
774 | } | ||
775 | |||
776 | static void alc880_unsol_event(struct hda_codec *codec, unsigned int res) | ||
777 | { | ||
778 | alc_exec_unsol_event(codec, res >> 28); | ||
779 | } | ||
780 | |||
781 | static void alc880_uniwill_p53_setup(struct hda_codec *codec) | ||
782 | { | ||
783 | struct alc_spec *spec = codec->spec; | ||
784 | |||
785 | spec->autocfg.hp_pins[0] = 0x14; | ||
786 | spec->autocfg.speaker_pins[0] = 0x15; | ||
787 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
788 | } | ||
789 | |||
790 | static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) | ||
791 | { | ||
792 | unsigned int present; | ||
793 | |||
794 | present = snd_hda_codec_read(codec, 0x21, 0, | ||
795 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); | ||
796 | present &= HDA_AMP_VOLMASK; | ||
797 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0, | ||
798 | HDA_AMP_VOLMASK, present); | ||
799 | snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0, | ||
800 | HDA_AMP_VOLMASK, present); | ||
801 | } | ||
802 | |||
803 | static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, | ||
804 | unsigned int res) | ||
805 | { | ||
806 | /* Looks like the unsol event is incompatible with the standard | ||
807 | * definition. 4bit tag is placed at 28 bit! | ||
808 | */ | ||
809 | res >>= 28; | ||
810 | if (res == ALC_DCVOL_EVENT) | ||
811 | alc880_uniwill_p53_dcvol_automute(codec); | ||
812 | else | ||
813 | alc_exec_unsol_event(codec, res); | ||
814 | } | ||
815 | |||
816 | /* | ||
817 | * F1734 pin configuration: | ||
818 | * HP = 0x14, speaker-out = 0x15, mic = 0x18 | ||
819 | */ | ||
820 | static const struct hda_verb alc880_pin_f1734_init_verbs[] = { | ||
821 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
822 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
823 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
824 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
825 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
826 | |||
827 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
828 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
829 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
830 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
831 | |||
832 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
833 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
834 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, | ||
835 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
836 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
837 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
838 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
839 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
840 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
841 | |||
842 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_HP_EVENT}, | ||
843 | {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_DCVOL_EVENT}, | ||
844 | |||
845 | { } | ||
846 | }; | ||
847 | |||
848 | /* | ||
849 | * ASUS pin configuration: | ||
850 | * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a | ||
851 | */ | ||
852 | static const struct hda_verb alc880_pin_asus_init_verbs[] = { | ||
853 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
854 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
855 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
856 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
857 | |||
858 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
859 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
860 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
861 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
862 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
863 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
864 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
865 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
866 | |||
867 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
868 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
869 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
870 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
871 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
872 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
873 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
874 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
875 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
876 | |||
877 | { } | ||
878 | }; | ||
879 | |||
880 | /* Enable GPIO mask and set output */ | ||
881 | #define alc880_gpio1_init_verbs alc_gpio1_init_verbs | ||
882 | #define alc880_gpio2_init_verbs alc_gpio2_init_verbs | ||
883 | #define alc880_gpio3_init_verbs alc_gpio3_init_verbs | ||
884 | |||
885 | /* Clevo m520g init */ | ||
886 | static const struct hda_verb alc880_pin_clevo_init_verbs[] = { | ||
887 | /* headphone output */ | ||
888 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
889 | /* line-out */ | ||
890 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
891 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
892 | /* Line-in */ | ||
893 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
894 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
895 | /* CD */ | ||
896 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
897 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
898 | /* Mic1 (rear panel) */ | ||
899 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
900 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
901 | /* Mic2 (front panel) */ | ||
902 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
903 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
904 | /* headphone */ | ||
905 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
906 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
907 | /* change to EAPD mode */ | ||
908 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
909 | {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, | ||
910 | |||
911 | { } | ||
912 | }; | ||
913 | |||
914 | static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { | ||
915 | /* change to EAPD mode */ | ||
916 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
917 | {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, | ||
918 | |||
919 | /* Headphone output */ | ||
920 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
921 | /* Front output*/ | ||
922 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
923 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
924 | |||
925 | /* Line In pin widget for input */ | ||
926 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
927 | /* CD pin widget for input */ | ||
928 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
929 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | ||
930 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
931 | |||
932 | /* change to EAPD mode */ | ||
933 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
934 | {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, | ||
935 | |||
936 | { } | ||
937 | }; | ||
938 | |||
939 | /* | ||
940 | * LG m1 express dual | ||
941 | * | ||
942 | * Pin assignment: | ||
943 | * Rear Line-In/Out (blue): 0x14 | ||
944 | * Build-in Mic-In: 0x15 | ||
945 | * Speaker-out: 0x17 | ||
946 | * HP-Out (green): 0x1b | ||
947 | * Mic-In/Out (red): 0x19 | ||
948 | * SPDIF-Out: 0x1e | ||
949 | */ | ||
950 | |||
951 | /* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */ | ||
952 | static const hda_nid_t alc880_lg_dac_nids[3] = { | ||
953 | 0x05, 0x02, 0x03 | ||
954 | }; | ||
955 | |||
956 | /* seems analog CD is not working */ | ||
957 | static const struct hda_input_mux alc880_lg_capture_source = { | ||
958 | .num_items = 3, | ||
959 | .items = { | ||
960 | { "Mic", 0x1 }, | ||
961 | { "Line", 0x5 }, | ||
962 | { "Internal Mic", 0x6 }, | ||
963 | }, | ||
964 | }; | ||
965 | |||
966 | /* 2,4,6 channel modes */ | ||
967 | static const struct hda_verb alc880_lg_ch2_init[] = { | ||
968 | /* set line-in and mic-in to input */ | ||
969 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
970 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
971 | { } | ||
972 | }; | ||
973 | |||
974 | static const struct hda_verb alc880_lg_ch4_init[] = { | ||
975 | /* set line-in to out and mic-in to input */ | ||
976 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
977 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
978 | { } | ||
979 | }; | ||
980 | |||
981 | static const struct hda_verb alc880_lg_ch6_init[] = { | ||
982 | /* set line-in and mic-in to output */ | ||
983 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
984 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
985 | { } | ||
986 | }; | ||
987 | |||
988 | static const struct hda_channel_mode alc880_lg_ch_modes[3] = { | ||
989 | { 2, alc880_lg_ch2_init }, | ||
990 | { 4, alc880_lg_ch4_init }, | ||
991 | { 6, alc880_lg_ch6_init }, | ||
992 | }; | ||
993 | |||
994 | static const struct snd_kcontrol_new alc880_lg_mixer[] = { | ||
995 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
996 | HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT), | ||
997 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
998 | HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT), | ||
999 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
1000 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), | ||
1001 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), | ||
1002 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), | ||
1003 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
1004 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
1005 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT), | ||
1006 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT), | ||
1007 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT), | ||
1008 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT), | ||
1009 | { | ||
1010 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1011 | .name = "Channel Mode", | ||
1012 | .info = alc_ch_mode_info, | ||
1013 | .get = alc_ch_mode_get, | ||
1014 | .put = alc_ch_mode_put, | ||
1015 | }, | ||
1016 | { } /* end */ | ||
1017 | }; | ||
1018 | |||
1019 | static const struct hda_verb alc880_lg_init_verbs[] = { | ||
1020 | /* set capture source to mic-in */ | ||
1021 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1022 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1023 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1024 | /* mute all amp mixer inputs */ | ||
1025 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | ||
1026 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, | ||
1027 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, | ||
1028 | /* line-in to input */ | ||
1029 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1030 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1031 | /* built-in mic */ | ||
1032 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1033 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1034 | /* speaker-out */ | ||
1035 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1036 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1037 | /* mic-in to input */ | ||
1038 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
1039 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1040 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1041 | /* HP-out */ | ||
1042 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
1043 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1044 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1045 | /* jack sense */ | ||
1046 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
1047 | { } | ||
1048 | }; | ||
1049 | |||
1050 | /* toggle speaker-output according to the hp-jack state */ | ||
1051 | static void alc880_lg_setup(struct hda_codec *codec) | ||
1052 | { | ||
1053 | struct alc_spec *spec = codec->spec; | ||
1054 | |||
1055 | spec->autocfg.hp_pins[0] = 0x1b; | ||
1056 | spec->autocfg.speaker_pins[0] = 0x17; | ||
1057 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
1058 | } | ||
1059 | |||
1060 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1061 | static const struct hda_amp_list alc880_lg_loopbacks[] = { | ||
1062 | { 0x0b, HDA_INPUT, 1 }, | ||
1063 | { 0x0b, HDA_INPUT, 6 }, | ||
1064 | { 0x0b, HDA_INPUT, 7 }, | ||
1065 | { } /* end */ | ||
1066 | }; | ||
1067 | #endif | ||
1068 | |||
1069 | /* | ||
1070 | * Test configuration for debugging | ||
1071 | * | ||
1072 | * Almost all inputs/outputs are enabled. I/O pins can be configured via | ||
1073 | * enum controls. | ||
1074 | */ | ||
1075 | #ifdef CONFIG_SND_DEBUG | ||
1076 | static const hda_nid_t alc880_test_dac_nids[4] = { | ||
1077 | 0x02, 0x03, 0x04, 0x05 | ||
1078 | }; | ||
1079 | |||
1080 | static const struct hda_input_mux alc880_test_capture_source = { | ||
1081 | .num_items = 7, | ||
1082 | .items = { | ||
1083 | { "In-1", 0x0 }, | ||
1084 | { "In-2", 0x1 }, | ||
1085 | { "In-3", 0x2 }, | ||
1086 | { "In-4", 0x3 }, | ||
1087 | { "CD", 0x4 }, | ||
1088 | { "Front", 0x5 }, | ||
1089 | { "Surround", 0x6 }, | ||
1090 | }, | ||
1091 | }; | ||
1092 | |||
1093 | static const struct hda_channel_mode alc880_test_modes[4] = { | ||
1094 | { 2, NULL }, | ||
1095 | { 4, NULL }, | ||
1096 | { 6, NULL }, | ||
1097 | { 8, NULL }, | ||
1098 | }; | ||
1099 | |||
1100 | static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, | ||
1101 | struct snd_ctl_elem_info *uinfo) | ||
1102 | { | ||
1103 | static const char * const texts[] = { | ||
1104 | "N/A", "Line Out", "HP Out", | ||
1105 | "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%" | ||
1106 | }; | ||
1107 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1108 | uinfo->count = 1; | ||
1109 | uinfo->value.enumerated.items = 8; | ||
1110 | if (uinfo->value.enumerated.item >= 8) | ||
1111 | uinfo->value.enumerated.item = 7; | ||
1112 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
1113 | return 0; | ||
1114 | } | ||
1115 | |||
1116 | static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, | ||
1117 | struct snd_ctl_elem_value *ucontrol) | ||
1118 | { | ||
1119 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1120 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1121 | unsigned int pin_ctl, item = 0; | ||
1122 | |||
1123 | pin_ctl = snd_hda_codec_read(codec, nid, 0, | ||
1124 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
1125 | if (pin_ctl & AC_PINCTL_OUT_EN) { | ||
1126 | if (pin_ctl & AC_PINCTL_HP_EN) | ||
1127 | item = 2; | ||
1128 | else | ||
1129 | item = 1; | ||
1130 | } else if (pin_ctl & AC_PINCTL_IN_EN) { | ||
1131 | switch (pin_ctl & AC_PINCTL_VREFEN) { | ||
1132 | case AC_PINCTL_VREF_HIZ: item = 3; break; | ||
1133 | case AC_PINCTL_VREF_50: item = 4; break; | ||
1134 | case AC_PINCTL_VREF_GRD: item = 5; break; | ||
1135 | case AC_PINCTL_VREF_80: item = 6; break; | ||
1136 | case AC_PINCTL_VREF_100: item = 7; break; | ||
1137 | } | ||
1138 | } | ||
1139 | ucontrol->value.enumerated.item[0] = item; | ||
1140 | return 0; | ||
1141 | } | ||
1142 | |||
1143 | static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, | ||
1144 | struct snd_ctl_elem_value *ucontrol) | ||
1145 | { | ||
1146 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1147 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1148 | static const unsigned int ctls[] = { | ||
1149 | 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN, | ||
1150 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ, | ||
1151 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_50, | ||
1152 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD, | ||
1153 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80, | ||
1154 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_100, | ||
1155 | }; | ||
1156 | unsigned int old_ctl, new_ctl; | ||
1157 | |||
1158 | old_ctl = snd_hda_codec_read(codec, nid, 0, | ||
1159 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
1160 | new_ctl = ctls[ucontrol->value.enumerated.item[0]]; | ||
1161 | if (old_ctl != new_ctl) { | ||
1162 | int val; | ||
1163 | snd_hda_codec_write_cache(codec, nid, 0, | ||
1164 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
1165 | new_ctl); | ||
1166 | val = ucontrol->value.enumerated.item[0] >= 3 ? | ||
1167 | HDA_AMP_MUTE : 0; | ||
1168 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
1169 | HDA_AMP_MUTE, val); | ||
1170 | return 1; | ||
1171 | } | ||
1172 | return 0; | ||
1173 | } | ||
1174 | |||
1175 | static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, | ||
1176 | struct snd_ctl_elem_info *uinfo) | ||
1177 | { | ||
1178 | static const char * const texts[] = { | ||
1179 | "Front", "Surround", "CLFE", "Side" | ||
1180 | }; | ||
1181 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1182 | uinfo->count = 1; | ||
1183 | uinfo->value.enumerated.items = 4; | ||
1184 | if (uinfo->value.enumerated.item >= 4) | ||
1185 | uinfo->value.enumerated.item = 3; | ||
1186 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
1187 | return 0; | ||
1188 | } | ||
1189 | |||
1190 | static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, | ||
1191 | struct snd_ctl_elem_value *ucontrol) | ||
1192 | { | ||
1193 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1194 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1195 | unsigned int sel; | ||
1196 | |||
1197 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); | ||
1198 | ucontrol->value.enumerated.item[0] = sel & 3; | ||
1199 | return 0; | ||
1200 | } | ||
1201 | |||
1202 | static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, | ||
1203 | struct snd_ctl_elem_value *ucontrol) | ||
1204 | { | ||
1205 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1206 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1207 | unsigned int sel; | ||
1208 | |||
1209 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; | ||
1210 | if (ucontrol->value.enumerated.item[0] != sel) { | ||
1211 | sel = ucontrol->value.enumerated.item[0] & 3; | ||
1212 | snd_hda_codec_write_cache(codec, nid, 0, | ||
1213 | AC_VERB_SET_CONNECT_SEL, sel); | ||
1214 | return 1; | ||
1215 | } | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | #define PIN_CTL_TEST(xname,nid) { \ | ||
1220 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1221 | .name = xname, \ | ||
1222 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
1223 | .info = alc_test_pin_ctl_info, \ | ||
1224 | .get = alc_test_pin_ctl_get, \ | ||
1225 | .put = alc_test_pin_ctl_put, \ | ||
1226 | .private_value = nid \ | ||
1227 | } | ||
1228 | |||
1229 | #define PIN_SRC_TEST(xname,nid) { \ | ||
1230 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1231 | .name = xname, \ | ||
1232 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
1233 | .info = alc_test_pin_src_info, \ | ||
1234 | .get = alc_test_pin_src_get, \ | ||
1235 | .put = alc_test_pin_src_put, \ | ||
1236 | .private_value = nid \ | ||
1237 | } | ||
1238 | |||
1239 | static const struct snd_kcontrol_new alc880_test_mixer[] = { | ||
1240 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
1241 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
1242 | HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), | ||
1243 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
1244 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
1245 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
1246 | HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT), | ||
1247 | HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), | ||
1248 | PIN_CTL_TEST("Front Pin Mode", 0x14), | ||
1249 | PIN_CTL_TEST("Surround Pin Mode", 0x15), | ||
1250 | PIN_CTL_TEST("CLFE Pin Mode", 0x16), | ||
1251 | PIN_CTL_TEST("Side Pin Mode", 0x17), | ||
1252 | PIN_CTL_TEST("In-1 Pin Mode", 0x18), | ||
1253 | PIN_CTL_TEST("In-2 Pin Mode", 0x19), | ||
1254 | PIN_CTL_TEST("In-3 Pin Mode", 0x1a), | ||
1255 | PIN_CTL_TEST("In-4 Pin Mode", 0x1b), | ||
1256 | PIN_SRC_TEST("In-1 Pin Source", 0x18), | ||
1257 | PIN_SRC_TEST("In-2 Pin Source", 0x19), | ||
1258 | PIN_SRC_TEST("In-3 Pin Source", 0x1a), | ||
1259 | PIN_SRC_TEST("In-4 Pin Source", 0x1b), | ||
1260 | HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
1261 | HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
1262 | HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
1263 | HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
1264 | HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT), | ||
1265 | HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT), | ||
1266 | HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT), | ||
1267 | HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), | ||
1268 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), | ||
1269 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), | ||
1270 | { | ||
1271 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1272 | .name = "Channel Mode", | ||
1273 | .info = alc_ch_mode_info, | ||
1274 | .get = alc_ch_mode_get, | ||
1275 | .put = alc_ch_mode_put, | ||
1276 | }, | ||
1277 | { } /* end */ | ||
1278 | }; | ||
1279 | |||
1280 | static const struct hda_verb alc880_test_init_verbs[] = { | ||
1281 | /* Unmute inputs of 0x0c - 0x0f */ | ||
1282 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1283 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1284 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1285 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1286 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1287 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1288 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1289 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1290 | /* Vol output for 0x0c-0x0f */ | ||
1291 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1292 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1293 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1294 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1295 | /* Set output pins 0x14-0x17 */ | ||
1296 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1297 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1298 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1299 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1300 | /* Unmute output pins 0x14-0x17 */ | ||
1301 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1302 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1303 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1304 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1305 | /* Set input pins 0x18-0x1c */ | ||
1306 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1307 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1308 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1309 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1310 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1311 | /* Mute input pins 0x18-0x1b */ | ||
1312 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1313 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1314 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1315 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1316 | /* ADC set up */ | ||
1317 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1318 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1319 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1320 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1321 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1322 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1323 | /* Analog input/passthru */ | ||
1324 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1325 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1326 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
1327 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
1328 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
1329 | { } | ||
1330 | }; | ||
1331 | #endif | ||
1332 | |||
1333 | /* | ||
1334 | */ | ||
1335 | |||
1336 | static const char * const alc880_models[ALC880_MODEL_LAST] = { | ||
1337 | [ALC880_3ST] = "3stack", | ||
1338 | [ALC880_TCL_S700] = "tcl", | ||
1339 | [ALC880_3ST_DIG] = "3stack-digout", | ||
1340 | [ALC880_CLEVO] = "clevo", | ||
1341 | [ALC880_5ST] = "5stack", | ||
1342 | [ALC880_5ST_DIG] = "5stack-digout", | ||
1343 | [ALC880_W810] = "w810", | ||
1344 | [ALC880_Z71V] = "z71v", | ||
1345 | [ALC880_6ST] = "6stack", | ||
1346 | [ALC880_6ST_DIG] = "6stack-digout", | ||
1347 | [ALC880_ASUS] = "asus", | ||
1348 | [ALC880_ASUS_W1V] = "asus-w1v", | ||
1349 | [ALC880_ASUS_DIG] = "asus-dig", | ||
1350 | [ALC880_ASUS_DIG2] = "asus-dig2", | ||
1351 | [ALC880_UNIWILL_DIG] = "uniwill", | ||
1352 | [ALC880_UNIWILL_P53] = "uniwill-p53", | ||
1353 | [ALC880_FUJITSU] = "fujitsu", | ||
1354 | [ALC880_F1734] = "F1734", | ||
1355 | [ALC880_LG] = "lg", | ||
1356 | #ifdef CONFIG_SND_DEBUG | ||
1357 | [ALC880_TEST] = "test", | ||
1358 | #endif | ||
1359 | [ALC880_AUTO] = "auto", | ||
1360 | }; | ||
1361 | |||
1362 | static const struct snd_pci_quirk alc880_cfg_tbl[] = { | ||
1363 | SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810), | ||
1364 | SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG), | ||
1365 | SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST), | ||
1366 | SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG), | ||
1367 | SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG), | ||
1368 | SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG), | ||
1369 | SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG), | ||
1370 | SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG), | ||
1371 | SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST), | ||
1372 | SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG), | ||
1373 | SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V), | ||
1374 | SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG), | ||
1375 | SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG), | ||
1376 | SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG), | ||
1377 | SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG), | ||
1378 | SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG), | ||
1379 | SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V), | ||
1380 | /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */ | ||
1381 | SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG), | ||
1382 | SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG), | ||
1383 | SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG), | ||
1384 | SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), | ||
1385 | SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), | ||
1386 | SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), | ||
1387 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */ | ||
1388 | SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST), | ||
1389 | SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST), | ||
1390 | SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST), | ||
1391 | SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST), | ||
1392 | SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST), | ||
1393 | SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG), | ||
1394 | SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG), | ||
1395 | SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG), | ||
1396 | SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG), | ||
1397 | SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO), | ||
1398 | SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO), | ||
1399 | SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2), | ||
1400 | SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), | ||
1401 | SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG), | ||
1402 | SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734), | ||
1403 | SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL), | ||
1404 | SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53), | ||
1405 | SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810), | ||
1406 | SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG), | ||
1407 | SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), | ||
1408 | SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734), | ||
1409 | SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU), | ||
1410 | SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734), | ||
1411 | SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), | ||
1412 | SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG), | ||
1413 | SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG), | ||
1414 | SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG), | ||
1415 | SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700), | ||
1416 | SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */ | ||
1417 | SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG), | ||
1418 | SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG), | ||
1419 | SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG), | ||
1420 | SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG), | ||
1421 | SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG), | ||
1422 | SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG), | ||
1423 | SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG), | ||
1424 | SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG), | ||
1425 | SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG), | ||
1426 | SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG), | ||
1427 | SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG), | ||
1428 | /* default Intel */ | ||
1429 | SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST), | ||
1430 | SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG), | ||
1431 | SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG), | ||
1432 | {} | ||
1433 | }; | ||
1434 | |||
1435 | /* | ||
1436 | * ALC880 codec presets | ||
1437 | */ | ||
1438 | static const struct alc_config_preset alc880_presets[] = { | ||
1439 | [ALC880_3ST] = { | ||
1440 | .mixers = { alc880_three_stack_mixer }, | ||
1441 | .init_verbs = { alc880_volume_init_verbs, | ||
1442 | alc880_pin_3stack_init_verbs }, | ||
1443 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1444 | .dac_nids = alc880_dac_nids, | ||
1445 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
1446 | .channel_mode = alc880_threestack_modes, | ||
1447 | .need_dac_fix = 1, | ||
1448 | .input_mux = &alc880_capture_source, | ||
1449 | }, | ||
1450 | [ALC880_3ST_DIG] = { | ||
1451 | .mixers = { alc880_three_stack_mixer }, | ||
1452 | .init_verbs = { alc880_volume_init_verbs, | ||
1453 | alc880_pin_3stack_init_verbs }, | ||
1454 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1455 | .dac_nids = alc880_dac_nids, | ||
1456 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1457 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
1458 | .channel_mode = alc880_threestack_modes, | ||
1459 | .need_dac_fix = 1, | ||
1460 | .input_mux = &alc880_capture_source, | ||
1461 | }, | ||
1462 | [ALC880_TCL_S700] = { | ||
1463 | .mixers = { alc880_tcl_s700_mixer }, | ||
1464 | .init_verbs = { alc880_volume_init_verbs, | ||
1465 | alc880_pin_tcl_S700_init_verbs, | ||
1466 | alc880_gpio2_init_verbs }, | ||
1467 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1468 | .dac_nids = alc880_dac_nids, | ||
1469 | .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */ | ||
1470 | .num_adc_nids = 1, /* single ADC */ | ||
1471 | .hp_nid = 0x03, | ||
1472 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
1473 | .channel_mode = alc880_2_jack_modes, | ||
1474 | .input_mux = &alc880_capture_source, | ||
1475 | }, | ||
1476 | [ALC880_5ST] = { | ||
1477 | .mixers = { alc880_three_stack_mixer, | ||
1478 | alc880_five_stack_mixer}, | ||
1479 | .init_verbs = { alc880_volume_init_verbs, | ||
1480 | alc880_pin_5stack_init_verbs }, | ||
1481 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1482 | .dac_nids = alc880_dac_nids, | ||
1483 | .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), | ||
1484 | .channel_mode = alc880_fivestack_modes, | ||
1485 | .input_mux = &alc880_capture_source, | ||
1486 | }, | ||
1487 | [ALC880_5ST_DIG] = { | ||
1488 | .mixers = { alc880_three_stack_mixer, | ||
1489 | alc880_five_stack_mixer }, | ||
1490 | .init_verbs = { alc880_volume_init_verbs, | ||
1491 | alc880_pin_5stack_init_verbs }, | ||
1492 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1493 | .dac_nids = alc880_dac_nids, | ||
1494 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1495 | .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), | ||
1496 | .channel_mode = alc880_fivestack_modes, | ||
1497 | .input_mux = &alc880_capture_source, | ||
1498 | }, | ||
1499 | [ALC880_6ST] = { | ||
1500 | .mixers = { alc880_six_stack_mixer }, | ||
1501 | .init_verbs = { alc880_volume_init_verbs, | ||
1502 | alc880_pin_6stack_init_verbs }, | ||
1503 | .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), | ||
1504 | .dac_nids = alc880_6st_dac_nids, | ||
1505 | .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), | ||
1506 | .channel_mode = alc880_sixstack_modes, | ||
1507 | .input_mux = &alc880_6stack_capture_source, | ||
1508 | }, | ||
1509 | [ALC880_6ST_DIG] = { | ||
1510 | .mixers = { alc880_six_stack_mixer }, | ||
1511 | .init_verbs = { alc880_volume_init_verbs, | ||
1512 | alc880_pin_6stack_init_verbs }, | ||
1513 | .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), | ||
1514 | .dac_nids = alc880_6st_dac_nids, | ||
1515 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1516 | .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), | ||
1517 | .channel_mode = alc880_sixstack_modes, | ||
1518 | .input_mux = &alc880_6stack_capture_source, | ||
1519 | }, | ||
1520 | [ALC880_W810] = { | ||
1521 | .mixers = { alc880_w810_base_mixer }, | ||
1522 | .init_verbs = { alc880_volume_init_verbs, | ||
1523 | alc880_pin_w810_init_verbs, | ||
1524 | alc880_gpio2_init_verbs }, | ||
1525 | .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), | ||
1526 | .dac_nids = alc880_w810_dac_nids, | ||
1527 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1528 | .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), | ||
1529 | .channel_mode = alc880_w810_modes, | ||
1530 | .input_mux = &alc880_capture_source, | ||
1531 | }, | ||
1532 | [ALC880_Z71V] = { | ||
1533 | .mixers = { alc880_z71v_mixer }, | ||
1534 | .init_verbs = { alc880_volume_init_verbs, | ||
1535 | alc880_pin_z71v_init_verbs }, | ||
1536 | .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), | ||
1537 | .dac_nids = alc880_z71v_dac_nids, | ||
1538 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1539 | .hp_nid = 0x03, | ||
1540 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
1541 | .channel_mode = alc880_2_jack_modes, | ||
1542 | .input_mux = &alc880_capture_source, | ||
1543 | }, | ||
1544 | [ALC880_F1734] = { | ||
1545 | .mixers = { alc880_f1734_mixer }, | ||
1546 | .init_verbs = { alc880_volume_init_verbs, | ||
1547 | alc880_pin_f1734_init_verbs }, | ||
1548 | .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), | ||
1549 | .dac_nids = alc880_f1734_dac_nids, | ||
1550 | .hp_nid = 0x02, | ||
1551 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
1552 | .channel_mode = alc880_2_jack_modes, | ||
1553 | .input_mux = &alc880_f1734_capture_source, | ||
1554 | .unsol_event = alc880_uniwill_p53_unsol_event, | ||
1555 | .setup = alc880_uniwill_p53_setup, | ||
1556 | .init_hook = alc_hp_automute, | ||
1557 | }, | ||
1558 | [ALC880_ASUS] = { | ||
1559 | .mixers = { alc880_asus_mixer }, | ||
1560 | .init_verbs = { alc880_volume_init_verbs, | ||
1561 | alc880_pin_asus_init_verbs, | ||
1562 | alc880_gpio1_init_verbs }, | ||
1563 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1564 | .dac_nids = alc880_asus_dac_nids, | ||
1565 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1566 | .channel_mode = alc880_asus_modes, | ||
1567 | .need_dac_fix = 1, | ||
1568 | .input_mux = &alc880_capture_source, | ||
1569 | }, | ||
1570 | [ALC880_ASUS_DIG] = { | ||
1571 | .mixers = { alc880_asus_mixer }, | ||
1572 | .init_verbs = { alc880_volume_init_verbs, | ||
1573 | alc880_pin_asus_init_verbs, | ||
1574 | alc880_gpio1_init_verbs }, | ||
1575 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1576 | .dac_nids = alc880_asus_dac_nids, | ||
1577 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1578 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1579 | .channel_mode = alc880_asus_modes, | ||
1580 | .need_dac_fix = 1, | ||
1581 | .input_mux = &alc880_capture_source, | ||
1582 | }, | ||
1583 | [ALC880_ASUS_DIG2] = { | ||
1584 | .mixers = { alc880_asus_mixer }, | ||
1585 | .init_verbs = { alc880_volume_init_verbs, | ||
1586 | alc880_pin_asus_init_verbs, | ||
1587 | alc880_gpio2_init_verbs }, /* use GPIO2 */ | ||
1588 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1589 | .dac_nids = alc880_asus_dac_nids, | ||
1590 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1591 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1592 | .channel_mode = alc880_asus_modes, | ||
1593 | .need_dac_fix = 1, | ||
1594 | .input_mux = &alc880_capture_source, | ||
1595 | }, | ||
1596 | [ALC880_ASUS_W1V] = { | ||
1597 | .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, | ||
1598 | .init_verbs = { alc880_volume_init_verbs, | ||
1599 | alc880_pin_asus_init_verbs, | ||
1600 | alc880_gpio1_init_verbs }, | ||
1601 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1602 | .dac_nids = alc880_asus_dac_nids, | ||
1603 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1604 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1605 | .channel_mode = alc880_asus_modes, | ||
1606 | .need_dac_fix = 1, | ||
1607 | .input_mux = &alc880_capture_source, | ||
1608 | }, | ||
1609 | [ALC880_UNIWILL_DIG] = { | ||
1610 | .mixers = { alc880_asus_mixer }, | ||
1611 | .init_verbs = { alc880_volume_init_verbs, | ||
1612 | alc880_pin_asus_init_verbs }, | ||
1613 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1614 | .dac_nids = alc880_asus_dac_nids, | ||
1615 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1616 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1617 | .channel_mode = alc880_asus_modes, | ||
1618 | .need_dac_fix = 1, | ||
1619 | .input_mux = &alc880_capture_source, | ||
1620 | }, | ||
1621 | [ALC880_UNIWILL] = { | ||
1622 | .mixers = { alc880_uniwill_mixer }, | ||
1623 | .init_verbs = { alc880_volume_init_verbs, | ||
1624 | alc880_uniwill_init_verbs }, | ||
1625 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1626 | .dac_nids = alc880_asus_dac_nids, | ||
1627 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1628 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
1629 | .channel_mode = alc880_threestack_modes, | ||
1630 | .need_dac_fix = 1, | ||
1631 | .input_mux = &alc880_capture_source, | ||
1632 | .unsol_event = alc880_uniwill_unsol_event, | ||
1633 | .setup = alc880_uniwill_setup, | ||
1634 | .init_hook = alc880_uniwill_init_hook, | ||
1635 | }, | ||
1636 | [ALC880_UNIWILL_P53] = { | ||
1637 | .mixers = { alc880_uniwill_p53_mixer }, | ||
1638 | .init_verbs = { alc880_volume_init_verbs, | ||
1639 | alc880_uniwill_p53_init_verbs }, | ||
1640 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1641 | .dac_nids = alc880_asus_dac_nids, | ||
1642 | .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), | ||
1643 | .channel_mode = alc880_threestack_modes, | ||
1644 | .input_mux = &alc880_capture_source, | ||
1645 | .unsol_event = alc880_uniwill_p53_unsol_event, | ||
1646 | .setup = alc880_uniwill_p53_setup, | ||
1647 | .init_hook = alc_hp_automute, | ||
1648 | }, | ||
1649 | [ALC880_FUJITSU] = { | ||
1650 | .mixers = { alc880_fujitsu_mixer }, | ||
1651 | .init_verbs = { alc880_volume_init_verbs, | ||
1652 | alc880_uniwill_p53_init_verbs, | ||
1653 | alc880_beep_init_verbs }, | ||
1654 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1655 | .dac_nids = alc880_dac_nids, | ||
1656 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1657 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
1658 | .channel_mode = alc880_2_jack_modes, | ||
1659 | .input_mux = &alc880_capture_source, | ||
1660 | .unsol_event = alc880_uniwill_p53_unsol_event, | ||
1661 | .setup = alc880_uniwill_p53_setup, | ||
1662 | .init_hook = alc_hp_automute, | ||
1663 | }, | ||
1664 | [ALC880_CLEVO] = { | ||
1665 | .mixers = { alc880_three_stack_mixer }, | ||
1666 | .init_verbs = { alc880_volume_init_verbs, | ||
1667 | alc880_pin_clevo_init_verbs }, | ||
1668 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1669 | .dac_nids = alc880_dac_nids, | ||
1670 | .hp_nid = 0x03, | ||
1671 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
1672 | .channel_mode = alc880_threestack_modes, | ||
1673 | .need_dac_fix = 1, | ||
1674 | .input_mux = &alc880_capture_source, | ||
1675 | }, | ||
1676 | [ALC880_LG] = { | ||
1677 | .mixers = { alc880_lg_mixer }, | ||
1678 | .init_verbs = { alc880_volume_init_verbs, | ||
1679 | alc880_lg_init_verbs }, | ||
1680 | .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids), | ||
1681 | .dac_nids = alc880_lg_dac_nids, | ||
1682 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1683 | .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes), | ||
1684 | .channel_mode = alc880_lg_ch_modes, | ||
1685 | .need_dac_fix = 1, | ||
1686 | .input_mux = &alc880_lg_capture_source, | ||
1687 | .unsol_event = alc880_unsol_event, | ||
1688 | .setup = alc880_lg_setup, | ||
1689 | .init_hook = alc_hp_automute, | ||
1690 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1691 | .loopbacks = alc880_lg_loopbacks, | ||
1692 | #endif | ||
1693 | }, | ||
1694 | #ifdef CONFIG_SND_DEBUG | ||
1695 | [ALC880_TEST] = { | ||
1696 | .mixers = { alc880_test_mixer }, | ||
1697 | .init_verbs = { alc880_test_init_verbs }, | ||
1698 | .num_dacs = ARRAY_SIZE(alc880_test_dac_nids), | ||
1699 | .dac_nids = alc880_test_dac_nids, | ||
1700 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1701 | .num_channel_mode = ARRAY_SIZE(alc880_test_modes), | ||
1702 | .channel_mode = alc880_test_modes, | ||
1703 | .input_mux = &alc880_test_capture_source, | ||
1704 | }, | ||
1705 | #endif | ||
1706 | }; | ||
1707 | |||
diff --git a/sound/pci/hda/alc882_quirks.c b/sound/pci/hda/alc882_quirks.c deleted file mode 100644 index bb364a53f546..000000000000 --- a/sound/pci/hda/alc882_quirks.c +++ /dev/null | |||
@@ -1,866 +0,0 @@ | |||
1 | /* | ||
2 | * ALC882/ALC883/ALC888/ALC889 quirk models | ||
3 | * included by patch_realtek.c | ||
4 | */ | ||
5 | |||
6 | /* ALC882 models */ | ||
7 | enum { | ||
8 | ALC882_AUTO, | ||
9 | ALC885_MBA21, | ||
10 | ALC885_MBP3, | ||
11 | ALC885_MB5, | ||
12 | ALC885_MACMINI3, | ||
13 | ALC885_IMAC91, | ||
14 | ALC889A_MB31, | ||
15 | ALC882_MODEL_LAST, | ||
16 | }; | ||
17 | |||
18 | #define ALC882_DIGOUT_NID 0x06 | ||
19 | #define ALC882_DIGIN_NID 0x0a | ||
20 | #define ALC883_DIGOUT_NID ALC882_DIGOUT_NID | ||
21 | #define ALC883_DIGIN_NID ALC882_DIGIN_NID | ||
22 | #define ALC1200_DIGOUT_NID 0x10 | ||
23 | |||
24 | |||
25 | static const struct hda_channel_mode alc882_ch_modes[1] = { | ||
26 | { 8, NULL } | ||
27 | }; | ||
28 | |||
29 | /* DACs */ | ||
30 | static const hda_nid_t alc882_dac_nids[4] = { | ||
31 | /* front, rear, clfe, rear_surr */ | ||
32 | 0x02, 0x03, 0x04, 0x05 | ||
33 | }; | ||
34 | #define alc883_dac_nids alc882_dac_nids | ||
35 | |||
36 | /* ADCs */ | ||
37 | #define alc882_adc_nids alc880_adc_nids | ||
38 | #define alc882_adc_nids_alt alc880_adc_nids_alt | ||
39 | #define alc883_adc_nids alc882_adc_nids_alt | ||
40 | |||
41 | static const hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 }; | ||
42 | #define alc883_capsrc_nids alc882_capsrc_nids_alt | ||
43 | |||
44 | /* input MUX */ | ||
45 | /* FIXME: should be a matrix-type input source selection */ | ||
46 | |||
47 | static const struct hda_input_mux alc882_capture_source = { | ||
48 | .num_items = 4, | ||
49 | .items = { | ||
50 | { "Mic", 0x0 }, | ||
51 | { "Front Mic", 0x1 }, | ||
52 | { "Line", 0x2 }, | ||
53 | { "CD", 0x4 }, | ||
54 | }, | ||
55 | }; | ||
56 | |||
57 | #define alc883_capture_source alc882_capture_source | ||
58 | |||
59 | static const struct hda_input_mux mb5_capture_source = { | ||
60 | .num_items = 3, | ||
61 | .items = { | ||
62 | { "Mic", 0x1 }, | ||
63 | { "Line", 0x7 }, | ||
64 | { "CD", 0x4 }, | ||
65 | }, | ||
66 | }; | ||
67 | |||
68 | static const struct hda_input_mux macmini3_capture_source = { | ||
69 | .num_items = 2, | ||
70 | .items = { | ||
71 | { "Line", 0x2 }, | ||
72 | { "CD", 0x4 }, | ||
73 | }, | ||
74 | }; | ||
75 | |||
76 | static const struct hda_input_mux alc883_3stack_6ch_intel = { | ||
77 | .num_items = 4, | ||
78 | .items = { | ||
79 | { "Mic", 0x1 }, | ||
80 | { "Front Mic", 0x0 }, | ||
81 | { "Line", 0x2 }, | ||
82 | { "CD", 0x4 }, | ||
83 | }, | ||
84 | }; | ||
85 | |||
86 | static const struct hda_input_mux alc889A_mb31_capture_source = { | ||
87 | .num_items = 2, | ||
88 | .items = { | ||
89 | { "Mic", 0x0 }, | ||
90 | /* Front Mic (0x01) unused */ | ||
91 | { "Line", 0x2 }, | ||
92 | /* Line 2 (0x03) unused */ | ||
93 | /* CD (0x04) unused? */ | ||
94 | }, | ||
95 | }; | ||
96 | |||
97 | static const struct hda_input_mux alc889A_imac91_capture_source = { | ||
98 | .num_items = 2, | ||
99 | .items = { | ||
100 | { "Mic", 0x01 }, | ||
101 | { "Line", 0x2 }, /* Not sure! */ | ||
102 | }, | ||
103 | }; | ||
104 | |||
105 | /* Macbook Air 2,1 */ | ||
106 | |||
107 | static const struct hda_channel_mode alc885_mba21_ch_modes[1] = { | ||
108 | { 2, NULL }, | ||
109 | }; | ||
110 | |||
111 | /* | ||
112 | * macbook pro ALC885 can switch LineIn to LineOut without losing Mic | ||
113 | */ | ||
114 | |||
115 | /* | ||
116 | * 2ch mode | ||
117 | */ | ||
118 | static const struct hda_verb alc885_mbp_ch2_init[] = { | ||
119 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
120 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
121 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
122 | { } /* end */ | ||
123 | }; | ||
124 | |||
125 | /* | ||
126 | * 4ch mode | ||
127 | */ | ||
128 | static const struct hda_verb alc885_mbp_ch4_init[] = { | ||
129 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
130 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
131 | { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
132 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
133 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
134 | { } /* end */ | ||
135 | }; | ||
136 | |||
137 | static const struct hda_channel_mode alc885_mbp_4ch_modes[2] = { | ||
138 | { 2, alc885_mbp_ch2_init }, | ||
139 | { 4, alc885_mbp_ch4_init }, | ||
140 | }; | ||
141 | |||
142 | /* | ||
143 | * 2ch | ||
144 | * Speakers/Woofer/HP = Front | ||
145 | * LineIn = Input | ||
146 | */ | ||
147 | static const struct hda_verb alc885_mb5_ch2_init[] = { | ||
148 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
149 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
150 | { } /* end */ | ||
151 | }; | ||
152 | |||
153 | /* | ||
154 | * 6ch mode | ||
155 | * Speakers/HP = Front | ||
156 | * Woofer = LFE | ||
157 | * LineIn = Surround | ||
158 | */ | ||
159 | static const struct hda_verb alc885_mb5_ch6_init[] = { | ||
160 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
161 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
162 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
163 | { } /* end */ | ||
164 | }; | ||
165 | |||
166 | static const struct hda_channel_mode alc885_mb5_6ch_modes[2] = { | ||
167 | { 2, alc885_mb5_ch2_init }, | ||
168 | { 6, alc885_mb5_ch6_init }, | ||
169 | }; | ||
170 | |||
171 | #define alc885_macmini3_6ch_modes alc885_mb5_6ch_modes | ||
172 | |||
173 | /* Macbook Air 2,1 same control for HP and internal Speaker */ | ||
174 | |||
175 | static const struct snd_kcontrol_new alc885_mba21_mixer[] = { | ||
176 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
177 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT), | ||
178 | { } | ||
179 | }; | ||
180 | |||
181 | |||
182 | static const struct snd_kcontrol_new alc885_mbp3_mixer[] = { | ||
183 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
184 | HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT), | ||
185 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT), | ||
186 | HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT), | ||
187 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), | ||
188 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
189 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
190 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), | ||
191 | HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT), | ||
192 | HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT), | ||
193 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT), | ||
194 | { } /* end */ | ||
195 | }; | ||
196 | |||
197 | static const struct snd_kcontrol_new alc885_mb5_mixer[] = { | ||
198 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
199 | HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT), | ||
200 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), | ||
201 | HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT), | ||
202 | HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT), | ||
203 | HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT), | ||
204 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT), | ||
205 | HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), | ||
206 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT), | ||
207 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), | ||
208 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | ||
209 | HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | ||
210 | HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT), | ||
211 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0x00, HDA_INPUT), | ||
212 | { } /* end */ | ||
213 | }; | ||
214 | |||
215 | static const struct snd_kcontrol_new alc885_macmini3_mixer[] = { | ||
216 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
217 | HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT), | ||
218 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), | ||
219 | HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT), | ||
220 | HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT), | ||
221 | HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT), | ||
222 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT), | ||
223 | HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), | ||
224 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT), | ||
225 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), | ||
226 | HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT), | ||
227 | { } /* end */ | ||
228 | }; | ||
229 | |||
230 | static const struct snd_kcontrol_new alc885_imac91_mixer[] = { | ||
231 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
232 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT), | ||
233 | { } /* end */ | ||
234 | }; | ||
235 | |||
236 | |||
237 | static const struct snd_kcontrol_new alc882_chmode_mixer[] = { | ||
238 | { | ||
239 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
240 | .name = "Channel Mode", | ||
241 | .info = alc_ch_mode_info, | ||
242 | .get = alc_ch_mode_get, | ||
243 | .put = alc_ch_mode_put, | ||
244 | }, | ||
245 | { } /* end */ | ||
246 | }; | ||
247 | |||
248 | static const struct hda_verb alc882_base_init_verbs[] = { | ||
249 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | ||
250 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
251 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
252 | /* Rear mixer */ | ||
253 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
254 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
255 | /* CLFE mixer */ | ||
256 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
257 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
258 | /* Side mixer */ | ||
259 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
260 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
261 | |||
262 | /* Front Pin: output 0 (0x0c) */ | ||
263 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
264 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
265 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
266 | /* Rear Pin: output 1 (0x0d) */ | ||
267 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
268 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
269 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
270 | /* CLFE Pin: output 2 (0x0e) */ | ||
271 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
272 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
273 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
274 | /* Side Pin: output 3 (0x0f) */ | ||
275 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
276 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
277 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
278 | /* Mic (rear) pin: input vref at 80% */ | ||
279 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
280 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
281 | /* Front Mic pin: input vref at 80% */ | ||
282 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
283 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
284 | /* Line In pin: input */ | ||
285 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
286 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
287 | /* Line-2 In: Headphone output (output 0 - 0x0c) */ | ||
288 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
289 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
290 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
291 | /* CD pin widget for input */ | ||
292 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
293 | |||
294 | /* FIXME: use matrix-type input source selection */ | ||
295 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | ||
296 | /* Input mixer2 */ | ||
297 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
298 | /* Input mixer3 */ | ||
299 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
300 | /* ADC2: mute amp left and right */ | ||
301 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
302 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
303 | /* ADC3: mute amp left and right */ | ||
304 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
305 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
306 | |||
307 | { } | ||
308 | }; | ||
309 | |||
310 | #define alc883_init_verbs alc882_base_init_verbs | ||
311 | |||
312 | /* Macbook 5,1 */ | ||
313 | static const struct hda_verb alc885_mb5_init_verbs[] = { | ||
314 | /* DACs */ | ||
315 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
316 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
317 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
318 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
319 | /* Front mixer */ | ||
320 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
321 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
322 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
323 | /* Surround mixer */ | ||
324 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
325 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
326 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
327 | /* LFE mixer */ | ||
328 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
329 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
330 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
331 | /* HP mixer */ | ||
332 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
333 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
334 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
335 | /* Front Pin (0x0c) */ | ||
336 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, | ||
337 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
338 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
339 | /* LFE Pin (0x0e) */ | ||
340 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, | ||
341 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
342 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
343 | /* HP Pin (0x0f) */ | ||
344 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
345 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
346 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
347 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN}, | ||
348 | /* Front Mic pin: input vref at 80% */ | ||
349 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
350 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
351 | /* Line In pin */ | ||
352 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
353 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
354 | |||
355 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)}, | ||
356 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)}, | ||
357 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)}, | ||
358 | { } | ||
359 | }; | ||
360 | |||
361 | /* Macmini 3,1 */ | ||
362 | static const struct hda_verb alc885_macmini3_init_verbs[] = { | ||
363 | /* DACs */ | ||
364 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
365 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
366 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
367 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
368 | /* Front mixer */ | ||
369 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
370 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
371 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
372 | /* Surround mixer */ | ||
373 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
374 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
375 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
376 | /* LFE mixer */ | ||
377 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
378 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
379 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
380 | /* HP mixer */ | ||
381 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
382 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
383 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
384 | /* Front Pin (0x0c) */ | ||
385 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, | ||
386 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
387 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
388 | /* LFE Pin (0x0e) */ | ||
389 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01}, | ||
390 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
391 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
392 | /* HP Pin (0x0f) */ | ||
393 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
394 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
395 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
396 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN}, | ||
397 | /* Line In pin */ | ||
398 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
399 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
400 | |||
401 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
402 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
403 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
404 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
405 | { } | ||
406 | }; | ||
407 | |||
408 | |||
409 | static const struct hda_verb alc885_mba21_init_verbs[] = { | ||
410 | /*Internal and HP Speaker Mixer*/ | ||
411 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
412 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
413 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
414 | /*Internal Speaker Pin (0x0c)*/ | ||
415 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) }, | ||
416 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
417 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
418 | /* HP Pin: output 0 (0x0e) */ | ||
419 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, | ||
420 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
421 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
422 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)}, | ||
423 | /* Line in (is hp when jack connected)*/ | ||
424 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50}, | ||
425 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
426 | |||
427 | { } | ||
428 | }; | ||
429 | |||
430 | |||
431 | /* Macbook Pro rev3 */ | ||
432 | static const struct hda_verb alc885_mbp3_init_verbs[] = { | ||
433 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | ||
434 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
435 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
436 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
437 | /* Rear mixer */ | ||
438 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
439 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
440 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
441 | /* HP mixer */ | ||
442 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
443 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
444 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
445 | /* Front Pin: output 0 (0x0c) */ | ||
446 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
447 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
448 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
449 | /* HP Pin: output 0 (0x0e) */ | ||
450 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, | ||
451 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
452 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
453 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN}, | ||
454 | /* Mic (rear) pin: input vref at 80% */ | ||
455 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
456 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
457 | /* Front Mic pin: input vref at 80% */ | ||
458 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
459 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
460 | /* Line In pin: use output 1 when in LineOut mode */ | ||
461 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
462 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
463 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
464 | |||
465 | /* FIXME: use matrix-type input source selection */ | ||
466 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | ||
467 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ | ||
468 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
469 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
470 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
471 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
472 | /* Input mixer2 */ | ||
473 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
474 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
475 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
476 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
477 | /* Input mixer3 */ | ||
478 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
479 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
480 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
481 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
482 | /* ADC1: mute amp left and right */ | ||
483 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
484 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
485 | /* ADC2: mute amp left and right */ | ||
486 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
487 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
488 | /* ADC3: mute amp left and right */ | ||
489 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
490 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
491 | |||
492 | { } | ||
493 | }; | ||
494 | |||
495 | /* iMac 9,1 */ | ||
496 | static const struct hda_verb alc885_imac91_init_verbs[] = { | ||
497 | /* Internal Speaker Pin (0x0c) */ | ||
498 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) }, | ||
499 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
500 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
501 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) }, | ||
502 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
503 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
504 | /* HP Pin: Rear */ | ||
505 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
506 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
507 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
508 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)}, | ||
509 | /* Line in Rear */ | ||
510 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50}, | ||
511 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
512 | /* Front Mic pin: input vref at 80% */ | ||
513 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
514 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
515 | /* Rear mixer */ | ||
516 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
517 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
518 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
519 | /* Line-Out mixer: unmute input/output amp left and right (volume = 0) */ | ||
520 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
521 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
522 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
523 | /* 0x24 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */ | ||
524 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
525 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
526 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
527 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
528 | /* 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */ | ||
529 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
530 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
531 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
532 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
533 | /* 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */ | ||
534 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
535 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
536 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
537 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
538 | /* 0x07 [Audio Input] wcaps 0x10011b: Stereo Amp-In */ | ||
539 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
540 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
541 | /* 0x08 [Audio Input] wcaps 0x10011b: Stereo Amp-In */ | ||
542 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
543 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
544 | /* 0x09 [Audio Input] wcaps 0x10011b: Stereo Amp-In */ | ||
545 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
546 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
547 | { } | ||
548 | }; | ||
549 | |||
550 | /* Toggle speaker-output according to the hp-jack state */ | ||
551 | static void alc885_imac24_setup(struct hda_codec *codec) | ||
552 | { | ||
553 | struct alc_spec *spec = codec->spec; | ||
554 | |||
555 | spec->autocfg.hp_pins[0] = 0x14; | ||
556 | spec->autocfg.speaker_pins[0] = 0x18; | ||
557 | spec->autocfg.speaker_pins[1] = 0x1a; | ||
558 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
559 | } | ||
560 | |||
561 | #define alc885_mb5_setup alc885_imac24_setup | ||
562 | #define alc885_macmini3_setup alc885_imac24_setup | ||
563 | |||
564 | /* Macbook Air 2,1 */ | ||
565 | static void alc885_mba21_setup(struct hda_codec *codec) | ||
566 | { | ||
567 | struct alc_spec *spec = codec->spec; | ||
568 | |||
569 | spec->autocfg.hp_pins[0] = 0x14; | ||
570 | spec->autocfg.speaker_pins[0] = 0x18; | ||
571 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
572 | } | ||
573 | |||
574 | |||
575 | |||
576 | static void alc885_mbp3_setup(struct hda_codec *codec) | ||
577 | { | ||
578 | struct alc_spec *spec = codec->spec; | ||
579 | |||
580 | spec->autocfg.hp_pins[0] = 0x15; | ||
581 | spec->autocfg.speaker_pins[0] = 0x14; | ||
582 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
583 | } | ||
584 | |||
585 | static void alc885_imac91_setup(struct hda_codec *codec) | ||
586 | { | ||
587 | struct alc_spec *spec = codec->spec; | ||
588 | |||
589 | spec->autocfg.hp_pins[0] = 0x14; | ||
590 | spec->autocfg.speaker_pins[0] = 0x18; | ||
591 | spec->autocfg.speaker_pins[1] = 0x1a; | ||
592 | alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP); | ||
593 | } | ||
594 | |||
595 | /* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */ | ||
596 | static const struct hda_verb alc889A_mb31_ch2_init[] = { | ||
597 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */ | ||
598 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */ | ||
599 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */ | ||
600 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */ | ||
601 | { } /* end */ | ||
602 | }; | ||
603 | |||
604 | /* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */ | ||
605 | static const struct hda_verb alc889A_mb31_ch4_init[] = { | ||
606 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */ | ||
607 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */ | ||
608 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */ | ||
609 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */ | ||
610 | { } /* end */ | ||
611 | }; | ||
612 | |||
613 | /* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */ | ||
614 | static const struct hda_verb alc889A_mb31_ch5_init[] = { | ||
615 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as rear */ | ||
616 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */ | ||
617 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */ | ||
618 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */ | ||
619 | { } /* end */ | ||
620 | }; | ||
621 | |||
622 | /* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */ | ||
623 | static const struct hda_verb alc889A_mb31_ch6_init[] = { | ||
624 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as front */ | ||
625 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Subwoofer off */ | ||
626 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */ | ||
627 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */ | ||
628 | { } /* end */ | ||
629 | }; | ||
630 | |||
631 | static const struct hda_channel_mode alc889A_mb31_6ch_modes[4] = { | ||
632 | { 2, alc889A_mb31_ch2_init }, | ||
633 | { 4, alc889A_mb31_ch4_init }, | ||
634 | { 5, alc889A_mb31_ch5_init }, | ||
635 | { 6, alc889A_mb31_ch6_init }, | ||
636 | }; | ||
637 | |||
638 | static const struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { | ||
639 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
640 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
641 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
642 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
643 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
644 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
645 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
646 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
647 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
648 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
649 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
650 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
651 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
652 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
653 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), | ||
654 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
655 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
656 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), | ||
657 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
658 | { } /* end */ | ||
659 | }; | ||
660 | |||
661 | static const struct snd_kcontrol_new alc889A_mb31_mixer[] = { | ||
662 | /* Output mixers */ | ||
663 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
664 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT), | ||
665 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), | ||
666 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT), | ||
667 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00, | ||
668 | HDA_OUTPUT), | ||
669 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT), | ||
670 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT), | ||
671 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT), | ||
672 | /* Output switches */ | ||
673 | HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT), | ||
674 | HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT), | ||
675 | HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT), | ||
676 | /* Boost mixers */ | ||
677 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT), | ||
678 | HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT), | ||
679 | /* Input mixers */ | ||
680 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), | ||
681 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT), | ||
682 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
683 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
684 | { } /* end */ | ||
685 | }; | ||
686 | |||
687 | static const struct snd_kcontrol_new alc883_chmode_mixer[] = { | ||
688 | { | ||
689 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
690 | .name = "Channel Mode", | ||
691 | .info = alc_ch_mode_info, | ||
692 | .get = alc_ch_mode_get, | ||
693 | .put = alc_ch_mode_put, | ||
694 | }, | ||
695 | { } /* end */ | ||
696 | }; | ||
697 | |||
698 | static const struct hda_verb alc889A_mb31_verbs[] = { | ||
699 | /* Init rear pin (used as headphone output) */ | ||
700 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, /* Apple Headphones */ | ||
701 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Connect to front */ | ||
702 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN}, | ||
703 | /* Init line pin (used as output in 4ch and 6ch mode) */ | ||
704 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Connect to CLFE */ | ||
705 | /* Init line 2 pin (used as headphone out by default) */ | ||
706 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Use as input */ | ||
707 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */ | ||
708 | { } /* end */ | ||
709 | }; | ||
710 | |||
711 | /* Mute speakers according to the headphone jack state */ | ||
712 | static void alc889A_mb31_automute(struct hda_codec *codec) | ||
713 | { | ||
714 | unsigned int present; | ||
715 | |||
716 | /* Mute only in 2ch or 4ch mode */ | ||
717 | if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0) | ||
718 | == 0x00) { | ||
719 | present = snd_hda_jack_detect(codec, 0x15); | ||
720 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
721 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
722 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, | ||
723 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
724 | } | ||
725 | } | ||
726 | |||
727 | static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res) | ||
728 | { | ||
729 | if ((res >> 26) == ALC_HP_EVENT) | ||
730 | alc889A_mb31_automute(codec); | ||
731 | } | ||
732 | |||
733 | static void alc882_unsol_event(struct hda_codec *codec, unsigned int res) | ||
734 | { | ||
735 | alc_exec_unsol_event(codec, res >> 26); | ||
736 | } | ||
737 | |||
738 | /* | ||
739 | * configuration and preset | ||
740 | */ | ||
741 | static const char * const alc882_models[ALC882_MODEL_LAST] = { | ||
742 | [ALC885_MB5] = "mb5", | ||
743 | [ALC885_MACMINI3] = "macmini3", | ||
744 | [ALC885_MBA21] = "mba21", | ||
745 | [ALC885_MBP3] = "mbp3", | ||
746 | [ALC885_IMAC91] = "imac91", | ||
747 | [ALC889A_MB31] = "mb31", | ||
748 | [ALC882_AUTO] = "auto", | ||
749 | }; | ||
750 | |||
751 | /* codec SSID table for Intel Mac */ | ||
752 | static const struct snd_pci_quirk alc882_ssid_cfg_tbl[] = { | ||
753 | SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3), | ||
754 | SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3), | ||
755 | SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3), | ||
756 | SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3), | ||
757 | SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31), | ||
758 | SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3), | ||
759 | SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21), | ||
760 | SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31), | ||
761 | SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3), | ||
762 | SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91), | ||
763 | SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5), | ||
764 | SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5), | ||
765 | /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2, | ||
766 | * so apparently no perfect solution yet | ||
767 | */ | ||
768 | SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5), | ||
769 | SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5), | ||
770 | SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3), | ||
771 | {} /* terminator */ | ||
772 | }; | ||
773 | |||
774 | static const struct alc_config_preset alc882_presets[] = { | ||
775 | [ALC885_MBA21] = { | ||
776 | .mixers = { alc885_mba21_mixer }, | ||
777 | .init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs }, | ||
778 | .num_dacs = 2, | ||
779 | .dac_nids = alc882_dac_nids, | ||
780 | .channel_mode = alc885_mba21_ch_modes, | ||
781 | .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes), | ||
782 | .input_mux = &alc882_capture_source, | ||
783 | .unsol_event = alc882_unsol_event, | ||
784 | .setup = alc885_mba21_setup, | ||
785 | .init_hook = alc_hp_automute, | ||
786 | }, | ||
787 | [ALC885_MBP3] = { | ||
788 | .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, | ||
789 | .init_verbs = { alc885_mbp3_init_verbs, | ||
790 | alc880_gpio1_init_verbs }, | ||
791 | .num_dacs = 2, | ||
792 | .dac_nids = alc882_dac_nids, | ||
793 | .hp_nid = 0x04, | ||
794 | .channel_mode = alc885_mbp_4ch_modes, | ||
795 | .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes), | ||
796 | .input_mux = &alc882_capture_source, | ||
797 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
798 | .dig_in_nid = ALC882_DIGIN_NID, | ||
799 | .unsol_event = alc882_unsol_event, | ||
800 | .setup = alc885_mbp3_setup, | ||
801 | .init_hook = alc_hp_automute, | ||
802 | }, | ||
803 | [ALC885_MB5] = { | ||
804 | .mixers = { alc885_mb5_mixer, alc882_chmode_mixer }, | ||
805 | .init_verbs = { alc885_mb5_init_verbs, | ||
806 | alc880_gpio1_init_verbs }, | ||
807 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
808 | .dac_nids = alc882_dac_nids, | ||
809 | .channel_mode = alc885_mb5_6ch_modes, | ||
810 | .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes), | ||
811 | .input_mux = &mb5_capture_source, | ||
812 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
813 | .dig_in_nid = ALC882_DIGIN_NID, | ||
814 | .unsol_event = alc882_unsol_event, | ||
815 | .setup = alc885_mb5_setup, | ||
816 | .init_hook = alc_hp_automute, | ||
817 | }, | ||
818 | [ALC885_MACMINI3] = { | ||
819 | .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer }, | ||
820 | .init_verbs = { alc885_macmini3_init_verbs, | ||
821 | alc880_gpio1_init_verbs }, | ||
822 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
823 | .dac_nids = alc882_dac_nids, | ||
824 | .channel_mode = alc885_macmini3_6ch_modes, | ||
825 | .num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes), | ||
826 | .input_mux = &macmini3_capture_source, | ||
827 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
828 | .dig_in_nid = ALC882_DIGIN_NID, | ||
829 | .unsol_event = alc882_unsol_event, | ||
830 | .setup = alc885_macmini3_setup, | ||
831 | .init_hook = alc_hp_automute, | ||
832 | }, | ||
833 | [ALC885_IMAC91] = { | ||
834 | .mixers = {alc885_imac91_mixer}, | ||
835 | .init_verbs = { alc885_imac91_init_verbs, | ||
836 | alc880_gpio1_init_verbs }, | ||
837 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
838 | .dac_nids = alc882_dac_nids, | ||
839 | .channel_mode = alc885_mba21_ch_modes, | ||
840 | .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes), | ||
841 | .input_mux = &alc889A_imac91_capture_source, | ||
842 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
843 | .dig_in_nid = ALC882_DIGIN_NID, | ||
844 | .unsol_event = alc882_unsol_event, | ||
845 | .setup = alc885_imac91_setup, | ||
846 | .init_hook = alc_hp_automute, | ||
847 | }, | ||
848 | [ALC889A_MB31] = { | ||
849 | .mixers = { alc889A_mb31_mixer, alc883_chmode_mixer}, | ||
850 | .init_verbs = { alc883_init_verbs, alc889A_mb31_verbs, | ||
851 | alc880_gpio1_init_verbs }, | ||
852 | .adc_nids = alc883_adc_nids, | ||
853 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
854 | .capsrc_nids = alc883_capsrc_nids, | ||
855 | .dac_nids = alc883_dac_nids, | ||
856 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
857 | .channel_mode = alc889A_mb31_6ch_modes, | ||
858 | .num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes), | ||
859 | .input_mux = &alc889A_mb31_capture_source, | ||
860 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
861 | .unsol_event = alc889A_mb31_unsol_event, | ||
862 | .init_hook = alc889A_mb31_automute, | ||
863 | }, | ||
864 | }; | ||
865 | |||
866 | |||
diff --git a/sound/pci/hda/alc_quirks.c b/sound/pci/hda/alc_quirks.c deleted file mode 100644 index a18952ed4311..000000000000 --- a/sound/pci/hda/alc_quirks.c +++ /dev/null | |||
@@ -1,480 +0,0 @@ | |||
1 | /* | ||
2 | * Common codes for Realtek codec quirks | ||
3 | * included by patch_realtek.c | ||
4 | */ | ||
5 | |||
6 | /* | ||
7 | * configuration template - to be copied to the spec instance | ||
8 | */ | ||
9 | struct alc_config_preset { | ||
10 | const struct snd_kcontrol_new *mixers[5]; /* should be identical size | ||
11 | * with spec | ||
12 | */ | ||
13 | const struct snd_kcontrol_new *cap_mixer; /* capture mixer */ | ||
14 | const struct hda_verb *init_verbs[5]; | ||
15 | unsigned int num_dacs; | ||
16 | const hda_nid_t *dac_nids; | ||
17 | hda_nid_t dig_out_nid; /* optional */ | ||
18 | hda_nid_t hp_nid; /* optional */ | ||
19 | const hda_nid_t *slave_dig_outs; | ||
20 | unsigned int num_adc_nids; | ||
21 | const hda_nid_t *adc_nids; | ||
22 | const hda_nid_t *capsrc_nids; | ||
23 | hda_nid_t dig_in_nid; | ||
24 | unsigned int num_channel_mode; | ||
25 | const struct hda_channel_mode *channel_mode; | ||
26 | int need_dac_fix; | ||
27 | int const_channel_count; | ||
28 | unsigned int num_mux_defs; | ||
29 | const struct hda_input_mux *input_mux; | ||
30 | void (*unsol_event)(struct hda_codec *, unsigned int); | ||
31 | void (*setup)(struct hda_codec *); | ||
32 | void (*init_hook)(struct hda_codec *); | ||
33 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
34 | const struct hda_amp_list *loopbacks; | ||
35 | void (*power_hook)(struct hda_codec *codec); | ||
36 | #endif | ||
37 | }; | ||
38 | |||
39 | /* | ||
40 | * channel mode setting | ||
41 | */ | ||
42 | static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, | ||
43 | struct snd_ctl_elem_info *uinfo) | ||
44 | { | ||
45 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
46 | struct alc_spec *spec = codec->spec; | ||
47 | return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, | ||
48 | spec->num_channel_mode); | ||
49 | } | ||
50 | |||
51 | static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, | ||
52 | struct snd_ctl_elem_value *ucontrol) | ||
53 | { | ||
54 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
55 | struct alc_spec *spec = codec->spec; | ||
56 | return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, | ||
57 | spec->num_channel_mode, | ||
58 | spec->ext_channel_count); | ||
59 | } | ||
60 | |||
61 | static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, | ||
62 | struct snd_ctl_elem_value *ucontrol) | ||
63 | { | ||
64 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
65 | struct alc_spec *spec = codec->spec; | ||
66 | int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, | ||
67 | spec->num_channel_mode, | ||
68 | &spec->ext_channel_count); | ||
69 | if (err >= 0 && !spec->const_channel_count) { | ||
70 | spec->multiout.max_channels = spec->ext_channel_count; | ||
71 | if (spec->need_dac_fix) | ||
72 | spec->multiout.num_dacs = spec->multiout.max_channels / 2; | ||
73 | } | ||
74 | return err; | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * Control the mode of pin widget settings via the mixer. "pc" is used | ||
79 | * instead of "%" to avoid consequences of accidentally treating the % as | ||
80 | * being part of a format specifier. Maximum allowed length of a value is | ||
81 | * 63 characters plus NULL terminator. | ||
82 | * | ||
83 | * Note: some retasking pin complexes seem to ignore requests for input | ||
84 | * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these | ||
85 | * are requested. Therefore order this list so that this behaviour will not | ||
86 | * cause problems when mixer clients move through the enum sequentially. | ||
87 | * NIDs 0x0f and 0x10 have been observed to have this behaviour as of | ||
88 | * March 2006. | ||
89 | */ | ||
90 | static const char * const alc_pin_mode_names[] = { | ||
91 | "Mic 50pc bias", "Mic 80pc bias", | ||
92 | "Line in", "Line out", "Headphone out", | ||
93 | }; | ||
94 | static const unsigned char alc_pin_mode_values[] = { | ||
95 | PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP, | ||
96 | }; | ||
97 | /* The control can present all 5 options, or it can limit the options based | ||
98 | * in the pin being assumed to be exclusively an input or an output pin. In | ||
99 | * addition, "input" pins may or may not process the mic bias option | ||
100 | * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to | ||
101 | * accept requests for bias as of chip versions up to March 2006) and/or | ||
102 | * wiring in the computer. | ||
103 | */ | ||
104 | #define ALC_PIN_DIR_IN 0x00 | ||
105 | #define ALC_PIN_DIR_OUT 0x01 | ||
106 | #define ALC_PIN_DIR_INOUT 0x02 | ||
107 | #define ALC_PIN_DIR_IN_NOMICBIAS 0x03 | ||
108 | #define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04 | ||
109 | |||
110 | /* Info about the pin modes supported by the different pin direction modes. | ||
111 | * For each direction the minimum and maximum values are given. | ||
112 | */ | ||
113 | static const signed char alc_pin_mode_dir_info[5][2] = { | ||
114 | { 0, 2 }, /* ALC_PIN_DIR_IN */ | ||
115 | { 3, 4 }, /* ALC_PIN_DIR_OUT */ | ||
116 | { 0, 4 }, /* ALC_PIN_DIR_INOUT */ | ||
117 | { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */ | ||
118 | { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */ | ||
119 | }; | ||
120 | #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0]) | ||
121 | #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1]) | ||
122 | #define alc_pin_mode_n_items(_dir) \ | ||
123 | (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1) | ||
124 | |||
125 | static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, | ||
126 | struct snd_ctl_elem_info *uinfo) | ||
127 | { | ||
128 | unsigned int item_num = uinfo->value.enumerated.item; | ||
129 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; | ||
130 | |||
131 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
132 | uinfo->count = 1; | ||
133 | uinfo->value.enumerated.items = alc_pin_mode_n_items(dir); | ||
134 | |||
135 | if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir)) | ||
136 | item_num = alc_pin_mode_min(dir); | ||
137 | strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]); | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, | ||
142 | struct snd_ctl_elem_value *ucontrol) | ||
143 | { | ||
144 | unsigned int i; | ||
145 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
146 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
147 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; | ||
148 | long *valp = ucontrol->value.integer.value; | ||
149 | unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, | ||
150 | AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
151 | 0x00); | ||
152 | |||
153 | /* Find enumerated value for current pinctl setting */ | ||
154 | i = alc_pin_mode_min(dir); | ||
155 | while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl) | ||
156 | i++; | ||
157 | *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir); | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, | ||
162 | struct snd_ctl_elem_value *ucontrol) | ||
163 | { | ||
164 | signed int change; | ||
165 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
166 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
167 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; | ||
168 | long val = *ucontrol->value.integer.value; | ||
169 | unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, | ||
170 | AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
171 | 0x00); | ||
172 | |||
173 | if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) | ||
174 | val = alc_pin_mode_min(dir); | ||
175 | |||
176 | change = pinctl != alc_pin_mode_values[val]; | ||
177 | if (change) { | ||
178 | /* Set pin mode to that requested */ | ||
179 | snd_hda_codec_write_cache(codec, nid, 0, | ||
180 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
181 | alc_pin_mode_values[val]); | ||
182 | |||
183 | /* Also enable the retasking pin's input/output as required | ||
184 | * for the requested pin mode. Enum values of 2 or less are | ||
185 | * input modes. | ||
186 | * | ||
187 | * Dynamically switching the input/output buffers probably | ||
188 | * reduces noise slightly (particularly on input) so we'll | ||
189 | * do it. However, having both input and output buffers | ||
190 | * enabled simultaneously doesn't seem to be problematic if | ||
191 | * this turns out to be necessary in the future. | ||
192 | */ | ||
193 | if (val <= 2) { | ||
194 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
195 | HDA_AMP_MUTE, HDA_AMP_MUTE); | ||
196 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, | ||
197 | HDA_AMP_MUTE, 0); | ||
198 | } else { | ||
199 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, | ||
200 | HDA_AMP_MUTE, HDA_AMP_MUTE); | ||
201 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
202 | HDA_AMP_MUTE, 0); | ||
203 | } | ||
204 | } | ||
205 | return change; | ||
206 | } | ||
207 | |||
208 | #define ALC_PIN_MODE(xname, nid, dir) \ | ||
209 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
210 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
211 | .info = alc_pin_mode_info, \ | ||
212 | .get = alc_pin_mode_get, \ | ||
213 | .put = alc_pin_mode_put, \ | ||
214 | .private_value = nid | (dir<<16) } | ||
215 | |||
216 | /* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged | ||
217 | * together using a mask with more than one bit set. This control is | ||
218 | * currently used only by the ALC260 test model. At this stage they are not | ||
219 | * needed for any "production" models. | ||
220 | */ | ||
221 | #ifdef CONFIG_SND_DEBUG | ||
222 | #define alc_gpio_data_info snd_ctl_boolean_mono_info | ||
223 | |||
224 | static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, | ||
225 | struct snd_ctl_elem_value *ucontrol) | ||
226 | { | ||
227 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
228 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
229 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
230 | long *valp = ucontrol->value.integer.value; | ||
231 | unsigned int val = snd_hda_codec_read(codec, nid, 0, | ||
232 | AC_VERB_GET_GPIO_DATA, 0x00); | ||
233 | |||
234 | *valp = (val & mask) != 0; | ||
235 | return 0; | ||
236 | } | ||
237 | static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, | ||
238 | struct snd_ctl_elem_value *ucontrol) | ||
239 | { | ||
240 | signed int change; | ||
241 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
242 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
243 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
244 | long val = *ucontrol->value.integer.value; | ||
245 | unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0, | ||
246 | AC_VERB_GET_GPIO_DATA, | ||
247 | 0x00); | ||
248 | |||
249 | /* Set/unset the masked GPIO bit(s) as needed */ | ||
250 | change = (val == 0 ? 0 : mask) != (gpio_data & mask); | ||
251 | if (val == 0) | ||
252 | gpio_data &= ~mask; | ||
253 | else | ||
254 | gpio_data |= mask; | ||
255 | snd_hda_codec_write_cache(codec, nid, 0, | ||
256 | AC_VERB_SET_GPIO_DATA, gpio_data); | ||
257 | |||
258 | return change; | ||
259 | } | ||
260 | #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ | ||
261 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
262 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
263 | .info = alc_gpio_data_info, \ | ||
264 | .get = alc_gpio_data_get, \ | ||
265 | .put = alc_gpio_data_put, \ | ||
266 | .private_value = nid | (mask<<16) } | ||
267 | #endif /* CONFIG_SND_DEBUG */ | ||
268 | |||
269 | /* A switch control to allow the enabling of the digital IO pins on the | ||
270 | * ALC260. This is incredibly simplistic; the intention of this control is | ||
271 | * to provide something in the test model allowing digital outputs to be | ||
272 | * identified if present. If models are found which can utilise these | ||
273 | * outputs a more complete mixer control can be devised for those models if | ||
274 | * necessary. | ||
275 | */ | ||
276 | #ifdef CONFIG_SND_DEBUG | ||
277 | #define alc_spdif_ctrl_info snd_ctl_boolean_mono_info | ||
278 | |||
279 | static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, | ||
280 | struct snd_ctl_elem_value *ucontrol) | ||
281 | { | ||
282 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
283 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
284 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
285 | long *valp = ucontrol->value.integer.value; | ||
286 | unsigned int val = snd_hda_codec_read(codec, nid, 0, | ||
287 | AC_VERB_GET_DIGI_CONVERT_1, 0x00); | ||
288 | |||
289 | *valp = (val & mask) != 0; | ||
290 | return 0; | ||
291 | } | ||
292 | static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, | ||
293 | struct snd_ctl_elem_value *ucontrol) | ||
294 | { | ||
295 | signed int change; | ||
296 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
297 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
298 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
299 | long val = *ucontrol->value.integer.value; | ||
300 | unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, | ||
301 | AC_VERB_GET_DIGI_CONVERT_1, | ||
302 | 0x00); | ||
303 | |||
304 | /* Set/unset the masked control bit(s) as needed */ | ||
305 | change = (val == 0 ? 0 : mask) != (ctrl_data & mask); | ||
306 | if (val==0) | ||
307 | ctrl_data &= ~mask; | ||
308 | else | ||
309 | ctrl_data |= mask; | ||
310 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | ||
311 | ctrl_data); | ||
312 | |||
313 | return change; | ||
314 | } | ||
315 | #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ | ||
316 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
317 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
318 | .info = alc_spdif_ctrl_info, \ | ||
319 | .get = alc_spdif_ctrl_get, \ | ||
320 | .put = alc_spdif_ctrl_put, \ | ||
321 | .private_value = nid | (mask<<16) } | ||
322 | #endif /* CONFIG_SND_DEBUG */ | ||
323 | |||
324 | /* A switch control to allow the enabling EAPD digital outputs on the ALC26x. | ||
325 | * Again, this is only used in the ALC26x test models to help identify when | ||
326 | * the EAPD line must be asserted for features to work. | ||
327 | */ | ||
328 | #ifdef CONFIG_SND_DEBUG | ||
329 | #define alc_eapd_ctrl_info snd_ctl_boolean_mono_info | ||
330 | |||
331 | static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol, | ||
332 | struct snd_ctl_elem_value *ucontrol) | ||
333 | { | ||
334 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
335 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
336 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
337 | long *valp = ucontrol->value.integer.value; | ||
338 | unsigned int val = snd_hda_codec_read(codec, nid, 0, | ||
339 | AC_VERB_GET_EAPD_BTLENABLE, 0x00); | ||
340 | |||
341 | *valp = (val & mask) != 0; | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol, | ||
346 | struct snd_ctl_elem_value *ucontrol) | ||
347 | { | ||
348 | int change; | ||
349 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
350 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
351 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
352 | long val = *ucontrol->value.integer.value; | ||
353 | unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, | ||
354 | AC_VERB_GET_EAPD_BTLENABLE, | ||
355 | 0x00); | ||
356 | |||
357 | /* Set/unset the masked control bit(s) as needed */ | ||
358 | change = (!val ? 0 : mask) != (ctrl_data & mask); | ||
359 | if (!val) | ||
360 | ctrl_data &= ~mask; | ||
361 | else | ||
362 | ctrl_data |= mask; | ||
363 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
364 | ctrl_data); | ||
365 | |||
366 | return change; | ||
367 | } | ||
368 | |||
369 | #define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \ | ||
370 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
371 | .subdevice = HDA_SUBDEV_NID_FLAG | nid, \ | ||
372 | .info = alc_eapd_ctrl_info, \ | ||
373 | .get = alc_eapd_ctrl_get, \ | ||
374 | .put = alc_eapd_ctrl_put, \ | ||
375 | .private_value = nid | (mask<<16) } | ||
376 | #endif /* CONFIG_SND_DEBUG */ | ||
377 | |||
378 | static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec) | ||
379 | { | ||
380 | struct alc_spec *spec = codec->spec; | ||
381 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
382 | |||
383 | if (!cfg->line_outs) { | ||
384 | while (cfg->line_outs < AUTO_CFG_MAX_OUTS && | ||
385 | cfg->line_out_pins[cfg->line_outs]) | ||
386 | cfg->line_outs++; | ||
387 | } | ||
388 | if (!cfg->speaker_outs) { | ||
389 | while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS && | ||
390 | cfg->speaker_pins[cfg->speaker_outs]) | ||
391 | cfg->speaker_outs++; | ||
392 | } | ||
393 | if (!cfg->hp_outs) { | ||
394 | while (cfg->hp_outs < AUTO_CFG_MAX_OUTS && | ||
395 | cfg->hp_pins[cfg->hp_outs]) | ||
396 | cfg->hp_outs++; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | /* | ||
401 | * set up from the preset table | ||
402 | */ | ||
403 | static void setup_preset(struct hda_codec *codec, | ||
404 | const struct alc_config_preset *preset) | ||
405 | { | ||
406 | struct alc_spec *spec = codec->spec; | ||
407 | int i; | ||
408 | |||
409 | for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) | ||
410 | add_mixer(spec, preset->mixers[i]); | ||
411 | spec->cap_mixer = preset->cap_mixer; | ||
412 | for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; | ||
413 | i++) | ||
414 | add_verb(spec, preset->init_verbs[i]); | ||
415 | |||
416 | spec->channel_mode = preset->channel_mode; | ||
417 | spec->num_channel_mode = preset->num_channel_mode; | ||
418 | spec->need_dac_fix = preset->need_dac_fix; | ||
419 | spec->const_channel_count = preset->const_channel_count; | ||
420 | |||
421 | if (preset->const_channel_count) | ||
422 | spec->multiout.max_channels = preset->const_channel_count; | ||
423 | else | ||
424 | spec->multiout.max_channels = spec->channel_mode[0].channels; | ||
425 | spec->ext_channel_count = spec->channel_mode[0].channels; | ||
426 | |||
427 | spec->multiout.num_dacs = preset->num_dacs; | ||
428 | spec->multiout.dac_nids = preset->dac_nids; | ||
429 | spec->multiout.dig_out_nid = preset->dig_out_nid; | ||
430 | spec->multiout.slave_dig_outs = preset->slave_dig_outs; | ||
431 | spec->multiout.hp_nid = preset->hp_nid; | ||
432 | |||
433 | spec->num_mux_defs = preset->num_mux_defs; | ||
434 | if (!spec->num_mux_defs) | ||
435 | spec->num_mux_defs = 1; | ||
436 | spec->input_mux = preset->input_mux; | ||
437 | |||
438 | spec->num_adc_nids = preset->num_adc_nids; | ||
439 | spec->adc_nids = preset->adc_nids; | ||
440 | spec->capsrc_nids = preset->capsrc_nids; | ||
441 | spec->dig_in_nid = preset->dig_in_nid; | ||
442 | |||
443 | spec->unsol_event = preset->unsol_event; | ||
444 | spec->init_hook = preset->init_hook; | ||
445 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
446 | spec->power_hook = preset->power_hook; | ||
447 | spec->loopback.amplist = preset->loopbacks; | ||
448 | #endif | ||
449 | |||
450 | if (preset->setup) | ||
451 | preset->setup(codec); | ||
452 | |||
453 | alc_fixup_autocfg_pin_nums(codec); | ||
454 | } | ||
455 | |||
456 | static void alc_simple_setup_automute(struct alc_spec *spec, int mode) | ||
457 | { | ||
458 | int lo_pin = spec->autocfg.line_out_pins[0]; | ||
459 | |||
460 | if (lo_pin == spec->autocfg.speaker_pins[0] || | ||
461 | lo_pin == spec->autocfg.hp_pins[0]) | ||
462 | lo_pin = 0; | ||
463 | spec->automute_mode = mode; | ||
464 | spec->detect_hp = !!spec->autocfg.hp_pins[0]; | ||
465 | spec->detect_lo = !!lo_pin; | ||
466 | spec->automute_lo = spec->automute_lo_possible = !!lo_pin; | ||
467 | spec->automute_speaker = spec->automute_speaker_possible = !!spec->autocfg.speaker_pins[0]; | ||
468 | } | ||
469 | |||
470 | /* auto-toggle front mic */ | ||
471 | static void alc88x_simple_mic_automute(struct hda_codec *codec) | ||
472 | { | ||
473 | unsigned int present; | ||
474 | unsigned char bits; | ||
475 | |||
476 | present = snd_hda_jack_detect(codec, 0x18); | ||
477 | bits = present ? HDA_AMP_MUTE : 0; | ||
478 | snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits); | ||
479 | } | ||
480 | |||
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 684307372d73..7a8fcc4c15f8 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/mm.h> | ||
22 | #include <linux/init.h> | 23 | #include <linux/init.h> |
23 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
@@ -2304,7 +2305,7 @@ typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *); | |||
2304 | 2305 | ||
2305 | /* apply the function to all matching slave ctls in the mixer list */ | 2306 | /* apply the function to all matching slave ctls in the mixer list */ |
2306 | static int map_slaves(struct hda_codec *codec, const char * const *slaves, | 2307 | static int map_slaves(struct hda_codec *codec, const char * const *slaves, |
2307 | map_slave_func_t func, void *data) | 2308 | const char *suffix, map_slave_func_t func, void *data) |
2308 | { | 2309 | { |
2309 | struct hda_nid_item *items; | 2310 | struct hda_nid_item *items; |
2310 | const char * const *s; | 2311 | const char * const *s; |
@@ -2317,7 +2318,14 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves, | |||
2317 | sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER) | 2318 | sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER) |
2318 | continue; | 2319 | continue; |
2319 | for (s = slaves; *s; s++) { | 2320 | for (s = slaves; *s; s++) { |
2320 | if (!strcmp(sctl->id.name, *s)) { | 2321 | char tmpname[sizeof(sctl->id.name)]; |
2322 | const char *name = *s; | ||
2323 | if (suffix) { | ||
2324 | snprintf(tmpname, sizeof(tmpname), "%s %s", | ||
2325 | name, suffix); | ||
2326 | name = tmpname; | ||
2327 | } | ||
2328 | if (!strcmp(sctl->id.name, name)) { | ||
2321 | err = func(data, sctl); | 2329 | err = func(data, sctl); |
2322 | if (err) | 2330 | if (err) |
2323 | return err; | 2331 | return err; |
@@ -2333,12 +2341,65 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl) | |||
2333 | return 1; | 2341 | return 1; |
2334 | } | 2342 | } |
2335 | 2343 | ||
2344 | /* guess the value corresponding to 0dB */ | ||
2345 | static int get_kctl_0dB_offset(struct snd_kcontrol *kctl) | ||
2346 | { | ||
2347 | int _tlv[4]; | ||
2348 | const int *tlv = NULL; | ||
2349 | int val = -1; | ||
2350 | |||
2351 | if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { | ||
2352 | /* FIXME: set_fs() hack for obtaining user-space TLV data */ | ||
2353 | mm_segment_t fs = get_fs(); | ||
2354 | set_fs(get_ds()); | ||
2355 | if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv)) | ||
2356 | tlv = _tlv; | ||
2357 | set_fs(fs); | ||
2358 | } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) | ||
2359 | tlv = kctl->tlv.p; | ||
2360 | if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) | ||
2361 | val = -tlv[2] / tlv[3]; | ||
2362 | return val; | ||
2363 | } | ||
2364 | |||
2365 | /* call kctl->put with the given value(s) */ | ||
2366 | static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) | ||
2367 | { | ||
2368 | struct snd_ctl_elem_value *ucontrol; | ||
2369 | ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL); | ||
2370 | if (!ucontrol) | ||
2371 | return -ENOMEM; | ||
2372 | ucontrol->value.integer.value[0] = val; | ||
2373 | ucontrol->value.integer.value[1] = val; | ||
2374 | kctl->put(kctl, ucontrol); | ||
2375 | kfree(ucontrol); | ||
2376 | return 0; | ||
2377 | } | ||
2378 | |||
2379 | /* initialize the slave volume with 0dB */ | ||
2380 | static int init_slave_0dB(void *data, struct snd_kcontrol *slave) | ||
2381 | { | ||
2382 | int offset = get_kctl_0dB_offset(slave); | ||
2383 | if (offset > 0) | ||
2384 | put_kctl_with_value(slave, offset); | ||
2385 | return 0; | ||
2386 | } | ||
2387 | |||
2388 | /* unmute the slave */ | ||
2389 | static int init_slave_unmute(void *data, struct snd_kcontrol *slave) | ||
2390 | { | ||
2391 | return put_kctl_with_value(slave, 1); | ||
2392 | } | ||
2393 | |||
2336 | /** | 2394 | /** |
2337 | * snd_hda_add_vmaster - create a virtual master control and add slaves | 2395 | * snd_hda_add_vmaster - create a virtual master control and add slaves |
2338 | * @codec: HD-audio codec | 2396 | * @codec: HD-audio codec |
2339 | * @name: vmaster control name | 2397 | * @name: vmaster control name |
2340 | * @tlv: TLV data (optional) | 2398 | * @tlv: TLV data (optional) |
2341 | * @slaves: slave control names (optional) | 2399 | * @slaves: slave control names (optional) |
2400 | * @suffix: suffix string to each slave name (optional) | ||
2401 | * @init_slave_vol: initialize slaves to unmute/0dB | ||
2402 | * @ctl_ret: store the vmaster kcontrol in return | ||
2342 | * | 2403 | * |
2343 | * Create a virtual master control with the given name. The TLV data | 2404 | * Create a virtual master control with the given name. The TLV data |
2344 | * must be either NULL or a valid data. | 2405 | * must be either NULL or a valid data. |
@@ -2349,13 +2410,18 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl) | |||
2349 | * | 2410 | * |
2350 | * This function returns zero if successful or a negative error code. | 2411 | * This function returns zero if successful or a negative error code. |
2351 | */ | 2412 | */ |
2352 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 2413 | int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
2353 | unsigned int *tlv, const char * const *slaves) | 2414 | unsigned int *tlv, const char * const *slaves, |
2415 | const char *suffix, bool init_slave_vol, | ||
2416 | struct snd_kcontrol **ctl_ret) | ||
2354 | { | 2417 | { |
2355 | struct snd_kcontrol *kctl; | 2418 | struct snd_kcontrol *kctl; |
2356 | int err; | 2419 | int err; |
2357 | 2420 | ||
2358 | err = map_slaves(codec, slaves, check_slave_present, NULL); | 2421 | if (ctl_ret) |
2422 | *ctl_ret = NULL; | ||
2423 | |||
2424 | err = map_slaves(codec, slaves, suffix, check_slave_present, NULL); | ||
2359 | if (err != 1) { | 2425 | if (err != 1) { |
2360 | snd_printdd("No slave found for %s\n", name); | 2426 | snd_printdd("No slave found for %s\n", name); |
2361 | return 0; | 2427 | return 0; |
@@ -2367,13 +2433,119 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
2367 | if (err < 0) | 2433 | if (err < 0) |
2368 | return err; | 2434 | return err; |
2369 | 2435 | ||
2370 | err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave, | 2436 | err = map_slaves(codec, slaves, suffix, |
2371 | kctl); | 2437 | (map_slave_func_t)snd_ctl_add_slave, kctl); |
2372 | if (err < 0) | 2438 | if (err < 0) |
2373 | return err; | 2439 | return err; |
2440 | |||
2441 | /* init with master mute & zero volume */ | ||
2442 | put_kctl_with_value(kctl, 0); | ||
2443 | if (init_slave_vol) | ||
2444 | map_slaves(codec, slaves, suffix, | ||
2445 | tlv ? init_slave_0dB : init_slave_unmute, kctl); | ||
2446 | |||
2447 | if (ctl_ret) | ||
2448 | *ctl_ret = kctl; | ||
2374 | return 0; | 2449 | return 0; |
2375 | } | 2450 | } |
2376 | EXPORT_SYMBOL_HDA(snd_hda_add_vmaster); | 2451 | EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster); |
2452 | |||
2453 | /* | ||
2454 | * mute-LED control using vmaster | ||
2455 | */ | ||
2456 | static int vmaster_mute_mode_info(struct snd_kcontrol *kcontrol, | ||
2457 | struct snd_ctl_elem_info *uinfo) | ||
2458 | { | ||
2459 | static const char * const texts[] = { | ||
2460 | "Off", "On", "Follow Master" | ||
2461 | }; | ||
2462 | unsigned int index; | ||
2463 | |||
2464 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2465 | uinfo->count = 1; | ||
2466 | uinfo->value.enumerated.items = 3; | ||
2467 | index = uinfo->value.enumerated.item; | ||
2468 | if (index >= 3) | ||
2469 | index = 2; | ||
2470 | strcpy(uinfo->value.enumerated.name, texts[index]); | ||
2471 | return 0; | ||
2472 | } | ||
2473 | |||
2474 | static int vmaster_mute_mode_get(struct snd_kcontrol *kcontrol, | ||
2475 | struct snd_ctl_elem_value *ucontrol) | ||
2476 | { | ||
2477 | struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol); | ||
2478 | ucontrol->value.enumerated.item[0] = hook->mute_mode; | ||
2479 | return 0; | ||
2480 | } | ||
2481 | |||
2482 | static int vmaster_mute_mode_put(struct snd_kcontrol *kcontrol, | ||
2483 | struct snd_ctl_elem_value *ucontrol) | ||
2484 | { | ||
2485 | struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol); | ||
2486 | unsigned int old_mode = hook->mute_mode; | ||
2487 | |||
2488 | hook->mute_mode = ucontrol->value.enumerated.item[0]; | ||
2489 | if (hook->mute_mode > HDA_VMUTE_FOLLOW_MASTER) | ||
2490 | hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; | ||
2491 | if (old_mode == hook->mute_mode) | ||
2492 | return 0; | ||
2493 | snd_hda_sync_vmaster_hook(hook); | ||
2494 | return 1; | ||
2495 | } | ||
2496 | |||
2497 | static struct snd_kcontrol_new vmaster_mute_mode = { | ||
2498 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2499 | .name = "Mute-LED Mode", | ||
2500 | .info = vmaster_mute_mode_info, | ||
2501 | .get = vmaster_mute_mode_get, | ||
2502 | .put = vmaster_mute_mode_put, | ||
2503 | }; | ||
2504 | |||
2505 | /* | ||
2506 | * Add a mute-LED hook with the given vmaster switch kctl | ||
2507 | * "Mute-LED Mode" control is automatically created and associated with | ||
2508 | * the given hook. | ||
2509 | */ | ||
2510 | int snd_hda_add_vmaster_hook(struct hda_codec *codec, | ||
2511 | struct hda_vmaster_mute_hook *hook, | ||
2512 | bool expose_enum_ctl) | ||
2513 | { | ||
2514 | struct snd_kcontrol *kctl; | ||
2515 | |||
2516 | if (!hook->hook || !hook->sw_kctl) | ||
2517 | return 0; | ||
2518 | snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec); | ||
2519 | hook->codec = codec; | ||
2520 | hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; | ||
2521 | if (!expose_enum_ctl) | ||
2522 | return 0; | ||
2523 | kctl = snd_ctl_new1(&vmaster_mute_mode, hook); | ||
2524 | if (!kctl) | ||
2525 | return -ENOMEM; | ||
2526 | return snd_hda_ctl_add(codec, 0, kctl); | ||
2527 | } | ||
2528 | EXPORT_SYMBOL_HDA(snd_hda_add_vmaster_hook); | ||
2529 | |||
2530 | /* | ||
2531 | * Call the hook with the current value for synchronization | ||
2532 | * Should be called in init callback | ||
2533 | */ | ||
2534 | void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook) | ||
2535 | { | ||
2536 | if (!hook->hook || !hook->codec) | ||
2537 | return; | ||
2538 | switch (hook->mute_mode) { | ||
2539 | case HDA_VMUTE_FOLLOW_MASTER: | ||
2540 | snd_ctl_sync_vmaster_hook(hook->sw_kctl); | ||
2541 | break; | ||
2542 | default: | ||
2543 | hook->hook(hook->codec, hook->mute_mode); | ||
2544 | break; | ||
2545 | } | ||
2546 | } | ||
2547 | EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook); | ||
2548 | |||
2377 | 2549 | ||
2378 | /** | 2550 | /** |
2379 | * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch | 2551 | * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch |
@@ -5272,6 +5444,10 @@ int snd_hda_suspend(struct hda_bus *bus) | |||
5272 | list_for_each_entry(codec, &bus->codec_list, list) { | 5444 | list_for_each_entry(codec, &bus->codec_list, list) { |
5273 | if (hda_codec_is_power_on(codec)) | 5445 | if (hda_codec_is_power_on(codec)) |
5274 | hda_call_codec_suspend(codec); | 5446 | hda_call_codec_suspend(codec); |
5447 | else /* forcibly change the power to D3 even if not used */ | ||
5448 | hda_set_power_state(codec, | ||
5449 | codec->afg ? codec->afg : codec->mfg, | ||
5450 | AC_PWRST_D3); | ||
5275 | if (codec->patch_ops.post_suspend) | 5451 | if (codec->patch_ops.post_suspend) |
5276 | codec->patch_ops.post_suspend(codec); | 5452 | codec->patch_ops.post_suspend(codec); |
5277 | } | 5453 | } |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index f0f1943a4b2c..9a9f372e1be4 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -855,6 +855,7 @@ struct hda_codec { | |||
855 | unsigned int pins_shutup:1; /* pins are shut up */ | 855 | unsigned int pins_shutup:1; /* pins are shut up */ |
856 | unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ | 856 | unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ |
857 | unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */ | 857 | unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */ |
858 | unsigned int no_jack_detect:1; /* Machine has no jack-detection */ | ||
858 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 859 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
859 | unsigned int power_on :1; /* current (global) power-state */ | 860 | unsigned int power_on :1; /* current (global) power-state */ |
860 | unsigned int power_transition :1; /* power-state in transition */ | 861 | unsigned int power_transition :1; /* power-state in transition */ |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 95dfb6874941..c19e71a94e1b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -84,7 +84,7 @@ module_param_array(model, charp, NULL, 0444); | |||
84 | MODULE_PARM_DESC(model, "Use the given board model."); | 84 | MODULE_PARM_DESC(model, "Use the given board model."); |
85 | module_param_array(position_fix, int, NULL, 0444); | 85 | module_param_array(position_fix, int, NULL, 0444); |
86 | MODULE_PARM_DESC(position_fix, "DMA pointer read method." | 86 | MODULE_PARM_DESC(position_fix, "DMA pointer read method." |
87 | "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO)."); | 87 | "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO)."); |
88 | module_param_array(bdl_pos_adj, int, NULL, 0644); | 88 | module_param_array(bdl_pos_adj, int, NULL, 0644); |
89 | MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); | 89 | MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); |
90 | module_param_array(probe_mask, int, NULL, 0444); | 90 | module_param_array(probe_mask, int, NULL, 0444); |
@@ -94,7 +94,7 @@ MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); | |||
94 | module_param(single_cmd, bool, 0444); | 94 | module_param(single_cmd, bool, 0444); |
95 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " | 95 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " |
96 | "(for debugging only)."); | 96 | "(for debugging only)."); |
97 | module_param(enable_msi, int, 0444); | 97 | module_param(enable_msi, bint, 0444); |
98 | MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); | 98 | MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); |
99 | #ifdef CONFIG_SND_HDA_PATCH_LOADER | 99 | #ifdef CONFIG_SND_HDA_PATCH_LOADER |
100 | module_param_array(patch, charp, NULL, 0444); | 100 | module_param_array(patch, charp, NULL, 0444); |
@@ -121,8 +121,8 @@ module_param(power_save_controller, bool, 0644); | |||
121 | MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); | 121 | MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); |
122 | #endif | 122 | #endif |
123 | 123 | ||
124 | static bool align_buffer_size = 1; | 124 | static int align_buffer_size = -1; |
125 | module_param(align_buffer_size, bool, 0644); | 125 | module_param(align_buffer_size, bint, 0644); |
126 | MODULE_PARM_DESC(align_buffer_size, | 126 | MODULE_PARM_DESC(align_buffer_size, |
127 | "Force buffer and period sizes to be multiple of 128 bytes."); | 127 | "Force buffer and period sizes to be multiple of 128 bytes."); |
128 | 128 | ||
@@ -148,6 +148,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," | |||
148 | "{Intel, PCH}," | 148 | "{Intel, PCH}," |
149 | "{Intel, CPT}," | 149 | "{Intel, CPT}," |
150 | "{Intel, PPT}," | 150 | "{Intel, PPT}," |
151 | "{Intel, LPT}," | ||
151 | "{Intel, PBG}," | 152 | "{Intel, PBG}," |
152 | "{Intel, SCH}," | 153 | "{Intel, SCH}," |
153 | "{ATI, SB450}," | 154 | "{ATI, SB450}," |
@@ -329,6 +330,7 @@ enum { | |||
329 | POS_FIX_LPIB, | 330 | POS_FIX_LPIB, |
330 | POS_FIX_POSBUF, | 331 | POS_FIX_POSBUF, |
331 | POS_FIX_VIACOMBO, | 332 | POS_FIX_VIACOMBO, |
333 | POS_FIX_COMBO, | ||
332 | }; | 334 | }; |
333 | 335 | ||
334 | /* Defines for ATI HD Audio support in SB450 south bridge */ | 336 | /* Defines for ATI HD Audio support in SB450 south bridge */ |
@@ -515,6 +517,7 @@ enum { | |||
515 | #define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */ | 517 | #define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */ |
516 | #define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */ | 518 | #define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */ |
517 | #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ | 519 | #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ |
520 | #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ | ||
518 | 521 | ||
519 | /* quirks for ATI SB / AMD Hudson */ | 522 | /* quirks for ATI SB / AMD Hudson */ |
520 | #define AZX_DCAPS_PRESET_ATI_SB \ | 523 | #define AZX_DCAPS_PRESET_ATI_SB \ |
@@ -527,7 +530,8 @@ enum { | |||
527 | 530 | ||
528 | /* quirks for Nvidia */ | 531 | /* quirks for Nvidia */ |
529 | #define AZX_DCAPS_PRESET_NVIDIA \ | 532 | #define AZX_DCAPS_PRESET_NVIDIA \ |
530 | (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI) | 533 | (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI |\ |
534 | AZX_DCAPS_ALIGN_BUFSIZE) | ||
531 | 535 | ||
532 | static char *driver_short_names[] __devinitdata = { | 536 | static char *driver_short_names[] __devinitdata = { |
533 | [AZX_DRIVER_ICH] = "HDA Intel", | 537 | [AZX_DRIVER_ICH] = "HDA Intel", |
@@ -2347,17 +2351,6 @@ static void azx_power_notify(struct hda_bus *bus) | |||
2347 | * power management | 2351 | * power management |
2348 | */ | 2352 | */ |
2349 | 2353 | ||
2350 | static int snd_hda_codecs_inuse(struct hda_bus *bus) | ||
2351 | { | ||
2352 | struct hda_codec *codec; | ||
2353 | |||
2354 | list_for_each_entry(codec, &bus->codec_list, list) { | ||
2355 | if (snd_hda_codec_needs_resume(codec)) | ||
2356 | return 1; | ||
2357 | } | ||
2358 | return 0; | ||
2359 | } | ||
2360 | |||
2361 | static int azx_suspend(struct pci_dev *pci, pm_message_t state) | 2354 | static int azx_suspend(struct pci_dev *pci, pm_message_t state) |
2362 | { | 2355 | { |
2363 | struct snd_card *card = pci_get_drvdata(pci); | 2356 | struct snd_card *card = pci_get_drvdata(pci); |
@@ -2404,8 +2397,7 @@ static int azx_resume(struct pci_dev *pci) | |||
2404 | return -EIO; | 2397 | return -EIO; |
2405 | azx_init_pci(chip); | 2398 | azx_init_pci(chip); |
2406 | 2399 | ||
2407 | if (snd_hda_codecs_inuse(chip->bus)) | 2400 | azx_init_chip(chip, 1); |
2408 | azx_init_chip(chip, 1); | ||
2409 | 2401 | ||
2410 | snd_hda_resume(chip->bus); | 2402 | snd_hda_resume(chip->bus); |
2411 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2403 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
@@ -2517,6 +2509,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
2517 | case POS_FIX_LPIB: | 2509 | case POS_FIX_LPIB: |
2518 | case POS_FIX_POSBUF: | 2510 | case POS_FIX_POSBUF: |
2519 | case POS_FIX_VIACOMBO: | 2511 | case POS_FIX_VIACOMBO: |
2512 | case POS_FIX_COMBO: | ||
2520 | return fix; | 2513 | return fix; |
2521 | } | 2514 | } |
2522 | 2515 | ||
@@ -2696,6 +2689,12 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2696 | 2689 | ||
2697 | chip->position_fix[0] = chip->position_fix[1] = | 2690 | chip->position_fix[0] = chip->position_fix[1] = |
2698 | check_position_fix(chip, position_fix[dev]); | 2691 | check_position_fix(chip, position_fix[dev]); |
2692 | /* combo mode uses LPIB for playback */ | ||
2693 | if (chip->position_fix[0] == POS_FIX_COMBO) { | ||
2694 | chip->position_fix[0] = POS_FIX_LPIB; | ||
2695 | chip->position_fix[1] = POS_FIX_AUTO; | ||
2696 | } | ||
2697 | |||
2699 | check_probe_mask(chip, dev); | 2698 | check_probe_mask(chip, dev); |
2700 | 2699 | ||
2701 | chip->single_cmd = single_cmd; | 2700 | chip->single_cmd = single_cmd; |
@@ -2774,9 +2773,16 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2774 | } | 2773 | } |
2775 | 2774 | ||
2776 | /* disable buffer size rounding to 128-byte multiples if supported */ | 2775 | /* disable buffer size rounding to 128-byte multiples if supported */ |
2777 | chip->align_buffer_size = align_buffer_size; | 2776 | if (align_buffer_size >= 0) |
2778 | if (chip->driver_caps & AZX_DCAPS_BUFSIZE) | 2777 | chip->align_buffer_size = !!align_buffer_size; |
2779 | chip->align_buffer_size = 0; | 2778 | else { |
2779 | if (chip->driver_caps & AZX_DCAPS_BUFSIZE) | ||
2780 | chip->align_buffer_size = 0; | ||
2781 | else if (chip->driver_caps & AZX_DCAPS_ALIGN_BUFSIZE) | ||
2782 | chip->align_buffer_size = 1; | ||
2783 | else | ||
2784 | chip->align_buffer_size = 1; | ||
2785 | } | ||
2780 | 2786 | ||
2781 | /* allow 64bit DMA address if supported by H/W */ | 2787 | /* allow 64bit DMA address if supported by H/W */ |
2782 | if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) | 2788 | if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) |
@@ -2992,6 +2998,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
2992 | { PCI_DEVICE(0x8086, 0x1e20), | 2998 | { PCI_DEVICE(0x8086, 0x1e20), |
2993 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 2999 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
2994 | AZX_DCAPS_BUFSIZE}, | 3000 | AZX_DCAPS_BUFSIZE}, |
3001 | /* Lynx Point */ | ||
3002 | { PCI_DEVICE(0x8086, 0x8c20), | ||
3003 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | ||
3004 | AZX_DCAPS_BUFSIZE}, | ||
2995 | /* SCH */ | 3005 | /* SCH */ |
2996 | { PCI_DEVICE(0x8086, 0x811b), | 3006 | { PCI_DEVICE(0x8086, 0x811b), |
2997 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | | 3007 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 9d819c4b4923..d68948499fbc 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c | |||
@@ -19,6 +19,22 @@ | |||
19 | #include "hda_local.h" | 19 | #include "hda_local.h" |
20 | #include "hda_jack.h" | 20 | #include "hda_jack.h" |
21 | 21 | ||
22 | bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) | ||
23 | { | ||
24 | if (codec->no_jack_detect) | ||
25 | return false; | ||
26 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) | ||
27 | return false; | ||
28 | if (!codec->ignore_misc_bit && | ||
29 | (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & | ||
30 | AC_DEFCFG_MISC_NO_PRESENCE)) | ||
31 | return false; | ||
32 | if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) | ||
33 | return false; | ||
34 | return true; | ||
35 | } | ||
36 | EXPORT_SYMBOL_HDA(is_jack_detectable); | ||
37 | |||
22 | /* execute pin sense measurement */ | 38 | /* execute pin sense measurement */ |
23 | static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid) | 39 | static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid) |
24 | { | 40 | { |
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index f8f97c71c9c1..c66655cf413a 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h | |||
@@ -62,18 +62,7 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, | |||
62 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); | 62 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); |
63 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); | 63 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); |
64 | 64 | ||
65 | static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) | 65 | bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid); |
66 | { | ||
67 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) | ||
68 | return false; | ||
69 | if (!codec->ignore_misc_bit && | ||
70 | (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & | ||
71 | AC_DEFCFG_MISC_NO_PRESENCE)) | ||
72 | return false; | ||
73 | if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) | ||
74 | return false; | ||
75 | return true; | ||
76 | } | ||
77 | 66 | ||
78 | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | 67 | int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, |
79 | const char *name, int idx); | 68 | const char *name, int idx); |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index aca8d3193b95..0ec9248165bc 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -139,10 +139,36 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
139 | unsigned int *tlv); | 139 | unsigned int *tlv); |
140 | struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, | 140 | struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, |
141 | const char *name); | 141 | const char *name); |
142 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 142 | int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
143 | unsigned int *tlv, const char * const *slaves); | 143 | unsigned int *tlv, const char * const *slaves, |
144 | const char *suffix, bool init_slave_vol, | ||
145 | struct snd_kcontrol **ctl_ret); | ||
146 | #define snd_hda_add_vmaster(codec, name, tlv, slaves, suffix) \ | ||
147 | __snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true, NULL) | ||
144 | int snd_hda_codec_reset(struct hda_codec *codec); | 148 | int snd_hda_codec_reset(struct hda_codec *codec); |
145 | 149 | ||
150 | enum { | ||
151 | HDA_VMUTE_OFF, | ||
152 | HDA_VMUTE_ON, | ||
153 | HDA_VMUTE_FOLLOW_MASTER, | ||
154 | }; | ||
155 | |||
156 | struct hda_vmaster_mute_hook { | ||
157 | /* below two fields must be filled by the caller of | ||
158 | * snd_hda_add_vmaster_hook() beforehand | ||
159 | */ | ||
160 | struct snd_kcontrol *sw_kctl; | ||
161 | void (*hook)(void *, int); | ||
162 | /* below are initialized automatically */ | ||
163 | unsigned int mute_mode; /* HDA_VMUTE_XXX */ | ||
164 | struct hda_codec *codec; | ||
165 | }; | ||
166 | |||
167 | int snd_hda_add_vmaster_hook(struct hda_codec *codec, | ||
168 | struct hda_vmaster_mute_hook *hook, | ||
169 | bool expose_enum_ctl); | ||
170 | void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook); | ||
171 | |||
146 | /* amp value bits */ | 172 | /* amp value bits */ |
147 | #define HDA_AMP_MUTE 0x80 | 173 | #define HDA_AMP_MUTE 0x80 |
148 | #define HDA_AMP_UNMUTE 0x00 | 174 | #define HDA_AMP_UNMUTE 0x00 |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 9cb14b42dfff..7143393927da 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -82,6 +82,7 @@ struct ad198x_spec { | |||
82 | unsigned int inv_jack_detect: 1;/* inverted jack-detection */ | 82 | unsigned int inv_jack_detect: 1;/* inverted jack-detection */ |
83 | unsigned int inv_eapd: 1; /* inverted EAPD implementation */ | 83 | unsigned int inv_eapd: 1; /* inverted EAPD implementation */ |
84 | unsigned int analog_beep: 1; /* analog beep input present */ | 84 | unsigned int analog_beep: 1; /* analog beep input present */ |
85 | unsigned int avoid_init_slave_vol:1; | ||
85 | 86 | ||
86 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 87 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
87 | struct hda_loopback_check loopback; | 88 | struct hda_loopback_check loopback; |
@@ -137,51 +138,17 @@ static int ad198x_init(struct hda_codec *codec) | |||
137 | return 0; | 138 | return 0; |
138 | } | 139 | } |
139 | 140 | ||
140 | static const char * const ad_slave_vols[] = { | 141 | static const char * const ad_slave_pfxs[] = { |
141 | "Front Playback Volume", | 142 | "Front", "Surround", "Center", "LFE", "Side", |
142 | "Surround Playback Volume", | 143 | "Headphone", "Mono", "Speaker", "IEC958", |
143 | "Center Playback Volume", | ||
144 | "LFE Playback Volume", | ||
145 | "Side Playback Volume", | ||
146 | "Headphone Playback Volume", | ||
147 | "Mono Playback Volume", | ||
148 | "Speaker Playback Volume", | ||
149 | "IEC958 Playback Volume", | ||
150 | NULL | 144 | NULL |
151 | }; | 145 | }; |
152 | 146 | ||
153 | static const char * const ad_slave_sws[] = { | 147 | static const char * const ad1988_6stack_fp_slave_pfxs[] = { |
154 | "Front Playback Switch", | 148 | "Front", "Surround", "Center", "LFE", "Side", "IEC958", |
155 | "Surround Playback Switch", | ||
156 | "Center Playback Switch", | ||
157 | "LFE Playback Switch", | ||
158 | "Side Playback Switch", | ||
159 | "Headphone Playback Switch", | ||
160 | "Mono Playback Switch", | ||
161 | "Speaker Playback Switch", | ||
162 | "IEC958 Playback Switch", | ||
163 | NULL | 149 | NULL |
164 | }; | 150 | }; |
165 | 151 | ||
166 | static const char * const ad1988_6stack_fp_slave_vols[] = { | ||
167 | "Front Playback Volume", | ||
168 | "Surround Playback Volume", | ||
169 | "Center Playback Volume", | ||
170 | "LFE Playback Volume", | ||
171 | "Side Playback Volume", | ||
172 | "IEC958 Playback Volume", | ||
173 | NULL | ||
174 | }; | ||
175 | |||
176 | static const char * const ad1988_6stack_fp_slave_sws[] = { | ||
177 | "Front Playback Switch", | ||
178 | "Surround Playback Switch", | ||
179 | "Center Playback Switch", | ||
180 | "LFE Playback Switch", | ||
181 | "Side Playback Switch", | ||
182 | "IEC958 Playback Switch", | ||
183 | NULL | ||
184 | }; | ||
185 | static void ad198x_free_kctls(struct hda_codec *codec); | 152 | static void ad198x_free_kctls(struct hda_codec *codec); |
186 | 153 | ||
187 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 154 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
@@ -257,10 +224,12 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
257 | unsigned int vmaster_tlv[4]; | 224 | unsigned int vmaster_tlv[4]; |
258 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | 225 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, |
259 | HDA_OUTPUT, vmaster_tlv); | 226 | HDA_OUTPUT, vmaster_tlv); |
260 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 227 | err = __snd_hda_add_vmaster(codec, "Master Playback Volume", |
261 | vmaster_tlv, | 228 | vmaster_tlv, |
262 | (spec->slave_vols ? | 229 | (spec->slave_vols ? |
263 | spec->slave_vols : ad_slave_vols)); | 230 | spec->slave_vols : ad_slave_pfxs), |
231 | "Playback Volume", | ||
232 | !spec->avoid_init_slave_vol, NULL); | ||
264 | if (err < 0) | 233 | if (err < 0) |
265 | return err; | 234 | return err; |
266 | } | 235 | } |
@@ -268,7 +237,8 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
268 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 237 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", |
269 | NULL, | 238 | NULL, |
270 | (spec->slave_sws ? | 239 | (spec->slave_sws ? |
271 | spec->slave_sws : ad_slave_sws)); | 240 | spec->slave_sws : ad_slave_pfxs), |
241 | "Playback Switch"); | ||
272 | if (err < 0) | 242 | if (err < 0) |
273 | return err; | 243 | return err; |
274 | } | 244 | } |
@@ -3385,8 +3355,8 @@ static int patch_ad1988(struct hda_codec *codec) | |||
3385 | 3355 | ||
3386 | if (spec->autocfg.hp_pins[0]) { | 3356 | if (spec->autocfg.hp_pins[0]) { |
3387 | spec->mixers[spec->num_mixers++] = ad1988_hp_mixers; | 3357 | spec->mixers[spec->num_mixers++] = ad1988_hp_mixers; |
3388 | spec->slave_vols = ad1988_6stack_fp_slave_vols; | 3358 | spec->slave_vols = ad1988_6stack_fp_slave_pfxs; |
3389 | spec->slave_sws = ad1988_6stack_fp_slave_sws; | 3359 | spec->slave_sws = ad1988_6stack_fp_slave_pfxs; |
3390 | spec->alt_dac_nid = ad1988_alt_dac_nid; | 3360 | spec->alt_dac_nid = ad1988_alt_dac_nid; |
3391 | spec->stream_analog_alt_playback = | 3361 | spec->stream_analog_alt_playback = |
3392 | &ad198x_pcm_analog_alt_playback; | 3362 | &ad198x_pcm_analog_alt_playback; |
@@ -3594,16 +3564,8 @@ static const struct hda_amp_list ad1884_loopbacks[] = { | |||
3594 | #endif | 3564 | #endif |
3595 | 3565 | ||
3596 | static const char * const ad1884_slave_vols[] = { | 3566 | static const char * const ad1884_slave_vols[] = { |
3597 | "PCM Playback Volume", | 3567 | "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD", |
3598 | "Mic Playback Volume", | 3568 | "Internal Mic", "Docking Mic", /* "Beep", */ "IEC958", |
3599 | "Mono Playback Volume", | ||
3600 | "Front Mic Playback Volume", | ||
3601 | "Mic Playback Volume", | ||
3602 | "CD Playback Volume", | ||
3603 | "Internal Mic Playback Volume", | ||
3604 | "Docking Mic Playback Volume", | ||
3605 | /* "Beep Playback Volume", */ | ||
3606 | "IEC958 Playback Volume", | ||
3607 | NULL | 3569 | NULL |
3608 | }; | 3570 | }; |
3609 | 3571 | ||
@@ -3644,6 +3606,8 @@ static int patch_ad1884(struct hda_codec *codec) | |||
3644 | spec->vmaster_nid = 0x04; | 3606 | spec->vmaster_nid = 0x04; |
3645 | /* we need to cover all playback volumes */ | 3607 | /* we need to cover all playback volumes */ |
3646 | spec->slave_vols = ad1884_slave_vols; | 3608 | spec->slave_vols = ad1884_slave_vols; |
3609 | /* slaves may contain input volumes, so we can't raise to 0dB blindly */ | ||
3610 | spec->avoid_init_slave_vol = 1; | ||
3647 | 3611 | ||
3648 | codec->patch_ops = ad198x_patch_ops; | 3612 | codec->patch_ops = ad198x_patch_ops; |
3649 | 3613 | ||
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index d29d6d377904..e6eafb18c8f5 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -70,6 +70,8 @@ struct conexant_spec { | |||
70 | const struct snd_kcontrol_new *mixers[5]; | 70 | const struct snd_kcontrol_new *mixers[5]; |
71 | int num_mixers; | 71 | int num_mixers; |
72 | hda_nid_t vmaster_nid; | 72 | hda_nid_t vmaster_nid; |
73 | struct hda_vmaster_mute_hook vmaster_mute; | ||
74 | bool vmaster_mute_led; | ||
73 | 75 | ||
74 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 76 | const struct hda_verb *init_verbs[5]; /* initialization verbs |
75 | * don't forget NULL | 77 | * don't forget NULL |
@@ -465,21 +467,8 @@ static const struct snd_kcontrol_new cxt_beep_mixer[] = { | |||
465 | }; | 467 | }; |
466 | #endif | 468 | #endif |
467 | 469 | ||
468 | static const char * const slave_vols[] = { | 470 | static const char * const slave_pfxs[] = { |
469 | "Headphone Playback Volume", | 471 | "Headphone", "Speaker", "Front", "Surround", "CLFE", |
470 | "Speaker Playback Volume", | ||
471 | "Front Playback Volume", | ||
472 | "Surround Playback Volume", | ||
473 | "CLFE Playback Volume", | ||
474 | NULL | ||
475 | }; | ||
476 | |||
477 | static const char * const slave_sws[] = { | ||
478 | "Headphone Playback Switch", | ||
479 | "Speaker Playback Switch", | ||
480 | "Front Playback Switch", | ||
481 | "Surround Playback Switch", | ||
482 | "CLFE Playback Switch", | ||
483 | NULL | 472 | NULL |
484 | }; | 473 | }; |
485 | 474 | ||
@@ -519,14 +508,17 @@ static int conexant_build_controls(struct hda_codec *codec) | |||
519 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | 508 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, |
520 | HDA_OUTPUT, vmaster_tlv); | 509 | HDA_OUTPUT, vmaster_tlv); |
521 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 510 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
522 | vmaster_tlv, slave_vols); | 511 | vmaster_tlv, slave_pfxs, |
512 | "Playback Volume"); | ||
523 | if (err < 0) | 513 | if (err < 0) |
524 | return err; | 514 | return err; |
525 | } | 515 | } |
526 | if (spec->vmaster_nid && | 516 | if (spec->vmaster_nid && |
527 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 517 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { |
528 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 518 | err = __snd_hda_add_vmaster(codec, "Master Playback Switch", |
529 | NULL, slave_sws); | 519 | NULL, slave_pfxs, |
520 | "Playback Switch", true, | ||
521 | &spec->vmaster_mute.sw_kctl); | ||
530 | if (err < 0) | 522 | if (err < 0) |
531 | return err; | 523 | return err; |
532 | } | 524 | } |
@@ -3034,7 +3026,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { | |||
3034 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), | 3026 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), |
3035 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), | 3027 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), |
3036 | SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), | 3028 | SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), |
3037 | SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */ | ||
3038 | SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO), | 3029 | SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO), |
3039 | {} | 3030 | {} |
3040 | }; | 3031 | }; |
@@ -3943,6 +3934,63 @@ static void enable_unsol_pins(struct hda_codec *codec, int num_pins, | |||
3943 | snd_hda_jack_detect_enable(codec, pins[i], action); | 3934 | snd_hda_jack_detect_enable(codec, pins[i], action); |
3944 | } | 3935 | } |
3945 | 3936 | ||
3937 | static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) | ||
3938 | { | ||
3939 | int i; | ||
3940 | for (i = 0; i < nums; i++) | ||
3941 | if (list[i] == nid) | ||
3942 | return true; | ||
3943 | return false; | ||
3944 | } | ||
3945 | |||
3946 | /* is the given NID found in any of autocfg items? */ | ||
3947 | static bool found_in_autocfg(struct auto_pin_cfg *cfg, hda_nid_t nid) | ||
3948 | { | ||
3949 | int i; | ||
3950 | |||
3951 | if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) || | ||
3952 | found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) || | ||
3953 | found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs) || | ||
3954 | found_in_nid_list(nid, cfg->dig_out_pins, cfg->dig_outs)) | ||
3955 | return true; | ||
3956 | for (i = 0; i < cfg->num_inputs; i++) | ||
3957 | if (cfg->inputs[i].pin == nid) | ||
3958 | return true; | ||
3959 | if (cfg->dig_in_pin == nid) | ||
3960 | return true; | ||
3961 | return false; | ||
3962 | } | ||
3963 | |||
3964 | /* clear unsol-event tags on unused pins; Conexant codecs seem to leave | ||
3965 | * invalid unsol tags by some reason | ||
3966 | */ | ||
3967 | static void clear_unsol_on_unused_pins(struct hda_codec *codec) | ||
3968 | { | ||
3969 | struct conexant_spec *spec = codec->spec; | ||
3970 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3971 | int i; | ||
3972 | |||
3973 | for (i = 0; i < codec->init_pins.used; i++) { | ||
3974 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | ||
3975 | if (!found_in_autocfg(cfg, pin->nid)) | ||
3976 | snd_hda_codec_write(codec, pin->nid, 0, | ||
3977 | AC_VERB_SET_UNSOLICITED_ENABLE, 0); | ||
3978 | } | ||
3979 | } | ||
3980 | |||
3981 | /* turn on/off EAPD according to Master switch */ | ||
3982 | static void cx_auto_vmaster_hook(void *private_data, int enabled) | ||
3983 | { | ||
3984 | struct hda_codec *codec = private_data; | ||
3985 | struct conexant_spec *spec = codec->spec; | ||
3986 | |||
3987 | if (enabled && spec->pin_eapd_ctrls) { | ||
3988 | cx_auto_update_speakers(codec); | ||
3989 | return; | ||
3990 | } | ||
3991 | cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled); | ||
3992 | } | ||
3993 | |||
3946 | static void cx_auto_init_output(struct hda_codec *codec) | 3994 | static void cx_auto_init_output(struct hda_codec *codec) |
3947 | { | 3995 | { |
3948 | struct conexant_spec *spec = codec->spec; | 3996 | struct conexant_spec *spec = codec->spec; |
@@ -3983,6 +4031,7 @@ static void cx_auto_init_output(struct hda_codec *codec) | |||
3983 | /* turn on all EAPDs if no individual EAPD control is available */ | 4031 | /* turn on all EAPDs if no individual EAPD control is available */ |
3984 | if (!spec->pin_eapd_ctrls) | 4032 | if (!spec->pin_eapd_ctrls) |
3985 | cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); | 4033 | cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); |
4034 | clear_unsol_on_unused_pins(codec); | ||
3986 | } | 4035 | } |
3987 | 4036 | ||
3988 | static void cx_auto_init_input(struct hda_codec *codec) | 4037 | static void cx_auto_init_input(struct hda_codec *codec) |
@@ -4046,11 +4095,13 @@ static void cx_auto_init_digital(struct hda_codec *codec) | |||
4046 | 4095 | ||
4047 | static int cx_auto_init(struct hda_codec *codec) | 4096 | static int cx_auto_init(struct hda_codec *codec) |
4048 | { | 4097 | { |
4098 | struct conexant_spec *spec = codec->spec; | ||
4049 | /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/ | 4099 | /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/ |
4050 | cx_auto_init_output(codec); | 4100 | cx_auto_init_output(codec); |
4051 | cx_auto_init_input(codec); | 4101 | cx_auto_init_input(codec); |
4052 | cx_auto_init_digital(codec); | 4102 | cx_auto_init_digital(codec); |
4053 | snd_hda_jack_report_sync(codec); | 4103 | snd_hda_jack_report_sync(codec); |
4104 | snd_hda_sync_vmaster_hook(&spec->vmaster_mute); | ||
4054 | return 0; | 4105 | return 0; |
4055 | } | 4106 | } |
4056 | 4107 | ||
@@ -4296,6 +4347,13 @@ static int cx_auto_build_controls(struct hda_codec *codec) | |||
4296 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); | 4347 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); |
4297 | if (err < 0) | 4348 | if (err < 0) |
4298 | return err; | 4349 | return err; |
4350 | if (spec->vmaster_mute.sw_kctl) { | ||
4351 | spec->vmaster_mute.hook = cx_auto_vmaster_hook; | ||
4352 | err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, | ||
4353 | spec->vmaster_mute_led); | ||
4354 | if (err < 0) | ||
4355 | return err; | ||
4356 | } | ||
4299 | return 0; | 4357 | return 0; |
4300 | } | 4358 | } |
4301 | 4359 | ||
@@ -4320,7 +4378,6 @@ static int cx_auto_search_adcs(struct hda_codec *codec) | |||
4320 | return 0; | 4378 | return 0; |
4321 | } | 4379 | } |
4322 | 4380 | ||
4323 | |||
4324 | static const struct hda_codec_ops cx_auto_patch_ops = { | 4381 | static const struct hda_codec_ops cx_auto_patch_ops = { |
4325 | .build_controls = cx_auto_build_controls, | 4382 | .build_controls = cx_auto_build_controls, |
4326 | .build_pcms = conexant_build_pcms, | 4383 | .build_pcms = conexant_build_pcms, |
@@ -4368,6 +4425,7 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { | |||
4368 | { 0x16, 0x042140ff }, /* HP (seq# overridden) */ | 4425 | { 0x16, 0x042140ff }, /* HP (seq# overridden) */ |
4369 | { 0x17, 0x21a11000 }, /* dock-mic */ | 4426 | { 0x17, 0x21a11000 }, /* dock-mic */ |
4370 | { 0x19, 0x2121103f }, /* dock-HP */ | 4427 | { 0x19, 0x2121103f }, /* dock-HP */ |
4428 | { 0x1c, 0x21440100 }, /* dock SPDIF out */ | ||
4371 | {} | 4429 | {} |
4372 | }; | 4430 | }; |
4373 | 4431 | ||
@@ -4421,6 +4479,18 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
4421 | 4479 | ||
4422 | apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); | 4480 | apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); |
4423 | 4481 | ||
4482 | /* Show mute-led control only on HP laptops | ||
4483 | * This is a sort of white-list: on HP laptops, EAPD corresponds | ||
4484 | * only to the mute-LED without actualy amp function. Meanwhile, | ||
4485 | * others may use EAPD really as an amp switch, so it might be | ||
4486 | * not good to expose it blindly. | ||
4487 | */ | ||
4488 | switch (codec->subsystem_id >> 16) { | ||
4489 | case 0x103c: | ||
4490 | spec->vmaster_mute_led = 1; | ||
4491 | break; | ||
4492 | } | ||
4493 | |||
4424 | err = cx_auto_search_adcs(codec); | 4494 | err = cx_auto_search_adcs(codec); |
4425 | if (err < 0) | 4495 | if (err < 0) |
4426 | return err; | 4496 | return err; |
@@ -4434,6 +4504,18 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
4434 | codec->patch_ops = cx_auto_patch_ops; | 4504 | codec->patch_ops = cx_auto_patch_ops; |
4435 | if (spec->beep_amp) | 4505 | if (spec->beep_amp) |
4436 | snd_hda_attach_beep_device(codec, spec->beep_amp); | 4506 | snd_hda_attach_beep_device(codec, spec->beep_amp); |
4507 | |||
4508 | /* Some laptops with Conexant chips show stalls in S3 resume, | ||
4509 | * which falls into the single-cmd mode. | ||
4510 | * Better to make reset, then. | ||
4511 | */ | ||
4512 | if (!codec->bus->sync_write) { | ||
4513 | snd_printd("hda_codec: " | ||
4514 | "Enable sync_write for stable communication\n"); | ||
4515 | codec->bus->sync_write = 1; | ||
4516 | codec->bus->allow_bus_reset = 1; | ||
4517 | } | ||
4518 | |||
4437 | return 0; | 4519 | return 0; |
4438 | } | 4520 | } |
4439 | 4521 | ||
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 1168ebd3fb5c..540cd13f7f15 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -1912,6 +1912,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | |||
1912 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | 1912 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, |
1913 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, | 1913 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, |
1914 | { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, | 1914 | { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, |
1915 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, | ||
1915 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, | 1916 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, |
1916 | {} /* terminator */ | 1917 | {} /* terminator */ |
1917 | }; | 1918 | }; |
@@ -1958,6 +1959,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862803"); | |||
1958 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | 1959 | MODULE_ALIAS("snd-hda-codec-id:80862804"); |
1959 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | 1960 | MODULE_ALIAS("snd-hda-codec-id:80862805"); |
1960 | MODULE_ALIAS("snd-hda-codec-id:80862806"); | 1961 | MODULE_ALIAS("snd-hda-codec-id:80862806"); |
1962 | MODULE_ALIAS("snd-hda-codec-id:80862880"); | ||
1961 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | 1963 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); |
1962 | 1964 | ||
1963 | MODULE_LICENSE("GPL"); | 1965 | MODULE_LICENSE("GPL"); |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 22c73b78ac6f..8ea2fd654327 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -198,8 +198,11 @@ struct alc_spec { | |||
198 | 198 | ||
199 | /* for virtual master */ | 199 | /* for virtual master */ |
200 | hda_nid_t vmaster_nid; | 200 | hda_nid_t vmaster_nid; |
201 | struct hda_vmaster_mute_hook vmaster_mute; | ||
201 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 202 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
202 | struct hda_loopback_check loopback; | 203 | struct hda_loopback_check loopback; |
204 | int num_loopbacks; | ||
205 | struct hda_amp_list loopback_list[8]; | ||
203 | #endif | 206 | #endif |
204 | 207 | ||
205 | /* for PLL fix */ | 208 | /* for PLL fix */ |
@@ -220,8 +223,6 @@ struct alc_spec { | |||
220 | struct snd_array bind_ctls; | 223 | struct snd_array bind_ctls; |
221 | }; | 224 | }; |
222 | 225 | ||
223 | #define ALC_MODEL_AUTO 0 /* common for all chips */ | ||
224 | |||
225 | static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, | 226 | static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, |
226 | int dir, unsigned int bits) | 227 | int dir, unsigned int bits) |
227 | { | 228 | { |
@@ -300,6 +301,9 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, | |||
300 | int i, type, num_conns; | 301 | int i, type, num_conns; |
301 | hda_nid_t nid; | 302 | hda_nid_t nid; |
302 | 303 | ||
304 | if (!spec->input_mux) | ||
305 | return 0; | ||
306 | |||
303 | mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; | 307 | mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; |
304 | imux = &spec->input_mux[mux_idx]; | 308 | imux = &spec->input_mux[mux_idx]; |
305 | if (!imux->num_items && mux_idx > 0) | 309 | if (!imux->num_items && mux_idx > 0) |
@@ -651,15 +655,51 @@ static void alc_exec_unsol_event(struct hda_codec *codec, int action) | |||
651 | snd_hda_jack_report_sync(codec); | 655 | snd_hda_jack_report_sync(codec); |
652 | } | 656 | } |
653 | 657 | ||
658 | /* update the master volume per volume-knob's unsol event */ | ||
659 | static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid) | ||
660 | { | ||
661 | unsigned int val; | ||
662 | struct snd_kcontrol *kctl; | ||
663 | struct snd_ctl_elem_value *uctl; | ||
664 | |||
665 | kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume"); | ||
666 | if (!kctl) | ||
667 | return; | ||
668 | uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); | ||
669 | if (!uctl) | ||
670 | return; | ||
671 | val = snd_hda_codec_read(codec, nid, 0, | ||
672 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); | ||
673 | val &= HDA_AMP_VOLMASK; | ||
674 | uctl->value.integer.value[0] = val; | ||
675 | uctl->value.integer.value[1] = val; | ||
676 | kctl->put(kctl, uctl); | ||
677 | kfree(uctl); | ||
678 | } | ||
679 | |||
654 | /* unsolicited event for HP jack sensing */ | 680 | /* unsolicited event for HP jack sensing */ |
655 | static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) | 681 | static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) |
656 | { | 682 | { |
683 | int action; | ||
684 | |||
657 | if (codec->vendor_id == 0x10ec0880) | 685 | if (codec->vendor_id == 0x10ec0880) |
658 | res >>= 28; | 686 | res >>= 28; |
659 | else | 687 | else |
660 | res >>= 26; | 688 | res >>= 26; |
661 | res = snd_hda_jack_get_action(codec, res); | 689 | action = snd_hda_jack_get_action(codec, res); |
662 | alc_exec_unsol_event(codec, res); | 690 | if (action == ALC_DCVOL_EVENT) { |
691 | /* Execute the dc-vol event here as it requires the NID | ||
692 | * but we don't pass NID to alc_exec_unsol_event(). | ||
693 | * Once when we convert all static quirks to the auto-parser, | ||
694 | * this can be integerated into there. | ||
695 | */ | ||
696 | struct hda_jack_tbl *jack; | ||
697 | jack = snd_hda_jack_tbl_get_from_tag(codec, res); | ||
698 | if (jack) | ||
699 | alc_update_knob_master(codec, jack->nid); | ||
700 | return; | ||
701 | } | ||
702 | alc_exec_unsol_event(codec, action); | ||
663 | } | 703 | } |
664 | 704 | ||
665 | /* call init functions of standard auto-mute helpers */ | 705 | /* call init functions of standard auto-mute helpers */ |
@@ -1033,45 +1073,6 @@ static bool alc_check_dyn_adc_switch(struct hda_codec *codec) | |||
1033 | return true; | 1073 | return true; |
1034 | } | 1074 | } |
1035 | 1075 | ||
1036 | /* rebuild imux for matching with the given auto-mic pins (if not yet) */ | ||
1037 | static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec) | ||
1038 | { | ||
1039 | struct alc_spec *spec = codec->spec; | ||
1040 | struct hda_input_mux *imux; | ||
1041 | static char * const texts[3] = { | ||
1042 | "Mic", "Internal Mic", "Dock Mic" | ||
1043 | }; | ||
1044 | int i; | ||
1045 | |||
1046 | if (!spec->auto_mic) | ||
1047 | return false; | ||
1048 | imux = &spec->private_imux[0]; | ||
1049 | if (spec->input_mux == imux) | ||
1050 | return true; | ||
1051 | spec->imux_pins[0] = spec->ext_mic_pin; | ||
1052 | spec->imux_pins[1] = spec->int_mic_pin; | ||
1053 | spec->imux_pins[2] = spec->dock_mic_pin; | ||
1054 | for (i = 0; i < 3; i++) { | ||
1055 | strcpy(imux->items[i].label, texts[i]); | ||
1056 | if (spec->imux_pins[i]) { | ||
1057 | hda_nid_t pin = spec->imux_pins[i]; | ||
1058 | int c; | ||
1059 | for (c = 0; c < spec->num_adc_nids; c++) { | ||
1060 | hda_nid_t cap = get_capsrc(spec, c); | ||
1061 | int idx = get_connection_index(codec, cap, pin); | ||
1062 | if (idx >= 0) { | ||
1063 | imux->items[i].index = idx; | ||
1064 | break; | ||
1065 | } | ||
1066 | } | ||
1067 | imux->num_items = i + 1; | ||
1068 | } | ||
1069 | } | ||
1070 | spec->num_mux_defs = 1; | ||
1071 | spec->input_mux = imux; | ||
1072 | return true; | ||
1073 | } | ||
1074 | |||
1075 | /* check whether all auto-mic pins are valid; setup indices if OK */ | 1076 | /* check whether all auto-mic pins are valid; setup indices if OK */ |
1076 | static bool alc_auto_mic_check_imux(struct hda_codec *codec) | 1077 | static bool alc_auto_mic_check_imux(struct hda_codec *codec) |
1077 | { | 1078 | { |
@@ -1441,6 +1442,7 @@ enum { | |||
1441 | ALC_FIXUP_ACT_PRE_PROBE, | 1442 | ALC_FIXUP_ACT_PRE_PROBE, |
1442 | ALC_FIXUP_ACT_PROBE, | 1443 | ALC_FIXUP_ACT_PROBE, |
1443 | ALC_FIXUP_ACT_INIT, | 1444 | ALC_FIXUP_ACT_INIT, |
1445 | ALC_FIXUP_ACT_BUILD, | ||
1444 | }; | 1446 | }; |
1445 | 1447 | ||
1446 | static void alc_apply_fixup(struct hda_codec *codec, int action) | 1448 | static void alc_apply_fixup(struct hda_codec *codec, int action) |
@@ -1520,6 +1522,13 @@ static void alc_pick_fixup(struct hda_codec *codec, | |||
1520 | int id = -1; | 1522 | int id = -1; |
1521 | const char *name = NULL; | 1523 | const char *name = NULL; |
1522 | 1524 | ||
1525 | /* when model=nofixup is given, don't pick up any fixups */ | ||
1526 | if (codec->modelname && !strcmp(codec->modelname, "nofixup")) { | ||
1527 | spec->fixup_list = NULL; | ||
1528 | spec->fixup_id = -1; | ||
1529 | return; | ||
1530 | } | ||
1531 | |||
1523 | if (codec->modelname && models) { | 1532 | if (codec->modelname && models) { |
1524 | while (models->name) { | 1533 | while (models->name) { |
1525 | if (!strcmp(codec->modelname, models->name)) { | 1534 | if (!strcmp(codec->modelname, models->name)) { |
@@ -1847,36 +1856,10 @@ DEFINE_CAPMIX_NOSRC(3); | |||
1847 | /* | 1856 | /* |
1848 | * slave controls for virtual master | 1857 | * slave controls for virtual master |
1849 | */ | 1858 | */ |
1850 | static const char * const alc_slave_vols[] = { | 1859 | static const char * const alc_slave_pfxs[] = { |
1851 | "Front Playback Volume", | 1860 | "Front", "Surround", "Center", "LFE", "Side", |
1852 | "Surround Playback Volume", | 1861 | "Headphone", "Speaker", "Mono", "Line Out", |
1853 | "Center Playback Volume", | 1862 | "CLFE", "Bass Speaker", "PCM", |
1854 | "LFE Playback Volume", | ||
1855 | "Side Playback Volume", | ||
1856 | "Headphone Playback Volume", | ||
1857 | "Speaker Playback Volume", | ||
1858 | "Mono Playback Volume", | ||
1859 | "Line Out Playback Volume", | ||
1860 | "CLFE Playback Volume", | ||
1861 | "Bass Speaker Playback Volume", | ||
1862 | "PCM Playback Volume", | ||
1863 | NULL, | ||
1864 | }; | ||
1865 | |||
1866 | static const char * const alc_slave_sws[] = { | ||
1867 | "Front Playback Switch", | ||
1868 | "Surround Playback Switch", | ||
1869 | "Center Playback Switch", | ||
1870 | "LFE Playback Switch", | ||
1871 | "Side Playback Switch", | ||
1872 | "Headphone Playback Switch", | ||
1873 | "Speaker Playback Switch", | ||
1874 | "Mono Playback Switch", | ||
1875 | "IEC958 Playback Switch", | ||
1876 | "Line Out Playback Switch", | ||
1877 | "CLFE Playback Switch", | ||
1878 | "Bass Speaker Playback Switch", | ||
1879 | "PCM Playback Switch", | ||
1880 | NULL, | 1863 | NULL, |
1881 | }; | 1864 | }; |
1882 | 1865 | ||
@@ -1967,14 +1950,17 @@ static int __alc_build_controls(struct hda_codec *codec) | |||
1967 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | 1950 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, |
1968 | HDA_OUTPUT, vmaster_tlv); | 1951 | HDA_OUTPUT, vmaster_tlv); |
1969 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 1952 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
1970 | vmaster_tlv, alc_slave_vols); | 1953 | vmaster_tlv, alc_slave_pfxs, |
1954 | "Playback Volume"); | ||
1971 | if (err < 0) | 1955 | if (err < 0) |
1972 | return err; | 1956 | return err; |
1973 | } | 1957 | } |
1974 | if (!spec->no_analog && | 1958 | if (!spec->no_analog && |
1975 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 1959 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { |
1976 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 1960 | err = __snd_hda_add_vmaster(codec, "Master Playback Switch", |
1977 | NULL, alc_slave_sws); | 1961 | NULL, alc_slave_pfxs, |
1962 | "Playback Switch", | ||
1963 | true, &spec->vmaster_mute.sw_kctl); | ||
1978 | if (err < 0) | 1964 | if (err < 0) |
1979 | return err; | 1965 | return err; |
1980 | } | 1966 | } |
@@ -2059,7 +2045,11 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2059 | int err = __alc_build_controls(codec); | 2045 | int err = __alc_build_controls(codec); |
2060 | if (err < 0) | 2046 | if (err < 0) |
2061 | return err; | 2047 | return err; |
2062 | return snd_hda_jack_add_kctls(codec, &spec->autocfg); | 2048 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); |
2049 | if (err < 0) | ||
2050 | return err; | ||
2051 | alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD); | ||
2052 | return 0; | ||
2063 | } | 2053 | } |
2064 | 2054 | ||
2065 | 2055 | ||
@@ -2068,15 +2058,15 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2068 | */ | 2058 | */ |
2069 | 2059 | ||
2070 | static void alc_init_special_input_src(struct hda_codec *codec); | 2060 | static void alc_init_special_input_src(struct hda_codec *codec); |
2071 | static int alc269_fill_coef(struct hda_codec *codec); | 2061 | static void alc_auto_init_std(struct hda_codec *codec); |
2072 | 2062 | ||
2073 | static int alc_init(struct hda_codec *codec) | 2063 | static int alc_init(struct hda_codec *codec) |
2074 | { | 2064 | { |
2075 | struct alc_spec *spec = codec->spec; | 2065 | struct alc_spec *spec = codec->spec; |
2076 | unsigned int i; | 2066 | unsigned int i; |
2077 | 2067 | ||
2078 | if (codec->vendor_id == 0x10ec0269) | 2068 | if (spec->init_hook) |
2079 | alc269_fill_coef(codec); | 2069 | spec->init_hook(codec); |
2080 | 2070 | ||
2081 | alc_fix_pll(codec); | 2071 | alc_fix_pll(codec); |
2082 | alc_auto_init_amp(codec, spec->init_amp); | 2072 | alc_auto_init_amp(codec, spec->init_amp); |
@@ -2084,9 +2074,7 @@ static int alc_init(struct hda_codec *codec) | |||
2084 | for (i = 0; i < spec->num_init_verbs; i++) | 2074 | for (i = 0; i < spec->num_init_verbs; i++) |
2085 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | 2075 | snd_hda_sequence_write(codec, spec->init_verbs[i]); |
2086 | alc_init_special_input_src(codec); | 2076 | alc_init_special_input_src(codec); |
2087 | 2077 | alc_auto_init_std(codec); | |
2088 | if (spec->init_hook) | ||
2089 | spec->init_hook(codec); | ||
2090 | 2078 | ||
2091 | alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT); | 2079 | alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT); |
2092 | 2080 | ||
@@ -2675,6 +2663,25 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, | |||
2675 | return channel_name[ch]; | 2663 | return channel_name[ch]; |
2676 | } | 2664 | } |
2677 | 2665 | ||
2666 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2667 | /* add the powersave loopback-list entry */ | ||
2668 | static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx) | ||
2669 | { | ||
2670 | struct hda_amp_list *list; | ||
2671 | |||
2672 | if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1) | ||
2673 | return; | ||
2674 | list = spec->loopback_list + spec->num_loopbacks; | ||
2675 | list->nid = mix; | ||
2676 | list->dir = HDA_INPUT; | ||
2677 | list->idx = idx; | ||
2678 | spec->num_loopbacks++; | ||
2679 | spec->loopback.amplist = spec->loopback_list; | ||
2680 | } | ||
2681 | #else | ||
2682 | #define add_loopback_list(spec, mix, idx) /* NOP */ | ||
2683 | #endif | ||
2684 | |||
2678 | /* create input playback/capture controls for the given pin */ | 2685 | /* create input playback/capture controls for the given pin */ |
2679 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, | 2686 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, |
2680 | const char *ctlname, int ctlidx, | 2687 | const char *ctlname, int ctlidx, |
@@ -2690,6 +2697,7 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, | |||
2690 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 2697 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
2691 | if (err < 0) | 2698 | if (err < 0) |
2692 | return err; | 2699 | return err; |
2700 | add_loopback_list(spec, mix_nid, idx); | ||
2693 | return 0; | 2701 | return 0; |
2694 | } | 2702 | } |
2695 | 2703 | ||
@@ -2954,10 +2962,27 @@ static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin, | |||
2954 | return 0; | 2962 | return 0; |
2955 | } | 2963 | } |
2956 | 2964 | ||
2965 | static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid) | ||
2966 | { | ||
2967 | struct alc_spec *spec = codec->spec; | ||
2968 | int i; | ||
2969 | if (found_in_nid_list(nid, spec->multiout.dac_nids, | ||
2970 | ARRAY_SIZE(spec->private_dac_nids)) || | ||
2971 | found_in_nid_list(nid, spec->multiout.hp_out_nid, | ||
2972 | ARRAY_SIZE(spec->multiout.hp_out_nid)) || | ||
2973 | found_in_nid_list(nid, spec->multiout.extra_out_nid, | ||
2974 | ARRAY_SIZE(spec->multiout.extra_out_nid))) | ||
2975 | return true; | ||
2976 | for (i = 0; i < spec->multi_ios; i++) { | ||
2977 | if (spec->multi_io[i].dac == nid) | ||
2978 | return true; | ||
2979 | } | ||
2980 | return false; | ||
2981 | } | ||
2982 | |||
2957 | /* look for an empty DAC slot */ | 2983 | /* look for an empty DAC slot */ |
2958 | static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) | 2984 | static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) |
2959 | { | 2985 | { |
2960 | struct alc_spec *spec = codec->spec; | ||
2961 | hda_nid_t srcs[5]; | 2986 | hda_nid_t srcs[5]; |
2962 | int i, num; | 2987 | int i, num; |
2963 | 2988 | ||
@@ -2967,16 +2992,8 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) | |||
2967 | hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]); | 2992 | hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]); |
2968 | if (!nid) | 2993 | if (!nid) |
2969 | continue; | 2994 | continue; |
2970 | if (found_in_nid_list(nid, spec->multiout.dac_nids, | 2995 | if (!alc_is_dac_already_used(codec, nid)) |
2971 | ARRAY_SIZE(spec->private_dac_nids))) | 2996 | return nid; |
2972 | continue; | ||
2973 | if (found_in_nid_list(nid, spec->multiout.hp_out_nid, | ||
2974 | ARRAY_SIZE(spec->multiout.hp_out_nid))) | ||
2975 | continue; | ||
2976 | if (found_in_nid_list(nid, spec->multiout.extra_out_nid, | ||
2977 | ARRAY_SIZE(spec->multiout.extra_out_nid))) | ||
2978 | continue; | ||
2979 | return nid; | ||
2980 | } | 2997 | } |
2981 | return 0; | 2998 | return 0; |
2982 | } | 2999 | } |
@@ -2988,6 +3005,8 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec, | |||
2988 | hda_nid_t srcs[5]; | 3005 | hda_nid_t srcs[5]; |
2989 | int i, num; | 3006 | int i, num; |
2990 | 3007 | ||
3008 | if (!pin || !dac) | ||
3009 | return false; | ||
2991 | pin = alc_go_down_to_selector(codec, pin); | 3010 | pin = alc_go_down_to_selector(codec, pin); |
2992 | num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs)); | 3011 | num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs)); |
2993 | for (i = 0; i < num; i++) { | 3012 | for (i = 0; i < num; i++) { |
@@ -3000,83 +3019,260 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec, | |||
3000 | 3019 | ||
3001 | static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) | 3020 | static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) |
3002 | { | 3021 | { |
3022 | struct alc_spec *spec = codec->spec; | ||
3003 | hda_nid_t sel = alc_go_down_to_selector(codec, pin); | 3023 | hda_nid_t sel = alc_go_down_to_selector(codec, pin); |
3004 | if (snd_hda_get_conn_list(codec, sel, NULL) == 1) | 3024 | hda_nid_t nid, nid_found, srcs[5]; |
3025 | int i, num = snd_hda_get_connections(codec, sel, srcs, | ||
3026 | ARRAY_SIZE(srcs)); | ||
3027 | if (num == 1) | ||
3005 | return alc_auto_look_for_dac(codec, pin); | 3028 | return alc_auto_look_for_dac(codec, pin); |
3006 | return 0; | 3029 | nid_found = 0; |
3030 | for (i = 0; i < num; i++) { | ||
3031 | if (srcs[i] == spec->mixer_nid) | ||
3032 | continue; | ||
3033 | nid = alc_auto_mix_to_dac(codec, srcs[i]); | ||
3034 | if (nid && !alc_is_dac_already_used(codec, nid)) { | ||
3035 | if (nid_found) | ||
3036 | return 0; | ||
3037 | nid_found = nid; | ||
3038 | } | ||
3039 | } | ||
3040 | return nid_found; | ||
3007 | } | 3041 | } |
3008 | 3042 | ||
3009 | /* return 0 if no possible DAC is found, 1 if one or more found */ | 3043 | /* mark up volume and mute control NIDs: used during badness parsing and |
3010 | static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, | 3044 | * at creating actual controls |
3011 | const hda_nid_t *pins, hda_nid_t *dacs) | 3045 | */ |
3046 | static inline unsigned int get_ctl_pos(unsigned int data) | ||
3012 | { | 3047 | { |
3013 | int i; | 3048 | hda_nid_t nid = get_amp_nid_(data); |
3049 | unsigned int dir; | ||
3050 | if (snd_BUG_ON(nid >= MAX_VOL_NIDS)) | ||
3051 | return 0; | ||
3052 | dir = get_amp_direction_(data); | ||
3053 | return (nid << 1) | dir; | ||
3054 | } | ||
3014 | 3055 | ||
3015 | if (num_outs && !dacs[0]) { | 3056 | #define is_ctl_used(bits, data) \ |
3016 | dacs[0] = alc_auto_look_for_dac(codec, pins[0]); | 3057 | test_bit(get_ctl_pos(data), bits) |
3017 | if (!dacs[0]) | 3058 | #define mark_ctl_usage(bits, data) \ |
3018 | return 0; | 3059 | set_bit(get_ctl_pos(data), bits) |
3019 | } | ||
3020 | 3060 | ||
3021 | for (i = 1; i < num_outs; i++) | 3061 | static void clear_vol_marks(struct hda_codec *codec) |
3022 | dacs[i] = get_dac_if_single(codec, pins[i]); | 3062 | { |
3023 | for (i = 1; i < num_outs; i++) { | 3063 | struct alc_spec *spec = codec->spec; |
3064 | memset(spec->vol_ctls, 0, sizeof(spec->vol_ctls)); | ||
3065 | memset(spec->sw_ctls, 0, sizeof(spec->sw_ctls)); | ||
3066 | } | ||
3067 | |||
3068 | /* badness definition */ | ||
3069 | enum { | ||
3070 | /* No primary DAC is found for the main output */ | ||
3071 | BAD_NO_PRIMARY_DAC = 0x10000, | ||
3072 | /* No DAC is found for the extra output */ | ||
3073 | BAD_NO_DAC = 0x4000, | ||
3074 | /* No possible multi-ios */ | ||
3075 | BAD_MULTI_IO = 0x103, | ||
3076 | /* No individual DAC for extra output */ | ||
3077 | BAD_NO_EXTRA_DAC = 0x102, | ||
3078 | /* No individual DAC for extra surrounds */ | ||
3079 | BAD_NO_EXTRA_SURR_DAC = 0x101, | ||
3080 | /* Primary DAC shared with main surrounds */ | ||
3081 | BAD_SHARED_SURROUND = 0x100, | ||
3082 | /* Primary DAC shared with main CLFE */ | ||
3083 | BAD_SHARED_CLFE = 0x10, | ||
3084 | /* Primary DAC shared with extra surrounds */ | ||
3085 | BAD_SHARED_EXTRA_SURROUND = 0x10, | ||
3086 | /* Volume widget is shared */ | ||
3087 | BAD_SHARED_VOL = 0x10, | ||
3088 | }; | ||
3089 | |||
3090 | static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec, | ||
3091 | hda_nid_t pin, hda_nid_t dac); | ||
3092 | static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec, | ||
3093 | hda_nid_t pin, hda_nid_t dac); | ||
3094 | |||
3095 | static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin, | ||
3096 | hda_nid_t dac) | ||
3097 | { | ||
3098 | struct alc_spec *spec = codec->spec; | ||
3099 | hda_nid_t nid; | ||
3100 | unsigned int val; | ||
3101 | int badness = 0; | ||
3102 | |||
3103 | nid = alc_look_for_out_vol_nid(codec, pin, dac); | ||
3104 | if (nid) { | ||
3105 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | ||
3106 | if (is_ctl_used(spec->vol_ctls, nid)) | ||
3107 | badness += BAD_SHARED_VOL; | ||
3108 | else | ||
3109 | mark_ctl_usage(spec->vol_ctls, val); | ||
3110 | } else | ||
3111 | badness += BAD_SHARED_VOL; | ||
3112 | nid = alc_look_for_out_mute_nid(codec, pin, dac); | ||
3113 | if (nid) { | ||
3114 | unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid)); | ||
3115 | if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) | ||
3116 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | ||
3117 | else | ||
3118 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT); | ||
3119 | if (is_ctl_used(spec->sw_ctls, val)) | ||
3120 | badness += BAD_SHARED_VOL; | ||
3121 | else | ||
3122 | mark_ctl_usage(spec->sw_ctls, val); | ||
3123 | } else | ||
3124 | badness += BAD_SHARED_VOL; | ||
3125 | return badness; | ||
3126 | } | ||
3127 | |||
3128 | struct badness_table { | ||
3129 | int no_primary_dac; /* no primary DAC */ | ||
3130 | int no_dac; /* no secondary DACs */ | ||
3131 | int shared_primary; /* primary DAC is shared with main output */ | ||
3132 | int shared_surr; /* secondary DAC shared with main or primary */ | ||
3133 | int shared_clfe; /* third DAC shared with main or primary */ | ||
3134 | int shared_surr_main; /* secondary DAC sahred with main/DAC0 */ | ||
3135 | }; | ||
3136 | |||
3137 | static struct badness_table main_out_badness = { | ||
3138 | .no_primary_dac = BAD_NO_PRIMARY_DAC, | ||
3139 | .no_dac = BAD_NO_DAC, | ||
3140 | .shared_primary = BAD_NO_PRIMARY_DAC, | ||
3141 | .shared_surr = BAD_SHARED_SURROUND, | ||
3142 | .shared_clfe = BAD_SHARED_CLFE, | ||
3143 | .shared_surr_main = BAD_SHARED_SURROUND, | ||
3144 | }; | ||
3145 | |||
3146 | static struct badness_table extra_out_badness = { | ||
3147 | .no_primary_dac = BAD_NO_DAC, | ||
3148 | .no_dac = BAD_NO_DAC, | ||
3149 | .shared_primary = BAD_NO_EXTRA_DAC, | ||
3150 | .shared_surr = BAD_SHARED_EXTRA_SURROUND, | ||
3151 | .shared_clfe = BAD_SHARED_EXTRA_SURROUND, | ||
3152 | .shared_surr_main = BAD_NO_EXTRA_SURR_DAC, | ||
3153 | }; | ||
3154 | |||
3155 | /* try to assign DACs to pins and return the resultant badness */ | ||
3156 | static int alc_auto_fill_dacs(struct hda_codec *codec, int num_outs, | ||
3157 | const hda_nid_t *pins, hda_nid_t *dacs, | ||
3158 | const struct badness_table *bad) | ||
3159 | { | ||
3160 | struct alc_spec *spec = codec->spec; | ||
3161 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3162 | int i, j; | ||
3163 | int badness = 0; | ||
3164 | hda_nid_t dac; | ||
3165 | |||
3166 | if (!num_outs) | ||
3167 | return 0; | ||
3168 | |||
3169 | for (i = 0; i < num_outs; i++) { | ||
3170 | hda_nid_t pin = pins[i]; | ||
3024 | if (!dacs[i]) | 3171 | if (!dacs[i]) |
3025 | dacs[i] = alc_auto_look_for_dac(codec, pins[i]); | 3172 | dacs[i] = alc_auto_look_for_dac(codec, pin); |
3173 | if (!dacs[i] && !i) { | ||
3174 | for (j = 1; j < num_outs; j++) { | ||
3175 | if (alc_auto_is_dac_reachable(codec, pin, dacs[j])) { | ||
3176 | dacs[0] = dacs[j]; | ||
3177 | dacs[j] = 0; | ||
3178 | break; | ||
3179 | } | ||
3180 | } | ||
3181 | } | ||
3182 | dac = dacs[i]; | ||
3183 | if (!dac) { | ||
3184 | if (alc_auto_is_dac_reachable(codec, pin, dacs[0])) | ||
3185 | dac = dacs[0]; | ||
3186 | else if (cfg->line_outs > i && | ||
3187 | alc_auto_is_dac_reachable(codec, pin, | ||
3188 | spec->private_dac_nids[i])) | ||
3189 | dac = spec->private_dac_nids[i]; | ||
3190 | if (dac) { | ||
3191 | if (!i) | ||
3192 | badness += bad->shared_primary; | ||
3193 | else if (i == 1) | ||
3194 | badness += bad->shared_surr; | ||
3195 | else | ||
3196 | badness += bad->shared_clfe; | ||
3197 | } else if (alc_auto_is_dac_reachable(codec, pin, | ||
3198 | spec->private_dac_nids[0])) { | ||
3199 | dac = spec->private_dac_nids[0]; | ||
3200 | badness += bad->shared_surr_main; | ||
3201 | } else if (!i) | ||
3202 | badness += bad->no_primary_dac; | ||
3203 | else | ||
3204 | badness += bad->no_dac; | ||
3205 | } | ||
3206 | if (dac) | ||
3207 | badness += eval_shared_vol_badness(codec, pin, dac); | ||
3026 | } | 3208 | } |
3027 | return 1; | 3209 | |
3210 | return badness; | ||
3028 | } | 3211 | } |
3029 | 3212 | ||
3030 | static int alc_auto_fill_multi_ios(struct hda_codec *codec, | 3213 | static int alc_auto_fill_multi_ios(struct hda_codec *codec, |
3031 | unsigned int location, int offset); | 3214 | hda_nid_t reference_pin, |
3032 | static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec, | 3215 | bool hardwired, int offset); |
3033 | hda_nid_t pin, hda_nid_t dac); | 3216 | |
3217 | static bool alc_map_singles(struct hda_codec *codec, int outs, | ||
3218 | const hda_nid_t *pins, hda_nid_t *dacs) | ||
3219 | { | ||
3220 | int i; | ||
3221 | bool found = false; | ||
3222 | for (i = 0; i < outs; i++) { | ||
3223 | if (dacs[i]) | ||
3224 | continue; | ||
3225 | dacs[i] = get_dac_if_single(codec, pins[i]); | ||
3226 | if (dacs[i]) | ||
3227 | found = true; | ||
3228 | } | ||
3229 | return found; | ||
3230 | } | ||
3034 | 3231 | ||
3035 | /* fill in the dac_nids table from the parsed pin configuration */ | 3232 | /* fill in the dac_nids table from the parsed pin configuration */ |
3036 | static int alc_auto_fill_dac_nids(struct hda_codec *codec) | 3233 | static int fill_and_eval_dacs(struct hda_codec *codec, |
3234 | bool fill_hardwired, | ||
3235 | bool fill_mio_first) | ||
3037 | { | 3236 | { |
3038 | struct alc_spec *spec = codec->spec; | 3237 | struct alc_spec *spec = codec->spec; |
3039 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3238 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3040 | unsigned int location, defcfg; | 3239 | int i, err, badness; |
3041 | int num_pins; | ||
3042 | bool redone = false; | ||
3043 | int i; | ||
3044 | 3240 | ||
3045 | again: | ||
3046 | /* set num_dacs once to full for alc_auto_look_for_dac() */ | 3241 | /* set num_dacs once to full for alc_auto_look_for_dac() */ |
3047 | spec->multiout.num_dacs = cfg->line_outs; | 3242 | spec->multiout.num_dacs = cfg->line_outs; |
3048 | spec->multiout.hp_out_nid[0] = 0; | ||
3049 | spec->multiout.extra_out_nid[0] = 0; | ||
3050 | memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); | ||
3051 | spec->multiout.dac_nids = spec->private_dac_nids; | 3243 | spec->multiout.dac_nids = spec->private_dac_nids; |
3244 | memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); | ||
3245 | memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid)); | ||
3246 | memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid)); | ||
3052 | spec->multi_ios = 0; | 3247 | spec->multi_ios = 0; |
3248 | clear_vol_marks(codec); | ||
3249 | badness = 0; | ||
3053 | 3250 | ||
3054 | /* fill hard-wired DACs first */ | 3251 | /* fill hard-wired DACs first */ |
3055 | if (!redone) { | 3252 | if (fill_hardwired) { |
3056 | for (i = 0; i < cfg->line_outs; i++) | 3253 | bool mapped; |
3057 | spec->private_dac_nids[i] = | 3254 | do { |
3058 | get_dac_if_single(codec, cfg->line_out_pins[i]); | 3255 | mapped = alc_map_singles(codec, cfg->line_outs, |
3059 | if (cfg->hp_outs) | 3256 | cfg->line_out_pins, |
3060 | spec->multiout.hp_out_nid[0] = | 3257 | spec->private_dac_nids); |
3061 | get_dac_if_single(codec, cfg->hp_pins[0]); | 3258 | mapped |= alc_map_singles(codec, cfg->hp_outs, |
3062 | if (cfg->speaker_outs) | 3259 | cfg->hp_pins, |
3063 | spec->multiout.extra_out_nid[0] = | 3260 | spec->multiout.hp_out_nid); |
3064 | get_dac_if_single(codec, cfg->speaker_pins[0]); | 3261 | mapped |= alc_map_singles(codec, cfg->speaker_outs, |
3262 | cfg->speaker_pins, | ||
3263 | spec->multiout.extra_out_nid); | ||
3264 | if (fill_mio_first && cfg->line_outs == 1 && | ||
3265 | cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | ||
3266 | err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], true, 0); | ||
3267 | if (!err) | ||
3268 | mapped = true; | ||
3269 | } | ||
3270 | } while (mapped); | ||
3065 | } | 3271 | } |
3066 | 3272 | ||
3067 | for (i = 0; i < cfg->line_outs; i++) { | 3273 | badness += alc_auto_fill_dacs(codec, cfg->line_outs, cfg->line_out_pins, |
3068 | hda_nid_t pin = cfg->line_out_pins[i]; | 3274 | spec->private_dac_nids, |
3069 | if (spec->private_dac_nids[i]) | 3275 | &main_out_badness); |
3070 | continue; | ||
3071 | spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin); | ||
3072 | if (!spec->private_dac_nids[i] && !redone) { | ||
3073 | /* if we can't find primary DACs, re-probe without | ||
3074 | * checking the hard-wired DACs | ||
3075 | */ | ||
3076 | redone = true; | ||
3077 | goto again; | ||
3078 | } | ||
3079 | } | ||
3080 | 3276 | ||
3081 | /* re-count num_dacs and squash invalid entries */ | 3277 | /* re-count num_dacs and squash invalid entries */ |
3082 | spec->multiout.num_dacs = 0; | 3278 | spec->multiout.num_dacs = 0; |
@@ -3091,30 +3287,144 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) | |||
3091 | } | 3287 | } |
3092 | } | 3288 | } |
3093 | 3289 | ||
3094 | if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | 3290 | if (fill_mio_first && |
3291 | cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | ||
3095 | /* try to fill multi-io first */ | 3292 | /* try to fill multi-io first */ |
3096 | defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]); | 3293 | err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0); |
3097 | location = get_defcfg_location(defcfg); | 3294 | if (err < 0) |
3098 | 3295 | return err; | |
3099 | num_pins = alc_auto_fill_multi_ios(codec, location, 0); | 3296 | /* we don't count badness at this stage yet */ |
3100 | if (num_pins > 0) { | ||
3101 | spec->multi_ios = num_pins; | ||
3102 | spec->ext_channel_count = 2; | ||
3103 | spec->multiout.num_dacs = num_pins + 1; | ||
3104 | } | ||
3105 | } | 3297 | } |
3106 | 3298 | ||
3107 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) | 3299 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) { |
3108 | alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins, | 3300 | err = alc_auto_fill_dacs(codec, cfg->hp_outs, cfg->hp_pins, |
3109 | spec->multiout.hp_out_nid); | 3301 | spec->multiout.hp_out_nid, |
3302 | &extra_out_badness); | ||
3303 | if (err < 0) | ||
3304 | return err; | ||
3305 | badness += err; | ||
3306 | } | ||
3110 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | 3307 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
3111 | int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, | 3308 | err = alc_auto_fill_dacs(codec, cfg->speaker_outs, |
3112 | cfg->speaker_pins, | 3309 | cfg->speaker_pins, |
3113 | spec->multiout.extra_out_nid); | 3310 | spec->multiout.extra_out_nid, |
3114 | /* if no speaker volume is assigned, try again as the primary | 3311 | &extra_out_badness); |
3115 | * output | 3312 | if (err < 0) |
3116 | */ | 3313 | return err; |
3117 | if (!err && cfg->speaker_outs > 0 && | 3314 | badness += err; |
3315 | } | ||
3316 | if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | ||
3317 | err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0); | ||
3318 | if (err < 0) | ||
3319 | return err; | ||
3320 | badness += err; | ||
3321 | } | ||
3322 | if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { | ||
3323 | /* try multi-ios with HP + inputs */ | ||
3324 | int offset = 0; | ||
3325 | if (cfg->line_outs >= 3) | ||
3326 | offset = 1; | ||
3327 | err = alc_auto_fill_multi_ios(codec, cfg->hp_pins[0], false, | ||
3328 | offset); | ||
3329 | if (err < 0) | ||
3330 | return err; | ||
3331 | badness += err; | ||
3332 | } | ||
3333 | |||
3334 | if (spec->multi_ios == 2) { | ||
3335 | for (i = 0; i < 2; i++) | ||
3336 | spec->private_dac_nids[spec->multiout.num_dacs++] = | ||
3337 | spec->multi_io[i].dac; | ||
3338 | spec->ext_channel_count = 2; | ||
3339 | } else if (spec->multi_ios) { | ||
3340 | spec->multi_ios = 0; | ||
3341 | badness += BAD_MULTI_IO; | ||
3342 | } | ||
3343 | |||
3344 | return badness; | ||
3345 | } | ||
3346 | |||
3347 | #define DEBUG_BADNESS | ||
3348 | |||
3349 | #ifdef DEBUG_BADNESS | ||
3350 | #define debug_badness snd_printdd | ||
3351 | #else | ||
3352 | #define debug_badness(...) | ||
3353 | #endif | ||
3354 | |||
3355 | static void debug_show_configs(struct alc_spec *spec, struct auto_pin_cfg *cfg) | ||
3356 | { | ||
3357 | debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", | ||
3358 | cfg->line_out_pins[0], cfg->line_out_pins[1], | ||
3359 | cfg->line_out_pins[2], cfg->line_out_pins[2], | ||
3360 | spec->multiout.dac_nids[0], | ||
3361 | spec->multiout.dac_nids[1], | ||
3362 | spec->multiout.dac_nids[2], | ||
3363 | spec->multiout.dac_nids[3]); | ||
3364 | if (spec->multi_ios > 0) | ||
3365 | debug_badness("multi_ios(%d) = %x/%x : %x/%x\n", | ||
3366 | spec->multi_ios, | ||
3367 | spec->multi_io[0].pin, spec->multi_io[1].pin, | ||
3368 | spec->multi_io[0].dac, spec->multi_io[1].dac); | ||
3369 | debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", | ||
3370 | cfg->hp_pins[0], cfg->hp_pins[1], | ||
3371 | cfg->hp_pins[2], cfg->hp_pins[2], | ||
3372 | spec->multiout.hp_out_nid[0], | ||
3373 | spec->multiout.hp_out_nid[1], | ||
3374 | spec->multiout.hp_out_nid[2], | ||
3375 | spec->multiout.hp_out_nid[3]); | ||
3376 | debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", | ||
3377 | cfg->speaker_pins[0], cfg->speaker_pins[1], | ||
3378 | cfg->speaker_pins[2], cfg->speaker_pins[3], | ||
3379 | spec->multiout.extra_out_nid[0], | ||
3380 | spec->multiout.extra_out_nid[1], | ||
3381 | spec->multiout.extra_out_nid[2], | ||
3382 | spec->multiout.extra_out_nid[3]); | ||
3383 | } | ||
3384 | |||
3385 | static int alc_auto_fill_dac_nids(struct hda_codec *codec) | ||
3386 | { | ||
3387 | struct alc_spec *spec = codec->spec; | ||
3388 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3389 | struct auto_pin_cfg *best_cfg; | ||
3390 | int best_badness = INT_MAX; | ||
3391 | int badness; | ||
3392 | bool fill_hardwired = true, fill_mio_first = true; | ||
3393 | bool best_wired = true, best_mio = true; | ||
3394 | bool hp_spk_swapped = false; | ||
3395 | |||
3396 | best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL); | ||
3397 | if (!best_cfg) | ||
3398 | return -ENOMEM; | ||
3399 | *best_cfg = *cfg; | ||
3400 | |||
3401 | for (;;) { | ||
3402 | badness = fill_and_eval_dacs(codec, fill_hardwired, | ||
3403 | fill_mio_first); | ||
3404 | if (badness < 0) | ||
3405 | return badness; | ||
3406 | debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n", | ||
3407 | cfg->line_out_type, fill_hardwired, fill_mio_first, | ||
3408 | badness); | ||
3409 | debug_show_configs(spec, cfg); | ||
3410 | if (badness < best_badness) { | ||
3411 | best_badness = badness; | ||
3412 | *best_cfg = *cfg; | ||
3413 | best_wired = fill_hardwired; | ||
3414 | best_mio = fill_mio_first; | ||
3415 | } | ||
3416 | if (!badness) | ||
3417 | break; | ||
3418 | fill_mio_first = !fill_mio_first; | ||
3419 | if (!fill_mio_first) | ||
3420 | continue; | ||
3421 | fill_hardwired = !fill_hardwired; | ||
3422 | if (!fill_hardwired) | ||
3423 | continue; | ||
3424 | if (hp_spk_swapped) | ||
3425 | break; | ||
3426 | hp_spk_swapped = true; | ||
3427 | if (cfg->speaker_outs > 0 && | ||
3118 | cfg->line_out_type == AUTO_PIN_HP_OUT) { | 3428 | cfg->line_out_type == AUTO_PIN_HP_OUT) { |
3119 | cfg->hp_outs = cfg->line_outs; | 3429 | cfg->hp_outs = cfg->line_outs; |
3120 | memcpy(cfg->hp_pins, cfg->line_out_pins, | 3430 | memcpy(cfg->hp_pins, cfg->line_out_pins, |
@@ -3125,48 +3435,45 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) | |||
3125 | cfg->speaker_outs = 0; | 3435 | cfg->speaker_outs = 0; |
3126 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | 3436 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); |
3127 | cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; | 3437 | cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; |
3128 | redone = false; | 3438 | fill_hardwired = true; |
3129 | goto again; | 3439 | continue; |
3130 | } | 3440 | } |
3441 | if (cfg->hp_outs > 0 && | ||
3442 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { | ||
3443 | cfg->speaker_outs = cfg->line_outs; | ||
3444 | memcpy(cfg->speaker_pins, cfg->line_out_pins, | ||
3445 | sizeof(cfg->speaker_pins)); | ||
3446 | cfg->line_outs = cfg->hp_outs; | ||
3447 | memcpy(cfg->line_out_pins, cfg->hp_pins, | ||
3448 | sizeof(cfg->hp_pins)); | ||
3449 | cfg->hp_outs = 0; | ||
3450 | memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); | ||
3451 | cfg->line_out_type = AUTO_PIN_HP_OUT; | ||
3452 | fill_hardwired = true; | ||
3453 | continue; | ||
3454 | } | ||
3455 | break; | ||
3131 | } | 3456 | } |
3132 | 3457 | ||
3133 | if (!spec->multi_ios && | 3458 | if (badness) { |
3134 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && | 3459 | *cfg = *best_cfg; |
3135 | cfg->hp_outs) { | 3460 | fill_and_eval_dacs(codec, best_wired, best_mio); |
3136 | /* try multi-ios with HP + inputs */ | ||
3137 | defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]); | ||
3138 | location = get_defcfg_location(defcfg); | ||
3139 | |||
3140 | num_pins = alc_auto_fill_multi_ios(codec, location, 1); | ||
3141 | if (num_pins > 0) { | ||
3142 | spec->multi_ios = num_pins; | ||
3143 | spec->ext_channel_count = 2; | ||
3144 | spec->multiout.num_dacs = num_pins + 1; | ||
3145 | } | ||
3146 | } | 3461 | } |
3462 | debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n", | ||
3463 | cfg->line_out_type, best_wired, best_mio); | ||
3464 | debug_show_configs(spec, cfg); | ||
3147 | 3465 | ||
3148 | if (cfg->line_out_pins[0]) | 3466 | if (cfg->line_out_pins[0]) |
3149 | spec->vmaster_nid = | 3467 | spec->vmaster_nid = |
3150 | alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0], | 3468 | alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0], |
3151 | spec->multiout.dac_nids[0]); | 3469 | spec->multiout.dac_nids[0]); |
3152 | return 0; | ||
3153 | } | ||
3154 | 3470 | ||
3155 | static inline unsigned int get_ctl_pos(unsigned int data) | 3471 | /* clear the bitmap flags for creating controls */ |
3156 | { | 3472 | clear_vol_marks(codec); |
3157 | hda_nid_t nid = get_amp_nid_(data); | 3473 | kfree(best_cfg); |
3158 | unsigned int dir; | 3474 | return 0; |
3159 | if (snd_BUG_ON(nid >= MAX_VOL_NIDS)) | ||
3160 | return 0; | ||
3161 | dir = get_amp_direction_(data); | ||
3162 | return (nid << 1) | dir; | ||
3163 | } | 3475 | } |
3164 | 3476 | ||
3165 | #define is_ctl_used(bits, data) \ | ||
3166 | test_bit(get_ctl_pos(data), bits) | ||
3167 | #define mark_ctl_usage(bits, data) \ | ||
3168 | set_bit(get_ctl_pos(data), bits) | ||
3169 | |||
3170 | static int alc_auto_add_vol_ctl(struct hda_codec *codec, | 3477 | static int alc_auto_add_vol_ctl(struct hda_codec *codec, |
3171 | const char *pfx, int cidx, | 3478 | const char *pfx, int cidx, |
3172 | hda_nid_t nid, unsigned int chs) | 3479 | hda_nid_t nid, unsigned int chs) |
@@ -3278,14 +3585,17 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
3278 | dac = spec->multiout.dac_nids[i]; | 3585 | dac = spec->multiout.dac_nids[i]; |
3279 | if (!dac) | 3586 | if (!dac) |
3280 | continue; | 3587 | continue; |
3281 | if (i >= cfg->line_outs) | 3588 | if (i >= cfg->line_outs) { |
3282 | pin = spec->multi_io[i - 1].pin; | 3589 | pin = spec->multi_io[i - 1].pin; |
3283 | else | 3590 | index = 0; |
3591 | name = channel_name[i]; | ||
3592 | } else { | ||
3284 | pin = cfg->line_out_pins[i]; | 3593 | pin = cfg->line_out_pins[i]; |
3594 | name = alc_get_line_out_pfx(spec, i, true, &index); | ||
3595 | } | ||
3285 | 3596 | ||
3286 | sw = alc_look_for_out_mute_nid(codec, pin, dac); | 3597 | sw = alc_look_for_out_mute_nid(codec, pin, dac); |
3287 | vol = alc_look_for_out_vol_nid(codec, pin, dac); | 3598 | vol = alc_look_for_out_vol_nid(codec, pin, dac); |
3288 | name = alc_get_line_out_pfx(spec, i, true, &index); | ||
3289 | if (!name || !strcmp(name, "CLFE")) { | 3599 | if (!name || !strcmp(name, "CLFE")) { |
3290 | /* Center/LFE */ | 3600 | /* Center/LFE */ |
3291 | err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1); | 3601 | err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1); |
@@ -3382,41 +3692,31 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, | |||
3382 | return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0); | 3692 | return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0); |
3383 | } | 3693 | } |
3384 | 3694 | ||
3385 | if (dacs[num_pins - 1]) { | ||
3386 | /* OK, we have a multi-output system with individual volumes */ | ||
3387 | for (i = 0; i < num_pins; i++) { | ||
3388 | if (num_pins >= 3) { | ||
3389 | snprintf(name, sizeof(name), "%s %s", | ||
3390 | pfx, channel_name[i]); | ||
3391 | err = alc_auto_create_extra_out(codec, pins[i], dacs[i], | ||
3392 | name, 0); | ||
3393 | } else { | ||
3394 | err = alc_auto_create_extra_out(codec, pins[i], dacs[i], | ||
3395 | pfx, i); | ||
3396 | } | ||
3397 | if (err < 0) | ||
3398 | return err; | ||
3399 | } | ||
3400 | return 0; | ||
3401 | } | ||
3402 | |||
3403 | /* Let's create a bind-controls */ | ||
3404 | ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_sw); | ||
3405 | if (!ctl) | ||
3406 | return -ENOMEM; | ||
3407 | n = 0; | ||
3408 | for (i = 0; i < num_pins; i++) { | 3695 | for (i = 0; i < num_pins; i++) { |
3409 | if (get_wcaps(codec, pins[i]) & AC_WCAP_OUT_AMP) | 3696 | hda_nid_t dac; |
3410 | ctl->values[n++] = | 3697 | if (dacs[num_pins - 1]) |
3411 | HDA_COMPOSE_AMP_VAL(pins[i], 3, 0, HDA_OUTPUT); | 3698 | dac = dacs[i]; /* with individual volumes */ |
3412 | } | 3699 | else |
3413 | if (n) { | 3700 | dac = 0; |
3414 | snprintf(name, sizeof(name), "%s Playback Switch", pfx); | 3701 | if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) { |
3415 | err = add_control(spec, ALC_CTL_BIND_SW, name, 0, (long)ctl); | 3702 | err = alc_auto_create_extra_out(codec, pins[i], dac, |
3703 | "Bass Speaker", 0); | ||
3704 | } else if (num_pins >= 3) { | ||
3705 | snprintf(name, sizeof(name), "%s %s", | ||
3706 | pfx, channel_name[i]); | ||
3707 | err = alc_auto_create_extra_out(codec, pins[i], dac, | ||
3708 | name, 0); | ||
3709 | } else { | ||
3710 | err = alc_auto_create_extra_out(codec, pins[i], dac, | ||
3711 | pfx, i); | ||
3712 | } | ||
3416 | if (err < 0) | 3713 | if (err < 0) |
3417 | return err; | 3714 | return err; |
3418 | } | 3715 | } |
3716 | if (dacs[num_pins - 1]) | ||
3717 | return 0; | ||
3419 | 3718 | ||
3719 | /* Let's create a bind-controls for volumes */ | ||
3420 | ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol); | 3720 | ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol); |
3421 | if (!ctl) | 3721 | if (!ctl) |
3422 | return -ENOMEM; | 3722 | return -ENOMEM; |
@@ -3552,58 +3852,111 @@ static void alc_auto_init_extra_out(struct hda_codec *codec) | |||
3552 | } | 3852 | } |
3553 | } | 3853 | } |
3554 | 3854 | ||
3855 | /* check whether the given pin can be a multi-io pin */ | ||
3856 | static bool can_be_multiio_pin(struct hda_codec *codec, | ||
3857 | unsigned int location, hda_nid_t nid) | ||
3858 | { | ||
3859 | unsigned int defcfg, caps; | ||
3860 | |||
3861 | defcfg = snd_hda_codec_get_pincfg(codec, nid); | ||
3862 | if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX) | ||
3863 | return false; | ||
3864 | if (location && get_defcfg_location(defcfg) != location) | ||
3865 | return false; | ||
3866 | caps = snd_hda_query_pin_caps(codec, nid); | ||
3867 | if (!(caps & AC_PINCAP_OUT)) | ||
3868 | return false; | ||
3869 | return true; | ||
3870 | } | ||
3871 | |||
3555 | /* | 3872 | /* |
3556 | * multi-io helper | 3873 | * multi-io helper |
3874 | * | ||
3875 | * When hardwired is set, try to fill ony hardwired pins, and returns | ||
3876 | * zero if any pins are filled, non-zero if nothing found. | ||
3877 | * When hardwired is off, try to fill possible input pins, and returns | ||
3878 | * the badness value. | ||
3557 | */ | 3879 | */ |
3558 | static int alc_auto_fill_multi_ios(struct hda_codec *codec, | 3880 | static int alc_auto_fill_multi_ios(struct hda_codec *codec, |
3559 | unsigned int location, | 3881 | hda_nid_t reference_pin, |
3560 | int offset) | 3882 | bool hardwired, int offset) |
3561 | { | 3883 | { |
3562 | struct alc_spec *spec = codec->spec; | 3884 | struct alc_spec *spec = codec->spec; |
3563 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3885 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3564 | hda_nid_t prime_dac = spec->private_dac_nids[0]; | 3886 | int type, i, j, dacs, num_pins, old_pins; |
3565 | int type, i, dacs, num_pins = 0; | 3887 | unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin); |
3888 | unsigned int location = get_defcfg_location(defcfg); | ||
3889 | int badness = 0; | ||
3890 | |||
3891 | old_pins = spec->multi_ios; | ||
3892 | if (old_pins >= 2) | ||
3893 | goto end_fill; | ||
3894 | |||
3895 | num_pins = 0; | ||
3896 | for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) { | ||
3897 | for (i = 0; i < cfg->num_inputs; i++) { | ||
3898 | if (cfg->inputs[i].type != type) | ||
3899 | continue; | ||
3900 | if (can_be_multiio_pin(codec, location, | ||
3901 | cfg->inputs[i].pin)) | ||
3902 | num_pins++; | ||
3903 | } | ||
3904 | } | ||
3905 | if (num_pins < 2) | ||
3906 | goto end_fill; | ||
3566 | 3907 | ||
3567 | dacs = spec->multiout.num_dacs; | 3908 | dacs = spec->multiout.num_dacs; |
3568 | for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) { | 3909 | for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) { |
3569 | for (i = 0; i < cfg->num_inputs; i++) { | 3910 | for (i = 0; i < cfg->num_inputs; i++) { |
3570 | hda_nid_t nid = cfg->inputs[i].pin; | 3911 | hda_nid_t nid = cfg->inputs[i].pin; |
3571 | hda_nid_t dac = 0; | 3912 | hda_nid_t dac = 0; |
3572 | unsigned int defcfg, caps; | 3913 | |
3573 | if (cfg->inputs[i].type != type) | 3914 | if (cfg->inputs[i].type != type) |
3574 | continue; | 3915 | continue; |
3575 | defcfg = snd_hda_codec_get_pincfg(codec, nid); | 3916 | if (!can_be_multiio_pin(codec, location, nid)) |
3576 | if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX) | ||
3577 | continue; | ||
3578 | if (location && get_defcfg_location(defcfg) != location) | ||
3579 | continue; | 3917 | continue; |
3580 | caps = snd_hda_query_pin_caps(codec, nid); | 3918 | for (j = 0; j < spec->multi_ios; j++) { |
3581 | if (!(caps & AC_PINCAP_OUT)) | 3919 | if (nid == spec->multi_io[j].pin) |
3920 | break; | ||
3921 | } | ||
3922 | if (j < spec->multi_ios) | ||
3582 | continue; | 3923 | continue; |
3583 | if (offset && offset + num_pins < dacs) { | 3924 | |
3584 | dac = spec->private_dac_nids[offset + num_pins]; | 3925 | if (offset && offset + spec->multi_ios < dacs) { |
3926 | dac = spec->private_dac_nids[offset + spec->multi_ios]; | ||
3585 | if (!alc_auto_is_dac_reachable(codec, nid, dac)) | 3927 | if (!alc_auto_is_dac_reachable(codec, nid, dac)) |
3586 | dac = 0; | 3928 | dac = 0; |
3587 | } | 3929 | } |
3588 | if (!dac) | 3930 | if (hardwired) |
3931 | dac = get_dac_if_single(codec, nid); | ||
3932 | else if (!dac) | ||
3589 | dac = alc_auto_look_for_dac(codec, nid); | 3933 | dac = alc_auto_look_for_dac(codec, nid); |
3590 | if (!dac) | 3934 | if (!dac) { |
3935 | badness++; | ||
3591 | continue; | 3936 | continue; |
3592 | spec->multi_io[num_pins].pin = nid; | 3937 | } |
3593 | spec->multi_io[num_pins].dac = dac; | 3938 | spec->multi_io[spec->multi_ios].pin = nid; |
3594 | num_pins++; | 3939 | spec->multi_io[spec->multi_ios].dac = dac; |
3595 | spec->private_dac_nids[spec->multiout.num_dacs++] = dac; | 3940 | spec->multi_ios++; |
3941 | if (spec->multi_ios >= 2) | ||
3942 | break; | ||
3596 | } | 3943 | } |
3597 | } | 3944 | } |
3598 | spec->multiout.num_dacs = dacs; | 3945 | end_fill: |
3599 | if (num_pins < 2) { | 3946 | if (badness) |
3600 | /* clear up again */ | 3947 | badness = BAD_MULTI_IO; |
3601 | memset(spec->private_dac_nids + dacs, 0, | 3948 | if (old_pins == spec->multi_ios) { |
3602 | sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - dacs)); | 3949 | if (hardwired) |
3603 | spec->private_dac_nids[0] = prime_dac; | 3950 | return 1; /* nothing found */ |
3604 | return 0; | 3951 | else |
3952 | return badness; /* no badness if nothing found */ | ||
3953 | } | ||
3954 | if (!hardwired && spec->multi_ios < 2) { | ||
3955 | spec->multi_ios = old_pins; | ||
3956 | return badness; | ||
3605 | } | 3957 | } |
3606 | return num_pins; | 3958 | |
3959 | return 0; | ||
3607 | } | 3960 | } |
3608 | 3961 | ||
3609 | static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol, | 3962 | static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol, |
@@ -3958,6 +4311,7 @@ static const struct snd_pci_quirk beep_white_list[] = { | |||
3958 | SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), | 4311 | SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), |
3959 | SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1), | 4312 | SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1), |
3960 | SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1), | 4313 | SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1), |
4314 | SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1), | ||
3961 | SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), | 4315 | SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), |
3962 | {} | 4316 | {} |
3963 | }; | 4317 | }; |
@@ -4057,6 +4411,9 @@ static int alc_parse_auto_config(struct hda_codec *codec, | |||
4057 | if (spec->kctls.list) | 4411 | if (spec->kctls.list) |
4058 | add_mixer(spec, spec->kctls.list); | 4412 | add_mixer(spec, spec->kctls.list); |
4059 | 4413 | ||
4414 | if (!spec->no_analog && !spec->cap_mixer) | ||
4415 | set_capture_mixer(codec); | ||
4416 | |||
4060 | return 1; | 4417 | return 1; |
4061 | } | 4418 | } |
4062 | 4419 | ||
@@ -4067,26 +4424,47 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
4067 | return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids); | 4424 | return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids); |
4068 | } | 4425 | } |
4069 | 4426 | ||
4070 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4071 | static const struct hda_amp_list alc880_loopbacks[] = { | ||
4072 | { 0x0b, HDA_INPUT, 0 }, | ||
4073 | { 0x0b, HDA_INPUT, 1 }, | ||
4074 | { 0x0b, HDA_INPUT, 2 }, | ||
4075 | { 0x0b, HDA_INPUT, 3 }, | ||
4076 | { 0x0b, HDA_INPUT, 4 }, | ||
4077 | { } /* end */ | ||
4078 | }; | ||
4079 | #endif | ||
4080 | |||
4081 | /* | 4427 | /* |
4082 | * ALC880 fix-ups | 4428 | * ALC880 fix-ups |
4083 | */ | 4429 | */ |
4084 | enum { | 4430 | enum { |
4431 | ALC880_FIXUP_GPIO1, | ||
4085 | ALC880_FIXUP_GPIO2, | 4432 | ALC880_FIXUP_GPIO2, |
4086 | ALC880_FIXUP_MEDION_RIM, | 4433 | ALC880_FIXUP_MEDION_RIM, |
4434 | ALC880_FIXUP_LG, | ||
4435 | ALC880_FIXUP_W810, | ||
4436 | ALC880_FIXUP_EAPD_COEF, | ||
4437 | ALC880_FIXUP_TCL_S700, | ||
4438 | ALC880_FIXUP_VOL_KNOB, | ||
4439 | ALC880_FIXUP_FUJITSU, | ||
4440 | ALC880_FIXUP_F1734, | ||
4441 | ALC880_FIXUP_UNIWILL, | ||
4442 | ALC880_FIXUP_UNIWILL_DIG, | ||
4443 | ALC880_FIXUP_Z71V, | ||
4444 | ALC880_FIXUP_3ST_BASE, | ||
4445 | ALC880_FIXUP_3ST, | ||
4446 | ALC880_FIXUP_3ST_DIG, | ||
4447 | ALC880_FIXUP_5ST_BASE, | ||
4448 | ALC880_FIXUP_5ST, | ||
4449 | ALC880_FIXUP_5ST_DIG, | ||
4450 | ALC880_FIXUP_6ST_BASE, | ||
4451 | ALC880_FIXUP_6ST, | ||
4452 | ALC880_FIXUP_6ST_DIG, | ||
4087 | }; | 4453 | }; |
4088 | 4454 | ||
4455 | /* enable the volume-knob widget support on NID 0x21 */ | ||
4456 | static void alc880_fixup_vol_knob(struct hda_codec *codec, | ||
4457 | const struct alc_fixup *fix, int action) | ||
4458 | { | ||
4459 | if (action == ALC_FIXUP_ACT_PROBE) | ||
4460 | snd_hda_jack_detect_enable(codec, 0x21, ALC_DCVOL_EVENT); | ||
4461 | } | ||
4462 | |||
4089 | static const struct alc_fixup alc880_fixups[] = { | 4463 | static const struct alc_fixup alc880_fixups[] = { |
4464 | [ALC880_FIXUP_GPIO1] = { | ||
4465 | .type = ALC_FIXUP_VERBS, | ||
4466 | .v.verbs = alc_gpio1_init_verbs, | ||
4467 | }, | ||
4090 | [ALC880_FIXUP_GPIO2] = { | 4468 | [ALC880_FIXUP_GPIO2] = { |
4091 | .type = ALC_FIXUP_VERBS, | 4469 | .type = ALC_FIXUP_VERBS, |
4092 | .v.verbs = alc_gpio2_init_verbs, | 4470 | .v.verbs = alc_gpio2_init_verbs, |
@@ -4101,40 +4479,323 @@ static const struct alc_fixup alc880_fixups[] = { | |||
4101 | .chained = true, | 4479 | .chained = true, |
4102 | .chain_id = ALC880_FIXUP_GPIO2, | 4480 | .chain_id = ALC880_FIXUP_GPIO2, |
4103 | }, | 4481 | }, |
4482 | [ALC880_FIXUP_LG] = { | ||
4483 | .type = ALC_FIXUP_PINS, | ||
4484 | .v.pins = (const struct alc_pincfg[]) { | ||
4485 | /* disable bogus unused pins */ | ||
4486 | { 0x16, 0x411111f0 }, | ||
4487 | { 0x18, 0x411111f0 }, | ||
4488 | { 0x1a, 0x411111f0 }, | ||
4489 | { } | ||
4490 | } | ||
4491 | }, | ||
4492 | [ALC880_FIXUP_W810] = { | ||
4493 | .type = ALC_FIXUP_PINS, | ||
4494 | .v.pins = (const struct alc_pincfg[]) { | ||
4495 | /* disable bogus unused pins */ | ||
4496 | { 0x17, 0x411111f0 }, | ||
4497 | { } | ||
4498 | }, | ||
4499 | .chained = true, | ||
4500 | .chain_id = ALC880_FIXUP_GPIO2, | ||
4501 | }, | ||
4502 | [ALC880_FIXUP_EAPD_COEF] = { | ||
4503 | .type = ALC_FIXUP_VERBS, | ||
4504 | .v.verbs = (const struct hda_verb[]) { | ||
4505 | /* change to EAPD mode */ | ||
4506 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, | ||
4507 | { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 }, | ||
4508 | {} | ||
4509 | }, | ||
4510 | }, | ||
4511 | [ALC880_FIXUP_TCL_S700] = { | ||
4512 | .type = ALC_FIXUP_VERBS, | ||
4513 | .v.verbs = (const struct hda_verb[]) { | ||
4514 | /* change to EAPD mode */ | ||
4515 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, | ||
4516 | { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 }, | ||
4517 | {} | ||
4518 | }, | ||
4519 | .chained = true, | ||
4520 | .chain_id = ALC880_FIXUP_GPIO2, | ||
4521 | }, | ||
4522 | [ALC880_FIXUP_VOL_KNOB] = { | ||
4523 | .type = ALC_FIXUP_FUNC, | ||
4524 | .v.func = alc880_fixup_vol_knob, | ||
4525 | }, | ||
4526 | [ALC880_FIXUP_FUJITSU] = { | ||
4527 | /* override all pins as BIOS on old Amilo is broken */ | ||
4528 | .type = ALC_FIXUP_PINS, | ||
4529 | .v.pins = (const struct alc_pincfg[]) { | ||
4530 | { 0x14, 0x0121411f }, /* HP */ | ||
4531 | { 0x15, 0x99030120 }, /* speaker */ | ||
4532 | { 0x16, 0x99030130 }, /* bass speaker */ | ||
4533 | { 0x17, 0x411111f0 }, /* N/A */ | ||
4534 | { 0x18, 0x411111f0 }, /* N/A */ | ||
4535 | { 0x19, 0x01a19950 }, /* mic-in */ | ||
4536 | { 0x1a, 0x411111f0 }, /* N/A */ | ||
4537 | { 0x1b, 0x411111f0 }, /* N/A */ | ||
4538 | { 0x1c, 0x411111f0 }, /* N/A */ | ||
4539 | { 0x1d, 0x411111f0 }, /* N/A */ | ||
4540 | { 0x1e, 0x01454140 }, /* SPDIF out */ | ||
4541 | { } | ||
4542 | }, | ||
4543 | .chained = true, | ||
4544 | .chain_id = ALC880_FIXUP_VOL_KNOB, | ||
4545 | }, | ||
4546 | [ALC880_FIXUP_F1734] = { | ||
4547 | /* almost compatible with FUJITSU, but no bass and SPDIF */ | ||
4548 | .type = ALC_FIXUP_PINS, | ||
4549 | .v.pins = (const struct alc_pincfg[]) { | ||
4550 | { 0x14, 0x0121411f }, /* HP */ | ||
4551 | { 0x15, 0x99030120 }, /* speaker */ | ||
4552 | { 0x16, 0x411111f0 }, /* N/A */ | ||
4553 | { 0x17, 0x411111f0 }, /* N/A */ | ||
4554 | { 0x18, 0x411111f0 }, /* N/A */ | ||
4555 | { 0x19, 0x01a19950 }, /* mic-in */ | ||
4556 | { 0x1a, 0x411111f0 }, /* N/A */ | ||
4557 | { 0x1b, 0x411111f0 }, /* N/A */ | ||
4558 | { 0x1c, 0x411111f0 }, /* N/A */ | ||
4559 | { 0x1d, 0x411111f0 }, /* N/A */ | ||
4560 | { 0x1e, 0x411111f0 }, /* N/A */ | ||
4561 | { } | ||
4562 | }, | ||
4563 | .chained = true, | ||
4564 | .chain_id = ALC880_FIXUP_VOL_KNOB, | ||
4565 | }, | ||
4566 | [ALC880_FIXUP_UNIWILL] = { | ||
4567 | /* need to fix HP and speaker pins to be parsed correctly */ | ||
4568 | .type = ALC_FIXUP_PINS, | ||
4569 | .v.pins = (const struct alc_pincfg[]) { | ||
4570 | { 0x14, 0x0121411f }, /* HP */ | ||
4571 | { 0x15, 0x99030120 }, /* speaker */ | ||
4572 | { 0x16, 0x99030130 }, /* bass speaker */ | ||
4573 | { } | ||
4574 | }, | ||
4575 | }, | ||
4576 | [ALC880_FIXUP_UNIWILL_DIG] = { | ||
4577 | .type = ALC_FIXUP_PINS, | ||
4578 | .v.pins = (const struct alc_pincfg[]) { | ||
4579 | /* disable bogus unused pins */ | ||
4580 | { 0x17, 0x411111f0 }, | ||
4581 | { 0x19, 0x411111f0 }, | ||
4582 | { 0x1b, 0x411111f0 }, | ||
4583 | { 0x1f, 0x411111f0 }, | ||
4584 | { } | ||
4585 | } | ||
4586 | }, | ||
4587 | [ALC880_FIXUP_Z71V] = { | ||
4588 | .type = ALC_FIXUP_PINS, | ||
4589 | .v.pins = (const struct alc_pincfg[]) { | ||
4590 | /* set up the whole pins as BIOS is utterly broken */ | ||
4591 | { 0x14, 0x99030120 }, /* speaker */ | ||
4592 | { 0x15, 0x0121411f }, /* HP */ | ||
4593 | { 0x16, 0x411111f0 }, /* N/A */ | ||
4594 | { 0x17, 0x411111f0 }, /* N/A */ | ||
4595 | { 0x18, 0x01a19950 }, /* mic-in */ | ||
4596 | { 0x19, 0x411111f0 }, /* N/A */ | ||
4597 | { 0x1a, 0x01813031 }, /* line-in */ | ||
4598 | { 0x1b, 0x411111f0 }, /* N/A */ | ||
4599 | { 0x1c, 0x411111f0 }, /* N/A */ | ||
4600 | { 0x1d, 0x411111f0 }, /* N/A */ | ||
4601 | { 0x1e, 0x0144111e }, /* SPDIF */ | ||
4602 | { } | ||
4603 | } | ||
4604 | }, | ||
4605 | [ALC880_FIXUP_3ST_BASE] = { | ||
4606 | .type = ALC_FIXUP_PINS, | ||
4607 | .v.pins = (const struct alc_pincfg[]) { | ||
4608 | { 0x14, 0x01014010 }, /* line-out */ | ||
4609 | { 0x15, 0x411111f0 }, /* N/A */ | ||
4610 | { 0x16, 0x411111f0 }, /* N/A */ | ||
4611 | { 0x17, 0x411111f0 }, /* N/A */ | ||
4612 | { 0x18, 0x01a19c30 }, /* mic-in */ | ||
4613 | { 0x19, 0x0121411f }, /* HP */ | ||
4614 | { 0x1a, 0x01813031 }, /* line-in */ | ||
4615 | { 0x1b, 0x02a19c40 }, /* front-mic */ | ||
4616 | { 0x1c, 0x411111f0 }, /* N/A */ | ||
4617 | { 0x1d, 0x411111f0 }, /* N/A */ | ||
4618 | /* 0x1e is filled in below */ | ||
4619 | { 0x1f, 0x411111f0 }, /* N/A */ | ||
4620 | { } | ||
4621 | } | ||
4622 | }, | ||
4623 | [ALC880_FIXUP_3ST] = { | ||
4624 | .type = ALC_FIXUP_PINS, | ||
4625 | .v.pins = (const struct alc_pincfg[]) { | ||
4626 | { 0x1e, 0x411111f0 }, /* N/A */ | ||
4627 | { } | ||
4628 | }, | ||
4629 | .chained = true, | ||
4630 | .chain_id = ALC880_FIXUP_3ST_BASE, | ||
4631 | }, | ||
4632 | [ALC880_FIXUP_3ST_DIG] = { | ||
4633 | .type = ALC_FIXUP_PINS, | ||
4634 | .v.pins = (const struct alc_pincfg[]) { | ||
4635 | { 0x1e, 0x0144111e }, /* SPDIF */ | ||
4636 | { } | ||
4637 | }, | ||
4638 | .chained = true, | ||
4639 | .chain_id = ALC880_FIXUP_3ST_BASE, | ||
4640 | }, | ||
4641 | [ALC880_FIXUP_5ST_BASE] = { | ||
4642 | .type = ALC_FIXUP_PINS, | ||
4643 | .v.pins = (const struct alc_pincfg[]) { | ||
4644 | { 0x14, 0x01014010 }, /* front */ | ||
4645 | { 0x15, 0x411111f0 }, /* N/A */ | ||
4646 | { 0x16, 0x01011411 }, /* CLFE */ | ||
4647 | { 0x17, 0x01016412 }, /* surr */ | ||
4648 | { 0x18, 0x01a19c30 }, /* mic-in */ | ||
4649 | { 0x19, 0x0121411f }, /* HP */ | ||
4650 | { 0x1a, 0x01813031 }, /* line-in */ | ||
4651 | { 0x1b, 0x02a19c40 }, /* front-mic */ | ||
4652 | { 0x1c, 0x411111f0 }, /* N/A */ | ||
4653 | { 0x1d, 0x411111f0 }, /* N/A */ | ||
4654 | /* 0x1e is filled in below */ | ||
4655 | { 0x1f, 0x411111f0 }, /* N/A */ | ||
4656 | { } | ||
4657 | } | ||
4658 | }, | ||
4659 | [ALC880_FIXUP_5ST] = { | ||
4660 | .type = ALC_FIXUP_PINS, | ||
4661 | .v.pins = (const struct alc_pincfg[]) { | ||
4662 | { 0x1e, 0x411111f0 }, /* N/A */ | ||
4663 | { } | ||
4664 | }, | ||
4665 | .chained = true, | ||
4666 | .chain_id = ALC880_FIXUP_5ST_BASE, | ||
4667 | }, | ||
4668 | [ALC880_FIXUP_5ST_DIG] = { | ||
4669 | .type = ALC_FIXUP_PINS, | ||
4670 | .v.pins = (const struct alc_pincfg[]) { | ||
4671 | { 0x1e, 0x0144111e }, /* SPDIF */ | ||
4672 | { } | ||
4673 | }, | ||
4674 | .chained = true, | ||
4675 | .chain_id = ALC880_FIXUP_5ST_BASE, | ||
4676 | }, | ||
4677 | [ALC880_FIXUP_6ST_BASE] = { | ||
4678 | .type = ALC_FIXUP_PINS, | ||
4679 | .v.pins = (const struct alc_pincfg[]) { | ||
4680 | { 0x14, 0x01014010 }, /* front */ | ||
4681 | { 0x15, 0x01016412 }, /* surr */ | ||
4682 | { 0x16, 0x01011411 }, /* CLFE */ | ||
4683 | { 0x17, 0x01012414 }, /* side */ | ||
4684 | { 0x18, 0x01a19c30 }, /* mic-in */ | ||
4685 | { 0x19, 0x02a19c40 }, /* front-mic */ | ||
4686 | { 0x1a, 0x01813031 }, /* line-in */ | ||
4687 | { 0x1b, 0x0121411f }, /* HP */ | ||
4688 | { 0x1c, 0x411111f0 }, /* N/A */ | ||
4689 | { 0x1d, 0x411111f0 }, /* N/A */ | ||
4690 | /* 0x1e is filled in below */ | ||
4691 | { 0x1f, 0x411111f0 }, /* N/A */ | ||
4692 | { } | ||
4693 | } | ||
4694 | }, | ||
4695 | [ALC880_FIXUP_6ST] = { | ||
4696 | .type = ALC_FIXUP_PINS, | ||
4697 | .v.pins = (const struct alc_pincfg[]) { | ||
4698 | { 0x1e, 0x411111f0 }, /* N/A */ | ||
4699 | { } | ||
4700 | }, | ||
4701 | .chained = true, | ||
4702 | .chain_id = ALC880_FIXUP_6ST_BASE, | ||
4703 | }, | ||
4704 | [ALC880_FIXUP_6ST_DIG] = { | ||
4705 | .type = ALC_FIXUP_PINS, | ||
4706 | .v.pins = (const struct alc_pincfg[]) { | ||
4707 | { 0x1e, 0x0144111e }, /* SPDIF */ | ||
4708 | { } | ||
4709 | }, | ||
4710 | .chained = true, | ||
4711 | .chain_id = ALC880_FIXUP_6ST_BASE, | ||
4712 | }, | ||
4104 | }; | 4713 | }; |
4105 | 4714 | ||
4106 | static const struct snd_pci_quirk alc880_fixup_tbl[] = { | 4715 | static const struct snd_pci_quirk alc880_fixup_tbl[] = { |
4716 | SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), | ||
4717 | SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V), | ||
4718 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1), | ||
4719 | SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2), | ||
4720 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), | ||
4721 | SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG), | ||
4722 | SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734), | ||
4723 | SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL), | ||
4724 | SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB), | ||
4725 | SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), | ||
4107 | SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), | 4726 | SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), |
4727 | SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734), | ||
4728 | SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU), | ||
4729 | SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734), | ||
4730 | SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU), | ||
4731 | SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG), | ||
4732 | SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG), | ||
4733 | SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG), | ||
4734 | SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700), | ||
4735 | |||
4736 | /* Below is the copied entries from alc880_quirks.c. | ||
4737 | * It's not quite sure whether BIOS sets the correct pin-config table | ||
4738 | * on these machines, thus they are kept to be compatible with | ||
4739 | * the old static quirks. Once when it's confirmed to work without | ||
4740 | * these overrides, it'd be better to remove. | ||
4741 | */ | ||
4742 | SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG), | ||
4743 | SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST), | ||
4744 | SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG), | ||
4745 | SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG), | ||
4746 | SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG), | ||
4747 | SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG), | ||
4748 | SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG), | ||
4749 | SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST), | ||
4750 | SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG), | ||
4751 | SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST), | ||
4752 | SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST), | ||
4753 | SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST), | ||
4754 | SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST), | ||
4755 | SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST), | ||
4756 | SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG), | ||
4757 | SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG), | ||
4758 | SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG), | ||
4759 | SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG), | ||
4760 | SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG), | ||
4761 | SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG), | ||
4762 | SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG), | ||
4763 | SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */ | ||
4764 | SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG), | ||
4765 | SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4766 | SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4767 | SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4768 | SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG), | ||
4769 | SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4770 | SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG), | ||
4771 | SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG), | ||
4772 | SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4773 | SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4774 | SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG), | ||
4775 | /* default Intel */ | ||
4776 | SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST), | ||
4777 | SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG), | ||
4778 | SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG), | ||
4108 | {} | 4779 | {} |
4109 | }; | 4780 | }; |
4110 | 4781 | ||
4782 | static const struct alc_model_fixup alc880_fixup_models[] = { | ||
4783 | {.id = ALC880_FIXUP_3ST, .name = "3stack"}, | ||
4784 | {.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"}, | ||
4785 | {.id = ALC880_FIXUP_5ST, .name = "5stack"}, | ||
4786 | {.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"}, | ||
4787 | {.id = ALC880_FIXUP_6ST, .name = "6stack"}, | ||
4788 | {.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"}, | ||
4789 | {} | ||
4790 | }; | ||
4111 | 4791 | ||
4112 | /* | ||
4113 | * board setups | ||
4114 | */ | ||
4115 | #ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS | ||
4116 | #define alc_board_config \ | ||
4117 | snd_hda_check_board_config | ||
4118 | #define alc_board_codec_sid_config \ | ||
4119 | snd_hda_check_board_codec_sid_config | ||
4120 | #include "alc_quirks.c" | ||
4121 | #else | ||
4122 | #define alc_board_config(codec, nums, models, tbl) -1 | ||
4123 | #define alc_board_codec_sid_config(codec, nums, models, tbl) -1 | ||
4124 | #define setup_preset(codec, x) /* NOP */ | ||
4125 | #endif | ||
4126 | 4792 | ||
4127 | /* | 4793 | /* |
4128 | * OK, here we have finally the patch for ALC880 | 4794 | * OK, here we have finally the patch for ALC880 |
4129 | */ | 4795 | */ |
4130 | #ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS | ||
4131 | #include "alc880_quirks.c" | ||
4132 | #endif | ||
4133 | |||
4134 | static int patch_alc880(struct hda_codec *codec) | 4796 | static int patch_alc880(struct hda_codec *codec) |
4135 | { | 4797 | { |
4136 | struct alc_spec *spec; | 4798 | struct alc_spec *spec; |
4137 | int board_config; | ||
4138 | int err; | 4799 | int err; |
4139 | 4800 | ||
4140 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4801 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
@@ -4146,47 +4807,14 @@ static int patch_alc880(struct hda_codec *codec) | |||
4146 | spec->mixer_nid = 0x0b; | 4807 | spec->mixer_nid = 0x0b; |
4147 | spec->need_dac_fix = 1; | 4808 | spec->need_dac_fix = 1; |
4148 | 4809 | ||
4149 | board_config = alc_board_config(codec, ALC880_MODEL_LAST, | 4810 | alc_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl, |
4150 | alc880_models, alc880_cfg_tbl); | 4811 | alc880_fixups); |
4151 | if (board_config < 0) { | 4812 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); |
4152 | printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | ||
4153 | codec->chip_name); | ||
4154 | board_config = ALC_MODEL_AUTO; | ||
4155 | } | ||
4156 | |||
4157 | if (board_config == ALC_MODEL_AUTO) { | ||
4158 | alc_pick_fixup(codec, NULL, alc880_fixup_tbl, alc880_fixups); | ||
4159 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | ||
4160 | } | ||
4161 | |||
4162 | if (board_config == ALC_MODEL_AUTO) { | ||
4163 | /* automatic parse from the BIOS config */ | ||
4164 | err = alc880_parse_auto_config(codec); | ||
4165 | if (err < 0) | ||
4166 | goto error; | ||
4167 | #ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS | ||
4168 | else if (!err) { | ||
4169 | printk(KERN_INFO | ||
4170 | "hda_codec: Cannot set up configuration " | ||
4171 | "from BIOS. Using 3-stack mode...\n"); | ||
4172 | board_config = ALC880_3ST; | ||
4173 | } | ||
4174 | #endif | ||
4175 | } | ||
4176 | |||
4177 | if (board_config != ALC_MODEL_AUTO) { | ||
4178 | spec->vmaster_nid = 0x0c; | ||
4179 | setup_preset(codec, &alc880_presets[board_config]); | ||
4180 | } | ||
4181 | |||
4182 | if (!spec->no_analog && !spec->adc_nids) { | ||
4183 | alc_auto_fill_adc_caps(codec); | ||
4184 | alc_rebuild_imux_for_auto_mic(codec); | ||
4185 | alc_remove_invalid_adc_nids(codec); | ||
4186 | } | ||
4187 | 4813 | ||
4188 | if (!spec->no_analog && !spec->cap_mixer) | 4814 | /* automatic parse from the BIOS config */ |
4189 | set_capture_mixer(codec); | 4815 | err = alc880_parse_auto_config(codec); |
4816 | if (err < 0) | ||
4817 | goto error; | ||
4190 | 4818 | ||
4191 | if (!spec->no_analog) { | 4819 | if (!spec->no_analog) { |
4192 | err = snd_hda_attach_beep_device(codec, 0x1); | 4820 | err = snd_hda_attach_beep_device(codec, 0x1); |
@@ -4195,17 +4823,9 @@ static int patch_alc880(struct hda_codec *codec) | |||
4195 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 4823 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
4196 | } | 4824 | } |
4197 | 4825 | ||
4198 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
4199 | |||
4200 | codec->patch_ops = alc_patch_ops; | 4826 | codec->patch_ops = alc_patch_ops; |
4201 | if (board_config == ALC_MODEL_AUTO) | 4827 | |
4202 | spec->init_hook = alc_auto_init_std; | 4828 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
4203 | else | ||
4204 | codec->patch_ops.build_controls = __alc_build_controls; | ||
4205 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4206 | if (!spec->loopback.amplist) | ||
4207 | spec->loopback.amplist = alc880_loopbacks; | ||
4208 | #endif | ||
4209 | 4829 | ||
4210 | return 0; | 4830 | return 0; |
4211 | 4831 | ||
@@ -4225,49 +4845,115 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
4225 | return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids); | 4845 | return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids); |
4226 | } | 4846 | } |
4227 | 4847 | ||
4228 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4229 | static const struct hda_amp_list alc260_loopbacks[] = { | ||
4230 | { 0x07, HDA_INPUT, 0 }, | ||
4231 | { 0x07, HDA_INPUT, 1 }, | ||
4232 | { 0x07, HDA_INPUT, 2 }, | ||
4233 | { 0x07, HDA_INPUT, 3 }, | ||
4234 | { 0x07, HDA_INPUT, 4 }, | ||
4235 | { } /* end */ | ||
4236 | }; | ||
4237 | #endif | ||
4238 | |||
4239 | /* | 4848 | /* |
4240 | * Pin config fixes | 4849 | * Pin config fixes |
4241 | */ | 4850 | */ |
4242 | enum { | 4851 | enum { |
4243 | PINFIX_HP_DC5750, | 4852 | ALC260_FIXUP_HP_DC5750, |
4853 | ALC260_FIXUP_HP_PIN_0F, | ||
4854 | ALC260_FIXUP_COEF, | ||
4855 | ALC260_FIXUP_GPIO1, | ||
4856 | ALC260_FIXUP_GPIO1_TOGGLE, | ||
4857 | ALC260_FIXUP_REPLACER, | ||
4858 | ALC260_FIXUP_HP_B1900, | ||
4244 | }; | 4859 | }; |
4245 | 4860 | ||
4861 | static void alc260_gpio1_automute(struct hda_codec *codec) | ||
4862 | { | ||
4863 | struct alc_spec *spec = codec->spec; | ||
4864 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, | ||
4865 | spec->hp_jack_present); | ||
4866 | } | ||
4867 | |||
4868 | static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, | ||
4869 | const struct alc_fixup *fix, int action) | ||
4870 | { | ||
4871 | struct alc_spec *spec = codec->spec; | ||
4872 | if (action == ALC_FIXUP_ACT_PROBE) { | ||
4873 | /* although the machine has only one output pin, we need to | ||
4874 | * toggle GPIO1 according to the jack state | ||
4875 | */ | ||
4876 | spec->automute_hook = alc260_gpio1_automute; | ||
4877 | spec->detect_hp = 1; | ||
4878 | spec->automute_speaker = 1; | ||
4879 | spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ | ||
4880 | snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT); | ||
4881 | spec->unsol_event = alc_sku_unsol_event; | ||
4882 | add_verb(codec->spec, alc_gpio1_init_verbs); | ||
4883 | } | ||
4884 | } | ||
4885 | |||
4246 | static const struct alc_fixup alc260_fixups[] = { | 4886 | static const struct alc_fixup alc260_fixups[] = { |
4247 | [PINFIX_HP_DC5750] = { | 4887 | [ALC260_FIXUP_HP_DC5750] = { |
4248 | .type = ALC_FIXUP_PINS, | 4888 | .type = ALC_FIXUP_PINS, |
4249 | .v.pins = (const struct alc_pincfg[]) { | 4889 | .v.pins = (const struct alc_pincfg[]) { |
4250 | { 0x11, 0x90130110 }, /* speaker */ | 4890 | { 0x11, 0x90130110 }, /* speaker */ |
4251 | { } | 4891 | { } |
4252 | } | 4892 | } |
4253 | }, | 4893 | }, |
4894 | [ALC260_FIXUP_HP_PIN_0F] = { | ||
4895 | .type = ALC_FIXUP_PINS, | ||
4896 | .v.pins = (const struct alc_pincfg[]) { | ||
4897 | { 0x0f, 0x01214000 }, /* HP */ | ||
4898 | { } | ||
4899 | } | ||
4900 | }, | ||
4901 | [ALC260_FIXUP_COEF] = { | ||
4902 | .type = ALC_FIXUP_VERBS, | ||
4903 | .v.verbs = (const struct hda_verb[]) { | ||
4904 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, | ||
4905 | { 0x20, AC_VERB_SET_PROC_COEF, 0x3040 }, | ||
4906 | { } | ||
4907 | }, | ||
4908 | .chained = true, | ||
4909 | .chain_id = ALC260_FIXUP_HP_PIN_0F, | ||
4910 | }, | ||
4911 | [ALC260_FIXUP_GPIO1] = { | ||
4912 | .type = ALC_FIXUP_VERBS, | ||
4913 | .v.verbs = alc_gpio1_init_verbs, | ||
4914 | }, | ||
4915 | [ALC260_FIXUP_GPIO1_TOGGLE] = { | ||
4916 | .type = ALC_FIXUP_FUNC, | ||
4917 | .v.func = alc260_fixup_gpio1_toggle, | ||
4918 | .chained = true, | ||
4919 | .chain_id = ALC260_FIXUP_HP_PIN_0F, | ||
4920 | }, | ||
4921 | [ALC260_FIXUP_REPLACER] = { | ||
4922 | .type = ALC_FIXUP_VERBS, | ||
4923 | .v.verbs = (const struct hda_verb[]) { | ||
4924 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, | ||
4925 | { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 }, | ||
4926 | { } | ||
4927 | }, | ||
4928 | .chained = true, | ||
4929 | .chain_id = ALC260_FIXUP_GPIO1_TOGGLE, | ||
4930 | }, | ||
4931 | [ALC260_FIXUP_HP_B1900] = { | ||
4932 | .type = ALC_FIXUP_FUNC, | ||
4933 | .v.func = alc260_fixup_gpio1_toggle, | ||
4934 | .chained = true, | ||
4935 | .chain_id = ALC260_FIXUP_COEF, | ||
4936 | } | ||
4254 | }; | 4937 | }; |
4255 | 4938 | ||
4256 | static const struct snd_pci_quirk alc260_fixup_tbl[] = { | 4939 | static const struct snd_pci_quirk alc260_fixup_tbl[] = { |
4257 | SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750), | 4940 | SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1), |
4941 | SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF), | ||
4942 | SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1), | ||
4943 | SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750), | ||
4944 | SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900), | ||
4945 | SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1), | ||
4946 | SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER), | ||
4947 | SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF), | ||
4258 | {} | 4948 | {} |
4259 | }; | 4949 | }; |
4260 | 4950 | ||
4261 | /* | 4951 | /* |
4262 | */ | 4952 | */ |
4263 | #ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS | ||
4264 | #include "alc260_quirks.c" | ||
4265 | #endif | ||
4266 | |||
4267 | static int patch_alc260(struct hda_codec *codec) | 4953 | static int patch_alc260(struct hda_codec *codec) |
4268 | { | 4954 | { |
4269 | struct alc_spec *spec; | 4955 | struct alc_spec *spec; |
4270 | int err, board_config; | 4956 | int err; |
4271 | 4957 | ||
4272 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4958 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
4273 | if (spec == NULL) | 4959 | if (spec == NULL) |
@@ -4277,47 +4963,13 @@ static int patch_alc260(struct hda_codec *codec) | |||
4277 | 4963 | ||
4278 | spec->mixer_nid = 0x07; | 4964 | spec->mixer_nid = 0x07; |
4279 | 4965 | ||
4280 | board_config = alc_board_config(codec, ALC260_MODEL_LAST, | 4966 | alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups); |
4281 | alc260_models, alc260_cfg_tbl); | 4967 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); |
4282 | if (board_config < 0) { | ||
4283 | snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | ||
4284 | codec->chip_name); | ||
4285 | board_config = ALC_MODEL_AUTO; | ||
4286 | } | ||
4287 | |||
4288 | if (board_config == ALC_MODEL_AUTO) { | ||
4289 | alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups); | ||
4290 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | ||
4291 | } | ||
4292 | |||
4293 | if (board_config == ALC_MODEL_AUTO) { | ||
4294 | /* automatic parse from the BIOS config */ | ||
4295 | err = alc260_parse_auto_config(codec); | ||
4296 | if (err < 0) | ||
4297 | goto error; | ||
4298 | #ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS | ||
4299 | else if (!err) { | ||
4300 | printk(KERN_INFO | ||
4301 | "hda_codec: Cannot set up configuration " | ||
4302 | "from BIOS. Using base mode...\n"); | ||
4303 | board_config = ALC260_BASIC; | ||
4304 | } | ||
4305 | #endif | ||
4306 | } | ||
4307 | |||
4308 | if (board_config != ALC_MODEL_AUTO) { | ||
4309 | setup_preset(codec, &alc260_presets[board_config]); | ||
4310 | spec->vmaster_nid = 0x08; | ||
4311 | } | ||
4312 | |||
4313 | if (!spec->no_analog && !spec->adc_nids) { | ||
4314 | alc_auto_fill_adc_caps(codec); | ||
4315 | alc_rebuild_imux_for_auto_mic(codec); | ||
4316 | alc_remove_invalid_adc_nids(codec); | ||
4317 | } | ||
4318 | 4968 | ||
4319 | if (!spec->no_analog && !spec->cap_mixer) | 4969 | /* automatic parse from the BIOS config */ |
4320 | set_capture_mixer(codec); | 4970 | err = alc260_parse_auto_config(codec); |
4971 | if (err < 0) | ||
4972 | goto error; | ||
4321 | 4973 | ||
4322 | if (!spec->no_analog) { | 4974 | if (!spec->no_analog) { |
4323 | err = snd_hda_attach_beep_device(codec, 0x1); | 4975 | err = snd_hda_attach_beep_device(codec, 0x1); |
@@ -4326,18 +4978,10 @@ static int patch_alc260(struct hda_codec *codec) | |||
4326 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); | 4978 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); |
4327 | } | 4979 | } |
4328 | 4980 | ||
4329 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
4330 | |||
4331 | codec->patch_ops = alc_patch_ops; | 4981 | codec->patch_ops = alc_patch_ops; |
4332 | if (board_config == ALC_MODEL_AUTO) | ||
4333 | spec->init_hook = alc_auto_init_std; | ||
4334 | else | ||
4335 | codec->patch_ops.build_controls = __alc_build_controls; | ||
4336 | spec->shutup = alc_eapd_shutup; | 4982 | spec->shutup = alc_eapd_shutup; |
4337 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4983 | |
4338 | if (!spec->loopback.amplist) | 4984 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
4339 | spec->loopback.amplist = alc260_loopbacks; | ||
4340 | #endif | ||
4341 | 4985 | ||
4342 | return 0; | 4986 | return 0; |
4343 | 4987 | ||
@@ -4358,9 +5002,6 @@ static int patch_alc260(struct hda_codec *codec) | |||
4358 | * In addition, an independent DAC for the multi-playback (not used in this | 5002 | * In addition, an independent DAC for the multi-playback (not used in this |
4359 | * driver yet). | 5003 | * driver yet). |
4360 | */ | 5004 | */ |
4361 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4362 | #define alc882_loopbacks alc880_loopbacks | ||
4363 | #endif | ||
4364 | 5005 | ||
4365 | /* | 5006 | /* |
4366 | * Pin config fixes | 5007 | * Pin config fixes |
@@ -4377,6 +5018,8 @@ enum { | |||
4377 | ALC882_FIXUP_EAPD, | 5018 | ALC882_FIXUP_EAPD, |
4378 | ALC883_FIXUP_EAPD, | 5019 | ALC883_FIXUP_EAPD, |
4379 | ALC883_FIXUP_ACER_EAPD, | 5020 | ALC883_FIXUP_ACER_EAPD, |
5021 | ALC882_FIXUP_GPIO1, | ||
5022 | ALC882_FIXUP_GPIO2, | ||
4380 | ALC882_FIXUP_GPIO3, | 5023 | ALC882_FIXUP_GPIO3, |
4381 | ALC889_FIXUP_COEF, | 5024 | ALC889_FIXUP_COEF, |
4382 | ALC882_FIXUP_ASUS_W2JC, | 5025 | ALC882_FIXUP_ASUS_W2JC, |
@@ -4385,6 +5028,8 @@ enum { | |||
4385 | ALC882_FIXUP_ASPIRE_8930G_VERBS, | 5028 | ALC882_FIXUP_ASPIRE_8930G_VERBS, |
4386 | ALC885_FIXUP_MACPRO_GPIO, | 5029 | ALC885_FIXUP_MACPRO_GPIO, |
4387 | ALC889_FIXUP_DAC_ROUTE, | 5030 | ALC889_FIXUP_DAC_ROUTE, |
5031 | ALC889_FIXUP_MBP_VREF, | ||
5032 | ALC889_FIXUP_IMAC91_VREF, | ||
4388 | }; | 5033 | }; |
4389 | 5034 | ||
4390 | static void alc889_fixup_coef(struct hda_codec *codec, | 5035 | static void alc889_fixup_coef(struct hda_codec *codec, |
@@ -4463,6 +5108,51 @@ static void alc889_fixup_dac_route(struct hda_codec *codec, | |||
4463 | } | 5108 | } |
4464 | } | 5109 | } |
4465 | 5110 | ||
5111 | /* Set VREF on HP pin */ | ||
5112 | static void alc889_fixup_mbp_vref(struct hda_codec *codec, | ||
5113 | const struct alc_fixup *fix, int action) | ||
5114 | { | ||
5115 | struct alc_spec *spec = codec->spec; | ||
5116 | static hda_nid_t nids[2] = { 0x14, 0x15 }; | ||
5117 | int i; | ||
5118 | |||
5119 | if (action != ALC_FIXUP_ACT_INIT) | ||
5120 | return; | ||
5121 | for (i = 0; i < ARRAY_SIZE(nids); i++) { | ||
5122 | unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]); | ||
5123 | if (get_defcfg_device(val) != AC_JACK_HP_OUT) | ||
5124 | continue; | ||
5125 | val = snd_hda_codec_read(codec, nids[i], 0, | ||
5126 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
5127 | val |= AC_PINCTL_VREF_80; | ||
5128 | snd_hda_codec_write(codec, nids[i], 0, | ||
5129 | AC_VERB_SET_PIN_WIDGET_CONTROL, val); | ||
5130 | spec->keep_vref_in_automute = 1; | ||
5131 | break; | ||
5132 | } | ||
5133 | } | ||
5134 | |||
5135 | /* Set VREF on speaker pins on imac91 */ | ||
5136 | static void alc889_fixup_imac91_vref(struct hda_codec *codec, | ||
5137 | const struct alc_fixup *fix, int action) | ||
5138 | { | ||
5139 | struct alc_spec *spec = codec->spec; | ||
5140 | static hda_nid_t nids[2] = { 0x18, 0x1a }; | ||
5141 | int i; | ||
5142 | |||
5143 | if (action != ALC_FIXUP_ACT_INIT) | ||
5144 | return; | ||
5145 | for (i = 0; i < ARRAY_SIZE(nids); i++) { | ||
5146 | unsigned int val; | ||
5147 | val = snd_hda_codec_read(codec, nids[i], 0, | ||
5148 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
5149 | val |= AC_PINCTL_VREF_50; | ||
5150 | snd_hda_codec_write(codec, nids[i], 0, | ||
5151 | AC_VERB_SET_PIN_WIDGET_CONTROL, val); | ||
5152 | } | ||
5153 | spec->keep_vref_in_automute = 1; | ||
5154 | } | ||
5155 | |||
4466 | static const struct alc_fixup alc882_fixups[] = { | 5156 | static const struct alc_fixup alc882_fixups[] = { |
4467 | [ALC882_FIXUP_ABIT_AW9D_MAX] = { | 5157 | [ALC882_FIXUP_ABIT_AW9D_MAX] = { |
4468 | .type = ALC_FIXUP_PINS, | 5158 | .type = ALC_FIXUP_PINS, |
@@ -4548,6 +5238,14 @@ static const struct alc_fixup alc882_fixups[] = { | |||
4548 | { } | 5238 | { } |
4549 | } | 5239 | } |
4550 | }, | 5240 | }, |
5241 | [ALC882_FIXUP_GPIO1] = { | ||
5242 | .type = ALC_FIXUP_VERBS, | ||
5243 | .v.verbs = alc_gpio1_init_verbs, | ||
5244 | }, | ||
5245 | [ALC882_FIXUP_GPIO2] = { | ||
5246 | .type = ALC_FIXUP_VERBS, | ||
5247 | .v.verbs = alc_gpio2_init_verbs, | ||
5248 | }, | ||
4551 | [ALC882_FIXUP_GPIO3] = { | 5249 | [ALC882_FIXUP_GPIO3] = { |
4552 | .type = ALC_FIXUP_VERBS, | 5250 | .type = ALC_FIXUP_VERBS, |
4553 | .v.verbs = alc_gpio3_init_verbs, | 5251 | .v.verbs = alc_gpio3_init_verbs, |
@@ -4621,6 +5319,18 @@ static const struct alc_fixup alc882_fixups[] = { | |||
4621 | .type = ALC_FIXUP_FUNC, | 5319 | .type = ALC_FIXUP_FUNC, |
4622 | .v.func = alc889_fixup_dac_route, | 5320 | .v.func = alc889_fixup_dac_route, |
4623 | }, | 5321 | }, |
5322 | [ALC889_FIXUP_MBP_VREF] = { | ||
5323 | .type = ALC_FIXUP_FUNC, | ||
5324 | .v.func = alc889_fixup_mbp_vref, | ||
5325 | .chained = true, | ||
5326 | .chain_id = ALC882_FIXUP_GPIO1, | ||
5327 | }, | ||
5328 | [ALC889_FIXUP_IMAC91_VREF] = { | ||
5329 | .type = ALC_FIXUP_FUNC, | ||
5330 | .v.func = alc889_fixup_imac91_vref, | ||
5331 | .chained = true, | ||
5332 | .chain_id = ALC882_FIXUP_GPIO1, | ||
5333 | }, | ||
4624 | }; | 5334 | }; |
4625 | 5335 | ||
4626 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { | 5336 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { |
@@ -4654,11 +5364,26 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { | |||
4654 | SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), | 5364 | SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), |
4655 | 5365 | ||
4656 | /* All Apple entries are in codec SSIDs */ | 5366 | /* All Apple entries are in codec SSIDs */ |
5367 | SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF), | ||
5368 | SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF), | ||
5369 | SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF), | ||
4657 | SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO), | 5370 | SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO), |
4658 | SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO), | 5371 | SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO), |
4659 | SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO), | 5372 | SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO), |
5373 | SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF), | ||
5374 | SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF), | ||
4660 | SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD), | 5375 | SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD), |
5376 | SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF), | ||
5377 | SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBP_VREF), | ||
5378 | SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF), | ||
5379 | SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF), | ||
4661 | SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO), | 5380 | SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO), |
5381 | SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF), | ||
5382 | SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF), | ||
5383 | SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF), | ||
5384 | SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF), | ||
5385 | SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF), | ||
5386 | SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF), | ||
4662 | 5387 | ||
4663 | SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), | 5388 | SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), |
4664 | SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), | 5389 | SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), |
@@ -4684,14 +5409,10 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
4684 | 5409 | ||
4685 | /* | 5410 | /* |
4686 | */ | 5411 | */ |
4687 | #ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS | ||
4688 | #include "alc882_quirks.c" | ||
4689 | #endif | ||
4690 | |||
4691 | static int patch_alc882(struct hda_codec *codec) | 5412 | static int patch_alc882(struct hda_codec *codec) |
4692 | { | 5413 | { |
4693 | struct alc_spec *spec; | 5414 | struct alc_spec *spec; |
4694 | int err, board_config; | 5415 | int err; |
4695 | 5416 | ||
4696 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 5417 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
4697 | if (spec == NULL) | 5418 | if (spec == NULL) |
@@ -4715,45 +5436,15 @@ static int patch_alc882(struct hda_codec *codec) | |||
4715 | if (err < 0) | 5436 | if (err < 0) |
4716 | goto error; | 5437 | goto error; |
4717 | 5438 | ||
4718 | board_config = alc_board_config(codec, ALC882_MODEL_LAST, | 5439 | alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups); |
4719 | alc882_models, NULL); | 5440 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); |
4720 | if (board_config < 0) | ||
4721 | board_config = alc_board_codec_sid_config(codec, | ||
4722 | ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl); | ||
4723 | |||
4724 | if (board_config < 0) { | ||
4725 | printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | ||
4726 | codec->chip_name); | ||
4727 | board_config = ALC_MODEL_AUTO; | ||
4728 | } | ||
4729 | |||
4730 | if (board_config == ALC_MODEL_AUTO) { | ||
4731 | alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups); | ||
4732 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | ||
4733 | } | ||
4734 | 5441 | ||
4735 | alc_auto_parse_customize_define(codec); | 5442 | alc_auto_parse_customize_define(codec); |
4736 | 5443 | ||
4737 | if (board_config == ALC_MODEL_AUTO) { | 5444 | /* automatic parse from the BIOS config */ |
4738 | /* automatic parse from the BIOS config */ | 5445 | err = alc882_parse_auto_config(codec); |
4739 | err = alc882_parse_auto_config(codec); | 5446 | if (err < 0) |
4740 | if (err < 0) | 5447 | goto error; |
4741 | goto error; | ||
4742 | } | ||
4743 | |||
4744 | if (board_config != ALC_MODEL_AUTO) { | ||
4745 | setup_preset(codec, &alc882_presets[board_config]); | ||
4746 | spec->vmaster_nid = 0x0c; | ||
4747 | } | ||
4748 | |||
4749 | if (!spec->no_analog && !spec->adc_nids) { | ||
4750 | alc_auto_fill_adc_caps(codec); | ||
4751 | alc_rebuild_imux_for_auto_mic(codec); | ||
4752 | alc_remove_invalid_adc_nids(codec); | ||
4753 | } | ||
4754 | |||
4755 | if (!spec->no_analog && !spec->cap_mixer) | ||
4756 | set_capture_mixer(codec); | ||
4757 | 5448 | ||
4758 | if (!spec->no_analog && has_cdefine_beep(codec)) { | 5449 | if (!spec->no_analog && has_cdefine_beep(codec)) { |
4759 | err = snd_hda_attach_beep_device(codec, 0x1); | 5450 | err = snd_hda_attach_beep_device(codec, 0x1); |
@@ -4762,18 +5453,9 @@ static int patch_alc882(struct hda_codec *codec) | |||
4762 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 5453 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
4763 | } | 5454 | } |
4764 | 5455 | ||
4765 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
4766 | |||
4767 | codec->patch_ops = alc_patch_ops; | 5456 | codec->patch_ops = alc_patch_ops; |
4768 | if (board_config == ALC_MODEL_AUTO) | ||
4769 | spec->init_hook = alc_auto_init_std; | ||
4770 | else | ||
4771 | codec->patch_ops.build_controls = __alc_build_controls; | ||
4772 | 5457 | ||
4773 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5458 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
4774 | if (!spec->loopback.amplist) | ||
4775 | spec->loopback.amplist = alc882_loopbacks; | ||
4776 | #endif | ||
4777 | 5459 | ||
4778 | return 0; | 5460 | return 0; |
4779 | 5461 | ||
@@ -4869,10 +5551,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = { | |||
4869 | }; | 5551 | }; |
4870 | 5552 | ||
4871 | 5553 | ||
4872 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4873 | #define alc262_loopbacks alc880_loopbacks | ||
4874 | #endif | ||
4875 | |||
4876 | /* | 5554 | /* |
4877 | */ | 5555 | */ |
4878 | static int patch_alc262(struct hda_codec *codec) | 5556 | static int patch_alc262(struct hda_codec *codec) |
@@ -4912,15 +5590,6 @@ static int patch_alc262(struct hda_codec *codec) | |||
4912 | if (err < 0) | 5590 | if (err < 0) |
4913 | goto error; | 5591 | goto error; |
4914 | 5592 | ||
4915 | if (!spec->no_analog && !spec->adc_nids) { | ||
4916 | alc_auto_fill_adc_caps(codec); | ||
4917 | alc_rebuild_imux_for_auto_mic(codec); | ||
4918 | alc_remove_invalid_adc_nids(codec); | ||
4919 | } | ||
4920 | |||
4921 | if (!spec->no_analog && !spec->cap_mixer) | ||
4922 | set_capture_mixer(codec); | ||
4923 | |||
4924 | if (!spec->no_analog && has_cdefine_beep(codec)) { | 5593 | if (!spec->no_analog && has_cdefine_beep(codec)) { |
4925 | err = snd_hda_attach_beep_device(codec, 0x1); | 5594 | err = snd_hda_attach_beep_device(codec, 0x1); |
4926 | if (err < 0) | 5595 | if (err < 0) |
@@ -4928,16 +5597,10 @@ static int patch_alc262(struct hda_codec *codec) | |||
4928 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 5597 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
4929 | } | 5598 | } |
4930 | 5599 | ||
4931 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
4932 | |||
4933 | codec->patch_ops = alc_patch_ops; | 5600 | codec->patch_ops = alc_patch_ops; |
4934 | spec->init_hook = alc_auto_init_std; | ||
4935 | spec->shutup = alc_eapd_shutup; | 5601 | spec->shutup = alc_eapd_shutup; |
4936 | 5602 | ||
4937 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5603 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
4938 | if (!spec->loopback.amplist) | ||
4939 | spec->loopback.amplist = alc262_loopbacks; | ||
4940 | #endif | ||
4941 | 5604 | ||
4942 | return 0; | 5605 | return 0; |
4943 | 5606 | ||
@@ -5031,17 +5694,7 @@ static int patch_alc268(struct hda_codec *codec) | |||
5031 | (0 << AC_AMPCAP_MUTE_SHIFT)); | 5694 | (0 << AC_AMPCAP_MUTE_SHIFT)); |
5032 | } | 5695 | } |
5033 | 5696 | ||
5034 | if (!spec->no_analog && !spec->adc_nids) { | ||
5035 | alc_auto_fill_adc_caps(codec); | ||
5036 | alc_rebuild_imux_for_auto_mic(codec); | ||
5037 | alc_remove_invalid_adc_nids(codec); | ||
5038 | } | ||
5039 | |||
5040 | if (!spec->no_analog && !spec->cap_mixer) | ||
5041 | set_capture_mixer(codec); | ||
5042 | |||
5043 | codec->patch_ops = alc_patch_ops; | 5697 | codec->patch_ops = alc_patch_ops; |
5044 | spec->init_hook = alc_auto_init_std; | ||
5045 | spec->shutup = alc_eapd_shutup; | 5698 | spec->shutup = alc_eapd_shutup; |
5046 | 5699 | ||
5047 | return 0; | 5700 | return 0; |
@@ -5054,10 +5707,6 @@ static int patch_alc268(struct hda_codec *codec) | |||
5054 | /* | 5707 | /* |
5055 | * ALC269 | 5708 | * ALC269 |
5056 | */ | 5709 | */ |
5057 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5058 | #define alc269_loopbacks alc880_loopbacks | ||
5059 | #endif | ||
5060 | |||
5061 | static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = { | 5710 | static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = { |
5062 | .substreams = 1, | 5711 | .substreams = 1, |
5063 | .channels_min = 2, | 5712 | .channels_min = 2, |
@@ -5079,35 +5728,6 @@ static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = { | |||
5079 | /* NID is set in alc_build_pcms */ | 5728 | /* NID is set in alc_build_pcms */ |
5080 | }; | 5729 | }; |
5081 | 5730 | ||
5082 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5083 | static int alc269_mic2_for_mute_led(struct hda_codec *codec) | ||
5084 | { | ||
5085 | switch (codec->subsystem_id) { | ||
5086 | case 0x103c1586: | ||
5087 | return 1; | ||
5088 | } | ||
5089 | return 0; | ||
5090 | } | ||
5091 | |||
5092 | static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid) | ||
5093 | { | ||
5094 | /* update mute-LED according to the speaker mute state */ | ||
5095 | if (nid == 0x01 || nid == 0x14) { | ||
5096 | int pinval; | ||
5097 | if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) & | ||
5098 | HDA_AMP_MUTE) | ||
5099 | pinval = 0x24; | ||
5100 | else | ||
5101 | pinval = 0x20; | ||
5102 | /* mic2 vref pin is used for mute LED control */ | ||
5103 | snd_hda_codec_update_cache(codec, 0x19, 0, | ||
5104 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
5105 | pinval); | ||
5106 | } | ||
5107 | return alc_check_power_status(codec, nid); | ||
5108 | } | ||
5109 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
5110 | |||
5111 | /* different alc269-variants */ | 5731 | /* different alc269-variants */ |
5112 | enum { | 5732 | enum { |
5113 | ALC269_TYPE_ALC269VA, | 5733 | ALC269_TYPE_ALC269VA, |
@@ -5258,6 +5878,31 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec, | |||
5258 | spec->automute_hook = alc269_quanta_automute; | 5878 | spec->automute_hook = alc269_quanta_automute; |
5259 | } | 5879 | } |
5260 | 5880 | ||
5881 | /* update mute-LED according to the speaker mute state via mic2 VREF pin */ | ||
5882 | static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled) | ||
5883 | { | ||
5884 | struct hda_codec *codec = private_data; | ||
5885 | unsigned int pinval = enabled ? 0x20 : 0x24; | ||
5886 | snd_hda_codec_update_cache(codec, 0x19, 0, | ||
5887 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
5888 | pinval); | ||
5889 | } | ||
5890 | |||
5891 | static void alc269_fixup_mic2_mute(struct hda_codec *codec, | ||
5892 | const struct alc_fixup *fix, int action) | ||
5893 | { | ||
5894 | struct alc_spec *spec = codec->spec; | ||
5895 | switch (action) { | ||
5896 | case ALC_FIXUP_ACT_BUILD: | ||
5897 | spec->vmaster_mute.hook = alc269_fixup_mic2_mute_hook; | ||
5898 | snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true); | ||
5899 | /* fallthru */ | ||
5900 | case ALC_FIXUP_ACT_INIT: | ||
5901 | snd_hda_sync_vmaster_hook(&spec->vmaster_mute); | ||
5902 | break; | ||
5903 | } | ||
5904 | } | ||
5905 | |||
5261 | enum { | 5906 | enum { |
5262 | ALC269_FIXUP_SONY_VAIO, | 5907 | ALC269_FIXUP_SONY_VAIO, |
5263 | ALC275_FIXUP_SONY_VAIO_GPIO2, | 5908 | ALC275_FIXUP_SONY_VAIO_GPIO2, |
@@ -5275,6 +5920,7 @@ enum { | |||
5275 | ALC269_FIXUP_DMIC, | 5920 | ALC269_FIXUP_DMIC, |
5276 | ALC269VB_FIXUP_AMIC, | 5921 | ALC269VB_FIXUP_AMIC, |
5277 | ALC269VB_FIXUP_DMIC, | 5922 | ALC269VB_FIXUP_DMIC, |
5923 | ALC269_FIXUP_MIC2_MUTE_LED, | ||
5278 | }; | 5924 | }; |
5279 | 5925 | ||
5280 | static const struct alc_fixup alc269_fixups[] = { | 5926 | static const struct alc_fixup alc269_fixups[] = { |
@@ -5395,9 +6041,14 @@ static const struct alc_fixup alc269_fixups[] = { | |||
5395 | { } | 6041 | { } |
5396 | }, | 6042 | }, |
5397 | }, | 6043 | }, |
6044 | [ALC269_FIXUP_MIC2_MUTE_LED] = { | ||
6045 | .type = ALC_FIXUP_FUNC, | ||
6046 | .v.func = alc269_fixup_mic2_mute, | ||
6047 | }, | ||
5398 | }; | 6048 | }; |
5399 | 6049 | ||
5400 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 6050 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
6051 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), | ||
5401 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), | 6052 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), |
5402 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), | 6053 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), |
5403 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), | 6054 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), |
@@ -5420,7 +6071,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5420 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), | 6071 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), |
5421 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), | 6072 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), |
5422 | 6073 | ||
5423 | #if 1 | 6074 | #if 0 |
5424 | /* Below is a quirk table taken from the old code. | 6075 | /* Below is a quirk table taken from the old code. |
5425 | * Basically the device should work as is without the fixup table. | 6076 | * Basically the device should work as is without the fixup table. |
5426 | * If BIOS doesn't give a proper info, enable the corresponding | 6077 | * If BIOS doesn't give a proper info, enable the corresponding |
@@ -5478,13 +6129,13 @@ static const struct alc_model_fixup alc269_fixup_models[] = { | |||
5478 | }; | 6129 | }; |
5479 | 6130 | ||
5480 | 6131 | ||
5481 | static int alc269_fill_coef(struct hda_codec *codec) | 6132 | static void alc269_fill_coef(struct hda_codec *codec) |
5482 | { | 6133 | { |
5483 | struct alc_spec *spec = codec->spec; | 6134 | struct alc_spec *spec = codec->spec; |
5484 | int val; | 6135 | int val; |
5485 | 6136 | ||
5486 | if (spec->codec_variant != ALC269_TYPE_ALC269VB) | 6137 | if (spec->codec_variant != ALC269_TYPE_ALC269VB) |
5487 | return 0; | 6138 | return; |
5488 | 6139 | ||
5489 | if ((alc_get_coef0(codec) & 0x00ff) < 0x015) { | 6140 | if ((alc_get_coef0(codec) & 0x00ff) < 0x015) { |
5490 | alc_write_coef_idx(codec, 0xf, 0x960b); | 6141 | alc_write_coef_idx(codec, 0xf, 0x960b); |
@@ -5520,8 +6171,6 @@ static int alc269_fill_coef(struct hda_codec *codec) | |||
5520 | 6171 | ||
5521 | val = alc_read_coef_idx(codec, 0x4); /* HP */ | 6172 | val = alc_read_coef_idx(codec, 0x4); /* HP */ |
5522 | alc_write_coef_idx(codec, 0x4, val | (1<<11)); | 6173 | alc_write_coef_idx(codec, 0x4, val | (1<<11)); |
5523 | |||
5524 | return 0; | ||
5525 | } | 6174 | } |
5526 | 6175 | ||
5527 | /* | 6176 | /* |
@@ -5565,6 +6214,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
5565 | } | 6214 | } |
5566 | if (err < 0) | 6215 | if (err < 0) |
5567 | goto error; | 6216 | goto error; |
6217 | spec->init_hook = alc269_fill_coef; | ||
5568 | alc269_fill_coef(codec); | 6218 | alc269_fill_coef(codec); |
5569 | } | 6219 | } |
5570 | 6220 | ||
@@ -5577,15 +6227,6 @@ static int patch_alc269(struct hda_codec *codec) | |||
5577 | if (err < 0) | 6227 | if (err < 0) |
5578 | goto error; | 6228 | goto error; |
5579 | 6229 | ||
5580 | if (!spec->no_analog && !spec->adc_nids) { | ||
5581 | alc_auto_fill_adc_caps(codec); | ||
5582 | alc_rebuild_imux_for_auto_mic(codec); | ||
5583 | alc_remove_invalid_adc_nids(codec); | ||
5584 | } | ||
5585 | |||
5586 | if (!spec->no_analog && !spec->cap_mixer) | ||
5587 | set_capture_mixer(codec); | ||
5588 | |||
5589 | if (!spec->no_analog && has_cdefine_beep(codec)) { | 6230 | if (!spec->no_analog && has_cdefine_beep(codec)) { |
5590 | err = snd_hda_attach_beep_device(codec, 0x1); | 6231 | err = snd_hda_attach_beep_device(codec, 0x1); |
5591 | if (err < 0) | 6232 | if (err < 0) |
@@ -5593,21 +6234,13 @@ static int patch_alc269(struct hda_codec *codec) | |||
5593 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 6234 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); |
5594 | } | 6235 | } |
5595 | 6236 | ||
5596 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
5597 | |||
5598 | codec->patch_ops = alc_patch_ops; | 6237 | codec->patch_ops = alc_patch_ops; |
5599 | #ifdef CONFIG_PM | 6238 | #ifdef CONFIG_PM |
5600 | codec->patch_ops.resume = alc269_resume; | 6239 | codec->patch_ops.resume = alc269_resume; |
5601 | #endif | 6240 | #endif |
5602 | spec->init_hook = alc_auto_init_std; | ||
5603 | spec->shutup = alc269_shutup; | 6241 | spec->shutup = alc269_shutup; |
5604 | 6242 | ||
5605 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 6243 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
5606 | if (!spec->loopback.amplist) | ||
5607 | spec->loopback.amplist = alc269_loopbacks; | ||
5608 | if (alc269_mic2_for_mute_led(codec)) | ||
5609 | codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps; | ||
5610 | #endif | ||
5611 | 6244 | ||
5612 | return 0; | 6245 | return 0; |
5613 | 6246 | ||
@@ -5627,21 +6260,12 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
5627 | return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids); | 6260 | return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids); |
5628 | } | 6261 | } |
5629 | 6262 | ||
5630 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5631 | static const struct hda_amp_list alc861_loopbacks[] = { | ||
5632 | { 0x15, HDA_INPUT, 0 }, | ||
5633 | { 0x15, HDA_INPUT, 1 }, | ||
5634 | { 0x15, HDA_INPUT, 2 }, | ||
5635 | { 0x15, HDA_INPUT, 3 }, | ||
5636 | { } /* end */ | ||
5637 | }; | ||
5638 | #endif | ||
5639 | |||
5640 | |||
5641 | /* Pin config fixes */ | 6263 | /* Pin config fixes */ |
5642 | enum { | 6264 | enum { |
5643 | PINFIX_FSC_AMILO_PI1505, | 6265 | ALC861_FIXUP_FSC_AMILO_PI1505, |
5644 | PINFIX_ASUS_A6RP, | 6266 | ALC861_FIXUP_AMP_VREF_0F, |
6267 | ALC861_FIXUP_NO_JACK_DETECT, | ||
6268 | ALC861_FIXUP_ASUS_A6RP, | ||
5645 | }; | 6269 | }; |
5646 | 6270 | ||
5647 | /* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */ | 6271 | /* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */ |
@@ -5663,8 +6287,16 @@ static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec, | |||
5663 | spec->keep_vref_in_automute = 1; | 6287 | spec->keep_vref_in_automute = 1; |
5664 | } | 6288 | } |
5665 | 6289 | ||
6290 | /* suppress the jack-detection */ | ||
6291 | static void alc_fixup_no_jack_detect(struct hda_codec *codec, | ||
6292 | const struct alc_fixup *fix, int action) | ||
6293 | { | ||
6294 | if (action == ALC_FIXUP_ACT_PRE_PROBE) | ||
6295 | codec->no_jack_detect = 1; | ||
6296 | } | ||
6297 | |||
5666 | static const struct alc_fixup alc861_fixups[] = { | 6298 | static const struct alc_fixup alc861_fixups[] = { |
5667 | [PINFIX_FSC_AMILO_PI1505] = { | 6299 | [ALC861_FIXUP_FSC_AMILO_PI1505] = { |
5668 | .type = ALC_FIXUP_PINS, | 6300 | .type = ALC_FIXUP_PINS, |
5669 | .v.pins = (const struct alc_pincfg[]) { | 6301 | .v.pins = (const struct alc_pincfg[]) { |
5670 | { 0x0b, 0x0221101f }, /* HP */ | 6302 | { 0x0b, 0x0221101f }, /* HP */ |
@@ -5672,17 +6304,29 @@ static const struct alc_fixup alc861_fixups[] = { | |||
5672 | { } | 6304 | { } |
5673 | } | 6305 | } |
5674 | }, | 6306 | }, |
5675 | [PINFIX_ASUS_A6RP] = { | 6307 | [ALC861_FIXUP_AMP_VREF_0F] = { |
5676 | .type = ALC_FIXUP_FUNC, | 6308 | .type = ALC_FIXUP_FUNC, |
5677 | .v.func = alc861_fixup_asus_amp_vref_0f, | 6309 | .v.func = alc861_fixup_asus_amp_vref_0f, |
5678 | }, | 6310 | }, |
6311 | [ALC861_FIXUP_NO_JACK_DETECT] = { | ||
6312 | .type = ALC_FIXUP_FUNC, | ||
6313 | .v.func = alc_fixup_no_jack_detect, | ||
6314 | }, | ||
6315 | [ALC861_FIXUP_ASUS_A6RP] = { | ||
6316 | .type = ALC_FIXUP_FUNC, | ||
6317 | .v.func = alc861_fixup_asus_amp_vref_0f, | ||
6318 | .chained = true, | ||
6319 | .chain_id = ALC861_FIXUP_NO_JACK_DETECT, | ||
6320 | } | ||
5679 | }; | 6321 | }; |
5680 | 6322 | ||
5681 | static const struct snd_pci_quirk alc861_fixup_tbl[] = { | 6323 | static const struct snd_pci_quirk alc861_fixup_tbl[] = { |
5682 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP), | 6324 | SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP), |
5683 | SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", PINFIX_ASUS_A6RP), | 6325 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F), |
5684 | SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP), | 6326 | SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT), |
5685 | SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505), | 6327 | SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F), |
6328 | SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F), | ||
6329 | SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505), | ||
5686 | {} | 6330 | {} |
5687 | }; | 6331 | }; |
5688 | 6332 | ||
@@ -5709,15 +6353,6 @@ static int patch_alc861(struct hda_codec *codec) | |||
5709 | if (err < 0) | 6353 | if (err < 0) |
5710 | goto error; | 6354 | goto error; |
5711 | 6355 | ||
5712 | if (!spec->no_analog && !spec->adc_nids) { | ||
5713 | alc_auto_fill_adc_caps(codec); | ||
5714 | alc_rebuild_imux_for_auto_mic(codec); | ||
5715 | alc_remove_invalid_adc_nids(codec); | ||
5716 | } | ||
5717 | |||
5718 | if (!spec->no_analog && !spec->cap_mixer) | ||
5719 | set_capture_mixer(codec); | ||
5720 | |||
5721 | if (!spec->no_analog) { | 6356 | if (!spec->no_analog) { |
5722 | err = snd_hda_attach_beep_device(codec, 0x23); | 6357 | err = snd_hda_attach_beep_device(codec, 0x23); |
5723 | if (err < 0) | 6358 | if (err < 0) |
@@ -5725,16 +6360,13 @@ static int patch_alc861(struct hda_codec *codec) | |||
5725 | set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); | 6360 | set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); |
5726 | } | 6361 | } |
5727 | 6362 | ||
5728 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
5729 | |||
5730 | codec->patch_ops = alc_patch_ops; | 6363 | codec->patch_ops = alc_patch_ops; |
5731 | spec->init_hook = alc_auto_init_std; | ||
5732 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 6364 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
5733 | spec->power_hook = alc_power_eapd; | 6365 | spec->power_hook = alc_power_eapd; |
5734 | if (!spec->loopback.amplist) | ||
5735 | spec->loopback.amplist = alc861_loopbacks; | ||
5736 | #endif | 6366 | #endif |
5737 | 6367 | ||
6368 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
6369 | |||
5738 | return 0; | 6370 | return 0; |
5739 | 6371 | ||
5740 | error: | 6372 | error: |
@@ -5749,10 +6381,6 @@ static int patch_alc861(struct hda_codec *codec) | |||
5749 | * | 6381 | * |
5750 | * In addition, an independent DAC | 6382 | * In addition, an independent DAC |
5751 | */ | 6383 | */ |
5752 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5753 | #define alc861vd_loopbacks alc880_loopbacks | ||
5754 | #endif | ||
5755 | |||
5756 | static int alc861vd_parse_auto_config(struct hda_codec *codec) | 6384 | static int alc861vd_parse_auto_config(struct hda_codec *codec) |
5757 | { | 6385 | { |
5758 | static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 }; | 6386 | static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 }; |
@@ -5833,15 +6461,6 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
5833 | add_verb(spec, alc660vd_eapd_verbs); | 6461 | add_verb(spec, alc660vd_eapd_verbs); |
5834 | } | 6462 | } |
5835 | 6463 | ||
5836 | if (!spec->no_analog && !spec->adc_nids) { | ||
5837 | alc_auto_fill_adc_caps(codec); | ||
5838 | alc_rebuild_imux_for_auto_mic(codec); | ||
5839 | alc_remove_invalid_adc_nids(codec); | ||
5840 | } | ||
5841 | |||
5842 | if (!spec->no_analog && !spec->cap_mixer) | ||
5843 | set_capture_mixer(codec); | ||
5844 | |||
5845 | if (!spec->no_analog) { | 6464 | if (!spec->no_analog) { |
5846 | err = snd_hda_attach_beep_device(codec, 0x23); | 6465 | err = snd_hda_attach_beep_device(codec, 0x23); |
5847 | if (err < 0) | 6466 | if (err < 0) |
@@ -5849,16 +6468,11 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
5849 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 6468 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
5850 | } | 6469 | } |
5851 | 6470 | ||
5852 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
5853 | |||
5854 | codec->patch_ops = alc_patch_ops; | 6471 | codec->patch_ops = alc_patch_ops; |
5855 | 6472 | ||
5856 | spec->init_hook = alc_auto_init_std; | ||
5857 | spec->shutup = alc_eapd_shutup; | 6473 | spec->shutup = alc_eapd_shutup; |
5858 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 6474 | |
5859 | if (!spec->loopback.amplist) | 6475 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
5860 | spec->loopback.amplist = alc861vd_loopbacks; | ||
5861 | #endif | ||
5862 | 6476 | ||
5863 | return 0; | 6477 | return 0; |
5864 | 6478 | ||
@@ -5878,9 +6492,6 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
5878 | * In addition, an independent DAC for the multi-playback (not used in this | 6492 | * In addition, an independent DAC for the multi-playback (not used in this |
5879 | * driver yet). | 6493 | * driver yet). |
5880 | */ | 6494 | */ |
5881 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5882 | #define alc662_loopbacks alc880_loopbacks | ||
5883 | #endif | ||
5884 | 6495 | ||
5885 | /* | 6496 | /* |
5886 | * BIOS auto configuration | 6497 | * BIOS auto configuration |
@@ -5930,6 +6541,7 @@ enum { | |||
5930 | ALC662_FIXUP_ASUS_MODE6, | 6541 | ALC662_FIXUP_ASUS_MODE6, |
5931 | ALC662_FIXUP_ASUS_MODE7, | 6542 | ALC662_FIXUP_ASUS_MODE7, |
5932 | ALC662_FIXUP_ASUS_MODE8, | 6543 | ALC662_FIXUP_ASUS_MODE8, |
6544 | ALC662_FIXUP_NO_JACK_DETECT, | ||
5933 | }; | 6545 | }; |
5934 | 6546 | ||
5935 | static const struct alc_fixup alc662_fixups[] = { | 6547 | static const struct alc_fixup alc662_fixups[] = { |
@@ -6075,6 +6687,10 @@ static const struct alc_fixup alc662_fixups[] = { | |||
6075 | .chained = true, | 6687 | .chained = true, |
6076 | .chain_id = ALC662_FIXUP_SKU_IGNORE | 6688 | .chain_id = ALC662_FIXUP_SKU_IGNORE |
6077 | }, | 6689 | }, |
6690 | [ALC662_FIXUP_NO_JACK_DETECT] = { | ||
6691 | .type = ALC_FIXUP_FUNC, | ||
6692 | .v.func = alc_fixup_no_jack_detect, | ||
6693 | }, | ||
6078 | }; | 6694 | }; |
6079 | 6695 | ||
6080 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { | 6696 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { |
@@ -6083,6 +6699,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { | |||
6083 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), | 6699 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), |
6084 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), | 6700 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), |
6085 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), | 6701 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), |
6702 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), | ||
6086 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), | 6703 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), |
6087 | SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), | 6704 | SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), |
6088 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), | 6705 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), |
@@ -6204,15 +6821,6 @@ static int patch_alc662(struct hda_codec *codec) | |||
6204 | if (err < 0) | 6821 | if (err < 0) |
6205 | goto error; | 6822 | goto error; |
6206 | 6823 | ||
6207 | if (!spec->no_analog && !spec->adc_nids) { | ||
6208 | alc_auto_fill_adc_caps(codec); | ||
6209 | alc_rebuild_imux_for_auto_mic(codec); | ||
6210 | alc_remove_invalid_adc_nids(codec); | ||
6211 | } | ||
6212 | |||
6213 | if (!spec->no_analog && !spec->cap_mixer) | ||
6214 | set_capture_mixer(codec); | ||
6215 | |||
6216 | if (!spec->no_analog && has_cdefine_beep(codec)) { | 6824 | if (!spec->no_analog && has_cdefine_beep(codec)) { |
6217 | err = snd_hda_attach_beep_device(codec, 0x1); | 6825 | err = snd_hda_attach_beep_device(codec, 0x1); |
6218 | if (err < 0) | 6826 | if (err < 0) |
@@ -6232,16 +6840,10 @@ static int patch_alc662(struct hda_codec *codec) | |||
6232 | } | 6840 | } |
6233 | } | 6841 | } |
6234 | 6842 | ||
6235 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | ||
6236 | |||
6237 | codec->patch_ops = alc_patch_ops; | 6843 | codec->patch_ops = alc_patch_ops; |
6238 | spec->init_hook = alc_auto_init_std; | ||
6239 | spec->shutup = alc_eapd_shutup; | 6844 | spec->shutup = alc_eapd_shutup; |
6240 | 6845 | ||
6241 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 6846 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
6242 | if (!spec->loopback.amplist) | ||
6243 | spec->loopback.amplist = alc662_loopbacks; | ||
6244 | #endif | ||
6245 | 6847 | ||
6246 | return 0; | 6848 | return 0; |
6247 | 6849 | ||
@@ -6281,11 +6883,7 @@ static int patch_alc680(struct hda_codec *codec) | |||
6281 | return err; | 6883 | return err; |
6282 | } | 6884 | } |
6283 | 6885 | ||
6284 | if (!spec->no_analog && !spec->cap_mixer) | ||
6285 | set_capture_mixer(codec); | ||
6286 | |||
6287 | codec->patch_ops = alc_patch_ops; | 6886 | codec->patch_ops = alc_patch_ops; |
6288 | spec->init_hook = alc_auto_init_std; | ||
6289 | 6887 | ||
6290 | return 0; | 6888 | return 0; |
6291 | } | 6889 | } |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 9dbb5735d778..33a9946b492c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -99,6 +99,7 @@ enum { | |||
99 | STAC_DELL_VOSTRO_3500, | 99 | STAC_DELL_VOSTRO_3500, |
100 | STAC_92HD83XXX_HP_cNB11_INTQUAD, | 100 | STAC_92HD83XXX_HP_cNB11_INTQUAD, |
101 | STAC_HP_DV7_4000, | 101 | STAC_HP_DV7_4000, |
102 | STAC_HP_ZEPHYR, | ||
102 | STAC_92HD83XXX_MODELS | 103 | STAC_92HD83XXX_MODELS |
103 | }; | 104 | }; |
104 | 105 | ||
@@ -309,6 +310,8 @@ struct sigmatel_spec { | |||
309 | unsigned long auto_capvols[MAX_ADCS_NUM]; | 310 | unsigned long auto_capvols[MAX_ADCS_NUM]; |
310 | unsigned auto_dmic_cnt; | 311 | unsigned auto_dmic_cnt; |
311 | hda_nid_t auto_dmic_nids[MAX_DMICS_NUM]; | 312 | hda_nid_t auto_dmic_nids[MAX_DMICS_NUM]; |
313 | |||
314 | struct hda_vmaster_mute_hook vmaster_mute; | ||
312 | }; | 315 | }; |
313 | 316 | ||
314 | static const hda_nid_t stac9200_adc_nids[1] = { | 317 | static const hda_nid_t stac9200_adc_nids[1] = { |
@@ -662,7 +665,6 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, | |||
662 | return 0; | 665 | return 0; |
663 | } | 666 | } |
664 | 667 | ||
665 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
666 | static int stac_vrefout_set(struct hda_codec *codec, | 668 | static int stac_vrefout_set(struct hda_codec *codec, |
667 | hda_nid_t nid, unsigned int new_vref) | 669 | hda_nid_t nid, unsigned int new_vref) |
668 | { | 670 | { |
@@ -686,7 +688,6 @@ static int stac_vrefout_set(struct hda_codec *codec, | |||
686 | 688 | ||
687 | return 1; | 689 | return 1; |
688 | } | 690 | } |
689 | #endif | ||
690 | 691 | ||
691 | static unsigned int stac92xx_vref_set(struct hda_codec *codec, | 692 | static unsigned int stac92xx_vref_set(struct hda_codec *codec, |
692 | hda_nid_t nid, unsigned int new_vref) | 693 | hda_nid_t nid, unsigned int new_vref) |
@@ -894,6 +895,13 @@ static const struct hda_verb stac92hd83xxx_core_init[] = { | |||
894 | {} | 895 | {} |
895 | }; | 896 | }; |
896 | 897 | ||
898 | static const struct hda_verb stac92hd83xxx_hp_zephyr_init[] = { | ||
899 | { 0x22, 0x785, 0x43 }, | ||
900 | { 0x22, 0x782, 0xe0 }, | ||
901 | { 0x22, 0x795, 0x00 }, | ||
902 | {} | ||
903 | }; | ||
904 | |||
897 | static const struct hda_verb stac92hd71bxx_core_init[] = { | 905 | static const struct hda_verb stac92hd71bxx_core_init[] = { |
898 | /* set master volume and direct control */ | 906 | /* set master volume and direct control */ |
899 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 907 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
@@ -999,8 +1007,8 @@ static const struct hda_verb stac9205_core_init[] = { | |||
999 | } | 1007 | } |
1000 | 1008 | ||
1001 | static const struct snd_kcontrol_new stac9200_mixer[] = { | 1009 | static const struct snd_kcontrol_new stac9200_mixer[] = { |
1002 | HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | 1010 | HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xb, 0, HDA_OUTPUT), |
1003 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | 1011 | HDA_CODEC_MUTE("PCM Playback Switch", 0xb, 0, HDA_OUTPUT), |
1004 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | 1012 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), |
1005 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | 1013 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), |
1006 | { } /* end */ | 1014 | { } /* end */ |
@@ -1027,8 +1035,8 @@ static const struct snd_kcontrol_new stac92hd71bxx_loopback[] = { | |||
1027 | }; | 1035 | }; |
1028 | 1036 | ||
1029 | static const struct snd_kcontrol_new stac925x_mixer[] = { | 1037 | static const struct snd_kcontrol_new stac925x_mixer[] = { |
1030 | HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xe, 0, HDA_OUTPUT), | 1038 | HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xe, 0, HDA_OUTPUT), |
1031 | HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), | 1039 | HDA_CODEC_MUTE("PCM Playback Switch", 0x0e, 0, HDA_OUTPUT), |
1032 | { } /* end */ | 1040 | { } /* end */ |
1033 | }; | 1041 | }; |
1034 | 1042 | ||
@@ -1060,34 +1068,25 @@ static struct snd_kcontrol_new stac_smux_mixer = { | |||
1060 | .put = stac92xx_smux_enum_put, | 1068 | .put = stac92xx_smux_enum_put, |
1061 | }; | 1069 | }; |
1062 | 1070 | ||
1063 | static const char * const slave_vols[] = { | 1071 | static const char * const slave_pfxs[] = { |
1064 | "Front Playback Volume", | 1072 | "Front", "Surround", "Center", "LFE", "Side", |
1065 | "Surround Playback Volume", | 1073 | "Headphone", "Speaker", "IEC958", |
1066 | "Center Playback Volume", | ||
1067 | "LFE Playback Volume", | ||
1068 | "Side Playback Volume", | ||
1069 | "Headphone Playback Volume", | ||
1070 | "Speaker Playback Volume", | ||
1071 | NULL | 1074 | NULL |
1072 | }; | 1075 | }; |
1073 | 1076 | ||
1074 | static const char * const slave_sws[] = { | 1077 | static void stac92xx_update_led_status(struct hda_codec *codec, int enabled); |
1075 | "Front Playback Switch", | 1078 | |
1076 | "Surround Playback Switch", | 1079 | static void stac92xx_vmaster_hook(void *private_data, int val) |
1077 | "Center Playback Switch", | 1080 | { |
1078 | "LFE Playback Switch", | 1081 | stac92xx_update_led_status(private_data, val); |
1079 | "Side Playback Switch", | 1082 | } |
1080 | "Headphone Playback Switch", | ||
1081 | "Speaker Playback Switch", | ||
1082 | "IEC958 Playback Switch", | ||
1083 | NULL | ||
1084 | }; | ||
1085 | 1083 | ||
1086 | static void stac92xx_free_kctls(struct hda_codec *codec); | 1084 | static void stac92xx_free_kctls(struct hda_codec *codec); |
1087 | 1085 | ||
1088 | static int stac92xx_build_controls(struct hda_codec *codec) | 1086 | static int stac92xx_build_controls(struct hda_codec *codec) |
1089 | { | 1087 | { |
1090 | struct sigmatel_spec *spec = codec->spec; | 1088 | struct sigmatel_spec *spec = codec->spec; |
1089 | unsigned int vmaster_tlv[4]; | ||
1091 | int err; | 1090 | int err; |
1092 | int i; | 1091 | int i; |
1093 | 1092 | ||
@@ -1144,22 +1143,28 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1144 | } | 1143 | } |
1145 | 1144 | ||
1146 | /* if we have no master control, let's create it */ | 1145 | /* if we have no master control, let's create it */ |
1147 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | 1146 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], |
1148 | unsigned int vmaster_tlv[4]; | 1147 | HDA_OUTPUT, vmaster_tlv); |
1149 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], | 1148 | /* correct volume offset */ |
1150 | HDA_OUTPUT, vmaster_tlv); | 1149 | vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; |
1151 | /* correct volume offset */ | 1150 | /* minimum value is actually mute */ |
1152 | vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; | 1151 | vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; |
1153 | /* minimum value is actually mute */ | 1152 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
1154 | vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; | 1153 | vmaster_tlv, slave_pfxs, |
1155 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 1154 | "Playback Volume"); |
1156 | vmaster_tlv, slave_vols); | 1155 | if (err < 0) |
1157 | if (err < 0) | 1156 | return err; |
1158 | return err; | 1157 | |
1159 | } | 1158 | err = __snd_hda_add_vmaster(codec, "Master Playback Switch", |
1160 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 1159 | NULL, slave_pfxs, |
1161 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 1160 | "Playback Switch", true, |
1162 | NULL, slave_sws); | 1161 | &spec->vmaster_mute.sw_kctl); |
1162 | if (err < 0) | ||
1163 | return err; | ||
1164 | |||
1165 | if (spec->gpio_led) { | ||
1166 | spec->vmaster_mute.hook = stac92xx_vmaster_hook; | ||
1167 | err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true); | ||
1163 | if (err < 0) | 1168 | if (err < 0) |
1164 | return err; | 1169 | return err; |
1165 | } | 1170 | } |
@@ -1636,6 +1641,12 @@ static const unsigned int hp_dv7_4000_pin_configs[10] = { | |||
1636 | 0x40f000f0, 0x40f000f0, | 1641 | 0x40f000f0, 0x40f000f0, |
1637 | }; | 1642 | }; |
1638 | 1643 | ||
1644 | static const unsigned int hp_zephyr_pin_configs[10] = { | ||
1645 | 0x01813050, 0x0421201f, 0x04a1205e, 0x96130310, | ||
1646 | 0x96130310, 0x0101401f, 0x1111611f, 0xd5a30130, | ||
1647 | 0, 0, | ||
1648 | }; | ||
1649 | |||
1639 | static const unsigned int hp_cNB11_intquad_pin_configs[10] = { | 1650 | static const unsigned int hp_cNB11_intquad_pin_configs[10] = { |
1640 | 0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110, | 1651 | 0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110, |
1641 | 0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130, | 1652 | 0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130, |
@@ -1649,6 +1660,7 @@ static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { | |||
1649 | [STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs, | 1660 | [STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs, |
1650 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs, | 1661 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs, |
1651 | [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, | 1662 | [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, |
1663 | [STAC_HP_ZEPHYR] = hp_zephyr_pin_configs, | ||
1652 | }; | 1664 | }; |
1653 | 1665 | ||
1654 | static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | 1666 | static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { |
@@ -1659,6 +1671,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | |||
1659 | [STAC_DELL_VOSTRO_3500] = "dell-vostro-3500", | 1671 | [STAC_DELL_VOSTRO_3500] = "dell-vostro-3500", |
1660 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", | 1672 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", |
1661 | [STAC_HP_DV7_4000] = "hp-dv7-4000", | 1673 | [STAC_HP_DV7_4000] = "hp-dv7-4000", |
1674 | [STAC_HP_ZEPHYR] = "hp-zephyr", | ||
1662 | }; | 1675 | }; |
1663 | 1676 | ||
1664 | static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | 1677 | static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { |
@@ -1711,6 +1724,14 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | |||
1711 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 1724 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
1712 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593, | 1725 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593, |
1713 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 1726 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
1727 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561, | ||
1728 | "HP", STAC_HP_ZEPHYR), | ||
1729 | {} /* terminator */ | ||
1730 | }; | ||
1731 | |||
1732 | static const struct snd_pci_quirk stac92hd83xxx_codec_id_cfg_tbl[] = { | ||
1733 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561, | ||
1734 | "HP", STAC_HP_ZEPHYR), | ||
1714 | {} /* terminator */ | 1735 | {} /* terminator */ |
1715 | }; | 1736 | }; |
1716 | 1737 | ||
@@ -4410,8 +4431,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4410 | snd_hda_jack_report_sync(codec); | 4431 | snd_hda_jack_report_sync(codec); |
4411 | 4432 | ||
4412 | /* sync mute LED */ | 4433 | /* sync mute LED */ |
4413 | if (spec->gpio_led) | 4434 | snd_hda_sync_vmaster_hook(&spec->vmaster_mute); |
4414 | hda_call_check_power_status(codec, 0x01); | ||
4415 | if (spec->dac_list) | 4435 | if (spec->dac_list) |
4416 | stac92xx_power_down(codec); | 4436 | stac92xx_power_down(codec); |
4417 | return 0; | 4437 | return 0; |
@@ -4989,7 +5009,6 @@ static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | |||
4989 | return 0; | 5009 | return 0; |
4990 | } | 5010 | } |
4991 | 5011 | ||
4992 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4993 | static int stac92xx_pre_resume(struct hda_codec *codec) | 5012 | static int stac92xx_pre_resume(struct hda_codec *codec) |
4994 | { | 5013 | { |
4995 | struct sigmatel_spec *spec = codec->spec; | 5014 | struct sigmatel_spec *spec = codec->spec; |
@@ -5024,82 +5043,40 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
5024 | afg_power_state); | 5043 | afg_power_state); |
5025 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | 5044 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); |
5026 | } | 5045 | } |
5046 | #else | ||
5047 | #define stac92xx_suspend NULL | ||
5048 | #define stac92xx_resume NULL | ||
5049 | #define stac92xx_pre_resume NULL | ||
5050 | #define stac92xx_set_power_state NULL | ||
5051 | #endif /* CONFIG_PM */ | ||
5027 | 5052 | ||
5028 | /* | 5053 | /* update mute-LED accoring to the master switch */ |
5029 | * For this feature CONFIG_SND_HDA_POWER_SAVE is needed | 5054 | static void stac92xx_update_led_status(struct hda_codec *codec, int enabled) |
5030 | * as mute LED state is updated in check_power_status hook | ||
5031 | */ | ||
5032 | static int stac92xx_update_led_status(struct hda_codec *codec) | ||
5033 | { | 5055 | { |
5034 | struct sigmatel_spec *spec = codec->spec; | 5056 | struct sigmatel_spec *spec = codec->spec; |
5035 | int i, num_ext_dacs, muted = 1; | 5057 | int muted = !enabled; |
5036 | unsigned int muted_lvl, notmtd_lvl; | ||
5037 | hda_nid_t nid; | ||
5038 | 5058 | ||
5039 | if (!spec->gpio_led) | 5059 | if (!spec->gpio_led) |
5040 | return 0; | 5060 | return; |
5061 | |||
5062 | /* LED state is inverted on these systems */ | ||
5063 | if (spec->gpio_led_polarity) | ||
5064 | muted = !muted; | ||
5041 | 5065 | ||
5042 | for (i = 0; i < spec->multiout.num_dacs; i++) { | ||
5043 | nid = spec->multiout.dac_nids[i]; | ||
5044 | if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & | ||
5045 | HDA_AMP_MUTE)) { | ||
5046 | muted = 0; /* something heard */ | ||
5047 | break; | ||
5048 | } | ||
5049 | } | ||
5050 | if (muted && spec->multiout.hp_nid) | ||
5051 | if (!(snd_hda_codec_amp_read(codec, | ||
5052 | spec->multiout.hp_nid, 0, HDA_OUTPUT, 0) & | ||
5053 | HDA_AMP_MUTE)) { | ||
5054 | muted = 0; /* HP is not muted */ | ||
5055 | } | ||
5056 | num_ext_dacs = ARRAY_SIZE(spec->multiout.extra_out_nid); | ||
5057 | for (i = 0; muted && i < num_ext_dacs; i++) { | ||
5058 | nid = spec->multiout.extra_out_nid[i]; | ||
5059 | if (nid == 0) | ||
5060 | break; | ||
5061 | if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & | ||
5062 | HDA_AMP_MUTE)) { | ||
5063 | muted = 0; /* extra output is not muted */ | ||
5064 | } | ||
5065 | } | ||
5066 | /*polarity defines *not* muted state level*/ | 5066 | /*polarity defines *not* muted state level*/ |
5067 | if (!spec->vref_mute_led_nid) { | 5067 | if (!spec->vref_mute_led_nid) { |
5068 | if (muted) | 5068 | if (muted) |
5069 | spec->gpio_data &= ~spec->gpio_led; /* orange */ | 5069 | spec->gpio_data &= ~spec->gpio_led; /* orange */ |
5070 | else | 5070 | else |
5071 | spec->gpio_data |= spec->gpio_led; /* white */ | 5071 | spec->gpio_data |= spec->gpio_led; /* white */ |
5072 | |||
5073 | if (!spec->gpio_led_polarity) { | ||
5074 | /* LED state is inverted on these systems */ | ||
5075 | spec->gpio_data ^= spec->gpio_led; | ||
5076 | } | ||
5077 | stac_gpio_set(codec, spec->gpio_mask, | 5072 | stac_gpio_set(codec, spec->gpio_mask, |
5078 | spec->gpio_dir, spec->gpio_data); | 5073 | spec->gpio_dir, spec->gpio_data); |
5079 | } else { | 5074 | } else { |
5080 | notmtd_lvl = spec->gpio_led_polarity ? | 5075 | spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD; |
5081 | AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD; | ||
5082 | muted_lvl = spec->gpio_led_polarity ? | ||
5083 | AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_50; | ||
5084 | spec->vref_led = muted ? muted_lvl : notmtd_lvl; | ||
5085 | stac_vrefout_set(codec, spec->vref_mute_led_nid, | 5076 | stac_vrefout_set(codec, spec->vref_mute_led_nid, |
5086 | spec->vref_led); | 5077 | spec->vref_led); |
5087 | } | 5078 | } |
5088 | return 0; | ||
5089 | } | ||
5090 | |||
5091 | /* | ||
5092 | * use power check for controlling mute led of HP notebooks | ||
5093 | */ | ||
5094 | static int stac92xx_check_power_status(struct hda_codec *codec, | ||
5095 | hda_nid_t nid) | ||
5096 | { | ||
5097 | stac92xx_update_led_status(codec); | ||
5098 | |||
5099 | return 0; | ||
5100 | } | 5079 | } |
5101 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
5102 | #endif /* CONFIG_PM */ | ||
5103 | 5080 | ||
5104 | static const struct hda_codec_ops stac92xx_patch_ops = { | 5081 | static const struct hda_codec_ops stac92xx_patch_ops = { |
5105 | .build_controls = stac92xx_build_controls, | 5082 | .build_controls = stac92xx_build_controls, |
@@ -5580,6 +5557,12 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
5580 | STAC_92HD83XXX_MODELS, | 5557 | STAC_92HD83XXX_MODELS, |
5581 | stac92hd83xxx_models, | 5558 | stac92hd83xxx_models, |
5582 | stac92hd83xxx_cfg_tbl); | 5559 | stac92hd83xxx_cfg_tbl); |
5560 | /* check codec subsystem id if not found */ | ||
5561 | if (spec->board_config < 0) | ||
5562 | spec->board_config = | ||
5563 | snd_hda_check_board_codec_sid_config(codec, | ||
5564 | STAC_92HD83XXX_MODELS, stac92hd83xxx_models, | ||
5565 | stac92hd83xxx_codec_id_cfg_tbl); | ||
5583 | again: | 5566 | again: |
5584 | if (spec->board_config < 0) | 5567 | if (spec->board_config < 0) |
5585 | snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | 5568 | snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", |
@@ -5590,12 +5573,17 @@ again: | |||
5590 | 5573 | ||
5591 | codec->patch_ops = stac92xx_patch_ops; | 5574 | codec->patch_ops = stac92xx_patch_ops; |
5592 | 5575 | ||
5576 | switch (spec->board_config) { | ||
5577 | case STAC_HP_ZEPHYR: | ||
5578 | spec->init = stac92hd83xxx_hp_zephyr_init; | ||
5579 | break; | ||
5580 | } | ||
5581 | |||
5593 | if (find_mute_led_cfg(codec, -1/*no default cfg*/)) | 5582 | if (find_mute_led_cfg(codec, -1/*no default cfg*/)) |
5594 | snd_printd("mute LED gpio %d polarity %d\n", | 5583 | snd_printd("mute LED gpio %d polarity %d\n", |
5595 | spec->gpio_led, | 5584 | spec->gpio_led, |
5596 | spec->gpio_led_polarity); | 5585 | spec->gpio_led_polarity); |
5597 | 5586 | ||
5598 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5599 | if (spec->gpio_led) { | 5587 | if (spec->gpio_led) { |
5600 | if (!spec->vref_mute_led_nid) { | 5588 | if (!spec->vref_mute_led_nid) { |
5601 | spec->gpio_mask |= spec->gpio_led; | 5589 | spec->gpio_mask |= spec->gpio_led; |
@@ -5605,11 +5593,10 @@ again: | |||
5605 | codec->patch_ops.set_power_state = | 5593 | codec->patch_ops.set_power_state = |
5606 | stac92xx_set_power_state; | 5594 | stac92xx_set_power_state; |
5607 | } | 5595 | } |
5596 | #ifdef CONFIG_PM | ||
5608 | codec->patch_ops.pre_resume = stac92xx_pre_resume; | 5597 | codec->patch_ops.pre_resume = stac92xx_pre_resume; |
5609 | codec->patch_ops.check_power_status = | 5598 | #endif |
5610 | stac92xx_check_power_status; | ||
5611 | } | 5599 | } |
5612 | #endif | ||
5613 | 5600 | ||
5614 | err = stac92xx_parse_auto_config(codec); | 5601 | err = stac92xx_parse_auto_config(codec); |
5615 | if (!err) { | 5602 | if (!err) { |
@@ -5906,7 +5893,6 @@ again: | |||
5906 | spec->gpio_led, | 5893 | spec->gpio_led, |
5907 | spec->gpio_led_polarity); | 5894 | spec->gpio_led_polarity); |
5908 | 5895 | ||
5909 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5910 | if (spec->gpio_led) { | 5896 | if (spec->gpio_led) { |
5911 | if (!spec->vref_mute_led_nid) { | 5897 | if (!spec->vref_mute_led_nid) { |
5912 | spec->gpio_mask |= spec->gpio_led; | 5898 | spec->gpio_mask |= spec->gpio_led; |
@@ -5916,11 +5902,10 @@ again: | |||
5916 | codec->patch_ops.set_power_state = | 5902 | codec->patch_ops.set_power_state = |
5917 | stac92xx_set_power_state; | 5903 | stac92xx_set_power_state; |
5918 | } | 5904 | } |
5905 | #ifdef CONFIG_PM | ||
5919 | codec->patch_ops.pre_resume = stac92xx_pre_resume; | 5906 | codec->patch_ops.pre_resume = stac92xx_pre_resume; |
5920 | codec->patch_ops.check_power_status = | 5907 | #endif |
5921 | stac92xx_check_power_status; | ||
5922 | } | 5908 | } |
5923 | #endif | ||
5924 | 5909 | ||
5925 | spec->multiout.dac_nids = spec->dac_nids; | 5910 | spec->multiout.dac_nids = spec->dac_nids; |
5926 | 5911 | ||
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index dff9a00ee8fb..06214fdc9486 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -550,7 +550,10 @@ static void via_auto_init_output(struct hda_codec *codec, | |||
550 | pin = path->path[path->depth - 1]; | 550 | pin = path->path[path->depth - 1]; |
551 | 551 | ||
552 | init_output_pin(codec, pin, pin_type); | 552 | init_output_pin(codec, pin, pin_type); |
553 | caps = query_amp_caps(codec, pin, HDA_OUTPUT); | 553 | if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) |
554 | caps = query_amp_caps(codec, pin, HDA_OUTPUT); | ||
555 | else | ||
556 | caps = 0; | ||
554 | if (caps & AC_AMPCAP_MUTE) { | 557 | if (caps & AC_AMPCAP_MUTE) { |
555 | unsigned int val; | 558 | unsigned int val; |
556 | val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; | 559 | val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; |
@@ -645,6 +648,10 @@ static void via_auto_init_analog_input(struct hda_codec *codec) | |||
645 | 648 | ||
646 | /* init ADCs */ | 649 | /* init ADCs */ |
647 | for (i = 0; i < spec->num_adc_nids; i++) { | 650 | for (i = 0; i < spec->num_adc_nids; i++) { |
651 | hda_nid_t nid = spec->adc_nids[i]; | ||
652 | if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP) || | ||
653 | !(query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE)) | ||
654 | continue; | ||
648 | snd_hda_codec_write(codec, spec->adc_nids[i], 0, | 655 | snd_hda_codec_write(codec, spec->adc_nids[i], 0, |
649 | AC_VERB_SET_AMP_GAIN_MUTE, | 656 | AC_VERB_SET_AMP_GAIN_MUTE, |
650 | AMP_IN_UNMUTE(0)); | 657 | AMP_IN_UNMUTE(0)); |
@@ -1445,25 +1452,9 @@ static const struct hda_pcm_stream via_pcm_digital_capture = { | |||
1445 | /* | 1452 | /* |
1446 | * slave controls for virtual master | 1453 | * slave controls for virtual master |
1447 | */ | 1454 | */ |
1448 | static const char * const via_slave_vols[] = { | 1455 | static const char * const via_slave_pfxs[] = { |
1449 | "Front Playback Volume", | 1456 | "Front", "Surround", "Center", "LFE", "Side", |
1450 | "Surround Playback Volume", | 1457 | "Headphone", "Speaker", |
1451 | "Center Playback Volume", | ||
1452 | "LFE Playback Volume", | ||
1453 | "Side Playback Volume", | ||
1454 | "Headphone Playback Volume", | ||
1455 | "Speaker Playback Volume", | ||
1456 | NULL, | ||
1457 | }; | ||
1458 | |||
1459 | static const char * const via_slave_sws[] = { | ||
1460 | "Front Playback Switch", | ||
1461 | "Surround Playback Switch", | ||
1462 | "Center Playback Switch", | ||
1463 | "LFE Playback Switch", | ||
1464 | "Side Playback Switch", | ||
1465 | "Headphone Playback Switch", | ||
1466 | "Speaker Playback Switch", | ||
1467 | NULL, | 1458 | NULL, |
1468 | }; | 1459 | }; |
1469 | 1460 | ||
@@ -1508,13 +1499,15 @@ static int via_build_controls(struct hda_codec *codec) | |||
1508 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], | 1499 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], |
1509 | HDA_OUTPUT, vmaster_tlv); | 1500 | HDA_OUTPUT, vmaster_tlv); |
1510 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 1501 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
1511 | vmaster_tlv, via_slave_vols); | 1502 | vmaster_tlv, via_slave_pfxs, |
1503 | "Playback Volume"); | ||
1512 | if (err < 0) | 1504 | if (err < 0) |
1513 | return err; | 1505 | return err; |
1514 | } | 1506 | } |
1515 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 1507 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { |
1516 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 1508 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", |
1517 | NULL, via_slave_sws); | 1509 | NULL, via_slave_pfxs, |
1510 | "Playback Switch"); | ||
1518 | if (err < 0) | 1511 | if (err < 0) |
1519 | return err; | 1512 | return err; |
1520 | } | 1513 | } |
@@ -1522,6 +1515,8 @@ static int via_build_controls(struct hda_codec *codec) | |||
1522 | /* assign Capture Source enums to NID */ | 1515 | /* assign Capture Source enums to NID */ |
1523 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); | 1516 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); |
1524 | for (i = 0; kctl && i < kctl->count; i++) { | 1517 | for (i = 0; kctl && i < kctl->count; i++) { |
1518 | if (!spec->mux_nids[i]) | ||
1519 | continue; | ||
1525 | err = snd_hda_add_nid(codec, kctl, i, spec->mux_nids[i]); | 1520 | err = snd_hda_add_nid(codec, kctl, i, spec->mux_nids[i]); |
1526 | if (err < 0) | 1521 | if (err < 0) |
1527 | return err; | 1522 | return err; |
@@ -2488,6 +2483,8 @@ static int create_mic_boost_ctls(struct hda_codec *codec) | |||
2488 | { | 2483 | { |
2489 | struct via_spec *spec = codec->spec; | 2484 | struct via_spec *spec = codec->spec; |
2490 | const struct auto_pin_cfg *cfg = &spec->autocfg; | 2485 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
2486 | const char *prev_label = NULL; | ||
2487 | int type_idx = 0; | ||
2491 | int i, err; | 2488 | int i, err; |
2492 | 2489 | ||
2493 | for (i = 0; i < cfg->num_inputs; i++) { | 2490 | for (i = 0; i < cfg->num_inputs; i++) { |
@@ -2502,8 +2499,13 @@ static int create_mic_boost_ctls(struct hda_codec *codec) | |||
2502 | if (caps == -1 || !(caps & AC_AMPCAP_NUM_STEPS)) | 2499 | if (caps == -1 || !(caps & AC_AMPCAP_NUM_STEPS)) |
2503 | continue; | 2500 | continue; |
2504 | label = hda_get_autocfg_input_label(codec, cfg, i); | 2501 | label = hda_get_autocfg_input_label(codec, cfg, i); |
2502 | if (prev_label && !strcmp(label, prev_label)) | ||
2503 | type_idx++; | ||
2504 | else | ||
2505 | type_idx = 0; | ||
2506 | prev_label = label; | ||
2505 | snprintf(name, sizeof(name), "%s Boost Volume", label); | 2507 | snprintf(name, sizeof(name), "%s Boost Volume", label); |
2506 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, | 2508 | err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx, |
2507 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT)); | 2509 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT)); |
2508 | if (err < 0) | 2510 | if (err < 0) |
2509 | return err; | 2511 | return err; |