Loading sound/pci/hda/hda_local.h +2 −1 Original line number Diff line number Diff line Loading @@ -600,7 +600,8 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, #define get_amp_nid_(pv) ((pv) & 0xffff) #define get_amp_nid(kc) get_amp_nid_((kc)->private_value) #define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) #define get_amp_direction_(pv) (((pv) >> 18) & 0x1) #define get_amp_direction(kc) get_amp_direction_((kc)->private_value) #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) #define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) #define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1) Loading sound/pci/hda/patch_conexant.c +49 −23 Original line number Diff line number Diff line Loading @@ -136,6 +136,8 @@ struct conexant_spec { unsigned int thinkpad:1; unsigned int hp_laptop:1; unsigned int asus:1; unsigned int pin_eapd_ctrls:1; unsigned int single_adc_amp:1; unsigned int adc_switching:1; Loading Loading @@ -3430,11 +3432,13 @@ static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins, static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins, bool on) { struct conexant_spec *spec = codec->spec; int i; for (i = 0; i < num_pins; i++) snd_hda_codec_write(codec, pins[i], 0, AC_VERB_SET_PIN_WIDGET_CONTROL, on ? PIN_OUT : 0); if (spec->pin_eapd_ctrls) cx_auto_turn_eapd(codec, num_pins, pins, on); } Loading @@ -3460,9 +3464,12 @@ static void cx_auto_update_speakers(struct hda_codec *codec) int on = 1; /* turn on HP EAPD when HP jacks are present */ if (spec->pin_eapd_ctrls) { if (spec->auto_mute) on = spec->hp_present; cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on); } /* mute speakers in auto-mode if HP or LO jacks are plugged */ if (spec->auto_mute) on = !(spec->hp_present || Loading Loading @@ -3889,20 +3896,10 @@ static void cx_auto_parse_beep(struct hda_codec *codec) #define cx_auto_parse_beep(codec) #endif static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) { int i; for (i = 0; i < nums; i++) if (list[i] == nid) return true; return false; } /* parse extra-EAPD that aren't assigned to any pins */ /* parse EAPDs */ static void cx_auto_parse_eapd(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; hda_nid_t nid, end_nid; end_nid = codec->start_nid + codec->num_nodes; Loading @@ -3911,14 +3908,18 @@ static void cx_auto_parse_eapd(struct hda_codec *codec) continue; if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) continue; if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) || found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) || found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs)) continue; spec->eapds[spec->num_eapds++] = nid; if (spec->num_eapds >= ARRAY_SIZE(spec->eapds)) break; } /* NOTE: below is a wild guess; if we have more than two EAPDs, * it's a new chip, where EAPDs are supposed to be associated to * pins, and we can control EAPD per pin. * OTOH, if only one or two EAPDs are found, it's an old chip, * thus it might control over all pins. */ spec->pin_eapd_ctrls = spec->num_eapds > 2; } static int cx_auto_parse_auto_config(struct hda_codec *codec) Loading Loading @@ -4024,7 +4025,8 @@ static void cx_auto_init_output(struct hda_codec *codec) } } cx_auto_update_speakers(codec); /* turn on/off extra EAPDs, too */ /* turn on all EAPDs if no individual EAPD control is available */ if (!spec->pin_eapd_ctrls) cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); } Loading Loading @@ -4212,6 +4214,8 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, int idx = get_input_connection(codec, adc_nid, nid); if (idx < 0) continue; if (spec->single_adc_amp) idx = 0; return cx_auto_add_volume_idx(codec, label, pfx, cidx, adc_nid, HDA_INPUT, idx); } Loading Loading @@ -4252,14 +4256,21 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) struct hda_input_mux *imux = &spec->private_imux; const char *prev_label; int input_conn[HDA_MAX_NUM_INPUTS]; int i, err, cidx; int i, j, err, cidx; int multi_connection; if (!imux->num_items) return 0; multi_connection = 0; for (i = 0; i < imux->num_items; i++) { cidx = get_input_connection(codec, spec->imux_info[i].adc, spec->imux_info[i].pin); input_conn[i] = (spec->imux_info[i].adc << 8) | cidx; if (cidx < 0) continue; input_conn[i] = spec->imux_info[i].adc; if (!spec->single_adc_amp) input_conn[i] |= cidx << 8; if (i > 0 && input_conn[i] != input_conn[0]) multi_connection = 1; } Loading Loading @@ -4288,6 +4299,15 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) err = cx_auto_add_capture_volume(codec, nid, "Capture", "", cidx); } else { bool dup_found = false; for (j = 0; j < i; j++) { if (input_conn[j] == input_conn[i]) { dup_found = true; break; } } if (dup_found) continue; err = cx_auto_add_capture_volume(codec, nid, label, " Capture", cidx); } Loading Loading @@ -4412,6 +4432,12 @@ static int patch_conexant_auto(struct hda_codec *codec) codec->spec = spec; codec->pin_amp_workaround = 1; switch (codec->vendor_id) { case 0x14f15045: spec->single_adc_amp = 1; break; } apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); err = cx_auto_search_adcs(codec); Loading sound/pci/hda/patch_realtek.c +37 −5 Original line number Diff line number Diff line Loading @@ -116,6 +116,8 @@ struct alc_spec { const hda_nid_t *capsrc_nids; hda_nid_t dig_in_nid; /* digital-in NID; optional */ hda_nid_t mixer_nid; /* analog-mixer NID */ DECLARE_BITMAP(vol_ctls, 0x20 << 1); DECLARE_BITMAP(sw_ctls, 0x20 << 1); /* capture setup for dynamic dual-adc switch */ hda_nid_t cur_adc; Loading Loading @@ -3006,14 +3008,32 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) return 0; } static inline unsigned int get_ctl_pos(unsigned int data) { hda_nid_t nid = get_amp_nid_(data); unsigned int dir = get_amp_direction_(data); return (nid << 1) | dir; } #define is_ctl_used(bits, data) \ test_bit(get_ctl_pos(data), bits) #define mark_ctl_usage(bits, data) \ set_bit(get_ctl_pos(data), bits) static int alc_auto_add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx, hda_nid_t nid, unsigned int chs) { struct alc_spec *spec = codec->spec; unsigned int val; if (!nid) return 0; val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT); if (is_ctl_used(spec->vol_ctls, val) && chs != 2) /* exclude LFE */ return 0; mark_ctl_usage(spec->vol_ctls, val); return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx, HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); val); } #define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \ Loading @@ -3026,6 +3046,7 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx, hda_nid_t nid, unsigned int chs) { struct alc_spec *spec = codec->spec; int wid_type; int type; unsigned long val; Loading @@ -3042,6 +3063,9 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec, type = ALC_CTL_BIND_MUTE; val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT); } if (is_ctl_used(spec->sw_ctls, val) && chs != 2) /* exclude LFE */ return 0; mark_ctl_usage(spec->sw_ctls, val); return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val); } Loading Loading @@ -3136,12 +3160,16 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, int err; if (!dac) { unsigned int val; /* the corresponding DAC is already occupied */ if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)) return 0; /* no way */ /* create a switch only */ return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); val = HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT); if (is_ctl_used(spec->sw_ctls, val)) return 0; /* already created */ mark_ctl_usage(spec->sw_ctls, val); return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val); } sw = alc_look_for_out_mute_nid(codec, pin, dac); Loading Loading @@ -3186,8 +3214,12 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, if (!num_pins || !pins[0]) return 0; if (num_pins == 1) return alc_auto_create_extra_out(codec, *pins, *dacs, pfx); if (num_pins == 1) { hda_nid_t dac = *dacs; if (!dac) dac = spec->multiout.dac_nids[0]; return alc_auto_create_extra_out(codec, *pins, dac, pfx); } if (dacs[num_pins - 1]) { /* OK, we have a multi-output system with individual volumes */ Loading Loading
sound/pci/hda/hda_local.h +2 −1 Original line number Diff line number Diff line Loading @@ -600,7 +600,8 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, #define get_amp_nid_(pv) ((pv) & 0xffff) #define get_amp_nid(kc) get_amp_nid_((kc)->private_value) #define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) #define get_amp_direction_(pv) (((pv) >> 18) & 0x1) #define get_amp_direction(kc) get_amp_direction_((kc)->private_value) #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) #define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) #define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1) Loading
sound/pci/hda/patch_conexant.c +49 −23 Original line number Diff line number Diff line Loading @@ -136,6 +136,8 @@ struct conexant_spec { unsigned int thinkpad:1; unsigned int hp_laptop:1; unsigned int asus:1; unsigned int pin_eapd_ctrls:1; unsigned int single_adc_amp:1; unsigned int adc_switching:1; Loading Loading @@ -3430,11 +3432,13 @@ static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins, static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins, bool on) { struct conexant_spec *spec = codec->spec; int i; for (i = 0; i < num_pins; i++) snd_hda_codec_write(codec, pins[i], 0, AC_VERB_SET_PIN_WIDGET_CONTROL, on ? PIN_OUT : 0); if (spec->pin_eapd_ctrls) cx_auto_turn_eapd(codec, num_pins, pins, on); } Loading @@ -3460,9 +3464,12 @@ static void cx_auto_update_speakers(struct hda_codec *codec) int on = 1; /* turn on HP EAPD when HP jacks are present */ if (spec->pin_eapd_ctrls) { if (spec->auto_mute) on = spec->hp_present; cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on); } /* mute speakers in auto-mode if HP or LO jacks are plugged */ if (spec->auto_mute) on = !(spec->hp_present || Loading Loading @@ -3889,20 +3896,10 @@ static void cx_auto_parse_beep(struct hda_codec *codec) #define cx_auto_parse_beep(codec) #endif static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) { int i; for (i = 0; i < nums; i++) if (list[i] == nid) return true; return false; } /* parse extra-EAPD that aren't assigned to any pins */ /* parse EAPDs */ static void cx_auto_parse_eapd(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; hda_nid_t nid, end_nid; end_nid = codec->start_nid + codec->num_nodes; Loading @@ -3911,14 +3908,18 @@ static void cx_auto_parse_eapd(struct hda_codec *codec) continue; if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) continue; if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) || found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) || found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs)) continue; spec->eapds[spec->num_eapds++] = nid; if (spec->num_eapds >= ARRAY_SIZE(spec->eapds)) break; } /* NOTE: below is a wild guess; if we have more than two EAPDs, * it's a new chip, where EAPDs are supposed to be associated to * pins, and we can control EAPD per pin. * OTOH, if only one or two EAPDs are found, it's an old chip, * thus it might control over all pins. */ spec->pin_eapd_ctrls = spec->num_eapds > 2; } static int cx_auto_parse_auto_config(struct hda_codec *codec) Loading Loading @@ -4024,7 +4025,8 @@ static void cx_auto_init_output(struct hda_codec *codec) } } cx_auto_update_speakers(codec); /* turn on/off extra EAPDs, too */ /* turn on all EAPDs if no individual EAPD control is available */ if (!spec->pin_eapd_ctrls) cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); } Loading Loading @@ -4212,6 +4214,8 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, int idx = get_input_connection(codec, adc_nid, nid); if (idx < 0) continue; if (spec->single_adc_amp) idx = 0; return cx_auto_add_volume_idx(codec, label, pfx, cidx, adc_nid, HDA_INPUT, idx); } Loading Loading @@ -4252,14 +4256,21 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) struct hda_input_mux *imux = &spec->private_imux; const char *prev_label; int input_conn[HDA_MAX_NUM_INPUTS]; int i, err, cidx; int i, j, err, cidx; int multi_connection; if (!imux->num_items) return 0; multi_connection = 0; for (i = 0; i < imux->num_items; i++) { cidx = get_input_connection(codec, spec->imux_info[i].adc, spec->imux_info[i].pin); input_conn[i] = (spec->imux_info[i].adc << 8) | cidx; if (cidx < 0) continue; input_conn[i] = spec->imux_info[i].adc; if (!spec->single_adc_amp) input_conn[i] |= cidx << 8; if (i > 0 && input_conn[i] != input_conn[0]) multi_connection = 1; } Loading Loading @@ -4288,6 +4299,15 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) err = cx_auto_add_capture_volume(codec, nid, "Capture", "", cidx); } else { bool dup_found = false; for (j = 0; j < i; j++) { if (input_conn[j] == input_conn[i]) { dup_found = true; break; } } if (dup_found) continue; err = cx_auto_add_capture_volume(codec, nid, label, " Capture", cidx); } Loading Loading @@ -4412,6 +4432,12 @@ static int patch_conexant_auto(struct hda_codec *codec) codec->spec = spec; codec->pin_amp_workaround = 1; switch (codec->vendor_id) { case 0x14f15045: spec->single_adc_amp = 1; break; } apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); err = cx_auto_search_adcs(codec); Loading
sound/pci/hda/patch_realtek.c +37 −5 Original line number Diff line number Diff line Loading @@ -116,6 +116,8 @@ struct alc_spec { const hda_nid_t *capsrc_nids; hda_nid_t dig_in_nid; /* digital-in NID; optional */ hda_nid_t mixer_nid; /* analog-mixer NID */ DECLARE_BITMAP(vol_ctls, 0x20 << 1); DECLARE_BITMAP(sw_ctls, 0x20 << 1); /* capture setup for dynamic dual-adc switch */ hda_nid_t cur_adc; Loading Loading @@ -3006,14 +3008,32 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) return 0; } static inline unsigned int get_ctl_pos(unsigned int data) { hda_nid_t nid = get_amp_nid_(data); unsigned int dir = get_amp_direction_(data); return (nid << 1) | dir; } #define is_ctl_used(bits, data) \ test_bit(get_ctl_pos(data), bits) #define mark_ctl_usage(bits, data) \ set_bit(get_ctl_pos(data), bits) static int alc_auto_add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx, hda_nid_t nid, unsigned int chs) { struct alc_spec *spec = codec->spec; unsigned int val; if (!nid) return 0; val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT); if (is_ctl_used(spec->vol_ctls, val) && chs != 2) /* exclude LFE */ return 0; mark_ctl_usage(spec->vol_ctls, val); return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx, HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); val); } #define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \ Loading @@ -3026,6 +3046,7 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx, hda_nid_t nid, unsigned int chs) { struct alc_spec *spec = codec->spec; int wid_type; int type; unsigned long val; Loading @@ -3042,6 +3063,9 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec, type = ALC_CTL_BIND_MUTE; val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT); } if (is_ctl_used(spec->sw_ctls, val) && chs != 2) /* exclude LFE */ return 0; mark_ctl_usage(spec->sw_ctls, val); return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val); } Loading Loading @@ -3136,12 +3160,16 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, int err; if (!dac) { unsigned int val; /* the corresponding DAC is already occupied */ if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)) return 0; /* no way */ /* create a switch only */ return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); val = HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT); if (is_ctl_used(spec->sw_ctls, val)) return 0; /* already created */ mark_ctl_usage(spec->sw_ctls, val); return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val); } sw = alc_look_for_out_mute_nid(codec, pin, dac); Loading Loading @@ -3186,8 +3214,12 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, if (!num_pins || !pins[0]) return 0; if (num_pins == 1) return alc_auto_create_extra_out(codec, *pins, *dacs, pfx); if (num_pins == 1) { hda_nid_t dac = *dacs; if (!dac) dac = spec->multiout.dac_nids[0]; return alc_auto_create_extra_out(codec, *pins, dac, pfx); } if (dacs[num_pins - 1]) { /* OK, we have a multi-output system with individual volumes */ Loading