[PATCH 01/24] drm/msm/dp: reject YUV420-only modes without VSC SDP support

From: Dmitry Baryshkov

Date: Wed Jul 22 2026 - 02:41:48 EST


DP conveys YUV 420 colorimetry through a VSC SDP. A sink that advertises
a mode as YUV-420-only therefore cannot be driven at all unless the panel
supports VSC SDP, yet msm_dp_bridge_mode_valid() only used the VSC SDP
capability to decide whether to halve the pixel clock, otherwise letting
such modes through to be validated (and possibly accepted) at the full
RGB clock the sink cannot display.

Reject 420-only modes with MODE_NO_420 when the panel does not support
VSC SDP. With those modes filtered out, being a 420-only mode implies VSC
SDP support, so the YUV-420 test reduces to drm_mode_is_420_only(): drop
msm_dp_is_yuv_420_enabled() and call the DRM helper directly at its two
callers (the DPU encoder already has the connector from the atomic state).

Fixes: df9cf852ca30 ("drm/msm/dp: account for widebus and yuv420 during mode validation")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxxxxxxxx>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 +--
drivers/gpu/drm/msm/dp/dp_display.c | 28 ++++++++++++----------------
drivers/gpu/drm/msm/msm_drv.h | 8 --------
3 files changed, 13 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 778e231d4967..1f20695f81e3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -710,8 +710,7 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb)))
topology->num_cdm++;
} else if (disp_info->intf_type == INTF_DP) {
- if (msm_dp_is_yuv_420_enabled(priv->kms->dp[disp_info->h_tile_instance[0]],
- adj_mode))
+ if (drm_mode_is_420_only(&connector->display_info, adj_mode))
topology->num_cdm++;
}
}
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index dc6f33809ca5..e0c44eef3aba 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -698,6 +698,7 @@ enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge,
u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0;
struct msm_dp *dp;
int mode_pclk_khz = mode->clock;
+ bool is_yuv_420;

dp = to_dp_bridge(bridge)->msm_dp_display;

@@ -709,9 +710,16 @@ enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge,
msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
link_info = &msm_dp_display->panel->link_info;

- if ((drm_mode_is_420_only(&dp->connector->display_info, mode) &&
- msm_dp_display->panel->vsc_sdp_supported) ||
- msm_dp_wide_bus_available(dp))
+ is_yuv_420 = drm_mode_is_420_only(&dp->connector->display_info, mode);
+
+ /*
+ * YUV 420 is carried over DP by signalling the colorimetry through a
+ * VSC SDP, so a 420-only mode cannot be driven without VSC SDP support.
+ */
+ if (is_yuv_420 && !msm_dp_display->panel->vsc_sdp_supported)
+ return MODE_NO_420;
+
+ if (is_yuv_420 || msm_dp_wide_bus_available(dp))
mode_pclk_khz /= 2;

if (mode_pclk_khz > DP_MAX_PIXEL_CLK_KHZ)
@@ -1277,22 +1285,10 @@ void __exit msm_dp_unregister(void)
platform_driver_unregister(&msm_dp_display_driver);
}

-bool msm_dp_is_yuv_420_enabled(const struct msm_dp *msm_dp_display,
- const struct drm_display_mode *mode)
-{
- struct msm_dp_display_private *dp;
- const struct drm_display_info *info;
-
- dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
- info = &msm_dp_display->connector->display_info;
-
- return dp->panel->vsc_sdp_supported && drm_mode_is_420_only(info, mode);
-}
-
bool msm_dp_needs_periph_flush(const struct msm_dp *msm_dp_display,
const struct drm_display_mode *mode)
{
- return msm_dp_is_yuv_420_enabled(msm_dp_display, mode);
+ return drm_mode_is_420_only(&msm_dp_display->connector->display_info, mode);
}

bool msm_dp_wide_bus_available(const struct msm_dp *msm_dp_display)
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 3787db8770ad..3d5679be488e 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -356,8 +356,6 @@ void __exit msm_dp_unregister(void);
int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
struct drm_encoder *encoder, bool yuv_supported);
void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display);
-bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
- const struct drm_display_mode *mode);
bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display,
const struct drm_display_mode *mode);
bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
@@ -382,12 +380,6 @@ static inline void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm
{
}

-static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
- const struct drm_display_mode *mode)
-{
- return false;
-}
-
static inline bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display,
const struct drm_display_mode *mode)
{

--
2.47.3