From ab75d6ab59d1bccd08204dd5fe7bddae2e19e1ee Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 24 Jul 2011 14:23:08 +0200 Subject: 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 --- isp/omap3isp-priv.h | 16 +++ 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 @@ -49,11 +49,27 @@ struct omap3_isp_video { bool running; }; +/* + * 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 @@ -118,6 +121,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,93 +403,12 @@ 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); -- cgit v1.2.3