* [PATCH RFC v2 1/4] media: i2c: adv7343: add support for asynchronous probing
2013-04-22 10:17 [PATCH RFC v2 0/4] media: davinci: vpif: capture/display support for async subdevice probing Prabhakar Lad
@ 2013-04-22 10:17 ` Prabhakar Lad
2013-04-22 10:38 ` Guennadi Liakhovetski
2013-04-22 10:17 ` [PATCH RFC v2 2/4] media: i2c: tvp514x: " Prabhakar Lad
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Prabhakar Lad @ 2013-04-22 10:17 UTC (permalink / raw)
To: LMML
Cc: DLOS, LKML, Lad, Prabhakar, Guennadi Liakhovetski,
Laurent Pinchart, Hans Verkuil, Sakari Ailus,
Mauro Carvalho Chehab
From: Lad, Prabhakar <prabhakar.csengg@gmail.com>
Both synchronous and asynchronous adv7343 subdevice probing is supported by
this patch.
Signed-off-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>
Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Cc: Sakari Ailus <sakari.ailus@iki.fi>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
---
drivers/media/i2c/adv7343.c | 17 +++++++++++++----
1 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c
index 9fc2b98..5b1417b 100644
--- a/drivers/media/i2c/adv7343.c
+++ b/drivers/media/i2c/adv7343.c
@@ -27,6 +27,7 @@
#include <linux/uaccess.h>
#include <media/adv7343.h>
+#include <media/v4l2-async.h>
#include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h>
@@ -44,6 +45,7 @@ struct adv7343_state {
struct v4l2_subdev sd;
struct v4l2_ctrl_handler hdl;
const struct adv7343_platform_data *pdata;
+ struct v4l2_async_subdev_list asdl;
u8 reg00;
u8 reg01;
u8 reg02;
@@ -455,16 +457,22 @@ static int adv7343_probe(struct i2c_client *client,
ADV7343_GAIN_DEF);
state->sd.ctrl_handler = &state->hdl;
if (state->hdl.error) {
- int err = state->hdl.error;
-
- v4l2_ctrl_handler_free(&state->hdl);
- return err;
+ err = state->hdl.error;
+ goto done;
}
v4l2_ctrl_handler_setup(&state->hdl);
err = adv7343_initialize(&state->sd);
if (err)
+ goto done;
+
+ state->sd.dev = &client->dev;
+ err = v4l2_async_register_subdev(&state->sd);
+
+done:
+ if (err < 0)
v4l2_ctrl_handler_free(&state->hdl);
+
return err;
}
@@ -473,6 +481,7 @@ static int adv7343_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct adv7343_state *state = to_state(sd);
+ v4l2_async_unregister_subdev(&state->sd);
v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(&state->hdl);
--
1.7.4.1
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH RFC v2 1/4] media: i2c: adv7343: add support for asynchronous probing
2013-04-22 10:17 ` [PATCH RFC v2 1/4] media: i2c: adv7343: add support for asynchronous probing Prabhakar Lad
@ 2013-04-22 10:38 ` Guennadi Liakhovetski
2013-04-22 10:41 ` Prabhakar Lad
0 siblings, 1 reply; 7+ messages in thread
From: Guennadi Liakhovetski @ 2013-04-22 10:38 UTC (permalink / raw)
To: Prabhakar Lad
Cc: LMML, DLOS, LKML, Laurent Pinchart, Hans Verkuil, Sakari Ailus,
Mauro Carvalho Chehab
Hi Prabhakar
On Mon, 22 Apr 2013, Prabhakar Lad wrote:
> From: Lad, Prabhakar <prabhakar.csengg@gmail.com>
>
> Both synchronous and asynchronous adv7343 subdevice probing is supported by
> this patch.
>
> Signed-off-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>
> Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Cc: Hans Verkuil <hverkuil@xs4all.nl>
> Cc: Sakari Ailus <sakari.ailus@iki.fi>
> Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
> ---
> drivers/media/i2c/adv7343.c | 17 +++++++++++++----
> 1 files changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c
> index 9fc2b98..5b1417b 100644
> --- a/drivers/media/i2c/adv7343.c
> +++ b/drivers/media/i2c/adv7343.c
> @@ -27,6 +27,7 @@
> #include <linux/uaccess.h>
>
> #include <media/adv7343.h>
> +#include <media/v4l2-async.h>
> #include <media/v4l2-device.h>
> #include <media/v4l2-chip-ident.h>
> #include <media/v4l2-ctrls.h>
> @@ -44,6 +45,7 @@ struct adv7343_state {
> struct v4l2_subdev sd;
> struct v4l2_ctrl_handler hdl;
> const struct adv7343_platform_data *pdata;
> + struct v4l2_async_subdev_list asdl;
Do you still need this? Don't think it's needed any more with the latest
V4L2-async version.
Thanks
Guennadi
> u8 reg00;
> u8 reg01;
> u8 reg02;
> @@ -455,16 +457,22 @@ static int adv7343_probe(struct i2c_client *client,
> ADV7343_GAIN_DEF);
> state->sd.ctrl_handler = &state->hdl;
> if (state->hdl.error) {
> - int err = state->hdl.error;
> -
> - v4l2_ctrl_handler_free(&state->hdl);
> - return err;
> + err = state->hdl.error;
> + goto done;
> }
> v4l2_ctrl_handler_setup(&state->hdl);
>
> err = adv7343_initialize(&state->sd);
> if (err)
> + goto done;
> +
> + state->sd.dev = &client->dev;
> + err = v4l2_async_register_subdev(&state->sd);
> +
> +done:
> + if (err < 0)
> v4l2_ctrl_handler_free(&state->hdl);
> +
> return err;
> }
>
> @@ -473,6 +481,7 @@ static int adv7343_remove(struct i2c_client *client)
> struct v4l2_subdev *sd = i2c_get_clientdata(client);
> struct adv7343_state *state = to_state(sd);
>
> + v4l2_async_unregister_subdev(&state->sd);
> v4l2_device_unregister_subdev(sd);
> v4l2_ctrl_handler_free(&state->hdl);
>
> --
> 1.7.4.1
>
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH RFC v2 1/4] media: i2c: adv7343: add support for asynchronous probing
2013-04-22 10:38 ` Guennadi Liakhovetski
@ 2013-04-22 10:41 ` Prabhakar Lad
0 siblings, 0 replies; 7+ messages in thread
From: Prabhakar Lad @ 2013-04-22 10:41 UTC (permalink / raw)
To: Guennadi Liakhovetski
Cc: LMML, DLOS, LKML, Laurent Pinchart, Hans Verkuil, Sakari Ailus,
Mauro Carvalho Chehab
Hi Guennadi,
Thanks for the quick review.
On Mon, Apr 22, 2013 at 4:08 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> Hi Prabhakar
>
> On Mon, 22 Apr 2013, Prabhakar Lad wrote:
>
>> From: Lad, Prabhakar <prabhakar.csengg@gmail.com>
>>
>> Both synchronous and asynchronous adv7343 subdevice probing is supported by
>> this patch.
>>
>> Signed-off-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>
>> Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
>> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> Cc: Hans Verkuil <hverkuil@xs4all.nl>
>> Cc: Sakari Ailus <sakari.ailus@iki.fi>
>> Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
>> ---
>> drivers/media/i2c/adv7343.c | 17 +++++++++++++----
>> 1 files changed, 13 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c
>> index 9fc2b98..5b1417b 100644
>> --- a/drivers/media/i2c/adv7343.c
>> +++ b/drivers/media/i2c/adv7343.c
>> @@ -27,6 +27,7 @@
>> #include <linux/uaccess.h>
>>
>> #include <media/adv7343.h>
>> +#include <media/v4l2-async.h>
>> #include <media/v4l2-device.h>
>> #include <media/v4l2-chip-ident.h>
>> #include <media/v4l2-ctrls.h>
>> @@ -44,6 +45,7 @@ struct adv7343_state {
>> struct v4l2_subdev sd;
>> struct v4l2_ctrl_handler hdl;
>> const struct adv7343_platform_data *pdata;
>> + struct v4l2_async_subdev_list asdl;
>
> Do you still need this? Don't think it's needed any more with the latest
> V4L2-async version.
>
Yes not required missed to remove :)
Regards,
--Prabhakar
> Thanks
> Guennadi
>
>> u8 reg00;
>> u8 reg01;
>> u8 reg02;
>> @@ -455,16 +457,22 @@ static int adv7343_probe(struct i2c_client *client,
>> ADV7343_GAIN_DEF);
>> state->sd.ctrl_handler = &state->hdl;
>> if (state->hdl.error) {
>> - int err = state->hdl.error;
>> -
>> - v4l2_ctrl_handler_free(&state->hdl);
>> - return err;
>> + err = state->hdl.error;
>> + goto done;
>> }
>> v4l2_ctrl_handler_setup(&state->hdl);
>>
>> err = adv7343_initialize(&state->sd);
>> if (err)
>> + goto done;
>> +
>> + state->sd.dev = &client->dev;
>> + err = v4l2_async_register_subdev(&state->sd);
>> +
>> +done:
>> + if (err < 0)
>> v4l2_ctrl_handler_free(&state->hdl);
>> +
>> return err;
>> }
>>
>> @@ -473,6 +481,7 @@ static int adv7343_remove(struct i2c_client *client)
>> struct v4l2_subdev *sd = i2c_get_clientdata(client);
>> struct adv7343_state *state = to_state(sd);
>>
>> + v4l2_async_unregister_subdev(&state->sd);
>> v4l2_device_unregister_subdev(sd);
>> v4l2_ctrl_handler_free(&state->hdl);
>>
>> --
>> 1.7.4.1
>>
>
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
> http://www.open-technology.de/
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH RFC v2 2/4] media: i2c: tvp514x: add support for asynchronous probing
2013-04-22 10:17 [PATCH RFC v2 0/4] media: davinci: vpif: capture/display support for async subdevice probing Prabhakar Lad
2013-04-22 10:17 ` [PATCH RFC v2 1/4] media: i2c: adv7343: add support for asynchronous probing Prabhakar Lad
@ 2013-04-22 10:17 ` Prabhakar Lad
2013-04-22 10:17 ` [PATCH RFC v2 3/4] media: davinci: vpif: capture: add V4L2-async support Prabhakar Lad
2013-04-22 10:17 ` [PATCH RFC v2 4/4] media: davinci: vpif: display: " Prabhakar Lad
3 siblings, 0 replies; 7+ messages in thread
From: Prabhakar Lad @ 2013-04-22 10:17 UTC (permalink / raw)
To: LMML
Cc: DLOS, LKML, Lad, Prabhakar, Lad, Prabhakar,
Guennadi Liakhovetski, Laurent Pinchart, Hans Verkuil,
Sakari Ailus, Mauro Carvalho Chehab
From: Lad, Prabhakar <prabhakar.csengg@gmail.com>
Both synchronous and asynchronous tvp514x subdevice probing is supported by
this patch.
Signed-off-by: Lad, Prabhakar <prabhakar.lad@ti.com>
Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Cc: Sakari Ailus <sakari.ailus@iki.fi>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
---
drivers/media/i2c/tvp514x.c | 23 ++++++++++++++++-------
1 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c
index ab8f3fe..887bd93 100644
--- a/drivers/media/i2c/tvp514x.c
+++ b/drivers/media/i2c/tvp514x.c
@@ -36,6 +36,7 @@
#include <linux/module.h>
#include <linux/v4l2-mediabus.h>
+#include <media/v4l2-async.h>
#include <media/v4l2-device.h>
#include <media/v4l2-common.h>
#include <media/v4l2-mediabus.h>
@@ -1109,9 +1110,9 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
/* Register with V4L2 layer as slave device */
sd = &decoder->sd;
v4l2_i2c_subdev_init(sd, client, &tvp514x_ops);
- strlcpy(sd->name, TVP514X_MODULE_NAME, sizeof(sd->name));
#if defined(CONFIG_MEDIA_CONTROLLER)
+ strlcpy(sd->name, TVP514X_MODULE_NAME, sizeof(sd->name));
decoder->pad.flags = MEDIA_PAD_FL_SOURCE;
decoder->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
decoder->sd.entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER;
@@ -1138,16 +1139,23 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
sd->ctrl_handler = &decoder->hdl;
if (decoder->hdl.error) {
ret = decoder->hdl.error;
-
- v4l2_ctrl_handler_free(&decoder->hdl);
- return ret;
+ goto done;
}
v4l2_ctrl_handler_setup(&decoder->hdl);
- v4l2_info(sd, "%s decoder driver registered !!\n", sd->name);
-
- return 0;
+ decoder->sd.dev = &client->dev;
+ ret = v4l2_async_register_subdev(&decoder->sd);
+ if (!ret)
+ v4l2_info(sd, "%s decoder driver registered !!\n", sd->name);
+done:
+ if (ret < 0) {
+ v4l2_ctrl_handler_free(&decoder->hdl);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+ media_entity_cleanup(&decoder->sd.entity);
+#endif
+ }
+ return ret;
}
/**
@@ -1162,6 +1170,7 @@ static int tvp514x_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct tvp514x_decoder *decoder = to_decoder(sd);
+ v4l2_async_unregister_subdev(&decoder->sd);
v4l2_device_unregister_subdev(sd);
#if defined(CONFIG_MEDIA_CONTROLLER)
media_entity_cleanup(&decoder->sd.entity);
--
1.7.4.1
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH RFC v2 3/4] media: davinci: vpif: capture: add V4L2-async support
2013-04-22 10:17 [PATCH RFC v2 0/4] media: davinci: vpif: capture/display support for async subdevice probing Prabhakar Lad
2013-04-22 10:17 ` [PATCH RFC v2 1/4] media: i2c: adv7343: add support for asynchronous probing Prabhakar Lad
2013-04-22 10:17 ` [PATCH RFC v2 2/4] media: i2c: tvp514x: " Prabhakar Lad
@ 2013-04-22 10:17 ` Prabhakar Lad
2013-04-22 10:17 ` [PATCH RFC v2 4/4] media: davinci: vpif: display: " Prabhakar Lad
3 siblings, 0 replies; 7+ messages in thread
From: Prabhakar Lad @ 2013-04-22 10:17 UTC (permalink / raw)
To: LMML
Cc: DLOS, LKML, Lad, Prabhakar, Guennadi Liakhovetski, Hans Verkuil,
Laurent Pinchart, Sakari Ailus, Mauro Carvalho Chehab
From: Lad, Prabhakar <prabhakar.csengg@gmail.com>
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: Prabhakar 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>
---
drivers/media/platform/davinci/vpif_capture.c | 151 +++++++++++++++++--------
drivers/media/platform/davinci/vpif_capture.h | 2 +
include/media/davinci/vpif_types.h | 2 +
3 files changed, 108 insertions(+), 47 deletions(-)
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index a1b42b0..d723b58 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <media/v4l2-async.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ioctl.h>
@@ -2045,6 +2046,76 @@ vpif_init_free_channel_objects:
return err;
}
+static int vpif_async_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_async_subdev_list *asdl)
+{
+ struct v4l2_subdev *subdev = v4l2_async_to_subdev(asdl);
+ int i = 0;
+
+ 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
@@ -2055,12 +2126,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;
@@ -2137,10 +2206,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) {
@@ -2149,53 +2217,42 @@ static __init int vpif_probe(struct platform_device *pdev)
goto vpif_sd_error;
}
- for (i = 0; i < subdev_count; i++) {
- subdevdata = &config->subdev_info[i];
- vpif_obj.sd[i] =
- v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
- i2c_adap,
- &subdevdata->board_info,
- NULL);
-
- if (!vpif_obj.sd[i]) {
- vpif_err("Error registering v4l2 subdevice\n");
+ if (!vpif_obj.config->asd_sizes) {
+ i2c_adap = i2c_get_adapter(1);
+ for (i = 0; i < subdev_count; 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,
+ NULL);
+
+ 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.subdev_num = 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, "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;
-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);
diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h
index 0ebb312..5a29d9a 100644
--- a/drivers/media/platform/davinci/vpif_capture.h
+++ b/drivers/media/platform/davinci/vpif_capture.h
@@ -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 {
diff --git a/include/media/davinci/vpif_types.h b/include/media/davinci/vpif_types.h
index 3882e06..e08bcde 100644
--- a/include/media/davinci/vpif_types.h
+++ b/include/media/davinci/vpif_types.h
@@ -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 */
--
1.7.4.1
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH RFC v2 4/4] media: davinci: vpif: display: add V4L2-async support
2013-04-22 10:17 [PATCH RFC v2 0/4] media: davinci: vpif: capture/display support for async subdevice probing Prabhakar Lad
` (2 preceding siblings ...)
2013-04-22 10:17 ` [PATCH RFC v2 3/4] media: davinci: vpif: capture: add V4L2-async support Prabhakar Lad
@ 2013-04-22 10:17 ` Prabhakar Lad
3 siblings, 0 replies; 7+ messages in thread
From: Prabhakar Lad @ 2013-04-22 10:17 UTC (permalink / raw)
To: LMML
Cc: DLOS, LKML, Lad, Prabhakar, Guennadi Liakhovetski, Hans Verkuil,
Laurent Pinchart, Sakari Ailus, Mauro Carvalho Chehab
From: Lad, Prabhakar <prabhakar.csengg@gmail.com>
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: Lad, Prabhakar <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>
---
drivers/media/platform/davinci/vpif_display.c | 219 +++++++++++++++----------
drivers/media/platform/davinci/vpif_display.h | 3 +-
include/media/davinci/vpif_types.h | 2 +
3 files changed, 136 insertions(+), 88 deletions(-)
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index 7b17368..4f53730 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <media/v4l2-async.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ioctl.h>
@@ -1684,6 +1685,105 @@ vpif_init_free_channel_objects:
return err;
}
+static int vpif_async_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_async_subdev_list *asdl)
+{
+ struct v4l2_subdev *subdev = v4l2_async_to_subdev(asdl);
+ int i = 0;
+
+ for (i = 0; i < vpif_obj.config->subdev_count; i++)
+ if (!strcmp(vpif_obj.config->subdevinfo[i].name,
+ subdev->name)) {
+ vpif_obj.sd[i] = subdev;
+ vpif_obj.sd[i]->grp_id = 1 << i;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int vpif_probe_complete(void)
+{
+ struct common_obj *common;
+ struct channel_obj *ch;
+ int j, err, k;
+
+ for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
+ ch = vpif_obj.dev[j];
+ /* Initialize field of the channel objects */
+ atomic_set(&ch->usrs, 0);
+ for (k = 0; k < VPIF_NUMOBJECTS; k++) {
+ ch->common[k].numbuffers = 0;
+ common = &ch->common[k];
+ common->io_usrs = 0;
+ common->started = 0;
+ spin_lock_init(&common->irqlock);
+ mutex_init(&common->lock);
+ common->numbuffers = 0;
+ common->set_addr = NULL;
+ common->ytop_off = 0;
+ common->ybtm_off = 0;
+ common->ctop_off = 0;
+ common->cbtm_off = 0;
+ common->cur_frm = NULL;
+ common->next_frm = NULL;
+ memset(&common->fmt, 0, sizeof(common->fmt));
+ common->numbuffers = config_params.numbuffers[k];
+ }
+ ch->initialized = 0;
+ if (vpif_obj.config->subdev_count)
+ ch->sd = vpif_obj.sd[0];
+ ch->channel_id = j;
+ if (j < 2)
+ ch->common[VPIF_VIDEO_INDEX].numbuffers =
+ config_params.numbuffers[ch->channel_id];
+ else
+ ch->common[VPIF_VIDEO_INDEX].numbuffers = 0;
+
+ memset(&ch->vpifparams, 0, sizeof(ch->vpifparams));
+
+ /* Initialize prio member of channel object */
+ v4l2_prio_init(&ch->prio);
+ ch->common[VPIF_VIDEO_INDEX].fmt.type =
+ V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ ch->video_dev->lock = &common->lock;
+ video_set_drvdata(ch->video_dev, ch);
+
+ /* select output 0 */
+ err = vpif_set_output(vpif_obj.config, ch, 0);
+ if (err)
+ goto probe_out;
+
+ /* register video device */
+ vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
+ (int)ch, (int)&ch->video_dev);
+
+ err = video_register_device(ch->video_dev,
+ VFL_TYPE_GRABBER, (j ? 3 : 2));
+ if (err < 0)
+ goto probe_out;
+ }
+
+ v4l2_info(&vpif_obj.v4l2_dev,
+ "VPIF display driver initialized\n");
+
+ return 0;
+
+probe_out:
+ for (k = 0; k < j; k++) {
+ ch = vpif_obj.dev[k];
+ video_unregister_device(ch->video_dev);
+ video_device_release(ch->video_dev);
+ ch->video_dev = NULL;
+ }
+ return err;
+}
+
+static int vpif_async_complete(struct v4l2_async_notifier *notifier)
+{
+ return vpif_probe_complete();
+}
+
/*
* vpif_probe: This function creates device entries by register itself to the
* V4L2 driver and initializes fields of each channel objects
@@ -1691,11 +1791,9 @@ vpif_init_free_channel_objects:
static __init int vpif_probe(struct platform_device *pdev)
{
struct vpif_subdev_info *subdevdata;
- struct vpif_display_config *config;
- int i, j = 0, k, err = 0;
+ int i, j = 0, err = 0;
int res_idx = 0;
struct i2c_adapter *i2c_adap;
- struct common_obj *common;
struct channel_obj *ch;
struct video_device *vfd;
struct resource *res;
@@ -1704,18 +1802,15 @@ static __init int vpif_probe(struct platform_device *pdev)
vpif_dev = &pdev->dev;
err = initialize_vpif();
-
if (err) {
v4l2_err(vpif_dev->driver, "Error initializing vpif\n");
return err;
}
-
err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
if (err) {
v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");
return err;
}
-
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {
for (i = res->start; i <= res->end; i++) {
if (request_irq(i, vpif_channel_isr, IRQF_SHARED,
@@ -1731,7 +1826,6 @@ static __init int vpif_probe(struct platform_device *pdev)
}
res_idx++;
}
-
for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
/* Get the pointer to the channel object */
ch = vpif_obj.dev[i];
@@ -1759,7 +1853,6 @@ static __init int vpif_probe(struct platform_device *pdev)
/* Set video_dev to the video device */
ch->video_dev = vfd;
}
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res) {
size = resource_size(res);
@@ -1777,11 +1870,9 @@ static __init int vpif_probe(struct platform_device *pdev)
size/2;
}
}
-
- i2c_adap = i2c_get_adapter(1);
- config = pdev->dev.platform_data;
- subdev_count = config->subdev_count;
- subdevdata = config->subdevinfo;
+ vpif_obj.config = pdev->dev.platform_data;
+ subdev_count = vpif_obj.config->subdev_count;
+ subdevdata = vpif_obj.config->subdevinfo;
vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
GFP_KERNEL);
if (vpif_obj.sd == NULL) {
@@ -1790,85 +1881,39 @@ static __init int vpif_probe(struct platform_device *pdev)
goto vpif_sd_error;
}
- for (i = 0; i < subdev_count; i++) {
- vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
- i2c_adap,
- &subdevdata[i].board_info,
- NULL);
- if (!vpif_obj.sd[i]) {
- vpif_err("Error registering v4l2 subdevice\n");
- goto probe_subdev_out;
- }
-
- if (vpif_obj.sd[i])
- vpif_obj.sd[i]->grp_id = 1 << i;
- }
-
- for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
- ch = vpif_obj.dev[j];
- /* Initialize field of the channel objects */
- atomic_set(&ch->usrs, 0);
- for (k = 0; k < VPIF_NUMOBJECTS; k++) {
- ch->common[k].numbuffers = 0;
- common = &ch->common[k];
- common->io_usrs = 0;
- common->started = 0;
- spin_lock_init(&common->irqlock);
- mutex_init(&common->lock);
- common->numbuffers = 0;
- common->set_addr = NULL;
- common->ytop_off = common->ybtm_off = 0;
- common->ctop_off = common->cbtm_off = 0;
- common->cur_frm = common->next_frm = NULL;
- memset(&common->fmt, 0, sizeof(common->fmt));
- common->numbuffers = config_params.numbuffers[k];
+ if (!vpif_obj.config->asd_sizes) {
+ i2c_adap = i2c_get_adapter(1);
+ for (i = 0; i < subdev_count; i++) {
+ vpif_obj.sd[i] =
+ v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
+ i2c_adap,
+ &subdevdata[i].
+ board_info,
+ NULL);
+ if (!vpif_obj.sd[i]) {
+ vpif_err("Error registering v4l2 subdevice\n");
+ goto probe_subdev_out;
+ }
+ if (vpif_obj.sd[i])
+ vpif_obj.sd[i]->grp_id = 1 << i;
+ }
+ vpif_probe_complete();
+ } else {
+ vpif_obj.notifier.subdev = vpif_obj.config->asd;
+ vpif_obj.notifier.subdev_num = 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;
}
- ch->initialized = 0;
- if (subdev_count)
- ch->sd = vpif_obj.sd[0];
- ch->channel_id = j;
- if (j < 2)
- ch->common[VPIF_VIDEO_INDEX].numbuffers =
- config_params.numbuffers[ch->channel_id];
- else
- ch->common[VPIF_VIDEO_INDEX].numbuffers = 0;
-
- memset(&ch->vpifparams, 0, sizeof(ch->vpifparams));
-
- /* Initialize prio member of channel object */
- v4l2_prio_init(&ch->prio);
- ch->common[VPIF_VIDEO_INDEX].fmt.type =
- V4L2_BUF_TYPE_VIDEO_OUTPUT;
- ch->video_dev->lock = &common->lock;
- video_set_drvdata(ch->video_dev, ch);
-
- /* select output 0 */
- err = vpif_set_output(config, ch, 0);
- if (err)
- goto probe_out;
-
- /* register video device */
- vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
- (int)ch, (int)&ch->video_dev);
-
- err = video_register_device(ch->video_dev,
- VFL_TYPE_GRABBER, (j ? 3 : 2));
- if (err < 0)
- goto probe_out;
}
-
- v4l2_info(&vpif_obj.v4l2_dev,
- " VPIF display driver initialized\n");
return 0;
-probe_out:
- for (k = 0; k < j; k++) {
- ch = vpif_obj.dev[k];
- video_unregister_device(ch->video_dev);
- video_device_release(ch->video_dev);
- ch->video_dev = NULL;
- }
probe_subdev_out:
kfree(vpif_obj.sd);
vpif_sd_error:
diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h
index 5d87fc8..4d0485b 100644
--- a/drivers/media/platform/davinci/vpif_display.h
+++ b/drivers/media/platform/davinci/vpif_display.h
@@ -148,7 +148,8 @@ struct vpif_device {
struct v4l2_device v4l2_dev;
struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS];
struct v4l2_subdev **sd;
-
+ struct v4l2_async_notifier notifier;
+ struct vpif_display_config *config;
};
struct vpif_config_params {
diff --git a/include/media/davinci/vpif_types.h b/include/media/davinci/vpif_types.h
index e08bcde..3cb1704 100644
--- a/include/media/davinci/vpif_types.h
+++ b/include/media/davinci/vpif_types.h
@@ -59,6 +59,8 @@ struct vpif_display_config {
int subdev_count;
struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS];
const char *card_name;
+ struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */
+ int *asd_sizes; /* 0-terminated array of asd group sizes */
};
struct vpif_input {
--
1.7.4.1
^ permalink raw reply [flat|nested] 7+ messages in thread