summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--isp/omap3isp-priv.h20
-rw-r--r--isp/omap3isp.c127
2 files changed, 127 insertions, 20 deletions
diff --git a/isp/omap3isp-priv.h b/isp/omap3isp-priv.h
index bb683b5..375c5c9 100644
--- a/isp/omap3isp-priv.h
+++ b/isp/omap3isp-priv.h
@@ -23,6 +23,8 @@
#ifndef __OMAP3ISP_PRIV_H
#define __OMAP3ISP_PRIV_H
+#include <linux/v4l2-mediabus.h>
+
#include "omap3isp.h"
/*
@@ -50,17 +52,27 @@ struct omap3_isp_video {
};
/*
+ * struct omap3_isp_pad - OMAP3 entity pad
+ * @link: Link connected to the pad
+ * @format: Format on the pad
+ */
+struct omap3_isp_pad {
+ struct media_entity_link *link;
+ struct v4l2_mbus_framefmt format;
+};
+
+/*
* 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
+ * @sink: Sink pad
+ * @source: Sink 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_pad sink;
+ struct omap3_isp_pad source;
};
/*
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;