summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/mxsfb
diff options
context:
space:
mode:
authorJae Hyun Yoo <jae.hyun.yoo@linux.intel.com>2021-10-01 21:38:40 +0300
committerJae Hyun Yoo <jae.hyun.yoo@linux.intel.com>2021-10-01 21:40:21 +0300
commit9c881021a269af242594e2dfc79f1c4701404887 (patch)
treec8ec14f412d7ea35009b2dee08770082ddbb5c6e /drivers/gpu/drm/mxsfb
parente9479d98b87227b8b7502c4c1e778887b23799f1 (diff)
parentcf06e1ab1c3ed354da5873e646f2164fea147c88 (diff)
downloadlinux-dev-5.10-intel.tar.xz
Merge branch 'dev-5.10' into dev-5.10-inteldev-5.10-intel
Pull 5.10.67 stable from OpenBMC upstream. Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
Diffstat (limited to 'drivers/gpu/drm/mxsfb')
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.c3
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.h1
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_kms.c40
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_regs.h9
4 files changed, 53 insertions, 0 deletions
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 17f26052e845..f31e8ef3c258 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -51,6 +51,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
.hs_wdth_mask = 0xff,
.hs_wdth_shift = 24,
.has_overlay = false,
+ .has_ctrl2 = false,
},
[MXSFB_V4] = {
.transfer_count = LCDC_V4_TRANSFER_COUNT,
@@ -59,6 +60,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
.hs_wdth_mask = 0x3fff,
.hs_wdth_shift = 18,
.has_overlay = false,
+ .has_ctrl2 = true,
},
[MXSFB_V6] = {
.transfer_count = LCDC_V4_TRANSFER_COUNT,
@@ -67,6 +69,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
.hs_wdth_mask = 0x3fff,
.hs_wdth_shift = 18,
.has_overlay = true,
+ .has_ctrl2 = true,
},
};
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index 399d23e91ed1..7c720e226fdf 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -22,6 +22,7 @@ struct mxsfb_devdata {
unsigned int hs_wdth_mask;
unsigned int hs_wdth_shift;
bool has_overlay;
+ bool has_ctrl2;
};
struct mxsfb_drm_private {
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
index 9e1224d54729..b535621f4f78 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
@@ -107,6 +107,14 @@ static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk_disp_axi);
clk_prepare_enable(mxsfb->clk);
+ /* Increase number of outstanding requests on all supported IPs */
+ if (mxsfb->devdata->has_ctrl2) {
+ reg = readl(mxsfb->base + LCDC_V4_CTRL2);
+ reg &= ~CTRL2_SET_OUTSTANDING_REQS_MASK;
+ reg |= CTRL2_SET_OUTSTANDING_REQS_16;
+ writel(reg, mxsfb->base + LCDC_V4_CTRL2);
+ }
+
/* If it was disabled, re-enable the mode again */
writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
@@ -115,6 +123,35 @@ static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
reg |= VDCTRL4_SYNC_SIGNALS_ON;
writel(reg, mxsfb->base + LCDC_VDCTRL4);
+ /*
+ * Enable recovery on underflow.
+ *
+ * There is some sort of corner case behavior of the controller,
+ * which could rarely be triggered at least on i.MX6SX connected
+ * to 800x480 DPI panel and i.MX8MM connected to DPI->DSI->LVDS
+ * bridged 1920x1080 panel (and likely on other setups too), where
+ * the image on the panel shifts to the right and wraps around.
+ * This happens either when the controller is enabled on boot or
+ * even later during run time. The condition does not correct
+ * itself automatically, i.e. the display image remains shifted.
+ *
+ * It seems this problem is known and is due to sporadic underflows
+ * of the LCDIF FIFO. While the LCDIF IP does have underflow/overflow
+ * IRQs, neither of the IRQs trigger and neither IRQ status bit is
+ * asserted when this condition occurs.
+ *
+ * All known revisions of the LCDIF IP have CTRL1 RECOVER_ON_UNDERFLOW
+ * bit, which is described in the reference manual since i.MX23 as
+ * "
+ * Set this bit to enable the LCDIF block to recover in the next
+ * field/frame if there was an underflow in the current field/frame.
+ * "
+ * Enable this bit to mitigate the sporadic underflows.
+ */
+ reg = readl(mxsfb->base + LCDC_CTRL1);
+ reg |= CTRL1_RECOVER_ON_UNDERFLOW;
+ writel(reg, mxsfb->base + LCDC_CTRL1);
+
writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
}
@@ -206,6 +243,9 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
/* Clear the FIFOs */
writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
+ readl(mxsfb->base + LCDC_CTRL1);
+ writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+ readl(mxsfb->base + LCDC_CTRL1);
if (mxsfb->devdata->has_overlay)
writel(0, mxsfb->base + LCDC_AS_CTRL);
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 55d28a27f912..694fea13e893 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -15,6 +15,7 @@
#define LCDC_CTRL 0x00
#define LCDC_CTRL1 0x10
#define LCDC_V3_TRANSFER_COUNT 0x20
+#define LCDC_V4_CTRL2 0x20
#define LCDC_V4_TRANSFER_COUNT 0x30
#define LCDC_V4_CUR_BUF 0x40
#define LCDC_V4_NEXT_BUF 0x50
@@ -54,12 +55,20 @@
#define CTRL_DF24 BIT(1)
#define CTRL_RUN BIT(0)
+#define CTRL1_RECOVER_ON_UNDERFLOW BIT(24)
#define CTRL1_FIFO_CLEAR BIT(21)
#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
#define CTRL1_CUR_FRAME_DONE_IRQ_EN BIT(13)
#define CTRL1_CUR_FRAME_DONE_IRQ BIT(9)
+#define CTRL2_SET_OUTSTANDING_REQS_1 0
+#define CTRL2_SET_OUTSTANDING_REQS_2 (0x1 << 21)
+#define CTRL2_SET_OUTSTANDING_REQS_4 (0x2 << 21)
+#define CTRL2_SET_OUTSTANDING_REQS_8 (0x3 << 21)
+#define CTRL2_SET_OUTSTANDING_REQS_16 (0x4 << 21)
+#define CTRL2_SET_OUTSTANDING_REQS_MASK (0x7 << 21)
+
#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
#define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff)