diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-05-13 11:22:05 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-05-13 11:22:05 -0400 |
commit | 1f8458a26293b692955f8dff671a3ed50dd9c603 (patch) | |
tree | e54609d3f90d53f2433f0e2a6d2d026cf4899102 /sound/pci | |
parent | 6764bcef4cb964456615565ff974ed917de3c12d (diff) |
ALSA: hda - Add auto-parser support to cxt5045 / CX20549 Venice
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 84 |
1 files changed, 65 insertions, 19 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index cdb9f499d7f1..623cd9be5477 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -1059,6 +1059,7 @@ enum { | |||
1059 | #ifdef CONFIG_SND_DEBUG | 1059 | #ifdef CONFIG_SND_DEBUG |
1060 | CXT5045_TEST, | 1060 | CXT5045_TEST, |
1061 | #endif | 1061 | #endif |
1062 | CXT5045_AUTO, | ||
1062 | CXT5045_MODELS | 1063 | CXT5045_MODELS |
1063 | }; | 1064 | }; |
1064 | 1065 | ||
@@ -1071,6 +1072,7 @@ static const char * const cxt5045_models[CXT5045_MODELS] = { | |||
1071 | #ifdef CONFIG_SND_DEBUG | 1072 | #ifdef CONFIG_SND_DEBUG |
1072 | [CXT5045_TEST] = "test", | 1073 | [CXT5045_TEST] = "test", |
1073 | #endif | 1074 | #endif |
1075 | [CXT5045_AUTO] = "auto", | ||
1074 | }; | 1076 | }; |
1075 | 1077 | ||
1076 | static const struct snd_pci_quirk cxt5045_cfg_tbl[] = { | 1078 | static const struct snd_pci_quirk cxt5045_cfg_tbl[] = { |
@@ -1097,6 +1099,14 @@ static int patch_cxt5045(struct hda_codec *codec) | |||
1097 | struct conexant_spec *spec; | 1099 | struct conexant_spec *spec; |
1098 | int board_config; | 1100 | int board_config; |
1099 | 1101 | ||
1102 | board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, | ||
1103 | cxt5045_models, | ||
1104 | cxt5045_cfg_tbl); | ||
1105 | if (board_config < 0) | ||
1106 | board_config = CXT5045_AUTO; | ||
1107 | if (board_config == CXT5045_AUTO) | ||
1108 | return patch_conexant_auto(codec); | ||
1109 | |||
1100 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1110 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
1101 | if (!spec) | 1111 | if (!spec) |
1102 | return -ENOMEM; | 1112 | return -ENOMEM; |
@@ -1123,9 +1133,6 @@ static int patch_cxt5045(struct hda_codec *codec) | |||
1123 | 1133 | ||
1124 | codec->patch_ops = conexant_patch_ops; | 1134 | codec->patch_ops = conexant_patch_ops; |
1125 | 1135 | ||
1126 | board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, | ||
1127 | cxt5045_models, | ||
1128 | cxt5045_cfg_tbl); | ||
1129 | switch (board_config) { | 1136 | switch (board_config) { |
1130 | case CXT5045_LAPTOP_HPSENSE: | 1137 | case CXT5045_LAPTOP_HPSENSE: |
1131 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | 1138 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; |
@@ -1956,11 +1963,8 @@ static int patch_cxt5051(struct hda_codec *codec) | |||
1956 | cxt5051_cfg_tbl); | 1963 | cxt5051_cfg_tbl); |
1957 | if (board_config < 0) | 1964 | if (board_config < 0) |
1958 | board_config = CXT5051_AUTO; | 1965 | board_config = CXT5051_AUTO; |
1959 | if (board_config == CXT5051_AUTO) { | 1966 | if (board_config == CXT5051_AUTO) |
1960 | printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | ||
1961 | codec->chip_name); | ||
1962 | return patch_conexant_auto(codec); | 1967 | return patch_conexant_auto(codec); |
1963 | } | ||
1964 | 1968 | ||
1965 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1969 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
1966 | if (!spec) | 1970 | if (!spec) |
@@ -3688,15 +3692,15 @@ static void select_connection(struct hda_codec *codec, hda_nid_t pin, | |||
3688 | AC_VERB_SET_CONNECT_SEL, idx); | 3692 | AC_VERB_SET_CONNECT_SEL, idx); |
3689 | } | 3693 | } |
3690 | 3694 | ||
3691 | static void cx_auto_init_output(struct hda_codec *codec) | 3695 | static void mute_outputs(struct hda_codec *codec, int num_nids, |
3696 | const hda_nid_t *nids) | ||
3692 | { | 3697 | { |
3693 | struct conexant_spec *spec = codec->spec; | ||
3694 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3695 | hda_nid_t nid; | ||
3696 | int i, val; | 3698 | int i, val; |
3697 | 3699 | ||
3698 | for (i = 0; i < spec->multiout.num_dacs; i++) { | 3700 | for (i = 0; i < num_nids; i++) { |
3699 | nid = spec->multiout.dac_nids[i]; | 3701 | hda_nid_t nid = nids[i]; |
3702 | if (!(get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | ||
3703 | continue; | ||
3700 | if (query_amp_caps(codec, nid, HDA_OUTPUT) & AC_AMPCAP_MUTE) | 3704 | if (query_amp_caps(codec, nid, HDA_OUTPUT) & AC_AMPCAP_MUTE) |
3701 | val = AMP_OUT_MUTE; | 3705 | val = AMP_OUT_MUTE; |
3702 | else | 3706 | else |
@@ -3704,10 +3708,22 @@ static void cx_auto_init_output(struct hda_codec *codec) | |||
3704 | snd_hda_codec_write(codec, nid, 0, | 3708 | snd_hda_codec_write(codec, nid, 0, |
3705 | AC_VERB_SET_AMP_GAIN_MUTE, val); | 3709 | AC_VERB_SET_AMP_GAIN_MUTE, val); |
3706 | } | 3710 | } |
3711 | } | ||
3707 | 3712 | ||
3713 | static void cx_auto_init_output(struct hda_codec *codec) | ||
3714 | { | ||
3715 | struct conexant_spec *spec = codec->spec; | ||
3716 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3717 | hda_nid_t nid; | ||
3718 | int i; | ||
3719 | |||
3720 | mute_outputs(codec, spec->multiout.num_dacs, spec->multiout.dac_nids); | ||
3708 | for (i = 0; i < cfg->hp_outs; i++) | 3721 | for (i = 0; i < cfg->hp_outs; i++) |
3709 | snd_hda_codec_write(codec, cfg->hp_pins[i], 0, | 3722 | snd_hda_codec_write(codec, cfg->hp_pins[i], 0, |
3710 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); | 3723 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); |
3724 | mute_outputs(codec, cfg->hp_outs, cfg->hp_pins); | ||
3725 | mute_outputs(codec, cfg->line_outs, cfg->line_out_pins); | ||
3726 | mute_outputs(codec, cfg->speaker_outs, cfg->speaker_pins); | ||
3711 | if (spec->auto_mute) { | 3727 | if (spec->auto_mute) { |
3712 | for (i = 0; i < cfg->hp_outs; i++) { | 3728 | for (i = 0; i < cfg->hp_outs; i++) { |
3713 | snd_hda_codec_write(codec, cfg->hp_pins[i], 0, | 3729 | snd_hda_codec_write(codec, cfg->hp_pins[i], 0, |
@@ -3747,6 +3763,8 @@ static void cx_auto_init_input(struct hda_codec *codec) | |||
3747 | 3763 | ||
3748 | for (i = 0; i < spec->num_adc_nids; i++) { | 3764 | for (i = 0; i < spec->num_adc_nids; i++) { |
3749 | hda_nid_t nid = spec->adc_nids[i]; | 3765 | hda_nid_t nid = spec->adc_nids[i]; |
3766 | if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) | ||
3767 | continue; | ||
3750 | if (query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE) | 3768 | if (query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE) |
3751 | val = AMP_IN_MUTE(0); | 3769 | val = AMP_IN_MUTE(0); |
3752 | else | 3770 | else |
@@ -3839,6 +3857,19 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename, | |||
3839 | #define cx_auto_add_pb_volume(codec, nid, str, idx) \ | 3857 | #define cx_auto_add_pb_volume(codec, nid, str, idx) \ |
3840 | cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT) | 3858 | cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT) |
3841 | 3859 | ||
3860 | static int try_add_pb_volume(struct hda_codec *codec, hda_nid_t dac, | ||
3861 | hda_nid_t pin, const char *name, int idx) | ||
3862 | { | ||
3863 | unsigned int caps; | ||
3864 | caps = query_amp_caps(codec, dac, HDA_OUTPUT); | ||
3865 | if (caps & AC_AMPCAP_NUM_STEPS) | ||
3866 | return cx_auto_add_pb_volume(codec, dac, name, idx); | ||
3867 | caps = query_amp_caps(codec, pin, HDA_OUTPUT); | ||
3868 | if (caps & AC_AMPCAP_NUM_STEPS) | ||
3869 | return cx_auto_add_pb_volume(codec, pin, name, idx); | ||
3870 | return 0; | ||
3871 | } | ||
3872 | |||
3842 | static int cx_auto_build_output_controls(struct hda_codec *codec) | 3873 | static int cx_auto_build_output_controls(struct hda_codec *codec) |
3843 | { | 3874 | { |
3844 | struct conexant_spec *spec = codec->spec; | 3875 | struct conexant_spec *spec = codec->spec; |
@@ -3847,8 +3878,10 @@ static int cx_auto_build_output_controls(struct hda_codec *codec) | |||
3847 | static const char * const texts[3] = { "Front", "Surround", "CLFE" }; | 3878 | static const char * const texts[3] = { "Front", "Surround", "CLFE" }; |
3848 | 3879 | ||
3849 | if (spec->dac_info_filled == 1) | 3880 | if (spec->dac_info_filled == 1) |
3850 | return cx_auto_add_pb_volume(codec, spec->dac_info[0].dac, | 3881 | return try_add_pb_volume(codec, spec->dac_info[0].dac, |
3851 | "Master", 0); | 3882 | spec->dac_info[0].pin, |
3883 | "Master", 0); | ||
3884 | |||
3852 | for (i = 0; i < spec->dac_info_filled; i++) { | 3885 | for (i = 0; i < spec->dac_info_filled; i++) { |
3853 | const char *label; | 3886 | const char *label; |
3854 | int idx, type; | 3887 | int idx, type; |
@@ -3872,8 +3905,9 @@ static int cx_auto_build_output_controls(struct hda_codec *codec) | |||
3872 | idx = num_spk++; | 3905 | idx = num_spk++; |
3873 | break; | 3906 | break; |
3874 | } | 3907 | } |
3875 | err = cx_auto_add_pb_volume(codec, spec->dac_info[i].dac, | 3908 | err = try_add_pb_volume(codec, spec->dac_info[i].dac, |
3876 | label, idx); | 3909 | spec->dac_info[i].pin, |
3910 | label, idx); | ||
3877 | if (err < 0) | 3911 | if (err < 0) |
3878 | return err; | 3912 | return err; |
3879 | } | 3913 | } |
@@ -3976,19 +4010,31 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
3976 | struct conexant_spec *spec; | 4010 | struct conexant_spec *spec; |
3977 | int err; | 4011 | int err; |
3978 | 4012 | ||
4013 | printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | ||
4014 | codec->chip_name); | ||
4015 | |||
3979 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4016 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
3980 | if (!spec) | 4017 | if (!spec) |
3981 | return -ENOMEM; | 4018 | return -ENOMEM; |
3982 | codec->spec = spec; | 4019 | codec->spec = spec; |
3983 | if (codec->vendor_id == 0x14f15051) { | 4020 | switch (codec->vendor_id) { |
4021 | case 0x14f15051: | ||
3984 | codec->pin_amp_workaround = 1; | 4022 | codec->pin_amp_workaround = 1; |
3985 | spec->adc_nids = cxt5051_adc_nids; | 4023 | spec->adc_nids = cxt5051_adc_nids; |
3986 | spec->num_adc_nids = ARRAY_SIZE(cxt5051_adc_nids); | 4024 | spec->num_adc_nids = ARRAY_SIZE(cxt5051_adc_nids); |
3987 | spec->capsrc_nids = spec->adc_nids; | 4025 | spec->capsrc_nids = spec->adc_nids; |
3988 | } else { | 4026 | break; |
4027 | case 0x14f15045: | ||
4028 | codec->pin_amp_workaround = 1; | ||
4029 | spec->adc_nids = cxt5045_adc_nids; | ||
4030 | spec->num_adc_nids = ARRAY_SIZE(cxt5045_adc_nids); | ||
4031 | spec->capsrc_nids = spec->adc_nids; | ||
4032 | break; | ||
4033 | default: | ||
3989 | spec->adc_nids = cx_auto_adc_nids; | 4034 | spec->adc_nids = cx_auto_adc_nids; |
3990 | spec->num_adc_nids = ARRAY_SIZE(cx_auto_adc_nids); | 4035 | spec->num_adc_nids = ARRAY_SIZE(cx_auto_adc_nids); |
3991 | spec->capsrc_nids = spec->adc_nids; | 4036 | spec->capsrc_nids = spec->adc_nids; |
4037 | break; | ||
3992 | } | 4038 | } |
3993 | err = cx_auto_parse_auto_config(codec); | 4039 | err = cx_auto_parse_auto_config(codec); |
3994 | if (err < 0) { | 4040 | if (err < 0) { |