summaryrefslogtreecommitdiff
path: root/isp/omap3isp.c
diff options
context:
space:
mode:
Diffstat (limited to 'isp/omap3isp.c')
-rw-r--r--isp/omap3isp.c164
1 files changed, 164 insertions, 0 deletions
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);