summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-07-28 15:09:11 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-09-04 15:39:31 +0200
commitea5563000447f0cef5688a35feb0071ec5d1ea58 (patch)
tree641ed980478dc395199722aca41c5e7884037334
parentc2cef3c8853213e50809189a245af3d859cacb19 (diff)
omap3isp: Implement pools buffer allocation and streaming events
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--isp/omap3isp-priv.h4
-rw-r--r--isp/omap3isp.c164
2 files changed, 168 insertions, 0 deletions
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
@@ -120,6 +120,169 @@ static const char *entity_name(struct omap3_isp_entity *entity)
}
/* -----------------------------------------------------------------------------
+ * 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);