Commit fb9c9671 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'mediatek-drm-fixes-5.17' of...

Merge tag 'mediatek-drm-fixes-5.17' of https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux into drm-fixes

Mediatek DRM Fixes for Linux 5.17

1. Avoid EPROBE_DEFER loop with external bridge
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/1645027727-19554-1-git-send-email-chunkuang.hu@kernel.org
parents 754e0b0e 647474b8
......@@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
mtk_dsi_poweroff(dsi);
}
static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
{
int ret;
ret = drm_simple_encoder_init(drm, &dsi->encoder,
DRM_MODE_ENCODER_DSI);
if (ret) {
DRM_ERROR("Failed to encoder init to drm\n");
return ret;
}
dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret)
goto err_cleanup_encoder;
dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
if (IS_ERR(dsi->connector)) {
DRM_ERROR("Unable to create bridge connector\n");
ret = PTR_ERR(dsi->connector);
goto err_cleanup_encoder;
}
drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
return 0;
err_cleanup_encoder:
drm_encoder_cleanup(&dsi->encoder);
return ret;
}
static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
{
int ret;
struct drm_device *drm = data;
struct mtk_dsi *dsi = dev_get_drvdata(dev);
ret = mtk_dsi_encoder_init(drm, dsi);
if (ret)
return ret;
return device_reset_optional(dev);
}
static void mtk_dsi_unbind(struct device *dev, struct device *master,
void *data)
{
struct mtk_dsi *dsi = dev_get_drvdata(dev);
drm_encoder_cleanup(&dsi->encoder);
}
static const struct component_ops mtk_dsi_component_ops = {
.bind = mtk_dsi_bind,
.unbind = mtk_dsi_unbind,
};
static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
struct mtk_dsi *dsi = host_to_dsi(host);
struct device *dev = host->dev;
int ret;
dsi->lanes = device->lanes;
dsi->format = device->format;
dsi->mode_flags = device->mode_flags;
dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
if (IS_ERR(dsi->next_bridge))
return PTR_ERR(dsi->next_bridge);
drm_bridge_add(&dsi->bridge);
ret = component_add(host->dev, &mtk_dsi_component_ops);
if (ret) {
DRM_ERROR("failed to add dsi_host component: %d\n", ret);
drm_bridge_remove(&dsi->bridge);
return ret;
}
return 0;
}
static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
struct mtk_dsi *dsi = host_to_dsi(host);
component_del(host->dev, &mtk_dsi_component_ops);
drm_bridge_remove(&dsi->bridge);
return 0;
}
static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
{
int ret;
......@@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
static const struct mipi_dsi_host_ops mtk_dsi_ops = {
.attach = mtk_dsi_host_attach,
.detach = mtk_dsi_host_detach,
.transfer = mtk_dsi_host_transfer,
};
static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
{
int ret;
ret = drm_simple_encoder_init(drm, &dsi->encoder,
DRM_MODE_ENCODER_DSI);
if (ret) {
DRM_ERROR("Failed to encoder init to drm\n");
return ret;
}
dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret)
goto err_cleanup_encoder;
dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
if (IS_ERR(dsi->connector)) {
DRM_ERROR("Unable to create bridge connector\n");
ret = PTR_ERR(dsi->connector);
goto err_cleanup_encoder;
}
drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
return 0;
err_cleanup_encoder:
drm_encoder_cleanup(&dsi->encoder);
return ret;
}
static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
{
int ret;
struct drm_device *drm = data;
struct mtk_dsi *dsi = dev_get_drvdata(dev);
ret = mtk_dsi_encoder_init(drm, dsi);
if (ret)
return ret;
return device_reset_optional(dev);
}
static void mtk_dsi_unbind(struct device *dev, struct device *master,
void *data)
{
struct mtk_dsi *dsi = dev_get_drvdata(dev);
drm_encoder_cleanup(&dsi->encoder);
}
static const struct component_ops mtk_dsi_component_ops = {
.bind = mtk_dsi_bind,
.unbind = mtk_dsi_unbind,
};
static int mtk_dsi_probe(struct platform_device *pdev)
{
struct mtk_dsi *dsi;
struct device *dev = &pdev->dev;
struct drm_panel *panel;
struct resource *regs;
int irq_num;
int ret;
......@@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
return ret;
}
ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
&panel, &dsi->next_bridge);
if (ret)
goto err_unregister_host;
if (panel) {
dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
if (IS_ERR(dsi->next_bridge)) {
ret = PTR_ERR(dsi->next_bridge);
goto err_unregister_host;
}
}
dsi->driver_data = of_device_get_match_data(dev);
dsi->engine_clk = devm_clk_get(dev, "engine");
......@@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
dsi->bridge.of_node = dev->of_node;
dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
drm_bridge_add(&dsi->bridge);
ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
if (ret) {
dev_err(&pdev->dev, "failed to add component: %d\n", ret);
goto err_unregister_host;
}
return 0;
err_unregister_host:
......@@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
struct mtk_dsi *dsi = platform_get_drvdata(pdev);
mtk_output_dsi_disable(dsi);
drm_bridge_remove(&dsi->bridge);
component_del(&pdev->dev, &mtk_dsi_component_ops);
mipi_dsi_host_unregister(&dsi->host);
return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment