diff options
Diffstat (limited to 'isp')
| -rw-r--r-- | isp/omap3isp-priv.h | 21 | ||||
| -rw-r--r-- | isp/omap3isp.c | 207 | 
2 files changed, 182 insertions, 46 deletions
| diff --git a/isp/omap3isp-priv.h b/isp/omap3isp-priv.h index b4d2114..9706ba8 100644 --- a/isp/omap3isp-priv.h +++ b/isp/omap3isp-priv.h @@ -40,6 +40,7 @@ struct omap3_isp_pad {  enum omap3_isp_entity_type {  	OMAP3_ISP_ENTITY_ENTITY, +	OMAP3_ISP_ENTITY_POOL,  	OMAP3_ISP_ENTITY_VIDEO,  }; @@ -82,14 +83,34 @@ struct omap3_isp_video {  #define to_omap3_isp_video(e)	container_of(e, struct omap3_isp_video, entity)  /* + * struct omap3_isp_pool - OMAP3 buffers pool + * @entity: OMAP3 entity + * @list: Pools list + * @input: Capture video device + * @output: Output video device + * @pool: Buffers pool + */ +struct omap3_isp_pool { +	struct omap3_isp_entity entity; +	struct list_entry list; +	struct omap3_isp_video *input; +	struct omap3_isp_video *output; +	struct v4l2_buffers_pool *pool; +}; + +#define to_omap3_isp_pool(e)	container_of(e, struct omap3_isp_pool, entity) + +/*   * struct omap3_isp_pipeline - OMAP3 pipeline   * @entitites: Entities in the pipeline   * @scaler: Whether scaling should be performed on the ISP or the sensor + * @pools: Pools in the pipeline   * @output: Video device at the output of the pipeline   */  struct omap3_isp_pipeline {  	struct list_entry entities;  	enum omap3_isp_scaler scaler; +	struct list_entry pools;  	struct omap3_isp_video *output;  }; diff --git a/isp/omap3isp.c b/isp/omap3isp.c index be5ea3d..eb90dcd 100644 --- a/isp/omap3isp.c +++ b/isp/omap3isp.c @@ -88,6 +88,17 @@ static __u32 mbus_to_pix(enum v4l2_mbus_pixelcode code)  	}  } +static const char *entity_name(struct omap3_isp_entity *entity) +{ +	if (entity == NULL) +		return "NULL"; + +	if (entity->type == OMAP3_ISP_ENTITY_POOL) +		return "POOL"; + +	return entity->entity->info.name; +} +  /* -----------------------------------------------------------------------------   * Pipeline management   */ @@ -95,6 +106,7 @@ static __u32 mbus_to_pix(enum v4l2_mbus_pixelcode code)  static void omap3_isp_pipeline_init(struct omap3_isp_pipeline *pipe)  {  	list_init(&pipe->entities); +	list_init(&pipe->pools);  }  static void omap3_isp_pipeline_destroy(struct omap3_isp_pipeline *pipe) @@ -102,10 +114,18 @@ static void omap3_isp_pipeline_destroy(struct omap3_isp_pipeline *pipe)  	struct omap3_isp_entity *entity;  	struct omap3_isp_entity *next;  	struct omap3_isp_video *video; +	struct omap3_isp_pool *pool;  	list_for_each_entry_safe(entity, next, &pipe->entities, list) {  		list_remove(&entity->list);  		switch (entity->type) { +		case OMAP3_ISP_ENTITY_POOL: +			pool = to_omap3_isp_pool(entity); +			v4l2_buffers_pool_delete(pool->pool); +			list_remove(&pool->list); +			free(pool); +			break; +  		case OMAP3_ISP_ENTITY_VIDEO:  			video = to_omap3_isp_video(entity);  			v4l2_close(video->video); @@ -119,14 +139,135 @@ static void omap3_isp_pipeline_destroy(struct omap3_isp_pipeline *pipe)  	}  } +static struct omap3_isp_pool * +omap3_isp_pipeline_create_pool(struct omap3_isp_device *isp __attribute__((__unused__)), +			       const char *name) +{ +	struct omap3_isp_pool *pool; +	unsigned int nbufs; +	char *endp; + +	name += 5; +	if (*name != '\0') { +		if (*name != ':') +			return NULL; + +		nbufs = strtoul(name + 1, &endp, 10); +		if (*endp != '\0') +			return NULL; +	} + +	pool = malloc(sizeof *pool); +	if (pool == NULL) +		return NULL; + +	memset(pool, 0, sizeof *pool); +	pool->entity.type = OMAP3_ISP_ENTITY_POOL; + +	pool->pool = v4l2_buffers_pool_new(nbufs); +	if (pool->pool == NULL) { +		free(pool); +		return NULL; +	} + +	return pool; +} + +static struct omap3_isp_entity * +omap3_isp_pipeline_create_entity(struct omap3_isp_device *isp, +				 const char *name) +{ +	struct omap3_isp_entity *entity; +	struct omap3_isp_video *video; +	struct media_entity *ment; + +	ment = media_get_entity_by_name(isp->mdev, name); +	if (ment == NULL) +		return NULL; + +	if (media_entity_type(ment) == MEDIA_ENT_T_DEVNODE) { +		video = malloc(sizeof *video); +		if (video == NULL) +			return NULL; + +		memset(video, 0, sizeof *video); + +		video->video = v4l2_open(ment->devname); +		if (video->video == NULL) { +			printf("error: unable to open video device %s\n", +				ment->devname); +			return NULL; +		} + +		entity = &video->entity; +		entity->type = OMAP3_ISP_ENTITY_VIDEO; +	} else { +		entity = malloc(sizeof *entity); +		if (entity == NULL) +			return NULL; + +		memset(entity, 0, sizeof *entity); +		entity->type = OMAP3_ISP_ENTITY_ENTITY; +	} + +	entity->entity = ment; +	return entity; +} + +static int omap3_isp_pipeline_validate_link(struct omap3_isp_entity *source, +					    struct omap3_isp_entity *sink) +{ +	struct omap3_isp_video *video; +	struct omap3_isp_pool *pool; +	unsigned int i; + +	if (source == NULL) +		return 0; + +	if (source->type != OMAP3_ISP_ENTITY_POOL && +	    sink->type != OMAP3_ISP_ENTITY_POOL) { +		/* Make sure there's a link between the source and sink +		 * entities. +		 */ +		for (i = 0; i < source->entity->num_links; ++i) { +			if (source->entity->links[i].sink->entity == sink->entity) +				break; +		} + +		if (i == source->entity->num_links) +			return -EPIPE; + +		/* Store link information in source and sink */ +		source->source.link = &source->entity->links[i]; +		sink->sink.link = &source->entity->links[i]; +		return 0; +	} + +	if (source->type == OMAP3_ISP_ENTITY_VIDEO && +	    sink->type == OMAP3_ISP_ENTITY_POOL) { +		pool = to_omap3_isp_pool(sink); +		video = to_omap3_isp_video(source); +		pool->input = video; +		return 0; +	} + +	if (source->type == OMAP3_ISP_ENTITY_POOL && +	    sink->type == OMAP3_ISP_ENTITY_VIDEO) { +		pool = to_omap3_isp_pool(source); +		video = to_omap3_isp_video(sink); +		pool->output = video; +		return 0; +	} + +	return -EPIPE; +} +  static int omap3_isp_pipeline_build(struct omap3_isp_device *isp,  				    struct omap3_isp_pipeline *pipe, ...)  {  	struct omap3_isp_entity *source = NULL;  	struct omap3_isp_entity *sink; -	struct omap3_isp_video *video; -	struct media_entity *entity; -	unsigned int i; +	struct omap3_isp_pool *pool;  	va_list ap;  	char *name;  	int ret; @@ -135,67 +276,41 @@ static int omap3_isp_pipeline_build(struct omap3_isp_device *isp,  	while ((name = va_arg(ap, char *)) != NULL) { -		entity = media_get_entity_by_name(isp->mdev, name); -		if (entity == NULL) { -			ret = -ENOENT; -			goto done; -		} +		if (strncmp(name, ":POOL", 5) == 0) { +			/* The previous entity must be a device node. */ +			if (source == NULL || media_entity_type(source->entity) +			    != MEDIA_ENT_T_DEVNODE) +				return -EPIPE; -		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE) { -			video = malloc(sizeof *video); -			if (video == NULL) { +			pool = omap3_isp_pipeline_create_pool(isp, name); +			if (pool == NULL) {  				ret = -ENOMEM;  				goto done;  			} -			memset(video, 0, sizeof *video); - -			video->video = v4l2_open(entity->devname); -			if (video->video == NULL) { -				printf("error: unable to open video device %s\n", -					entity->devname); -				ret = -ENXIO; -				goto done; -			} - -			sink = &video->entity; +			list_append(&pool->list, &pipe->pools); +			sink = &pool->entity;  		} else { -			sink = malloc(sizeof *entity); +			sink = omap3_isp_pipeline_create_entity(isp, name);  			if (sink == NULL) {  				ret = -ENOMEM;  				goto done;  			} - -			memset(sink, 0, sizeof *sink);  		} -		sink->entity = entity; - -		if (source != NULL) { -			/* Make sure there's a link between the source and sink -			 * entities. -			 */ -			for (i = 0; i < source->entity->num_links; ++i) { -				if (source->entity->links[i].sink->entity == sink->entity) -					break; -			} - -			if (i == source->entity->num_links) { -				free(sink); -				ret = -EPIPE; -				goto done; -			} +		list_append(&sink->list, &pipe->entities); -			/* Store link information in source and sink */ -			source->source.link = &source->entity->links[i]; -			sink->sink.link = &source->entity->links[i]; +		ret = omap3_isp_pipeline_validate_link(source, sink); +		if (ret < 0) { +			printf("No valid link found between %s and %s\n", +				entity_name(source), entity_name(sink)); +			goto done;  		} -		list_append(&sink->list, &pipe->entities);  		source = sink;  	} -	if (source == NULL) { +	if (source == NULL || source->type != OMAP3_ISP_ENTITY_VIDEO) {  		ret = -EINVAL;  		goto done;  	} | 
