V4L/DVB (11021): v4l2-device: add a notify callback.

Add a notify callback to v4l2_device to let sub-devices notify their
parent of special events.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index df0247e..4207590 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -94,6 +94,11 @@
 with ISA devices or when one device creates multiple PCI devices, thus making
 it impossible to associate v4l2_dev with a particular parent.
 
+You can also supply a notify() callback that can be called by sub-devices to
+notify you of events. Whether you need to set this depends on the sub-device.
+Any notifications a sub-device supports must be defined in a header in
+include/media/<subdevice>.h.
+
 You unregister with:
 
 	v4l2_device_unregister(struct v4l2_device *v4l2_dev);
@@ -281,6 +286,11 @@
 v4l2_device_call_all(). That ensures that it will only go to the subdev
 that needs it.
 
+If the sub-device needs to notify its v4l2_device parent of an event, then
+it can call v4l2_subdev_notify(sd, notification, arg). This macro checks
+whether there is a notify() callback defined and returns -ENODEV if not.
+Otherwise the result of the notify() call is returned.
+
 The advantage of using v4l2_subdev is that it is a generic struct and does
 not contain any knowledge about the underlying hardware. So a driver might
 contain several subdevs that use an I2C bus, but also a subdev that is
diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h
index 5d7146d..3d8e96f 100644
--- a/include/media/v4l2-device.h
+++ b/include/media/v4l2-device.h
@@ -44,6 +44,9 @@
 	spinlock_t lock;
 	/* unique device name, by default the driver name + bus ID */
 	char name[V4L2_DEVICE_NAME_SIZE];
+	/* notify callback called by some sub-devices. */
+	void (*notify)(struct v4l2_subdev *sd,
+			unsigned int notification, void *arg);
 };
 
 /* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev.
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 05b6965..1b97a2c 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -191,4 +191,9 @@
 	(!(sd) ? -ENODEV : (((sd) && (sd)->ops->o && (sd)->ops->o->f) ?	\
 		(sd)->ops->o->f((sd) , ##args) : -ENOIOCTLCMD))
 
+/* Send a notification to v4l2_device. */
+#define v4l2_subdev_notify(sd, notification, arg)			   \
+	((!(sd) || !(sd)->v4l2_dev || !(sd)->v4l2_dev->notify) ? -ENODEV : \
+	 (sd)->v4l2_dev->notify((sd), (notification), (arg)))
+
 #endif