aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2013-04-10 06:26:07 -0400
committerTakashi Iwai <tiwai@suse.de>2013-04-17 02:13:44 -0400
commit83f26ad2c909083fa638d2df1b1a25bcbf2d1be2 (patch)
tree87c8999c9e6dff6f0a922b8ba3795307fd8afd37 /sound
parent5ead56f2dad53c6c2eaaf13e2de4125a59a3935b (diff)
ALSA: hda - fixup D3 pin and right channel mute on Haswell HDMI audio
When graphics initializes the HDMI chip, sometimes this leads to pins going into D3 and right channel being muted. If the audio driver finishes initialization before the graphic driver does, this situation becomes permanent. This is a workaround that checks for this situation and corrects it on playback prepare. It has been verified working on at least one machine. BugLink: https://bugs.launchpad.net/bugs/1167270 Signed-off-by: David Henningsson <david.henningsson@canonical.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_hdmi.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index ede82156da0f..32930e668854 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1018,6 +1018,41 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
1018 hdmi_non_intrinsic_event(codec, res); 1018 hdmi_non_intrinsic_event(codec, res);
1019} 1019}
1020 1020
1021static void haswell_verify_pin_D0(struct hda_codec *codec, hda_nid_t nid)
1022{
1023 int pwr, lamp, ramp;
1024
1025 pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
1026 pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT;
1027 if (pwr != AC_PWRST_D0) {
1028 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
1029 AC_PWRST_D0);
1030 msleep(40);
1031 pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
1032 pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT;
1033 snd_printd("Haswell HDMI audio: Power for pin 0x%x is now D%d\n", nid, pwr);
1034 }
1035
1036 lamp = snd_hda_codec_read(codec, nid, 0,
1037 AC_VERB_GET_AMP_GAIN_MUTE,
1038 AC_AMP_GET_LEFT | AC_AMP_GET_OUTPUT);
1039 ramp = snd_hda_codec_read(codec, nid, 0,
1040 AC_VERB_GET_AMP_GAIN_MUTE,
1041 AC_AMP_GET_RIGHT | AC_AMP_GET_OUTPUT);
1042 if (lamp != ramp) {
1043 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1044 AC_AMP_SET_RIGHT | AC_AMP_SET_OUTPUT | lamp);
1045
1046 lamp = snd_hda_codec_read(codec, nid, 0,
1047 AC_VERB_GET_AMP_GAIN_MUTE,
1048 AC_AMP_GET_LEFT | AC_AMP_GET_OUTPUT);
1049 ramp = snd_hda_codec_read(codec, nid, 0,
1050 AC_VERB_GET_AMP_GAIN_MUTE,
1051 AC_AMP_GET_RIGHT | AC_AMP_GET_OUTPUT);
1052 snd_printd("Haswell HDMI audio: Mute after set on pin 0x%x: [0x%x 0x%x]\n", nid, lamp, ramp);
1053 }
1054}
1055
1021/* 1056/*
1022 * Callbacks 1057 * Callbacks
1023 */ 1058 */
@@ -1032,6 +1067,9 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
1032 int pinctl; 1067 int pinctl;
1033 int new_pinctl = 0; 1068 int new_pinctl = 0;
1034 1069
1070 if (codec->vendor_id == 0x80862807)
1071 haswell_verify_pin_D0(codec, pin_nid);
1072
1035 if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { 1073 if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) {
1036 pinctl = snd_hda_codec_read(codec, pin_nid, 0, 1074 pinctl = snd_hda_codec_read(codec, pin_nid, 0,
1037 AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 1075 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);