The DRM bridge core provides a standard next_bridge field in struct drm_bridge for chaining downstream bridges. Use dp->bridge.next_bridge consistently inside the analogix_dp driver and drop the separate dp->plat_data->next_bridge field.
The next bridge is now resolved in analogix_dp_aux_done_probing(): for Exynos platforms with legacy display-timings a display mode bridge is created and used directly, skipping the endpoint lookup; otherwise the remote endpoint bridge (panel or bridge) is looked up via of_drm_get_bridge_by_endpoint(). The reference returned by of_drm_get_bridge_by_endpoint() is transferred to bridge->next_bridge, and an explicit reference is taken for the devm-managed display mode bridge; the bridge core automatically puts bridge->next_bridge at bridge destroy time, pairing with both. Suggested-by: Heiko Stuebner <[email protected]> Link: https://lore.kernel.org/all/5609825.iZASKD2KPV@diego/ Signed-off-by: Damon Ding <[email protected]> --- .../drm/bridge/analogix/analogix_dp_core.c | 44 +++++++++---------- drivers/gpu/drm/exynos/exynos_dp.c | 15 +------ include/drm/bridge/analogix_dp.h | 1 - 3 files changed, 23 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 38857508d939..853b6a6a7fe4 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -21,6 +21,7 @@ #include <linux/platform_device.h> #include <drm/bridge/analogix_dp.h> +#include <drm/bridge/of-display-mode-bridge.h> #include <drm/display/drm_dp_aux_bus.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> @@ -32,6 +33,8 @@ #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> +#include <video/of_display_timing.h> + #include "analogix_dp_core.h" #include "analogix_dp_reg.h" @@ -909,7 +912,7 @@ analogix_dp_bridge_detect(struct drm_bridge *bridge, struct drm_connector *conne struct analogix_dp_device *dp = to_dp(bridge); enum drm_connector_status status = connector_status_disconnected; - if (dp->plat_data->next_bridge) + if (dp->bridge.next_bridge) return connector_status_connected; if (!analogix_dp_detect_hpd(dp)) @@ -930,8 +933,8 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge, return -EINVAL; } - if (dp->plat_data->next_bridge) { - ret = drm_bridge_attach(dp->encoder, dp->plat_data->next_bridge, bridge, + if (dp->bridge.next_bridge) { + ret = drm_bridge_attach(dp->encoder, dp->bridge.next_bridge, bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR); if (ret) { dev_err(dp->dev, "failed to attach following panel or bridge (%d)\n", ret); @@ -1655,37 +1658,34 @@ struct drm_dp_aux *analogix_dp_get_aux(struct analogix_dp_device *dp) } EXPORT_SYMBOL_GPL(analogix_dp_get_aux); -static void analogix_dp_put_bridge(void *data) -{ - drm_bridge_put(data); -} - static int analogix_dp_aux_done_probing(struct drm_dp_aux *aux) { struct analogix_dp_device *dp = to_dp(aux); struct analogix_dp_plat_data *plat_data = dp->plat_data; + struct drm_bridge *bridge = &dp->bridge, *next_bridge; int port = plat_data->dev_type == EXYNOS_DP ? 0 : 1; - int ret; + + if (plat_data->dev_type == EXYNOS_DP && of_get_display_timings(dp->dev->of_node)) { + next_bridge = devm_drm_of_display_mode_bridge(dp->dev, dp->dev->of_node, + DRM_MODE_CONNECTOR_eDP); + if (IS_ERR(next_bridge)) + return PTR_ERR(next_bridge); + bridge->next_bridge = drm_bridge_get(next_bridge); + + return component_add(dp->dev, plat_data->ops); + } /* * If of_drm_get_bridge_by_endpoint() returns -ENODEV, there may be no * valid panel or bridge nodes. The driver should go on for the * driver-free bridge or the DP mode applications. */ - plat_data->next_bridge = of_drm_get_bridge_by_endpoint(dp->dev->of_node, - port, 0); - if (IS_ERR(plat_data->next_bridge)) { - if (PTR_ERR(plat_data->next_bridge) == -ENODEV) - plat_data->next_bridge = NULL; + bridge->next_bridge = of_drm_get_bridge_by_endpoint(dp->dev->of_node, port, 0); + if (IS_ERR(bridge->next_bridge)) { + if (PTR_ERR(bridge->next_bridge) == -ENODEV) + bridge->next_bridge = NULL; else - return PTR_ERR(plat_data->next_bridge); - } - - if (plat_data->next_bridge) { - ret = devm_add_action_or_reset(dp->dev, analogix_dp_put_bridge, - plat_data->next_bridge); - if (ret) - return ret; + return PTR_ERR(bridge->next_bridge); } return component_add(dp->dev, plat_data->ops); diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c index 82c238829921..b1e130278ecc 100644 --- a/drivers/gpu/drm/exynos/exynos_dp.c +++ b/drivers/gpu/drm/exynos/exynos_dp.c @@ -14,12 +14,10 @@ #include <linux/of_graph.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> -#include <video/of_display_timing.h> #include <video/of_videomode.h> #include <video/videomode.h> #include <drm/bridge/analogix_dp.h> -#include <drm/bridge/of-display-mode-bridge.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_bridge_connector.h> @@ -161,14 +159,6 @@ static int exynos_dp_probe(struct platform_device *pdev) */ platform_set_drvdata(pdev, dp); - if (of_get_display_timings(dev->of_node)) { - dp->plat_data.next_bridge = devm_drm_of_display_mode_bridge(dp->dev, - dp->dev->of_node, - DRM_MODE_CONNECTOR_eDP); - if (IS_ERR(dp->plat_data.next_bridge)) - return PTR_ERR(dp->plat_data.next_bridge); - } - /* The remote port can be either a panel or a bridge */ dp->plat_data.dev_type = EXYNOS_DP; dp->plat_data.power_on = exynos_dp_poweron; @@ -179,10 +169,7 @@ static int exynos_dp_probe(struct platform_device *pdev) if (IS_ERR(dp->adp)) return PTR_ERR(dp->adp); - if (dp->plat_data.next_bridge) - return component_add(&pdev->dev, &exynos_dp_ops); - else - return analogix_dp_finish_probe(dp->adp); + return analogix_dp_finish_probe(dp->adp); } static void exynos_dp_remove(struct platform_device *pdev) diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h index 6033137b651e..f152ca8c3218 100644 --- a/include/drm/bridge/analogix_dp.h +++ b/include/drm/bridge/analogix_dp.h @@ -35,7 +35,6 @@ static inline bool analogix_dp_is_rockchip(enum analogix_dp_devtype type) struct analogix_dp_plat_data { enum analogix_dp_devtype dev_type; - struct drm_bridge *next_bridge; struct drm_encoder *encoder; struct drm_connector *connector; const struct component_ops *ops; -- 2.34.1
