aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_cmedia.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_cmedia.c')
-rw-r--r--sound/pci/hda/patch_cmedia.c236
1 files changed, 79 insertions, 157 deletions
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 087230ca20a5..2d6e3e3d0a38 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -51,6 +51,7 @@ struct cmi_spec {
51 /* playback */ 51 /* playback */
52 struct hda_multi_out multiout; 52 struct hda_multi_out multiout;
53 hda_nid_t dac_nids[4]; /* NID for each DAC */ 53 hda_nid_t dac_nids[4]; /* NID for each DAC */
54 int num_dacs;
54 55
55 /* capture */ 56 /* capture */
56 hda_nid_t *adc_nids; 57 hda_nid_t *adc_nids;
@@ -77,6 +78,19 @@ struct cmi_spec {
77 struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */ 78 struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */
78}; 79};
79 80
81/* amp values */
82#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
83#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
84#define AMP_OUT_MUTE 0xb080
85#define AMP_OUT_UNMUTE 0xb000
86#define AMP_OUT_ZERO 0xb000
87/* pinctl values */
88#define PIN_IN 0x20
89#define PIN_VREF80 0x24
90#define PIN_VREF50 0x21
91#define PIN_OUT 0x40
92#define PIN_HP 0xc0
93
80/* 94/*
81 * input MUX 95 * input MUX
82 */ 96 */
@@ -114,9 +128,9 @@ static int cmi_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
114/* 3-stack / 2 channel */ 128/* 3-stack / 2 channel */
115static struct hda_verb cmi9880_ch2_init[] = { 129static struct hda_verb cmi9880_ch2_init[] = {
116 /* set line-in PIN for input */ 130 /* set line-in PIN for input */
117 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 131 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
118 /* set mic PIN for input, also enable vref */ 132 /* set mic PIN for input, also enable vref */
119 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 133 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
120 /* route front PCM (DAC1) to HP */ 134 /* route front PCM (DAC1) to HP */
121 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 135 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
122 {} 136 {}
@@ -125,9 +139,9 @@ static struct hda_verb cmi9880_ch2_init[] = {
125/* 3-stack / 6 channel */ 139/* 3-stack / 6 channel */
126static struct hda_verb cmi9880_ch6_init[] = { 140static struct hda_verb cmi9880_ch6_init[] = {
127 /* set line-in PIN for output */ 141 /* set line-in PIN for output */
128 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 142 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
129 /* set mic PIN for output */ 143 /* set mic PIN for output */
130 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 144 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
131 /* route front PCM (DAC1) to HP */ 145 /* route front PCM (DAC1) to HP */
132 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 146 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
133 {} 147 {}
@@ -136,9 +150,9 @@ static struct hda_verb cmi9880_ch6_init[] = {
136/* 3-stack+front / 8 channel */ 150/* 3-stack+front / 8 channel */
137static struct hda_verb cmi9880_ch8_init[] = { 151static struct hda_verb cmi9880_ch8_init[] = {
138 /* set line-in PIN for output */ 152 /* set line-in PIN for output */
139 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 153 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
140 /* set mic PIN for output */ 154 /* set mic PIN for output */
141 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, 155 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
142 /* route rear-surround PCM (DAC4) to HP */ 156 /* route rear-surround PCM (DAC4) to HP */
143 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 }, 157 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
144 {} 158 {}
@@ -281,27 +295,27 @@ static hda_nid_t cmi9880_adc_nids[2] = {
281 */ 295 */
282static struct hda_verb cmi9880_basic_init[] = { 296static struct hda_verb cmi9880_basic_init[] = {
283 /* port-D for line out (rear panel) */ 297 /* port-D for line out (rear panel) */
284 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 298 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
285 /* port-E for HP out (front panel) */ 299 /* port-E for HP out (front panel) */
286 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 300 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
287 /* route front PCM to HP */ 301 /* route front PCM to HP */
288 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 302 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
289 /* port-A for surround (rear panel) */ 303 /* port-A for surround (rear panel) */
290 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 304 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
291 /* port-G for CLFE (rear panel) */ 305 /* port-G for CLFE (rear panel) */
292 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 306 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
293 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, 307 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
294 /* port-H for side (rear panel) */ 308 /* port-H for side (rear panel) */
295 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 309 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
296 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, 310 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
297 /* port-C for line-in (rear panel) */ 311 /* port-C for line-in (rear panel) */
298 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 312 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
299 /* port-B for mic-in (rear panel) with vref */ 313 /* port-B for mic-in (rear panel) with vref */
300 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 314 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
301 /* port-F for mic-in (front panel) with vref */ 315 /* port-F for mic-in (front panel) with vref */
302 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 316 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
303 /* CD-in */ 317 /* CD-in */
304 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 318 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
305 /* route front mic to ADC1/2 */ 319 /* route front mic to ADC1/2 */
306 { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, 320 { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
307 { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, 321 { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
@@ -310,27 +324,27 @@ static struct hda_verb cmi9880_basic_init[] = {
310 324
311static struct hda_verb cmi9880_allout_init[] = { 325static struct hda_verb cmi9880_allout_init[] = {
312 /* port-D for line out (rear panel) */ 326 /* port-D for line out (rear panel) */
313 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 327 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
314 /* port-E for HP out (front panel) */ 328 /* port-E for HP out (front panel) */
315 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 329 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
316 /* route front PCM to HP */ 330 /* route front PCM to HP */
317 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, 331 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
318 /* port-A for side (rear panel) */ 332 /* port-A for side (rear panel) */
319 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 333 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
320 /* port-G for CLFE (rear panel) */ 334 /* port-G for CLFE (rear panel) */
321 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 335 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
322 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, 336 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
323 /* port-H for side (rear panel) */ 337 /* port-H for side (rear panel) */
324 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 338 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
325 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, 339 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
326 /* port-C for surround (rear panel) */ 340 /* port-C for surround (rear panel) */
327 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 341 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
328 /* port-B for mic-in (rear panel) with vref */ 342 /* port-B for mic-in (rear panel) with vref */
329 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 343 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
330 /* port-F for mic-in (front panel) with vref */ 344 /* port-F for mic-in (front panel) with vref */
331 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 345 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
332 /* CD-in */ 346 /* CD-in */
333 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, 347 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
334 /* route front mic to ADC1/2 */ 348 /* route front mic to ADC1/2 */
335 { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, 349 { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
336 { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, 350 { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
@@ -365,101 +379,9 @@ static int cmi9880_build_controls(struct hda_codec *codec)
365 return 0; 379 return 0;
366} 380}
367 381
368#define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)
369#define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT)
370#define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE)
371
372/* get all pin default configuration in def_conf */
373static int cmi9880_get_pin_def_config(struct hda_codec *codec)
374{
375 struct cmi_spec *spec = codec->spec;
376 hda_nid_t nid, nid_start;
377 int i = 0, nodes;
378
379 nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start);
380 for (nid = nid_start; nid < nodes + nid_start; nid++) {
381 unsigned int wid_caps = snd_hda_param_read(codec, nid,
382 AC_PAR_AUDIO_WIDGET_CAP);
383 unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
384 /* read all default configuration for pin complex */
385 if (wid_type == AC_WID_PIN) {
386 spec->pin_nid[i] = nid;
387 spec->def_conf[i] =
388 snd_hda_codec_read(codec, nid, 0,
389 AC_VERB_GET_CONFIG_DEFAULT, 0);
390 i++;
391 }
392 }
393 spec->pin_def_confs = i;
394 return 0;
395}
396
397/* get a pin default configuration of nid in def_conf */
398static unsigned int cmi9880_get_def_config(struct hda_codec *codec, hda_nid_t nid)
399{
400 struct cmi_spec *spec = codec->spec;
401 int i = 0;
402
403 while (spec->pin_nid[i] != nid && i < spec->pin_def_confs)
404 i++;
405 if (i == spec->pin_def_confs)
406 return (unsigned int) -1;
407 else
408 return spec->def_conf[i];
409}
410
411/* decide what pins to use for multichannel playback */
412static int cmi9880_get_multich_pins(struct hda_codec *codec)
413{
414 struct cmi_spec *spec = codec->spec;
415 int i, j, pins, seq[4];
416 int max_channel = 0;
417 unsigned int def_conf, sequence;
418 hda_nid_t nid;
419
420 memset(spec->multich_pin, 0, sizeof(spec->multich_pin));
421 for (pins = 0, i = 0; i < spec->pin_def_confs && pins < 4; i++) {
422 def_conf = spec->def_conf[i];
423 /* skip pin not connected */
424 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
425 continue;
426 /* get the sequence if association == 1 */
427 /* the other pins have association = 0, incorrect in spec 1.0 */
428 if (get_defcfg_association(def_conf) == 1) {
429 sequence = get_defcfg_sequence(def_conf);
430 seq[pins] = sequence;
431 spec->multich_pin[pins] = spec->pin_nid[i];
432 pins++; // ready for next slot
433 max_channel += 2;
434 }
435 }
436 /* sort by sequence, data collected here will be for Windows */
437 for (i = 0; i < pins; i++) {
438 for (j = i + 1; j < pins; j++) {
439 if (seq[j] < seq[i]) {
440 sequence = seq[j];
441 nid = spec->multich_pin[j];
442 seq[j] = seq[i];
443 spec->multich_pin[j] = spec->multich_pin[i];
444 seq[i] = sequence;
445 spec->multich_pin[i] = nid;
446 }
447 }
448 }
449 /* the pin assignment is for front, C/LFE, surround and back */
450 if (max_channel >= 6) {
451 hda_nid_t temp;
452 /* exchange pin of C/LFE and surround */
453 temp = spec->multich_pin[1];
454 spec->multich_pin[1] = spec->multich_pin[2];
455 spec->multich_pin[2] = temp;
456 }
457 return max_channel;
458}
459
460/* fill in the multi_dac_nids table, which will decide 382/* fill in the multi_dac_nids table, which will decide
461 which audio widget to use for each channel */ 383 which audio widget to use for each channel */
462static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec) 384static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
463{ 385{
464 struct cmi_spec *spec = codec->spec; 386 struct cmi_spec *spec = codec->spec;
465 hda_nid_t nid; 387 hda_nid_t nid;
@@ -470,32 +392,34 @@ static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec)
470 memset(spec->dac_nids, 0, sizeof(spec->dac_nids)); 392 memset(spec->dac_nids, 0, sizeof(spec->dac_nids));
471 memset(assigned, 0, sizeof(assigned)); 393 memset(assigned, 0, sizeof(assigned));
472 /* check the pins we found */ 394 /* check the pins we found */
473 for (i = 0; i < spec->multiout.max_channels / 2; i++) { 395 for (i = 0; i < cfg->line_outs; i++) {
474 nid = spec->multich_pin[i]; 396 nid = cfg->line_out_pins[i];
475 /* nid 0x0b~0x0e is hardwired to audio widget 0x3~0x6 */ 397 /* nid 0x0b~0x0e is hardwired to audio widget 0x3~0x6 */
476 if (nid <= 0x0e && nid >= 0x0b) { 398 if (nid >= 0x0b && nid <= 0x0e) {
477 spec->dac_nids[i] = nid - 0x08; 399 spec->dac_nids[i] = (nid - 0x0b) + 0x03;
478 assigned[nid - 0x0b] = 1; 400 assigned[nid - 0x0b] = 1;
479 } 401 }
480 } 402 }
481 /* left pin can be connect to any audio widget */ 403 /* left pin can be connect to any audio widget */
482 for (i = 0; i < spec->multiout.max_channels / 2; i++) { 404 for (i = 0; i < cfg->line_outs; i++) {
483 if (!assigned[i]) { 405 nid = cfg->line_out_pins[i];
484 /* search for an empty channel */ 406 if (nid <= 0x0e)
485 /* I should also check the pin type */ 407 continue;
486 for (j = 0; j < ARRAY_SIZE(spec->dac_nids); j++) 408 /* search for an empty channel */
487 if (! spec->dac_nids[j]) { 409 for (j = 0; j < cfg->line_outs; j++) {
488 spec->dac_nids[j] = i + 3; 410 if (! assigned[j]) {
489 assigned[i] = 1; 411 spec->dac_nids[i] = i + 0x03;
490 break; 412 assigned[j] = 1;
491 } 413 break;
414 }
492 } 415 }
493 } 416 }
417 spec->num_dacs = cfg->line_outs;
494 return 0; 418 return 0;
495} 419}
496 420
497/* create multi_init table, which is used for multichannel initialization */ 421/* create multi_init table, which is used for multichannel initialization */
498static int cmi9880_fill_multi_init(struct hda_codec *codec) 422static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
499{ 423{
500 struct cmi_spec *spec = codec->spec; 424 struct cmi_spec *spec = codec->spec;
501 hda_nid_t nid; 425 hda_nid_t nid;
@@ -503,29 +427,26 @@ static int cmi9880_fill_multi_init(struct hda_codec *codec)
503 427
504 /* clear the table, only one c-media dac assumed here */ 428 /* clear the table, only one c-media dac assumed here */
505 memset(spec->multi_init, 0, sizeof(spec->multi_init)); 429 memset(spec->multi_init, 0, sizeof(spec->multi_init));
506 for (j = 0, i = 0; i < spec->multiout.max_channels / 2; i++) { 430 for (j = 0, i = 0; i < cfg->line_outs; i++) {
507 hda_nid_t conn[4]; 431 hda_nid_t conn[4];
508 nid = spec->multich_pin[i]; 432 nid = cfg->line_out_pins[i];
509 /* set as output */ 433 /* set as output */
510 spec->multi_init[j].nid = nid; 434 spec->multi_init[j].nid = nid;
511 spec->multi_init[j].verb = AC_VERB_SET_PIN_WIDGET_CONTROL; 435 spec->multi_init[j].verb = AC_VERB_SET_PIN_WIDGET_CONTROL;
512 spec->multi_init[j].param = 0xc0; 436 spec->multi_init[j].param = PIN_OUT;
513 j++; 437 j++;
514 /* nid 0x0f,0x10,0x1f,0x20 are needed to set connection */ 438 if (nid > 0x0e) {
515 switch (nid) {
516 case 0x0f:
517 case 0x10:
518 case 0x1f:
519 case 0x20:
520 /* set connection */ 439 /* set connection */
521 spec->multi_init[j].nid = nid; 440 spec->multi_init[j].nid = nid;
522 spec->multi_init[j].verb = AC_VERB_SET_CONNECT_SEL; 441 spec->multi_init[j].verb = AC_VERB_SET_CONNECT_SEL;
442 spec->multi_init[j].param = 0;
523 /* find the index in connect list */ 443 /* find the index in connect list */
524 len = snd_hda_get_connections(codec, nid, conn, 4); 444 len = snd_hda_get_connections(codec, nid, conn, 4);
525 for (k = 0; k < len; k++) 445 for (k = 0; k < len; k++)
526 if (conn[k] == spec->dac_nids[i]) 446 if (conn[k] == spec->dac_nids[i]) {
447 spec->multi_init[j].param = j;
527 break; 448 break;
528 spec->multi_init[j].param = k < len ? k : 0; 449 }
529 j++; 450 j++;
530 break; 451 break;
531 } 452 }
@@ -759,6 +680,7 @@ static int patch_cmi9880(struct hda_codec *codec)
759 680
760 /* copy default DAC NIDs */ 681 /* copy default DAC NIDs */
761 memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids)); 682 memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids));
683 spec->num_dacs = 4;
762 684
763 switch (spec->board_config) { 685 switch (spec->board_config) {
764 case CMI_MINIMAL: 686 case CMI_MINIMAL:
@@ -795,18 +717,16 @@ static int patch_cmi9880(struct hda_codec *codec)
795 { 717 {
796 unsigned int port_e, port_f, port_g, port_h; 718 unsigned int port_e, port_f, port_g, port_h;
797 unsigned int port_spdifi, port_spdifo; 719 unsigned int port_spdifi, port_spdifo;
798 int max_channels; 720 struct auto_pin_cfg cfg;
721
799 /* collect pin default configuration */ 722 /* collect pin default configuration */
800 cmi9880_get_pin_def_config(codec); 723 port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
801 port_e = cmi9880_get_def_config(codec, 0x0f); 724 port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
802 port_f = cmi9880_get_def_config(codec, 0x10);
803 port_g = cmi9880_get_def_config(codec, 0x1f);
804 port_h = cmi9880_get_def_config(codec, 0x20);
805 port_spdifi = cmi9880_get_def_config(codec, 0x13);
806 port_spdifo = cmi9880_get_def_config(codec, 0x12);
807 spec->front_panel = 1; 725 spec->front_panel = 1;
808 if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE || 726 if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE ||
809 get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) { 727 get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) {
728 port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
729 port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
810 spec->surr_switch = 1; 730 spec->surr_switch = 1;
811 /* no front panel */ 731 /* no front panel */
812 if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE || 732 if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE ||
@@ -824,24 +744,26 @@ static int patch_cmi9880(struct hda_codec *codec)
824 spec->multiout.max_channels = cmi9880_channel_modes[0].channels; 744 spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
825 } else { 745 } else {
826 spec->input_mux = &cmi9880_basic_mux; 746 spec->input_mux = &cmi9880_basic_mux;
747 port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
748 port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
827 if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE) 749 if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE)
828 spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; 750 spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
829 if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE) 751 if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE)
830 spec->dig_in_nid = CMI_DIG_IN_NID; 752 spec->dig_in_nid = CMI_DIG_IN_NID;
831 spec->multiout.max_channels = 8; 753 spec->multiout.max_channels = 8;
832 } 754 }
833 max_channels = cmi9880_get_multich_pins(codec); 755 snd_hda_parse_pin_def_config(codec, &cfg);
834 if (max_channels > 0) { 756 if (cfg.line_outs) {
835 spec->multiout.max_channels = max_channels; 757 spec->multiout.max_channels = cfg.line_outs * 2;
836 cmi9880_fill_multi_dac_nids(codec); 758 cmi9880_fill_multi_dac_nids(codec, &cfg);
837 cmi9880_fill_multi_init(codec); 759 cmi9880_fill_multi_init(codec, &cfg);
838 } else 760 } else
839 snd_printd("patch_cmedia: cannot detect association in defcfg\n"); 761 snd_printd("patch_cmedia: cannot detect association in defcfg\n");
840 break; 762 break;
841 } 763 }
842 } 764 }
843 765
844 spec->multiout.num_dacs = 4; 766 spec->multiout.num_dacs = spec->num_dacs;
845 spec->multiout.dac_nids = spec->dac_nids; 767 spec->multiout.dac_nids = spec->dac_nids;
846 768
847 spec->adc_nids = cmi9880_adc_nids; 769 spec->adc_nids = cmi9880_adc_nids;