From cd06fe652b33c7c556a5735a30ca5f48dbcb77b8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 25 Jul 2011 00:24:39 +0200 Subject: Add omap3_isp_pipeline_try_format() The function tries formats on pipeline pads to achieve the requested output format, and saves the format at each pad in the oamp3_isp_pad structure for later use. Replace the snapshot format try code by a call to omap3_isp_pipeline_try_format(). Signed-off-by: Laurent Pinchart --- isp/omap3isp.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 111 insertions(+), 16 deletions(-) (limited to 'isp/omap3isp.c') diff --git a/isp/omap3isp.c b/isp/omap3isp.c index 04d69ad..75467e1 100644 --- a/isp/omap3isp.c +++ b/isp/omap3isp.c @@ -187,8 +187,8 @@ static int omap3_isp_pipeline_build(struct omap3_isp_device *isp, } /* Store link information in source and sink */ - source->link_source = &source->entity->links[i]; - sink->link_sink = &source->entity->links[i]; + source->source.link = &source->entity->links[i]; + sink->sink.link = &source->entity->links[i]; } list_append(&sink->list, &pipe->entities); @@ -210,6 +210,97 @@ done: return ret; } +static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp, + struct omap3_isp_pipeline *pipe, + struct v4l2_mbus_framefmt *ofmt, + enum omap3_isp_scaler scaler) +{ + struct v4l2_mbus_framefmt format; + struct omap3_isp_entity *source = NULL; + struct omap3_isp_entity *sink; + struct media_entity_pad *pad; + 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, + 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) { + source = sink; + continue; + } + + if (media_entity_type(sink->entity) == MEDIA_ENT_T_DEVNODE) + break; + + /* Try to force the output format code onto the source pad. */ + pad = source->source.link->source; + + ret = v4l2_subdev_get_format(pad->entity, &format, pad->index, + V4L2_SUBDEV_FORMAT_TRY); + if (ret < 0) { + printf("error: get format failed on %s:%u.\n", + pad->entity->info.name, pad->index); + return ret; + } + + format.code = ofmt->code; + ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, + V4L2_SUBDEV_FORMAT_TRY); + if (ret < 0) { + printf("error: set format failed on %s:%u.\n", + pad->entity->info.name, pad->index); + return ret; + } + + source->source.format = format; + + /* Propagate the format to the link target. */ + pad = sink->sink.link->sink; + + ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, + V4L2_SUBDEV_FORMAT_TRY); + if (ret < 0) { + printf("error: set format failed on %s:%u.\n", + pad->entity->info.name, pad->index); + return ret; + } + + sink->sink.format = format; + + source = sink; + } + + pad = source->source.link->source; + + ret = v4l2_subdev_set_format(pad->entity, ofmt, pad->index, + V4L2_SUBDEV_FORMAT_TRY); + if (ret < 0) { + printf("error: set format failed on %s:%u.\n", + pad->entity->info.name, pad->index); + return ret; + } + + source->source.format = format; + return 0; +} + static int omap3_isp_pipeline_activate(struct omap3_isp_device *isp, struct omap3_isp_pipeline *pipe) { @@ -221,11 +312,11 @@ static int omap3_isp_pipeline_activate(struct omap3_isp_device *isp, return ret; list_for_each_entry(entity, &pipe->entities, list) { - if (entity->link_source == NULL) + if (entity->source.link == NULL) break; - ret = setup_link(isp, entity->link_source->source->entity, - entity->link_source->sink->entity, + ret = setup_link(isp, entity->source.link->source->entity, + entity->source.link->sink->entity, MEDIA_LNK_FL_ENABLED); if (ret < 0) return ret; @@ -467,6 +558,12 @@ int omap3_isp_viewfinder_setup(struct omap3_isp_device *isp, return ret; } + /* Try the format. */ + ret = omap3_isp_pipeline_try_format(isp, &isp->viewfinder, ofmt, + isp->viewfinder.output.scaler); + if (ret < 0) + return ret; + /* Setup the pipeline. */ ret = omap3_isp_viewfinder_setup_pipeline(isp, ofmt); if (ret < 0) @@ -523,13 +620,14 @@ int omap3_isp_viewfinder_set_scaler(struct omap3_isp_device *isp, isp->viewfinder.output.scaler = scaler; - /* If omap3_isp_viewfinder_setup() hasn't been called yet retur now. */ + /* If omap3_isp_viewfinder_setup() hasn't been called yet return now. */ if (isp->viewfinder.output.format.width == 0 || isp->viewfinder.output.format.height == 0) return 0; format = isp->viewfinder.output.format; - ret = omap3_isp_viewfinder_setup_pipeline(isp, &format); + ret = omap3_isp_pipeline_try_format(isp, &isp->viewfinder, &format, + isp->viewfinder.output.scaler); if (ret < 0) return ret; @@ -647,8 +745,7 @@ static int omap3_isp_snapshot_restore_pipeline(struct omap3_isp_device *isp) } static int omap3_isp_snapshot_setup_pipeline(struct omap3_isp_device *isp, - struct v4l2_mbus_framefmt *ofmt, - enum v4l2_subdev_format_whence which) + struct v4l2_mbus_framefmt *ofmt) { int ret; @@ -658,7 +755,8 @@ static int omap3_isp_snapshot_setup_pipeline(struct omap3_isp_device *isp, return ret; /* Configure the formats on the pipeline. */ - ret = omap3_isp_pipeline_set_format(isp, ofmt, isp->snapshot.output.scaler, which); + ret = omap3_isp_pipeline_set_format(isp, ofmt, isp->snapshot.output.scaler, + V4L2_SUBDEV_FORMAT_ACTIVE); if (ret < 0) { printf("error: unable to configure formats on pipeline.\n"); return ret; @@ -706,16 +804,13 @@ int omap3_isp_snapshot_setup(struct omap3_isp_device *isp, return -ENOENT; /* Try the format. */ - ret = omap3_isp_snapshot_setup_pipeline(isp, ofmt, V4L2_SUBDEV_FORMAT_TRY); + ret = omap3_isp_pipeline_try_format(isp, &isp->snapshot, ofmt, + OMAP3_ISP_SCALER_ISP); if (ret < 0) return ret; isp->snapshot.output.format = *ofmt; - ret = omap3_isp_snapshot_restore_pipeline(isp); - if (ret < 0) - return ret; - /* Open the V4L2 device. */ isp->snapshot.output.video = v4l2_open(isp->snapshot.output.node->devname); if (isp->snapshot.output.video == NULL) { @@ -831,7 +926,7 @@ int omap3_isp_snapshot_capture(struct omap3_isp_device *isp) /* Configure the pipeline. */ format = isp->snapshot.output.format; - ret = omap3_isp_snapshot_setup_pipeline(isp, &format, V4L2_SUBDEV_FORMAT_ACTIVE); + ret = omap3_isp_snapshot_setup_pipeline(isp, &format); if (ret < 0) { printf("error: unable to setup snapshot pipeline.\n"); return ret; -- cgit v1.2.3