[alsa-devel] [RFC PATCH v3 2/3] ALSA: hda - add DP mst audio support
Takashi Iwai
tiwai at suse.de
Fri Oct 21 10:43:43 CEST 2016
On Fri, 21 Oct 2016 10:24:26 +0200,
Yang, Libin wrote:
>
> Hi Takashi,
>
>
> > -----Original Message-----
> > From: Takashi Iwai [mailto:tiwai at suse.de]
> > Sent: Thursday, October 20, 2016 11:34 PM
> > To: libin.yang at linux.intel.com
> > Cc: alsa-devel at alsa-project.org; Yang, Libin <libin.yang at intel.com>; Lin,
> > Mengdong <mengdong.lin at intel.com>
> > Subject: Re: [alsa-devel] [RFC PATCH v3 2/3] ALSA: hda - add DP mst audio
> > support
> >
> > On Thu, 13 Oct 2016 09:49:36 +0200,
> > libin.yang at linux.intel.com wrote:
> > >
> > > From: Libin Yang <libin.yang at linux.intel.com>
> > >
> > > This patch adds the DP mst audio support.
> >
> > A bit more useful texts here please. I know you'll give more explanations in
> > the document in the later patch, but still something better should be
> > mentioned here.
>
> Yes, I will add more description here.
>
> >
> > >
> > > Signed-off-by: Libin Yang <libin.yang at linux.intel.com>
> > > ---
> > > sound/pci/hda/hda_codec.c | 4 +
> > > sound/pci/hda/patch_hdmi.c | 243
> > > +++++++++++++++++++++++++++++++++++----------
> > > 2 files changed, 196 insertions(+), 51 deletions(-)
> > >
> > > diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
> > > index caa2c9d..8a6b0a2 100644
> > > --- a/sound/pci/hda/hda_codec.c
> > > +++ b/sound/pci/hda/hda_codec.c
> > > @@ -468,6 +468,10 @@ static int read_pin_defaults(struct hda_codec
> > *codec)
> > > pin->nid = nid;
>
> ...
>
> > > +
> > >
> > > /* choose an unassigned converter. The conveters in the
> > > * connection list are in the same order as in the codec.
> > > @@ -1008,12 +1078,13 @@ static void intel_not_share_assigned_cvt(struct
> > hda_codec *codec,
> > > break;
> > > }
> > > }
> > > + snd_hda_set_dev_select(codec, nid, dev_id_saved);
> >
> > I guess this revert won't be reached when you break or continue the loop
> > beforehand?
>
> To make it easier to explain, please let me attach the full patched code here:
>
> for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
> int dev_id_saved;
> int dev_num;
>
> per_pin = get_pin(spec, pin_idx);
> /*
> * pin not connected to monitor
> * no need to operate on it
> */
> if (!per_pin->pcm)
> continue;
>
> if ((per_pin->pin_nid == pin_nid) &&
> (per_pin->dev_id == dev_id))
> continue;
>
> /*
> * if per_pin->dev_id >= dev_num,
> * snd_hda_get_dev_select() will fail,
> * and the following operation is unpredictable.
> * So skip this situation.
> */
> dev_num = snd_hda_get_num_devices(codec, per_pin->pin_nid) + 1;
> if (per_pin->dev_id >= dev_num)
> continue;
>
> nid = per_pin->pin_nid;
>
> /*
> * Calling this function should not impact
> * on the device entry selection
> * So let's save the dev id for each pin,
> * and restore it when return
> */
> dev_id_saved = snd_hda_get_dev_select(codec, nid);
> tag 1 snd_hda_set_dev_select(codec, nid, per_pin->dev_id);
> curr = snd_hda_codec_read(codec, nid, 0,
> AC_VERB_GET_CONNECT_SEL, 0);
> if (curr != mux_idx) {
> tag 2 snd_hda_set_dev_select(codec, nid, dev_id_saved);
> continue;
> }
>
>
> /* choose an unassigned converter. The conveters in the
> * connection list are in the same order as in the codec.
> */
> for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
> per_cvt = get_cvt(spec, cvt_idx);
> if (!per_cvt->assigned) {
> codec_dbg(codec,
> "choose cvt %d for pin nid %d\n",
> cvt_idx, nid);
> snd_hda_codec_write_cache(codec, nid, 0,
> AC_VERB_SET_CONNECT_SEL,
> cvt_idx);
> tag 3 break;
> }
> }
> snd_hda_set_dev_select(codec, nid, dev_id_saved);
> }
>
> We need revert dev_id only after we change the dev_id setting before.
> This is done by: snd_hda_set_dev_select(codec, nid, per_pn->dev_id) (tag1)
> There is one "continue" and we have reverted dev_id before continue (tag 2)
> There is one "break" (tag 3). However, this is for another for loop.
OK, fair enough.
> > Also, this rewrite changes the loop completely, so we you should update the
> > comment appropriately. It's no longer scanning the all pins (including
> > unused ones). And I'm not 100% sure whether it's OK to change in that way;
> > the function was written to do that (touching the unused pin as well) on
> > purpose, IIRC.
> >
> > Hm, or is it OK because we are listing always the three pins?
> > More explanation please, either in comments or in the changelog.
> >
>
> This function is a little complex now. Please let me explain it in detail.
>
> As you know, we need this function because we need fix: same cvt is
> connecting to several pins. In this situation, playback on one pin will also
> impact on other pins. Let's assume cvt 1 are connecting to pin 1, 2, 3.
> When we playback on pin1, we need call this function to make sure
> pin 2, 3 is connected to other cvts.
>
> In MST mode, we are using dynamic pcm. If no pcm is attached to
> the pin, it means there is no monitor connected to the pin. So we
> don't need to set the cvt. Let's still assume the cvt 1 are connecting to
> pin 1, 2, 3, 4, 5, 6, 7, 8, 9 (here pin is the virtual pin).
>
> Let's assume playback on pin 1 (which is connected to cvt 1).
> So we should make sure all others pins are not connected to cvt1.
>
> 1) For other pins:
> if (!per_pin->pcm)
> continue;
> This means no monitors is connected to the pin. So we don't care
> the cvt connection because the pin doesn't output sound to monitor.
> (when the virtual pin is connected to monitor later, this function will
> be called in present_sense(), which will make sure the cvt connected
> to the virtual pin is different from the cvt connected to pin 1)
>
> 2) For the following situation:
> dev_num = snd_hda_get_num_devices(codec, per_pin->pin_nid) + 1;
> if (per_pin->dev_id >= dev_num)
> continue;
> The per_pin->dev_id is greater than dev_num. This means no such
> virtual pin. We should skip this situation.
>
> 3) For the following situation:
> if (curr != mux_idx) {
> snd_hda_set_dev_select(codec, nid, dev_id_saved);
> continue;
> }
> It means the cvt connected to the virtual pin is already different to
> the cvt connected to the pin 1. So we don't need to do anything.
>
> 4) Otherwise (the cvt is the same to pin 1), we need change the cvt.
>
> I will add more description for this function in the next version patch.
One thing that is still unclear to me is how to deal with the
unconfigured pins. I thought that the pins with port=non pincfg are
still ignored in hdmi_add_pin() even after your patch. So they won't
be listed in the pins / nids arrays.
Now, your new code only loops over the enumerated pins, i.e. these
unconfigured pins are ignored. What if these pins are connected to
the active converters? I thought excluding such a connection is one
of the purposes of this function, judging from the function
description.
thanks,
Takashi
More information about the Alsa-devel
mailing list