[alsa-devel] [PATCH 0/3] HDMI HBR(High Bit Rate) Feature bug fix for Intel's Chips

Wang, Xingchao xingchao.wang at intel.com
Fri Sep 7 03:32:09 CEST 2012



> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai at suse.de]
> Sent: Friday, September 07, 2012 12:00 AM
> To: Wang, Xingchao
> Cc: alsa-devel at alsa-project.org; anssi.hannula at iki.fi; alanwww1 at xbmc.org;
> Wu, Fengguang
> Subject: Re: [PATCH 0/3] HDMI HBR(High Bit Rate) Feature bug fix for Intel's
> Chips
> 
> At Thu, 06 Sep 2012 08:53:53 +0200,
> Takashi Iwai wrote:
> >
> > At Thu,  6 Sep 2012 10:02:35 +0800,
> > Wang Xingchao wrote:
> > >
> > > As i have no A/V receiver handy and could not test HBR playback
> > > directly, i removed the "RFC" type until the patchset was tested and proved
> working well.
> > > The patchset was tested on Intel chips and get positive feedback.
> > >
> > > Quote from "Øyvind Kvålsvoll <oyvind at kvalsvoll.com>":
> > > "TrueHD and DTS-MA work fine from XBMC, 2-ch playback also works
> > > fine from XBMC.
> > > Channels are all mapped to the right speaker, all 7.1."
> > >
> > > Quote from alanwww1:
> > > "I tested the patches. They work perfectly. I tested it with both
> > > DTS Master Audio and Dolby Tru HD streams.
> > > Also tested with speaker-test. Channel mapping was right."
> > > From:
> > >
> http://forum.xbmc.org/showthread.php?tid=128298&pid=1184574#pid11845
> > > 74
> > >
> > > Maybe there's still potential bug and i will keep on track that.
> > >
> > > The idea of this patch comes from Anssi, Big credit to him at first!
> > > Thanks the guys from XBMC forum which help test the patches.
> > >
> > > For people interested to test the patch, please remember to apply
> > > another change in alsa-lib side, you can refer to the patch detail from XBMC
> forum:
> > >
> http://forum.xbmc.org/showthread.php?tid=128298&pid=1178776#pid11787
> > > 76
> >
> > Note that the alsa-lib fix isn't necessarily applied to all systems.
> > The bug appears only on systems with both SPDIF and HDMI.
> >
> > In anyway, I applied the kernel patches now.  Thanks.
> 
> While looking through the code again (and need to rebase my channel mapping
> branch), I found that the check of non-PCM should be done to each pin instead
> of converter.  Basically the setup is done to the audio infoframe of the pin, so
> when the driver reconnects to another converter upon the new option, there
> might be inconsistency regarding non-PCM status.
> 
> So I applied the patch below in addition now.

Looks better now, Thanks Takashi.

--xingchao
> 
> 
> Takashi
> 
> ===
> 
> From: Takashi Iwai <tiwai at suse.de>
> Subject: [PATCH] ALSA: hda - Move non-PCM check to per_pin in patch_hdmi.c
> 
> Recently the check for non-PCM stream state was added to the generic HDMI
> driver code.  But this check should be done rather to each pin instead of each
> converter.  Otherwise when a different converter is assigned at the next open,
> the audio infoframe can be inconsistent with the setup using the previous
> converter.
> 
> For fixing this issue, this patch moves the state of the current non-PCM status
> from per_cvt to per_pin.  (In addition an unused argument cvt_nid is stripped
> from hdmi_setup_channel_mapping())
> 
> Signed-off-by: Takashi Iwai <tiwai at suse.de>
> ---
>  sound/pci/hda/patch_hdmi.c | 46
> +++++++++++++++++++++++++---------------------
>  1 file changed, 25 insertions(+), 21 deletions(-)
> 
> diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index
> 5361298..333d533 100644
> --- a/sound/pci/hda/patch_hdmi.c
> +++ b/sound/pci/hda/patch_hdmi.c
> @@ -61,7 +61,6 @@ struct hdmi_spec_per_cvt {
>  	u32 rates;
>  	u64 formats;
>  	unsigned int maxbps;
> -	bool non_pcm;
>  };
> 
>  struct hdmi_spec_per_pin {
> @@ -73,6 +72,7 @@ struct hdmi_spec_per_pin {
>  	struct hdmi_eld sink_eld;
>  	struct delayed_work work;
>  	int repoll_count;
> +	bool non_pcm;
>  };
> 
>  struct hdmi_spec {
> @@ -550,7 +550,6 @@ static void hdmi_debug_channel_mapping(struct
> hda_codec *codec,
> 
>  static void hdmi_setup_channel_mapping(struct hda_codec *codec,
>  				       hda_nid_t pin_nid,
> -				       hda_nid_t cvt_nid,
>  				       bool non_pcm,
>  				       int ca)
>  {
> @@ -712,27 +711,16 @@ static bool hdmi_infoframe_uptodate(struct
> hda_codec *codec, hda_nid_t pin_nid,  }
> 
>  static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,
> -					hda_nid_t cvt_nid, struct snd_pcm_substream
> *substream)
> +				       bool non_pcm,
> +				       struct snd_pcm_substream *substream)
>  {
>  	struct hdmi_spec *spec = codec->spec;
>  	struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
> -	struct hdmi_spec_per_cvt *per_cvt;
> -	struct hda_spdif_out *spdif;
>  	hda_nid_t pin_nid = per_pin->pin_nid;
>  	int channels = substream->runtime->channels;
>  	struct hdmi_eld *eld;
>  	int ca;
> -	int cvt_idx;
>  	union audio_infoframe ai;
> -	bool non_pcm = false;
> -
> -	cvt_idx = cvt_nid_to_cvt_index(spec, cvt_nid);
> -	per_cvt = &spec->cvts[cvt_idx];
> -
> -	mutex_lock(&codec->spdif_mutex);
> -	spdif = snd_hda_spdif_out_of_nid(codec, cvt_nid);
> -	non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO);
> -	mutex_unlock(&codec->spdif_mutex);
> 
>  	eld = &spec->pins[pin_idx].sink_eld;
>  	if (!eld->monitor_present)
> @@ -775,7 +763,7 @@ static void hdmi_setup_audio_infoframe(struct
> hda_codec *codec, int pin_idx,
>  			    "pin=%d channels=%d\n",
>  			    pin_nid,
>  			    channels);
> -		hdmi_setup_channel_mapping(codec, pin_nid, cvt_nid, non_pcm,
> ca);
> +		hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca);
>  		hdmi_stop_infoframe_trans(codec, pin_nid);
>  		hdmi_fill_audio_infoframe(codec, pin_nid,
>  					    ai.bytes, sizeof(ai));
> @@ -783,11 +771,11 @@ static void hdmi_setup_audio_infoframe(struct
> hda_codec *codec, int pin_idx,
>  	} else {
>  		/* For non-pcm audio switch, setup new channel mapping
>  		 * accordingly */
> -		if (per_cvt->non_pcm != non_pcm)
> -			hdmi_setup_channel_mapping(codec, pin_nid, cvt_nid,
> non_pcm, ca);
> +		if (per_pin->non_pcm != non_pcm)
> +			hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca);
>  	}
> 
> -	per_cvt->non_pcm = non_pcm;
> +	per_pin->non_pcm = non_pcm;
>  }
> 
> 
> @@ -1080,6 +1068,7 @@ static int hdmi_add_pin(struct hda_codec *codec,
> hda_nid_t pin_nid)
>  	per_pin = &spec->pins[pin_idx];
> 
>  	per_pin->pin_nid = pin_nid;
> +	per_pin->non_pcm = false;
> 
>  	err = hdmi_read_pin_conn(codec, pin_idx);
>  	if (err < 0)
> @@ -1109,7 +1098,6 @@ static int hdmi_add_cvt(struct hda_codec *codec,
> hda_nid_t cvt_nid)
> 
>  	per_cvt->cvt_nid = cvt_nid;
>  	per_cvt->channels_min = 2;
> -	per_cvt->non_pcm = false;
>  	if (chans <= 16)
>  		per_cvt->channels_max = chans;
> 
> @@ -1179,6 +1167,19 @@ static char *get_hdmi_pcm_name(int idx)
>  	return &names[idx][0];
>  }
> 
> +static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t
> +cvt_nid) {
> +	struct hda_spdif_out *spdif;
> +	bool non_pcm;
> +
> +	mutex_lock(&codec->spdif_mutex);
> +	spdif = snd_hda_spdif_out_of_nid(codec, cvt_nid);
> +	non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO);
> +	mutex_unlock(&codec->spdif_mutex);
> +	return non_pcm;
> +}
> +
> +
>  /*
>   * HDMI callbacks
>   */
> @@ -1194,10 +1195,13 @@ static int
> generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
>  	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);
> 
>  	hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels);
> 
> -	hdmi_setup_audio_infoframe(codec, pin_idx, cvt_nid, substream);
> +	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);
> --
> 1.7.11.5
> 



More information about the Alsa-devel mailing list