From: Mario Limonciello <[email protected]> Discover the last bridge in a chain that owns brightness control, attach its relative luminance range to the connector, and forward atomic luminance updates to it.
Do not infer panel luminance support from a terminal panel bridge. Panels still have direct consumers, so their connector integration must remain explicit. Signed-off-by: Mario Limonciello <[email protected]> --- v10: * Split bridge connector integration into a separate patch * Do not special-case panels in the generic bridge connector --- drivers/gpu/drm/display/drm_bridge_connector.c | 48 ++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 81f3e26f6fdf5..bf0a6d162a7d3 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -125,6 +125,12 @@ struct drm_bridge_connector { */ struct drm_bridge *bridge_hdmi_cec; + /** + * @bridge_luminance: + * + * The last bridge in the chain that controls panel luminance. + */ + struct drm_bridge *bridge_luminance; /** * @hdmi_funcs: * @@ -421,6 +427,28 @@ static int drm_bridge_connector_atomic_check(struct drm_connector *connector, return 0; } +static void +drm_bridge_connector_set_luminance(const struct drm_connector_state *conn_state) +{ + struct drm_bridge_connector *bridge_connector = + to_drm_bridge_connector(conn_state->connector); + struct drm_bridge *bridge = bridge_connector->bridge_luminance; + + if (bridge) + bridge->funcs->set_luminance(bridge, conn_state->luminance); +} + +static void +drm_bridge_connector_disable_luminance(const struct drm_connector_state *conn_state) +{ + struct drm_bridge_connector *bridge_connector = + to_drm_bridge_connector(conn_state->connector); + struct drm_bridge *bridge = bridge_connector->bridge_luminance; + + if (bridge) + bridge->funcs->set_luminance(bridge, 0); +} + static const struct drm_connector_helper_funcs drm_bridge_connector_helper_funcs = { .get_modes = drm_bridge_connector_get_modes, .detect_ctx = drm_bridge_connector_detect_ctx, @@ -429,6 +457,8 @@ static const struct drm_connector_helper_funcs drm_bridge_connector_helper_funcs .enable_hpd = drm_bridge_connector_enable_hpd, .disable_hpd = drm_bridge_connector_disable_hpd, .atomic_check = drm_bridge_connector_atomic_check, + .set_luminance = drm_bridge_connector_set_luminance, + .disable_luminance = drm_bridge_connector_disable_luminance, }; static enum drm_mode_status @@ -835,6 +865,7 @@ static void drm_bridge_connector_put_bridges(struct drm_device *dev, void *data) drm_bridge_put(bridge_connector->bridge_hdmi_audio); drm_bridge_put(bridge_connector->bridge_dp_audio); drm_bridge_put(bridge_connector->bridge_hdmi_cec); + drm_bridge_put(bridge_connector->bridge_luminance); } /** @@ -918,6 +949,13 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, drm_bridge_put(bridge_connector->bridge_detect); bridge_connector->bridge_detect = drm_bridge_get(bridge); } + if (bridge->ops & DRM_BRIDGE_OP_LUMINANCE) { + if (!bridge->funcs->set_luminance) + return ERR_PTR(-EINVAL); + + drm_bridge_put(bridge_connector->bridge_luminance); + bridge_connector->bridge_luminance = drm_bridge_get(bridge); + } if (bridge->ops & DRM_BRIDGE_OP_HDMI) { if (bridge_connector->bridge_hdmi) return ERR_PTR(-EBUSY); @@ -1144,6 +1182,16 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, if (panel_bridge) drm_panel_bridge_set_orientation(connector, panel_bridge); + if (IS_ENABLED(CONFIG_DRM_LUMINANCE) && bridge_connector->bridge_luminance && !connector->luminance_property) { + struct drm_bridge *bridge = bridge_connector->bridge_luminance; + + ret = drm_connector_attach_luminance_property(connector, 0, + bridge->luminance_max, + bridge->luminance); + if (ret) + return ERR_PTR(ret); + } + if (support_hdcp && IS_REACHABLE(CONFIG_DRM_DISPLAY_HELPER) && IS_ENABLED(CONFIG_DRM_DISPLAY_HDCP_HELPER)) drm_connector_attach_content_protection_property(connector, true); -- 2.53.0
