From ea5563000447f0cef5688a35feb0071ec5d1ea58 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Jul 2011 15:09:11 +0200 Subject: omap3isp: Implement pools buffer allocation and streaming events Signed-off-by: Laurent Pinchart --- isp/omap3isp-priv.h | 4 ++ isp/omap3isp.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) diff --git a/isp/omap3isp-priv.h b/isp/omap3isp-priv.h index e9dae0c..4e3d8cf 100644 --- a/isp/omap3isp-priv.h +++ b/isp/omap3isp-priv.h @@ -28,6 +28,8 @@ #include "omap3isp.h" #include "tools.h" +struct omap3_isp_device; + /* * struct omap3_isp_pad - OMAP3 entity pad * @link: Link connected to the pad @@ -88,6 +90,7 @@ struct omap3_isp_video { * struct omap3_isp_pool - OMAP3 buffers pool * @entity: OMAP3 entity * @list: Pools list + * @isp: OMAP3 ISP device * @input: Capture video device * @output: Output video device * @pool: Buffers pool @@ -95,6 +98,7 @@ struct omap3_isp_video { struct omap3_isp_pool { struct omap3_isp_entity entity; struct list_entry list; + struct omap3_isp_device *isp; struct omap3_isp_video *input; struct omap3_isp_video *output; struct v4l2_buffers_pool *pool; diff --git a/isp/omap3isp.c b/isp/omap3isp.c index 5a11135..d6dc926 100644 --- a/isp/omap3isp.c +++ b/isp/omap3isp.c @@ -119,6 +119,169 @@ static const char *entity_name(struct omap3_isp_entity *entity) return entity->entity->info.name; } +/* ----------------------------------------------------------------------------- + * Pools + */ + +static void omap3_isp_pool_event_input(void *priv); +static void omap3_isp_pool_event_output(void *priv); + +static void omap3_isp_pool_event(struct omap3_isp_pool *pool, + struct omap3_isp_video *from, + struct omap3_isp_video *to, + bool input) +{ + struct omap3_isp_device *isp = pool->isp; + struct v4l2_video_buffer buffer; + int ret; + + /* Dequeue the buffer */ + ret = v4l2_dequeue_buffer(from->video, &buffer); + if (ret < 0) { + printf("error: pool: unable to dequeue buffer: %s (%d)\n", + strerror(-ret), ret); + return; + } + + from->dequeued |= 1 << buffer.index; + from->queued--; + + if (from->queued == 0) + isp->ops->unwatch_fd(from->video->fd); + + /* Queue it on the other side */ + to->dequeued &= ~(1 << buffer.index); + + if (to->queued == 0) { + if (input) + isp->ops->watch_fd(to->video->fd, OMAP3_ISP_EVENT_WRITE, + omap3_isp_pool_event_output, pool); + else + isp->ops->watch_fd(to->video->fd, OMAP3_ISP_EVENT_READ, + omap3_isp_pool_event_input, pool); + } + + to->queued++; + ret = v4l2_queue_buffer(to->video, &buffer); + if (ret < 0) + printf("error: pool: unable to requeue buffer: %s (%d)\n", + strerror(-ret), ret); +} + +static void omap3_isp_pool_event_input(void *priv) +{ + struct omap3_isp_pool *pool = priv; + + omap3_isp_pool_event(pool, pool->input, pool->output, true); +} + +static void omap3_isp_pool_event_output(void *priv) +{ + struct omap3_isp_pool *pool = priv; + + omap3_isp_pool_event(pool, pool->output, pool->input, false); +} + +static int omap3_isp_pool_start(struct omap3_isp_pool *pool) +{ + struct v4l2_video_buffer buffer; + unsigned int i; + int ret; + + /* Queue all buffers for video capture. */ + for (i = 0; i < pool->pool->nbufs; ++i) { + if (pool->input->dequeued & (1 << i)) + continue; + + buffer.index = i; + + ret = v4l2_queue_buffer(pool->input->video, &buffer); + if (ret < 0) { + printf("error: pool: unable to queue buffer %u (%d)\n", + i, ret); + return ret; + } + + pool->input->queued++; + } + + /* Watch the pool input file descriptor. */ + pool->isp->ops->watch_fd(pool->input->video->fd, OMAP3_ISP_EVENT_READ, + omap3_isp_pool_event_input, pool); + + ret = v4l2_stream_on(pool->input->video); + if (ret < 0) { + printf("error: pool: streamon failed on input (%d)\n", ret); + return ret; + } + + ret = v4l2_stream_on(pool->output->video); + if (ret < 0) { + printf("error: pool: streamon failed on output (%d)\n", ret); + return ret; + } + + pool->input->running = true; + pool->output->running = true; + + return 0; +} + +static void omap3_isp_pool_stop(struct omap3_isp_pool *pool) +{ + int ret; + + pool->isp->ops->unwatch_fd(pool->input->video->fd); + pool->isp->ops->unwatch_fd(pool->output->video->fd); + + ret = v4l2_stream_off(pool->input->video); + if (ret < 0) + printf("error: pool: streamoff failed for input (%d)\n", ret); + + ret = v4l2_stream_off(pool->output->video); + if (ret < 0) + printf("error: pool: streamoff failed for output (%d)\n", ret); + + pool->input->queued = 0; + pool->input->running = false; + pool->output->queued = 0; + pool->output->running = false; +} + +static int omap3_isp_pool_alloc_buffers(struct omap3_isp_pool *pool) +{ + int ret; + + ret = v4l2_alloc_buffers(pool->output->video, pool->pool, + V4L2_MEMORY_MMAP); + if (ret < 0) { + printf("error: pool: unable to allocate output buffers.\n"); + return ret; + } + + ret = v4l2_alloc_buffers(pool->input->video, pool->pool, + V4L2_MEMORY_USERPTR); + if (ret < 0) { + printf("error: pool: unable to allocate input buffers.\n"); + return ret; + } + + return 0; +} + +static void omap3_isp_pool_free_buffers(struct omap3_isp_pool *pool) +{ + int ret; + + ret = v4l2_free_buffers(pool->input->video); + if (ret < 0) + printf("error: pool: unable to free input buffers.\n"); + + ret = v4l2_free_buffers(pool->output->video); + if (ret < 0) + printf("error: pool: unable to free output buffers.\n"); +} + /* ----------------------------------------------------------------------------- * Pipeline management */ @@ -182,6 +345,7 @@ omap3_isp_pipeline_create_pool(struct omap3_isp_device *isp __attribute__((__unu return NULL; memset(pool, 0, sizeof *pool); + pool->isp = isp; pool->entity.type = OMAP3_ISP_ENTITY_POOL; pool->pool = v4l2_buffers_pool_new(nbufs); -- cgit v1.2.3