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

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
...@@ -542,13 +542,21 @@ static irqreturn_t decon_lcd_sys_irq_handler(int irq, void *dev_id) ...@@ -542,13 +542,21 @@ static irqreturn_t decon_lcd_sys_irq_handler(int irq, void *dev_id)
{ {
struct decon_context *ctx = dev_id; struct decon_context *ctx = dev_id;
u32 val; u32 val;
int win;
if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled)) if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
goto out; goto out;
val = readl(ctx->addr + DECON_VIDINTCON1); val = readl(ctx->addr + DECON_VIDINTCON1);
if (val & VIDINTCON1_INTFRMDONEPEND) { 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 */ /* clear */
writel(VIDINTCON1_INTFRMDONEPEND, writel(VIDINTCON1_INTFRMDONEPEND,
......
...@@ -623,6 +623,7 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id) ...@@ -623,6 +623,7 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)
{ {
struct decon_context *ctx = (struct decon_context *)dev_id; struct decon_context *ctx = (struct decon_context *)dev_id;
u32 val, clear_bit; u32 val, clear_bit;
int win;
val = readl(ctx->regs + VIDINTCON1); val = readl(ctx->regs + VIDINTCON1);
...@@ -636,7 +637,14 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id) ...@@ -636,7 +637,14 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)
if (!ctx->i80_if) { if (!ctx->i80_if) {
drm_crtc_handle_vblank(&ctx->crtc->base); 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. */ /* set wait vsync event to zero and wake up queue. */
if (atomic_read(&ctx->wait_vsync_event)) { if (atomic_read(&ctx->wait_vsync_event)) {
......
...@@ -197,18 +197,19 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe) ...@@ -197,18 +197,19 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
exynos_crtc->ops->disable_vblank(exynos_crtc); 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; struct drm_crtc *crtc = &exynos_crtc->base;
unsigned long flags; unsigned long flags;
exynos_plane->pending_fb = NULL;
spin_lock_irqsave(&crtc->dev->event_lock, flags); spin_lock_irqsave(&crtc->dev->event_lock, flags);
if (exynos_crtc->event) { if (exynos_crtc->event) {
drm_crtc_send_vblank_event(crtc, exynos_crtc->event); drm_crtc_send_vblank_event(crtc, exynos_crtc->event);
drm_crtc_vblank_put(crtc); drm_crtc_vblank_put(crtc);
wake_up(&exynos_crtc->pending_flip_queue); wake_up(&exynos_crtc->pending_flip_queue);
} }
exynos_crtc->event = NULL; exynos_crtc->event = NULL;
......
...@@ -25,7 +25,8 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, ...@@ -25,7 +25,8 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
void *context); void *context);
int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe); 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_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); void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);
/* This function gets pipe value to crtc device matched with out_type. */ /* This function gets pipe value to crtc device matched with out_type. */
......
...@@ -74,6 +74,7 @@ struct exynos_drm_plane { ...@@ -74,6 +74,7 @@ struct exynos_drm_plane {
unsigned int v_ratio; unsigned int v_ratio;
dma_addr_t dma_addr[MAX_FB_BUFFER]; dma_addr_t dma_addr[MAX_FB_BUFFER];
unsigned int zpos; unsigned int zpos;
struct drm_framebuffer *pending_fb;
}; };
/* /*
......
...@@ -896,6 +896,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id) ...@@ -896,6 +896,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
{ {
struct fimd_context *ctx = (struct fimd_context *)dev_id; struct fimd_context *ctx = (struct fimd_context *)dev_id;
u32 val, clear_bit; u32 val, clear_bit;
int win;
val = readl(ctx->regs + VIDINTCON1); val = readl(ctx->regs + VIDINTCON1);
...@@ -910,7 +911,14 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id) ...@@ -910,7 +911,14 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
if (!ctx->i80_if) if (!ctx->i80_if)
drm_crtc_handle_vblank(&ctx->crtc->base); 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);
}
if (ctx->i80_if) { if (ctx->i80_if) {
/* Exits triggering mode */ /* Exits triggering mode */
......
...@@ -168,6 +168,8 @@ static void exynos_plane_atomic_update(struct drm_plane *plane, ...@@ -168,6 +168,8 @@ static void exynos_plane_atomic_update(struct drm_plane *plane,
state->src_x >> 16, state->src_y >> 16, state->src_x >> 16, state->src_y >> 16,
state->src_w >> 16, state->src_h >> 16); state->src_w >> 16, state->src_h >> 16);
exynos_plane->pending_fb = state->fb;
if (exynos_crtc->ops->update_plane) if (exynos_crtc->ops->update_plane)
exynos_crtc->ops->update_plane(exynos_crtc, exynos_plane); exynos_crtc->ops->update_plane(exynos_crtc, exynos_plane);
} }
......
...@@ -179,6 +179,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work) ...@@ -179,6 +179,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
{ {
struct vidi_context *ctx = container_of(work, struct vidi_context, struct vidi_context *ctx = container_of(work, struct vidi_context,
work); work);
int win;
if (ctx->pipe < 0) if (ctx->pipe < 0)
return; return;
...@@ -197,7 +198,14 @@ static void vidi_fake_vblank_handler(struct work_struct *work) ...@@ -197,7 +198,14 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
mutex_unlock(&ctx->lock); mutex_unlock(&ctx->lock);
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);
}
} }
static int vidi_show_connection(struct device *dev, static int vidi_show_connection(struct device *dev,
......
...@@ -716,6 +716,7 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) ...@@ -716,6 +716,7 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
struct mixer_context *ctx = arg; struct mixer_context *ctx = arg;
struct mixer_resources *res = &ctx->mixer_res; struct mixer_resources *res = &ctx->mixer_res;
u32 val, base, shadow; u32 val, base, shadow;
int win;
spin_lock(&res->reg_slock); spin_lock(&res->reg_slock);
...@@ -742,7 +743,14 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) ...@@ -742,7 +743,14 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
} }
drm_crtc_handle_vblank(&ctx->crtc->base); drm_crtc_handle_vblank(&ctx->crtc->base);
exynos_drm_crtc_finish_pageflip(ctx->crtc); for (win = 0 ; win < MIXER_WIN_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. */ /* set wait vsync event to zero and wake up queue. */
if (atomic_read(&ctx->wait_vsync_event)) { if (atomic_read(&ctx->wait_vsync_event)) {
......
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