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

[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
...@@ -1979,6 +1979,76 @@ static int initialize_vpif(void) ...@@ -1979,6 +1979,76 @@ static int initialize_vpif(void)
return err; 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 * vpif_probe : This function probes the vpif capture driver
* @pdev: platform device pointer * @pdev: platform device pointer
...@@ -1989,12 +2059,10 @@ static int initialize_vpif(void) ...@@ -1989,12 +2059,10 @@ static int initialize_vpif(void)
static __init int vpif_probe(struct platform_device *pdev) static __init int vpif_probe(struct platform_device *pdev)
{ {
struct vpif_subdev_info *subdevdata; struct vpif_subdev_info *subdevdata;
struct vpif_capture_config *config; int i, j, err;
int i, j, k, err;
int res_idx = 0; int res_idx = 0;
struct i2c_adapter *i2c_adap; struct i2c_adapter *i2c_adap;
struct channel_obj *ch; struct channel_obj *ch;
struct common_obj *common;
struct video_device *vfd; struct video_device *vfd;
struct resource *res; struct resource *res;
int subdev_count; int subdev_count;
...@@ -2068,10 +2136,9 @@ static __init int vpif_probe(struct platform_device *pdev) ...@@ -2068,10 +2136,9 @@ static __init int vpif_probe(struct platform_device *pdev)
} }
} }
i2c_adap = i2c_get_adapter(1); vpif_obj.config = pdev->dev.platform_data;
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, vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
GFP_KERNEL); GFP_KERNEL);
if (vpif_obj.sd == NULL) { if (vpif_obj.sd == NULL) {
...@@ -2080,54 +2147,42 @@ static __init int vpif_probe(struct platform_device *pdev) ...@@ -2080,54 +2147,42 @@ static __init int vpif_probe(struct platform_device *pdev)
goto vpif_sd_error; goto vpif_sd_error;
} }
for (i = 0; i < subdev_count; i++) { if (!vpif_obj.config->asd_sizes) {
subdevdata = &config->subdev_info[i]; i2c_adap = i2c_get_adapter(1);
vpif_obj.sd[i] = for (i = 0; i < subdev_count; i++) {
v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, subdevdata = &vpif_obj.config->subdev_info[i];
i2c_adap, vpif_obj.sd[i] =
&subdevdata->board_info, v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
NULL); i2c_adap,
&subdevdata->
if (!vpif_obj.sd[i]) { board_info,
vpif_err("Error registering v4l2 subdevice\n"); NULL);
err = -ENODEV;
if (!vpif_obj.sd[i]) {
vpif_err("Error registering v4l2 subdevice\n");
goto probe_subdev_out;
}
v4l2_info(&vpif_obj.v4l2_dev,
"registered sub device %s\n",
subdevdata->name);
}
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; goto probe_subdev_out;
} }
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;
}
v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n");
return 0; 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: probe_subdev_out:
/* free sub devices memory */ /* free sub devices memory */
kfree(vpif_obj.sd); kfree(vpif_obj.sd);
......
...@@ -142,6 +142,8 @@ struct vpif_device { ...@@ -142,6 +142,8 @@ struct vpif_device {
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS]; struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS];
struct v4l2_subdev **sd; struct v4l2_subdev **sd;
struct v4l2_async_notifier notifier;
struct vpif_capture_config *config;
}; };
struct vpif_config_params { struct vpif_config_params {
......
...@@ -81,5 +81,7 @@ struct vpif_capture_config { ...@@ -81,5 +81,7 @@ struct vpif_capture_config {
struct vpif_subdev_info *subdev_info; struct vpif_subdev_info *subdev_info;
int subdev_count; int subdev_count;
const char *card_name; 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 */ #endif /* _VPIF_TYPES_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment