Linux Media Controller development
 help / color / mirror / Atom feed
* [PATCH] Add interlace support to sh_mobile_ceu_camera.c
@ 2008-12-11  0:02 Kuninori Morimoto
  2008-12-12  7:17 ` morimoto.kuninori
  2010-07-12  7:08 ` Guennadi Liakhovetski
  0 siblings, 2 replies; 13+ messages in thread
From: Kuninori Morimoto @ 2008-12-11  0:02 UTC (permalink / raw)
  To: Guennadi Liakhovetski; +Cc: V4L-Linux


Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com>
---
This patch needs Magnus's "nv1x/nvx1 support for the sh_mobile_ceu driver" patch

 drivers/media/video/sh_mobile_ceu_camera.c |   47 ++++++++++++++++++++++------
 1 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 5701363..13addd8 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -97,6 +97,7 @@ struct sh_mobile_ceu_dev {
 	spinlock_t lock;
 	struct list_head capture;
 	struct videobuf_buffer *active;
+	int is_interlace;
 
 	struct sh_mobile_ceu_info *pdata;
 
@@ -161,7 +162,7 @@ static void free_buffer(struct videobuf_queue *vq,
 static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
 {
 	struct soc_camera_device *icd = pcdev->icd;
-	unsigned long phys_addr;
+	unsigned long phys_addr_t, phys_addr_b = 0;
 
 	ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~1);
 	ceu_write(pcdev, CETCR, ~ceu_read(pcdev, CETCR) & 0x0317f313);
@@ -174,16 +175,25 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
 	if (!pcdev->active)
 		return;
 
-	phys_addr = videobuf_to_dma_contig(pcdev->active);
-	ceu_write(pcdev, CDAYR, phys_addr);
+	phys_addr_t = videobuf_to_dma_contig(pcdev->active);
+	ceu_write(pcdev, CDAYR, phys_addr_t);
+	if (pcdev->is_interlace) {
+		phys_addr_b = phys_addr_t + icd->width;
+		ceu_write(pcdev, CDBYR, phys_addr_b);
+	}
+
 
 	switch (icd->current_fmt->fourcc) {
 	case V4L2_PIX_FMT_NV12:
 	case V4L2_PIX_FMT_NV21:
 	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_NV61:
-		phys_addr += (icd->width * icd->height);
-		ceu_write(pcdev, CDACR, phys_addr);
+		phys_addr_t += (icd->width * icd->height);
+		ceu_write(pcdev, CDACR, phys_addr_t);
+		if (pcdev->is_interlace) {
+			phys_addr_b += (icd->width * icd->height);
+			ceu_write(pcdev, CDBCR, phys_addr_b);
+		}
 	}
 
 	pcdev->active->state = VIDEOBUF_ACTIVE;
@@ -379,7 +389,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
-	int ret, buswidth, width, cfszr_width, cdwdr_width;
+	int ret, buswidth, width, height, cfszr_width, cdwdr_width;
 	unsigned long camera_flags, common_flags, value;
 	int yuv_mode, yuv_lineskip;
 
@@ -446,7 +456,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
 	ceu_write(pcdev, CAMCR, value);
 
 	ceu_write(pcdev, CAPCR, 0x00300000);
-	ceu_write(pcdev, CAIFR, 0);
+	ceu_write(pcdev, CAIFR, (pcdev->is_interlace) ? 0x101 : 0);
 
 	mdelay(1);
 
@@ -461,10 +471,16 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
 		cdwdr_width = (buswidth == 16) ? width * 2 : width;
 	}
 
+	height = icd->height;
+	if (pcdev->is_interlace) {
+		height      /= 2;
+		cdwdr_width *= 2;
+	}
+
 	ceu_write(pcdev, CAMOR, 0);
-	ceu_write(pcdev, CAPWR, (icd->height << 16) | width);
+	ceu_write(pcdev, CAPWR, (height << 16) | width);
 	ceu_write(pcdev, CFLCR, 0); /* no scaling */
-	ceu_write(pcdev, CFSZR, (icd->height << 16) | cfszr_width);
+	ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width);
 	ceu_write(pcdev, CLFCR, 0); /* no lowpass filter */
 
 	/* A few words about byte order (observed in Big Endian mode)
@@ -613,8 +629,10 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
 				 struct v4l2_format *f)
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct sh_mobile_ceu_dev *pcdev = ici->priv;
 	const struct soc_camera_format_xlate *xlate;
 	__u32 pixfmt = f->fmt.pix.pixelformat;
+	int ret;
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
 	if (!xlate) {
@@ -640,8 +658,16 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 
 	/* limit to sensor capabilities */
-	return icd->ops->try_fmt(icd, f);
+	ret = icd->ops->try_fmt(icd, f);
+
+	pcdev->is_interlace = 0;
+	if (V4L2_FIELD_INTERLACED == f->fmt.pix.field) {
+		pcdev->is_interlace = 1;
+		f->fmt.pix.field = V4L2_FIELD_NONE;
+	}
+
+	return ret;
+
 }
 
 static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf,
-- 
1.5.6.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread
* [PATCH] Add interlace support to sh_mobile_ceu_camera.c
@ 2008-12-16  1:41 Kuninori Morimoto
  2008-12-16  2:04 ` morimoto.kuninori
  0 siblings, 1 reply; 13+ messages in thread
From: Kuninori Morimoto @ 2008-12-16  1:41 UTC (permalink / raw)
  To: Guennadi Liakhovetski; +Cc: V4L-Linux


Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com>
---
 drivers/media/video/sh_mobile_ceu_camera.c |   56 +++++++++++++++++++++++-----
 1 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 4dea1ff..ec44df3 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -97,6 +97,7 @@ struct sh_mobile_ceu_dev {
 	spinlock_t lock;
 	struct list_head capture;
 	struct videobuf_buffer *active;
+	int is_interlace;
 
 	struct sh_mobile_ceu_info *pdata;
 
@@ -165,7 +166,8 @@ static void free_buffer(struct videobuf_queue *vq,
 static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
 {
 	struct soc_camera_device *icd = pcdev->icd;
-	dma_addr_t phys_addr;
+	dma_addr_t phys_addr_top;
+	dma_addr_t phys_addr_bottom = icd->width;
 
 	/* The hardware is _very_ picky about this sequence. Especially
 	 * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge
@@ -180,16 +182,24 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
 	if (!pcdev->active)
 		return;
 
-	phys_addr = videobuf_to_dma_contig(pcdev->active);
-	ceu_write(pcdev, CDAYR, phys_addr);
+	phys_addr_top = videobuf_to_dma_contig(pcdev->active);
+	ceu_write(pcdev, CDAYR, phys_addr_top);
+	if (pcdev->is_interlace) {
+		phys_addr_bottom += phys_addr_top;
+		ceu_write(pcdev, CDBYR, phys_addr_bottom);
+	}
 
 	switch (icd->current_fmt->fourcc) {
 	case V4L2_PIX_FMT_NV12:
 	case V4L2_PIX_FMT_NV21:
 	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_NV61:
-		phys_addr += icd->width * icd->height;
-		ceu_write(pcdev, CDACR, phys_addr);
+		phys_addr_top += icd->width * icd->height;
+		ceu_write(pcdev, CDACR, phys_addr_top);
+		if (pcdev->is_interlace) {
+			phys_addr_bottom += icd->width * icd->height;
+			ceu_write(pcdev, CDBCR, phys_addr_bottom);
+		}
 	}
 
 	pcdev->active->state = VIDEOBUF_ACTIVE;
@@ -385,7 +395,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
-	int ret, buswidth, width, cfszr_width, cdwdr_width;
+	int ret, buswidth, width, height, cfszr_width, cdwdr_width;
 	unsigned long camera_flags, common_flags, value;
 	int yuv_mode, yuv_lineskip;
 
@@ -452,7 +462,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
 	ceu_write(pcdev, CAMCR, value);
 
 	ceu_write(pcdev, CAPCR, 0x00300000);
-	ceu_write(pcdev, CAIFR, 0);
+	ceu_write(pcdev, CAIFR, (pcdev->is_interlace) ? 0x101 : 0);
 
 	mdelay(1);
 
@@ -467,10 +477,16 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
 		cdwdr_width = buswidth == 16 ? width * 2 : width;
 	}
 
+	height = icd->height;
+	if (pcdev->is_interlace) {
+		height      /= 2;
+		cdwdr_width *= 2;
+	}
+
 	ceu_write(pcdev, CAMOR, 0);
-	ceu_write(pcdev, CAPWR, (icd->height << 16) | width);
+	ceu_write(pcdev, CAPWR, (height << 16) | width);
 	ceu_write(pcdev, CFLCR, 0); /* no scaling */
-	ceu_write(pcdev, CFSZR, (icd->height << 16) | cfszr_width);
+	ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width);
 	ceu_write(pcdev, CLFCR, 0); /* no lowpass filter */
 
 	/* A few words about byte order (observed in Big Endian mode)
@@ -619,8 +635,10 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
 				 struct v4l2_format *f)
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct sh_mobile_ceu_dev *pcdev = ici->priv;
 	const struct soc_camera_format_xlate *xlate;
 	__u32 pixfmt = f->fmt.pix.pixelformat;
+	int ret;
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
 	if (!xlate) {
@@ -646,7 +664,25 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 
 	/* limit to sensor capabilities */
-	return icd->ops->try_fmt(icd, f);
+	ret = icd->ops->try_fmt(icd, f);
+	if (ret < 0)
+		return ret;
+
+	switch (f->fmt.pix.field) {
+	case V4L2_FIELD_INTERLACED:
+		pcdev->is_interlace = 1;
+		break;
+	case V4L2_FIELD_ANY:
+		f->fmt.pix.field = V4L2_FIELD_NONE;
+	case V4L2_FIELD_NONE:
+		pcdev->is_interlace = 0;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
 }
 
 static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf,
-- 
1.5.6.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2010-07-16  3:35 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-11  0:02 [PATCH] Add interlace support to sh_mobile_ceu_camera.c Kuninori Morimoto
2008-12-12  7:17 ` morimoto.kuninori
2010-07-12  7:08 ` Guennadi Liakhovetski
2010-07-13  1:16   ` Kuninori Morimoto
2010-07-13 14:35     ` Guennadi Liakhovetski
2010-07-14  0:12       ` Kuninori Morimoto
2010-07-14  2:35         ` hermann pitton
2010-07-14  5:18           ` Kuninori Morimoto
2010-07-15  2:48             ` hermann pitton
2010-07-15  5:37               ` Kuninori Morimoto
2010-07-16  3:25                 ` hermann pitton
  -- strict thread matches above, loose matches on Subject: below --
2008-12-16  1:41 Kuninori Morimoto
2008-12-16  2:04 ` morimoto.kuninori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox