diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-10-27 11:06:43 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-10-27 11:06:43 -0400 |
commit | 8128c9f21509f9a8b6da94ac432d845dda458406 (patch) | |
tree | 587b5e785571ac7630c7f2b31cbbca6e70cc0d4b /sound | |
parent | bb14eb0da72afb69be261b28ec858cbd5a35e089 (diff) | |
parent | 6b45214277bec2193ad3ccb8d7aa6100b5a0f1a9 (diff) |
Merge branch 'topic/hda' into for-linus
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_local.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 72 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 42 |
3 files changed, 88 insertions, 29 deletions
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 46c581c3fa84..81e12c0ed0a2 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -600,7 +600,8 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, | |||
600 | #define get_amp_nid_(pv) ((pv) & 0xffff) | 600 | #define get_amp_nid_(pv) ((pv) & 0xffff) |
601 | #define get_amp_nid(kc) get_amp_nid_((kc)->private_value) | 601 | #define get_amp_nid(kc) get_amp_nid_((kc)->private_value) |
602 | #define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) | 602 | #define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) |
603 | #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) | 603 | #define get_amp_direction_(pv) (((pv) >> 18) & 0x1) |
604 | #define get_amp_direction(kc) get_amp_direction_((kc)->private_value) | ||
604 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) | 605 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) |
605 | #define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) | 606 | #define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) |
606 | #define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1) | 607 | #define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1) |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 686ec6d75c64..0c8b5a1993ed 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -136,6 +136,8 @@ struct conexant_spec { | |||
136 | unsigned int thinkpad:1; | 136 | unsigned int thinkpad:1; |
137 | unsigned int hp_laptop:1; | 137 | unsigned int hp_laptop:1; |
138 | unsigned int asus:1; | 138 | unsigned int asus:1; |
139 | unsigned int pin_eapd_ctrls:1; | ||
140 | unsigned int single_adc_amp:1; | ||
139 | 141 | ||
140 | unsigned int adc_switching:1; | 142 | unsigned int adc_switching:1; |
141 | 143 | ||
@@ -3430,12 +3432,14 @@ static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins, | |||
3430 | static void do_automute(struct hda_codec *codec, int num_pins, | 3432 | static void do_automute(struct hda_codec *codec, int num_pins, |
3431 | hda_nid_t *pins, bool on) | 3433 | hda_nid_t *pins, bool on) |
3432 | { | 3434 | { |
3435 | struct conexant_spec *spec = codec->spec; | ||
3433 | int i; | 3436 | int i; |
3434 | for (i = 0; i < num_pins; i++) | 3437 | for (i = 0; i < num_pins; i++) |
3435 | snd_hda_codec_write(codec, pins[i], 0, | 3438 | snd_hda_codec_write(codec, pins[i], 0, |
3436 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 3439 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
3437 | on ? PIN_OUT : 0); | 3440 | on ? PIN_OUT : 0); |
3438 | cx_auto_turn_eapd(codec, num_pins, pins, on); | 3441 | if (spec->pin_eapd_ctrls) |
3442 | cx_auto_turn_eapd(codec, num_pins, pins, on); | ||
3439 | } | 3443 | } |
3440 | 3444 | ||
3441 | static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins) | 3445 | static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins) |
@@ -3460,9 +3464,12 @@ static void cx_auto_update_speakers(struct hda_codec *codec) | |||
3460 | int on = 1; | 3464 | int on = 1; |
3461 | 3465 | ||
3462 | /* turn on HP EAPD when HP jacks are present */ | 3466 | /* turn on HP EAPD when HP jacks are present */ |
3463 | if (spec->auto_mute) | 3467 | if (spec->pin_eapd_ctrls) { |
3464 | on = spec->hp_present; | 3468 | if (spec->auto_mute) |
3465 | cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on); | 3469 | on = spec->hp_present; |
3470 | cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on); | ||
3471 | } | ||
3472 | |||
3466 | /* mute speakers in auto-mode if HP or LO jacks are plugged */ | 3473 | /* mute speakers in auto-mode if HP or LO jacks are plugged */ |
3467 | if (spec->auto_mute) | 3474 | if (spec->auto_mute) |
3468 | on = !(spec->hp_present || | 3475 | on = !(spec->hp_present || |
@@ -3889,20 +3896,10 @@ static void cx_auto_parse_beep(struct hda_codec *codec) | |||
3889 | #define cx_auto_parse_beep(codec) | 3896 | #define cx_auto_parse_beep(codec) |
3890 | #endif | 3897 | #endif |
3891 | 3898 | ||
3892 | static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) | 3899 | /* parse EAPDs */ |
3893 | { | ||
3894 | int i; | ||
3895 | for (i = 0; i < nums; i++) | ||
3896 | if (list[i] == nid) | ||
3897 | return true; | ||
3898 | return false; | ||
3899 | } | ||
3900 | |||
3901 | /* parse extra-EAPD that aren't assigned to any pins */ | ||
3902 | static void cx_auto_parse_eapd(struct hda_codec *codec) | 3900 | static void cx_auto_parse_eapd(struct hda_codec *codec) |
3903 | { | 3901 | { |
3904 | struct conexant_spec *spec = codec->spec; | 3902 | struct conexant_spec *spec = codec->spec; |
3905 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3906 | hda_nid_t nid, end_nid; | 3903 | hda_nid_t nid, end_nid; |
3907 | 3904 | ||
3908 | end_nid = codec->start_nid + codec->num_nodes; | 3905 | end_nid = codec->start_nid + codec->num_nodes; |
@@ -3911,14 +3908,18 @@ static void cx_auto_parse_eapd(struct hda_codec *codec) | |||
3911 | continue; | 3908 | continue; |
3912 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) | 3909 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) |
3913 | continue; | 3910 | continue; |
3914 | if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) || | ||
3915 | found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) || | ||
3916 | found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs)) | ||
3917 | continue; | ||
3918 | spec->eapds[spec->num_eapds++] = nid; | 3911 | spec->eapds[spec->num_eapds++] = nid; |
3919 | if (spec->num_eapds >= ARRAY_SIZE(spec->eapds)) | 3912 | if (spec->num_eapds >= ARRAY_SIZE(spec->eapds)) |
3920 | break; | 3913 | break; |
3921 | } | 3914 | } |
3915 | |||
3916 | /* NOTE: below is a wild guess; if we have more than two EAPDs, | ||
3917 | * it's a new chip, where EAPDs are supposed to be associated to | ||
3918 | * pins, and we can control EAPD per pin. | ||
3919 | * OTOH, if only one or two EAPDs are found, it's an old chip, | ||
3920 | * thus it might control over all pins. | ||
3921 | */ | ||
3922 | spec->pin_eapd_ctrls = spec->num_eapds > 2; | ||
3922 | } | 3923 | } |
3923 | 3924 | ||
3924 | static int cx_auto_parse_auto_config(struct hda_codec *codec) | 3925 | static int cx_auto_parse_auto_config(struct hda_codec *codec) |
@@ -4024,8 +4025,9 @@ static void cx_auto_init_output(struct hda_codec *codec) | |||
4024 | } | 4025 | } |
4025 | } | 4026 | } |
4026 | cx_auto_update_speakers(codec); | 4027 | cx_auto_update_speakers(codec); |
4027 | /* turn on/off extra EAPDs, too */ | 4028 | /* turn on all EAPDs if no individual EAPD control is available */ |
4028 | cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); | 4029 | if (!spec->pin_eapd_ctrls) |
4030 | cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); | ||
4029 | } | 4031 | } |
4030 | 4032 | ||
4031 | static void cx_auto_init_input(struct hda_codec *codec) | 4033 | static void cx_auto_init_input(struct hda_codec *codec) |
@@ -4212,6 +4214,8 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, | |||
4212 | int idx = get_input_connection(codec, adc_nid, nid); | 4214 | int idx = get_input_connection(codec, adc_nid, nid); |
4213 | if (idx < 0) | 4215 | if (idx < 0) |
4214 | continue; | 4216 | continue; |
4217 | if (spec->single_adc_amp) | ||
4218 | idx = 0; | ||
4215 | return cx_auto_add_volume_idx(codec, label, pfx, | 4219 | return cx_auto_add_volume_idx(codec, label, pfx, |
4216 | cidx, adc_nid, HDA_INPUT, idx); | 4220 | cidx, adc_nid, HDA_INPUT, idx); |
4217 | } | 4221 | } |
@@ -4252,14 +4256,21 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) | |||
4252 | struct hda_input_mux *imux = &spec->private_imux; | 4256 | struct hda_input_mux *imux = &spec->private_imux; |
4253 | const char *prev_label; | 4257 | const char *prev_label; |
4254 | int input_conn[HDA_MAX_NUM_INPUTS]; | 4258 | int input_conn[HDA_MAX_NUM_INPUTS]; |
4255 | int i, err, cidx; | 4259 | int i, j, err, cidx; |
4256 | int multi_connection; | 4260 | int multi_connection; |
4257 | 4261 | ||
4262 | if (!imux->num_items) | ||
4263 | return 0; | ||
4264 | |||
4258 | multi_connection = 0; | 4265 | multi_connection = 0; |
4259 | for (i = 0; i < imux->num_items; i++) { | 4266 | for (i = 0; i < imux->num_items; i++) { |
4260 | cidx = get_input_connection(codec, spec->imux_info[i].adc, | 4267 | cidx = get_input_connection(codec, spec->imux_info[i].adc, |
4261 | spec->imux_info[i].pin); | 4268 | spec->imux_info[i].pin); |
4262 | input_conn[i] = (spec->imux_info[i].adc << 8) | cidx; | 4269 | if (cidx < 0) |
4270 | continue; | ||
4271 | input_conn[i] = spec->imux_info[i].adc; | ||
4272 | if (!spec->single_adc_amp) | ||
4273 | input_conn[i] |= cidx << 8; | ||
4263 | if (i > 0 && input_conn[i] != input_conn[0]) | 4274 | if (i > 0 && input_conn[i] != input_conn[0]) |
4264 | multi_connection = 1; | 4275 | multi_connection = 1; |
4265 | } | 4276 | } |
@@ -4288,6 +4299,15 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) | |||
4288 | err = cx_auto_add_capture_volume(codec, nid, | 4299 | err = cx_auto_add_capture_volume(codec, nid, |
4289 | "Capture", "", cidx); | 4300 | "Capture", "", cidx); |
4290 | } else { | 4301 | } else { |
4302 | bool dup_found = false; | ||
4303 | for (j = 0; j < i; j++) { | ||
4304 | if (input_conn[j] == input_conn[i]) { | ||
4305 | dup_found = true; | ||
4306 | break; | ||
4307 | } | ||
4308 | } | ||
4309 | if (dup_found) | ||
4310 | continue; | ||
4291 | err = cx_auto_add_capture_volume(codec, nid, | 4311 | err = cx_auto_add_capture_volume(codec, nid, |
4292 | label, " Capture", cidx); | 4312 | label, " Capture", cidx); |
4293 | } | 4313 | } |
@@ -4412,6 +4432,12 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
4412 | codec->spec = spec; | 4432 | codec->spec = spec; |
4413 | codec->pin_amp_workaround = 1; | 4433 | codec->pin_amp_workaround = 1; |
4414 | 4434 | ||
4435 | switch (codec->vendor_id) { | ||
4436 | case 0x14f15045: | ||
4437 | spec->single_adc_amp = 1; | ||
4438 | break; | ||
4439 | } | ||
4440 | |||
4415 | apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); | 4441 | apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); |
4416 | 4442 | ||
4417 | err = cx_auto_search_adcs(codec); | 4443 | err = cx_auto_search_adcs(codec); |
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 | ||
3011 | static 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 | |||
3009 | static int alc_auto_add_vol_ctl(struct hda_codec *codec, | 3023 | static 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 */ |