diff --git a/drivers/media/video/s5p-tv/mixer.h b/drivers/media/video/s5p-tv/mixer.h index 1597078c4a5070043270d1b54b9d980ba6cadc90..fa3e30f27447439c9e207315cf99577444a23157 100644 --- a/drivers/media/video/s5p-tv/mixer.h +++ b/drivers/media/video/s5p-tv/mixer.h @@ -226,6 +226,7 @@ struct mxr_resources { /* event flags used */ enum mxr_devide_flags { MXR_EVENT_VSYNC = 0, + MXR_EVENT_TOP = 1, }; /** drivers instance */ diff --git a/drivers/media/video/s5p-tv/mixer_reg.c b/drivers/media/video/s5p-tv/mixer_reg.c index 4800a3cbb297726a235e4d7cdc1e7fc055b1efce..3b1670a045f4ac4d67df4e24434db2b01232cde0 100644 --- a/drivers/media/video/s5p-tv/mixer_reg.c +++ b/drivers/media/video/s5p-tv/mixer_reg.c @@ -296,21 +296,25 @@ irqreturn_t mxr_irq_handler(int irq, void *dev_data) /* wake up process waiting for VSYNC */ if (val & MXR_INT_STATUS_VSYNC) { set_bit(MXR_EVENT_VSYNC, &mdev->event_flags); + /* toggle TOP field event if working in interlaced mode */ + if (~mxr_read(mdev, MXR_CFG) & MXR_CFG_SCAN_PROGRASSIVE) + change_bit(MXR_EVENT_TOP, &mdev->event_flags); wake_up(&mdev->event_queue); - } - - /* clear interrupts */ - if (~val & MXR_INT_EN_VSYNC) { /* vsync interrupt use different bit for read and clear */ - val &= ~MXR_INT_EN_VSYNC; + val &= ~MXR_INT_STATUS_VSYNC; val |= MXR_INT_CLEAR_VSYNC; } + + /* clear interrupts */ mxr_write(mdev, MXR_INT_STATUS, val); spin_unlock(&mdev->reg_slock); /* leave on non-vsync event */ if (~val & MXR_INT_CLEAR_VSYNC) return IRQ_HANDLED; + /* skip layer update on bottom field */ + if (!test_bit(MXR_EVENT_TOP, &mdev->event_flags)) + return IRQ_HANDLED; for (i = 0; i < MXR_MAX_LAYERS; ++i) mxr_irq_layer_handle(mdev->layer[i]); return IRQ_HANDLED; @@ -333,6 +337,7 @@ void mxr_reg_streamon(struct mxr_device *mdev) /* start MIXER */ mxr_write_mask(mdev, MXR_STATUS, ~0, MXR_STATUS_REG_RUN); + set_bit(MXR_EVENT_TOP, &mdev->event_flags); spin_unlock_irqrestore(&mdev->reg_slock, flags); }