summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c52
1 files changed, 33 insertions, 19 deletions
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 952cfdb1961d..1d556482bb46 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -81,7 +81,7 @@ struct dsi_hw_ctx {
struct dw_dsi {
struct drm_encoder encoder;
- struct drm_bridge *bridge;
+ struct device *dev;
struct mipi_dsi_host host;
struct drm_display_mode cur_mode;
struct dsi_hw_ctx *ctx;
@@ -720,10 +720,13 @@ static int dw_drm_encoder_init(struct device *dev,
return 0;
}
+static const struct component_ops dsi_ops;
static int dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *mdsi)
{
struct dw_dsi *dsi = host_to_dsi(host);
+ struct device *dev = host->dev;
+ int ret;
if (mdsi->lanes < 1 || mdsi->lanes > 4) {
DRM_ERROR("dsi device params invalid\n");
@@ -734,13 +737,20 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
dsi->format = mdsi->format;
dsi->mode_flags = mdsi->mode_flags;
+ ret = component_add(dev, &dsi_ops);
+ if (ret)
+ return ret;
+
return 0;
}
static int dsi_host_detach(struct mipi_dsi_host *host,
struct mipi_dsi_device *mdsi)
{
- /* do nothing */
+ struct device *dev = host->dev;
+
+ component_del(dev, &dsi_ops);
+
return 0;
}
@@ -768,7 +778,17 @@ static int dsi_host_init(struct device *dev, struct dw_dsi *dsi)
static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
{
struct drm_encoder *encoder = &dsi->encoder;
- struct drm_bridge *bridge = dsi->bridge;
+ struct drm_bridge *bridge;
+ struct device_node *np = dsi->dev->of_node;
+ int ret;
+
+ /*
+ * Get the endpoint node. In our case, dsi has one output port1
+ * to which the external HDMI bridge is connected.
+ */
+ ret = drm_of_find_panel_or_bridge(np, 1, 0, NULL, &bridge);
+ if (ret)
+ return ret;
/* associate the bridge to dsi encoder */
return drm_bridge_attach(encoder, bridge, NULL, 0);
@@ -785,10 +805,6 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
if (ret)
return ret;
- ret = dsi_host_init(dev, dsi);
- if (ret)
- return ret;
-
ret = dsi_bridge_init(drm_dev, dsi);
if (ret)
return ret;
@@ -809,17 +825,7 @@ static const struct component_ops dsi_ops = {
static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
{
struct dsi_hw_ctx *ctx = dsi->ctx;
- struct device_node *np = pdev->dev.of_node;
struct resource *res;
- int ret;
-
- /*
- * Get the endpoint node. In our case, dsi has one output port1
- * to which the external HDMI bridge is connected.
- */
- ret = drm_of_find_panel_or_bridge(np, 1, 0, NULL, &dsi->bridge);
- if (ret)
- return ret;
ctx->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(ctx->pclk)) {
@@ -852,6 +858,7 @@ static int dsi_probe(struct platform_device *pdev)
dsi = &data->dsi;
ctx = &data->ctx;
dsi->ctx = ctx;
+ dsi->dev = &pdev->dev;
ret = dsi_parse_dt(pdev, dsi);
if (ret)
@@ -859,12 +866,19 @@ static int dsi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
- return component_add(&pdev->dev, &dsi_ops);
+ ret = dsi_host_init(&pdev->dev, dsi);
+ if (ret)
+ return ret;
+
+ return 0;
}
static int dsi_remove(struct platform_device *pdev)
{
- component_del(&pdev->dev, &dsi_ops);
+ struct dsi_data *data = platform_get_drvdata(pdev);
+ struct dw_dsi *dsi = &data->dsi;
+
+ mipi_dsi_host_unregister(&dsi->host);
return 0;
}