diff options
| -rw-r--r-- | isp/omap3isp-priv.h | 19 | ||||
| -rw-r--r-- | isp/omap3isp.c | 83 | ||||
| -rw-r--r-- | isp/omap3isp.h | 2 | 
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,  | 
