summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-07-04 16:02:19 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-10-20 21:28:24 +0200
commit51e34d1d5a4a18b8f918eaf9a6e9adf6ea1dcc76 (patch)
tree3d37964b414b08c9a717a3d028a1b1c0aae68273
parent0ad854915eba288d17a9c9779c8deed831e74fec (diff)
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 <laurent.pinchart@ideasonboard.com>
-rw-r--r--isp/omap3isp-priv.h2
-rw-r--r--isp/omap3isp.c85
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;