Skip to content

Commit

Permalink
S5PC11X : FIMC apply v4l2 standard for asynchronous dequeue/queue
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
pawitp authored and nushor committed Jan 1, 2012
1 parent 8bdee33 commit 8096332
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 36 deletions.
3 changes: 0 additions & 3 deletions drivers/media/video/samsung/fimc/fimc.h
Expand Up @@ -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
Expand Down
77 changes: 44 additions & 33 deletions drivers/media/video/samsung/fimc/fimc_capture.c
Expand Up @@ -406,27 +406,42 @@ 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;
}

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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -826,23 +839,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));

/*
Expand Down Expand Up @@ -939,7 +949,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;
}
Expand Down Expand Up @@ -1517,7 +1527,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);
Expand Down Expand Up @@ -1701,16 +1711,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;
}
Expand Down Expand Up @@ -1742,7 +1755,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
Expand All @@ -1753,16 +1766,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);

Expand Down

0 comments on commit 8096332

Please sign in to comment.