mirror of
https://git.yoctoproject.org/meta-ti
synced 2026-06-05 10:21:52 +00:00
linux-omap 2.6.37: sync with OE .dev
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# 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
|
||||
@@ -286,6 +286,8 @@ CONFIG_OMAP_RESET_CLOCKS=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
|
||||
@@ -1846,10 +1848,12 @@ CONFIG_MEDIA_SUPPORT=y
|
||||
#
|
||||
# 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
|
||||
|
||||
@@ -1991,6 +1995,8 @@ CONFIG_VIDEO_OMAP2_VOUT=y
|
||||
# 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
|
||||
|
||||
+297
@@ -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
|
||||
|
||||
+31
@@ -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
|
||||
|
||||
+132
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+103
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+889
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+115
@@ -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
|
||||
|
||||
+234
@@ -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
|
||||
|
||||
+265
@@ -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
|
||||
|
||||
+205
@@ -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
|
||||
|
||||
+50
@@ -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
|
||||
|
||||
+154
@@ -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
|
||||
|
||||
+112
@@ -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
|
||||
|
||||
+243
@@ -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
|
||||
|
||||
+93
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+479
@@ -0,0 +1,479 @@
|
||||
From b137f96a198afb39c8457e2c5d28c1c4bca129a3 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Date: Wed, 5 May 2010 16:38:35 +0200
|
||||
Subject: [PATCH 29/43] v4l: v4l2_subdev userspace frame interval API
|
||||
|
||||
The three new ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL,
|
||||
VIDIOC_SUBDEV_G_FRAME_INTERVAL and VIDIOC_SUBDEV_S_FRAME_INTERVAL can be
|
||||
used to enumerate and configure a subdev's frame rate from userspace.
|
||||
|
||||
Two new video::g/s_frame_interval subdev operations are introduced to
|
||||
support those ioctls. The existing video::g/s_parm operations are
|
||||
deprecated and shouldn't be used anymore.
|
||||
|
||||
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 | 6 +
|
||||
Documentation/DocBook/v4l/v4l2.xml | 2 +
|
||||
.../v4l/vidioc-subdev-enum-frame-interval.xml | 146 ++++++++++++++++++++
|
||||
.../DocBook/v4l/vidioc-subdev-g-frame-interval.xml | 135 ++++++++++++++++++
|
||||
drivers/media/video/v4l2-subdev.c | 16 ++
|
||||
include/linux/v4l2-subdev.h | 36 +++++
|
||||
include/media/v4l2-subdev.h | 7 +
|
||||
7 files changed, 348 insertions(+), 0 deletions(-)
|
||||
create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml
|
||||
create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml
|
||||
|
||||
diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
|
||||
index 538f8fe..4af3c2e 100644
|
||||
--- a/Documentation/DocBook/media-entities.tmpl
|
||||
+++ b/Documentation/DocBook/media-entities.tmpl
|
||||
@@ -89,7 +89,9 @@
|
||||
<!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-G-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-S-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_S_FMT</constant></link>">
|
||||
+<!ENTITY VIDIOC-SUBDEV-S-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</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>">
|
||||
@@ -190,6 +192,8 @@
|
||||
<!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-interval "struct <link linkend='v4l2-subdev-frame-interval'>v4l2_subdev_frame_interval</link>">
|
||||
+<!ENTITY v4l2-subdev-frame-interval-enum "struct <link linkend='v4l2-subdev-frame-interval-enum'>v4l2_subdev_frame_interval_enum</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>">
|
||||
@@ -325,10 +329,12 @@
|
||||
<!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-interval SYSTEM "v4l/vidioc-subdev-enum-frame-interval.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-subdev-g-frame-interval SYSTEM "v4l/vidioc-subdev-g-frame-interval.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/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml
|
||||
index 695e3bf..e6225e0 100644
|
||||
--- a/Documentation/DocBook/v4l/v4l2.xml
|
||||
+++ b/Documentation/DocBook/v4l/v4l2.xml
|
||||
@@ -478,9 +478,11 @@ and discussions on the V4L mailing list.</revremark>
|
||||
&sub-reqbufs;
|
||||
&sub-s-hw-freq-seek;
|
||||
&sub-streamon;
|
||||
+ &sub-subdev-enum-frame-interval;
|
||||
&sub-subdev-enum-frame-size;
|
||||
&sub-subdev-enum-mbus-code;
|
||||
&sub-subdev-g-fmt;
|
||||
+ &sub-subdev-g-frame-interval;
|
||||
&sub-subscribe-event;
|
||||
<!-- End of ioctls. -->
|
||||
&sub-mmap;
|
||||
diff --git a/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml
|
||||
new file mode 100644
|
||||
index 0000000..bcea9d4
|
||||
--- /dev/null
|
||||
+++ b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml
|
||||
@@ -0,0 +1,146 @@
|
||||
+<refentry id="vidioc-subdev-enum-frame-interval">
|
||||
+ <refmeta>
|
||||
+ <refentrytitle>ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</refentrytitle>
|
||||
+ &manvol;
|
||||
+ </refmeta>
|
||||
+
|
||||
+ <refnamediv>
|
||||
+ <refname>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</refname>
|
||||
+ <refpurpose>Enumerate frame intervals</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 v4l2_subdev_frame_interval_enum *
|
||||
+ <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>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><parameter>argp</parameter></term>
|
||||
+ <listitem>
|
||||
+ <para></para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>Description</title>
|
||||
+
|
||||
+ <para>This ioctl lets applications enumerate available frame intervals on a
|
||||
+ given sub-device pad. Frame intervals only makes sense for sub-devices that
|
||||
+ can control the frame period on their own. This includes, for instance,
|
||||
+ image sensors and TV tuners.</para>
|
||||
+
|
||||
+ <para>For the common use case of image sensors, the frame intervals
|
||||
+ available on the sub-device output pad depend on the frame format and size
|
||||
+ on the same pad. Applications must thus specify the desired format and size
|
||||
+ when enumerating frame intervals.</para>
|
||||
+
|
||||
+ <para>To enumerate frame intervals applications initialize the
|
||||
+ <structfield>index</structfield>, <structfield>pad</structfield>,
|
||||
+ <structfield>code</structfield>, <structfield>width</structfield> and
|
||||
+ <structfield>height</structfield> fields of
|
||||
+ &v4l2-subdev-frame-interval-enum; and call the
|
||||
+ <constant>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</constant> ioctl with a pointer
|
||||
+ to this structure. Drivers fill the rest of the structure or return
|
||||
+ an &EINVAL; if one of the input fields is invalid. All frame intervals are
|
||||
+ enumerable by beginning at index zero and incrementing by one until
|
||||
+ <errorcode>EINVAL</errorcode> is returned.</para>
|
||||
+
|
||||
+ <para>Available frame intervals may depend on the current 'try' formats
|
||||
+ at other pads of the sub-device, as well as on the current active links. See
|
||||
+ &VIDIOC-SUBDEV-G-FMT; for more information about the try formats.</para>
|
||||
+
|
||||
+ <para>Sub-devices that support the frame interval enumeration ioctl should
|
||||
+ implemented it on a single pad only. Its behaviour when supported on
|
||||
+ multiple pads of the same sub-device is not defined.</para>
|
||||
+
|
||||
+ <table pgwide="1" frame="none" id="v4l2-subdev-frame-interval-enum">
|
||||
+ <title>struct <structname>v4l2_subdev_frame_interval_enum</structname></title>
|
||||
+ <tgroup cols="3">
|
||||
+ &cs-str;
|
||||
+ <tbody valign="top">
|
||||
+ <row>
|
||||
+ <entry>__u32</entry>
|
||||
+ <entry><structfield>index</structfield></entry>
|
||||
+ <entry>Number of the format in the enumeration, set by the
|
||||
+ application.</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry>__u32</entry>
|
||||
+ <entry><structfield>pad</structfield></entry>
|
||||
+ <entry>Pad number as reported by the media controller API.</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry>__u32</entry>
|
||||
+ <entry><structfield>code</structfield></entry>
|
||||
+ <entry>The media bus format code, as defined in
|
||||
+ <xref linkend="v4l2-mbus-format" />.</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry>__u32</entry>
|
||||
+ <entry><structfield>width</structfield></entry>
|
||||
+ <entry>Frame width, in pixels.</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry>__u32</entry>
|
||||
+ <entry><structfield>height</structfield></entry>
|
||||
+ <entry>Frame height, in pixels.</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry>&v4l2-fract;</entry>
|
||||
+ <entry><structfield>interval</structfield></entry>
|
||||
+ <entry>Period, in seconds, between consecutive video frames.</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry>__u32</entry>
|
||||
+ <entry><structfield>reserved</structfield>[9]</entry>
|
||||
+ <entry>Reserved for future extensions. Applications and drivers must
|
||||
+ set the array to zero.</entry>
|
||||
+ </row>
|
||||
+ </tbody>
|
||||
+ </tgroup>
|
||||
+ </table>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ &return-value;
|
||||
+
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><errorcode>EINVAL</errorcode></term>
|
||||
+ <listitem>
|
||||
+ <para>The &v4l2-subdev-frame-interval-enum;
|
||||
+ <structfield>pad</structfield> references a non-existing pad, one of
|
||||
+ the <structfield>code</structfield>, <structfield>width</structfield>
|
||||
+ or <structfield>height</structfield> fields are invalid for the given
|
||||
+ pad or the <structfield>index</structfield> field is out of bounds.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+</refentry>
|
||||
diff --git a/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml b/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml
|
||||
new file mode 100644
|
||||
index 0000000..848ec78
|
||||
--- /dev/null
|
||||
+++ b/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml
|
||||
@@ -0,0 +1,135 @@
|
||||
+<refentry id="vidioc-subdev-g-frame-interval">
|
||||
+ <refmeta>
|
||||
+ <refentrytitle>ioctl VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL</refentrytitle>
|
||||
+ &manvol;
|
||||
+ </refmeta>
|
||||
+
|
||||
+ <refnamediv>
|
||||
+ <refname>VIDIOC_SUBDEV_G_FRAME_INTERVAL</refname>
|
||||
+ <refname>VIDIOC_SUBDEV_S_FRAME_INTERVAL</refname>
|
||||
+ <refpurpose>Get or set the frame interval on a subdev pad</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 v4l2_subdev_frame_interval *<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>VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><parameter>argp</parameter></term>
|
||||
+ <listitem>
|
||||
+ <para></para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>Description</title>
|
||||
+
|
||||
+ <para>These ioctls are used to get and set the frame interval at specific
|
||||
+ subdev pads in the image pipeline. The frame interval only makes sense for
|
||||
+ sub-devices that can control the frame period on their own. This includes,
|
||||
+ for instance, image sensors and TV tuners. Sub-devices that don't support
|
||||
+ frame intervals must not implement these ioctls.</para>
|
||||
+
|
||||
+ <para>To retrieve the current frame interval applications set the
|
||||
+ <structfield>pad</structfield> field of a &v4l2-subdev-frame-interval; to
|
||||
+ the desired pad number as reported by the media controller API. When they
|
||||
+ call the <constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant> ioctl with a
|
||||
+ pointer to this structure the driver fills the members of the
|
||||
+ <structfield>interval</structfield> field.</para>
|
||||
+
|
||||
+ <para>To change the current frame interval applications set both the
|
||||
+ <structfield>pad</structfield> field and all members of the
|
||||
+ <structfield>interval</structfield> field. When they call the
|
||||
+ <constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant> ioctl with a pointer to
|
||||
+ this structure the driver verifies the requested interval, adjusts it based
|
||||
+ on the hardware capabilities and configures the device. Upon return the
|
||||
+ &v4l2-subdev-frame-interval; contains the current frame interval as would be
|
||||
+ returned by a <constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant> call.
|
||||
+ </para>
|
||||
+
|
||||
+ <para>Drivers must not return an error solely because the requested interval
|
||||
+ doesn't match the device capabilities. They must instead modify the interval
|
||||
+ to match what the hardware can provide. The modified interval should be as
|
||||
+ close as possible to the original request.</para>
|
||||
+
|
||||
+ <para>Sub-devices that support the frame interval ioctls should implement
|
||||
+ them on a single pad only. Their behaviour when supported on multiple pads
|
||||
+ of the same sub-device is not defined.</para>
|
||||
+
|
||||
+ <table pgwide="1" frame="none" id="v4l2-subdev-frame-interval">
|
||||
+ <title>struct <structname>v4l2_subdev_frame_interval</structname></title>
|
||||
+ <tgroup cols="3">
|
||||
+ &cs-str;
|
||||
+ <tbody valign="top">
|
||||
+ <row>
|
||||
+ <entry>__u32</entry>
|
||||
+ <entry><structfield>pad</structfield></entry>
|
||||
+ <entry>Pad number as reported by the media controller API.</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry>&v4l2-fract;</entry>
|
||||
+ <entry><structfield>interval</structfield></entry>
|
||||
+ <entry>Period, in seconds, between consecutive video frames.</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry>__u32</entry>
|
||||
+ <entry><structfield>reserved</structfield>[9]</entry>
|
||||
+ <entry>Reserved for future extensions. Applications and drivers must
|
||||
+ set the array to zero.</entry>
|
||||
+ </row>
|
||||
+ </tbody>
|
||||
+ </tgroup>
|
||||
+ </table>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ &return-value;
|
||||
+
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><errorcode>EBUSY</errorcode></term>
|
||||
+ <listitem>
|
||||
+ <para>The frame interval can't be changed because the pad is currently
|
||||
+ busy. This can be caused, for instance, by an active video stream on
|
||||
+ the pad. The ioctl must not be retried without performing another
|
||||
+ action to fix the problem first. Only returned by
|
||||
+ <constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant></para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><errorcode>EINVAL</errorcode></term>
|
||||
+ <listitem>
|
||||
+ <para>The &v4l2-subdev-frame-interval; <structfield>pad</structfield>
|
||||
+ references a non-existing pad, or the pad doesn't support frame
|
||||
+ intervals.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+</refentry>
|
||||
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
|
||||
index 73aae00..316a08a 100644
|
||||
--- a/drivers/media/video/v4l2-subdev.c
|
||||
+++ b/drivers/media/video/v4l2-subdev.c
|
||||
@@ -232,6 +232,22 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
||||
return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh,
|
||||
fse);
|
||||
}
|
||||
+
|
||||
+ case VIDIOC_SUBDEV_G_FRAME_INTERVAL:
|
||||
+ return v4l2_subdev_call(sd, video, g_frame_interval, arg);
|
||||
+
|
||||
+ case VIDIOC_SUBDEV_S_FRAME_INTERVAL:
|
||||
+ return v4l2_subdev_call(sd, video, s_frame_interval, arg);
|
||||
+
|
||||
+ case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: {
|
||||
+ struct v4l2_subdev_frame_interval_enum *fie = arg;
|
||||
+
|
||||
+ if (fie->pad >= sd->entity.num_pads)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh,
|
||||
+ fie);
|
||||
+ }
|
||||
#endif
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h
|
||||
index 38d0eda..bf9f3e9 100644
|
||||
--- a/include/linux/v4l2-subdev.h
|
||||
+++ b/include/linux/v4l2-subdev.h
|
||||
@@ -80,11 +80,47 @@ struct v4l2_subdev_frame_size_enum {
|
||||
__u32 reserved[9];
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * struct v4l2_subdev_frame_interval - Pad-level frame rate
|
||||
+ * @pad: pad number, as reported by the media API
|
||||
+ * @interval: frame interval in seconds
|
||||
+ */
|
||||
+struct v4l2_subdev_frame_interval {
|
||||
+ __u32 pad;
|
||||
+ struct v4l2_fract interval;
|
||||
+ __u32 reserved[9];
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct v4l2_subdev_frame_interval_enum - Frame interval enumeration
|
||||
+ * @pad: pad number, as reported by the media API
|
||||
+ * @index: frame interval index during enumeration
|
||||
+ * @code: format code (from enum v4l2_mbus_pixelcode)
|
||||
+ * @width: frame width in pixels
|
||||
+ * @height: frame height in pixels
|
||||
+ * @interval: frame interval in seconds
|
||||
+ */
|
||||
+struct v4l2_subdev_frame_interval_enum {
|
||||
+ __u32 index;
|
||||
+ __u32 pad;
|
||||
+ __u32 code;
|
||||
+ __u32 width;
|
||||
+ __u32 height;
|
||||
+ struct v4l2_fract interval;
|
||||
+ __u32 reserved[9];
|
||||
+};
|
||||
+
|
||||
#define VIDIOC_SUBDEV_G_FMT _IOWR('V', 4, struct v4l2_subdev_format)
|
||||
#define VIDIOC_SUBDEV_S_FMT _IOWR('V', 5, struct v4l2_subdev_format)
|
||||
+#define VIDIOC_SUBDEV_G_FRAME_INTERVAL \
|
||||
+ _IOWR('V', 21, struct v4l2_subdev_frame_interval)
|
||||
+#define VIDIOC_SUBDEV_S_FRAME_INTERVAL \
|
||||
+ _IOWR('V', 22, struct v4l2_subdev_frame_interval)
|
||||
#define VIDIOC_SUBDEV_ENUM_MBUS_CODE \
|
||||
_IOWR('V', 2, struct v4l2_subdev_mbus_code_enum)
|
||||
#define VIDIOC_SUBDEV_ENUM_FRAME_SIZE \
|
||||
_IOWR('V', 74, struct v4l2_subdev_frame_size_enum)
|
||||
+#define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \
|
||||
+ _IOWR('V', 75, struct v4l2_subdev_frame_interval_enum)
|
||||
|
||||
#endif
|
||||
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
|
||||
index f5611c2..9c8bcd3 100644
|
||||
--- a/include/media/v4l2-subdev.h
|
||||
+++ b/include/media/v4l2-subdev.h
|
||||
@@ -281,6 +281,10 @@ struct v4l2_subdev_video_ops {
|
||||
int (*s_crop)(struct v4l2_subdev *sd, struct v4l2_crop *crop);
|
||||
int (*g_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
|
||||
int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
|
||||
+ int (*g_frame_interval)(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_frame_interval *interval);
|
||||
+ int (*s_frame_interval)(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_frame_interval *interval);
|
||||
int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize);
|
||||
int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival);
|
||||
int (*enum_dv_presets) (struct v4l2_subdev *sd,
|
||||
@@ -431,6 +435,9 @@ struct v4l2_subdev_pad_ops {
|
||||
int (*enum_frame_size)(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_frame_size_enum *fse);
|
||||
+ int (*enum_frame_interval)(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_frame_interval_enum *fie);
|
||||
int (*get_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_format *format);
|
||||
int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
From 9e87e6d59dc364ec78717fb91cbe9bad7df14223 Mon Sep 17 00:00:00 2001
|
||||
From: Antti Koskipaa <antti.koskipaa@nokia.com>
|
||||
Date: Wed, 23 Jun 2010 11:03:42 +0300
|
||||
Subject: [PATCH 30/43] v4l: v4l2_subdev userspace crop API
|
||||
|
||||
This patch adds the VIDIOC_SUBDEV_S_CROP and G_CROP ioctls to the
|
||||
userland API. CROPCAP is not implemented because it's redundant.
|
||||
|
||||
Signed-off-by: Antti Koskipaa <antti.koskipaa@nokia.com>
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
---
|
||||
Documentation/DocBook/media-entities.tmpl | 4 +
|
||||
Documentation/DocBook/v4l/dev-subdev.xml | 33 +++++
|
||||
Documentation/DocBook/v4l/v4l2.xml | 1 +
|
||||
Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml | 149 ++++++++++++++++++++
|
||||
drivers/media/video/v4l2-subdev.c | 26 ++++
|
||||
include/linux/v4l2-subdev.h | 15 ++
|
||||
include/media/v4l2-subdev.h | 4 +
|
||||
7 files changed, 232 insertions(+), 0 deletions(-)
|
||||
create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml
|
||||
|
||||
diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
|
||||
index 4af3c2e..157d147 100644
|
||||
--- a/Documentation/DocBook/media-entities.tmpl
|
||||
+++ b/Documentation/DocBook/media-entities.tmpl
|
||||
@@ -88,8 +88,10 @@
|
||||
<!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-CROP "<link linkend='vidioc-subdev-g-crop'><constant>VIDIOC_SUBDEV_G_CROP</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-G-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_G_FMT</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-G-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant></link>">
|
||||
+<!ENTITY VIDIOC-SUBDEV-S-CROP "<link linkend='vidioc-subdev-g-crop'><constant>VIDIOC_SUBDEV_S_CROP</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-S-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_S_FMT</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-S-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant></link>">
|
||||
<!ENTITY VIDIOC-TRY-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_TRY_ENCODER_CMD</constant></link>">
|
||||
@@ -195,6 +197,7 @@
|
||||
<!ENTITY v4l2-subdev-frame-interval "struct <link linkend='v4l2-subdev-frame-interval'>v4l2_subdev_frame_interval</link>">
|
||||
<!ENTITY v4l2-subdev-frame-interval-enum "struct <link linkend='v4l2-subdev-frame-interval-enum'>v4l2_subdev_frame_interval_enum</link>">
|
||||
<!ENTITY v4l2-subdev-frame-size-enum "struct <link linkend='v4l2-subdev-frame-size-enum'>v4l2_subdev_frame_size_enum</link>">
|
||||
+<!ENTITY v4l2-subdev-crop "struct <link linkend='v4l2-subdev-crop'>v4l2_subdev_crop</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>">
|
||||
@@ -333,6 +336,7 @@
|
||||
<!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-crop SYSTEM "v4l/vidioc-subdev-g-crop.xml">
|
||||
<!ENTITY sub-subdev-g-fmt SYSTEM "v4l/vidioc-subdev-g-fmt.xml">
|
||||
<!ENTITY sub-subdev-g-frame-interval SYSTEM "v4l/vidioc-subdev-g-frame-interval.xml">
|
||||
<!ENTITY sub-capture-c SYSTEM "v4l/capture.c.xml">
|
||||
diff --git a/Documentation/DocBook/v4l/dev-subdev.xml b/Documentation/DocBook/v4l/dev-subdev.xml
|
||||
index 12fdca4..a8da916 100644
|
||||
--- a/Documentation/DocBook/v4l/dev-subdev.xml
|
||||
+++ b/Documentation/DocBook/v4l/dev-subdev.xml
|
||||
@@ -269,6 +269,39 @@
|
||||
</para>
|
||||
</section>
|
||||
|
||||
+ <section>
|
||||
+ <title>Cropping and scaling</title>
|
||||
+
|
||||
+ <para>Many sub-devices support cropping frames on their input or output
|
||||
+ pads (or possible even on both). Cropping is used to select the area of
|
||||
+ interest in an image, typically on a video sensor or video decoder. It can
|
||||
+ also be used as part of digital zoom implementations to select the area of
|
||||
+ the image that will be scaled up.</para>
|
||||
+
|
||||
+ <para>Crop settings are defined by a crop rectangle and represented in a
|
||||
+ &v4l2-rect; by the coordinates of the top left corner and the rectangle
|
||||
+ size. Both the coordinates and sizes are expressed in pixels.</para>
|
||||
+
|
||||
+ <para>The crop rectangle is retrieved and set using the
|
||||
+ &VIDIOC-SUBDEV-G-CROP; and &VIDIOC-SUBDEV-S-CROP; ioctls. Like for pad
|
||||
+ formats, drivers store try and active crop rectangles. The format
|
||||
+ negotiation mechanism applies to crop settings as well.</para>
|
||||
+
|
||||
+ <para>On input pads, cropping is applied relatively to the current pad
|
||||
+ format. The pad format represents the image size as received by the
|
||||
+ sub-device from the previous block in the pipeline, and the crop rectangle
|
||||
+ represents the sub-image that will be transmitted further inside the
|
||||
+ sub-device for processing. The crop rectangle be entirely containted
|
||||
+ inside the input image size.</para>
|
||||
+
|
||||
+ <para>Input crop rectangle are reset to their default value when the input
|
||||
+ image format is modified. Drivers should use the input image size as the
|
||||
+ crop rectangle default value, but hardware requirements may prevent this.
|
||||
+ </para>
|
||||
+
|
||||
+ <para>Cropping behaviour on output pads is not defined.</para>
|
||||
+
|
||||
+ </section>
|
||||
</section>
|
||||
|
||||
&sub-subdev-formats;
|
||||
diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml
|
||||
index e6225e0..5e640ca 100644
|
||||
--- a/Documentation/DocBook/v4l/v4l2.xml
|
||||
+++ b/Documentation/DocBook/v4l/v4l2.xml
|
||||
@@ -481,6 +481,7 @@ and discussions on the V4L mailing list.</revremark>
|
||||
&sub-subdev-enum-frame-interval;
|
||||
&sub-subdev-enum-frame-size;
|
||||
&sub-subdev-enum-mbus-code;
|
||||
+ &sub-subdev-g-crop;
|
||||
&sub-subdev-g-fmt;
|
||||
&sub-subdev-g-frame-interval;
|
||||
&sub-subscribe-event;
|
||||
diff --git a/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml b/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml
|
||||
new file mode 100644
|
||||
index 0000000..cef127f
|
||||
--- /dev/null
|
||||
+++ b/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml
|
||||
@@ -0,0 +1,149 @@
|
||||
+<refentry id="vidioc-subdev-g-crop">
|
||||
+ <refmeta>
|
||||
+ <refentrytitle>ioctl VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP</refentrytitle>
|
||||
+ &manvol;
|
||||
+ </refmeta>
|
||||
+
|
||||
+ <refnamediv>
|
||||
+ <refname>VIDIOC_SUBDEV_G_CROP</refname>
|
||||
+ <refname>VIDIOC_SUBDEV_S_CROP</refname>
|
||||
+ <refpurpose>Get or set the crop rectangle on a subdev pad</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 v4l2_subdev_crop *<parameter>argp</parameter></paramdef>
|
||||
+ </funcprototype>
|
||||
+ </funcsynopsis>
|
||||
+ <funcsynopsis>
|
||||
+ <funcprototype>
|
||||
+ <funcdef>int <function>ioctl</function></funcdef>
|
||||
+ <paramdef>int <parameter>fd</parameter></paramdef>
|
||||
+ <paramdef>int <parameter>request</parameter></paramdef>
|
||||
+ <paramdef>const struct v4l2_subdev_crop *<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>VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><parameter>argp</parameter></term>
|
||||
+ <listitem>
|
||||
+ <para></para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>Description</title>
|
||||
+
|
||||
+ <para>To retrieve the current crop rectangle applications set the
|
||||
+ <structfield>pad</structfield> field of a &v4l2-subdev-crop; to the
|
||||
+ desired pad number as reported by the media API and the
|
||||
+ <structfield>which</structfield> field to
|
||||
+ <constant>V4L2_SUBDEV_FORMAT_ACTIVE</constant>. They then call the
|
||||
+ <constant>VIDIOC_SUBDEV_G_CROP</constant> ioctl with a pointer to this
|
||||
+ structure. The driver fills the members of the <structfield>rect</structfield>
|
||||
+ field or returns &EINVAL; if the input arguments are invalid, or if cropping
|
||||
+ is not supported on the given pad.</para>
|
||||
+
|
||||
+ <para>To change the current crop rectangle applications set both the
|
||||
+ <structfield>pad</structfield> and <structfield>which</structfield> fields
|
||||
+ and all members of the <structfield>rect</structfield> field. They then call
|
||||
+ the <constant>VIDIOC_SUBDEV_S_CROP</constant> ioctl with a pointer to this
|
||||
+ structure. The driver verifies the requested crop rectangle, adjusts it
|
||||
+ based on the hardware capabilities and configures the device. Upon return
|
||||
+ the &v4l2-subdev-crop; contains the current format as would be returned
|
||||
+ by a <constant>VIDIOC_SUBDEV_G_CROP</constant> call.</para>
|
||||
+
|
||||
+ <para>Applications can query the device capabilities by setting the
|
||||
+ <structfield>which</structfield> to
|
||||
+ <constant>V4L2_SUBDEV_FORMAT_TRY</constant>. When set, 'try' crop
|
||||
+ rectangles are not applied to the device by the driver, but are mangled
|
||||
+ exactly as active crop rectangles and stored in the sub-device file handle.
|
||||
+ Two applications querying the same sub-device would thus not interact with
|
||||
+ each other.</para>
|
||||
+
|
||||
+ <para>Drivers must not return an error solely because the requested crop
|
||||
+ rectangle doesn't match the device capabilities. They must instead modify
|
||||
+ the rectangle to match what the hardware can provide. The modified format
|
||||
+ should be as close as possible to the original request.</para>
|
||||
+
|
||||
+ <table pgwide="1" frame="none" id="v4l2-subdev-crop">
|
||||
+ <title>struct <structname>v4l2_subdev_crop</structname></title>
|
||||
+ <tgroup cols="3">
|
||||
+ &cs-str;
|
||||
+ <tbody valign="top">
|
||||
+ <row>
|
||||
+ <entry>__u32</entry>
|
||||
+ <entry><structfield>pad</structfield></entry>
|
||||
+ <entry>Pad number as reported by the media framework.</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry>__u32</entry>
|
||||
+ <entry><structfield>which</structfield></entry>
|
||||
+ <entry>Crop rectangle to get or set, from
|
||||
+ &v4l2-subdev-format-whence;.</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry>&v4l2-rect;</entry>
|
||||
+ <entry><structfield>rect</structfield></entry>
|
||||
+ <entry>Crop rectangle boundaries, in pixels.</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry>__u32</entry>
|
||||
+ <entry><structfield>reserved</structfield>[8]</entry>
|
||||
+ <entry>Reserved for future extensions. Applications and drivers must
|
||||
+ set the array to zero.</entry>
|
||||
+ </row>
|
||||
+ </tbody>
|
||||
+ </tgroup>
|
||||
+ </table>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ &return-value;
|
||||
+
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><errorcode>EBUSY</errorcode></term>
|
||||
+ <listitem>
|
||||
+ <para>The crop rectangle can't be changed because the pad is currently
|
||||
+ busy. This can be caused, for instance, by an active video stream on
|
||||
+ the pad. The ioctl must not be retried without performing another
|
||||
+ action to fix the problem first. Only returned by
|
||||
+ <constant>VIDIOC_SUBDEV_S_CROP</constant></para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><errorcode>EINVAL</errorcode></term>
|
||||
+ <listitem>
|
||||
+ <para>The &v4l2-subdev-crop; <structfield>pad</structfield>
|
||||
+ references a non-existing pad, the <structfield>which</structfield>
|
||||
+ field references a non-existing format, or cropping is not supported
|
||||
+ on the given subdev pad.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+</refentry>
|
||||
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
|
||||
index 316a08a..e706c4c 100644
|
||||
--- a/drivers/media/video/v4l2-subdev.c
|
||||
+++ b/drivers/media/video/v4l2-subdev.c
|
||||
@@ -213,6 +213,32 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
||||
return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh, format);
|
||||
}
|
||||
|
||||
+ case VIDIOC_SUBDEV_G_CROP: {
|
||||
+ struct v4l2_subdev_crop *crop = arg;
|
||||
+
|
||||
+ if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
|
||||
+ crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (crop->pad >= sd->entity.num_pads)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return v4l2_subdev_call(sd, pad, get_crop, subdev_fh, crop);
|
||||
+ }
|
||||
+
|
||||
+ case VIDIOC_SUBDEV_S_CROP: {
|
||||
+ struct v4l2_subdev_crop *crop = arg;
|
||||
+
|
||||
+ if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
|
||||
+ crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (crop->pad >= sd->entity.num_pads)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return v4l2_subdev_call(sd, pad, set_crop, subdev_fh, crop);
|
||||
+ }
|
||||
+
|
||||
case VIDIOC_SUBDEV_ENUM_MBUS_CODE: {
|
||||
struct v4l2_subdev_mbus_code_enum *code = arg;
|
||||
|
||||
diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h
|
||||
index bf9f3e9..49ec1e0 100644
|
||||
--- a/include/linux/v4l2-subdev.h
|
||||
+++ b/include/linux/v4l2-subdev.h
|
||||
@@ -51,6 +51,19 @@ struct v4l2_subdev_format {
|
||||
};
|
||||
|
||||
/**
|
||||
+ * struct v4l2_subdev_crop - Pad-level crop settings
|
||||
+ * @which: format type (from enum v4l2_subdev_format_whence)
|
||||
+ * @pad: pad number, as reported by the media API
|
||||
+ * @rect: pad crop rectangle boundaries
|
||||
+ */
|
||||
+struct v4l2_subdev_crop {
|
||||
+ __u32 which;
|
||||
+ __u32 pad;
|
||||
+ struct v4l2_rect rect;
|
||||
+ __u32 reserved[8];
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
* struct v4l2_subdev_mbus_code_enum - Media bus format enumeration
|
||||
* @pad: pad number, as reported by the media API
|
||||
* @index: format index during enumeration
|
||||
@@ -122,5 +135,7 @@ struct v4l2_subdev_frame_interval_enum {
|
||||
_IOWR('V', 74, struct v4l2_subdev_frame_size_enum)
|
||||
#define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \
|
||||
_IOWR('V', 75, struct v4l2_subdev_frame_interval_enum)
|
||||
+#define VIDIOC_SUBDEV_G_CROP _IOWR('V', 59, struct v4l2_subdev_crop)
|
||||
+#define VIDIOC_SUBDEV_S_CROP _IOWR('V', 60, struct v4l2_subdev_crop)
|
||||
|
||||
#endif
|
||||
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
|
||||
index 9c8bcd3..a02663e 100644
|
||||
--- a/include/media/v4l2-subdev.h
|
||||
+++ b/include/media/v4l2-subdev.h
|
||||
@@ -442,6 +442,10 @@ struct v4l2_subdev_pad_ops {
|
||||
struct v4l2_subdev_format *format);
|
||||
int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_format *format);
|
||||
+ int (*set_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_crop *crop);
|
||||
+ int (*get_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_crop *crop);
|
||||
};
|
||||
|
||||
struct v4l2_subdev_ops {
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
From 3378e81670a983f084f6d8e6be654234b258e482 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Date: Fri, 26 Feb 2010 16:23:10 +0100
|
||||
Subject: [PATCH 31/43] v4l: subdev: Generic ioctl support
|
||||
|
||||
Instead of returning an error when receiving an ioctl call with an
|
||||
unsupported command, forward the call to the subdev core::ioctl handler.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
---
|
||||
Documentation/video4linux/v4l2-framework.txt | 5 +++++
|
||||
drivers/media/video/v4l2-subdev.c | 2 +-
|
||||
2 files changed, 6 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
|
||||
index d0fb880..1bb5f22 100644
|
||||
--- a/Documentation/video4linux/v4l2-framework.txt
|
||||
+++ b/Documentation/video4linux/v4l2-framework.txt
|
||||
@@ -407,6 +407,11 @@ VIDIOC_UNSUBSCRIBE_EVENT
|
||||
To properly support events, the poll() file operation is also
|
||||
implemented.
|
||||
|
||||
+Private ioctls
|
||||
+
|
||||
+ All ioctls not in the above list are passed directly to the sub-device
|
||||
+ driver through the core::ioctl operation.
|
||||
+
|
||||
|
||||
I2C sub-device drivers
|
||||
----------------------
|
||||
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
|
||||
index e706c4c..1710a64 100644
|
||||
--- a/drivers/media/video/v4l2-subdev.c
|
||||
+++ b/drivers/media/video/v4l2-subdev.c
|
||||
@@ -276,7 +276,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
- return -ENOIOCTLCMD;
|
||||
+ return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
From 80c35f54b7d24b5f05e1e510f87e2ad1b94efede Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Date: Tue, 16 Nov 2010 06:21:06 +0200
|
||||
Subject: [PATCH 32/43] v4l: Add subdev sensor g_skip_frames operation
|
||||
|
||||
Some buggy sensors generate corrupt frames when the stream is started.
|
||||
This new operation return the number of corrupt frames to skip when
|
||||
starting the stream.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
---
|
||||
include/media/v4l2-subdev.h | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
|
||||
index a02663e..181de59 100644
|
||||
--- a/include/media/v4l2-subdev.h
|
||||
+++ b/include/media/v4l2-subdev.h
|
||||
@@ -352,9 +352,13 @@ struct v4l2_subdev_vbi_ops {
|
||||
* This is needed for some sensors, which always corrupt
|
||||
* several top lines of the output image, or which send their
|
||||
* metadata in them.
|
||||
+ * @g_skip_frames: number of frames to skip at stream start. This is needed for
|
||||
+ * buggy sensors that generate faulty frames when they are
|
||||
+ * turned on.
|
||||
*/
|
||||
struct v4l2_subdev_sensor_ops {
|
||||
int (*g_skip_top_lines)(struct v4l2_subdev *sd, u32 *lines);
|
||||
+ int (*g_skip_frames)(struct v4l2_subdev *sd, u32 *frames);
|
||||
};
|
||||
|
||||
/*
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
From 70e40e24f3da31a0c29f6f6042da9a085aa9ba7f Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Date: Fri, 19 Nov 2010 15:20:06 +0100
|
||||
Subject: [PATCH 33/43] v4l: Include linux/videodev2.h in media/v4l2-ctrls.h
|
||||
|
||||
The later makes extensive use of structures defined in the former.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
---
|
||||
include/media/v4l2-ctrls.h | 1 +
|
||||
1 files changed, 1 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
|
||||
index 9b7bea9..3b133b7 100644
|
||||
--- a/include/media/v4l2-ctrls.h
|
||||
+++ b/include/media/v4l2-ctrls.h
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/device.h>
|
||||
+#include <linux/videodev2.h>
|
||||
|
||||
/* forward references */
|
||||
struct v4l2_ctrl_handler;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
From d887b7e4224fa03f080ab6ede038eee8aac4c221 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Date: Tue, 7 Dec 2010 12:57:25 +0100
|
||||
Subject: [PATCH 34/43] v4l: Fix a use-before-set in the control framework
|
||||
|
||||
v4l2_queryctrl sets the step value based on the control type. That would
|
||||
be fine if it used the control type stored in the V4L2 kernel control
|
||||
object, not the one stored in the userspace ioctl structure that has
|
||||
just been memset to 0. Fix this.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
|
||||
---
|
||||
drivers/media/video/v4l2-ctrls.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
|
||||
index 9d2502c..5f74fec 100644
|
||||
--- a/drivers/media/video/v4l2-ctrls.c
|
||||
+++ b/drivers/media/video/v4l2-ctrls.c
|
||||
@@ -1338,7 +1338,7 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
|
||||
qc->minimum = ctrl->minimum;
|
||||
qc->maximum = ctrl->maximum;
|
||||
qc->default_value = ctrl->default_value;
|
||||
- if (qc->type == V4L2_CTRL_TYPE_MENU)
|
||||
+ if (ctrl->type == V4L2_CTRL_TYPE_MENU)
|
||||
qc->step = 1;
|
||||
else
|
||||
qc->step = ctrl->step;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
From 4ad2d8ab7eef4bc2a482c228f334cfbf30d71855 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Date: Wed, 1 Sep 2010 17:59:36 +0200
|
||||
Subject: [PATCH 35/43] v4l: Add 8-bit YUYV on 16-bit bus and SGRBG10 media bus pixel codes
|
||||
|
||||
Add the following media bus format code definitions:
|
||||
|
||||
- V4L2_MBUS_FMT_SGRBG10_1X10 for 10-bit GRBG Bayer
|
||||
- V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 for 10-bit DPCM compressed GRBG Bayer
|
||||
- V4L2_MBUS_FMT_YUYV16_1X16 for 8-bit YUYV on 16-bit bus
|
||||
- V4L2_MBUS_FMT_UYVY16_1X16 for 8-bit UYVY on 16-bit bus
|
||||
- V4L2_MBUS_FMT_YVYU16_1X16 for 8-bit YVYU on 16-bit bus
|
||||
- V4L2_MBUS_FMT_VYUY16_1X16 for 8-bit VYUY on 16-bit bus
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
---
|
||||
include/linux/v4l2-mediabus.h | 10 ++++++++--
|
||||
1 files changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/include/linux/v4l2-mediabus.h b/include/linux/v4l2-mediabus.h
|
||||
index cccfa34..c4caca3 100644
|
||||
--- a/include/linux/v4l2-mediabus.h
|
||||
+++ b/include/linux/v4l2-mediabus.h
|
||||
@@ -47,7 +47,7 @@ enum v4l2_mbus_pixelcode {
|
||||
V4L2_MBUS_FMT_RGB565_2X8_BE = 0x1007,
|
||||
V4L2_MBUS_FMT_RGB565_2X8_LE = 0x1008,
|
||||
|
||||
- /* YUV (including grey) - next is 0x200f */
|
||||
+ /* YUV (including grey) - next is 0x2013 */
|
||||
V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
|
||||
V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
|
||||
V4L2_MBUS_FMT_VYUY8_1_5X8 = 0x2003,
|
||||
@@ -60,17 +60,23 @@ enum v4l2_mbus_pixelcode {
|
||||
V4L2_MBUS_FMT_Y10_1X10 = 0x200a,
|
||||
V4L2_MBUS_FMT_YUYV10_2X10 = 0x200b,
|
||||
V4L2_MBUS_FMT_YVYU10_2X10 = 0x200c,
|
||||
+ V4L2_MBUS_FMT_UYVY8_1X16 = 0x200f,
|
||||
+ V4L2_MBUS_FMT_VYUY8_1X16 = 0x2010,
|
||||
+ V4L2_MBUS_FMT_YUYV8_1X16 = 0x2011,
|
||||
+ V4L2_MBUS_FMT_YVYU8_1X16 = 0x2012,
|
||||
V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d,
|
||||
V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
|
||||
|
||||
- /* Bayer - next is 0x3009 */
|
||||
+ /* Bayer - next is 0x300b */
|
||||
V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
|
||||
V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002,
|
||||
+ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 = 0x3009,
|
||||
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_SGRBG10_1X10 = 0x300a,
|
||||
V4L2_MBUS_FMT_SBGGR12_1X12 = 0x3008,
|
||||
};
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
From a63be84f54298581d51efb8a4745747ca17a9d0d Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Date: Fri, 3 Sep 2010 10:47:25 +0200
|
||||
Subject: [PATCH 36/43] v4l: Add remaining RAW10 patterns w DPCM pixel code variants
|
||||
|
||||
This adds following formats:
|
||||
- V4L2_MBUS_FMT_SRGGB10_1X10
|
||||
- V4L2_MBUS_FMT_SGBRG10_1X10
|
||||
- V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8
|
||||
- V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8
|
||||
- V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8
|
||||
|
||||
Signed-off-by: Sergio Aguirre <saaguirre@ti.com>
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
---
|
||||
include/linux/v4l2-mediabus.h | 7 ++++++-
|
||||
1 files changed, 6 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/include/linux/v4l2-mediabus.h b/include/linux/v4l2-mediabus.h
|
||||
index c4caca3..5c64924 100644
|
||||
--- a/include/linux/v4l2-mediabus.h
|
||||
+++ b/include/linux/v4l2-mediabus.h
|
||||
@@ -67,16 +67,21 @@ enum v4l2_mbus_pixelcode {
|
||||
V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d,
|
||||
V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
|
||||
|
||||
- /* Bayer - next is 0x300b */
|
||||
+ /* Bayer - next is 0x3010 */
|
||||
V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
|
||||
V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002,
|
||||
+ V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 = 0x300b,
|
||||
+ V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 = 0x300c,
|
||||
V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 = 0x3009,
|
||||
+ V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8 = 0x300d,
|
||||
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_SGBRG10_1X10 = 0x300e,
|
||||
V4L2_MBUS_FMT_SGRBG10_1X10 = 0x300a,
|
||||
+ V4L2_MBUS_FMT_SRGGB10_1X10 = 0x300f,
|
||||
V4L2_MBUS_FMT_SBGGR12_1X12 = 0x3008,
|
||||
};
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
From 6585f70cdd7cbe63e6618d06a10819d31c7009fe Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Date: Thu, 23 Dec 2010 15:14:49 +0100
|
||||
Subject: [PATCH 37/43] v4l: Add missing 12 bits bayer media bus formats
|
||||
|
||||
Add codes and documentation for the following media bus formats:
|
||||
|
||||
- V4L2_MBUS_FMT_SGBRG12_1X12
|
||||
- V4L2_MBUS_FMT_SGRBG12_1X12
|
||||
- V4L2_MBUS_FMT_SRGGB12_1X12
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
---
|
||||
Documentation/DocBook/v4l/subdev-formats.xml | 51 ++++++++++++++++++++++++++
|
||||
include/linux/v4l2-mediabus.h | 5 ++-
|
||||
2 files changed, 55 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/Documentation/DocBook/v4l/subdev-formats.xml b/Documentation/DocBook/v4l/subdev-formats.xml
|
||||
index 0cae572..2fed9be 100644
|
||||
--- a/Documentation/DocBook/v4l/subdev-formats.xml
|
||||
+++ b/Documentation/DocBook/v4l/subdev-formats.xml
|
||||
@@ -490,6 +490,57 @@
|
||||
<entry>b<subscript>1</subscript></entry>
|
||||
<entry>b<subscript>0</subscript></entry>
|
||||
</row>
|
||||
+ <row id="V4L2-MBUS-FMT-SGBRG12-1X12">
|
||||
+ <entry>V4L2_MBUS_FMT_SGBRG12_1X12</entry>
|
||||
+ <entry>0x3010</entry>
|
||||
+ <entry></entry>
|
||||
+ <entry>g<subscript>11</subscript></entry>
|
||||
+ <entry>g<subscript>10</subscript></entry>
|
||||
+ <entry>g<subscript>9</subscript></entry>
|
||||
+ <entry>g<subscript>8</subscript></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-SGRBG12-1X12">
|
||||
+ <entry>V4L2_MBUS_FMT_SGRBG12_1X12</entry>
|
||||
+ <entry>0x3011</entry>
|
||||
+ <entry></entry>
|
||||
+ <entry>g<subscript>11</subscript></entry>
|
||||
+ <entry>g<subscript>10</subscript></entry>
|
||||
+ <entry>g<subscript>9</subscript></entry>
|
||||
+ <entry>g<subscript>8</subscript></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-SRGGB12-1X12">
|
||||
+ <entry>V4L2_MBUS_FMT_SRGGB12_1X12</entry>
|
||||
+ <entry>0x3012</entry>
|
||||
+ <entry></entry>
|
||||
+ <entry>r<subscript>11</subscript></entry>
|
||||
+ <entry>r<subscript>10</subscript></entry>
|
||||
+ <entry>r<subscript>9</subscript></entry>
|
||||
+ <entry>r<subscript>8</subscript></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-SGBRG10-DPCM8-1X8">
|
||||
<entry>V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8</entry>
|
||||
<entry>0x300c</entry>
|
||||
diff --git a/include/linux/v4l2-mediabus.h b/include/linux/v4l2-mediabus.h
|
||||
index 5c64924..7054a7a 100644
|
||||
--- a/include/linux/v4l2-mediabus.h
|
||||
+++ b/include/linux/v4l2-mediabus.h
|
||||
@@ -67,7 +67,7 @@ enum v4l2_mbus_pixelcode {
|
||||
V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d,
|
||||
V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
|
||||
|
||||
- /* Bayer - next is 0x3010 */
|
||||
+ /* Bayer - next is 0x3013 */
|
||||
V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
|
||||
V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002,
|
||||
V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 = 0x300b,
|
||||
@@ -83,6 +83,9 @@ enum v4l2_mbus_pixelcode {
|
||||
V4L2_MBUS_FMT_SGRBG10_1X10 = 0x300a,
|
||||
V4L2_MBUS_FMT_SRGGB10_1X10 = 0x300f,
|
||||
V4L2_MBUS_FMT_SBGGR12_1X12 = 0x3008,
|
||||
+ V4L2_MBUS_FMT_SGBRG12_1X12 = 0x3010,
|
||||
+ V4L2_MBUS_FMT_SGRBG12_1X12 = 0x3011,
|
||||
+ V4L2_MBUS_FMT_SRGGB12_1X12 = 0x3012,
|
||||
};
|
||||
|
||||
/**
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
From 859b5c38e30c3d41e7987a6bb46f7d062f7e02ad Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Date: Thu, 23 Dec 2010 15:14:50 +0100
|
||||
Subject: [PATCH 38/43] v4l: Add 12 bits bayer pixel formats
|
||||
|
||||
Add FCCs for the following pixel formats:
|
||||
|
||||
- V4L2_PIX_FMT_SBGGR12
|
||||
- V4L2_PIX_FMT_SGBRG12
|
||||
- V4L2_PIX_FMT_SGRBG12
|
||||
- V4L2_PIX_FMT_SRGGB12
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
---
|
||||
include/linux/videodev2.h | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
|
||||
index 5f6f470..02da9e7 100644
|
||||
--- a/include/linux/videodev2.h
|
||||
+++ b/include/linux/videodev2.h
|
||||
@@ -328,6 +328,10 @@ struct v4l2_pix_format {
|
||||
#define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '0') /* 10 GBGB.. RGRG.. */
|
||||
#define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10 GRGR.. BGBG.. */
|
||||
#define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '0') /* 10 RGRG.. GBGB.. */
|
||||
+#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2') /* 12 BGBG.. GRGR.. */
|
||||
+#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12 GBGB.. RGRG.. */
|
||||
+#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12 GRGR.. BGBG.. */
|
||||
+#define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2') /* 12 RGRG.. GBGB.. */
|
||||
/* 10bit raw bayer DPCM compressed to 8 bits */
|
||||
#define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0')
|
||||
/*
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
From 0fe8d5d2b4d1e48bf2ef9b5803636dc68c91b5f2 Mon Sep 17 00:00:00 2001
|
||||
From: Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
|
||||
Date: Tue, 2 Feb 2010 16:17:33 +0200
|
||||
Subject: [PATCH 39/43] ARM: OMAP3: Update Camera ISP definitions for OMAP3630
|
||||
|
||||
Add new/changed base address definitions and resources for
|
||||
OMAP3630 ISP.
|
||||
|
||||
The OMAP3430 CSI2PHY block is same as the OMAP3630 CSIPHY2
|
||||
block. But the later name is chosen as it gives more symmetry
|
||||
to the names.
|
||||
|
||||
Signed-off-by: Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
|
||||
Signed-off-by: Vimarsh Zutshi <vimarsh.zutshi@nokia.com>
|
||||
Acked-by: Tony Lindgren <tony@atomide.com>
|
||||
---
|
||||
arch/arm/mach-omap2/devices.c | 28 ++++++++++++++++++++++++----
|
||||
arch/arm/plat-omap/include/plat/omap34xx.h | 16 ++++++++++++----
|
||||
2 files changed, 36 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
|
||||
index 381f4eb..40c64b9 100644
|
||||
--- a/arch/arm/mach-omap2/devices.c
|
||||
+++ b/arch/arm/mach-omap2/devices.c
|
||||
@@ -109,13 +109,33 @@ static struct resource omap3isp_resources[] = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
- .start = OMAP3430_ISP_CSI2A_BASE,
|
||||
- .end = OMAP3430_ISP_CSI2A_END,
|
||||
+ .start = OMAP3430_ISP_CSI2A_REGS1_BASE,
|
||||
+ .end = OMAP3430_ISP_CSI2A_REGS1_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
- .start = OMAP3430_ISP_CSI2PHY_BASE,
|
||||
- .end = OMAP3430_ISP_CSI2PHY_END,
|
||||
+ .start = OMAP3430_ISP_CSIPHY2_BASE,
|
||||
+ .end = OMAP3430_ISP_CSIPHY2_END,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ {
|
||||
+ .start = OMAP3630_ISP_CSI2A_REGS2_BASE,
|
||||
+ .end = OMAP3630_ISP_CSI2A_REGS2_END,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ {
|
||||
+ .start = OMAP3630_ISP_CSI2C_REGS1_BASE,
|
||||
+ .end = OMAP3630_ISP_CSI2C_REGS1_END,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ {
|
||||
+ .start = OMAP3630_ISP_CSIPHY1_BASE,
|
||||
+ .end = OMAP3630_ISP_CSIPHY1_END,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ {
|
||||
+ .start = OMAP3630_ISP_CSI2C_REGS2_BASE,
|
||||
+ .end = OMAP3630_ISP_CSI2C_REGS2_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
diff --git a/arch/arm/plat-omap/include/plat/omap34xx.h b/arch/arm/plat-omap/include/plat/omap34xx.h
|
||||
index 98fc8b4..b9e8588 100644
|
||||
--- a/arch/arm/plat-omap/include/plat/omap34xx.h
|
||||
+++ b/arch/arm/plat-omap/include/plat/omap34xx.h
|
||||
@@ -56,8 +56,12 @@
|
||||
#define OMAP3430_ISP_RESZ_BASE (OMAP3430_ISP_BASE + 0x1000)
|
||||
#define OMAP3430_ISP_SBL_BASE (OMAP3430_ISP_BASE + 0x1200)
|
||||
#define OMAP3430_ISP_MMU_BASE (OMAP3430_ISP_BASE + 0x1400)
|
||||
-#define OMAP3430_ISP_CSI2A_BASE (OMAP3430_ISP_BASE + 0x1800)
|
||||
-#define OMAP3430_ISP_CSI2PHY_BASE (OMAP3430_ISP_BASE + 0x1970)
|
||||
+#define OMAP3430_ISP_CSI2A_REGS1_BASE (OMAP3430_ISP_BASE + 0x1800)
|
||||
+#define OMAP3430_ISP_CSIPHY2_BASE (OMAP3430_ISP_BASE + 0x1970)
|
||||
+#define OMAP3630_ISP_CSI2A_REGS2_BASE (OMAP3430_ISP_BASE + 0x19C0)
|
||||
+#define OMAP3630_ISP_CSI2C_REGS1_BASE (OMAP3430_ISP_BASE + 0x1C00)
|
||||
+#define OMAP3630_ISP_CSIPHY1_BASE (OMAP3430_ISP_BASE + 0x1D70)
|
||||
+#define OMAP3630_ISP_CSI2C_REGS2_BASE (OMAP3430_ISP_BASE + 0x1DC0)
|
||||
|
||||
#define OMAP3430_ISP_END (OMAP3430_ISP_BASE + 0x06F)
|
||||
#define OMAP3430_ISP_CBUFF_END (OMAP3430_ISP_CBUFF_BASE + 0x077)
|
||||
@@ -69,8 +73,12 @@
|
||||
#define OMAP3430_ISP_RESZ_END (OMAP3430_ISP_RESZ_BASE + 0x0AB)
|
||||
#define OMAP3430_ISP_SBL_END (OMAP3430_ISP_SBL_BASE + 0x0FB)
|
||||
#define OMAP3430_ISP_MMU_END (OMAP3430_ISP_MMU_BASE + 0x06F)
|
||||
-#define OMAP3430_ISP_CSI2A_END (OMAP3430_ISP_CSI2A_BASE + 0x16F)
|
||||
-#define OMAP3430_ISP_CSI2PHY_END (OMAP3430_ISP_CSI2PHY_BASE + 0x007)
|
||||
+#define OMAP3430_ISP_CSI2A_REGS1_END (OMAP3430_ISP_CSI2A_REGS1_BASE + 0x16F)
|
||||
+#define OMAP3430_ISP_CSIPHY2_END (OMAP3430_ISP_CSIPHY2_BASE + 0x00B)
|
||||
+#define OMAP3630_ISP_CSI2A_REGS2_END (OMAP3630_ISP_CSI2A_REGS2_BASE + 0x3F)
|
||||
+#define OMAP3630_ISP_CSI2C_REGS1_END (OMAP3630_ISP_CSI2C_REGS1_BASE + 0x16F)
|
||||
+#define OMAP3630_ISP_CSIPHY1_END (OMAP3630_ISP_CSIPHY1_BASE + 0x00B)
|
||||
+#define OMAP3630_ISP_CSI2C_REGS2_END (OMAP3630_ISP_CSI2C_REGS2_BASE + 0x3F)
|
||||
|
||||
#define OMAP34XX_HSUSB_OTG_BASE (L4_34XX_BASE + 0xAB000)
|
||||
#define OMAP34XX_USBTLL_BASE (L4_34XX_BASE + 0x62000)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
From 70b39450b2de8e96504332730c9b00c663cfeaf9 Mon Sep 17 00:00:00 2001
|
||||
From: Sergio Aguirre <saaguirre@ti.com>
|
||||
Date: Mon, 15 Nov 2010 08:29:56 -0600
|
||||
Subject: [PATCH 40/43] omap3: Remove unusued ISP CBUFF resource
|
||||
|
||||
The ISP CBUFF module isn't use, its resource isn't needed.
|
||||
|
||||
Signed-off-by: Sergio Aguirre <saaguirre@ti.com>
|
||||
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
---
|
||||
arch/arm/mach-omap2/devices.c | 5 -----
|
||||
1 files changed, 0 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
|
||||
index 40c64b9..60cb86f 100644
|
||||
--- a/arch/arm/mach-omap2/devices.c
|
||||
+++ b/arch/arm/mach-omap2/devices.c
|
||||
@@ -69,11 +69,6 @@ static struct resource omap3isp_resources[] = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
- .start = OMAP3430_ISP_CBUFF_BASE,
|
||||
- .end = OMAP3430_ISP_CBUFF_END,
|
||||
- .flags = IORESOURCE_MEM,
|
||||
- },
|
||||
- {
|
||||
.start = OMAP3430_ISP_CCP2_BASE,
|
||||
.end = OMAP3430_ISP_CCP2_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
From d59f7c080e1c0d35a71f788350b619e76cee5033 Mon Sep 17 00:00:00 2001
|
||||
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Date: Mon, 14 Dec 2009 13:09:07 +0200
|
||||
Subject: [PATCH 41/43] omap3: Add function to register omap3isp platform device structure
|
||||
|
||||
The omap3isp platform device requires platform data. Instead of
|
||||
registering the device in omap2_init_devices(), export an
|
||||
omap3_init_camera() function to fill the device structure with the
|
||||
platform data pointer and register the device.
|
||||
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Acked-by: Tony Lindgren <tony@atomide.com>
|
||||
---
|
||||
arch/arm/mach-omap2/devices.c | 20 +++++++++++---------
|
||||
arch/arm/mach-omap2/devices.h | 17 +++++++++++++++++
|
||||
2 files changed, 28 insertions(+), 9 deletions(-)
|
||||
create mode 100644 arch/arm/mach-omap2/devices.h
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
|
||||
index 60cb86f..9b243be 100644
|
||||
--- a/arch/arm/mach-omap2/devices.c
|
||||
+++ b/arch/arm/mach-omap2/devices.c
|
||||
@@ -34,6 +34,8 @@
|
||||
#include "mux.h"
|
||||
#include "control.h"
|
||||
|
||||
+#include "devices.h"
|
||||
+
|
||||
#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
|
||||
|
||||
static struct resource cam_resources[] = {
|
||||
@@ -59,8 +61,11 @@ static inline void omap_init_camera(void)
|
||||
{
|
||||
platform_device_register(&omap_cam_device);
|
||||
}
|
||||
-
|
||||
-#elif defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
|
||||
+#else
|
||||
+static inline void omap_init_camera(void)
|
||||
+{
|
||||
+}
|
||||
+#endif
|
||||
|
||||
static struct resource omap3isp_resources[] = {
|
||||
{
|
||||
@@ -146,15 +151,12 @@ static struct platform_device omap3isp_device = {
|
||||
.resource = omap3isp_resources,
|
||||
};
|
||||
|
||||
-static inline void omap_init_camera(void)
|
||||
-{
|
||||
- platform_device_register(&omap3isp_device);
|
||||
-}
|
||||
-#else
|
||||
-static inline void omap_init_camera(void)
|
||||
+int omap3_init_camera(void *pdata)
|
||||
{
|
||||
+ omap3isp_device.dev.platform_data = pdata;
|
||||
+ return platform_device_register(&omap3isp_device);
|
||||
}
|
||||
-#endif
|
||||
+EXPORT_SYMBOL_GPL(omap3_init_camera);
|
||||
|
||||
#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/devices.h b/arch/arm/mach-omap2/devices.h
|
||||
new file mode 100644
|
||||
index 0000000..12ddb8a
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-omap2/devices.h
|
||||
@@ -0,0 +1,17 @@
|
||||
+/*
|
||||
+ * arch/arm/mach-omap2/devices.h
|
||||
+ *
|
||||
+ * OMAP2 platform device setup/initialization
|
||||
+ *
|
||||
+ * 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; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __ARCH_ARM_MACH_OMAP_DEVICES_H
|
||||
+#define __ARCH_ARM_MACH_OMAP_DEVICES_H
|
||||
+
|
||||
+int omap3_init_camera(void *pdata);
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
From 5cc262328a97b1d048ae42234909ac33c2fc342c Mon Sep 17 00:00:00 2001
|
||||
From: Sergio Aguirre <saaguirre@ti.com>
|
||||
Date: Mon, 15 Nov 2010 08:29:54 -0600
|
||||
Subject: [PATCH 42/43] omap2: Fix camera resources for multiomap
|
||||
|
||||
Make sure the kernel can be compiled with both OMAP2 and OMAP3 camera
|
||||
support linked in, and give public symbols proper omap2/omap3 prefixes.
|
||||
|
||||
Signed-off-by: Sergio Aguirre <saaguirre@ti.com>
|
||||
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
---
|
||||
arch/arm/mach-omap2/devices.c | 25 ++++++++++++-------------
|
||||
1 files changed, 12 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
|
||||
index 9b243be..c132c65 100644
|
||||
--- a/arch/arm/mach-omap2/devices.c
|
||||
+++ b/arch/arm/mach-omap2/devices.c
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
|
||||
|
||||
-static struct resource cam_resources[] = {
|
||||
+static struct resource omap2cam_resources[] = {
|
||||
{
|
||||
.start = OMAP24XX_CAMERA_BASE,
|
||||
.end = OMAP24XX_CAMERA_BASE + 0xfff,
|
||||
@@ -50,21 +50,12 @@ static struct resource cam_resources[] = {
|
||||
}
|
||||
};
|
||||
|
||||
-static struct platform_device omap_cam_device = {
|
||||
+static struct platform_device omap2cam_device = {
|
||||
.name = "omap24xxcam",
|
||||
.id = -1,
|
||||
- .num_resources = ARRAY_SIZE(cam_resources),
|
||||
- .resource = cam_resources,
|
||||
+ .num_resources = ARRAY_SIZE(omap2cam_resources),
|
||||
+ .resource = omap2cam_resources,
|
||||
};
|
||||
-
|
||||
-static inline void omap_init_camera(void)
|
||||
-{
|
||||
- platform_device_register(&omap_cam_device);
|
||||
-}
|
||||
-#else
|
||||
-static inline void omap_init_camera(void)
|
||||
-{
|
||||
-}
|
||||
#endif
|
||||
|
||||
static struct resource omap3isp_resources[] = {
|
||||
@@ -158,6 +149,14 @@ int omap3_init_camera(void *pdata)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap3_init_camera);
|
||||
|
||||
+static inline void omap_init_camera(void)
|
||||
+{
|
||||
+#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
|
||||
+ if (cpu_is_omap24xx())
|
||||
+ platform_device_register(&omap2cam_device);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
|
||||
|
||||
#define MBOX_REG_SIZE 0x120
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,8 @@ COMPATIBLE_MACHINE = "(beagleboard|overo|omap3evm|omap3-touchbook|usrp-e1xx)"
|
||||
|
||||
# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc
|
||||
PV = "2.6.37"
|
||||
MACHINE_KERNEL_PR_append = "a+gitr${SRCREV}"
|
||||
SRCREV_pn-${PN} = "fa3b4e23ec20cfc944db7cc2b30b0d82c20e4472"
|
||||
MACHINE_KERNEL_PR_append = "c+gitr${SRCREV}"
|
||||
SRCREV = "fa3b4e23ec20cfc944db7cc2b30b0d82c20e4472"
|
||||
|
||||
FILESPATHPKG_prepend = "linux-omap-2.6.37:"
|
||||
|
||||
@@ -149,6 +149,54 @@ SRC_URI_append = " \
|
||||
file://wl1271/0013-drivers-media-radio-Update-Kconfig-and-Makefile-for-.patch \
|
||||
file://wl1271/0014-drivers-misc-ti-st-change-protocol-parse-logic.patch \
|
||||
file://wl1271/0015-Bluetooth-btwilink-driver.patch \
|
||||
\
|
||||
file://media/0001-v4l-Share-code-between-video_usercopy-and-video_ioct.patch \
|
||||
file://media/0002-v4l-subdev-Don-t-require-core-operations.patch \
|
||||
file://media/0003-v4l-subdev-Merge-v4l2_i2c_new_subdev_cfg-and-v4l2_i2.patch \
|
||||
file://media/0004-v4l-subdev-Add-device-node-support.patch \
|
||||
file://media/0005-v4l-subdev-Uninline-the-v4l2_subdev_init-function.patch \
|
||||
file://media/0006-v4l-subdev-Control-ioctls-support.patch \
|
||||
file://media/0007-v4l-subdev-Events-support.patch \
|
||||
file://media/0008-media-Media-device-node-support.patch \
|
||||
file://media/0009-media-Media-device.patch \
|
||||
file://media/0010-media-Entities-pads-and-links.patch \
|
||||
file://media/0011-media-Entity-graph-traversal.patch \
|
||||
file://media/0012-media-Entity-use-count.patch \
|
||||
file://media/0013-media-Media-device-information-query.patch \
|
||||
file://media/0014-media-Entities-pads-and-links-enumeration.patch \
|
||||
file://media/0015-media-Links-setup.patch \
|
||||
file://media/0016-media-Pipelines-and-media-streams.patch \
|
||||
file://media/0017-v4l-Add-a-media_device-pointer-to-the-v4l2_device-st.patch \
|
||||
file://media/0018-v4l-Make-video_device-inherit-from-media_entity.patch \
|
||||
file://media/0019-v4l-Make-v4l2_subdev-inherit-from-media_entity.patch \
|
||||
file://media/0020-v4l-Move-the-media-v4l2-mediabus.h-header-to-include.patch \
|
||||
file://media/0021-v4l-Replace-enums-with-fixed-sized-fields-in-public-.patch \
|
||||
file://media/0022-v4l-Rename-V4L2_MBUS_FMT_GREY8_1X8-to-V4L2_MBUS_FMT_.patch \
|
||||
file://media/0023-v4l-Group-media-bus-pixel-codes-by-types-and-sort-th.patch \
|
||||
file://media/0024-v4l-Create-v4l2-subdev-file-handle-structure.patch \
|
||||
file://media/0025-v4l-subdev-Add-a-new-file-operations-class.patch \
|
||||
file://media/0026-v4l-v4l2_subdev-pad-level-operations.patch \
|
||||
file://media/0028-v4l-v4l2_subdev-userspace-format-API.patch \
|
||||
file://media/0029-v4l-v4l2_subdev-userspace-frame-interval-API.patch \
|
||||
file://media/0030-v4l-v4l2_subdev-userspace-crop-API.patch \
|
||||
file://media/0031-v4l-subdev-Generic-ioctl-support.patch \
|
||||
file://media/0032-v4l-Add-subdev-sensor-g_skip_frames-operation.patch \
|
||||
file://media/0033-v4l-Include-linux-videodev2.h-in-media-v4l2-ctrls.h.patch \
|
||||
file://media/0034-v4l-Fix-a-use-before-set-in-the-control-framework.patch \
|
||||
file://media/0035-v4l-Add-8-bit-YUYV-on-16-bit-bus-and-SGRBG10-media-b.patch \
|
||||
file://media/0036-v4l-Add-remaining-RAW10-patterns-w-DPCM-pixel-code-v.patch \
|
||||
file://media/0037-v4l-Add-missing-12-bits-bayer-media-bus-formats.patch \
|
||||
file://media/0038-v4l-Add-12-bits-bayer-pixel-formats.patch \
|
||||
file://media/0039-ARM-OMAP3-Update-Camera-ISP-definitions-for-OMAP3630.patch \
|
||||
file://media/0040-omap3-Remove-unusued-ISP-CBUFF-resource.patch \
|
||||
file://media/0041-omap3-Add-function-to-register-omap3isp-platform-dev.patch \
|
||||
file://media/0042-omap2-Fix-camera-resources-for-multiomap.patch \
|
||||
file://media/0043-OMAP3-ISP-driver.patch \
|
||||
\
|
||||
file://0001-beagleboard-hack-in-support-from-xM-rev-C.patch \
|
||||
file://0001-xM-audio-fix-from-Ashok.patch \
|
||||
file://0001-omap3-allow-1GHz-mpurates.patch \
|
||||
file://0001-BeagleBoard-Adjust-USER-button-pin-for-xM.patch \
|
||||
"
|
||||
|
||||
SRC_URI_append_usrp-e1xx = "\
|
||||
|
||||
Reference in New Issue
Block a user