[RFC,10/10] drm/mxsfb: stop controller and drain FIFOs if already initialized

Message ID 20241028102559.1451383-11-dario.binacchi@amarulasolutions.com
State New
Headers show
Series
  • Support simple-framebuffer on imx8m
Related show

Commit Message

Dario Binacchi Oct. 28, 2024, 10:25 a.m. UTC
You can't re-program the controller if it is still running. This may
lead to shifted pictures, so stop the controller and drain its FIFOs
in case it's already properly setup.
This patch is crucial when supporting the simple framebuffer, as the
controller has already been initialized by the bootloader.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---

 drivers/gpu/drm/mxsfb/mxsfb_drv.c |  3 +++
 drivers/gpu/drm/mxsfb/mxsfb_drv.h |  1 +
 drivers/gpu/drm/mxsfb/mxsfb_kms.c | 14 +++++++++++++-
 3 files changed, 17 insertions(+), 1 deletion(-)

Patch

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index cb5ce4e81fc7..38c94cdc8f6c 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -10,6 +10,7 @@ 
 
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
+#include <linux/of.h>
 #include <linux/io.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
@@ -221,6 +222,8 @@  static int mxsfb_load(struct drm_device *drm,
 	if (!mxsfb)
 		return -ENOMEM;
 
+	mxsfb->enabled =
+		of_property_read_bool(drm->dev->of_node, "fsl,boot-on");
 	mxsfb->drm = drm;
 	drm->dev_private = mxsfb;
 	mxsfb->devdata = devdata;
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index d160d921b25f..0f9ae4ce450c 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -47,6 +47,7 @@  struct mxsfb_drm_private {
 	struct drm_bridge		*bridge;
 
 	bool				crc_active;
+	bool                            enabled;
 };
 
 static inline struct mxsfb_drm_private *
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index 7ed2516b6de0..d064a2bb65df 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -202,9 +202,11 @@  static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
 	writel(reg, mxsfb->base + LCDC_CTRL1);
 
 	writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
+
+	mxsfb->enabled = true;
 }
 
-static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
+static void _mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
 {
 	u32 reg;
 
@@ -221,6 +223,13 @@  static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
 	reg &= ~VDCTRL4_SYNC_SIGNALS_ON;
 	writel(reg, mxsfb->base + LCDC_VDCTRL4);
 
+	mxsfb->enabled = false;
+}
+
+static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
+{
+	_mxsfb_disable_controller(mxsfb);
+
 	clk_disable_unprepare(mxsfb->clk);
 	if (mxsfb->clk_disp_axi)
 		clk_disable_unprepare(mxsfb->clk_disp_axi);
@@ -354,6 +363,9 @@  static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
 	u32 bus_format = 0;
 	dma_addr_t dma_addr;
 
+	if (mxsfb->enabled)
+		_mxsfb_disable_controller(mxsfb);
+
 	pm_runtime_get_sync(drm->dev);
 	mxsfb_enable_axi_clk(mxsfb);