diff options
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 2503 |
1 files changed, 1821 insertions, 682 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 17c5062423ae..9edd558d6bd3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -33,38 +33,73 @@ | |||
33 | 33 | ||
34 | /* ALC880 board config type */ | 34 | /* ALC880 board config type */ |
35 | enum { | 35 | enum { |
36 | ALC880_MINIMAL, | ||
37 | ALC880_3ST, | 36 | ALC880_3ST, |
38 | ALC880_3ST_DIG, | 37 | ALC880_3ST_DIG, |
39 | ALC880_5ST, | 38 | ALC880_5ST, |
40 | ALC880_5ST_DIG, | 39 | ALC880_5ST_DIG, |
41 | ALC880_W810, | 40 | ALC880_W810, |
41 | ALC880_Z71V, | ||
42 | ALC880_AUTO, | ||
43 | ALC880_6ST_DIG, | ||
44 | ALC880_F1734, | ||
45 | ALC880_ASUS, | ||
46 | ALC880_ASUS_DIG, | ||
47 | ALC880_ASUS_W1V, | ||
48 | ALC880_UNIWILL_DIG, | ||
49 | #ifdef CONFIG_SND_DEBUG | ||
50 | ALC880_TEST, | ||
51 | #endif | ||
52 | ALC880_MODEL_LAST /* last tag */ | ||
53 | }; | ||
54 | |||
55 | /* ALC260 models */ | ||
56 | enum { | ||
57 | ALC260_BASIC, | ||
58 | ALC260_HP, | ||
59 | ALC260_MODEL_LAST /* last tag */ | ||
42 | }; | 60 | }; |
43 | 61 | ||
62 | /* amp values */ | ||
63 | #define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) | ||
64 | #define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) | ||
65 | #define AMP_OUT_MUTE 0xb080 | ||
66 | #define AMP_OUT_UNMUTE 0xb000 | ||
67 | #define AMP_OUT_ZERO 0xb000 | ||
68 | /* pinctl values */ | ||
69 | #define PIN_IN 0x20 | ||
70 | #define PIN_VREF80 0x24 | ||
71 | #define PIN_VREF50 0x21 | ||
72 | #define PIN_OUT 0x40 | ||
73 | #define PIN_HP 0xc0 | ||
74 | |||
44 | struct alc_spec { | 75 | struct alc_spec { |
45 | /* codec parameterization */ | 76 | /* codec parameterization */ |
46 | unsigned int front_panel: 1; | 77 | snd_kcontrol_new_t *mixers[3]; /* mixer arrays */ |
47 | |||
48 | snd_kcontrol_new_t* mixers[2]; | ||
49 | unsigned int num_mixers; | 78 | unsigned int num_mixers; |
50 | 79 | ||
51 | struct hda_verb *init_verbs; | 80 | const struct hda_verb *init_verbs[3]; /* initialization verbs |
81 | * don't forget NULL termination! | ||
82 | */ | ||
83 | unsigned int num_init_verbs; | ||
52 | 84 | ||
53 | char* stream_name_analog; | 85 | char *stream_name_analog; /* analog PCM stream */ |
54 | struct hda_pcm_stream *stream_analog_playback; | 86 | struct hda_pcm_stream *stream_analog_playback; |
55 | struct hda_pcm_stream *stream_analog_capture; | 87 | struct hda_pcm_stream *stream_analog_capture; |
56 | 88 | ||
57 | char* stream_name_digital; | 89 | char *stream_name_digital; /* digital PCM stream */ |
58 | struct hda_pcm_stream *stream_digital_playback; | 90 | struct hda_pcm_stream *stream_digital_playback; |
59 | struct hda_pcm_stream *stream_digital_capture; | 91 | struct hda_pcm_stream *stream_digital_capture; |
60 | 92 | ||
61 | /* playback */ | 93 | /* playback */ |
62 | struct hda_multi_out multiout; | 94 | struct hda_multi_out multiout; /* playback set-up |
95 | * max_channels, dacs must be set | ||
96 | * dig_out_nid and hp_nid are optional | ||
97 | */ | ||
63 | 98 | ||
64 | /* capture */ | 99 | /* capture */ |
65 | unsigned int num_adc_nids; | 100 | unsigned int num_adc_nids; |
66 | hda_nid_t *adc_nids; | 101 | hda_nid_t *adc_nids; |
67 | hda_nid_t dig_in_nid; | 102 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ |
68 | 103 | ||
69 | /* capture source */ | 104 | /* capture source */ |
70 | const struct hda_input_mux *input_mux; | 105 | const struct hda_input_mux *input_mux; |
@@ -75,61 +110,17 @@ struct alc_spec { | |||
75 | int num_channel_mode; | 110 | int num_channel_mode; |
76 | 111 | ||
77 | /* PCM information */ | 112 | /* PCM information */ |
78 | struct hda_pcm pcm_rec[2]; | 113 | struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */ |
79 | }; | ||
80 | |||
81 | /* DAC/ADC assignment */ | ||
82 | |||
83 | static hda_nid_t alc880_dac_nids[4] = { | ||
84 | /* front, rear, clfe, rear_surr */ | ||
85 | 0x02, 0x05, 0x04, 0x03 | ||
86 | }; | ||
87 | |||
88 | static hda_nid_t alc880_w810_dac_nids[3] = { | ||
89 | /* front, rear/surround, clfe */ | ||
90 | 0x02, 0x03, 0x04 | ||
91 | }; | ||
92 | |||
93 | static hda_nid_t alc880_adc_nids[3] = { | ||
94 | /* ADC0-2 */ | ||
95 | 0x07, 0x08, 0x09, | ||
96 | }; | ||
97 | |||
98 | #define ALC880_DIGOUT_NID 0x06 | ||
99 | #define ALC880_DIGIN_NID 0x0a | ||
100 | 114 | ||
101 | static hda_nid_t alc260_dac_nids[1] = { | 115 | struct semaphore bind_mutex; /* for bound controls */ |
102 | /* front */ | ||
103 | 0x02, | ||
104 | }; | ||
105 | 116 | ||
106 | static hda_nid_t alc260_adc_nids[2] = { | 117 | /* dynamic controls, init_verbs and input_mux */ |
107 | /* ADC0-1 */ | 118 | struct auto_pin_cfg autocfg; |
108 | 0x04, 0x05, | 119 | unsigned int num_kctl_alloc, num_kctl_used; |
120 | snd_kcontrol_new_t *kctl_alloc; | ||
121 | struct hda_input_mux private_imux; | ||
109 | }; | 122 | }; |
110 | 123 | ||
111 | #define ALC260_DIGOUT_NID 0x03 | ||
112 | #define ALC260_DIGIN_NID 0x06 | ||
113 | |||
114 | static struct hda_input_mux alc880_capture_source = { | ||
115 | .num_items = 4, | ||
116 | .items = { | ||
117 | { "Mic", 0x0 }, | ||
118 | { "Front Mic", 0x3 }, | ||
119 | { "Line", 0x2 }, | ||
120 | { "CD", 0x4 }, | ||
121 | }, | ||
122 | }; | ||
123 | |||
124 | static struct hda_input_mux alc260_capture_source = { | ||
125 | .num_items = 4, | ||
126 | .items = { | ||
127 | { "Mic", 0x0 }, | ||
128 | { "Front Mic", 0x1 }, | ||
129 | { "Line", 0x2 }, | ||
130 | { "CD", 0x4 }, | ||
131 | }, | ||
132 | }; | ||
133 | 124 | ||
134 | /* | 125 | /* |
135 | * input MUX handling | 126 | * input MUX handling |
@@ -160,6 +151,7 @@ static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon | |||
160 | spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); | 151 | spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); |
161 | } | 152 | } |
162 | 153 | ||
154 | |||
163 | /* | 155 | /* |
164 | * channel mode setting | 156 | * channel mode setting |
165 | */ | 157 | */ |
@@ -168,135 +160,18 @@ struct alc_channel_mode { | |||
168 | const struct hda_verb *sequence; | 160 | const struct hda_verb *sequence; |
169 | }; | 161 | }; |
170 | 162 | ||
171 | |||
172 | /* | ||
173 | * channel source setting (2/6 channel selection for 3-stack) | ||
174 | */ | ||
175 | |||
176 | /* | ||
177 | * set the path ways for 2 channel output | ||
178 | * need to set the codec line out and mic 1 pin widgets to inputs | ||
179 | */ | ||
180 | static struct hda_verb alc880_threestack_ch2_init[] = { | ||
181 | /* set pin widget 1Ah (line in) for input */ | ||
182 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
183 | /* set pin widget 18h (mic1) for input, for mic also enable the vref */ | ||
184 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
185 | /* mute the output for Line In PW */ | ||
186 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, | ||
187 | /* mute for Mic1 PW */ | ||
188 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, | ||
189 | { } /* end */ | ||
190 | }; | ||
191 | |||
192 | /* | ||
193 | * 6ch mode | ||
194 | * need to set the codec line out and mic 1 pin widgets to outputs | ||
195 | */ | ||
196 | static struct hda_verb alc880_threestack_ch6_init[] = { | ||
197 | /* set pin widget 1Ah (line in) for output */ | ||
198 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
199 | /* set pin widget 18h (mic1) for output */ | ||
200 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
201 | /* unmute the output for Line In PW */ | ||
202 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 }, | ||
203 | /* unmute for Mic1 PW */ | ||
204 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 }, | ||
205 | /* for rear channel output using Line In 1 | ||
206 | * set select widget connection (nid = 0x12) - to summer node | ||
207 | * for rear NID = 0x0f...offset 3 in connection list | ||
208 | */ | ||
209 | { 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 }, | ||
210 | /* for Mic1 - retask for center/lfe */ | ||
211 | /* set select widget connection (nid = 0x10) - to summer node for | ||
212 | * front CLFE NID = 0x0e...offset 2 in connection list | ||
213 | */ | ||
214 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 }, | ||
215 | { } /* end */ | ||
216 | }; | ||
217 | |||
218 | static struct alc_channel_mode alc880_threestack_modes[2] = { | ||
219 | { 2, alc880_threestack_ch2_init }, | ||
220 | { 6, alc880_threestack_ch6_init }, | ||
221 | }; | ||
222 | |||
223 | |||
224 | /* | ||
225 | * channel source setting (6/8 channel selection for 5-stack) | ||
226 | */ | ||
227 | |||
228 | /* set the path ways for 6 channel output | ||
229 | * need to set the codec line out and mic 1 pin widgets to inputs | ||
230 | */ | ||
231 | static struct hda_verb alc880_fivestack_ch6_init[] = { | ||
232 | /* set pin widget 1Ah (line in) for input */ | ||
233 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
234 | /* mute the output for Line In PW */ | ||
235 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, | ||
236 | { } /* end */ | ||
237 | }; | ||
238 | |||
239 | /* need to set the codec line out and mic 1 pin widgets to outputs */ | ||
240 | static struct hda_verb alc880_fivestack_ch8_init[] = { | ||
241 | /* set pin widget 1Ah (line in) for output */ | ||
242 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
243 | /* unmute the output for Line In PW */ | ||
244 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 }, | ||
245 | /* output for surround channel output using Line In 1 */ | ||
246 | /* set select widget connection (nid = 0x12) - to summer node | ||
247 | * for surr_rear NID = 0x0d...offset 1 in connection list | ||
248 | */ | ||
249 | { 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 }, | ||
250 | { } /* end */ | ||
251 | }; | ||
252 | |||
253 | static struct alc_channel_mode alc880_fivestack_modes[2] = { | ||
254 | { 6, alc880_fivestack_ch6_init }, | ||
255 | { 8, alc880_fivestack_ch8_init }, | ||
256 | }; | ||
257 | |||
258 | /* | ||
259 | * channel source setting for W810 system | ||
260 | * | ||
261 | * W810 has rear IO for: | ||
262 | * Front (DAC 02) | ||
263 | * Surround (DAC 03) | ||
264 | * Center/LFE (DAC 04) | ||
265 | * Digital out (06) | ||
266 | * | ||
267 | * The system also has a pair of internal speakers, and a headphone jack. | ||
268 | * These are both connected to Line2 on the codec, hence to DAC 02. | ||
269 | * | ||
270 | * There is a variable resistor to control the speaker or headphone | ||
271 | * volume. This is a hardware-only device without a software API. | ||
272 | * | ||
273 | * Plugging headphones in will disable the internal speakers. This is | ||
274 | * implemented in hardware, not via the driver using jack sense. In | ||
275 | * a similar fashion, plugging into the rear socket marked "front" will | ||
276 | * disable both the speakers and headphones. | ||
277 | * | ||
278 | * For input, there's a microphone jack, and an "audio in" jack. | ||
279 | * These may not do anything useful with this driver yet, because I | ||
280 | * haven't setup any initialization verbs for these yet... | ||
281 | */ | ||
282 | |||
283 | static struct alc_channel_mode alc880_w810_modes[1] = { | ||
284 | { 6, NULL } | ||
285 | }; | ||
286 | |||
287 | /* | ||
288 | */ | ||
289 | static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | 163 | static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) |
290 | { | 164 | { |
291 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 165 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
292 | struct alc_spec *spec = codec->spec; | 166 | struct alc_spec *spec = codec->spec; |
167 | int items = kcontrol->private_value ? (int)kcontrol->private_value : 2; | ||
293 | 168 | ||
294 | snd_assert(spec->channel_mode, return -ENXIO); | 169 | snd_assert(spec->channel_mode, return -ENXIO); |
295 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 170 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
296 | uinfo->count = 1; | 171 | uinfo->count = 1; |
297 | uinfo->value.enumerated.items = 2; | 172 | uinfo->value.enumerated.items = items; |
298 | if (uinfo->value.enumerated.item >= 2) | 173 | if (uinfo->value.enumerated.item >= items) |
299 | uinfo->value.enumerated.item = 1; | 174 | uinfo->value.enumerated.item = items - 1; |
300 | sprintf(uinfo->value.enumerated.name, "%dch", | 175 | sprintf(uinfo->value.enumerated.name, "%dch", |
301 | spec->channel_mode[uinfo->value.enumerated.item].channels); | 176 | spec->channel_mode[uinfo->value.enumerated.item].channels); |
302 | return 0; | 177 | return 0; |
@@ -306,10 +181,16 @@ static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc | |||
306 | { | 181 | { |
307 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 182 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
308 | struct alc_spec *spec = codec->spec; | 183 | struct alc_spec *spec = codec->spec; |
184 | int items = kcontrol->private_value ? (int)kcontrol->private_value : 2; | ||
185 | int i; | ||
309 | 186 | ||
310 | snd_assert(spec->channel_mode, return -ENXIO); | 187 | snd_assert(spec->channel_mode, return -ENXIO); |
311 | ucontrol->value.enumerated.item[0] = | 188 | for (i = 0; i < items; i++) { |
312 | (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1; | 189 | if (spec->multiout.max_channels == spec->channel_mode[i].channels) { |
190 | ucontrol->value.enumerated.item[0] = i; | ||
191 | break; | ||
192 | } | ||
193 | } | ||
313 | return 0; | 194 | return 0; |
314 | } | 195 | } |
315 | 196 | ||
@@ -335,21 +216,149 @@ static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc | |||
335 | 216 | ||
336 | 217 | ||
337 | /* | 218 | /* |
219 | * bound volume controls | ||
220 | * | ||
221 | * bind multiple volumes (# indices, from 0) | ||
222 | */ | ||
223 | |||
224 | #define AMP_VAL_IDX_SHIFT 19 | ||
225 | #define AMP_VAL_IDX_MASK (0x0f<<19) | ||
226 | |||
227 | static int alc_bind_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
228 | { | ||
229 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
230 | struct alc_spec *spec = codec->spec; | ||
231 | unsigned long pval; | ||
232 | |||
233 | down(&spec->bind_mutex); | ||
234 | pval = kcontrol->private_value; | ||
235 | kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ | ||
236 | snd_hda_mixer_amp_switch_info(kcontrol, uinfo); | ||
237 | kcontrol->private_value = pval; | ||
238 | up(&spec->bind_mutex); | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static int alc_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
243 | { | ||
244 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
245 | struct alc_spec *spec = codec->spec; | ||
246 | unsigned long pval; | ||
247 | |||
248 | down(&spec->bind_mutex); | ||
249 | pval = kcontrol->private_value; | ||
250 | kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ | ||
251 | snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); | ||
252 | kcontrol->private_value = pval; | ||
253 | up(&spec->bind_mutex); | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static int alc_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
258 | { | ||
259 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
260 | struct alc_spec *spec = codec->spec; | ||
261 | unsigned long pval; | ||
262 | int i, indices, change = 0; | ||
263 | |||
264 | down(&spec->bind_mutex); | ||
265 | pval = kcontrol->private_value; | ||
266 | indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; | ||
267 | for (i = 0; i < indices; i++) { | ||
268 | kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT); | ||
269 | change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
270 | } | ||
271 | kcontrol->private_value = pval; | ||
272 | up(&spec->bind_mutex); | ||
273 | return change; | ||
274 | } | ||
275 | |||
276 | #define ALC_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ | ||
277 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
278 | .info = alc_bind_switch_info, \ | ||
279 | .get = alc_bind_switch_get, \ | ||
280 | .put = alc_bind_switch_put, \ | ||
281 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } | ||
282 | |||
283 | #define ALC_BIND_MUTE(xname,nid,indices,dir) ALC_BIND_MUTE_MONO(xname,nid,3,indices,dir) | ||
284 | |||
285 | |||
286 | /* | ||
287 | * ALC880 3-stack model | ||
288 | * | ||
289 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) | ||
290 | * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b | ||
291 | * HP = 0x19 | ||
338 | */ | 292 | */ |
339 | 293 | ||
340 | /* 3-stack mode | 294 | static hda_nid_t alc880_dac_nids[4] = { |
341 | * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b | 295 | /* front, rear, clfe, rear_surr */ |
342 | * HP=0x19 | 296 | 0x02, 0x05, 0x04, 0x03 |
297 | }; | ||
298 | |||
299 | static hda_nid_t alc880_adc_nids[3] = { | ||
300 | /* ADC0-2 */ | ||
301 | 0x07, 0x08, 0x09, | ||
302 | }; | ||
303 | |||
304 | /* The datasheet says the node 0x07 is connected from inputs, | ||
305 | * but it shows zero connection in the real implementation on some devices. | ||
343 | */ | 306 | */ |
344 | static snd_kcontrol_new_t alc880_base_mixer[] = { | 307 | static hda_nid_t alc880_adc_nids_alt[2] = { |
308 | /* ADC1-2 */ | ||
309 | 0x08, 0x09, | ||
310 | }; | ||
311 | |||
312 | #define ALC880_DIGOUT_NID 0x06 | ||
313 | #define ALC880_DIGIN_NID 0x0a | ||
314 | |||
315 | static struct hda_input_mux alc880_capture_source = { | ||
316 | .num_items = 4, | ||
317 | .items = { | ||
318 | { "Mic", 0x0 }, | ||
319 | { "Front Mic", 0x3 }, | ||
320 | { "Line", 0x2 }, | ||
321 | { "CD", 0x4 }, | ||
322 | }, | ||
323 | }; | ||
324 | |||
325 | /* channel source setting (2/6 channel selection for 3-stack) */ | ||
326 | /* 2ch mode */ | ||
327 | static struct hda_verb alc880_threestack_ch2_init[] = { | ||
328 | /* set line-in to input, mute it */ | ||
329 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
330 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
331 | /* set mic-in to input vref 80%, mute it */ | ||
332 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
333 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
334 | { } /* end */ | ||
335 | }; | ||
336 | |||
337 | /* 6ch mode */ | ||
338 | static struct hda_verb alc880_threestack_ch6_init[] = { | ||
339 | /* set line-in to output, unmute it */ | ||
340 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
341 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
342 | /* set mic-in to output, unmute it */ | ||
343 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
344 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
345 | { } /* end */ | ||
346 | }; | ||
347 | |||
348 | static struct alc_channel_mode alc880_threestack_modes[2] = { | ||
349 | { 2, alc880_threestack_ch2_init }, | ||
350 | { 6, alc880_threestack_ch6_init }, | ||
351 | }; | ||
352 | |||
353 | static snd_kcontrol_new_t alc880_three_stack_mixer[] = { | ||
345 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 354 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
346 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 355 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
347 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | 356 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), |
348 | HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT), | 357 | ALC_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), |
349 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | 358 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), |
350 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | 359 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
351 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT), | 360 | ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), |
352 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 0x0, HDA_OUTPUT), | 361 | ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), |
353 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 362 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
354 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 363 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
355 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 364 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
@@ -360,12 +369,25 @@ static snd_kcontrol_new_t alc880_base_mixer[] = { | |||
360 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), | 369 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), |
361 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 370 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
362 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 371 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), |
363 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
364 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), | 372 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), |
373 | { | ||
374 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
375 | .name = "Channel Mode", | ||
376 | .info = alc880_ch_mode_info, | ||
377 | .get = alc880_ch_mode_get, | ||
378 | .put = alc880_ch_mode_put, | ||
379 | }, | ||
380 | { } /* end */ | ||
381 | }; | ||
382 | |||
383 | /* capture mixer elements */ | ||
384 | static snd_kcontrol_new_t alc880_capture_mixer[] = { | ||
365 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | 385 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), |
366 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | 386 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), |
367 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | 387 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), |
368 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | 388 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), |
389 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | ||
390 | HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), | ||
369 | { | 391 | { |
370 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 392 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
371 | /* The multiple "Capture Source" controls confuse alsamixer | 393 | /* The multiple "Capture Source" controls confuse alsamixer |
@@ -374,65 +396,125 @@ static snd_kcontrol_new_t alc880_base_mixer[] = { | |||
374 | */ | 396 | */ |
375 | /* .name = "Capture Source", */ | 397 | /* .name = "Capture Source", */ |
376 | .name = "Input Source", | 398 | .name = "Input Source", |
377 | .count = 2, | 399 | .count = 3, |
378 | .info = alc_mux_enum_info, | 400 | .info = alc_mux_enum_info, |
379 | .get = alc_mux_enum_get, | 401 | .get = alc_mux_enum_get, |
380 | .put = alc_mux_enum_put, | 402 | .put = alc_mux_enum_put, |
381 | }, | 403 | }, |
404 | { } /* end */ | ||
405 | }; | ||
406 | |||
407 | /* capture mixer elements (in case NID 0x07 not available) */ | ||
408 | static snd_kcontrol_new_t alc880_capture_alt_mixer[] = { | ||
409 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
410 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
411 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
412 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
382 | { | 413 | { |
383 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 414 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
384 | .name = "Channel Mode", | 415 | /* The multiple "Capture Source" controls confuse alsamixer |
385 | .info = alc880_ch_mode_info, | 416 | * So call somewhat different.. |
386 | .get = alc880_ch_mode_get, | 417 | * FIXME: the controls appear in the "playback" view! |
387 | .put = alc880_ch_mode_put, | 418 | */ |
419 | /* .name = "Capture Source", */ | ||
420 | .name = "Input Source", | ||
421 | .count = 2, | ||
422 | .info = alc_mux_enum_info, | ||
423 | .get = alc_mux_enum_get, | ||
424 | .put = alc_mux_enum_put, | ||
388 | }, | 425 | }, |
389 | { } /* end */ | 426 | { } /* end */ |
390 | }; | 427 | }; |
391 | 428 | ||
392 | /* 5-stack mode | 429 | |
393 | * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16 | 430 | |
394 | * Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19 | 431 | /* |
432 | * ALC880 5-stack model | ||
433 | * | ||
434 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd) | ||
435 | * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 | ||
436 | * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 | ||
395 | */ | 437 | */ |
438 | |||
439 | /* additional mixers to alc880_three_stack_mixer */ | ||
396 | static snd_kcontrol_new_t alc880_five_stack_mixer[] = { | 440 | static snd_kcontrol_new_t alc880_five_stack_mixer[] = { |
441 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
442 | ALC_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT), | ||
443 | { } /* end */ | ||
444 | }; | ||
445 | |||
446 | /* channel source setting (6/8 channel selection for 5-stack) */ | ||
447 | /* 6ch mode */ | ||
448 | static struct hda_verb alc880_fivestack_ch6_init[] = { | ||
449 | /* set line-in to input, mute it */ | ||
450 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
451 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
452 | { } /* end */ | ||
453 | }; | ||
454 | |||
455 | /* 8ch mode */ | ||
456 | static struct hda_verb alc880_fivestack_ch8_init[] = { | ||
457 | /* set line-in to output, unmute it */ | ||
458 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
459 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
460 | { } /* end */ | ||
461 | }; | ||
462 | |||
463 | static struct alc_channel_mode alc880_fivestack_modes[2] = { | ||
464 | { 6, alc880_fivestack_ch6_init }, | ||
465 | { 8, alc880_fivestack_ch8_init }, | ||
466 | }; | ||
467 | |||
468 | |||
469 | /* | ||
470 | * ALC880 6-stack model | ||
471 | * | ||
472 | * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f) | ||
473 | * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, | ||
474 | * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b | ||
475 | */ | ||
476 | |||
477 | static hda_nid_t alc880_6st_dac_nids[4] = { | ||
478 | /* front, rear, clfe, rear_surr */ | ||
479 | 0x02, 0x03, 0x04, 0x05 | ||
480 | }; | ||
481 | |||
482 | static struct hda_input_mux alc880_6stack_capture_source = { | ||
483 | .num_items = 4, | ||
484 | .items = { | ||
485 | { "Mic", 0x0 }, | ||
486 | { "Front Mic", 0x1 }, | ||
487 | { "Line", 0x2 }, | ||
488 | { "CD", 0x4 }, | ||
489 | }, | ||
490 | }; | ||
491 | |||
492 | /* fixed 8-channels */ | ||
493 | static struct alc_channel_mode alc880_sixstack_modes[1] = { | ||
494 | { 8, NULL }, | ||
495 | }; | ||
496 | |||
497 | static snd_kcontrol_new_t alc880_six_stack_mixer[] = { | ||
397 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 498 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
398 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 499 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
399 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | 500 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
400 | HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT), | 501 | ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), |
401 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | 502 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), |
402 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | 503 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
403 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), | 504 | ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), |
404 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), | 505 | ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), |
405 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 506 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), |
406 | HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 0x0, HDA_OUTPUT), | 507 | ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), |
407 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 508 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
408 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 509 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
409 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 510 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
410 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 511 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
411 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 512 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
412 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 513 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
413 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), | 514 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
414 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), | 515 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
415 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 516 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
416 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 517 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), |
417 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
418 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), | ||
419 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | ||
420 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | ||
421 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | ||
422 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | ||
423 | { | ||
424 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
425 | /* The multiple "Capture Source" controls confuse alsamixer | ||
426 | * So call somewhat different.. | ||
427 | * FIXME: the controls appear in the "playback" view! | ||
428 | */ | ||
429 | /* .name = "Capture Source", */ | ||
430 | .name = "Input Source", | ||
431 | .count = 2, | ||
432 | .info = alc_mux_enum_info, | ||
433 | .get = alc_mux_enum_get, | ||
434 | .put = alc_mux_enum_put, | ||
435 | }, | ||
436 | { | 518 | { |
437 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 519 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
438 | .name = "Channel Mode", | 520 | .name = "Channel Mode", |
@@ -443,39 +525,169 @@ static snd_kcontrol_new_t alc880_five_stack_mixer[] = { | |||
443 | { } /* end */ | 525 | { } /* end */ |
444 | }; | 526 | }; |
445 | 527 | ||
528 | |||
529 | /* | ||
530 | * ALC880 W810 model | ||
531 | * | ||
532 | * W810 has rear IO for: | ||
533 | * Front (DAC 02) | ||
534 | * Surround (DAC 03) | ||
535 | * Center/LFE (DAC 04) | ||
536 | * Digital out (06) | ||
537 | * | ||
538 | * The system also has a pair of internal speakers, and a headphone jack. | ||
539 | * These are both connected to Line2 on the codec, hence to DAC 02. | ||
540 | * | ||
541 | * There is a variable resistor to control the speaker or headphone | ||
542 | * volume. This is a hardware-only device without a software API. | ||
543 | * | ||
544 | * Plugging headphones in will disable the internal speakers. This is | ||
545 | * implemented in hardware, not via the driver using jack sense. In | ||
546 | * a similar fashion, plugging into the rear socket marked "front" will | ||
547 | * disable both the speakers and headphones. | ||
548 | * | ||
549 | * For input, there's a microphone jack, and an "audio in" jack. | ||
550 | * These may not do anything useful with this driver yet, because I | ||
551 | * haven't setup any initialization verbs for these yet... | ||
552 | */ | ||
553 | |||
554 | static hda_nid_t alc880_w810_dac_nids[3] = { | ||
555 | /* front, rear/surround, clfe */ | ||
556 | 0x02, 0x03, 0x04 | ||
557 | }; | ||
558 | |||
559 | /* fixed 6 channels */ | ||
560 | static struct alc_channel_mode alc880_w810_modes[1] = { | ||
561 | { 6, NULL } | ||
562 | }; | ||
563 | |||
564 | /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */ | ||
446 | static snd_kcontrol_new_t alc880_w810_base_mixer[] = { | 565 | static snd_kcontrol_new_t alc880_w810_base_mixer[] = { |
447 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 566 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
448 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 567 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
449 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 568 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
450 | HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 569 | ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), |
451 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | 570 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), |
452 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | 571 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
453 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), | 572 | ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), |
454 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), | 573 | ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), |
455 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 574 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
456 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | 575 | { } /* end */ |
457 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | 576 | }; |
458 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | 577 | |
459 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | 578 | |
460 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | 579 | /* |
461 | HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), | 580 | * Z710V model |
581 | * | ||
582 | * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) | ||
583 | * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a | ||
584 | */ | ||
585 | |||
586 | static hda_nid_t alc880_z71v_dac_nids[1] = { | ||
587 | 0x02 | ||
588 | }; | ||
589 | #define ALC880_Z71V_HP_DAC 0x03 | ||
590 | |||
591 | /* fixed 2 channels */ | ||
592 | static struct alc_channel_mode alc880_2_jack_modes[1] = { | ||
593 | { 2, NULL } | ||
594 | }; | ||
595 | |||
596 | static snd_kcontrol_new_t alc880_z71v_mixer[] = { | ||
597 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
598 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
599 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
600 | ALC_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), | ||
601 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
602 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
603 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
604 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
605 | { } /* end */ | ||
606 | }; | ||
607 | |||
608 | |||
609 | /* FIXME! */ | ||
610 | /* | ||
611 | * ALC880 F1734 model | ||
612 | * | ||
613 | * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d) | ||
614 | * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18 | ||
615 | */ | ||
616 | |||
617 | static hda_nid_t alc880_f1734_dac_nids[1] = { | ||
618 | 0x03 | ||
619 | }; | ||
620 | #define ALC880_F1734_HP_DAC 0x02 | ||
621 | |||
622 | static snd_kcontrol_new_t alc880_f1734_mixer[] = { | ||
623 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
624 | ALC_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), | ||
625 | HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
626 | ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | ||
627 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
628 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
629 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
630 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
631 | { } /* end */ | ||
632 | }; | ||
633 | |||
634 | |||
635 | /* FIXME! */ | ||
636 | /* | ||
637 | * ALC880 ASUS model | ||
638 | * | ||
639 | * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) | ||
640 | * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, | ||
641 | * Mic = 0x18, Line = 0x1a | ||
642 | */ | ||
643 | |||
644 | #define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */ | ||
645 | #define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */ | ||
646 | |||
647 | static snd_kcontrol_new_t alc880_asus_mixer[] = { | ||
648 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
649 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
650 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
651 | ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
652 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
653 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
654 | ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
655 | ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
656 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
657 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
658 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
659 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
660 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
661 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
462 | { | 662 | { |
463 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 663 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
464 | /* The multiple "Capture Source" controls confuse alsamixer | 664 | .name = "Channel Mode", |
465 | * So call somewhat different.. | 665 | .info = alc880_ch_mode_info, |
466 | * FIXME: the controls appear in the "playback" view! | 666 | .get = alc880_ch_mode_get, |
467 | */ | 667 | .put = alc880_ch_mode_put, |
468 | /* .name = "Capture Source", */ | ||
469 | .name = "Input Source", | ||
470 | .count = 3, | ||
471 | .info = alc_mux_enum_info, | ||
472 | .get = alc_mux_enum_get, | ||
473 | .put = alc_mux_enum_put, | ||
474 | }, | 668 | }, |
475 | { } /* end */ | 669 | { } /* end */ |
476 | }; | 670 | }; |
477 | 671 | ||
672 | /* FIXME! */ | ||
478 | /* | 673 | /* |
674 | * ALC880 ASUS W1V model | ||
675 | * | ||
676 | * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) | ||
677 | * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, | ||
678 | * Mic = 0x18, Line = 0x1a, Line2 = 0x1b | ||
679 | */ | ||
680 | |||
681 | /* additional mixers to alc880_asus_mixer */ | ||
682 | static snd_kcontrol_new_t alc880_asus_w1v_mixer[] = { | ||
683 | HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT), | ||
684 | HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT), | ||
685 | { } /* end */ | ||
686 | }; | ||
687 | |||
688 | |||
689 | /* | ||
690 | * build control elements | ||
479 | */ | 691 | */ |
480 | static int alc_build_controls(struct hda_codec *codec) | 692 | static int alc_build_controls(struct hda_codec *codec) |
481 | { | 693 | { |
@@ -502,227 +714,297 @@ static int alc_build_controls(struct hda_codec *codec) | |||
502 | return 0; | 714 | return 0; |
503 | } | 715 | } |
504 | 716 | ||
717 | |||
505 | /* | 718 | /* |
506 | * initialize the codec volumes, etc | 719 | * initialize the codec volumes, etc |
507 | */ | 720 | */ |
508 | 721 | ||
509 | static struct hda_verb alc880_init_verbs_three_stack[] = { | 722 | /* |
510 | /* Line In pin widget for input */ | 723 | * generic initialization of ADC, input mixers and output mixers |
511 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 724 | */ |
512 | /* CD pin widget for input */ | 725 | static struct hda_verb alc880_volume_init_verbs[] = { |
513 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 726 | /* |
514 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | 727 | * Unmute ADC0-2 and set the default input to mic-in |
515 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 728 | */ |
516 | /* Mic2 (front panel) pin widget for input and vref at 80% */ | 729 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
517 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 730 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
518 | /* unmute amp left and right */ | 731 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, |
519 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 732 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
520 | /* set connection select to line in (default select for this ADC) */ | 733 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
521 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x02}, | 734 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
522 | /* unmute front mixer amp left (volume = 0) */ | 735 | |
523 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 736 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
524 | /* mute pin widget amp left and right (no gain on this amp) */ | 737 | * mixer widget |
525 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
526 | /* unmute rear mixer amp left and right (volume = 0) */ | ||
527 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
528 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
529 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
530 | /* unmute rear mixer amp left and right (volume = 0) */ | ||
531 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
532 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
533 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
534 | |||
535 | /* using rear surround as the path for headphone output */ | ||
536 | /* unmute rear surround mixer amp left and right (volume = 0) */ | ||
537 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
538 | /* PASD 3 stack boards use the Mic 2 as the headphone output */ | ||
539 | /* need to program the selector associated with the Mic 2 pin widget to | ||
540 | * surround path (index 0x01) for headphone output */ | ||
541 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
542 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
543 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
544 | /* need to retask the Mic 2 pin widget to output */ | ||
545 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
546 | |||
547 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B) | ||
548 | * to support the input path of analog loopback | ||
549 | * Note: PASD motherboards uses the Line In 2 as the input for front panel | 738 | * Note: PASD motherboards uses the Line In 2 as the input for front panel |
550 | * mic (mic 2) | 739 | * mic (mic 2) |
551 | */ | 740 | */ |
552 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ | 741 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
553 | /* unmute CD */ | 742 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
554 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 743 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
555 | /* unmute Line In */ | 744 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
556 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | 745 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, |
557 | /* unmute Mic 1 */ | 746 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
558 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 747 | |
559 | /* unmute Line In 2 (for PASD boards Mic 2) */ | 748 | /* |
560 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, | 749 | * Set up output mixers (0x0c - 0x0f) |
561 | |||
562 | /* Unmute input amps for the line out paths to support the output path of | ||
563 | * analog loopback | ||
564 | * the mixers on the output path has 2 inputs, one from the DAC and one | ||
565 | * from the mixer | ||
566 | */ | 750 | */ |
567 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 751 | /* set vol=0 to output mixers */ |
568 | /* Unmute Front out path */ | 752 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
569 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 753 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
570 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 754 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
571 | /* Unmute Surround (used as HP) out path */ | 755 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
572 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 756 | /* set up input amps for analog loopback */ |
573 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 757 | /* Amp Indices: DAC = 0, mixer = 1 */ |
574 | /* Unmute C/LFE out path */ | 758 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
575 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 759 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
576 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */ | 760 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
577 | /* Unmute rear Surround out path */ | 761 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
578 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 762 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
579 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 763 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
764 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
765 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
580 | 766 | ||
581 | { } | 767 | { } |
582 | }; | 768 | }; |
583 | 769 | ||
584 | static struct hda_verb alc880_init_verbs_five_stack[] = { | 770 | /* |
585 | /* Line In pin widget for input */ | 771 | * 3-stack pin configuration: |
586 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 772 | * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b |
587 | /* CD pin widget for input */ | 773 | */ |
588 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 774 | static struct hda_verb alc880_pin_3stack_init_verbs[] = { |
589 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | 775 | /* |
590 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 776 | * preset connection lists of input pins |
591 | /* Mic2 (front panel) pin widget for input and vref at 80% */ | 777 | * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround |
592 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
593 | /* unmute amp left and right */ | ||
594 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
595 | /* set connection select to line in (default select for this ADC) */ | ||
596 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
597 | /* unmute front mixer amp left and right (volume = 0) */ | ||
598 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
599 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
600 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
601 | /* five rear and clfe */ | ||
602 | /* unmute rear mixer amp left and right (volume = 0) */ | ||
603 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
604 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
605 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
606 | /* unmute clfe mixer amp left and right (volume = 0) */ | ||
607 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
608 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
609 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
610 | |||
611 | /* using rear surround as the path for headphone output */ | ||
612 | /* unmute rear surround mixer amp left and right (volume = 0) */ | ||
613 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
614 | /* PASD 3 stack boards use the Mic 2 as the headphone output */ | ||
615 | /* need to program the selector associated with the Mic 2 pin widget to | ||
616 | * surround path (index 0x01) for headphone output | ||
617 | */ | ||
618 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
619 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
620 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
621 | /* need to retask the Mic 2 pin widget to output */ | ||
622 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
623 | |||
624 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer | ||
625 | * widget(nid=0x0B) to support the input path of analog loopback | ||
626 | */ | 778 | */ |
627 | /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */ | 779 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ |
628 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/ | 780 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ |
629 | /* unmute CD */ | 781 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ |
630 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 782 | |
631 | /* unmute Line In */ | 783 | /* |
632 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | 784 | * Set pin mode and muting |
633 | /* unmute Mic 1 */ | ||
634 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
635 | /* unmute Line In 2 (for PASD boards Mic 2) */ | ||
636 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, | ||
637 | |||
638 | /* Unmute input amps for the line out paths to support the output path of | ||
639 | * analog loopback | ||
640 | * the mixers on the output path has 2 inputs, one from the DAC and | ||
641 | * one from the mixer | ||
642 | */ | 785 | */ |
643 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 786 | /* set front pin widgets 0x14 for output */ |
644 | /* Unmute Front out path */ | 787 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
645 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 788 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
646 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 789 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ |
647 | /* Unmute Surround (used as HP) out path */ | 790 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
648 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 791 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
649 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 792 | /* Mic2 (as headphone out) for HP output */ |
650 | /* Unmute C/LFE out path */ | 793 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
651 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 794 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
652 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */ | 795 | /* Line In pin widget for input */ |
653 | /* Unmute rear Surround out path */ | 796 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
654 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 797 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
655 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 798 | /* Line2 (as front mic) pin widget for input and vref at 80% */ |
799 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
800 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
801 | /* CD pin widget for input */ | ||
802 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
656 | 803 | ||
657 | { } | 804 | { } |
658 | }; | 805 | }; |
659 | 806 | ||
660 | static struct hda_verb alc880_w810_init_verbs[] = { | 807 | /* |
661 | /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */ | 808 | * 5-stack pin configuration: |
662 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 809 | * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19, |
663 | 810 | * line-in/side = 0x1a, f-mic = 0x1b | |
664 | /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */ | 811 | */ |
665 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180}, | 812 | static struct hda_verb alc880_pin_5stack_init_verbs[] = { |
666 | 813 | /* | |
667 | /* front channel selector/amp: output 0: unmuted, max volume */ | 814 | * preset connection lists of input pins |
668 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 815 | * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround |
669 | 816 | */ | |
670 | /* front out pin: muted, (no volume selection) */ | 817 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ |
671 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 818 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */ |
672 | |||
673 | /* front out pin: NOT headphone enable, out enable, vref disabled */ | ||
674 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
675 | 819 | ||
820 | /* | ||
821 | * Set pin mode and muting | ||
822 | */ | ||
823 | /* set pin widgets 0x14-0x17 for output */ | ||
824 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
825 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
826 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
827 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
828 | /* unmute pins for output (no gain on this amp) */ | ||
829 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
830 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
831 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
832 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
676 | 833 | ||
677 | /* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */ | 834 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ |
678 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 835 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
836 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
837 | /* Mic2 (as headphone out) for HP output */ | ||
838 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
839 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
840 | /* Line In pin widget for input */ | ||
841 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
842 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
843 | /* Line2 (as front mic) pin widget for input and vref at 80% */ | ||
844 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
845 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
846 | /* CD pin widget for input */ | ||
847 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
679 | 848 | ||
680 | /* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */ | 849 | { } |
681 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180}, | 850 | }; |
682 | 851 | ||
683 | /* surround channel selector/amp: output 0: unmuted, max volume */ | 852 | /* |
684 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 853 | * W810 pin configuration: |
854 | * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b | ||
855 | */ | ||
856 | static struct hda_verb alc880_pin_w810_init_verbs[] = { | ||
857 | /* hphone/speaker input selector: front DAC */ | ||
858 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
685 | 859 | ||
686 | /* surround out pin: muted, (no volume selection) */ | 860 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
687 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 861 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
862 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
863 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
864 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
865 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
688 | 866 | ||
689 | /* surround out pin: NOT headphone enable, out enable, vref disabled */ | 867 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
690 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 868 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
691 | 869 | ||
870 | { } | ||
871 | }; | ||
692 | 872 | ||
693 | /* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */ | 873 | /* |
694 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 874 | * Z71V pin configuration: |
875 | * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?) | ||
876 | */ | ||
877 | static struct hda_verb alc880_pin_z71v_init_verbs[] = { | ||
878 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
879 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
880 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
881 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
695 | 882 | ||
696 | /* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */ | 883 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
697 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180}, | 884 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
885 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
886 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
698 | 887 | ||
699 | /* c/lfe channel selector/amp: output 0: unmuted, max volume */ | 888 | { } |
700 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 889 | }; |
701 | 890 | ||
702 | /* c/lfe out pin: muted, (no volume selection) */ | 891 | /* |
703 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 892 | * 6-stack pin configuration: |
893 | * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19, | ||
894 | * line = 0x1a, HP = 0x1b | ||
895 | */ | ||
896 | static struct hda_verb alc880_pin_6stack_init_verbs[] = { | ||
897 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
898 | |||
899 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
900 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
901 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
902 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
903 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
904 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
905 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
906 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
907 | |||
908 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
909 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
910 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
911 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
912 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
913 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
914 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
915 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
916 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
917 | |||
918 | { } | ||
919 | }; | ||
704 | 920 | ||
705 | /* c/lfe out pin: NOT headphone enable, out enable, vref disabled */ | 921 | /* FIXME! */ |
706 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 922 | /* |
923 | * F1734 pin configuration: | ||
924 | * HP = 0x14, speaker-out = 0x15, mic = 0x18 | ||
925 | */ | ||
926 | static struct hda_verb alc880_pin_f1734_init_verbs[] = { | ||
927 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
928 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
929 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
930 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
931 | |||
932 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
933 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
934 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
935 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
936 | |||
937 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
938 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
939 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
940 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
941 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
942 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
943 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
944 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
945 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
707 | 946 | ||
947 | { } | ||
948 | }; | ||
708 | 949 | ||
709 | /* hphone/speaker input selector: front DAC */ | 950 | /* FIXME! */ |
710 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, | 951 | /* |
952 | * ASUS pin configuration: | ||
953 | * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a | ||
954 | */ | ||
955 | static struct hda_verb alc880_pin_asus_init_verbs[] = { | ||
956 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
957 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
958 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
959 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
960 | |||
961 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
962 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
963 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
964 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
965 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
966 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
967 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
968 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
969 | |||
970 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
971 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
972 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
973 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
974 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
975 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
976 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
977 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
978 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
979 | |||
980 | { } | ||
981 | }; | ||
711 | 982 | ||
712 | /* hphone/speaker out pin: muted, (no volume selection) */ | 983 | /* Enable GPIO mask and set output */ |
713 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 984 | static struct hda_verb alc880_gpio1_init_verbs[] = { |
985 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
986 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
987 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
988 | }; | ||
714 | 989 | ||
715 | /* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */ | 990 | /* Enable GPIO mask and set output */ |
716 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 991 | static struct hda_verb alc880_gpio2_init_verbs[] = { |
992 | {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, | ||
993 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, | ||
994 | {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, | ||
995 | }; | ||
717 | 996 | ||
718 | 997 | ||
719 | { } | 998 | /* |
720 | }; | 999 | */ |
721 | 1000 | ||
722 | static int alc_init(struct hda_codec *codec) | 1001 | static int alc_init(struct hda_codec *codec) |
723 | { | 1002 | { |
724 | struct alc_spec *spec = codec->spec; | 1003 | struct alc_spec *spec = codec->spec; |
725 | snd_hda_sequence_write(codec, spec->init_verbs); | 1004 | unsigned int i; |
1005 | |||
1006 | for (i = 0; i < spec->num_init_verbs; i++) | ||
1007 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | ||
726 | return 0; | 1008 | return 0; |
727 | } | 1009 | } |
728 | 1010 | ||
@@ -736,9 +1018,8 @@ static int alc_resume(struct hda_codec *codec) | |||
736 | int i; | 1018 | int i; |
737 | 1019 | ||
738 | alc_init(codec); | 1020 | alc_init(codec); |
739 | for (i = 0; i < spec->num_mixers; i++) { | 1021 | for (i = 0; i < spec->num_mixers; i++) |
740 | snd_hda_resume_ctls(codec, spec->mixers[i]); | 1022 | snd_hda_resume_ctls(codec, spec->mixers[i]); |
741 | } | ||
742 | if (spec->multiout.dig_out_nid) | 1023 | if (spec->multiout.dig_out_nid) |
743 | snd_hda_resume_spdif_out(codec); | 1024 | snd_hda_resume_spdif_out(codec); |
744 | if (spec->dig_in_nid) | 1025 | if (spec->dig_in_nid) |
@@ -830,7 +1111,7 @@ static struct hda_pcm_stream alc880_pcm_analog_playback = { | |||
830 | .substreams = 1, | 1111 | .substreams = 1, |
831 | .channels_min = 2, | 1112 | .channels_min = 2, |
832 | .channels_max = 8, | 1113 | .channels_max = 8, |
833 | .nid = 0x02, /* NID to query formats and rates */ | 1114 | /* NID is set in alc_build_pcms */ |
834 | .ops = { | 1115 | .ops = { |
835 | .open = alc880_playback_pcm_open, | 1116 | .open = alc880_playback_pcm_open, |
836 | .prepare = alc880_playback_pcm_prepare, | 1117 | .prepare = alc880_playback_pcm_prepare, |
@@ -842,7 +1123,7 @@ static struct hda_pcm_stream alc880_pcm_analog_capture = { | |||
842 | .substreams = 2, | 1123 | .substreams = 2, |
843 | .channels_min = 2, | 1124 | .channels_min = 2, |
844 | .channels_max = 2, | 1125 | .channels_max = 2, |
845 | .nid = 0x07, /* NID to query formats and rates */ | 1126 | /* NID is set in alc_build_pcms */ |
846 | .ops = { | 1127 | .ops = { |
847 | .prepare = alc880_capture_pcm_prepare, | 1128 | .prepare = alc880_capture_pcm_prepare, |
848 | .cleanup = alc880_capture_pcm_cleanup | 1129 | .cleanup = alc880_capture_pcm_cleanup |
@@ -878,7 +1159,9 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
878 | 1159 | ||
879 | info->name = spec->stream_name_analog; | 1160 | info->name = spec->stream_name_analog; |
880 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); | 1161 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); |
1162 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; | ||
881 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); | 1163 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); |
1164 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; | ||
882 | 1165 | ||
883 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0; | 1166 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0; |
884 | for (i = 0; i < spec->num_channel_mode; i++) { | 1167 | for (i = 0; i < spec->num_channel_mode; i++) { |
@@ -906,7 +1189,18 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
906 | 1189 | ||
907 | static void alc_free(struct hda_codec *codec) | 1190 | static void alc_free(struct hda_codec *codec) |
908 | { | 1191 | { |
909 | kfree(codec->spec); | 1192 | struct alc_spec *spec = codec->spec; |
1193 | unsigned int i; | ||
1194 | |||
1195 | if (! spec) | ||
1196 | return; | ||
1197 | |||
1198 | if (spec->kctl_alloc) { | ||
1199 | for (i = 0; i < spec->num_kctl_used; i++) | ||
1200 | kfree(spec->kctl_alloc[i].name); | ||
1201 | kfree(spec->kctl_alloc); | ||
1202 | } | ||
1203 | kfree(spec); | ||
910 | } | 1204 | } |
911 | 1205 | ||
912 | /* | 1206 | /* |
@@ -921,153 +1215,915 @@ static struct hda_codec_ops alc_patch_ops = { | |||
921 | #endif | 1215 | #endif |
922 | }; | 1216 | }; |
923 | 1217 | ||
1218 | |||
1219 | /* | ||
1220 | * Test configuration for debugging | ||
1221 | * | ||
1222 | * Almost all inputs/outputs are enabled. I/O pins can be configured via | ||
1223 | * enum controls. | ||
1224 | */ | ||
1225 | #ifdef CONFIG_SND_DEBUG | ||
1226 | static hda_nid_t alc880_test_dac_nids[4] = { | ||
1227 | 0x02, 0x03, 0x04, 0x05 | ||
1228 | }; | ||
1229 | |||
1230 | static struct hda_input_mux alc880_test_capture_source = { | ||
1231 | .num_items = 5, | ||
1232 | .items = { | ||
1233 | { "In-1", 0x0 }, | ||
1234 | { "In-2", 0x1 }, | ||
1235 | { "In-3", 0x2 }, | ||
1236 | { "In-4", 0x3 }, | ||
1237 | { "CD", 0x4 }, | ||
1238 | }, | ||
1239 | }; | ||
1240 | |||
1241 | static struct alc_channel_mode alc880_test_modes[4] = { | ||
1242 | { 2, NULL }, | ||
1243 | { 4, NULL }, | ||
1244 | { 6, NULL }, | ||
1245 | { 8, NULL }, | ||
1246 | }; | ||
1247 | |||
1248 | static int alc_test_pin_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
1249 | { | ||
1250 | static char *texts[] = { | ||
1251 | "N/A", "Line Out", "HP Out", | ||
1252 | "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%" | ||
1253 | }; | ||
1254 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1255 | uinfo->count = 1; | ||
1256 | uinfo->value.enumerated.items = 8; | ||
1257 | if (uinfo->value.enumerated.item >= 8) | ||
1258 | uinfo->value.enumerated.item = 7; | ||
1259 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
1260 | return 0; | ||
1261 | } | ||
1262 | |||
1263 | static int alc_test_pin_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1264 | { | ||
1265 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1266 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1267 | unsigned int pin_ctl, item = 0; | ||
1268 | |||
1269 | pin_ctl = snd_hda_codec_read(codec, nid, 0, | ||
1270 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
1271 | if (pin_ctl & AC_PINCTL_OUT_EN) { | ||
1272 | if (pin_ctl & AC_PINCTL_HP_EN) | ||
1273 | item = 2; | ||
1274 | else | ||
1275 | item = 1; | ||
1276 | } else if (pin_ctl & AC_PINCTL_IN_EN) { | ||
1277 | switch (pin_ctl & AC_PINCTL_VREFEN) { | ||
1278 | case AC_PINCTL_VREF_HIZ: item = 3; break; | ||
1279 | case AC_PINCTL_VREF_50: item = 4; break; | ||
1280 | case AC_PINCTL_VREF_GRD: item = 5; break; | ||
1281 | case AC_PINCTL_VREF_80: item = 6; break; | ||
1282 | case AC_PINCTL_VREF_100: item = 7; break; | ||
1283 | } | ||
1284 | } | ||
1285 | ucontrol->value.enumerated.item[0] = item; | ||
1286 | return 0; | ||
1287 | } | ||
1288 | |||
1289 | static int alc_test_pin_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1290 | { | ||
1291 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1292 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1293 | static unsigned int ctls[] = { | ||
1294 | 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN, | ||
1295 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ, | ||
1296 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_50, | ||
1297 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD, | ||
1298 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80, | ||
1299 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_100, | ||
1300 | }; | ||
1301 | unsigned int old_ctl, new_ctl; | ||
1302 | |||
1303 | old_ctl = snd_hda_codec_read(codec, nid, 0, | ||
1304 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
1305 | new_ctl = ctls[ucontrol->value.enumerated.item[0]]; | ||
1306 | if (old_ctl != new_ctl) { | ||
1307 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); | ||
1308 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1309 | ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000); | ||
1310 | return 1; | ||
1311 | } | ||
1312 | return 0; | ||
1313 | } | ||
1314 | |||
1315 | static int alc_test_pin_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
1316 | { | ||
1317 | static char *texts[] = { | ||
1318 | "Front", "Surround", "CLFE", "Side" | ||
1319 | }; | ||
1320 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1321 | uinfo->count = 1; | ||
1322 | uinfo->value.enumerated.items = 4; | ||
1323 | if (uinfo->value.enumerated.item >= 4) | ||
1324 | uinfo->value.enumerated.item = 3; | ||
1325 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
1326 | return 0; | ||
1327 | } | ||
1328 | |||
1329 | static int alc_test_pin_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1330 | { | ||
1331 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1332 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1333 | unsigned int sel; | ||
1334 | |||
1335 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); | ||
1336 | ucontrol->value.enumerated.item[0] = sel & 3; | ||
1337 | return 0; | ||
1338 | } | ||
1339 | |||
1340 | static int alc_test_pin_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1341 | { | ||
1342 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1343 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1344 | unsigned int sel; | ||
1345 | |||
1346 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; | ||
1347 | if (ucontrol->value.enumerated.item[0] != sel) { | ||
1348 | sel = ucontrol->value.enumerated.item[0] & 3; | ||
1349 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel); | ||
1350 | return 1; | ||
1351 | } | ||
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1355 | #define PIN_CTL_TEST(xname,nid) { \ | ||
1356 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1357 | .name = xname, \ | ||
1358 | .info = alc_test_pin_ctl_info, \ | ||
1359 | .get = alc_test_pin_ctl_get, \ | ||
1360 | .put = alc_test_pin_ctl_put, \ | ||
1361 | .private_value = nid \ | ||
1362 | } | ||
1363 | |||
1364 | #define PIN_SRC_TEST(xname,nid) { \ | ||
1365 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1366 | .name = xname, \ | ||
1367 | .info = alc_test_pin_src_info, \ | ||
1368 | .get = alc_test_pin_src_get, \ | ||
1369 | .put = alc_test_pin_src_put, \ | ||
1370 | .private_value = nid \ | ||
1371 | } | ||
1372 | |||
1373 | static snd_kcontrol_new_t alc880_test_mixer[] = { | ||
1374 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
1375 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
1376 | HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), | ||
1377 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
1378 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
1379 | ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
1380 | ALC_BIND_MUTE("CLFE Playback Volume", 0x0e, 2, HDA_INPUT), | ||
1381 | ALC_BIND_MUTE("Side Playback Volume", 0x0f, 2, HDA_INPUT), | ||
1382 | PIN_CTL_TEST("Front Pin Mode", 0x14), | ||
1383 | PIN_CTL_TEST("Surround Pin Mode", 0x15), | ||
1384 | PIN_CTL_TEST("CLFE Pin Mode", 0x16), | ||
1385 | PIN_CTL_TEST("Side Pin Mode", 0x17), | ||
1386 | PIN_CTL_TEST("In-1 Pin Mode", 0x18), | ||
1387 | PIN_CTL_TEST("In-2 Pin Mode", 0x19), | ||
1388 | PIN_CTL_TEST("In-3 Pin Mode", 0x1a), | ||
1389 | PIN_CTL_TEST("In-4 Pin Mode", 0x1b), | ||
1390 | PIN_SRC_TEST("In-1 Pin Source", 0x18), | ||
1391 | PIN_SRC_TEST("In-2 Pin Source", 0x19), | ||
1392 | PIN_SRC_TEST("In-3 Pin Source", 0x1a), | ||
1393 | PIN_SRC_TEST("In-4 Pin Source", 0x1b), | ||
1394 | HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
1395 | HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
1396 | HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
1397 | HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
1398 | HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT), | ||
1399 | HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT), | ||
1400 | HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT), | ||
1401 | HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), | ||
1402 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), | ||
1403 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), | ||
1404 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
1405 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
1406 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
1407 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
1408 | { | ||
1409 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1410 | .name = "Input Source", | ||
1411 | .count = 2, | ||
1412 | .info = alc_mux_enum_info, | ||
1413 | .get = alc_mux_enum_get, | ||
1414 | .put = alc_mux_enum_put, | ||
1415 | }, | ||
1416 | { | ||
1417 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1418 | .name = "Channel Mode", | ||
1419 | .info = alc880_ch_mode_info, | ||
1420 | .get = alc880_ch_mode_get, | ||
1421 | .put = alc880_ch_mode_put, | ||
1422 | }, | ||
1423 | { } /* end */ | ||
1424 | }; | ||
1425 | |||
1426 | static struct hda_verb alc880_test_init_verbs[] = { | ||
1427 | /* Unmute inputs of 0x0c - 0x0f */ | ||
1428 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1429 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1430 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1431 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1432 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1433 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1434 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1435 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1436 | /* Vol output for 0x0c-0x0f */ | ||
1437 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1438 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1439 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1440 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1441 | /* Set output pins 0x14-0x17 */ | ||
1442 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1443 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1444 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1445 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1446 | /* Unmute output pins 0x14-0x17 */ | ||
1447 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1448 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1449 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1450 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1451 | /* Set input pins 0x18-0x1c */ | ||
1452 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1453 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1454 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1455 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1456 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1457 | /* Mute input pins 0x18-0x1b */ | ||
1458 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1459 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1460 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1461 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1462 | /* ADC set up */ | ||
1463 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1464 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1465 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1466 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1467 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1468 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1469 | /* Analog input/passthru */ | ||
1470 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1471 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1472 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
1473 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
1474 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
1475 | { } | ||
1476 | }; | ||
1477 | #endif | ||
1478 | |||
924 | /* | 1479 | /* |
925 | */ | 1480 | */ |
926 | 1481 | ||
927 | static struct hda_board_config alc880_cfg_tbl[] = { | 1482 | static struct hda_board_config alc880_cfg_tbl[] = { |
928 | /* Back 3 jack, front 2 jack */ | 1483 | /* Back 3 jack, front 2 jack */ |
929 | { .modelname = "3stack", .config = ALC880_3ST }, | 1484 | { .modelname = "3stack", .config = ALC880_3ST }, |
930 | { .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST }, | 1485 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST }, |
931 | { .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST }, | 1486 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST }, |
932 | { .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST }, | 1487 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST }, |
933 | { .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST }, | 1488 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST }, |
934 | { .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST }, | 1489 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST }, |
935 | { .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST }, | 1490 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST }, |
936 | { .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST }, | 1491 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST }, |
937 | { .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST }, | 1492 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST }, |
938 | { .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST }, | 1493 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST }, |
939 | { .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST }, | 1494 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST }, |
940 | { .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST }, | 1495 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST }, |
941 | { .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST }, | 1496 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST }, |
942 | { .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST }, | 1497 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST }, |
943 | { .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST }, | 1498 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST }, |
944 | { .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST }, | 1499 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST }, |
945 | { .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST }, | 1500 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST }, |
946 | { .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST }, | 1501 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST }, |
947 | { .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST }, | 1502 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST }, |
948 | { .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST }, | 1503 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST }, |
949 | { .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST }, | 1504 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST }, |
950 | { .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST }, | 1505 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST }, |
951 | { .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST }, | 1506 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST }, |
952 | { .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST }, | 1507 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST }, |
953 | { .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST }, | 1508 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST }, |
954 | { .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST }, | 1509 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST }, |
955 | { .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST }, | 1510 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST }, |
956 | { .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST }, | 1511 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST }, |
957 | { .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST }, | 1512 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST }, |
958 | { .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST }, | 1513 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST }, |
959 | { .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST }, | 1514 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST }, |
960 | { .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST }, | 1515 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST }, |
961 | { .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST }, | 1516 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST }, |
962 | 1517 | ||
963 | /* Back 3 jack, front 2 jack (Internal add Aux-In) */ | 1518 | /* Back 3 jack, front 2 jack (Internal add Aux-In) */ |
964 | { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST }, | 1519 | { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST }, |
1520 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST }, | ||
965 | 1521 | ||
966 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */ | 1522 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */ |
967 | { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, | 1523 | { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, |
968 | { .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG }, | 1524 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, |
969 | 1525 | ||
970 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ | 1526 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ |
971 | { .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG }, | 1527 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, |
972 | { .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG }, | 1528 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG }, |
973 | { .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG }, | 1529 | { .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG }, |
974 | 1530 | ||
975 | /* Back 5 jack, front 2 jack */ | 1531 | /* Back 5 jack, front 2 jack */ |
976 | { .modelname = "5stack", .config = ALC880_5ST }, | 1532 | { .modelname = "5stack", .config = ALC880_5ST }, |
977 | { .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST }, | 1533 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST }, |
978 | { .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST }, | 1534 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST }, |
979 | { .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST }, | 1535 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST }, |
980 | { .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST }, | 1536 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST }, |
1537 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST }, | ||
981 | 1538 | ||
982 | /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */ | 1539 | /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */ |
983 | { .modelname = "5stack-digout", .config = ALC880_5ST_DIG }, | 1540 | { .modelname = "5stack-digout", .config = ALC880_5ST_DIG }, |
984 | { .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG }, | 1541 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG }, |
985 | { .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG }, | 1542 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG }, |
986 | { .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG }, | 1543 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG }, |
987 | { .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG }, | 1544 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG }, |
988 | { .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG }, | 1545 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG }, |
989 | { .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG }, | 1546 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG }, |
990 | { .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG }, | 1547 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG }, |
991 | { .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG }, | 1548 | { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG }, |
1549 | { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG }, | ||
1550 | { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, | ||
1551 | { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG }, | ||
1552 | { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, | ||
992 | 1553 | ||
993 | { .modelname = "w810", .config = ALC880_W810 }, | 1554 | { .modelname = "w810", .config = ALC880_W810 }, |
994 | { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 }, | 1555 | { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 }, |
1556 | |||
1557 | { .modelname = "z71v", .config = ALC880_Z71V }, | ||
1558 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V }, | ||
1559 | |||
1560 | { .modelname = "6statack-digout", .config = ALC880_6ST_DIG }, | ||
1561 | { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG }, | ||
1562 | { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG }, | ||
1563 | { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG }, | ||
1564 | { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG }, | ||
1565 | |||
1566 | { .modelname = "asus", .config = ALC880_ASUS }, | ||
1567 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG }, | ||
1568 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG }, | ||
1569 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG }, | ||
1570 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG }, | ||
1571 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS }, | ||
1572 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG }, | ||
1573 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS }, | ||
1574 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG }, | ||
1575 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS }, | ||
1576 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V }, | ||
1577 | |||
1578 | { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG }, | ||
1579 | { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG }, | ||
1580 | |||
1581 | { .modelname = "F1734", .config = ALC880_F1734 }, | ||
1582 | { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 }, | ||
1583 | |||
1584 | #ifdef CONFIG_SND_DEBUG | ||
1585 | { .modelname = "test", .config = ALC880_TEST }, | ||
1586 | #endif | ||
995 | 1587 | ||
996 | {} | 1588 | {} |
997 | }; | 1589 | }; |
998 | 1590 | ||
1591 | /* | ||
1592 | * configuration template - to be copied to the spec instance | ||
1593 | */ | ||
1594 | struct alc_config_preset { | ||
1595 | snd_kcontrol_new_t *mixers[4]; | ||
1596 | const struct hda_verb *init_verbs[4]; | ||
1597 | unsigned int num_dacs; | ||
1598 | hda_nid_t *dac_nids; | ||
1599 | hda_nid_t dig_out_nid; /* optional */ | ||
1600 | hda_nid_t hp_nid; /* optional */ | ||
1601 | unsigned int num_adc_nids; | ||
1602 | hda_nid_t *adc_nids; | ||
1603 | unsigned int num_channel_mode; | ||
1604 | const struct alc_channel_mode *channel_mode; | ||
1605 | const struct hda_input_mux *input_mux; | ||
1606 | }; | ||
1607 | |||
1608 | static struct alc_config_preset alc880_presets[] = { | ||
1609 | [ALC880_3ST] = { | ||
1610 | .mixers = { alc880_three_stack_mixer }, | ||
1611 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs }, | ||
1612 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1613 | .dac_nids = alc880_dac_nids, | ||
1614 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
1615 | .channel_mode = alc880_threestack_modes, | ||
1616 | .input_mux = &alc880_capture_source, | ||
1617 | }, | ||
1618 | [ALC880_3ST_DIG] = { | ||
1619 | .mixers = { alc880_three_stack_mixer }, | ||
1620 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs }, | ||
1621 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1622 | .dac_nids = alc880_dac_nids, | ||
1623 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1624 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
1625 | .channel_mode = alc880_threestack_modes, | ||
1626 | .input_mux = &alc880_capture_source, | ||
1627 | }, | ||
1628 | [ALC880_5ST] = { | ||
1629 | .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer}, | ||
1630 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, | ||
1631 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1632 | .dac_nids = alc880_dac_nids, | ||
1633 | .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), | ||
1634 | .channel_mode = alc880_fivestack_modes, | ||
1635 | .input_mux = &alc880_capture_source, | ||
1636 | }, | ||
1637 | [ALC880_5ST_DIG] = { | ||
1638 | .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer }, | ||
1639 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, | ||
1640 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1641 | .dac_nids = alc880_dac_nids, | ||
1642 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1643 | .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), | ||
1644 | .channel_mode = alc880_fivestack_modes, | ||
1645 | .input_mux = &alc880_capture_source, | ||
1646 | }, | ||
1647 | [ALC880_6ST_DIG] = { | ||
1648 | .mixers = { alc880_six_stack_mixer }, | ||
1649 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, | ||
1650 | .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), | ||
1651 | .dac_nids = alc880_6st_dac_nids, | ||
1652 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1653 | .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), | ||
1654 | .channel_mode = alc880_sixstack_modes, | ||
1655 | .input_mux = &alc880_6stack_capture_source, | ||
1656 | }, | ||
1657 | [ALC880_W810] = { | ||
1658 | .mixers = { alc880_w810_base_mixer }, | ||
1659 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs }, | ||
1660 | .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), | ||
1661 | .dac_nids = alc880_w810_dac_nids, | ||
1662 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1663 | .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), | ||
1664 | .channel_mode = alc880_w810_modes, | ||
1665 | .input_mux = &alc880_capture_source, | ||
1666 | }, | ||
1667 | [ALC880_Z71V] = { | ||
1668 | .mixers = { alc880_z71v_mixer }, | ||
1669 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs, | ||
1670 | alc880_gpio2_init_verbs }, | ||
1671 | .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), | ||
1672 | .dac_nids = alc880_z71v_dac_nids, | ||
1673 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1674 | .hp_nid = 0x03, | ||
1675 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
1676 | .channel_mode = alc880_2_jack_modes, | ||
1677 | .input_mux = &alc880_capture_source, | ||
1678 | }, | ||
1679 | [ALC880_F1734] = { | ||
1680 | .mixers = { alc880_f1734_mixer }, | ||
1681 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs }, | ||
1682 | .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), | ||
1683 | .dac_nids = alc880_f1734_dac_nids, | ||
1684 | .hp_nid = 0x02, | ||
1685 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
1686 | .channel_mode = alc880_2_jack_modes, | ||
1687 | .input_mux = &alc880_capture_source, | ||
1688 | }, | ||
1689 | [ALC880_ASUS] = { | ||
1690 | .mixers = { alc880_asus_mixer }, | ||
1691 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, | ||
1692 | alc880_gpio1_init_verbs }, | ||
1693 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1694 | .dac_nids = alc880_asus_dac_nids, | ||
1695 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1696 | .channel_mode = alc880_asus_modes, | ||
1697 | .input_mux = &alc880_capture_source, | ||
1698 | }, | ||
1699 | [ALC880_ASUS_DIG] = { | ||
1700 | .mixers = { alc880_asus_mixer }, | ||
1701 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, | ||
1702 | alc880_gpio1_init_verbs }, | ||
1703 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1704 | .dac_nids = alc880_asus_dac_nids, | ||
1705 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1706 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1707 | .channel_mode = alc880_asus_modes, | ||
1708 | .input_mux = &alc880_capture_source, | ||
1709 | }, | ||
1710 | [ALC880_ASUS_W1V] = { | ||
1711 | .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, | ||
1712 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, | ||
1713 | alc880_gpio1_init_verbs }, | ||
1714 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1715 | .dac_nids = alc880_asus_dac_nids, | ||
1716 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1717 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1718 | .channel_mode = alc880_asus_modes, | ||
1719 | .input_mux = &alc880_capture_source, | ||
1720 | }, | ||
1721 | [ALC880_UNIWILL_DIG] = { | ||
1722 | .mixers = { alc880_asus_mixer }, | ||
1723 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs }, | ||
1724 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1725 | .dac_nids = alc880_asus_dac_nids, | ||
1726 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1727 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1728 | .channel_mode = alc880_asus_modes, | ||
1729 | .input_mux = &alc880_capture_source, | ||
1730 | }, | ||
1731 | #ifdef CONFIG_SND_DEBUG | ||
1732 | [ALC880_TEST] = { | ||
1733 | .mixers = { alc880_test_mixer }, | ||
1734 | .init_verbs = { alc880_test_init_verbs }, | ||
1735 | .num_dacs = ARRAY_SIZE(alc880_test_dac_nids), | ||
1736 | .dac_nids = alc880_test_dac_nids, | ||
1737 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1738 | .num_channel_mode = ARRAY_SIZE(alc880_test_modes), | ||
1739 | .channel_mode = alc880_test_modes, | ||
1740 | .input_mux = &alc880_test_capture_source, | ||
1741 | }, | ||
1742 | #endif | ||
1743 | }; | ||
1744 | |||
1745 | /* | ||
1746 | * Automatic parse of I/O pins from the BIOS configuration | ||
1747 | */ | ||
1748 | |||
1749 | #define NUM_CONTROL_ALLOC 32 | ||
1750 | #define NUM_VERB_ALLOC 32 | ||
1751 | |||
1752 | enum { | ||
1753 | ALC_CTL_WIDGET_VOL, | ||
1754 | ALC_CTL_WIDGET_MUTE, | ||
1755 | ALC_CTL_BIND_MUTE, | ||
1756 | }; | ||
1757 | static snd_kcontrol_new_t alc880_control_templates[] = { | ||
1758 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | ||
1759 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | ||
1760 | ALC_BIND_MUTE(NULL, 0, 0, 0), | ||
1761 | }; | ||
1762 | |||
1763 | /* add dynamic controls */ | ||
1764 | static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val) | ||
1765 | { | ||
1766 | snd_kcontrol_new_t *knew; | ||
1767 | |||
1768 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | ||
1769 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | ||
1770 | |||
1771 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | ||
1772 | if (! knew) | ||
1773 | return -ENOMEM; | ||
1774 | if (spec->kctl_alloc) { | ||
1775 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
1776 | kfree(spec->kctl_alloc); | ||
1777 | } | ||
1778 | spec->kctl_alloc = knew; | ||
1779 | spec->num_kctl_alloc = num; | ||
1780 | } | ||
1781 | |||
1782 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
1783 | *knew = alc880_control_templates[type]; | ||
1784 | knew->name = snd_kmalloc_strdup(name, GFP_KERNEL); | ||
1785 | if (! knew->name) | ||
1786 | return -ENOMEM; | ||
1787 | knew->private_value = val; | ||
1788 | spec->num_kctl_used++; | ||
1789 | return 0; | ||
1790 | } | ||
1791 | |||
1792 | #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) | ||
1793 | #define alc880_fixed_pin_idx(nid) ((nid) - 0x14) | ||
1794 | #define alc880_is_multi_pin(nid) ((nid) >= 0x18) | ||
1795 | #define alc880_multi_pin_idx(nid) ((nid) - 0x18) | ||
1796 | #define alc880_is_input_pin(nid) ((nid) >= 0x18) | ||
1797 | #define alc880_input_pin_idx(nid) ((nid) - 0x18) | ||
1798 | #define alc880_idx_to_dac(nid) ((nid) + 0x02) | ||
1799 | #define alc880_dac_to_idx(nid) ((nid) - 0x02) | ||
1800 | #define alc880_idx_to_mixer(nid) ((nid) + 0x0c) | ||
1801 | #define alc880_idx_to_selector(nid) ((nid) + 0x10) | ||
1802 | #define ALC880_PIN_CD_NID 0x1c | ||
1803 | |||
1804 | /* fill in the dac_nids table from the parsed pin configuration */ | ||
1805 | static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | ||
1806 | { | ||
1807 | hda_nid_t nid; | ||
1808 | int assigned[4]; | ||
1809 | int i, j; | ||
1810 | |||
1811 | memset(assigned, 0, sizeof(assigned)); | ||
1812 | |||
1813 | /* check the pins hardwired to audio widget */ | ||
1814 | for (i = 0; i < cfg->line_outs; i++) { | ||
1815 | nid = cfg->line_out_pins[i]; | ||
1816 | if (alc880_is_fixed_pin(nid)) { | ||
1817 | int idx = alc880_fixed_pin_idx(nid); | ||
1818 | spec->multiout.dac_nids[i] = alc880_dac_to_idx(idx); | ||
1819 | assigned[idx] = 1; | ||
1820 | } | ||
1821 | } | ||
1822 | /* left pins can be connect to any audio widget */ | ||
1823 | for (i = 0; i < cfg->line_outs; i++) { | ||
1824 | nid = cfg->line_out_pins[i]; | ||
1825 | if (alc880_is_fixed_pin(nid)) | ||
1826 | continue; | ||
1827 | /* search for an empty channel */ | ||
1828 | for (j = 0; j < cfg->line_outs; j++) { | ||
1829 | if (! assigned[j]) { | ||
1830 | spec->multiout.dac_nids[i] = alc880_idx_to_dac(j); | ||
1831 | assigned[j] = 1; | ||
1832 | break; | ||
1833 | } | ||
1834 | } | ||
1835 | } | ||
1836 | spec->multiout.num_dacs = cfg->line_outs; | ||
1837 | return 0; | ||
1838 | } | ||
1839 | |||
1840 | /* add playback controls from the parsed DAC table */ | ||
1841 | static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | ||
1842 | { | ||
1843 | char name[32]; | ||
1844 | static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; | ||
1845 | hda_nid_t nid; | ||
1846 | int i, err; | ||
1847 | |||
1848 | for (i = 0; i < cfg->line_outs; i++) { | ||
1849 | if (! spec->multiout.dac_nids[i]) | ||
1850 | continue; | ||
1851 | nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); | ||
1852 | if (i == 2) { | ||
1853 | /* Center/LFE */ | ||
1854 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume", | ||
1855 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | ||
1856 | return err; | ||
1857 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume", | ||
1858 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | ||
1859 | return err; | ||
1860 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch", | ||
1861 | HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0) | ||
1862 | return err; | ||
1863 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch", | ||
1864 | HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0) | ||
1865 | return err; | ||
1866 | } else { | ||
1867 | sprintf(name, "%s Playback Volume", chname[i]); | ||
1868 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | ||
1869 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
1870 | return err; | ||
1871 | sprintf(name, "%s Playback Switch", chname[i]); | ||
1872 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, | ||
1873 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) | ||
1874 | return err; | ||
1875 | } | ||
1876 | } | ||
1877 | |||
1878 | return 0; | ||
1879 | } | ||
1880 | |||
1881 | /* add playback controls for HP output */ | ||
1882 | static int alc880_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) | ||
1883 | { | ||
1884 | hda_nid_t nid; | ||
1885 | int err; | ||
1886 | |||
1887 | if (! pin) | ||
1888 | return 0; | ||
1889 | |||
1890 | if (alc880_is_fixed_pin(pin)) { | ||
1891 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); | ||
1892 | if (! spec->multiout.dac_nids[0]) { | ||
1893 | /* use this as the primary output */ | ||
1894 | spec->multiout.dac_nids[0] = nid; | ||
1895 | if (! spec->multiout.num_dacs) | ||
1896 | spec->multiout.num_dacs = 1; | ||
1897 | } else | ||
1898 | /* specify the DAC as the extra HP output */ | ||
1899 | spec->multiout.hp_nid = nid; | ||
1900 | /* control HP volume/switch on the output mixer amp */ | ||
1901 | nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); | ||
1902 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume", | ||
1903 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
1904 | return err; | ||
1905 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Headphone Playback Switch", | ||
1906 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) | ||
1907 | return err; | ||
1908 | } else if (alc880_is_multi_pin(pin)) { | ||
1909 | /* set manual connection */ | ||
1910 | if (! spec->multiout.dac_nids[0]) { | ||
1911 | /* use this as the primary output */ | ||
1912 | spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin)); | ||
1913 | if (! spec->multiout.num_dacs) | ||
1914 | spec->multiout.num_dacs = 1; | ||
1915 | } | ||
1916 | /* we have only a switch on HP-out PIN */ | ||
1917 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", | ||
1918 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0) | ||
1919 | return err; | ||
1920 | } | ||
1921 | return 0; | ||
1922 | } | ||
1923 | |||
1924 | /* create input playback/capture controls for the given pin */ | ||
1925 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname) | ||
1926 | { | ||
1927 | char name[32]; | ||
1928 | int err, idx; | ||
1929 | |||
1930 | sprintf(name, "%s Playback Volume", ctlname); | ||
1931 | idx = alc880_input_pin_idx(pin); | ||
1932 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | ||
1933 | HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0) | ||
1934 | return err; | ||
1935 | sprintf(name, "%s Playback Switch", ctlname); | ||
1936 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | ||
1937 | HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0) | ||
1938 | return err; | ||
1939 | return 0; | ||
1940 | } | ||
1941 | |||
1942 | /* create playback/capture controls for input pins */ | ||
1943 | static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | ||
1944 | { | ||
1945 | static char *labels[AUTO_PIN_LAST] = { | ||
1946 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" | ||
1947 | }; | ||
1948 | struct hda_input_mux *imux = &spec->private_imux; | ||
1949 | int i, err; | ||
1950 | |||
1951 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
1952 | if (alc880_is_input_pin(cfg->input_pins[i])) { | ||
1953 | err = new_analog_input(spec, cfg->input_pins[i], labels[i]); | ||
1954 | if (err < 0) | ||
1955 | return err; | ||
1956 | imux->items[imux->num_items].label = labels[i]; | ||
1957 | imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]); | ||
1958 | imux->num_items++; | ||
1959 | } | ||
1960 | } | ||
1961 | return 0; | ||
1962 | } | ||
1963 | |||
1964 | static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type, | ||
1965 | int dac_idx) | ||
1966 | { | ||
1967 | /* set as output */ | ||
1968 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | ||
1969 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | ||
1970 | /* need the manual connection? */ | ||
1971 | if (alc880_is_multi_pin(nid)) { | ||
1972 | struct alc_spec *spec = codec->spec; | ||
1973 | int idx = alc880_multi_pin_idx(nid); | ||
1974 | snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, | ||
1975 | AC_VERB_SET_CONNECT_SEL, | ||
1976 | alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); | ||
1977 | } | ||
1978 | } | ||
1979 | |||
1980 | static void alc880_auto_init_multi_out(struct hda_codec *codec) | ||
1981 | { | ||
1982 | struct alc_spec *spec = codec->spec; | ||
1983 | int i; | ||
1984 | |||
1985 | for (i = 0; i < spec->autocfg.line_outs; i++) { | ||
1986 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | ||
1987 | alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); | ||
1988 | } | ||
1989 | } | ||
1990 | |||
1991 | static void alc880_auto_init_hp_out(struct hda_codec *codec) | ||
1992 | { | ||
1993 | struct alc_spec *spec = codec->spec; | ||
1994 | hda_nid_t pin; | ||
1995 | |||
1996 | pin = spec->autocfg.hp_pin; | ||
1997 | if (pin) /* connect to front */ | ||
1998 | alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | ||
1999 | } | ||
2000 | |||
2001 | static void alc880_auto_init_analog_input(struct hda_codec *codec) | ||
2002 | { | ||
2003 | struct alc_spec *spec = codec->spec; | ||
2004 | int i; | ||
2005 | |||
2006 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
2007 | hda_nid_t nid = spec->autocfg.input_pins[i]; | ||
2008 | if (alc880_is_input_pin(nid)) { | ||
2009 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
2010 | i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); | ||
2011 | if (nid != ALC880_PIN_CD_NID) | ||
2012 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
2013 | AMP_OUT_MUTE); | ||
2014 | } | ||
2015 | } | ||
2016 | } | ||
2017 | |||
2018 | /* parse the BIOS configuration and set up the alc_spec */ | ||
2019 | /* return 1 if successful, 0 if the proper config is not found, or a negative error code */ | ||
2020 | static int alc880_parse_auto_config(struct hda_codec *codec) | ||
2021 | { | ||
2022 | struct alc_spec *spec = codec->spec; | ||
2023 | int err; | ||
2024 | |||
2025 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0) | ||
2026 | return err; | ||
2027 | if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0) | ||
2028 | return err; | ||
2029 | if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) | ||
2030 | return 0; /* can't find valid BIOS pin config */ | ||
2031 | if ((err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | ||
2032 | (err = alc880_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 || | ||
2033 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | ||
2034 | return err; | ||
2035 | |||
2036 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | ||
2037 | |||
2038 | if (spec->autocfg.dig_out_pin) | ||
2039 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | ||
2040 | if (spec->autocfg.dig_in_pin) | ||
2041 | spec->dig_in_nid = ALC880_DIGIN_NID; | ||
2042 | |||
2043 | if (spec->kctl_alloc) | ||
2044 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | ||
2045 | |||
2046 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; | ||
2047 | |||
2048 | spec->input_mux = &spec->private_imux; | ||
2049 | |||
2050 | return 1; | ||
2051 | } | ||
2052 | |||
2053 | /* init callback for auto-configuration model -- overriding the default init */ | ||
2054 | static int alc880_auto_init(struct hda_codec *codec) | ||
2055 | { | ||
2056 | alc_init(codec); | ||
2057 | alc880_auto_init_multi_out(codec); | ||
2058 | alc880_auto_init_hp_out(codec); | ||
2059 | alc880_auto_init_analog_input(codec); | ||
2060 | return 0; | ||
2061 | } | ||
2062 | |||
2063 | /* | ||
2064 | * OK, here we have finally the patch for ALC880 | ||
2065 | */ | ||
2066 | |||
999 | static int patch_alc880(struct hda_codec *codec) | 2067 | static int patch_alc880(struct hda_codec *codec) |
1000 | { | 2068 | { |
1001 | struct alc_spec *spec; | 2069 | struct alc_spec *spec; |
1002 | int board_config; | 2070 | int board_config; |
2071 | int i, err; | ||
1003 | 2072 | ||
1004 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | 2073 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
1005 | if (spec == NULL) | 2074 | if (spec == NULL) |
1006 | return -ENOMEM; | 2075 | return -ENOMEM; |
1007 | 2076 | ||
2077 | init_MUTEX(&spec->bind_mutex); | ||
1008 | codec->spec = spec; | 2078 | codec->spec = spec; |
1009 | 2079 | ||
1010 | board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl); | 2080 | board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl); |
1011 | if (board_config < 0) { | 2081 | if (board_config < 0 || board_config >= ALC880_MODEL_LAST) { |
1012 | snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n"); | 2082 | printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n"); |
1013 | board_config = ALC880_MINIMAL; | 2083 | board_config = ALC880_AUTO; |
1014 | } | 2084 | } |
1015 | 2085 | ||
1016 | switch (board_config) { | 2086 | if (board_config == ALC880_AUTO) { |
1017 | case ALC880_W810: | 2087 | /* automatic parse from the BIOS config */ |
1018 | spec->mixers[spec->num_mixers] = alc880_w810_base_mixer; | 2088 | err = alc880_parse_auto_config(codec); |
1019 | spec->num_mixers++; | 2089 | if (err < 0) { |
1020 | break; | 2090 | alc_free(codec); |
1021 | case ALC880_5ST: | 2091 | return err; |
1022 | case ALC880_5ST_DIG: | 2092 | } else if (! err) { |
1023 | spec->mixers[spec->num_mixers] = alc880_five_stack_mixer; | 2093 | printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 3-stack mode...\n"); |
1024 | spec->num_mixers++; | 2094 | board_config = ALC880_3ST; |
1025 | break; | 2095 | } |
1026 | default: | ||
1027 | spec->mixers[spec->num_mixers] = alc880_base_mixer; | ||
1028 | spec->num_mixers++; | ||
1029 | break; | ||
1030 | } | 2096 | } |
1031 | 2097 | ||
1032 | switch (board_config) { | 2098 | if (board_config != ALC880_AUTO) { |
1033 | case ALC880_3ST_DIG: | 2099 | /* set up from the preset table */ |
1034 | case ALC880_5ST_DIG: | 2100 | const struct alc_config_preset *preset; |
1035 | case ALC880_W810: | ||
1036 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | ||
1037 | break; | ||
1038 | default: | ||
1039 | break; | ||
1040 | } | ||
1041 | 2101 | ||
1042 | switch (board_config) { | 2102 | preset = &alc880_presets[board_config]; |
1043 | case ALC880_3ST: | ||
1044 | case ALC880_3ST_DIG: | ||
1045 | case ALC880_5ST: | ||
1046 | case ALC880_5ST_DIG: | ||
1047 | case ALC880_W810: | ||
1048 | spec->front_panel = 1; | ||
1049 | break; | ||
1050 | default: | ||
1051 | break; | ||
1052 | } | ||
1053 | 2103 | ||
1054 | switch (board_config) { | 2104 | for (i = 0; preset->mixers[i]; i++) { |
1055 | case ALC880_5ST: | 2105 | snd_assert(spec->num_mixers < ARRAY_SIZE(spec->mixers), break); |
1056 | case ALC880_5ST_DIG: | 2106 | spec->mixers[spec->num_mixers++] = preset->mixers[i]; |
1057 | spec->init_verbs = alc880_init_verbs_five_stack; | 2107 | } |
1058 | spec->channel_mode = alc880_fivestack_modes; | 2108 | for (i = 0; preset->init_verbs[i]; i++) { |
1059 | spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes); | 2109 | snd_assert(spec->num_init_verbs < ARRAY_SIZE(spec->init_verbs), break); |
1060 | break; | 2110 | spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i]; |
1061 | case ALC880_W810: | 2111 | } |
1062 | spec->init_verbs = alc880_w810_init_verbs; | 2112 | |
1063 | spec->channel_mode = alc880_w810_modes; | 2113 | spec->channel_mode = preset->channel_mode; |
1064 | spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes); | 2114 | spec->num_channel_mode = preset->num_channel_mode; |
1065 | break; | 2115 | |
1066 | default: | 2116 | spec->multiout.max_channels = spec->channel_mode[0].channels; |
1067 | spec->init_verbs = alc880_init_verbs_three_stack; | 2117 | |
1068 | spec->channel_mode = alc880_threestack_modes; | 2118 | spec->multiout.num_dacs = preset->num_dacs; |
1069 | spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes); | 2119 | spec->multiout.dac_nids = preset->dac_nids; |
1070 | break; | 2120 | spec->multiout.dig_out_nid = preset->dig_out_nid; |
2121 | spec->multiout.hp_nid = preset->hp_nid; | ||
2122 | |||
2123 | spec->input_mux = preset->input_mux; | ||
2124 | |||
2125 | spec->num_adc_nids = preset->num_adc_nids; | ||
2126 | spec->adc_nids = preset->adc_nids; | ||
1071 | } | 2127 | } |
1072 | 2128 | ||
1073 | spec->stream_name_analog = "ALC880 Analog"; | 2129 | spec->stream_name_analog = "ALC880 Analog"; |
@@ -1078,34 +2134,64 @@ static int patch_alc880(struct hda_codec *codec) | |||
1078 | spec->stream_digital_playback = &alc880_pcm_digital_playback; | 2134 | spec->stream_digital_playback = &alc880_pcm_digital_playback; |
1079 | spec->stream_digital_capture = &alc880_pcm_digital_capture; | 2135 | spec->stream_digital_capture = &alc880_pcm_digital_capture; |
1080 | 2136 | ||
1081 | spec->multiout.max_channels = spec->channel_mode[0].channels; | 2137 | if (! spec->adc_nids && spec->input_mux) { |
1082 | 2138 | /* check whether NID 0x07 is valid */ | |
1083 | switch (board_config) { | 2139 | unsigned int wcap = snd_hda_param_read(codec, alc880_adc_nids[0], |
1084 | case ALC880_W810: | 2140 | AC_PAR_AUDIO_WIDGET_CAP); |
1085 | spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids); | 2141 | wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ |
1086 | spec->multiout.dac_nids = alc880_w810_dac_nids; | 2142 | if (wcap != AC_WID_AUD_IN) { |
1087 | // No dedicated headphone socket - it's shared with built-in speakers. | 2143 | spec->adc_nids = alc880_adc_nids_alt; |
1088 | break; | 2144 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); |
1089 | default: | 2145 | spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer; |
1090 | spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids); | 2146 | spec->num_mixers++; |
1091 | spec->multiout.dac_nids = alc880_dac_nids; | 2147 | } else { |
1092 | spec->multiout.hp_nid = 0x03; /* rear-surround NID */ | 2148 | spec->adc_nids = alc880_adc_nids; |
1093 | break; | 2149 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); |
2150 | spec->mixers[spec->num_mixers] = alc880_capture_mixer; | ||
2151 | spec->num_mixers++; | ||
2152 | } | ||
1094 | } | 2153 | } |
1095 | 2154 | ||
1096 | spec->input_mux = &alc880_capture_source; | ||
1097 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); | ||
1098 | spec->adc_nids = alc880_adc_nids; | ||
1099 | |||
1100 | codec->patch_ops = alc_patch_ops; | 2155 | codec->patch_ops = alc_patch_ops; |
2156 | if (board_config == ALC880_AUTO) | ||
2157 | codec->patch_ops.init = alc880_auto_init; | ||
1101 | 2158 | ||
1102 | return 0; | 2159 | return 0; |
1103 | } | 2160 | } |
1104 | 2161 | ||
2162 | |||
1105 | /* | 2163 | /* |
1106 | * ALC260 support | 2164 | * ALC260 support |
1107 | */ | 2165 | */ |
1108 | 2166 | ||
2167 | static hda_nid_t alc260_dac_nids[1] = { | ||
2168 | /* front */ | ||
2169 | 0x02, | ||
2170 | }; | ||
2171 | |||
2172 | static hda_nid_t alc260_adc_nids[1] = { | ||
2173 | /* ADC0 */ | ||
2174 | 0x04, | ||
2175 | }; | ||
2176 | |||
2177 | static hda_nid_t alc260_hp_adc_nids[1] = { | ||
2178 | /* ADC1 */ | ||
2179 | 0x05, | ||
2180 | }; | ||
2181 | |||
2182 | #define ALC260_DIGOUT_NID 0x03 | ||
2183 | #define ALC260_DIGIN_NID 0x06 | ||
2184 | |||
2185 | static struct hda_input_mux alc260_capture_source = { | ||
2186 | .num_items = 4, | ||
2187 | .items = { | ||
2188 | { "Mic", 0x0 }, | ||
2189 | { "Front Mic", 0x1 }, | ||
2190 | { "Line", 0x2 }, | ||
2191 | { "CD", 0x4 }, | ||
2192 | }, | ||
2193 | }; | ||
2194 | |||
1109 | /* | 2195 | /* |
1110 | * This is just place-holder, so there's something for alc_build_pcms to look | 2196 | * This is just place-holder, so there's something for alc_build_pcms to look |
1111 | * at when it calculates the maximum number of channels. ALC260 has no mixer | 2197 | * at when it calculates the maximum number of channels. ALC260 has no mixer |
@@ -1116,11 +2202,9 @@ static struct alc_channel_mode alc260_modes[1] = { | |||
1116 | { 2, NULL }, | 2202 | { 2, NULL }, |
1117 | }; | 2203 | }; |
1118 | 2204 | ||
1119 | snd_kcontrol_new_t alc260_base_mixer[] = { | 2205 | static snd_kcontrol_new_t alc260_base_mixer[] = { |
1120 | HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), | 2206 | HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), |
1121 | /* use LINE2 for the output */ | 2207 | ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), |
1122 | /* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */ | ||
1123 | HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
1124 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | 2208 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), |
1125 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | 2209 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), |
1126 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | 2210 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), |
@@ -1132,9 +2216,9 @@ snd_kcontrol_new_t alc260_base_mixer[] = { | |||
1132 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), | 2216 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), |
1133 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), | 2217 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), |
1134 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), | 2218 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), |
1135 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT), | 2219 | ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), |
1136 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), | 2220 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), |
1137 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT), | 2221 | ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT), |
1138 | HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), | 2222 | HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), |
1139 | HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), | 2223 | HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), |
1140 | { | 2224 | { |
@@ -1147,60 +2231,91 @@ snd_kcontrol_new_t alc260_base_mixer[] = { | |||
1147 | { } /* end */ | 2231 | { } /* end */ |
1148 | }; | 2232 | }; |
1149 | 2233 | ||
2234 | static snd_kcontrol_new_t alc260_hp_mixer[] = { | ||
2235 | HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
2236 | ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), | ||
2237 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
2238 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
2239 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
2240 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
2241 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
2242 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
2243 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), | ||
2244 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), | ||
2245 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), | ||
2246 | ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), | ||
2247 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), | ||
2248 | ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT), | ||
2249 | HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT), | ||
2250 | HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT), | ||
2251 | { | ||
2252 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2253 | .name = "Capture Source", | ||
2254 | .info = alc_mux_enum_info, | ||
2255 | .get = alc_mux_enum_get, | ||
2256 | .put = alc_mux_enum_put, | ||
2257 | }, | ||
2258 | { } /* end */ | ||
2259 | }; | ||
2260 | |||
1150 | static struct hda_verb alc260_init_verbs[] = { | 2261 | static struct hda_verb alc260_init_verbs[] = { |
1151 | /* Line In pin widget for input */ | 2262 | /* Line In pin widget for input */ |
1152 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 2263 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
1153 | /* CD pin widget for input */ | 2264 | /* CD pin widget for input */ |
1154 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 2265 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
1155 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | 2266 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ |
1156 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 2267 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
1157 | /* Mic2 (front panel) pin widget for input and vref at 80% */ | 2268 | /* Mic2 (front panel) pin widget for input and vref at 80% */ |
1158 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 2269 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
1159 | /* LINE-2 is used for line-out in rear */ | 2270 | /* LINE-2 is used for line-out in rear */ |
1160 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2271 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1161 | /* select line-out */ | 2272 | /* select line-out */ |
1162 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | 2273 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1163 | /* LINE-OUT pin */ | 2274 | /* LINE-OUT pin */ |
1164 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2275 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1165 | /* enable HP */ | 2276 | /* enable HP */ |
1166 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2277 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
1167 | /* enable Mono */ | 2278 | /* enable Mono */ |
1168 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2279 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1169 | /* unmute amp left and right */ | 2280 | /* mute capture amp left and right */ |
1170 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 2281 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1171 | /* set connection select to line in (default select for this ADC) */ | 2282 | /* set connection select to line in (default select for this ADC) */ |
1172 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, | 2283 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, |
1173 | /* unmute Line-Out mixer amp left and right (volume = 0) */ | 2284 | /* mute capture amp left and right */ |
1174 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2285 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1175 | /* mute pin widget amp left and right (no gain on this amp) */ | 2286 | /* set connection select to line in (default select for this ADC) */ |
1176 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2287 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, |
1177 | /* unmute HP mixer amp left and right (volume = 0) */ | 2288 | /* set vol=0 Line-Out mixer amp left and right */ |
1178 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2289 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
1179 | /* mute pin widget amp left and right (no gain on this amp) */ | 2290 | /* unmute pin widget amp left and right (no gain on this amp) */ |
1180 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 2291 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1181 | /* unmute Mono mixer amp left and right (volume = 0) */ | 2292 | /* set vol=0 HP mixer amp left and right */ |
1182 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2293 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
1183 | /* mute pin widget amp left and right (no gain on this amp) */ | 2294 | /* unmute pin widget amp left and right (no gain on this amp) */ |
1184 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 2295 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1185 | /* mute LINE-2 out */ | 2296 | /* set vol=0 Mono mixer amp left and right */ |
1186 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 2297 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
2298 | /* unmute pin widget amp left and right (no gain on this amp) */ | ||
2299 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2300 | /* unmute LINE-2 out pin */ | ||
2301 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1187 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ | 2302 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ |
1188 | /* unmute CD */ | 2303 | /* mute CD */ |
1189 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 2304 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
1190 | /* unmute Line In */ | 2305 | /* mute Line In */ |
1191 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | 2306 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
1192 | /* unmute Mic */ | 2307 | /* mute Mic */ |
1193 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2308 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1194 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 2309 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ |
1195 | /* Unmute Front out path */ | 2310 | /* mute Front out path */ |
1196 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2311 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1197 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 2312 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
1198 | /* Unmute Headphone out path */ | 2313 | /* mute Headphone out path */ |
1199 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2314 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1200 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 2315 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
1201 | /* Unmute Mono out path */ | 2316 | /* mute Mono out path */ |
1202 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2317 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1203 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 2318 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
1204 | { } | 2319 | { } |
1205 | }; | 2320 | }; |
1206 | 2321 | ||
@@ -1208,30 +2323,52 @@ static struct hda_pcm_stream alc260_pcm_analog_playback = { | |||
1208 | .substreams = 1, | 2323 | .substreams = 1, |
1209 | .channels_min = 2, | 2324 | .channels_min = 2, |
1210 | .channels_max = 2, | 2325 | .channels_max = 2, |
1211 | .nid = 0x2, | ||
1212 | }; | 2326 | }; |
1213 | 2327 | ||
1214 | static struct hda_pcm_stream alc260_pcm_analog_capture = { | 2328 | static struct hda_pcm_stream alc260_pcm_analog_capture = { |
1215 | .substreams = 1, | 2329 | .substreams = 1, |
1216 | .channels_min = 2, | 2330 | .channels_min = 2, |
1217 | .channels_max = 2, | 2331 | .channels_max = 2, |
1218 | .nid = 0x4, | 2332 | }; |
2333 | |||
2334 | static struct hda_board_config alc260_cfg_tbl[] = { | ||
2335 | { .modelname = "hp", .config = ALC260_HP }, | ||
2336 | { .pci_subvendor = 0x103c, .config = ALC260_HP }, | ||
2337 | {} | ||
1219 | }; | 2338 | }; |
1220 | 2339 | ||
1221 | static int patch_alc260(struct hda_codec *codec) | 2340 | static int patch_alc260(struct hda_codec *codec) |
1222 | { | 2341 | { |
1223 | struct alc_spec *spec; | 2342 | struct alc_spec *spec; |
2343 | int board_config; | ||
1224 | 2344 | ||
1225 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | 2345 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
1226 | if (spec == NULL) | 2346 | if (spec == NULL) |
1227 | return -ENOMEM; | 2347 | return -ENOMEM; |
1228 | 2348 | ||
2349 | init_MUTEX(&spec->bind_mutex); | ||
1229 | codec->spec = spec; | 2350 | codec->spec = spec; |
1230 | 2351 | ||
1231 | spec->mixers[spec->num_mixers] = alc260_base_mixer; | 2352 | board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl); |
1232 | spec->num_mixers++; | 2353 | if (board_config < 0 || board_config >= ALC260_MODEL_LAST) { |
2354 | snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n"); | ||
2355 | board_config = ALC260_BASIC; | ||
2356 | } | ||
2357 | |||
2358 | switch (board_config) { | ||
2359 | case ALC260_HP: | ||
2360 | spec->mixers[spec->num_mixers] = alc260_hp_mixer; | ||
2361 | spec->num_mixers++; | ||
2362 | break; | ||
2363 | default: | ||
2364 | spec->mixers[spec->num_mixers] = alc260_base_mixer; | ||
2365 | spec->num_mixers++; | ||
2366 | break; | ||
2367 | } | ||
2368 | |||
2369 | spec->init_verbs[0] = alc260_init_verbs; | ||
2370 | spec->num_init_verbs = 1; | ||
1233 | 2371 | ||
1234 | spec->init_verbs = alc260_init_verbs; | ||
1235 | spec->channel_mode = alc260_modes; | 2372 | spec->channel_mode = alc260_modes; |
1236 | spec->num_channel_mode = ARRAY_SIZE(alc260_modes); | 2373 | spec->num_channel_mode = ARRAY_SIZE(alc260_modes); |
1237 | 2374 | ||
@@ -1244,14 +2381,23 @@ static int patch_alc260(struct hda_codec *codec) | |||
1244 | spec->multiout.dac_nids = alc260_dac_nids; | 2381 | spec->multiout.dac_nids = alc260_dac_nids; |
1245 | 2382 | ||
1246 | spec->input_mux = &alc260_capture_source; | 2383 | spec->input_mux = &alc260_capture_source; |
1247 | spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); | 2384 | switch (board_config) { |
1248 | spec->adc_nids = alc260_adc_nids; | 2385 | case ALC260_HP: |
2386 | spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids); | ||
2387 | spec->adc_nids = alc260_hp_adc_nids; | ||
2388 | break; | ||
2389 | default: | ||
2390 | spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); | ||
2391 | spec->adc_nids = alc260_adc_nids; | ||
2392 | break; | ||
2393 | } | ||
1249 | 2394 | ||
1250 | codec->patch_ops = alc_patch_ops; | 2395 | codec->patch_ops = alc_patch_ops; |
1251 | 2396 | ||
1252 | return 0; | 2397 | return 0; |
1253 | } | 2398 | } |
1254 | 2399 | ||
2400 | |||
1255 | /* | 2401 | /* |
1256 | * ALC882 support | 2402 | * ALC882 support |
1257 | * | 2403 | * |
@@ -1324,15 +2470,15 @@ static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u | |||
1324 | */ | 2470 | */ |
1325 | static snd_kcontrol_new_t alc882_base_mixer[] = { | 2471 | static snd_kcontrol_new_t alc882_base_mixer[] = { |
1326 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 2472 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
1327 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 2473 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
1328 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 2474 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
1329 | HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 2475 | ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), |
1330 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | 2476 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), |
1331 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | 2477 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
1332 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), | 2478 | ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), |
1333 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), | 2479 | ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_OUTPUT), |
1334 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | 2480 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), |
1335 | HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT), | 2481 | ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), |
1336 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 2482 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
1337 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 2483 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
1338 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 2484 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
@@ -1364,89 +2510,80 @@ static snd_kcontrol_new_t alc882_base_mixer[] = { | |||
1364 | 2510 | ||
1365 | static struct hda_verb alc882_init_verbs[] = { | 2511 | static struct hda_verb alc882_init_verbs[] = { |
1366 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | 2512 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ |
1367 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2513 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
1368 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2514 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
2515 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1369 | /* Rear mixer */ | 2516 | /* Rear mixer */ |
1370 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2517 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
1371 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2518 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
2519 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1372 | /* CLFE mixer */ | 2520 | /* CLFE mixer */ |
1373 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2521 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
1374 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2522 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
2523 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1375 | /* Side mixer */ | 2524 | /* Side mixer */ |
1376 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2525 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
1377 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2526 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1378 | 2527 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | |
1379 | /* Front Pin: to output mode */ | 2528 | |
1380 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2529 | /* Front Pin: output 0 (0x0c) */ |
1381 | /* Front Pin: mute amp left and right (no volume) */ | 2530 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1382 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | 2531 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1383 | /* select Front mixer (0x0c, index 0) */ | ||
1384 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | 2532 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1385 | /* Rear Pin */ | 2533 | /* Rear Pin: output 1 (0x0d) */ |
1386 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2534 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1387 | /* Rear Pin: mute amp left and right (no volume) */ | 2535 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1388 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
1389 | /* select Rear mixer (0x0d, index 1) */ | ||
1390 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | 2536 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, |
1391 | /* CLFE Pin */ | 2537 | /* CLFE Pin: output 2 (0x0e) */ |
1392 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2538 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1393 | /* CLFE Pin: mute amp left and right (no volume) */ | 2539 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1394 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
1395 | /* select CLFE mixer (0x0e, index 2) */ | ||
1396 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, | 2540 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, |
1397 | /* Side Pin */ | 2541 | /* Side Pin: output 3 (0x0f) */ |
1398 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2542 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1399 | /* Side Pin: mute amp left and right (no volume) */ | 2543 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1400 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
1401 | /* select Side mixer (0x0f, index 3) */ | ||
1402 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, | 2544 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, |
1403 | /* Headphone Pin */ | 2545 | /* Mic (rear) pin: input vref at 80% */ |
1404 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2546 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
1405 | /* Headphone Pin: mute amp left and right (no volume) */ | 2547 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
1406 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | 2548 | /* Front Mic pin: input vref at 80% */ |
1407 | /* select Front mixer (0x0c, index 0) */ | 2549 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
2550 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2551 | /* Line In pin: input */ | ||
2552 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2553 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2554 | /* Line-2 In: Headphone output (output 0 - 0x0c) */ | ||
2555 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2556 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1408 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | 2557 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1409 | /* Mic (rear) pin widget for input and vref at 80% */ | ||
1410 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
1411 | /* Front Mic pin widget for input and vref at 80% */ | ||
1412 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
1413 | /* Line In pin widget for input */ | ||
1414 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
1415 | /* CD pin widget for input */ | 2558 | /* CD pin widget for input */ |
1416 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 2559 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
1417 | 2560 | ||
1418 | /* FIXME: use matrix-type input source selection */ | 2561 | /* FIXME: use matrix-type input source selection */ |
1419 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | 2562 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ |
1420 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ | 2563 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ |
1421 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2564 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1422 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, | 2565 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
1423 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, | 2566 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
1424 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, | 2567 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
1425 | /* Input mixer2 */ | 2568 | /* Input mixer2 */ |
1426 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2569 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1427 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, | 2570 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
1428 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, | 2571 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
1429 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, | 2572 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
1430 | /* Input mixer3 */ | 2573 | /* Input mixer3 */ |
1431 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2574 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1432 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, | 2575 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
1433 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, | 2576 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
1434 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, | 2577 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
1435 | /* ADC1: unmute amp left and right */ | 2578 | /* ADC1: mute amp left and right */ |
1436 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 2579 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1437 | /* ADC2: unmute amp left and right */ | 2580 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1438 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 2581 | /* ADC2: mute amp left and right */ |
1439 | /* ADC3: unmute amp left and right */ | 2582 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1440 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 2583 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1441 | 2584 | /* ADC3: mute amp left and right */ | |
1442 | /* Unmute front loopback */ | 2585 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1443 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 2586 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1444 | /* Unmute rear loopback */ | ||
1445 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
1446 | /* Mute CLFE loopback */ | ||
1447 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, | ||
1448 | /* Unmute side loopback */ | ||
1449 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
1450 | 2587 | ||
1451 | { } | 2588 | { } |
1452 | }; | 2589 | }; |
@@ -1459,6 +2596,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
1459 | if (spec == NULL) | 2596 | if (spec == NULL) |
1460 | return -ENOMEM; | 2597 | return -ENOMEM; |
1461 | 2598 | ||
2599 | init_MUTEX(&spec->bind_mutex); | ||
1462 | codec->spec = spec; | 2600 | codec->spec = spec; |
1463 | 2601 | ||
1464 | spec->mixers[spec->num_mixers] = alc882_base_mixer; | 2602 | spec->mixers[spec->num_mixers] = alc882_base_mixer; |
@@ -1466,8 +2604,9 @@ static int patch_alc882(struct hda_codec *codec) | |||
1466 | 2604 | ||
1467 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | 2605 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; |
1468 | spec->dig_in_nid = ALC880_DIGIN_NID; | 2606 | spec->dig_in_nid = ALC880_DIGIN_NID; |
1469 | spec->front_panel = 1; | 2607 | spec->init_verbs[0] = alc882_init_verbs; |
1470 | spec->init_verbs = alc882_init_verbs; | 2608 | spec->num_init_verbs = 1; |
2609 | |||
1471 | spec->channel_mode = alc882_ch_modes; | 2610 | spec->channel_mode = alc882_ch_modes; |
1472 | spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes); | 2611 | spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes); |
1473 | 2612 | ||