Having the DSI interrupt enabled before actually binding the DSI
component to the display controller driver is both useless and
dangerous: the main purpose of this interrupt is to signal CMD
done, LP RX data ready, or VideoMode done, or to reset the HW
engine if this doesn't come.

Should this interrupt come too late (during probe), the HW will
be reset only at the next occurrence of a timeout, which slows
down boot and may render artifacts to the DSI display.

Moreover, clearing the DSI interrupt while the display controller
is not ready yet, may result in an interrupt storm.

In order to prevent this from happening, request the interrupt
with IRQF_NO_AUTOEN, and enable it only when binding DSI to its
display controller component master.

Signed-off-by: AngeloGioacchino Del Regno 
<[email protected]>
---
 drivers/gpu/drm/mediatek/mtk_dsi.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c 
b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 3fbcb22ee15e..56c69f80a2ef 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -225,6 +225,7 @@ struct mtk_dsi {
        int refcount;
        bool enabled;
        bool lanes_ready;
+       int irq;
        u32 irq_data;
        wait_queue_head_t irq_wait_queue;
        const struct mtk_dsi_driver_data *driver_data;
@@ -1048,7 +1049,13 @@ static int mtk_dsi_bind(struct device *dev, struct 
device *master, void *data)
        if (ret)
                return ret;
 
-       return device_reset_optional(dev);
+       ret = device_reset_optional(dev);
+       if (ret)
+               return ret;
+
+       enable_irq(dsi->irq);
+
+       return 0;
 }
 
 static void mtk_dsi_unbind(struct device *dev, struct device *master,
@@ -1056,6 +1063,8 @@ static void mtk_dsi_unbind(struct device *dev, struct 
device *master,
 {
        struct mtk_dsi *dsi = dev_get_drvdata(dev);
 
+       disable_irq(dsi->irq);
+
        drm_encoder_cleanup(&dsi->encoder);
 }
 
@@ -1283,7 +1292,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 {
        struct mtk_dsi *dsi;
        struct device *dev = &pdev->dev;
-       int irq_num;
        int ret;
 
        dsi = devm_drm_bridge_alloc(dev, struct mtk_dsi, bridge,
@@ -1316,9 +1324,9 @@ static int mtk_dsi_probe(struct platform_device *pdev)
        if (IS_ERR(dsi->phy))
                return dev_err_probe(dev, PTR_ERR(dsi->phy), "Failed to get 
MIPI-DPHY\n");
 
-       irq_num = platform_get_irq(pdev, 0);
-       if (irq_num < 0)
-               return irq_num;
+       dsi->irq = platform_get_irq(pdev, 0);
+       if (dsi->irq < 0)
+               return dsi->irq;
 
        dsi->host.ops = &mtk_dsi_ops;
        dsi->host.dev = dev;
@@ -1331,8 +1339,8 @@ static int mtk_dsi_probe(struct platform_device *pdev)
        if (ret < 0)
                return dev_err_probe(dev, ret, "Failed to register DSI host\n");
 
-       ret = devm_request_irq(&pdev->dev, irq_num, mtk_dsi_irq,
-                              IRQF_TRIGGER_NONE, dev_name(&pdev->dev), dsi);
+       ret = devm_request_irq(&pdev->dev, dsi->irq, mtk_dsi_irq,
+                              IRQF_NO_AUTOEN, dev_name(&pdev->dev), dsi);
        if (ret) {
                mipi_dsi_host_unregister(&dsi->host);
                return dev_err_probe(&pdev->dev, ret, "Failed to request DSI 
irq\n");
-- 
2.54.0

Reply via email to