summaryrefslogtreecommitdiff
path: root/isp/omap3isp.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-07-25 00:24:39 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-09-04 15:36:34 +0200
commitcd06fe652b33c7c556a5735a30ca5f48dbcb77b8 (patch)
tree2d4de03e3639f1c31dc0b9919941d21b8cbda4fc /isp/omap3isp.c
parentd3e7371b152c98ebac4c5202223c1c962bf390c6 (diff)
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 <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'isp/omap3isp.c')
-rw-r--r--isp/omap3isp.c127
1 files changed, 111 insertions, 16 deletions
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;