summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobby Cai <R63905@freescale.com>2013-07-01 14:28:22 +0800
committerRobby Cai <R63905@freescale.com>2013-07-10 20:25:38 +0800
commitbfa270d00180f3faf8d304c104f3314743740209 (patch)
treef21355d5698a63dc442e768610aee26d00241014
parent28edbc5d3b89dda8311871c27d34358c9da036f8 (diff)
ENGR00261293-1 mx6sl: csi/v4l2: resize function not work for v4l2 capture
- the root cause is pxp input/output buffer for csi post-processing is same one, some part of content is overridded. - use S_CROP ioctl to control crop, S_FMT to control output size. Signed-off-by: Robby Cai <R63905@freescale.com> (cherry picked from commit 9f3685ea1cd4e56b5d89bfbaf48920ba862edb49)
-rw-r--r--drivers/media/video/mxc/capture/csi_v4l2_capture.c71
1 files changed, 63 insertions, 8 deletions
diff --git a/drivers/media/video/mxc/capture/csi_v4l2_capture.c b/drivers/media/video/mxc/capture/csi_v4l2_capture.c
index 4a60c65ba9ff..fe6a89c2d48a 100644
--- a/drivers/media/video/mxc/capture/csi_v4l2_capture.c
+++ b/drivers/media/video/mxc/capture/csi_v4l2_capture.c
@@ -42,10 +42,13 @@
static int video_nr = -1;
static cam_data *g_cam;
+static int req_buf_number;
static int csi_v4l2_master_attach(struct v4l2_int_device *slave);
static void csi_v4l2_master_detach(struct v4l2_int_device *slave);
static u8 camera_power(cam_data *cam, bool cameraOn);
+struct v4l2_crop crop_current;
+struct v4l2_window win_current;
/*! Information about this driver. */
static struct v4l2_int_master csi_v4l2_master = {
@@ -108,7 +111,7 @@ static int pxp_chan_init(cam_data *cam)
/*
* Function to call PxP DMA driver and send our new V4L2 buffer
- * through the PxP and PxP will process this buffer in place.
+ * through the PxP.
* Note: This is a blocking call, so upon return the PxP tx should be complete.
*/
static int pxp_process_update(cam_data *cam)
@@ -177,11 +180,30 @@ static int pxp_process_update(cam_data *cam)
proc_data->srect.width = pxp_conf->s0_param.width;
proc_data->srect.height = pxp_conf->s0_param.height;
- proc_data->drect.top = 0;
+ if (crop_current.c.top != 0)
+ proc_data->srect.top = crop_current.c.top;
+ if (crop_current.c.left != 0)
+ proc_data->srect.left = crop_current.c.left;
+ if (crop_current.c.width != 0)
+ proc_data->srect.width = crop_current.c.width;
+ if (crop_current.c.height != 0)
+ proc_data->srect.height = crop_current.c.height;
+
proc_data->drect.left = 0;
+ proc_data->drect.top = 0;
proc_data->drect.width = proc_data->srect.width;
proc_data->drect.height = proc_data->srect.height;
- proc_data->scaling = 0;
+
+
+ if (win_current.w.left != 0)
+ proc_data->drect.left = win_current.w.left;
+ if (win_current.w.top != 0)
+ proc_data->drect.top = win_current.w.top;
+ if (win_current.w.width != 0)
+ proc_data->drect.width = win_current.w.width;
+ if (win_current.w.height != 0)
+ proc_data->drect.height = win_current.w.height;
+
proc_data->hflip = 0;
proc_data->vflip = 0;
proc_data->rotate = 0;
@@ -824,6 +846,10 @@ static int csi_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f)
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
pr_debug(" type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n");
cam->win = f->fmt.win;
+ win_current = f->fmt.win;
+ size = win_current.w.width * win_current.w.height * 2;
+ if (cam->v2f.fmt.pix.sizeimage < size)
+ cam->v2f.fmt.pix.sizeimage = size;
break;
default:
retval = -EINVAL;
@@ -959,9 +985,9 @@ static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
* to RGB565; but for encoding, usually we don't use RGB format.
*/
if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
- /* PxP processes it in place */
sg_dma_address(&cam->sg[0]) = buf->m.offset;
- sg_dma_address(&cam->sg[1]) = buf->m.offset;
+ sg_dma_address(&cam->sg[1]) =
+ cam->frame[req_buf_number].paddress;
retval = pxp_process_update(cam);
if (retval) {
pr_err("Unable to submit PxP update task.\n");
@@ -970,6 +996,9 @@ static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
pxp_complete_update(cam);
}
up(&cam->busy_lock);
+ memcpy(cam->frame[buf->index].vaddress,
+ cam->frame[req_buf_number].vaddress,
+ cam->v2f.fmt.pix.sizeimage);
return retval;
}
@@ -1246,9 +1275,33 @@ static long csi_v4l_do_ioctl(struct file *file,
}
case VIDIOC_S_CROP:
- pr_debug(" case not supported\n");
+ {
+ struct v4l2_crop *crop = arg;
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ retval = -EINVAL;
+ break;
+ }
+ crop->c.width -= crop->c.width % 8;
+ crop->c.height -= crop->c.height % 8;
+
+ crop_current.c = crop->c;
+
break;
+ }
+ case VIDIOC_G_CROP:
+ {
+ struct v4l2_crop *crop = arg;
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ retval = -EINVAL;
+ break;
+ }
+ crop->c = crop_current.c;
+
+ break;
+
+ }
case VIDIOC_REQBUFS: {
struct v4l2_requestbuffers *req = arg;
pr_debug(" case VIDIOC_REQBUFS\n");
@@ -1269,7 +1322,8 @@ static long csi_v4l_do_ioctl(struct file *file,
csi_streamoff(cam);
if (req->memory & V4L2_MEMORY_MMAP) {
csi_free_frame_buf(cam);
- retval = csi_allocate_frame_buf(cam, req->count);
+ retval = csi_allocate_frame_buf(cam, req->count + 1);
+ req_buf_number = req->count;
}
break;
}
@@ -1401,7 +1455,6 @@ static long csi_v4l_do_ioctl(struct file *file,
case VIDIOC_G_OUTPUT:
case VIDIOC_S_OUTPUT:
case VIDIOC_ENUMSTD:
- case VIDIOC_G_CROP:
case VIDIOC_CROPCAP:
case VIDIOC_S_STD:
case VIDIOC_G_CTRL:
@@ -1594,6 +1647,8 @@ static int __devinit csi_v4l2_probe(struct platform_device *pdev)
err = -ENOMEM;
goto out;
}
+ memset(&crop_current, 0, sizeof(crop_current));
+ memset(&win_current, 0, sizeof(win_current));
init_camera_struct(g_cam);
platform_set_drvdata(pdev, (void *)g_cam);