diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-06-28 09:08:22 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-06-28 13:31:43 -0400 |
commit | 9c7f852e8b2cc37da5dc5e1ba416238166a37d0f (patch) | |
tree | b441419aa9ae275ec016bfbf6d5136452e2be5ba /sound/pci | |
parent | 8c42d5bafa08baad5d647dd0b9050086ffe36e15 (diff) |
[ALSA] Fix/add support of Realtek ALC883 / ALC888 and ALC861 codecs
Patch from Realtek:
- Fix ALC883 support code
- Add support of ALC888 codec
- Add ALC660 support (ALC861-compatible)
- Add HP xw4400/6400/8400/9400 support (model=hp-bpc)
- Code clean-up: fix spaces and indentation
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 1084 |
2 files changed, 991 insertions, 97 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 8c2a8174ece1..23201f3eeb12 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -408,7 +408,9 @@ static const struct hda_codec_preset *find_codec_preset(struct hda_codec *codec) | |||
408 | u32 mask = preset->mask; | 408 | u32 mask = preset->mask; |
409 | if (! mask) | 409 | if (! mask) |
410 | mask = ~0; | 410 | mask = ~0; |
411 | if (preset->id == (codec->vendor_id & mask)) | 411 | if (preset->id == (codec->vendor_id & mask) && |
412 | (! preset->rev || | ||
413 | preset->rev == codec->revision_id)) | ||
412 | return preset; | 414 | return preset; |
413 | } | 415 | } |
414 | } | 416 | } |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 98b9f16c26ff..18d105263fea 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -78,6 +78,7 @@ enum { | |||
78 | enum { | 78 | enum { |
79 | ALC262_BASIC, | 79 | ALC262_BASIC, |
80 | ALC262_FUJITSU, | 80 | ALC262_FUJITSU, |
81 | ALC262_HP_BPC, | ||
81 | ALC262_AUTO, | 82 | ALC262_AUTO, |
82 | ALC262_MODEL_LAST /* last tag */ | 83 | ALC262_MODEL_LAST /* last tag */ |
83 | }; | 84 | }; |
@@ -85,6 +86,7 @@ enum { | |||
85 | /* ALC861 models */ | 86 | /* ALC861 models */ |
86 | enum { | 87 | enum { |
87 | ALC861_3ST, | 88 | ALC861_3ST, |
89 | ALC660_3ST, | ||
88 | ALC861_3ST_DIG, | 90 | ALC861_3ST_DIG, |
89 | ALC861_6ST_DIG, | 91 | ALC861_6ST_DIG, |
90 | ALC861_AUTO, | 92 | ALC861_AUTO, |
@@ -99,6 +101,17 @@ enum { | |||
99 | ALC882_MODEL_LAST, | 101 | ALC882_MODEL_LAST, |
100 | }; | 102 | }; |
101 | 103 | ||
104 | /* ALC883 models */ | ||
105 | enum { | ||
106 | ALC883_3ST_2ch_DIG, | ||
107 | ALC883_3ST_6ch_DIG, | ||
108 | ALC883_3ST_6ch, | ||
109 | ALC883_6ST_DIG, | ||
110 | ALC888_DEMO_BOARD, | ||
111 | ALC883_AUTO, | ||
112 | ALC883_MODEL_LAST, | ||
113 | }; | ||
114 | |||
102 | /* for GPIO Poll */ | 115 | /* for GPIO Poll */ |
103 | #define GPIO_MASK 0x03 | 116 | #define GPIO_MASK 0x03 |
104 | 117 | ||
@@ -108,7 +121,8 @@ struct alc_spec { | |||
108 | unsigned int num_mixers; | 121 | unsigned int num_mixers; |
109 | 122 | ||
110 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 123 | const struct hda_verb *init_verbs[5]; /* initialization verbs |
111 | * don't forget NULL termination! | 124 | * don't forget NULL |
125 | * termination! | ||
112 | */ | 126 | */ |
113 | unsigned int num_init_verbs; | 127 | unsigned int num_init_verbs; |
114 | 128 | ||
@@ -163,7 +177,9 @@ struct alc_spec { | |||
163 | * configuration template - to be copied to the spec instance | 177 | * configuration template - to be copied to the spec instance |
164 | */ | 178 | */ |
165 | struct alc_config_preset { | 179 | struct alc_config_preset { |
166 | struct snd_kcontrol_new *mixers[5]; /* should be identical size with spec */ | 180 | struct snd_kcontrol_new *mixers[5]; /* should be identical size |
181 | * with spec | ||
182 | */ | ||
167 | const struct hda_verb *init_verbs[5]; | 183 | const struct hda_verb *init_verbs[5]; |
168 | unsigned int num_dacs; | 184 | unsigned int num_dacs; |
169 | hda_nid_t *dac_nids; | 185 | hda_nid_t *dac_nids; |
@@ -184,7 +200,8 @@ struct alc_config_preset { | |||
184 | /* | 200 | /* |
185 | * input MUX handling | 201 | * input MUX handling |
186 | */ | 202 | */ |
187 | static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 203 | static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, |
204 | struct snd_ctl_elem_info *uinfo) | ||
188 | { | 205 | { |
189 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 206 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
190 | struct alc_spec *spec = codec->spec; | 207 | struct alc_spec *spec = codec->spec; |
@@ -194,7 +211,8 @@ static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
194 | return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo); | 211 | return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo); |
195 | } | 212 | } |
196 | 213 | ||
197 | static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 214 | static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, |
215 | struct snd_ctl_elem_value *ucontrol) | ||
198 | { | 216 | { |
199 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 217 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
200 | struct alc_spec *spec = codec->spec; | 218 | struct alc_spec *spec = codec->spec; |
@@ -204,21 +222,24 @@ static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
204 | return 0; | 222 | return 0; |
205 | } | 223 | } |
206 | 224 | ||
207 | static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 225 | static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, |
226 | struct snd_ctl_elem_value *ucontrol) | ||
208 | { | 227 | { |
209 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 228 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
210 | struct alc_spec *spec = codec->spec; | 229 | struct alc_spec *spec = codec->spec; |
211 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 230 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
212 | unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; | 231 | unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; |
213 | return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol, | 232 | return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol, |
214 | spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); | 233 | spec->adc_nids[adc_idx], |
234 | &spec->cur_mux[adc_idx]); | ||
215 | } | 235 | } |
216 | 236 | ||
217 | 237 | ||
218 | /* | 238 | /* |
219 | * channel mode setting | 239 | * channel mode setting |
220 | */ | 240 | */ |
221 | static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 241 | static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, |
242 | struct snd_ctl_elem_info *uinfo) | ||
222 | { | 243 | { |
223 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 244 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
224 | struct alc_spec *spec = codec->spec; | 245 | struct alc_spec *spec = codec->spec; |
@@ -226,20 +247,24 @@ static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_i | |||
226 | spec->num_channel_mode); | 247 | spec->num_channel_mode); |
227 | } | 248 | } |
228 | 249 | ||
229 | static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 250 | static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, |
251 | struct snd_ctl_elem_value *ucontrol) | ||
230 | { | 252 | { |
231 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 253 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
232 | struct alc_spec *spec = codec->spec; | 254 | struct alc_spec *spec = codec->spec; |
233 | return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, | 255 | return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, |
234 | spec->num_channel_mode, spec->multiout.max_channels); | 256 | spec->num_channel_mode, |
257 | spec->multiout.max_channels); | ||
235 | } | 258 | } |
236 | 259 | ||
237 | static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 260 | static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, |
261 | struct snd_ctl_elem_value *ucontrol) | ||
238 | { | 262 | { |
239 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 263 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
240 | struct alc_spec *spec = codec->spec; | 264 | struct alc_spec *spec = codec->spec; |
241 | return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, | 265 | return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, |
242 | spec->num_channel_mode, &spec->multiout.max_channels); | 266 | spec->num_channel_mode, |
267 | &spec->multiout.max_channels); | ||
243 | } | 268 | } |
244 | 269 | ||
245 | /* | 270 | /* |
@@ -290,7 +315,8 @@ static signed char alc_pin_mode_dir_info[5][2] = { | |||
290 | #define alc_pin_mode_n_items(_dir) \ | 315 | #define alc_pin_mode_n_items(_dir) \ |
291 | (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1) | 316 | (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1) |
292 | 317 | ||
293 | static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 318 | static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, |
319 | struct snd_ctl_elem_info *uinfo) | ||
294 | { | 320 | { |
295 | unsigned int item_num = uinfo->value.enumerated.item; | 321 | unsigned int item_num = uinfo->value.enumerated.item; |
296 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; | 322 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; |
@@ -305,40 +331,46 @@ static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
305 | return 0; | 331 | return 0; |
306 | } | 332 | } |
307 | 333 | ||
308 | static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 334 | static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, |
335 | struct snd_ctl_elem_value *ucontrol) | ||
309 | { | 336 | { |
310 | unsigned int i; | 337 | unsigned int i; |
311 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 338 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
312 | hda_nid_t nid = kcontrol->private_value & 0xffff; | 339 | hda_nid_t nid = kcontrol->private_value & 0xffff; |
313 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; | 340 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; |
314 | long *valp = ucontrol->value.integer.value; | 341 | long *valp = ucontrol->value.integer.value; |
315 | unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00); | 342 | unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, |
343 | AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
344 | 0x00); | ||
316 | 345 | ||
317 | /* Find enumerated value for current pinctl setting */ | 346 | /* Find enumerated value for current pinctl setting */ |
318 | i = alc_pin_mode_min(dir); | 347 | i = alc_pin_mode_min(dir); |
319 | while (alc_pin_mode_values[i]!=pinctl && i<=alc_pin_mode_max(dir)) | 348 | while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir)) |
320 | i++; | 349 | i++; |
321 | *valp = i<=alc_pin_mode_max(dir)?i:alc_pin_mode_min(dir); | 350 | *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir); |
322 | return 0; | 351 | return 0; |
323 | } | 352 | } |
324 | 353 | ||
325 | static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 354 | static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, |
355 | struct snd_ctl_elem_value *ucontrol) | ||
326 | { | 356 | { |
327 | signed int change; | 357 | signed int change; |
328 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 358 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
329 | hda_nid_t nid = kcontrol->private_value & 0xffff; | 359 | hda_nid_t nid = kcontrol->private_value & 0xffff; |
330 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; | 360 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; |
331 | long val = *ucontrol->value.integer.value; | 361 | long val = *ucontrol->value.integer.value; |
332 | unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00); | 362 | unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, |
363 | AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
364 | 0x00); | ||
333 | 365 | ||
334 | if (val<alc_pin_mode_min(dir) || val>alc_pin_mode_max(dir)) | 366 | if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) |
335 | val = alc_pin_mode_min(dir); | 367 | val = alc_pin_mode_min(dir); |
336 | 368 | ||
337 | change = pinctl != alc_pin_mode_values[val]; | 369 | change = pinctl != alc_pin_mode_values[val]; |
338 | if (change) { | 370 | if (change) { |
339 | /* Set pin mode to that requested */ | 371 | /* Set pin mode to that requested */ |
340 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL, | 372 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL, |
341 | alc_pin_mode_values[val]); | 373 | alc_pin_mode_values[val]); |
342 | 374 | ||
343 | /* Also enable the retasking pin's input/output as required | 375 | /* Also enable the retasking pin's input/output as required |
344 | * for the requested pin mode. Enum values of 2 or less are | 376 | * for the requested pin mode. Enum values of 2 or less are |
@@ -351,15 +383,19 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
351 | * this turns out to be necessary in the future. | 383 | * this turns out to be necessary in the future. |
352 | */ | 384 | */ |
353 | if (val <= 2) { | 385 | if (val <= 2) { |
354 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, | 386 | snd_hda_codec_write(codec, nid, 0, |
355 | AMP_OUT_MUTE); | 387 | AC_VERB_SET_AMP_GAIN_MUTE, |
356 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, | 388 | AMP_OUT_MUTE); |
357 | AMP_IN_UNMUTE(0)); | 389 | snd_hda_codec_write(codec, nid, 0, |
390 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
391 | AMP_IN_UNMUTE(0)); | ||
358 | } else { | 392 | } else { |
359 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, | 393 | snd_hda_codec_write(codec, nid, 0, |
360 | AMP_IN_MUTE(0)); | 394 | AC_VERB_SET_AMP_GAIN_MUTE, |
361 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, | 395 | AMP_IN_MUTE(0)); |
362 | AMP_OUT_UNMUTE); | 396 | snd_hda_codec_write(codec, nid, 0, |
397 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
398 | AMP_OUT_UNMUTE); | ||
363 | } | 399 | } |
364 | } | 400 | } |
365 | return change; | 401 | return change; |
@@ -378,7 +414,8 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
378 | * needed for any "production" models. | 414 | * needed for any "production" models. |
379 | */ | 415 | */ |
380 | #ifdef CONFIG_SND_DEBUG | 416 | #ifdef CONFIG_SND_DEBUG |
381 | static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 417 | static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, |
418 | struct snd_ctl_elem_info *uinfo) | ||
382 | { | 419 | { |
383 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | 420 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
384 | uinfo->count = 1; | 421 | uinfo->count = 1; |
@@ -386,33 +423,38 @@ static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
386 | uinfo->value.integer.max = 1; | 423 | uinfo->value.integer.max = 1; |
387 | return 0; | 424 | return 0; |
388 | } | 425 | } |
389 | static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 426 | static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, |
427 | struct snd_ctl_elem_value *ucontrol) | ||
390 | { | 428 | { |
391 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 429 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
392 | hda_nid_t nid = kcontrol->private_value & 0xffff; | 430 | hda_nid_t nid = kcontrol->private_value & 0xffff; |
393 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | 431 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; |
394 | long *valp = ucontrol->value.integer.value; | 432 | long *valp = ucontrol->value.integer.value; |
395 | unsigned int val = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_GPIO_DATA,0x00); | 433 | unsigned int val = snd_hda_codec_read(codec, nid, 0, |
434 | AC_VERB_GET_GPIO_DATA, 0x00); | ||
396 | 435 | ||
397 | *valp = (val & mask) != 0; | 436 | *valp = (val & mask) != 0; |
398 | return 0; | 437 | return 0; |
399 | } | 438 | } |
400 | static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 439 | static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, |
440 | struct snd_ctl_elem_value *ucontrol) | ||
401 | { | 441 | { |
402 | signed int change; | 442 | signed int change; |
403 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 443 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
404 | hda_nid_t nid = kcontrol->private_value & 0xffff; | 444 | hda_nid_t nid = kcontrol->private_value & 0xffff; |
405 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | 445 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; |
406 | long val = *ucontrol->value.integer.value; | 446 | long val = *ucontrol->value.integer.value; |
407 | unsigned int gpio_data = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_GPIO_DATA,0x00); | 447 | unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0, |
448 | AC_VERB_GET_GPIO_DATA, | ||
449 | 0x00); | ||
408 | 450 | ||
409 | /* Set/unset the masked GPIO bit(s) as needed */ | 451 | /* Set/unset the masked GPIO bit(s) as needed */ |
410 | change = (val==0?0:mask) != (gpio_data & mask); | 452 | change = (val == 0 ? 0 : mask) != (gpio_data & mask); |
411 | if (val==0) | 453 | if (val == 0) |
412 | gpio_data &= ~mask; | 454 | gpio_data &= ~mask; |
413 | else | 455 | else |
414 | gpio_data |= mask; | 456 | gpio_data |= mask; |
415 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_GPIO_DATA,gpio_data); | 457 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data); |
416 | 458 | ||
417 | return change; | 459 | return change; |
418 | } | 460 | } |
@@ -432,7 +474,8 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
432 | * necessary. | 474 | * necessary. |
433 | */ | 475 | */ |
434 | #ifdef CONFIG_SND_DEBUG | 476 | #ifdef CONFIG_SND_DEBUG |
435 | static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 477 | static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, |
478 | struct snd_ctl_elem_info *uinfo) | ||
436 | { | 479 | { |
437 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | 480 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
438 | uinfo->count = 1; | 481 | uinfo->count = 1; |
@@ -440,33 +483,39 @@ static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ele | |||
440 | uinfo->value.integer.max = 1; | 483 | uinfo->value.integer.max = 1; |
441 | return 0; | 484 | return 0; |
442 | } | 485 | } |
443 | static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 486 | static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, |
487 | struct snd_ctl_elem_value *ucontrol) | ||
444 | { | 488 | { |
445 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 489 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
446 | hda_nid_t nid = kcontrol->private_value & 0xffff; | 490 | hda_nid_t nid = kcontrol->private_value & 0xffff; |
447 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | 491 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; |
448 | long *valp = ucontrol->value.integer.value; | 492 | long *valp = ucontrol->value.integer.value; |
449 | unsigned int val = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_DIGI_CONVERT,0x00); | 493 | unsigned int val = snd_hda_codec_read(codec, nid, 0, |
494 | AC_VERB_GET_DIGI_CONVERT, 0x00); | ||
450 | 495 | ||
451 | *valp = (val & mask) != 0; | 496 | *valp = (val & mask) != 0; |
452 | return 0; | 497 | return 0; |
453 | } | 498 | } |
454 | static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 499 | static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, |
500 | struct snd_ctl_elem_value *ucontrol) | ||
455 | { | 501 | { |
456 | signed int change; | 502 | signed int change; |
457 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 503 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
458 | hda_nid_t nid = kcontrol->private_value & 0xffff; | 504 | hda_nid_t nid = kcontrol->private_value & 0xffff; |
459 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | 505 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; |
460 | long val = *ucontrol->value.integer.value; | 506 | long val = *ucontrol->value.integer.value; |
461 | unsigned int ctrl_data = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_DIGI_CONVERT,0x00); | 507 | unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, |
508 | AC_VERB_GET_DIGI_CONVERT, | ||
509 | 0x00); | ||
462 | 510 | ||
463 | /* Set/unset the masked control bit(s) as needed */ | 511 | /* Set/unset the masked control bit(s) as needed */ |
464 | change = (val==0?0:mask) != (ctrl_data & mask); | 512 | change = (val == 0 ? 0 : mask) != (ctrl_data & mask); |
465 | if (val==0) | 513 | if (val==0) |
466 | ctrl_data &= ~mask; | 514 | ctrl_data &= ~mask; |
467 | else | 515 | else |
468 | ctrl_data |= mask; | 516 | ctrl_data |= mask; |
469 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_DIGI_CONVERT_1,ctrl_data); | 517 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, |
518 | ctrl_data); | ||
470 | 519 | ||
471 | return change; | 520 | return change; |
472 | } | 521 | } |
@@ -481,14 +530,17 @@ static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
481 | /* | 530 | /* |
482 | * set up from the preset table | 531 | * set up from the preset table |
483 | */ | 532 | */ |
484 | static void setup_preset(struct alc_spec *spec, const struct alc_config_preset *preset) | 533 | static void setup_preset(struct alc_spec *spec, |
534 | const struct alc_config_preset *preset) | ||
485 | { | 535 | { |
486 | int i; | 536 | int i; |
487 | 537 | ||
488 | for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) | 538 | for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) |
489 | spec->mixers[spec->num_mixers++] = preset->mixers[i]; | 539 | spec->mixers[spec->num_mixers++] = preset->mixers[i]; |
490 | for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; i++) | 540 | for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; |
491 | spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i]; | 541 | i++) |
542 | spec->init_verbs[spec->num_init_verbs++] = | ||
543 | preset->init_verbs[i]; | ||
492 | 544 | ||
493 | spec->channel_mode = preset->channel_mode; | 545 | spec->channel_mode = preset->channel_mode; |
494 | spec->num_channel_mode = preset->num_channel_mode; | 546 | spec->num_channel_mode = preset->num_channel_mode; |
@@ -517,8 +569,8 @@ static void setup_preset(struct alc_spec *spec, const struct alc_config_preset * | |||
517 | * ALC880 3-stack model | 569 | * ALC880 3-stack model |
518 | * | 570 | * |
519 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) | 571 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) |
520 | * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b | 572 | * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, |
521 | * HP = 0x19 | 573 | * F-Mic = 0x1b, HP = 0x19 |
522 | */ | 574 | */ |
523 | 575 | ||
524 | static hda_nid_t alc880_dac_nids[4] = { | 576 | static hda_nid_t alc880_dac_nids[4] = { |
@@ -662,7 +714,8 @@ static struct snd_kcontrol_new alc880_capture_alt_mixer[] = { | |||
662 | /* | 714 | /* |
663 | * ALC880 5-stack model | 715 | * ALC880 5-stack model |
664 | * | 716 | * |
665 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd) | 717 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), |
718 | * Side = 0x02 (0xd) | ||
666 | * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 | 719 | * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 |
667 | * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 | 720 | * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 |
668 | */ | 721 | */ |
@@ -700,7 +753,8 @@ static struct hda_channel_mode alc880_fivestack_modes[2] = { | |||
700 | /* | 753 | /* |
701 | * ALC880 6-stack model | 754 | * ALC880 6-stack model |
702 | * | 755 | * |
703 | * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f) | 756 | * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), |
757 | * Side = 0x05 (0x0f) | ||
704 | * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, | 758 | * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, |
705 | * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b | 759 | * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b |
706 | */ | 760 | */ |
@@ -811,7 +865,8 @@ static struct snd_kcontrol_new alc880_w810_base_mixer[] = { | |||
811 | * Z710V model | 865 | * Z710V model |
812 | * | 866 | * |
813 | * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) | 867 | * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) |
814 | * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a | 868 | * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), |
869 | * Line = 0x1a | ||
815 | */ | 870 | */ |
816 | 871 | ||
817 | static hda_nid_t alc880_z71v_dac_nids[1] = { | 872 | static hda_nid_t alc880_z71v_dac_nids[1] = { |
@@ -966,7 +1021,8 @@ static int alc_build_controls(struct hda_codec *codec) | |||
966 | } | 1021 | } |
967 | 1022 | ||
968 | if (spec->multiout.dig_out_nid) { | 1023 | if (spec->multiout.dig_out_nid) { |
969 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | 1024 | err = snd_hda_create_spdif_out_ctls(codec, |
1025 | spec->multiout.dig_out_nid); | ||
970 | if (err < 0) | 1026 | if (err < 0) |
971 | return err; | 1027 | return err; |
972 | } | 1028 | } |
@@ -999,8 +1055,8 @@ static struct hda_verb alc880_volume_init_verbs[] = { | |||
999 | 1055 | ||
1000 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 1056 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
1001 | * mixer widget | 1057 | * mixer widget |
1002 | * Note: PASD motherboards uses the Line In 2 as the input for front panel | 1058 | * Note: PASD motherboards uses the Line In 2 as the input for front |
1003 | * mic (mic 2) | 1059 | * panel mic (mic 2) |
1004 | */ | 1060 | */ |
1005 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 1061 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
1006 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1062 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -1154,8 +1210,8 @@ static struct hda_verb alc880_pin_z71v_init_verbs[] = { | |||
1154 | 1210 | ||
1155 | /* | 1211 | /* |
1156 | * 6-stack pin configuration: | 1212 | * 6-stack pin configuration: |
1157 | * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19, | 1213 | * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, |
1158 | * line = 0x1a, HP = 0x1b | 1214 | * f-mic = 0x19, line = 0x1a, HP = 0x1b |
1159 | */ | 1215 | */ |
1160 | static struct hda_verb alc880_pin_6stack_init_verbs[] = { | 1216 | static struct hda_verb alc880_pin_6stack_init_verbs[] = { |
1161 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | 1217 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ |
@@ -1587,8 +1643,8 @@ static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
1587 | struct snd_pcm_substream *substream) | 1643 | struct snd_pcm_substream *substream) |
1588 | { | 1644 | { |
1589 | struct alc_spec *spec = codec->spec; | 1645 | struct alc_spec *spec = codec->spec; |
1590 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, | 1646 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, |
1591 | format, substream); | 1647 | stream_tag, format, substream); |
1592 | } | 1648 | } |
1593 | 1649 | ||
1594 | static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | 1650 | static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, |
@@ -1640,7 +1696,8 @@ static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
1640 | { | 1696 | { |
1641 | struct alc_spec *spec = codec->spec; | 1697 | struct alc_spec *spec = codec->spec; |
1642 | 1698 | ||
1643 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0); | 1699 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], |
1700 | 0, 0, 0); | ||
1644 | return 0; | 1701 | return 0; |
1645 | } | 1702 | } |
1646 | 1703 | ||
@@ -1822,7 +1879,8 @@ static struct hda_channel_mode alc880_test_modes[4] = { | |||
1822 | { 8, NULL }, | 1879 | { 8, NULL }, |
1823 | }; | 1880 | }; |
1824 | 1881 | ||
1825 | static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1882 | static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, |
1883 | struct snd_ctl_elem_info *uinfo) | ||
1826 | { | 1884 | { |
1827 | static char *texts[] = { | 1885 | static char *texts[] = { |
1828 | "N/A", "Line Out", "HP Out", | 1886 | "N/A", "Line Out", "HP Out", |
@@ -1837,7 +1895,8 @@ static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1837 | return 0; | 1895 | return 0; |
1838 | } | 1896 | } |
1839 | 1897 | ||
1840 | static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1898 | static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, |
1899 | struct snd_ctl_elem_value *ucontrol) | ||
1841 | { | 1900 | { |
1842 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1901 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1843 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | 1902 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; |
@@ -1863,7 +1922,8 @@ static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
1863 | return 0; | 1922 | return 0; |
1864 | } | 1923 | } |
1865 | 1924 | ||
1866 | static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1925 | static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, |
1926 | struct snd_ctl_elem_value *ucontrol) | ||
1867 | { | 1927 | { |
1868 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1928 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1869 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | 1929 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; |
@@ -1881,15 +1941,18 @@ static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
1881 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 1941 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
1882 | new_ctl = ctls[ucontrol->value.enumerated.item[0]]; | 1942 | new_ctl = ctls[ucontrol->value.enumerated.item[0]]; |
1883 | if (old_ctl != new_ctl) { | 1943 | if (old_ctl != new_ctl) { |
1884 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); | 1944 | snd_hda_codec_write(codec, nid, 0, |
1945 | AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); | ||
1885 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 1946 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, |
1886 | ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000); | 1947 | (ucontrol->value.enumerated.item[0] >= 3 ? |
1948 | 0xb080 : 0xb000)); | ||
1887 | return 1; | 1949 | return 1; |
1888 | } | 1950 | } |
1889 | return 0; | 1951 | return 0; |
1890 | } | 1952 | } |
1891 | 1953 | ||
1892 | static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1954 | static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, |
1955 | struct snd_ctl_elem_info *uinfo) | ||
1893 | { | 1956 | { |
1894 | static char *texts[] = { | 1957 | static char *texts[] = { |
1895 | "Front", "Surround", "CLFE", "Side" | 1958 | "Front", "Surround", "CLFE", "Side" |
@@ -1903,7 +1966,8 @@ static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1903 | return 0; | 1966 | return 0; |
1904 | } | 1967 | } |
1905 | 1968 | ||
1906 | static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1969 | static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, |
1970 | struct snd_ctl_elem_value *ucontrol) | ||
1907 | { | 1971 | { |
1908 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1972 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1909 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | 1973 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; |
@@ -1914,7 +1978,8 @@ static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
1914 | return 0; | 1978 | return 0; |
1915 | } | 1979 | } |
1916 | 1980 | ||
1917 | static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1981 | static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, |
1982 | struct snd_ctl_elem_value *ucontrol) | ||
1918 | { | 1983 | { |
1919 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1984 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1920 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | 1985 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; |
@@ -2739,7 +2804,8 @@ static int patch_alc880(struct hda_codec *codec) | |||
2739 | 2804 | ||
2740 | board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl); | 2805 | board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl); |
2741 | if (board_config < 0 || board_config >= ALC880_MODEL_LAST) { | 2806 | if (board_config < 0 || board_config >= ALC880_MODEL_LAST) { |
2742 | printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n"); | 2807 | printk(KERN_INFO "hda_codec: Unknown model for ALC880, " |
2808 | "trying auto-probe from BIOS...\n"); | ||
2743 | board_config = ALC880_AUTO; | 2809 | board_config = ALC880_AUTO; |
2744 | } | 2810 | } |
2745 | 2811 | ||
@@ -2750,7 +2816,9 @@ static int patch_alc880(struct hda_codec *codec) | |||
2750 | alc_free(codec); | 2816 | alc_free(codec); |
2751 | return err; | 2817 | return err; |
2752 | } else if (! err) { | 2818 | } else if (! err) { |
2753 | printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 3-stack mode...\n"); | 2819 | printk(KERN_INFO |
2820 | "hda_codec: Cannot set up configuration " | ||
2821 | "from BIOS. Using 3-stack mode...\n"); | ||
2754 | board_config = ALC880_3ST; | 2822 | board_config = ALC880_3ST; |
2755 | } | 2823 | } |
2756 | } | 2824 | } |
@@ -3947,7 +4015,8 @@ static int patch_alc260(struct hda_codec *codec) | |||
3947 | 4015 | ||
3948 | board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl); | 4016 | board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl); |
3949 | if (board_config < 0 || board_config >= ALC260_MODEL_LAST) { | 4017 | if (board_config < 0 || board_config >= ALC260_MODEL_LAST) { |
3950 | snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n"); | 4018 | snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260, " |
4019 | "trying auto-probe from BIOS...\n"); | ||
3951 | board_config = ALC260_AUTO; | 4020 | board_config = ALC260_AUTO; |
3952 | } | 4021 | } |
3953 | 4022 | ||
@@ -3958,7 +4027,9 @@ static int patch_alc260(struct hda_codec *codec) | |||
3958 | alc_free(codec); | 4027 | alc_free(codec); |
3959 | return err; | 4028 | return err; |
3960 | } else if (! err) { | 4029 | } else if (! err) { |
3961 | printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n"); | 4030 | printk(KERN_INFO |
4031 | "hda_codec: Cannot set up configuration " | ||
4032 | "from BIOS. Using base mode...\n"); | ||
3962 | board_config = ALC260_BASIC; | 4033 | board_config = ALC260_BASIC; |
3963 | } | 4034 | } |
3964 | } | 4035 | } |
@@ -4320,9 +4391,12 @@ static struct snd_kcontrol_new alc882_capture_mixer[] = { | |||
4320 | static struct hda_board_config alc882_cfg_tbl[] = { | 4391 | static struct hda_board_config alc882_cfg_tbl[] = { |
4321 | { .modelname = "3stack-dig", .config = ALC882_3ST_DIG }, | 4392 | { .modelname = "3stack-dig", .config = ALC882_3ST_DIG }, |
4322 | { .modelname = "6stack-dig", .config = ALC882_6ST_DIG }, | 4393 | { .modelname = "6stack-dig", .config = ALC882_6ST_DIG }, |
4323 | { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* MSI */ | 4394 | { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, |
4324 | { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* Foxconn */ | 4395 | .config = ALC882_6ST_DIG }, /* MSI */ |
4325 | { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* ECS */ | 4396 | { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, |
4397 | .config = ALC882_6ST_DIG }, /* Foxconn */ | ||
4398 | { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, | ||
4399 | .config = ALC882_6ST_DIG }, /* ECS to Intel*/ | ||
4326 | { .modelname = "auto", .config = ALC882_AUTO }, | 4400 | { .modelname = "auto", .config = ALC882_AUTO }, |
4327 | {} | 4401 | {} |
4328 | }; | 4402 | }; |
@@ -4439,10 +4513,6 @@ static void alc882_auto_init(struct hda_codec *codec) | |||
4439 | alc882_auto_init_analog_input(codec); | 4513 | alc882_auto_init_analog_input(codec); |
4440 | } | 4514 | } |
4441 | 4515 | ||
4442 | /* | ||
4443 | * ALC882 Headphone poll in 3.5.1a or 3.5.2 | ||
4444 | */ | ||
4445 | |||
4446 | static int patch_alc882(struct hda_codec *codec) | 4516 | static int patch_alc882(struct hda_codec *codec) |
4447 | { | 4517 | { |
4448 | struct alc_spec *spec; | 4518 | struct alc_spec *spec; |
@@ -4457,7 +4527,8 @@ static int patch_alc882(struct hda_codec *codec) | |||
4457 | board_config = snd_hda_check_board_config(codec, alc882_cfg_tbl); | 4527 | board_config = snd_hda_check_board_config(codec, alc882_cfg_tbl); |
4458 | 4528 | ||
4459 | if (board_config < 0 || board_config >= ALC882_MODEL_LAST) { | 4529 | if (board_config < 0 || board_config >= ALC882_MODEL_LAST) { |
4460 | printk(KERN_INFO "hda_codec: Unknown model for ALC882, trying auto-probe from BIOS...\n"); | 4530 | printk(KERN_INFO "hda_codec: Unknown model for ALC882, " |
4531 | "trying auto-probe from BIOS...\n"); | ||
4461 | board_config = ALC882_AUTO; | 4532 | board_config = ALC882_AUTO; |
4462 | } | 4533 | } |
4463 | 4534 | ||
@@ -4468,7 +4539,9 @@ static int patch_alc882(struct hda_codec *codec) | |||
4468 | alc_free(codec); | 4539 | alc_free(codec); |
4469 | return err; | 4540 | return err; |
4470 | } else if (! err) { | 4541 | } else if (! err) { |
4471 | printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n"); | 4542 | printk(KERN_INFO |
4543 | "hda_codec: Cannot set up configuration " | ||
4544 | "from BIOS. Using base mode...\n"); | ||
4472 | board_config = ALC882_3ST_DIG; | 4545 | board_config = ALC882_3ST_DIG; |
4473 | } | 4546 | } |
4474 | } | 4547 | } |
@@ -4509,6 +4582,652 @@ static int patch_alc882(struct hda_codec *codec) | |||
4509 | } | 4582 | } |
4510 | 4583 | ||
4511 | /* | 4584 | /* |
4585 | * ALC883 support | ||
4586 | * | ||
4587 | * ALC883 is almost identical with ALC880 but has cleaner and more flexible | ||
4588 | * configuration. Each pin widget can choose any input DACs and a mixer. | ||
4589 | * Each ADC is connected from a mixer of all inputs. This makes possible | ||
4590 | * 6-channel independent captures. | ||
4591 | * | ||
4592 | * In addition, an independent DAC for the multi-playback (not used in this | ||
4593 | * driver yet). | ||
4594 | */ | ||
4595 | #define ALC883_DIGOUT_NID 0x06 | ||
4596 | #define ALC883_DIGIN_NID 0x0a | ||
4597 | |||
4598 | static hda_nid_t alc883_dac_nids[4] = { | ||
4599 | /* front, rear, clfe, rear_surr */ | ||
4600 | 0x02, 0x04, 0x03, 0x05 | ||
4601 | }; | ||
4602 | |||
4603 | static hda_nid_t alc883_adc_nids[2] = { | ||
4604 | /* ADC1-2 */ | ||
4605 | 0x08, 0x09, | ||
4606 | }; | ||
4607 | /* input MUX */ | ||
4608 | /* FIXME: should be a matrix-type input source selection */ | ||
4609 | |||
4610 | static struct hda_input_mux alc883_capture_source = { | ||
4611 | .num_items = 4, | ||
4612 | .items = { | ||
4613 | { "Mic", 0x0 }, | ||
4614 | { "Front Mic", 0x1 }, | ||
4615 | { "Line", 0x2 }, | ||
4616 | { "CD", 0x4 }, | ||
4617 | }, | ||
4618 | }; | ||
4619 | #define alc883_mux_enum_info alc_mux_enum_info | ||
4620 | #define alc883_mux_enum_get alc_mux_enum_get | ||
4621 | |||
4622 | static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
4623 | struct snd_ctl_elem_value *ucontrol) | ||
4624 | { | ||
4625 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4626 | struct alc_spec *spec = codec->spec; | ||
4627 | const struct hda_input_mux *imux = spec->input_mux; | ||
4628 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
4629 | static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; | ||
4630 | hda_nid_t nid = capture_mixers[adc_idx]; | ||
4631 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; | ||
4632 | unsigned int i, idx; | ||
4633 | |||
4634 | idx = ucontrol->value.enumerated.item[0]; | ||
4635 | if (idx >= imux->num_items) | ||
4636 | idx = imux->num_items - 1; | ||
4637 | if (*cur_val == idx && ! codec->in_resume) | ||
4638 | return 0; | ||
4639 | for (i = 0; i < imux->num_items; i++) { | ||
4640 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | ||
4641 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
4642 | v | (imux->items[i].index << 8)); | ||
4643 | } | ||
4644 | *cur_val = idx; | ||
4645 | return 1; | ||
4646 | } | ||
4647 | /* | ||
4648 | * 2ch mode | ||
4649 | */ | ||
4650 | static struct hda_channel_mode alc883_3ST_2ch_modes[1] = { | ||
4651 | { 2, NULL } | ||
4652 | }; | ||
4653 | |||
4654 | /* | ||
4655 | * 2ch mode | ||
4656 | */ | ||
4657 | static struct hda_verb alc883_3ST_ch2_init[] = { | ||
4658 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
4659 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
4660 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
4661 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
4662 | { } /* end */ | ||
4663 | }; | ||
4664 | |||
4665 | /* | ||
4666 | * 6ch mode | ||
4667 | */ | ||
4668 | static struct hda_verb alc883_3ST_ch6_init[] = { | ||
4669 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
4670 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
4671 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
4672 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
4673 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
4674 | { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
4675 | { } /* end */ | ||
4676 | }; | ||
4677 | |||
4678 | static struct hda_channel_mode alc883_3ST_6ch_modes[2] = { | ||
4679 | { 2, alc883_3ST_ch2_init }, | ||
4680 | { 6, alc883_3ST_ch6_init }, | ||
4681 | }; | ||
4682 | |||
4683 | /* | ||
4684 | * 6ch mode | ||
4685 | */ | ||
4686 | static struct hda_verb alc883_sixstack_ch6_init[] = { | ||
4687 | { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, | ||
4688 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
4689 | { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
4690 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
4691 | { } /* end */ | ||
4692 | }; | ||
4693 | |||
4694 | /* | ||
4695 | * 8ch mode | ||
4696 | */ | ||
4697 | static struct hda_verb alc883_sixstack_ch8_init[] = { | ||
4698 | { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
4699 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
4700 | { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
4701 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
4702 | { } /* end */ | ||
4703 | }; | ||
4704 | |||
4705 | static struct hda_channel_mode alc883_sixstack_modes[2] = { | ||
4706 | { 6, alc883_sixstack_ch6_init }, | ||
4707 | { 8, alc883_sixstack_ch8_init }, | ||
4708 | }; | ||
4709 | |||
4710 | /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 | ||
4711 | * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b | ||
4712 | */ | ||
4713 | |||
4714 | static struct snd_kcontrol_new alc883_base_mixer[] = { | ||
4715 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
4716 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
4717 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
4718 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
4719 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
4720 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
4721 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
4722 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
4723 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
4724 | HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), | ||
4725 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
4726 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
4727 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
4728 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
4729 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
4730 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
4731 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
4732 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
4733 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
4734 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
4735 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
4736 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
4737 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
4738 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
4739 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
4740 | { | ||
4741 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4742 | /* .name = "Capture Source", */ | ||
4743 | .name = "Input Source", | ||
4744 | .count = 2, | ||
4745 | .info = alc883_mux_enum_info, | ||
4746 | .get = alc883_mux_enum_get, | ||
4747 | .put = alc883_mux_enum_put, | ||
4748 | }, | ||
4749 | { } /* end */ | ||
4750 | }; | ||
4751 | |||
4752 | static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = { | ||
4753 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
4754 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
4755 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
4756 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
4757 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
4758 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
4759 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
4760 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
4761 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
4762 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
4763 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
4764 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
4765 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
4766 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
4767 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
4768 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
4769 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
4770 | { | ||
4771 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4772 | /* .name = "Capture Source", */ | ||
4773 | .name = "Input Source", | ||
4774 | .count = 2, | ||
4775 | .info = alc883_mux_enum_info, | ||
4776 | .get = alc883_mux_enum_get, | ||
4777 | .put = alc883_mux_enum_put, | ||
4778 | }, | ||
4779 | { } /* end */ | ||
4780 | }; | ||
4781 | |||
4782 | static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { | ||
4783 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
4784 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
4785 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
4786 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
4787 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
4788 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
4789 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
4790 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
4791 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
4792 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
4793 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
4794 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
4795 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
4796 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
4797 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
4798 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
4799 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
4800 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
4801 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
4802 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
4803 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
4804 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
4805 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
4806 | { | ||
4807 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4808 | /* .name = "Capture Source", */ | ||
4809 | .name = "Input Source", | ||
4810 | .count = 2, | ||
4811 | .info = alc883_mux_enum_info, | ||
4812 | .get = alc883_mux_enum_get, | ||
4813 | .put = alc883_mux_enum_put, | ||
4814 | }, | ||
4815 | { } /* end */ | ||
4816 | }; | ||
4817 | |||
4818 | static struct snd_kcontrol_new alc883_chmode_mixer[] = { | ||
4819 | { | ||
4820 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4821 | .name = "Channel Mode", | ||
4822 | .info = alc_ch_mode_info, | ||
4823 | .get = alc_ch_mode_get, | ||
4824 | .put = alc_ch_mode_put, | ||
4825 | }, | ||
4826 | { } /* end */ | ||
4827 | }; | ||
4828 | |||
4829 | static struct hda_verb alc883_init_verbs[] = { | ||
4830 | /* ADC1: mute amp left and right */ | ||
4831 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
4832 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
4833 | /* ADC2: mute amp left and right */ | ||
4834 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
4835 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
4836 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | ||
4837 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
4838 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
4839 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
4840 | /* Rear mixer */ | ||
4841 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
4842 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
4843 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
4844 | /* CLFE mixer */ | ||
4845 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
4846 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
4847 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
4848 | /* Side mixer */ | ||
4849 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
4850 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
4851 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
4852 | |||
4853 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4854 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4855 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
4856 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
4857 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
4858 | |||
4859 | /* Front Pin: output 0 (0x0c) */ | ||
4860 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
4861 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
4862 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
4863 | /* Rear Pin: output 1 (0x0d) */ | ||
4864 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
4865 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
4866 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
4867 | /* CLFE Pin: output 2 (0x0e) */ | ||
4868 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
4869 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
4870 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
4871 | /* Side Pin: output 3 (0x0f) */ | ||
4872 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
4873 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
4874 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
4875 | /* Mic (rear) pin: input vref at 80% */ | ||
4876 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
4877 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
4878 | /* Front Mic pin: input vref at 80% */ | ||
4879 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
4880 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
4881 | /* Line In pin: input */ | ||
4882 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
4883 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
4884 | /* Line-2 In: Headphone output (output 0 - 0x0c) */ | ||
4885 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
4886 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
4887 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
4888 | /* CD pin widget for input */ | ||
4889 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
4890 | |||
4891 | /* FIXME: use matrix-type input source selection */ | ||
4892 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | ||
4893 | /* Input mixer2 */ | ||
4894 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4895 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4896 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
4897 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
4898 | /* Input mixer3 */ | ||
4899 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4900 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4901 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
4902 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
4903 | { } | ||
4904 | }; | ||
4905 | |||
4906 | /* | ||
4907 | * generic initialization of ADC, input mixers and output mixers | ||
4908 | */ | ||
4909 | static struct hda_verb alc883_auto_init_verbs[] = { | ||
4910 | /* | ||
4911 | * Unmute ADC0-2 and set the default input to mic-in | ||
4912 | */ | ||
4913 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
4914 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4915 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
4916 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4917 | |||
4918 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | ||
4919 | * mixer widget | ||
4920 | * Note: PASD motherboards uses the Line In 2 as the input for front panel | ||
4921 | * mic (mic 2) | ||
4922 | */ | ||
4923 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | ||
4924 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4925 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4926 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
4927 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
4928 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
4929 | |||
4930 | /* | ||
4931 | * Set up output mixers (0x0c - 0x0f) | ||
4932 | */ | ||
4933 | /* set vol=0 to output mixers */ | ||
4934 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
4935 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
4936 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
4937 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
4938 | /* set up input amps for analog loopback */ | ||
4939 | /* Amp Indices: DAC = 0, mixer = 1 */ | ||
4940 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4941 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4942 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4943 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4944 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4945 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4946 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4947 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4948 | {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4949 | {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4950 | |||
4951 | /* FIXME: use matrix-type input source selection */ | ||
4952 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | ||
4953 | /* Input mixer1 */ | ||
4954 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4955 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4956 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
4957 | //{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
4958 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
4959 | /* Input mixer2 */ | ||
4960 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4961 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
4962 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
4963 | //{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
4964 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
4965 | |||
4966 | { } | ||
4967 | }; | ||
4968 | |||
4969 | /* capture mixer elements */ | ||
4970 | static struct snd_kcontrol_new alc883_capture_mixer[] = { | ||
4971 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
4972 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
4973 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
4974 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
4975 | { | ||
4976 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4977 | /* The multiple "Capture Source" controls confuse alsamixer | ||
4978 | * So call somewhat different.. | ||
4979 | * FIXME: the controls appear in the "playback" view! | ||
4980 | */ | ||
4981 | /* .name = "Capture Source", */ | ||
4982 | .name = "Input Source", | ||
4983 | .count = 2, | ||
4984 | .info = alc882_mux_enum_info, | ||
4985 | .get = alc882_mux_enum_get, | ||
4986 | .put = alc882_mux_enum_put, | ||
4987 | }, | ||
4988 | { } /* end */ | ||
4989 | }; | ||
4990 | |||
4991 | /* pcm configuration: identiacal with ALC880 */ | ||
4992 | #define alc883_pcm_analog_playback alc880_pcm_analog_playback | ||
4993 | #define alc883_pcm_analog_capture alc880_pcm_analog_capture | ||
4994 | #define alc883_pcm_digital_playback alc880_pcm_digital_playback | ||
4995 | #define alc883_pcm_digital_capture alc880_pcm_digital_capture | ||
4996 | |||
4997 | /* | ||
4998 | * configuration and preset | ||
4999 | */ | ||
5000 | static struct hda_board_config alc883_cfg_tbl[] = { | ||
5001 | { .modelname = "3stack-dig", .config = ALC883_3ST_2ch_DIG }, | ||
5002 | { .modelname = "6stack-dig", .config = ALC883_6ST_DIG }, | ||
5003 | { .modelname = "6stack-dig-demo", .config = ALC888_DEMO_BOARD }, | ||
5004 | { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, | ||
5005 | .config = ALC883_6ST_DIG }, /* MSI */ | ||
5006 | { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, | ||
5007 | .config = ALC883_6ST_DIG }, /* Foxconn */ | ||
5008 | { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, | ||
5009 | .config = ALC883_3ST_6ch_DIG }, /* ECS to Intel*/ | ||
5010 | { .pci_subvendor = 0x108e, .pci_subdevice = 0x534d, | ||
5011 | .config = ALC883_3ST_6ch }, | ||
5012 | { .modelname = "auto", .config = ALC883_AUTO }, | ||
5013 | {} | ||
5014 | }; | ||
5015 | |||
5016 | static struct alc_config_preset alc883_presets[] = { | ||
5017 | [ALC883_3ST_2ch_DIG] = { | ||
5018 | .mixers = { alc883_3ST_2ch_mixer }, | ||
5019 | .init_verbs = { alc883_init_verbs }, | ||
5020 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
5021 | .dac_nids = alc883_dac_nids, | ||
5022 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
5023 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
5024 | .adc_nids = alc883_adc_nids, | ||
5025 | .dig_in_nid = ALC883_DIGIN_NID, | ||
5026 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | ||
5027 | .channel_mode = alc883_3ST_2ch_modes, | ||
5028 | .input_mux = &alc883_capture_source, | ||
5029 | }, | ||
5030 | [ALC883_3ST_6ch_DIG] = { | ||
5031 | .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, | ||
5032 | .init_verbs = { alc883_init_verbs }, | ||
5033 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
5034 | .dac_nids = alc883_dac_nids, | ||
5035 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
5036 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
5037 | .adc_nids = alc883_adc_nids, | ||
5038 | .dig_in_nid = ALC883_DIGIN_NID, | ||
5039 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), | ||
5040 | .channel_mode = alc883_3ST_6ch_modes, | ||
5041 | .input_mux = &alc883_capture_source, | ||
5042 | }, | ||
5043 | [ALC883_3ST_6ch] = { | ||
5044 | .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, | ||
5045 | .init_verbs = { alc883_init_verbs }, | ||
5046 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
5047 | .dac_nids = alc883_dac_nids, | ||
5048 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
5049 | .adc_nids = alc883_adc_nids, | ||
5050 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), | ||
5051 | .channel_mode = alc883_3ST_6ch_modes, | ||
5052 | .input_mux = &alc883_capture_source, | ||
5053 | }, | ||
5054 | [ALC883_6ST_DIG] = { | ||
5055 | .mixers = { alc883_base_mixer, alc883_chmode_mixer }, | ||
5056 | .init_verbs = { alc883_init_verbs }, | ||
5057 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
5058 | .dac_nids = alc883_dac_nids, | ||
5059 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
5060 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
5061 | .adc_nids = alc883_adc_nids, | ||
5062 | .dig_in_nid = ALC883_DIGIN_NID, | ||
5063 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), | ||
5064 | .channel_mode = alc883_sixstack_modes, | ||
5065 | .input_mux = &alc883_capture_source, | ||
5066 | }, | ||
5067 | [ALC888_DEMO_BOARD] = { | ||
5068 | .mixers = { alc883_base_mixer, alc883_chmode_mixer }, | ||
5069 | .init_verbs = { alc883_init_verbs }, | ||
5070 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
5071 | .dac_nids = alc883_dac_nids, | ||
5072 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
5073 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
5074 | .adc_nids = alc883_adc_nids, | ||
5075 | .dig_in_nid = ALC883_DIGIN_NID, | ||
5076 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), | ||
5077 | .channel_mode = alc883_sixstack_modes, | ||
5078 | .input_mux = &alc883_capture_source, | ||
5079 | }, | ||
5080 | }; | ||
5081 | |||
5082 | |||
5083 | /* | ||
5084 | * BIOS auto configuration | ||
5085 | */ | ||
5086 | static void alc883_auto_set_output_and_unmute(struct hda_codec *codec, | ||
5087 | hda_nid_t nid, int pin_type, | ||
5088 | int dac_idx) | ||
5089 | { | ||
5090 | /* set as output */ | ||
5091 | struct alc_spec *spec = codec->spec; | ||
5092 | int idx; | ||
5093 | |||
5094 | if (spec->multiout.dac_nids[dac_idx] == 0x25) | ||
5095 | idx = 4; | ||
5096 | else | ||
5097 | idx = spec->multiout.dac_nids[dac_idx] - 2; | ||
5098 | |||
5099 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
5100 | pin_type); | ||
5101 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
5102 | AMP_OUT_UNMUTE); | ||
5103 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); | ||
5104 | |||
5105 | } | ||
5106 | |||
5107 | static void alc883_auto_init_multi_out(struct hda_codec *codec) | ||
5108 | { | ||
5109 | struct alc_spec *spec = codec->spec; | ||
5110 | int i; | ||
5111 | |||
5112 | for (i = 0; i <= HDA_SIDE; i++) { | ||
5113 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | ||
5114 | if (nid) | ||
5115 | alc883_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); | ||
5116 | } | ||
5117 | } | ||
5118 | |||
5119 | static void alc883_auto_init_hp_out(struct hda_codec *codec) | ||
5120 | { | ||
5121 | struct alc_spec *spec = codec->spec; | ||
5122 | hda_nid_t pin; | ||
5123 | |||
5124 | pin = spec->autocfg.hp_pin; | ||
5125 | if (pin) /* connect to front */ | ||
5126 | /* use dac 0 */ | ||
5127 | alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | ||
5128 | } | ||
5129 | |||
5130 | #define alc883_is_input_pin(nid) alc880_is_input_pin(nid) | ||
5131 | #define ALC883_PIN_CD_NID ALC880_PIN_CD_NID | ||
5132 | |||
5133 | static void alc883_auto_init_analog_input(struct hda_codec *codec) | ||
5134 | { | ||
5135 | struct alc_spec *spec = codec->spec; | ||
5136 | int i; | ||
5137 | |||
5138 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
5139 | hda_nid_t nid = spec->autocfg.input_pins[i]; | ||
5140 | if (alc883_is_input_pin(nid)) { | ||
5141 | snd_hda_codec_write(codec, nid, 0, | ||
5142 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
5143 | (i <= AUTO_PIN_FRONT_MIC ? | ||
5144 | PIN_VREF80 : PIN_IN)); | ||
5145 | if (nid != ALC883_PIN_CD_NID) | ||
5146 | snd_hda_codec_write(codec, nid, 0, | ||
5147 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
5148 | AMP_OUT_MUTE); | ||
5149 | } | ||
5150 | } | ||
5151 | } | ||
5152 | |||
5153 | /* almost identical with ALC880 parser... */ | ||
5154 | static int alc883_parse_auto_config(struct hda_codec *codec) | ||
5155 | { | ||
5156 | struct alc_spec *spec = codec->spec; | ||
5157 | int err = alc880_parse_auto_config(codec); | ||
5158 | |||
5159 | if (err < 0) | ||
5160 | return err; | ||
5161 | else if (err > 0) | ||
5162 | /* hack - override the init verbs */ | ||
5163 | spec->init_verbs[0] = alc883_auto_init_verbs; | ||
5164 | spec->mixers[spec->num_mixers] = alc883_capture_mixer; | ||
5165 | spec->num_mixers++; | ||
5166 | return err; | ||
5167 | } | ||
5168 | |||
5169 | /* additional initialization for auto-configuration model */ | ||
5170 | static void alc883_auto_init(struct hda_codec *codec) | ||
5171 | { | ||
5172 | alc883_auto_init_multi_out(codec); | ||
5173 | alc883_auto_init_hp_out(codec); | ||
5174 | alc883_auto_init_analog_input(codec); | ||
5175 | } | ||
5176 | |||
5177 | static int patch_alc883(struct hda_codec *codec) | ||
5178 | { | ||
5179 | struct alc_spec *spec; | ||
5180 | int err, board_config; | ||
5181 | |||
5182 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
5183 | if (spec == NULL) | ||
5184 | return -ENOMEM; | ||
5185 | |||
5186 | codec->spec = spec; | ||
5187 | |||
5188 | board_config = snd_hda_check_board_config(codec, alc883_cfg_tbl); | ||
5189 | if (board_config < 0 || board_config >= ALC883_MODEL_LAST) { | ||
5190 | printk(KERN_INFO "hda_codec: Unknown model for ALC883, " | ||
5191 | "trying auto-probe from BIOS...\n"); | ||
5192 | board_config = ALC883_AUTO; | ||
5193 | } | ||
5194 | |||
5195 | if (board_config == ALC883_AUTO) { | ||
5196 | /* automatic parse from the BIOS config */ | ||
5197 | err = alc883_parse_auto_config(codec); | ||
5198 | if (err < 0) { | ||
5199 | alc_free(codec); | ||
5200 | return err; | ||
5201 | } else if (! err) { | ||
5202 | printk(KERN_INFO | ||
5203 | "hda_codec: Cannot set up configuration " | ||
5204 | "from BIOS. Using base mode...\n"); | ||
5205 | board_config = ALC883_3ST_2ch_DIG; | ||
5206 | } | ||
5207 | } | ||
5208 | |||
5209 | if (board_config != ALC883_AUTO) | ||
5210 | setup_preset(spec, &alc883_presets[board_config]); | ||
5211 | |||
5212 | spec->stream_name_analog = "ALC883 Analog"; | ||
5213 | spec->stream_analog_playback = &alc883_pcm_analog_playback; | ||
5214 | spec->stream_analog_capture = &alc883_pcm_analog_capture; | ||
5215 | |||
5216 | spec->stream_name_digital = "ALC883 Digital"; | ||
5217 | spec->stream_digital_playback = &alc883_pcm_digital_playback; | ||
5218 | spec->stream_digital_capture = &alc883_pcm_digital_capture; | ||
5219 | |||
5220 | spec->adc_nids = alc883_adc_nids; | ||
5221 | spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); | ||
5222 | |||
5223 | codec->patch_ops = alc_patch_ops; | ||
5224 | if (board_config == ALC883_AUTO) | ||
5225 | spec->init_hook = alc883_auto_init; | ||
5226 | |||
5227 | return 0; | ||
5228 | } | ||
5229 | |||
5230 | /* | ||
4512 | * ALC262 support | 5231 | * ALC262 support |
4513 | */ | 5232 | */ |
4514 | 5233 | ||
@@ -4542,6 +5261,28 @@ static struct snd_kcontrol_new alc262_base_mixer[] = { | |||
4542 | { } /* end */ | 5261 | { } /* end */ |
4543 | }; | 5262 | }; |
4544 | 5263 | ||
5264 | static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { | ||
5265 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
5266 | HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
5267 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
5268 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
5269 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), | ||
5270 | |||
5271 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
5272 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
5273 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | ||
5274 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | ||
5275 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
5276 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
5277 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
5278 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
5279 | HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
5280 | HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
5281 | HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT), | ||
5282 | HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT), | ||
5283 | { } /* end */ | ||
5284 | }; | ||
5285 | |||
4545 | #define alc262_capture_mixer alc882_capture_mixer | 5286 | #define alc262_capture_mixer alc882_capture_mixer |
4546 | #define alc262_capture_alt_mixer alc882_capture_alt_mixer | 5287 | #define alc262_capture_alt_mixer alc882_capture_alt_mixer |
4547 | 5288 | ||
@@ -4645,6 +5386,17 @@ static struct hda_input_mux alc262_fujitsu_capture_source = { | |||
4645 | }, | 5386 | }, |
4646 | }; | 5387 | }; |
4647 | 5388 | ||
5389 | static struct hda_input_mux alc262_HP_capture_source = { | ||
5390 | .num_items = 5, | ||
5391 | .items = { | ||
5392 | { "Mic", 0x0 }, | ||
5393 | { "Front Mic", 0x3 }, | ||
5394 | { "Line", 0x2 }, | ||
5395 | { "CD", 0x4 }, | ||
5396 | { "AUX IN", 0x6 }, | ||
5397 | }, | ||
5398 | }; | ||
5399 | |||
4648 | /* mute/unmute internal speaker according to the hp jack and mute state */ | 5400 | /* mute/unmute internal speaker according to the hp jack and mute state */ |
4649 | static void alc262_fujitsu_automute(struct hda_codec *codec, int force) | 5401 | static void alc262_fujitsu_automute(struct hda_codec *codec, int force) |
4650 | { | 5402 | { |
@@ -4868,6 +5620,93 @@ static struct hda_verb alc262_volume_init_verbs[] = { | |||
4868 | { } | 5620 | { } |
4869 | }; | 5621 | }; |
4870 | 5622 | ||
5623 | static struct hda_verb alc262_HP_BPC_init_verbs[] = { | ||
5624 | /* | ||
5625 | * Unmute ADC0-2 and set the default input to mic-in | ||
5626 | */ | ||
5627 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5628 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5629 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5630 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5631 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5632 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5633 | |||
5634 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | ||
5635 | * mixer widget | ||
5636 | * Note: PASD motherboards uses the Line In 2 as the input for front panel | ||
5637 | * mic (mic 2) | ||
5638 | */ | ||
5639 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | ||
5640 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5641 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
5642 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
5643 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | ||
5644 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
5645 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | ||
5646 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | ||
5647 | |||
5648 | /* | ||
5649 | * Set up output mixers (0x0c - 0x0e) | ||
5650 | */ | ||
5651 | /* set vol=0 to output mixers */ | ||
5652 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5653 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5654 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5655 | |||
5656 | /* set up input amps for analog loopback */ | ||
5657 | /* Amp Indices: DAC = 0, mixer = 1 */ | ||
5658 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5659 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
5660 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5661 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
5662 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5663 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
5664 | |||
5665 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, | ||
5666 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
5667 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
5668 | |||
5669 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
5670 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
5671 | |||
5672 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5673 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5674 | |||
5675 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
5676 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
5677 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
5678 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
5679 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
5680 | |||
5681 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, | ||
5682 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, | ||
5683 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, | ||
5684 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, | ||
5685 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, | ||
5686 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, | ||
5687 | |||
5688 | |||
5689 | /* FIXME: use matrix-type input source selection */ | ||
5690 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | ||
5691 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ | ||
5692 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
5693 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, | ||
5694 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | ||
5695 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | ||
5696 | /* Input mixer2 */ | ||
5697 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
5698 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, | ||
5699 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | ||
5700 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | ||
5701 | /* Input mixer3 */ | ||
5702 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
5703 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, | ||
5704 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | ||
5705 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | ||
5706 | |||
5707 | { } | ||
5708 | }; | ||
5709 | |||
4871 | /* pcm configuration: identiacal with ALC880 */ | 5710 | /* pcm configuration: identiacal with ALC880 */ |
4872 | #define alc262_pcm_analog_playback alc880_pcm_analog_playback | 5711 | #define alc262_pcm_analog_playback alc880_pcm_analog_playback |
4873 | #define alc262_pcm_analog_capture alc880_pcm_analog_capture | 5712 | #define alc262_pcm_analog_capture alc880_pcm_analog_capture |
@@ -4928,7 +5767,16 @@ static void alc262_auto_init(struct hda_codec *codec) | |||
4928 | static struct hda_board_config alc262_cfg_tbl[] = { | 5767 | static struct hda_board_config alc262_cfg_tbl[] = { |
4929 | { .modelname = "basic", .config = ALC262_BASIC }, | 5768 | { .modelname = "basic", .config = ALC262_BASIC }, |
4930 | { .modelname = "fujitsu", .config = ALC262_FUJITSU }, | 5769 | { .modelname = "fujitsu", .config = ALC262_FUJITSU }, |
4931 | { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397, .config = ALC262_FUJITSU }, | 5770 | { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397, |
5771 | .config = ALC262_FUJITSU }, | ||
5772 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x208c, | ||
5773 | .config = ALC262_HP_BPC }, /* xw4400 */ | ||
5774 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, | ||
5775 | .config = ALC262_HP_BPC }, /* xw6400 */ | ||
5776 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, | ||
5777 | .config = ALC262_HP_BPC }, /* xw8400 */ | ||
5778 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x12fe, | ||
5779 | .config = ALC262_HP_BPC }, /* xw9400 */ | ||
4932 | { .modelname = "auto", .config = ALC262_AUTO }, | 5780 | { .modelname = "auto", .config = ALC262_AUTO }, |
4933 | {} | 5781 | {} |
4934 | }; | 5782 | }; |
@@ -4956,6 +5804,16 @@ static struct alc_config_preset alc262_presets[] = { | |||
4956 | .input_mux = &alc262_fujitsu_capture_source, | 5804 | .input_mux = &alc262_fujitsu_capture_source, |
4957 | .unsol_event = alc262_fujitsu_unsol_event, | 5805 | .unsol_event = alc262_fujitsu_unsol_event, |
4958 | }, | 5806 | }, |
5807 | [ALC262_HP_BPC] = { | ||
5808 | .mixers = { alc262_HP_BPC_mixer }, | ||
5809 | .init_verbs = { alc262_HP_BPC_init_verbs }, | ||
5810 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | ||
5811 | .dac_nids = alc262_dac_nids, | ||
5812 | .hp_nid = 0x03, | ||
5813 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | ||
5814 | .channel_mode = alc262_modes, | ||
5815 | .input_mux = &alc262_HP_capture_source, | ||
5816 | }, | ||
4959 | }; | 5817 | }; |
4960 | 5818 | ||
4961 | static int patch_alc262(struct hda_codec *codec) | 5819 | static int patch_alc262(struct hda_codec *codec) |
@@ -4981,8 +5839,10 @@ static int patch_alc262(struct hda_codec *codec) | |||
4981 | #endif | 5839 | #endif |
4982 | 5840 | ||
4983 | board_config = snd_hda_check_board_config(codec, alc262_cfg_tbl); | 5841 | board_config = snd_hda_check_board_config(codec, alc262_cfg_tbl); |
5842 | |||
4984 | if (board_config < 0 || board_config >= ALC262_MODEL_LAST) { | 5843 | if (board_config < 0 || board_config >= ALC262_MODEL_LAST) { |
4985 | printk(KERN_INFO "hda_codec: Unknown model for ALC262, trying auto-probe from BIOS...\n"); | 5844 | printk(KERN_INFO "hda_codec: Unknown model for ALC262, " |
5845 | "trying auto-probe from BIOS...\n"); | ||
4986 | board_config = ALC262_AUTO; | 5846 | board_config = ALC262_AUTO; |
4987 | } | 5847 | } |
4988 | 5848 | ||
@@ -4993,7 +5853,9 @@ static int patch_alc262(struct hda_codec *codec) | |||
4993 | alc_free(codec); | 5853 | alc_free(codec); |
4994 | return err; | 5854 | return err; |
4995 | } else if (! err) { | 5855 | } else if (! err) { |
4996 | printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n"); | 5856 | printk(KERN_INFO |
5857 | "hda_codec: Cannot set up configuration " | ||
5858 | "from BIOS. Using base mode...\n"); | ||
4997 | board_config = ALC262_BASIC; | 5859 | board_config = ALC262_BASIC; |
4998 | } | 5860 | } |
4999 | } | 5861 | } |
@@ -5034,7 +5896,6 @@ static int patch_alc262(struct hda_codec *codec) | |||
5034 | return 0; | 5896 | return 0; |
5035 | } | 5897 | } |
5036 | 5898 | ||
5037 | |||
5038 | /* | 5899 | /* |
5039 | * ALC861 channel source setting (2/6 channel selection for 3-stack) | 5900 | * ALC861 channel source setting (2/6 channel selection for 3-stack) |
5040 | */ | 5901 | */ |
@@ -5049,9 +5910,11 @@ static struct hda_verb alc861_threestack_ch2_init[] = { | |||
5049 | /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */ | 5910 | /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */ |
5050 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 5911 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, |
5051 | 5912 | ||
5052 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, | 5913 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, |
5053 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, //mic | 5914 | #if 0 |
5054 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, //line in | 5915 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ |
5916 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/ | ||
5917 | #endif | ||
5055 | { } /* end */ | 5918 | { } /* end */ |
5056 | }; | 5919 | }; |
5057 | /* | 5920 | /* |
@@ -5065,11 +5928,13 @@ static struct hda_verb alc861_threestack_ch6_init[] = { | |||
5065 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 5928 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, |
5066 | 5929 | ||
5067 | { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 }, | 5930 | { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 }, |
5068 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 }, | 5931 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 }, |
5069 | 5932 | ||
5070 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, | 5933 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, |
5071 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, //mic | 5934 | #if 0 |
5072 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, //line in | 5935 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ |
5936 | { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/ | ||
5937 | #endif | ||
5073 | { } /* end */ | 5938 | { } /* end */ |
5074 | }; | 5939 | }; |
5075 | 5940 | ||
@@ -5353,6 +6218,11 @@ static hda_nid_t alc861_dac_nids[4] = { | |||
5353 | 0x03, 0x06, 0x05, 0x04 | 6218 | 0x03, 0x06, 0x05, 0x04 |
5354 | }; | 6219 | }; |
5355 | 6220 | ||
6221 | static hda_nid_t alc660_dac_nids[3] = { | ||
6222 | /* front, clfe, surround */ | ||
6223 | 0x03, 0x05, 0x06 | ||
6224 | }; | ||
6225 | |||
5356 | static hda_nid_t alc861_adc_nids[1] = { | 6226 | static hda_nid_t alc861_adc_nids[1] = { |
5357 | /* ADC0-2 */ | 6227 | /* ADC0-2 */ |
5358 | 0x08, | 6228 | 0x08, |
@@ -5605,7 +6475,10 @@ static void alc861_auto_init(struct hda_codec *codec) | |||
5605 | */ | 6475 | */ |
5606 | static struct hda_board_config alc861_cfg_tbl[] = { | 6476 | static struct hda_board_config alc861_cfg_tbl[] = { |
5607 | { .modelname = "3stack", .config = ALC861_3ST }, | 6477 | { .modelname = "3stack", .config = ALC861_3ST }, |
5608 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, .config = ALC861_3ST }, | 6478 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, |
6479 | .config = ALC861_3ST }, | ||
6480 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x81e7, | ||
6481 | .config = ALC660_3ST }, | ||
5609 | { .modelname = "3stack-dig", .config = ALC861_3ST_DIG }, | 6482 | { .modelname = "3stack-dig", .config = ALC861_3ST_DIG }, |
5610 | { .modelname = "6stack-dig", .config = ALC861_6ST_DIG }, | 6483 | { .modelname = "6stack-dig", .config = ALC861_6ST_DIG }, |
5611 | { .modelname = "auto", .config = ALC861_AUTO }, | 6484 | { .modelname = "auto", .config = ALC861_AUTO }, |
@@ -5648,6 +6521,17 @@ static struct alc_config_preset alc861_presets[] = { | |||
5648 | .adc_nids = alc861_adc_nids, | 6521 | .adc_nids = alc861_adc_nids, |
5649 | .input_mux = &alc861_capture_source, | 6522 | .input_mux = &alc861_capture_source, |
5650 | }, | 6523 | }, |
6524 | [ALC660_3ST] = { | ||
6525 | .mixers = { alc861_3ST_mixer }, | ||
6526 | .init_verbs = { alc861_threestack_init_verbs }, | ||
6527 | .num_dacs = ARRAY_SIZE(alc660_dac_nids), | ||
6528 | .dac_nids = alc660_dac_nids, | ||
6529 | .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), | ||
6530 | .channel_mode = alc861_threestack_modes, | ||
6531 | .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), | ||
6532 | .adc_nids = alc861_adc_nids, | ||
6533 | .input_mux = &alc861_capture_source, | ||
6534 | }, | ||
5651 | }; | 6535 | }; |
5652 | 6536 | ||
5653 | 6537 | ||
@@ -5664,8 +6548,10 @@ static int patch_alc861(struct hda_codec *codec) | |||
5664 | codec->spec = spec; | 6548 | codec->spec = spec; |
5665 | 6549 | ||
5666 | board_config = snd_hda_check_board_config(codec, alc861_cfg_tbl); | 6550 | board_config = snd_hda_check_board_config(codec, alc861_cfg_tbl); |
6551 | |||
5667 | if (board_config < 0 || board_config >= ALC861_MODEL_LAST) { | 6552 | if (board_config < 0 || board_config >= ALC861_MODEL_LAST) { |
5668 | printk(KERN_INFO "hda_codec: Unknown model for ALC861, trying auto-probe from BIOS...\n"); | 6553 | printk(KERN_INFO "hda_codec: Unknown model for ALC861, " |
6554 | "trying auto-probe from BIOS...\n"); | ||
5669 | board_config = ALC861_AUTO; | 6555 | board_config = ALC861_AUTO; |
5670 | } | 6556 | } |
5671 | 6557 | ||
@@ -5676,7 +6562,9 @@ static int patch_alc861(struct hda_codec *codec) | |||
5676 | alc_free(codec); | 6562 | alc_free(codec); |
5677 | return err; | 6563 | return err; |
5678 | } else if (! err) { | 6564 | } else if (! err) { |
5679 | printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n"); | 6565 | printk(KERN_INFO |
6566 | "hda_codec: Cannot set up configuration " | ||
6567 | "from BIOS. Using base mode...\n"); | ||
5680 | board_config = ALC861_3ST_DIG; | 6568 | board_config = ALC861_3ST_DIG; |
5681 | } | 6569 | } |
5682 | } | 6570 | } |
@@ -5707,8 +6595,12 @@ struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
5707 | { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, | 6595 | { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, |
5708 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, | 6596 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, |
5709 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, | 6597 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, |
5710 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, | 6598 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 }, |
5711 | { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, | 6599 | { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, |
5712 | { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 }, | 6600 | { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 }, |
6601 | { .id = 0x10ec0861, .rev = 0x100300, .name = "ALC861", | ||
6602 | .patch = patch_alc861 }, | ||
6603 | { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", | ||
6604 | .patch = patch_alc861 }, | ||
5713 | {} /* terminator */ | 6605 | {} /* terminator */ |
5714 | }; | 6606 | }; |