From 58bf4d40bfbfb156588a95ead469b32ea133f070 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: Tue, 28 Feb 2012 14:36:38 +0100
Subject: omap3isp: Support cropping for snapshot capture

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 isp/omap3isp-priv.h |  2 ++
 isp/omap3isp.c      | 42 +++++++++++++++++++++++++++++++++++++++---
 isp/omap3isp.h      |  1 +
 3 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/isp/omap3isp-priv.h b/isp/omap3isp-priv.h
index e1ee179..b6484de 100644
--- a/isp/omap3isp-priv.h
+++ b/isp/omap3isp-priv.h
@@ -34,10 +34,12 @@ struct omap3_isp_device;
 /*
  * struct omap3_isp_pad - OMAP3 entity pad
  * @link: Link connected to the pad
+ * @crop: Crop rectangle
  * @format: Format on the pad
  */
 struct omap3_isp_pad {
 	struct media_entity_link *link;
+	struct v4l2_rect crop;
 	struct v4l2_mbus_framefmt format;
 };
 
diff --git a/isp/omap3isp.c b/isp/omap3isp.c
index 9fbd984..f6ec060 100644
--- a/isp/omap3isp.c
+++ b/isp/omap3isp.c
@@ -609,6 +609,7 @@ 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,
 					 enum omap3_isp_scaler scaler)
 {
@@ -618,6 +619,7 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp,
 	struct omap3_isp_entity *sink;
 	struct omap3_isp_video *video;
 	struct media_entity_pad *pad;
+	struct v4l2_rect rect;
 	int ret;
 
 	/* Configure formats. Start from the sensor output and propagate the
@@ -632,6 +634,22 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp,
 	else
 		format = *ofmt;
 
+	if (crop) {
+		ret = v4l2_subdev_set_crop(isp->sensor.entity, crop, 0,
+					   V4L2_SUBDEV_FORMAT_TRY);
+		if (ret < 0 && ret != -ENOTTY) {
+			printf("error: set crop on sensor output failed.\n");
+			return ret;
+		}
+	} else {
+		ret = v4l2_subdev_get_crop(isp->sensor.entity, &rect, 0,
+					   V4L2_SUBDEV_FORMAT_TRY);
+		if (ret < 0 && ret != -ENOTTY) {
+			printf("error: get crop on sensor output failed.\n");
+			return ret;
+		}
+	}
+
 	ret = v4l2_subdev_set_format(isp->sensor.entity, &format, 0,
 				     V4L2_SUBDEV_FORMAT_TRY);
 	if (ret < 0) {
@@ -642,6 +660,11 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp,
 	list_for_each_entry(sink, &pipe->entities, list) {
 		if (source == NULL) {
 			source = sink;
+
+			if (crop)
+				source->source.crop = *crop;
+			else
+				source->source.crop = rect;
 			continue;
 		}
 
@@ -769,6 +792,18 @@ static int omap3_isp_pipeline_activate(struct omap3_isp_device *isp,
 		if (source->type == OMAP3_ISP_ENTITY_ENTITY) {
 			pad = source->source.link->source;
 
+			if (first) {
+				struct v4l2_rect crop = source->source.crop;
+
+				ret = v4l2_subdev_set_crop(pad->entity, &crop, pad->index,
+							   V4L2_SUBDEV_FORMAT_ACTIVE);
+				if (ret < 0 && ret != -ENOTTY) {
+					printf("error: set crop failed on %s:%u.\n",
+						pad->entity->info.name, pad->index);
+					return ret;
+				}
+			}
+
 			if (sink->last || first) {
 				format = source->source.format;
 			} else {
@@ -1021,7 +1056,7 @@ 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, ofmt,
+	ret = omap3_isp_pipeline_try_format(isp, &isp->viewfinder, NULL, ofmt,
 					    isp->viewfinder.scaler);
 	if (ret < 0)
 		return ret;
@@ -1078,7 +1113,7 @@ 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, &format,
+	ret = omap3_isp_pipeline_try_format(isp, &isp->viewfinder, NULL, &format,
 					    isp->viewfinder.scaler);
 	if (ret < 0)
 		return ret;
@@ -1124,6 +1159,7 @@ static int omap3_isp_snapshot_setup_pipeline(struct omap3_isp_device *isp)
 }
 
 int omap3_isp_snapshot_setup(struct omap3_isp_device *isp,
+			     struct v4l2_rect *crop,
 			     struct v4l2_mbus_framefmt *ofmt)
 {
 	struct v4l2_video_buffer buffer;
@@ -1154,7 +1190,7 @@ 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, ofmt,
+	ret = omap3_isp_pipeline_try_format(isp, &isp->snapshot, crop, ofmt,
 					    OMAP3_ISP_SCALER_ISP);
 	if (ret < 0)
 		return ret;
diff --git a/isp/omap3isp.h b/isp/omap3isp.h
index db1002e..d454965 100644
--- a/isp/omap3isp.h
+++ b/isp/omap3isp.h
@@ -70,6 +70,7 @@ int omap3_isp_viewfinder_put_buffer(struct omap3_isp_device *isp,
 				    struct v4l2_video_buffer *buffer);
 
 int omap3_isp_snapshot_setup(struct omap3_isp_device *isp,
+			     struct v4l2_rect *crop,
 			     struct v4l2_mbus_framefmt *ofmt);
 int omap3_isp_snapshot_capture(struct omap3_isp_device *isp);
 int omap3_isp_snapshot_put_buffer(struct omap3_isp_device *isp,
-- 
cgit v1.2.3