diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-07-08 05:07:59 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-07-08 05:07:59 -0400 |
commit | afcd551508dcdb38e80728137c1c166d19bd47dd (patch) | |
tree | 4d47ffda5118018780d19f77ca98926ec7f3fc32 /sound | |
parent | e59ea3ed9fe0cde526c004441465d13287426b29 (diff) |
ALSA: hda - Merge ALC680 auto-parser to the standard parser
Improved the standard Realtek auto-parser to support the codec topology
like ALC680.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 231 |
1 files changed, 90 insertions, 141 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a29e6b3c6a70..f82333b11e41 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -2682,6 +2682,8 @@ static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid) | |||
2682 | hda_nid_t list[5]; | 2682 | hda_nid_t list[5]; |
2683 | int i, num; | 2683 | int i, num; |
2684 | 2684 | ||
2685 | if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT) | ||
2686 | return nid; | ||
2685 | num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list)); | 2687 | num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list)); |
2686 | for (i = 0; i < num; i++) { | 2688 | for (i = 0; i < num; i++) { |
2687 | if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT) | 2689 | if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT) |
@@ -2838,6 +2840,8 @@ static int alc_auto_add_vol_ctl(struct hda_codec *codec, | |||
2838 | const char *pfx, int cidx, | 2840 | const char *pfx, int cidx, |
2839 | hda_nid_t nid, unsigned int chs) | 2841 | hda_nid_t nid, unsigned int chs) |
2840 | { | 2842 | { |
2843 | if (!nid) | ||
2844 | return 0; | ||
2841 | return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx, | 2845 | return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx, |
2842 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | 2846 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); |
2843 | } | 2847 | } |
@@ -2852,9 +2856,16 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec, | |||
2852 | const char *pfx, int cidx, | 2856 | const char *pfx, int cidx, |
2853 | hda_nid_t nid, unsigned int chs) | 2857 | hda_nid_t nid, unsigned int chs) |
2854 | { | 2858 | { |
2859 | int wid_type; | ||
2855 | int type; | 2860 | int type; |
2856 | unsigned long val; | 2861 | unsigned long val; |
2857 | if (snd_hda_get_conn_list(codec, nid, NULL) == 1) { | 2862 | if (!nid) |
2863 | return 0; | ||
2864 | wid_type = get_wcaps_type(get_wcaps(codec, nid)); | ||
2865 | if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) { | ||
2866 | type = ALC_CTL_WIDGET_MUTE; | ||
2867 | val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT); | ||
2868 | } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) { | ||
2858 | type = ALC_CTL_WIDGET_MUTE; | 2869 | type = ALC_CTL_WIDGET_MUTE; |
2859 | val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT); | 2870 | val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT); |
2860 | } else { | 2871 | } else { |
@@ -2867,12 +2878,42 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec, | |||
2867 | #define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \ | 2878 | #define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \ |
2868 | alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3) | 2879 | alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3) |
2869 | 2880 | ||
2881 | #define nid_has_mute(codec, nid, dir) \ | ||
2882 | (query_amp_caps(codec, nid, dir) & AC_AMPCAP_MUTE) | ||
2883 | #define nid_has_volume(codec, nid, dir) \ | ||
2884 | (query_amp_caps(codec, nid, dir) & AC_AMPCAP_NUM_STEPS) | ||
2885 | |||
2886 | static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec, | ||
2887 | hda_nid_t pin, hda_nid_t dac) | ||
2888 | { | ||
2889 | hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac); | ||
2890 | if (nid_has_mute(codec, pin, HDA_OUTPUT)) | ||
2891 | return pin; | ||
2892 | else if (mix && nid_has_mute(codec, mix, HDA_INPUT)) | ||
2893 | return mix; | ||
2894 | else if (nid_has_mute(codec, dac, HDA_OUTPUT)) | ||
2895 | return dac; | ||
2896 | return 0; | ||
2897 | } | ||
2898 | |||
2899 | static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec, | ||
2900 | hda_nid_t pin, hda_nid_t dac) | ||
2901 | { | ||
2902 | hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac); | ||
2903 | if (nid_has_volume(codec, dac, HDA_OUTPUT)) | ||
2904 | return dac; | ||
2905 | else if (nid_has_volume(codec, mix, HDA_OUTPUT)) | ||
2906 | return mix; | ||
2907 | else if (nid_has_volume(codec, pin, HDA_OUTPUT)) | ||
2908 | return pin; | ||
2909 | return 0; | ||
2910 | } | ||
2911 | |||
2870 | /* add playback controls from the parsed DAC table */ | 2912 | /* add playback controls from the parsed DAC table */ |
2871 | static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, | 2913 | static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, |
2872 | const struct auto_pin_cfg *cfg) | 2914 | const struct auto_pin_cfg *cfg) |
2873 | { | 2915 | { |
2874 | struct alc_spec *spec = codec->spec; | 2916 | struct alc_spec *spec = codec->spec; |
2875 | hda_nid_t nid, mix, pin; | ||
2876 | int i, err, noutputs; | 2917 | int i, err, noutputs; |
2877 | 2918 | ||
2878 | noutputs = cfg->line_outs; | 2919 | noutputs = cfg->line_outs; |
@@ -2882,36 +2923,39 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
2882 | for (i = 0; i < noutputs; i++) { | 2923 | for (i = 0; i < noutputs; i++) { |
2883 | const char *name; | 2924 | const char *name; |
2884 | int index; | 2925 | int index; |
2885 | nid = spec->multiout.dac_nids[i]; | 2926 | hda_nid_t dac, pin; |
2886 | if (!nid) | 2927 | hda_nid_t sw, vol; |
2928 | |||
2929 | dac = spec->multiout.dac_nids[i]; | ||
2930 | if (!dac) | ||
2887 | continue; | 2931 | continue; |
2888 | if (i >= cfg->line_outs) | 2932 | if (i >= cfg->line_outs) |
2889 | pin = spec->multi_io[i - 1].pin; | 2933 | pin = spec->multi_io[i - 1].pin; |
2890 | else | 2934 | else |
2891 | pin = cfg->line_out_pins[i]; | 2935 | pin = cfg->line_out_pins[i]; |
2892 | mix = alc_auto_dac_to_mix(codec, pin, nid); | 2936 | |
2893 | if (!mix) | 2937 | sw = alc_look_for_out_mute_nid(codec, pin, dac); |
2894 | continue; | 2938 | vol = alc_look_for_out_vol_nid(codec, pin, dac); |
2895 | name = alc_get_line_out_pfx(spec, i, true, &index); | 2939 | name = alc_get_line_out_pfx(spec, i, true, &index); |
2896 | if (!name) { | 2940 | if (!name) { |
2897 | /* Center/LFE */ | 2941 | /* Center/LFE */ |
2898 | err = alc_auto_add_vol_ctl(codec, "Center", 0, nid, 1); | 2942 | err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1); |
2899 | if (err < 0) | 2943 | if (err < 0) |
2900 | return err; | 2944 | return err; |
2901 | err = alc_auto_add_vol_ctl(codec, "LFE", 0, nid, 2); | 2945 | err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2); |
2902 | if (err < 0) | 2946 | if (err < 0) |
2903 | return err; | 2947 | return err; |
2904 | err = alc_auto_add_sw_ctl(codec, "Center", 0, mix, 1); | 2948 | err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1); |
2905 | if (err < 0) | 2949 | if (err < 0) |
2906 | return err; | 2950 | return err; |
2907 | err = alc_auto_add_sw_ctl(codec, "LFE", 0, mix, 2); | 2951 | err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2); |
2908 | if (err < 0) | 2952 | if (err < 0) |
2909 | return err; | 2953 | return err; |
2910 | } else { | 2954 | } else { |
2911 | err = alc_auto_add_stereo_vol(codec, name, index, nid); | 2955 | err = alc_auto_add_stereo_vol(codec, name, index, vol); |
2912 | if (err < 0) | 2956 | if (err < 0) |
2913 | return err; | 2957 | return err; |
2914 | err = alc_auto_add_stereo_sw(codec, name, index, mix); | 2958 | err = alc_auto_add_stereo_sw(codec, name, index, sw); |
2915 | if (err < 0) | 2959 | if (err < 0) |
2916 | return err; | 2960 | return err; |
2917 | } | 2961 | } |
@@ -2924,7 +2968,7 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, | |||
2924 | hda_nid_t dac, const char *pfx) | 2968 | hda_nid_t dac, const char *pfx) |
2925 | { | 2969 | { |
2926 | struct alc_spec *spec = codec->spec; | 2970 | struct alc_spec *spec = codec->spec; |
2927 | hda_nid_t mix; | 2971 | hda_nid_t sw, vol; |
2928 | int err; | 2972 | int err; |
2929 | 2973 | ||
2930 | if (!pin) | 2974 | if (!pin) |
@@ -2938,13 +2982,12 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, | |||
2938 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); | 2982 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); |
2939 | } | 2983 | } |
2940 | 2984 | ||
2941 | mix = alc_auto_dac_to_mix(codec, pin, dac); | 2985 | sw = alc_look_for_out_mute_nid(codec, pin, dac); |
2942 | if (!mix) | 2986 | vol = alc_look_for_out_vol_nid(codec, pin, dac); |
2943 | return 0; | 2987 | err = alc_auto_add_stereo_vol(codec, pfx, 0, vol); |
2944 | err = alc_auto_add_stereo_vol(codec, pfx, 0, dac); | ||
2945 | if (err < 0) | 2988 | if (err < 0) |
2946 | return err; | 2989 | return err; |
2947 | err = alc_auto_add_stereo_sw(codec, pfx, 0, mix); | 2990 | err = alc_auto_add_stereo_sw(codec, pfx, 0, sw); |
2948 | if (err < 0) | 2991 | if (err < 0) |
2949 | return err; | 2992 | return err; |
2950 | return 0; | 2993 | return 0; |
@@ -2967,15 +3010,15 @@ static int alc_auto_create_speaker_out(struct hda_codec *codec) | |||
2967 | } | 3010 | } |
2968 | 3011 | ||
2969 | static void alc_auto_set_output_and_unmute(struct hda_codec *codec, | 3012 | static void alc_auto_set_output_and_unmute(struct hda_codec *codec, |
2970 | hda_nid_t nid, int pin_type, | 3013 | hda_nid_t pin, int pin_type, |
2971 | hda_nid_t dac) | 3014 | hda_nid_t dac) |
2972 | { | 3015 | { |
2973 | int i, num; | 3016 | int i, num; |
2974 | hda_nid_t mix = 0; | 3017 | hda_nid_t nid, mix = 0; |
2975 | hda_nid_t srcs[HDA_MAX_CONNECTIONS]; | 3018 | hda_nid_t srcs[HDA_MAX_CONNECTIONS]; |
2976 | 3019 | ||
2977 | alc_set_pin_output(codec, nid, pin_type); | 3020 | alc_set_pin_output(codec, pin, pin_type); |
2978 | nid = alc_go_down_to_selector(codec, nid); | 3021 | nid = alc_go_down_to_selector(codec, pin); |
2979 | num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs)); | 3022 | num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs)); |
2980 | for (i = 0; i < num; i++) { | 3023 | for (i = 0; i < num; i++) { |
2981 | if (alc_auto_mix_to_dac(codec, srcs[i]) != dac) | 3024 | if (alc_auto_mix_to_dac(codec, srcs[i]) != dac) |
@@ -2990,19 +3033,17 @@ static void alc_auto_set_output_and_unmute(struct hda_codec *codec, | |||
2990 | if (num > 1) | 3033 | if (num > 1) |
2991 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i); | 3034 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i); |
2992 | /* unmute mixer widget inputs */ | 3035 | /* unmute mixer widget inputs */ |
2993 | snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 3036 | if (nid_has_mute(codec, mix, HDA_INPUT)) { |
3037 | snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
2994 | AMP_IN_UNMUTE(0)); | 3038 | AMP_IN_UNMUTE(0)); |
2995 | snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 3039 | snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE, |
2996 | AMP_IN_UNMUTE(1)); | 3040 | AMP_IN_UNMUTE(1)); |
3041 | } | ||
2997 | /* initialize volume */ | 3042 | /* initialize volume */ |
2998 | if (query_amp_caps(codec, dac, HDA_OUTPUT) & AC_AMPCAP_NUM_STEPS) | 3043 | nid = alc_look_for_out_vol_nid(codec, pin, dac); |
2999 | nid = dac; | 3044 | if (nid) |
3000 | else if (query_amp_caps(codec, mix, HDA_OUTPUT) & AC_AMPCAP_NUM_STEPS) | 3045 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, |
3001 | nid = mix; | 3046 | AMP_OUT_ZERO); |
3002 | else | ||
3003 | return; | ||
3004 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
3005 | AMP_OUT_ZERO); | ||
3006 | } | 3047 | } |
3007 | 3048 | ||
3008 | static void alc_auto_init_multi_out(struct hda_codec *codec) | 3049 | static void alc_auto_init_multi_out(struct hda_codec *codec) |
@@ -6333,112 +6374,7 @@ static int patch_alc899(struct hda_codec *codec) | |||
6333 | /* | 6374 | /* |
6334 | * ALC680 support | 6375 | * ALC680 support |
6335 | */ | 6376 | */ |
6336 | /* create input playback/capture controls for the given pin */ | ||
6337 | static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid, | ||
6338 | const char *ctlname, int idx) | ||
6339 | { | ||
6340 | hda_nid_t dac; | ||
6341 | int err; | ||
6342 | |||
6343 | switch (nid) { | ||
6344 | case 0x14: | ||
6345 | dac = 0x02; | ||
6346 | break; | ||
6347 | case 0x15: | ||
6348 | dac = 0x03; | ||
6349 | break; | ||
6350 | case 0x16: | ||
6351 | dac = 0x04; | ||
6352 | break; | ||
6353 | default: | ||
6354 | return 0; | ||
6355 | } | ||
6356 | if (spec->multiout.dac_nids[0] != dac && | ||
6357 | spec->multiout.dac_nids[1] != dac) { | ||
6358 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, | ||
6359 | HDA_COMPOSE_AMP_VAL(dac, 3, idx, | ||
6360 | HDA_OUTPUT)); | ||
6361 | if (err < 0) | ||
6362 | return err; | ||
6363 | |||
6364 | err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, | ||
6365 | HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT)); | ||
6366 | |||
6367 | if (err < 0) | ||
6368 | return err; | ||
6369 | spec->private_dac_nids[spec->multiout.num_dacs++] = dac; | ||
6370 | } | ||
6371 | |||
6372 | return 0; | ||
6373 | } | ||
6374 | |||
6375 | /* add playback controls from the parsed DAC table */ | ||
6376 | static int alc680_auto_create_multi_out_ctls(struct alc_spec *spec, | ||
6377 | const struct auto_pin_cfg *cfg) | ||
6378 | { | ||
6379 | hda_nid_t nid; | ||
6380 | int err; | ||
6381 | |||
6382 | spec->multiout.dac_nids = spec->private_dac_nids; | ||
6383 | |||
6384 | nid = cfg->line_out_pins[0]; | ||
6385 | if (nid) { | ||
6386 | const char *name; | ||
6387 | int index; | ||
6388 | name = alc_get_line_out_pfx(spec, 0, true, &index); | ||
6389 | err = alc680_new_analog_output(spec, nid, name, 0); | ||
6390 | if (err < 0) | ||
6391 | return err; | ||
6392 | } | ||
6393 | |||
6394 | nid = cfg->speaker_pins[0]; | ||
6395 | if (nid) { | ||
6396 | err = alc680_new_analog_output(spec, nid, "Speaker", 0); | ||
6397 | if (err < 0) | ||
6398 | return err; | ||
6399 | } | ||
6400 | nid = cfg->hp_pins[0]; | ||
6401 | if (nid) { | ||
6402 | err = alc680_new_analog_output(spec, nid, "Headphone", 0); | ||
6403 | if (err < 0) | ||
6404 | return err; | ||
6405 | } | ||
6406 | |||
6407 | return 0; | ||
6408 | } | ||
6409 | |||
6410 | static void alc680_auto_set_output_and_unmute(struct hda_codec *codec, | ||
6411 | hda_nid_t nid, int pin_type) | ||
6412 | { | ||
6413 | alc_set_pin_output(codec, nid, pin_type); | ||
6414 | } | ||
6415 | 6377 | ||
6416 | static void alc680_auto_init_multi_out(struct hda_codec *codec) | ||
6417 | { | ||
6418 | struct alc_spec *spec = codec->spec; | ||
6419 | hda_nid_t nid = spec->autocfg.line_out_pins[0]; | ||
6420 | if (nid) { | ||
6421 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
6422 | alc680_auto_set_output_and_unmute(codec, nid, pin_type); | ||
6423 | } | ||
6424 | } | ||
6425 | |||
6426 | static void alc680_auto_init_hp_out(struct hda_codec *codec) | ||
6427 | { | ||
6428 | struct alc_spec *spec = codec->spec; | ||
6429 | hda_nid_t pin; | ||
6430 | |||
6431 | pin = spec->autocfg.hp_pins[0]; | ||
6432 | if (pin) | ||
6433 | alc680_auto_set_output_and_unmute(codec, pin, PIN_HP); | ||
6434 | pin = spec->autocfg.speaker_pins[0]; | ||
6435 | if (pin) | ||
6436 | alc680_auto_set_output_and_unmute(codec, pin, PIN_OUT); | ||
6437 | } | ||
6438 | |||
6439 | /* | ||
6440 | * BIOS auto configuration | ||
6441 | */ | ||
6442 | static int alc680_parse_auto_config(struct hda_codec *codec) | 6378 | static int alc680_parse_auto_config(struct hda_codec *codec) |
6443 | { | 6379 | { |
6444 | struct alc_spec *spec = codec->spec; | 6380 | struct alc_spec *spec = codec->spec; |
@@ -6458,7 +6394,20 @@ static int alc680_parse_auto_config(struct hda_codec *codec) | |||
6458 | } | 6394 | } |
6459 | return 0; /* can't find valid BIOS pin config */ | 6395 | return 0; /* can't find valid BIOS pin config */ |
6460 | } | 6396 | } |
6461 | err = alc680_auto_create_multi_out_ctls(spec, &spec->autocfg); | 6397 | |
6398 | err = alc_auto_fill_dac_nids(codec); | ||
6399 | if (err < 0) | ||
6400 | return err; | ||
6401 | |||
6402 | err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg); | ||
6403 | if (err < 0) | ||
6404 | return err; | ||
6405 | |||
6406 | err = alc_auto_create_hp_out(codec); | ||
6407 | if (err < 0) | ||
6408 | return err; | ||
6409 | |||
6410 | err = alc_auto_create_speaker_out(codec); | ||
6462 | if (err < 0) | 6411 | if (err < 0) |
6463 | return err; | 6412 | return err; |
6464 | 6413 | ||
@@ -6489,8 +6438,8 @@ static int alc680_parse_auto_config(struct hda_codec *codec) | |||
6489 | static void alc680_auto_init(struct hda_codec *codec) | 6438 | static void alc680_auto_init(struct hda_codec *codec) |
6490 | { | 6439 | { |
6491 | struct alc_spec *spec = codec->spec; | 6440 | struct alc_spec *spec = codec->spec; |
6492 | alc680_auto_init_multi_out(codec); | 6441 | alc_auto_init_multi_out(codec); |
6493 | alc680_auto_init_hp_out(codec); | 6442 | alc_auto_init_extra_out(codec); |
6494 | alc_auto_init_analog_input(codec); | 6443 | alc_auto_init_analog_input(codec); |
6495 | alc_auto_init_input_src(codec); | 6444 | alc_auto_init_input_src(codec); |
6496 | alc_auto_init_digital(codec); | 6445 | alc_auto_init_digital(codec); |