aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r--sound/pci/hda/patch_realtek.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 011644b7c2d1..8f93b97559a5 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -116,6 +116,8 @@ struct alc_spec {
116 const hda_nid_t *capsrc_nids; 116 const hda_nid_t *capsrc_nids;
117 hda_nid_t dig_in_nid; /* digital-in NID; optional */ 117 hda_nid_t dig_in_nid; /* digital-in NID; optional */
118 hda_nid_t mixer_nid; /* analog-mixer NID */ 118 hda_nid_t mixer_nid; /* analog-mixer NID */
119 DECLARE_BITMAP(vol_ctls, 0x20 << 1);
120 DECLARE_BITMAP(sw_ctls, 0x20 << 1);
119 121
120 /* capture setup for dynamic dual-adc switch */ 122 /* capture setup for dynamic dual-adc switch */
121 hda_nid_t cur_adc; 123 hda_nid_t cur_adc;
@@ -3006,14 +3008,32 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
3006 return 0; 3008 return 0;
3007} 3009}
3008 3010
3011static inline unsigned int get_ctl_pos(unsigned int data)
3012{
3013 hda_nid_t nid = get_amp_nid_(data);
3014 unsigned int dir = get_amp_direction_(data);
3015 return (nid << 1) | dir;
3016}
3017
3018#define is_ctl_used(bits, data) \
3019 test_bit(get_ctl_pos(data), bits)
3020#define mark_ctl_usage(bits, data) \
3021 set_bit(get_ctl_pos(data), bits)
3022
3009static int alc_auto_add_vol_ctl(struct hda_codec *codec, 3023static int alc_auto_add_vol_ctl(struct hda_codec *codec,
3010 const char *pfx, int cidx, 3024 const char *pfx, int cidx,
3011 hda_nid_t nid, unsigned int chs) 3025 hda_nid_t nid, unsigned int chs)
3012{ 3026{
3027 struct alc_spec *spec = codec->spec;
3028 unsigned int val;
3013 if (!nid) 3029 if (!nid)
3014 return 0; 3030 return 0;
3031 val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
3032 if (is_ctl_used(spec->vol_ctls, val) && chs != 2) /* exclude LFE */
3033 return 0;
3034 mark_ctl_usage(spec->vol_ctls, val);
3015 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx, 3035 return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
3016 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); 3036 val);
3017} 3037}
3018 3038
3019#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \ 3039#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
@@ -3026,6 +3046,7 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec,
3026 const char *pfx, int cidx, 3046 const char *pfx, int cidx,
3027 hda_nid_t nid, unsigned int chs) 3047 hda_nid_t nid, unsigned int chs)
3028{ 3048{
3049 struct alc_spec *spec = codec->spec;
3029 int wid_type; 3050 int wid_type;
3030 int type; 3051 int type;
3031 unsigned long val; 3052 unsigned long val;
@@ -3042,6 +3063,9 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec,
3042 type = ALC_CTL_BIND_MUTE; 3063 type = ALC_CTL_BIND_MUTE;
3043 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT); 3064 val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
3044 } 3065 }
3066 if (is_ctl_used(spec->sw_ctls, val) && chs != 2) /* exclude LFE */
3067 return 0;
3068 mark_ctl_usage(spec->sw_ctls, val);
3045 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val); 3069 return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
3046} 3070}
3047 3071
@@ -3136,12 +3160,16 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
3136 int err; 3160 int err;
3137 3161
3138 if (!dac) { 3162 if (!dac) {
3163 unsigned int val;
3139 /* the corresponding DAC is already occupied */ 3164 /* the corresponding DAC is already occupied */
3140 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)) 3165 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
3141 return 0; /* no way */ 3166 return 0; /* no way */
3142 /* create a switch only */ 3167 /* create a switch only */
3143 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, 3168 val = HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT);
3144 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); 3169 if (is_ctl_used(spec->sw_ctls, val))
3170 return 0; /* already created */
3171 mark_ctl_usage(spec->sw_ctls, val);
3172 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val);
3145 } 3173 }
3146 3174
3147 sw = alc_look_for_out_mute_nid(codec, pin, dac); 3175 sw = alc_look_for_out_mute_nid(codec, pin, dac);
@@ -3186,8 +3214,12 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins,
3186 if (!num_pins || !pins[0]) 3214 if (!num_pins || !pins[0])
3187 return 0; 3215 return 0;
3188 3216
3189 if (num_pins == 1) 3217 if (num_pins == 1) {
3190 return alc_auto_create_extra_out(codec, *pins, *dacs, pfx); 3218 hda_nid_t dac = *dacs;
3219 if (!dac)
3220 dac = spec->multiout.dac_nids[0];
3221 return alc_auto_create_extra_out(codec, *pins, dac, pfx);
3222 }
3191 3223
3192 if (dacs[num_pins - 1]) { 3224 if (dacs[num_pins - 1]) {
3193 /* OK, we have a multi-output system with individual volumes */ 3225 /* OK, we have a multi-output system with individual volumes */