diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-10-14 09:22:34 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-10-27 10:58:10 -0400 |
commit | 254f296840b64b034a4c850d45dbde7c040f0819 (patch) | |
tree | 0341a73271adc08dd7fc6e654e46e23682cca081 /sound | |
parent | 527e4d73af16dfc35a770dfdc3874ef63c359ea6 (diff) |
ALSA: hda - Keep EAPD turned on for old Conexant chips
In the old Conexant chips (5045, 5047, 5051 and 5066), a single EAPD
may handle both headphone and speaker outputs while it's assigned only
to one of them. Turning off dynamically leads to the unexpected silent
output in such a configuration with the auto-mute function.
Since it's difficult to know how the EAPD is handled in the actual h/w
implementation, better to keep EAPD on while running for such codecs.
Cc: <stable@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 686ec6d75c6..1d69a3e0ce2 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -136,6 +136,7 @@ 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; | ||
139 | 140 | ||
140 | unsigned int adc_switching:1; | 141 | unsigned int adc_switching:1; |
141 | 142 | ||
@@ -3430,12 +3431,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, | 3431 | static void do_automute(struct hda_codec *codec, int num_pins, |
3431 | hda_nid_t *pins, bool on) | 3432 | hda_nid_t *pins, bool on) |
3432 | { | 3433 | { |
3434 | struct conexant_spec *spec = codec->spec; | ||
3433 | int i; | 3435 | int i; |
3434 | for (i = 0; i < num_pins; i++) | 3436 | for (i = 0; i < num_pins; i++) |
3435 | snd_hda_codec_write(codec, pins[i], 0, | 3437 | snd_hda_codec_write(codec, pins[i], 0, |
3436 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 3438 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
3437 | on ? PIN_OUT : 0); | 3439 | on ? PIN_OUT : 0); |
3438 | cx_auto_turn_eapd(codec, num_pins, pins, on); | 3440 | if (spec->pin_eapd_ctrls) |
3441 | cx_auto_turn_eapd(codec, num_pins, pins, on); | ||
3439 | } | 3442 | } |
3440 | 3443 | ||
3441 | static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins) | 3444 | static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins) |
@@ -3460,9 +3463,12 @@ static void cx_auto_update_speakers(struct hda_codec *codec) | |||
3460 | int on = 1; | 3463 | int on = 1; |
3461 | 3464 | ||
3462 | /* turn on HP EAPD when HP jacks are present */ | 3465 | /* turn on HP EAPD when HP jacks are present */ |
3463 | if (spec->auto_mute) | 3466 | if (spec->pin_eapd_ctrls) { |
3464 | on = spec->hp_present; | 3467 | if (spec->auto_mute) |
3465 | cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on); | 3468 | on = spec->hp_present; |
3469 | cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on); | ||
3470 | } | ||
3471 | |||
3466 | /* mute speakers in auto-mode if HP or LO jacks are plugged */ | 3472 | /* mute speakers in auto-mode if HP or LO jacks are plugged */ |
3467 | if (spec->auto_mute) | 3473 | if (spec->auto_mute) |
3468 | on = !(spec->hp_present || | 3474 | on = !(spec->hp_present || |
@@ -3889,20 +3895,10 @@ static void cx_auto_parse_beep(struct hda_codec *codec) | |||
3889 | #define cx_auto_parse_beep(codec) | 3895 | #define cx_auto_parse_beep(codec) |
3890 | #endif | 3896 | #endif |
3891 | 3897 | ||
3892 | static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) | 3898 | /* 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) | 3899 | static void cx_auto_parse_eapd(struct hda_codec *codec) |
3903 | { | 3900 | { |
3904 | struct conexant_spec *spec = codec->spec; | 3901 | struct conexant_spec *spec = codec->spec; |
3905 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3906 | hda_nid_t nid, end_nid; | 3902 | hda_nid_t nid, end_nid; |
3907 | 3903 | ||
3908 | end_nid = codec->start_nid + codec->num_nodes; | 3904 | end_nid = codec->start_nid + codec->num_nodes; |
@@ -3911,14 +3907,18 @@ static void cx_auto_parse_eapd(struct hda_codec *codec) | |||
3911 | continue; | 3907 | continue; |
3912 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) | 3908 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) |
3913 | continue; | 3909 | 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; | 3910 | spec->eapds[spec->num_eapds++] = nid; |
3919 | if (spec->num_eapds >= ARRAY_SIZE(spec->eapds)) | 3911 | if (spec->num_eapds >= ARRAY_SIZE(spec->eapds)) |
3920 | break; | 3912 | break; |
3921 | } | 3913 | } |
3914 | |||
3915 | /* NOTE: below is a wild guess; if we have more than two EAPDs, | ||
3916 | * it's a new chip, where EAPDs are supposed to be associated to | ||
3917 | * pins, and we can control EAPD per pin. | ||
3918 | * OTOH, if only one or two EAPDs are found, it's an old chip, | ||
3919 | * thus it might control over all pins. | ||
3920 | */ | ||
3921 | spec->pin_eapd_ctrls = spec->num_eapds > 2; | ||
3922 | } | 3922 | } |
3923 | 3923 | ||
3924 | static int cx_auto_parse_auto_config(struct hda_codec *codec) | 3924 | static int cx_auto_parse_auto_config(struct hda_codec *codec) |
@@ -4024,8 +4024,9 @@ static void cx_auto_init_output(struct hda_codec *codec) | |||
4024 | } | 4024 | } |
4025 | } | 4025 | } |
4026 | cx_auto_update_speakers(codec); | 4026 | cx_auto_update_speakers(codec); |
4027 | /* turn on/off extra EAPDs, too */ | 4027 | /* turn on all EAPDs if no individual EAPD control is available */ |
4028 | cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); | 4028 | if (!spec->pin_eapd_ctrls) |
4029 | cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); | ||
4029 | } | 4030 | } |
4030 | 4031 | ||
4031 | static void cx_auto_init_input(struct hda_codec *codec) | 4032 | static void cx_auto_init_input(struct hda_codec *codec) |