diff options
author | Tobin Davis <tdavis@dsl-only.net> | 2007-03-12 06:39:01 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-05-11 10:55:47 -0400 |
commit | 7f29673b2b20071a407af0a0a6acab8230912c6e (patch) | |
tree | 387b2a3e6b07851fe76cad4e4f57b7f87919cf15 /sound/pci | |
parent | 68e22543eec3e44508d0d4ed584562478b942b09 (diff) |
[ALSA] hda-codec - Conexant improvements
This patch further improves on the Conexant Audio driver.
Adds support for Fujistu Siemens Si1520 series laptops.
Adds support for mic/line in on CX20549 based systems (aka 5045).
removes duplicated or unused controls (gpio, spdif) from test model.
Signed-off-by: Tobin Davis <tdavis@dsl-only.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 267 |
1 files changed, 93 insertions, 174 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 46e93c6b9a42..c7fb0b8dfb8f 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -452,115 +452,6 @@ static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol, | |||
452 | .put = conexant_ch_mode_put, \ | 452 | .put = conexant_ch_mode_put, \ |
453 | .private_value = nid | (dir<<16) } | 453 | .private_value = nid | (dir<<16) } |
454 | 454 | ||
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 */ | 455 | #endif /* CONFIG_SND_DEBUG */ |
565 | 456 | ||
566 | /* Conexant 5045 specific */ | 457 | /* Conexant 5045 specific */ |
@@ -599,6 +490,7 @@ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
599 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80; | 490 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80; |
600 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); | 491 | 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); | 492 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); |
493 | |||
602 | bits = spec->cur_eapd ? 0 : 0x80; | 494 | bits = spec->cur_eapd ? 0 : 0x80; |
603 | snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits); | 495 | 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); | 496 | snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits); |
@@ -624,6 +516,29 @@ static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol, | |||
624 | return change; | 516 | return change; |
625 | } | 517 | } |
626 | 518 | ||
519 | /* toggle input of built-in and mic jack appropriately */ | ||
520 | static void cxt5045_hp_automic(struct hda_codec *codec) | ||
521 | { | ||
522 | static struct hda_verb mic_jack_on[] = { | ||
523 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
524 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
525 | {} | ||
526 | }; | ||
527 | static struct hda_verb mic_jack_off[] = { | ||
528 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
529 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
530 | {} | ||
531 | }; | ||
532 | unsigned int present; | ||
533 | |||
534 | present = snd_hda_codec_read(codec, 0x12, 0, | ||
535 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
536 | if (present) | ||
537 | snd_hda_sequence_write(codec, mic_jack_on); | ||
538 | else | ||
539 | snd_hda_sequence_write(codec, mic_jack_off); | ||
540 | } | ||
541 | |||
627 | 542 | ||
628 | /* mute internal speaker if HP is plugged */ | 543 | /* mute internal speaker if HP is plugged */ |
629 | static void cxt5045_hp_automute(struct hda_codec *codec) | 544 | static void cxt5045_hp_automute(struct hda_codec *codec) |
@@ -634,7 +549,7 @@ static void cxt5045_hp_automute(struct hda_codec *codec) | |||
634 | spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, | 549 | spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, |
635 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 550 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
636 | 551 | ||
637 | bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; | 552 | bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; |
638 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); | 553 | 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); | 554 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); |
640 | } | 555 | } |
@@ -648,6 +563,10 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec, | |||
648 | case CONEXANT_HP_EVENT: | 563 | case CONEXANT_HP_EVENT: |
649 | cxt5045_hp_automute(codec); | 564 | cxt5045_hp_automute(codec); |
650 | break; | 565 | break; |
566 | case CONEXANT_MIC_EVENT: | ||
567 | cxt5045_hp_automic(codec); | ||
568 | break; | ||
569 | |||
651 | } | 570 | } |
652 | } | 571 | } |
653 | 572 | ||
@@ -659,12 +578,10 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { | |||
659 | .get = conexant_mux_enum_get, | 578 | .get = conexant_mux_enum_get, |
660 | .put = conexant_mux_enum_put | 579 | .put = conexant_mux_enum_put |
661 | }, | 580 | }, |
662 | HDA_CODEC_VOLUME("Int Mic Volume", 0x17, 0x01, HDA_INPUT), | 581 | HDA_CODEC_VOLUME("Int Mic Volume", 0x1a, 0x01, HDA_INPUT), |
663 | HDA_CODEC_MUTE("Int Mic Switch", 0x17, 0x01, HDA_INPUT), | 582 | HDA_CODEC_MUTE("Int Mic Switch", 0x1a, 0x01, HDA_INPUT), |
664 | HDA_CODEC_VOLUME("Ext Mic Volume", 0x17, 0x02, HDA_INPUT), | 583 | HDA_CODEC_VOLUME("Ext Mic Volume", 0x1a, 0x02, HDA_INPUT), |
665 | HDA_CODEC_MUTE("Ext Mic Switch", 0x17, 0x02, HDA_INPUT), | 584 | 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 | { | 585 | { |
669 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 586 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
670 | .name = "Master Playback Volume", | 587 | .name = "Master Playback Volume", |
@@ -688,7 +605,7 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { | |||
688 | static struct hda_verb cxt5045_init_verbs[] = { | 605 | static struct hda_verb cxt5045_init_verbs[] = { |
689 | /* Line in, Mic */ | 606 | /* Line in, Mic */ |
690 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | 607 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
691 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | 608 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, |
692 | /* HP, Amp */ | 609 | /* HP, Amp */ |
693 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | 610 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
694 | {0x17, AC_VERB_SET_CONNECT_SEL,0x01}, | 611 | {0x17, AC_VERB_SET_CONNECT_SEL,0x01}, |
@@ -701,18 +618,27 @@ static struct hda_verb cxt5045_init_verbs[] = { | |||
701 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, | 618 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, |
702 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x04}, | 619 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x04}, |
703 | /* Record selector: Int mic */ | 620 | /* Record selector: Int mic */ |
704 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x0}, | 621 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, |
705 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, | 622 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, |
706 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | 623 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, |
707 | /* SPDIF route: PCM */ | 624 | /* SPDIF route: PCM */ |
708 | { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 }, | 625 | { 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 */ | 626 | /* EAPD */ |
712 | {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ | 627 | {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ |
713 | { } /* end */ | 628 | { } /* end */ |
714 | }; | 629 | }; |
715 | 630 | ||
631 | |||
632 | static struct hda_verb cxt5045_hp_sense_init_verbs[] = { | ||
633 | /* pin sensing on HP jack */ | ||
634 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
635 | }; | ||
636 | |||
637 | static struct hda_verb cxt5045_mic_sense_init_verbs[] = { | ||
638 | /* pin sensing on HP jack */ | ||
639 | {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
640 | }; | ||
641 | |||
716 | #ifdef CONFIG_SND_DEBUG | 642 | #ifdef CONFIG_SND_DEBUG |
717 | /* Test configuration for debugging, modelled after the ALC260 test | 643 | /* Test configuration for debugging, modelled after the ALC260 test |
718 | * configuration. | 644 | * configuration. |
@@ -733,6 +659,10 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = { | |||
733 | /* Output controls */ | 659 | /* Output controls */ |
734 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), | 660 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), |
735 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), | 661 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), |
662 | HDA_CODEC_VOLUME("Node 11 Playback Volume", 0x11, 0x0, HDA_OUTPUT), | ||
663 | HDA_CODEC_MUTE("Node 11 Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
664 | HDA_CODEC_VOLUME("Node 12 Playback Volume", 0x12, 0x0, HDA_OUTPUT), | ||
665 | HDA_CODEC_MUTE("Node 12 Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
736 | 666 | ||
737 | /* Modes for retasking pin widgets */ | 667 | /* Modes for retasking pin widgets */ |
738 | CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), | 668 | CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), |
@@ -742,25 +672,17 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = { | |||
742 | CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0), | 672 | CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0), |
743 | 673 | ||
744 | /* Loopback mixer controls */ | 674 | /* Loopback mixer controls */ |
745 | HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x17, 0x01, HDA_INPUT), | 675 | |
746 | HDA_CODEC_MUTE("MIC1 Playback Switch", 0x17, 0x01, HDA_INPUT), | 676 | HDA_CODEC_VOLUME("Mixer-1 Volume", 0x17, 0x0, HDA_INPUT), |
747 | HDA_CODEC_VOLUME("LINE loopback Playback Volume", 0x17, 0x02, HDA_INPUT), | 677 | HDA_CODEC_MUTE("Mixer-1 Switch", 0x17, 0x0, HDA_INPUT), |
748 | HDA_CODEC_MUTE("LINE loopback Playback Switch", 0x17, 0x02, HDA_INPUT), | 678 | HDA_CODEC_VOLUME("Mixer-2 Volume", 0x17, 0x1, HDA_INPUT), |
749 | HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x17, 0x03, HDA_INPUT), | 679 | HDA_CODEC_MUTE("Mixer-2 Switch", 0x17, 0x1, HDA_INPUT), |
750 | HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x17, 0x03, HDA_INPUT), | 680 | HDA_CODEC_VOLUME("Mixer-3 Volume", 0x17, 0x2, HDA_INPUT), |
751 | HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x04, HDA_INPUT), | 681 | HDA_CODEC_MUTE("Mixer-3 Switch", 0x17, 0x2, HDA_INPUT), |
752 | HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x04, HDA_INPUT), | 682 | HDA_CODEC_VOLUME("Mixer-4 Volume", 0x17, 0x3, HDA_INPUT), |
753 | 683 | HDA_CODEC_MUTE("Mixer-4 Switch", 0x17, 0x3, HDA_INPUT), | |
754 | HDA_CODEC_VOLUME("Capture-1 Volume", 0x17, 0x0, HDA_INPUT), | 684 | HDA_CODEC_VOLUME("Mixer-5 Volume", 0x17, 0x4, HDA_INPUT), |
755 | HDA_CODEC_MUTE("Capture-1 Switch", 0x17, 0x0, HDA_INPUT), | 685 | 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 | { | 686 | { |
765 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 687 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
766 | .name = "Input Source", | 688 | .name = "Input Source", |
@@ -768,14 +690,17 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = { | |||
768 | .get = conexant_mux_enum_get, | 690 | .get = conexant_mux_enum_get, |
769 | .put = conexant_mux_enum_put, | 691 | .put = conexant_mux_enum_put, |
770 | }, | 692 | }, |
771 | |||
772 | { } /* end */ | 693 | { } /* end */ |
773 | }; | 694 | }; |
774 | 695 | ||
775 | static struct hda_verb cxt5045_test_init_verbs[] = { | 696 | static struct hda_verb cxt5045_test_init_verbs[] = { |
697 | /* Set connections */ | ||
698 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
699 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
700 | { 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
776 | /* Enable retasking pins as output, initially without power amp */ | 701 | /* Enable retasking pins as output, initially without power amp */ |
777 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 702 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
778 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 703 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
779 | 704 | ||
780 | /* Disable digital (SPDIF) pins initially, but users can enable | 705 | /* Disable digital (SPDIF) pins initially, but users can enable |
781 | * them via a mixer switch. In the case of SPDIF-out, this initverb | 706 | * them via a mixer switch. In the case of SPDIF-out, this initverb |
@@ -804,6 +729,7 @@ static struct hda_verb cxt5045_test_init_verbs[] = { | |||
804 | * pin) | 729 | * pin) |
805 | */ | 730 | */ |
806 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | 731 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, |
732 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
807 | 733 | ||
808 | /* Mute all inputs to mixer widget (even unconnected ones) */ | 734 | /* Mute all inputs to mixer widget (even unconnected ones) */ |
809 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */ | 735 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */ |
@@ -827,7 +753,8 @@ static int cxt5045_init(struct hda_codec *codec) | |||
827 | 753 | ||
828 | 754 | ||
829 | enum { | 755 | enum { |
830 | CXT5045_LAPTOP, /* Laptops w/ EAPD support */ | 756 | CXT5045_LAPTOP, /* Laptops w/ EAPD support */ |
757 | CXT5045_FUJITSU, /* Laptops w/ EAPD support */ | ||
831 | #ifdef CONFIG_SND_DEBUG | 758 | #ifdef CONFIG_SND_DEBUG |
832 | CXT5045_TEST, | 759 | CXT5045_TEST, |
833 | #endif | 760 | #endif |
@@ -836,6 +763,7 @@ enum { | |||
836 | 763 | ||
837 | static const char *cxt5045_models[CXT5045_MODELS] = { | 764 | static const char *cxt5045_models[CXT5045_MODELS] = { |
838 | [CXT5045_LAPTOP] = "laptop", | 765 | [CXT5045_LAPTOP] = "laptop", |
766 | [CXT5045_FUJITSU] = "fujitsu", | ||
839 | #ifdef CONFIG_SND_DEBUG | 767 | #ifdef CONFIG_SND_DEBUG |
840 | [CXT5045_TEST] = "test", | 768 | [CXT5045_TEST] = "test", |
841 | #endif | 769 | #endif |
@@ -844,7 +772,8 @@ static const char *cxt5045_models[CXT5045_MODELS] = { | |||
844 | static struct snd_pci_quirk cxt5045_cfg_tbl[] = { | 772 | static struct snd_pci_quirk cxt5045_cfg_tbl[] = { |
845 | SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP), | 773 | SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP), |
846 | SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP), | 774 | SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP), |
847 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP), | 775 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_FUJITSU), |
776 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP), | ||
848 | {} | 777 | {} |
849 | }; | 778 | }; |
850 | 779 | ||
@@ -877,16 +806,23 @@ static int patch_cxt5045(struct hda_codec *codec) | |||
877 | 806 | ||
878 | 807 | ||
879 | codec->patch_ops = conexant_patch_ops; | 808 | codec->patch_ops = conexant_patch_ops; |
880 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
881 | 809 | ||
882 | board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, | 810 | board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, |
883 | cxt5045_models, | 811 | cxt5045_models, |
884 | cxt5045_cfg_tbl); | 812 | cxt5045_cfg_tbl); |
885 | switch (board_config) { | 813 | switch (board_config) { |
886 | case CXT5045_LAPTOP: | 814 | case CXT5045_LAPTOP: |
815 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
816 | spec->input_mux = &cxt5045_capture_source; | ||
817 | spec->num_init_verbs = 2; | ||
818 | spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; | ||
819 | spec->mixers[0] = cxt5045_mixers; | ||
820 | codec->patch_ops.init = cxt5045_init; | ||
821 | break; | ||
822 | case CXT5045_FUJITSU: | ||
887 | spec->input_mux = &cxt5045_capture_source; | 823 | spec->input_mux = &cxt5045_capture_source; |
888 | spec->num_init_verbs = 2; | 824 | spec->num_init_verbs = 2; |
889 | spec->init_verbs[1] = cxt5045_init_verbs; | 825 | spec->init_verbs[1] = cxt5045_mic_sense_init_verbs; |
890 | spec->mixers[0] = cxt5045_mixers; | 826 | spec->mixers[0] = cxt5045_mixers; |
891 | codec->patch_ops.init = cxt5045_init; | 827 | codec->patch_ops.init = cxt5045_init; |
892 | break; | 828 | break; |
@@ -913,10 +849,9 @@ static struct hda_channel_mode cxt5047_modes[1] = { | |||
913 | }; | 849 | }; |
914 | 850 | ||
915 | static struct hda_input_mux cxt5047_capture_source = { | 851 | static struct hda_input_mux cxt5047_capture_source = { |
916 | .num_items = 2, | 852 | .num_items = 1, |
917 | .items = { | 853 | .items = { |
918 | { "ExtMic", 0x0 }, | 854 | { "Mic", 0x2 }, |
919 | { "IntMic", 0x1 }, | ||
920 | } | 855 | } |
921 | }; | 856 | }; |
922 | 857 | ||
@@ -1009,7 +944,7 @@ static void cxt5047_hp_automic(struct hda_codec *codec) | |||
1009 | }; | 944 | }; |
1010 | unsigned int present; | 945 | unsigned int present; |
1011 | 946 | ||
1012 | present = snd_hda_codec_read(codec, 0x08, 0, | 947 | present = snd_hda_codec_read(codec, 0x15, 0, |
1013 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 948 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1014 | if (present) | 949 | if (present) |
1015 | snd_hda_sequence_write(codec, mic_jack_on); | 950 | snd_hda_sequence_write(codec, mic_jack_on); |
@@ -1033,15 +968,10 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec, | |||
1033 | } | 968 | } |
1034 | 969 | ||
1035 | static struct snd_kcontrol_new cxt5047_mixers[] = { | 970 | 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), | 971 | HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT), |
1044 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), | 972 | HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT), |
973 | HDA_CODEC_VOLUME("Mic Gain Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
974 | HDA_CODEC_MUTE("Mic Gain Switch", 0x1a, 0x0, HDA_OUTPUT), | ||
1045 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | 975 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), |
1046 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | 976 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), |
1047 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | 977 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), |
@@ -1133,18 +1063,18 @@ static struct hda_verb cxt5047_init_verbs[] = { | |||
1133 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | 1063 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
1134 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | 1064 | {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 }, | 1065 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, |
1136 | /* HP, Amp, Speaker */ | 1066 | /* HP, Speaker */ |
1137 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | 1067 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
1138 | {0x1A, AC_VERB_SET_CONNECT_SEL,0x00}, | ||
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}, | 1068 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x0}, |
1144 | /* Record selector: Front mic */ | 1069 | /* Record selector: Mic */ |
1145 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | 1070 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, |
1146 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | 1071 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, |
1147 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | 1072 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, |
1073 | {0x1A, AC_VERB_SET_CONNECT_SEL,0x02}, | ||
1074 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1075 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, | ||
1076 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1077 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, | ||
1148 | /* SPDIF route: PCM */ | 1078 | /* SPDIF route: PCM */ |
1149 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 }, | 1079 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 }, |
1150 | /* Enable unsolicited events */ | 1080 | /* Enable unsolicited events */ |
@@ -1161,8 +1091,6 @@ static struct hda_verb cxt5047_toshiba_init_verbs[] = { | |||
1161 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | 1091 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, |
1162 | /* Speaker routing */ | 1092 | /* Speaker routing */ |
1163 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, | 1093 | {0x1d, AC_VERB_SET_CONNECT_SEL,0x1}, |
1164 | /* Change default to ExtMic for recording */ | ||
1165 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x2}, | ||
1166 | {} | 1094 | {} |
1167 | }; | 1095 | }; |
1168 | 1096 | ||
@@ -1172,7 +1100,6 @@ static struct hda_verb cxt5047_hp_init_verbs[] = { | |||
1172 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | 1100 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, |
1173 | /* Record selector: Ext Mic */ | 1101 | /* Record selector: Ext Mic */ |
1174 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | 1102 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, |
1175 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x02}, | ||
1176 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | 1103 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, |
1177 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | 1104 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, |
1178 | /* Speaker routing */ | 1105 | /* Speaker routing */ |
@@ -1242,14 +1169,6 @@ static struct snd_kcontrol_new cxt5047_test_mixer[] = { | |||
1242 | .get = conexant_mux_enum_get, | 1169 | .get = conexant_mux_enum_get, |
1243 | .put = conexant_mux_enum_put, | 1170 | .put = conexant_mux_enum_put, |
1244 | }, | 1171 | }, |
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 */ | 1172 | { } /* end */ |
1254 | }; | 1173 | }; |
1255 | 1174 | ||