aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_crtc.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 1144e0c9e894..0abe77675b76 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -35,6 +35,13 @@
35#include "mxsfb_drv.h" 35#include "mxsfb_drv.h"
36#include "mxsfb_regs.h" 36#include "mxsfb_regs.h"
37 37
38#define MXS_SET_ADDR 0x4
39#define MXS_CLR_ADDR 0x8
40#define MODULE_CLKGATE BIT(30)
41#define MODULE_SFTRST BIT(31)
42/* 1 second delay should be plenty of time for block reset */
43#define RESET_TIMEOUT 1000000
44
38static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val) 45static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
39{ 46{
40 return (val & mxsfb->devdata->hs_wdth_mask) << 47 return (val & mxsfb->devdata->hs_wdth_mask) <<
@@ -159,6 +166,36 @@ static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
159 clk_disable_unprepare(mxsfb->clk_disp_axi); 166 clk_disable_unprepare(mxsfb->clk_disp_axi);
160} 167}
161 168
169/*
170 * Clear the bit and poll it cleared. This is usually called with
171 * a reset address and mask being either SFTRST(bit 31) or CLKGATE
172 * (bit 30).
173 */
174static int clear_poll_bit(void __iomem *addr, u32 mask)
175{
176 u32 reg;
177
178 writel(mask, addr + MXS_CLR_ADDR);
179 return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT);
180}
181
182static int mxsfb_reset_block(void __iomem *reset_addr)
183{
184 int ret;
185
186 ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
187 if (ret)
188 return ret;
189
190 writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
191
192 ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
193 if (ret)
194 return ret;
195
196 return clear_poll_bit(reset_addr, MODULE_CLKGATE);
197}
198
162static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) 199static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
163{ 200{
164 struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode; 201 struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
@@ -173,6 +210,11 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
173 */ 210 */
174 mxsfb_enable_axi_clk(mxsfb); 211 mxsfb_enable_axi_clk(mxsfb);
175 212
213 /* Mandatory eLCDIF reset as per the Reference Manual */
214 err = mxsfb_reset_block(mxsfb->base);
215 if (err)
216 return;
217
176 /* Clear the FIFOs */ 218 /* Clear the FIFOs */
177 writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET); 219 writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
178 220