diff options
| author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2011-07-24 14:23:08 +0200 | 
|---|---|---|
| committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2011-09-04 15:35:35 +0200 | 
| commit | ab75d6ab59d1bccd08204dd5fe7bddae2e19e1ee (patch) | |
| tree | bf6f3a01d59ee7c34851c13c995faa8d0dfef4fb | |
| parent | 3e7b97b2b945b616de12ba466592820145976daf (diff) | |
Add entities to pipeline structure
Add a omap3_isp_pipeline_build() function to build a pipeline from a
list of entity names.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
| -rw-r--r-- | isp/omap3isp-priv.h | 16 | ||||
| -rw-r--r-- | isp/omap3isp.c | 279 | 
2 files changed, 211 insertions, 84 deletions
| diff --git a/isp/omap3isp-priv.h b/isp/omap3isp-priv.h index 3e78acc..bb683b5 100644 --- a/isp/omap3isp-priv.h +++ b/isp/omap3isp-priv.h @@ -50,10 +50,26 @@ struct omap3_isp_video {  };  /* + * struct omap3_isp_entity - OMAP3 entity in a pipeline + * @list: Entities list + * @entity: Media entity information + * @link_sink: Link connected to the sink pad + * @link_source: Link connected to the source pad + */ +struct omap3_isp_entity { +	struct list_entry list; +	struct media_entity *entity; +	struct media_entity_link *link_sink; +	struct media_entity_link *link_source; +}; + +/*   * struct omap3_isp_pipeline - OMAP3 pipeline + * @entitites: Entities in the pipeline   * @output: Video device at the output of the pipeline   */  struct omap3_isp_pipeline { +	struct list_entry entities;  	struct omap3_isp_video output;  }; diff --git a/isp/omap3isp.c b/isp/omap3isp.c index 200cb9a..3d0872f 100644 --- a/isp/omap3isp.c +++ b/isp/omap3isp.c @@ -28,13 +28,16 @@  #include "controls.h"  #include "list.h" -#include "omap3isp.h"  #include "omap3isp-priv.h" +#include "omap3isp.h"  #include "subdev.h" +#define ENTITY_SENSOR		"mt9t001 3-005d"  #define ENTITY_CCDC		"OMAP3 ISP CCDC" +#define ENTITY_CCDC_OUTPUT	"OMAP3 ISP CCDC output"  #define ENTITY_PREVIEW		"OMAP3 ISP preview"  #define ENTITY_RESIZER		"OMAP3 ISP resizer" +#define ENTITY_RESIZER_OUTPUT	"OMAP3 ISP resizer output"  /* -----------------------------------------------------------------------------   * Helper functions @@ -119,6 +122,174 @@ static __u32 mbus_to_pix(enum v4l2_mbus_pixelcode code)  }  /* ----------------------------------------------------------------------------- + * Pipeline management + */ + +static void omap3_isp_pipeline_init(struct omap3_isp_pipeline *pipe) +{ +	list_init(&pipe->entities); +} + +static void omap3_isp_pipeline_destroy(struct omap3_isp_pipeline *pipe) +{ +	struct omap3_isp_entity *entity; +	struct omap3_isp_entity *next; + +	list_for_each_entry_safe(entity, next, &pipe->entities, list) { +		list_remove(&entity->list); +		free(entity); +	} +} + +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 media_entity *entity; +	unsigned int i; +	va_list ap; +	char *name; +	int ret; + +	va_start(ap, pipe); + +	while ((name = va_arg(ap, char *)) != NULL) { + +		entity = media_get_entity_by_name(isp->mdev, name); +		if (entity == NULL) { +			ret = -ENOENT; +			goto done; +		} + +		sink = malloc(sizeof *entity); +		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; +			} + +			/* Store link information in source and sink */ +			source->link_source = &source->entity->links[i]; +			sink->link_sink = &source->entity->links[i]; +		} + +		list_append(&sink->list, &pipe->entities); +		source = sink; +	} + +	if (source == NULL) { +		ret = -EINVAL; +		goto done; +	} + +	va_end(ap); +	ret = 0; + +done: +	if (ret < 0) +		omap3_isp_pipeline_destroy(pipe); + +	return ret; +} + +static int omap3_isp_pipeline_set_format(struct omap3_isp_device *isp, +					 struct v4l2_mbus_framefmt *ofmt, +					 enum omap3_isp_scaler scaler, +					 enum v4l2_subdev_format_whence which) +{ +	struct v4l2_mbus_framefmt format; +	struct media_entity_link *link; +	struct media_entity_pad *pad; +	struct media_entity *entity; +	int ret; + +	/* Configure formats. Start from the sensor output and propagate the +	 * format through the pipeline. +	 */ + +	/* When scaling on the ISP, select the sensor default output format. +	 * Otherwise scale as much as possible on the sensor. +	 */ +	if (scaler == OMAP3_ISP_SCALER_ISP) +		format = isp->sensor_format; +	else +		format = *ofmt; + +	ret = v4l2_subdev_set_format(isp->sensor, &format, 0, which); +	if (ret < 0) { +		printf("error: get format on sensor output failed.\n"); +		return ret; +	} + +	for (entity = isp->sensor; ; ) { + +		link = entity_output_link(entity); +		if (link == NULL) +			break; + +		entity = link->sink->entity; +		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE) +			break; + +		pad = link->source; +		ret = v4l2_subdev_get_format(pad->entity, &format, pad->index, which); +		if (ret < 0) { +			printf("error: get format failed on %s:%u.\n", +				pad->entity->info.name, pad->index); +			return ret; +		} + +		/* Try to force the output format code onto the output pad. */ +		format.code = ofmt->code; +		ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, which); +		if (ret < 0) { +			printf("error: set format failed on %s:%u.\n", +				pad->entity->info.name, pad->index); +			return ret; +		} + +		pad = link->sink; +		ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, which); +		if (ret < 0) { +			printf("error: set format failed on %s:%u.\n", +				pad->entity->info.name, pad->index); +			return ret; +		} +	} + +	if (ofmt == NULL) +		return 0; + +	pad = link->source; +	ret = v4l2_subdev_set_format(pad->entity, ofmt, pad->index, which); +	if (ret < 0) { +		printf("error: set format failed on %s:%u.\n", +			pad->entity->info.name, pad->index); +		return ret; +	} + +	return 0; +} + +/* -----------------------------------------------------------------------------   * Open/close   */ @@ -137,6 +308,9 @@ struct omap3_isp_device *omap3_isp_open(const char *devname,  	memset(isp, 0, sizeof *isp);  	isp->ops = ops; +	omap3_isp_pipeline_init(&isp->viewfinder); +	omap3_isp_pipeline_init(&isp->snapshot); +  	/* Open the media device and reset all links to make sure we're in a  	 * consistent, known state.  	 */ @@ -229,94 +403,13 @@ void omap3_isp_close(struct omap3_isp_device *isp)  	if (isp == NULL)  		return; +	omap3_isp_pipeline_destroy(&isp->viewfinder); +	omap3_isp_pipeline_destroy(&isp->snapshot);  	media_close(isp->mdev);  	free(isp);  }  /* ----------------------------------------------------------------------------- - * Pipeline management - */ - -static int omap3_isp_pipeline_set_format(struct omap3_isp_device *isp, -					 struct v4l2_mbus_framefmt *ofmt, -					 enum omap3_isp_scaler scaler, -					 enum v4l2_subdev_format_whence which) -{ -	struct v4l2_mbus_framefmt format; -	struct media_entity_link *link; -	struct media_entity_pad *pad; -	struct media_entity *entity; -	int ret; - -	/* Configure formats. Start from the sensor output and propagate the -	 * format through the pipeline. -	 */ - -	/* When scaling on the ISP, select the sensor default output format. -	 * Otherwise scale as much as possible on the sensor. -	 */ -	if (scaler == OMAP3_ISP_SCALER_ISP) -		format = isp->sensor_format; -	else -		format = *ofmt; - -	ret = v4l2_subdev_set_format(isp->sensor, &format, 0, which); -	if (ret < 0) { -		printf("error: get format on sensor output failed.\n"); -		return ret; -	} - -	for (entity = isp->sensor; ; ) { - -		link = entity_output_link(entity); -		if (link == NULL) -			break; - -		entity = link->sink->entity; -		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE) -			break; - -		pad = link->source; -		ret = v4l2_subdev_get_format(pad->entity, &format, pad->index, which); -		if (ret < 0) { -			printf("error: get format failed on %s:%u.\n", -				pad->entity->info.name, pad->index); -			return ret; -		} - -		/* Try to force the output format code onto the output pad. */ -		format.code = ofmt->code; -		ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, which); -		if (ret < 0) { -			printf("error: set format failed on %s:%u.\n", -				pad->entity->info.name, pad->index); -			return ret; -		} - -		pad = link->sink; -		ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, which); -		if (ret < 0) { -			printf("error: set format failed on %s:%u.\n", -				pad->entity->info.name, pad->index); -			return ret; -		} -	} - -	if (ofmt == NULL) -		return 0; - -	pad = link->source; -	ret = v4l2_subdev_set_format(pad->entity, ofmt, pad->index, which); -	if (ret < 0) { -		printf("error: set format failed on %s:%u.\n", -			pad->entity->info.name, pad->index); -		return ret; -	} - -	return 0; -} - -/* -----------------------------------------------------------------------------   * Viewfinder   */ @@ -342,6 +435,14 @@ int omap3_isp_viewfinder_setup(struct omap3_isp_device *isp,  	struct v4l2_pix_format format;  	int ret; +	ret = omap3_isp_pipeline_build(isp, &isp->viewfinder, ENTITY_SENSOR, +				       ENTITY_CCDC, ENTITY_PREVIEW, ENTITY_RESIZER, +				       ENTITY_RESIZER_OUTPUT, NULL); +	if (ret < 0) { +		printf("error: unable to build viewfinder pipeline (%d)\n", ret); +		return ret; +	} +  	/* Setup the pipeline. */  	ret = omap3_isp_viewfinder_setup_pipeline(isp, ofmt);  	if (ret < 0) @@ -582,12 +683,22 @@ int omap3_isp_snapshot_setup(struct omap3_isp_device *isp,  	case V4L2_MBUS_FMT_UYVY8_1X16:  	case V4L2_MBUS_FMT_YUYV8_1X16:  		entity = isp->resizer; +		ret = omap3_isp_pipeline_build(isp, &isp->snapshot, ENTITY_SENSOR, +					       ENTITY_CCDC, ENTITY_PREVIEW, ENTITY_RESIZER, +					       ENTITY_RESIZER_OUTPUT, NULL);  		break;  	default:  		entity = isp->ccdc; +		ret = omap3_isp_pipeline_build(isp, &isp->snapshot, ENTITY_SENSOR, +					       ENTITY_CCDC, ENTITY_CCDC_OUTPUT, NULL);  		break;  	} +	if (ret < 0) { +		printf("error: unable to build snapshot pipeline (%d)\n", ret); +		return ret; +	} +  	isp->snapshot.output.scaler = OMAP3_ISP_SCALER_ISP;  	isp->snapshot.output.subdev = entity;  	isp->snapshot.output.node = entity_output_node(entity); | 
