Commit 95db3a60 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

[media] v4l: Add a media_device pointer to the v4l2_device structure

The pointer will later be used to register/unregister media entities
when registering/unregistering a v4l2_subdev or a video_device.

With the introduction of media devices, device drivers need to store a
pointer to a driver-specific structure in the device's drvdata.
v4l2_device can't claim ownership of the drvdata anymore.

To maintain compatibility with drivers that rely on v4l2_device storing
a pointer to itself in the device's drvdata, v4l2_device_register() will
keep doing so if the drvdata is NULL.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent e02188c9
...@@ -83,11 +83,17 @@ You must register the device instance: ...@@ -83,11 +83,17 @@ You must register the device instance:
v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
Registration will initialize the v4l2_device struct and link dev->driver_data Registration will initialize the v4l2_device struct. If the dev->driver_data
to v4l2_dev. If v4l2_dev->name is empty then it will be set to a value derived field is NULL, it will be linked to v4l2_dev. Drivers that use the media
from dev (driver name followed by the bus_id, to be precise). If you set it device framework in addition to the V4L2 framework need to set
up before calling v4l2_device_register then it will be untouched. If dev is dev->driver_data manually to point to the driver-specific device structure
NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register. that embed the struct v4l2_device instance. This is achieved by a
dev_set_drvdata() call before registering the V4L2 device instance.
If v4l2_dev->name is empty then it will be set to a value derived from dev
(driver name followed by the bus_id, to be precise). If you set it up before
calling v4l2_device_register then it will be untouched. If dev is NULL, then
you *must* setup v4l2_dev->name before calling v4l2_device_register.
You can use v4l2_device_set_name() to set the name based on a driver name and You can use v4l2_device_set_name() to set the name based on a driver name and
a driver-global atomic_t instance. This will generate names like ivtv0, ivtv1, a driver-global atomic_t instance. This will generate names like ivtv0, ivtv1,
...@@ -108,6 +114,7 @@ You unregister with: ...@@ -108,6 +114,7 @@ You unregister with:
v4l2_device_unregister(struct v4l2_device *v4l2_dev); v4l2_device_unregister(struct v4l2_device *v4l2_dev);
If the dev->driver_data field points to v4l2_dev, it will be reset to NULL.
Unregistering will also automatically unregister all subdevs from the device. Unregistering will also automatically unregister all subdevs from the device.
If you have a hotpluggable device (e.g. a USB device), then when a disconnect If you have a hotpluggable device (e.g. a USB device), then when a disconnect
......
...@@ -47,9 +47,8 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) ...@@ -47,9 +47,8 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
if (!v4l2_dev->name[0]) if (!v4l2_dev->name[0])
snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
dev->driver->name, dev_name(dev)); dev->driver->name, dev_name(dev));
if (dev_get_drvdata(dev)) if (!dev_get_drvdata(dev))
v4l2_warn(v4l2_dev, "Non-NULL drvdata on register\n"); dev_set_drvdata(dev, v4l2_dev);
dev_set_drvdata(dev, v4l2_dev);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(v4l2_device_register); EXPORT_SYMBOL_GPL(v4l2_device_register);
...@@ -72,10 +71,12 @@ EXPORT_SYMBOL_GPL(v4l2_device_set_name); ...@@ -72,10 +71,12 @@ EXPORT_SYMBOL_GPL(v4l2_device_set_name);
void v4l2_device_disconnect(struct v4l2_device *v4l2_dev) void v4l2_device_disconnect(struct v4l2_device *v4l2_dev)
{ {
if (v4l2_dev->dev) { if (v4l2_dev->dev == NULL)
return;
if (dev_get_drvdata(v4l2_dev->dev) == v4l2_dev)
dev_set_drvdata(v4l2_dev->dev, NULL); dev_set_drvdata(v4l2_dev->dev, NULL);
v4l2_dev->dev = NULL; v4l2_dev->dev = NULL;
}
} }
EXPORT_SYMBOL_GPL(v4l2_device_disconnect); EXPORT_SYMBOL_GPL(v4l2_device_disconnect);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#ifndef _V4L2_DEVICE_H #ifndef _V4L2_DEVICE_H
#define _V4L2_DEVICE_H #define _V4L2_DEVICE_H
#include <media/media-device.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
/* Each instance of a V4L2 device should create the v4l2_device struct, /* Each instance of a V4L2 device should create the v4l2_device struct,
...@@ -39,6 +40,9 @@ struct v4l2_device { ...@@ -39,6 +40,9 @@ struct v4l2_device {
Note: dev might be NULL if there is no parent device Note: dev might be NULL if there is no parent device
as is the case with e.g. ISA devices. */ as is the case with e.g. ISA devices. */
struct device *dev; struct device *dev;
#if defined(CONFIG_MEDIA_CONTROLLER)
struct media_device *mdev;
#endif
/* used to keep track of the registered subdevs */ /* used to keep track of the registered subdevs */
struct list_head subdevs; struct list_head subdevs;
/* lock this struct; can be used by the driver as well if this /* lock this struct; can be used by the driver as well if this
......
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