summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/rcar-vin
diff options
context:
space:
mode:
authorNiklas Söderlund <niklas.soderlund+renesas@ragnatech.se>2018-05-28 19:26:37 -0400
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-06-28 07:24:54 -0400
commit23689ab1add36964b69b6e4fdb97d52f315119f5 (patch)
treef8cd76f41eaa9ee848b5ed54bd6ed0feb92bc7dc /drivers/media/platform/rcar-vin
parente10cf92ead486b24a3169bb3b3215cf5775225fd (diff)
downloadlinux-23689ab1add36964b69b6e4fdb97d52f315119f5.tar.bz2
media: rcar-vin: sync which hardware buffer to start capture from
When starting the VIN capture procedure we are not guaranteed that the first buffer written to is VnMB1 to which we assigned the first buffer queued. This is problematic for two reasons. Buffers might not be dequeued in the same order they where queued for capture. Future features planed for the VIN driver is support for outputting frames in SEQ_TB/BT format and to do that it's important that capture starts from the first buffer slot, VnMB1. We are guaranteed that capturing always happens in sequence (VnMB1 -> VnMB2 -> VnMB3 -> VnMB1). So drop up to two frames when starting capturing so that the driver always returns buffers in the same order they are queued and prepare for SEQ_TB/BT output. Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'drivers/media/platform/rcar-vin')
-rw-r--r--drivers/media/platform/rcar-vin/rcar-dma.c16
-rw-r--r--drivers/media/platform/rcar-vin/rcar-vin.h2
2 files changed, 17 insertions, 1 deletions
diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c
index ac07f99e3516..cfe5d7a9d44e 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -856,7 +856,7 @@ static int rvin_capture_start(struct rvin_dev *vin)
/* Continuous Frame Capture Mode */
rvin_write(vin, VNFC_C_FRAME, VNFC_REG);
- vin->state = RUNNING;
+ vin->state = STARTING;
return 0;
}
@@ -910,6 +910,20 @@ static irqreturn_t rvin_irq(int irq, void *data)
vnms = rvin_read(vin, VNMS_REG);
slot = (vnms & VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
+ /*
+ * To hand buffers back in a known order to userspace start
+ * to capture first from slot 0.
+ */
+ if (vin->state == STARTING) {
+ if (slot != 0) {
+ vin_dbg(vin, "Starting sync slot: %d\n", slot);
+ goto done;
+ }
+
+ vin_dbg(vin, "Capture start synced!\n");
+ vin->state = RUNNING;
+ }
+
/* Capture frame */
if (vin->queue_buf[slot]) {
vin->queue_buf[slot]->field = vin->format.field;
diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
index c2aef789b491..ff747e22d8cf 100644
--- a/drivers/media/platform/rcar-vin/rcar-vin.h
+++ b/drivers/media/platform/rcar-vin/rcar-vin.h
@@ -53,11 +53,13 @@ enum rvin_csi_id {
/**
* STOPPED - No operation in progress
+ * STARTING - Capture starting up
* RUNNING - Operation in progress have buffers
* STOPPING - Stopping operation
*/
enum rvin_dma_state {
STOPPED = 0,
+ STARTING,
RUNNING,
STOPPING,
};