Hi!
From: Takashi Iwai tiwai@suse.de Date: Fri, 14 Dec 2012 09:22:35 +0000 (+0100) Subject: ALSA: hda - Always turn on pins for HDMI/DP X-Git-Tag: v3.8-rc1~29^2~7 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fstable%2Flinux-stable.git;a=...
ALSA: hda - Always turn on pins for HDMI/DP
We've seen the broken HDMI *video* output on some machines with GM965, and the debugging session pointed that the culprit is the disabled audio output pins. Toggling these pins dynamically on demand caused flickering of HDMI TV.
This patch changes the behavior to keep the pin ON constantly.
Unfortunately this seems to cause a regression on at least some "NVIDIA ION2" systems.
When running snd_pcm_open() and snd_pcm_close() on an hdmi device on an affected system, the HDMI port seemingly continues to transmit an empty audio stream.
However, when hw_params have been set and snd_pcm_prepare() called before closing the device (and optionally audio has been output), the HDMI port stops transmitting at snd_pcm_close() time.
(I use "transmitting" here to mean that the HDMI sink/receiver receives/shows a an active audio stream)
On systems _not_ affected by the issue, the HDMI port never starts transmitting if just snd_pcm_open()+snd_pcm_close() have been called (but note [1]).
HDMI port continuing transmitting has the unfortunate effect that when the user has connected the system to an amplifier via HDMI (for video playback purposes), the amplifier may continue to play back empty audio from HDMI even when there is actual audio data on its S/PDIF input. An snd_pcm_open()+snd_pcm_close() sequence can be caused by e.g. device probing by an application.
Several OpenELEC users have reported this issue on stable 3.7.x, here's some alsainfo: http://onse.fi/files/ion-regression-alsainfo-1.txt http://onse.fi/files/ion-regression-alsainfo-2.txt Both of these have the Nvidia GPU 0b HDMI/DP codecs: Vendor Id: 0x10de000b Subsystem Id: 0x10de0101 Revision Id: 0x100200
However, e.g. my non-ION2 laptop with 0b codecs (but different rev) is _not_ affected: Vendor Id: 0x10de000b Subsystem Id: 0x10de0101 Revision Id: 0x100100 http://www.alsa-project.org/db/?f=bc940d23d19ae7e2ee1e83895d85f711c2d0e5b1
I'm still working with the OpenELEC devs and users to pinpoint the issue further, but it is progressing rather slowly due to not many people having affected systems (especially in the affected dual HDMI + S/PDIF cabled configuration).
Feel free to suggest anything we should try out if you have some ideas :) In the meantime, I'll continue investigating exactly why snd_pcm_close() doesn't stop the HDMI output on the affected systems (or why does a simple snd_pcm_open() even start outputting the audio, since that does not seem to happen on other systems).
I'll keep you posted.
[1] It seems that on my Intel HDMI system ( http://www.alsa-project.org/db/?f=bb3fc8680b372c0475719d42d7fc8b2bb7bfb4eb ) the HDMI port keeps transmitting in approximately reversed situation than in the above ION2 case. That is, if audio has been output in the port e.g. with a speaker-test command, closing the device will not cause the stream to stop (and therefore the above issue happens again, receives ignores S/PDIF stream as HDMI stream is given higher priority by default). I found out that the attached patch solves that one. What are your thoughts on that? (obviously the patch will not solve the ION2 regression, since cleanup() is not called if prepare() has not been called; or at least I assume so, way too tired to check that now...) Note that closing the device after audio has been output stops HDMI port transmission even without the patch on both the NVIDIA ION2 systems and on my NVIDIA laptop, it is just the Intel HDMI codec where that does not happen (well, of the tested ones, at least).
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=51421
Cc: stable@vger.kernel.org Signed-off-by: Takashi Iwai tiwai@suse.de
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 0fcfa6f..37dd06d 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -431,9 +431,11 @@ static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid) if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
- /* Disable pin out until stream is active*/
- /* Enable pin out: some machines with GM965 gets broken output when
* the pin is disabled or changed while using with HDMI
snd_hda_codec_write(codec, pin_nid, 0,*/
AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
}
static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid) @@ -1341,7 +1343,6 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct hdmi_spec *spec = codec->spec; int pin_idx = hinfo_to_pin_index(spec, hinfo); hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid;
int pinctl; bool non_pcm;
non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
@@ -1350,11 +1351,6 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
hdmi_setup_audio_infoframe(codec, pin_idx, non_pcm, substream);
- pinctl = snd_hda_codec_read(codec, pin_nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- snd_hda_codec_write(codec, pin_nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl | PIN_OUT);
- return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
}
@@ -1374,7 +1370,6 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, int cvt_idx, pin_idx; struct hdmi_spec_per_cvt *per_cvt; struct hdmi_spec_per_pin *per_pin;
int pinctl;
if (hinfo->nid) { cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid);
@@ -1391,11 +1386,6 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, return -EINVAL; per_pin = &spec->pins[pin_idx];
pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
snd_hda_codec_write(codec, per_pin->pin_nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
snd_hda_spdif_ctls_unassign(codec, pin_idx); per_pin->chmap_set = false; memset(per_pin->chmap, 0, sizeof(per_pin->chmap));pinctl & ~PIN_OUT);