summaryrefslogtreecommitdiff
path: root/isp/omap3isp.c
diff options
context:
space:
mode:
Diffstat (limited to 'isp/omap3isp.c')
-rw-r--r--isp/omap3isp.c207
1 files changed, 161 insertions, 46 deletions
diff --git a/isp/omap3isp.c b/isp/omap3isp.c
index be5ea3d..eb90dcd 100644
--- a/isp/omap3isp.c
+++ b/isp/omap3isp.c
@@ -88,6 +88,17 @@ static __u32 mbus_to_pix(enum v4l2_mbus_pixelcode code)
}
}
+static const char *entity_name(struct omap3_isp_entity *entity)
+{
+ if (entity == NULL)
+ return "NULL";
+
+ if (entity->type == OMAP3_ISP_ENTITY_POOL)
+ return "POOL";
+
+ return entity->entity->info.name;
+}
+
/* -----------------------------------------------------------------------------
* Pipeline management
*/
@@ -95,6 +106,7 @@ static __u32 mbus_to_pix(enum v4l2_mbus_pixelcode code)
static void omap3_isp_pipeline_init(struct omap3_isp_pipeline *pipe)
{
list_init(&pipe->entities);
+ list_init(&pipe->pools);
}
static void omap3_isp_pipeline_destroy(struct omap3_isp_pipeline *pipe)
@@ -102,10 +114,18 @@ static void omap3_isp_pipeline_destroy(struct omap3_isp_pipeline *pipe)
struct omap3_isp_entity *entity;
struct omap3_isp_entity *next;
struct omap3_isp_video *video;
+ struct omap3_isp_pool *pool;
list_for_each_entry_safe(entity, next, &pipe->entities, list) {
list_remove(&entity->list);
switch (entity->type) {
+ case OMAP3_ISP_ENTITY_POOL:
+ pool = to_omap3_isp_pool(entity);
+ v4l2_buffers_pool_delete(pool->pool);
+ list_remove(&pool->list);
+ free(pool);
+ break;
+
case OMAP3_ISP_ENTITY_VIDEO:
video = to_omap3_isp_video(entity);
v4l2_close(video->video);
@@ -119,14 +139,135 @@ static void omap3_isp_pipeline_destroy(struct omap3_isp_pipeline *pipe)
}
}
+static struct omap3_isp_pool *
+omap3_isp_pipeline_create_pool(struct omap3_isp_device *isp __attribute__((__unused__)),
+ const char *name)
+{
+ struct omap3_isp_pool *pool;
+ unsigned int nbufs;
+ char *endp;
+
+ name += 5;
+ if (*name != '\0') {
+ if (*name != ':')
+ return NULL;
+
+ nbufs = strtoul(name + 1, &endp, 10);
+ if (*endp != '\0')
+ return NULL;
+ }
+
+ pool = malloc(sizeof *pool);
+ if (pool == NULL)
+ return NULL;
+
+ memset(pool, 0, sizeof *pool);
+ pool->entity.type = OMAP3_ISP_ENTITY_POOL;
+
+ pool->pool = v4l2_buffers_pool_new(nbufs);
+ if (pool->pool == NULL) {
+ free(pool);
+ return NULL;
+ }
+
+ return pool;
+}
+
+static struct omap3_isp_entity *
+omap3_isp_pipeline_create_entity(struct omap3_isp_device *isp,
+ const char *name)
+{
+ struct omap3_isp_entity *entity;
+ struct omap3_isp_video *video;
+ struct media_entity *ment;
+
+ ment = media_get_entity_by_name(isp->mdev, name);
+ if (ment == NULL)
+ return NULL;
+
+ if (media_entity_type(ment) == MEDIA_ENT_T_DEVNODE) {
+ video = malloc(sizeof *video);
+ if (video == NULL)
+ return NULL;
+
+ memset(video, 0, sizeof *video);
+
+ video->video = v4l2_open(ment->devname);
+ if (video->video == NULL) {
+ printf("error: unable to open video device %s\n",
+ ment->devname);
+ return NULL;
+ }
+
+ entity = &video->entity;
+ entity->type = OMAP3_ISP_ENTITY_VIDEO;
+ } else {
+ entity = malloc(sizeof *entity);
+ if (entity == NULL)
+ return NULL;
+
+ memset(entity, 0, sizeof *entity);
+ entity->type = OMAP3_ISP_ENTITY_ENTITY;
+ }
+
+ entity->entity = ment;
+ return entity;
+}
+
+static int omap3_isp_pipeline_validate_link(struct omap3_isp_entity *source,
+ struct omap3_isp_entity *sink)
+{
+ struct omap3_isp_video *video;
+ struct omap3_isp_pool *pool;
+ unsigned int i;
+
+ if (source == NULL)
+ return 0;
+
+ if (source->type != OMAP3_ISP_ENTITY_POOL &&
+ sink->type != OMAP3_ISP_ENTITY_POOL) {
+ /* 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)
+ return -EPIPE;
+
+ /* Store link information in source and sink */
+ source->source.link = &source->entity->links[i];
+ sink->sink.link = &source->entity->links[i];
+ return 0;
+ }
+
+ if (source->type == OMAP3_ISP_ENTITY_VIDEO &&
+ sink->type == OMAP3_ISP_ENTITY_POOL) {
+ pool = to_omap3_isp_pool(sink);
+ video = to_omap3_isp_video(source);
+ pool->input = video;
+ return 0;
+ }
+
+ if (source->type == OMAP3_ISP_ENTITY_POOL &&
+ sink->type == OMAP3_ISP_ENTITY_VIDEO) {
+ pool = to_omap3_isp_pool(source);
+ video = to_omap3_isp_video(sink);
+ pool->output = video;
+ return 0;
+ }
+
+ return -EPIPE;
+}
+
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 omap3_isp_video *video;
- struct media_entity *entity;
- unsigned int i;
+ struct omap3_isp_pool *pool;
va_list ap;
char *name;
int ret;
@@ -135,67 +276,41 @@ static int omap3_isp_pipeline_build(struct omap3_isp_device *isp,
while ((name = va_arg(ap, char *)) != NULL) {
- entity = media_get_entity_by_name(isp->mdev, name);
- if (entity == NULL) {
- ret = -ENOENT;
- goto done;
- }
+ if (strncmp(name, ":POOL", 5) == 0) {
+ /* The previous entity must be a device node. */
+ if (source == NULL || media_entity_type(source->entity)
+ != MEDIA_ENT_T_DEVNODE)
+ return -EPIPE;
- if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE) {
- video = malloc(sizeof *video);
- if (video == NULL) {
+ pool = omap3_isp_pipeline_create_pool(isp, name);
+ if (pool == NULL) {
ret = -ENOMEM;
goto done;
}
- memset(video, 0, sizeof *video);
-
- video->video = v4l2_open(entity->devname);
- if (video->video == NULL) {
- printf("error: unable to open video device %s\n",
- entity->devname);
- ret = -ENXIO;
- goto done;
- }
-
- sink = &video->entity;
+ list_append(&pool->list, &pipe->pools);
+ sink = &pool->entity;
} else {
- sink = malloc(sizeof *entity);
+ sink = omap3_isp_pipeline_create_entity(isp, name);
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;
- }
+ list_append(&sink->list, &pipe->entities);
- /* Store link information in source and sink */
- source->source.link = &source->entity->links[i];
- sink->sink.link = &source->entity->links[i];
+ ret = omap3_isp_pipeline_validate_link(source, sink);
+ if (ret < 0) {
+ printf("No valid link found between %s and %s\n",
+ entity_name(source), entity_name(sink));
+ goto done;
}
- list_append(&sink->list, &pipe->entities);
source = sink;
}
- if (source == NULL) {
+ if (source == NULL || source->type != OMAP3_ISP_ENTITY_VIDEO) {
ret = -EINVAL;
goto done;
}