aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-12-12 11:25:00 -0500
committerTakashi Iwai <tiwai@suse.de>2013-01-10 04:34:28 -0500
commit36f0fd540e299c7746601ce7bff7d062a6757c2f (patch)
treeacb79e5ba74c7f83f10d6b9e81619fd1aa7762ee /sound/pci/hda/patch_realtek.c
parent95e960cece76cb538fcac03ac80893db0f1e6a15 (diff)
ALSA: hda/realtek - Parse input paths
Just like the output paths, parse the whole paths for inputs as well and store in a path list. For that purpose, rewrite the output parser code to be generically usable. The input path list is not referred at all in this patch. It'll be used to replace the fixed adc/capsrc array in later patches for more flexible input path selections. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r--sound/pci/hda/patch_realtek.c103
1 files changed, 73 insertions, 30 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 434856376bf0..fbc4a97ea8f6 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -101,7 +101,11 @@ enum {
101 101
102#define MAX_NID_PATH_DEPTH 5 102#define MAX_NID_PATH_DEPTH 5
103 103
104/* output-path: DAC -> ... -> pin 104/* Widget connection path
105 *
106 * For output, stored in the order of DAC -> ... -> pin,
107 * for input, pin -> ... -> ADC.
108 *
105 * idx[i] contains the source index number to select on of the widget path[i]; 109 * idx[i] contains the source index number to select on of the widget path[i];
106 * e.g. idx[1] is the index of the DAC (path[0]) selected by path[1] widget 110 * e.g. idx[1] is the index of the DAC (path[0]) selected by path[1] widget
107 * multi[] indicates whether it's a selector widget with multi-connectors 111 * multi[] indicates whether it's a selector widget with multi-connectors
@@ -196,6 +200,9 @@ struct alc_spec {
196 /* output paths */ 200 /* output paths */
197 struct snd_array out_path; 201 struct snd_array out_path;
198 202
203 /* input paths */
204 struct snd_array in_path;
205
199 /* hooks */ 206 /* hooks */
200 void (*init_hook)(struct hda_codec *codec); 207 void (*init_hook)(struct hda_codec *codec);
201#ifdef CONFIG_PM 208#ifdef CONFIG_PM
@@ -2428,6 +2435,7 @@ static void alc_free(struct hda_codec *codec)
2428 alc_free_kctls(codec); 2435 alc_free_kctls(codec);
2429 alc_free_bind_ctls(codec); 2436 alc_free_bind_ctls(codec);
2430 snd_array_free(&spec->out_path); 2437 snd_array_free(&spec->out_path);
2438 snd_array_free(&spec->in_path);
2431 snd_hda_gen_free(&spec->gen); 2439 snd_hda_gen_free(&spec->gen);
2432 kfree(spec); 2440 kfree(spec);
2433 snd_hda_detach_beep_device(codec); 2441 snd_hda_detach_beep_device(codec);
@@ -2628,6 +2636,10 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
2628 return channel_name[ch]; 2636 return channel_name[ch];
2629} 2637}
2630 2638
2639static bool parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
2640 hda_nid_t to_nid, int with_aa_mix,
2641 struct nid_path *path);
2642
2631#ifdef CONFIG_PM 2643#ifdef CONFIG_PM
2632/* add the powersave loopback-list entry */ 2644/* add the powersave loopback-list entry */
2633static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx) 2645static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx)
@@ -2666,6 +2678,28 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
2666 return 0; 2678 return 0;
2667} 2679}
2668 2680
2681static int new_capture_source(struct hda_codec *codec, int adc_idx,
2682 hda_nid_t pin, int idx, const char *label)
2683{
2684 struct alc_spec *spec = codec->spec;
2685 struct hda_input_mux *imux = &spec->private_imux[0];
2686 struct nid_path *path;
2687
2688 path = snd_array_new(&spec->in_path);
2689 if (!path)
2690 return -ENOMEM;
2691 memset(path, 0, sizeof(*path));
2692 if (!parse_nid_path(codec, pin, spec->adc_nids[adc_idx], 2, path)) {
2693 snd_printd(KERN_ERR "invalid input path 0x%x -> 0x%x\n",
2694 pin, spec->adc_nids[adc_idx]);
2695 return -EINVAL;
2696 }
2697
2698 spec->imux_pins[imux->num_items] = pin;
2699 snd_hda_add_imux_item(imux, label, idx, NULL);
2700 return 0;
2701}
2702
2669static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid) 2703static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
2670{ 2704{
2671 unsigned int pincap = snd_hda_query_pin_caps(codec, nid); 2705 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
@@ -2767,8 +2801,9 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
2767 hda_nid_t cap = get_capsrc(spec, c); 2801 hda_nid_t cap = get_capsrc(spec, c);
2768 idx = get_connection_index(codec, cap, pin); 2802 idx = get_connection_index(codec, cap, pin);
2769 if (idx >= 0) { 2803 if (idx >= 0) {
2770 spec->imux_pins[imux->num_items] = pin; 2804 err = new_capture_source(codec, c, pin, idx, label);
2771 snd_hda_add_imux_item(imux, label, idx, NULL); 2805 if (err < 0)
2806 return err;
2772 break; 2807 break;
2773 } 2808 }
2774 } 2809 }
@@ -2897,40 +2932,45 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
2897} 2932}
2898 2933
2899/* called recursively */ 2934/* called recursively */
2900static bool __parse_output_path(struct hda_codec *codec, hda_nid_t nid, 2935static bool __parse_nid_path(struct hda_codec *codec,
2901 hda_nid_t target_dac, int with_aa_mix, 2936 hda_nid_t from_nid, hda_nid_t to_nid,
2902 struct nid_path *path, int depth) 2937 int with_aa_mix, struct nid_path *path, int depth)
2903{ 2938{
2904 struct alc_spec *spec = codec->spec; 2939 struct alc_spec *spec = codec->spec;
2905 hda_nid_t conn[8]; 2940 hda_nid_t conn[16];
2906 int i, nums; 2941 int i, nums;
2907 2942
2908 if (nid == spec->mixer_nid) { 2943 if (to_nid == spec->mixer_nid) {
2909 if (!with_aa_mix) 2944 if (!with_aa_mix)
2910 return false; 2945 return false;
2911 with_aa_mix = 2; /* mark aa-mix is included */ 2946 with_aa_mix = 2; /* mark aa-mix is included */
2912 } 2947 }
2913 2948
2914 nums = snd_hda_get_connections(codec, nid, conn, ARRAY_SIZE(conn)); 2949 nums = snd_hda_get_connections(codec, to_nid, conn, ARRAY_SIZE(conn));
2915 for (i = 0; i < nums; i++) { 2950 for (i = 0; i < nums; i++) {
2916 if (get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT) 2951 if (conn[i] != from_nid) {
2917 continue; 2952 /* special case: when from_nid is 0,
2918 if (conn[i] == target_dac || 2953 * try to find an empty DAC
2919 (!target_dac && !alc_is_dac_already_used(codec, conn[i]))) { 2954 */
2920 /* aa-mix is requested but not included? */ 2955 if (from_nid ||
2921 if (!(spec->mixer_nid && with_aa_mix == 1)) 2956 get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
2922 goto found; 2957 alc_is_dac_already_used(codec, conn[i]))
2958 continue;
2923 } 2959 }
2960 /* aa-mix is requested but not included? */
2961 if (!(spec->mixer_nid && with_aa_mix == 1))
2962 goto found;
2924 } 2963 }
2925 if (depth >= MAX_NID_PATH_DEPTH) 2964 if (depth >= MAX_NID_PATH_DEPTH)
2926 return false; 2965 return false;
2927 for (i = 0; i < nums; i++) { 2966 for (i = 0; i < nums; i++) {
2928 unsigned int type; 2967 unsigned int type;
2929 type = get_wcaps_type(get_wcaps(codec, conn[i])); 2968 type = get_wcaps_type(get_wcaps(codec, conn[i]));
2930 if (type == AC_WID_AUD_OUT) 2969 if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
2970 type == AC_WID_PIN)
2931 continue; 2971 continue;
2932 if (__parse_output_path(codec, conn[i], target_dac, 2972 if (__parse_nid_path(codec, from_nid, conn[i],
2933 with_aa_mix, path, depth + 1)) 2973 with_aa_mix, path, depth + 1))
2934 goto found; 2974 goto found;
2935 } 2975 }
2936 return false; 2976 return false;
@@ -2938,25 +2978,27 @@ static bool __parse_output_path(struct hda_codec *codec, hda_nid_t nid,
2938 found: 2978 found:
2939 path->path[path->depth] = conn[i]; 2979 path->path[path->depth] = conn[i];
2940 path->idx[path->depth + 1] = i; 2980 path->idx[path->depth + 1] = i;
2941 if (nums > 1 && get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_MIX) 2981 if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
2942 path->multi[path->depth + 1] = 1; 2982 path->multi[path->depth + 1] = 1;
2943 path->depth++; 2983 path->depth++;
2944 return true; 2984 return true;
2945} 2985}
2946 2986
2947/* parse the output path from the given nid to the target DAC; 2987/* parse the widget path from the given nid to the target nid;
2948 * when target_dac is 0, try to find an empty DAC; 2988 * when @from_nid is 0, try to find an empty DAC;
2949 * when with_aa_mix is 0, paths with spec->mixer_nid are excluded 2989 * when @with_aa_mix is 0, paths with spec->mixer_nid are excluded.
2990 * when @with_aa_mix is 1, paths without spec->mixer_nid are excluded.
2991 * when @with_aa_mix is 2, no special handling about spec->mixer_nid.
2950 */ 2992 */
2951static bool parse_output_path(struct hda_codec *codec, hda_nid_t nid, 2993static bool parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
2952 hda_nid_t target_dac, int with_aa_mix, 2994 hda_nid_t to_nid, int with_aa_mix,
2953 struct nid_path *path) 2995 struct nid_path *path)
2954{ 2996{
2955 if (__parse_output_path(codec, nid, target_dac, with_aa_mix, path, 1)) { 2997 if (__parse_nid_path(codec, from_nid, to_nid, with_aa_mix, path, 1)) {
2956 path->path[path->depth] = nid; 2998 path->path[path->depth] = to_nid;
2957 path->depth++; 2999 path->depth++;
2958#if 0 3000#if 0
2959 snd_printdd("output-path: depth=%d, %02x/%02x/%02x/%02x/%02x\n", 3001 snd_printdd("path: depth=%d, %02x/%02x/%02x/%02x/%02x\n",
2960 path->depth, path->path[0], path->path[1], 3002 path->depth, path->path[0], path->path[1],
2961 path->path[2], path->path[3], path->path[4]); 3003 path->path[2], path->path[3], path->path[4]);
2962#endif 3004#endif
@@ -3034,7 +3076,7 @@ static bool add_new_out_path(struct hda_codec *codec, hda_nid_t pin,
3034 if (!path) 3076 if (!path)
3035 return false; 3077 return false;
3036 memset(path, 0, sizeof(*path)); 3078 memset(path, 0, sizeof(*path));
3037 if (parse_output_path(codec, pin, dac, 0, path)) 3079 if (parse_nid_path(codec, dac, pin, 0, path))
3038 return true; 3080 return true;
3039 /* push back */ 3081 /* push back */
3040 spec->out_path.used--; 3082 spec->out_path.used--;
@@ -4529,6 +4571,7 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
4529 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); 4571 snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
4530 snd_array_init(&spec->bind_ctls, sizeof(struct hda_bind_ctls *), 8); 4572 snd_array_init(&spec->bind_ctls, sizeof(struct hda_bind_ctls *), 8);
4531 snd_array_init(&spec->out_path, sizeof(struct nid_path), 8); 4573 snd_array_init(&spec->out_path, sizeof(struct nid_path), 8);
4574 snd_array_init(&spec->in_path, sizeof(struct nid_path), 8);
4532 4575
4533 err = alc_codec_rename_from_preset(codec); 4576 err = alc_codec_rename_from_preset(codec);
4534 if (err < 0) { 4577 if (err < 0) {