diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-subdev.c')
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-subdev.c | 44 | 
1 files changed, 38 insertions, 6 deletions
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index d63083803144..953eab08e420 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -35,9 +35,11 @@  static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd)  {  #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) -	fh->pad = kzalloc(sizeof(*fh->pad) * sd->entity.num_pads, GFP_KERNEL); -	if (fh->pad == NULL) -		return -ENOMEM; +	if (sd->entity.num_pads) { +		fh->pad = v4l2_subdev_alloc_pad_config(sd); +		if (fh->pad == NULL) +			return -ENOMEM; +	}  #endif  	return 0;  } @@ -45,7 +47,7 @@ static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd)  static void subdev_fh_free(struct v4l2_subdev_fh *fh)  {  #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) -	kfree(fh->pad); +	v4l2_subdev_free_pad_config(fh->pad);  	fh->pad = NULL;  #endif  } @@ -508,7 +510,7 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,  	if (source_fmt->format.width != sink_fmt->format.width  	    || source_fmt->format.height != sink_fmt->format.height  	    || source_fmt->format.code != sink_fmt->format.code) -		return -EINVAL; +		return -EPIPE;  	/* The field order must match, or the sink field order must be NONE  	 * to support interlaced hardware connected to bridges that support @@ -516,7 +518,7 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,  	 */  	if (source_fmt->format.field != sink_fmt->format.field &&  	    sink_fmt->format.field != V4L2_FIELD_NONE) -		return -EINVAL; +		return -EPIPE;  	return 0;  } @@ -569,6 +571,35 @@ int v4l2_subdev_link_validate(struct media_link *link)  		sink, link, &source_fmt, &sink_fmt);  }  EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate); + +struct v4l2_subdev_pad_config * +v4l2_subdev_alloc_pad_config(struct v4l2_subdev *sd) +{ +	struct v4l2_subdev_pad_config *cfg; +	int ret; + +	if (!sd->entity.num_pads) +		return NULL; + +	cfg = kcalloc(sd->entity.num_pads, sizeof(*cfg), GFP_KERNEL); +	if (!cfg) +		return NULL; + +	ret = v4l2_subdev_call(sd, pad, init_cfg, cfg); +	if (ret < 0 && ret != -ENOIOCTLCMD) { +		kfree(cfg); +		return NULL; +	} + +	return cfg; +} +EXPORT_SYMBOL_GPL(v4l2_subdev_alloc_pad_config); + +void v4l2_subdev_free_pad_config(struct v4l2_subdev_pad_config *cfg) +{ +	kfree(cfg); +} +EXPORT_SYMBOL_GPL(v4l2_subdev_free_pad_config);  #endif /* CONFIG_MEDIA_CONTROLLER */  void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) @@ -584,6 +615,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)  	sd->host_priv = NULL;  #if defined(CONFIG_MEDIA_CONTROLLER)  	sd->entity.name = sd->name; +	sd->entity.obj_type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV;  	sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;  #endif  }  |