aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawit Pornkitprasan <p.pawit@gmail.com>2012-01-01 20:37:07 +0700
committerPawit Pornkitprasan <p.pawit@gmail.com>2012-01-01 20:37:07 +0700
commitcbb71a509e85224731c96426e4221363f598fe86 (patch)
tree10bce83c80e7015e559e927438d1aea1b32b1485
parente129a21c2f5519faf6d5ffe34bcfd834382ad740 (diff)
downloadkernel_samsung_aries-cbb71a509e85224731c96426e4221363f598fe86.zip
kernel_samsung_aries-cbb71a509e85224731c96426e4221363f598fe86.tar.gz
kernel_samsung_aries-cbb71a509e85224731c96426e4221363f598fe86.tar.bz2
S5PC11X : FIMC apply v4l2 standard for asynchronous dequeue/queue
To make framedrop in camera HAL layer, FIMC should support v4l2 standard Signed-off-by: Song Youngmok <ym.song@samsung.com> (Re-added for video recording fix)
-rw-r--r--drivers/media/video/samsung/fimc/fimc.h3
-rw-r--r--drivers/media/video/samsung/fimc/fimc_capture.c77
2 files changed, 44 insertions, 36 deletions
diff --git a/drivers/media/video/samsung/fimc/fimc.h b/drivers/media/video/samsung/fimc/fimc.h
index b3df54d..7ad4495 100644
--- a/drivers/media/video/samsung/fimc/fimc.h
+++ b/drivers/media/video/samsung/fimc/fimc.h
@@ -65,10 +65,7 @@
#define FIMC_SCLK 1
#define FIMC_OVLY_MODE FIMC_OVLY_DMA_AUTO
-#define PINGPONG_2ADDR_MODE
-#if defined(PINGPONG_2ADDR_MODE)
#define FIMC_PINGPONG 2
-#endif
/*
* ENUMERATIONS
diff --git a/drivers/media/video/samsung/fimc/fimc_capture.c b/drivers/media/video/samsung/fimc/fimc_capture.c
index 09a9b22..570ed70 100644
--- a/drivers/media/video/samsung/fimc/fimc_capture.c
+++ b/drivers/media/video/samsung/fimc/fimc_capture.c
@@ -406,19 +406,34 @@ static int fimc_add_outqueue(struct fimc_control *ctrl, int i)
struct fimc_capinfo *cap = ctrl->cap;
struct fimc_buf_set *buf;
- if (cap->nr_bufs > FIMC_PHYBUFS) {
- if (list_empty(&cap->inq))
- return -ENOENT;
+ unsigned int mask = 0x2;
- buf = list_first_entry(&cap->inq, struct fimc_buf_set, list);
- list_del(&buf->list);
- } else {
- buf = &cap->bufs[i];
+ /* 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;
}
+ 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;
}
@@ -426,7 +441,7 @@ static int fimc_update_hwaddr(struct fimc_control *ctrl)
{
int i;
- for (i = 0; i < FIMC_PHYBUFS; i++)
+ for (i = 0; i < FIMC_PINGPONG; i++)
fimc_add_outqueue(ctrl, i);
return 0;
@@ -707,7 +722,6 @@ 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;
@@ -726,7 +740,6 @@ 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);
@@ -827,23 +840,20 @@ 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?
*/
- if (!cap) {
- cap = kzalloc(sizeof(*cap), GFP_KERNEL);
- if (!cap) {
+ mutex_lock(&ctrl->v4l2_lock);
+
+ if (!ctrl->cap) {
+ ctrl->cap = kmalloc(sizeof(*cap), GFP_KERNEL);
+ if (!ctrl->cap) {
+ mutex_unlock(&ctrl->v4l2_lock);
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));
}
-
- mutex_lock(&ctrl->v4l2_lock);
-
- memset(&cap->fmt, 0, sizeof(cap->fmt));
+ cap = ctrl->cap;
+ memset(cap, 0, sizeof(*cap));
memcpy(&cap->fmt, &f->fmt.pix, sizeof(cap->fmt));
v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, 0);
@@ -943,7 +953,7 @@ static void fimc_free_buffers(struct fimc_control *ctrl)
return;
- for (i = 0; i < FIMC_PHYBUFS; i++) {
+ for (i = 0; i < cap->nr_bufs; i++) {
memset(&cap->bufs[i], 0, sizeof(cap->bufs[i]));
cap->bufs[i].state = VIDEOBUF_NEEDS_INIT;
}
@@ -1521,7 +1531,7 @@ static void fimc_reset_capture(struct fimc_control *ctrl)
fimc_stop_capture(ctrl);
- for (i = 0; i < FIMC_PHYBUFS; i++)
+ for (i = 0; i < FIMC_PINGPONG; i++)
fimc_add_inqueue(ctrl, ctrl->cap->outq[i]);
fimc_hwset_reset(ctrl);
@@ -1705,16 +1715,19 @@ 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;
}
- if (ctrl->cap->nr_bufs > FIMC_PHYBUFS) {
- mutex_lock(&ctrl->v4l2_lock);
- fimc_add_inqueue(ctrl, b->index);
- mutex_unlock(&ctrl->v4l2_lock);
- }
+ mutex_lock(&ctrl->v4l2_lock);
+ fimc_add_inqueue(ctrl, b->index);
+ mutex_unlock(&ctrl->v4l2_lock);
return 0;
}
@@ -1746,7 +1759,7 @@ int fimc_dqbuf_capture(void *fh, struct v4l2_buffer *b)
}
/* find out the real index */
- pp = ((fimc_hwget_frame_count(ctrl) + 2) % 4) % cap->nr_bufs;
+ pp = ((fimc_hwget_frame_count(ctrl) + 2) % 4);
/* We have read the latest frame, hence should reset availability
* flag
@@ -1757,16 +1770,14 @@ 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);