summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-07-03 00:33:55 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-10-20 21:21:35 +0200
commit23b31323e49efd89d1ef40ceb9488579069929e6 (patch)
tree0ea73235cd49cb010b83c2d45bfd7b3da8d678f9
parentc8ca837395028751f79a6b6a690c37acc58f2f8c (diff)
isp: Add live zoom support
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--isp/omap3isp-priv.h19
-rw-r--r--isp/omap3isp.c83
-rw-r--r--isp/omap3isp.h2
3 files changed, 103 insertions, 1 deletions
diff --git a/isp/omap3isp-priv.h b/isp/omap3isp-priv.h
index c71ed40..2d639e1 100644
--- a/isp/omap3isp-priv.h
+++ b/isp/omap3isp-priv.h
@@ -112,6 +112,21 @@ struct omap3_isp_pool {
#define to_omap3_isp_pool(e) container_of(e, struct omap3_isp_pool, entity)
+/*
+ * struct omap3_isp_resizer - OMAP3 ISP resizer parameters in a pipeline
+ * @entity: The resizer entity
+ * @zoom_min: Crop rectangle at minimum zoom
+ * @zoom_max: Crop rectangle at maximum zoom (up to x4.0)
+ * @pan_x: Zoom center along X axis
+ * @pan_y: Zoom center along Y axis
+ * @zoom: Zoom level (0.0 - 1.0)
+ */
+struct omap3_isp_resizer {
+ struct omap3_isp_entity *entity;
+ struct v4l2_rect zoom_min;
+ struct v4l2_rect zoom_max;
+};
+
enum omap3_isp_pipeline_state {
OMAP3_ISP_PIPELINE_STOPPED,
OMAP3_ISP_PIPELINE_RUNNING,
@@ -132,6 +147,7 @@ struct omap3_isp_pipeline {
struct list_entry pools;
struct omap3_isp_video *output;
enum omap3_isp_pipeline_state state;
+ struct omap3_isp_resizer resizer;
};
struct omap3_isp_device {
@@ -150,6 +166,9 @@ struct omap3_isp_device {
struct media_entity *entity;
struct omap3isp_prev_wbal wbal;
} preview;
+ struct {
+ struct media_entity *entity;
+ } resizer;
struct omap3_isp_aewb aewb;
struct omap3_isp_pipeline viewfinder;
diff --git a/isp/omap3isp.c b/isp/omap3isp.c
index 7ff2d7e..1e6f317 100644
--- a/isp/omap3isp.c
+++ b/isp/omap3isp.c
@@ -629,6 +629,8 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp,
struct media_entity_pad *pad;
int ret;
+ pipe->resizer.entity = NULL;
+
/* Configure formats. Start from the sensor output and propagate the
* format through the pipeline.
*/
@@ -726,6 +728,17 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp,
}
sink->sink.format = format;
+
+ if (sink->entity == isp->resizer.entity) {
+ ret = v4l2_subdev_get_crop(sink->entity,
+ &pipe->resizer.zoom_min,
+ 0, V4L2_SUBDEV_FORMAT_TRY);
+ if (ret < 0)
+ printf("error: failed to get minimum zoom limit, "
+ "zoom will be disabled.\n");
+ else
+ pipe->resizer.entity = sink;
+ }
} else if (sink->type == OMAP3_ISP_ENTITY_VIDEO) {
video = to_omap3_isp_video(sink);
@@ -756,6 +769,24 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp,
source = sink;
}
+ if (pipe->resizer.entity) {
+ pipe->resizer.zoom_max.left = pipe->resizer.zoom_min.left
+ + pipe->resizer.zoom_min.width / 2;
+ pipe->resizer.zoom_max.top = pipe->resizer.zoom_min.top
+ + pipe->resizer.zoom_min.height / 2;
+ pipe->resizer.zoom_max.width = 0;
+ pipe->resizer.zoom_max.height = 0;
+
+ ret = v4l2_subdev_set_crop(isp->resizer.entity,
+ &pipe->resizer.zoom_max, 0,
+ V4L2_SUBDEV_FORMAT_TRY);
+ if (ret < 0) {
+ printf("error: failed to get maximum zoom limit, "
+ "zoom will be disabled.\n");
+ pipe->resizer.entity = NULL;
+ }
+ }
+
return 0;
}
@@ -876,6 +907,48 @@ static int omap3_isp_pipeline_put_buffer(struct omap3_isp_device *isp,
return omap3_isp_video_queue_buffer(pipe->output, buffer);
}
+
+static int omap3_isp_pipeline_pan_zoom(struct omap3_isp_device *isp,
+ struct omap3_isp_pipeline *pipe,
+ float pan_x, float pan_y, float zoom)
+{
+ struct v4l2_mbus_framefmt *format;
+ struct v4l2_rect rect;
+ float delta;
+ int ret;
+
+ if (pipe->resizer.entity == NULL)
+ return -ENODEV;
+
+ format = &pipe->resizer.entity->sink.format;
+
+ /* A x4.0 zoom level results in SBL overflows at the resizer output. */
+ zoom = clamp(zoom, 1.0, 3.8);
+
+ delta = pipe->resizer.zoom_min.width - pipe->resizer.zoom_max.width;
+ rect.width = format->width - (zoom - 1.0) / 3.0 * delta;
+ rect.left = (format->width - rect.width) * pan_x;
+
+ delta = pipe->resizer.zoom_min.height - pipe->resizer.zoom_max.height;
+ rect.height = format->height - (zoom - 1.0) / 3.0 * delta;
+ rect.top = (format->height - rect.height) * pan_y;
+
+ if (pipe->resizer.entity->sink.crop.left == rect.left &&
+ pipe->resizer.entity->sink.crop.top == rect.top &&
+ pipe->resizer.entity->sink.crop.width == rect.width &&
+ pipe->resizer.entity->sink.crop.height == rect.height)
+ return 0;
+
+ ret = v4l2_subdev_set_crop(isp->resizer.entity, &rect, 0,
+ V4L2_SUBDEV_FORMAT_ACTIVE);
+ if (ret < 0)
+ return ret;
+
+ pipe->resizer.entity->sink.crop = rect;
+
+ return 0;
+}
+
/* -----------------------------------------------------------------------------
* Open/close
*/
@@ -918,8 +991,10 @@ struct omap3_isp_device *omap3_isp_open(const char *devname,
*/
isp->ccdc.entity = media_get_entity_by_name(isp->mdev, ENTITY_CCDC);
isp->preview.entity = media_get_entity_by_name(isp->mdev, ENTITY_PREVIEW);
+ isp->resizer.entity = media_get_entity_by_name(isp->mdev, ENTITY_RESIZER);
- if (isp->ccdc.entity == NULL || isp->preview.entity == NULL) {
+ if (isp->ccdc.entity == NULL || isp->preview.entity == NULL ||
+ isp->resizer.entity == NULL) {
printf("error: unable to locate one or more ISP entities.\n");
goto error;
}
@@ -1231,6 +1306,12 @@ static int omap3_isp_viewfinder_resume(struct omap3_isp_device *isp)
return 0;
}
+int omap3_isp_viewfinder_pan_zoom(struct omap3_isp_device *isp,
+ float x, float y, float zoom)
+{
+ return omap3_isp_pipeline_pan_zoom(isp, &isp->viewfinder, x, y, zoom);
+}
+
/* -----------------------------------------------------------------------------
* Snapshot
*
diff --git a/isp/omap3isp.h b/isp/omap3isp.h
index 545c82c..16c96bd 100644
--- a/isp/omap3isp.h
+++ b/isp/omap3isp.h
@@ -71,6 +71,8 @@ int omap3_isp_viewfinder_start(struct omap3_isp_device *isp);
int omap3_isp_viewfinder_stop(struct omap3_isp_device *isp);
int omap3_isp_viewfinder_put_buffer(struct omap3_isp_device *isp,
struct v4l2_video_buffer *buffer);
+int omap3_isp_viewfinder_pan_zoom(struct omap3_isp_device *isp,
+ float x, float y, float zoom);
int omap3_isp_snapshot_setup(struct omap3_isp_device *isp,
struct v4l2_rect *crop,