diff options
Diffstat (limited to 'drivers/media/video/samsung/fimc/fimc_capture.c')
-rw-r--r-- | drivers/media/video/samsung/fimc/fimc_capture.c | 154 |
1 files changed, 102 insertions, 52 deletions
diff --git a/drivers/media/video/samsung/fimc/fimc_capture.c b/drivers/media/video/samsung/fimc/fimc_capture.c index 2367bf6..09a9b22 100644 --- a/drivers/media/video/samsung/fimc/fimc_capture.c +++ b/drivers/media/video/samsung/fimc/fimc_capture.c @@ -40,6 +40,9 @@ #define fimc_dbg fimc_err #endif +static int vtmode = 0; +static int device_id = 0; + static const struct v4l2_fmtdesc capture_fmts[] = { { .index = 0, @@ -257,20 +260,34 @@ static int fimc_camera_start(struct fimc_control *ctrl) struct v4l2_frmsizeenum cam_frmsize; struct v4l2_control cam_ctrl; int ret; - ret = subdev_call(ctrl, video, enum_framesizes, &cam_frmsize); if (ret < 0) { fimc_err("%s: enum_framesizes failed\n", __func__); if (ret != -ENOIOCTLCMD) return ret; } else { - ctrl->cam->width = cam_frmsize.discrete.width; - ctrl->cam->height = cam_frmsize.discrete.height; - - ctrl->cam->window.left = 0; - ctrl->cam->window.top = 0; - ctrl->cam->window.width = ctrl->cam->width; - ctrl->cam->window.height = ctrl->cam->height; + if (vtmode == 1 && device_id != 0 && (ctrl->cap->rotate == 90 || ctrl->cap->rotate == 270)) { + ctrl->cam->window.left = 136; + ctrl->cam->window.top = 0; + ctrl->cam->window.width = 368; + ctrl->cam->window.height = 480; + ctrl->cam->width = cam_frmsize.discrete.width; + ctrl->cam->height = cam_frmsize.discrete.height; + dev_err(ctrl->dev, "vtmode = 1, rotate = %d, device = front, cam->width = %d, cam->height = %d\n", ctrl->cap->rotate, ctrl->cam->width, ctrl->cam->height); + } else if (device_id != 0 && vtmode != 1) { + ctrl->cam->window.left = 136; + ctrl->cam->window.top = 0; + ctrl->cam->window.width = 368; + ctrl->cam->window.height = 480; + ctrl->cam->width = cam_frmsize.discrete.width; + ctrl->cam->height = cam_frmsize.discrete.height; + dev_err(ctrl->dev, "%s, crop(368x480), vtmode = 0, device = front, cam->width = %d, cam->height = %d\n", __func__, ctrl->cam->width, ctrl->cam->height); + } else { + ctrl->cam->window.left = 0; + ctrl->cam->window.top = 0; + ctrl->cam->window.width = ctrl->cam->width; + ctrl->cam->window.height = ctrl->cam->height; + } } cam_ctrl.id = V4L2_CID_CAM_PREVIEW_ONOFF; @@ -389,34 +406,19 @@ static int fimc_add_outqueue(struct fimc_control *ctrl, int i) struct fimc_capinfo *cap = ctrl->cap; struct fimc_buf_set *buf; - unsigned int mask = 0x2; + if (cap->nr_bufs > FIMC_PHYBUFS) { + if (list_empty(&cap->inq)) + return -ENOENT; - /* PINGPONG_2ADDR_MODE Only */ - /* pair_buf_index stands for pair index of i. (0<->2) (1<->3) */ - - int pair_buf_index = (i^mask); - - /* FIMC have 4 h/w registers */ - if (i < 0 || i >= FIMC_PHYBUFS) { - fimc_err("%s: invalid queue index : %d\n", __func__, i); - return -ENOENT; + buf = list_first_entry(&cap->inq, struct fimc_buf_set, list); + list_del(&buf->list); + } else { + buf = &cap->bufs[i]; } - if (list_empty(&cap->inq)) - return -ENOENT; - - buf = list_first_entry(&cap->inq, struct fimc_buf_set, list); - - /* pair index buffer should be allocated first */ - cap->outq[pair_buf_index] = buf->id; - fimc_hwset_output_address(ctrl, buf, pair_buf_index); - cap->outq[i] = buf->id; fimc_hwset_output_address(ctrl, buf, i); - if (cap->nr_bufs != 1) - list_del(&buf->list); - return 0; } @@ -424,7 +426,7 @@ static int fimc_update_hwaddr(struct fimc_control *ctrl) { int i; - for (i = 0; i < FIMC_PINGPONG; i++) + for (i = 0; i < FIMC_PHYBUFS; i++) fimc_add_outqueue(ctrl, i); return 0; @@ -705,6 +707,7 @@ int fimc_enum_fmt_vid_capture(struct file *file, void *fh, return ret; } + memset(f, 0, sizeof(*f)); memcpy(f, &capture_fmts[i], sizeof(*f)); return 0; @@ -723,6 +726,7 @@ int fimc_g_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f) mutex_lock(&ctrl->v4l2_lock); + memset(&f->fmt.pix, 0, sizeof(f->fmt.pix)); memcpy(&f->fmt.pix, &ctrl->cap->fmt, sizeof(f->fmt.pix)); mutex_unlock(&ctrl->v4l2_lock); @@ -823,20 +827,23 @@ int fimc_s_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f) * released at the file close. * Anyone has better idea to do this? */ - mutex_lock(&ctrl->v4l2_lock); - - if (!ctrl->cap) { - ctrl->cap = kmalloc(sizeof(*cap), GFP_KERNEL); - if (!ctrl->cap) { - mutex_unlock(&ctrl->v4l2_lock); + if (!cap) { + cap = kzalloc(sizeof(*cap), GFP_KERNEL); + if (!cap) { fimc_err("%s: no memory for " "capture device info\n", __func__); return -ENOMEM; } + /* assign to ctrl */ + ctrl->cap = cap; + } else { + memset(cap, 0, sizeof(*cap)); } - cap = ctrl->cap; - memset(cap, 0, sizeof(*cap)); + + mutex_lock(&ctrl->v4l2_lock); + + memset(&cap->fmt, 0, sizeof(cap->fmt)); memcpy(&cap->fmt, &f->fmt.pix, sizeof(cap->fmt)); v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, 0); @@ -936,7 +943,7 @@ static void fimc_free_buffers(struct fimc_control *ctrl) return; - for (i = 0; i < cap->nr_bufs; i++) { + for (i = 0; i < FIMC_PHYBUFS; i++) { memset(&cap->bufs[i], 0, sizeof(cap->bufs[i])); cap->bufs[i].state = VIDEOBUF_NEEDS_INIT; } @@ -1214,6 +1221,11 @@ int fimc_s_ctrl_capture(void *fh, struct v4l2_control *c) ret = 0; break; + case V4L2_CID_CAMERA_VT_MODE: + vtmode = c->value; + ret = subdev_call(ctrl, core, s_ctrl, c); + break; + default: /* try on subdev */ mutex_unlock(&ctrl->v4l2_lock); @@ -1509,7 +1521,7 @@ static void fimc_reset_capture(struct fimc_control *ctrl) fimc_stop_capture(ctrl); - for (i = 0; i < FIMC_PINGPONG; i++) + for (i = 0; i < FIMC_PHYBUFS; i++) fimc_add_inqueue(ctrl, ctrl->cap->outq[i]); fimc_hwset_reset(ctrl); @@ -1525,10 +1537,14 @@ int fimc_streamon_capture(void *fh) { struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl; struct fimc_capinfo *cap = ctrl->cap; + struct v4l2_frmsizeenum cam_frmsize; int rot; int ret; fimc_dbg("%s\n", __func__); + char *ce147 = "CE147 0-003c"; + device_id = strcmp(ctrl->cam->sd->name, ce147); + fimc_dbg("%s, name(%s), device_id(%d), vtmode(%d)\n", __func__, ctrl->cam->sd->name , device_id, vtmode); if (!ctrl->cam || !ctrl->cam->sd) { fimc_err("%s: No capture device.\n", __func__); @@ -1553,6 +1569,36 @@ int fimc_streamon_capture(void *fh) if (!ctrl->cam->initialized) fimc_camera_init(ctrl); + ret = subdev_call(ctrl, video, enum_framesizes, &cam_frmsize); + if (ret < 0) { + dev_err(ctrl->dev, "%s: enum_framesizes failed\n", __func__); + if(ret != -ENOIOCTLCMD) + return ret; + } else { + if (vtmode == 1 && device_id != 0 && (cap->rotate == 90 || cap->rotate == 270)) { + ctrl->cam->window.left = 136; + ctrl->cam->window.top = 0;// + ctrl->cam->window.width = 368; + ctrl->cam->window.height = 480; + ctrl->cam->width = cam_frmsize.discrete.width; + ctrl->cam->height = cam_frmsize.discrete.height; + dev_err(ctrl->dev, "vtmode = 1, rotate = %d, device = front, cam->width = %d, cam->height = %d\n", cap->rotate, ctrl->cam->width, ctrl->cam->height); + } else if (device_id != 0 && vtmode != 1) { + ctrl->cam->window.left = 136; + ctrl->cam->window.top = 0; + ctrl->cam->window.width = 368; + ctrl->cam->window.height = 480; + ctrl->cam->width = cam_frmsize.discrete.width; + ctrl->cam->height =cam_frmsize.discrete.height; + dev_err(ctrl->dev, "%s, crop(368x480), vtmode = 0, device = front, cam->width = %d, cam->height = %d\n", __func__, ctrl->cam->width, ctrl->cam->height); + } else { + ctrl->cam->window.left = 0; + ctrl->cam->window.top = 0; + ctrl->cam->width = ctrl->cam->window.width = cam_frmsize.discrete.width; + ctrl->cam->height = ctrl->cam->window.height = cam_frmsize.discrete.height; + } + } + if (ctrl->id != 2 && ctrl->cap->fmt.colorspace != V4L2_COLORSPACE_JPEG) { ret = fimc_camera_start(ctrl); @@ -1587,6 +1633,11 @@ int fimc_streamon_capture(void *fh) fimc_hwset_output_size(ctrl, cap->fmt.width, cap->fmt.height); + if ((device_id != 0) && (vtmode != 1)) { + ctrl->cap->rotate = 90; + dev_err(ctrl->dev, "%s, rotate 90", __func__); + } + fimc_hwset_output_scan(ctrl, &cap->fmt); fimc_hwset_output_rot_flip(ctrl, cap->rotate, cap->flip); rot = fimc_mapping_rot_flip(cap->rotate, cap->flip); @@ -1654,19 +1705,16 @@ int fimc_qbuf_capture(void *fh, struct v4l2_buffer *b) { struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl; - if (!ctrl->cap || !ctrl->cap->nr_bufs) { - fimc_err("%s: Invalid capture setting.\n", __func__); - return -EINVAL; - } - if (b->memory != V4L2_MEMORY_MMAP) { fimc_err("%s: invalid memory type\n", __func__); return -EINVAL; } - mutex_lock(&ctrl->v4l2_lock); - fimc_add_inqueue(ctrl, b->index); - mutex_unlock(&ctrl->v4l2_lock); + if (ctrl->cap->nr_bufs > FIMC_PHYBUFS) { + mutex_lock(&ctrl->v4l2_lock); + fimc_add_inqueue(ctrl, b->index); + mutex_unlock(&ctrl->v4l2_lock); + } return 0; } @@ -1698,7 +1746,7 @@ int fimc_dqbuf_capture(void *fh, struct v4l2_buffer *b) } /* find out the real index */ - pp = ((fimc_hwget_frame_count(ctrl) + 2) % 4); + pp = ((fimc_hwget_frame_count(ctrl) + 2) % 4) % cap->nr_bufs; /* We have read the latest frame, hence should reset availability * flag @@ -1709,14 +1757,16 @@ int fimc_dqbuf_capture(void *fh, struct v4l2_buffer *b) if (cap->fmt.field == V4L2_FIELD_INTERLACED_TB) pp &= ~0x1; + if (cap->nr_bufs > FIMC_PHYBUFS) { b->index = cap->outq[pp]; - fimc_dbg("%s: buffer(%d) outq[%d]\n", __func__, b->index, pp); - ret = fimc_add_outqueue(ctrl, pp); if (ret) { b->index = -1; fimc_err("%s: no inqueue buffer\n", __func__); } + } else { + b->index = pp; + } mutex_unlock(&ctrl->v4l2_lock); |