diff options
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 310 |
1 files changed, 118 insertions, 192 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 46e93c6b9a42..a5a4b2bddf20 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -136,6 +136,18 @@ static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | |||
136 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 136 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
137 | } | 137 | } |
138 | 138 | ||
139 | static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
140 | struct hda_codec *codec, | ||
141 | unsigned int stream_tag, | ||
142 | unsigned int format, | ||
143 | struct snd_pcm_substream *substream) | ||
144 | { | ||
145 | struct conexant_spec *spec = codec->spec; | ||
146 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
147 | stream_tag, | ||
148 | format, substream); | ||
149 | } | ||
150 | |||
139 | /* | 151 | /* |
140 | * Analog capture | 152 | * Analog capture |
141 | */ | 153 | */ |
@@ -194,7 +206,8 @@ static struct hda_pcm_stream conexant_pcm_digital_playback = { | |||
194 | .nid = 0, /* fill later */ | 206 | .nid = 0, /* fill later */ |
195 | .ops = { | 207 | .ops = { |
196 | .open = conexant_dig_playback_pcm_open, | 208 | .open = conexant_dig_playback_pcm_open, |
197 | .close = conexant_dig_playback_pcm_close | 209 | .close = conexant_dig_playback_pcm_close, |
210 | .prepare = conexant_dig_playback_pcm_prepare | ||
198 | }, | 211 | }, |
199 | }; | 212 | }; |
200 | 213 | ||
@@ -452,115 +465,6 @@ static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol, | |||
452 | .put = conexant_ch_mode_put, \ | 465 | .put = conexant_ch_mode_put, \ |
453 | .private_value = nid | (dir<<16) } | 466 | .private_value = nid | (dir<<16) } |
454 | 467 | ||
455 | static int cxt_gpio_data_info(struct snd_kcontrol *kcontrol, | ||
456 | struct snd_ctl_elem_info *uinfo) | ||
457 | { | ||
458 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
459 | uinfo->count = 1; | ||
460 | uinfo->value.integer.min = 0; | ||
461 | uinfo->value.integer.max = 1; | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static int cxt_gpio_data_get(struct snd_kcontrol *kcontrol, | ||
466 | struct snd_ctl_elem_value *ucontrol) | ||
467 | { | ||
468 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
469 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
470 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
471 | long *valp = ucontrol->value.integer.value; | ||
472 | unsigned int val = snd_hda_codec_read(codec, nid, 0, | ||
473 | AC_VERB_GET_GPIO_DATA, 0x00); | ||
474 | |||
475 | *valp = (val & mask) != 0; | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static int cxt_gpio_data_put(struct snd_kcontrol *kcontrol, | ||
480 | struct snd_ctl_elem_value *ucontrol) | ||
481 | { | ||
482 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
483 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
484 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
485 | long val = *ucontrol->value.integer.value; | ||
486 | unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0, | ||
487 | AC_VERB_GET_GPIO_DATA, | ||
488 | 0x00); | ||
489 | unsigned int old_data = gpio_data; | ||
490 | |||
491 | /* Set/unset the masked GPIO bit(s) as needed */ | ||
492 | if (val == 0) | ||
493 | gpio_data &= ~mask; | ||
494 | else | ||
495 | gpio_data |= mask; | ||
496 | if (gpio_data == old_data && !codec->in_resume) | ||
497 | return 0; | ||
498 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data); | ||
499 | return 1; | ||
500 | } | ||
501 | |||
502 | #define CXT_GPIO_DATA_SWITCH(xname, nid, mask) \ | ||
503 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
504 | .info = cxt_gpio_data_info, \ | ||
505 | .get = cxt_gpio_data_get, \ | ||
506 | .put = cxt_gpio_data_put, \ | ||
507 | .private_value = nid | (mask<<16) } | ||
508 | #if 0 | ||
509 | static int cxt_spdif_ctrl_info(struct snd_kcontrol *kcontrol, | ||
510 | struct snd_ctl_elem_info *uinfo) | ||
511 | { | ||
512 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
513 | uinfo->count = 1; | ||
514 | uinfo->value.integer.min = 0; | ||
515 | uinfo->value.integer.max = 1; | ||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | static int cxt_spdif_ctrl_get(struct snd_kcontrol *kcontrol, | ||
520 | struct snd_ctl_elem_value *ucontrol) | ||
521 | { | ||
522 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
523 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
524 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
525 | long *valp = ucontrol->value.integer.value; | ||
526 | unsigned int val = snd_hda_codec_read(codec, nid, 0, | ||
527 | AC_VERB_GET_DIGI_CONVERT, 0x00); | ||
528 | |||
529 | *valp = (val & mask) != 0; | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | static int cxt_spdif_ctrl_put(struct snd_kcontrol *kcontrol, | ||
534 | struct snd_ctl_elem_value *ucontrol) | ||
535 | { | ||
536 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
537 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
538 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
539 | long val = *ucontrol->value.integer.value; | ||
540 | unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, | ||
541 | AC_VERB_GET_DIGI_CONVERT, | ||
542 | 0x00); | ||
543 | unsigned int old_data = ctrl_data; | ||
544 | |||
545 | /* Set/unset the masked control bit(s) as needed */ | ||
546 | if (val == 0) | ||
547 | ctrl_data &= ~mask; | ||
548 | else | ||
549 | ctrl_data |= mask; | ||
550 | if (ctrl_data == old_data && !codec->in_resume) | ||
551 | return 0; | ||
552 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | ||
553 | ctrl_data); | ||
554 | return 1; | ||
555 | } | ||
556 | |||
557 | #define CXT_SPDIF_CTRL_SWITCH(xname, nid, mask) \ | ||
558 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
559 | .info = cxt_spdif_ctrl_info, \ | ||
560 | .get = cxt_spdif_ctrl_get, \ | ||
561 | .put = cxt_spdif_ctrl_put, \ | ||
562 | .private_value = nid | (mask<<16) } | ||
563 | #endif | ||
564 | #endif /* CONFIG_SND_DEBUG */ | 468 | #endif /* CONFIG_SND_DEBUG */ |
565 | 469 | ||
566 | /* Conexant 5045 specific */ | 470 | /* Conexant 5045 specific */ |
@@ -599,6 +503,7 @@ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
599 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80; | 503 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80; |
600 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); | 504 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); |
601 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); | 505 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); |
506 | |||
602 | bits = spec->cur_eapd ? 0 : 0x80; | 507 | bits = spec->cur_eapd ? 0 : 0x80; |
603 | snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits); | 508 | snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits); |
604 | snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits); | 509 | snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits); |
@@ -624,6 +529,29 @@ static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol, | |||
624 | return change; | 529 | return change; |
625 | } | 530 | } |
626 | 531 | ||
532 | /* toggle input of built-in and mic jack appropriately */ | ||
533 | static void cxt5045_hp_automic(struct hda_codec *codec) | ||
534 | { | ||
535 | static struct hda_verb mic_jack_on[] = { | ||
536 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
537 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
538 | {} | ||
539 | }; | ||
540 | static struct hda_verb mic_jack_off[] = { | ||
541 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
542 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
543 | {} | ||
544 | }; | ||
545 | unsigned int present; | ||
546 | |||
547 | present = snd_hda_codec_read(codec, 0x12, 0, | ||
548 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
549 | if (present) | ||
550 | snd_hda_sequence_write(codec, mic_jack_on); | ||
551 | else | ||
552 | snd_hda_sequence_write(codec, mic_jack_off); | ||
553 | } | ||
554 | |||
627 | 555 | ||
628 | /* mute internal speaker if HP is plugged */ | 556 | /* mute internal speaker if HP is plugged */ |
629 | static void cxt5045_hp_automute(struct hda_codec *codec) | 557 | static void cxt5045_hp_automute(struct hda_codec *codec) |
@@ -634,7 +562,7 @@ static void cxt5045_hp_automute(struct hda_codec *codec) | |||
634 | spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, | 562 | spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, |
635 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 563 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
636 | 564 | ||
637 | bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; | 565 | bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; |
638 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); | 566 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); |
639 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); | 567 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); |
640 | } | 568 | } |
@@ -648,6 +576,10 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec, | |||
648 | case CONEXANT_HP_EVENT: | 576 | case CONEXANT_HP_EVENT: |
649 | cxt5045_hp_automute(codec); | 577 | cxt5045_hp_automute(codec); |
650 | break; | 578 | break; |
579 | case CONEXANT_MIC_EVENT: | ||
580 | cxt5045_hp_automic(codec); | ||
581 | break; | ||
582 | |||
651 | } | 583 | } |
652 | } | 584 | } |
653 | 585 | ||
@@ -659,12 +591,10 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { | |||
659 | .get = conexant_mux_enum_get, | 591 | .get = conexant_mux_enum_get, |
660 | .put = conexant_mux_enum_put | 592 | .put = conexant_mux_enum_put |
661 | }, | 593 | }, |
662 | HDA_CODEC_VOLUME("Int Mic Volume", 0x17, 0x01, HDA_INPUT), | 594 | HDA_CODEC_VOLUME("Int Mic Volume", 0x1a, 0x01, HDA_INPUT), |
663 | HDA_CODEC_MUTE("Int Mic Switch", 0x17, 0x01, HDA_INPUT), | 595 | HDA_CODEC_MUTE("Int Mic Switch", 0x1a, 0x01, HDA_INPUT), |
664 | HDA_CODEC_VOLUME("Ext Mic Volume", 0x17, 0x02, HDA_INPUT), | 596 | HDA_CODEC_VOLUME("Ext Mic Volume", 0x1a, 0x02, HDA_INPUT), |
665 | HDA_CODEC_MUTE("Ext Mic Switch", 0x17, 0x02, HDA_INPUT), | 597 | HDA_CODEC_MUTE("Ext Mic Switch", 0x1a, 0x02, HDA_INPUT), |
666 | HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT), | ||
667 | HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), | ||
668 | { | 598 | { |
669 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 599 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
670 | .name = "Master Playback Volume", | 600 | .name = "Master Playback Volume", |
@@ -688,7 +618,7 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { | |||
688 | static struct hda_verb cxt5045_init_verbs[] = { | 618 | static struct hda_verb cxt5045_init_verbs[] = { |
689 | /* Line in, Mic */ | 619 | /* Line in, Mic */ |
690 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | 620 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
691 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | 621 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, |
692 | /* HP, Amp */ | 622 | /* HP, Amp */ |
693 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | 623 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
694 | {0x17, AC_VERB_SET_CONNECT_SEL,0x01}, | 624 | {0x17, AC_VERB_SET_CONNECT_SEL,0x01}, |
@@ -701,18 +631,29 @@ static struct hda_verb cxt5045_init_verbs[] = { | |||
701 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, | 631 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, |
702 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x04}, | 632 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x04}, |
703 | /* Record selector: Int mic */ | 633 | /* Record selector: Int mic */ |
704 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x0}, | 634 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, |
705 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, | 635 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, |
706 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | 636 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, |
707 | /* SPDIF route: PCM */ | 637 | /* SPDIF route: PCM */ |
708 | { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 }, | 638 | { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 }, |
709 | /* pin sensing on HP and Mic jacks */ | ||
710 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
711 | /* EAPD */ | 639 | /* EAPD */ |
712 | {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ | 640 | {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ |
713 | { } /* end */ | 641 | { } /* end */ |
714 | }; | 642 | }; |
715 | 643 | ||
644 | |||
645 | static struct hda_verb cxt5045_hp_sense_init_verbs[] = { | ||
646 | /* pin sensing on HP jack */ | ||
647 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
648 | { } /* end */ | ||
649 | }; | ||
650 | |||
651 | static struct hda_verb cxt5045_mic_sense_init_verbs[] = { | ||
652 | /* pin sensing on HP jack */ | ||
653 | {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
654 | { } /* end */ | ||
655 | }; | ||
656 | |||
716 | #ifdef CONFIG_SND_DEBUG | 657 | #ifdef CONFIG_SND_DEBUG |
717 | /* Test configuration for debugging, modelled after the ALC260 test | 658 | /* Test configuration for debugging, modelled after the ALC260 test |
718 | * configuration. | 659 | * configuration. |
@@ -733,6 +674,10 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = { | |||
733 | /* Output controls */ | 674 | /* Output controls */ |
734 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), | 675 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), |
735 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), | 676 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), |
677 | HDA_CODEC_VOLUME("Node 11 Playback Volume", 0x11, 0x0, HDA_OUTPUT), | ||
678 | HDA_CODEC_MUTE("Node 11 Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
679 | HDA_CODEC_VOLUME("Node 12 Playback Volume", 0x12, 0x0, HDA_OUTPUT), | ||
680 | HDA_CODEC_MUTE("Node 12 Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
736 | 681 | ||
737 | /* Modes for retasking pin widgets */ | 682 | /* Modes for retasking pin widgets */ |
738 | CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), | 683 | CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), |
@@ -742,25 +687,17 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = { | |||
742 | CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0), | 687 | CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0), |
743 | 688 | ||
744 | /* Loopback mixer controls */ | 689 | /* Loopback mixer controls */ |
745 | HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x17, 0x01, HDA_INPUT), | 690 | |
746 | HDA_CODEC_MUTE("MIC1 Playback Switch", 0x17, 0x01, HDA_INPUT), | 691 | HDA_CODEC_VOLUME("Mixer-1 Volume", 0x17, 0x0, HDA_INPUT), |
747 | HDA_CODEC_VOLUME("LINE loopback Playback Volume", 0x17, 0x02, HDA_INPUT), | 692 | HDA_CODEC_MUTE("Mixer-1 Switch", 0x17, 0x0, HDA_INPUT), |
748 | HDA_CODEC_MUTE("LINE loopback Playback Switch", 0x17, 0x02, HDA_INPUT), | 693 | HDA_CODEC_VOLUME("Mixer-2 Volume", 0x17, 0x1, HDA_INPUT), |
749 | HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x17, 0x03, HDA_INPUT), | 694 | HDA_CODEC_MUTE("Mixer-2 Switch", 0x17, 0x1, HDA_INPUT), |
750 | HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x17, 0x03, HDA_INPUT), | 695 | HDA_CODEC_VOLUME("Mixer-3 Volume", 0x17, 0x2, HDA_INPUT), |
751 | HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x04, HDA_INPUT), | 696 | HDA_CODEC_MUTE("Mixer-3 Switch", 0x17, 0x2, HDA_INPUT), |
752 | HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x04, HDA_INPUT), | 697 | HDA_CODEC_VOLUME("Mixer-4 Volume", 0x17, 0x3, HDA_INPUT), |
753 | 698 | HDA_CODEC_MUTE("Mixer-4 Switch", 0x17, 0x3, HDA_INPUT), | |
754 | HDA_CODEC_VOLUME("Capture-1 Volume", 0x17, 0x0, HDA_INPUT), | 699 | HDA_CODEC_VOLUME("Mixer-5 Volume", 0x17, 0x4, HDA_INPUT), |
755 | HDA_CODEC_MUTE("Capture-1 Switch", 0x17, 0x0, HDA_INPUT), | 700 | HDA_CODEC_MUTE("Mixer-5 Switch", 0x17, 0x4, HDA_INPUT), |
756 | HDA_CODEC_VOLUME("Capture-2 Volume", 0x17, 0x1, HDA_INPUT), | ||
757 | HDA_CODEC_MUTE("Capture-2 Switch", 0x17, 0x1, HDA_INPUT), | ||
758 | HDA_CODEC_VOLUME("Capture-3 Volume", 0x17, 0x2, HDA_INPUT), | ||
759 | HDA_CODEC_MUTE("Capture-3 Switch", 0x17, 0x2, HDA_INPUT), | ||
760 | HDA_CODEC_VOLUME("Capture-4 Volume", 0x17, 0x3, HDA_INPUT), | ||
761 | HDA_CODEC_MUTE("Capture-4 Switch", 0x17, 0x3, HDA_INPUT), | ||
762 | HDA_CODEC_VOLUME("Capture-5 Volume", 0x17, 0x4, HDA_INPUT), | ||
763 | HDA_CODEC_MUTE("Capture-5 Switch", 0x17, 0x4, HDA_INPUT), | ||
764 | { | 701 | { |
765 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 702 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
766 | .name = "Input Source", | 703 | .name = "Input Source", |
@@ -768,14 +705,17 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = { | |||
768 | .get = conexant_mux_enum_get, | 705 | .get = conexant_mux_enum_get, |
769 | .put = conexant_mux_enum_put, | 706 | .put = conexant_mux_enum_put, |
770 | }, | 707 | }, |
771 | |||
772 | { } /* end */ | 708 | { } /* end */ |
773 | }; | 709 | }; |
774 | 710 | ||
775 | static struct hda_verb cxt5045_test_init_verbs[] = { | 711 | static struct hda_verb cxt5045_test_init_verbs[] = { |
712 | /* Set connections */ | ||
713 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
714 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
715 | { 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
776 | /* Enable retasking pins as output, initially without power amp */ | 716 | /* Enable retasking pins as output, initially without power amp */ |
777 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 717 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
778 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 718 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
779 | 719 | ||
780 | /* Disable digital (SPDIF) pins initially, but users can enable | 720 | /* Disable digital (SPDIF) pins initially, but users can enable |
781 | * them via a mixer switch. In the case of SPDIF-out, this initverb | 721 | * them via a mixer switch. In the case of SPDIF-out, this initverb |
@@ -804,6 +744,7 @@ static struct hda_verb cxt5045_test_init_verbs[] = { | |||
804 | * pin) | 744 | * pin) |
805 | */ | 745 | */ |
806 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | 746 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, |
747 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
807 | 748 | ||
808 | /* Mute all inputs to mixer widget (even unconnected ones) */ | 749 | /* Mute all inputs to mixer widget (even unconnected ones) */ |
809 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */ | 750 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */ |
@@ -827,7 +768,8 @@ static int cxt5045_init(struct hda_codec *codec) | |||
827 | 768 | ||
828 | 769 | ||
829 | enum { | 770 | enum { |
830 | CXT5045_LAPTOP, /* Laptops w/ EAPD support */ | 771 | CXT5045_LAPTOP, /* Laptops w/ EAPD support */ |
772 | CXT5045_FUJITSU, /* Laptops w/ EAPD support */ | ||
831 | #ifdef CONFIG_SND_DEBUG | 773 | #ifdef CONFIG_SND_DEBUG |
832 | CXT5045_TEST, | 774 | CXT5045_TEST, |
833 | #endif | 775 | #endif |
@@ -836,6 +778,7 @@ enum { | |||
836 | 778 | ||
837 | static const char *cxt5045_models[CXT5045_MODELS] = { | 779 | static const char *cxt5045_models[CXT5045_MODELS] = { |
838 | [CXT5045_LAPTOP] = "laptop", | 780 | [CXT5045_LAPTOP] = "laptop", |
781 | [CXT5045_FUJITSU] = "fujitsu", | ||
839 | #ifdef CONFIG_SND_DEBUG | 782 | #ifdef CONFIG_SND_DEBUG |
840 | [CXT5045_TEST] = "test", | 783 | [CXT5045_TEST] = "test", |
841 | #endif | 784 | #endif |
@@ -844,7 +787,11 @@ static const char *cxt5045_models[CXT5045_MODELS] = { | |||
844 | static struct snd_pci_quirk cxt5045_cfg_tbl[] = { | 787 | static struct snd_pci_quirk cxt5045_cfg_tbl[] = { |
845 | SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP), | 788 | SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP), |
846 | SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP), | 789 | SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP), |
847 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP), | 790 | SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP), |
791 | SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP), | ||
792 | SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP), | ||
793 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_FUJITSU), | ||
794 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP), | ||
848 | {} | 795 | {} |
849 | }; | 796 | }; |
850 | 797 | ||
@@ -877,16 +824,23 @@ static int patch_cxt5045(struct hda_codec *codec) | |||
877 | 824 | ||
878 | 825 | ||
879 | codec->patch_ops = conexant_patch_ops; | 826 | codec->patch_ops = conexant_patch_ops; |
880 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
881 | 827 | ||
882 | board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, | 828 | board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, |
883 | cxt5045_models, | 829 | cxt5045_models, |
884 | cxt5045_cfg_tbl); | 830 | cxt5045_cfg_tbl); |
885 | switch (board_config) { | 831 | switch (board_config) { |
886 | case CXT5045_LAPTOP: | 832 | case CXT5045_LAPTOP: |
833 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
834 | spec->input_mux = &cxt5045_capture_source; | ||
835 | spec->num_init_verbs = 2; | ||
836 | spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; | ||
837 | spec->mixers[0] = cxt5045_mixers; | ||
838 | codec->patch_ops.init = cxt5045_init; | ||
839 | break; | ||
840 | case CXT5045_FUJITSU: | ||
887 | spec->input_mux = &cxt5045_capture_source; | 841 | spec->input_mux = &cxt5045_capture_source; |
888 | spec->num_init_verbs = 2; | 842 | spec->num_init_verbs = 2; |
889 | spec->init_verbs[1] = cxt5045_init_verbs; | 843 | spec->init_verbs[1] = cxt5045_mic_sense_init_verbs; |
890 | spec->mixers[0] = cxt5045_mixers; | 844 | spec->mixers[0] = cxt5045_mixers; |
891 | codec->patch_ops.init = cxt5045_init; | 845 | codec->patch_ops.init = cxt5045_init; |
892 | break; | 846 | break; |
@@ -913,10 +867,9 @@ static struct hda_channel_mode cxt5047_modes[1] = { | |||
913 | }; | 867 | }; |
914 | 868 | ||
915 | static struct hda_input_mux cxt5047_capture_source = { | 869 | static struct hda_input_mux cxt5047_capture_source = { |
916 | .num_items = 2, | 870 | .num_items = 1, |
917 | .items = { | 871 | .items = { |
918 | { "ExtMic", 0x0 }, | 872 | { "Mic", 0x2 }, |
919 | { "IntMic", 0x1 }, | ||
920 | } | 873 | } |
921 | }; | 874 | }; |
922 | 875 | ||
@@ -1009,7 +962,7 @@ static void cxt5047_hp_automic(struct hda_codec *codec) | |||
1009 | }; | 962 | }; |
1010 | unsigned int present; | 963 | unsigned int present; |
1011 | 964 | ||
1012 | present = snd_hda_codec_read(codec, 0x08, 0, | 965 | present = snd_hda_codec_read(codec, 0x15, 0, |
1013 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 966 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1014 | if (present) | 967 | if (present) |
1015 | snd_hda_sequence_write(codec, mic_jack_on); | 968 | snd_hda_sequence_write(codec, mic_jack_on); |
@@ -1033,37 +986,20 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec, | |||
1033 | } | 986 | } |
1034 | 987 | ||
1035 | static struct snd_kcontrol_new cxt5047_mixers[] = { | 988 | static struct snd_kcontrol_new cxt5047_mixers[] = { |
1036 | { | ||
1037 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1038 | .name = "Capture Source", | ||
1039 | .info = conexant_mux_enum_info, | ||
1040 | .get = conexant_mux_enum_get, | ||
1041 | .put = conexant_mux_enum_put | ||
1042 | }, | ||
1043 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), | 989 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), |
1044 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), | 990 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), |
991 | HDA_CODEC_VOLUME("Mic Gain Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
992 | HDA_CODEC_MUTE("Mic Gain Switch", 0x1a, 0x0, HDA_OUTPUT), | ||
1045 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | 993 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), |
1046 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | 994 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), |
1047 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | 995 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), |
1048 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | 996 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), |
1049 | HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT), | 997 | HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT), |
1050 | HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT), | 998 | HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT), |
1051 | { | 999 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT), |
1052 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1000 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x00, HDA_OUTPUT), |
1053 | .name = "Master Playback Volume", | 1001 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), |
1054 | .info = snd_hda_mixer_amp_volume_info, | 1002 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x13, 0x00, HDA_OUTPUT), |
1055 | .get = snd_hda_mixer_amp_volume_get, | ||
1056 | .put = cxt5047_hp_master_vol_put, | ||
1057 | .private_value = HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT), | ||
1058 | }, | ||
1059 | { | ||
1060 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1061 | .name = "Master Playback Switch", | ||
1062 | .info = cxt_eapd_info, | ||
1063 | .get = cxt_eapd_get, | ||
1064 | .put = cxt5047_hp_master_sw_put, | ||
1065 | .private_value = 0x13, | ||
1066 | }, | ||
1067 | 1003 | ||
1068 | {} | 1004 | {} |
1069 | }; | 1005 | }; |
@@ -1133,18 +1069,19 @@ static struct hda_verb cxt5047_init_verbs[] = { | |||
1133 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | 1069 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
1134 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | 1070 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, |
1135 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | 1071 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, |
1136 | /* HP, Amp, Speaker */ | 1072 | /* HP, Speaker */ |
1137 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | 1073 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
1138 | {0x1A, AC_VERB_SET_CONNECT_SEL,0x00}, | 1074 | {0x13, AC_VERB_SET_CONNECT_SEL,0x1}, |
1139 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1140 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, | ||
1141 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1142 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, | ||
1143 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x0}, | 1075 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x0}, |
1144 | /* Record selector: Front mic */ | 1076 | /* Record selector: Mic */ |
1145 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | 1077 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, |
1146 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | 1078 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, |
1147 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | 1079 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, |
1080 | {0x1A, AC_VERB_SET_CONNECT_SEL,0x02}, | ||
1081 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1082 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, | ||
1083 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1084 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, | ||
1148 | /* SPDIF route: PCM */ | 1085 | /* SPDIF route: PCM */ |
1149 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 }, | 1086 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 }, |
1150 | /* Enable unsolicited events */ | 1087 | /* Enable unsolicited events */ |
@@ -1161,8 +1098,6 @@ static struct hda_verb cxt5047_toshiba_init_verbs[] = { | |||
1161 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | 1098 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, |
1162 | /* Speaker routing */ | 1099 | /* Speaker routing */ |
1163 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, | 1100 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, |
1164 | /* Change default to ExtMic for recording */ | ||
1165 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x2}, | ||
1166 | {} | 1101 | {} |
1167 | }; | 1102 | }; |
1168 | 1103 | ||
@@ -1172,7 +1107,6 @@ static struct hda_verb cxt5047_hp_init_verbs[] = { | |||
1172 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | 1107 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, |
1173 | /* Record selector: Ext Mic */ | 1108 | /* Record selector: Ext Mic */ |
1174 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | 1109 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, |
1175 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x02}, | ||
1176 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | 1110 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, |
1177 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | 1111 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, |
1178 | /* Speaker routing */ | 1112 | /* Speaker routing */ |
@@ -1242,14 +1176,6 @@ static struct snd_kcontrol_new cxt5047_test_mixer[] = { | |||
1242 | .get = conexant_mux_enum_get, | 1176 | .get = conexant_mux_enum_get, |
1243 | .put = conexant_mux_enum_put, | 1177 | .put = conexant_mux_enum_put, |
1244 | }, | 1178 | }, |
1245 | /* Controls for GPIO pins, assuming they exist and are configured | ||
1246 | * as outputs | ||
1247 | */ | ||
1248 | CXT_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01), | ||
1249 | CXT_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02), | ||
1250 | CXT_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04), | ||
1251 | CXT_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08), | ||
1252 | |||
1253 | { } /* end */ | 1179 | { } /* end */ |
1254 | }; | 1180 | }; |
1255 | 1181 | ||