[alsa-devel] HDMI regression on close (was: ALSA: hda - Always turn on pins for HDMI/DP)

Anssi Hannula anssi.hannula at iki.fi
Sat Feb 16 03:23:44 CET 2013


Hi!

> From: Takashi Iwai <tiwai at 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=commitdiff_plain;h=6169b673618bf0b2518ce413b54925782a603f06
> 
> 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 at vger.kernel.org>
> Signed-off-by: Takashi Iwai <tiwai at 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,
> -				    pinctl & ~PIN_OUT);
>  		snd_hda_spdif_ctls_unassign(codec, pin_idx);
>  		per_pin->chmap_set = false;
>  		memset(per_pin->chmap, 0, sizeof(per_pin->chmap));


-- 
Anssi Hannula
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-ALSA-hda-Always-clean-up-HDMI-streams-in-cleanup-cal.patch
Type: text/x-patch
Size: 1590 bytes
Desc: not available
URL: <http://mailman.alsa-project.org/pipermail/alsa-devel/attachments/20130216/04625ecc/attachment.bin>


More information about the Alsa-devel mailing list