Move the mixer's layer update command out of the vsync interrupt and do
it only once per layer per vsync. We also don't want to finish a
pageflip if a layer update is in progress since it will still be
scanning out and X/userspace will start drawing to the front buffer.
BUG=chrome-os-partner:13692
TEST=Tested on snow, no corruption detected
Change-Id: I811da726daaf52117f9a42a299dbc98b43d7c3bd
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/33252
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
unsigned int mode_width;
unsigned int mode_height;
unsigned int scan_flags;
unsigned int mode_width;
unsigned int mode_height;
unsigned int scan_flags;
};
struct mixer_resources {
};
struct mixer_resources {
+static int mixer_get_layer_update_count(struct mixer_context *ctx)
+{
+ struct mixer_resources *res = &ctx->mixer_res;
+ u32 val;
+
+ if (!res->is_soc_exynos5)
+ return 0;
+
+ val = mixer_reg_read(res, MXR_CFG);
+
+ return (val & MXR_CFG_LAYER_UPDATE_COUNT_MASK) >>
+ MXR_CFG_LAYER_UPDATE_COUNT0;
+}
+
+static void mixer_layer_update(struct mixer_context *ctx)
+{
+ struct mixer_resources *res = &ctx->mixer_res;
+
+ if (!res->is_soc_exynos5)
+ return;
+
+ mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
+}
+
static void vp_video_buffer(struct mixer_context *ctx, int win)
{
struct mixer_resources *res = &ctx->mixer_res;
static void vp_video_buffer(struct mixer_context *ctx, int win)
{
struct mixer_resources *res = &ctx->mixer_res;
mixer_cfg_rgb_fmt(ctx, mode_height);
mixer_cfg_layer(ctx, win, true);
mixer_cfg_layer(ctx, MIXER_DEFAULT_WIN, true);
mixer_cfg_rgb_fmt(ctx, mode_height);
mixer_cfg_layer(ctx, win, true);
mixer_cfg_layer(ctx, MIXER_DEFAULT_WIN, true);
+
+ /* Only allow one update per vsync */
+ if (!win_data->updated)
+ mixer_layer_update(ctx);
+
+ win_data->updated = true;
+
mixer_run(ctx);
mixer_vsync_set_update(ctx, true);
mixer_run(ctx);
mixer_vsync_set_update(ctx, true);
struct mixer_context *ctx = drm_hdmi_ctx->ctx;
struct mixer_resources *res = &ctx->mixer_res;
u32 val, base, shadow;
struct mixer_context *ctx = drm_hdmi_ctx->ctx;
struct mixer_resources *res = &ctx->mixer_res;
u32 val, base, shadow;
spin_lock(&res->reg_slock);
spin_lock(&res->reg_slock);
wake_up(&ctx->mixer_res.event_queue);
goto out;
}
wake_up(&ctx->mixer_res.event_queue);
goto out;
}
- /* layer update mandatory for exynos5 soc,and not present
- * in exynos4 */
- if (res->is_soc_exynos5)
- mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
/* interlace scan need to check shadow register */
if (ctx->interlace) {
/* interlace scan need to check shadow register */
if (ctx->interlace) {
}
drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
}
drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
+
+ /* Bail out if a layer update is pending */
+ if (mixer_get_layer_update_count(ctx))
+ goto out;
+
+ for (i = 0; i < MIXER_WIN_NR; i++)
+ ctx->win_data[i].updated = false;
+
exynos_drm_crtc_finish_pageflip(drm_hdmi_ctx->drm_dev,
ctx->pipe);
exynos_drm_crtc_finish_pageflip(drm_hdmi_ctx->drm_dev,
ctx->pipe);
/* Adding reset and Layer update registers Exynos5 */
#define MXR_CFG_LAYER_UPDATE (1 << 31)
/* Adding reset and Layer update registers Exynos5 */
#define MXR_CFG_LAYER_UPDATE (1 << 31)
+#define MXR_CFG_LAYER_UPDATE_COUNT0 29
+#define MXR_CFG_LAYER_UPDATE_COUNT_MASK ((1 << 29) | (1 << 30))
#define MXR_STATUS_SOFT_RESET (1 << 8)
#endif /* SAMSUNG_REGS_MIXER_H */
#define MXR_STATUS_SOFT_RESET (1 << 8)
#endif /* SAMSUNG_REGS_MIXER_H */