Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 873229e4 authored by Lad, Prabhakar's avatar Lad, Prabhakar Committed by Mauro Carvalho Chehab
Browse files

[media] media: davinci: vpif: capture: add V4L2-async support



Add support for asynchronous subdevice probing, using the v4l2-async API.
The legacy synchronous mode is still supported too, which allows to
gradually update drivers and platforms.

Signed-off-by: default avatarPrabhakar Lad <prabhakar.csengg@gmail.com>
Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Cc: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Sakari Ailus <sakari.ailus@iki.fi>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent 8f23acb5
Loading
Loading
Loading
Loading
+103 −48
Original line number Diff line number Diff line
@@ -1979,6 +1979,76 @@ vpif_init_free_channel_objects:
	return err;
}

static int vpif_async_bound(struct v4l2_async_notifier *notifier,
			    struct v4l2_subdev *subdev,
			    struct v4l2_async_subdev *asd)
{
	int i;

	for (i = 0; i < vpif_obj.config->subdev_count; i++)
		if (!strcmp(vpif_obj.config->subdev_info[i].name,
			    subdev->name)) {
			vpif_obj.sd[i] = subdev;
			return 0;
		}

	return -EINVAL;
}

static int vpif_probe_complete(void)
{
	struct common_obj *common;
	struct channel_obj *ch;
	int i, j, err, k;

	for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
		ch = vpif_obj.dev[j];
		ch->channel_id = j;
		common = &(ch->common[VPIF_VIDEO_INDEX]);
		spin_lock_init(&common->irqlock);
		mutex_init(&common->lock);
		ch->video_dev->lock = &common->lock;
		/* Initialize prio member of channel object */
		v4l2_prio_init(&ch->prio);
		video_set_drvdata(ch->video_dev, ch);

		/* select input 0 */
		err = vpif_set_input(vpif_obj.config, ch, 0);
		if (err)
			goto probe_out;

		err = video_register_device(ch->video_dev,
					    VFL_TYPE_GRABBER, (j ? 1 : 0));
		if (err)
			goto probe_out;
	}

	v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n");
	return 0;

probe_out:
	for (k = 0; k < j; k++) {
		/* Get the pointer to the channel object */
		ch = vpif_obj.dev[k];
		/* Unregister video device */
		video_unregister_device(ch->video_dev);
	}
	kfree(vpif_obj.sd);
	for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
		ch = vpif_obj.dev[i];
		/* Note: does nothing if ch->video_dev == NULL */
		video_device_release(ch->video_dev);
	}
	v4l2_device_unregister(&vpif_obj.v4l2_dev);

	return err;
}

static int vpif_async_complete(struct v4l2_async_notifier *notifier)
{
	return vpif_probe_complete();
}

/**
 * vpif_probe : This function probes the vpif capture driver
 * @pdev: platform device pointer
@@ -1989,12 +2059,10 @@ vpif_init_free_channel_objects:
static __init int vpif_probe(struct platform_device *pdev)
{
	struct vpif_subdev_info *subdevdata;
	struct vpif_capture_config *config;
	int i, j, k, err;
	int i, j, err;
	int res_idx = 0;
	struct i2c_adapter *i2c_adap;
	struct channel_obj *ch;
	struct common_obj *common;
	struct video_device *vfd;
	struct resource *res;
	int subdev_count;
@@ -2068,10 +2136,9 @@ static __init int vpif_probe(struct platform_device *pdev)
		}
	}

	i2c_adap = i2c_get_adapter(1);
	config = pdev->dev.platform_data;
	vpif_obj.config = pdev->dev.platform_data;

	subdev_count = config->subdev_count;
	subdev_count = vpif_obj.config->subdev_count;
	vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
				GFP_KERNEL);
	if (vpif_obj.sd == NULL) {
@@ -2080,54 +2147,42 @@ static __init int vpif_probe(struct platform_device *pdev)
		goto vpif_sd_error;
	}

	if (!vpif_obj.config->asd_sizes) {
		i2c_adap = i2c_get_adapter(1);
		for (i = 0; i < subdev_count; i++) {
		subdevdata = &config->subdev_info[i];
			subdevdata = &vpif_obj.config->subdev_info[i];
			vpif_obj.sd[i] =
				v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
							  i2c_adap,
						  &subdevdata->board_info,
							  &subdevdata->
							  board_info,
							  NULL);

			if (!vpif_obj.sd[i]) {
				vpif_err("Error registering v4l2 subdevice\n");
			err = -ENODEV;
				goto probe_subdev_out;
			}
		v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n",
			v4l2_info(&vpif_obj.v4l2_dev,
				  "registered sub device %s\n",
				   subdevdata->name);
		}

	for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
		ch = vpif_obj.dev[j];
		ch->channel_id = j;
		common = &(ch->common[VPIF_VIDEO_INDEX]);
		spin_lock_init(&common->irqlock);
		mutex_init(&common->lock);
		ch->video_dev->lock = &common->lock;
		/* Initialize prio member of channel object */
		v4l2_prio_init(&ch->prio);
		video_set_drvdata(ch->video_dev, ch);

		/* select input 0 */
		err = vpif_set_input(config, ch, 0);
		if (err)
			goto probe_out;

		err = video_register_device(ch->video_dev,
					    VFL_TYPE_GRABBER, (j ? 1 : 0));
		if (err)
			goto probe_out;
		vpif_probe_complete();
	} else {
		vpif_obj.notifier.subdev = vpif_obj.config->asd;
		vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0];
		vpif_obj.notifier.bound = vpif_async_bound;
		vpif_obj.notifier.complete = vpif_async_complete;
		err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev,
						   &vpif_obj.notifier);
		if (err) {
			vpif_err("Error registering async notifier\n");
			err = -EINVAL;
			goto probe_subdev_out;
		}
	v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n");
	}

	return 0;

probe_out:
	for (k = 0; k < j; k++) {
		/* Get the pointer to the channel object */
		ch = vpif_obj.dev[k];
		/* Unregister video device */
		video_unregister_device(ch->video_dev);
	}
probe_subdev_out:
	/* free sub devices memory */
	kfree(vpif_obj.sd);
+2 −0
Original line number Diff line number Diff line
@@ -142,6 +142,8 @@ struct vpif_device {
	struct v4l2_device v4l2_dev;
	struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS];
	struct v4l2_subdev **sd;
	struct v4l2_async_notifier notifier;
	struct vpif_capture_config *config;
};

struct vpif_config_params {
+2 −0
Original line number Diff line number Diff line
@@ -81,5 +81,7 @@ struct vpif_capture_config {
	struct vpif_subdev_info *subdev_info;
	int subdev_count;
	const char *card_name;
	struct v4l2_async_subdev **asd;	/* Flat array, arranged in groups */
	int *asd_sizes;		/* 0-terminated array of asd group sizes */
};
#endif /* _VPIF_TYPES_H */