Commit ef6a6ddc authored by Tomasz Stanislawski's avatar Tomasz Stanislawski Committed by Mauro Carvalho Chehab

[media] v4l: s5p-tv: mixer: fix handling of interlaced modes

The next frame was fetched by Mixer at every VSYNC event.  This caused tearing
when Mixer's output in interlaced mode.  This patch fixes this bug by fetching
new frame every second VSYNC when working in interlaced mode.
Signed-off-by: default avatarTomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 2fd07a4a
...@@ -226,6 +226,7 @@ struct mxr_resources { ...@@ -226,6 +226,7 @@ struct mxr_resources {
/* event flags used */ /* event flags used */
enum mxr_devide_flags { enum mxr_devide_flags {
MXR_EVENT_VSYNC = 0, MXR_EVENT_VSYNC = 0,
MXR_EVENT_TOP = 1,
}; };
/** drivers instance */ /** drivers instance */
......
...@@ -296,21 +296,25 @@ irqreturn_t mxr_irq_handler(int irq, void *dev_data) ...@@ -296,21 +296,25 @@ irqreturn_t mxr_irq_handler(int irq, void *dev_data)
/* wake up process waiting for VSYNC */ /* wake up process waiting for VSYNC */
if (val & MXR_INT_STATUS_VSYNC) { if (val & MXR_INT_STATUS_VSYNC) {
set_bit(MXR_EVENT_VSYNC, &mdev->event_flags); 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); wake_up(&mdev->event_queue);
}
/* clear interrupts */
if (~val & MXR_INT_EN_VSYNC) {
/* vsync interrupt use different bit for read and clear */ /* vsync interrupt use different bit for read and clear */
val &= ~MXR_INT_EN_VSYNC; val &= ~MXR_INT_STATUS_VSYNC;
val |= MXR_INT_CLEAR_VSYNC; val |= MXR_INT_CLEAR_VSYNC;
} }
/* clear interrupts */
mxr_write(mdev, MXR_INT_STATUS, val); mxr_write(mdev, MXR_INT_STATUS, val);
spin_unlock(&mdev->reg_slock); spin_unlock(&mdev->reg_slock);
/* leave on non-vsync event */ /* leave on non-vsync event */
if (~val & MXR_INT_CLEAR_VSYNC) if (~val & MXR_INT_CLEAR_VSYNC)
return IRQ_HANDLED; 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) for (i = 0; i < MXR_MAX_LAYERS; ++i)
mxr_irq_layer_handle(mdev->layer[i]); mxr_irq_layer_handle(mdev->layer[i]);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -333,6 +337,7 @@ void mxr_reg_streamon(struct mxr_device *mdev) ...@@ -333,6 +337,7 @@ void mxr_reg_streamon(struct mxr_device *mdev)
/* start MIXER */ /* start MIXER */
mxr_write_mask(mdev, MXR_STATUS, ~0, MXR_STATUS_REG_RUN); 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); spin_unlock_irqrestore(&mdev->reg_slock, flags);
} }
......
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