From 92e794fab87af0793403d5e4a547f0be94a0e656 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 22 Nov 2021 12:36:32 +0530 Subject: drm: exynos: dsi: Convert to bridge driver Some display panels would come up with a non-DSI output, those can have an option to connect the DSI host by means of interface bridge converter. This DSI to non-DSI interface bridge converter would requires DSI Host to handle drm bridge functionalities in order to DSI Host to Interface bridge. This patch convert the existing to a drm bridge driver with a built-in encoder support for compatibility with existing component drivers. Signed-off-by: Jagan Teki Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20211122070633.89219-2-jagan@amarulasolutions.com --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 73 +++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/exynos') diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 8d137857818c..174590f543c3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -257,6 +257,7 @@ struct exynos_dsi { struct drm_connector connector; struct drm_panel *panel; struct list_head bridge_chain; + struct drm_bridge bridge; struct drm_bridge *out_bridge; struct device *dev; @@ -287,9 +288,9 @@ struct exynos_dsi { #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) #define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector) -static inline struct exynos_dsi *encoder_to_dsi(struct drm_encoder *e) +static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b) { - return container_of(e, struct exynos_dsi, encoder); + return container_of(b, struct exynos_dsi, bridge); } enum reg_idx { @@ -1374,9 +1375,10 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi) } } -static void exynos_dsi_enable(struct drm_encoder *encoder) +static void exynos_dsi_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { - struct exynos_dsi *dsi = encoder_to_dsi(encoder); + struct exynos_dsi *dsi = bridge_to_dsi(bridge); struct drm_bridge *iter; int ret; @@ -1399,7 +1401,8 @@ static void exynos_dsi_enable(struct drm_encoder *encoder) list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) { if (iter->funcs->pre_enable) - iter->funcs->pre_enable(iter); + iter->funcs->atomic_pre_enable(iter, + old_bridge_state); } } @@ -1413,7 +1416,7 @@ static void exynos_dsi_enable(struct drm_encoder *encoder) } else { list_for_each_entry(iter, &dsi->bridge_chain, chain_node) { if (iter->funcs->enable) - iter->funcs->enable(iter); + iter->funcs->atomic_enable(iter, old_bridge_state); } } @@ -1429,9 +1432,10 @@ err_put_sync: pm_runtime_put(dsi->dev); } -static void exynos_dsi_disable(struct drm_encoder *encoder) +static void exynos_dsi_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { - struct exynos_dsi *dsi = encoder_to_dsi(encoder); + struct exynos_dsi *dsi = bridge_to_dsi(bridge); struct drm_bridge *iter; if (!(dsi->state & DSIM_STATE_ENABLED)) @@ -1443,7 +1447,7 @@ static void exynos_dsi_disable(struct drm_encoder *encoder) list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) { if (iter->funcs->disable) - iter->funcs->disable(iter); + iter->funcs->atomic_disable(iter, old_bridge_state); } exynos_dsi_set_display_enable(dsi, false); @@ -1451,7 +1455,7 @@ static void exynos_dsi_disable(struct drm_encoder *encoder) list_for_each_entry(iter, &dsi->bridge_chain, chain_node) { if (iter->funcs->post_disable) - iter->funcs->post_disable(iter); + iter->funcs->atomic_post_disable(iter, old_bridge_state); } dsi->state &= ~DSIM_STATE_ENABLED; @@ -1494,9 +1498,9 @@ static const struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs .get_modes = exynos_dsi_get_modes, }; -static int exynos_dsi_create_connector(struct drm_encoder *encoder) +static int exynos_dsi_create_connector(struct exynos_dsi *dsi) { - struct exynos_dsi *dsi = encoder_to_dsi(encoder); + struct drm_encoder *encoder = &dsi->encoder; struct drm_connector *connector = &dsi->connector; struct drm_device *drm = encoder->dev; int ret; @@ -1522,9 +1526,21 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder) return 0; } -static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = { - .enable = exynos_dsi_enable, - .disable = exynos_dsi_disable, +static int exynos_dsi_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct exynos_dsi *dsi = bridge_to_dsi(bridge); + + return drm_bridge_attach(bridge->encoder, dsi->out_bridge, NULL, 0); +} + +static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = { + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_enable = exynos_dsi_atomic_enable, + .atomic_disable = exynos_dsi_atomic_disable, + .attach = exynos_dsi_attach, }; MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); @@ -1543,7 +1559,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, dsi->out_bridge = out_bridge; list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain); } else { - int ret = exynos_dsi_create_connector(encoder); + int ret = exynos_dsi_create_connector(dsi); if (ret) { DRM_DEV_ERROR(dsi->dev, @@ -1596,7 +1612,7 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, if (dsi->panel) { mutex_lock(&drm->mode_config.mutex); - exynos_dsi_disable(&dsi->encoder); + exynos_dsi_atomic_disable(&dsi->bridge, NULL); dsi->panel = NULL; dsi->connector.status = connector_status_disconnected; mutex_unlock(&drm->mode_config.mutex); @@ -1702,12 +1718,16 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS); - drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs); - ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD); if (ret < 0) return ret; + ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, 0); + if (ret) { + drm_encoder_cleanup(&dsi->encoder); + return ret; + } + in_bridge_node = of_graph_get_remote_node(dev->of_node, DSI_PORT_IN, 0); if (in_bridge_node) { in_bridge = of_drm_find_bridge(in_bridge_node); @@ -1723,10 +1743,9 @@ static void exynos_dsi_unbind(struct device *dev, struct device *master, void *data) { struct exynos_dsi *dsi = dev_get_drvdata(dev); - struct drm_encoder *encoder = &dsi->encoder; - - exynos_dsi_disable(encoder); + exynos_dsi_atomic_disable(&dsi->bridge, NULL); + drm_encoder_cleanup(&dsi->encoder); mipi_dsi_host_unregister(&dsi->dsi_host); } @@ -1819,6 +1838,12 @@ static int exynos_dsi_probe(struct platform_device *pdev) pm_runtime_enable(dev); + dsi->bridge.funcs = &exynos_dsi_bridge_funcs; + dsi->bridge.of_node = dev->of_node; + dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; + + drm_bridge_add(&dsi->bridge); + ret = component_add(dev, &exynos_dsi_component_ops); if (ret) goto err_disable_runtime; @@ -1833,6 +1858,10 @@ err_disable_runtime: static int exynos_dsi_remove(struct platform_device *pdev) { + struct exynos_dsi *dsi = platform_get_drvdata(pdev); + + drm_bridge_remove(&dsi->bridge); + pm_runtime_disable(&pdev->dev); component_del(&pdev->dev, &exynos_dsi_component_ops); -- cgit v1.2.3 From aee039e66035b66f0c587cc1b0dd32fb04c9a892 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 22 Nov 2021 12:36:33 +0530 Subject: drm: exynos: dsi: Add mode_set function Get the display mode settings via mode_set bridge function instead of explicitly de-reference. Signed-off-by: Jagan Teki Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20211122070633.89219-3-jagan@amarulasolutions.com --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/exynos') diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 174590f543c3..3d4713346949 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -260,6 +260,7 @@ struct exynos_dsi { struct drm_bridge bridge; struct drm_bridge *out_bridge; struct device *dev; + struct drm_display_mode mode; void __iomem *reg_base; struct phy *phy; @@ -883,7 +884,7 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi) { - struct drm_display_mode *m = &dsi->encoder.crtc->state->adjusted_mode; + struct drm_display_mode *m = &dsi->mode; unsigned int num_bits_resol = dsi->driver_data->num_bits_resol; u32 reg; @@ -1526,6 +1527,15 @@ static int exynos_dsi_create_connector(struct exynos_dsi *dsi) return 0; } +static void exynos_dsi_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) +{ + struct exynos_dsi *dsi = bridge_to_dsi(bridge); + + drm_mode_copy(&dsi->mode, adjusted_mode); +} + static int exynos_dsi_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { @@ -1540,6 +1550,7 @@ static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = { .atomic_reset = drm_atomic_helper_bridge_reset, .atomic_enable = exynos_dsi_atomic_enable, .atomic_disable = exynos_dsi_atomic_disable, + .mode_set = exynos_dsi_mode_set, .attach = exynos_dsi_attach, }; -- cgit v1.2.3 From bd29823e05ac5ba81e9f6c8ca51f040c8b47a741 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Wed, 12 Jan 2022 00:13:47 +0530 Subject: Revert "drm: exynos: dsi: Convert to bridge driver" This reverts commit 92e794fab87af0793403d5e4a547f0be94a0e656. It is merged by accident, the actual patch series on this bridge conversion is still under review. Revert this as it breaks the exynos DSI. Signed-off-by: Jagan Teki Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220111184347.502471-1-jagan@amarulasolutions.com Reviewed-by: Robert Foss --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 93 ++++++++++++--------------------- 1 file changed, 32 insertions(+), 61 deletions(-) (limited to 'drivers/gpu/drm/exynos') diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 3d4713346949..bce5331ed1e6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -257,7 +257,6 @@ struct exynos_dsi { struct drm_connector connector; struct drm_panel *panel; struct list_head bridge_chain; - struct drm_bridge bridge; struct drm_bridge *out_bridge; struct device *dev; struct drm_display_mode mode; @@ -289,9 +288,9 @@ struct exynos_dsi { #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) #define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector) -static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b) +static inline struct exynos_dsi *encoder_to_dsi(struct drm_encoder *e) { - return container_of(b, struct exynos_dsi, bridge); + return container_of(e, struct exynos_dsi, encoder); } enum reg_idx { @@ -1376,10 +1375,9 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi) } } -static void exynos_dsi_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void exynos_dsi_enable(struct drm_encoder *encoder) { - struct exynos_dsi *dsi = bridge_to_dsi(bridge); + struct exynos_dsi *dsi = encoder_to_dsi(encoder); struct drm_bridge *iter; int ret; @@ -1402,8 +1400,7 @@ static void exynos_dsi_atomic_enable(struct drm_bridge *bridge, list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) { if (iter->funcs->pre_enable) - iter->funcs->atomic_pre_enable(iter, - old_bridge_state); + iter->funcs->pre_enable(iter); } } @@ -1417,7 +1414,7 @@ static void exynos_dsi_atomic_enable(struct drm_bridge *bridge, } else { list_for_each_entry(iter, &dsi->bridge_chain, chain_node) { if (iter->funcs->enable) - iter->funcs->atomic_enable(iter, old_bridge_state); + iter->funcs->enable(iter); } } @@ -1433,10 +1430,9 @@ err_put_sync: pm_runtime_put(dsi->dev); } -static void exynos_dsi_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void exynos_dsi_disable(struct drm_encoder *encoder) { - struct exynos_dsi *dsi = bridge_to_dsi(bridge); + struct exynos_dsi *dsi = encoder_to_dsi(encoder); struct drm_bridge *iter; if (!(dsi->state & DSIM_STATE_ENABLED)) @@ -1448,7 +1444,7 @@ static void exynos_dsi_atomic_disable(struct drm_bridge *bridge, list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) { if (iter->funcs->disable) - iter->funcs->atomic_disable(iter, old_bridge_state); + iter->funcs->disable(iter); } exynos_dsi_set_display_enable(dsi, false); @@ -1456,13 +1452,22 @@ static void exynos_dsi_atomic_disable(struct drm_bridge *bridge, list_for_each_entry(iter, &dsi->bridge_chain, chain_node) { if (iter->funcs->post_disable) - iter->funcs->atomic_post_disable(iter, old_bridge_state); + iter->funcs->post_disable(iter); } dsi->state &= ~DSIM_STATE_ENABLED; pm_runtime_put_sync(dsi->dev); } +static void exynos_dsi_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct exynos_dsi *dsi = encoder_to_dsi(encoder); + + drm_mode_copy(&dsi->mode, adjusted_mode); +} + static enum drm_connector_status exynos_dsi_detect(struct drm_connector *connector, bool force) { @@ -1499,9 +1504,9 @@ static const struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs .get_modes = exynos_dsi_get_modes, }; -static int exynos_dsi_create_connector(struct exynos_dsi *dsi) +static int exynos_dsi_create_connector(struct drm_encoder *encoder) { - struct drm_encoder *encoder = &dsi->encoder; + struct exynos_dsi *dsi = encoder_to_dsi(encoder); struct drm_connector *connector = &dsi->connector; struct drm_device *drm = encoder->dev; int ret; @@ -1527,31 +1532,10 @@ static int exynos_dsi_create_connector(struct exynos_dsi *dsi) return 0; } -static void exynos_dsi_mode_set(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - const struct drm_display_mode *adjusted_mode) -{ - struct exynos_dsi *dsi = bridge_to_dsi(bridge); - - drm_mode_copy(&dsi->mode, adjusted_mode); -} - -static int exynos_dsi_attach(struct drm_bridge *bridge, - enum drm_bridge_attach_flags flags) -{ - struct exynos_dsi *dsi = bridge_to_dsi(bridge); - - return drm_bridge_attach(bridge->encoder, dsi->out_bridge, NULL, 0); -} - -static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = { - .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, - .atomic_reset = drm_atomic_helper_bridge_reset, - .atomic_enable = exynos_dsi_atomic_enable, - .atomic_disable = exynos_dsi_atomic_disable, - .mode_set = exynos_dsi_mode_set, - .attach = exynos_dsi_attach, +static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = { + .enable = exynos_dsi_enable, + .disable = exynos_dsi_disable, + .mode_set = exynos_dsi_mode_set, }; MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); @@ -1570,7 +1554,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, dsi->out_bridge = out_bridge; list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain); } else { - int ret = exynos_dsi_create_connector(dsi); + int ret = exynos_dsi_create_connector(encoder); if (ret) { DRM_DEV_ERROR(dsi->dev, @@ -1623,7 +1607,7 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, if (dsi->panel) { mutex_lock(&drm->mode_config.mutex); - exynos_dsi_atomic_disable(&dsi->bridge, NULL); + exynos_dsi_disable(&dsi->encoder); dsi->panel = NULL; dsi->connector.status = connector_status_disconnected; mutex_unlock(&drm->mode_config.mutex); @@ -1729,16 +1713,12 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS); + drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs); + ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD); if (ret < 0) return ret; - ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, 0); - if (ret) { - drm_encoder_cleanup(&dsi->encoder); - return ret; - } - in_bridge_node = of_graph_get_remote_node(dev->of_node, DSI_PORT_IN, 0); if (in_bridge_node) { in_bridge = of_drm_find_bridge(in_bridge_node); @@ -1754,9 +1734,10 @@ static void exynos_dsi_unbind(struct device *dev, struct device *master, void *data) { struct exynos_dsi *dsi = dev_get_drvdata(dev); + struct drm_encoder *encoder = &dsi->encoder; + + exynos_dsi_disable(encoder); - exynos_dsi_atomic_disable(&dsi->bridge, NULL); - drm_encoder_cleanup(&dsi->encoder); mipi_dsi_host_unregister(&dsi->dsi_host); } @@ -1849,12 +1830,6 @@ static int exynos_dsi_probe(struct platform_device *pdev) pm_runtime_enable(dev); - dsi->bridge.funcs = &exynos_dsi_bridge_funcs; - dsi->bridge.of_node = dev->of_node; - dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; - - drm_bridge_add(&dsi->bridge); - ret = component_add(dev, &exynos_dsi_component_ops); if (ret) goto err_disable_runtime; @@ -1869,10 +1844,6 @@ err_disable_runtime: static int exynos_dsi_remove(struct platform_device *pdev) { - struct exynos_dsi *dsi = platform_get_drvdata(pdev); - - drm_bridge_remove(&dsi->bridge); - pm_runtime_disable(&pdev->dev); component_del(&pdev->dev, &exynos_dsi_component_ops); -- cgit v1.2.3