aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2011-08-01 09:06:37 +0200
committerJohn Rigby <john.rigby@linaro.org>2011-09-23 08:54:44 -0600
commit87ef30862e2d6b598d0d9627cef51e343e1d0ff2 (patch)
tree38726b672b34bb6d5e03d8b5a902c1c1e8e4bc83 /sound
parentbc01c2ee27036a49325eeacfcbcbcf5a6f828cc9 (diff)
ALSA: hda - Turn on extra EAPDs on Conexant codecs
Some machines seem to use EAPD control of the unused pin for controlling the overall EAPD. Since the driver currently doesn't check the EAPD of unused pins, the EAPD isn't enabled. For avoiding such a problem, turn all extra EAPDs on as default. Signed-off-by: Takashi Iwai <tiwai@suse.de> (cherry picked from commit 19110595c89b2d606883b7cb99260c7e47fd2143) BugLink: http://bugs.launchpad.net/bugs/783582 Signed-off-by: David Henningsson <david.henningsson@canonical.com> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_conexant.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 1ab6663d745..f32682b304c 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -155,6 +155,10 @@ struct conexant_spec {
unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */
unsigned int beep_amp;
+
+ /* extra EAPD pins */
+ unsigned int num_eapds;
+ hda_nid_t eapds[4];
};
static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
@@ -3911,6 +3915,38 @@ 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 */
+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;
+ for (nid = codec->start_nid; nid < end_nid; nid++) {
+ if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
+ 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;
+ }
+}
+
static int cx_auto_parse_auto_config(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
@@ -3924,6 +3960,7 @@ static int cx_auto_parse_auto_config(struct hda_codec *codec)
cx_auto_parse_input(codec);
cx_auto_parse_digital(codec);
cx_auto_parse_beep(codec);
+ cx_auto_parse_eapd(codec);
return 0;
}
@@ -4011,6 +4048,8 @@ static void cx_auto_init_output(struct hda_codec *codec)
}
}
cx_auto_update_speakers(codec);
+ /* turn on/off extra EAPDs, too */
+ cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
}
static void cx_auto_init_input(struct hda_codec *codec)