aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/samsung/fimc/fimc_capture.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/samsung/fimc/fimc_capture.c')
-rw-r--r--drivers/media/video/samsung/fimc/fimc_capture.c154
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);