Web lists-archives.com

[PATCH] sh_mobile_ceu_camera: add VBP error cure operation




If CEU driver can not receive data from camera,
CETCR has VBP error state.
Then, CEU is stopped and cure operation is needed.
This patch add VBP error cure operation.
Special thanks to Magnus

Signed-off-by: Kuninori Morimoto <morimoto.kuninori@xxxxxxxxxxx>
---
 drivers/media/video/sh_mobile_ceu_camera.c |   33 +++++++++++++++++++++------
 1 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 0db88a5..7ce78a3 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -182,26 +182,42 @@ static void free_buffer(struct videobuf_queue *vq,
 #define CEU_CETCR_MAGIC 0x0317f313 /* acknowledge magical interrupt sources */
 #define CEU_CETCR_IGRW (1 << 4) /* prohibited register access interrupt bit */
 #define CEU_CEIER_CPEIE (1 << 0) /* one-frame capture end interrupt */
+#define CEU_CEIER_VBP   (1 << 20) /* vbp error */
 #define CEU_CAPCR_CTNCP (1 << 16) /* continuous capture mode (if set) */
+#define CEU_CEIER_MASK (CEU_CEIER_CPEIE | CEU_CEIER_VBP)
 
 
-static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
+static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
 {
 	struct soc_camera_device *icd = pcdev->icd;
 	dma_addr_t phys_addr_top, phys_addr_bottom;
+	u32 status;
+	int ret = 0;
 
 	/* The hardware is _very_ picky about this sequence. Especially
 	 * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge
 	 * several not-so-well documented interrupt sources in CETCR.
 	 */
-	ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~CEU_CEIER_CPEIE);
-	ceu_write(pcdev, CETCR, ~ceu_read(pcdev, CETCR) & CEU_CETCR_MAGIC);
-	ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | CEU_CEIER_CPEIE);
+	ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~CEU_CEIER_MASK);
+	status = ceu_read(pcdev, CETCR);
+	ceu_write(pcdev, CETCR, ~status & CEU_CETCR_MAGIC);
+	ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | CEU_CEIER_MASK);
 	ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~CEU_CAPCR_CTNCP);
 	ceu_write(pcdev, CETCR, CEU_CETCR_MAGIC ^ CEU_CETCR_IGRW);
 
+	/* VBP error */
+	if (status & CEU_CEIER_VBP) {
+		/* soft reset */
+		ceu_write(pcdev, CAPSR, 1 << 16);
+		while ((1 << 16) & ceu_read(pcdev, CAPSR))
+			cpu_relax();
+		while (ceu_read(pcdev, CSTSR) & 1)
+			cpu_relax();
+		ret = -1;
+	}
+
 	if (!pcdev->active)
-		return;
+		return ret;
 
 	phys_addr_top = videobuf_to_dma_contig(pcdev->active);
 	ceu_write(pcdev, CDAYR, phys_addr_top);
@@ -225,6 +241,8 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
 
 	pcdev->active->state = VIDEOBUF_ACTIVE;
 	ceu_write(pcdev, CAPSR, 0x1); /* start capture */
+
+	return ret;
 }
 
 static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq,
@@ -335,9 +353,8 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data)
 	else
 		pcdev->active = NULL;
 
-	sh_mobile_ceu_capture(pcdev);
-
-	vb->state = VIDEOBUF_DONE;
+	vb->state = sh_mobile_ceu_capture(pcdev) == 0 ?
+		VIDEOBUF_DONE : VIDEOBUF_ERROR;
 	do_gettimeofday(&vb->ts);
 	vb->field_count++;
 	wake_up(&vb->done);
-- 
1.6.0.4

--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@xxxxxxxxxx?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list