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

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
Loading
Loading
Loading
Loading
+32 −13
Original line number Diff line number Diff line
@@ -193,6 +193,21 @@ static int mxsfb_reset_block(void __iomem *reset_addr)
	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)
{
	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)

void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
{
	dma_addr_t paddr;

	mxsfb_enable_axi_clk(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);
}

@@ -285,12 +310,8 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
{
	struct drm_simple_display_pipe *pipe = &mxsfb->pipe;
	struct drm_crtc *crtc = &pipe->crtc;
	struct drm_framebuffer *fb = pipe->plane.state->fb;
	struct drm_pending_vblank_event *event;
	struct drm_gem_cma_object *gem;

	if (!crtc)
		return;
	dma_addr_t paddr;

	spin_lock_irq(&crtc->dev->event_lock);
	event = crtc->state->event;
@@ -305,12 +326,10 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
	}
	spin_unlock_irq(&crtc->dev->event_lock);

	if (!fb)
		return;

	gem = drm_fb_cma_get_gem_obj(fb, 0);

	paddr = mxsfb_get_fb_paddr(mxsfb);
	if (paddr) {
		mxsfb_enable_axi_clk(mxsfb);
	writel(gem->paddr, mxsfb->base + mxsfb->devdata->next_buf);
		writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
		mxsfb_disable_axi_clk(mxsfb);
	}
}