summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Salido <salidoa@google.com>2023-06-05 23:01:17 -0700
committerKen Huang <kenbshuang@google.com>2024-01-03 20:33:53 +0800
commitdbae3b71deeb0fd0b9bcf56ff7e5167f4f48c0e4 (patch)
treea4348d029c3458906419cad55483f3e94a779303
parent1436920681a69f17aa1fcff5dc50d4960dcc6f8d (diff)
downloaddisplay-dbae3b71deeb0fd0b9bcf56ff7e5167f4f48c0e4.tar.gz
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 <salidoa@google.com> (cherry picked from commit 428b0c700d36ccd4080dc8f11d53a0aeba869927)
-rw-r--r--samsung/exynos_drm_dsim.c114
1 files 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 <linux/clk.h>
#include <linux/console.h>
+#include <linux/errno.h>
#include <linux/gpio/consumer.h>
#include <linux/irq.h>
#include <linux/of_address.h>
@@ -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);