瀏覽代碼

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>
Niklas Söderlund 7 年之前
父節點
當前提交
23689ab1ad
共有 2 個文件被更改,包括 17 次插入1 次删除
  1. 15 1
      drivers/media/platform/rcar-vin/rcar-dma.c
  2. 2 0
      drivers/media/platform/rcar-vin/rcar-vin.h

+ 15 - 1
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 */
 	/* Continuous Frame Capture Mode */
 	rvin_write(vin, VNFC_C_FRAME, VNFC_REG);
 	rvin_write(vin, VNFC_C_FRAME, VNFC_REG);
 
 
-	vin->state = RUNNING;
+	vin->state = STARTING;
 
 
 	return 0;
 	return 0;
 }
 }
@@ -910,6 +910,20 @@ static irqreturn_t rvin_irq(int irq, void *data)
 	vnms = rvin_read(vin, VNMS_REG);
 	vnms = rvin_read(vin, VNMS_REG);
 	slot = (vnms & VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
 	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 */
 	/* Capture frame */
 	if (vin->queue_buf[slot]) {
 	if (vin->queue_buf[slot]) {
 		vin->queue_buf[slot]->field = vin->format.field;
 		vin->queue_buf[slot]->field = vin->format.field;

+ 2 - 0
drivers/media/platform/rcar-vin/rcar-vin.h

@@ -53,11 +53,13 @@ enum rvin_csi_id {
 
 
 /**
 /**
  * STOPPED  - No operation in progress
  * STOPPED  - No operation in progress
+ * STARTING - Capture starting up
  * RUNNING  - Operation in progress have buffers
  * RUNNING  - Operation in progress have buffers
  * STOPPING - Stopping operation
  * STOPPING - Stopping operation
  */
  */
 enum rvin_dma_state {
 enum rvin_dma_state {
 	STOPPED = 0,
 	STOPPED = 0,
+	STARTING,
 	RUNNING,
 	RUNNING,
 	STOPPING,
 	STOPPING,
 };
 };