diff options
Diffstat (limited to 'isp/omap3isp.c')
| -rw-r--r-- | isp/omap3isp.c | 127 | 
1 files changed, 111 insertions, 16 deletions
diff --git a/isp/omap3isp.c b/isp/omap3isp.c index 04d69ad..75467e1 100644 --- a/isp/omap3isp.c +++ b/isp/omap3isp.c @@ -187,8 +187,8 @@ static int omap3_isp_pipeline_build(struct omap3_isp_device *isp,  			}  			/* Store link information in source and sink */ -			source->link_source = &source->entity->links[i]; -			sink->link_sink = &source->entity->links[i]; +			source->source.link = &source->entity->links[i]; +			sink->sink.link = &source->entity->links[i];  		}  		list_append(&sink->list, &pipe->entities); @@ -210,6 +210,97 @@ done:  	return ret;  } +static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp, +					 struct omap3_isp_pipeline *pipe, +					 struct v4l2_mbus_framefmt *ofmt, +					 enum omap3_isp_scaler scaler) +{ +	struct v4l2_mbus_framefmt format; +	struct omap3_isp_entity *source = NULL; +	struct omap3_isp_entity *sink; +	struct media_entity_pad *pad; +	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, +				     V4L2_SUBDEV_FORMAT_TRY); +	if (ret < 0) { +		printf("error: get format on sensor output failed.\n"); +		return ret; +	} + +	list_for_each_entry(sink, &pipe->entities, list) { +		if (source == NULL) { +			source = sink; +			continue; +		} + +		if (media_entity_type(sink->entity) == MEDIA_ENT_T_DEVNODE) +			break; + +		/* Try to force the output format code onto the source pad. */ +		pad = source->source.link->source; + +		ret = v4l2_subdev_get_format(pad->entity, &format, pad->index, +					     V4L2_SUBDEV_FORMAT_TRY); +		if (ret < 0) { +			printf("error: get format failed on %s:%u.\n", +				pad->entity->info.name, pad->index); +			return ret; +		} + +		format.code = ofmt->code; +		ret = v4l2_subdev_set_format(pad->entity, &format, pad->index, +					     V4L2_SUBDEV_FORMAT_TRY); +		if (ret < 0) { +			printf("error: set format failed on %s:%u.\n", +				pad->entity->info.name, pad->index); +			return ret; +		} + +		source->source.format = format; + +		/* 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_TRY); +		if (ret < 0) { +			printf("error: set format failed on %s:%u.\n", +				pad->entity->info.name, pad->index); +			return ret; +		} + +		sink->sink.format = format; + +		source = sink; +	} + +	pad = source->source.link->source; + +	ret = v4l2_subdev_set_format(pad->entity, ofmt, pad->index, +				     V4L2_SUBDEV_FORMAT_TRY); +	if (ret < 0) { +		printf("error: set format failed on %s:%u.\n", +			pad->entity->info.name, pad->index); +		return ret; +	} + +	source->source.format = format; +	return 0; +} +  static int omap3_isp_pipeline_activate(struct omap3_isp_device *isp,  				       struct omap3_isp_pipeline *pipe)  { @@ -221,11 +312,11 @@ static int omap3_isp_pipeline_activate(struct omap3_isp_device *isp,  		return ret;  	list_for_each_entry(entity, &pipe->entities, list) { -		if (entity->link_source == NULL) +		if (entity->source.link == NULL)  			break; -		ret = setup_link(isp, entity->link_source->source->entity, -				 entity->link_source->sink->entity, +		ret = setup_link(isp, entity->source.link->source->entity, +				 entity->source.link->sink->entity,  				 MEDIA_LNK_FL_ENABLED);  		if (ret < 0)  			return ret; @@ -467,6 +558,12 @@ int omap3_isp_viewfinder_setup(struct omap3_isp_device *isp,  		return ret;  	} +	/* Try the format. */ +	ret = omap3_isp_pipeline_try_format(isp, &isp->viewfinder, ofmt, +					    isp->viewfinder.output.scaler); +	if (ret < 0) +		return ret; +  	/* Setup the pipeline. */  	ret = omap3_isp_viewfinder_setup_pipeline(isp, ofmt);  	if (ret < 0) @@ -523,13 +620,14 @@ int omap3_isp_viewfinder_set_scaler(struct omap3_isp_device *isp,  	isp->viewfinder.output.scaler = scaler; -	/* If omap3_isp_viewfinder_setup() hasn't been called yet retur now. */ +	/* If omap3_isp_viewfinder_setup() hasn't been called yet return now. */  	if (isp->viewfinder.output.format.width == 0 ||  	    isp->viewfinder.output.format.height == 0)  		return 0;  	format = isp->viewfinder.output.format; -	ret = omap3_isp_viewfinder_setup_pipeline(isp, &format); +	ret = omap3_isp_pipeline_try_format(isp, &isp->viewfinder, &format, +					    isp->viewfinder.output.scaler);  	if (ret < 0)  		return ret; @@ -647,8 +745,7 @@ static int omap3_isp_snapshot_restore_pipeline(struct omap3_isp_device *isp)  }  static int omap3_isp_snapshot_setup_pipeline(struct omap3_isp_device *isp, -					     struct v4l2_mbus_framefmt *ofmt, -					     enum v4l2_subdev_format_whence which) +					     struct v4l2_mbus_framefmt *ofmt)  {  	int ret; @@ -658,7 +755,8 @@ static int omap3_isp_snapshot_setup_pipeline(struct omap3_isp_device *isp,  		return ret;  	/* Configure the formats on the pipeline. */ -	ret = omap3_isp_pipeline_set_format(isp, ofmt, isp->snapshot.output.scaler, which); +	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; @@ -706,16 +804,13 @@ int omap3_isp_snapshot_setup(struct omap3_isp_device *isp,  		return -ENOENT;  	/* Try the format. */ -	ret = omap3_isp_snapshot_setup_pipeline(isp, ofmt, V4L2_SUBDEV_FORMAT_TRY); +	ret = omap3_isp_pipeline_try_format(isp, &isp->snapshot, ofmt, +					    OMAP3_ISP_SCALER_ISP);  	if (ret < 0)  		return ret;  	isp->snapshot.output.format = *ofmt; -	ret = omap3_isp_snapshot_restore_pipeline(isp); -	if (ret < 0) -		return ret; -  	/* Open the V4L2 device. */  	isp->snapshot.output.video = v4l2_open(isp->snapshot.output.node->devname);  	if (isp->snapshot.output.video == NULL) { @@ -831,7 +926,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, V4L2_SUBDEV_FORMAT_ACTIVE); +	ret = omap3_isp_snapshot_setup_pipeline(isp, &format);  	if (ret < 0) {  		printf("error: unable to setup snapshot pipeline.\n");  		return ret;  | 
