From dc70272cc184b945cf526a23999fc8645e76bbed Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 18 May 2026 19:37:44 +0000 Subject: [PATCH] drm/rockchip: dw_hdmi: Propagate bus format to display driver The HDMI block is currently hardcoded to expect RGB output from the display controller. However, the VOP in some SoCs are capable of YCbCr output to the HDMI block. Read the negotiated bus format from the bridge state and propagate it to the CRCT state in form of output mode and bus format. Treat the format MEDIA_BUS_FMT_FIXED as RGB888 and reject any unsupported formats. This has no inpact until dw-hdmi bridge is fully converted to a HDMI bridge and also adds support for the "color format" connector property. Signed-off-by: Jonas Karlman Tested-by: Heiko Stuebner #rk3328 Signed-off-by: Heiko Stuebner Link: https://patch.msgid.link/20260518193748.2482823-11-jonas@kwiboo.se --- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 44 ++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 6bf86a3f3c51..5ec079eafbf7 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -275,6 +276,26 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) dev_dbg(hdmi->dev, "vop %s output to hdmi\n", ret ? "LIT" : "BIG"); } +static u32 dw_hdmi_rockchip_get_bus_format(struct drm_encoder *encoder, + struct drm_connector_state *conn_state) +{ + struct drm_bridge *bridge __free(drm_bridge_put) = NULL; + struct drm_bridge_state *bridge_state; + + bridge = drm_bridge_chain_get_first_bridge(encoder); + if (!bridge) + return 0; + + bridge_state = drm_atomic_get_bridge_state(conn_state->state, bridge); + if (!bridge_state) + return 0; + + if (bridge_state->input_bus_cfg.format != MEDIA_BUS_FMT_FIXED) + return bridge_state->input_bus_cfg.format; + + return bridge_state->output_bus_cfg.format; +} + static int dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, @@ -283,9 +304,30 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); union phy_configure_opts opts = {}; + u32 bus_format; + + bus_format = dw_hdmi_rockchip_get_bus_format(encoder, conn_state); + + switch (bus_format) { + case MEDIA_BUS_FMT_FIXED: + bus_format = MEDIA_BUS_FMT_RGB888_1X24; + fallthrough; + case MEDIA_BUS_FMT_RGB888_1X24: + case MEDIA_BUS_FMT_RGB101010_1X30: + case MEDIA_BUS_FMT_YUV8_1X24: + case MEDIA_BUS_FMT_YUV10_1X30: + s->output_mode = ROCKCHIP_OUT_MODE_AAAA; + break; + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: + case MEDIA_BUS_FMT_UYYVYY10_0_5X30: + s->output_mode = ROCKCHIP_OUT_MODE_YUV420; + break; + default: + return -EINVAL; + } - s->output_mode = ROCKCHIP_OUT_MODE_AAAA; s->output_type = DRM_MODE_CONNECTOR_HDMIA; + s->bus_format = bus_format; if (!hdmi->phy || !conn_state->hdmi.tmds_char_rate) return 0;