diff options
| -rw-r--r-- | isp/omap3isp-priv.h | 4 | ||||
| -rw-r--r-- | isp/omap3isp.c | 164 | 
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); | 
