HDMI 2.1 PCON devices (e.g. Parade PS196) that do not have an internal
DSC encoder can still forward a DSC-compressed stream from the DP source
to the downstream HDMI 2.1 sink unchanged (passthrough mode). The HDMI
sink (e.g. Lenovo ThinkVision Pro 27UD-10) then decompresses the stream
itself. This mode is signalled by DP_DSC_PASSTHROUGH_IS_SUPPORTED (DPCD
0x060 bit1) on the PCON.

Previously the driver had no awareness of this path: the PCON would fall
back to its autonomous passthrough mode and write 0x160=0x02 by itself,
leaving the source with no control over DSC parameters or DPCD 0x160.

This patch adds explicit driver control of PCON DSC passthrough:

- Detect passthrough capability at connect time from DPCD 0x060 bit1
  combined with the downstream HDMI 2.1 sink's DSC 1.2 support from
  EDID HF-VSDB. Cache the result in connector->dp.pcon_dsc_passthrough
  (same lifecycle as fec_capability and dsc_dpcd).

- Treat the PCON as DSC-capable in intel_dp_has_dsc() when passthrough
  is supported, allowing the normal DSC compute_config path to proceed.

- Derive DSC parameters (slice count, bpc limits) from the downstream
  HDMI sink's EDID DSC capabilities rather than from the PCON encoder
  DPCD (all-zero for passthrough-only PCONs).

- Add PCON passthrough branch in intel_dp_dsc_compute_params() to use
  DSC 1.2 defaults (version 1.2, convert_rgb per output format,
  line_buf_depth=13, block_pred=true) instead of the PCON dsc_dpcd
  fields which reflect passthrough device constraints, not the actual
  HDMI sink decompressor.

- Skip align_max_sink_dsc_input_bpp() for PCON passthrough to prevent
  the PCON dsc_dpcd color_depth_cap from zeroing pipe.max_bpp.

- Write DP_DSC_PASSTHROUGH_EN (0x160 bit1) to the PCON via
  intel_dp_sink_set_dsc_passthrough() on enable, and clear it on
  disable. The existing MST hub passthrough path is preserved; the PCON
  case is handled by redirecting aux to intel_dp->aux (SST) or
  connector->mst.port->aux (MST via REMOTE_DPCD_WRITE) when
  pcon_dsc_passthrough is set.

- Short-circuit intel_dp_sink_set_dsc_decompression() for PCON
  passthrough since the PCON itself does not decompress.

- Add passthrough branch in intel_dp_mode_valid_with_dsc() to use
  EDID max_slices capped by PCON dsc_dpcd slice capability.

Tested with Parade PS196G (HW 0.2, SW 241.62) connected directly (SST)
and via PS8650 MST hub to a Lenovo ThinkVision Pro 27UD-10 (HDMI 2.1,
DSC 1.2, max 16 slices, 400 MHz/slice). At 4K@240Hz DSC compression is
required; driver now writes 0x160=0x02 explicitly and DSC parameters are
correctly derived from the HDMI sink EDID. Depends on the preceding
drm/dp/mst patch for MST topology support.

Signed-off-by: Xiao Lu <[email protected]>
---
v8: Sincere apologies - v7 was sent with a typo that left the old
    single-parameter signature for intel_dp_pcon_set_dsc_passthrough_cap()
    in place, causing the build failure. This version correctly updates
    the function to accept an explicit struct intel_connector * parameter.

v7: Fix intel_dp_pcon_set_dsc_passthrough_cap() to accept an explicit
    connector parameter instead of deriving it from
    intel_dp->attached_connector, fixing incorrect root SST connector
    access in MST paths. Make the function non-static and add a header
    declaration so intel_dp_mst.c can call it. Update both SST
    (intel_dp_set_edid) and MST (mst_connector_get_ddc_modes) call
    sites to pass the correct per-connector context.
    Remove the !connector->mst.port early-return so MST connectors
    can also have pcon_dsc_passthrough set, enabling the correct
    REMOTE_DPCD_WRITE path in intel_dp_sink_set_dsc_passthrough().
    Remove the !connector->mst.dp guard in
    intel_dp_sink_set_dsc_decompression() so MST PCON passthrough
    connectors are also short-circuited correctly.
    Fix intel_dp_mode_valid_with_dsc() to handle all-zero PCON dsc_dpcd
    by falling back to EDID max_slices when pcon_max is zero.

v6: Add intel_dp_pcon_set_dsc_passthrough_cap() call in
    mst_connector_get_ddc_modes() after EDID parsing so that MST
    connectors also have pcon_dsc_passthrough evaluated using the
    correct display_info.hdmi.dsc_cap values.
    Fix checkpatch warnings: break long lines in the non-passthrough
    branch of intel_dp_dsc_compute_params() and fix parenthesis
    alignment in drm_dbg_kms() call.

v5: Split into two patches: the drm/dp/mst fix for recognizing
    DP-to-HDMI PCON as virtual DPCD is now patch 1/2.
    Inline PCON passthrough DSC parameter overrides into
    intel_dp_dsc_compute_params() instead of a separate function;
    fix convert_rgb to depend on output_format instead of being
    unconditionally true.
    Remove intel_dp_pcon_set_dsc_passthrough_cap() call from
    intel_dp_get_dsc_sink_cap() - keep only the intel_dp_set_edid()
    call so MST streams do not incorrectly update the root connector.
    Pass INT_MAX as src_max_slice_width to intel_hdmi_dsc_get_num_slices()
    so only the HDMI spec 2720px limit applies.
    Add hdisplay divisibility check for the computed slice count.
    Add PCON passthrough branch in intel_dp_mode_valid_with_dsc() using
    EDID max_slices capped by PCON dsc_dpcd slice capability.

v4: Rebase onto drm-intel-next-2026-09-03 to fix compilation failures.

v3: Restrict PCON DSC passthrough to SST direct connections only.

v2: Fix build failure on drm-tip.
---
 .../drm/i915/display/intel_display_types.h    |   1 +
 drivers/gpu/drm/i915/display/intel_dp.c       | 286 +++++++++++++++---
 drivers/gpu/drm/i915/display/intel_dp.h       |   2 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |   7 +
 4 files changed, 262 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 5f0fe18c0..90d77aa4d 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -564,6 +564,7 @@ struct intel_connector {
                u8 dsc_hblank_expansion_quirk:1;
                u8 dsc_throughput_quirk:1;
                u8 dsc_decompression_enabled:1;
+               u8 pcon_dsc_passthrough:1; /* PCON DSC PT supported and HDMI 
sink DSC 1.2 */
 
                struct {
                        struct {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index c46397edf..83d3a7648 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1259,8 +1259,14 @@ bool intel_dp_has_dsc(const struct intel_connector 
*connector)
            connector->panel.vbt.edp.dsc_disable)
                return false;
 
-       if (!drm_dp_sink_supports_dsc(connector->dp.dsc_dpcd))
-               return false;
+       if (!drm_dp_sink_supports_dsc(connector->dp.dsc_dpcd)) {
+               /*
+                * PCON passthrough: PCON has no DSC decoder so dsc_dpcd is
+                * zero, but if pcon_dsc_passthrough is set (cached at connect
+                * time) the downstream HDMI 2.1 sink will decompress instead.
+                */
+               return connector->dp.pcon_dsc_passthrough;
+       }
 
        return true;
 }
@@ -1866,28 +1872,49 @@ static int intel_dp_dsc_compute_params(const struct 
intel_connector *connector,
        if (ret)
                return ret;
 
-       vdsc_cfg->dsc_version_major =
-               (connector->dp.dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] &
-                DP_DSC_MAJOR_MASK) >> DP_DSC_MAJOR_SHIFT;
-       vdsc_cfg->dsc_version_minor =
-               min(intel_dp_source_dsc_version_minor(display),
-                   intel_dp_sink_dsc_version_minor(connector->dp.dsc_dpcd));
-       if (vdsc_cfg->convert_rgb)
-               vdsc_cfg->convert_rgb =
-                       connector->dp.dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - 
DP_DSC_SUPPORT] &
-                       DP_DSC_RGB;
-
-       vdsc_cfg->line_buf_depth = min(INTEL_DP_DSC_MAX_LINE_BUF_DEPTH,
-                                      
drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd));
-       if (!vdsc_cfg->line_buf_depth) {
-               drm_dbg_kms(display->drm,
-                           "DSC Sink Line Buffer Depth invalid\n");
-               return -EINVAL;
-       }
+       if (connector->dp.pcon_dsc_passthrough) {
+               /*
+                * For PCON passthrough the HDMI 2.1 sink decompresses, not the
+                * PCON. The PCON dsc_dpcd fields reflect passthrough device
+                * constraints and are not valid for configuring the source VDSC
+                * engine. Use DSC 1.2 sink defaults instead.
+                */
+               vdsc_cfg->dsc_version_major = 1;
+               vdsc_cfg->dsc_version_minor = 
min(intel_dp_source_dsc_version_minor(display), 2);
+               /* Only set convert_rgb for RGB output; leave unchanged for 
YCbCr */
+               if (vdsc_cfg->convert_rgb)
+                       vdsc_cfg->convert_rgb =
+                               (crtc_state->output_format == 
INTEL_OUTPUT_FORMAT_RGB);
+               vdsc_cfg->line_buf_depth = min(INTEL_DP_DSC_MAX_LINE_BUF_DEPTH, 
13);
+               vdsc_cfg->block_pred_enable = true;
+       } else {
+               vdsc_cfg->dsc_version_major =
+                       (connector->dp.dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] &
+                        DP_DSC_MAJOR_MASK) >> DP_DSC_MAJOR_SHIFT;
+               vdsc_cfg->dsc_version_minor =
+                       min(intel_dp_source_dsc_version_minor(display),
+                           
intel_dp_sink_dsc_version_minor(connector->dp.dsc_dpcd));
+               if (vdsc_cfg->convert_rgb) {
+                       u8 color_fmt_cap =
+                               
connector->dp.dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP -
+                                                      DP_DSC_SUPPORT];
+
+                       vdsc_cfg->convert_rgb = color_fmt_cap & DP_DSC_RGB;
+               }
+
+               vdsc_cfg->line_buf_depth =
+                       min(INTEL_DP_DSC_MAX_LINE_BUF_DEPTH,
+                           
drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd));
+               if (!vdsc_cfg->line_buf_depth) {
+                       drm_dbg_kms(display->drm,
+                                   "DSC Sink Line Buffer Depth invalid\n");
+                       return -EINVAL;
+               }
 
-       vdsc_cfg->block_pred_enable =
-               connector->dp.dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - 
DP_DSC_SUPPORT] &
-               DP_DSC_BLK_PREDICTION_IS_SUPPORTED;
+               vdsc_cfg->block_pred_enable =
+                       connector->dp.dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - 
DP_DSC_SUPPORT] &
+                       DP_DSC_BLK_PREDICTION_IS_SUPPORTED;
+       }
 
        return drm_dsc_compute_rc_parameters(vdsc_cfg);
 }
@@ -2316,6 +2343,10 @@ void intel_dp_dsc_reset_config(struct intel_crtc_state 
*crtc_state)
        memset(&crtc_state->dsc.config, 0, sizeof(crtc_state->dsc.config));
 }
 
+static bool intel_dp_pcon_passthrough_dsc_slice_config(struct intel_dp 
*intel_dp,
+                                                      const struct 
intel_crtc_state *crtc_state,
+                                                      struct 
intel_dsc_slice_config *config_ret);
+
 int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
                                struct intel_crtc_state *pipe_config,
                                struct drm_connector_state *conn_state,
@@ -2354,7 +2385,19 @@ int intel_dp_dsc_compute_config(struct intel_dp 
*intel_dp,
                }
        }
 
-       if (!intel_dp_dsc_get_slice_config(connector, adjusted_mode->crtc_clock,
+       if (connector->dp.pcon_dsc_passthrough) {
+               /*
+                * PCON passthrough: no PCON encoder DPCD, derive slice config
+                * from the downstream HDMI 2.1 sink DSC capabilities in EDID.
+                */
+               if (!intel_dp_pcon_passthrough_dsc_slice_config(intel_dp,
+                                                               pipe_config,
+                                                               
&pipe_config->dsc.slice_config)) {
+                       drm_dbg_kms(display->drm,
+                                   "PCON DSC passthrough: no valid slice 
config\n");
+                       return -EINVAL;
+               }
+       } else if (!intel_dp_dsc_get_slice_config(connector, 
adjusted_mode->crtc_clock,
                                           adjusted_mode->crtc_hdisplay, 
num_joined_pipes,
                                           &pipe_config->dsc.slice_config))
                return -EINVAL;
@@ -2485,10 +2528,27 @@ bool intel_dp_mode_valid_with_dsc(struct 
intel_connector *connector,
                                                         num_joined_pipes,
                                                         output_format,
                                                         pipe_bpp, INT_MAX);
-       int dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
-                                                          mode_clock,
-                                                          mode_hdisplay,
-                                                          num_joined_pipes);
+       int dsc_slice_count;
+
+       if (connector->dp.pcon_dsc_passthrough) {
+               /*
+                * For PCON passthrough, use the HDMI sink EDID max_slices
+                * capped by the PCON's own slice capability from dsc_dpcd.
+                * If the PCON dsc_dpcd is all-zero, fall back to EDID only.
+                */
+               const struct drm_display_info *info = 
&connector->base.display_info;
+               int pcon_max = 
drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd,
+                                                              false);
+
+               dsc_slice_count = pcon_max ?
+                       min_t(int, info->hdmi.dsc_cap.max_slices, pcon_max) :
+                       info->hdmi.dsc_cap.max_slices;
+       } else {
+               dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
+                                                              mode_clock,
+                                                              mode_hdisplay,
+                                                              
num_joined_pipes);
+       }
 
        if (min_bpp_x16 <= 0 || min_bpp_x16 > max_bpp_x16)
                return false;
@@ -2683,8 +2743,33 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
                return false;
        }
 
-       if (dsc && !intel_dp_dsc_compute_pipe_bpp_limits(connector, limits))
-               return false;
+       if (dsc) {
+               if (connector->dp.pcon_dsc_passthrough) {
+                       /*
+                        * PCON passthrough: PCON has no DSC encoder DPCD so
+                        * intel_dp_dsc_compute_pipe_bpp_limits() would see
+                        * all-zero dsc_dpcd and fail.  Use the downstream HDMI
+                        * sink DSC bpc cap to constrain the pipe bpp instead.
+                        */
+                       const struct drm_display_info *info =
+                               &connector->base.display_info;
+                       u8 hdmi_max_bpc = info->hdmi.dsc_cap.bpc_supported ?: 8;
+                       int dsc_min_bpc = intel_dp_dsc_min_src_input_bpc();
+                       int dsc_max_bpc = min_t(int,
+                                               
intel_dp_dsc_max_src_input_bpc(display),
+                                               hdmi_max_bpc);
+
+                       limits->pipe.min_bpp = max(limits->pipe.min_bpp,
+                                                  dsc_min_bpc * 3);
+                       limits->pipe.max_bpp = min(limits->pipe.max_bpp,
+                                                  dsc_max_bpc * 3);
+
+                       if (limits->pipe.min_bpp > limits->pipe.max_bpp)
+                               return false;
+               } else if (!intel_dp_dsc_compute_pipe_bpp_limits(connector, 
limits)) {
+                       return false;
+               }
+       }
 
        /*
         * crtc_state->pipe_bpp is the non-DP specific baseline (platform /
@@ -2697,7 +2782,7 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
         */
        limits->pipe.max_bpp = clamp(crtc_state->pipe_bpp, limits->pipe.min_bpp,
                                     limits->pipe.max_bpp);
-       if (dsc)
+       if (dsc && !connector->dp.pcon_dsc_passthrough)
                limits->pipe.max_bpp = align_max_sink_dsc_input_bpp(connector,
                                                                    
limits->pipe.max_bpp);
 
@@ -3716,6 +3801,10 @@ intel_dp_sink_set_dsc_decompression(struct 
intel_connector *connector,
 {
        struct intel_display *display = to_intel_display(connector);
 
+       /* PCON passthrough: PCON forwards the stream, sink decompresses. */
+       if (connector->dp.pcon_dsc_passthrough)
+               return;
+
        if (write_dsc_decompression_flag(connector->dp.dsc_decompression_aux,
                                         DP_DECOMPRESSION_EN, enable) < 0)
                drm_dbg_kms(display->drm,
@@ -3728,8 +3817,22 @@ intel_dp_sink_set_dsc_passthrough(const struct 
intel_connector *connector,
                                  bool enable)
 {
        struct intel_display *display = to_intel_display(connector);
-       struct drm_dp_aux *aux = connector->mst.port ?
-                                connector->mst.port->passthrough_aux : NULL;
+       struct drm_dp_aux *aux = NULL;
+
+       if (connector->dp.pcon_dsc_passthrough) {
+               /*
+                * HDMI 2.1 PCON passthrough: write DP_DSC_PASSTHROUGH_EN
+                * directly to the PCON so it forwards the compressed stream
+                * to the HDMI sink. For SST use the root port aux; for MST
+                * use the MST port aux which routes via REMOTE_DPCD_WRITE.
+                */
+               if (connector->mst.port)
+                       aux = &connector->mst.port->aux;
+               else
+                       aux = &intel_attached_dp((struct intel_connector 
*)connector)->aux;
+       } else if (connector->mst.port) {
+               aux = connector->mst.port->passthrough_aux;
+       }
 
        if (!aux)
                return;
@@ -3737,7 +3840,7 @@ intel_dp_sink_set_dsc_passthrough(const struct 
intel_connector *connector,
        if (write_dsc_decompression_flag(aux,
                                         DP_DSC_PASSTHROUGH_EN, enable) < 0)
                drm_dbg_kms(display->drm,
-                           "Failed to %s sink compression passthrough state\n",
+                           "Failed to %s DSC passthrough\n",
                            str_enable_disable(enable));
 }
 
@@ -4259,6 +4362,113 @@ void intel_dp_check_frl_training(struct intel_dp 
*intel_dp)
        }
 }
 
+/*
+ * intel_dp_pcon_set_dsc_passthrough_cap - cache PCON DSC passthrough 
capability
+ *
+ * Called once at connect time (from intel_dp_get_dsc_sink_cap()) after
+ * dsc_dpcd and the HDMI sink EDID have been read. Caches the result in
+ * connector->dp.pcon_dsc_passthrough so modeset paths can read it cheaply
+ * without repeating the DPCD and EDID lookups.
+ *
+ * A PCON supports DSC passthrough when it explicitly advertises
+ * DP_DSC_PASSTHROUGH_IS_SUPPORTED (DPCD 0x060 bit1) and the downstream
+ * HDMI 2.1 sink supports DSC 1.2. The compressed stream produced by the
+ * source VDSC engine is forwarded unchanged through the PCON to the HDMI
+ * sink for decompression (DP_DSC_ENABLE bit1 on the PCON).
+ */
+void
+intel_dp_pcon_set_dsc_passthrough_cap(struct intel_dp *intel_dp,
+                                     struct intel_connector *connector)
+{
+       const struct drm_display_info *info = &connector->base.display_info;
+
+       connector->dp.pcon_dsc_passthrough = false;
+
+       /*
+        * Check PCON HDMI 2.1 capability directly from this connector's
+        * display_info so that MST connectors use their own EDID data
+        * rather than intel_dp->attached_connector (the SST root connector).
+        */
+       if (!drm_dp_is_branch(intel_dp->dpcd))
+               return;
+
+       if (!info->is_hdmi)
+               return;
+
+       if (!info->hdmi.max_frl_rate_per_lane)
+               return;
+
+       if (!(connector->dp.dsc_dpcd[0] & DP_DSC_PASSTHROUGH_IS_SUPPORTED))
+               return;
+
+       connector->dp.pcon_dsc_passthrough = info->hdmi.dsc_cap.v_1p2;
+}
+
+static bool
+intel_dp_pcon_passthrough_dsc_slice_config(struct intel_dp *intel_dp,
+                                          const struct intel_crtc_state 
*crtc_state,
+                                          struct intel_dsc_slice_config 
*config_ret)
+{
+       struct intel_display *display = to_intel_display(intel_dp);
+       struct intel_connector *connector = intel_dp->attached_connector;
+       const struct drm_display_info *info = &connector->base.display_info;
+       int num_joined_pipes = intel_crtc_num_joined_pipes(crtc_state);
+       int hdmi_throughput = info->hdmi.dsc_cap.clk_per_slice;
+       int hdmi_max_slices = info->hdmi.dsc_cap.max_slices;
+       int target_slices;
+       int slices_per_pipe;
+
+       /*
+        * Derive the required slice count from the downstream HDMI 2.1 sink
+        * DSC capabilities in EDID (not from the PCON encoder DPCD which is
+        * all-zero for passthrough-only devices).
+        */
+       /*
+        * src_max_slice_width: pass INT_MAX so the HDMI spec limit of 2720px
+        * applies; the source VDSC HW limit (5120px) is higher so it is not
+        * the binding constraint here.
+        * src_max_slices: use hdmi_max_slices as the binding upper limit since
+        * the PCON passthrough capability bit (already checked) is the gate;
+        * the for-loop below further constrains to what the Intel VDSC HW can
+        * actually produce.
+        */
+       target_slices = 
intel_hdmi_dsc_get_num_slices(&crtc_state->hw.adjusted_mode,
+                                                     crtc_state->output_format,
+                                                     hdmi_max_slices, INT_MAX,
+                                                     hdmi_max_slices,
+                                                     hdmi_throughput);
+       if (!target_slices)
+               return false;
+
+       drm_dbg_kms(display->drm,
+                   "PCON DSC passthrough: target %d slices from HDMI sink EDID 
cap"
+                   " (max_slices=%d clk_per_slice=%d MHz)\n",
+                   target_slices, hdmi_max_slices, hdmi_throughput);
+
+       for (slices_per_pipe = 1; slices_per_pipe <= 4; slices_per_pipe++) {
+               struct intel_dsc_slice_config config;
+               int line_slices;
+
+               if (!intel_dsc_get_slice_config(display,
+                                               num_joined_pipes, 
slices_per_pipe,
+                                               &config))
+                       continue;
+
+               line_slices = intel_dsc_line_slice_count(&config);
+               if (line_slices != target_slices)
+                       continue;
+
+               /* Slice count must evenly divide the horizontal display width 
*/
+               if (crtc_state->hw.adjusted_mode.hdisplay % line_slices)
+                       continue;
+
+               *config_ret = config;
+               return true;
+       }
+
+       return false;
+}
+
 static int
 intel_dp_pcon_dsc_enc_slice_height(const struct intel_crtc_state *crtc_state)
 {
@@ -4510,6 +4720,7 @@ void intel_dp_get_dsc_sink_cap(u8 dpcd_rev,
 
        memset(&connector->dp.dsc_branch_caps, 0, 
sizeof(connector->dp.dsc_branch_caps));
        connector->dp.dsc_throughput_quirk = false;
+       connector->dp.pcon_dsc_passthrough = false;
 
        if (dpcd_rev < DP_DPCD_REV_14)
                return;
@@ -6148,6 +6359,12 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
        intel_dp_update_dfp(intel_dp, drm_edid);
        intel_dp_update_420(intel_dp);
 
+       /*
+        * Re-evaluate PCON DSC passthrough capability now that the EDID has
+        * been parsed and display_info.hdmi.dsc_cap is up to date.
+        */
+       intel_dp_pcon_set_dsc_passthrough_cap(intel_dp, connector);
+
        drm_dp_cec_attach(&intel_dp->aux,
                          connector->base.display_info.source_physical_address);
 }
@@ -6170,6 +6387,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 
        intel_dp->dfp.ycbcr_444_to_420 = false;
        connector->base.ycbcr_420_allowed = false;
+       connector->dp.pcon_dsc_passthrough = false;
 
        drm_connector_set_vrr_capable_property(&connector->base,
                                               false);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 04fae203b..42c2fb5c2 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -187,6 +187,8 @@ void intel_dp_sync_state(struct intel_encoder *encoder,
                         const struct intel_crtc_state *crtc_state);
 
 void intel_dp_check_frl_training(struct intel_dp *intel_dp);
+void intel_dp_pcon_set_dsc_passthrough_cap(struct intel_dp *intel_dp,
+                                          struct intel_connector *connector);
 void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp,
                                 const struct intel_crtc_state *crtc_state);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 6a869d0f6..d48fe87ce 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -1451,6 +1451,13 @@ static int mst_connector_get_ddc_modes(struct 
drm_connector *_connector)
 
        ret = intel_connector_update_modes(&connector->base, drm_edid);
 
+       /*
+        * Re-evaluate PCON DSC passthrough capability now that the MST
+        * connector's EDID has been parsed and display_info.hdmi.dsc_cap
+        * is populated.
+        */
+       intel_dp_pcon_set_dsc_passthrough_cap(intel_dp, connector);
+
        drm_edid_free(drm_edid);
 
        if (intel_dp_tunnel_uhbr_lanes_wa_setup(intel_dp)) {
-- 
2.43.0

Reply via email to