diff options
author | Pawit Pornkitprasan <p.pawit@gmail.com> | 2012-01-01 20:37:07 +0700 |
---|---|---|
committer | Pawit Pornkitprasan <p.pawit@gmail.com> | 2012-01-01 20:37:07 +0700 |
commit | cbb71a509e85224731c96426e4221363f598fe86 (patch) | |
tree | 10bce83c80e7015e559e927438d1aea1b32b1485 | |
parent | e129a21c2f5519faf6d5ffe34bcfd834382ad740 (diff) | |
download | kernel_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.h | 3 | ||||
-rw-r--r-- | drivers/media/video/samsung/fimc/fimc_capture.c | 77 |
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); |