> Subject: [PATCH v2] drm/i915/audio: treat UHBR SST like MST for
> cpu_transcoder signalling
> 
> Both DP MST and UHBR SST require the audio component to use a real
> cpu_transcoder (>= 0) value to identify the audio stream on a port.
> For DP MST this was already handled; for UHBR SST it was not, causing
> pin_eld_notify() to signal cpu_transcoder = -1 (the legacy SST sentinel) and
> find_audio_state() to skip the per-transcoder entry for the UHBR stream.
> 
> After suspend/resume or replug, the ELD lookup fails and audio goes silent. 
> Fix
> by detecting UHBR SST alongside DP MST when deciding whether a real
> cpu_transcoder value must be used for audio state addressing, in both the
> pin_eld_notify() signalling and the
> find_audio_state() lookup paths.
> 
> --v2:
> - Commit message and comment update. (Suraj)
> - Change function name has_mst_transcoder. (Suraj)
> - Avoid Live crtc access in find_audio_state. (Suraj)
> 
> Signed-off-by: Kai Vehmanen <[email protected]>
> Signed-off-by: Mitul Golani <[email protected]>
> ---
>  drivers/gpu/drm/i915/display/intel_audio.c    | 61 ++++++++++++++-----
>  .../gpu/drm/i915/display/intel_display_core.h |  1 +
>  2 files changed, 48 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_audio.c
> b/drivers/gpu/drm/i915/display/intel_audio.c
> index 9729f1837d2c..7a2bc73744a3 100644
> --- a/drivers/gpu/drm/i915/display/intel_audio.c
> +++ b/drivers/gpu/drm/i915/display/intel_audio.c
> @@ -38,6 +38,7 @@
>  #include "intel_de.h"
>  #include "intel_display_types.h"
>  #include "intel_display_wa.h"
> +#include "intel_dp.h"
>  #include "intel_lpe_audio.h"
> 
>  /**
> @@ -696,6 +697,21 @@ static void ibx_audio_codec_enable(struct
> intel_encoder *encoder,
>       mutex_unlock(&display->audio.mutex);
>  }
> 
> +/*
> + * 128b/132b transport is used for both DP MST and UHBR SST. As far as
> +audio
> + * is concerned the hardware behaves identically in both cases: the
> +port can
> + * carry multiple streams and the cpu_transcoder is a meaningful (>= 0,
> + * possibly > 0) identifier of the audio stream on that port. Legacy
> +8b/10b
> + * SST instead carries a single stream per port, for which the audio
> +drivers
> + * expect the cpu_transcoder to be signalled as -1.
> + */
> +static
> +bool intel_audio_needs_cpu_transcoder_id(const struct intel_crtc_state
> +*crtc_state) {
> +     return intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) ||
> +            intel_dp_is_uhbr(crtc_state);
> +}
> +
>  bool intel_audio_compute_config(struct intel_encoder *encoder,
>                               struct intel_crtc_state *crtc_state,
>                               struct drm_connector_state *conn_state) @@
> -762,6 +778,8 @@ void intel_audio_codec_enable(struct intel_encoder
> *encoder,
>       audio_state = &display->audio.state[cpu_transcoder];
> 
>       audio_state->encoder = encoder;
> +     audio_state->needs_cpu_transcoder_id =
> +                     intel_audio_needs_cpu_transcoder_id(crtc_state);
>       BUILD_BUG_ON(sizeof(audio_state->eld) != sizeof(crtc_state->eld));
>       memcpy(audio_state->eld, crtc_state->eld, sizeof(audio_state->eld));
> 
> @@ -769,8 +787,12 @@ void intel_audio_codec_enable(struct intel_encoder
> *encoder,
> 
>       if (acomp && acomp->base.audio_ops &&
>           acomp->base.audio_ops->pin_eld_notify) {
> -             /* audio drivers expect cpu_transcoder = -1 to indicate Non-
> MST cases */
> -             if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))
> +             /*
> +              * Audio drivers expect cpu_transcoder = -1 to indicate
> +              * Non-MST/HBR cases. MST and UHBR SST are addressed by
> +              * a real cpu_transcoder.
> +              */
> +             if (!intel_audio_needs_cpu_transcoder_id(crtc_state))
>                       cpu_transcoder = -1;
>               acomp->base.audio_ops->pin_eld_notify(acomp-
> >base.audio_ops->audio_ptr,
>                                                     (int)port,
> (int)cpu_transcoder); @@ -819,14 +841,19 @@ void
> intel_audio_codec_disable(struct intel_encoder *encoder,
>       audio_state = &display->audio.state[cpu_transcoder];
> 
>       audio_state->encoder = NULL;
> +     audio_state->needs_cpu_transcoder_id = false;
>       memset(audio_state->eld, 0, sizeof(audio_state->eld));
> 
>       mutex_unlock(&display->audio.mutex);
> 
>       if (acomp && acomp->base.audio_ops &&
>           acomp->base.audio_ops->pin_eld_notify) {
> -             /* audio drivers expect cpu_transcoder = -1 to indicate Non-
> MST cases */
> -             if (!intel_crtc_has_type(old_crtc_state,
> INTEL_OUTPUT_DP_MST))
> +             /*
> +              * Audio drivers expect cpu_transcoder = -1 to indicate
> +              * Non-MST/HBR cases. MST and UHBR SST are addressed by
> +              * a real cpu_transcoder.
> +              */
> +             if (!intel_audio_needs_cpu_transcoder_id(old_crtc_state))
>                       cpu_transcoder = -1;
>               acomp->base.audio_ops->pin_eld_notify(acomp-
> >base.audio_ops->audio_ptr,
>                                                     (int)port,
> (int)cpu_transcoder); @@ -1118,18 +1145,24 @@ static int
> intel_audio_component_get_cdclk_freq(struct device *kdev)  }
> 
>  /*
> - * get the intel audio state according to the parameter port and
> cpu_transcoder
> - * MST & (cpu_transcoder >= 0): return the
> audio.state[cpu_transcoder].encoder],
> + * Get the intel audio state according to the parameter port and
> + cpu_transcoder
> + *
> + * A "MST transcoder" below means 128b/132b transport, i.e. either DP
> + MST or
> + * UHBR SST, both of which use a meaningful (>= 0) cpu_transcoder to
> + identify
> + * the audio stream on a port (see intel_audio_needs_cpu_transcoder_id()):
> + *
> + * MST transcoder & (cpu_transcoder >= 0): return the
> + audio.state[cpu_transcoder],
>   *   when port is matched
> - * MST & (cpu_transcoder < 0): this is invalid
> - * Non-MST & (cpu_transcoder >= 0): only cpu_transcoder = 0 (the first device
> entry)
> - *   will get the right intel_encoder with port matched
> - * Non-MST & (cpu_transcoder < 0): get the right intel_encoder with port
> matched
> + * MST transcoder & (cpu_transcoder < 0): this is invalid
> + * Non-MST transcoder & (cpu_transcoder >= 0): only cpu_transcoder = 0 (the
> first
> + *   device entry) will get the right intel_encoder with port matched
> + * Non-MST transcoder & (cpu_transcoder < 0): get the right intel_encoder
> with
> + *   port matched
>   */
>  static struct intel_audio_state *find_audio_state(struct intel_display 
> *display,
>                                                 int port, int cpu_transcoder)
>  {
> -     /* MST */
> +     /* MST, or UHBR SST. */
>       if (cpu_transcoder >= 0) {
>               struct intel_audio_state *audio_state;
>               struct intel_encoder *encoder;
> @@ -1142,11 +1175,11 @@ static struct intel_audio_state
> *find_audio_state(struct intel_display *display,
>               encoder = audio_state->encoder;
> 
>               if (encoder && encoder->port == port &&
> -                 encoder->type == INTEL_OUTPUT_DP_MST)
> +                 audio_state->needs_cpu_transcoder_id)
>                       return audio_state;
>       }
> 
> -     /* Non-MST */
> +     /* Legacy SST. */
>       if (cpu_transcoder > 0)
>               return NULL;
> 
> @@ -1158,7 +1191,7 @@ static struct intel_audio_state
> *find_audio_state(struct intel_display *display,
>               encoder = audio_state->encoder;
> 
>               if (encoder && encoder->port == port &&
> -                 encoder->type != INTEL_OUTPUT_DP_MST)
> +                 !audio_state->needs_cpu_transcoder_id)
>                       return audio_state;
>       }
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h
> b/drivers/gpu/drm/i915/display/intel_display_core.h
> index 17f7d3abdb9c..a6129d0b523f 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_core.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
> @@ -97,6 +97,7 @@ struct intel_wm_funcs {  struct intel_audio_state {
>       struct intel_encoder *encoder;
>       u8 eld[MAX_ELD_BYTES];
> +     bool needs_cpu_transcoder_id;  /* MST, or SST on UHBR link */

Another thing The comment should sit on top on the variable field rather than 
beside it.

Regards,
Suraj Kandpal

>  };
> 
>  struct intel_audio {
> --
> 2.48.1

Reply via email to