summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-07-24 14:23:08 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-09-04 15:35:35 +0200
commitab75d6ab59d1bccd08204dd5fe7bddae2e19e1ee (patch)
treebf6f3a01d59ee7c34851c13c995faa8d0dfef4fb
parent3e7b97b2b945b616de12ba466592820145976daf (diff)
Add entities to pipeline structure
Add a omap3_isp_pipeline_build() function to build a pipeline from a list of entity names. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--isp/omap3isp-priv.h16
-rw-r--r--isp/omap3isp.c279
2 files changed, 211 insertions, 84 deletions
diff --git a/isp/omap3isp-priv.h b/isp/omap3isp-priv.h
index 3e78acc..bb683b5 100644
--- a/isp/omap3isp-priv.h
+++ b/isp/omap3isp-priv.h
@@ -50,10 +50,26 @@ struct omap3_isp_video {
};
/*
+ * 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
+ */
+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_pipeline - OMAP3 pipeline
+ * @entitites: Entities in the pipeline
* @output: Video device at the output of the pipeline
*/
struct omap3_isp_pipeline {
+ struct list_entry entities;
struct omap3_isp_video output;
};
diff --git a/isp/omap3isp.c b/isp/omap3isp.c
index 200cb9a..3d0872f 100644
--- a/isp/omap3isp.c
+++ b/isp/omap3isp.c
@@ -28,13 +28,16 @@
#include "controls.h"
#include "list.h"
-#include "omap3isp.h"
#include "omap3isp-priv.h"
+#include "omap3isp.h"
#include "subdev.h"
+#define ENTITY_SENSOR "mt9t001 3-005d"
#define ENTITY_CCDC "OMAP3 ISP CCDC"
+#define ENTITY_CCDC_OUTPUT "OMAP3 ISP CCDC output"
#define ENTITY_PREVIEW "OMAP3 ISP preview"
#define ENTITY_RESIZER "OMAP3 ISP resizer"
+#define ENTITY_RESIZER_OUTPUT "OMAP3 ISP resizer output"
/* -----------------------------------------------------------------------------
* Helper functions
@@ -119,6 +122,174 @@ static __u32 mbus_to_pix(enum v4l2_mbus_pixelcode code)
}
/* -----------------------------------------------------------------------------
+ * Pipeline management
+ */
+
+static void omap3_isp_pipeline_init(struct omap3_isp_pipeline *pipe)
+{
+ list_init(&pipe->entities);
+}
+
+static void omap3_isp_pipeline_destroy(struct omap3_isp_pipeline *pipe)
+{
+ struct omap3_isp_entity *entity;
+ struct omap3_isp_entity *next;
+
+ list_for_each_entry_safe(entity, next, &pipe->entities, list) {
+ list_remove(&entity->list);
+ free(entity);
+ }
+}
+
+static int omap3_isp_pipeline_build(struct omap3_isp_device *isp,
+ struct omap3_isp_pipeline *pipe, ...)
+{
+ struct omap3_isp_entity *source = NULL;
+ struct omap3_isp_entity *sink;
+ struct media_entity *entity;
+ unsigned int i;
+ va_list ap;
+ char *name;
+ int ret;
+
+ va_start(ap, pipe);
+
+ while ((name = va_arg(ap, char *)) != NULL) {
+
+ entity = media_get_entity_by_name(isp->mdev, name);
+ if (entity == NULL) {
+ ret = -ENOENT;
+ goto done;
+ }
+
+ sink = malloc(sizeof *entity);
+ if (sink == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ memset(sink, 0, sizeof *sink);
+ sink->entity = entity;
+
+ if (source != NULL) {
+ /* Make sure there's a link between the source and sink
+ * entities.
+ */
+ for (i = 0; i < source->entity->num_links; ++i) {
+ if (source->entity->links[i].sink->entity == sink->entity)
+ break;
+ }
+
+ if (i == source->entity->num_links) {
+ free(sink);
+ ret = -EPIPE;
+ goto done;
+ }
+
+ /* Store link information in source and sink */
+ source->link_source = &source->entity->links[i];
+ sink->link_sink = &source->entity->links[i];
+ }
+
+ list_append(&sink->list, &pipe->entities);
+ source = sink;
+ }
+
+ if (source == NULL) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ va_end(ap);
+ ret = 0;
+
+done:
+ if (ret < 0)
+ omap3_isp_pipeline_destroy(pipe);
+
+ return ret;
+}
+
+static int omap3_isp_pipeline_set_format(struct omap3_isp_device *isp,
+ struct v4l2_mbus_framefmt *ofmt,
+ enum omap3_isp_scaler scaler,
+ enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_mbus_framefmt format;
+ struct media_entity_link *link;
+ struct media_entity_pad *pad;
+ struct media_entity *entity;
+ 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, which);
+ if (ret < 0) {
+ printf("error: get format on sensor output failed.\n");
+ return ret;
+ }
+
+ for (entity = isp->sensor; ; ) {
+
+ link = entity_output_link(entity);
+ if (link == NULL)
+ break;
+
+ entity = link->sink->entity;
+ if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+ break;
+
+ pad = link->source;
+ ret = v4l2_subdev_get_format(pad->entity, &format, pad->index, which);
+ if (ret < 0) {
+ printf("error: get format failed on %s:%u.\n",
+ pad->entity->info.name, pad->index);
+ return ret;
+ }
+
+ /* Try to force the output format code onto the output pad. */
+ format.code = ofmt->code;
+ ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, which);
+ if (ret < 0) {
+ printf("error: set format failed on %s:%u.\n",
+ pad->entity->info.name, pad->index);
+ return ret;
+ }
+
+ pad = link->sink;
+ ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, which);
+ if (ret < 0) {
+ printf("error: set format failed on %s:%u.\n",
+ pad->entity->info.name, pad->index);
+ return ret;
+ }
+ }
+
+ if (ofmt == NULL)
+ return 0;
+
+ pad = link->source;
+ ret = v4l2_subdev_set_format(pad->entity, ofmt, pad->index, which);
+ if (ret < 0) {
+ printf("error: set format failed on %s:%u.\n",
+ pad->entity->info.name, pad->index);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
* Open/close
*/
@@ -137,6 +308,9 @@ struct omap3_isp_device *omap3_isp_open(const char *devname,
memset(isp, 0, sizeof *isp);
isp->ops = ops;
+ omap3_isp_pipeline_init(&isp->viewfinder);
+ omap3_isp_pipeline_init(&isp->snapshot);
+
/* Open the media device and reset all links to make sure we're in a
* consistent, known state.
*/
@@ -229,94 +403,13 @@ void omap3_isp_close(struct omap3_isp_device *isp)
if (isp == NULL)
return;
+ omap3_isp_pipeline_destroy(&isp->viewfinder);
+ omap3_isp_pipeline_destroy(&isp->snapshot);
media_close(isp->mdev);
free(isp);
}
/* -----------------------------------------------------------------------------
- * Pipeline management
- */
-
-static int omap3_isp_pipeline_set_format(struct omap3_isp_device *isp,
- struct v4l2_mbus_framefmt *ofmt,
- enum omap3_isp_scaler scaler,
- enum v4l2_subdev_format_whence which)
-{
- struct v4l2_mbus_framefmt format;
- struct media_entity_link *link;
- struct media_entity_pad *pad;
- struct media_entity *entity;
- 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, which);
- if (ret < 0) {
- printf("error: get format on sensor output failed.\n");
- return ret;
- }
-
- for (entity = isp->sensor; ; ) {
-
- link = entity_output_link(entity);
- if (link == NULL)
- break;
-
- entity = link->sink->entity;
- if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
- break;
-
- pad = link->source;
- ret = v4l2_subdev_get_format(pad->entity, &format, pad->index, which);
- if (ret < 0) {
- printf("error: get format failed on %s:%u.\n",
- pad->entity->info.name, pad->index);
- return ret;
- }
-
- /* Try to force the output format code onto the output pad. */
- format.code = ofmt->code;
- ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, which);
- if (ret < 0) {
- printf("error: set format failed on %s:%u.\n",
- pad->entity->info.name, pad->index);
- return ret;
- }
-
- pad = link->sink;
- ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, which);
- if (ret < 0) {
- printf("error: set format failed on %s:%u.\n",
- pad->entity->info.name, pad->index);
- return ret;
- }
- }
-
- if (ofmt == NULL)
- return 0;
-
- pad = link->source;
- ret = v4l2_subdev_set_format(pad->entity, ofmt, pad->index, which);
- if (ret < 0) {
- printf("error: set format failed on %s:%u.\n",
- pad->entity->info.name, pad->index);
- return ret;
- }
-
- return 0;
-}
-
-/* -----------------------------------------------------------------------------
* Viewfinder
*/
@@ -342,6 +435,14 @@ int omap3_isp_viewfinder_setup(struct omap3_isp_device *isp,
struct v4l2_pix_format format;
int ret;
+ ret = omap3_isp_pipeline_build(isp, &isp->viewfinder, ENTITY_SENSOR,
+ ENTITY_CCDC, ENTITY_PREVIEW, ENTITY_RESIZER,
+ ENTITY_RESIZER_OUTPUT, NULL);
+ if (ret < 0) {
+ printf("error: unable to build viewfinder pipeline (%d)\n", ret);
+ return ret;
+ }
+
/* Setup the pipeline. */
ret = omap3_isp_viewfinder_setup_pipeline(isp, ofmt);
if (ret < 0)
@@ -582,12 +683,22 @@ int omap3_isp_snapshot_setup(struct omap3_isp_device *isp,
case V4L2_MBUS_FMT_UYVY8_1X16:
case V4L2_MBUS_FMT_YUYV8_1X16:
entity = isp->resizer;
+ ret = omap3_isp_pipeline_build(isp, &isp->snapshot, ENTITY_SENSOR,
+ ENTITY_CCDC, ENTITY_PREVIEW, ENTITY_RESIZER,
+ ENTITY_RESIZER_OUTPUT, NULL);
break;
default:
entity = isp->ccdc;
+ ret = omap3_isp_pipeline_build(isp, &isp->snapshot, ENTITY_SENSOR,
+ ENTITY_CCDC, ENTITY_CCDC_OUTPUT, NULL);
break;
}
+ if (ret < 0) {
+ printf("error: unable to build snapshot pipeline (%d)\n", ret);
+ return ret;
+ }
+
isp->snapshot.output.scaler = OMAP3_ISP_SCALER_ISP;
isp->snapshot.output.subdev = entity;
isp->snapshot.output.node = entity_output_node(entity);