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: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: Inki Dae <inki.dae@samsung.com>

fixup! drm/exynos: check for pending fb before finish update
This commit is contained in:
Gustavo Padovan 2015-08-15 13:26:14 -03:00 committed by Inki Dae
parent ce3ff36be9
commit 822f6dfd71
9 changed files with 54 additions and 9 deletions

View File

@ -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,

View File

@ -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)) {

View File

@ -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;

View File

@ -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. */

View File

@ -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;
};
/*

View File

@ -896,6 +896,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
{
struct fimd_context *ctx = (struct fimd_context *)dev_id;
u32 val, clear_bit;
int win;
val = readl(ctx->regs + VIDINTCON1);
@ -910,7 +911,14 @@ static irqreturn_t fimd_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);
}
if (ctx->i80_if) {
/* Exits triggering mode */

View File

@ -168,6 +168,8 @@ static void exynos_plane_atomic_update(struct drm_plane *plane,
state->src_x >> 16, state->src_y >> 16,
state->src_w >> 16, state->src_h >> 16);
exynos_plane->pending_fb = state->fb;
if (exynos_crtc->ops->update_plane)
exynos_crtc->ops->update_plane(exynos_crtc, exynos_plane);
}

View File

@ -179,6 +179,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
{
struct vidi_context *ctx = container_of(work, struct vidi_context,
work);
int win;
if (ctx->pipe < 0)
return;
@ -197,7 +198,14 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
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,

View File

@ -716,6 +716,7 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
struct mixer_context *ctx = arg;
struct mixer_resources *res = &ctx->mixer_res;
u32 val, base, shadow;
int win;
spin_lock(&res->reg_slock);
@ -742,7 +743,14 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
}
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. */
if (atomic_read(&ctx->wait_vsync_event)) {