writel(val, ctx->addr + DECON_TRIGCON);
}
+static void decon_update(struct decon_context *ctx)
+{
+ decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
+}
+
+static void decon_wait_for_update(struct decon_context *ctx)
+{
+ /* wait up to duration of 2 frames */
+ unsigned long timeout = jiffies + msecs_to_jiffies(2 * 1000 / 60);
+
+ while (readl(ctx->addr + DECON_UPDATE) & STANDALONE_UPDATE_F) {
+ if (time_is_after_jiffies(timeout))
+ break;
+ usleep_range(500, 1000);
+ }
+}
+
static void decon_commit(struct exynos_drm_crtc *crtc)
{
struct decon_context *ctx = crtc->ctx;
bool interlaced = false;
u32 val;
+ decon_wait_for_update(ctx);
+
decon_set_bits(ctx, DECON_VIDCON0, VIDCON0_ENVID, 0);
/* enable clock gate */
/* enable output and display signal */
decon_set_bits(ctx, DECON_VIDCON0, VIDCON0_ENVID | VIDCON0_ENVID_F, ~0);
+ decon_update(ctx);
}
#define BIT_VAL(x, e, s) (((x) & ((1 << ((e) - (s) + 1)) - 1)) << (s))
return;
}
+ decon_wait_for_update(ctx);
+
decon_shadow_protect_win(ctx, win, true);
/* FIXME: padding? padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width */
decon_shadow_protect_win(ctx, win, false);
- /* standalone update */
- val = readl(ctx->addr + DECON_UPDATE);
- val |= STANDALONE_UPDATE_F;
- writel(val, ctx->addr + DECON_UPDATE);
+ decon_update(ctx);
if (ctx->i80_if && ctx->trg_type == EXYNOS_DISPLAY_SW_TRIGGER)
atomic_set(&ctx->win_updated, 1);
return;
}
+ decon_wait_for_update(ctx);
+
decon_shadow_protect_win(ctx, win, true);
/* window disable */
decon_shadow_protect_win(ctx, win, false);
- /* standalone update */
- val = readl(ctx->addr + DECON_UPDATE);
- val |= STANDALONE_UPDATE_F;
- writel(val, ctx->addr + DECON_UPDATE);
+ decon_update(ctx);
plane->enabled = false;
}
goto err;
}
+ decon_wait_for_update(ctx);
+
for (win = 0; win < WINDOWS_NR; win++) {
/* shadow update disable */
val = readl(ctx->addr + DECON_SHADOWCON);
val = readl(ctx->addr + DECON_SHADOWCON);
val &= ~SHADOWCON_Wx_PROTECT(win);
writel(val, ctx->addr + DECON_SHADOWCON);
-
- /* standalone update */
- val = readl(ctx->addr + DECON_UPDATE);
- val |= STANDALONE_UPDATE_F;
- writel(val, ctx->addr + DECON_UPDATE);
}
+ decon_update(ctx);
+
atomic_set(&ctx->wait_vsync_event, 1);
/*