mnt4001-lcdif-fix-pcie-interference.patch 1.74 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index 3e1bb0aefb87..13128b6f2770 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -212,7 +212,7 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 
 	mxsfb_set_formats(mxsfb);
 
-	clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
+	clk_set_rate(mxsfb->clk, m->crtc_clock * 660);
 
 	if (mxsfb->bridge && mxsfb->bridge->timings)
 		bus_flags = mxsfb->bridge->timings->input_bus_flags;
@@ -540,12 +540,44 @@ static const uint64_t mxsfb_modifiers[] = {
  * Initialization
  */
 
+void imx8mq_pcie_qos_for_lcdif(void)
+{
+	void __iomem *qosc = ioremap(0x307f0000, 0x2100);
+	// clock and unlock QoSC registers
+	writel(0x0, qosc);
+	writel(0x1, qosc);
+	writel(0x0, qosc+0x60);
+
+	// limit number of outstanding transactions for PCIe1
+	writel(0x0, qosc+0x1000);
+	writel(0x1, qosc+0x1000);
+	writel(0x01010100, qosc+0x1050);
+	writel(0x01010100, qosc+0x1060);
+	writel(0x01010100, qosc+0x1070);
+	writel(0x1, qosc+0x1000);
+
+	// limit number of outstanding transactions for PCIe2
+	writel(0x0, qosc+0x2000);
+	writel(0x1, qosc+0x2000);
+	writel(0x01010100, qosc+0x2050);
+	writel(0x01010100, qosc+0x2060);
+	writel(0x01010100, qosc+0x2070);
+	writel(0x1, qosc+0x2000);
+
+	iounmap(qosc);
+}
+
 int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb)
 {
 	struct drm_encoder *encoder = &mxsfb->encoder;
 	struct drm_crtc *crtc = &mxsfb->crtc;
 	int ret;
 
+	/*
+		FIXME Workaround to fix PCIe interfering with LCDIF refresh (MNT Reform)
+	*/
+	imx8mq_pcie_qos_for_lcdif();
+
 	drm_plane_helper_add(&mxsfb->planes.primary,
 			     &mxsfb_plane_primary_helper_funcs);
 	ret = drm_universal_plane_init(mxsfb->drm, &mxsfb->planes.primary, 1,