summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: f9e942c)
raw | patch | inline | side by side (parent: f9e942c)
author | Koen Kooi <koen@dominion.thruhere.net> | |
Thu, 10 Mar 2011 14:14:42 +0000 (15:14 +0100) | ||
committer | Koen Kooi <koen@dominion.thruhere.net> | |
Thu, 10 Mar 2011 14:14:42 +0000 (15:14 +0100) |
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
48 files changed:
diff --git a/recipes-bsp/linux/linux-omap/0001-BeagleBoard-Adjust-USER-button-pin-for-xM.patch b/recipes-bsp/linux/linux-omap/0001-BeagleBoard-Adjust-USER-button-pin-for-xM.patch
--- /dev/null
@@ -0,0 +1,29 @@
+From 3b1dc08ab568d1fdbc2a3731d7643cfeb48023e8 Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 10 Mar 2011 14:16:08 +0100
+Subject: [PATCH] BeagleBoard: Adjust USER button pin for xM
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 5 +++++
+ 1 files changed, 5 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 731f4b5..fae3104 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -949,6 +949,11 @@ static void __init omap3_beagle_init(void)
+ omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+ omap3_beagle_init_rev();
+ omap3_beagle_i2c_init();
++
++ if (cpu_is_omap3630()) {
++ gpio_buttons[0].gpio = 4;
++ }
++
+ platform_add_devices(omap3_beagle_devices,
+ ARRAY_SIZE(omap3_beagle_devices));
+ omap_serial_init();
+--
+1.7.0
+
diff --git a/recipes-bsp/linux/linux-omap/0001-beagleboard-hack-in-support-from-xM-rev-C.patch b/recipes-bsp/linux/linux-omap/0001-beagleboard-hack-in-support-from-xM-rev-C.patch
--- /dev/null
@@ -0,0 +1,94 @@
+From d9c289c5f98bb109aa7a9e5a802638ba89639e70 Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 10 Mar 2011 13:15:38 +0100
+Subject: [PATCH] beagleboard: hack in support from xM rev C
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 20 +++++++++++++-------
+ 1 files changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 6abb79a..731f4b5 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -64,6 +64,7 @@
+ * C4 = GPIO173, GPIO172, GPIO171: 1 0 1
+ * XMA = GPIO173, GPIO172, GPIO171: 0 0 0
+ * XMB = GPIO173, GPIO172, GPIO171: 0 0 1
++ * XMC = GPIO173, GPIO172, GPIO171: 0 1 0
+ */
+ enum {
+ OMAP3BEAGLE_BOARD_UNKN = 0,
+@@ -71,6 +72,7 @@ enum {
+ OMAP3BEAGLE_BOARD_C1_3,
+ OMAP3BEAGLE_BOARD_C4,
+ OMAP3BEAGLE_BOARD_XM,
++ OMAP3BEAGLE_BOARD_XMC,
+ };
+
+ static u8 omap3_beagle_version;
+@@ -129,9 +131,13 @@ static void __init omap3_beagle_init_rev(void)
+ printk(KERN_INFO "OMAP3 Beagle Rev: xM B\n");
+ omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
+ break;
++ case 2:
++ printk(KERN_INFO "OMAP3 Beagle Rev: xM C\n");
++ omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
++ break;
+ default:
+- printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
+- omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
++ printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd, assuming xM C or newer\n", beagle_rev);
++ omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
+ }
+
+ return;
+@@ -484,7 +490,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
+ {
+ int r;
+
+- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
++ if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) {
+ mmc[0].gpio_wp = -EINVAL;
+ } else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
+ (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) {
+@@ -517,7 +523,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
+ /* REVISIT: need ehci-omap hooks for external VBUS
+ * power switch and overcurrent detect
+ */
+- if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM) {
++ if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM && omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XMC) {
+ r = gpio_request(gpio + 1, "EHCI_nOC");
+ if (!r) {
+ r = gpio_direction_input(gpio + 1);
+@@ -539,7 +545,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
+ gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
+
+ /* DVI reset GPIO is different between beagle revisions */
+- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM)
++ if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC)
+ beagle_dvi_device.reset_gpio = 129;
+ else
+ beagle_dvi_device.reset_gpio = 170;
+@@ -553,7 +559,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
+ * P7/P8 revisions(prototype): Camera EN
+ * A2+ revisions (production): LDO (supplies DVI, serial, led blocks)
+ */
+- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
++ if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) {
+ r = gpio_request(gpio + 1, "nDVI_PWR_EN");
+ if (!r) {
+ r = gpio_direction_output(gpio + 1, 0);
+@@ -899,7 +905,7 @@ static void __init beagle_opp_init(void)
+ }
+
+ /* Custom OPP enabled for XM */
+- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
++ if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) {
+ struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
+ struct omap_hwmod *dh = omap_hwmod_lookup("iva");
+ struct device *dev;
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/0001-omap3-allow-1GHz-mpurates.patch b/recipes-bsp/linux/linux-omap/0001-omap3-allow-1GHz-mpurates.patch
--- /dev/null
@@ -0,0 +1,26 @@
+From 095749d8941257799eaf5b2509918373f1a08152 Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 10 Mar 2011 14:03:08 +0100
+Subject: [PATCH] omap3: allow 1GHz mpurates
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/plat-omap/clock.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
+index fc62fb5..f3e3d29 100644
+--- a/arch/arm/plat-omap/clock.c
++++ b/arch/arm/plat-omap/clock.c
+@@ -181,7 +181,7 @@ static int __init omap_clk_setup(char *str)
+ if (!mpurate)
+ return 1;
+
+- if (mpurate < 1000)
++ if (mpurate < 2000)
+ mpurate *= 1000000;
+
+ return 1;
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/0001-xM-audio-fix-from-Ashok.patch b/recipes-bsp/linux/linux-omap/0001-xM-audio-fix-from-Ashok.patch
--- /dev/null
@@ -0,0 +1,27 @@
+From d53f988fc10fe22ec7e64457eac22f264bb72491 Mon Sep 17 00:00:00 2001
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Thu, 13 Jan 2011 11:37:56 -0600
+Subject: [PATCH] xM audio fix from Ashok
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ sound/soc/omap/omap-mcbsp.c | 3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
+index 7e84f24..1038686 100644
+--- a/sound/soc/omap/omap-mcbsp.c
++++ b/sound/soc/omap/omap-mcbsp.c
+@@ -332,6 +332,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
+ } else if (cpu_is_omap343x()) {
+ dma = omap24xx_dma_reqs[bus_id][substream->stream];
+ port = omap34xx_mcbsp_port[bus_id][substream->stream];
++ } else if (cpu_is_omap3630()) {
++ dma = omap24xx_dma_reqs[bus_id][substream->stream];
++ port = omap34xx_mcbsp_port[bus_id][substream->stream];
+ } else {
+ return -ENODEV;
+ }
+--
+1.7.1
+
diff --git a/recipes-bsp/linux/linux-omap/beagleboard/defconfig b/recipes-bsp/linux/linux-omap/beagleboard/defconfig
index cb21bec1f52a020bba3725d6185a96aa25d454e9..738d89496478ed624891d0f91eb97cc09afcb614 100644 (file)
#
# Automatically generated make config: don't edit
# Linux/arm 2.6.37 Kernel Configuration
-# Sun Jan 23 11:58:18 2011
+# Thu Jan 27 16:18:14 2011
#
CONFIG_ARM=y
CONFIG_HAVE_PWM=y
CONFIG_OMAP_MCBSP=y
CONFIG_OMAP_MBOX_FWK=m
CONFIG_OMAP_MBOX_KFIFO_SIZE=256
+CONFIG_OMAP_IOMMU=m
+CONFIG_OMAP_IOMMU_DEBUG=m
# CONFIG_OMAP_MPU_TIMER is not set
CONFIG_OMAP_32K_TIMER=y
# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set
#
# Multimedia core support
#
+CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_DEV=y
CONFIG_VIDEO_V4L2_COMMON=y
CONFIG_VIDEO_ALLOW_V4L1=y
CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_DVB_CORE=m
CONFIG_VIDEO_MEDIA=m
# CONFIG_VIDEO_CPIA2 is not set
# CONFIG_VIDEO_AU0828 is not set
CONFIG_VIDEO_SR030PC30=m
+CONFIG_VIDEO_OMAP3=y
+# CONFIG_VIDEO_OMAP3_DEBUG is not set
# CONFIG_SOC_CAMERA is not set
CONFIG_V4L_USB_DRIVERS=y
CONFIG_USB_VIDEO_CLASS=m
diff --git a/recipes-bsp/linux/linux-omap/media/0001-v4l-Share-code-between-video_usercopy-and-video_ioct.patch b/recipes-bsp/linux/linux-omap/media/0001-v4l-Share-code-between-video_usercopy-and-video_ioct.patch
--- /dev/null
+++ b/recipes-bsp/linux/linux-omap/media/0001-v4l-Share-code-between-video_usercopy-and-video_ioct.patch
@@ -0,0 +1,297 @@
+From d71c2e533be956a95e4ddde8b87f657ada3c9de3 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Mon, 12 Jul 2010 16:09:41 +0200
+Subject: [PATCH 01/43] v4l: Share code between video_usercopy and video_ioctl2
+
+The two functions are mostly identical. They handle the copy_from_user
+and copy_to_user operations related with V4L2 ioctls and call the real
+ioctl handler.
+
+Create a __video_usercopy function that implements the core of
+video_usercopy and video_ioctl2, and call that function from both.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/video/v4l2-ioctl.c | 218 ++++++++++++-------------------------
+ 1 files changed, 71 insertions(+), 147 deletions(-)
+
+diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
+index dd9283f..1e01554 100644
+--- a/drivers/media/video/v4l2-ioctl.c
++++ b/drivers/media/video/v4l2-ioctl.c
+@@ -374,35 +374,62 @@ video_fix_command(unsigned int cmd)
+ }
+ #endif
+
+-/*
+- * Obsolete usercopy function - Should be removed soon
+- */
+-long
+-video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
++/* In some cases, only a few fields are used as input, i.e. when the app sets
++ * "index" and then the driver fills in the rest of the structure for the thing
++ * with that index. We only need to copy up the first non-input field. */
++static unsigned long cmd_input_size(unsigned int cmd)
++{
++ /* Size of structure up to and including 'field' */
++#define CMDINSIZE(cmd, type, field) \
++ case VIDIOC_##cmd: \
++ return offsetof(struct v4l2_##type, field) + \
++ sizeof(((struct v4l2_##type *)0)->field);
++
++ switch (cmd) {
++ CMDINSIZE(ENUM_FMT, fmtdesc, type);
++ CMDINSIZE(G_FMT, format, type);
++ CMDINSIZE(QUERYBUF, buffer, type);
++ CMDINSIZE(G_PARM, streamparm, type);
++ CMDINSIZE(ENUMSTD, standard, index);
++ CMDINSIZE(ENUMINPUT, input, index);
++ CMDINSIZE(G_CTRL, control, id);
++ CMDINSIZE(G_TUNER, tuner, index);
++ CMDINSIZE(QUERYCTRL, queryctrl, id);
++ CMDINSIZE(QUERYMENU, querymenu, index);
++ CMDINSIZE(ENUMOUTPUT, output, index);
++ CMDINSIZE(G_MODULATOR, modulator, index);
++ CMDINSIZE(G_FREQUENCY, frequency, tuner);
++ CMDINSIZE(CROPCAP, cropcap, type);
++ CMDINSIZE(G_CROP, crop, type);
++ CMDINSIZE(ENUMAUDIO, audio, index);
++ CMDINSIZE(ENUMAUDOUT, audioout, index);
++ CMDINSIZE(ENCODER_CMD, encoder_cmd, flags);
++ CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags);
++ CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type);
++ CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format);
++ CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height);
++ default:
++ return _IOC_SIZE(cmd);
++ }
++}
++
++static long
++__video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
+ v4l2_kioctl func)
+ {
+ char sbuf[128];
+ void *mbuf = NULL;
+- void *parg = NULL;
++ void *parg = (void *)arg;
+ long err = -EINVAL;
+ int is_ext_ctrl;
+ size_t ctrls_size = 0;
+ void __user *user_ptr = NULL;
+
+-#ifdef __OLD_VIDIOC_
+- cmd = video_fix_command(cmd);
+-#endif
+ is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
+ cmd == VIDIOC_TRY_EXT_CTRLS);
+
+ /* Copy arguments into temp kernel buffer */
+- switch (_IOC_DIR(cmd)) {
+- case _IOC_NONE:
+- parg = NULL;
+- break;
+- case _IOC_READ:
+- case _IOC_WRITE:
+- case (_IOC_WRITE | _IOC_READ):
++ if (_IOC_DIR(cmd) != _IOC_NONE) {
+ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
+ parg = sbuf;
+ } else {
+@@ -414,11 +441,21 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
+ }
+
+ err = -EFAULT;
+- if (_IOC_DIR(cmd) & _IOC_WRITE)
+- if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
++ if (_IOC_DIR(cmd) & _IOC_WRITE) {
++ unsigned long n = cmd_input_size(cmd);
++
++ if (copy_from_user(parg, (void __user *)arg, n))
+ goto out;
+- break;
++
++ /* zero out anything we don't copy from userspace */
++ if (n < _IOC_SIZE(cmd))
++ memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
++ } else {
++ /* read-only ioctl */
++ memset(parg, 0, _IOC_SIZE(cmd));
++ }
+ }
++
+ if (is_ext_ctrl) {
+ struct v4l2_ext_controls *p = parg;
+
+@@ -440,7 +477,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
+ }
+ }
+
+- /* call driver */
++ /* Handles IOCTL */
+ err = func(file, cmd, parg);
+ if (err == -ENOIOCTLCMD)
+ err = -EINVAL;
+@@ -469,6 +506,19 @@ out:
+ kfree(mbuf);
+ return err;
+ }
++
++/*
++ * Obsolete usercopy function - Should be removed soon
++ */
++long
++video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
++ v4l2_kioctl func)
++{
++#ifdef __OLD_VIDIOC_
++ cmd = video_fix_command(cmd);
++#endif
++ return __video_usercopy(file, cmd, arg, func);
++}
+ EXPORT_SYMBOL(video_usercopy);
+
+ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
+@@ -2041,138 +2091,12 @@ static long __video_do_ioctl(struct file *file,
+ return ret;
+ }
+
+-/* In some cases, only a few fields are used as input, i.e. when the app sets
+- * "index" and then the driver fills in the rest of the structure for the thing
+- * with that index. We only need to copy up the first non-input field. */
+-static unsigned long cmd_input_size(unsigned int cmd)
+-{
+- /* Size of structure up to and including 'field' */
+-#define CMDINSIZE(cmd, type, field) \
+- case VIDIOC_##cmd: \
+- return offsetof(struct v4l2_##type, field) + \
+- sizeof(((struct v4l2_##type *)0)->field);
+-
+- switch (cmd) {
+- CMDINSIZE(ENUM_FMT, fmtdesc, type);
+- CMDINSIZE(G_FMT, format, type);
+- CMDINSIZE(QUERYBUF, buffer, type);
+- CMDINSIZE(G_PARM, streamparm, type);
+- CMDINSIZE(ENUMSTD, standard, index);
+- CMDINSIZE(ENUMINPUT, input, index);
+- CMDINSIZE(G_CTRL, control, id);
+- CMDINSIZE(G_TUNER, tuner, index);
+- CMDINSIZE(QUERYCTRL, queryctrl, id);
+- CMDINSIZE(QUERYMENU, querymenu, index);
+- CMDINSIZE(ENUMOUTPUT, output, index);
+- CMDINSIZE(G_MODULATOR, modulator, index);
+- CMDINSIZE(G_FREQUENCY, frequency, tuner);
+- CMDINSIZE(CROPCAP, cropcap, type);
+- CMDINSIZE(G_CROP, crop, type);
+- CMDINSIZE(ENUMAUDIO, audio, index);
+- CMDINSIZE(ENUMAUDOUT, audioout, index);
+- CMDINSIZE(ENCODER_CMD, encoder_cmd, flags);
+- CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags);
+- CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type);
+- CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format);
+- CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height);
+- default:
+- return _IOC_SIZE(cmd);
+- }
+-}
+-
+ long video_ioctl2(struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- char sbuf[128];
+- void *mbuf = NULL;
+- void *parg = (void *)arg;
+- long err = -EINVAL;
+- int is_ext_ctrl;
+- size_t ctrls_size = 0;
+- void __user *user_ptr = NULL;
+-
+ #ifdef __OLD_VIDIOC_
+ cmd = video_fix_command(cmd);
+ #endif
+- is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
+- cmd == VIDIOC_TRY_EXT_CTRLS);
+-
+- /* Copy arguments into temp kernel buffer */
+- if (_IOC_DIR(cmd) != _IOC_NONE) {
+- if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
+- parg = sbuf;
+- } else {
+- /* too big to allocate from stack */
+- mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
+- if (NULL == mbuf)
+- return -ENOMEM;
+- parg = mbuf;
+- }
+-
+- err = -EFAULT;
+- if (_IOC_DIR(cmd) & _IOC_WRITE) {
+- unsigned long n = cmd_input_size(cmd);
+-
+- if (copy_from_user(parg, (void __user *)arg, n))
+- goto out;
+-
+- /* zero out anything we don't copy from userspace */
+- if (n < _IOC_SIZE(cmd))
+- memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
+- } else {
+- /* read-only ioctl */
+- memset(parg, 0, _IOC_SIZE(cmd));
+- }
+- }
+-
+- if (is_ext_ctrl) {
+- struct v4l2_ext_controls *p = parg;
+-
+- /* In case of an error, tell the caller that it wasn't
+- a specific control that caused it. */
+- p->error_idx = p->count;
+- user_ptr = (void __user *)p->controls;
+- if (p->count) {
+- ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
+- /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
+- mbuf = kmalloc(ctrls_size, GFP_KERNEL);
+- err = -ENOMEM;
+- if (NULL == mbuf)
+- goto out_ext_ctrl;
+- err = -EFAULT;
+- if (copy_from_user(mbuf, user_ptr, ctrls_size))
+- goto out_ext_ctrl;
+- p->controls = mbuf;
+- }
+- }
+-
+- /* Handles IOCTL */
+- err = __video_do_ioctl(file, cmd, parg);
+- if (err == -ENOIOCTLCMD)
+- err = -EINVAL;
+- if (is_ext_ctrl) {
+- struct v4l2_ext_controls *p = parg;
+-
+- p->controls = (void *)user_ptr;
+- if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
+- err = -EFAULT;
+- goto out_ext_ctrl;
+- }
+- if (err < 0)
+- goto out;
+-
+-out_ext_ctrl:
+- /* Copy results into user buffer */
+- switch (_IOC_DIR(cmd)) {
+- case _IOC_READ:
+- case (_IOC_WRITE | _IOC_READ):
+- if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
+- err = -EFAULT;
+- break;
+- }
+-
+-out:
+- kfree(mbuf);
+- return err;
++ return __video_usercopy(file, cmd, arg, __video_do_ioctl);
+ }
+ EXPORT_SYMBOL(video_ioctl2);
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0002-v4l-subdev-Don-t-require-core-operations.patch b/recipes-bsp/linux/linux-omap/media/0002-v4l-subdev-Don-t-require-core-operations.patch
--- /dev/null
@@ -0,0 +1,31 @@
+From e501e49dfa290479eaf23fcc5bd0623102220e0c Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Mon, 31 May 2010 11:33:06 +0300
+Subject: [PATCH 02/43] v4l: subdev: Don't require core operations
+
+There's no reason to require subdevices to implement the core
+operations. Remove the check for non-NULL core operations when
+initializing the subdev.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ include/media/v4l2-subdev.h | 3 +--
+ 1 files changed, 1 insertions(+), 2 deletions(-)
+
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index b0316a7..b636444 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -466,8 +466,7 @@ static inline void v4l2_subdev_init(struct v4l2_subdev *sd,
+ const struct v4l2_subdev_ops *ops)
+ {
+ INIT_LIST_HEAD(&sd->list);
+- /* ops->core MUST be set */
+- BUG_ON(!ops || !ops->core);
++ BUG_ON(!ops);
+ sd->ops = ops;
+ sd->v4l2_dev = NULL;
+ sd->flags = 0;
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0003-v4l-subdev-Merge-v4l2_i2c_new_subdev_cfg-and-v4l2_i2.patch b/recipes-bsp/linux/linux-omap/media/0003-v4l-subdev-Merge-v4l2_i2c_new_subdev_cfg-and-v4l2_i2.patch
--- /dev/null
+++ b/recipes-bsp/linux/linux-omap/media/0003-v4l-subdev-Merge-v4l2_i2c_new_subdev_cfg-and-v4l2_i2.patch
@@ -0,0 +1,132 @@
+From 2c7009851d70caeb91ac806b133b7d77c5c2ca19 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Thu, 8 Jul 2010 12:01:09 +0200
+Subject: [PATCH 03/43] v4l: subdev: Merge v4l2_i2c_new_subdev_cfg and v4l2_i2c_new_subdev
+
+v4l2_i2c_new_subdev is a thin wrapper around v4l2_i2c_new_subdev_cfg,
+which is itself a wrapper around v4l2_i2c_new_subdev_board.
+
+The intermediate v4l2_i2c_new_subdev_cfg function is called directly by
+the ivtv and cafe-ccic drivers only. Merge it with v4l2_i2c_new_subdev
+and use v4l2_i2c_new_subdev_board in the ivtv and cafe-ccic drivers.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/video/cafe_ccic.c | 11 +++++++++--
+ drivers/media/video/ivtv/ivtv-i2c.c | 11 +++++++++--
+ drivers/media/video/v4l2-common.c | 7 ++-----
+ include/media/v4l2-common.h | 13 +------------
+ 4 files changed, 21 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
+index 0dfff50..6e23add 100644
+--- a/drivers/media/video/cafe_ccic.c
++++ b/drivers/media/video/cafe_ccic.c
+@@ -1992,6 +1992,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
+ {
+ int ret;
+ struct cafe_camera *cam;
++ struct i2c_board_info info;
+ struct ov7670_config sensor_cfg = {
+ /* This controller only does SMBUS */
+ .use_smbus = true,
+@@ -2065,8 +2066,14 @@ static int cafe_pci_probe(struct pci_dev *pdev,
+ sensor_cfg.clock_speed = 45;
+
+ cam->sensor_addr = 0x42;
+- cam->sensor = v4l2_i2c_new_subdev_cfg(&cam->v4l2_dev, &cam->i2c_adapter,
+- "ov7670", 0, &sensor_cfg, cam->sensor_addr, NULL);
++
++ memset(&info, 0, sizeof(info));
++ strlcpy(info.type, "ov7670", sizeof(info.type));
++ info.addr = cam->sensor_addr;
++ info.platform_data = &sensor_cfg;
++
++ cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev,
++ &cam->i2c_adapter, &info, NULL);
+ if (cam->sensor == NULL) {
+ ret = -ENODEV;
+ goto out_smbus;
+diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
+index 665191c..6651a6c 100644
+--- a/drivers/media/video/ivtv/ivtv-i2c.c
++++ b/drivers/media/video/ivtv/ivtv-i2c.c
+@@ -267,10 +267,17 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
+ adap, type, 0, I2C_ADDRS(hw_addrs[idx]));
+ } else if (hw == IVTV_HW_CX25840) {
+ struct cx25840_platform_data pdata;
++ struct i2c_board_info info;
+
+ pdata.pvr150_workaround = itv->pvr150_workaround;
+- sd = v4l2_i2c_new_subdev_cfg(&itv->v4l2_dev,
+- adap, type, 0, &pdata, hw_addrs[idx], NULL);
++
++ memset(&info, 0, sizeof(info));
++ strlcpy(info.type, type, sizeof(info.type));
++ info.addr = hw_addrs[idx];
++ info.platform_data = &pdata;
++
++ sd = v4l2_i2c_new_subdev_board(&itv->v4l2_dev, adap, &info,
++ NULL);
+ } else {
+ sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
+ adap, type, hw_addrs[idx], NULL);
+diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
+index b5eb1f3..e007e61 100644
+--- a/drivers/media/video/v4l2-common.c
++++ b/drivers/media/video/v4l2-common.c
+@@ -428,9 +428,8 @@ error:
+ }
+ EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board);
+
+-struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev,
++struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
+ struct i2c_adapter *adapter, const char *client_type,
+- int irq, void *platform_data,
+ u8 addr, const unsigned short *probe_addrs)
+ {
+ struct i2c_board_info info;
+@@ -440,12 +439,10 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev,
+ memset(&info, 0, sizeof(info));
+ strlcpy(info.type, client_type, sizeof(info.type));
+ info.addr = addr;
+- info.irq = irq;
+- info.platform_data = platform_data;
+
+ return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs);
+ }
+-EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_cfg);
++EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev);
+
+ /* Return i2c client address of v4l2_subdev. */
+ unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd)
+diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
+index 239125a..565fb32 100644
+--- a/include/media/v4l2-common.h
++++ b/include/media/v4l2-common.h
+@@ -138,21 +138,10 @@ struct v4l2_subdev_ops;
+
+ /* Load an i2c module and return an initialized v4l2_subdev struct.
+ The client_type argument is the name of the chip that's on the adapter. */
+-struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev,
++struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
+ struct i2c_adapter *adapter, const char *client_type,
+- int irq, void *platform_data,
+ u8 addr, const unsigned short *probe_addrs);
+
+-/* Load an i2c module and return an initialized v4l2_subdev struct.
+- The client_type argument is the name of the chip that's on the adapter. */
+-static inline struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
+- struct i2c_adapter *adapter, const char *client_type,
+- u8 addr, const unsigned short *probe_addrs)
+-{
+- return v4l2_i2c_new_subdev_cfg(v4l2_dev, adapter, client_type, 0, NULL,
+- addr, probe_addrs);
+-}
+-
+ struct i2c_board_info;
+
+ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0004-v4l-subdev-Add-device-node-support.patch b/recipes-bsp/linux/linux-omap/media/0004-v4l-subdev-Add-device-node-support.patch
--- /dev/null
@@ -0,0 +1,615 @@
+From e5b8af4e36ca5e922dd2b881d6c215e9d4d30a6f Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:38:49 +0100
+Subject: [PATCH 04/43] v4l: subdev: Add device node support
+
+Create a device node named subdevX for every registered subdev.
+
+As the device node is registered before the subdev core::s_config
+function is called, return -EGAIN on open until initialization
+completes.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Vimarsh Zutshi <vimarsh.zutshi@nokia.com>
+---
+ Documentation/video4linux/v4l2-framework.txt | 18 +++++++
+ drivers/media/radio/radio-si4713.c | 2 +-
+ drivers/media/video/Makefile | 2 +-
+ drivers/media/video/cafe_ccic.c | 2 +-
+ drivers/media/video/davinci/vpfe_capture.c | 2 +-
+ drivers/media/video/davinci/vpif_capture.c | 2 +-
+ drivers/media/video/davinci/vpif_display.c | 2 +-
+ drivers/media/video/ivtv/ivtv-i2c.c | 2 +-
+ drivers/media/video/s5p-fimc/fimc-capture.c | 2 +-
+ drivers/media/video/sh_vou.c | 2 +-
+ drivers/media/video/soc_camera.c | 2 +-
+ drivers/media/video/v4l2-common.c | 15 +++++-
+ drivers/media/video/v4l2-dev.c | 27 ++++------
+ drivers/media/video/v4l2-device.c | 24 +++++++++-
+ drivers/media/video/v4l2-ioctl.c | 2 +-
+ drivers/media/video/v4l2-subdev.c | 66 ++++++++++++++++++++++++++
+ include/media/v4l2-common.h | 5 +-
+ include/media/v4l2-dev.h | 18 ++++++-
+ include/media/v4l2-ioctl.h | 3 +
+ include/media/v4l2-subdev.h | 16 ++++++-
+ 20 files changed, 176 insertions(+), 38 deletions(-)
+ create mode 100644 drivers/media/video/v4l2-subdev.c
+
+diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
+index f22f35c..4c9185a 100644
+--- a/Documentation/video4linux/v4l2-framework.txt
++++ b/Documentation/video4linux/v4l2-framework.txt
+@@ -319,6 +319,24 @@ controlled through GPIO pins. This distinction is only relevant when setting
+ up the device, but once the subdev is registered it is completely transparent.
+
+
++V4L2 sub-device userspace API
++-----------------------------
++
++Beside exposing a kernel API through the v4l2_subdev_ops structure, V4L2
++sub-devices can also be controlled directly by userspace applications.
++
++When a sub-device is registered, a device node named v4l-subdevX can be created
++in /dev. If the sub-device supports direct userspace configuration it must set
++the V4L2_SUBDEV_FL_HAS_DEVNODE flag before being registered.
++
++For I2C and SPI sub-devices, the v4l2_device driver can disable registration of
++the device node if it wants to control the sub-device on its own. In that case
++it must set the v4l2_i2c_new_subdev_board or v4l2_spi_new_subdev enable_devnode
++argument to 0. Setting the argument to 1 will only enable device node
++registration if the sub-device driver has set the V4L2_SUBDEV_FL_HAS_DEVNODE
++flag.
++
++
+ I2C sub-device drivers
+ ----------------------
+
+diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c
+index 726d367..f7c942f 100644
+--- a/drivers/media/radio/radio-si4713.c
++++ b/drivers/media/radio/radio-si4713.c
+@@ -293,7 +293,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
+ }
+
+ sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter,
+- pdata->subdev_board_info, NULL);
++ pdata->subdev_board_info, NULL, 0);
+ if (!sd) {
+ dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
+ rval = -ENODEV;
+diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
+index af79d47..adc1bd5 100644
+--- a/drivers/media/video/Makefile
++++ b/drivers/media/video/Makefile
+@@ -11,7 +11,7 @@ stkwebcam-objs := stk-webcam.o stk-sensor.o
+ omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o
+
+ videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
+- v4l2-event.o v4l2-ctrls.o
++ v4l2-event.o v4l2-ctrls.o v4l2-subdev.o
+
+ # V4L2 core modules
+
+diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
+index 6e23add..f932da1 100644
+--- a/drivers/media/video/cafe_ccic.c
++++ b/drivers/media/video/cafe_ccic.c
+@@ -2073,7 +2073,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
+ info.platform_data = &sensor_cfg;
+
+ cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev,
+- &cam->i2c_adapter, &info, NULL);
++ &cam->i2c_adapter, &info, NULL, 0);
+ if (cam->sensor == NULL) {
+ ret = -ENODEV;
+ goto out_smbus;
+diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c
+index 7333a9b..bfc2a47 100644
+--- a/drivers/media/video/davinci/vpfe_capture.c
++++ b/drivers/media/video/davinci/vpfe_capture.c
+@@ -1987,7 +1987,7 @@ static __init int vpfe_probe(struct platform_device *pdev)
+ v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev,
+ i2c_adap,
+ &sdinfo->board_info,
+- NULL);
++ NULL, 0);
+ if (vpfe_dev->sd[i]) {
+ v4l2_info(&vpfe_dev->v4l2_dev,
+ "v4l2 sub device %s registered\n",
+diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c
+index 193abab..d2228e0 100644
+--- a/drivers/media/video/davinci/vpif_capture.c
++++ b/drivers/media/video/davinci/vpif_capture.c
+@@ -2014,7 +2014,7 @@ static __init int vpif_probe(struct platform_device *pdev)
+ v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
+ i2c_adap,
+ &subdevdata->board_info,
+- NULL);
++ NULL, 0);
+
+ if (!vpif_obj.sd[i]) {
+ vpif_err("Error registering v4l2 subdevice\n");
+diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c
+index 412c65d..060c049 100644
+--- a/drivers/media/video/davinci/vpif_display.c
++++ b/drivers/media/video/davinci/vpif_display.c
+@@ -1555,7 +1555,7 @@ static __init int vpif_probe(struct platform_device *pdev)
+ vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
+ i2c_adap,
+ &subdevdata[i].board_info,
+- NULL);
++ NULL, 0);
+ if (!vpif_obj.sd[i]) {
+ vpif_err("Error registering v4l2 subdevice\n");
+ goto probe_subdev_out;
+diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
+index 6651a6c..3d3b62d 100644
+--- a/drivers/media/video/ivtv/ivtv-i2c.c
++++ b/drivers/media/video/ivtv/ivtv-i2c.c
+@@ -277,7 +277,7 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
+ info.platform_data = &pdata;
+
+ sd = v4l2_i2c_new_subdev_board(&itv->v4l2_dev, adap, &info,
+- NULL);
++ NULL, 0);
+ } else {
+ sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
+ adap, type, hw_addrs[idx], NULL);
+diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
+index 2f50080..b237daa 100644
+--- a/drivers/media/video/s5p-fimc/fimc-capture.c
++++ b/drivers/media/video/s5p-fimc/fimc-capture.c
+@@ -44,7 +44,7 @@ static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc,
+ return ERR_PTR(-ENOMEM);
+
+ sd = v4l2_i2c_new_subdev_board(&vid_cap->v4l2_dev, i2c_adap,
+- isp_info->board_info, NULL);
++ isp_info->board_info, NULL, 0);
+ if (!sd) {
+ v4l2_err(&vid_cap->v4l2_dev, "failed to acquire subdev\n");
+ return NULL;
+diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c
+index 07cf0c6..c50f0f5 100644
+--- a/drivers/media/video/sh_vou.c
++++ b/drivers/media/video/sh_vou.c
+@@ -1409,7 +1409,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
+ goto ereset;
+
+ subdev = v4l2_i2c_new_subdev_board(&vou_dev->v4l2_dev, i2c_adap,
+- vou_pdata->board_info, NULL);
++ vou_pdata->board_info, NULL, 0);
+ if (!subdev) {
+ ret = -ENOMEM;
+ goto ei2cnd;
+diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
+index 052bd6d..5afb601 100644
+--- a/drivers/media/video/soc_camera.c
++++ b/drivers/media/video/soc_camera.c
+@@ -896,7 +896,7 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd,
+ icl->board_info->platform_data = icd;
+
+ subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap,
+- icl->board_info, NULL);
++ icl->board_info, NULL, 0);
+ if (!subdev)
+ goto ei2cnd;
+
+diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
+index e007e61..ffee794 100644
+--- a/drivers/media/video/v4l2-common.c
++++ b/drivers/media/video/v4l2-common.c
+@@ -369,7 +369,7 @@ EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init);
+ /* Load an i2c sub-device. */
+ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
+ struct i2c_adapter *adapter, struct i2c_board_info *info,
+- const unsigned short *probe_addrs)
++ const unsigned short *probe_addrs, int enable_devnode)
+ {
+ struct v4l2_subdev *sd = NULL;
+ struct i2c_client *client;
+@@ -399,9 +399,12 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
+ if (!try_module_get(client->driver->driver.owner))
+ goto error;
+ sd = i2c_get_clientdata(client);
++ if (!enable_devnode)
++ sd->flags &= ~V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ /* Register with the v4l2_device which increases the module's
+ use count as well. */
++ sd->initialized = 0;
+ if (v4l2_device_register_subdev(v4l2_dev, sd))
+ sd = NULL;
+ /* Decrease the module use count to match the first try_module_get. */
+@@ -416,6 +419,8 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
+ if (err && err != -ENOIOCTLCMD) {
+ v4l2_device_unregister_subdev(sd);
+ sd = NULL;
++ } else {
++ sd->initialized = 1;
+ }
+ }
+
+@@ -440,7 +445,8 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
+ strlcpy(info.type, client_type, sizeof(info.type));
+ info.addr = addr;
+
+- return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs);
++ return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs,
++ 0);
+ }
+ EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev);
+
+@@ -510,7 +516,8 @@ void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
+ EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init);
+
+ struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
+- struct spi_master *master, struct spi_board_info *info)
++ struct spi_master *master, struct spi_board_info *info,
++ int enable_devnode)
+ {
+ struct v4l2_subdev *sd = NULL;
+ struct spi_device *spi = NULL;
+@@ -529,6 +536,8 @@ struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
+ goto error;
+
+ sd = spi_get_drvdata(spi);
++ if (!enable_devnode)
++ sd->flags &= ~V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ /* Register with the v4l2_device which increases the module's
+ use count as well. */
+diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
+index 359e232..f22bd41 100644
+--- a/drivers/media/video/v4l2-dev.c
++++ b/drivers/media/video/v4l2-dev.c
+@@ -408,13 +408,14 @@ static int get_index(struct video_device *vdev)
+ }
+
+ /**
+- * video_register_device - register video4linux devices
++ * __video_register_device - register video4linux devices
+ * @vdev: video device structure we want to register
+ * @type: type of device to register
+ * @nr: which device node number (0 == /dev/video0, 1 == /dev/video1, ...
+ * -1 == first free)
+ * @warn_if_nr_in_use: warn if the desired device node number
+ * was already in use and another number was chosen instead.
++ * @owner: module that owns the video device node
+ *
+ * The registration code assigns minor numbers and device node numbers
+ * based on the requested type and registers the new device node with
+@@ -431,9 +432,11 @@ static int get_index(struct video_device *vdev)
+ * %VFL_TYPE_VBI - Vertical blank data (undecoded)
+ *
+ * %VFL_TYPE_RADIO - A radio card
++ *
++ * %VFL_TYPE_SUBDEV - A subdevice
+ */
+-static int __video_register_device(struct video_device *vdev, int type, int nr,
+- int warn_if_nr_in_use)
++int __video_register_device(struct video_device *vdev, int type, int nr,
++ int warn_if_nr_in_use, struct module *owner)
+ {
+ int i = 0;
+ int ret;
+@@ -466,6 +469,9 @@ static int __video_register_device(struct video_device *vdev, int type, int nr,
+ case VFL_TYPE_RADIO:
+ name_base = "radio";
+ break;
++ case VFL_TYPE_SUBDEV:
++ name_base = "v4l-subdev";
++ break;
+ default:
+ printk(KERN_ERR "%s called with unknown type: %d\n",
+ __func__, type);
+@@ -549,7 +555,7 @@ static int __video_register_device(struct video_device *vdev, int type, int nr,
+ goto cleanup;
+ }
+ vdev->cdev->ops = &v4l2_fops;
+- vdev->cdev->owner = vdev->fops->owner;
++ vdev->cdev->owner = owner;
+ ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: cdev_add failed\n", __func__);
+@@ -598,18 +604,7 @@ cleanup:
+ vdev->minor = -1;
+ return ret;
+ }
+-
+-int video_register_device(struct video_device *vdev, int type, int nr)
+-{
+- return __video_register_device(vdev, type, nr, 1);
+-}
+-EXPORT_SYMBOL(video_register_device);
+-
+-int video_register_device_no_warn(struct video_device *vdev, int type, int nr)
+-{
+- return __video_register_device(vdev, type, nr, 0);
+-}
+-EXPORT_SYMBOL(video_register_device_no_warn);
++EXPORT_SYMBOL(__video_register_device);
+
+ /**
+ * video_unregister_device - unregister a video4linux device
+diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
+index 7fe6f92..97e84df 100644
+--- a/drivers/media/video/v4l2-device.c
++++ b/drivers/media/video/v4l2-device.c
+@@ -117,24 +117,43 @@ EXPORT_SYMBOL_GPL(v4l2_device_unregister);
+ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
+ struct v4l2_subdev *sd)
+ {
++ struct video_device *vdev;
+ int err;
+
+ /* Check for valid input */
+ if (v4l2_dev == NULL || sd == NULL || !sd->name[0])
+ return -EINVAL;
++
+ /* Warn if we apparently re-register a subdev */
+ WARN_ON(sd->v4l2_dev != NULL);
++
+ if (!try_module_get(sd->owner))
+ return -ENODEV;
++
+ /* This just returns 0 if either of the two args is NULL */
+ err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
+ if (err)
+ return err;
++
+ sd->v4l2_dev = v4l2_dev;
+ spin_lock(&v4l2_dev->lock);
+ list_add_tail(&sd->list, &v4l2_dev->subdevs);
+ spin_unlock(&v4l2_dev->lock);
+- return 0;
++
++ /* Register the device node. */
++ vdev = &sd->devnode;
++ strlcpy(vdev->name, sd->name, sizeof(vdev->name));
++ vdev->parent = v4l2_dev->dev;
++ vdev->fops = &v4l2_subdev_fops;
++ vdev->release = video_device_release_empty;
++ if (sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE) {
++ err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
++ sd->owner);
++ if (err < 0)
++ v4l2_device_unregister_subdev(sd);
++ }
++
++ return err;
+ }
+ EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
+
+@@ -143,10 +162,13 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
+ /* return if it isn't registered */
+ if (sd == NULL || sd->v4l2_dev == NULL)
+ return;
++
+ spin_lock(&sd->v4l2_dev->lock);
+ list_del(&sd->list);
+ spin_unlock(&sd->v4l2_dev->lock);
+ sd->v4l2_dev = NULL;
++
+ module_put(sd->owner);
++ video_unregister_device(&sd->devnode);
+ }
+ EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
+diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
+index 1e01554..4137e4c 100644
+--- a/drivers/media/video/v4l2-ioctl.c
++++ b/drivers/media/video/v4l2-ioctl.c
+@@ -413,7 +413,7 @@ static unsigned long cmd_input_size(unsigned int cmd)
+ }
+ }
+
+-static long
++long
+ __video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
+ v4l2_kioctl func)
+ {
+diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
+new file mode 100644
+index 0000000..00bd4b1
+--- /dev/null
++++ b/drivers/media/video/v4l2-subdev.c
+@@ -0,0 +1,66 @@
++/*
++ * V4L2 subdevice support.
++ *
++ * Copyright (C) 2010 Nokia Corporation
++ *
++ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/types.h>
++#include <linux/ioctl.h>
++#include <linux/videodev2.h>
++
++#include <media/v4l2-device.h>
++#include <media/v4l2-ioctl.h>
++
++static int subdev_open(struct file *file)
++{
++ struct video_device *vdev = video_devdata(file);
++ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
++
++ if (!sd->initialized)
++ return -EAGAIN;
++
++ return 0;
++}
++
++static int subdev_close(struct file *file)
++{
++ return 0;
++}
++
++static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
++{
++ switch (cmd) {
++ default:
++ return -ENOIOCTLCMD;
++ }
++
++ return 0;
++}
++
++static long subdev_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ return __video_usercopy(file, cmd, arg, subdev_do_ioctl);
++}
++
++const struct v4l2_file_operations v4l2_subdev_fops = {
++ .owner = THIS_MODULE,
++ .open = subdev_open,
++ .unlocked_ioctl = subdev_ioctl,
++ .release = subdev_close,
++};
+diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
+index 565fb32..ef8965d 100644
+--- a/include/media/v4l2-common.h
++++ b/include/media/v4l2-common.h
+@@ -146,7 +146,7 @@ struct i2c_board_info;
+
+ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
+ struct i2c_adapter *adapter, struct i2c_board_info *info,
+- const unsigned short *probe_addrs);
++ const unsigned short *probe_addrs, int enable_devnode);
+
+ /* Initialize an v4l2_subdev with data from an i2c_client struct */
+ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
+@@ -179,7 +179,8 @@ struct spi_device;
+ /* Load an spi module and return an initialized v4l2_subdev struct.
+ The client_type argument is the name of the chip that's on the adapter. */
+ struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
+- struct spi_master *master, struct spi_board_info *info);
++ struct spi_master *master, struct spi_board_info *info,
++ int enable_devnode);
+
+ /* Initialize an v4l2_subdev with data from an spi_device struct */
+ void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
+diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
+index 15802a0..4fe6831 100644
+--- a/include/media/v4l2-dev.h
++++ b/include/media/v4l2-dev.h
+@@ -21,7 +21,8 @@
+ #define VFL_TYPE_GRABBER 0
+ #define VFL_TYPE_VBI 1
+ #define VFL_TYPE_RADIO 2
+-#define VFL_TYPE_MAX 3
++#define VFL_TYPE_SUBDEV 3
++#define VFL_TYPE_MAX 4
+
+ struct v4l2_ioctl_callbacks;
+ struct video_device;
+@@ -102,15 +103,26 @@ struct video_device
+ /* dev to video-device */
+ #define to_video_device(cd) container_of(cd, struct video_device, dev)
+
++int __must_check __video_register_device(struct video_device *vdev, int type,
++ int nr, int warn_if_nr_in_use, struct module *owner);
++
+ /* Register video devices. Note that if video_register_device fails,
+ the release() callback of the video_device structure is *not* called, so
+ the caller is responsible for freeing any data. Usually that means that
+ you call video_device_release() on failure. */
+-int __must_check video_register_device(struct video_device *vdev, int type, int nr);
++static inline int __must_check video_register_device(struct video_device *vdev,
++ int type, int nr)
++{
++ return __video_register_device(vdev, type, nr, 1, vdev->fops->owner);
++}
+
+ /* Same as video_register_device, but no warning is issued if the desired
+ device node number was already in use. */
+-int __must_check video_register_device_no_warn(struct video_device *vdev, int type, int nr);
++static inline int __must_check video_register_device_no_warn(
++ struct video_device *vdev, int type, int nr)
++{
++ return __video_register_device(vdev, type, nr, 0, vdev->fops->owner);
++}
+
+ /* Unregister video devices. Will do nothing if vdev == NULL or
+ video_is_registered() returns false. */
+diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
+index 06daa6e..abb64d0 100644
+--- a/include/media/v4l2-ioctl.h
++++ b/include/media/v4l2-ioctl.h
+@@ -316,6 +316,9 @@ extern long v4l2_compat_ioctl32(struct file *file, unsigned int cmd,
+ unsigned long arg);
+ #endif
+
++extern long __video_usercopy(struct file *file, unsigned int cmd,
++ unsigned long arg, v4l2_kioctl func);
++
+ /* Include support for obsoleted stuff */
+ extern long video_usercopy(struct file *file, unsigned int cmd,
+ unsigned long arg, v4l2_kioctl func);
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index b636444..de181db 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -22,6 +22,7 @@
+ #define _V4L2_SUBDEV_H
+
+ #include <media/v4l2-common.h>
++#include <media/v4l2-dev.h>
+ #include <media/v4l2-mediabus.h>
+
+ /* generic v4l2_device notify callback notification values */
+@@ -418,9 +419,11 @@ struct v4l2_subdev_ops {
+ #define V4L2_SUBDEV_NAME_SIZE 32
+
+ /* Set this flag if this subdev is a i2c device. */
+-#define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
++#define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
+ /* Set this flag if this subdev is a spi device. */
+-#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
++#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
++/* Set this flag if this subdev needs a device node. */
++#define V4L2_SUBDEV_FL_HAS_DEVNODE (1U << 2)
+
+ /* Each instance of a subdev driver should create this struct, either
+ stand-alone or embedded in a larger struct.
+@@ -440,8 +443,16 @@ struct v4l2_subdev {
+ /* pointer to private data */
+ void *dev_priv;
+ void *host_priv;
++ /* subdev device node */
++ struct video_device devnode;
++ unsigned int initialized;
+ };
+
++#define vdev_to_v4l2_subdev(vdev) \
++ container_of(vdev, struct v4l2_subdev, devnode)
++
++extern const struct v4l2_file_operations v4l2_subdev_fops;
++
+ static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)
+ {
+ sd->dev_priv = p;
+@@ -474,6 +485,7 @@ static inline void v4l2_subdev_init(struct v4l2_subdev *sd,
+ sd->grp_id = 0;
+ sd->dev_priv = NULL;
+ sd->host_priv = NULL;
++ sd->initialized = 1;
+ }
+
+ /* Call an ops of a v4l2_subdev, doing the right checks against
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0005-v4l-subdev-Uninline-the-v4l2_subdev_init-function.patch b/recipes-bsp/linux/linux-omap/media/0005-v4l-subdev-Uninline-the-v4l2_subdev_init-function.patch
--- /dev/null
+++ b/recipes-bsp/linux/linux-omap/media/0005-v4l-subdev-Uninline-the-v4l2_subdev_init-function.patch
@@ -0,0 +1,103 @@
+From 7acd77b0cdf013213a6513a75ee5bc2c3e92e1a1 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:38:52 +0100
+Subject: [PATCH 05/43] v4l: subdev: Uninline the v4l2_subdev_init function
+
+The function isn't small or performance sensitive enough to be inlined.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/video/v4l2-subdev.c | 42 +++++++++++++++++++++++++-----------
+ include/media/v4l2-subdev.h | 16 +------------
+ 2 files changed, 31 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
+index 00bd4b1..0deff78 100644
+--- a/drivers/media/video/v4l2-subdev.c
++++ b/drivers/media/video/v4l2-subdev.c
+@@ -1,22 +1,23 @@
+ /*
+- * V4L2 subdevice support.
++ * V4L2 sub-device
+ *
+- * Copyright (C) 2010 Nokia Corporation
++ * Copyright (C) 2010 Nokia Corporation
+ *
+- * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation.
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
+ *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
+ *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+ #include <linux/types.h>
+@@ -64,3 +65,18 @@ const struct v4l2_file_operations v4l2_subdev_fops = {
+ .unlocked_ioctl = subdev_ioctl,
+ .release = subdev_close,
+ };
++
++void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
++{
++ INIT_LIST_HEAD(&sd->list);
++ BUG_ON(!ops);
++ sd->ops = ops;
++ sd->v4l2_dev = NULL;
++ sd->flags = 0;
++ sd->name[0] = '\0';
++ sd->grp_id = 0;
++ sd->dev_priv = NULL;
++ sd->host_priv = NULL;
++ sd->initialized = 1;
++}
++EXPORT_SYMBOL(v4l2_subdev_init);
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index de181db..90022f5 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -473,20 +473,8 @@ static inline void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd)
+ return sd->host_priv;
+ }
+
+-static inline void v4l2_subdev_init(struct v4l2_subdev *sd,
+- const struct v4l2_subdev_ops *ops)
+-{
+- INIT_LIST_HEAD(&sd->list);
+- BUG_ON(!ops);
+- sd->ops = ops;
+- sd->v4l2_dev = NULL;
+- sd->flags = 0;
+- sd->name[0] = '\0';
+- sd->grp_id = 0;
+- sd->dev_priv = NULL;
+- sd->host_priv = NULL;
+- sd->initialized = 1;
+-}
++void v4l2_subdev_init(struct v4l2_subdev *sd,
++ const struct v4l2_subdev_ops *ops);
+
+ /* Call an ops of a v4l2_subdev, doing the right checks against
+ NULL pointers.
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0006-v4l-subdev-Control-ioctls-support.patch b/recipes-bsp/linux/linux-omap/media/0006-v4l-subdev-Control-ioctls-support.patch
--- /dev/null
@@ -0,0 +1,88 @@
+From dd0b366441249eb10daa2275e968431507f8d0d5 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:39:54 +0100
+Subject: [PATCH 06/43] v4l: subdev: Control ioctls support
+
+Pass the control-related ioctls to the subdev driver through the control
+framework.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ Documentation/video4linux/v4l2-framework.txt | 16 ++++++++++++++++
+ drivers/media/video/v4l2-subdev.c | 25 +++++++++++++++++++++++++
+ 2 files changed, 41 insertions(+), 0 deletions(-)
+
+diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
+index 4c9185a..f683f63 100644
+--- a/Documentation/video4linux/v4l2-framework.txt
++++ b/Documentation/video4linux/v4l2-framework.txt
+@@ -336,6 +336,22 @@ argument to 0. Setting the argument to 1 will only enable device node
+ registration if the sub-device driver has set the V4L2_SUBDEV_FL_HAS_DEVNODE
+ flag.
+
++The device node handles a subset of the V4L2 API.
++
++VIDIOC_QUERYCTRL
++VIDIOC_QUERYMENU
++VIDIOC_G_CTRL
++VIDIOC_S_CTRL
++VIDIOC_G_EXT_CTRLS
++VIDIOC_S_EXT_CTRLS
++VIDIOC_TRY_EXT_CTRLS
++
++ The controls ioctls are identical to the ones defined in V4L2. They
++ behave identically, with the only exception that they deal only with
++ controls implemented in the sub-device. Depending on the driver, those
++ controls can be also be accessed through one (or several) V4L2 device
++ nodes.
++
+
+ I2C sub-device drivers
+ ----------------------
+diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
+index 0deff78..fc57ce7 100644
+--- a/drivers/media/video/v4l2-subdev.c
++++ b/drivers/media/video/v4l2-subdev.c
+@@ -24,6 +24,7 @@
+ #include <linux/ioctl.h>
+ #include <linux/videodev2.h>
+
++#include <media/v4l2-ctrls.h>
+ #include <media/v4l2-device.h>
+ #include <media/v4l2-ioctl.h>
+
+@@ -45,7 +46,31 @@ static int subdev_close(struct file *file)
+
+ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+ {
++ struct video_device *vdev = video_devdata(file);
++ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
++
+ switch (cmd) {
++ case VIDIOC_QUERYCTRL:
++ return v4l2_subdev_queryctrl(sd, arg);
++
++ case VIDIOC_QUERYMENU:
++ return v4l2_subdev_querymenu(sd, arg);
++
++ case VIDIOC_G_CTRL:
++ return v4l2_subdev_g_ctrl(sd, arg);
++
++ case VIDIOC_S_CTRL:
++ return v4l2_subdev_s_ctrl(sd, arg);
++
++ case VIDIOC_G_EXT_CTRLS:
++ return v4l2_subdev_g_ext_ctrls(sd, arg);
++
++ case VIDIOC_S_EXT_CTRLS:
++ return v4l2_subdev_s_ext_ctrls(sd, arg);
++
++ case VIDIOC_TRY_EXT_CTRLS:
++ return v4l2_subdev_try_ext_ctrls(sd, arg);
++
+ default:
+ return -ENOIOCTLCMD;
+ }
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0007-v4l-subdev-Events-support.patch b/recipes-bsp/linux/linux-omap/media/0007-v4l-subdev-Events-support.patch
--- /dev/null
@@ -0,0 +1,223 @@
+From 127fac73175e73c509ba203717be618a611294cd Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Wed, 3 Mar 2010 17:49:38 +0200
+Subject: [PATCH 07/43] v4l: subdev: Events support
+
+Provide v4l2_subdevs with v4l2_event support. Subdev drivers only need very
+little to support events.
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Signed-off-by: David Cohen <david.cohen@nokia.com>
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ Documentation/video4linux/v4l2-framework.txt | 18 ++++++
+ drivers/media/video/v4l2-subdev.c | 75 +++++++++++++++++++++++++-
+ include/media/v4l2-subdev.h | 10 ++++
+ 3 files changed, 102 insertions(+), 1 deletions(-)
+
+diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
+index f683f63..4db1def 100644
+--- a/Documentation/video4linux/v4l2-framework.txt
++++ b/Documentation/video4linux/v4l2-framework.txt
+@@ -352,6 +352,24 @@ VIDIOC_TRY_EXT_CTRLS
+ controls can be also be accessed through one (or several) V4L2 device
+ nodes.
+
++VIDIOC_DQEVENT
++VIDIOC_SUBSCRIBE_EVENT
++VIDIOC_UNSUBSCRIBE_EVENT
++
++ The events ioctls are identical to the ones defined in V4L2. They
++ behave identically, with the only exception that they deal only with
++ events generated by the sub-device. Depending on the driver, those
++ events can also be reported by one (or several) V4L2 device nodes.
++
++ Sub-device drivers that want to use events need to set the
++ V4L2_SUBDEV_USES_EVENTS v4l2_subdev::flags and initialize
++ v4l2_subdev::nevents to events queue depth before registering the
++ sub-device. After registration events can be queued as usual on the
++ v4l2_subdev::devnode device node.
++
++ To properly support events, the poll() file operation is also
++ implemented.
++
+
+ I2C sub-device drivers
+ ----------------------
+diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
+index fc57ce7..fbccefd 100644
+--- a/drivers/media/video/v4l2-subdev.c
++++ b/drivers/media/video/v4l2-subdev.c
+@@ -20,27 +20,69 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+-#include <linux/types.h>
+ #include <linux/ioctl.h>
++#include <linux/slab.h>
++#include <linux/types.h>
+ #include <linux/videodev2.h>
+
+ #include <media/v4l2-ctrls.h>
+ #include <media/v4l2-device.h>
+ #include <media/v4l2-ioctl.h>
++#include <media/v4l2-fh.h>
++#include <media/v4l2-event.h>
+
+ static int subdev_open(struct file *file)
+ {
+ struct video_device *vdev = video_devdata(file);
+ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
++ struct v4l2_fh *vfh;
++ int ret;
+
+ if (!sd->initialized)
+ return -EAGAIN;
+
++ if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) {
++ vfh = kzalloc(sizeof(*vfh), GFP_KERNEL);
++ if (vfh == NULL)
++ return -ENOMEM;
++
++ ret = v4l2_fh_init(vfh, vdev);
++ if (ret)
++ goto err;
++
++ ret = v4l2_event_init(vfh);
++ if (ret)
++ goto err;
++
++ ret = v4l2_event_alloc(vfh, sd->nevents);
++ if (ret)
++ goto err;
++
++ v4l2_fh_add(vfh);
++ file->private_data = vfh;
++ }
++
+ return 0;
++
++err:
++ if (vfh != NULL) {
++ v4l2_fh_exit(vfh);
++ kfree(vfh);
++ }
++
++ return ret;
+ }
+
+ static int subdev_close(struct file *file)
+ {
++ struct v4l2_fh *vfh = file->private_data;
++
++ if (vfh != NULL) {
++ v4l2_fh_del(vfh);
++ v4l2_fh_exit(vfh);
++ kfree(vfh);
++ }
++
+ return 0;
+ }
+
+@@ -48,6 +90,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+ {
+ struct video_device *vdev = video_devdata(file);
+ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
++ struct v4l2_fh *fh = file->private_data;
+
+ switch (cmd) {
+ case VIDIOC_QUERYCTRL:
+@@ -71,6 +114,18 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+ case VIDIOC_TRY_EXT_CTRLS:
+ return v4l2_subdev_try_ext_ctrls(sd, arg);
+
++ case VIDIOC_DQEVENT:
++ if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
++ return -ENOIOCTLCMD;
++
++ return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK);
++
++ case VIDIOC_SUBSCRIBE_EVENT:
++ return v4l2_subdev_call(sd, core, subscribe_event, fh, arg);
++
++ case VIDIOC_UNSUBSCRIBE_EVENT:
++ return v4l2_subdev_call(sd, core, unsubscribe_event, fh, arg);
++
+ default:
+ return -ENOIOCTLCMD;
+ }
+@@ -84,11 +139,29 @@ static long subdev_ioctl(struct file *file, unsigned int cmd,
+ return __video_usercopy(file, cmd, arg, subdev_do_ioctl);
+ }
+
++static unsigned int subdev_poll(struct file *file, poll_table *wait)
++{
++ struct video_device *vdev = video_devdata(file);
++ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
++ struct v4l2_fh *fh = file->private_data;
++
++ if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
++ return POLLERR;
++
++ poll_wait(file, &fh->events->wait, wait);
++
++ if (v4l2_event_pending(fh))
++ return POLLPRI;
++
++ return 0;
++}
++
+ const struct v4l2_file_operations v4l2_subdev_fops = {
+ .owner = THIS_MODULE,
+ .open = subdev_open,
+ .unlocked_ioctl = subdev_ioctl,
+ .release = subdev_close,
++ .poll = subdev_poll,
+ };
+
+ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index 90022f5..68cbe48 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -37,6 +37,8 @@
+
+ struct v4l2_device;
+ struct v4l2_ctrl_handler;
++struct v4l2_event_subscription;
++struct v4l2_fh;
+ struct v4l2_subdev;
+ struct tuner_setup;
+
+@@ -165,6 +167,10 @@ struct v4l2_subdev_core_ops {
+ int (*s_power)(struct v4l2_subdev *sd, int on);
+ int (*interrupt_service_routine)(struct v4l2_subdev *sd,
+ u32 status, bool *handled);
++ int (*subscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
++ struct v4l2_event_subscription *sub);
++ int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
++ struct v4l2_event_subscription *sub);
+ };
+
+ /* s_mode: switch the tuner to a specific tuner mode. Replacement of s_radio.
+@@ -424,6 +430,8 @@ struct v4l2_subdev_ops {
+ #define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
+ /* Set this flag if this subdev needs a device node. */
+ #define V4L2_SUBDEV_FL_HAS_DEVNODE (1U << 2)
++/* Set this flag if this subdev generates events. */
++#define V4L2_SUBDEV_FL_HAS_EVENTS (1U << 3)
+
+ /* Each instance of a subdev driver should create this struct, either
+ stand-alone or embedded in a larger struct.
+@@ -446,6 +454,8 @@ struct v4l2_subdev {
+ /* subdev device node */
+ struct video_device devnode;
+ unsigned int initialized;
++ /* number of events to be allocated on open */
++ unsigned int nevents;
+ };
+
+ #define vdev_to_v4l2_subdev(vdev) \
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0008-media-Media-device-node-support.patch b/recipes-bsp/linux/linux-omap/media/0008-media-Media-device-node-support.patch
--- /dev/null
@@ -0,0 +1,500 @@
+From 27c789f3ae1d24212355d10857efb2d406d0fedd Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:39:56 +0100
+Subject: [PATCH 08/43] media: Media device node support
+
+The media_devnode structure provides support for registering and
+unregistering character devices using a dynamic major number. Reference
+counting is handled internally, making device drivers easier to write
+without having to solve the open/disconnect race condition issue over
+and over again.
+
+The code is based on video/v4l2-dev.c.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/Kconfig | 13 ++
+ drivers/media/Makefile | 10 +-
+ drivers/media/media-devnode.c | 321 +++++++++++++++++++++++++++++++++++++++++
+ include/media/media-devnode.h | 97 +++++++++++++
+ 4 files changed, 439 insertions(+), 2 deletions(-)
+ create mode 100644 drivers/media/media-devnode.c
+ create mode 100644 include/media/media-devnode.h
+
+diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
+index a28541b..6b946e6 100644
+--- a/drivers/media/Kconfig
++++ b/drivers/media/Kconfig
+@@ -14,6 +14,19 @@ if MEDIA_SUPPORT
+ comment "Multimedia core support"
+
+ #
++# Media controller
++#
++
++config MEDIA_CONTROLLER
++ bool "Media Controller API (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ ---help---
++ Enable the media controller API used to query media devices internal
++ topology and configure it dynamically.
++
++ This API is mostly used by camera interfaces in embedded platforms.
++
++#
+ # V4L core and enabled API's
+ #
+
+diff --git a/drivers/media/Makefile b/drivers/media/Makefile
+index 499b081..3a08991 100644
+--- a/drivers/media/Makefile
++++ b/drivers/media/Makefile
+@@ -2,7 +2,13 @@
+ # Makefile for the kernel multimedia device drivers.
+ #
+
++media-objs := media-devnode.o
++
++ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
++ obj-$(CONFIG_MEDIA_SUPPORT) += media.o
++endif
++
+ obj-y += common/ IR/ video/
+
+-obj-$(CONFIG_VIDEO_DEV) += radio/
+-obj-$(CONFIG_DVB_CORE) += dvb/
++obj-$(CONFIG_VIDEO_DEV) += radio/
++obj-$(CONFIG_DVB_CORE) += dvb/
+diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
+new file mode 100644
+index 0000000..7804b70
+--- /dev/null
++++ b/drivers/media/media-devnode.c
+@@ -0,0 +1,321 @@
++/*
++ * Media device node
++ *
++ * Copyright (C) 2010 Nokia Corporation
++ *
++ * Based on drivers/media/video/v4l2_dev.c code authored by
++ * Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
++ * Alan Cox, <alan@lxorguk.ukuu.org.uk> (version 1)
++ *
++ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * --
++ *
++ * Generic media device node infrastructure to register and unregister
++ * character devices using a dynamic major number and proper reference
++ * counting.
++ */
++
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/kmod.h>
++#include <linux/slab.h>
++#include <linux/mm.h>
++#include <linux/smp_lock.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/uaccess.h>
++#include <asm/system.h>
++
++#include <media/media-devnode.h>
++
++#define MEDIA_NUM_DEVICES 256
++#define MEDIA_NAME "media"
++
++static dev_t media_dev_t;
++
++/*
++ * Active devices
++ */
++static DEFINE_MUTEX(media_devnode_lock);
++static DECLARE_BITMAP(media_devnode_nums, MEDIA_NUM_DEVICES);
++
++/* Called when the last user of the media device exits. */
++static void media_devnode_release(struct device *cd)
++{
++ struct media_devnode *mdev = to_media_devnode(cd);
++
++ mutex_lock(&media_devnode_lock);
++
++ /* Delete the cdev on this minor as well */
++ cdev_del(&mdev->cdev);
++
++ /* Mark device node number as free */
++ clear_bit(mdev->minor, media_devnode_nums);
++
++ mutex_unlock(&media_devnode_lock);
++
++ /* Release media_devnode and perform other cleanups as needed. */
++ if (mdev->release)
++ mdev->release(mdev);
++}
++
++static struct bus_type media_bus_type = {
++ .name = MEDIA_NAME,
++};
++
++static ssize_t media_read(struct file *filp, char __user *buf,
++ size_t sz, loff_t *off)
++{
++ struct media_devnode *mdev = media_devnode_data(filp);
++
++ if (!mdev->fops->read)
++ return -EINVAL;
++ if (!media_devnode_is_registered(mdev))
++ return -EIO;
++ return mdev->fops->read(filp, buf, sz, off);
++}
++
++static ssize_t media_write(struct file *filp, const char __user *buf,
++ size_t sz, loff_t *off)
++{
++ struct media_devnode *mdev = media_devnode_data(filp);
++
++ if (!mdev->fops->write)
++ return -EINVAL;
++ if (!media_devnode_is_registered(mdev))
++ return -EIO;
++ return mdev->fops->write(filp, buf, sz, off);
++}
++
++static unsigned int media_poll(struct file *filp,
++ struct poll_table_struct *poll)
++{
++ struct media_devnode *mdev = media_devnode_data(filp);
++
++ if (!media_devnode_is_registered(mdev))
++ return POLLERR | POLLHUP;
++ if (!mdev->fops->poll)
++ return DEFAULT_POLLMASK;
++ return mdev->fops->poll(filp, poll);
++}
++
++static long media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
++{
++ struct media_devnode *mdev = media_devnode_data(filp);
++
++ if (!mdev->fops->ioctl)
++ return -ENOTTY;
++
++ if (!media_devnode_is_registered(mdev))
++ return -EIO;
++
++ return mdev->fops->ioctl(filp, cmd, arg);
++}
++
++/* Override for the open function */
++static int media_open(struct inode *inode, struct file *filp)
++{
++ struct media_devnode *mdev;
++ int ret;
++
++ /* Check if the media device is available. This needs to be done with
++ * the media_devnode_lock held to prevent an open/unregister race:
++ * without the lock, the device could be unregistered and freed between
++ * the media_devnode_is_registered() and get_device() calls, leading to
++ * a crash.
++ */
++ mutex_lock(&media_devnode_lock);
++ mdev = container_of(inode->i_cdev, struct media_devnode, cdev);
++ /* return ENXIO if the media device has been removed
++ already or if it is not registered anymore. */
++ if (!media_devnode_is_registered(mdev)) {
++ mutex_unlock(&media_devnode_lock);
++ return -ENXIO;
++ }
++ /* and increase the device refcount */
++ get_device(&mdev->dev);
++ mutex_unlock(&media_devnode_lock);
++
++ filp->private_data = mdev;
++
++ if (mdev->fops->open) {
++ ret = mdev->fops->open(filp);
++ if (ret) {
++ put_device(&mdev->dev);
++ return ret;
++ }
++ }
++
++ return 0;
++}
++
++/* Override for the release function */
++static int media_release(struct inode *inode, struct file *filp)
++{
++ struct media_devnode *mdev = media_devnode_data(filp);
++ int ret = 0;
++
++ if (mdev->fops->release)
++ mdev->fops->release(filp);
++
++ /* decrease the refcount unconditionally since the release()
++ return value is ignored. */
++ put_device(&mdev->dev);
++ filp->private_data = NULL;
++ return ret;
++}
++
++static const struct file_operations media_devnode_fops = {
++ .owner = THIS_MODULE,
++ .read = media_read,
++ .write = media_write,
++ .open = media_open,
++ .unlocked_ioctl = media_ioctl,
++ .release = media_release,
++ .poll = media_poll,
++ .llseek = no_llseek,
++};
++
++/**
++ * media_devnode_register - register a media device node
++ * @mdev: media device node structure we want to register
++ *
++ * The registration code assigns minor numbers and registers the new device node
++ * with the kernel. An error is returned if no free minor number can be found,
++ * or if the registration of the device node fails.
++ *
++ * Zero is returned on success.
++ *
++ * Note that if the media_devnode_register call fails, the release() callback of
++ * the media_devnode structure is *not* called, so the caller is responsible for
++ * freeing any data.
++ */
++int __must_check media_devnode_register(struct media_devnode *mdev)
++{
++ int minor;
++ int ret;
++
++ /* Part 1: Find a free minor number */
++ mutex_lock(&media_devnode_lock);
++ minor = find_next_zero_bit(media_devnode_nums, 0, MEDIA_NUM_DEVICES);
++ if (minor == MEDIA_NUM_DEVICES) {
++ mutex_unlock(&media_devnode_lock);
++ printk(KERN_ERR "could not get a free minor\n");
++ return -ENFILE;
++ }
++
++ set_bit(mdev->minor, media_devnode_nums);
++ mutex_unlock(&media_devnode_lock);
++
++ mdev->minor = minor;
++
++ /* Part 2: Initialize and register the character device */
++ cdev_init(&mdev->cdev, &media_devnode_fops);
++ mdev->cdev.owner = mdev->fops->owner;
++
++ ret = cdev_add(&mdev->cdev, MKDEV(MAJOR(media_dev_t), mdev->minor), 1);
++ if (ret < 0) {
++ printk(KERN_ERR "%s: cdev_add failed\n", __func__);
++ goto error;
++ }
++
++ /* Part 3: Register the media device */
++ mdev->dev.bus = &media_bus_type;
++ mdev->dev.devt = MKDEV(MAJOR(media_dev_t), mdev->minor);
++ mdev->dev.release = media_devnode_release;
++ if (mdev->parent)
++ mdev->dev.parent = mdev->parent;
++ dev_set_name(&mdev->dev, "media%d", mdev->minor);
++ ret = device_register(&mdev->dev);
++ if (ret < 0) {
++ printk(KERN_ERR "%s: device_register failed\n", __func__);
++ goto error;
++ }
++
++ /* Part 4: Activate this minor. The char device can now be used. */
++ set_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
++
++ return 0;
++
++error:
++ cdev_del(&mdev->cdev);
++ clear_bit(mdev->minor, media_devnode_nums);
++ return ret;
++}
++
++/**
++ * media_devnode_unregister - unregister a media device node
++ * @mdev: the device node to unregister
++ *
++ * This unregisters the passed device. Future open calls will be met with
++ * errors.
++ *
++ * This function can safely be called if the device node has never been
++ * registered or has already been unregistered.
++ */
++void media_devnode_unregister(struct media_devnode *mdev)
++{
++ /* Check if mdev was ever registered at all */
++ if (!media_devnode_is_registered(mdev))
++ return;
++
++ mutex_lock(&media_devnode_lock);
++ clear_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
++ mutex_unlock(&media_devnode_lock);
++ device_unregister(&mdev->dev);
++}
++
++/*
++ * Initialise media for linux
++ */
++static int __init media_devnode_init(void)
++{
++ int ret;
++
++ printk(KERN_INFO "Linux media interface: v0.10\n");
++ ret = alloc_chrdev_region(&media_dev_t, 0, MEDIA_NUM_DEVICES,
++ MEDIA_NAME);
++ if (ret < 0) {
++ printk(KERN_WARNING "media: unable to allocate major\n");
++ return ret;
++ }
++
++ ret = bus_register(&media_bus_type);
++ if (ret < 0) {
++ unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
++ printk(KERN_WARNING "media: bus_register failed\n");
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static void __exit media_devnode_exit(void)
++{
++ bus_unregister(&media_bus_type);
++ unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
++}
++
++module_init(media_devnode_init)
++module_exit(media_devnode_exit)
++
++MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
++MODULE_DESCRIPTION("Device node registration for media drivers");
++MODULE_LICENSE("GPL");
+diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h
+new file mode 100644
+index 0000000..01cd034
+--- /dev/null
++++ b/include/media/media-devnode.h
+@@ -0,0 +1,97 @@
++/*
++ * Media device node
++ *
++ * Copyright (C) 2010 Nokia Corporation
++ *
++ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * --
++ *
++ * Common functions for media-related drivers to register and unregister media
++ * device nodes.
++ */
++
++#ifndef _MEDIA_DEVNODE_H
++#define _MEDIA_DEVNODE_H
++
++#include <linux/poll.h>
++#include <linux/fs.h>
++#include <linux/device.h>
++#include <linux/cdev.h>
++
++/*
++ * Flag to mark the media_devnode struct as registered. Drivers must not touch
++ * this flag directly, it will be set and cleared by media_devnode_register and
++ * media_devnode_unregister.
++ */
++#define MEDIA_FLAG_REGISTERED 0
++
++struct media_file_operations {
++ struct module *owner;
++ ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
++ ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
++ unsigned int (*poll) (struct file *, struct poll_table_struct *);
++ long (*ioctl) (struct file *, unsigned int, unsigned long);
++ int (*open) (struct file *);
++ int (*release) (struct file *);
++};
++
++/**
++ * struct media_devnode - Media device node
++ * @parent: parent device
++ * @minor: device node minor number
++ * @flags: flags, combination of the MEDIA_FLAG_* constants
++ *
++ * This structure represents a media-related device node.
++ *
++ * The @parent is a physical device. It must be set by core or device drivers
++ * before registering the node.
++ */
++struct media_devnode {
++ /* device ops */
++ const struct media_file_operations *fops;
++
++ /* sysfs */
++ struct device dev; /* media device */
++ struct cdev cdev; /* character device */
++ struct device *parent; /* device parent */
++
++ /* device info */
++ int minor;
++ unsigned long flags; /* Use bitops to access flags */
++
++ /* callbacks */
++ void (*release)(struct media_devnode *mdev);
++};
++
++/* dev to media_devnode */
++#define to_media_devnode(cd) container_of(cd, struct media_devnode, dev)
++
++int __must_check media_devnode_register(struct media_devnode *mdev);
++void media_devnode_unregister(struct media_devnode *mdev);
++
++static inline struct media_devnode *media_devnode_data(struct file *filp)
++{
++ return filp->private_data;
++}
++
++static inline int media_devnode_is_registered(struct media_devnode *mdev)
++{
++ return test_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
++}
++
++#endif /* _MEDIA_DEVNODE_H */
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0009-media-Media-device.patch b/recipes-bsp/linux/linux-omap/media/0009-media-Media-device.patch
--- /dev/null
@@ -0,0 +1,398 @@
+From 6bfbc237b86be01ad23b836ba047e76e23cc7a00 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:39:58 +0100
+Subject: [PATCH 09/43] media: Media device
+
+The media_device structure abstracts functions common to all kind of
+media devices (v4l2, dvb, alsa, ...). It manages media entities and
+offers a userspace API to discover and configure the media device
+internal topology.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ Documentation/ABI/testing/sysfs-bus-media | 6 ++
+ Documentation/DocBook/media-entities.tmpl | 2 +
+ Documentation/DocBook/media.tmpl | 3 +
+ Documentation/DocBook/v4l/media-controller.xml | 56 +++++++++++++
+ Documentation/media-framework.txt | 67 ++++++++++++++++
+ drivers/media/Makefile | 2 +-
+ drivers/media/media-device.c | 100 ++++++++++++++++++++++++
+ include/media/media-device.h | 69 ++++++++++++++++
+ 8 files changed, 304 insertions(+), 1 deletions(-)
+ create mode 100644 Documentation/ABI/testing/sysfs-bus-media
+ create mode 100644 Documentation/DocBook/v4l/media-controller.xml
+ create mode 100644 Documentation/media-framework.txt
+ create mode 100644 drivers/media/media-device.c
+ create mode 100644 include/media/media-device.h
+
+diff --git a/Documentation/ABI/testing/sysfs-bus-media b/Documentation/ABI/testing/sysfs-bus-media
+new file mode 100644
+index 0000000..7057e57
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-bus-media
+@@ -0,0 +1,6 @@
++What: /sys/bus/media/devices/.../model
++Date: January 2011
++Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++ linux-media@vger.kernel.org
++Description: Contains the device model name in UTF-8. The device version is
++ is not be appended to the model name.
+diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
+index be34dcb..61d6f11 100644
+--- a/Documentation/DocBook/media-entities.tmpl
++++ b/Documentation/DocBook/media-entities.tmpl
+@@ -321,6 +321,8 @@
+ <!ENTITY sub-media-entities SYSTEM "media-entities.tmpl">
+ <!ENTITY sub-media-indices SYSTEM "media-indices.tmpl">
+
++<!ENTITY sub-media-controller SYSTEM "v4l/media-controller.xml">
++
+ <!-- Function Reference -->
+ <!ENTITY close SYSTEM "v4l/func-close.xml">
+ <!ENTITY ioctl SYSTEM "v4l/func-ioctl.xml">
+diff --git a/Documentation/DocBook/media.tmpl b/Documentation/DocBook/media.tmpl
+index f11048d..73464b0 100644
+--- a/Documentation/DocBook/media.tmpl
++++ b/Documentation/DocBook/media.tmpl
+@@ -106,6 +106,9 @@ Foundation. A copy of the license is included in the chapter entitled
+ &sub-remote_controllers;
+ </chapter>
+ </part>
++<part id="media_common">
++&sub-media-controller;
++</part>
+
+ &sub-fdl-appendix;
+
+diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml
+new file mode 100644
+index 0000000..253ddb4
+--- /dev/null
++++ b/Documentation/DocBook/v4l/media-controller.xml
+@@ -0,0 +1,56 @@
++<partinfo>
++ <authorgroup>
++ <author>
++ <firstname>Laurent</firstname>
++ <surname>Pinchart</surname>
++ <affiliation><address><email>laurent.pinchart@ideasonboard.com</email></address></affiliation>
++ <contrib>Initial version.</contrib>
++ </author>
++ </authorgroup>
++ <copyright>
++ <year>2010</year>
++ <holder>Laurent Pinchart</holder>
++ </copyright>
++
++ <revhistory>
++ <!-- Put document revisions here, newest first. -->
++ <revision>
++ <revnumber>1.0.0</revnumber>
++ <date>2010-11-10</date>
++ <authorinitials>lp</authorinitials>
++ <revremark>Initial revision</revremark>
++ </revision>
++ </revhistory>
++</partinfo>
++
++<title>Media Controller API</title>
++
++<chapter id="media_controller">
++ <title>Media Controller</title>
++
++ <section id="media-controller-intro">
++ <title>Introduction</title>
++ <para>Media devices increasingly handle multiple related functions. Many USB
++ cameras include microphones, video capture hardware can also output video,
++ or SoC camera interfaces also perform memory-to-memory operations similar to
++ video codecs.</para>
++ <para>Independent functions, even when implemented in the same hardware, can
++ be modelled as separate devices. A USB camera with a microphone will be
++ presented to userspace applications as V4L2 and ALSA capture devices. The
++ devices' relationships (when using a webcam, end-users shouldn't have to
++ manually select the associated USB microphone), while not made available
++ directly to applications by the drivers, can usually be retrieved from
++ sysfs.</para>
++ <para>With more and more advanced SoC devices being introduced, the current
++ approach will not scale. Device topologies are getting increasingly complex
++ and can't always be represented by a tree structure. Hardware blocks are
++ shared between different functions, creating dependencies between seemingly
++ unrelated devices.</para>
++ <para>Kernel abstraction APIs such as V4L2 and ALSA provide means for
++ applications to access hardware parameters. As newer hardware expose an
++ increasingly high number of those parameters, drivers need to guess what
++ applications really require based on limited information, thereby
++ implementing policies that belong to userspace.</para>
++ <para>The media controller API aims at solving those problems.</para>
++ </section>
++</chapter>
+diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt
+new file mode 100644
+index 0000000..1844c3f
+--- /dev/null
++++ b/Documentation/media-framework.txt
+@@ -0,0 +1,67 @@
++Linux kernel media framework
++============================
++
++This document describes the Linux kernel media framework, its data structures,
++functions and their usage.
++
++
++Introduction
++------------
++
++The media controller API is documented in DocBook format in
++Documentation/DocBook/v4l/media-controller.xml. This document will focus on
++the kernel-side implementation of the media framework.
++
++
++Media device
++------------
++
++A media device is represented by a struct media_device instance, defined in
++include/media/media-device.h. Allocation of the structure is handled by the
++media device driver, usually by embedding the media_device instance in a
++larger driver-specific structure.
++
++Drivers register media device instances by calling
++
++ media_device_register(struct media_device *mdev);
++
++The caller is responsible for initializing the media_device structure before
++registration. The following fields must be set:
++
++ - dev must point to the parent device (usually a pci_dev, usb_interface or
++ platform_device instance).
++
++ - model must be filled with the device model name as a NUL-terminated UTF-8
++ string. The device/model revision must not be stored in this field.
++
++The following fields are optional:
++
++ - serial is a unique serial number stored as a NUL-terminated ASCII string.
++ The field is big enough to store a GUID in text form. If the hardware
++ doesn't provide a unique serial number this field must be left empty.
++
++ - bus_info represents the location of the device in the system as a
++ NUL-terminated ASCII string. For PCI/PCIe devices bus_info must be set to
++ "PCI:" (or "PCIe:") followed by the value of pci_name(). For USB devices,
++ the usb_make_path() function must be used. This field is used by
++ applications to distinguish between otherwise identical devices that don't
++ provide a serial number.
++
++ - hw_revision is the hardware device revision in a driver-specific format.
++ When possible the revision should be formatted with the KERNEL_VERSION
++ macro.
++
++ - driver_version is formatted with the KERNEL_VERSION macro. The version
++ minor must be incremented when new features are added to the userspace API
++ without breaking binary compatibility. The version major must be
++ incremented when binary compatibility is broken.
++
++Upon successful registration a character device named media[0-9]+ is created.
++The device major and minor numbers are dynamic. The model name is exported as
++a sysfs attribute.
++
++Drivers unregister media device instances by calling
++
++ media_device_unregister(struct media_device *mdev);
++
++Unregistering a media device that hasn't been registered is *NOT* safe.
+diff --git a/drivers/media/Makefile b/drivers/media/Makefile
+index 3a08991..019d3e0 100644
+--- a/drivers/media/Makefile
++++ b/drivers/media/Makefile
+@@ -2,7 +2,7 @@
+ # Makefile for the kernel multimedia device drivers.
+ #
+
+-media-objs := media-devnode.o
++media-objs := media-device.o media-devnode.o
+
+ ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
+ obj-$(CONFIG_MEDIA_SUPPORT) += media.o
+diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
+new file mode 100644
+index 0000000..57a9c6b
+--- /dev/null
++++ b/drivers/media/media-device.c
+@@ -0,0 +1,100 @@
++/*
++ * Media device
++ *
++ * Copyright (C) 2010 Nokia Corporation
++ *
++ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/types.h>
++#include <linux/ioctl.h>
++
++#include <media/media-device.h>
++#include <media/media-devnode.h>
++
++static const struct media_file_operations media_device_fops = {
++ .owner = THIS_MODULE,
++};
++
++/* -----------------------------------------------------------------------------
++ * sysfs
++ */
++
++static ssize_t show_model(struct device *cd,
++ struct device_attribute *attr, char *buf)
++{
++ struct media_device *mdev = to_media_device(to_media_devnode(cd));
++
++ return sprintf(buf, "%.*s\n", (int)sizeof(mdev->model), mdev->model);
++}
++
++static DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
++
++/* -----------------------------------------------------------------------------
++ * Registration/unregistration
++ */
++
++static void media_device_release(struct media_devnode *mdev)
++{
++}
++
++/**
++ * media_device_register - register a media device
++ * @mdev: The media device
++ *
++ * The caller is responsible for initializing the media device before
++ * registration. The following fields must be set:
++ *
++ * - dev must point to the parent device
++ * - model must be filled with the device model name
++ */
++int __must_check media_device_register(struct media_device *mdev)
++{
++ int ret;
++
++ if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0))
++ return -EINVAL;
++
++ /* Register the device node. */
++ mdev->devnode.fops = &media_device_fops;
++ mdev->devnode.parent = mdev->dev;
++ mdev->devnode.release = media_device_release;
++ ret = media_devnode_register(&mdev->devnode);
++ if (ret < 0)
++ return ret;
++
++ ret = device_create_file(&mdev->devnode.dev, &dev_attr_model);
++ if (ret < 0) {
++ media_devnode_unregister(&mdev->devnode);
++ return ret;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(media_device_register);
++
++/**
++ * media_device_unregister - unregister a media device
++ * @mdev: The media device
++ *
++ */
++void media_device_unregister(struct media_device *mdev)
++{
++ device_remove_file(&mdev->devnode.dev, &dev_attr_model);
++ media_devnode_unregister(&mdev->devnode);
++}
++EXPORT_SYMBOL_GPL(media_device_unregister);
+diff --git a/include/media/media-device.h b/include/media/media-device.h
+new file mode 100644
+index 0000000..e11f01a
+--- /dev/null
++++ b/include/media/media-device.h
+@@ -0,0 +1,69 @@
++/*
++ * Media device
++ *
++ * Copyright (C) 2010 Nokia Corporation
++ *
++ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _MEDIA_DEVICE_H
++#define _MEDIA_DEVICE_H
++
++#include <linux/device.h>
++#include <linux/list.h>
++
++#include <media/media-devnode.h>
++
++/**
++ * struct media_device - Media device
++ * @dev: Parent device
++ * @devnode: Media device node
++ * @model: Device model name
++ * @serial: Device serial number (optional)
++ * @bus_info: Unique and stable device location identifier
++ * @hw_revision: Hardware device revision
++ * @driver_version: Device driver version
++ *
++ * This structure represents an abstract high-level media device. It allows easy
++ * access to entities and provides basic media device-level support. The
++ * structure can be allocated directly or embedded in a larger structure.
++ *
++ * The parent @dev is a physical device. It must be set before registering the
++ * media device.
++ *
++ * @model is a descriptive model name exported through sysfs. It doesn't have to
++ * be unique.
++ */
++struct media_device {
++ /* dev->driver_data points to this struct. */
++ struct device *dev;
++ struct media_devnode devnode;
++
++ char model[32];
++ char serial[40];
++ char bus_info[32];
++ u32 hw_revision;
++ u32 driver_version;
++};
++
++/* media_devnode to media_device */
++#define to_media_device(node) container_of(node, struct media_device, devnode)
++
++int __must_check media_device_register(struct media_device *mdev);
++void media_device_unregister(struct media_device *mdev);
++
++#endif
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0010-media-Entities-pads-and-links.patch b/recipes-bsp/linux/linux-omap/media/0010-media-Entities-pads-and-links.patch
--- /dev/null
@@ -0,0 +1,690 @@
+From b4697e5a8ad1e564ea378d435c2ce190318c1027 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:40:00 +0100
+Subject: [PATCH 10/43] media: Entities, pads and links
+
+As video hardware pipelines become increasingly complex and
+configurable, the current hardware description through v4l2 subdevices
+reaches its limits. In addition to enumerating and configuring
+subdevices, video camera drivers need a way to discover and modify at
+runtime how those subdevices are connected. This is done through new
+elements called entities, pads and links.
+
+An entity is a basic media hardware building block. It can correspond to
+a large variety of logical blocks such as physical hardware devices
+(CMOS sensor for instance), logical hardware devices (a building block
+in a System-on-Chip image processing pipeline), DMA channels or physical
+connectors.
+
+A pad is a connection endpoint through which an entity can interact with
+other entities. Data (not restricted to video) produced by an entity
+flows from the entity's output to one or more entity inputs. Pads should
+not be confused with physical pins at chip boundaries.
+
+A link is a point-to-point oriented connection between two pads, either
+on the same entity or on different entities. Data flows from a source
+pad to a sink pad.
+
+Links are stored in the source entity. To make backwards graph walk
+faster, a copy of all links is also stored in the sink entity. The copy
+is known as a backlink and is only used to help graph traversal.
+
+The entity API is made of three functions:
+
+- media_entity_init() initializes an entity. The caller must provide an
+array of pads as well as an estimated number of links. The links array
+is allocated dynamically and will be reallocated if it grows beyond the
+initial estimate.
+
+- media_entity_cleanup() frees resources allocated for an entity. It
+must be called during the cleanup phase after unregistering the entity
+and before freeing it.
+
+- media_entity_create_link() creates a link between two entities. An
+entry in the link array of each entity is allocated and stores pointers
+to source and sink pads.
+
+When a media device is unregistered, all its entities are unregistered
+automatically.
+
+The code is based on Hans Verkuil <hverkuil@xs4all.nl> initial work.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ Documentation/DocBook/v4l/media-controller.xml | 20 +++
+ Documentation/media-framework.txt | 151 ++++++++++++++++++++++++
+ drivers/media/Makefile | 2 +-
+ drivers/media/media-device.c | 56 +++++++++
+ drivers/media/media-entity.c | 147 +++++++++++++++++++++++
+ include/media/media-device.h | 19 +++
+ include/media/media-entity.h | 122 +++++++++++++++++++
+ 7 files changed, 516 insertions(+), 1 deletions(-)
+ create mode 100644 drivers/media/media-entity.c
+ create mode 100644 include/media/media-entity.h
+
+diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml
+index 253ddb4..f89228d 100644
+--- a/Documentation/DocBook/v4l/media-controller.xml
++++ b/Documentation/DocBook/v4l/media-controller.xml
+@@ -53,4 +53,24 @@
+ implementing policies that belong to userspace.</para>
+ <para>The media controller API aims at solving those problems.</para>
+ </section>
++
++ <section id="media-controller-model">
++ <title>Media device model</title>
++ <para>Discovering a device internal topology, and configuring it at runtime,
++ is one of the goals of the media controller API. To achieve this, hardware
++ devices are modelled as an oriented graph of building blocks called entities
++ connected through pads.</para>
++ <para>An entity is a basic media hardware or software building block. It can
++ correspond to a large variety of logical blocks such as physical hardware
++ devices (CMOS sensor for instance), logical hardware devices (a building
++ block in a System-on-Chip image processing pipeline), DMA channels or
++ physical connectors.</para>
++ <para>A pad is a connection endpoint through which an entity can interact
++ with other entities. Data (not restricted to video) produced by an entity
++ flows from the entity's output to one or more entity inputs. Pads should not
++ be confused with physical pins at chip boundaries.</para>
++ <para>A link is a point-to-point oriented connection between two pads,
++ either on the same entity or on different entities. Data flows from a source
++ pad to a sink pad.</para>
++ </section>
+ </chapter>
+diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt
+index 1844c3f..b252cf9 100644
+--- a/Documentation/media-framework.txt
++++ b/Documentation/media-framework.txt
+@@ -13,6 +13,30 @@ Documentation/DocBook/v4l/media-controller.xml. This document will focus on
+ the kernel-side implementation of the media framework.
+
+
++Abstract media device model
++---------------------------
++
++Discovering a device internal topology, and configuring it at runtime, is one
++of the goals of the media framework. To achieve this, hardware devices are
++modeled as an oriented graph of building blocks called entities connected
++through pads.
++
++An entity is a basic media hardware building block. It can correspond to
++a large variety of logical blocks such as physical hardware devices
++(CMOS sensor for instance), logical hardware devices (a building block
++in a System-on-Chip image processing pipeline), DMA channels or physical
++connectors.
++
++A pad is a connection endpoint through which an entity can interact with
++other entities. Data (not restricted to video) produced by an entity
++flows from the entity's output to one or more entity inputs. Pads should
++not be confused with physical pins at chip boundaries.
++
++A link is a point-to-point oriented connection between two pads, either
++on the same entity or on different entities. Data flows from a source
++pad to a sink pad.
++
++
+ Media device
+ ------------
+
+@@ -65,3 +89,130 @@ Drivers unregister media device instances by calling
+ media_device_unregister(struct media_device *mdev);
+
+ Unregistering a media device that hasn't been registered is *NOT* safe.
++
++
++Entities, pads and links
++------------------------
++
++- Entities
++
++Entities are represented by a struct media_entity instance, defined in
++include/media/media-entity.h. The structure is usually embedded into a
++higher-level structure, such as a v4l2_subdev or video_device instance,
++although drivers can allocate entities directly.
++
++Drivers initialize entities by calling
++
++ media_entity_init(struct media_entity *entity, u16 num_pads,
++ struct media_pad *pads, u16 extra_links);
++
++The media_entity name, type, flags, revision and group_id fields can be
++initialized before or after calling media_entity_init. Entities embedded in
++higher-level standard structures can have some of those fields set by the
++higher-level framework.
++
++As the number of pads is known in advance, the pads array is not allocated
++dynamically but is managed by the entity driver. Most drivers will embed the
++pads array in a driver-specific structure, avoiding dynamic allocation.
++
++Drivers must set the direction of every pad in the pads array before calling
++media_entity_init. The function will initialize the other pads fields.
++
++Unlike the number of pads, the total number of links isn't always known in
++advance by the entity driver. As an initial estimate, media_entity_init
++pre-allocates a number of links equal to the number of pads plus an optional
++number of extra links. The links array will be reallocated if it grows beyond
++the initial estimate.
++
++Drivers register entities with a media device by calling
++
++ media_device_register_entity(struct media_device *mdev,
++ struct media_entity *entity);
++
++Entities are identified by a unique positive integer ID. Drivers can provide an
++ID by filling the media_entity id field prior to registration, or request the
++media controller framework to assign an ID automatically. Drivers that provide
++IDs manually must ensure that all IDs are unique. IDs are not guaranteed to be
++contiguous even when they are all assigned automatically by the framework.
++
++Drivers unregister entities by calling
++
++ media_device_unregister_entity(struct media_entity *entity);
++
++Unregistering an entity will not change the IDs of the other entities, and the
++ID will never be reused for a newly registered entity.
++
++When a media device is unregistered, all its entities are unregistered
++automatically. No manual entities unregistration is then required.
++
++Drivers free resources associated with an entity by calling
++
++ media_entity_cleanup(struct media_entity *entity);
++
++This function must be called during the cleanup phase after unregistering the
++entity. Note that the media_entity instance itself must be freed explicitly by
++the driver if required.
++
++Entities have flags that describe the entity capabilities and state.
++
++ MEDIA_ENT_FL_DEFAULT indicates the default entity for a given type.
++ This can be used to report the default audio and video devices or the
++ default camera sensor.
++
++Logical entity groups can be defined by setting the group ID of all member
++entities to the same non-zero value. An entity group serves no purpose in the
++kernel, but is reported to userspace during entities enumeration. The group_id
++field belongs to the media device driver and must not by touched by entity
++drivers.
++
++Media device drivers should define groups if several entities are logically
++bound together. Example usages include reporting
++
++ - ALSA, VBI and video nodes that carry the same media stream
++ - lens and flash controllers associated with a sensor
++
++- Pads
++
++Pads are represented by a struct media_pad instance, defined in
++include/media/media-entity.h. Each entity stores its pads in a pads array
++managed by the entity driver. Drivers usually embed the array in a
++driver-specific structure.
++
++Pads are identified by their entity and their 0-based index in the pads array.
++Both information are stored in the media_pad structure, making the media_pad
++pointer the canonical way to store and pass link references.
++
++Pads have flags that describe the pad capabilities and state.
++
++ MEDIA_PAD_FL_INPUT indicates that the pad supports sinking data.
++ MEDIA_PAD_FL_OUTPUT indicates that the pad supports sourcing data.
++
++One and only one of MEDIA_PAD_FL_INPUT and MEDIA_PAD_FL_OUTPUT must be set for
++each pad.
++
++- Links
++
++Links are represented by a struct media_link instance, defined in
++include/media/media-entity.h. Each entity stores all links originating at or
++targetting any of its pads in a links array. A given link is thus stored
++twice, once in the source entity and once in the target entity. The array is
++pre-allocated and grows dynamically as needed.
++
++Drivers create links by calling
++
++ media_entity_create_link(struct media_entity *source, u16 source_pad,
++ struct media_entity *sink, u16 sink_pad,
++ u32 flags);
++
++An entry in the link array of each entity is allocated and stores pointers
++to source and sink pads.
++
++Links have flags that describe the link capabilities and state.
++
++ MEDIA_LNK_FL_ENABLED indicates that the link is enabled and can be used
++ to transfer media data. When two or more links target a sink pad, only
++ one of them can be enabled at a time.
++ MEDIA_LNK_FL_IMMUTABLE indicates that the link enabled state can't be
++ modified at runtime. If MEDIA_LNK_FL_IMMUTABLE is set, then
++ MEDIA_LNK_FL_ENABLED must also be set since an immutable link is always
++ enabled.
+diff --git a/drivers/media/Makefile b/drivers/media/Makefile
+index 019d3e0..b890248 100644
+--- a/drivers/media/Makefile
++++ b/drivers/media/Makefile
+@@ -2,7 +2,7 @@
+ # Makefile for the kernel multimedia device drivers.
+ #
+
+-media-objs := media-device.o media-devnode.o
++media-objs := media-device.o media-devnode.o media-entity.o
+
+ ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
+ obj-$(CONFIG_MEDIA_SUPPORT) += media.o
+diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
+index 57a9c6b..b8a3ace 100644
+--- a/drivers/media/media-device.c
++++ b/drivers/media/media-device.c
+@@ -25,6 +25,7 @@
+
+ #include <media/media-device.h>
+ #include <media/media-devnode.h>
++#include <media/media-entity.h>
+
+ static const struct media_file_operations media_device_fops = {
+ .owner = THIS_MODULE,
+@@ -69,6 +70,10 @@ int __must_check media_device_register(struct media_device *mdev)
+ if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0))
+ return -EINVAL;
+
++ mdev->entity_id = 1;
++ INIT_LIST_HEAD(&mdev->entities);
++ spin_lock_init(&mdev->lock);
++
+ /* Register the device node. */
+ mdev->devnode.fops = &media_device_fops;
+ mdev->devnode.parent = mdev->dev;
+@@ -94,7 +99,58 @@ EXPORT_SYMBOL_GPL(media_device_register);
+ */
+ void media_device_unregister(struct media_device *mdev)
+ {
++ struct media_entity *entity;
++ struct media_entity *next;
++
++ list_for_each_entry_safe(entity, next, &mdev->entities, list)
++ media_device_unregister_entity(entity);
++
+ device_remove_file(&mdev->devnode.dev, &dev_attr_model);
+ media_devnode_unregister(&mdev->devnode);
+ }
+ EXPORT_SYMBOL_GPL(media_device_unregister);
++
++/**
++ * media_device_register_entity - Register an entity with a media device
++ * @mdev: The media device
++ * @entity: The entity
++ */
++int __must_check media_device_register_entity(struct media_device *mdev,
++ struct media_entity *entity)
++{
++ /* Warn if we apparently re-register an entity */
++ WARN_ON(entity->parent != NULL);
++ entity->parent = mdev;
++
++ spin_lock(&mdev->lock);
++ if (entity->id == 0)
++ entity->id = mdev->entity_id++;
++ else
++ mdev->entity_id = max(entity->id + 1, mdev->entity_id);
++ list_add_tail(&entity->list, &mdev->entities);
++ spin_unlock(&mdev->lock);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(media_device_register_entity);
++
++/**
++ * media_device_unregister_entity - Unregister an entity
++ * @entity: The entity
++ *
++ * If the entity has never been registered this function will return
++ * immediately.
++ */
++void media_device_unregister_entity(struct media_entity *entity)
++{
++ struct media_device *mdev = entity->parent;
++
++ if (mdev == NULL)
++ return;
++
++ spin_lock(&mdev->lock);
++ list_del(&entity->list);
++ spin_unlock(&mdev->lock);
++ entity->parent = NULL;
++}
++EXPORT_SYMBOL_GPL(media_device_unregister_entity);
+diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
+new file mode 100644
+index 0000000..e4ba2bc
+--- /dev/null
++++ b/drivers/media/media-entity.c
+@@ -0,0 +1,147 @@
++/*
++ * Media entity
++ *
++ * Copyright (C) 2010 Nokia Corporation
++ *
++ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <media/media-entity.h>
++
++/**
++ * media_entity_init - Initialize a media entity
++ *
++ * @num_pads: Total number of input and output pads.
++ * @extra_links: Initial estimate of the number of extra links.
++ * @pads: Array of 'num_pads' pads.
++ *
++ * The total number of pads is an intrinsic property of entities known by the
++ * entity driver, while the total number of links depends on hardware design
++ * and is an extrinsic property unknown to the entity driver. However, in most
++ * use cases the entity driver can guess the number of links which can safely
++ * be assumed to be equal to or larger than the number of pads.
++ *
++ * For those reasons the links array can be preallocated based on the entity
++ * driver guess and will be reallocated later if extra links need to be
++ * created.
++ *
++ * This function allocates a links array with enough space to hold at least
++ * 'num_pads' + 'extra_links' elements. The media_entity::max_links field will
++ * be set to the number of allocated elements.
++ *
++ * The pads array is managed by the entity driver and passed to
++ * media_entity_init() where its pointer will be stored in the entity structure.
++ */
++int
++media_entity_init(struct media_entity *entity, u16 num_pads,
++ struct media_pad *pads, u16 extra_links)
++{
++ struct media_link *links;
++ unsigned int max_links = num_pads + extra_links;
++ unsigned int i;
++
++ links = kzalloc(max_links * sizeof(links[0]), GFP_KERNEL);
++ if (links == NULL)
++ return -ENOMEM;
++
++ entity->group_id = 0;
++ entity->max_links = max_links;
++ entity->num_links = 0;
++ entity->num_backlinks = 0;
++ entity->num_pads = num_pads;
++ entity->pads = pads;
++ entity->links = links;
++
++ for (i = 0; i < num_pads; i++) {
++ pads[i].entity = entity;
++ pads[i].index = i;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(media_entity_init);
++
++void
++media_entity_cleanup(struct media_entity *entity)
++{
++ kfree(entity->links);
++}
++EXPORT_SYMBOL_GPL(media_entity_cleanup);
++
++static struct media_link *media_entity_add_link(struct media_entity *entity)
++{
++ if (entity->num_links >= entity->max_links) {
++ struct media_link *links = entity->links;
++ unsigned int max_links = entity->max_links + 2;
++ unsigned int i;
++
++ links = krealloc(links, max_links * sizeof(*links), GFP_KERNEL);
++ if (links == NULL)
++ return NULL;
++
++ for (i = 0; i < entity->num_links; i++)
++ links[i].reverse->reverse = &links[i];
++
++ entity->max_links = max_links;
++ entity->links = links;
++ }
++
++ return &entity->links[entity->num_links++];
++}
++
++int
++media_entity_create_link(struct media_entity *source, u16 source_pad,
++ struct media_entity *sink, u16 sink_pad, u32 flags)
++{
++ struct media_link *link;
++ struct media_link *backlink;
++
++ BUG_ON(source == NULL || sink == NULL);
++ BUG_ON(source_pad >= source->num_pads);
++ BUG_ON(sink_pad >= sink->num_pads);
++
++ link = media_entity_add_link(source);
++ if (link == NULL)
++ return -ENOMEM;
++
++ link->source = &source->pads[source_pad];
++ link->sink = &sink->pads[sink_pad];
++ link->flags = flags;
++
++ /* Create the backlink. Backlinks are used to help graph traversal and
++ * are not reported to userspace.
++ */
++ backlink = media_entity_add_link(sink);
++ if (backlink == NULL) {
++ source->num_links--;
++ return -ENOMEM;
++ }
++
++ backlink->source = &source->pads[source_pad];
++ backlink->sink = &sink->pads[sink_pad];
++ backlink->flags = flags;
++
++ link->reverse = backlink;
++ backlink->reverse = link;
++
++ sink->num_backlinks++;
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(media_entity_create_link);
+diff --git a/include/media/media-device.h b/include/media/media-device.h
+index e11f01a..0b1ecf5 100644
+--- a/include/media/media-device.h
++++ b/include/media/media-device.h
+@@ -25,8 +25,10 @@
+
+ #include <linux/device.h>
+ #include <linux/list.h>
++#include <linux/spinlock.h>
+
+ #include <media/media-devnode.h>
++#include <media/media-entity.h>
+
+ /**
+ * struct media_device - Media device
+@@ -37,6 +39,9 @@
+ * @bus_info: Unique and stable device location identifier
+ * @hw_revision: Hardware device revision
+ * @driver_version: Device driver version
++ * @entity_id: ID of the next entity to be registered
++ * @entities: List of registered entities
++ * @lock: Entities list lock
+ *
+ * This structure represents an abstract high-level media device. It allows easy
+ * access to entities and provides basic media device-level support. The
+@@ -58,6 +63,12 @@ struct media_device {
+ char bus_info[32];
+ u32 hw_revision;
+ u32 driver_version;
++
++ u32 entity_id;
++ struct list_head entities;
++
++ /* Protects the entities list */
++ spinlock_t lock;
+ };
+
+ /* media_devnode to media_device */
+@@ -66,4 +77,12 @@ struct media_device {
+ int __must_check media_device_register(struct media_device *mdev);
+ void media_device_unregister(struct media_device *mdev);
+
++int __must_check media_device_register_entity(struct media_device *mdev,
++ struct media_entity *entity);
++void media_device_unregister_entity(struct media_entity *entity);
++
++/* Iterate over all entities. */
++#define media_device_for_each_entity(entity, mdev) \
++ list_for_each_entry(entity, &(mdev)->entities, list)
++
+ #endif
+diff --git a/include/media/media-entity.h b/include/media/media-entity.h
+new file mode 100644
+index 0000000..7cf9135
+--- /dev/null
++++ b/include/media/media-entity.h
+@@ -0,0 +1,122 @@
++/*
++ * Media entity
++ *
++ * Copyright (C) 2010 Nokia Corporation
++ *
++ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _MEDIA_ENTITY_H
++#define _MEDIA_ENTITY_H
++
++#include <linux/list.h>
++
++#define MEDIA_ENT_TYPE_SHIFT 16
++#define MEDIA_ENT_TYPE_MASK 0x00ff0000
++#define MEDIA_ENT_SUBTYPE_MASK 0x0000ffff
++
++#define MEDIA_ENT_T_DEVNODE (1 << MEDIA_ENTITY_TYPE_SHIFT)
++#define MEDIA_ENT_T_DEVNODE_V4L (MEDIA_ENTITY_T_DEVNODE + 1)
++#define MEDIA_ENT_T_DEVNODE_FB (MEDIA_ENTITY_T_DEVNODE + 2)
++#define MEDIA_ENT_T_DEVNODE_ALSA (MEDIA_ENTITY_T_DEVNODE + 3)
++#define MEDIA_ENT_T_DEVNODE_DVB (MEDIA_ENTITY_T_DEVNODE + 4)
++
++#define MEDIA_ENT_T_V4L2_SUBDEV (2 << MEDIA_ENTITY_TYPE_SHIFT)
++#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR (MEDIA_ENTITY_T_V4L2_SUBDEV + 1)
++#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH (MEDIA_ENTITY_T_V4L2_SUBDEV + 2)
++#define MEDIA_ENT_T_V4L2_SUBDEV_LENS (MEDIA_ENTITY_T_V4L2_SUBDEV + 3)
++
++#define MEDIA_ENT_FL_DEFAULT (1 << 0)
++
++#define MEDIA_LNK_FL_ENABLED (1 << 0)
++#define MEDIA_LNK_FL_IMMUTABLE (1 << 1)
++
++#define MEDIA_PAD_FL_INPUT (1 << 0)
++#define MEDIA_PAD_FL_OUTPUT (1 << 1)
++
++struct media_link {
++ struct media_pad *source; /* Source pad */
++ struct media_pad *sink; /* Sink pad */
++ struct media_link *reverse; /* Link in the reverse direction */
++ unsigned long flags; /* Link flags (MEDIA_LNK_FL_*) */
++};
++
++struct media_pad {
++ struct media_entity *entity; /* Entity this pad belongs to */
++ u16 index; /* Pad index in the entity pads array */
++ unsigned long flags; /* Pad flags (MEDIA_PAD_FL_*) */
++};
++
++struct media_entity {
++ struct list_head list;
++ struct media_device *parent; /* Media device this entity belongs to*/
++ u32 id; /* Entity ID, unique in the parent media
++ * device context */
++ const char *name; /* Entity name */
++ u32 type; /* Entity type (MEDIA_ENT_T_*) */
++ u32 revision; /* Entity revision, driver specific */
++ unsigned long flags; /* Entity flags (MEDIA_ENT_FL_*) */
++ u32 group_id; /* Entity group ID */
++
++ u16 num_pads; /* Number of input and output pads */
++ u16 num_links; /* Number of existing links, both
++ * enabled and disabled */
++ u16 num_backlinks; /* Number of backlinks */
++ u16 max_links; /* Maximum number of links */
++
++ struct media_pad *pads; /* Pads array (num_pads elements) */
++ struct media_link *links; /* Links array (max_links elements)*/
++
++ union {
++ /* Node specifications */
++ struct {
++ u32 major;
++ u32 minor;
++ } v4l;
++ struct {
++ u32 major;
++ u32 minor;
++ } fb;
++ struct {
++ u32 card;
++ u32 device;
++ u32 subdevice;
++ } alsa;
++ int dvb;
++
++ /* Sub-device specifications */
++ /* Nothing needed yet */
++ };
++};
++
++static inline u32 media_entity_type(struct media_entity *entity)
++{
++ return entity->type & MEDIA_ENT_TYPE_MASK;
++}
++
++static inline u32 media_entity_subtype(struct media_entity *entity)
++{
++ return entity->type & MEDIA_ENT_SUBTYPE_MASK;
++}
++
++int media_entity_init(struct media_entity *entity, u16 num_pads,
++ struct media_pad *pads, u16 extra_links);
++void media_entity_cleanup(struct media_entity *entity);
++int media_entity_create_link(struct media_entity *source, u16 source_pad,
++ struct media_entity *sink, u16 sink_pad, u32 flags);
++
++#endif
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0011-media-Entity-graph-traversal.patch b/recipes-bsp/linux/linux-omap/media/0011-media-Entity-graph-traversal.patch
--- /dev/null
@@ -0,0 +1,228 @@
+From 5b45472e8a692e6acea3cb6d601b44c17ea8d59e Mon Sep 17 00:00:00 2001
+From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Date: Sun, 7 Mar 2010 21:14:14 +0200
+Subject: [PATCH 11/43] media: Entity graph traversal
+
+Add media entity graph traversal. The traversal follows enabled links by
+depth first. Traversing graph backwards is prevented by comparing the next
+possible entity in the graph with the previous one. Multiply connected
+graphs are thus not supported.
+
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Vimarsh Zutshi <vimarsh.zutshi@nokia.com>
+---
+ Documentation/media-framework.txt | 42 +++++++++++++
+ drivers/media/media-entity.c | 115 +++++++++++++++++++++++++++++++++++++
+ include/media/media-entity.h | 15 +++++
+ 3 files changed, 172 insertions(+), 0 deletions(-)
+
+diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt
+index b252cf9..88fe379 100644
+--- a/Documentation/media-framework.txt
++++ b/Documentation/media-framework.txt
+@@ -216,3 +216,45 @@ Links have flags that describe the link capabilities and state.
+ modified at runtime. If MEDIA_LNK_FL_IMMUTABLE is set, then
+ MEDIA_LNK_FL_ENABLED must also be set since an immutable link is always
+ enabled.
++
++
++Graph traversal
++---------------
++
++The media framework provides APIs to iterate over entities in a graph.
++
++To iterate over all entities belonging to a media device, drivers can use the
++media_device_for_each_entity macro, defined in include/media/media-device.h.
++
++ struct media_entity *entity;
++
++ media_device_for_each_entity(entity, mdev) {
++ /* entity will point to each entity in turn */
++ ...
++ }
++
++Drivers might also need to iterate over all entities in a graph that can be
++reached only through enabled links starting at a given entity. The media
++framework provides a depth-first graph traversal API for that purpose.
++
++Note that graphs with cycles (whether directed or undirected) are *NOT*
++supported by the graph traversal API. To prevent infinite loops, the graph
++traversal code limits the maximum depth to MEDIA_ENTITY_ENUM_MAX_DEPTH,
++currently defined as 16.
++
++Drivers initiate a graph traversal by calling
++
++ media_entity_graph_walk_start(struct media_entity_graph *graph,
++ struct media_entity *entity);
++
++The graph structure, provided by the caller, is initialized to start graph
++traversal at the given entity.
++
++Drivers can then retrieve the next entity by calling
++
++ media_entity_graph_walk_next(struct media_entity_graph *graph);
++
++When the graph traversal is complete the function will return NULL.
++
++Graph traversal can be interrupted at any moment. No cleanup function call is
++required and the graph structure can be freed normally.
+diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
+index e4ba2bc..a805f20 100644
+--- a/drivers/media/media-entity.c
++++ b/drivers/media/media-entity.c
+@@ -84,6 +84,121 @@ media_entity_cleanup(struct media_entity *entity)
+ }
+ EXPORT_SYMBOL_GPL(media_entity_cleanup);
+
++/* -----------------------------------------------------------------------------
++ * Graph traversal
++ */
++
++static struct media_entity *
++media_entity_other(struct media_entity *entity, struct media_link *link)
++{
++ if (link->source->entity == entity)
++ return link->sink->entity;
++ else
++ return link->source->entity;
++}
++
++/* push an entity to traversal stack */
++static void stack_push(struct media_entity_graph *graph,
++ struct media_entity *entity)
++{
++ if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
++ WARN_ON(1);
++ return;
++ }
++ graph->top++;
++ graph->stack[graph->top].link = 0;
++ graph->stack[graph->top].entity = entity;
++}
++
++static struct media_entity *stack_pop(struct media_entity_graph *graph)
++{
++ struct media_entity *entity;
++
++ entity = graph->stack[graph->top].entity;
++ graph->top--;
++
++ return entity;
++}
++
++#define stack_peek(en) ((en)->stack[(en)->top - 1].entity)
++#define link_top(en) ((en)->stack[(en)->top].link)
++#define stack_top(en) ((en)->stack[(en)->top].entity)
++
++/**
++ * media_entity_graph_walk_start - Start walking the media graph at a given entity
++ * @graph: Media graph structure that will be used to walk the graph
++ * @entity: Starting entity
++ *
++ * This function initializes the graph traversal structure to walk the entities
++ * graph starting at the given entity. The traversal structure must not be
++ * modified by the caller during graph traversal. When done the structure can
++ * safely be freed.
++ */
++void media_entity_graph_walk_start(struct media_entity_graph *graph,
++ struct media_entity *entity)
++{
++ graph->top = 0;
++ graph->stack[graph->top].entity = NULL;
++ stack_push(graph, entity);
++}
++EXPORT_SYMBOL_GPL(media_entity_graph_walk_start);
++
++/**
++ * media_entity_graph_walk_next - Get the next entity in the graph
++ * @graph: Media graph structure
++ *
++ * Perform a depth-first traversal of the given media entities graph.
++ *
++ * The graph structure must have been previously initialized with a call to
++ * media_entity_graph_walk_start().
++ *
++ * Return the next entity in the graph or NULL if the whole graph have been
++ * traversed.
++ */
++struct media_entity *
++media_entity_graph_walk_next(struct media_entity_graph *graph)
++{
++ if (stack_top(graph) == NULL)
++ return NULL;
++
++ /*
++ * Depth first search. Push entity to stack and continue from
++ * top of the stack until no more entities on the level can be
++ * found.
++ */
++ while (link_top(graph) < stack_top(graph)->num_links) {
++ struct media_entity *entity = stack_top(graph);
++ struct media_link *link = &entity->links[link_top(graph)];
++ struct media_entity *next;
++
++ /* The link is not enabled so we do not follow. */
++ if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
++ link_top(graph)++;
++ continue;
++ }
++
++ /* Get the entity in the other end of the link . */
++ next = media_entity_other(entity, link);
++
++ /* Was it the entity we came here from? */
++ if (next == stack_peek(graph)) {
++ link_top(graph)++;
++ continue;
++ }
++
++ /* Push the new entity to stack and start over. */
++ link_top(graph)++;
++ stack_push(graph, next);
++ }
++
++ return stack_pop(graph);
++}
++EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
++
++/* -----------------------------------------------------------------------------
++ * Links management
++ */
++
+ static struct media_link *media_entity_add_link(struct media_entity *entity)
+ {
+ if (entity->num_links >= entity->max_links) {
+diff --git a/include/media/media-entity.h b/include/media/media-entity.h
+index 7cf9135..b82f824 100644
+--- a/include/media/media-entity.h
++++ b/include/media/media-entity.h
+@@ -113,10 +113,25 @@ static inline u32 media_entity_subtype(struct media_entity *entity)
+ return entity->type & MEDIA_ENT_SUBTYPE_MASK;
+ }
+
++#define MEDIA_ENTITY_ENUM_MAX_DEPTH 16
++
++struct media_entity_graph {
++ struct {
++ struct media_entity *entity;
++ int link;
++ } stack[MEDIA_ENTITY_ENUM_MAX_DEPTH];
++ int top;
++};
++
+ int media_entity_init(struct media_entity *entity, u16 num_pads,
+ struct media_pad *pads, u16 extra_links);
+ void media_entity_cleanup(struct media_entity *entity);
+ int media_entity_create_link(struct media_entity *source, u16 source_pad,
+ struct media_entity *sink, u16 sink_pad, u32 flags);
+
++void media_entity_graph_walk_start(struct media_entity_graph *graph,
++ struct media_entity *entity);
++struct media_entity *
++media_entity_graph_walk_next(struct media_entity_graph *graph);
++
+ #endif
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0012-media-Entity-use-count.patch b/recipes-bsp/linux/linux-omap/media/0012-media-Entity-use-count.patch
--- /dev/null
@@ -0,0 +1,176 @@
+From 3be6a2d10ff0cad0b240c65054da28395b014f82 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Sun, 7 Mar 2010 20:04:59 +0200
+Subject: [PATCH 12/43] media: Entity use count
+
+Due to the wide differences between drivers regarding power management
+needs, the media controller does not implement power management.
+However, the media_entity structure includes a use_count field that
+media drivers can use to track the number of users of every entity for
+power management needs.
+
+The use_count field is owned by media drivers and must not be touched by
+entity drivers. Access to the field must be protected by the media
+device graph_mutex lock.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ Documentation/media-framework.txt | 13 ++++++++++
+ drivers/media/media-device.c | 1 +
+ drivers/media/media-entity.c | 46 +++++++++++++++++++++++++++++++++++++
+ include/media/media-device.h | 4 +++
+ include/media/media-entity.h | 5 ++++
+ 5 files changed, 69 insertions(+), 0 deletions(-)
+
+diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt
+index 88fe379..9017a41 100644
+--- a/Documentation/media-framework.txt
++++ b/Documentation/media-framework.txt
+@@ -258,3 +258,16 @@ When the graph traversal is complete the function will return NULL.
+
+ Graph traversal can be interrupted at any moment. No cleanup function call is
+ required and the graph structure can be freed normally.
++
++
++Use count and power handling
++----------------------------
++
++Due to the wide differences between drivers regarding power management needs,
++the media controller does not implement power management. However, the
++media_entity structure includes a use_count field that media drivers can use to
++track the number of users of every entity for power management needs.
++
++The use_count field is owned by media drivers and must not be touched by entity
++drivers. Access to the field must be protected by the media device graph_mutex
++lock.
+diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
+index b8a3ace..e4c2157 100644
+--- a/drivers/media/media-device.c
++++ b/drivers/media/media-device.c
+@@ -73,6 +73,7 @@ int __must_check media_device_register(struct media_device *mdev)
+ mdev->entity_id = 1;
+ INIT_LIST_HEAD(&mdev->entities);
+ spin_lock_init(&mdev->lock);
++ mutex_init(&mdev->graph_mutex);
+
+ /* Register the device node. */
+ mdev->devnode.fops = &media_device_fops;
+diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
+index a805f20..fe6bfd2 100644
+--- a/drivers/media/media-entity.c
++++ b/drivers/media/media-entity.c
+@@ -23,6 +23,7 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <media/media-entity.h>
++#include <media/media-device.h>
+
+ /**
+ * media_entity_init - Initialize a media entity
+@@ -196,6 +197,51 @@ media_entity_graph_walk_next(struct media_entity_graph *graph)
+ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
+
+ /* -----------------------------------------------------------------------------
++ * Module use count
++ */
++
++/*
++ * media_entity_get - Get a reference to the parent module
++ * @entity: The entity
++ *
++ * Get a reference to the parent media device module.
++ *
++ * The function will return immediately if @entity is NULL.
++ *
++ * Return a pointer to the entity on success or NULL on failure.
++ */
++struct media_entity *media_entity_get(struct media_entity *entity)
++{
++ if (entity == NULL)
++ return NULL;
++
++ if (entity->parent->dev &&
++ !try_module_get(entity->parent->dev->driver->owner))
++ return NULL;
++
++ return entity;
++}
++EXPORT_SYMBOL_GPL(media_entity_get);
++
++/*
++ * media_entity_put - Release the reference to the parent module
++ * @entity: The entity
++ *
++ * Release the reference count acquired by media_entity_get().
++ *
++ * The function will return immediately if @entity is NULL.
++ */
++void media_entity_put(struct media_entity *entity)
++{
++ if (entity == NULL)
++ return;
++
++ if (entity->parent->dev)
++ module_put(entity->parent->dev->driver->owner);
++}
++EXPORT_SYMBOL_GPL(media_entity_put);
++
++/* -----------------------------------------------------------------------------
+ * Links management
+ */
+
+diff --git a/include/media/media-device.h b/include/media/media-device.h
+index 0b1ecf5..260d59c 100644
+--- a/include/media/media-device.h
++++ b/include/media/media-device.h
+@@ -25,6 +25,7 @@
+
+ #include <linux/device.h>
+ #include <linux/list.h>
++#include <linux/mutex.h>
+ #include <linux/spinlock.h>
+
+ #include <media/media-devnode.h>
+@@ -42,6 +43,7 @@
+ * @entity_id: ID of the next entity to be registered
+ * @entities: List of registered entities
+ * @lock: Entities list lock
++ * @graph_mutex: Entities graph operation lock
+ *
+ * This structure represents an abstract high-level media device. It allows easy
+ * access to entities and provides basic media device-level support. The
+@@ -69,6 +71,8 @@ struct media_device {
+
+ /* Protects the entities list */
+ spinlock_t lock;
++ /* Serializes graph operations. */
++ struct mutex graph_mutex;
+ };
+
+ /* media_devnode to media_device */
+diff --git a/include/media/media-entity.h b/include/media/media-entity.h
+index b82f824..114541a 100644
+--- a/include/media/media-entity.h
++++ b/include/media/media-entity.h
+@@ -81,6 +81,8 @@ struct media_entity {
+ struct media_pad *pads; /* Pads array (num_pads elements) */
+ struct media_link *links; /* Links array (max_links elements)*/
+
++ int use_count; /* Use count for the entity. */
++
+ union {
+ /* Node specifications */
+ struct {
+@@ -129,6 +131,9 @@ void media_entity_cleanup(struct media_entity *entity);
+ int media_entity_create_link(struct media_entity *source, u16 source_pad,
+ struct media_entity *sink, u16 sink_pad, u32 flags);
+
++struct media_entity *media_entity_get(struct media_entity *entity);
++void media_entity_put(struct media_entity *entity);
++
+ void media_entity_graph_walk_start(struct media_entity_graph *graph,
+ struct media_entity *entity);
+ struct media_entity *
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0013-media-Media-device-information-query.patch b/recipes-bsp/linux/linux-omap/media/0013-media-Media-device-information-query.patch
--- /dev/null
@@ -0,0 +1,659 @@
+From cb6936ced565e168ac7f9be06dc3320733aac17f Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 18 Aug 2010 16:41:22 +0200
+Subject: [PATCH 13/43] media: Media device information query
+
+Create the following ioctl and implement it at the media device level to
+query device information.
+
+- MEDIA_IOC_DEVICE_INFO: Query media device information
+
+The ioctl and its data structure are defined in the new kernel header
+linux/media.h available to userspace applications.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ Documentation/DocBook/media-entities.tmpl | 12 ++
+ Documentation/DocBook/v4l/media-controller.xml | 10 ++
+ Documentation/DocBook/v4l/media-func-close.xml | 59 +++++++++
+ Documentation/DocBook/v4l/media-func-ioctl.xml | 116 +++++++++++++++++
+ Documentation/DocBook/v4l/media-func-open.xml | 94 ++++++++++++++
+ .../DocBook/v4l/media-ioc-device-info.xml | 132 ++++++++++++++++++++
+ drivers/media/media-device.c | 57 +++++++++
+ include/linux/Kbuild | 1 +
+ include/linux/media.h | 45 +++++++
+ 9 files changed, 526 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/DocBook/v4l/media-func-close.xml
+ create mode 100644 Documentation/DocBook/v4l/media-func-ioctl.xml
+ create mode 100644 Documentation/DocBook/v4l/media-func-open.xml
+ create mode 100644 Documentation/DocBook/v4l/media-ioc-device-info.xml
+ create mode 100644 include/linux/media.h
+
+diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
+index 61d6f11..6af3375 100644
+--- a/Documentation/DocBook/media-entities.tmpl
++++ b/Documentation/DocBook/media-entities.tmpl
+@@ -11,6 +11,10 @@
+ <!ENTITY func-select "<link linkend='func-select'><function>select()</function></link>">
+ <!ENTITY func-write "<link linkend='func-write'><function>write()</function></link>">
+
++<!ENTITY media-func-close "<link linkend='media-func-close'><function>close()</function></link>">
++<!ENTITY media-func-ioctl "<link linkend='media-func-ioctl'><function>ioctl()</function></link>">
++<!ENTITY media-func-open "<link linkend='media-func-open'><function>open()</function></link>">
++
+ <!-- Ioctls -->
+ <!ENTITY VIDIOC-CROPCAP "<link linkend='vidioc-cropcap'><constant>VIDIOC_CROPCAP</constant></link>">
+ <!ENTITY VIDIOC-DBG-G-CHIP-IDENT "<link linkend='vidioc-dbg-g-chip-ident'><constant>VIDIOC_DBG_G_CHIP_IDENT</constant></link>">
+@@ -87,6 +91,8 @@
+ <!ENTITY VIDIOC-TRY-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_TRY_FMT</constant></link>">
+ <!ENTITY VIDIOC-UNSUBSCRIBE-EVENT "<link linkend='vidioc-subscribe-event'><constant>VIDIOC_UNSUBSCRIBE_EVENT</constant></link>">
+
++<!ENTITY MEDIA-IOC-DEVICE-INFO "<link linkend='media-ioc-device-info'><constant>MEDIA_IOC_DEVICE_INFO</constant></link>">
++
+ <!-- Types -->
+ <!ENTITY v4l2-std-id "<link linkend='v4l2-std-id'>v4l2_std_id</link>">
+
+@@ -181,6 +187,8 @@
+ <!ENTITY v4l2-vbi-format "struct <link linkend='v4l2-vbi-format'>v4l2_vbi_format</link>">
+ <!ENTITY v4l2-window "struct <link linkend='v4l2-window'>v4l2_window</link>">
+
++<!ENTITY media-device-info "struct <link linkend='media-device-info'>media_device_info</link>">
++
+ <!-- Error Codes -->
+ <!ENTITY EACCES "<errorcode>EACCES</errorcode> error code">
+ <!ENTITY EAGAIN "<errorcode>EAGAIN</errorcode> error code">
+@@ -322,6 +330,10 @@
+ <!ENTITY sub-media-indices SYSTEM "media-indices.tmpl">
+
+ <!ENTITY sub-media-controller SYSTEM "v4l/media-controller.xml">
++<!ENTITY sub-media-open SYSTEM "v4l/media-func-open.xml">
++<!ENTITY sub-media-close SYSTEM "v4l/media-func-close.xml">
++<!ENTITY sub-media-ioctl SYSTEM "v4l/media-func-ioctl.xml">
++<!ENTITY sub-media-ioc-device-info SYSTEM "v4l/media-ioc-device-info.xml">
+
+ <!-- Function Reference -->
+ <!ENTITY close SYSTEM "v4l/func-close.xml">
+diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml
+index f89228d..a46b786 100644
+--- a/Documentation/DocBook/v4l/media-controller.xml
++++ b/Documentation/DocBook/v4l/media-controller.xml
+@@ -74,3 +74,13 @@
+ pad to a sink pad.</para>
+ </section>
+ </chapter>
++
++<appendix id="media-user-func">
++ <title>Function Reference</title>
++ <!-- Keep this alphabetically sorted. -->
++ &sub-media-open;
++ &sub-media-close;
++ &sub-media-ioctl;
++ <!-- All ioctls go here. -->
++ &sub-media-ioc-device-info;
++</appendix>
+diff --git a/Documentation/DocBook/v4l/media-func-close.xml b/Documentation/DocBook/v4l/media-func-close.xml
+new file mode 100644
+index 0000000..be149c8
+--- /dev/null
++++ b/Documentation/DocBook/v4l/media-func-close.xml
+@@ -0,0 +1,59 @@
++<refentry id="media-func-close">
++ <refmeta>
++ <refentrytitle>media close()</refentrytitle>
++ &manvol;
++ </refmeta>
++
++ <refnamediv>
++ <refname>media-close</refname>
++ <refpurpose>Close a media device</refpurpose>
++ </refnamediv>
++
++ <refsynopsisdiv>
++ <funcsynopsis>
++ <funcsynopsisinfo>#include <unistd.h></funcsynopsisinfo>
++ <funcprototype>
++ <funcdef>int <function>close</function></funcdef>
++ <paramdef>int <parameter>fd</parameter></paramdef>
++ </funcprototype>
++ </funcsynopsis>
++ </refsynopsisdiv>
++
++ <refsect1>
++ <title>Arguments</title>
++
++ <variablelist>
++ <varlistentry>
++ <term><parameter>fd</parameter></term>
++ <listitem>
++ <para>&fd;</para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++
++ <refsect1>
++ <title>Description</title>
++
++ <para>Closes the media device. Resources associated with the file descriptor
++ are freed. The device configuration remain unchanged.</para>
++ </refsect1>
++
++ <refsect1>
++ <title>Return Value</title>
++
++ <para><function>close</function> returns 0 on success. On error, -1 is
++ returned, and <varname>errno</varname> is set appropriately. Possible error
++ codes are:</para>
++
++ <variablelist>
++ <varlistentry>
++ <term><errorcode>EBADF</errorcode></term>
++ <listitem>
++ <para><parameter>fd</parameter> is not a valid open file descriptor.
++ </para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++</refentry>
+diff --git a/Documentation/DocBook/v4l/media-func-ioctl.xml b/Documentation/DocBook/v4l/media-func-ioctl.xml
+new file mode 100644
+index 0000000..bda8604
+--- /dev/null
++++ b/Documentation/DocBook/v4l/media-func-ioctl.xml
+@@ -0,0 +1,116 @@
++<refentry id="media-func-ioctl">
++ <refmeta>
++ <refentrytitle>media ioctl()</refentrytitle>
++ &manvol;
++ </refmeta>
++
++ <refnamediv>
++ <refname>media-ioctl</refname>
++ <refpurpose>Control a media device</refpurpose>
++ </refnamediv>
++
++ <refsynopsisdiv>
++ <funcsynopsis>
++ <funcsynopsisinfo>#include <sys/ioctl.h></funcsynopsisinfo>
++ <funcprototype>
++ <funcdef>int <function>ioctl</function></funcdef>
++ <paramdef>int <parameter>fd</parameter></paramdef>
++ <paramdef>int <parameter>request</parameter></paramdef>
++ <paramdef>void *<parameter>argp</parameter></paramdef>
++ </funcprototype>
++ </funcsynopsis>
++ </refsynopsisdiv>
++
++ <refsect1>
++ <title>Arguments</title>
++
++ <variablelist>
++ <varlistentry>
++ <term><parameter>fd</parameter></term>
++ <listitem>
++ <para>&fd;</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><parameter>request</parameter></term>
++ <listitem>
++ <para>Media ioctl request code as defined in the media.h header file,
++ for example MEDIA_IOC_SETUP_LINK.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><parameter>argp</parameter></term>
++ <listitem>
++ <para>Pointer to a request-specific structure.</para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++
++ <refsect1>
++ <title>Description</title>
++ <para>The <function>ioctl()</function> function manipulates media device
++ parameters. The argument <parameter>fd</parameter> must be an open file
++ descriptor.</para>
++ <para>The ioctl <parameter>request</parameter> code specifies the media
++ function to be called. It has encoded in it whether the argument is an
++ input, output or read/write parameter, and the size of the argument
++ <parameter>argp</parameter> in bytes.</para>
++ <para>Macros and structures definitions specifying media ioctl requests and
++ their parameters are located in the media.h header file. All media ioctl
++ requests, their respective function and parameters are specified in
++ <xref linkend="media-user-func" />.</para>
++ </refsect1>
++
++ <refsect1>
++ <title>Return Value</title>
++
++ <para><function>ioctl()</function> returns <returnvalue>0</returnvalue> on
++ success. On failure, <returnvalue>-1</returnvalue> is returned, and the
++ <varname>errno</varname> variable is set appropriately. Generic error codes
++ are listed below, and request-specific error codes are listed in the
++ individual requests descriptions.</para>
++ <para>When an ioctl that takes an output or read/write parameter fails,
++ the parameter remains unmodified.</para>
++
++ <variablelist>
++ <varlistentry>
++ <term><errorcode>EBADF</errorcode></term>
++ <listitem>
++ <para><parameter>fd</parameter> is not a valid open file descriptor.
++ </para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><errorcode>EFAULT</errorcode></term>
++ <listitem>
++ <para><parameter>argp</parameter> references an inaccessible memory
++ area.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><errorcode>EINVAL</errorcode></term>
++ <listitem>
++ <para>The <parameter>request</parameter> or the data pointed to by
++ <parameter>argp</parameter> is not valid. This is a very common error
++ code, see the individual ioctl requests listed in
++ <xref linkend="media-user-func" /> for actual causes.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><errorcode>ENOMEM</errorcode></term>
++ <listitem>
++ <para>Insufficient kernel memory was available to complete the
++ request.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><errorcode>ENOTTY</errorcode></term>
++ <listitem>
++ <para><parameter>fd</parameter> is not associated with a character
++ special device.</para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++</refentry>
+diff --git a/Documentation/DocBook/v4l/media-func-open.xml b/Documentation/DocBook/v4l/media-func-open.xml
+new file mode 100644
+index 0000000..f7df034
+--- /dev/null
++++ b/Documentation/DocBook/v4l/media-func-open.xml
+@@ -0,0 +1,94 @@
++<refentry id="media-func-open">
++ <refmeta>
++ <refentrytitle>media open()</refentrytitle>
++ &manvol;
++ </refmeta>
++
++ <refnamediv>
++ <refname>media-open</refname>
++ <refpurpose>Open a media device</refpurpose>
++ </refnamediv>
++
++ <refsynopsisdiv>
++ <funcsynopsis>
++ <funcsynopsisinfo>#include <fcntl.h></funcsynopsisinfo>
++ <funcprototype>
++ <funcdef>int <function>open</function></funcdef>
++ <paramdef>const char *<parameter>device_name</parameter></paramdef>
++ <paramdef>int <parameter>flags</parameter></paramdef>
++ </funcprototype>
++ </funcsynopsis>
++ </refsynopsisdiv>
++
++ <refsect1>
++ <title>Arguments</title>
++
++ <variablelist>
++ <varlistentry>
++ <term><parameter>device_name</parameter></term>
++ <listitem>
++ <para>Device to be opened.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><parameter>flags</parameter></term>
++ <listitem>
++ <para>Open flags. Access mode must be either <constant>O_RDONLY</constant>
++ or <constant>O_RDWR</constant>. Other flags have no effect.</para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++ <refsect1>
++ <title>Description</title>
++ <para>To open a media device applications call <function>open()</function>
++ with the desired device name. The function has no side effects; the device
++ configuration remain unchanged.</para>
++ <para>When the device is opened in read-only mode, attemps to modify its
++ configuration will result in an error, and <varname>errno</varname> will be
++ set to <errorcode>EBADF</errorcode>.</para>
++ </refsect1>
++ <refsect1>
++ <title>Return Value</title>
++
++ <para><function>open</function> returns the new file descriptor on success.
++ On error, -1 is returned, and <varname>errno</varname> is set appropriately.
++ Possible error codes are:</para>
++
++ <variablelist>
++ <varlistentry>
++ <term><errorcode>EACCES</errorcode></term>
++ <listitem>
++ <para>The requested access to the file is not allowed.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><errorcode>EMFILE</errorcode></term>
++ <listitem>
++ <para>The process already has the maximum number of files open.
++ </para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><errorcode>ENFILE</errorcode></term>
++ <listitem>
++ <para>The system limit on the total number of open files has been
++ reached.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><errorcode>ENOMEM</errorcode></term>
++ <listitem>
++ <para>Insufficient kernel memory was available.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><errorcode>ENXIO</errorcode></term>
++ <listitem>
++ <para>No device corresponding to this device special file exists.
++ </para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++</refentry>
+diff --git a/Documentation/DocBook/v4l/media-ioc-device-info.xml b/Documentation/DocBook/v4l/media-ioc-device-info.xml
+new file mode 100644
+index 0000000..278a312
+--- /dev/null
++++ b/Documentation/DocBook/v4l/media-ioc-device-info.xml
+@@ -0,0 +1,132 @@
++<refentry id="media-ioc-device-info">
++ <refmeta>
++ <refentrytitle>ioctl MEDIA_IOC_DEVICE_INFO</refentrytitle>
++ &manvol;
++ </refmeta>
++
++ <refnamediv>
++ <refname>MEDIA_IOC_DEVICE_INFO</refname>
++ <refpurpose>Query device information</refpurpose>
++ </refnamediv>
++
++ <refsynopsisdiv>
++ <funcsynopsis>
++ <funcprototype>
++ <funcdef>int <function>ioctl</function></funcdef>
++ <paramdef>int <parameter>fd</parameter></paramdef>
++ <paramdef>int <parameter>request</parameter></paramdef>
++ <paramdef>struct media_device_info *<parameter>argp</parameter></paramdef>
++ </funcprototype>
++ </funcsynopsis>
++ </refsynopsisdiv>
++
++ <refsect1>
++ <title>Arguments</title>
++
++ <variablelist>
++ <varlistentry>
++ <term><parameter>fd</parameter></term>
++ <listitem>
++ <para>&fd;</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><parameter>request</parameter></term>
++ <listitem>
++ <para>MEDIA_IOC_DEVICE_INFO</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><parameter>argp</parameter></term>
++ <listitem>
++ <para></para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++
++ <refsect1>
++ <title>Description</title>
++
++ <para>All media devices must support the <constant>MEDIA_IOC_DEVICE_INFO</constant>
++ ioctl. To query device information, applications call the ioctl with a
++ pointer to a &media-device-info;. The driver fills the structure and returns
++ the information to the application.
++ The ioctl never fails.</para>
++
++ <table pgwide="1" frame="none" id="media-device-info">
++ <title>struct <structname>media_device_info</structname></title>
++ <tgroup cols="3">
++ &cs-str;
++ <tbody valign="top">
++ <row>
++ <entry>char</entry>
++ <entry><structfield>driver</structfield>[16]</entry>
++ <entry><para>Name of the driver implementing the media API as a
++ NUL-terminated ASCII string. The driver version is stored in the
++ <structfield>driver_version</structfield> field.</para>
++ <para>Driver specific applications can use this information to
++ verify the driver identity. It is also useful to work around
++ known bugs, or to identify drivers in error reports.</para></entry>
++ </row>
++ <row>
++ <entry>char</entry>
++ <entry><structfield>model</structfield>[32]</entry>
++ <entry>Device model name as a NUL-terminated UTF-8 string. The
++ device version is stored in the <structfield>device_version</structfield>
++ field and is not be appended to the model name.</entry>
++ </row>
++ <row>
++ <entry>char</entry>
++ <entry><structfield>serial</structfield>[40]</entry>
++ <entry>Serial number as a NUL-terminated ASCII string.</entry>
++ </row>
++ <row>
++ <entry>char</entry>
++ <entry><structfield>bus_info</structfield>[32]</entry>
++ <entry>Location of the device in the system as a NUL-terminated
++ ASCII string. This includes the bus type name (PCI, USB, ...) and a
++ bus-specific identifier.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>media_version</structfield></entry>
++ <entry>Media API version, formatted with the
++ <constant>KERNEL_VERSION()</constant> macro.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>hw_revision</structfield></entry>
++ <entry>Hardware device revision in a driver-specific format.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>media_version</structfield></entry>
++ <entry>Media device driver version, formatted with the
++ <constant>KERNEL_VERSION()</constant> macro. Together with the
++ <structfield>driver</structfield> field this identifies a particular
++ driver.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>reserved</structfield>[31]</entry>
++ <entry>Reserved for future extensions. Drivers and applications must
++ set this array to zero.</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ <para>The <structfield>serial</structfield> and <structfield>bus_info</structfield>
++ fields can be used to distinguish between multiple instances of otherwise
++ identical hardware. The serial number takes precedence when provided and can
++ be assumed to be unique. If the serial number is an empty string, the
++ <structfield>bus_info</structfield> field can be used instead. The
++ <structfield>bus_info</structfield> field is guaranteed to be unique, but
++ can vary across reboots or device unplug/replug.</para>
++ </refsect1>
++
++ <refsect1>
++ <title>Return value</title>
++ <para>This function doesn't return specific error codes.</para>
++ </refsect1>
++</refentry>
+diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
+index e4c2157..5c745be 100644
+--- a/drivers/media/media-device.c
++++ b/drivers/media/media-device.c
+@@ -22,13 +22,70 @@
+
+ #include <linux/types.h>
+ #include <linux/ioctl.h>
++#include <linux/media.h>
+
+ #include <media/media-device.h>
+ #include <media/media-devnode.h>
+ #include <media/media-entity.h>
+
++/* -----------------------------------------------------------------------------
++ * Userspace API
++ */
++
++static int media_device_open(struct file *filp)
++{
++ return 0;
++}
++
++static int media_device_close(struct file *filp)
++{
++ return 0;
++}
++
++static int media_device_get_info(struct media_device *dev,
++ struct media_device_info __user *__info)
++{
++ struct media_device_info info;
++
++ memset(&info, 0, sizeof(info));
++
++ strlcpy(info.driver, dev->dev->driver->name, sizeof(info.driver));
++ strlcpy(info.model, dev->model, sizeof(info.model));
++ strlcpy(info.serial, dev->serial, sizeof(info.serial));
++ strlcpy(info.bus_info, dev->bus_info, sizeof(info.bus_info));
++
++ info.media_version = MEDIA_API_VERSION;
++ info.hw_revision = dev->hw_revision;
++ info.driver_version = dev->driver_version;
++
++ return copy_to_user(__info, &info, sizeof(*__info));
++}
++
++static long media_device_ioctl(struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ struct media_devnode *devnode = media_devnode_data(filp);
++ struct media_device *dev = to_media_device(devnode);
++ long ret;
++
++ switch (cmd) {
++ case MEDIA_IOC_DEVICE_INFO:
++ ret = media_device_get_info(dev,
++ (struct media_device_info __user *)arg);
++ break;
++
++ default:
++ ret = -ENOIOCTLCMD;
++ }
++
++ return ret;
++}
++
+ static const struct media_file_operations media_device_fops = {
+ .owner = THIS_MODULE,
++ .open = media_device_open,
++ .ioctl = media_device_ioctl,
++ .release = media_device_close,
+ };
+
+ /* -----------------------------------------------------------------------------
+diff --git a/include/linux/Kbuild b/include/linux/Kbuild
+index 97319a8..26e0a7f 100644
+--- a/include/linux/Kbuild
++++ b/include/linux/Kbuild
+@@ -228,6 +228,7 @@ header-y += magic.h
+ header-y += major.h
+ header-y += map_to_7segment.h
+ header-y += matroxfb.h
++header-y += media.h
+ header-y += mempolicy.h
+ header-y += meye.h
+ header-y += mii.h
+diff --git a/include/linux/media.h b/include/linux/media.h
+new file mode 100644
+index 0000000..4c52f08
+--- /dev/null
++++ b/include/linux/media.h
+@@ -0,0 +1,45 @@
++/*
++ * Multimedia device API
++ *
++ * Copyright (C) 2010 Nokia Corporation
++ *
++ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef __LINUX_MEDIA_H
++#define __LINUX_MEDIA_H
++
++#include <linux/ioctl.h>
++#include <linux/types.h>
++#include <linux/version.h>
++
++#define MEDIA_API_VERSION KERNEL_VERSION(0, 1, 0)
++
++struct media_device_info {
++ char driver[16];
++ char model[32];
++ char serial[40];
++ char bus_info[32];
++ __u32 media_version;
++ __u32 hw_revision;
++ __u32 driver_version;
++ __u32 reserved[31];
++};
++
++#define MEDIA_IOC_DEVICE_INFO _IOWR('M', 1, struct media_device_info)
++
++#endif /* __LINUX_MEDIA_H */
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0014-media-Entities-pads-and-links-enumeration.patch b/recipes-bsp/linux/linux-omap/media/0014-media-Entities-pads-and-links-enumeration.patch
--- /dev/null
@@ -0,0 +1,889 @@
+From d7784ca094970b836c99e5f2a6344811625753a3 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:40:01 +0100
+Subject: [PATCH 14/43] media: Entities, pads and links enumeration
+
+Create the following two ioctls and implement them at the media device
+level to enumerate entities, pads and links.
+
+- MEDIA_IOC_ENUM_ENTITIES: Enumerate entities and their properties
+- MEDIA_IOC_ENUM_LINKS: Enumerate all pads and links for a given entity
+
+Entity IDs can be non-contiguous. Userspace applications should
+enumerate entities using the MEDIA_ENT_ID_FLAG_NEXT flag. When the flag
+is set in the entity ID, the MEDIA_IOC_ENUM_ENTITIES will return the
+next entity with an ID bigger than the requested one.
+
+Only forward links that originate at one of the entity's source pads are
+returned during the enumeration process.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ Documentation/DocBook/media-entities.tmpl | 8 +
+ Documentation/DocBook/v4l/media-controller.xml | 2 +
+ .../DocBook/v4l/media-ioc-device-info.xml | 3 +-
+ .../DocBook/v4l/media-ioc-enum-entities.xml | 308 ++++++++++++++++++++
+ Documentation/DocBook/v4l/media-ioc-enum-links.xml | 202 +++++++++++++
+ drivers/media/media-device.c | 123 ++++++++
+ include/linux/media.h | 85 ++++++
+ include/media/media-entity.h | 24 +--
+ 8 files changed, 731 insertions(+), 24 deletions(-)
+ create mode 100644 Documentation/DocBook/v4l/media-ioc-enum-entities.xml
+ create mode 100644 Documentation/DocBook/v4l/media-ioc-enum-links.xml
+
+diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
+index 6af3375..6e7dae4 100644
+--- a/Documentation/DocBook/media-entities.tmpl
++++ b/Documentation/DocBook/media-entities.tmpl
+@@ -92,6 +92,8 @@
+ <!ENTITY VIDIOC-UNSUBSCRIBE-EVENT "<link linkend='vidioc-subscribe-event'><constant>VIDIOC_UNSUBSCRIBE_EVENT</constant></link>">
+
+ <!ENTITY MEDIA-IOC-DEVICE-INFO "<link linkend='media-ioc-device-info'><constant>MEDIA_IOC_DEVICE_INFO</constant></link>">
++<!ENTITY MEDIA-IOC-ENUM-ENTITIES "<link linkend='media-ioc-enum-entities'><constant>MEDIA_IOC_ENUM_ENTITIES</constant></link>">
++<!ENTITY MEDIA-IOC-ENUM-LINKS "<link linkend='media-ioc-enum-links'><constant>MEDIA_IOC_ENUM_LINKS</constant></link>">
+
+ <!-- Types -->
+ <!ENTITY v4l2-std-id "<link linkend='v4l2-std-id'>v4l2_std_id</link>">
+@@ -188,6 +190,10 @@
+ <!ENTITY v4l2-window "struct <link linkend='v4l2-window'>v4l2_window</link>">
+
+ <!ENTITY media-device-info "struct <link linkend='media-device-info'>media_device_info</link>">
++<!ENTITY media-entity-desc "struct <link linkend='media-entity-desc'>media_entity_desc</link>">
++<!ENTITY media-links-enum "struct <link linkend='media-links-enum'>media_links_enum</link>">
++<!ENTITY media-pad-desc "struct <link linkend='media-pad-desc'>media_pad_desc</link>">
++<!ENTITY media-link-desc "struct <link linkend='media-link-desc'>media_link_desc</link>">
+
+ <!-- Error Codes -->
+ <!ENTITY EACCES "<errorcode>EACCES</errorcode> error code">
+@@ -334,6 +340,8 @@
+ <!ENTITY sub-media-close SYSTEM "v4l/media-func-close.xml">
+ <!ENTITY sub-media-ioctl SYSTEM "v4l/media-func-ioctl.xml">
+ <!ENTITY sub-media-ioc-device-info SYSTEM "v4l/media-ioc-device-info.xml">
++<!ENTITY sub-media-ioc-enum-entities SYSTEM "v4l/media-ioc-enum-entities.xml">
++<!ENTITY sub-media-ioc-enum-links SYSTEM "v4l/media-ioc-enum-links.xml">
+
+ <!-- Function Reference -->
+ <!ENTITY close SYSTEM "v4l/func-close.xml">
+diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml
+index a46b786..2c4fd2b 100644
+--- a/Documentation/DocBook/v4l/media-controller.xml
++++ b/Documentation/DocBook/v4l/media-controller.xml
+@@ -83,4 +83,6 @@
+ &sub-media-ioctl;
+ <!-- All ioctls go here. -->
+ &sub-media-ioc-device-info;
++ &sub-media-ioc-enum-entities;
++ &sub-media-ioc-enum-links;
+ </appendix>
+diff --git a/Documentation/DocBook/v4l/media-ioc-device-info.xml b/Documentation/DocBook/v4l/media-ioc-device-info.xml
+index 278a312..1f32373 100644
+--- a/Documentation/DocBook/v4l/media-ioc-device-info.xml
++++ b/Documentation/DocBook/v4l/media-ioc-device-info.xml
+@@ -27,7 +27,8 @@
+ <varlistentry>
+ <term><parameter>fd</parameter></term>
+ <listitem>
+- <para>&fd;</para>
++ <para>File descriptor returned by
++ <link linkend='media-func-open'><function>open()</function></link>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+diff --git a/Documentation/DocBook/v4l/media-ioc-enum-entities.xml b/Documentation/DocBook/v4l/media-ioc-enum-entities.xml
+new file mode 100644
+index 0000000..13d0cc4
+--- /dev/null
++++ b/Documentation/DocBook/v4l/media-ioc-enum-entities.xml
+@@ -0,0 +1,308 @@
++<refentry id="media-ioc-enum-entities">
++ <refmeta>
++ <refentrytitle>ioctl MEDIA_IOC_ENUM_ENTITIES</refentrytitle>
++ &manvol;
++ </refmeta>
++
++ <refnamediv>
++ <refname>MEDIA_IOC_ENUM_ENTITIES</refname>
++ <refpurpose>Enumerate entities and their properties</refpurpose>
++ </refnamediv>
++
++ <refsynopsisdiv>
++ <funcsynopsis>
++ <funcprototype>
++ <funcdef>int <function>ioctl</function></funcdef>
++ <paramdef>int <parameter>fd</parameter></paramdef>
++ <paramdef>int <parameter>request</parameter></paramdef>
++ <paramdef>struct media_entity_desc *<parameter>argp</parameter></paramdef>
++ </funcprototype>
++ </funcsynopsis>
++ </refsynopsisdiv>
++
++ <refsect1>
++ <title>Arguments</title>
++
++ <variablelist>
++ <varlistentry>
++ <term><parameter>fd</parameter></term>
++ <listitem>
++ <para>File descriptor returned by
++ <link linkend='media-func-open'><function>open()</function></link>.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><parameter>request</parameter></term>
++ <listitem>
++ <para>MEDIA_IOC_ENUM_ENTITIES</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><parameter>argp</parameter></term>
++ <listitem>
++ <para></para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++
++ <refsect1>
++ <title>Description</title>
++ <para>To query the attributes of an entity, applications set the id field
++ of a &media-entity-desc; structure and call the MEDIA_IOC_ENUM_ENTITIES
++ ioctl with a pointer to this structure. The driver fills the rest of the
++ structure or returns an &EINVAL; when the id is invalid.</para>
++ <para>Entities can be enumerated by or'ing the id with the
++ <constant>MEDIA_ENT_ID_FLAG_NEXT</constant> flag. The driver will return
++ information about the entity with the smallest id strictly larger than the
++ requested one ('next entity'), or the &EINVAL; if there is none.</para>
++ <para>Entity IDs can be non-contiguous. Applications must
++ <emphasis>not</emphasis> try to enumerate entities by calling
++ MEDIA_IOC_ENUM_ENTITIES with increasing id's until they get an error.</para>
++ <para>Two or more entities that share a common non-zero
++ <structfield>group_id</structfield> value are considered as logically
++ grouped. Groups are used to report
++ <itemizedlist>
++ <listitem>ALSA, VBI and video nodes that carry the same media
++ stream</listitem>
++ <listitem>lens and flash controllers associated with a sensor</listitem>
++ </itemizedlist>
++ </para>
++
++ <table pgwide="1" frame="none" id="media-entity-desc">
++ <title>struct <structname>media_entity_desc</structname></title>
++ <tgroup cols="5">
++ <colspec colname="c1" />
++ <colspec colname="c2" />
++ <colspec colname="c3" />
++ <colspec colname="c4" />
++ <colspec colname="c5" />
++ <tbody valign="top">
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>id</structfield></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>Entity id, set by the application. When the id is or'ed with
++ <constant>MEDIA_ENT_ID_FLAG_NEXT</constant>, the driver clears the
++ flag and returns the first entity with a larger id.</entry>
++ </row>
++ <row>
++ <entry>char</entry>
++ <entry><structfield>name</structfield>[32]</entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>Entity name as an UTF-8 NULL-terminated string.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>type</structfield></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>Entity type, see <xref linkend="media-entity-type" /> for details.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>revision</structfield></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>Entity revision in a driver/hardware specific format.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>flags</structfield></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>Entity flags, see <xref linkend="media-entity-flag" /> for details.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>group_id</structfield></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>Entity group ID</entry>
++ </row>
++ <row>
++ <entry>__u16</entry>
++ <entry><structfield>pads</structfield></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>Number of pads</entry>
++ </row>
++ <row>
++ <entry>__u16</entry>
++ <entry><structfield>links</structfield></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>Total number of outbound links. Inbound links are not counted
++ in this field.</entry>
++ </row>
++ <row>
++ <entry>union</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry>struct</entry>
++ <entry><structfield>v4l</structfield></entry>
++ <entry></entry>
++ <entry>Valid for V4L sub-devices and nodes only.</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry>__u32</entry>
++ <entry><structfield>major</structfield></entry>
++ <entry>V4L device node major number. For V4L sub-devices with no
++ device node, set by the driver to 0.</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry>__u32</entry>
++ <entry><structfield>minor</structfield></entry>
++ <entry>V4L device node minor number. For V4L sub-devices with no
++ device node, set by the driver to 0.</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry>struct</entry>
++ <entry><structfield>fb</structfield></entry>
++ <entry></entry>
++ <entry>Valid for frame buffer nodes only.</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry>__u32</entry>
++ <entry><structfield>major</structfield></entry>
++ <entry>Frame buffer device node major number.</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry>__u32</entry>
++ <entry><structfield>minor</structfield></entry>
++ <entry>Frame buffer device node minor number.</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry>struct</entry>
++ <entry><structfield>alsa</structfield></entry>
++ <entry></entry>
++ <entry>Valid for ALSA devices only.</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry>__u32</entry>
++ <entry><structfield>card</structfield></entry>
++ <entry>ALSA card number</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry>__u32</entry>
++ <entry><structfield>device</structfield></entry>
++ <entry>ALSA device number</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry>__u32</entry>
++ <entry><structfield>subdevice</structfield></entry>
++ <entry>ALSA sub-device number</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry>int</entry>
++ <entry><structfield>dvb</structfield></entry>
++ <entry></entry>
++ <entry>DVB card number</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry>__u8</entry>
++ <entry><structfield>raw</structfield>[180]</entry>
++ <entry></entry>
++ <entry></entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++
++ <table frame="none" pgwide="1" id="media-entity-type">
++ <title>Media entity types</title>
++ <tgroup cols="2">
++ <colspec colname="c1"/>
++ <colspec colname="c2"/>
++ <tbody valign="top">
++ <row>
++ <entry><constant>MEDIA_ENT_T_DEVNODE</constant></entry>
++ <entry>Unknown device node</entry>
++ </row>
++ <row>
++ <entry><constant>MEDIA_ENT_T_DEVNODE_V4L</constant></entry>
++ <entry>V4L video, radio or vbi device node</entry>
++ </row>
++ <row>
++ <entry><constant>MEDIA_ENT_T_DEVNODE_FB</constant></entry>
++ <entry>Frame buffer device node</entry>
++ </row>
++ <row>
++ <entry><constant>MEDIA_ENT_T_DEVNODE_ALSA</constant></entry>
++ <entry>ALSA card</entry>
++ </row>
++ <row>
++ <entry><constant>MEDIA_ENT_T_DEVNODE_DVB</constant></entry>
++ <entry>DVB card</entry>
++ </row>
++ <row>
++ <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV</constant></entry>
++ <entry>Unknown V4L sub-device</entry>
++ </row>
++ <row>
++ <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_SENSOR</constant></entry>
++ <entry>Video sensor</entry>
++ </row>
++ <row>
++ <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_FLASH</constant></entry>
++ <entry>Flash controller</entry>
++ </row>
++ <row>
++ <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_LENS</constant></entry>
++ <entry>Lens controller</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++
++ <table frame="none" pgwide="1" id="media-entity-flag">
++ <title>Media entity flags</title>
++ <tgroup cols="2">
++ <colspec colname="c1"/>
++ <colspec colname="c2"/>
++ <tbody valign="top">
++ <row>
++ <entry><constant>MEDIA_ENT_FL_DEFAULT</constant></entry>
++ <entry>Default entity for its type. Used to discover the default
++ audio, VBI and video devices, the default camera sensor, ...</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ </refsect1>
++
++ <refsect1>
++ &return-value;
++
++ <variablelist>
++ <varlistentry>
++ <term><errorcode>EINVAL</errorcode></term>
++ <listitem>
++ <para>The &media-entity-desc; <structfield>id</structfield> references
++ a non-existing entity.</para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++</refentry>
+diff --git a/Documentation/DocBook/v4l/media-ioc-enum-links.xml b/Documentation/DocBook/v4l/media-ioc-enum-links.xml
+new file mode 100644
+index 0000000..daf0360
+--- /dev/null
++++ b/Documentation/DocBook/v4l/media-ioc-enum-links.xml
+@@ -0,0 +1,202 @@
++<refentry id="media-ioc-enum-links">
++ <refmeta>
++ <refentrytitle>ioctl MEDIA_IOC_ENUM_LINKS</refentrytitle>
++ &manvol;
++ </refmeta>
++
++ <refnamediv>
++ <refname>MEDIA_IOC_ENUM_LINKS</refname>
++ <refpurpose>Enumerate all pads and links for a given entity</refpurpose>
++ </refnamediv>
++
++ <refsynopsisdiv>
++ <funcsynopsis>
++ <funcprototype>
++ <funcdef>int <function>ioctl</function></funcdef>
++ <paramdef>int <parameter>fd</parameter></paramdef>
++ <paramdef>int <parameter>request</parameter></paramdef>
++ <paramdef>struct media_links_enum *<parameter>argp</parameter></paramdef>
++ </funcprototype>
++ </funcsynopsis>
++ </refsynopsisdiv>
++
++ <refsect1>
++ <title>Arguments</title>
++
++ <variablelist>
++ <varlistentry>
++ <term><parameter>fd</parameter></term>
++ <listitem>
++ <para>File descriptor returned by
++ <link linkend='media-func-open'><function>open()</function></link>.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><parameter>request</parameter></term>
++ <listitem>
++ <para>MEDIA_IOC_ENUM_LINKS</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><parameter>argp</parameter></term>
++ <listitem>
++ <para></para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++
++ <refsect1>
++ <title>Description</title>
++
++ <para>To enumerate pads and/or links for a given entity, applications set
++ the entity field of a &media-links-enum; structure and initialize the
++ &media-pad-desc; and &media-link-desc; structure arrays pointed by the
++ <structfield>pads</structfield> and <structfield>links</structfield> fields.
++ They then call the MEDIA_IOC_ENUM_LINKS ioctl with a pointer to this
++ structure.</para>
++ <para>If the <structfield>pads</structfield> field is not NULL, the driver
++ fills the <structfield>pads</structfield> array with information about the
++ entity's pads. The array must have enough room to store all the entity's
++ pads. The number of pads can be retrieved with the &MEDIA-IOC-ENUM-ENTITIES;
++ ioctl.</para>
++ <para>If the <structfield>links</structfield> field is not NULL, the driver
++ fills the <structfield>links</structfield> array with information about the
++ entity's outbound links. The array must have enough room to store all the
++ entity's outbound links. The number of outbound links can be retrieved with
++ the &MEDIA-IOC-ENUM-ENTITIES; ioctl.</para>
++ <para>Only forward links that originate at one of the entity's source pads
++ are returned during the enumeration process.</para>
++
++ <table pgwide="1" frame="none" id="media-links-enum">
++ <title>struct <structname>media_links_enum</structname></title>
++ <tgroup cols="3">
++ &cs-str;
++ <tbody valign="top">
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>entity</structfield></entry>
++ <entry>Entity id, set by the application.</entry>
++ </row>
++ <row>
++ <entry>struct &media-pad-desc;</entry>
++ <entry>*<structfield>pads</structfield></entry>
++ <entry>Pointer to a pads array allocated by the application. Ignored
++ if NULL.</entry>
++ </row>
++ <row>
++ <entry>struct &media-link-desc;</entry>
++ <entry>*<structfield>links</structfield></entry>
++ <entry>Pointer to a links array allocated by the application. Ignored
++ if NULL.</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++
++ <table pgwide="1" frame="none" id="media-pad-desc">
++ <title>struct <structname>media_pad_desc</structname></title>
++ <tgroup cols="3">
++ &cs-str;
++ <tbody valign="top">
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>entity</structfield></entry>
++ <entry>ID of the entity this pad belongs to.</entry>
++ </row>
++ <row>
++ <entry>__u16</entry>
++ <entry><structfield>index</structfield></entry>
++ <entry>0-based pad index.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>flags</structfield></entry>
++ <entry>Pad flags, see <xref linkend="media-pad-flag" /> for more details.</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++
++ <table frame="none" pgwide="1" id="media-pad-flag">
++ <title>Media pad flags</title>
++ <tgroup cols="2">
++ <colspec colname="c1"/>
++ <colspec colname="c2"/>
++ <tbody valign="top">
++ <row>
++ <entry><constant>MEDIA_PAD_FL_INPUT</constant></entry>
++ <entry>Input pad, relative to the entity. Input pads sink data and
++ are targets of links.</entry>
++ </row>
++ <row>
++ <entry><constant>MEDIA_PAD_FL_OUTPUT</constant></entry>
++ <entry>Output pad, relative to the entity. Output pads source data
++ and are origins of links.</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++
++ <table pgwide="1" frame="none" id="media-link-desc">
++ <title>struct <structname>media_links_enum</structname></title>
++ <tgroup cols="3">
++ &cs-str;
++ <tbody valign="top">
++ <row>
++ <entry>struct &media-pad-desc;</entry>
++ <entry><structfield>source</structfield></entry>
++ <entry>Pad at the origin of this link.</entry>
++ </row>
++ <row>
++ <entry>struct &media-pad-desc;</entry>
++ <entry><structfield>sink</structfield></entry>
++ <entry>Pad at the target of this link.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>flags</structfield></entry>
++ <entry>Link flags, see <xref linkend="media-link-flag" /> for more details.</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++
++ <table frame="none" pgwide="1" id="media-link-flag">
++ <title>Media link flags</title>
++ <tgroup cols="2">
++ <colspec colname="c1"/>
++ <colspec colname="c2"/>
++ <tbody valign="top">
++ <row>
++ <entry><constant>MEDIA_LNK_FL_ENABLED</constant></entry>
++ <entry>The link is enabled and can be used to transfer media data.
++ When two or more links target a sink pad, only one of them can be
++ enabled at a time.</entry>
++ </row>
++ <row>
++ <entry><constant>MEDIA_LNK_FL_IMMUTABLE</constant></entry>
++ <entry>The link enabled state can't be modified at runtime. An
++ immutable link is always enabled.</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ <para>One and only one of <constant>MEDIA_PAD_FL_INPUT</constant> and
++ <constant>MEDIA_PAD_FL_OUTPUT</constant> must be set for every pad.</para>
++ </refsect1>
++
++ <refsect1>
++ &return-value;
++
++ <variablelist>
++ <varlistentry>
++ <term><errorcode>EINVAL</errorcode></term>
++ <listitem>
++ <para>The &media-links-enum; <structfield>id</structfield> references
++ a non-existing entity.</para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++</refentry>
+diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
+index 5c745be..1f46acb 100644
+--- a/drivers/media/media-device.c
++++ b/drivers/media/media-device.c
+@@ -61,6 +61,117 @@ static int media_device_get_info(struct media_device *dev,
+ return copy_to_user(__info, &info, sizeof(*__info));
+ }
+
++static struct media_entity *find_entity(struct media_device *mdev, u32 id)
++{
++ struct media_entity *entity;
++ int next = id & MEDIA_ENT_ID_FLAG_NEXT;
++
++ id &= ~MEDIA_ENT_ID_FLAG_NEXT;
++
++ spin_lock(&mdev->lock);
++
++ media_device_for_each_entity(entity, mdev) {
++ if ((entity->id == id && !next) ||
++ (entity->id > id && next)) {
++ spin_unlock(&mdev->lock);
++ return entity;
++ }
++ }
++
++ spin_unlock(&mdev->lock);
++
++ return NULL;
++}
++
++static long media_device_enum_entities(struct media_device *mdev,
++ struct media_entity_desc __user *uent)
++{
++ struct media_entity *ent;
++ struct media_entity_desc u_ent;
++
++ if (copy_from_user(&u_ent.id, &uent->id, sizeof(u_ent.id)))
++ return -EFAULT;
++
++ ent = find_entity(mdev, u_ent.id);
++
++ if (ent == NULL)
++ return -EINVAL;
++
++ u_ent.id = ent->id;
++ u_ent.name[0] = '\0';
++ if (ent->name)
++ strlcpy(u_ent.name, ent->name, sizeof(u_ent.name));
++ u_ent.type = ent->type;
++ u_ent.revision = ent->revision;
++ u_ent.flags = ent->flags;
++ u_ent.group_id = ent->group_id;
++ u_ent.pads = ent->num_pads;
++ u_ent.links = ent->num_links - ent->num_backlinks;
++ u_ent.v4l.major = ent->v4l.major;
++ u_ent.v4l.minor = ent->v4l.minor;
++ if (copy_to_user(uent, &u_ent, sizeof(u_ent)))
++ return -EFAULT;
++ return 0;
++}
++
++static void media_device_kpad_to_upad(const struct media_pad *kpad,
++ struct media_pad_desc *upad)
++{
++ upad->entity = kpad->entity->id;
++ upad->index = kpad->index;
++ upad->flags = kpad->flags;
++}
++
++static long media_device_enum_links(struct media_device *mdev,
++ struct media_links_enum __user *ulinks)
++{
++ struct media_entity *entity;
++ struct media_links_enum links;
++
++ if (copy_from_user(&links, ulinks, sizeof(links)))
++ return -EFAULT;
++
++ entity = find_entity(mdev, links.entity);
++ if (entity == NULL)
++ return -EINVAL;
++
++ if (links.pads) {
++ unsigned int p;
++
++ for (p = 0; p < entity->num_pads; p++) {
++ struct media_pad_desc pad;
++ media_device_kpad_to_upad(&entity->pads[p], &pad);
++ if (copy_to_user(&links.pads[p], &pad, sizeof(pad)))
++ return -EFAULT;
++ }
++ }
++
++ if (links.links) {
++ struct media_link_desc __user *ulink;
++ unsigned int l;
++
++ for (l = 0, ulink = links.links; l < entity->num_links; l++) {
++ struct media_link_desc link;
++
++ /* Ignore backlinks. */
++ if (entity->links[l].source->entity != entity)
++ continue;
++
++ media_device_kpad_to_upad(entity->links[l].source,
++ &link.source);
++ media_device_kpad_to_upad(entity->links[l].sink,
++ &link.sink);
++ link.flags = entity->links[l].flags;
++ if (copy_to_user(ulink, &link, sizeof(*ulink)))
++ return -EFAULT;
++ ulink++;
++ }
++ }
++ if (copy_to_user(ulinks, &links, sizeof(*ulinks)))
++ return -EFAULT;
++ return 0;
++}
++
+ static long media_device_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+ {
+@@ -74,6 +185,18 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd,
+ (struct media_device_info __user *)arg);
+ break;
+
++ case MEDIA_IOC_ENUM_ENTITIES:
++ ret = media_device_enum_entities(dev,
++ (struct media_entity_desc __user *)arg);
++ break;
++
++ case MEDIA_IOC_ENUM_LINKS:
++ mutex_lock(&dev->graph_mutex);
++ ret = media_device_enum_links(dev,
++ (struct media_links_enum __user *)arg);
++ mutex_unlock(&dev->graph_mutex);
++ break;
++
+ default:
+ ret = -ENOIOCTLCMD;
+ }
+diff --git a/include/linux/media.h b/include/linux/media.h
+index 4c52f08..64c0313 100644
+--- a/include/linux/media.h
++++ b/include/linux/media.h
+@@ -40,6 +40,91 @@ struct media_device_info {
+ __u32 reserved[31];
+ };
+
++#define MEDIA_ENT_ID_FLAG_NEXT (1 << 31)
++
++#define MEDIA_ENT_TYPE_SHIFT 16
++#define MEDIA_ENT_TYPE_MASK 0x00ff0000
++#define MEDIA_ENT_SUBTYPE_MASK 0x0000ffff
++
++#define MEDIA_ENT_T_DEVNODE (1 << MEDIA_ENT_TYPE_SHIFT)
++#define MEDIA_ENT_T_DEVNODE_V4L (MEDIA_ENT_T_DEVNODE + 1)
++#define MEDIA_ENT_T_DEVNODE_FB (MEDIA_ENT_T_DEVNODE + 2)
++#define MEDIA_ENT_T_DEVNODE_ALSA (MEDIA_ENT_T_DEVNODE + 3)
++#define MEDIA_ENT_T_DEVNODE_DVB (MEDIA_ENT_T_DEVNODE + 4)
++
++#define MEDIA_ENT_T_V4L2_SUBDEV (2 << MEDIA_ENT_TYPE_SHIFT)
++#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR (MEDIA_ENT_T_V4L2_SUBDEV + 1)
++#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH (MEDIA_ENT_T_V4L2_SUBDEV + 2)
++#define MEDIA_ENT_T_V4L2_SUBDEV_LENS (MEDIA_ENT_T_V4L2_SUBDEV + 3)
++
++#define MEDIA_ENT_FL_DEFAULT (1 << 0)
++
++struct media_entity_desc {
++ __u32 id;
++ char name[32];
++ __u32 type;
++ __u32 revision;
++ __u32 flags;
++ __u32 group_id;
++ __u16 pads;
++ __u16 links;
++
++ __u32 reserved[4];
++
++ union {
++ /* Node specifications */
++ struct {
++ __u32 major;
++ __u32 minor;
++ } v4l;
++ struct {
++ __u32 major;
++ __u32 minor;
++ } fb;
++ struct {
++ __u32 card;
++ __u32 device;
++ __u32 subdevice;
++ } alsa;
++ int dvb;
++
++ /* Sub-device specifications */
++ /* Nothing needed yet */
++ __u8 raw[184];
++ };
++};
++
++#define MEDIA_PAD_FL_INPUT (1 << 0)
++#define MEDIA_PAD_FL_OUTPUT (1 << 1)
++
++struct media_pad_desc {
++ __u32 entity; /* entity ID */
++ __u16 index; /* pad index */
++ __u32 flags; /* pad flags */
++ __u32 reserved[2];
++};
++
++#define MEDIA_LNK_FL_ENABLED (1 << 0)
++#define MEDIA_LNK_FL_IMMUTABLE (1 << 1)
++
++struct media_link_desc {
++ struct media_pad_desc source;
++ struct media_pad_desc sink;
++ __u32 flags;
++ __u32 reserved[2];
++};
++
++struct media_links_enum {
++ __u32 entity;
++ /* Should have enough room for pads elements */
++ struct media_pad_desc __user *pads;
++ /* Should have enough room for links elements */
++ struct media_link_desc __user *links;
++ __u32 reserved[4];
++};
++
+ #define MEDIA_IOC_DEVICE_INFO _IOWR('M', 1, struct media_device_info)
++#define MEDIA_IOC_ENUM_ENTITIES _IOWR('M', 2, struct media_entity_desc)
++#define MEDIA_IOC_ENUM_LINKS _IOWR('M', 3, struct media_links_enum)
+
+ #endif /* __LINUX_MEDIA_H */
+diff --git a/include/media/media-entity.h b/include/media/media-entity.h
+index 114541a..0954490 100644
+--- a/include/media/media-entity.h
++++ b/include/media/media-entity.h
+@@ -24,29 +24,7 @@
+ #define _MEDIA_ENTITY_H
+
+ #include <linux/list.h>
+-
+-#define MEDIA_ENT_TYPE_SHIFT 16
+-#define MEDIA_ENT_TYPE_MASK 0x00ff0000
+-#define MEDIA_ENT_SUBTYPE_MASK 0x0000ffff
+-
+-#define MEDIA_ENT_T_DEVNODE (1 << MEDIA_ENTITY_TYPE_SHIFT)
+-#define MEDIA_ENT_T_DEVNODE_V4L (MEDIA_ENTITY_T_DEVNODE + 1)
+-#define MEDIA_ENT_T_DEVNODE_FB (MEDIA_ENTITY_T_DEVNODE + 2)
+-#define MEDIA_ENT_T_DEVNODE_ALSA (MEDIA_ENTITY_T_DEVNODE + 3)
+-#define MEDIA_ENT_T_DEVNODE_DVB (MEDIA_ENTITY_T_DEVNODE + 4)
+-
+-#define MEDIA_ENT_T_V4L2_SUBDEV (2 << MEDIA_ENTITY_TYPE_SHIFT)
+-#define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR (MEDIA_ENTITY_T_V4L2_SUBDEV + 1)
+-#define MEDIA_ENT_T_V4L2_SUBDEV_FLASH (MEDIA_ENTITY_T_V4L2_SUBDEV + 2)
+-#define MEDIA_ENT_T_V4L2_SUBDEV_LENS (MEDIA_ENTITY_T_V4L2_SUBDEV + 3)
+-
+-#define MEDIA_ENT_FL_DEFAULT (1 << 0)
+-
+-#define MEDIA_LNK_FL_ENABLED (1 << 0)
+-#define MEDIA_LNK_FL_IMMUTABLE (1 << 1)
+-
+-#define MEDIA_PAD_FL_INPUT (1 << 0)
+-#define MEDIA_PAD_FL_OUTPUT (1 << 1)
++#include <linux/media.h>
+
+ struct media_link {
+ struct media_pad *source; /* Source pad */
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0015-media-Links-setup.patch b/recipes-bsp/linux/linux-omap/media/0015-media-Links-setup.patch
--- /dev/null
@@ -0,0 +1,517 @@
+From 9991c219079532183cc33f16064f86680b80237c Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:40:03 +0100
+Subject: [PATCH 15/43] media: Links setup
+
+Create the following ioctl and implement it at the media device level to
+setup links.
+
+- MEDIA_IOC_SETUP_LINK: Modify the properties of a given link
+
+The only property that can currently be modified is the ENABLED link
+flag to enable/disable a link. Links marked with the IMMUTABLE link flag
+can not be enabled or disabled.
+
+Enabling or disabling a link has effects on entities' use count. Those
+changes are automatically propagated through the graph.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ Documentation/DocBook/media-entities.tmpl | 2 +
+ Documentation/DocBook/v4l/media-controller.xml | 1 +
+ Documentation/DocBook/v4l/media-ioc-setup-link.xml | 90 +++++++++++
+ Documentation/media-framework.txt | 42 ++++++
+ drivers/media/media-device.c | 45 ++++++
+ drivers/media/media-entity.c | 155 ++++++++++++++++++++
+ include/linux/media.h | 1 +
+ include/media/media-device.h | 3 +
+ include/media/media-entity.h | 17 ++
+ 9 files changed, 356 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/DocBook/v4l/media-ioc-setup-link.xml
+
+diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
+index 6e7dae4..679c585 100644
+--- a/Documentation/DocBook/media-entities.tmpl
++++ b/Documentation/DocBook/media-entities.tmpl
+@@ -94,6 +94,7 @@
+ <!ENTITY MEDIA-IOC-DEVICE-INFO "<link linkend='media-ioc-device-info'><constant>MEDIA_IOC_DEVICE_INFO</constant></link>">
+ <!ENTITY MEDIA-IOC-ENUM-ENTITIES "<link linkend='media-ioc-enum-entities'><constant>MEDIA_IOC_ENUM_ENTITIES</constant></link>">
+ <!ENTITY MEDIA-IOC-ENUM-LINKS "<link linkend='media-ioc-enum-links'><constant>MEDIA_IOC_ENUM_LINKS</constant></link>">
++<!ENTITY MEDIA-IOC-SETUP-LINK "<link linkend='media-ioc-setup-link'><constant>MEDIA_IOC_SETUP_LINK</constant></link>">
+
+ <!-- Types -->
+ <!ENTITY v4l2-std-id "<link linkend='v4l2-std-id'>v4l2_std_id</link>">
+@@ -342,6 +343,7 @@
+ <!ENTITY sub-media-ioc-device-info SYSTEM "v4l/media-ioc-device-info.xml">
+ <!ENTITY sub-media-ioc-enum-entities SYSTEM "v4l/media-ioc-enum-entities.xml">
+ <!ENTITY sub-media-ioc-enum-links SYSTEM "v4l/media-ioc-enum-links.xml">
++<!ENTITY sub-media-ioc-setup-link SYSTEM "v4l/media-ioc-setup-link.xml">
+
+ <!-- Function Reference -->
+ <!ENTITY close SYSTEM "v4l/func-close.xml">
+diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml
+index 2c4fd2b..2dc25e1 100644
+--- a/Documentation/DocBook/v4l/media-controller.xml
++++ b/Documentation/DocBook/v4l/media-controller.xml
+@@ -85,4 +85,5 @@
+ &sub-media-ioc-device-info;
+ &sub-media-ioc-enum-entities;
+ &sub-media-ioc-enum-links;
++ &sub-media-ioc-setup-link;
+ </appendix>
+diff --git a/Documentation/DocBook/v4l/media-ioc-setup-link.xml b/Documentation/DocBook/v4l/media-ioc-setup-link.xml
+new file mode 100644
+index 0000000..09ab3d2
+--- /dev/null
++++ b/Documentation/DocBook/v4l/media-ioc-setup-link.xml
+@@ -0,0 +1,90 @@
++<refentry id="media-ioc-setup-link">
++ <refmeta>
++ <refentrytitle>ioctl MEDIA_IOC_SETUP_LINK</refentrytitle>
++ &manvol;
++ </refmeta>
++
++ <refnamediv>
++ <refname>MEDIA_IOC_SETUP_LINK</refname>
++ <refpurpose>Modify the properties of a link</refpurpose>
++ </refnamediv>
++
++ <refsynopsisdiv>
++ <funcsynopsis>
++ <funcprototype>
++ <funcdef>int <function>ioctl</function></funcdef>
++ <paramdef>int <parameter>fd</parameter></paramdef>
++ <paramdef>int <parameter>request</parameter></paramdef>
++ <paramdef>struct media_link_desc *<parameter>argp</parameter></paramdef>
++ </funcprototype>
++ </funcsynopsis>
++ </refsynopsisdiv>
++
++ <refsect1>
++ <title>Arguments</title>
++
++ <variablelist>
++ <varlistentry>
++ <term><parameter>fd</parameter></term>
++ <listitem>
++ <para>File descriptor returned by
++ <link linkend='media-func-open'><function>open()</function></link>.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><parameter>request</parameter></term>
++ <listitem>
++ <para>MEDIA_IOC_ENUM_LINKS</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><parameter>argp</parameter></term>
++ <listitem>
++ <para></para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++
++ <refsect1>
++ <title>Description</title>
++
++ <para>To change link properties applications fill a &media-link-desc; with
++ link identification information (source and sink pad) and the new requested
++ link flags. They then call the MEDIA_IOC_SETUP_LINK ioctl with a pointer to
++ that structure.</para>
++ <para>The only configurable property is the <constant>ENABLED</constant>
++ link flag to enable/disable a link. Links marked with the
++ <constant>IMMUTABLE</constant> link flag can not be enabled or disabled.
++ </para>
++ <para>Link configuration has no side effect on other links. If an enabled
++ link at the sink pad prevents the link from being enabled, the driver
++ returns with an &EBUSY;.</para>
++ <para>If the specified link can't be found the driver returns with an
++ &EINVAL;.</para>
++ </refsect1>
++
++ <refsect1>
++ &return-value;
++
++ <variablelist>
++ <varlistentry>
++ <term><errorcode>EBUSY</errorcode></term>
++ <listitem>
++ <para>The link properties can't be changed because the link is
++ currently busy. This can be caused, for instance, by an active media
++ stream (audio or video) on the link. The ioctl shouldn't be retried if
++ no other action is performed before to fix the problem.</para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term><errorcode>EINVAL</errorcode></term>
++ <listitem>
++ <para>The &media-link-desc; references a non-existing link, or the
++ link is immutable and an attempt to modify its configuration was made.
++ </para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++</refentry>
+diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt
+index 9017a41..634845e 100644
+--- a/Documentation/media-framework.txt
++++ b/Documentation/media-framework.txt
+@@ -259,6 +259,16 @@ When the graph traversal is complete the function will return NULL.
+ Graph traversal can be interrupted at any moment. No cleanup function call is
+ required and the graph structure can be freed normally.
+
++Helper functions can be used to find a link between two given pads, or a pad
++connected to another pad through an enabled link
++
++ media_entity_find_link(struct media_pad *source,
++ struct media_pad *sink);
++
++ media_entity_remote_source(struct media_pad *pad);
++
++Refer to the kerneldoc documentation for more information.
++
+
+ Use count and power handling
+ ----------------------------
+@@ -271,3 +281,35 @@ track the number of users of every entity for power management needs.
+ The use_count field is owned by media drivers and must not be touched by entity
+ drivers. Access to the field must be protected by the media device graph_mutex
+ lock.
++
++
++Links setup
++-----------
++
++Link properties can be modified at runtime by calling
++
++ media_entity_setup_link(struct media_link *link, u32 flags);
++
++The flags argument contains the requested new link flags.
++
++The only configurable property is the ENABLED link flag to enable/disable a
++link. Links marked with the IMMUTABLE link flag can not be enabled or disabled.
++
++When a link is enabled or disabled, the media framework calls the
++link_setup operation for the two entities at the source and sink of the link,
++in that order. If the second link_setup call fails, another link_setup call is
++made on the first entity to restore the original link flags.
++
++Media device drivers can be notified of link setup operations by setting the
++media_device::link_notify pointer to a callback function. If provided, the
++notification callback will be called before enabling and after disabling
++links.
++
++Entity drivers must implement the link_setup operation if any of their links
++is non-immutable. The operation must either configure the hardware or store
++the configuration information to be applied later.
++
++Link configuration must not have any side effect on other links. If an enabled
++link at a sink pad prevents another link at the same pad from being disabled,
++the link_setup operation must return -EBUSY and can't implicitly disable the
++first enabled link.
+diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
+index 1f46acb..719deba 100644
+--- a/drivers/media/media-device.c
++++ b/drivers/media/media-device.c
+@@ -172,6 +172,44 @@ static long media_device_enum_links(struct media_device *mdev,
+ return 0;
+ }
+
++static long media_device_setup_link(struct media_device *mdev,
++ struct media_link_desc __user *_ulink)
++{
++ struct media_link *link = NULL;
++ struct media_link_desc ulink;
++ struct media_entity *source;
++ struct media_entity *sink;
++ int ret;
++
++ if (copy_from_user(&ulink, _ulink, sizeof(ulink)))
++ return -EFAULT;
++
++ /* Find the source and sink entities and link.
++ */
++ source = find_entity(mdev, ulink.source.entity);
++ sink = find_entity(mdev, ulink.sink.entity);
++
++ if (source == NULL || sink == NULL)
++ return -EINVAL;
++
++ if (ulink.source.index >= source->num_pads ||
++ ulink.sink.index >= sink->num_pads)
++ return -EINVAL;
++
++ link = media_entity_find_link(&source->pads[ulink.source.index],
++ &sink->pads[ulink.sink.index]);
++ if (link == NULL)
++ return -EINVAL;
++
++ /* Setup the link on both entities. */
++ ret = __media_entity_setup_link(link, ulink.flags);
++
++ if (copy_to_user(_ulink, &ulink, sizeof(ulink)))
++ return -EFAULT;
++
++ return ret;
++}
++
+ static long media_device_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+ {
+@@ -197,6 +235,13 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd,
+ mutex_unlock(&dev->graph_mutex);
+ break;
+
++ case MEDIA_IOC_SETUP_LINK:
++ mutex_lock(&dev->graph_mutex);
++ ret = media_device_setup_link(dev,
++ (struct media_link_desc __user *)arg);
++ mutex_unlock(&dev->graph_mutex);
++ break;
++
+ default:
+ ret = -ENOIOCTLCMD;
+ }
+diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
+index fe6bfd2..d703ce8 100644
+--- a/drivers/media/media-entity.c
++++ b/drivers/media/media-entity.c
+@@ -306,3 +306,158 @@ media_entity_create_link(struct media_entity *source, u16 source_pad,
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(media_entity_create_link);
++
++static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
++{
++ const u32 mask = MEDIA_LNK_FL_ENABLED;
++ int ret;
++
++ /* Notify both entities. */
++ ret = media_entity_call(link->source->entity, link_setup,
++ link->source, link->sink, flags);
++ if (ret < 0 && ret != -ENOIOCTLCMD)
++ return ret;
++
++ ret = media_entity_call(link->sink->entity, link_setup,
++ link->sink, link->source, flags);
++ if (ret < 0 && ret != -ENOIOCTLCMD) {
++ media_entity_call(link->source->entity, link_setup,
++ link->source, link->sink, link->flags);
++ return ret;
++ }
++
++ link->flags = (link->flags & ~mask) | (flags & mask);
++ link->reverse->flags = link->flags;
++
++ return 0;
++}
++
++/**
++ * __media_entity_setup_link - Configure a media link
++ * @link: The link being configured
++ * @flags: Link configuration flags
++ *
++ * The bulk of link setup is handled by the two entities connected through the
++ * link. This function notifies both entities of the link configuration change.
++ *
++ * If the link is immutable or if the current and new configuration are
++ * identical, return immediately.
++ *
++ * The user is expected to hold link->source->parent->mutex. If not,
++ * media_entity_setup_link() should be used instead.
++ */
++int __media_entity_setup_link(struct media_link *link, u32 flags)
++{
++ struct media_device *mdev;
++ struct media_entity *source, *sink;
++ int ret = -EBUSY;
++
++ if (link == NULL)
++ return -EINVAL;
++
++ if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
++ return link->flags == flags ? 0 : -EINVAL;
++
++ if (link->flags == flags)
++ return 0;
++
++ source = link->source->entity;
++ sink = link->sink->entity;
++
++ mdev = source->parent;
++
++ if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) {
++ ret = mdev->link_notify(link->source, link->sink,
++ MEDIA_LNK_FL_ENABLED);
++ if (ret < 0)
++ return ret;
++ }
++
++ ret = __media_entity_setup_link_notify(link, flags);
++ if (ret < 0)
++ goto err;
++
++ if (!(flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify)
++ mdev->link_notify(link->source, link->sink, 0);
++
++ return 0;
++
++err:
++ if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify)
++ mdev->link_notify(link->source, link->sink, 0);
++
++ return ret;
++}
++
++int media_entity_setup_link(struct media_link *link, u32 flags)
++{
++ int ret;
++
++ mutex_lock(&link->source->entity->parent->graph_mutex);
++ ret = __media_entity_setup_link(link, flags);
++ mutex_unlock(&link->source->entity->parent->graph_mutex);
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(media_entity_setup_link);
++
++/**
++ * media_entity_find_link - Find a link between two pads
++ * @source: Source pad
++ * @sink: Sink pad
++ *
++ * Return a pointer to the link between the two entities. If no such link
++ * exists, return NULL.
++ */
++struct media_link *
++media_entity_find_link(struct media_pad *source, struct media_pad *sink)
++{
++ struct media_link *link;
++ unsigned int i;
++
++ for (i = 0; i < source->entity->num_links; ++i) {
++ link = &source->entity->links[i];
++
++ if (link->source->entity == source->entity &&
++ link->source->index == source->index &&
++ link->sink->entity == sink->entity &&
++ link->sink->index == sink->index)
++ return link;
++ }
++
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(media_entity_find_link);
++
++/**
++ * media_entity_remote_source - Find the source pad at the remote end of a link
++ * @pad: Sink pad at the local end of the link
++ *
++ * Search for a remote source pad connected to the given sink pad by iterating
++ * over all links originating or terminating at that pad until an enabled link
++ * is found.
++ *
++ * Return a pointer to the pad at the remote end of the first found enabled
++ * link, or NULL if no enabled link has been found.
++ */
++struct media_pad *media_entity_remote_source(struct media_pad *pad)
++{
++ unsigned int i;
++
++ for (i = 0; i < pad->entity->num_links; i++) {
++ struct media_link *link = &pad->entity->links[i];
++
++ if (!(link->flags & MEDIA_LNK_FL_ENABLED))
++ continue;
++
++ if (link->source == pad)
++ return link->sink;
++
++ if (link->sink == pad)
++ return link->source;
++ }
++
++ return NULL;
++
++}
++EXPORT_SYMBOL_GPL(media_entity_remote_source);
+diff --git a/include/linux/media.h b/include/linux/media.h
+index 64c0313..2f67ed2 100644
+--- a/include/linux/media.h
++++ b/include/linux/media.h
+@@ -126,5 +126,6 @@ struct media_links_enum {
+ #define MEDIA_IOC_DEVICE_INFO _IOWR('M', 1, struct media_device_info)
+ #define MEDIA_IOC_ENUM_ENTITIES _IOWR('M', 2, struct media_entity_desc)
+ #define MEDIA_IOC_ENUM_LINKS _IOWR('M', 3, struct media_links_enum)
++#define MEDIA_IOC_SETUP_LINK _IOWR('M', 4, struct media_link_desc)
+
+ #endif /* __LINUX_MEDIA_H */
+diff --git a/include/media/media-device.h b/include/media/media-device.h
+index 260d59c..ad93e66 100644
+--- a/include/media/media-device.h
++++ b/include/media/media-device.h
+@@ -73,6 +73,9 @@ struct media_device {
+ spinlock_t lock;
+ /* Serializes graph operations. */
+ struct mutex graph_mutex;
++
++ int (*link_notify)(struct media_pad *source,
++ struct media_pad *sink, u32 flags);
+ };
+
+ /* media_devnode to media_device */
+diff --git a/include/media/media-entity.h b/include/media/media-entity.h
+index 0954490..60fc7bd 100644
+--- a/include/media/media-entity.h
++++ b/include/media/media-entity.h
+@@ -39,6 +39,12 @@ struct media_pad {
+ unsigned long flags; /* Pad flags (MEDIA_PAD_FL_*) */
+ };
+
++struct media_entity_operations {
++ int (*link_setup)(struct media_entity *entity,
++ const struct media_pad *local,
++ const struct media_pad *remote, u32 flags);
++};
++
+ struct media_entity {
+ struct list_head list;
+ struct media_device *parent; /* Media device this entity belongs to*/
+@@ -59,6 +65,8 @@ struct media_entity {
+ struct media_pad *pads; /* Pads array (num_pads elements) */
+ struct media_link *links; /* Links array (max_links elements)*/
+
++ const struct media_entity_operations *ops; /* Entity operations */
++
+ int use_count; /* Use count for the entity. */
+
+ union {
+@@ -108,6 +116,11 @@ int media_entity_init(struct media_entity *entity, u16 num_pads,
+ void media_entity_cleanup(struct media_entity *entity);
+ int media_entity_create_link(struct media_entity *source, u16 source_pad,
+ struct media_entity *sink, u16 sink_pad, u32 flags);
++int __media_entity_setup_link(struct media_link *link, u32 flags);
++int media_entity_setup_link(struct media_link *link, u32 flags);
++struct media_link *media_entity_find_link(struct media_pad *source,
++ struct media_pad *sink);
++struct media_pad *media_entity_remote_source(struct media_pad *pad);
+
+ struct media_entity *media_entity_get(struct media_entity *entity);
+ void media_entity_put(struct media_entity *entity);
+@@ -117,4 +130,8 @@ void media_entity_graph_walk_start(struct media_entity_graph *graph,
+ struct media_entity *
+ media_entity_graph_walk_next(struct media_entity_graph *graph);
+
++#define media_entity_call(entity, operation, args...) \
++ (((entity)->ops && (entity)->ops->operation) ? \
++ (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD)
++
+ #endif
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0016-media-Pipelines-and-media-streams.patch b/recipes-bsp/linux/linux-omap/media/0016-media-Pipelines-and-media-streams.patch
--- /dev/null
@@ -0,0 +1,259 @@
+From 4e07e9ada1b3baaec6d4948eccf3c0499e3228df Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 25 Aug 2010 15:00:41 +0300
+Subject: [PATCH 16/43] media: Pipelines and media streams
+
+Drivers often need to associate pipeline objects to entities, and to
+take stream state into account when configuring entities and links. The
+pipeline API helps drivers manage that information.
+
+When starting streaming, drivers call media_entity_pipeline_start(). The
+function marks all entities connected to the given entity through
+enabled links, either directly or indirectly, as streaming. Similarly,
+when stopping the stream, drivers call media_entity_pipeline_stop().
+
+The media_entity_pipeline_start() function takes a pointer to a media
+pipeline and stores it in every entity in the graph. Drivers should
+embed the media_pipeline structure in higher-level pipeline structures
+and can then access the pipeline through the media_entity structure.
+
+Link configuration will fail with -EBUSY by default if either end of the
+link is a streaming entity, unless the link is marked with the
+MEDIA_LNK_FL_DYNAMIC flag.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ Documentation/DocBook/v4l/media-ioc-enum-links.xml | 5 ++
+ Documentation/DocBook/v4l/media-ioc-setup-link.xml | 3 +
+ Documentation/media-framework.txt | 38 ++++++++++
+ drivers/media/media-entity.c | 73 ++++++++++++++++++++
+ include/linux/media.h | 1 +
+ include/media/media-entity.h | 10 +++
+ 6 files changed, 130 insertions(+), 0 deletions(-)
+
+diff --git a/Documentation/DocBook/v4l/media-ioc-enum-links.xml b/Documentation/DocBook/v4l/media-ioc-enum-links.xml
+index daf0360..b204bfb 100644
+--- a/Documentation/DocBook/v4l/media-ioc-enum-links.xml
++++ b/Documentation/DocBook/v4l/media-ioc-enum-links.xml
+@@ -179,6 +179,11 @@
+ <entry>The link enabled state can't be modified at runtime. An
+ immutable link is always enabled.</entry>
+ </row>
++ <row>
++ <entry><constant>MEDIA_LNK_FL_DYNAMIC</constant></entry>
++ <entry>The link enabled state can be modified during streaming. This
++ flag is set by drivers and is read-only for applications.</entry>
++ </row>
+ </tbody>
+ </tgroup>
+ </table>
+diff --git a/Documentation/DocBook/v4l/media-ioc-setup-link.xml b/Documentation/DocBook/v4l/media-ioc-setup-link.xml
+index 09ab3d2..2331e76 100644
+--- a/Documentation/DocBook/v4l/media-ioc-setup-link.xml
++++ b/Documentation/DocBook/v4l/media-ioc-setup-link.xml
+@@ -60,6 +60,9 @@
+ <para>Link configuration has no side effect on other links. If an enabled
+ link at the sink pad prevents the link from being enabled, the driver
+ returns with an &EBUSY;.</para>
++ <para>Only links marked with the <constant>DYNAMIC</constant> link flag can
++ be enabled/disabled while streaming media data. Attempting to enable or
++ disable a streaming non-dynamic link will return an &EBUSY;.</para>
+ <para>If the specified link can't be found the driver returns with an
+ &EINVAL;.</para>
+ </refsect1>
+diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt
+index 634845e..435d0c4 100644
+--- a/Documentation/media-framework.txt
++++ b/Documentation/media-framework.txt
+@@ -313,3 +313,41 @@ Link configuration must not have any side effect on other links. If an enabled
+ link at a sink pad prevents another link at the same pad from being disabled,
+ the link_setup operation must return -EBUSY and can't implicitly disable the
+ first enabled link.
++
++
++Pipelines and media streams
++---------------------------
++
++When starting streaming, drivers must notify all entities in the pipeline to
++prevent link states from being modified during streaming by calling
++
++ media_entity_pipeline_start(struct media_entity *entity,
++ struct media_pipeline *pipe);
++
++The function will mark all entities connected to the given entity through
++enabled links, either directly or indirectly, as streaming.
++
++The media_pipeline instance pointed to by the pipe argument will be stored in
++every entity in the pipeline. Drivers should embed the media_pipeline structure
++in higher-level pipeline structures and can then access the pipeline through
++the media_entity pipe field.
++
++Calls to media_entity_pipeline_start() can be nested. The pipeline pointer must
++be identical for all nested calls to the function.
++
++When stopping the stream, drivers must notify the entities with
++
++ media_entity_pipeline_stop(struct media_entity *entity);
++
++If multiple calls to media_entity_pipeline_start() have been made the same
++number of media_entity_pipeline_stop() calls are required to stop streaming. The
++media_entity pipe field is reset to NULL on the last nested stop call.
++
++Link configuration will fail with -EBUSY by default if either end of the link is
++a streaming entity. Links that can be modified while streaming must be marked
++with the MEDIA_LNK_FL_DYNAMIC flag.
++
++If other operations need to be disallowed on streaming entities (such as
++changing entities configuration parameters) drivers can explictly check the
++media_entity stream_count field to find out if an entity is streaming. This
++operation must be done with the media_device graph_mutex held.
+diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
+index d703ce8..e63e089 100644
+--- a/drivers/media/media-entity.c
++++ b/drivers/media/media-entity.c
+@@ -197,6 +197,75 @@ media_entity_graph_walk_next(struct media_entity_graph *graph)
+ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
+
+ /* -----------------------------------------------------------------------------
++ * Pipeline management
++ */
++
++/**
++ * media_entity_pipeline_start - Mark a pipeline as streaming
++ * @entity: Starting entity
++ * @pipe: Media pipeline to be assigned to all entities in the pipeline.
++ *
++ * Mark all entities connected to a given entity through enabled links, either
++ * directly or indirectly, as streaming. The given pipeline object is assigned to
++ * every entity in the pipeline and stored in the media_entity pipe field.
++ *
++ * Calls to this function can be nested, in which case the same number of
++ * media_entity_pipeline_stop() calls will be required to stop streaming. The
++ * pipeline pointer must be identical for all nested calls to
++ * media_entity_pipeline_start().
++ */
++void media_entity_pipeline_start(struct media_entity *entity,
++ struct media_pipeline *pipe)
++{
++ struct media_device *mdev = entity->parent;
++ struct media_entity_graph graph;
++
++ mutex_lock(&mdev->graph_mutex);
++
++ media_entity_graph_walk_start(&graph, entity);
++
++ while ((entity = media_entity_graph_walk_next(&graph))) {
++ entity->stream_count++;
++ WARN_ON(entity->pipe && entity->pipe != pipe);
++ entity->pipe = pipe;
++ }
++
++ mutex_unlock(&mdev->graph_mutex);
++}
++EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
++
++/**
++ * media_entity_pipeline_stop - Mark a pipeline as not streaming
++ * @entity: Starting entity
++ *
++ * Mark all entities connected to a given entity through enabled links, either
++ * directly or indirectly, as not streaming. The media_entity pipe field is
++ * reset to NULL.
++ *
++ * If multiple calls to media_entity_pipeline_start() have been made, the same
++ * number of calls to this function are required to mark the pipeline as not
++ * streaming.
++ */
++void media_entity_pipeline_stop(struct media_entity *entity)
++{
++ struct media_device *mdev = entity->parent;
++ struct media_entity_graph graph;
++
++ mutex_lock(&mdev->graph_mutex);
++
++ media_entity_graph_walk_start(&graph, entity);
++
++ while ((entity = media_entity_graph_walk_next(&graph))) {
++ entity->stream_count--;
++ if (entity->stream_count == 0)
++ entity->pipe = NULL;
++ }
++
++ mutex_unlock(&mdev->graph_mutex);
++}
++EXPORT_SYMBOL_GPL(media_entity_pipeline_stop);
++
++/* -----------------------------------------------------------------------------
+ * Module use count
+ */
+
+@@ -364,6 +433,10 @@ int __media_entity_setup_link(struct media_link *link, u32 flags)
+ source = link->source->entity;
+ sink = link->sink->entity;
+
++ if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
++ (source->stream_count || sink->stream_count))
++ return -EBUSY;
++
+ mdev = source->parent;
+
+ if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) {
+diff --git a/include/linux/media.h b/include/linux/media.h
+index 2f67ed2..29039e8 100644
+--- a/include/linux/media.h
++++ b/include/linux/media.h
+@@ -106,6 +106,7 @@ struct media_pad_desc {
+
+ #define MEDIA_LNK_FL_ENABLED (1 << 0)
+ #define MEDIA_LNK_FL_IMMUTABLE (1 << 1)
++#define MEDIA_LNK_FL_DYNAMIC (1 << 2)
+
+ struct media_link_desc {
+ struct media_pad_desc source;
+diff --git a/include/media/media-entity.h b/include/media/media-entity.h
+index 60fc7bd..450ba12 100644
+--- a/include/media/media-entity.h
++++ b/include/media/media-entity.h
+@@ -26,6 +26,9 @@
+ #include <linux/list.h>
+ #include <linux/media.h>
+
++struct media_pipeline {
++};
++
+ struct media_link {
+ struct media_pad *source; /* Source pad */
+ struct media_pad *sink; /* Sink pad */
+@@ -67,8 +70,11 @@ struct media_entity {
+
+ const struct media_entity_operations *ops; /* Entity operations */
+
++ int stream_count; /* Stream count for the entity. */
+ int use_count; /* Use count for the entity. */
+
++ struct media_pipeline *pipe; /* Pipeline this entity belongs to. */
++
+ union {
+ /* Node specifications */
+ struct {
+@@ -114,6 +120,7 @@ struct media_entity_graph {
+ int media_entity_init(struct media_entity *entity, u16 num_pads,
+ struct media_pad *pads, u16 extra_links);
+ void media_entity_cleanup(struct media_entity *entity);
++
+ int media_entity_create_link(struct media_entity *source, u16 source_pad,
+ struct media_entity *sink, u16 sink_pad, u32 flags);
+ int __media_entity_setup_link(struct media_link *link, u32 flags);
+@@ -129,6 +136,9 @@ void media_entity_graph_walk_start(struct media_entity_graph *graph,
+ struct media_entity *entity);
+ struct media_entity *
+ media_entity_graph_walk_next(struct media_entity_graph *graph);
++void media_entity_pipeline_start(struct media_entity *entity,
++ struct media_pipeline *pipe);
++void media_entity_pipeline_stop(struct media_entity *entity);
+
+ #define media_entity_call(entity, operation, args...) \
+ (((entity)->ops && (entity)->ops->operation) ? \
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0017-v4l-Add-a-media_device-pointer-to-the-v4l2_device-st.patch b/recipes-bsp/linux/linux-omap/media/0017-v4l-Add-a-media_device-pointer-to-the-v4l2_device-st.patch
--- /dev/null
+++ b/recipes-bsp/linux/linux-omap/media/0017-v4l-Add-a-media_device-pointer-to-the-v4l2_device-st.patch
@@ -0,0 +1,115 @@
+From 56e006c01032f98483195e572700e17fb8aaa8b1 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:40:05 +0100
+Subject: [PATCH 17/43] 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: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ Documentation/video4linux/v4l2-framework.txt | 17 ++++++++++++-----
+ drivers/media/video/v4l2-device.c | 13 +++++++------
+ include/media/v4l2-device.h | 4 ++++
+ 3 files changed, 23 insertions(+), 11 deletions(-)
+
+diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
+index 4db1def..aeb2a22 100644
+--- a/Documentation/video4linux/v4l2-framework.txt
++++ b/Documentation/video4linux/v4l2-framework.txt
+@@ -83,11 +83,17 @@ You must register the device instance:
+
+ v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
+
+-Registration will initialize the v4l2_device struct and link dev->driver_data
+-to v4l2_dev. 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.
++Registration will initialize the v4l2_device struct. If the dev->driver_data
++field is NULL, it will be linked to v4l2_dev. Drivers that use the media
++device framework in addition to the V4L2 framework need to set
++dev->driver_data manually to point to the driver-specific device structure
++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
+ a driver-global atomic_t instance. This will generate names like ivtv0, ivtv1,
+@@ -108,6 +114,7 @@ You unregister with:
+
+ 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.
+
+ If you have a hotpluggable device (e.g. a USB device), then when a disconnect
+diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
+index 97e84df..5c16a12 100644
+--- a/drivers/media/video/v4l2-device.c
++++ b/drivers/media/video/v4l2-device.c
+@@ -47,9 +47,8 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
+ if (!v4l2_dev->name[0])
+ snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
+ dev->driver->name, dev_name(dev));
+- if (dev_get_drvdata(dev))
+- v4l2_warn(v4l2_dev, "Non-NULL drvdata on register\n");
+- dev_set_drvdata(dev, v4l2_dev);
++ if (!dev_get_drvdata(dev))
++ dev_set_drvdata(dev, v4l2_dev);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(v4l2_device_register);
+@@ -72,10 +71,12 @@ EXPORT_SYMBOL_GPL(v4l2_device_set_name);
+
+ 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);
+- v4l2_dev->dev = NULL;
+- }
++ v4l2_dev->dev = NULL;
+ }
+ EXPORT_SYMBOL_GPL(v4l2_device_disconnect);
+
+diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h
+index b16f307..759db73 100644
+--- a/include/media/v4l2-device.h
++++ b/include/media/v4l2-device.h
+@@ -21,6 +21,7 @@
+ #ifndef _V4L2_DEVICE_H
+ #define _V4L2_DEVICE_H
+
++#include <media/media-device.h>
+ #include <media/v4l2-subdev.h>
+
+ /* Each instance of a V4L2 device should create the v4l2_device struct,
+@@ -39,6 +40,9 @@ struct v4l2_device {
+ Note: dev might be NULL if there is no parent device
+ as is the case with e.g. ISA devices. */
+ struct device *dev;
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ struct media_device *mdev;
++#endif
+ /* used to keep track of the registered subdevs */
+ struct list_head subdevs;
+ /* lock this struct; can be used by the driver as well if this
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0018-v4l-Make-video_device-inherit-from-media_entity.patch b/recipes-bsp/linux/linux-omap/media/0018-v4l-Make-video_device-inherit-from-media_entity.patch
--- /dev/null
@@ -0,0 +1,234 @@
+From e31cb57c733341b49256a47f086fa4cc1c1c56ac Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:40:10 +0100
+Subject: [PATCH 18/43] v4l: Make video_device inherit from media_entity
+
+V4L2 devices are media entities. As such they need to inherit from
+(include) the media_entity structure.
+
+When registering/unregistering the device, the media entity is
+automatically registered/unregistered. The entity is acquired on device
+open and released on device close.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ Documentation/video4linux/v4l2-framework.txt | 38 ++++++++++++++++++--
+ drivers/media/video/v4l2-dev.c | 49 +++++++++++++++++++++++--
+ include/media/v4l2-dev.h | 7 ++++
+ 3 files changed, 87 insertions(+), 7 deletions(-)
+
+diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
+index aeb2a22..f231bc2 100644
+--- a/Documentation/video4linux/v4l2-framework.txt
++++ b/Documentation/video4linux/v4l2-framework.txt
+@@ -71,6 +71,10 @@ sub-device instances, the video_device struct stores V4L2 device node data
+ and in the future a v4l2_fh struct will keep track of filehandle instances
+ (this is not yet implemented).
+
++The V4L2 framework also optionally integrates with the media framework. If a
++driver sets the struct v4l2_device mdev field, sub-devices and video nodes
++will automatically appear in the media framework as entities.
++
+
+ struct v4l2_device
+ ------------------
+@@ -84,11 +88,14 @@ You must register the device instance:
+ v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
+
+ Registration will initialize the v4l2_device struct. If the dev->driver_data
+-field is NULL, it will be linked to v4l2_dev. Drivers that use the media
+-device framework in addition to the V4L2 framework need to set
++field is NULL, it will be linked to v4l2_dev.
++
++Drivers that want integration with the media device framework need to set
+ dev->driver_data manually to point to the driver-specific device structure
+ that embed the struct v4l2_device instance. This is achieved by a
+-dev_set_drvdata() call before registering the V4L2 device instance.
++dev_set_drvdata() call before registering the V4L2 device instance. They must
++also set the struct v4l2_device mdev field to point to a properly initialized
++and registered media_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
+@@ -532,6 +539,21 @@ If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or
+ The v4l2_file_operations struct is a subset of file_operations. The main
+ difference is that the inode argument is omitted since it is never used.
+
++If integration with the media framework is needed, you must initialize the
++media_entity struct embedded in the video_device struct (entity field) by
++calling media_entity_init():
++
++ struct media_pad *pad = &my_vdev->pad;
++ int err;
++
++ err = media_entity_init(&vdev->entity, 1, pad, 0);
++
++The pads array must have been previously initialized. There is no need to
++manually set the struct media_entity type and name fields.
++
++A reference to the entity will be automatically acquired/released when the
++video device is opened/closed.
++
+ v4l2_file_operations and locking
+ --------------------------------
+
+@@ -561,6 +583,9 @@ for you.
+ return err;
+ }
+
++If the v4l2_device parent device has a non-NULL mdev field, the video device
++entity will be automatically registered with the media device.
++
+ Which device is registered depends on the type argument. The following
+ types exist:
+
+@@ -636,6 +661,13 @@ release, of course) will return an error as well.
+ When the last user of the video device node exits, then the vdev->release()
+ callback is called and you can do the final cleanup there.
+
++Don't forget to cleanup the media entity associated with the video device if
++it has been initialized:
++
++ media_entity_cleanup(&vdev->entity);
++
++This can be done from the release callback.
++
+
+ video_device helper functions
+ -----------------------------
+diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
+index f22bd41..f91348f 100644
+--- a/drivers/media/video/v4l2-dev.c
++++ b/drivers/media/video/v4l2-dev.c
+@@ -303,6 +303,9 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
+ static int v4l2_open(struct inode *inode, struct file *filp)
+ {
+ struct video_device *vdev;
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ struct media_entity *entity = NULL;
++#endif
+ int ret = 0;
+
+ /* Check if the video device is available */
+@@ -316,6 +319,16 @@ static int v4l2_open(struct inode *inode, struct file *filp)
+ /* and increase the device refcount */
+ video_get(vdev);
+ mutex_unlock(&videodev_lock);
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
++ entity = media_entity_get(&vdev->entity);
++ if (!entity) {
++ ret = -EBUSY;
++ video_put(vdev);
++ return ret;
++ }
++ }
++#endif
+ if (vdev->fops->open) {
+ if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
+ ret = -ERESTARTSYS;
+@@ -331,8 +344,13 @@ static int v4l2_open(struct inode *inode, struct file *filp)
+
+ err:
+ /* decrease the refcount in case of an error */
+- if (ret)
++ if (ret) {
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
++ media_entity_put(entity);
++#endif
+ video_put(vdev);
++ }
+ return ret;
+ }
+
+@@ -349,7 +367,10 @@ static int v4l2_release(struct inode *inode, struct file *filp)
+ if (vdev->lock)
+ mutex_unlock(vdev->lock);
+ }
+-
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
++ media_entity_put(&vdev->entity);
++#endif
+ /* decrease the refcount unconditionally since the release()
+ return value is ignored. */
+ video_put(vdev);
+@@ -586,12 +607,27 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
+ if (nr != -1 && nr != vdev->num && warn_if_nr_in_use)
+ printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__,
+ name_base, nr, video_device_node_name(vdev));
+-
+- /* Part 5: Activate this minor. The char device can now be used. */
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ /* Part 5: Register the entity. */
++ if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
++ vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
++ vdev->entity.name = vdev->name;
++ vdev->entity.v4l.major = VIDEO_MAJOR;
++ vdev->entity.v4l.minor = vdev->minor;
++ ret = media_device_register_entity(vdev->v4l2_dev->mdev,
++ &vdev->entity);
++ if (ret < 0)
++ printk(KERN_WARNING
++ "%s: media_device_register_entity failed\n",
++ __func__);
++ }
++#endif
++ /* Part 6: Activate this minor. The char device can now be used. */
+ set_bit(V4L2_FL_REGISTERED, &vdev->flags);
+ mutex_lock(&videodev_lock);
+ video_device[vdev->minor] = vdev;
+ mutex_unlock(&videodev_lock);
++
+ return 0;
+
+ cleanup:
+@@ -619,6 +655,11 @@ void video_unregister_device(struct video_device *vdev)
+ if (!vdev || !video_is_registered(vdev))
+ return;
+
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
++ media_device_unregister_entity(&vdev->entity);
++#endif
++
+ mutex_lock(&videodev_lock);
+ /* This must be in a critical section to prevent a race with v4l2_open.
+ * Once this bit has been cleared video_get may never be called again.
+diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
+index 4fe6831..51b2c51 100644
+--- a/include/media/v4l2-dev.h
++++ b/include/media/v4l2-dev.h
+@@ -16,6 +16,8 @@
+ #include <linux/mutex.h>
+ #include <linux/videodev2.h>
+
++#include <media/media-entity.h>
++
+ #define VIDEO_MAJOR 81
+
+ #define VFL_TYPE_GRABBER 0
+@@ -55,6 +57,9 @@ struct v4l2_file_operations {
+
+ struct video_device
+ {
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ struct media_entity entity;
++#endif
+ /* device ops */
+ const struct v4l2_file_operations *fops;
+
+@@ -100,6 +105,8 @@ struct video_device
+ struct mutex *lock;
+ };
+
++#define media_entity_to_video_device(entity) \
++ container_of(entity, struct video_device, entity)
+ /* dev to video-device */
+ #define to_video_device(cd) container_of(cd, struct video_device, dev)
+
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0019-v4l-Make-v4l2_subdev-inherit-from-media_entity.patch b/recipes-bsp/linux/linux-omap/media/0019-v4l-Make-v4l2_subdev-inherit-from-media_entity.patch
--- /dev/null
@@ -0,0 +1,265 @@
+From ab4bf9e43078f79ba2b287e6dd6d6871901d0341 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:40:08 +0100
+Subject: [PATCH 19/43] v4l: Make v4l2_subdev inherit from media_entity
+
+V4L2 subdevices are media entities. As such they need to inherit from
+(include) the media_entity structure.
+
+When registering/unregistering the subdevice, the media entity is
+automatically registered/unregistered. The entity is acquired on device
+open and released on device close.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ Documentation/video4linux/v4l2-framework.txt | 23 ++++++++++++++
+ drivers/media/video/v4l2-device.c | 39 ++++++++++++++++++++----
+ drivers/media/video/v4l2-subdev.c | 41 ++++++++++++++++++++++++-
+ include/media/v4l2-subdev.h | 10 ++++++
+ 4 files changed, 104 insertions(+), 9 deletions(-)
+
+diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
+index f231bc2..d0fb880 100644
+--- a/Documentation/video4linux/v4l2-framework.txt
++++ b/Documentation/video4linux/v4l2-framework.txt
+@@ -268,6 +268,26 @@ A sub-device driver initializes the v4l2_subdev struct using:
+ Afterwards you need to initialize subdev->name with a unique name and set the
+ module owner. This is done for you if you use the i2c helper functions.
+
++If integration with the media framework is needed, you must initialize the
++media_entity struct embedded in the v4l2_subdev struct (entity field) by
++calling media_entity_init():
++
++ struct media_pad *pads = &my_sd->pads;
++ int err;
++
++ err = media_entity_init(&sd->entity, npads, pads, 0);
++
++The pads array must have been previously initialized. There is no need to
++manually set the struct media_entity type and name fields, but the revision
++field must be initialized if needed.
++
++A reference to the entity will be automatically acquired/released when the
++subdev device node (if any) is opened/closed.
++
++Don't forget to cleanup the media entity before the sub-device is destroyed:
++
++ media_entity_cleanup(&sd->entity);
++
+ A device (bridge) driver needs to register the v4l2_subdev with the
+ v4l2_device:
+
+@@ -277,6 +297,9 @@ This can fail if the subdev module disappeared before it could be registered.
+ After this function was called successfully the subdev->dev field points to
+ the v4l2_device.
+
++If the v4l2_device parent device has a non-NULL mdev field, the sub-device
++entity will be automatically registered with the media device.
++
+ You can unregister a sub-device using:
+
+ v4l2_device_unregister_subdev(sd);
+diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
+index 5c16a12..69cb429 100644
+--- a/drivers/media/video/v4l2-device.c
++++ b/drivers/media/video/v4l2-device.c
+@@ -116,8 +116,11 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev)
+ EXPORT_SYMBOL_GPL(v4l2_device_unregister);
+
+ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
+- struct v4l2_subdev *sd)
++ struct v4l2_subdev *sd)
+ {
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ struct media_entity *entity = &sd->entity;
++#endif
+ struct video_device *vdev;
+ int err;
+
+@@ -135,7 +138,16 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
+ err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
+ if (err)
+ return err;
+-
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ /* Register the entity. */
++ if (v4l2_dev->mdev) {
++ err = media_device_register_entity(v4l2_dev->mdev, entity);
++ if (err < 0) {
++ module_put(sd->owner);
++ return err;
++ }
++ }
++#endif
+ sd->v4l2_dev = v4l2_dev;
+ spin_lock(&v4l2_dev->lock);
+ list_add_tail(&sd->list, &v4l2_dev->subdevs);
+@@ -150,26 +162,39 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
+ if (sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE) {
+ err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
+ sd->owner);
+- if (err < 0)
++ if (err < 0) {
+ v4l2_device_unregister_subdev(sd);
++ return err;
++ }
+ }
+-
+- return err;
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ entity->v4l.major = VIDEO_MAJOR;
++ entity->v4l.minor = vdev->minor;
++#endif
++ return 0;
+ }
+ EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
+
+ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
+ {
++ struct v4l2_device *v4l2_dev;
++
+ /* return if it isn't registered */
+ if (sd == NULL || sd->v4l2_dev == NULL)
+ return;
+
+- spin_lock(&sd->v4l2_dev->lock);
++ v4l2_dev = sd->v4l2_dev;
++
++ spin_lock(&v4l2_dev->lock);
+ list_del(&sd->list);
+- spin_unlock(&sd->v4l2_dev->lock);
++ spin_unlock(&v4l2_dev->lock);
+ sd->v4l2_dev = NULL;
+
+ module_put(sd->owner);
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ if (v4l2_dev->mdev)
++ media_device_unregister_entity(&sd->entity);
++#endif
+ video_unregister_device(&sd->devnode);
+ }
+ EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
+diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
+index fbccefd..a49856a 100644
+--- a/drivers/media/video/v4l2-subdev.c
++++ b/drivers/media/video/v4l2-subdev.c
+@@ -35,7 +35,10 @@ static int subdev_open(struct file *file)
+ {
+ struct video_device *vdev = video_devdata(file);
+ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+- struct v4l2_fh *vfh;
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ struct media_entity *entity;
++#endif
++ struct v4l2_fh *vfh = NULL;
+ int ret;
+
+ if (!sd->initialized)
+@@ -61,11 +64,20 @@ static int subdev_open(struct file *file)
+ v4l2_fh_add(vfh);
+ file->private_data = vfh;
+ }
+-
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ if (sd->v4l2_dev->mdev) {
++ entity = media_entity_get(&sd->entity);
++ if (!entity) {
++ ret = -EBUSY;
++ goto err;
++ }
++ }
++#endif
+ return 0;
+
+ err:
+ if (vfh != NULL) {
++ v4l2_fh_del(vfh);
+ v4l2_fh_exit(vfh);
+ kfree(vfh);
+ }
+@@ -75,8 +87,16 @@ err:
+
+ static int subdev_close(struct file *file)
+ {
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ struct video_device *vdev = video_devdata(file);
++ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
++#endif
+ struct v4l2_fh *vfh = file->private_data;
+
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ if (sd->v4l2_dev->mdev)
++ media_entity_put(&sd->entity);
++#endif
+ if (vfh != NULL) {
+ v4l2_fh_del(vfh);
+ v4l2_fh_exit(vfh);
+@@ -176,5 +196,22 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
+ sd->dev_priv = NULL;
+ sd->host_priv = NULL;
+ sd->initialized = 1;
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ sd->entity.name = sd->name;
++ sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
++#endif
+ }
+ EXPORT_SYMBOL(v4l2_subdev_init);
++
++#if defined(CONFIG_MEDIA_CONTROLLER)
++int v4l2_subdev_set_power(struct media_entity *entity, int power)
++{
++ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
++
++ dev_dbg(entity->parent->dev,
++ "%s power%s\n", entity->name, power ? "on" : "off");
++
++ return v4l2_subdev_call(sd, core, s_power, power);
++}
++EXPORT_SYMBOL_GPL(v4l2_subdev_set_power);
++#endif
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index 68cbe48..7d55b0c 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -21,6 +21,7 @@
+ #ifndef _V4L2_SUBDEV_H
+ #define _V4L2_SUBDEV_H
+
++#include <media/media-entity.h>
+ #include <media/v4l2-common.h>
+ #include <media/v4l2-dev.h>
+ #include <media/v4l2-mediabus.h>
+@@ -437,6 +438,9 @@ struct v4l2_subdev_ops {
+ stand-alone or embedded in a larger struct.
+ */
+ struct v4l2_subdev {
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ struct media_entity entity;
++#endif
+ struct list_head list;
+ struct module *owner;
+ u32 flags;
+@@ -458,6 +462,8 @@ struct v4l2_subdev {
+ unsigned int nevents;
+ };
+
++#define media_entity_to_v4l2_subdev(ent) \
++ container_of(ent, struct v4l2_subdev, entity)
+ #define vdev_to_v4l2_subdev(vdev) \
+ container_of(vdev, struct v4l2_subdev, devnode)
+
+@@ -486,6 +492,10 @@ static inline void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd)
+ void v4l2_subdev_init(struct v4l2_subdev *sd,
+ const struct v4l2_subdev_ops *ops);
+
++#if defined(CONFIG_MEDIA_CONTROLLER)
++int v4l2_subdev_set_power(struct media_entity *entity, int power);
++#endif
++
+ /* Call an ops of a v4l2_subdev, doing the right checks against
+ NULL pointers.
+
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0020-v4l-Move-the-media-v4l2-mediabus.h-header-to-include.patch b/recipes-bsp/linux/linux-omap/media/0020-v4l-Move-the-media-v4l2-mediabus.h-header-to-include.patch
--- /dev/null
+++ b/recipes-bsp/linux/linux-omap/media/0020-v4l-Move-the-media-v4l2-mediabus.h-header-to-include.patch
@@ -0,0 +1,205 @@
+From 0d2a2247733eca8f357f5a93fcc357edbb941ec1 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Mon, 15 Mar 2010 23:33:31 +0100
+Subject: [PATCH 20/43] v4l: Move the media/v4l2-mediabus.h header to include/linux
+
+The header defines the v4l2_mbus_framefmt structure which will be used
+by the V4L2 subdevs userspace API.
+
+Change the type of the v4l2_mbus_framefmt::code field to __u32, as enum
+sizes can differ between different ABIs on the same architectures.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ include/linux/Kbuild | 1 +
+ include/linux/v4l2-mediabus.h | 78 +++++++++++++++++++++++++++++++++++++++++
+ include/media/soc_mediabus.h | 3 +-
+ include/media/v4l2-mediabus.h | 61 +-------------------------------
+ 4 files changed, 81 insertions(+), 62 deletions(-)
+ create mode 100644 include/linux/v4l2-mediabus.h
+
+diff --git a/include/linux/Kbuild b/include/linux/Kbuild
+index 26e0a7f..796e1d8 100644
+--- a/include/linux/Kbuild
++++ b/include/linux/Kbuild
+@@ -366,6 +366,7 @@ header-y += unistd.h
+ header-y += usbdevice_fs.h
+ header-y += utime.h
+ header-y += utsname.h
++header-y += v4l2-mediabus.h
+ header-y += veth.h
+ header-y += vhost.h
+ header-y += videodev.h
+diff --git a/include/linux/v4l2-mediabus.h b/include/linux/v4l2-mediabus.h
+new file mode 100644
+index 0000000..a62cd64
+--- /dev/null
++++ b/include/linux/v4l2-mediabus.h
+@@ -0,0 +1,78 @@
++/*
++ * Media Bus API header
++ *
++ * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __LINUX_V4L2_MEDIABUS_H
++#define __LINUX_V4L2_MEDIABUS_H
++
++#include <linux/types.h>
++#include <linux/videodev2.h>
++
++/*
++ * These pixel codes uniquely identify data formats on the media bus. Mostly
++ * they correspond to similarly named V4L2_PIX_FMT_* formats, format 0 is
++ * reserved, V4L2_MBUS_FMT_FIXED shall be used by host-client pairs, where the
++ * data format is fixed. Additionally, "2X8" means that one pixel is transferred
++ * in two 8-bit samples, "BE" or "LE" specify in which order those samples are
++ * transferred over the bus: "LE" means that the least significant bits are
++ * transferred first, "BE" means that the most significant bits are transferred
++ * first, and "PADHI" and "PADLO" define which bits - low or high, in the
++ * incomplete high byte, are filled with padding bits.
++ */
++enum v4l2_mbus_pixelcode {
++ V4L2_MBUS_FMT_FIXED = 1,
++ V4L2_MBUS_FMT_YUYV8_2X8,
++ V4L2_MBUS_FMT_YVYU8_2X8,
++ V4L2_MBUS_FMT_UYVY8_2X8,
++ V4L2_MBUS_FMT_VYUY8_2X8,
++ V4L2_MBUS_FMT_YVYU10_2X10,
++ V4L2_MBUS_FMT_YUYV10_2X10,
++ V4L2_MBUS_FMT_YVYU10_1X20,
++ V4L2_MBUS_FMT_YUYV10_1X20,
++ V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
++ V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE,
++ V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
++ V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
++ V4L2_MBUS_FMT_RGB565_2X8_LE,
++ V4L2_MBUS_FMT_RGB565_2X8_BE,
++ V4L2_MBUS_FMT_BGR565_2X8_LE,
++ V4L2_MBUS_FMT_BGR565_2X8_BE,
++ V4L2_MBUS_FMT_SBGGR8_1X8,
++ V4L2_MBUS_FMT_SBGGR10_1X10,
++ V4L2_MBUS_FMT_GREY8_1X8,
++ V4L2_MBUS_FMT_Y10_1X10,
++ V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE,
++ V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
++ V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE,
++ V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE,
++ V4L2_MBUS_FMT_SGRBG8_1X8,
++ V4L2_MBUS_FMT_SBGGR12_1X12,
++ V4L2_MBUS_FMT_YUYV8_1_5X8,
++ V4L2_MBUS_FMT_YVYU8_1_5X8,
++ V4L2_MBUS_FMT_UYVY8_1_5X8,
++ V4L2_MBUS_FMT_VYUY8_1_5X8,
++};
++
++/**
++ * struct v4l2_mbus_framefmt - frame format on the media bus
++ * @width: frame width
++ * @height: frame height
++ * @code: data format code
++ * @field: used interlacing type
++ * @colorspace: colorspace of the data
++ */
++struct v4l2_mbus_framefmt {
++ __u32 width;
++ __u32 height;
++ __u32 code;
++ enum v4l2_field field;
++ enum v4l2_colorspace colorspace;
++};
++
++#endif
+diff --git a/include/media/soc_mediabus.h b/include/media/soc_mediabus.h
+index 037cd7b..6243147 100644
+--- a/include/media/soc_mediabus.h
++++ b/include/media/soc_mediabus.h
+@@ -12,8 +12,7 @@
+ #define SOC_MEDIABUS_H
+
+ #include <linux/videodev2.h>
+-
+-#include <media/v4l2-mediabus.h>
++#include <linux/v4l2-mediabus.h>
+
+ /**
+ * enum soc_mbus_packing - data packing types on the media-bus
+diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h
+index 8e65598..971c7fa 100644
+--- a/include/media/v4l2-mediabus.h
++++ b/include/media/v4l2-mediabus.h
+@@ -11,66 +11,7 @@
+ #ifndef V4L2_MEDIABUS_H
+ #define V4L2_MEDIABUS_H
+
+-/*
+- * These pixel codes uniquely identify data formats on the media bus. Mostly
+- * they correspond to similarly named V4L2_PIX_FMT_* formats, format 0 is
+- * reserved, V4L2_MBUS_FMT_FIXED shall be used by host-client pairs, where the
+- * data format is fixed. Additionally, "2X8" means that one pixel is transferred
+- * in two 8-bit samples, "BE" or "LE" specify in which order those samples are
+- * transferred over the bus: "LE" means that the least significant bits are
+- * transferred first, "BE" means that the most significant bits are transferred
+- * first, and "PADHI" and "PADLO" define which bits - low or high, in the
+- * incomplete high byte, are filled with padding bits.
+- */
+-enum v4l2_mbus_pixelcode {
+- V4L2_MBUS_FMT_FIXED = 1,
+- V4L2_MBUS_FMT_YUYV8_2X8,
+- V4L2_MBUS_FMT_YVYU8_2X8,
+- V4L2_MBUS_FMT_UYVY8_2X8,
+- V4L2_MBUS_FMT_VYUY8_2X8,
+- V4L2_MBUS_FMT_YVYU10_2X10,
+- V4L2_MBUS_FMT_YUYV10_2X10,
+- V4L2_MBUS_FMT_YVYU10_1X20,
+- V4L2_MBUS_FMT_YUYV10_1X20,
+- V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
+- V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE,
+- V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+- V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
+- V4L2_MBUS_FMT_RGB565_2X8_LE,
+- V4L2_MBUS_FMT_RGB565_2X8_BE,
+- V4L2_MBUS_FMT_BGR565_2X8_LE,
+- V4L2_MBUS_FMT_BGR565_2X8_BE,
+- V4L2_MBUS_FMT_SBGGR8_1X8,
+- V4L2_MBUS_FMT_SBGGR10_1X10,
+- V4L2_MBUS_FMT_GREY8_1X8,
+- V4L2_MBUS_FMT_Y10_1X10,
+- V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE,
+- V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
+- V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE,
+- V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE,
+- V4L2_MBUS_FMT_SGRBG8_1X8,
+- V4L2_MBUS_FMT_SBGGR12_1X12,
+- V4L2_MBUS_FMT_YUYV8_1_5X8,
+- V4L2_MBUS_FMT_YVYU8_1_5X8,
+- V4L2_MBUS_FMT_UYVY8_1_5X8,
+- V4L2_MBUS_FMT_VYUY8_1_5X8,
+-};
+-
+-/**
+- * struct v4l2_mbus_framefmt - frame format on the media bus
+- * @width: frame width
+- * @height: frame height
+- * @code: data format code
+- * @field: used interlacing type
+- * @colorspace: colorspace of the data
+- */
+-struct v4l2_mbus_framefmt {
+- __u32 width;
+- __u32 height;
+- enum v4l2_mbus_pixelcode code;
+- enum v4l2_field field;
+- enum v4l2_colorspace colorspace;
+-};
++#include <linux/v4l2-mediabus.h>
+
+ static inline void v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt,
+ const struct v4l2_mbus_framefmt *mbus_fmt)
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0021-v4l-Replace-enums-with-fixed-sized-fields-in-public-.patch b/recipes-bsp/linux/linux-omap/media/0021-v4l-Replace-enums-with-fixed-sized-fields-in-public-.patch
--- /dev/null
+++ b/recipes-bsp/linux/linux-omap/media/0021-v4l-Replace-enums-with-fixed-sized-fields-in-public-.patch
@@ -0,0 +1,50 @@
+From fb1156d3125e36952f884b09afb9d0815ddeafd7 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 6 Oct 2010 08:30:26 +0200
+Subject: [PATCH 21/43] v4l: Replace enums with fixed-sized fields in public structure
+
+The v4l2_mbus_framefmt structure will be part of the public userspace
+API and used (albeit indirectly) as an ioctl argument. As such, its size
+must be fixed across userspace ABIs.
+
+Replace the v4l2_field and v4l2_colorspace enums by __u32 fields and add
+padding for future enhancements.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ include/linux/v4l2-mediabus.h | 17 +++++++++--------
+ 1 files changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/include/linux/v4l2-mediabus.h b/include/linux/v4l2-mediabus.h
+index a62cd64..feeb88c 100644
+--- a/include/linux/v4l2-mediabus.h
++++ b/include/linux/v4l2-mediabus.h
+@@ -63,16 +63,17 @@ enum v4l2_mbus_pixelcode {
+ * struct v4l2_mbus_framefmt - frame format on the media bus
+ * @width: frame width
+ * @height: frame height
+- * @code: data format code
+- * @field: used interlacing type
+- * @colorspace: colorspace of the data
++ * @code: data format code (from enum v4l2_mbus_pixelcode)
++ * @field: used interlacing type (from enum v4l2_field)
++ * @colorspace: colorspace of the data (from enum v4l2_colorspace)
+ */
+ struct v4l2_mbus_framefmt {
+- __u32 width;
+- __u32 height;
+- __u32 code;
+- enum v4l2_field field;
+- enum v4l2_colorspace colorspace;
++ __u32 width;
++ __u32 height;
++ __u32 code;
++ __u32 field;
++ __u32 colorspace;
++ __u32 reserved[7];
+ };
+
+ #endif
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0022-v4l-Rename-V4L2_MBUS_FMT_GREY8_1X8-to-V4L2_MBUS_FMT_.patch b/recipes-bsp/linux/linux-omap/media/0022-v4l-Rename-V4L2_MBUS_FMT_GREY8_1X8-to-V4L2_MBUS_FMT_.patch
--- /dev/null
+++ b/recipes-bsp/linux/linux-omap/media/0022-v4l-Rename-V4L2_MBUS_FMT_GREY8_1X8-to-V4L2_MBUS_FMT_.patch
@@ -0,0 +1,154 @@
+From 0be9c8b998cef9ce650e1e53d12bb5a6d772d151 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Tue, 28 Sep 2010 12:01:44 +0200
+Subject: [PATCH 22/43] v4l: Rename V4L2_MBUS_FMT_GREY8_1X8 to V4L2_MBUS_FMT_Y8_1X8
+
+For consistency with the V4L2_MBUS_FMT_Y10_1X10 format.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/video/mt9m001.c | 2 +-
+ drivers/media/video/mt9v022.c | 4 ++--
+ drivers/media/video/ov6650.c | 10 +++++-----
+ drivers/media/video/sh_mobile_csi2.c | 6 +++---
+ drivers/media/video/soc_mediabus.c | 2 +-
+ include/linux/v4l2-mediabus.h | 2 +-
+ 6 files changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
+index fcb4cd9..3aaedf6 100644
+--- a/drivers/media/video/mt9m001.c
++++ b/drivers/media/video/mt9m001.c
+@@ -79,7 +79,7 @@ static const struct mt9m001_datafmt mt9m001_colour_fmts[] = {
+ static const struct mt9m001_datafmt mt9m001_monochrome_fmts[] = {
+ /* Order important - see above */
+ {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
+- {V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG},
++ {V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
+ };
+
+ struct mt9m001 {
+diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
+index b96171c..56dd4fc 100644
+--- a/drivers/media/video/mt9v022.c
++++ b/drivers/media/video/mt9v022.c
+@@ -95,7 +95,7 @@ static const struct mt9v022_datafmt mt9v022_colour_fmts[] = {
+ static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = {
+ /* Order important - see above */
+ {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
+- {V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG},
++ {V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
+ };
+
+ struct mt9v022 {
+@@ -392,7 +392,7 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd,
+ * icd->try_fmt(), datawidth is from our supported format list
+ */
+ switch (mf->code) {
+- case V4L2_MBUS_FMT_GREY8_1X8:
++ case V4L2_MBUS_FMT_Y8_1X8:
+ case V4L2_MBUS_FMT_Y10_1X10:
+ if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
+ return -EINVAL;
+diff --git a/drivers/media/video/ov6650.c b/drivers/media/video/ov6650.c
+index cf93de9..fe8e3eb 100644
+--- a/drivers/media/video/ov6650.c
++++ b/drivers/media/video/ov6650.c
+@@ -207,7 +207,7 @@ static enum v4l2_mbus_pixelcode ov6650_codes[] = {
+ V4L2_MBUS_FMT_YVYU8_2X8,
+ V4L2_MBUS_FMT_VYUY8_2X8,
+ V4L2_MBUS_FMT_SBGGR8_1X8,
+- V4L2_MBUS_FMT_GREY8_1X8,
++ V4L2_MBUS_FMT_Y8_1X8,
+ };
+
+ static const struct v4l2_queryctrl ov6650_controls[] = {
+@@ -800,7 +800,7 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+
+ /* select color matrix configuration for given color encoding */
+ switch (code) {
+- case V4L2_MBUS_FMT_GREY8_1X8:
++ case V4L2_MBUS_FMT_Y8_1X8:
+ dev_dbg(&client->dev, "pixel format GREY8_1X8\n");
+ coma_mask |= COMA_RGB | COMA_WORD_SWAP | COMA_BYTE_SWAP;
+ coma_set |= COMA_BW;
+@@ -846,7 +846,7 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+ }
+ priv->code = code;
+
+- if (code == V4L2_MBUS_FMT_GREY8_1X8 ||
++ if (code == V4L2_MBUS_FMT_Y8_1X8 ||
+ code == V4L2_MBUS_FMT_SBGGR8_1X8) {
+ coml_mask = COML_ONE_CHANNEL;
+ coml_set = 0;
+@@ -936,8 +936,8 @@ static int ov6650_try_fmt(struct v4l2_subdev *sd,
+
+ switch (mf->code) {
+ case V4L2_MBUS_FMT_Y10_1X10:
+- mf->code = V4L2_MBUS_FMT_GREY8_1X8;
+- case V4L2_MBUS_FMT_GREY8_1X8:
++ mf->code = V4L2_MBUS_FMT_Y8_1X8;
++ case V4L2_MBUS_FMT_Y8_1X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
+diff --git a/drivers/media/video/sh_mobile_csi2.c b/drivers/media/video/sh_mobile_csi2.c
+index 84a6468..dd1b81b 100644
+--- a/drivers/media/video/sh_mobile_csi2.c
++++ b/drivers/media/video/sh_mobile_csi2.c
+@@ -56,7 +56,7 @@ static int sh_csi2_try_fmt(struct v4l2_subdev *sd,
+ switch (mf->code) {
+ case V4L2_MBUS_FMT_UYVY8_2X8: /* YUV422 */
+ case V4L2_MBUS_FMT_YUYV8_1_5X8: /* YUV420 */
+- case V4L2_MBUS_FMT_GREY8_1X8: /* RAW8 */
++ case V4L2_MBUS_FMT_Y8_1X8: /* RAW8 */
+ case V4L2_MBUS_FMT_SBGGR8_1X8:
+ case V4L2_MBUS_FMT_SGRBG8_1X8:
+ break;
+@@ -67,7 +67,7 @@ static int sh_csi2_try_fmt(struct v4l2_subdev *sd,
+ break;
+ case SH_CSI2I:
+ switch (mf->code) {
+- case V4L2_MBUS_FMT_GREY8_1X8: /* RAW8 */
++ case V4L2_MBUS_FMT_Y8_1X8: /* RAW8 */
+ case V4L2_MBUS_FMT_SBGGR8_1X8:
+ case V4L2_MBUS_FMT_SGRBG8_1X8:
+ case V4L2_MBUS_FMT_SBGGR10_1X10: /* RAW10 */
+@@ -111,7 +111,7 @@ static int sh_csi2_s_fmt(struct v4l2_subdev *sd,
+ case V4L2_MBUS_FMT_RGB565_2X8_BE:
+ tmp |= 0x22; /* RGB565 */
+ break;
+- case V4L2_MBUS_FMT_GREY8_1X8:
++ case V4L2_MBUS_FMT_Y8_1X8:
+ case V4L2_MBUS_FMT_SBGGR8_1X8:
+ case V4L2_MBUS_FMT_SGRBG8_1X8:
+ tmp |= 0x2a; /* RAW8 */
+diff --git a/drivers/media/video/soc_mediabus.c b/drivers/media/video/soc_mediabus.c
+index 9139121..d9c297d 100644
+--- a/drivers/media/video/soc_mediabus.c
++++ b/drivers/media/video/soc_mediabus.c
+@@ -88,7 +88,7 @@ static const struct soc_mbus_pixelfmt mbus_fmt[] = {
+ .packing = SOC_MBUS_PACKING_EXTEND16,
+ .order = SOC_MBUS_ORDER_LE,
+ },
+- [MBUS_IDX(GREY8_1X8)] = {
++ [MBUS_IDX(Y8_1X8)] = {
+ .fourcc = V4L2_PIX_FMT_GREY,
+ .name = "Grey",
+ .bits_per_sample = 8,
+diff --git a/include/linux/v4l2-mediabus.h b/include/linux/v4l2-mediabus.h
+index feeb88c..dc1d5c0 100644
+--- a/include/linux/v4l2-mediabus.h
++++ b/include/linux/v4l2-mediabus.h
+@@ -45,7 +45,7 @@ enum v4l2_mbus_pixelcode {
+ V4L2_MBUS_FMT_BGR565_2X8_BE,
+ V4L2_MBUS_FMT_SBGGR8_1X8,
+ V4L2_MBUS_FMT_SBGGR10_1X10,
+- V4L2_MBUS_FMT_GREY8_1X8,
++ V4L2_MBUS_FMT_Y8_1X8,
+ V4L2_MBUS_FMT_Y10_1X10,
+ V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE,
+ V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0023-v4l-Group-media-bus-pixel-codes-by-types-and-sort-th.patch b/recipes-bsp/linux/linux-omap/media/0023-v4l-Group-media-bus-pixel-codes-by-types-and-sort-th.patch
--- /dev/null
+++ b/recipes-bsp/linux/linux-omap/media/0023-v4l-Group-media-bus-pixel-codes-by-types-and-sort-th.patch
@@ -0,0 +1,112 @@
+From 9a13751e47503b4c966538e194a5027e5e7d9c5d Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 1 Sep 2010 17:58:22 +0200
+Subject: [PATCH 23/43] v4l: Group media bus pixel codes by types and sort them alphabetically
+
+Adding new pixel codes at the end of the enumeration will soon create a
+mess, so group the pixel codes by type and sort them by bus_width, bits
+per component, samples per pixel and order of subsamples.
+
+As the codes are part of the kernel ABI their value can't change when a
+new code is inserted in the enumeration, so they are given an explicit
+numerical value. When inserting a new pixel code developers must use and
+update the next free value.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ include/linux/v4l2-mediabus.h | 77 ++++++++++++++++++++++++----------------
+ 1 files changed, 46 insertions(+), 31 deletions(-)
+
+diff --git a/include/linux/v4l2-mediabus.h b/include/linux/v4l2-mediabus.h
+index dc1d5c0..cccfa34 100644
+--- a/include/linux/v4l2-mediabus.h
++++ b/include/linux/v4l2-mediabus.h
+@@ -24,39 +24,54 @@
+ * transferred first, "BE" means that the most significant bits are transferred
+ * first, and "PADHI" and "PADLO" define which bits - low or high, in the
+ * incomplete high byte, are filled with padding bits.
++ *
++ * The pixel codes are grouped by type, bus_width, bits per component, samples
++ * per pixel and order of subsamples. Numerical values are sorted using generic
++ * numerical sort order (8 thus comes before 10).
++ *
++ * As their value can't change when a new pixel code is inserted in the
++ * enumeration, the pixel codes are explicitly given a numerical value. The next
++ * free values for each category are listed below, update them when inserting
++ * new pixel codes.
+ */
+ enum v4l2_mbus_pixelcode {
+- V4L2_MBUS_FMT_FIXED = 1,
+- V4L2_MBUS_FMT_YUYV8_2X8,
+- V4L2_MBUS_FMT_YVYU8_2X8,
+- V4L2_MBUS_FMT_UYVY8_2X8,
+- V4L2_MBUS_FMT_VYUY8_2X8,
+- V4L2_MBUS_FMT_YVYU10_2X10,
+- V4L2_MBUS_FMT_YUYV10_2X10,
+- V4L2_MBUS_FMT_YVYU10_1X20,
+- V4L2_MBUS_FMT_YUYV10_1X20,
+- V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
+- V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE,
+- V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+- V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
+- V4L2_MBUS_FMT_RGB565_2X8_LE,
+- V4L2_MBUS_FMT_RGB565_2X8_BE,
+- V4L2_MBUS_FMT_BGR565_2X8_LE,
+- V4L2_MBUS_FMT_BGR565_2X8_BE,
+- V4L2_MBUS_FMT_SBGGR8_1X8,
+- V4L2_MBUS_FMT_SBGGR10_1X10,
+- V4L2_MBUS_FMT_Y8_1X8,
+- V4L2_MBUS_FMT_Y10_1X10,
+- V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE,
+- V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
+- V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE,
+- V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE,
+- V4L2_MBUS_FMT_SGRBG8_1X8,
+- V4L2_MBUS_FMT_SBGGR12_1X12,
+- V4L2_MBUS_FMT_YUYV8_1_5X8,
+- V4L2_MBUS_FMT_YVYU8_1_5X8,
+- V4L2_MBUS_FMT_UYVY8_1_5X8,
+- V4L2_MBUS_FMT_VYUY8_1_5X8,
++ V4L2_MBUS_FMT_FIXED = 0x0001,
++
++ /* RGB - next is 0x1009 */
++ V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE = 0x1001,
++ V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE = 0x1002,
++ V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE = 0x1003,
++ V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE = 0x1004,
++ V4L2_MBUS_FMT_BGR565_2X8_BE = 0x1005,
++ V4L2_MBUS_FMT_BGR565_2X8_LE = 0x1006,
++ V4L2_MBUS_FMT_RGB565_2X8_BE = 0x1007,
++ V4L2_MBUS_FMT_RGB565_2X8_LE = 0x1008,
++
++ /* YUV (including grey) - next is 0x200f */
++ V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
++ V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
++ V4L2_MBUS_FMT_VYUY8_1_5X8 = 0x2003,
++ V4L2_MBUS_FMT_YUYV8_1_5X8 = 0x2004,
++ V4L2_MBUS_FMT_YVYU8_1_5X8 = 0x2005,
++ V4L2_MBUS_FMT_UYVY8_2X8 = 0x2006,
++ V4L2_MBUS_FMT_VYUY8_2X8 = 0x2007,
++ V4L2_MBUS_FMT_YUYV8_2X8 = 0x2008,
++ V4L2_MBUS_FMT_YVYU8_2X8 = 0x2009,
++ V4L2_MBUS_FMT_Y10_1X10 = 0x200a,
++ V4L2_MBUS_FMT_YUYV10_2X10 = 0x200b,
++ V4L2_MBUS_FMT_YVYU10_2X10 = 0x200c,
++ V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d,
++ V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
++
++ /* Bayer - next is 0x3009 */
++ V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
++ V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002,
++ V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE = 0x3003,
++ V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE = 0x3004,
++ V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE = 0x3005,
++ V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE = 0x3006,
++ V4L2_MBUS_FMT_SBGGR10_1X10 = 0x3007,
++ V4L2_MBUS_FMT_SBGGR12_1X12 = 0x3008,
+ };
+
+ /**
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0024-v4l-Create-v4l2-subdev-file-handle-structure.patch b/recipes-bsp/linux/linux-omap/media/0024-v4l-Create-v4l2-subdev-file-handle-structure.patch
--- /dev/null
@@ -0,0 +1,243 @@
+From 47f7677adda05f6d85a35047c4aac940c46a123c Mon Sep 17 00:00:00 2001
+From: Stanimir Varbanov <svarbanov@mm-sol.com>
+Date: Fri, 21 May 2010 12:04:24 +0300
+Subject: [PATCH 24/43] v4l: Create v4l2 subdev file handle structure
+
+Used for storing subdev information per file handle and hold V4L2 file
+handle.
+
+Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
+Signed-off-by: Antti Koskipaa <antti.koskipaa@nokia.com>
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/Kconfig | 9 ++++
+ drivers/media/video/v4l2-subdev.c | 85 +++++++++++++++++++++++++------------
+ include/media/v4l2-subdev.h | 29 +++++++++++++
+ 3 files changed, 96 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
+index 6b946e6..eaf4734 100644
+--- a/drivers/media/Kconfig
++++ b/drivers/media/Kconfig
+@@ -82,6 +82,15 @@ config VIDEO_V4L1_COMPAT
+
+ If you are unsure as to whether this is required, answer Y.
+
++config VIDEO_V4L2_SUBDEV_API
++ bool "V4L2 sub-device userspace API (EXPERIMENTAL)"
++ depends on VIDEO_DEV && MEDIA_CONTROLLER && EXPERIMENTAL
++ ---help---
++ Enables the V4L2 sub-device pad-level userspace API used to configure
++ video format, size and frame rate between hardware blocks.
++
++ This API is mostly used by camera interfaces in embedded platforms.
++
+ #
+ # DVB Core
+ #
+diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
+index a49856a..15449fc 100644
+--- a/drivers/media/video/v4l2-subdev.c
++++ b/drivers/media/video/v4l2-subdev.c
+@@ -31,39 +31,69 @@
+ #include <media/v4l2-fh.h>
+ #include <media/v4l2-event.h>
+
++static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd)
++{
++#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
++ /* Allocate try format and crop in the same memory block */
++ fh->try_fmt = kzalloc((sizeof(*fh->try_fmt) + sizeof(*fh->try_crop))
++ * sd->entity.num_pads, GFP_KERNEL);
++ if (fh->try_fmt == NULL)
++ return -ENOMEM;
++
++ fh->try_crop = (struct v4l2_rect *)
++ (fh->try_fmt + sd->entity.num_pads);
++#endif
++ return 0;
++}
++
++static void subdev_fh_free(struct v4l2_subdev_fh *fh)
++{
++#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
++ kfree(fh->try_fmt);
++ fh->try_fmt = NULL;
++ fh->try_crop = NULL;
++#endif
++}
++
+ static int subdev_open(struct file *file)
+ {
+ struct video_device *vdev = video_devdata(file);
+ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
++ struct v4l2_subdev_fh *subdev_fh;
+ #if defined(CONFIG_MEDIA_CONTROLLER)
+ struct media_entity *entity;
+ #endif
+- struct v4l2_fh *vfh = NULL;
+ int ret;
+
+ if (!sd->initialized)
+ return -EAGAIN;
+
+- if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) {
+- vfh = kzalloc(sizeof(*vfh), GFP_KERNEL);
+- if (vfh == NULL)
+- return -ENOMEM;
++ subdev_fh = kzalloc(sizeof(*subdev_fh), GFP_KERNEL);
++ if (subdev_fh == NULL)
++ return -ENOMEM;
+
+- ret = v4l2_fh_init(vfh, vdev);
+- if (ret)
+- goto err;
++ ret = subdev_fh_init(subdev_fh, sd);
++ if (ret) {
++ kfree(subdev_fh);
++ return ret;
++ }
++
++ ret = v4l2_fh_init(&subdev_fh->vfh, vdev);
++ if (ret)
++ goto err;
+
+- ret = v4l2_event_init(vfh);
++ if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) {
++ ret = v4l2_event_init(&subdev_fh->vfh);
+ if (ret)
+ goto err;
+
+- ret = v4l2_event_alloc(vfh, sd->nevents);
++ ret = v4l2_event_alloc(&subdev_fh->vfh, sd->nevents);
+ if (ret)
+ goto err;
+-
+- v4l2_fh_add(vfh);
+- file->private_data = vfh;
+ }
++
++ v4l2_fh_add(&subdev_fh->vfh);
++ file->private_data = &subdev_fh->vfh;
+ #if defined(CONFIG_MEDIA_CONTROLLER)
+ if (sd->v4l2_dev->mdev) {
+ entity = media_entity_get(&sd->entity);
+@@ -73,14 +103,14 @@ static int subdev_open(struct file *file)
+ }
+ }
+ #endif
++
+ return 0;
+
+ err:
+- if (vfh != NULL) {
+- v4l2_fh_del(vfh);
+- v4l2_fh_exit(vfh);
+- kfree(vfh);
+- }
++ v4l2_fh_del(&subdev_fh->vfh);
++ v4l2_fh_exit(&subdev_fh->vfh);
++ subdev_fh_free(subdev_fh);
++ kfree(subdev_fh);
+
+ return ret;
+ }
+@@ -92,16 +122,17 @@ static int subdev_close(struct file *file)
+ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+ #endif
+ struct v4l2_fh *vfh = file->private_data;
++ struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
+
+ #if defined(CONFIG_MEDIA_CONTROLLER)
+ if (sd->v4l2_dev->mdev)
+ media_entity_put(&sd->entity);
+ #endif
+- if (vfh != NULL) {
+- v4l2_fh_del(vfh);
+- v4l2_fh_exit(vfh);
+- kfree(vfh);
+- }
++ v4l2_fh_del(vfh);
++ v4l2_fh_exit(vfh);
++ subdev_fh_free(subdev_fh);
++ kfree(subdev_fh);
++ file->private_data = NULL;
+
+ return 0;
+ }
+@@ -110,7 +141,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+ {
+ struct video_device *vdev = video_devdata(file);
+ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+- struct v4l2_fh *fh = file->private_data;
++ struct v4l2_fh *vfh = file->private_data;
+
+ switch (cmd) {
+ case VIDIOC_QUERYCTRL:
+@@ -138,13 +169,13 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+ if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
+ return -ENOIOCTLCMD;
+
+- return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK);
++ return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK);
+
+ case VIDIOC_SUBSCRIBE_EVENT:
+- return v4l2_subdev_call(sd, core, subscribe_event, fh, arg);
++ return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg);
+
+ case VIDIOC_UNSUBSCRIBE_EVENT:
+- return v4l2_subdev_call(sd, core, unsubscribe_event, fh, arg);
++ return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg);
+
+ default:
+ return -ENOIOCTLCMD;
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index 7d55b0c..f8704ff 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -24,6 +24,7 @@
+ #include <media/media-entity.h>
+ #include <media/v4l2-common.h>
+ #include <media/v4l2-dev.h>
++#include <media/v4l2-fh.h>
+ #include <media/v4l2-mediabus.h>
+
+ /* generic v4l2_device notify callback notification values */
+@@ -467,6 +468,34 @@ struct v4l2_subdev {
+ #define vdev_to_v4l2_subdev(vdev) \
+ container_of(vdev, struct v4l2_subdev, devnode)
+
++/*
++ * Used for storing subdev information per file handle
++ */
++struct v4l2_subdev_fh {
++ struct v4l2_fh vfh;
++#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
++ struct v4l2_mbus_framefmt *try_fmt;
++ struct v4l2_rect *try_crop;
++#endif
++};
++
++#define to_v4l2_subdev_fh(fh) \
++ container_of(fh, struct v4l2_subdev_fh, vfh)
++
++#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
++static inline struct v4l2_mbus_framefmt *
++v4l2_subdev_get_try_format(struct v4l2_subdev_fh *fh, unsigned int pad)
++{
++ return &fh->try_fmt[pad];
++}
++
++static inline struct v4l2_rect *
++v4l2_subdev_get_try_crop(struct v4l2_subdev_fh *fh, unsigned int pad)
++{
++ return &fh->try_crop[pad];
++}
++#endif
++
+ extern const struct v4l2_file_operations v4l2_subdev_fops;
+
+ static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0025-v4l-subdev-Add-a-new-file-operations-class.patch b/recipes-bsp/linux/linux-omap/media/0025-v4l-subdev-Add-a-new-file-operations-class.patch
--- /dev/null
@@ -0,0 +1,93 @@
+From 4dc43ce10d8b66537a680635d4f2dbe0a1daa1d9 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Mon, 2 Aug 2010 00:05:09 +0200
+Subject: [PATCH 25/43] v4l: subdev: Add a new file operations class
+
+V4L2 sub-devices store pad formats and crop settings in the file handle.
+To let drivers initialize those settings properly, add a file::open
+operation that is called when the subdev is opened as well as a
+corresponding file::close operation.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/media/video/v4l2-subdev.c | 13 ++++++++++---
+ include/media/v4l2-subdev.h | 10 ++++++++++
+ 2 files changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
+index 15449fc..0f904e2 100644
+--- a/drivers/media/video/v4l2-subdev.c
++++ b/drivers/media/video/v4l2-subdev.c
+@@ -61,7 +61,7 @@ static int subdev_open(struct file *file)
+ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+ struct v4l2_subdev_fh *subdev_fh;
+ #if defined(CONFIG_MEDIA_CONTROLLER)
+- struct media_entity *entity;
++ struct media_entity *entity = NULL;
+ #endif
+ int ret;
+
+@@ -104,9 +104,17 @@ static int subdev_open(struct file *file)
+ }
+ #endif
+
++ ret = v4l2_subdev_call(sd, file, open, subdev_fh);
++ if (ret < 0 && ret != -ENOIOCTLCMD)
++ goto err;
++
+ return 0;
+
+ err:
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ if (entity)
++ media_entity_put(entity);
++#endif
+ v4l2_fh_del(&subdev_fh->vfh);
+ v4l2_fh_exit(&subdev_fh->vfh);
+ subdev_fh_free(subdev_fh);
+@@ -117,13 +125,12 @@ err:
+
+ static int subdev_close(struct file *file)
+ {
+-#if defined(CONFIG_MEDIA_CONTROLLER)
+ struct video_device *vdev = video_devdata(file);
+ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+-#endif
+ struct v4l2_fh *vfh = file->private_data;
+ struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
+
++ v4l2_subdev_call(sd, file, close, subdev_fh);
+ #if defined(CONFIG_MEDIA_CONTROLLER)
+ if (sd->v4l2_dev->mdev)
+ media_entity_put(&sd->entity);
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index f8704ff..af704df 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -175,6 +175,15 @@ struct v4l2_subdev_core_ops {
+ struct v4l2_event_subscription *sub);
+ };
+
++/* open: called when the subdev device node is opened by an application.
++
++ close: called when the subdev device node is close.
++ */
++struct v4l2_subdev_file_ops {
++ int (*open)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
++ int (*close)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
++};
++
+ /* s_mode: switch the tuner to a specific tuner mode. Replacement of s_radio.
+
+ s_radio: v4l device was opened in Radio mode, to be replaced by s_mode.
+@@ -416,6 +425,7 @@ struct v4l2_subdev_ir_ops {
+
+ struct v4l2_subdev_ops {
+ const struct v4l2_subdev_core_ops *core;
++ const struct v4l2_subdev_file_ops *file;
+ const struct v4l2_subdev_tuner_ops *tuner;
+ const struct v4l2_subdev_audio_ops *audio;
+ const struct v4l2_subdev_video_ops *video;
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0026-v4l-v4l2_subdev-pad-level-operations.patch b/recipes-bsp/linux/linux-omap/media/0026-v4l-v4l2_subdev-pad-level-operations.patch
--- /dev/null
@@ -0,0 +1,49 @@
+From 7a089b741d5c2ca3881d61e81971a1a0e464aa27 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:39:52 +0100
+Subject: [PATCH 26/43] v4l: v4l2_subdev pad-level operations
+
+Add a v4l2_subdev_pad_ops structure for the operations that need to be
+performed at the pad level such as format-related operations.
+
+Pad format-related operations use v4l2_mbus_framefmt instead of
+v4l2_format.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ include/media/v4l2-subdev.h | 5 +++++
+ 1 files changed, 5 insertions(+), 0 deletions(-)
+
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index af704df..4f6ddba 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -42,6 +42,7 @@ struct v4l2_ctrl_handler;
+ struct v4l2_event_subscription;
+ struct v4l2_fh;
+ struct v4l2_subdev;
++struct v4l2_subdev_fh;
+ struct tuner_setup;
+
+ /* decode_vbi_line */
+@@ -423,6 +424,9 @@ struct v4l2_subdev_ir_ops {
+ struct v4l2_subdev_ir_parameters *params);
+ };
+
++struct v4l2_subdev_pad_ops {
++};
++
+ struct v4l2_subdev_ops {
+ const struct v4l2_subdev_core_ops *core;
+ const struct v4l2_subdev_file_ops *file;
+@@ -432,6 +436,7 @@ struct v4l2_subdev_ops {
+ const struct v4l2_subdev_vbi_ops *vbi;
+ const struct v4l2_subdev_ir_ops *ir;
+ const struct v4l2_subdev_sensor_ops *sensor;
++ const struct v4l2_subdev_pad_ops *pad;
+ };
+
+ #define V4L2_SUBDEV_NAME_SIZE 32
+--
+1.6.6.1
+
diff --git a/recipes-bsp/linux/linux-omap/media/0028-v4l-v4l2_subdev-userspace-format-API.patch b/recipes-bsp/linux/linux-omap/media/0028-v4l-v4l2_subdev-userspace-format-API.patch
--- /dev/null
@@ -0,0 +1,3546 @@
+From 58fa3ca8af541e6704ac11703fc3091d856e0700 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Tue, 16 Mar 2010 00:26:04 +0100
+Subject: [PATCH 28/43] v4l: v4l2_subdev userspace format API
+
+Add a userspace API to get, set and enumerate the media format on a
+subdev pad.
+
+The format at the output of a subdev usually depends on the format at
+its input(s). The try format operation is thus not suitable for probing
+format at individual pads, as it can't modify the device state and thus
+can't remember the format tried at the input to compute the output
+format.
+
+To fix the problem, pass an extra argument to the get/set format
+operations to select the 'try' or 'active' format.
+
+The try format is used when probing the subdev. Setting the try format
+must not change the device configuration but can store data for later
+reuse. Data storage is provided at the file-handle level so applications
+probing the subdev concurently won't interfere with each other.
+
+The active format is used when configuring the subdev. It's identical to
+the format handled by the usual get/set operations.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ Documentation/DocBook/Makefile | 5 +-
+ Documentation/DocBook/media-entities.tmpl | 16 +
+ Documentation/DocBook/v4l/dev-subdev.xml | 274 +++
+ Documentation/DocBook/v4l/subdev-formats.xml | 2416 ++++++++++++++++++++
+ Documentation/DocBook/v4l/v4l2.xml | 4 +
+ Documentation/DocBook/v4l/vidioc-streamon.xml | 9 +
+ .../DocBook/v4l/vidioc-subdev-enum-frame-size.xml | 148 ++
+ .../DocBook/v4l/vidioc-subdev-enum-mbus-code.xml | 113 +
+ Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml | 174 ++
+ drivers/media/video/v4l2-subdev.c | 49 +
+ include/linux/Kbuild | 1 +
+ include/linux/v4l2-subdev.h | 90 +
+ include/media/v4l2-subdev.h | 10 +
+ 13 files changed, 3308 insertions(+), 1 deletions(-)
+ create mode 100644 Documentation/DocBook/v4l/dev-subdev.xml
+ create mode 100644 Documentation/DocBook/v4l/subdev-formats.xml
+ create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml
+ create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml
+ create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml
+ create mode 100644 include/linux/v4l2-subdev.h
+
+diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
+index 8b6e00a..2deb069 100644
+--- a/Documentation/DocBook/Makefile
++++ b/Documentation/DocBook/Makefile
+@@ -53,7 +53,10 @@ MAN := $(patsubst %.xml, %.9, $(BOOKS))
+ mandocs: $(MAN)
+
+ build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \
+- cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(objtree)/Documentation/DocBook/media/
++ cp $(srctree)/Documentation/DocBook/dvb/*.png \
++ $(srctree)/Documentation/DocBook/v4l/*.gif \
++ $(srctree)/Documentation/DocBook/v4l/*.png \
++ $(objtree)/Documentation/DocBook/media/
+
+ xmldoclinks:
+ ifneq ($(objtree),$(srctree))
+diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
+index 679c585..538f8fe 100644
+--- a/Documentation/DocBook/media-entities.tmpl
++++ b/Documentation/DocBook/media-entities.tmpl
+@@ -86,6 +86,10 @@
+ <!ENTITY VIDIOC-S-PRIORITY "<link linkend='vidioc-g-priority'><constant>VIDIOC_S_PRIORITY</constant></link>">
+ <!ENTITY VIDIOC-S-STD "<link linkend='vidioc-g-std'><constant>VIDIOC_S_STD</constant></link>">
+ <!ENTITY VIDIOC-S-TUNER "<link linkend='vidioc-g-tuner'><constant>VIDIOC_S_TUNER</constant></link>">
++<!ENTITY VIDIOC-SUBDEV-ENUM-FRAME-SIZE "<link linkend='vidioc-subdev-enum-frame-size'><constant>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</constant></link>">
++<!ENTITY VIDIOC-SUBDEV-ENUM-MBUS-CODE "<link linkend='vidioc-subdev-enum-mbus-code'><constant>VIDIOC_SUBDEV_ENUM_MBUS_CODE</constant></link>">
++<!ENTITY VIDIOC-SUBDEV-G-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_G_FMT</constant></link>">
++<!ENTITY VIDIOC-SUBDEV-S-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_S_FMT</constant></link>">
+ <!ENTITY VIDIOC-TRY-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_TRY_ENCODER_CMD</constant></link>">
+ <!ENTITY VIDIOC-TRY-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_TRY_EXT_CTRLS</constant></link>">
+ <!ENTITY VIDIOC-TRY-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_TRY_FMT</constant></link>">
+@@ -107,6 +111,7 @@
+ <!ENTITY v4l2-field "enum <link linkend='v4l2-field'>v4l2_field</link>">
+ <!ENTITY v4l2-frmivaltypes "enum <link linkend='v4l2-frmivaltypes'>v4l2_frmivaltypes</link>">
+ <!ENTITY v4l2-frmsizetypes "enum <link linkend='v4l2-frmsizetypes'>v4l2_frmsizetypes</link>">
++<!ENTITY v4l2-mbus-pixelcode "enum <link linkend='v4l2-mbus-pixelcode'>v4l2_mbus_pixelcode</link>">
+ <!ENTITY v4l2-memory "enum <link linkend='v4l2-memory'>v4l2_memory</link>">
+ <!ENTITY v4l2-mpeg-audio-ac3-bitrate "enum <link linkend='v4l2-mpeg-audio-ac3-bitrate'>v4l2_mpeg_audio_ac3_bitrate</link>">
+ <!ENTITY v4l2-mpeg-audio-crc "enum <link linkend='v4l2-mpeg-audio-crc'>v4l2_mpeg_audio_crc</link>">
+@@ -130,6 +135,7 @@
+ <!ENTITY v4l2-mpeg-video-encoding "enum <link linkend='v4l2-mpeg-video-encoding'>v4l2_mpeg_video_encoding</link>">
+ <!ENTITY v4l2-power-line-frequency "enum <link linkend='v4l2-power-line-frequency'>v4l2_power_line_frequency</link>">
+ <!ENTITY v4l2-priority "enum <link linkend='v4l2-priority'>v4l2_priority</link>">
++<!ENTITY v4l2-subdev-format-whence "enum <link linkend='v4l2-subdev-format-whence'>v4l2_subdev_format_whence</link>">
+ <!ENTITY v4l2-tuner-type "enum <link linkend='v4l2-tuner-type'>v4l2_tuner_type</link>">
+ <!ENTITY v4l2-preemphasis "enum <link linkend='v4l2-preemphasis'>v4l2_preemphasis</link>">
+
+@@ -171,6 +177,7 @@
+ <!ENTITY v4l2-hw-freq-seek "struct <link linkend='v4l2-hw-freq-seek'>v4l2_hw_freq_seek</link>">
+ <!ENTITY v4l2-input "struct <link linkend='v4l2-input'>v4l2_input</link>">
+ <!ENTITY v4l2-jpegcompression "struct <link linkend='v4l2-jpegcompression'>v4l2_jpegcompression</link>">
++<!ENTITY v4l2-mbus-framefmt "struct <link linkend='v4l2-mbus-framefmt'>v4l2_mbus_framefmt</link>">
+ <!ENTITY v4l2-modulator "struct <link linkend='v4l2-modulator'>v4l2_modulator</link>">
+ <!ENTITY v4l2-mpeg-vbi-fmt-ivtv "struct <link linkend='v4l2-mpeg-vbi-fmt-ivtv'>v4l2_mpeg_vbi_fmt_ivtv</link>">
+ <!ENTITY v4l2-output "struct <link linkend='v4l2-output'>v4l2_output</link>">
+@@ -183,6 +190,9 @@
+ <!ENTITY v4l2-sliced-vbi-cap "struct <link linkend='v4l2-sliced-vbi-cap'>v4l2_sliced_vbi_cap</link>">
+ <!ENTITY v4l2-sliced-vbi-data "struct <link linkend='v4l2-sliced-vbi-data'>v4l2_sliced_vbi_data</link>">
+ <!ENTITY v4l2-sliced-vbi-format "struct <link linkend='v4l2-sliced-vbi-format'>v4l2_sliced_vbi_format</link>">
++<!ENTITY v4l2-subdev-frame-size-enum "struct <link linkend='v4l2-subdev-frame-size-enum'>v4l2_subdev_frame_size_enum</link>">
++<!ENTITY v4l2-subdev-format "struct <link linkend='v4l2-subdev-format'>v4l2_subdev_format</link>">
++<!ENTITY v4l2-subdev-mbus-code-enum "struct <link linkend='v4l2-subdev-mbus-code-enum'>v4l2_subdev_mbus_code_enum</link>">
+ <!ENTITY v4l2-standard "struct <link linkend='v4l2-standard'>v4l2_standard</link>">
+ <!ENTITY v4l2-streamparm "struct <link linkend='v4l2-streamparm'>v4l2_streamparm</link>">
+ <!ENTITY v4l2-timecode "struct <link linkend='v4l2-timecode'>v4l2_timecode</link>">
+@@ -212,6 +222,7 @@
+ <!ENTITY ENXIO "<errorcode>ENXIO</errorcode> error code">
+ <!ENTITY EMFILE "<errorcode>EMFILE</errorcode> error code">
+ <!ENTITY EPERM "<errorcode>EPERM</errorcode> error code">
++<!ENTITY EPIPE "<errorcode>EPIPE</errorcode> error code">
+ <!ENTITY ERANGE "<errorcode>ERANGE</errorcode> error code">
+
+ <!-- Subsections -->
+@@ -230,6 +241,7 @@
+ <!ENTITY sub-dev-raw-vbi SYSTEM "v4l/dev-raw-vbi.xml">
+ <!ENTITY sub-dev-rds SYSTEM "v4l/dev-rds.xml">
+ <!ENTITY sub-dev-sliced-vbi SYSTEM "v4l/dev-sliced-vbi.xml">
++<!ENTITY sub-dev-subdev SYSTEM "v4l/dev-subdev.xml">
+ <!ENTITY sub-dev-teletext SYSTEM "v4l/dev-teletext.xml">
+ <!ENTITY sub-driver SYSTEM "v4l/driver.xml">
+ <!ENTITY sub-libv4l SYSTEM "v4l/libv4l.xml">
+@@ -313,6 +325,10 @@
+ <!ENTITY sub-reqbufs SYSTEM "v4l/vidioc-reqbufs.xml">
+ <!ENTITY sub-s-hw-freq-seek SYSTEM "v4l/vidioc-s-hw-freq-seek.xml">
+ <!ENTITY sub-streamon SYSTEM "v4l/vidioc-streamon.xml">
++<!ENTITY sub-subdev-enum-frame-size SYSTEM "v4l/vidioc-subdev-enum-frame-size.xml">
++<!ENTITY sub-subdev-enum-mbus-code SYSTEM "v4l/vidioc-subdev-enum-mbus-code.xml">
++<!ENTITY sub-subdev-formats SYSTEM "v4l/subdev-formats.xml">
++<!ENTITY sub-subdev-g-fmt SYSTEM "v4l/vidioc-subdev-g-fmt.xml">
+ <!ENTITY sub-capture-c SYSTEM "v4l/capture.c.xml">
+ <!ENTITY sub-keytable-c SYSTEM "v4l/keytable.c.xml">
+ <!ENTITY sub-v4l2grab-c SYSTEM "v4l/v4l2grab.c.xml">
+diff --git a/Documentation/DocBook/v4l/dev-subdev.xml b/Documentation/DocBook/v4l/dev-subdev.xml
+new file mode 100644
+index 0000000..12fdca4
+--- /dev/null
++++ b/Documentation/DocBook/v4l/dev-subdev.xml
+@@ -0,0 +1,274 @@
++ <title>Sub-device Interface</title>
++
++ <para>The complex nature of V4L2 devices, where hardware is often made of
++ several integrated circuits that need to interact with each other in a
++ controlled way, leads to complex V4L2 drivers. The drivers usually reflect
++ the hardware model in software, and model the different hardware components
++ as software blocks called sub-devices.</para>
++
++ <para>V4L2 sub-devices are usually kernel-only objects. If the V4L2 driver
++ implements the media device API, they will automatically inherit from media
++ entities. Applications will be able to enumerate the sub-devices and discover
++ the hardware topology using the media entities, pads and links enumeration
++ API.</para>
++
++ <para>In addition to make sub-devices discoverable, drivers can also choose
++ to make them directly configurable by applications. When both the sub-device
++ driver and the V4L2 device driver support this, sub-devices will feature a
++ character device node on which ioctls can be called to
++ <itemizedlist>
++ <listitem>query, read and write sub-devices controls</listitem>
++ <listitem>subscribe and unsubscribe to events and retrieve them</listitem>
++ <listitem>negotiate image formats on individual pads</listitem>
++ </itemizedlist>
++ </para>
++
++ <para>Sub-device character device nodes, conventionally named
++ <filename>/dev/v4l-subdev*</filename>, use major number 81.</para>
++
++ <section>
++ <title>Controls</title>
++ <para>Most V4L2 controls are implemented by sub-device hardware. Drivers
++ usually merge all controls and expose them through video device nodes.
++ Applications can control all sub-devices through a single interface.</para>
++
++ <para>Complex devices sometimes implement the same control in different
++ pieces of hardware. This situation is common in embedded platforms, where
++ both sensors and image processing hardware implement identical functions,
++ such as contrast adjustment, white balance or faulty pixels correction. As
++ the V4L2 controls API doesn't support several identical controls in a single
++ device, all but one of the identical controls are hidden.</para>
++
++ <para>Applications can access those hidden controls through the sub-device
++ node with the V4L2 control API described in <xref linkend="control" />. The
++ ioctls behave identically as when issued on V4L2 device nodes, with the
++ exception that they deal only with controls implemented in the sub-device.
++ </para>
++
++ <para>Depending on the driver, those controls might also be exposed through
++ one (or several) V4L2 device nodes.</para>
++ </section>
++
++ <section>
++ <title>Events</title>
++ <para>V4L2 sub-devices can notify applications of events as described in
++ <xref linkend="event" />. The API behaves identically as when used on V4L2
++ device nodes, with the exception that it only deals with events generated by
++ the sub-device. Depending on the driver, those events might also be reported
++ on one (or several) V4L2 device nodes.</para>
++ </section>
++
++ <section id="pad-level-formats">
++ <title>Pad-level Formats</title>
++
++ <warning>Pad-level formats are only applicable to very complex device that
++ need to expose low-level format configuration to user space. Generic V4L2
++ applications do <emphasis>not</emphasis> need to use the API described in
++ this section.</warning>
++
++ <note>For the purpose of this section, the term
++ <wordasword>format</wordasword> means the combination of media bus data
++ format, frame width and frame height.</note>
++
++ <para>Image formats are typically negotiated on video capture and output
++ devices using the <link linkend="crop">cropping and scaling</link> ioctls.
++ The driver is responsible for configuring every block in the video pipeline
++ according to the requested format at the pipeline input and/or
++ output.</para>
++
++ <para>For complex devices, such as often found in embedded systems,
++ identical image sizes at the output of a pipeline can be achieved using
++ different hardware configurations. One such exemple is shown on
++ <xref linkend="pipeline-scaling" xrefstyle="template: Figure %n" />, where
++ image scaling can be performed on both the video sensor and the host image
++ processing hardware.</para>
++
++ <figure id="pipeline-scaling">
++ <title>Image Format Negotation on Pipelines</title>
++ <mediaobject>
++ <imageobject>
++ <imagedata fileref="pipeline.pdf" format="PS" />
++ </imageobject>
++ <imageobject>
++ <imagedata fileref="pipeline.png" format="PNG" />
++ </imageobject>
++ <textobject>
++ <phrase>High quality and high speed pipeline configuration</phrase>
++ </textobject>
++ </mediaobject>
++ </figure>
++
++ <para>The sensor scaler is usually of less quality than the host scaler, but
++ scaling on the sensor is required to achieve higher frame rates. Depending
++ on the use case (quality vs. speed), the pipeline must be configured
++ differently. Applications need to configure the formats at every point in
++ the pipeline explicitly.</para>
++
++ <para>Drivers that implement the <link linkend="media-controller-intro">media
++ API</link> can expose pad-level image format configuration to applications.
++ When they do, applications can use the &VIDIOC-SUBDEV-G-FMT; and
++ &VIDIOC-SUBDEV-S-FMT; ioctls. to negotiate formats on a per-pad basis.</para>
++
++ <para>Applications are responsible for configuring coherent parameters on
++ the whole pipeline and making sure that connected pads have compatible
++ formats. The pipeline is checked for formats mismatch at &VIDIOC-STREAMON;
++ time, and an &EPIPE; is then returned if the configuration is
++ invalid.</para>
++
++ <para>Pad-level image format configuration support can be tested by calling
++ the &VIDIOC-SUBDEV-G-FMT; ioctl on pad 0. If the driver returns an &EINVAL;
++ pad-level format configuration is not supported by the sub-device.</para>
++
++ <section>
++ <title>Format Negotiation</title>
++
++ <para>Acceptable formats on pads can (and usually do) depend on a number
++ of external parameters, such as formats on other pads, active links, or
++ even controls. Finding a combination of formats on all pads in a video
++ pipeline, acceptable to both application and driver, can't rely on formats
++ enumeration only. A format negotiation mechanism is required.</para>
++
++ <para>Central to the format negotiation mechanism are the get/set format
++ operations. When called with the <structfield>which</structfield> argument
++ set to <constant>V4L2_SUBDEV_FORMAT_TRY</constant>, the
++ &VIDIOC-SUBDEV-G-FMT; and &VIDIOC-SUBDEV-S-FMT; ioctls operate on a set of
++ formats parameters that are not connected to the hardware configuration.
++ Modifying those 'try' formats leaves the device state untouched (this
++ applies to both the software state stored in the driver and the hardware
++ state stored in the device itself).</para>
++
++ <para>While not kept as part of the device state, try formats are stored
++ in the sub-device file handles. A &VIDIOC-SUBDEV-G-FMT; call will return
++ the last try format set <emphasis>on the same sub-device file
++ handle</emphasis>. Several applications querying the same sub-device at
++ the same time will thus not interact with each other.</para>
++
++ <para>To find out whether a particular format is supported by the device,
++ applications use the &VIDIOC-SUBDEV-S-FMT; ioctl. Drivers verify and, if
++ needed, change the requested <structfield>format</structfield> based on
++ device requirements and return the possibly modified value. Applications
++ can then choose to try a different format or accept the returned value and
++ continue.</para>
++
++ <para>Formats returned by the driver during a negotiation iteration are
++ guaranteed to be supported by the device. In particular, drivers guarantee
++ that a returned format will not be further changed if passed to an
++ &VIDIOC-SUBDEV-S-FMT; call as-is (as long as external parameters, such as
++ formats on other pads or links' configuration are not changed).</para>
++
++ <para>Drivers automatically propagate formats inside sub-devices. When a
++ try or active format is set on a pad, corresponding formats on other pads
++ of the same sub-device can be modified by the driver. Drivers are free to
++ modify formats as required by the device. However, they should comply with
++ the following rules when possible:
++ <itemizedlist>
++ <listitem>Formats should be propagated from sink pads to source pads.
++ Modifying a format on a source pad should not modify the format on any
++ sink pad.</listitem>
++ <listitem>Sub-devices that scale frames using variable scaling factors
++ should reset the scale factors to default values when sink pads formats
++ are modified. If the 1:1 scaling ratio is supported, this means that
++ source pads formats should be reset to the sink pads formats.</listitem>
++ </itemizedlist>
++ </para>
++
++ <para>Formats are not propagated across links, as that would involve
++ propagating them from one sub-device file handle to another. Applications
++ must then take care to configure both ends of every link explicitly with
++ compatible formats. Identical formats on the two ends of a link are
++ guaranteed to be compatible. Drivers are free to accept different formats
++ matching device requirements as being compatible.</para>
++
++ <para><xref linkend="sample-pipeline-config" xrefstyle="template:Table %n"/>
++ shows a sample configuration sequence for the pipeline described in
++ <xref linkend="pipeline-scaling" xrefstyle="template:Figure %n"/> (table
++ columns list entity names and pad numbers).</para>
++
++ <table pgwide="0" frame="none" id="sample-pipeline-config">
++ <title>Sample Pipeline Configuration</title>
++ <tgroup cols="3">
++ <colspec colname="what"/>
++ <colspec colname="sensor-0" />
++ <colspec colname="frontend-0" />
++ <colspec colname="frontend-1" />
++ <colspec colname="scaler-0" />
++ <colspec colname="scaler-1" />
++ <thead>
++ <row>
++ <entry></entry>
++ <entry>Sensor/0</entry>
++ <entry>Frontend/0</entry>
++ <entry>Frontend/1</entry>
++ <entry>Scaler/0</entry>
++ <entry>Scaler/1</entry>
++ </row>
++ </thead>
++ <tbody valign="top">
++ <row>
++ <entry>Initial state</entry>
++ <entry>2048x1536</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ </row>
++ <row>
++ <entry>Configure frontend input</entry>
++ <entry>2048x1536</entry>
++ <entry><emphasis>2048x1536</emphasis></entry>
++ <entry><emphasis>2046x1534</emphasis></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ </row>
++ <row>
++ <entry>Configure scaler input</entry>
++ <entry>2048x1536</entry>
++ <entry>2048x1536</entry>
++ <entry>2046x1534</entry>
++ <entry><emphasis>2046x1534</emphasis></entry>
++ <entry><emphasis>2046x1534</emphasis></entry>
++ </row>
++ <row>
++ <entry>Configure scaler output</entry>
++ <entry>2048x1536</entry>
++ <entry>2048x1536</entry>
++ <entry>2046x1534</entry>
++ <entry>2046x1534</entry>
++ <entry><emphasis>1280x960</emphasis></entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++
++ <para>
++ <orderedlist>
++ <listitem>Initial state. The sensor output is set to its native 3MP
++ resolution. Resolutions on the host frontend and scaler input and output
++ pads are undefined.</listitem>
++ <listitem>The application configures the frontend input pad resolution to
++ 2048x1536. The driver propagates the format to the frontend output pad.
++ Note that the propagated output format can be different, as in this case,
++ than the input format, as the hardware might need to crop pixels (for
++ instance when converting a Bayer filter pattern to RGB or YUV).</listitem>
++ <listitem>The application configures the scaler input pad resolution to
++ 2046x1534 to match the frontend output resolution. The driver propagates
++ the format to the scaler output pad.</listitem>
++ <listitem>The application configures the scaler output pad resolution to
++ 1280x960.</listitem>
++ </orderedlist>
++ </para>
++
++ <para>When satisfied with the try results, applications can set the active
++ formats by setting the <structfield>which</structfield> argument to
++ <constant>V4L2_SUBDEV_FORMAT_TRY</constant>. Active formats are changed
++ exactly as try formats by drivers. To avoid modifying the hardware state
++ during format negotiation, applications should negotiate try formats first
++ and then modify the active settings using the try formats returned during
++ the last negotiation iteration. This guarantees that the active format
++ will be applied as-is by the driver without being modified.
++ </para>
++ </section>
++
++ </section>
++
++ &sub-subdev-formats;
+diff --git a/Documentation/DocBook/v4l/subdev-formats.xml b/Documentation/DocBook/v4l/subdev-formats.xml
+new file mode 100644
+index 0000000..0cae572
+--- /dev/null
++++ b/Documentation/DocBook/v4l/subdev-formats.xml
+@@ -0,0 +1,2416 @@
++<section id="v4l2-mbus-format">
++ <title>Media Bus Formats</title>
++
++ <table pgwide="1" frame="none" id="v4l2-mbus-framefmt">
++ <title>struct <structname>v4l2_mbus_framefmt</structname></title>
++ <tgroup cols="3">
++ &cs-str;
++ <tbody valign="top">
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>width</structfield></entry>
++ <entry>Image width, in pixels.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>height</structfield></entry>
++ <entry>Image height, in pixels.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>code</structfield></entry>
++ <entry>Format code, from &v4l2-mbus-pixelcode;.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>field</structfield></entry>
++ <entry>Field order, from &v4l2-field;. See
++ <xref linkend="field-order" /> for details.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>colorspace</structfield></entry>
++ <entry>Image colorspace, from &v4l2-colorspace;. See
++ <xref linkend="colorspaces" /> for details.</entry>
++ </row>
++ <row>
++ <entry>__u32</entry>
++ <entry><structfield>reserved</structfield>[7]</entry>
++ <entry>Reserved for future extensions. Applications and drivers must
++ set the array to zero.</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++
++ <section id="v4l2-mbus-pixelcode">
++ <title>Media Bus Pixel Codes</title>
++
++ <para>The media bus pixel codes describe image formats as flowing over
++ physical busses (both between separate physical components and inside SoC
++ devices). This should not be confused with the V4L2 pixel formats that
++ describe, using four character codes, image formats as stored in memory.
++ </para>
++
++ <para>While there is a relationship between image formats on busses and
++ image formats in memory (a raw Bayer image won't be magically converted to
++ JPEG just by storing it to memory), there is no one-to-one correspondance
++ between them.</para>
++
++ <section>
++ <title>Packed RGB Formats</title>
++
++ <para>Those formats transfer pixel data as red, green and blue components.
++ The format code is made of the following information.
++ <itemizedlist>
++ <listitem>The red, green and blue components order code, as encoded in a
++ pixel sample. Possible values are RGB and BGR.</listitem>
++ <listitem>The number of bits per component, for each component. The values
++ can be different for all components. Common values are 555 and 565.
++ </listitem>
++ <listitem>The number of bus samples per pixel. Pixels that are wider than
++ the bus width must be transferred in multiple samples. Common values are
++ 1 and 2.</listitem>
++ <listitem>The bus width.</listitem>
++ <listitem>For formats where the total number of bits per pixel is smaller
++ than the number of bus samples per pixel times the bus width, a padding
++ value stating if the bytes are padded in their most high order bits
++ (PADHI) or low order bits (PADLO).</listitem>
++ <listitem>For formats where the number of bus samples per pixel is larger
++ than 1, an endianness value stating if the pixel is transferred MSB first
++ (BE) or LSB first (LE).</listitem>
++ </itemizedlist>
++ </para>
++
++ <para>For instance, a format where pixels are encoded as 5-bits red, 5-bits
++ green and 5-bit blue values padded on the high bit, transferred as 2 8-bit
++ samples per pixel with the most significant bits (padding, red and half of
++ the green value) transferred first will be named
++ <constant>V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE</constant>.
++ </para>
++
++ <para>The following tables list existing packet RGB formats.</para>
++
++ <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-rgb">
++ <title>RGB formats</title>
++ <tgroup cols="11">
++ <colspec colname="id" align="left" />
++ <colspec colname="code" align="center"/>
++ <colspec colname="bit" />
++ <colspec colnum="4" colname="b07" align="center" />
++ <colspec colnum="5" colname="b06" align="center" />
++ <colspec colnum="6" colname="b05" align="center" />
++ <colspec colnum="7" colname="b04" align="center" />
++ <colspec colnum="8" colname="b03" align="center" />
++ <colspec colnum="9" colname="b02" align="center" />
++ <colspec colnum="10" colname="b01" align="center" />
++ <colspec colnum="11" colname="b00" align="center" />
++ <spanspec namest="b07" nameend="b00" spanname="b0" />
++ <thead>
++ <row>
++ <entry>Identifier</entry>
++ <entry>Code</entry>
++ <entry></entry>
++ <entry spanname="b0">Data organization</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry>Bit</entry>
++ <entry>7</entry>
++ <entry>6</entry>
++ <entry>5</entry>
++ <entry>4</entry>
++ <entry>3</entry>
++ <entry>2</entry>
++ <entry>1</entry>
++ <entry>0</entry>
++ </row>
++ </thead>
++ <tbody valign="top">
++ <row id="V4L2-MBUS-FMT-RGB444-2X8-PADHI-BE">
++ <entry>V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE</entry>
++ <entry>0x1001</entry>
++ <entry></entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>r<subscript>3</subscript></entry>
++ <entry>r<subscript>2</subscript></entry>
++ <entry>r<subscript>1</subscript></entry>
++ <entry>r<subscript>0</subscript></entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>g<subscript>3</subscript></entry>
++ <entry>g<subscript>2</subscript></entry>
++ <entry>g<subscript>1</subscript></entry>
++ <entry>g<subscript>0</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-RGB444-2X8-PADHI-LE">
++ <entry>V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE</entry>
++ <entry>0x1002</entry>
++ <entry></entry>
++ <entry>g<subscript>3</subscript></entry>
++ <entry>g<subscript>2</subscript></entry>
++ <entry>g<subscript>1</subscript></entry>
++ <entry>g<subscript>0</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>r<subscript>3</subscript></entry>
++ <entry>r<subscript>2</subscript></entry>
++ <entry>r<subscript>1</subscript></entry>
++ <entry>r<subscript>0</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-RGB555-2X8-PADHI-BE">
++ <entry>V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE</entry>
++ <entry>0x1003</entry>
++ <entry></entry>
++ <entry>0</entry>
++ <entry>r<subscript>4</subscript></entry>
++ <entry>r<subscript>3</subscript></entry>
++ <entry>r<subscript>2</subscript></entry>
++ <entry>r<subscript>1</subscript></entry>
++ <entry>r<subscript>0</subscript></entry>
++ <entry>g<subscript>4</subscript></entry>
++ <entry>g<subscript>3</subscript></entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>g<subscript>2</subscript></entry>
++ <entry>g<subscript>1</subscript></entry>
++ <entry>g<subscript>0</subscript></entry>
++ <entry>b<subscript>4</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-RGB555-2X8-PADHI-LE">
++ <entry>V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE</entry>
++ <entry>0x1004</entry>
++ <entry></entry>
++ <entry>g<subscript>2</subscript></entry>
++ <entry>g<subscript>1</subscript></entry>
++ <entry>g<subscript>0</subscript></entry>
++ <entry>b<subscript>4</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>0</entry>
++ <entry>r<subscript>4</subscript></entry>
++ <entry>r<subscript>3</subscript></entry>
++ <entry>r<subscript>2</subscript></entry>
++ <entry>r<subscript>1</subscript></entry>
++ <entry>r<subscript>0</subscript></entry>
++ <entry>g<subscript>4</subscript></entry>
++ <entry>g<subscript>3</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-BGR565-2X8-BE">
++ <entry>V4L2_MBUS_FMT_BGR565_2X8_BE</entry>
++ <entry>0x1005</entry>
++ <entry></entry>
++ <entry>b<subscript>4</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ <entry>g<subscript>5</subscript></entry>
++ <entry>g<subscript>4</subscript></entry>
++ <entry>g<subscript>3</subscript></entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>g<subscript>2</subscript></entry>
++ <entry>g<subscript>1</subscript></entry>
++ <entry>g<subscript>0</subscript></entry>
++ <entry>r<subscript>4</subscript></entry>
++ <entry>r<subscript>3</subscript></entry>
++ <entry>r<subscript>2</subscript></entry>
++ <entry>r<subscript>1</subscript></entry>
++ <entry>r<subscript>0</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-BGR565-2X8-LE">
++ <entry>V4L2_MBUS_FMT_BGR565_2X8_LE</entry>
++ <entry>0x1006</entry>
++ <entry></entry>
++ <entry>g<subscript>2</subscript></entry>
++ <entry>g<subscript>1</subscript></entry>
++ <entry>g<subscript>0</subscript></entry>
++ <entry>r<subscript>4</subscript></entry>
++ <entry>r<subscript>3</subscript></entry>
++ <entry>r<subscript>2</subscript></entry>
++ <entry>r<subscript>1</subscript></entry>
++ <entry>r<subscript>0</subscript></entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>b<subscript>4</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ <entry>g<subscript>5</subscript></entry>
++ <entry>g<subscript>4</subscript></entry>
++ <entry>g<subscript>3</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-RGB565-2X8-BE">
++ <entry>V4L2_MBUS_FMT_RGB565_2X8_BE</entry>
++ <entry>0x1007</entry>
++ <entry></entry>
++ <entry>r<subscript>4</subscript></entry>
++ <entry>r<subscript>3</subscript></entry>
++ <entry>r<subscript>2</subscript></entry>
++ <entry>r<subscript>1</subscript></entry>
++ <entry>r<subscript>0</subscript></entry>
++ <entry>g<subscript>5</subscript></entry>
++ <entry>g<subscript>4</subscript></entry>
++ <entry>g<subscript>3</subscript></entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>g<subscript>2</subscript></entry>
++ <entry>g<subscript>1</subscript></entry>
++ <entry>g<subscript>0</subscript></entry>
++ <entry>b<subscript>4</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-RGB565-2X8-LE">
++ <entry>V4L2_MBUS_FMT_RGB565_2X8_LE</entry>
++ <entry>0x1008</entry>
++ <entry></entry>
++ <entry>g<subscript>2</subscript></entry>
++ <entry>g<subscript>1</subscript></entry>
++ <entry>g<subscript>0</subscript></entry>
++ <entry>b<subscript>4</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>r<subscript>4</subscript></entry>
++ <entry>r<subscript>3</subscript></entry>
++ <entry>r<subscript>2</subscript></entry>
++ <entry>r<subscript>1</subscript></entry>
++ <entry>r<subscript>0</subscript></entry>
++ <entry>g<subscript>5</subscript></entry>
++ <entry>g<subscript>4</subscript></entry>
++ <entry>g<subscript>3</subscript></entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ </section>
++
++ <section>
++ <title>Bayer Formats</title>
++
++ <para>Those formats transfer pixel data as red, green and blue components.
++ The format code is made of the following information.
++ <itemizedlist>
++ <listitem>The red, green and blue components order code, as encoded in a
++ pixel sample. The possible values are shown in <xref
++ linkend="bayer-patterns" />.</listitem>
++ <listitem>The number of bits per pixel component. All components are
++ transferred on the same number of bits. Common values are 8, 10 and 12.
++ </listitem>
++ <listitem>If the pixel components are DPCM-compressed, a mention of the
++ DPCM compression and the number of bits per compressed pixel component.
++ </listitem>
++ <listitem>The number of bus samples per pixel. Pixels that are wider than
++ the bus width must be transferred in multiple samples. Common values are
++ 1 and 2.</listitem>
++ <listitem>The bus width.</listitem>
++ <listitem>For formats where the total number of bits per pixel is smaller
++ than the number of bus samples per pixel times the bus width, a padding
++ value stating if the bytes are padded in their most high order bits
++ (PADHI) or low order bits (PADLO).</listitem>
++ <listitem>For formats where the number of bus samples per pixel is larger
++ than 1, an endianness value stating if the pixel is transferred MSB first
++ (BE) or LSB first (LE).</listitem>
++ </itemizedlist>
++ </para>
++
++ <para>For instance, a format with uncompressed 10-bit Bayer components
++ arranged in a red, green, green, blue pattern transferred as 2 8-bit
++ samples per pixel with the least significant bits transferred first will
++ be named <constant>V4L2_MBUS_FMT_SRGGB10_2X8_PADHI_LE</constant>.
++ </para>
++
++ <figure id="bayer-patterns">
++ <title>Bayer Patterns</title>
++ <mediaobject>
++ <imageobject>
++ <imagedata fileref="bayer.pdf" format="PS" />
++ </imageobject>
++ <imageobject>
++ <imagedata fileref="bayer.png" format="PNG" />
++ </imageobject>
++ <textobject>
++ <phrase>Bayer filter color patterns</phrase>
++ </textobject>
++ </mediaobject>
++ </figure>
++
++ <para>The following table lists existing packet Bayer formats. The data
++ organization is given as an example for the first pixel only.</para>
++
++ <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-bayer">
++ <title>Bayer Formats</title>
++ <tgroup cols="15">
++ <colspec colname="id" align="left" />
++ <colspec colname="code" align="center"/>
++ <colspec colname="bit" />
++ <colspec colnum="4" colname="b11" align="center" />
++ <colspec colnum="5" colname="b10" align="center" />
++ <colspec colnum="6" colname="b09" align="center" />
++ <colspec colnum="7" colname="b08" align="center" />
++ <colspec colnum="8" colname="b07" align="center" />
++ <colspec colnum="9" colname="b06" align="center" />
++ <colspec colnum="10" colname="b05" align="center" />
++ <colspec colnum="11" colname="b04" align="center" />
++ <colspec colnum="12" colname="b03" align="center" />
++ <colspec colnum="13" colname="b02" align="center" />
++ <colspec colnum="14" colname="b01" align="center" />
++ <colspec colnum="15" colname="b00" align="center" />
++ <spanspec namest="b11" nameend="b00" spanname="b0" />
++ <thead>
++ <row>
++ <entry>Identifier</entry>
++ <entry>Code</entry>
++ <entry></entry>
++ <entry spanname="b0">Data organization</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry>Bit</entry>
++ <entry>11</entry>
++ <entry>10</entry>
++ <entry>9</entry>
++ <entry>8</entry>
++ <entry>7</entry>
++ <entry>6</entry>
++ <entry>5</entry>
++ <entry>4</entry>
++ <entry>3</entry>
++ <entry>2</entry>
++ <entry>1</entry>
++ <entry>0</entry>
++ </row>
++ </thead>
++ <tbody valign="top">
++ <row id="V4L2-MBUS-FMT-SBGGR8-1X8">
++ <entry>V4L2_MBUS_FMT_SBGGR8_1X8</entry>
++ <entry>0x3001</entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>b<subscript>7</subscript></entry>
++ <entry>b<subscript>6</subscript></entry>
++ <entry>b<subscript>5</subscript></entry>
++ <entry>b<subscript>4</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-SGRBG8-1X8">
++ <entry>V4L2_MBUS_FMT_SGRBG8_1X8</entry>
++ <entry>0x3002</entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>g<subscript>7</subscript></entry>
++ <entry>g<subscript>6</subscript></entry>
++ <entry>g<subscript>5</subscript></entry>
++ <entry>g<subscript>4</subscript></entry>
++ <entry>g<subscript>3</subscript></entry>
++ <entry>g<subscript>2</subscript></entry>
++ <entry>g<subscript>1</subscript></entry>
++ <entry>g<subscript>0</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-SBGGR10-DPCM8-1X8">
++ <entry>V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8</entry>
++ <entry>0x300b</entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>b<subscript>7</subscript></entry>
++ <entry>b<subscript>6</subscript></entry>
++ <entry>b<subscript>5</subscript></entry>
++ <entry>b<subscript>4</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-SGBRG10-DPCM8-1X8">
++ <entry>V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8</entry>
++ <entry>0x300c</entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>g<subscript>7</subscript></entry>
++ <entry>g<subscript>6</subscript></entry>
++ <entry>g<subscript>5</subscript></entry>
++ <entry>g<subscript>4</subscript></entry>
++ <entry>g<subscript>3</subscript></entry>
++ <entry>g<subscript>2</subscript></entry>
++ <entry>g<subscript>1</subscript></entry>
++ <entry>g<subscript>0</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-SGRBG10-DPCM8-1X8">
++ <entry>V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8</entry>
++ <entry>0x3009</entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>g<subscript>7</subscript></entry>
++ <entry>g<subscript>6</subscript></entry>
++ <entry>g<subscript>5</subscript></entry>
++ <entry>g<subscript>4</subscript></entry>
++ <entry>g<subscript>3</subscript></entry>
++ <entry>g<subscript>2</subscript></entry>
++ <entry>g<subscript>1</subscript></entry>
++ <entry>g<subscript>0</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-SRGGB10-DPCM8-1X8">
++ <entry>V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8</entry>
++ <entry>0x300d</entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>r<subscript>7</subscript></entry>
++ <entry>r<subscript>6</subscript></entry>
++ <entry>r<subscript>5</subscript></entry>
++ <entry>r<subscript>4</subscript></entry>
++ <entry>r<subscript>3</subscript></entry>
++ <entry>r<subscript>2</subscript></entry>
++ <entry>r<subscript>1</subscript></entry>
++ <entry>r<subscript>0</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-SBGGR10-2X8-PADHI-BE">
++ <entry>V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE</entry>
++ <entry>0x3003</entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>b<subscript>9</subscript></entry>
++ <entry>b<subscript>8</subscript></entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>b<subscript>7</subscript></entry>
++ <entry>b<subscript>6</subscript></entry>
++ <entry>b<subscript>5</subscript></entry>
++ <entry>b<subscript>4</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-SBGGR10-2X8-PADHI-LE">
++ <entry>V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE</entry>
++ <entry>0x3004</entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>b<subscript>7</subscript></entry>
++ <entry>b<subscript>6</subscript></entry>
++ <entry>b<subscript>5</subscript></entry>
++ <entry>b<subscript>4</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>b<subscript>9</subscript></entry>
++ <entry>b<subscript>8</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-SBGGR10-2X8-PADLO-BE">
++ <entry>V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE</entry>
++ <entry>0x3005</entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>b<subscript>9</subscript></entry>
++ <entry>b<subscript>8</subscript></entry>
++ <entry>b<subscript>7</subscript></entry>
++ <entry>b<subscript>6</subscript></entry>
++ <entry>b<subscript>5</subscript></entry>
++ <entry>b<subscript>4</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-SBGGR10-2X8-PADLO-LE">
++ <entry>V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE</entry>
++ <entry>0x3006</entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>b<subscript>1</subscript></entry>
++ <entry>b<subscript>0</subscript></entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ <entry>0</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry></entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>b<subscript>9</subscript></entry>
++ <entry>b<subscript>8</subscript></entry>
++ <entry>b<subscript>7</subscript></entry>
++ <entry>b<subscript>6</subscript></entry>
++ <entry>b<subscript>5</subscript></entry>
++ <entry>b<subscript>4</subscript></entry>
++ <entry>b<subscript>3</subscript></entry>
++ <entry>b<subscript>2</subscript></entry>
++ </row>
++ <row id="V4L2-MBUS-FMT-SBGGR10-1X10">
++ <entry>V4L2_MBUS_FMT_SBGGR10_1X10</entry>
++ <entry>0x3007</entry>
++ <entry></entry>
++ <entry>-</entry>
++ <entry>-</entry>
++ <entry>b<subscript>9</subscript></entry>
++ <entry>b<subscript>8</subscript></entry>
++ <entry>b<subscript>7</subscript></entry>
++ <entry>b<subscript>6</subscript></entry>
++ &