Patchwork [Raring] Ubuntu (no-up): ALSA: hda - fixup D3 pin and right channel mute on Haswell HDMI audio

login
register
mail settings
Submitter David Henningsson
Date April 11, 2013, 7:38 a.m.
Message ID <5166685B.9070207@canonical.com>
Download mbox | patch
Permalink /patch/235597/
State New
Headers show

Comments

David Henningsson - April 11, 2013, 7:38 a.m.
BugLink: https://bugs.launchpad.net/bugs/1167270

This patch has been tested on two machines, and found to resolve one of 
the HDMI audio issues on Haswell.

The root cause is lack of synchronisation between the video driver and 
the audio driver. Upstream wants to resolve this by adding 
synchronisation mechanisms, so they won't take this patch. But since 
kernel freeze is today, I wanted to ask you to accept this intermediate 
workaround, which at every playback start checks for the error and 
corrects it if found.
Leann Ogasawara - April 11, 2013, 1:09 p.m.
Applied to Raring master-next.

Thanks,
Leann

On 04/11/2013 12:38 AM, David Henningsson wrote:
> BugLink: https://bugs.launchpad.net/bugs/1167270
>
> This patch has been tested on two machines, and found to resolve one
> of the HDMI audio issues on Haswell.
>
> The root cause is lack of synchronisation between the video driver and
> the audio driver. Upstream wants to resolve this by adding
> synchronisation mechanisms, so they won't take this patch. But since
> kernel freeze is today, I wanted to ask you to accept this
> intermediate workaround, which at every playback start checks for the
> error and corrects it if found.
>
>
>
>
Leann Ogasawara - April 11, 2013, 1:28 p.m.
On 04/11/2013 06:09 AM, Leann Ogasawara wrote:
> Applied to Raring master-next.

Hi David,

After I'd applied this to Raring master-next, there was some concern
raised about the patch via the #ubuntu-kernel IRC channel.  We are
hoping to get some clarification and feedback from you.

[06:12:36] <rtg_> ogasawara, actually, I was gonna question David on
that patch. it seems over engineered to me.
[06:14:13] <ogasawara> rtg_: I thought it seemed fairly well contained
and tested
[06:14:40] <ogasawara> rtg_: it's not too late to yank it if you have
reservations
[06:15:12] <rtg_> ogasawara, in that it only affects haswell. however,
why not just force the D0 and mute settings rather then interrogate the
HW ? less code I think.
[06:17:24] <ogasawara> rtg_: it's a valid question, want me to punt it
till we get clarification?
[06:18:54] <rtg_> ogasawara, if we can get ahold of him today.
[06:20:23] <rtg_> ogasawara, by collapsing the code into a more
definitive form I might worry about audio artifacts such as pops and
clicks whilst programming those registers. thats really what I'd like to
confirm from him.

>
> On 04/11/2013 12:38 AM, David Henningsson wrote:
>> BugLink: https://bugs.launchpad.net/bugs/1167270
>>
>> This patch has been tested on two machines, and found to resolve one
>> of the HDMI audio issues on Haswell.
>>
>> The root cause is lack of synchronisation between the video driver and
>> the audio driver. Upstream wants to resolve this by adding
>> synchronisation mechanisms, so they won't take this patch. But since
>> kernel freeze is today, I wanted to ask you to accept this
>> intermediate workaround, which at every playback start checks for the
>> error and corrects it if found.
>>
>>
>>
>>
>

Patch

From 37b4fbb88dc03160fd71d1ec11ba14e83e6a79dc Mon Sep 17 00:00:00 2001
From: David Henningsson <david.henningsson@canonical.com>
Date: Wed, 10 Apr 2013 12:26:07 +0200
Subject: [PATCH] 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>
---
 sound/pci/hda/patch_hdmi.c |   38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index ede8215..32930e6 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)
 		hdmi_non_intrinsic_event(codec, res);
 }
 
+static void haswell_verify_pin_D0(struct hda_codec *codec, hda_nid_t nid)
+{
+	int pwr, lamp, ramp;
+
+	pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
+	pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT;
+	if (pwr != AC_PWRST_D0) {
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
+				    AC_PWRST_D0);
+		msleep(40);
+		pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
+		pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT;
+		snd_printd("Haswell HDMI audio: Power for pin 0x%x is now D%d\n", nid, pwr);
+	}
+
+	lamp = snd_hda_codec_read(codec, nid, 0,
+				  AC_VERB_GET_AMP_GAIN_MUTE,
+				  AC_AMP_GET_LEFT | AC_AMP_GET_OUTPUT);
+	ramp = snd_hda_codec_read(codec, nid, 0,
+				  AC_VERB_GET_AMP_GAIN_MUTE,
+				  AC_AMP_GET_RIGHT | AC_AMP_GET_OUTPUT);
+	if (lamp != ramp) {
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+				    AC_AMP_SET_RIGHT | AC_AMP_SET_OUTPUT | lamp);
+
+		lamp = snd_hda_codec_read(codec, nid, 0,
+				  AC_VERB_GET_AMP_GAIN_MUTE,
+				  AC_AMP_GET_LEFT | AC_AMP_GET_OUTPUT);
+		ramp = snd_hda_codec_read(codec, nid, 0,
+				  AC_VERB_GET_AMP_GAIN_MUTE,
+				  AC_AMP_GET_RIGHT | AC_AMP_GET_OUTPUT);
+		snd_printd("Haswell HDMI audio: Mute after set on pin 0x%x: [0x%x 0x%x]\n", nid, lamp, ramp);
+	}
+}
+
 /*
  * Callbacks
  */
@@ -1032,6 +1067,9 @@  static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
 	int pinctl;
 	int new_pinctl = 0;
 
+	if (codec->vendor_id == 0x80862807)
+		haswell_verify_pin_D0(codec, pin_nid);
+
 	if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) {
 		pinctl = snd_hda_codec_read(codec, pin_nid, 0,
 					    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-- 
1.7.9.5