From dbae3b71deeb0fd0b9bcf56ff7e5167f4f48c0e4 Mon Sep 17 00:00:00 2001 From: Adrian Salido Date: Mon, 5 Jun 2023 23:01:17 -0700 Subject: drm: samsung: fix dsim component model/probing order Revert a912aa0d802a ("drm: samsung: fix encoder sequence for DSIM") and address issues with component model and dsim/panel probing order. Bug: 275278929 Test: force probe deferral of dsim driver, observe boot logs Change-Id: Ic9585eb8224992d8869ce0449c95e23a5ac1646c Signed-off-by: Adrian Salido (cherry picked from commit 428b0c700d36ccd4080dc8f11d53a0aeba869927) --- samsung/exynos_drm_dsim.c | 114 ++++++++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 40 deletions(-) diff --git a/samsung/exynos_drm_dsim.c b/samsung/exynos_drm_dsim.c index ca6114d..1232973 100644 --- a/samsung/exynos_drm_dsim.c +++ b/samsung/exynos_drm_dsim.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -1375,6 +1376,45 @@ static int dsim_parse_panel_name(struct dsim_device *dsim) return -ENODEV; } +static int dsim_attach_bridge(struct dsim_device *dsim) +{ + struct drm_bridge *bridge; + struct device_node *np; + int ret; + + if (!dsim->dsi_device) + return -ENODEV; + + np = dsim->dsi_device->dev.of_node; + if (!np) + return -ENOENT; + + bridge = of_drm_find_bridge(np); + if (!bridge) { + struct drm_panel *panel; + + panel = of_drm_find_panel(np); + if (IS_ERR(panel)) { + dsim_err(dsim, "failed to find panel\n"); + return PTR_ERR(panel); + } + + bridge = devm_drm_panel_bridge_add_typed(dsim->dev, panel, DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(bridge)) { + dsim_err(dsim, "failed to create panel bridge\n"); + return PTR_ERR(bridge); + } + } + + ret = drm_bridge_attach(&dsim->encoder, bridge, NULL, 0); + if (ret) + dsim_err(dsim, "Unable to attach panel bridge\n"); + else + dsim->panel_bridge = bridge; + + return ret; +} + static int dsim_bind(struct device *dev, struct device *master, void *data) { struct drm_encoder *encoder = dev_get_drvdata(dev); @@ -1384,9 +1424,13 @@ static int dsim_bind(struct device *dev, struct device *master, void *data) dsim_debug(dsim, "%s +\n", __func__); - if (dsim->dual_dsi == DSIM_DUAL_DSI_SEC) + /* ignore cases where there's no dsi device to be attached */ + if (PTR_ERR(dsim->dsi_device) == -ENODEV) return 0; + if (!dsim->dsi_device) + return -EPROBE_DEFER; + drm_encoder_init(drm_dev, encoder, &dsim_encoder_funcs, DRM_MODE_ENCODER_DSI, NULL); drm_encoder_helper_add(encoder, &dsim_encoder_helper_funcs); @@ -1399,7 +1443,7 @@ static int dsim_bind(struct device *dev, struct device *master, void *data) return -ENOTSUPP; } - ret = mipi_dsi_host_register(&dsim->dsi_host); + ret = dsim_attach_bridge(dsim); dsim_debug(dsim, "%s -\n", __func__); @@ -1416,8 +1460,6 @@ static void dsim_unbind(struct device *dev, struct device *master, if (dsim->dual_dsi == DSIM_DUAL_DSI_SEC) return; - - mipi_dsi_host_unregister(&dsim->dsi_host); } static const struct component_ops dsim_component_ops = { @@ -1764,41 +1806,11 @@ static int dsim_host_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *device) { struct dsim_device *dsim = host_to_dsi(host); - struct drm_bridge *bridge; int ret; dsim_debug(dsim, "%s +\n", __func__); - bridge = of_drm_find_bridge(device->dev.of_node); - if (!bridge) { - struct drm_panel *panel; - - panel = of_drm_find_panel(device->dev.of_node); - if (IS_ERR(panel)) { - dsim_err(dsim, "failed to find panel\n"); - return PTR_ERR(panel); - } - - bridge = devm_drm_panel_bridge_add_typed(host->dev, panel, - DRM_MODE_CONNECTOR_DSI); - if (IS_ERR(bridge)) { - dsim_err(dsim, "failed to create panel bridge\n"); - return PTR_ERR(bridge); - } - } - - if (IS_ERR_OR_NULL(dsim->encoder.dev)) { - dsim_err(dsim, "encoder is not initialized\n"); - return PTR_ERR(dsim->encoder.dev); - } - - ret = drm_bridge_attach(&dsim->encoder, bridge, NULL, 0); - if (ret) { - dsim_err(dsim, "Unable to attach panel bridge\n"); - } else { - dsim->panel_bridge = bridge; - dsim->dsi_device = device; - } + dsim->dsi_device = device; ret = sysfs_create_link(&device->dev.kobj, &host->dev->kobj, "dsim"); if (ret) @@ -1806,7 +1818,7 @@ static int dsim_host_attach(struct mipi_dsi_host *host, dsim_debug(dsim, "%s -\n", __func__); - return ret; + return component_add(dsim->dev, &dsim_component_ops); } static int dsim_host_detach(struct mipi_dsi_host *host, @@ -1816,7 +1828,9 @@ static int dsim_host_detach(struct mipi_dsi_host *host, dsim_info(dsim, "%s +\n", __func__); - _dsim_disable(dsim); + if (dsim->state != DSIM_STATE_HANDOVER) + _dsim_disable(dsim); + if (dsim->panel_bridge) { struct drm_bridge *bridge = dsim->panel_bridge; @@ -2720,7 +2734,7 @@ static int dsim_probe(struct platform_device *pdev) dsim->state = DSIM_STATE_HANDOVER; /* parse the panel name to select the dsi device for the detected panel */ - dsim_parse_panel_name(dsim); + ret = dsim_parse_panel_name(dsim); // TODO: get which panel is active from bootloader? @@ -2734,8 +2748,25 @@ static int dsim_probe(struct platform_device *pdev) phy_init(dsim->res.phy_ex); } + if ((ret < 0) || dsim->dual_dsi == DSIM_DUAL_DSI_SEC) { + /* ignore cases where unable to find panel */ + dsim->dsi_device = ERR_PTR(-ENODEV); + + ret = component_add(dsim->dev, &dsim_component_ops); + if (ret < 0) { + dsim_err(dsim, "unable to add dsim component\n"); + goto err; + } + } else { + ret = mipi_dsi_host_register(&dsim->dsi_host); + if (ret) { + dsim_err(dsim, "unable to register dsi host\n"); + goto err; + } + } + dsim_info(dsim, "driver has been probed.\n"); - return component_add(dsim->dev, &dsim_component_ops); + return 0; err: dsim_err(dsim, "failed to probe exynos dsim driver\n"); @@ -2750,7 +2781,10 @@ static int dsim_remove(struct platform_device *pdev) device_remove_file(dsim->dev, &dev_attr_hs_clock); pm_runtime_disable(&pdev->dev); - component_del(&pdev->dev, &dsim_component_ops); + if (PTR_ERR(dsim->dsi_device) == -ENODEV) + component_del(&pdev->dev, &dsim_component_ops); + + mipi_dsi_host_unregister(&dsim->dsi_host); iounmap(dsim->res.ss_reg_base); iounmap(dsim->res.phy_regs_ex); -- cgit v1.2.3