Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 822f6dfd authored by Gustavo Padovan's avatar Gustavo Padovan Committed by Inki Dae
Browse files

drm/exynos: check for pending fb before finish update



The current code was ignoring the end of update for all overlay planes,
caring only for the primary plane update in case of pageflip.

This change adds a change to start to check for pending updates for all
planes through exynos_plane->pending_fb. At the start of plane update the
pending_fb is set with the fb to be shown on the screen. Then only when to
fb is already presented in the screen we set pending_fb to NULL to
signal that the update was finished.

Signed-off-by: default avatarGustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>

fixup! drm/exynos: check for pending fb before finish update
parent ce3ff36b
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -542,13 +542,21 @@ static irqreturn_t decon_lcd_sys_irq_handler(int irq, void *dev_id)
{
	struct decon_context *ctx = dev_id;
	u32 val;
	int win;

	if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
		goto out;

	val = readl(ctx->addr + DECON_VIDINTCON1);
	if (val & VIDINTCON1_INTFRMDONEPEND) {
		exynos_drm_crtc_finish_pageflip(ctx->crtc);
		for (win = 0 ; win < WINDOWS_NR ; win++) {
			struct exynos_drm_plane *plane = &ctx->planes[win];

			if (!plane->pending_fb)
				continue;

			exynos_drm_crtc_finish_update(ctx->crtc, plane);
		}

		/* clear */
		writel(VIDINTCON1_INTFRMDONEPEND,
+9 −1
Original line number Diff line number Diff line
@@ -623,6 +623,7 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)
{
	struct decon_context *ctx = (struct decon_context *)dev_id;
	u32 val, clear_bit;
	int win;

	val = readl(ctx->regs + VIDINTCON1);

@@ -636,7 +637,14 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)

	if (!ctx->i80_if) {
		drm_crtc_handle_vblank(&ctx->crtc->base);
		exynos_drm_crtc_finish_pageflip(ctx->crtc);
		for (win = 0 ; win < WINDOWS_NR ; win++) {
			struct exynos_drm_plane *plane = &ctx->planes[win];

			if (!plane->pending_fb)
				continue;

			exynos_drm_crtc_finish_update(ctx->crtc, plane);
		}

		/* set wait vsync event to zero and wake up queue. */
		if (atomic_read(&ctx->wait_vsync_event)) {
+4 −3
Original line number Diff line number Diff line
@@ -197,18 +197,19 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
		exynos_crtc->ops->disable_vblank(exynos_crtc);
}

void exynos_drm_crtc_finish_pageflip(struct exynos_drm_crtc *exynos_crtc)
void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
				struct exynos_drm_plane *exynos_plane)
{
	struct drm_crtc *crtc = &exynos_crtc->base;
	unsigned long flags;

	exynos_plane->pending_fb = NULL;

	spin_lock_irqsave(&crtc->dev->event_lock, flags);
	if (exynos_crtc->event) {

		drm_crtc_send_vblank_event(crtc, exynos_crtc->event);
		drm_crtc_vblank_put(crtc);
		wake_up(&exynos_crtc->pending_flip_queue);

	}

	exynos_crtc->event = NULL;
+2 −1
Original line number Diff line number Diff line
@@ -25,7 +25,8 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
					void *context);
int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe);
void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe);
void exynos_drm_crtc_finish_pageflip(struct exynos_drm_crtc *exynos_crtc);
void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
				   struct exynos_drm_plane *exynos_plane);
void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);

/* This function gets pipe value to crtc device matched with out_type. */
+1 −0
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ struct exynos_drm_plane {
	unsigned int v_ratio;
	dma_addr_t dma_addr[MAX_FB_BUFFER];
	unsigned int zpos;
	struct drm_framebuffer *pending_fb;
};

/*
Loading