diff options
Diffstat (limited to 'isp')
| -rw-r--r-- | isp/omap3isp.c | 163 | 
1 files changed, 49 insertions, 114 deletions
| diff --git a/isp/omap3isp.c b/isp/omap3isp.c index c41e514..2ee87c5 100644 --- a/isp/omap3isp.c +++ b/isp/omap3isp.c @@ -68,19 +68,6 @@ static int setup_link(struct omap3_isp_device *isp, struct media_entity *source,  	return ret;  } -static struct media_entity_link *entity_output_link(struct media_entity *entity) -{ -	unsigned int i; - -	for (i = 0; i < entity->num_links; ++i) { -		if (entity->links[i].source->entity == entity && -		    entity->links[i].flags & MEDIA_LNK_FL_ENABLED) -			return &entity->links[i]; -	} - -	return NULL; -} -  static struct media_entity *entity_output_node(struct media_entity *entity)  {  	struct media_entity *node; @@ -297,104 +284,87 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp,  		return ret;  	} -	source->source.format = format; +	source->source.format = *ofmt;  	return 0;  }  static int omap3_isp_pipeline_activate(struct omap3_isp_device *isp,  				       struct omap3_isp_pipeline *pipe)  { -	struct omap3_isp_entity *entity; +	struct v4l2_mbus_framefmt format; +	struct omap3_isp_entity *source = NULL; +	struct omap3_isp_entity *sink; +	struct media_entity_pad *pad;  	int ret;  	ret = media_reset_links(isp->mdev);  	if (ret < 0)  		return ret; -	list_for_each_entry(entity, &pipe->entities, list) { -		if (entity->source.link == NULL) -			break; +	list_for_each_entry(sink, &pipe->entities, list) { +		if (source == NULL) { +			format = sink->source.format; +			source = sink; +			continue; +		} -		ret = setup_link(isp, entity->source.link->source->entity, -				 entity->source.link->sink->entity, +		/* Enable the link. */ +		ret = setup_link(isp, source->entity, sink->entity,  				 MEDIA_LNK_FL_ENABLED);  		if (ret < 0)  			return ret; -	} - -	return 0; -} - -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) +		if (media_entity_type(sink->entity) == MEDIA_ENT_T_DEVNODE)  			break; -		entity = link->sink->entity; -		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE) -			break; +		/* Configure formats. +		 * +		 * HACK: The number of columns cropped by the preview engine for +		 * its internal operations requirements depend on whether the +		 * CCDC to preview engine link is enabled or not. This can lead +		 * to inconsistent results if the link state is changed between +		 * trying formats on the pipeline and applying them. For this +		 * reason, instead of blindly applying formats that have been +		 * tried earlier, repropagate them through the pipeline. +		 */ +		pad = source->source.link->source; -		pad = link->source; -		ret = v4l2_subdev_get_format(pad->entity, &format, pad->index, which); +		ret = v4l2_subdev_get_format(pad->entity, &format, pad->index, +					     V4L2_SUBDEV_FORMAT_ACTIVE);  		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); +		format.code = source->source.format.code; +		ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, +					     V4L2_SUBDEV_FORMAT_ACTIVE);  		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); +		/* Propagate the format to the link target. */ +		pad = sink->sink.link->sink; + +		ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, +					     V4L2_SUBDEV_FORMAT_ACTIVE);  		if (ret < 0) {  			printf("error: set format failed on %s:%u.\n",  				pad->entity->info.name, pad->index);  			return ret;  		} + +		source = sink;  	} -	if (ofmt == NULL) -		return 0; +	pad = source->source.link->source; +	format = source->source.format; -	pad = link->source; -	ret = v4l2_subdev_set_format(pad->entity, ofmt, pad->index, which); +	ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, +				     V4L2_SUBDEV_FORMAT_ACTIVE);  	if (ret < 0) {  		printf("error: set format failed on %s:%u.\n",  			pad->entity->info.name, pad->index); @@ -510,24 +480,9 @@ void omap3_isp_close(struct omap3_isp_device *isp)   * Viewfinder   */ -static int omap3_isp_viewfinder_setup_pipeline(struct omap3_isp_device *isp, -					       struct v4l2_mbus_framefmt *ofmt) +static int omap3_isp_viewfinder_setup_pipeline(struct omap3_isp_device *isp)  { -	int ret; - -	ret = omap3_isp_pipeline_activate(isp, &isp->viewfinder); -	if (ret < 0) -		return ret; - -	/* Configure the formats on the pipeline. */ -	ret = omap3_isp_pipeline_set_format(isp, ofmt, isp->viewfinder.output.scaler, -					    V4L2_SUBDEV_FORMAT_ACTIVE); -	if (ret < 0) { -		printf("error: unable to configure formats on pipeline.\n"); -		return ret; -	} - -	return 0; +	return omap3_isp_pipeline_activate(isp, &isp->viewfinder);  }  int omap3_isp_viewfinder_setup(struct omap3_isp_device *isp, @@ -551,7 +506,7 @@ int omap3_isp_viewfinder_setup(struct omap3_isp_device *isp,  		return ret;  	/* Setup the pipeline. */ -	ret = omap3_isp_viewfinder_setup_pipeline(isp, ofmt); +	ret = omap3_isp_viewfinder_setup_pipeline(isp);  	if (ret < 0)  		return ret; @@ -675,7 +630,7 @@ int omap3_isp_viewfinder_start(struct omap3_isp_device *isp)  	ret = v4l2_stream_on(isp->viewfinder.output.video);  	if (ret < 0) { -		printf("error: streamon failed for viewfinder\n"); +		printf("error: streamon failed for viewfinder (%d)\n", ret);  		return ret;  	} @@ -725,25 +680,9 @@ int omap3_isp_viewfinder_put_buffer(struct omap3_isp_device *isp,   * omap3_isp_snapshot_setup() before starting the viewfinder.   */ -static int omap3_isp_snapshot_setup_pipeline(struct omap3_isp_device *isp, -					     struct v4l2_mbus_framefmt *ofmt) +static int omap3_isp_snapshot_setup_pipeline(struct omap3_isp_device *isp)  { -	int ret; - -	/*  Setup the links. */ -	ret = omap3_isp_pipeline_activate(isp, &isp->snapshot); -	if (ret < 0) -		return ret; - -	/* Configure the formats on the pipeline. */ -	ret = omap3_isp_pipeline_set_format(isp, ofmt, isp->snapshot.output.scaler, -					    V4L2_SUBDEV_FORMAT_ACTIVE); -	if (ret < 0) { -		printf("error: unable to configure formats on pipeline.\n"); -		return ret; -	} - -	return 0; +	return omap3_isp_pipeline_activate(isp, &isp->snapshot);  }  int omap3_isp_snapshot_setup(struct omap3_isp_device *isp, @@ -841,7 +780,6 @@ int omap3_isp_snapshot_setup(struct omap3_isp_device *isp,  static void omap3_isp_snapshot_event(void *priv)  {  	struct omap3_isp_device *isp = priv; -	struct v4l2_mbus_framefmt format;  	struct v4l2_video_buffer buffer;  	unsigned int i;  	int ret; @@ -866,8 +804,7 @@ static void omap3_isp_snapshot_event(void *priv)  	isp->ops->snapshot_ready(isp, &buffer);  	/* Resume the viewfinder. */ -	format = isp->viewfinder.output.format; -	ret = omap3_isp_viewfinder_setup_pipeline(isp, &format); +	ret = omap3_isp_viewfinder_setup_pipeline(isp);  	if (ret < 0)  		return; @@ -891,7 +828,6 @@ static void omap3_isp_snapshot_event(void *priv)  int omap3_isp_snapshot_capture(struct omap3_isp_device *isp)  { -	struct v4l2_mbus_framefmt format;  	int ret;  	/* Suspend the viewfinder. */ @@ -902,8 +838,7 @@ int omap3_isp_snapshot_capture(struct omap3_isp_device *isp)  	}  	/* Configure the pipeline. */ -	format = isp->snapshot.output.format; -	ret = omap3_isp_snapshot_setup_pipeline(isp, &format); +	ret = omap3_isp_snapshot_setup_pipeline(isp);  	if (ret < 0) {  		printf("error: unable to setup snapshot pipeline.\n");  		return ret; | 
