[alsa-devel] [PATCH V1] ALSA: hda - Avoid choose same converter for unused pins

Wang, Xingchao xingchao.wang at intel.com
Tue Jun 18 16:16:56 CEST 2013


> -----Original Message-----
> From: Takashi Iwai [mailto:tiwai at suse.de]
> Sent: Tuesday, June 18, 2013 10:14 PM
> To: Wang Xingchao
> Cc: daniel.vetter at ffwll.ch; alsa-devel at alsa-project.org;
> intel-gfx at lists.freedesktop.org; Wang, Xingchao
> Subject: Re: [PATCH V1] ALSA: hda - Avoid choose same converter for unused
> pins
> 
> At Tue, 18 Jun 2013 21:42:14 +0800,
> Wang Xingchao wrote:
> >
> > For Intel Haswell HDMI codecs, the pins choose converter 0 by default.
> > This would cause conflict when playing audio on unused pins,the pin
> > with physical device connected would get audio data too.
> > i.e. Pin 0/1/2 default choose converter 0, pin 1 has HDMI monitor connected.
> > when play audio on Pin 0 or pin 2, pin 1 could get audio data too.
> >
> > This patch configure unused pins to choose different converter.
> >
> > Signed-off-by: Wang Xingchao <xingchao.wang at linux.intel.com>
> > ---
> >  sound/pci/hda/patch_hdmi.c |   91
> ++++++++++++++++++++++++++++++++++++--------
> >  1 file changed, 76 insertions(+), 15 deletions(-)
> >
> > diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
> > index 8983747..43f8b76 100644
> > --- a/sound/pci/hda/patch_hdmi.c
> > +++ b/sound/pci/hda/patch_hdmi.c
> > @@ -1110,26 +1110,15 @@ static int hdmi_setup_stream(struct hda_codec
> *codec, hda_nid_t cvt_nid,
> >  	return 0;
> >  }
> >
> > -/*
> > - * HDA PCM callbacks
> > - */
> > -static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
> > -			 struct hda_codec *codec,
> > -			 struct snd_pcm_substream *substream)
> > +static int hdmi_choose_cvt(struct hda_codec *codec,
> > +			int pin_idx, int *cvt_id, int *mux_id)
> >  {
> >  	struct hdmi_spec *spec = codec->spec;
> > -	struct snd_pcm_runtime *runtime = substream->runtime;
> > -	int pin_idx, cvt_idx, mux_idx = 0;
> >  	struct hdmi_spec_per_pin *per_pin;
> > -	struct hdmi_eld *eld;
> >  	struct hdmi_spec_per_cvt *per_cvt = NULL;
> > +	int cvt_idx, mux_idx = 0;
> >
> > -	/* Validate hinfo */
> > -	pin_idx = hinfo_to_pin_index(spec, hinfo);
> > -	if (snd_BUG_ON(pin_idx < 0))
> > -		return -EINVAL;
> >  	per_pin = get_pin(spec, pin_idx);
> > -	eld = &per_pin->sink_eld;
> >
> >  	/* Dynamically assign converter to stream */
> >  	for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { @@ -1147,17
> > +1136,89 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
> >  			continue;
> >  		break;
> >  	}
> > +
> >  	/* No free converters */
> >  	if (cvt_idx == spec->num_cvts)
> >  		return -ENODEV;
> >
> > +	if (cvt_id)
> > +		*cvt_id = cvt_idx;
> > +	if (mux_id)
> > +		*mux_id = mux_idx;
> > +
> > +	return 0;
> > +}
> > +
> > +static void haswell_config_cvts(struct hda_codec *codec,
> > +			int pin_id, int mux_id)
> > +{
> > +	struct hdmi_spec *spec = codec->spec;
> > +	struct hdmi_spec_per_pin *per_pin;
> > +	int pin_idx, mux_idx;
> > +	int curr;
> > +	int err;
> > +
> > +	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
> > +		per_pin = get_pin(spec, pin_idx);
> > +
> > +		if (pin_idx == pin_id)
> > +			continue;
> > +
> > +		curr = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
> > +					  AC_VERB_GET_CONNECT_SEL, 0);
> > +
> > +		/* Choose another unused converter */
> > +		if (curr == mux_id) {
> > +			err = hdmi_choose_cvt(codec, pin_idx, NULL, &mux_idx);
> > +			if (err < 0)
> > +				return;
> > +			snd_printdd("HDMI: choose converter %d for pin %d\n",
> mux_idx, pin_idx);
> > +			snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
> > +					    AC_VERB_SET_CONNECT_SEL,
> > +					    mux_idx);
> > +		}
> > +	}
> > +}
> > +
> > +/*
> > + * HDA PCM callbacks
> > + */
> > +static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
> > +			 struct hda_codec *codec,
> > +			 struct snd_pcm_substream *substream) {
> > +	struct hdmi_spec *spec = codec->spec;
> > +	struct snd_pcm_runtime *runtime = substream->runtime;
> > +	int pin_idx, cvt_idx, mux_idx = 0;
> > +	struct hdmi_spec_per_pin *per_pin;
> > +	struct hdmi_eld *eld;
> > +	struct hdmi_spec_per_cvt *per_cvt = NULL;
> > +	int err;
> > +
> > +	/* Validate hinfo */
> > +	pin_idx = hinfo_to_pin_index(spec, hinfo);
> > +	if (snd_BUG_ON(pin_idx < 0))
> > +		return -EINVAL;
> > +	per_pin = get_pin(spec, pin_idx);
> > +	eld = &per_pin->sink_eld;
> > +
> > +	err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, &mux_idx);
> > +	if (err < 0)
> > +		return err;
> > +
> > +	per_cvt = get_cvt(spec, cvt_idx);
> >  	/* Claim converter */
> >  	per_cvt->assigned = 1;
> >  	hinfo->nid = per_cvt->cvt_nid;
> >
> > -	snd_hda_codec_write(codec, per_pin->pin_nid, 0,
> > +	snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
> >  			    AC_VERB_SET_CONNECT_SEL,
> >  			    mux_idx);
> 
> You shouldn't mix this fix into your patch.
> This change should be applied as a separate patch and go to stable kernel.
> 
> I'll cook up your patch to remove that chunk and apply the rest as is.
> 
Okay, thanks a lot. :)

Thanks
--xingchao
> 
> thanks,
> 
> Takashi


More information about the Alsa-devel mailing list