Commit 90ed5785 authored by Niklas Söderlund's avatar Niklas Söderlund Committed by Mauro Carvalho Chehab

media: rcar-vin: Use scratch buffer when not in running state

In its early stages the VIN driver did not use an internal scratch
buffer. This leads to a unnecessary complex start and stop behavior,
specially for TB/BT. The driver now always allocates a scratch buffer to
deal with buffer under-runs, use the scratch buffer to also simplify
starting and stopping.

When capture is starting use the scratch buffer instead of a user-space
buffers while syncing the driver with the hardware state. This allows
the driver to know that no user-space buffer is given to the hardware
before the running state is reached.

When capture is stopping use the scratch buffer instead of leaving the
user-space buffers in place and add a check that all user-space buffers
are processed by the hardware before transitioning from the stopping to
stopped state. This allows the driver to know all user-space buffers
given to the hardware are fully processed.

This change in itself does not improve the driver much but it paves the
way for future simplifications and enhancements. One direct improvement
of this change is that TB/BT buffers returned to user-space while stopping
will always contain both fields, that was not guaranteed before.
Signed-off-by: default avatarNiklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: default avatarJacopo Mondi <jacopo+renesas@jmondi.org>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 8b77d1f9
......@@ -905,7 +905,7 @@ static void rvin_fill_hw_slot(struct rvin_dev *vin, int slot)
vin->format.sizeimage / 2;
break;
}
} else if (list_empty(&vin->buf_list)) {
} else if (vin->state != RUNNING || list_empty(&vin->buf_list)) {
vin->buf_hw[slot].buffer = NULL;
vin->buf_hw[slot].type = FULL;
phys_addr = vin->scratch_phys;
......@@ -998,12 +998,6 @@ static irqreturn_t rvin_irq(int irq, void *data)
goto done;
}
/* Nothing to do if capture status is 'STOPPING' */
if (vin->state == STOPPING) {
vin_dbg(vin, "IRQ while state stopping\n");
goto done;
}
/* Prepare for capture and update state */
vnms = rvin_read(vin, VNMS_REG);
slot = (vnms & VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
......@@ -1313,14 +1307,32 @@ static int rvin_start_streaming(struct vb2_queue *vq, unsigned int count)
static void rvin_stop_streaming(struct vb2_queue *vq)
{
struct rvin_dev *vin = vb2_get_drv_priv(vq);
unsigned int i, retries;
unsigned long flags;
int retries = 0;
bool buffersFreed;
spin_lock_irqsave(&vin->qlock, flags);
vin->state = STOPPING;
/* Wait until only scratch buffer is used, max 3 interrupts. */
retries = 0;
while (retries++ < RVIN_RETRIES) {
buffersFreed = true;
for (i = 0; i < HW_BUFFER_NUM; i++)
if (vin->buf_hw[i].buffer)
buffersFreed = false;
if (buffersFreed)
break;
spin_unlock_irqrestore(&vin->qlock, flags);
msleep(RVIN_TIMEOUT_MS);
spin_lock_irqsave(&vin->qlock, flags);
}
/* Wait for streaming to stop */
retries = 0;
while (retries++ < RVIN_RETRIES) {
rvin_capture_stop(vin);
......@@ -1336,7 +1348,7 @@ static void rvin_stop_streaming(struct vb2_queue *vq)
spin_lock_irqsave(&vin->qlock, flags);
}
if (vin->state != STOPPED) {
if (!buffersFreed || vin->state != STOPPED) {
/*
* If this happens something have gone horribly wrong.
* Set state to stopped to prevent the interrupt handler
......
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