Commit 2dc3620e authored by Leonard Crestez's avatar Leonard Crestez Committed by Stefan Agner

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: default avatarLeonard Crestez <leonard.crestez@nxp.com>
Tested-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: default avatarStefan Agner <stefan@agner.ch>
Reviewed-by: default avatarSean Paul <seanpaul@chromium.org>
Signed-off-by: default avatarStefan Agner <stefan@agner.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/7cdac9c064cc2b8a3d237934f186da98cefe6cb3.1537191359.git.leonard.crestez@nxp.com
parent 626a2c52
...@@ -193,6 +193,21 @@ static int mxsfb_reset_block(void __iomem *reset_addr) ...@@ -193,6 +193,21 @@ static int mxsfb_reset_block(void __iomem *reset_addr)
return clear_poll_bit(reset_addr, MODULE_CLKGATE); return clear_poll_bit(reset_addr, MODULE_CLKGATE);
} }
static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb)
{
struct drm_framebuffer *fb = mxsfb->pipe.plane.state->fb;
struct drm_gem_cma_object *gem;
if (!fb)
return 0;
gem = drm_fb_cma_get_gem_obj(fb, 0);
if (!gem)
return 0;
return gem->paddr;
}
static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
{ {
struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode; 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,8 +284,18 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb) void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
{ {
dma_addr_t paddr;
mxsfb_enable_axi_clk(mxsfb); mxsfb_enable_axi_clk(mxsfb);
mxsfb_crtc_mode_set_nofb(mxsfb); mxsfb_crtc_mode_set_nofb(mxsfb);
/* Write cur_buf as well to avoid an initial corrupt frame */
paddr = mxsfb_get_fb_paddr(mxsfb);
if (paddr) {
writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf);
writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
}
mxsfb_enable_controller(mxsfb); mxsfb_enable_controller(mxsfb);
} }
...@@ -285,12 +310,8 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb, ...@@ -285,12 +310,8 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
{ {
struct drm_simple_display_pipe *pipe = &mxsfb->pipe; struct drm_simple_display_pipe *pipe = &mxsfb->pipe;
struct drm_crtc *crtc = &pipe->crtc; struct drm_crtc *crtc = &pipe->crtc;
struct drm_framebuffer *fb = pipe->plane.state->fb;
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;
struct drm_gem_cma_object *gem; dma_addr_t paddr;
if (!crtc)
return;
spin_lock_irq(&crtc->dev->event_lock); spin_lock_irq(&crtc->dev->event_lock);
event = crtc->state->event; event = crtc->state->event;
...@@ -305,12 +326,10 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb, ...@@ -305,12 +326,10 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
} }
spin_unlock_irq(&crtc->dev->event_lock); spin_unlock_irq(&crtc->dev->event_lock);
if (!fb) paddr = mxsfb_get_fb_paddr(mxsfb);
return; if (paddr) {
mxsfb_enable_axi_clk(mxsfb);
gem = drm_fb_cma_get_gem_obj(fb, 0); writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
mxsfb_disable_axi_clk(mxsfb);
mxsfb_enable_axi_clk(mxsfb); }
writel(gem->paddr, mxsfb->base + mxsfb->devdata->next_buf);
mxsfb_disable_axi_clk(mxsfb);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment