From: Dmitry Baryshkov Date: Wed, 7 Jan 2026 18:15:06 +0000 (+0200) Subject: drm/display: bridge_connector: dynamically generate HDMI callbacks X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ae219fdc952c315182b471f5aa71b379584b70ca;p=thirdparty%2Fkernel%2Flinux.git drm/display: bridge_connector: dynamically generate HDMI callbacks The rest of the DRM framework uses presence of the callbacks to check if the particular infoframe is supported. Register HDMI callbacks dynamically, basing on the corresponding drm_bridge ops. Acked-by: Maxime Ripard Link: https://patch.msgid.link/20260107-limit-infoframes-2-v4-9-213d0d3bd490@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index ca6a72a4cf80..ba8ff113cff1 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -123,6 +123,14 @@ struct drm_bridge_connector { * DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER). */ struct drm_bridge *bridge_hdmi_cec; + + /** + * @hdmi_funcs: + * + * The particular &drm_connector_hdmi_funcs implementation for this + * bridge connector. + */ + struct drm_connector_hdmi_funcs hdmi_funcs; }; #define to_drm_bridge_connector(x) \ @@ -465,12 +473,7 @@ static int drm_bridge_connector_clear_audio_infoframe(struct drm_connector *conn if (!bridge) return -EINVAL; - if (bridge->ops & DRM_BRIDGE_OP_HDMI_AUDIO) - return bridge->funcs->hdmi_clear_audio_infoframe(bridge); - - drm_dbg_driver(connector->dev, "Unsupported HDMI Audio InfoFrame\n"); - - return 0; + return bridge->funcs->hdmi_clear_audio_infoframe(bridge); } static int drm_bridge_connector_write_audio_infoframe(struct drm_connector *connector, @@ -484,12 +487,7 @@ static int drm_bridge_connector_write_audio_infoframe(struct drm_connector *conn if (!bridge) return -EINVAL; - if (bridge->ops & DRM_BRIDGE_OP_HDMI_AUDIO) - return bridge->funcs->hdmi_write_audio_infoframe(bridge, buffer, len); - - drm_dbg_driver(connector->dev, "Unsupported HDMI Audio InfoFrame\n"); - - return 0; + return bridge->funcs->hdmi_write_audio_infoframe(bridge, buffer, len); } static int drm_bridge_connector_clear_hdr_drm_infoframe(struct drm_connector *connector) @@ -502,12 +500,7 @@ static int drm_bridge_connector_clear_hdr_drm_infoframe(struct drm_connector *co if (!bridge) return -EINVAL; - if (bridge->ops & DRM_BRIDGE_OP_HDMI_HDR_DRM_INFOFRAME) - return bridge->funcs->hdmi_clear_hdr_drm_infoframe(bridge); - - drm_dbg_driver(connector->dev, "Unsupported HDMI HDR DRM InfoFrame\n"); - - return 0; + return bridge->funcs->hdmi_clear_hdr_drm_infoframe(bridge); } static int drm_bridge_connector_write_hdr_drm_infoframe(struct drm_connector *connector, @@ -521,12 +514,7 @@ static int drm_bridge_connector_write_hdr_drm_infoframe(struct drm_connector *co if (!bridge) return -EINVAL; - if (bridge->ops & DRM_BRIDGE_OP_HDMI_HDR_DRM_INFOFRAME) - return bridge->funcs->hdmi_write_hdr_drm_infoframe(bridge, buffer, len); - - drm_dbg_driver(connector->dev, "Unsupported HDMI HDR DRM InfoFrame\n"); - - return 0; + return bridge->funcs->hdmi_write_hdr_drm_infoframe(bridge, buffer, len); } static int drm_bridge_connector_clear_spd_infoframe(struct drm_connector *connector) @@ -539,12 +527,7 @@ static int drm_bridge_connector_clear_spd_infoframe(struct drm_connector *connec if (!bridge) return -EINVAL; - if (bridge->ops & DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME) - return bridge->funcs->hdmi_clear_spd_infoframe(bridge); - - drm_dbg_driver(connector->dev, "Unsupported HDMI SPD InfoFrame\n"); - - return 0; + return bridge->funcs->hdmi_clear_spd_infoframe(bridge); } static int drm_bridge_connector_write_spd_infoframe(struct drm_connector *connector, @@ -558,12 +541,7 @@ static int drm_bridge_connector_write_spd_infoframe(struct drm_connector *connec if (!bridge) return -EINVAL; - if (bridge->ops & DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME) - return bridge->funcs->hdmi_write_spd_infoframe(bridge, buffer, len); - - drm_dbg_driver(connector->dev, "Unsupported HDMI SPD InfoFrame\n"); - - return 0; + return bridge->funcs->hdmi_write_spd_infoframe(bridge, buffer, len); } static const struct drm_edid * @@ -591,18 +569,22 @@ static const struct drm_connector_hdmi_funcs drm_bridge_connector_hdmi_funcs = { .clear_infoframe = drm_bridge_connector_clear_hdmi_infoframe, .write_infoframe = drm_bridge_connector_write_hdmi_infoframe, }, - .audio = { - .clear_infoframe = drm_bridge_connector_clear_audio_infoframe, - .write_infoframe = drm_bridge_connector_write_audio_infoframe, - }, - .hdr_drm = { - .clear_infoframe = drm_bridge_connector_clear_hdr_drm_infoframe, - .write_infoframe = drm_bridge_connector_write_hdr_drm_infoframe, - }, - .spd = { - .clear_infoframe = drm_bridge_connector_clear_spd_infoframe, - .write_infoframe = drm_bridge_connector_write_spd_infoframe, - }, + /* audio, hdr_drm and spd are set dynamically during init */ +}; + +static const struct drm_connector_infoframe_funcs drm_bridge_connector_hdmi_audio_infoframe = { + .clear_infoframe = drm_bridge_connector_clear_audio_infoframe, + .write_infoframe = drm_bridge_connector_write_audio_infoframe, +}; + +static const struct drm_connector_infoframe_funcs drm_bridge_connector_hdmi_hdr_drm_infoframe = { + .clear_infoframe = drm_bridge_connector_clear_hdr_drm_infoframe, + .write_infoframe = drm_bridge_connector_write_hdr_drm_infoframe, +}; + +static const struct drm_connector_infoframe_funcs drm_bridge_connector_hdmi_spd_infoframe = { + .clear_infoframe = drm_bridge_connector_clear_spd_infoframe, + .write_infoframe = drm_bridge_connector_write_spd_infoframe, }; static int drm_bridge_connector_audio_startup(struct drm_connector *connector) @@ -971,11 +953,25 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, if (!connector->ycbcr_420_allowed) supported_formats &= ~BIT(HDMI_COLORSPACE_YUV420); + bridge_connector->hdmi_funcs = drm_bridge_connector_hdmi_funcs; + + if (bridge_connector->bridge_hdmi->ops & DRM_BRIDGE_OP_HDMI_AUDIO) + bridge_connector->hdmi_funcs.audio = + drm_bridge_connector_hdmi_audio_infoframe; + + if (bridge_connector->bridge_hdmi->ops & DRM_BRIDGE_OP_HDMI_HDR_DRM_INFOFRAME) + bridge_connector->hdmi_funcs.hdr_drm = + drm_bridge_connector_hdmi_hdr_drm_infoframe; + + if (bridge_connector->bridge_hdmi->ops & DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME) + bridge_connector->hdmi_funcs.spd = + drm_bridge_connector_hdmi_spd_infoframe; + ret = drmm_connector_hdmi_init(drm, connector, bridge_connector->bridge_hdmi->vendor, bridge_connector->bridge_hdmi->product, &drm_bridge_connector_funcs, - &drm_bridge_connector_hdmi_funcs, + &bridge_connector->hdmi_funcs, connector_type, ddc, supported_formats, max_bpc);