diff options
author | Leonard Crestez <leonard.crestez@nxp.com> | 2018-09-17 09:42:12 -0400 |
---|---|---|
committer | Stefan Agner <stefan@agner.ch> | 2018-09-26 16:07:40 -0400 |
commit | 2dc3620eac2df1545bc4a4b9110dcc7961c24a50 (patch) | |
tree | ea718c68775cb44af5648c47fa0d278669ac1fc1 | |
parent | 626a2c52f1050b4581a0ffcd71245505b24315a2 (diff) |
drm/mxsfb: Fix initial corrupt frame when activating display
LCDIF will repeatedly display data from CUR_BUF and set CUR_BUF to
NEXT_BUF when done. Since we are only ever writing to NEXT_BUF the
display will show an initial corrupt frame.
Fix by writing the FB paddr to both CUR_BUF and NEXT_BUF when
activating the CRTC.
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Stefan Agner <stefan@agner.ch>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Stefan Agner <stefan@agner.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/7cdac9c064cc2b8a3d237934f186da98cefe6cb3.1537191359.git.leonard.crestez@nxp.com
-rw-r--r-- | drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index e4fcbb65b969..24b1f0c1432e 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c | |||
@@ -193,6 +193,21 @@ static int mxsfb_reset_block(void __iomem *reset_addr) | |||
193 | return clear_poll_bit(reset_addr, MODULE_CLKGATE); | 193 | return clear_poll_bit(reset_addr, MODULE_CLKGATE); |
194 | } | 194 | } |
195 | 195 | ||
196 | static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb) | ||
197 | { | ||
198 | struct drm_framebuffer *fb = mxsfb->pipe.plane.state->fb; | ||
199 | struct drm_gem_cma_object *gem; | ||
200 | |||
201 | if (!fb) | ||
202 | return 0; | ||
203 | |||
204 | gem = drm_fb_cma_get_gem_obj(fb, 0); | ||
205 | if (!gem) | ||
206 | return 0; | ||
207 | |||
208 | return gem->paddr; | ||
209 | } | ||
210 | |||
196 | static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) | 211 | static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) |
197 | { | 212 | { |
198 | struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode; | 213 | struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode; |
@@ -269,8 +284,18 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) | |||
269 | 284 | ||
270 | void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb) | 285 | void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb) |
271 | { | 286 | { |
287 | dma_addr_t paddr; | ||
288 | |||
272 | mxsfb_enable_axi_clk(mxsfb); | 289 | mxsfb_enable_axi_clk(mxsfb); |
273 | mxsfb_crtc_mode_set_nofb(mxsfb); | 290 | mxsfb_crtc_mode_set_nofb(mxsfb); |
291 | |||
292 | /* Write cur_buf as well to avoid an initial corrupt frame */ | ||
293 | paddr = mxsfb_get_fb_paddr(mxsfb); | ||
294 | if (paddr) { | ||
295 | writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf); | ||
296 | writel(paddr, mxsfb->base + mxsfb->devdata->next_buf); | ||
297 | } | ||
298 | |||
274 | mxsfb_enable_controller(mxsfb); | 299 | mxsfb_enable_controller(mxsfb); |
275 | } | 300 | } |
276 | 301 | ||
@@ -285,12 +310,8 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb, | |||
285 | { | 310 | { |
286 | struct drm_simple_display_pipe *pipe = &mxsfb->pipe; | 311 | struct drm_simple_display_pipe *pipe = &mxsfb->pipe; |
287 | struct drm_crtc *crtc = &pipe->crtc; | 312 | struct drm_crtc *crtc = &pipe->crtc; |
288 | struct drm_framebuffer *fb = pipe->plane.state->fb; | ||
289 | struct drm_pending_vblank_event *event; | 313 | struct drm_pending_vblank_event *event; |
290 | struct drm_gem_cma_object *gem; | 314 | dma_addr_t paddr; |
291 | |||
292 | if (!crtc) | ||
293 | return; | ||
294 | 315 | ||
295 | spin_lock_irq(&crtc->dev->event_lock); | 316 | spin_lock_irq(&crtc->dev->event_lock); |
296 | event = crtc->state->event; | 317 | event = crtc->state->event; |
@@ -305,12 +326,10 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb, | |||
305 | } | 326 | } |
306 | spin_unlock_irq(&crtc->dev->event_lock); | 327 | spin_unlock_irq(&crtc->dev->event_lock); |
307 | 328 | ||
308 | if (!fb) | 329 | paddr = mxsfb_get_fb_paddr(mxsfb); |
309 | return; | 330 | if (paddr) { |
310 | 331 | mxsfb_enable_axi_clk(mxsfb); | |
311 | gem = drm_fb_cma_get_gem_obj(fb, 0); | 332 | writel(paddr, mxsfb->base + mxsfb->devdata->next_buf); |
312 | 333 | mxsfb_disable_axi_clk(mxsfb); | |
313 | mxsfb_enable_axi_clk(mxsfb); | 334 | } |
314 | writel(gem->paddr, mxsfb->base + mxsfb->devdata->next_buf); | ||
315 | mxsfb_disable_axi_clk(mxsfb); | ||
316 | } | 335 | } |