aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-06-28 09:08:22 -0400
committerJaroslav Kysela <perex@suse.cz>2006-06-28 13:31:43 -0400
commit9c7f852e8b2cc37da5dc5e1ba416238166a37d0f (patch)
treeb441419aa9ae275ec016bfbf6d5136452e2be5ba /sound
parent8c42d5bafa08baad5d647dd0b9050086ffe36e15 (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')
-rw-r--r--sound/pci/hda/hda_codec.c4
-rw-r--r--sound/pci/hda/patch_realtek.c1084
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 {
78enum { 78enum {
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 */
86enum { 87enum {
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 */
105enum {
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 */
165struct alc_config_preset { 179struct 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 */
187static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 203static 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
197static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 214static 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
207static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 225static 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 */
221static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 241static 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
229static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 250static 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
237static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 260static 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
293static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 318static 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
308static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 334static 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
325static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 354static 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
381static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 417static 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}
389static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 426static 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}
400static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 439static 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
435static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 477static 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}
443static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 486static 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}
454static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 499static 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 */
484static void setup_preset(struct alc_spec *spec, const struct alc_config_preset *preset) 533static 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
524static hda_nid_t alc880_dac_nids[4] = { 576static 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
817static hda_nid_t alc880_z71v_dac_nids[1] = { 872static 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 */
1160static struct hda_verb alc880_pin_6stack_init_verbs[] = { 1216static 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
1594static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, 1650static 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
1825static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 1882static 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
1840static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1898static 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
1866static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1925static 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
1892static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 1954static 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
1906static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1969static 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
1917static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1981static 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[] = {
4320static struct hda_board_config alc882_cfg_tbl[] = { 4391static 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
4446static int patch_alc882(struct hda_codec *codec) 4516static 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
4598static hda_nid_t alc883_dac_nids[4] = {
4599 /* front, rear, clfe, rear_surr */
4600 0x02, 0x04, 0x03, 0x05
4601};
4602
4603static 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
4610static 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
4622static 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 */
4650static struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
4651 { 2, NULL }
4652};
4653
4654/*
4655 * 2ch mode
4656 */
4657static 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 */
4668static 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
4678static 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 */
4686static 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 */
4697static 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
4705static 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
4714static 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
4752static 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
4782static 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
4818static 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
4829static 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 */
4909static 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 */
4970static 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 */
5000static 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
5016static 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 */
5086static 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
5107static 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
5119static 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
5133static 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... */
5154static 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 */
5170static 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
5177static 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
5264static 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
5389static 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 */
4649static void alc262_fujitsu_automute(struct hda_codec *codec, int force) 5401static 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
5623static 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)
4928static struct hda_board_config alc262_cfg_tbl[] = { 5767static 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
4961static int patch_alc262(struct hda_codec *codec) 5819static 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
6221static hda_nid_t alc660_dac_nids[3] = {
6222 /* front, clfe, surround */
6223 0x03, 0x05, 0x06
6224};
6225
5356static hda_nid_t alc861_adc_nids[1] = { 6226static 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 */
5606static struct hda_board_config alc861_cfg_tbl[] = { 6476static 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};