From 51e34d1d5a4a18b8f918eaf9a6e9adf6ea1dcc76 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 4 Jul 2012 16:02:19 +0200 Subject: isp: Add support for memory-to-memory pipelines Make building and trying format possible on a pipeline that starts with a video node. Signed-off-by: Laurent Pinchart --- isp/omap3isp-priv.h | 2 ++ isp/omap3isp.c | 85 +++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 65 insertions(+), 22 deletions(-) diff --git a/isp/omap3isp-priv.h b/isp/omap3isp-priv.h index 2d639e1..c9f73a1 100644 --- a/isp/omap3isp-priv.h +++ b/isp/omap3isp-priv.h @@ -138,6 +138,7 @@ enum omap3_isp_pipeline_state { * @entitites: Entities in the pipeline * @scaler: Whether scaling should be performed on the ISP or the sensor * @pools: Pools in the pipeline + * @input: Video device at the input of the pipeline * @output: Video device at the output of the pipeline * @state: Pipeline state */ @@ -145,6 +146,7 @@ struct omap3_isp_pipeline { struct list_entry entities; enum omap3_isp_scaler scaler; struct list_entry pools; + struct omap3_isp_video *input; struct omap3_isp_video *output; enum omap3_isp_pipeline_state state; struct omap3_isp_resizer resizer; diff --git a/isp/omap3isp.c b/isp/omap3isp.c index 7a2d8c0..8b87b10 100644 --- a/isp/omap3isp.c +++ b/isp/omap3isp.c @@ -555,6 +555,7 @@ static int omap3_isp_pipeline_build(struct omap3_isp_device *isp, struct omap3_isp_entity *source = NULL; struct omap3_isp_entity *sink; struct omap3_isp_pool *pool; + bool first = true; va_list ap; char *name; int ret; @@ -585,6 +586,9 @@ static int omap3_isp_pipeline_build(struct omap3_isp_device *isp, } } + if (first && sink->type == OMAP3_ISP_ENTITY_VIDEO) + pipe->input = to_omap3_isp_video(sink); + list_append(&sink->list, &pipe->entities); ret = omap3_isp_pipeline_validate_link(source, sink); @@ -595,6 +599,7 @@ static int omap3_isp_pipeline_build(struct omap3_isp_device *isp, } source = sink; + first = false; } if (source == NULL || source->type != OMAP3_ISP_ENTITY_VIDEO) { @@ -617,8 +622,10 @@ done: static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp, struct omap3_isp_pipeline *pipe, - struct v4l2_rect *crop, - struct v4l2_mbus_framefmt *ofmt) + const struct v4l2_mbus_framefmt *ifmt, + struct v4l2_mbus_framefmt *ofmt, + struct v4l2_rect *crop) + { struct v4l2_mbus_framefmt format; struct v4l2_pix_format v4l2_fmt; @@ -630,27 +637,54 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp, pipe->resizer.entity = NULL; - /* 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. + /* Configure formats. Start from the input and propagate the format + * through the pipeline. + * + * When scaling on the ISP, select the input format, otherwise scale as + * much as possible on the sensor. */ if (pipe->scaler == OMAP3_ISP_SCALER_ISP) format = isp->sensor.format; else format = *ofmt; - ret = v4l2_subdev_set_format(isp->sensor.entity, &format, 0, - V4L2_SUBDEV_FORMAT_TRY); - if (ret < 0) { - printf("error: get format on sensor output failed.\n"); - return ret; - } list_for_each_entry(sink, &pipe->entities, list) { if (source == NULL) { + /* Configure the first entity in the pipeline with the + * initial format. + */ + pad = sink->source.link->source; + + if (sink->type == OMAP3_ISP_ENTITY_ENTITY) { + ret = v4l2_subdev_set_format(sink->entity, &format, 0, + V4L2_SUBDEV_FORMAT_TRY); + if (ret < 0) { + printf("error: get format on sensor output failed.\n"); + return ret; + } + } else if (sink->type == OMAP3_ISP_ENTITY_VIDEO) { + video = to_omap3_isp_video(sink); + + memset(&v4l2_fmt, 0, sizeof v4l2_fmt); + v4l2_fmt.pixelformat = mbus_to_pix(format.code); + v4l2_fmt.width = format.width; + v4l2_fmt.height = format.height; + + ret = v4l2_set_format(video->video, &v4l2_fmt); + if (ret < 0) { + printf("error: set format failed on %s.\n", + sink->entity->info.name); + return ret; + } + + format.code = pix_to_mbus(v4l2_fmt.pixelformat); + format.width = v4l2_fmt.width; + format.height = v4l2_fmt.height; + + video->format = format; + } + source = sink; continue; } @@ -704,11 +738,12 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp, return ret; } - source->source.format = format; if (sink->last) *ofmt = format; } + source->source.format = format; + if (sink->type == OMAP3_ISP_ENTITY_ENTITY) { if (sink->entity == isp->ccdc.entity) { if (format_is_shiftable(format.code, ofmt->code)) @@ -726,7 +761,6 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp, return ret; } - sink->sink.format = format; if (sink->entity == isp->resizer.entity) { ret = v4l2_subdev_get_crop(sink->entity, @@ -760,11 +794,15 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp, return ret; } - video->format.code = pix_to_mbus(v4l2_fmt.pixelformat); - video->format.width = v4l2_fmt.width; - video->format.height = v4l2_fmt.height; + format.code = pix_to_mbus(v4l2_fmt.pixelformat); + format.width = v4l2_fmt.width; + format.height = v4l2_fmt.height; + + video->format = format; } + sink->sink.format = format; + source = sink; } @@ -1165,7 +1203,8 @@ int omap3_isp_viewfinder_setup(struct omap3_isp_device *isp, isp->viewfinder.scaler = OMAP3_ISP_SCALER_ISP; /* Try the format. */ - ret = omap3_isp_pipeline_try_format(isp, &isp->viewfinder, NULL, ofmt); + ret = omap3_isp_pipeline_try_format(isp, &isp->viewfinder, + &isp->sensor.format, ofmt, NULL); if (ret < 0) return ret; @@ -1221,7 +1260,8 @@ int omap3_isp_viewfinder_set_scaler(struct omap3_isp_device *isp, /* Try the format. */ format = isp->viewfinder.output->format; - ret = omap3_isp_pipeline_try_format(isp, &isp->viewfinder, NULL, &format); + ret = omap3_isp_pipeline_try_format(isp, &isp->viewfinder, + &isp->sensor.format, &format, NULL); if (ret < 0) return ret; @@ -1353,7 +1393,8 @@ int omap3_isp_snapshot_setup(struct omap3_isp_device *isp, isp->snapshot.scaler = OMAP3_ISP_SCALER_ISP; /* Try the format. */ - ret = omap3_isp_pipeline_try_format(isp, &isp->snapshot, crop, ofmt); + ret = omap3_isp_pipeline_try_format(isp, &isp->snapshot, + &isp->sensor.format, ofmt, crop); if (ret < 0) return ret; -- cgit v1.2.3