From f8f3914cf922f5f9e1d60e9e10f6fb92742907ad Mon Sep 17 00:00:00 2001
From: Pawel Osciak
Date: Thu, 29 Jul 2010 14:44:25 -0300
Subject: [media] v4l: Add multi-planar API definitions to the V4L2 API
Multi-planar API is as a backwards-compatible extension of the V4L2 API,
which allows video buffers to consist of one or more planes. Planes are
separate memory buffers; each has its own mapping, backed by usually
separate physical memory buffers.
Many different uses for the multi-planar API are possible, examples
include:
- embedded devices requiring video components to be placed in physically
separate buffers, e.g. for Samsung S3C/S5P SoC series' video codec,
Y and interleaved Cb/Cr components reside in buffers in different
memory banks;
- applications may receive (or choose to store) video data of one video
buffer in separate memory buffers; such data would have to be temporarily
copied together into one buffer before passing it to a V4L2 device;
- applications or drivers may want to pass metadata related to a buffer and
it may not be possible to place it in the same buffer, together with video
data.
[mchehab@redhat.com: CodingStyle fixes]
Signed-off-by: Pawel Osciak
Signed-off-by: Kyungmin Park
Reviewed-by: Marek Szyprowski
Signed-off-by: Marek Szyprowski
Reviewed-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
include/linux/videodev2.h | 124 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 122 insertions(+), 2 deletions(-)
(limited to 'include/linux')
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 5f6f47044abf..bb0a3ae2ebd0 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -70,6 +70,7 @@
* Moved from videodev.h
*/
#define VIDEO_MAX_FRAME 32
+#define VIDEO_MAX_PLANES 8
#ifndef __KERNEL__
@@ -157,9 +158,23 @@ enum v4l2_buf_type {
/* Experimental */
V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,
#endif
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = 10,
V4L2_BUF_TYPE_PRIVATE = 0x80,
};
+#define V4L2_TYPE_IS_MULTIPLANAR(type) \
+ ((type) == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE \
+ || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+
+#define V4L2_TYPE_IS_OUTPUT(type) \
+ ((type) == V4L2_BUF_TYPE_VIDEO_OUTPUT \
+ || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE \
+ || (type) == V4L2_BUF_TYPE_VIDEO_OVERLAY \
+ || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY \
+ || (type) == V4L2_BUF_TYPE_VBI_OUTPUT \
+ || (type) == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
+
enum v4l2_tuner_type {
V4L2_TUNER_RADIO = 1,
V4L2_TUNER_ANALOG_TV = 2,
@@ -245,6 +260,11 @@ struct v4l2_capability {
#define V4L2_CAP_HW_FREQ_SEEK 0x00000400 /* Can do hardware frequency seek */
#define V4L2_CAP_RDS_OUTPUT 0x00000800 /* Is an RDS encoder */
+/* Is a video capture device that supports multiplanar formats */
+#define V4L2_CAP_VIDEO_CAPTURE_MPLANE 0x00001000
+/* Is a video output device that supports multiplanar formats */
+#define V4L2_CAP_VIDEO_OUTPUT_MPLANE 0x00002000
+
#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */
@@ -517,6 +537,62 @@ struct v4l2_requestbuffers {
__u32 reserved[2];
};
+/**
+ * struct v4l2_plane - plane info for multi-planar buffers
+ * @bytesused: number of bytes occupied by data in the plane (payload)
+ * @length: size of this plane (NOT the payload) in bytes
+ * @mem_offset: when memory in the associated struct v4l2_buffer is
+ * V4L2_MEMORY_MMAP, equals the offset from the start of
+ * the device memory for this plane (or is a "cookie" that
+ * should be passed to mmap() called on the video node)
+ * @userptr: when memory is V4L2_MEMORY_USERPTR, a userspace pointer
+ * pointing to this plane
+ * @data_offset: offset in the plane to the start of data; usually 0,
+ * unless there is a header in front of the data
+ *
+ * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer
+ * with two planes can have one plane for Y, and another for interleaved CbCr
+ * components. Each plane can reside in a separate memory buffer, or even in
+ * a completely separate memory node (e.g. in embedded devices).
+ */
+struct v4l2_plane {
+ __u32 bytesused;
+ __u32 length;
+ union {
+ __u32 mem_offset;
+ unsigned long userptr;
+ } m;
+ __u32 data_offset;
+ __u32 reserved[11];
+};
+
+/**
+ * struct v4l2_buffer - video buffer info
+ * @index: id number of the buffer
+ * @type: buffer type (type == *_MPLANE for multiplanar buffers)
+ * @bytesused: number of bytes occupied by data in the buffer (payload);
+ * unused (set to 0) for multiplanar buffers
+ * @flags: buffer informational flags
+ * @field: field order of the image in the buffer
+ * @timestamp: frame timestamp
+ * @timecode: frame timecode
+ * @sequence: sequence count of this frame
+ * @memory: the method, in which the actual video data is passed
+ * @offset: for non-multiplanar buffers with memory == V4L2_MEMORY_MMAP;
+ * offset from the start of the device memory for this plane,
+ * (or a "cookie" that should be passed to mmap() as offset)
+ * @userptr: for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR;
+ * a userspace pointer pointing to this buffer
+ * @planes: for multiplanar buffers; userspace pointer to the array of plane
+ * info structs for this buffer
+ * @length: size in bytes of the buffer (NOT its payload) for single-plane
+ * buffers (when type != *_MPLANE); number of elements in the
+ * planes array for multi-plane buffers
+ * @input: input number from which the video data has has been captured
+ *
+ * Contains data exchanged by application and driver using one of the Streaming
+ * I/O methods.
+ */
struct v4l2_buffer {
__u32 index;
enum v4l2_buf_type type;
@@ -532,6 +608,7 @@ struct v4l2_buffer {
union {
__u32 offset;
unsigned long userptr;
+ struct v4l2_plane *planes;
} m;
__u32 length;
__u32 input;
@@ -1622,12 +1699,56 @@ struct v4l2_mpeg_vbi_fmt_ivtv {
* A G G R E G A T E S T R U C T U R E S
*/
-/* Stream data format
+/**
+ * struct v4l2_plane_pix_format - additional, per-plane format definition
+ * @sizeimage: maximum size in bytes required for data, for which
+ * this plane will be used
+ * @bytesperline: distance in bytes between the leftmost pixels in two
+ * adjacent lines
+ */
+struct v4l2_plane_pix_format {
+ __u32 sizeimage;
+ __u16 bytesperline;
+ __u16 reserved[7];
+} __attribute__ ((packed));
+
+/**
+ * struct v4l2_pix_format_mplane - multiplanar format definition
+ * @width: image width in pixels
+ * @height: image height in pixels
+ * @pixelformat: little endian four character code (fourcc)
+ * @field: field order (for interlaced video)
+ * @colorspace: supplemental to pixelformat
+ * @plane_fmt: per-plane information
+ * @num_planes: number of planes for this format
+ */
+struct v4l2_pix_format_mplane {
+ __u32 width;
+ __u32 height;
+ __u32 pixelformat;
+ enum v4l2_field field;
+ enum v4l2_colorspace colorspace;
+
+ struct v4l2_plane_pix_format plane_fmt[VIDEO_MAX_PLANES];
+ __u8 num_planes;
+ __u8 reserved[11];
+} __attribute__ ((packed));
+
+/**
+ * struct v4l2_format - stream data format
+ * @type: type of the data stream
+ * @pix: definition of an image format
+ * @pix_mp: definition of a multiplanar image format
+ * @win: definition of an overlaid image
+ * @vbi: raw VBI capture or output parameters
+ * @sliced: sliced VBI capture or output parameters
+ * @raw_data: placeholder for future extensions and custom formats
*/
struct v4l2_format {
enum v4l2_buf_type type;
union {
struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
+ struct v4l2_pix_format_mplane pix_mp; /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */
struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
@@ -1635,7 +1756,6 @@ struct v4l2_format {
} fmt;
};
-
/* Stream type-dependent parameters
*/
struct v4l2_streamparm {
--
cgit v1.2.3
From 4a3c9b4f0df43207eb0b4d0da9cb51e185506bd5 Mon Sep 17 00:00:00 2001
From: Sylwester Nawrocki
Date: Tue, 28 Dec 2010 12:32:39 -0300
Subject: [media] v4l: Add multiplanar format fourccs for s5p-fimc driver
Add definitions for format with color planes non-contiguous
in physical memory. These formats apply only if the V4L2 multiplane
extension is used.
V4L2_PIX_FMT_NV12M - 2-plane Y/CbCr
V4L2_PIX_FMT_NV12MT - 2-plane Y/CbCr tiled (64x32 pixel macroblocks)
V4L2_PIX_FMT_YUV420M - 3-plane Y/Cb/Cr
Signed-off-by: Sylwester Nawrocki
Signed-off-by: Kyungmin Park
Signed-off-by: Mauro Carvalho Chehab
---
include/linux/videodev2.h | 7 +++++++
1 file changed, 7 insertions(+)
(limited to 'include/linux')
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index bb0a3ae2ebd0..5122b265dde6 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -339,6 +339,13 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */
#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') /* 16 Y/CrCb 4:2:2 */
+/* two non contiguous planes - one Y, one Cr + Cb interleaved */
+#define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */
+#define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */
+
+/* three non contiguous planes - Y, Cb, Cr */
+#define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12 YUV420 planar */
+
/* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */
#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */
--
cgit v1.2.3
From 7ee40aadabd59b6cab60835f0ef9cdbe385df438 Mon Sep 17 00:00:00 2001
From: Hans Verkuil
Date: Sat, 5 Feb 2011 10:10:38 -0300
Subject: [media] v4l: removal of old, obsolete ioctls
Some ioctl's were defined wrong on 2.6.2 and 2.6.6, using the wrong
type of R/W arguments. They were fixed, but the old ioctl names are
still there, maintained to avoid breaking binary compatibility:
There's no sense on preserving those forever, as it is very doubtful
that someone would try to use a such old binary with a modern kernel.
Removing them will allow us to remove some magic done at the V4L ioctl
handler.
Note that any application compiled with a videodev2.h from 2.6.7 or later
will be using the correct ioctls.
Signed-off-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
Documentation/feature-removal-schedule.txt | 21 -----------------
drivers/media/video/v4l2-common.c | 1 -
drivers/media/video/v4l2-compat-ioctl32.c | 15 ------------
drivers/media/video/v4l2-ioctl.c | 38 ------------------------------
drivers/staging/easycap/easycap_ioctl.c | 5 ----
include/linux/videodev2.h | 10 --------
6 files changed, 90 deletions(-)
(limited to 'include/linux')
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 08e0df12df37..61fb823e5a95 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -97,27 +97,6 @@ Who: Pavel Machek
---------------------------
-What: Video4Linux: Remove obsolete ioctl's
-When: kernel 2.6.39
-Files: include/media/videodev2.h
-Why: Some ioctl's were defined wrong on 2.6.2 and 2.6.6, using the wrong
- type of R/W arguments. They were fixed, but the old ioctl names are
- still there, maintained to avoid breaking binary compatibility:
- #define VIDIOC_OVERLAY_OLD _IOWR('V', 14, int)
- #define VIDIOC_S_PARM_OLD _IOW('V', 22, struct v4l2_streamparm)
- #define VIDIOC_S_CTRL_OLD _IOW('V', 28, struct v4l2_control)
- #define VIDIOC_G_AUDIO_OLD _IOWR('V', 33, struct v4l2_audio)
- #define VIDIOC_G_AUDOUT_OLD _IOWR('V', 49, struct v4l2_audioout)
- #define VIDIOC_CROPCAP_OLD _IOR('V', 58, struct v4l2_cropcap)
- There's no sense on preserving those forever, as it is very doubtful
- that someone would try to use a such old binary with a modern kernel.
- Removing them will allow us to remove some magic done at the V4L ioctl
- handler.
-
-Who: Mauro Carvalho Chehab
-
----------------------------
-
What: sys_sysctl
When: September 2010
Option: CONFIG_SYSCTL_SYSCALL
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 810eef43c216..940b5db3463e 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -59,7 +59,6 @@
#include
#include
#include
-#define __OLD_VIDIOC_ /* To allow fixing old calls*/
#include
#include
#include
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index c19208a07b48..7c2694738b31 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -14,7 +14,6 @@
*/
#include
-#define __OLD_VIDIOC_ /* To allow fixing old calls*/
#include
#include
#include
@@ -678,9 +677,6 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
#define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
#define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
-#ifdef __OLD_VIDIOC_
-#define VIDIOC_OVERLAY32_OLD _IOWR('V', 14, s32)
-#endif
#define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
#define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32)
#define VIDIOC_G_INPUT32 _IOR ('V', 38, s32)
@@ -720,9 +716,6 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
-#ifdef __OLD_VIDIOC_
- case VIDIOC_OVERLAY32_OLD: cmd = VIDIOC_OVERLAY; break;
-#endif
case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
@@ -856,14 +849,6 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
return ret;
switch (cmd) {
-#ifdef __OLD_VIDIOC_
- case VIDIOC_OVERLAY32_OLD:
- case VIDIOC_S_PARM_OLD:
- case VIDIOC_S_CTRL_OLD:
- case VIDIOC_G_AUDIO_OLD:
- case VIDIOC_G_AUDOUT_OLD:
- case VIDIOC_CROPCAP_OLD:
-#endif
case VIDIOC_QUERYCAP:
case VIDIOC_RESERVED:
case VIDIOC_ENUM_FMT:
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 8360ed2d933a..7a720745c3fa 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -17,7 +17,6 @@
#include
#include
-#define __OLD_VIDIOC_ /* To allow fixing old calls */
#include
#include
@@ -297,37 +296,6 @@ EXPORT_SYMBOL(v4l_printk_ioctl);
/*
* helper function -- handles userspace copying for ioctl arguments
- */
-
-#ifdef __OLD_VIDIOC_
-static unsigned int
-video_fix_command(unsigned int cmd)
-{
- switch (cmd) {
- case VIDIOC_OVERLAY_OLD:
- cmd = VIDIOC_OVERLAY;
- break;
- case VIDIOC_S_PARM_OLD:
- cmd = VIDIOC_S_PARM;
- break;
- case VIDIOC_S_CTRL_OLD:
- cmd = VIDIOC_S_CTRL;
- break;
- case VIDIOC_G_AUDIO_OLD:
- cmd = VIDIOC_G_AUDIO;
- break;
- case VIDIOC_G_AUDOUT_OLD:
- cmd = VIDIOC_G_AUDOUT;
- break;
- case VIDIOC_CROPCAP_OLD:
- cmd = VIDIOC_CROPCAP;
- break;
- }
- return cmd;
-}
-#endif
-
-/*
* Obsolete usercopy function - Should be removed soon
*/
long
@@ -342,9 +310,6 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
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);
@@ -2379,9 +2344,6 @@ long video_ioctl2(struct file *file,
void __user *user_ptr = NULL;
void **kernel_ptr = NULL;
-#ifdef __OLD_VIDIOC_
- cmd = video_fix_command(cmd);
-#endif
/* Copy arguments into temp kernel buffer */
if (_IOC_DIR(cmd) != _IOC_NONE) {
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
diff --git a/drivers/staging/easycap/easycap_ioctl.c b/drivers/staging/easycap/easycap_ioctl.c
index 447953a4e80c..7ac43da4e252 100644
--- a/drivers/staging/easycap/easycap_ioctl.c
+++ b/drivers/staging/easycap/easycap_ioctl.c
@@ -1399,11 +1399,6 @@ case VIDIOC_G_CTRL: {
break;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-#if defined(VIDIOC_S_CTRL_OLD)
-case VIDIOC_S_CTRL_OLD: {
- JOM(8, "VIDIOC_S_CTRL_OLD required at least for xawtv\n");
-}
-#endif /*VIDIOC_S_CTRL_OLD*/
case VIDIOC_S_CTRL:
{
struct v4l2_control v4l2_control;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 5122b265dde6..a94c4d5ac340 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1935,16 +1935,6 @@ struct v4l2_dbg_chip_ident {
/* Reminder: when adding new ioctls please add support for them to
drivers/media/video/v4l2-compat-ioctl32.c as well! */
-#ifdef __OLD_VIDIOC_
-/* for compatibility, will go away some day */
-#define VIDIOC_OVERLAY_OLD _IOWR('V', 14, int)
-#define VIDIOC_S_PARM_OLD _IOW('V', 22, struct v4l2_streamparm)
-#define VIDIOC_S_CTRL_OLD _IOW('V', 28, struct v4l2_control)
-#define VIDIOC_G_AUDIO_OLD _IOWR('V', 33, struct v4l2_audio)
-#define VIDIOC_G_AUDOUT_OLD _IOWR('V', 49, struct v4l2_audioout)
-#define VIDIOC_CROPCAP_OLD _IOR('V', 58, struct v4l2_cropcap)
-#endif
-
#define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */
#endif /* __LINUX_VIDEODEV2_H */
--
cgit v1.2.3
From 94fd5b7401e330498331ea3667d796e74c63d08a Mon Sep 17 00:00:00 2001
From: Matti Aaltonen
Date: Tue, 1 Mar 2011 10:10:35 -0300
Subject: [media] MFD: WL1273 FM Radio: MFD driver for the FM radio
This is the core of the WL1273 FM radio driver, it connects
the two child modules. The two child drivers are
drivers/media/radio/radio-wl1273.c and sound/soc/codecs/wl1273.c.
The radio-wl1273 driver implements the V4L2 interface and communicates
with the device. The ALSA codec offers digital audio, without it only
analog audio is available.
Signed-off-by: Matti J. Aaltonen
Acked-by: Samuel Ortiz
Signed-off-by: Mauro Carvalho Chehab
---
drivers/mfd/Kconfig | 2 +-
drivers/mfd/wl1273-core.c | 149 +++++++++++++++++++++++++++++++++++++++-
include/linux/mfd/wl1273-core.h | 2 +
3 files changed, 149 insertions(+), 4 deletions(-)
(limited to 'include/linux')
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fd018366d670..9db079be0e08 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -615,7 +615,7 @@ config MFD_VX855
and/or vx855_gpio drivers for this to do anything useful.
config MFD_WL1273_CORE
- tristate
+ tristate "Support for TI WL1273 FM radio."
depends on I2C
select MFD_CORE
default n
diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c
index d2ecc2435736..4025a4bec8d5 100644
--- a/drivers/mfd/wl1273-core.c
+++ b/drivers/mfd/wl1273-core.c
@@ -1,7 +1,7 @@
/*
* MFD driver for wl1273 FM radio and audio codec submodules.
*
- * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2011 Nokia Corporation
* Author: Matti Aaltonen
*
* This program is free software; you can redistribute it and/or modify
@@ -31,6 +31,145 @@ static struct i2c_device_id wl1273_driver_id_table[] = {
};
MODULE_DEVICE_TABLE(i2c, wl1273_driver_id_table);
+static int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value)
+{
+ struct i2c_client *client = core->client;
+ u8 b[2];
+ int r;
+
+ r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), b);
+ if (r != 2) {
+ dev_err(&client->dev, "%s: Read: %d fails.\n", __func__, reg);
+ return -EREMOTEIO;
+ }
+
+ *value = (u16)b[0] << 8 | b[1];
+
+ return 0;
+}
+
+static int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param)
+{
+ struct i2c_client *client = core->client;
+ u8 buf[] = { (param >> 8) & 0xff, param & 0xff };
+ int r;
+
+ r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf);
+ if (r) {
+ dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd);
+ return r;
+ }
+
+ return 0;
+}
+
+static int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len)
+{
+ struct i2c_client *client = core->client;
+ struct i2c_msg msg;
+ int r;
+
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.buf = data;
+ msg.len = len;
+
+ r = i2c_transfer(client->adapter, &msg, 1);
+ if (r != 1) {
+ dev_err(&client->dev, "%s: write error.\n", __func__);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+/**
+ * wl1273_fm_set_audio() - Set audio mode.
+ * @core: A pointer to the device struct.
+ * @new_mode: The new audio mode.
+ *
+ * Audio modes are WL1273_AUDIO_DIGITAL and WL1273_AUDIO_ANALOG.
+ */
+static int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode)
+{
+ int r = 0;
+
+ if (core->mode == WL1273_MODE_OFF ||
+ core->mode == WL1273_MODE_SUSPENDED)
+ return -EPERM;
+
+ if (core->mode == WL1273_MODE_RX && new_mode == WL1273_AUDIO_DIGITAL) {
+ r = wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET,
+ WL1273_PCM_DEF_MODE);
+ if (r)
+ goto out;
+
+ r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
+ core->i2s_mode);
+ if (r)
+ goto out;
+
+ r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
+ WL1273_AUDIO_ENABLE_I2S);
+ if (r)
+ goto out;
+
+ } else if (core->mode == WL1273_MODE_RX &&
+ new_mode == WL1273_AUDIO_ANALOG) {
+ r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
+ WL1273_AUDIO_ENABLE_ANALOG);
+ if (r)
+ goto out;
+
+ } else if (core->mode == WL1273_MODE_TX &&
+ new_mode == WL1273_AUDIO_DIGITAL) {
+ r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
+ core->i2s_mode);
+ if (r)
+ goto out;
+
+ r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
+ WL1273_AUDIO_IO_SET_I2S);
+ if (r)
+ goto out;
+
+ } else if (core->mode == WL1273_MODE_TX &&
+ new_mode == WL1273_AUDIO_ANALOG) {
+ r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
+ WL1273_AUDIO_IO_SET_ANALOG);
+ if (r)
+ goto out;
+ }
+
+ core->audio_mode = new_mode;
+out:
+ return r;
+}
+
+/**
+ * wl1273_fm_set_volume() - Set volume.
+ * @core: A pointer to the device struct.
+ * @volume: The new volume value.
+ */
+static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume)
+{
+ u16 val;
+ int r;
+
+ if (volume > WL1273_MAX_VOLUME)
+ return -EINVAL;
+
+ if (core->volume == volume)
+ return 0;
+
+ r = wl1273_fm_write_cmd(core, WL1273_VOLUME_SET, volume);
+ if (r)
+ return r;
+
+ core->volume = volume;
+ return 0;
+}
+
static int wl1273_core_remove(struct i2c_client *client)
{
struct wl1273_core *core = i2c_get_clientdata(client);
@@ -38,7 +177,6 @@ static int wl1273_core_remove(struct i2c_client *client)
dev_dbg(&client->dev, "%s\n", __func__);
mfd_remove_devices(&client->dev);
- i2c_set_clientdata(client, NULL);
kfree(core);
return 0;
@@ -83,6 +221,12 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,
cell->data_size = sizeof(core);
children++;
+ core->read = wl1273_fm_read_reg;
+ core->write = wl1273_fm_write_cmd;
+ core->write_data = wl1273_fm_write_data;
+ core->set_audio = wl1273_fm_set_audio;
+ core->set_volume = wl1273_fm_set_volume;
+
if (pdata->children & WL1273_CODEC_CHILD) {
cell = &core->cells[children];
@@ -104,7 +248,6 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,
return 0;
err:
- i2c_set_clientdata(client, NULL);
pdata->free_resources();
kfree(core);
diff --git a/include/linux/mfd/wl1273-core.h b/include/linux/mfd/wl1273-core.h
index 9787293eae5f..db2f3f454a1b 100644
--- a/include/linux/mfd/wl1273-core.h
+++ b/include/linux/mfd/wl1273-core.h
@@ -280,7 +280,9 @@ struct wl1273_core {
struct i2c_client *client;
+ int (*read)(struct wl1273_core *core, u8, u16 *);
int (*write)(struct wl1273_core *core, u8, u16);
+ int (*write_data)(struct wl1273_core *core, u8 *, u16);
int (*set_audio)(struct wl1273_core *core, unsigned int);
int (*set_volume)(struct wl1273_core *core, unsigned int);
};
--
cgit v1.2.3
From 140d88165c25137e871f9559e67986ed89251105 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart
Date: Wed, 18 Aug 2010 11:41:22 -0300
Subject: [media] 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
Acked-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
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(+)
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
(limited to 'include/linux')
diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
index c47897f046b1..034f891399ed 100644
--- a/Documentation/DocBook/media-entities.tmpl
+++ b/Documentation/DocBook/media-entities.tmpl
@@ -11,6 +11,10 @@
select()">
write()">
+close()">
+ioctl()">
+open()">
+
VIDIOC_CROPCAP">
VIDIOC_DBG_G_CHIP_IDENT">
@@ -87,6 +91,8 @@
VIDIOC_TRY_FMT">
VIDIOC_UNSUBSCRIBE_EVENT">
+MEDIA_IOC_DEVICE_INFO">
+
v4l2_std_id">
@@ -184,6 +190,8 @@
v4l2_vbi_format">
v4l2_window">
+media_device_info">
+
EACCES error code">
EAGAIN error code">
@@ -328,6 +336,10 @@
+
+
+
+
diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml
index f89228d3ec2a..a46b786e9f2b 100644
--- a/Documentation/DocBook/v4l/media-controller.xml
+++ b/Documentation/DocBook/v4l/media-controller.xml
@@ -74,3 +74,13 @@
pad to a sink pad.
+
+
+ Function Reference
+
+ &sub-media-open;
+ &sub-media-close;
+ &sub-media-ioctl;
+
+ &sub-media-ioc-device-info;
+
diff --git a/Documentation/DocBook/v4l/media-func-close.xml b/Documentation/DocBook/v4l/media-func-close.xml
new file mode 100644
index 000000000000..be149c802aeb
--- /dev/null
+++ b/Documentation/DocBook/v4l/media-func-close.xml
@@ -0,0 +1,59 @@
+
+
+ media close()
+ &manvol;
+
+
+
+ media-close
+ Close a media device
+
+
+
+
+ #include <unistd.h>
+
+ int close
+ int fd
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ &fd;
+
+
+
+
+
+
+ Description
+
+ Closes the media device. Resources associated with the file descriptor
+ are freed. The device configuration remain unchanged.
+
+
+
+ Return Value
+
+ close returns 0 on success. On error, -1 is
+ returned, and errno is set appropriately. Possible error
+ codes are:
+
+
+
+ EBADF
+
+ fd is not a valid open file descriptor.
+
+
+
+
+
+
diff --git a/Documentation/DocBook/v4l/media-func-ioctl.xml b/Documentation/DocBook/v4l/media-func-ioctl.xml
new file mode 100644
index 000000000000..bda8604de15c
--- /dev/null
+++ b/Documentation/DocBook/v4l/media-func-ioctl.xml
@@ -0,0 +1,116 @@
+
+
+ media ioctl()
+ &manvol;
+
+
+
+ media-ioctl
+ Control a media device
+
+
+
+
+ #include <sys/ioctl.h>
+
+ int ioctl
+ int fd
+ int request
+ void *argp
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ &fd;
+
+
+
+ request
+
+ Media ioctl request code as defined in the media.h header file,
+ for example MEDIA_IOC_SETUP_LINK.
+
+
+
+ argp
+
+ Pointer to a request-specific structure.
+
+
+
+
+
+
+ Description
+ The ioctl() function manipulates media device
+ parameters. The argument fd must be an open file
+ descriptor.
+ The ioctl request 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
+ argp in bytes.
+ 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
+ .
+
+
+
+ Return Value
+
+ ioctl() returns 0 on
+ success. On failure, -1 is returned, and the
+ errno variable is set appropriately. Generic error codes
+ are listed below, and request-specific error codes are listed in the
+ individual requests descriptions.
+ When an ioctl that takes an output or read/write parameter fails,
+ the parameter remains unmodified.
+
+
+
+ EBADF
+
+ fd is not a valid open file descriptor.
+
+
+
+
+ EFAULT
+
+ argp references an inaccessible memory
+ area.
+
+
+
+ EINVAL
+
+ The request or the data pointed to by
+ argp is not valid. This is a very common error
+ code, see the individual ioctl requests listed in
+ for actual causes.
+
+
+
+ ENOMEM
+
+ Insufficient kernel memory was available to complete the
+ request.
+
+
+
+ ENOTTY
+
+ fd is not associated with a character
+ special device.
+
+
+
+
+
diff --git a/Documentation/DocBook/v4l/media-func-open.xml b/Documentation/DocBook/v4l/media-func-open.xml
new file mode 100644
index 000000000000..f7df034dc9ed
--- /dev/null
+++ b/Documentation/DocBook/v4l/media-func-open.xml
@@ -0,0 +1,94 @@
+
+
+ media open()
+ &manvol;
+
+
+
+ media-open
+ Open a media device
+
+
+
+
+ #include <fcntl.h>
+
+ int open
+ const char *device_name
+ int flags
+
+
+
+
+
+ Arguments
+
+
+
+ device_name
+
+ Device to be opened.
+
+
+
+ flags
+
+ Open flags. Access mode must be either O_RDONLY
+ or O_RDWR. Other flags have no effect.
+
+
+
+
+
+ Description
+ To open a media device applications call open()
+ with the desired device name. The function has no side effects; the device
+ configuration remain unchanged.
+ When the device is opened in read-only mode, attemps to modify its
+ configuration will result in an error, and errno will be
+ set to EBADF.
+
+
+ Return Value
+
+ open returns the new file descriptor on success.
+ On error, -1 is returned, and errno is set appropriately.
+ Possible error codes are:
+
+
+
+ EACCES
+
+ The requested access to the file is not allowed.
+
+
+
+ EMFILE
+
+ The process already has the maximum number of files open.
+
+
+
+
+ ENFILE
+
+ The system limit on the total number of open files has been
+ reached.
+
+
+
+ ENOMEM
+
+ Insufficient kernel memory was available.
+
+
+
+ ENXIO
+
+ No device corresponding to this device special file exists.
+
+
+
+
+
+
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 000000000000..278a3120ee2e
--- /dev/null
+++ b/Documentation/DocBook/v4l/media-ioc-device-info.xml
@@ -0,0 +1,132 @@
+
+
+ ioctl MEDIA_IOC_DEVICE_INFO
+ &manvol;
+
+
+
+ MEDIA_IOC_DEVICE_INFO
+ Query device information
+
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ struct media_device_info *argp
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ &fd;
+
+
+
+ request
+
+ MEDIA_IOC_DEVICE_INFO
+
+
+
+ argp
+
+
+
+
+
+
+
+
+ Description
+
+ All media devices must support the MEDIA_IOC_DEVICE_INFO
+ 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.
+
+
+ struct media_device_info
+
+ &cs-str;
+
+
+ char
+ driver[16]
+ Name of the driver implementing the media API as a
+ NUL-terminated ASCII string. The driver version is stored in the
+ driver_version field.
+ 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.
+
+
+ char
+ model[32]
+ Device model name as a NUL-terminated UTF-8 string. The
+ device version is stored in the device_version
+ field and is not be appended to the model name.
+
+
+ char
+ serial[40]
+ Serial number as a NUL-terminated ASCII string.
+
+
+ char
+ bus_info[32]
+ 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.
+
+
+ __u32
+ media_version
+ Media API version, formatted with the
+ KERNEL_VERSION() macro.
+
+
+ __u32
+ hw_revision
+ Hardware device revision in a driver-specific format.
+
+
+ __u32
+ media_version
+ Media device driver version, formatted with the
+ KERNEL_VERSION() macro. Together with the
+ driver field this identifies a particular
+ driver.
+
+
+ __u32
+ reserved[31]
+ Reserved for future extensions. Drivers and applications must
+ set this array to zero.
+
+
+
+
+ The serial and bus_info
+ 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
+ bus_info field can be used instead. The
+ bus_info field is guaranteed to be unique, but
+ can vary across reboots or device unplug/replug.
+
+
+
+ Return value
+ This function doesn't return specific error codes.
+
+
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index d2bc809d7a2a..92e0d4eb84b8 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -22,13 +22,70 @@
#include
#include
+#include
#include
#include
#include
+/* -----------------------------------------------------------------------------
+ * 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 b0ada6f37dd6..31eb174a2267 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -233,6 +233,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 000000000000..64090db3c1fc
--- /dev/null
+++ b/include/linux/media.h
@@ -0,0 +1,45 @@
+/*
+ * Multimedia device API
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Contacts: Laurent Pinchart
+ * Sakari Ailus
+ *
+ * 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
+#include
+#include
+
+#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 */
--
cgit v1.2.3
From 1651333b09743887bc2dd3d158a11853a2be3fe7 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart
Date: Wed, 9 Dec 2009 08:40:01 -0300
Subject: [media] 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
Signed-off-by: Sakari Ailus
Acked-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
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
(limited to 'include/linux')
diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
index 034f891399ed..2bd7b27f8553 100644
--- a/Documentation/DocBook/media-entities.tmpl
+++ b/Documentation/DocBook/media-entities.tmpl
@@ -92,6 +92,8 @@
VIDIOC_UNSUBSCRIBE_EVENT">
MEDIA_IOC_DEVICE_INFO">
+MEDIA_IOC_ENUM_ENTITIES">
+MEDIA_IOC_ENUM_LINKS">
v4l2_std_id">
@@ -191,6 +193,10 @@
v4l2_window">
media_device_info">
+media_entity_desc">
+media_links_enum">
+media_pad_desc">
+media_link_desc">
EACCES error code">
@@ -340,6 +346,8 @@
+
+
diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml
index a46b786e9f2b..2c4fd2b27683 100644
--- a/Documentation/DocBook/v4l/media-controller.xml
+++ b/Documentation/DocBook/v4l/media-controller.xml
@@ -83,4 +83,6 @@
&sub-media-ioctl;
&sub-media-ioc-device-info;
+ &sub-media-ioc-enum-entities;
+ &sub-media-ioc-enum-links;
diff --git a/Documentation/DocBook/v4l/media-ioc-device-info.xml b/Documentation/DocBook/v4l/media-ioc-device-info.xml
index 278a3120ee2e..1f3237351bba 100644
--- a/Documentation/DocBook/v4l/media-ioc-device-info.xml
+++ b/Documentation/DocBook/v4l/media-ioc-device-info.xml
@@ -27,7 +27,8 @@
fd
- &fd;
+ File descriptor returned by
+ open().
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 000000000000..13d0cc44865a
--- /dev/null
+++ b/Documentation/DocBook/v4l/media-ioc-enum-entities.xml
@@ -0,0 +1,308 @@
+
+
+ ioctl MEDIA_IOC_ENUM_ENTITIES
+ &manvol;
+
+
+
+ MEDIA_IOC_ENUM_ENTITIES
+ Enumerate entities and their properties
+
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ struct media_entity_desc *argp
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ File descriptor returned by
+ open().
+
+
+
+ request
+
+ MEDIA_IOC_ENUM_ENTITIES
+
+
+
+ argp
+
+
+
+
+
+
+
+
+ Description
+ 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.
+ Entities can be enumerated by or'ing the id with the
+ MEDIA_ENT_ID_FLAG_NEXT 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.
+ Entity IDs can be non-contiguous. Applications must
+ not try to enumerate entities by calling
+ MEDIA_IOC_ENUM_ENTITIES with increasing id's until they get an error.
+ Two or more entities that share a common non-zero
+ group_id value are considered as logically
+ grouped. Groups are used to report
+
+ ALSA, VBI and video nodes that carry the same media
+ stream
+ lens and flash controllers associated with a sensor
+
+
+
+
+ struct media_entity_desc
+
+
+
+
+
+
+
+
+ __u32
+ id
+
+
+ Entity id, set by the application. When the id is or'ed with
+ MEDIA_ENT_ID_FLAG_NEXT, the driver clears the
+ flag and returns the first entity with a larger id.
+
+
+ char
+ name[32]
+
+
+ Entity name as an UTF-8 NULL-terminated string.
+
+
+ __u32
+ type
+
+
+ Entity type, see for details.
+
+
+ __u32
+ revision
+
+
+ Entity revision in a driver/hardware specific format.
+
+
+ __u32
+ flags
+
+
+ Entity flags, see for details.
+
+
+ __u32
+ group_id
+
+
+ Entity group ID
+
+
+ __u16
+ pads
+
+
+ Number of pads
+
+
+ __u16
+ links
+
+
+ Total number of outbound links. Inbound links are not counted
+ in this field.
+
+
+ union
+
+
+
+ struct
+ v4l
+
+ Valid for V4L sub-devices and nodes only.
+
+
+
+
+ __u32
+ major
+ V4L device node major number. For V4L sub-devices with no
+ device node, set by the driver to 0.
+
+
+
+
+ __u32
+ minor
+ V4L device node minor number. For V4L sub-devices with no
+ device node, set by the driver to 0.
+
+
+
+ struct
+ fb
+
+ Valid for frame buffer nodes only.
+
+
+
+
+ __u32
+ major
+ Frame buffer device node major number.
+
+
+
+
+ __u32
+ minor
+ Frame buffer device node minor number.
+
+
+
+ struct
+ alsa
+
+ Valid for ALSA devices only.
+
+
+
+
+ __u32
+ card
+ ALSA card number
+
+
+
+
+ __u32
+ device
+ ALSA device number
+
+
+
+
+ __u32
+ subdevice
+ ALSA sub-device number
+
+
+
+ int
+ dvb
+
+ DVB card number
+
+
+
+ __u8
+ raw[180]
+
+
+
+
+
+
+ Media entity flags
+
+
+
+
+
+ MEDIA_ENT_FL_DEFAULT
+ Default entity for its type. Used to discover the default
+ audio, VBI and video devices, the default camera sensor, ...
+
+
+
+
+
+
+
+ &return-value;
+
+
+
+ EINVAL
+
+ The &media-entity-desc; id references
+ a non-existing entity.
+
+
+
+
+
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 000000000000..6da884159cab
--- /dev/null
+++ b/Documentation/DocBook/v4l/media-ioc-enum-links.xml
@@ -0,0 +1,202 @@
+
+
+ ioctl MEDIA_IOC_ENUM_LINKS
+ &manvol;
+
+
+
+ MEDIA_IOC_ENUM_LINKS
+ Enumerate all pads and links for a given entity
+
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ struct media_links_enum *argp
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ File descriptor returned by
+ open().
+
+
+
+ request
+
+ MEDIA_IOC_ENUM_LINKS
+
+
+
+ argp
+
+
+
+
+
+
+
+
+ Description
+
+ 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
+ pads and links fields.
+ They then call the MEDIA_IOC_ENUM_LINKS ioctl with a pointer to this
+ structure.
+ If the pads field is not NULL, the driver
+ fills the pads 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.
+ If the links field is not NULL, the driver
+ fills the links 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.
+ Only forward links that originate at one of the entity's source pads
+ are returned during the enumeration process.
+
+
+ struct media_links_enum
+
+ &cs-str;
+
+
+ __u32
+ entity
+ Entity id, set by the application.
+
+
+ struct &media-pad-desc;
+ *pads
+ Pointer to a pads array allocated by the application. Ignored
+ if NULL.
+
+
+ struct &media-link-desc;
+ *links
+ Pointer to a links array allocated by the application. Ignored
+ if NULL.
+
+
+
+
+
+
+ struct media_pad_desc
+
+ &cs-str;
+
+
+ __u32
+ entity
+ ID of the entity this pad belongs to.
+
+
+ __u16
+ index
+ 0-based pad index.
+
+
+ __u32
+ flags
+ Pad flags, see for more details.
+
+
+
+
+
+
+ Media pad flags
+
+
+
+
+
+ MEDIA_PAD_FL_SINK
+ Input pad, relative to the entity. Input pads sink data and
+ are targets of links.
+
+
+ MEDIA_PAD_FL_SOURCE
+ Output pad, relative to the entity. Output pads source data
+ and are origins of links.
+
+
+
+
+
+
+ struct media_links_desc
+
+ &cs-str;
+
+
+ struct &media-pad-desc;
+ source
+ Pad at the origin of this link.
+
+
+ struct &media-pad-desc;
+ sink
+ Pad at the target of this link.
+
+
+ __u32
+ flags
+ Link flags, see for more details.
+
+
+
+
+
+
+ Media link flags
+
+
+
+
+
+ MEDIA_LNK_FL_ENABLED
+ 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
+ The link enabled state can't be modified at runtime. An
+ immutable link is always enabled.
+
+
+
+
+ One and only one of MEDIA_PAD_FL_SINK and
+ MEDIA_PAD_FL_SOURCE must be set for every pad.
+
+
+
+ &return-value;
+
+
+
+ EINVAL
+
+ The &media-links-enum; id references
+ a non-existing entity.
+
+
+
+
+
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 92e0d4eb84b8..648a9d892ac1 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 64090db3c1fc..17c93a413677 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_SINK (1 << 0)
+#define MEDIA_PAD_FL_SOURCE (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 a9b31d98e3c6..51bdafce72c7 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -24,29 +24,7 @@
#define _MEDIA_ENTITY_H
#include
-
-#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)
-
-#define MEDIA_LNK_FL_ENABLED (1 << 0)
-#define MEDIA_LNK_FL_IMMUTABLE (1 << 1)
-
-#define MEDIA_PAD_FL_SINK (1 << 0)
-#define MEDIA_PAD_FL_SOURCE (1 << 1)
+#include
struct media_link {
struct media_pad *source; /* Source pad */
--
cgit v1.2.3
From 97548ed4c4661502cdfd1aabd5d3876fa4f5cc2e Mon Sep 17 00:00:00 2001
From: Laurent Pinchart
Date: Wed, 9 Dec 2009 08:40:03 -0300
Subject: [media] 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
Signed-off-by: Stanimir Varbanov
Signed-off-by: Sakari Ailus
Acked-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
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(+)
create mode 100644 Documentation/DocBook/v4l/media-ioc-setup-link.xml
(limited to 'include/linux')
diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
index 2bd7b27f8553..121db1549244 100644
--- a/Documentation/DocBook/media-entities.tmpl
+++ b/Documentation/DocBook/media-entities.tmpl
@@ -94,6 +94,7 @@
MEDIA_IOC_DEVICE_INFO">
MEDIA_IOC_ENUM_ENTITIES">
MEDIA_IOC_ENUM_LINKS">
+MEDIA_IOC_SETUP_LINK">
v4l2_std_id">
@@ -348,6 +349,7 @@
+
diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml
index 2c4fd2b27683..2dc25e1d4089 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;
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 000000000000..09ab3d2b3a52
--- /dev/null
+++ b/Documentation/DocBook/v4l/media-ioc-setup-link.xml
@@ -0,0 +1,90 @@
+
+
+ ioctl MEDIA_IOC_SETUP_LINK
+ &manvol;
+
+
+
+ MEDIA_IOC_SETUP_LINK
+ Modify the properties of a link
+
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ struct media_link_desc *argp
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ File descriptor returned by
+ open().
+
+
+
+ request
+
+ MEDIA_IOC_ENUM_LINKS
+
+
+
+ argp
+
+
+
+
+
+
+
+
+ Description
+
+ 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.
+ 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.
+
+ 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;.
+ If the specified link can't be found the driver returns with an
+ &EINVAL;.
+
+
+
+ &return-value;
+
+
+
+ EBUSY
+
+ 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.
+
+
+
+ EINVAL
+
+ The &media-link-desc; references a non-existing link, or the
+ link is immutable and an attempt to modify its configuration was made.
+
+
+
+
+
+
diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt
index 78ae02095372..4809221c0ff9 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 648a9d892ac1..16b70b4412f7 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 3e7e2d569cec..6795c920d460 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 17c93a413677..7c69913c0ad2 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 5d2bff4fc9e0..6a27d916c250 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 51bdafce72c7..d889dcc67d0d 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 */
+
/* Reference counts must never be negative, but are signed integers on
* purpose: a simple WARN_ON(<0) check can be used to detect reference
* count bugs that would make them negative.
@@ -112,6 +120,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);
@@ -121,4 +134,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
--
cgit v1.2.3
From e02188c90f6ef61f0844c42508fe603c5d4fa42b Mon Sep 17 00:00:00 2001
From: Laurent Pinchart
Date: Wed, 25 Aug 2010 09:00:41 -0300
Subject: [media] 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
Acked-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
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(+)
(limited to 'include/linux')
diff --git a/Documentation/DocBook/v4l/media-ioc-enum-links.xml b/Documentation/DocBook/v4l/media-ioc-enum-links.xml
index 6da884159cab..d2fc73ef8d56 100644
--- a/Documentation/DocBook/v4l/media-ioc-enum-links.xml
+++ b/Documentation/DocBook/v4l/media-ioc-enum-links.xml
@@ -179,6 +179,11 @@
The link enabled state can't be modified at runtime. An
immutable link is always enabled.
+
+ MEDIA_LNK_FL_DYNAMIC
+ The link enabled state can be modified during streaming. This
+ flag is set by drivers and is read-only for applications.
+
diff --git a/Documentation/DocBook/v4l/media-ioc-setup-link.xml b/Documentation/DocBook/v4l/media-ioc-setup-link.xml
index 09ab3d2b3a52..2331e76ded17 100644
--- a/Documentation/DocBook/v4l/media-ioc-setup-link.xml
+++ b/Documentation/DocBook/v4l/media-ioc-setup-link.xml
@@ -60,6 +60,9 @@
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;.
+ Only links marked with the DYNAMIC link flag can
+ be enabled/disabled while streaming media data. Attempting to enable or
+ disable a streaming non-dynamic link will return an &EBUSY;.If the specified link can't be found the driver returns with an
&EINVAL;.
diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt
index 4809221c0ff9..fd48add02cb0 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 6795c920d460..23640ed44d85 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -196,6 +196,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 7c69913c0ad2..7ed23b43f43b 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 d889dcc67d0d..cd8bca63a502 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -26,6 +26,9 @@
#include
#include
+struct media_pipeline {
+};
+
struct media_link {
struct media_pad *source; /* Source pad */
struct media_pad *sink; /* Sink pad */
@@ -71,8 +74,11 @@ struct media_entity {
* purpose: a simple WARN_ON(<0) check can be used to detect reference
* count bugs that would make them negative.
*/
+ 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 {
@@ -118,6 +124,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);
@@ -133,6 +140,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) ? \
--
cgit v1.2.3
From 2ef2d5a336891ee38fee7c7ad2396e31ac9d8aaa Mon Sep 17 00:00:00 2001
From: Laurent Pinchart
Date: Mon, 15 Mar 2010 19:33:31 -0300
Subject: [media] 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
Acked-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
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
(limited to 'include/linux')
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 31eb174a2267..c33f22a6a404 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -371,6 +371,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 += videodev2.h
diff --git a/include/linux/v4l2-mediabus.h b/include/linux/v4l2-mediabus.h
new file mode 100644
index 000000000000..a62cd64e8462
--- /dev/null
+++ b/include/linux/v4l2-mediabus.h
@@ -0,0 +1,78 @@
+/*
+ * Media Bus API header
+ *
+ * Copyright (C) 2009, Guennadi Liakhovetski
+ *
+ * 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
+#include
+
+/*
+ * 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 f5522b3f175a..b338108ec305 100644
--- a/include/media/soc_mediabus.h
+++ b/include/media/soc_mediabus.h
@@ -12,8 +12,7 @@
#define SOC_MEDIABUS_H
#include
-
-#include
+#include
/**
* 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 8e6559838ae3..971c7fa29614 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
static inline void v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt,
const struct v4l2_mbus_framefmt *mbus_fmt)
--
cgit v1.2.3
From 84d0688dfc7eedb2147532bf52ff7073d5c3c7b9 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart
Date: Wed, 6 Oct 2010 03:30:26 -0300
Subject: [media] 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
Acked-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
include/linux/v4l2-mediabus.h | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
(limited to 'include/linux')
diff --git a/include/linux/v4l2-mediabus.h b/include/linux/v4l2-mediabus.h
index a62cd64e8462..feeb88cf705e 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
--
cgit v1.2.3
From 076704332ca6da550cbc279918ef8b88b4ac1e45 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart
Date: Tue, 28 Sep 2010 07:01:44 -0300
Subject: [media] 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
Acked-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
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(-)
(limited to 'include/linux')
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index f7fc88d240e6..e2bbd8c35c98 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 6a784c87e5ff..e313d8390092 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 cf93de988068..fe8e3ebd9ce4 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 84a646819318..dd1b81b1442b 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 73b4138709e4..ed77aa055b63 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 feeb88cf705e..dc1d5c0432d4 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,
--
cgit v1.2.3
From dacdde78b39e49edf2f7af85be4b613978280b26 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart
Date: Wed, 1 Sep 2010 12:58:22 -0300
Subject: [media] 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
Acked-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
include/linux/v4l2-mediabus.h | 77 ++++++++++++++++++++++++++-----------------
1 file changed, 46 insertions(+), 31 deletions(-)
(limited to 'include/linux')
diff --git a/include/linux/v4l2-mediabus.h b/include/linux/v4l2-mediabus.h
index dc1d5c0432d4..cccfa34bab1f 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,
};
/**
--
cgit v1.2.3
From 333c8b97785d5afd5085ba3720b4d259623290f6 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart
Date: Mon, 15 Mar 2010 20:26:04 -0300
Subject: [media] v4l: v4l2_subdev userspace format API
Add a userspace API to get, set and enumerate the media format on a
subdev pad.
The format at the output of a subdev usually depends on the format at
its input(s). The try format operation is thus not suitable for probing
format at individual pads, as it can't modify the device state and thus
can't remember the format tried at the input to compute the output
format.
To fix the problem, pass an extra argument to the get/set format
operations to select the 'try' or 'active' format.
The try format is used when probing the subdev. Setting the try format
must not change the device configuration but can store data for later
reuse. Data storage is provided at the file-handle level so applications
probing the subdev concurently won't interfere with each other.
The active format is used when configuring the subdev. It's identical to
the format handled by the usual get/set operations.
Signed-off-by: Laurent Pinchart
Signed-off-by: Stanimir Varbanov
Signed-off-by: Sakari Ailus
Acked-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
Documentation/DocBook/Makefile | 5 +-
Documentation/DocBook/media-entities.tmpl | 16 +
Documentation/DocBook/v4l/dev-subdev.xml | 280 +++
Documentation/DocBook/v4l/subdev-formats.xml | 2416 ++++++++++++++++++++
Documentation/DocBook/v4l/v4l2.xml | 4 +
Documentation/DocBook/v4l/vidioc-streamon.xml | 9 +
.../DocBook/v4l/vidioc-subdev-enum-frame-size.xml | 154 ++
.../DocBook/v4l/vidioc-subdev-enum-mbus-code.xml | 119 +
Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml | 180 ++
drivers/media/video/v4l2-subdev.c | 49 +
include/linux/Kbuild | 1 +
include/linux/v4l2-subdev.h | 90 +
include/media/v4l2-subdev.h | 10 +
13 files changed, 3332 insertions(+), 1 deletion(-)
create mode 100644 Documentation/DocBook/v4l/dev-subdev.xml
create mode 100644 Documentation/DocBook/v4l/subdev-formats.xml
create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml
create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml
create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml
create mode 100644 include/linux/v4l2-subdev.h
(limited to 'include/linux')
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 8b6e00a71034..2deb069aedf1 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -53,7 +53,10 @@ MAN := $(patsubst %.xml, %.9, $(BOOKS))
mandocs: $(MAN)
build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \
- cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(objtree)/Documentation/DocBook/media/
+ cp $(srctree)/Documentation/DocBook/dvb/*.png \
+ $(srctree)/Documentation/DocBook/v4l/*.gif \
+ $(srctree)/Documentation/DocBook/v4l/*.png \
+ $(objtree)/Documentation/DocBook/media/
xmldoclinks:
ifneq ($(objtree),$(srctree))
diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
index 121db1549244..dbb9cb2e1ec6 100644
--- a/Documentation/DocBook/media-entities.tmpl
+++ b/Documentation/DocBook/media-entities.tmpl
@@ -86,6 +86,10 @@
VIDIOC_S_PRIORITY">
VIDIOC_S_STD">
VIDIOC_S_TUNER">
+VIDIOC_SUBDEV_ENUM_FRAME_SIZE">
+VIDIOC_SUBDEV_ENUM_MBUS_CODE">
+VIDIOC_SUBDEV_G_FMT">
+VIDIOC_SUBDEV_S_FMT">
VIDIOC_TRY_ENCODER_CMD">
VIDIOC_TRY_EXT_CTRLS">
VIDIOC_TRY_FMT">
@@ -107,6 +111,7 @@
v4l2_field">
v4l2_frmivaltypes">
v4l2_frmsizetypes">
+v4l2_mbus_pixelcode">
v4l2_memory">
v4l2_mpeg_audio_ac3_bitrate">
v4l2_mpeg_audio_crc">
@@ -130,6 +135,7 @@
v4l2_mpeg_video_encoding">
v4l2_power_line_frequency">
v4l2_priority">
+v4l2_subdev_format_whence">
v4l2_tuner_type">
v4l2_preemphasis">
@@ -172,6 +178,7 @@
v4l2_hw_freq_seek">
v4l2_input">
v4l2_jpegcompression">
+v4l2_mbus_framefmt">
v4l2_modulator">
v4l2_mpeg_vbi_fmt_ivtv">
v4l2_output">
@@ -186,6 +193,9 @@
v4l2_sliced_vbi_cap">
v4l2_sliced_vbi_data">
v4l2_sliced_vbi_format">
+v4l2_subdev_frame_size_enum">
+v4l2_subdev_format">
+v4l2_subdev_mbus_code_enum">
v4l2_standard">
v4l2_streamparm">
v4l2_timecode">
@@ -215,6 +225,7 @@
ENXIO error code">
EMFILE error code">
EPERM error code">
+EPIPE error code">
ERANGE error code">
@@ -234,6 +245,7 @@
+
@@ -319,6 +331,10 @@
+
+
+
+
diff --git a/Documentation/DocBook/v4l/dev-subdev.xml b/Documentation/DocBook/v4l/dev-subdev.xml
new file mode 100644
index 000000000000..fc62e65f45ef
--- /dev/null
+++ b/Documentation/DocBook/v4l/dev-subdev.xml
@@ -0,0 +1,280 @@
+ Sub-device Interface
+
+
+ Experimental
+ This is an experimental
+ interface and may change in the future.
+
+
+ The complex nature of V4L2 devices, where hardware is often made of
+ several integrated circuits that need to interact with each other in a
+ controlled way, leads to complex V4L2 drivers. The drivers usually reflect
+ the hardware model in software, and model the different hardware components
+ as software blocks called sub-devices.
+
+ V4L2 sub-devices are usually kernel-only objects. If the V4L2 driver
+ implements the media device API, they will automatically inherit from media
+ entities. Applications will be able to enumerate the sub-devices and discover
+ the hardware topology using the media entities, pads and links enumeration
+ API.
+
+ In addition to make sub-devices discoverable, drivers can also choose
+ to make them directly configurable by applications. When both the sub-device
+ driver and the V4L2 device driver support this, sub-devices will feature a
+ character device node on which ioctls can be called to
+
+ query, read and write sub-devices controls
+ subscribe and unsubscribe to events and retrieve them
+ negotiate image formats on individual pads
+
+
+
+ Sub-device character device nodes, conventionally named
+ /dev/v4l-subdev*, use major number 81.
+
+
+ Controls
+ Most V4L2 controls are implemented by sub-device hardware. Drivers
+ usually merge all controls and expose them through video device nodes.
+ Applications can control all sub-devices through a single interface.
+
+ Complex devices sometimes implement the same control in different
+ pieces of hardware. This situation is common in embedded platforms, where
+ both sensors and image processing hardware implement identical functions,
+ such as contrast adjustment, white balance or faulty pixels correction. As
+ the V4L2 controls API doesn't support several identical controls in a single
+ device, all but one of the identical controls are hidden.
+
+ Applications can access those hidden controls through the sub-device
+ node with the V4L2 control API described in . The
+ ioctls behave identically as when issued on V4L2 device nodes, with the
+ exception that they deal only with controls implemented in the sub-device.
+
+
+ Depending on the driver, those controls might also be exposed through
+ one (or several) V4L2 device nodes.
+
+
+
+ Events
+ V4L2 sub-devices can notify applications of events as described in
+ . The API behaves identically as when used on V4L2
+ device nodes, with the exception that it only deals with events generated by
+ the sub-device. Depending on the driver, those events might also be reported
+ on one (or several) V4L2 device nodes.
+
+
+
+ Pad-level Formats
+
+ Pad-level formats are only applicable to very complex device that
+ need to expose low-level format configuration to user space. Generic V4L2
+ applications do not need to use the API described in
+ this section.
+
+ For the purpose of this section, the term
+ format means the combination of media bus data
+ format, frame width and frame height.
+
+ Image formats are typically negotiated on video capture and output
+ devices using the cropping and scaling ioctls.
+ The driver is responsible for configuring every block in the video pipeline
+ according to the requested format at the pipeline input and/or
+ output.
+
+ For complex devices, such as often found in embedded systems,
+ identical image sizes at the output of a pipeline can be achieved using
+ different hardware configurations. One such exemple is shown on
+ , where
+ image scaling can be performed on both the video sensor and the host image
+ processing hardware.
+
+
+ Image Format Negotation on Pipelines
+
+
+
+
+
+
+
+
+ High quality and high speed pipeline configuration
+
+
+
+
+ The sensor scaler is usually of less quality than the host scaler, but
+ scaling on the sensor is required to achieve higher frame rates. Depending
+ on the use case (quality vs. speed), the pipeline must be configured
+ differently. Applications need to configure the formats at every point in
+ the pipeline explicitly.
+
+ Drivers that implement the media
+ API can expose pad-level image format configuration to applications.
+ When they do, applications can use the &VIDIOC-SUBDEV-G-FMT; and
+ &VIDIOC-SUBDEV-S-FMT; ioctls. to negotiate formats on a per-pad basis.
+
+ Applications are responsible for configuring coherent parameters on
+ the whole pipeline and making sure that connected pads have compatible
+ formats. The pipeline is checked for formats mismatch at &VIDIOC-STREAMON;
+ time, and an &EPIPE; is then returned if the configuration is
+ invalid.
+
+ Pad-level image format configuration support can be tested by calling
+ the &VIDIOC-SUBDEV-G-FMT; ioctl on pad 0. If the driver returns an &EINVAL;
+ pad-level format configuration is not supported by the sub-device.
+
+
+ Format Negotiation
+
+ Acceptable formats on pads can (and usually do) depend on a number
+ of external parameters, such as formats on other pads, active links, or
+ even controls. Finding a combination of formats on all pads in a video
+ pipeline, acceptable to both application and driver, can't rely on formats
+ enumeration only. A format negotiation mechanism is required.
+
+ Central to the format negotiation mechanism are the get/set format
+ operations. When called with the which argument
+ set to V4L2_SUBDEV_FORMAT_TRY, the
+ &VIDIOC-SUBDEV-G-FMT; and &VIDIOC-SUBDEV-S-FMT; ioctls operate on a set of
+ formats parameters that are not connected to the hardware configuration.
+ Modifying those 'try' formats leaves the device state untouched (this
+ applies to both the software state stored in the driver and the hardware
+ state stored in the device itself).
+
+ While not kept as part of the device state, try formats are stored
+ in the sub-device file handles. A &VIDIOC-SUBDEV-G-FMT; call will return
+ the last try format set on the same sub-device file
+ handle. Several applications querying the same sub-device at
+ the same time will thus not interact with each other.
+
+ To find out whether a particular format is supported by the device,
+ applications use the &VIDIOC-SUBDEV-S-FMT; ioctl. Drivers verify and, if
+ needed, change the requested format based on
+ device requirements and return the possibly modified value. Applications
+ can then choose to try a different format or accept the returned value and
+ continue.
+
+ Formats returned by the driver during a negotiation iteration are
+ guaranteed to be supported by the device. In particular, drivers guarantee
+ that a returned format will not be further changed if passed to an
+ &VIDIOC-SUBDEV-S-FMT; call as-is (as long as external parameters, such as
+ formats on other pads or links' configuration are not changed).
+
+ Drivers automatically propagate formats inside sub-devices. When a
+ try or active format is set on a pad, corresponding formats on other pads
+ of the same sub-device can be modified by the driver. Drivers are free to
+ modify formats as required by the device. However, they should comply with
+ the following rules when possible:
+
+ Formats should be propagated from sink pads to source pads.
+ Modifying a format on a source pad should not modify the format on any
+ sink pad.
+ Sub-devices that scale frames using variable scaling factors
+ should reset the scale factors to default values when sink pads formats
+ are modified. If the 1:1 scaling ratio is supported, this means that
+ source pads formats should be reset to the sink pads formats.
+
+
+
+ Formats are not propagated across links, as that would involve
+ propagating them from one sub-device file handle to another. Applications
+ must then take care to configure both ends of every link explicitly with
+ compatible formats. Identical formats on the two ends of a link are
+ guaranteed to be compatible. Drivers are free to accept different formats
+ matching device requirements as being compatible.
+
+
+ shows a sample configuration sequence for the pipeline described in
+ (table
+ columns list entity names and pad numbers).
+
+
+
+
+
+ Initial state. The sensor output is set to its native 3MP
+ resolution. Resolutions on the host frontend and scaler input and output
+ pads are undefined.
+ The application configures the frontend input pad resolution to
+ 2048x1536. The driver propagates the format to the frontend output pad.
+ Note that the propagated output format can be different, as in this case,
+ than the input format, as the hardware might need to crop pixels (for
+ instance when converting a Bayer filter pattern to RGB or YUV).
+ The application configures the scaler input pad resolution to
+ 2046x1534 to match the frontend output resolution. The driver propagates
+ the format to the scaler output pad.
+ The application configures the scaler output pad resolution to
+ 1280x960.
+
+
+
+ When satisfied with the try results, applications can set the active
+ formats by setting the which argument to
+ V4L2_SUBDEV_FORMAT_TRY. Active formats are changed
+ exactly as try formats by drivers. To avoid modifying the hardware state
+ during format negotiation, applications should negotiate try formats first
+ and then modify the active settings using the try formats returned during
+ the last negotiation iteration. This guarantees that the active format
+ will be applied as-is by the driver without being modified.
+
+
+
+
+
+ &sub-subdev-formats;
diff --git a/Documentation/DocBook/v4l/subdev-formats.xml b/Documentation/DocBook/v4l/subdev-formats.xml
new file mode 100644
index 000000000000..0cae57207006
--- /dev/null
+++ b/Documentation/DocBook/v4l/subdev-formats.xml
@@ -0,0 +1,2416 @@
+
+ Media Bus Formats
+
+
+ struct v4l2_mbus_framefmt
+
+ &cs-str;
+
+
+ __u32
+ width
+ Image width, in pixels.
+
+
+ __u32
+ height
+ Image height, in pixels.
+
+
+ __u32
+ code
+ Format code, from &v4l2-mbus-pixelcode;.
+
+
+ __u32
+ field
+ Field order, from &v4l2-field;. See
+ for details.
+
+
+ __u32
+ colorspace
+ Image colorspace, from &v4l2-colorspace;. See
+ for details.
+
+
+ __u32
+ reserved[7]
+ Reserved for future extensions. Applications and drivers must
+ set the array to zero.
+
+
+
+
+
+
+ Media Bus Pixel Codes
+
+ The media bus pixel codes describe image formats as flowing over
+ physical busses (both between separate physical components and inside SoC
+ devices). This should not be confused with the V4L2 pixel formats that
+ describe, using four character codes, image formats as stored in memory.
+
+
+ While there is a relationship between image formats on busses and
+ image formats in memory (a raw Bayer image won't be magically converted to
+ JPEG just by storing it to memory), there is no one-to-one correspondance
+ between them.
+
+
+ Packed RGB Formats
+
+ Those formats transfer pixel data as red, green and blue components.
+ The format code is made of the following information.
+
+ The red, green and blue components order code, as encoded in a
+ pixel sample. Possible values are RGB and BGR.
+ The number of bits per component, for each component. The values
+ can be different for all components. Common values are 555 and 565.
+
+ The number of bus samples per pixel. Pixels that are wider than
+ the bus width must be transferred in multiple samples. Common values are
+ 1 and 2.
+ The bus width.
+ For formats where the total number of bits per pixel is smaller
+ than the number of bus samples per pixel times the bus width, a padding
+ value stating if the bytes are padded in their most high order bits
+ (PADHI) or low order bits (PADLO).
+ For formats where the number of bus samples per pixel is larger
+ than 1, an endianness value stating if the pixel is transferred MSB first
+ (BE) or LSB first (LE).
+
+
+
+ For instance, a format where pixels are encoded as 5-bits red, 5-bits
+ green and 5-bit blue values padded on the high bit, transferred as 2 8-bit
+ samples per pixel with the most significant bits (padding, red and half of
+ the green value) transferred first will be named
+ V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE.
+
+
+ The following tables list existing packet RGB formats.
+
+
+
+
+
+ Bayer Formats
+
+ Those formats transfer pixel data as red, green and blue components.
+ The format code is made of the following information.
+
+ The red, green and blue components order code, as encoded in a
+ pixel sample. The possible values are shown in .
+ The number of bits per pixel component. All components are
+ transferred on the same number of bits. Common values are 8, 10 and 12.
+
+ If the pixel components are DPCM-compressed, a mention of the
+ DPCM compression and the number of bits per compressed pixel component.
+
+ The number of bus samples per pixel. Pixels that are wider than
+ the bus width must be transferred in multiple samples. Common values are
+ 1 and 2.
+ The bus width.
+ For formats where the total number of bits per pixel is smaller
+ than the number of bus samples per pixel times the bus width, a padding
+ value stating if the bytes are padded in their most high order bits
+ (PADHI) or low order bits (PADLO).
+ For formats where the number of bus samples per pixel is larger
+ than 1, an endianness value stating if the pixel is transferred MSB first
+ (BE) or LSB first (LE).
+
+
+
+ For instance, a format with uncompressed 10-bit Bayer components
+ arranged in a red, green, green, blue pattern transferred as 2 8-bit
+ samples per pixel with the least significant bits transferred first will
+ be named V4L2_MBUS_FMT_SRGGB10_2X8_PADHI_LE.
+
+
+
+ Bayer Patterns
+
+
+
+
+
+
+
+
+ Bayer filter color patterns
+
+
+
+
+ The following table lists existing packet Bayer formats. The data
+ organization is given as an example for the first pixel only.
+
+
+
+
+
+ Packed YUV Formats
+
+ Those data formats transfer pixel data as (possibly downsampled) Y, U
+ and V components. The format code is made of the following information.
+
+ The Y, U and V components order code, as transferred on the
+ bus. Possible values are YUYV, UYVY, YVYU and VYUY.
+ The number of bits per pixel component. All components are
+ transferred on the same number of bits. Common values are 8, 10 and 12.
+
+ The number of bus samples per pixel. Pixels that are wider than
+ the bus width must be transferred in multiple samples. Common values are
+ 1, 1.5 (encoded as 1_5) and 2.
+ The bus width. When the bus width is larger than the number of
+ bits per pixel component, several components are packed in a single bus
+ sample. The components are ordered as specified by the order code, with
+ components on the left of the code transferred in the high order bits.
+ Common values are 8 and 16.
+
+
+
+
+ For instance, a format where pixels are encoded as 8-bit YUV values
+ downsampled to 4:2:2 and transferred as 2 8-bit bus samples per pixel in the
+ U, Y, V, Y order will be named V4L2_MBUS_FMT_UYVY8_2X8.
+
+
+ The following table lisst existing packet YUV formats.
+
+
+
+
+
diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml
index 7859d7d9da39..2ada2f86bb54 100644
--- a/Documentation/DocBook/v4l/v4l2.xml
+++ b/Documentation/DocBook/v4l/v4l2.xml
@@ -439,6 +439,7 @@ and discussions on the V4L mailing list.
&sub-dev-radio; &sub-dev-rds; &sub-dev-event;
+ &sub-dev-subdev;
@@ -506,6 +507,9 @@ and discussions on the V4L mailing list.
&sub-reqbufs;
&sub-s-hw-freq-seek;
&sub-streamon;
+ &sub-subdev-enum-frame-size;
+ &sub-subdev-enum-mbus-code;
+ &sub-subdev-g-fmt;
&sub-subscribe-event;
&sub-mmap;
diff --git a/Documentation/DocBook/v4l/vidioc-streamon.xml b/Documentation/DocBook/v4l/vidioc-streamon.xml
index e42bff1f2c0a..75ed39bf4d2b 100644
--- a/Documentation/DocBook/v4l/vidioc-streamon.xml
+++ b/Documentation/DocBook/v4l/vidioc-streamon.xml
@@ -93,6 +93,15 @@ synchronize with other events.
been allocated (memory mapping) or enqueued (output) yet.
+
+ EPIPE
+
+ The driver implements pad-level format configuration and
+ the pipeline configuration is invalid.
+
+
+
diff --git a/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml
new file mode 100644
index 000000000000..79ce42b7c60c
--- /dev/null
+++ b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml
@@ -0,0 +1,154 @@
+
+
+ ioctl VIDIOC_SUBDEV_ENUM_FRAME_SIZE
+ &manvol;
+
+
+
+ VIDIOC_SUBDEV_ENUM_FRAME_SIZE
+ Enumerate media bus frame sizes
+
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ struct v4l2_subdev_frame_size_enum *
+ argp
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ &fd;
+
+
+
+ request
+
+ VIDIOC_SUBDEV_ENUM_FRAME_SIZE
+
+
+
+ argp
+
+
+
+
+
+
+
+
+ Description
+
+
+ Experimental
+ This is an experimental
+ interface and may change in the future.
+
+
+ This ioctl allows applications to enumerate all frame sizes
+ supported by a sub-device on the given pad for the given media bus format.
+ Supported formats can be retrieved with the &VIDIOC-SUBDEV-ENUM-MBUS-CODE;
+ ioctl.
+
+ To enumerate frame sizes applications initialize the
+ pad, code and
+ index fields of the
+ &v4l2-subdev-mbus-code-enum; and call the
+ VIDIOC_SUBDEV_ENUM_FRAME_SIZE ioctl with a pointer to
+ the structure. Drivers fill the minimum and maximum frame sizes or return
+ an &EINVAL; if one of the input parameters is invalid.
+
+ Sub-devices that only support discrete frame sizes (such as most
+ sensors) will return one or more frame sizes with identical minimum and
+ maximum values.
+
+ Not all possible sizes in given [minimum, maximum] ranges need to be
+ supported. For instance, a scaler that uses a fixed-point scaling ratio
+ might not be able to produce every frame size between the minimum and
+ maximum values. Applications must use the &VIDIOC-SUBDEV-S-FMT; ioctl to
+ try the sub-device for an exact supported frame size.
+
+ Available frame sizes may depend on the current 'try' formats at other
+ pads of the sub-device, as well as on the current active links and the
+ current values of V4L2 controls. See &VIDIOC-SUBDEV-G-FMT; for more
+ information about try formats.
+
+
+ struct v4l2_subdev_frame_size_enum
+
+ &cs-str;
+
+
+ __u32
+ index
+ Number of the format in the enumeration, set by the
+ application.
+
+
+ __u32
+ pad
+ Pad number as reported by the media controller API.
+
+
+ __u32
+ code
+ The media bus format code, as defined in
+ .
+
+
+ __u32
+ min_width
+ Minimum frame width, in pixels.
+
+
+ __u32
+ max_width
+ Maximum frame width, in pixels.
+
+
+ __u32
+ min_height
+ Minimum frame height, in pixels.
+
+
+ __u32
+ max_height
+ Maximum frame height, in pixels.
+
+
+ __u32
+ reserved[9]
+ Reserved for future extensions. Applications and drivers must
+ set the array to zero.
+
+
+
+
+
+
+
+ &return-value;
+
+
+
+ EINVAL
+
+ The &v4l2-subdev-frame-size-enum; pad
+ references a non-existing pad, the code is
+ invalid for the given pad or the index
+ field is out of bounds.
+
+
+
+
+
diff --git a/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml b/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml
new file mode 100644
index 000000000000..a6b3432449f6
--- /dev/null
+++ b/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml
@@ -0,0 +1,119 @@
+
+
+ ioctl VIDIOC_SUBDEV_ENUM_MBUS_CODE
+ &manvol;
+
+
+
+ VIDIOC_SUBDEV_ENUM_MBUS_CODE
+ Enumerate media bus formats
+
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ struct v4l2_subdev_mbus_code_enum *
+ argp
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ &fd;
+
+
+
+ request
+
+ VIDIOC_SUBDEV_ENUM_MBUS_CODE
+
+
+
+ argp
+
+
+
+
+
+
+
+
+ Description
+
+
+ Experimental
+ This is an experimental
+ interface and may change in the future.
+
+
+ To enumerate media bus formats available at a given sub-device pad
+ applications initialize the pad and
+ index fields of &v4l2-subdev-mbus-code-enum; and
+ call the VIDIOC_SUBDEV_ENUM_MBUS_CODE ioctl with a
+ pointer to this structure. Drivers fill the rest of the structure or return
+ an &EINVAL; if either the pad or
+ index are invalid. All media bus formats are
+ enumerable by beginning at index zero and incrementing by one until
+ EINVAL is returned.
+
+ Available media bus formats 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.
+
+
+ struct v4l2_subdev_mbus_code_enum
+
+ &cs-str;
+
+
+ __u32
+ pad
+ Pad number as reported by the media controller API.
+
+
+ __u32
+ index
+ Number of the format in the enumeration, set by the
+ application.
+
+
+ __u32
+ code
+ The media bus format code, as defined in
+ .
+
+
+ __u32
+ reserved[9]
+ Reserved for future extensions. Applications and drivers must
+ set the array to zero.
+
+
+
+
+
+
+
+ &return-value;
+
+
+
+ EINVAL
+
+ The &v4l2-subdev-mbus-code-enum; pad
+ references a non-existing pad, or the index
+ field is out of bounds.
+
+
+
+
+
diff --git a/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml b/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml
new file mode 100644
index 000000000000..f367c570c530
--- /dev/null
+++ b/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml
@@ -0,0 +1,180 @@
+
+
+ ioctl VIDIOC_SUBDEV_G_FMT, VIDIOC_SUBDEV_S_FMT
+ &manvol;
+
+
+
+ VIDIOC_SUBDEV_G_FMT
+ VIDIOC_SUBDEV_S_FMT
+ Get or set the data format on a subdev pad
+
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ struct v4l2_subdev_format *argp
+
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ &fd;
+
+
+
+ request
+
+ VIDIOC_SUBDEV_G_FMT, VIDIOC_SUBDEV_S_FMT
+
+
+
+ argp
+
+
+
+
+
+
+
+
+ Description
+
+
+ Experimental
+ This is an experimental
+ interface and may change in the future.
+
+
+ These ioctls are used to negotiate the frame format at specific
+ subdev pads in the image pipeline.
+
+ To retrieve the current format applications set the
+ pad field of a &v4l2-subdev-format; to the
+ desired pad number as reported by the media API and the
+ which field to
+ V4L2_SUBDEV_FORMAT_ACTIVE. When they call the
+ VIDIOC_SUBDEV_G_FMT ioctl with a pointer to this
+ structure the driver fills the members of the format
+ field.
+
+ To change the current format applications set both the
+ pad and which fields
+ and all members of the format field. When they
+ call the VIDIOC_SUBDEV_S_FMT ioctl with a pointer to this
+ structure the driver verifies the requested format, adjusts it based on the
+ hardware capabilities and configures the device. Upon return the
+ &v4l2-subdev-format; contains the current format as would be returned by a
+ VIDIOC_SUBDEV_G_FMT call.
+
+ Applications can query the device capabilities by setting the
+ which to
+ V4L2_SUBDEV_FORMAT_TRY. When set, 'try' formats are not
+ applied to the device by the driver, but are changed exactly as active
+ formats and stored in the sub-device file handle. Two applications querying
+ the same sub-device would thus not interact with each other.
+
+ For instance, to try a format at the output pad of a sub-device,
+ applications would first set the try format at the sub-device input with the
+ VIDIOC_SUBDEV_S_FMT ioctl. They would then either
+ retrieve the default format at the output pad with the
+ VIDIOC_SUBDEV_G_FMT ioctl, or set the desired output
+ pad format with the VIDIOC_SUBDEV_S_FMT ioctl and check
+ the returned value.
+
+ Try formats do not depend on active formats, but can depend on the
+ current links configuration or sub-device controls value. For instance, a
+ low-pass noise filter might crop pixels at the frame boundaries, modifying
+ its output frame size.
+
+ Drivers must not return an error solely because the requested format
+ doesn't match the device capabilities. They must instead modify the format
+ to match what the hardware can provide. The modified format should be as
+ close as possible to the original request.
+
+
+ struct v4l2_subdev_format
+
+ &cs-str;
+
+
+ __u32
+ pad
+ Pad number as reported by the media controller API.
+
+
+ __u32
+ which
+ Format to modified, from &v4l2-subdev-format-whence;.
+
+
+ &v4l2-mbus-framefmt;
+ format
+ Definition of an image format, see for details.
+
+
+ __u32
+ reserved[8]
+ Reserved for future extensions. Applications and drivers must
+ set the array to zero.
+
+
+
+
+
+
+ enum v4l2_subdev_format_whence
+
+ &cs-def;
+
+
+ V4L2_SUBDEV_FORMAT_TRY
+ 0
+ Try formats, used for querying device capabilities.
+
+
+ V4L2_SUBDEV_FORMAT_ACTIVE
+ 1
+ Active formats, applied to the hardware.
+
+
+
+
+
+
+
+ &return-value;
+
+
+
+ EBUSY
+
+ The format 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
+ VIDIOC_SUBDEV_S_FMT
+
+
+
+ EINVAL
+
+ The &v4l2-subdev-format; pad
+ references a non-existing pad, or the which
+ field references a non-existing format.
+
+
+
+
+
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
index bc763db385df..207cc5cceb29 100644
--- a/drivers/media/video/v4l2-subdev.c
+++ b/drivers/media/video/v4l2-subdev.c
@@ -149,6 +149,9 @@ 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 *vfh = file->private_data;
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+ struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
+#endif
switch (cmd) {
case VIDIOC_QUERYCTRL:
@@ -183,7 +186,53 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_UNSUBSCRIBE_EVENT:
return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg);
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+ case VIDIOC_SUBDEV_G_FMT: {
+ struct v4l2_subdev_format *format = arg;
+
+ if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
+ format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ if (format->pad >= sd->entity.num_pads)
+ return -EINVAL;
+
+ return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh, format);
+ }
+
+ case VIDIOC_SUBDEV_S_FMT: {
+ struct v4l2_subdev_format *format = arg;
+
+ if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
+ format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ if (format->pad >= sd->entity.num_pads)
+ return -EINVAL;
+ return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh, format);
+ }
+
+ case VIDIOC_SUBDEV_ENUM_MBUS_CODE: {
+ struct v4l2_subdev_mbus_code_enum *code = arg;
+
+ if (code->pad >= sd->entity.num_pads)
+ return -EINVAL;
+
+ return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh,
+ code);
+ }
+
+ case VIDIOC_SUBDEV_ENUM_FRAME_SIZE: {
+ struct v4l2_subdev_frame_size_enum *fse = arg;
+
+ if (fse->pad >= sd->entity.num_pads)
+ return -EINVAL;
+
+ return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh,
+ fse);
+ }
+#endif
default:
return -ENOIOCTLCMD;
}
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index c33f22a6a404..43918a34db9f 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -372,6 +372,7 @@ header-y += usbdevice_fs.h
header-y += utime.h
header-y += utsname.h
header-y += v4l2-mediabus.h
+header-y += v4l2-subdev.h
header-y += veth.h
header-y += vhost.h
header-y += videodev2.h
diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h
new file mode 100644
index 000000000000..8dbb44873821
--- /dev/null
+++ b/include/linux/v4l2-subdev.h
@@ -0,0 +1,90 @@
+/*
+ * V4L2 subdev userspace API
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Contacts: Laurent Pinchart
+ * Sakari Ailus
+ *
+ * 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_V4L2_SUBDEV_H
+#define __LINUX_V4L2_SUBDEV_H
+
+#include
+#include
+#include
+
+/**
+ * enum v4l2_subdev_format_whence - Media bus format type
+ * @V4L2_SUBDEV_FORMAT_TRY: try format, for negotiation only
+ * @V4L2_SUBDEV_FORMAT_ACTIVE: active format, applied to the device
+ */
+enum v4l2_subdev_format_whence {
+ V4L2_SUBDEV_FORMAT_TRY = 0,
+ V4L2_SUBDEV_FORMAT_ACTIVE = 1,
+};
+
+/**
+ * struct v4l2_subdev_format - Pad-level media bus format
+ * @which: format type (from enum v4l2_subdev_format_whence)
+ * @pad: pad number, as reported by the media API
+ * @format: media bus format (format code and frame size)
+ */
+struct v4l2_subdev_format {
+ __u32 which;
+ __u32 pad;
+ struct v4l2_mbus_framefmt format;
+ __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
+ * @code: format code (from enum v4l2_mbus_pixelcode)
+ */
+struct v4l2_subdev_mbus_code_enum {
+ __u32 pad;
+ __u32 index;
+ __u32 code;
+ __u32 reserved[9];
+};
+
+/**
+ * struct v4l2_subdev_frame_size_enum - Media bus format enumeration
+ * @pad: pad number, as reported by the media API
+ * @index: format index during enumeration
+ * @code: format code (from enum v4l2_mbus_pixelcode)
+ */
+struct v4l2_subdev_frame_size_enum {
+ __u32 index;
+ __u32 pad;
+ __u32 code;
+ __u32 min_width;
+ __u32 max_width;
+ __u32 min_height;
+ __u32 max_height;
+ __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_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)
+
+#endif
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index d4d3653426a9..4215650151be 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
#include
#include
#include
@@ -414,6 +415,15 @@ struct v4l2_subdev_ir_ops {
};
struct v4l2_subdev_pad_ops {
+ int (*enum_mbus_code)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_mbus_code_enum *code);
+ int (*enum_frame_size)(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_frame_size_enum *fse);
+ 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,
+ struct v4l2_subdev_format *format);
};
struct v4l2_subdev_ops {
--
cgit v1.2.3
From 35c3017a29d278c4405a7f3ab30b814999d156d3 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart
Date: Wed, 5 May 2010 11:38:35 -0300
Subject: [media] 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
Signed-off-by: Sakari Ailus
Acked-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
Documentation/DocBook/media-entities.tmpl | 6 +
Documentation/DocBook/v4l/v4l2.xml | 2 +
.../v4l/vidioc-subdev-enum-frame-interval.xml | 152 +++++++++++++++++++++
.../DocBook/v4l/vidioc-subdev-g-frame-interval.xml | 141 +++++++++++++++++++
drivers/media/video/v4l2-subdev.c | 16 +++
include/linux/v4l2-subdev.h | 36 +++++
include/media/v4l2-subdev.h | 7 +
7 files changed, 360 insertions(+)
create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml
create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml
(limited to 'include/linux')
diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
index dbb9cb2e1ec6..a95eb5783760 100644
--- a/Documentation/DocBook/media-entities.tmpl
+++ b/Documentation/DocBook/media-entities.tmpl
@@ -89,7 +89,9 @@
VIDIOC_SUBDEV_ENUM_FRAME_SIZE">
VIDIOC_SUBDEV_ENUM_MBUS_CODE">
VIDIOC_SUBDEV_G_FMT">
+VIDIOC_SUBDEV_G_FRAME_INTERVAL">
VIDIOC_SUBDEV_S_FMT">
+VIDIOC_SUBDEV_S_FRAME_INTERVAL">
VIDIOC_TRY_ENCODER_CMD">
VIDIOC_TRY_EXT_CTRLS">
VIDIOC_TRY_FMT">
@@ -193,6 +195,8 @@
v4l2_sliced_vbi_cap">
v4l2_sliced_vbi_data">
v4l2_sliced_vbi_format">
+v4l2_subdev_frame_interval">
+v4l2_subdev_frame_interval_enum">
v4l2_subdev_frame_size_enum">
v4l2_subdev_format">
v4l2_subdev_mbus_code_enum">
@@ -331,10 +335,12 @@
+
+
diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml
index 2ada2f86bb54..a436716ef3bc 100644
--- a/Documentation/DocBook/v4l/v4l2.xml
+++ b/Documentation/DocBook/v4l/v4l2.xml
@@ -507,9 +507,11 @@ and discussions on the V4L mailing list.
&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;
&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 000000000000..2f8f4f0a0235
--- /dev/null
+++ b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml
@@ -0,0 +1,152 @@
+
+
+ ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL
+ &manvol;
+
+
+
+ VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL
+ Enumerate frame intervals
+
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ struct v4l2_subdev_frame_interval_enum *
+ argp
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ &fd;
+
+
+
+ request
+
+ VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL
+
+
+
+ argp
+
+
+
+
+
+
+
+
+ Description
+
+
+ Experimental
+ This is an experimental
+ interface and may change in the future.
+
+
+ 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.
+
+ 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.
+
+ To enumerate frame intervals applications initialize the
+ index, pad,
+ code, width and
+ height fields of
+ &v4l2-subdev-frame-interval-enum; and call the
+ VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL 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
+ EINVAL is returned.
+
+ 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.
+
+ 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.
+
+
+ struct v4l2_subdev_frame_interval_enum
+
+ &cs-str;
+
+
+ __u32
+ index
+ Number of the format in the enumeration, set by the
+ application.
+
+
+ __u32
+ pad
+ Pad number as reported by the media controller API.
+
+
+ __u32
+ code
+ The media bus format code, as defined in
+ .
+
+
+ __u32
+ width
+ Frame width, in pixels.
+
+
+ __u32
+ height
+ Frame height, in pixels.
+
+
+ &v4l2-fract;
+ interval
+ Period, in seconds, between consecutive video frames.
+
+
+ __u32
+ reserved[9]
+ Reserved for future extensions. Applications and drivers must
+ set the array to zero.
+
+
+
+
+
+
+
+ &return-value;
+
+
+
+ EINVAL
+
+ The &v4l2-subdev-frame-interval-enum;
+ pad references a non-existing pad, one of
+ the code, width
+ or height fields are invalid for the given
+ pad or the index field is out of bounds.
+
+
+
+
+
+
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 000000000000..0bc3ea22d31f
--- /dev/null
+++ b/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml
@@ -0,0 +1,141 @@
+
+
+ ioctl VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL
+ &manvol;
+
+
+
+ VIDIOC_SUBDEV_G_FRAME_INTERVAL
+ VIDIOC_SUBDEV_S_FRAME_INTERVAL
+ Get or set the frame interval on a subdev pad
+
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ struct v4l2_subdev_frame_interval *argp
+
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ &fd;
+
+
+
+ request
+
+ VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL
+
+
+
+ argp
+
+
+
+
+
+
+
+
+ Description
+
+
+ Experimental
+ This is an experimental
+ interface and may change in the future.
+
+
+ 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.
+
+ To retrieve the current frame interval applications set the
+ pad field of a &v4l2-subdev-frame-interval; to
+ the desired pad number as reported by the media controller API. When they
+ call the VIDIOC_SUBDEV_G_FRAME_INTERVAL ioctl with a
+ pointer to this structure the driver fills the members of the
+ interval field.
+
+ To change the current frame interval applications set both the
+ pad field and all members of the
+ interval field. When they call the
+ VIDIOC_SUBDEV_S_FRAME_INTERVAL 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 VIDIOC_SUBDEV_G_FRAME_INTERVAL call.
+
+
+ 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.
+
+ 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.
+
+
+ struct v4l2_subdev_frame_interval
+
+ &cs-str;
+
+
+ __u32
+ pad
+ Pad number as reported by the media controller API.
+
+
+ &v4l2-fract;
+ interval
+ Period, in seconds, between consecutive video frames.
+
+
+ __u32
+ reserved[9]
+ Reserved for future extensions. Applications and drivers must
+ set the array to zero.
+
+
+
+
+
+
+
+ &return-value;
+
+
+
+ EBUSY
+
+ 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
+ VIDIOC_SUBDEV_S_FRAME_INTERVAL
+
+
+
+ EINVAL
+
+ The &v4l2-subdev-frame-interval; pad
+ references a non-existing pad, or the pad doesn't support frame
+ intervals.
+
+
+
+
+
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
index 207cc5cceb29..a4a12563ec3c 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 8dbb44873821..c55f9e9e1dd3 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 4215650151be..8b7a78a013c6 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -268,6 +268,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,
@@ -420,6 +424,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,
--
cgit v1.2.3
From f6a5cb1be894468cdc69ec557d47f40c28f64642 Mon Sep 17 00:00:00 2001
From: Antti Koskipaa
Date: Wed, 23 Jun 2010 05:03:42 -0300
Subject: [media] 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
Signed-off-by: Laurent Pinchart
Acked-by: Hans Verkuil
Signed-off-by: Mauro Carvalho Chehab
---
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 | 155 +++++++++++++++++++++
drivers/media/video/v4l2-subdev.c | 26 ++++
include/linux/v4l2-subdev.h | 15 ++
include/media/v4l2-subdev.h | 4 +
7 files changed, 238 insertions(+)
create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml
(limited to 'include/linux')
diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
index a95eb5783760..40158ee3d369 100644
--- a/Documentation/DocBook/media-entities.tmpl
+++ b/Documentation/DocBook/media-entities.tmpl
@@ -88,8 +88,10 @@
VIDIOC_S_TUNER">
VIDIOC_SUBDEV_ENUM_FRAME_SIZE">
VIDIOC_SUBDEV_ENUM_MBUS_CODE">
+VIDIOC_SUBDEV_G_CROP">
VIDIOC_SUBDEV_G_FMT">
VIDIOC_SUBDEV_G_FRAME_INTERVAL">
+VIDIOC_SUBDEV_S_CROP">
VIDIOC_SUBDEV_S_FMT">
VIDIOC_SUBDEV_S_FRAME_INTERVAL">
VIDIOC_TRY_ENCODER_CMD">
@@ -198,6 +200,7 @@
v4l2_subdev_frame_interval">
v4l2_subdev_frame_interval_enum">
v4l2_subdev_frame_size_enum">
+v4l2_subdev_crop">
v4l2_subdev_format">
v4l2_subdev_mbus_code_enum">
v4l2_standard">
@@ -339,6 +342,7 @@
+
diff --git a/Documentation/DocBook/v4l/dev-subdev.xml b/Documentation/DocBook/v4l/dev-subdev.xml
index fc62e65f45ef..e9eb8af0f303 100644
--- a/Documentation/DocBook/v4l/dev-subdev.xml
+++ b/Documentation/DocBook/v4l/dev-subdev.xml
@@ -275,6 +275,39 @@
+
+ Cropping and scaling
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+
+ Cropping behaviour on output pads is not defined.
+
+
&sub-subdev-formats;
diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml
index a436716ef3bc..3a6e3b5c0944 100644
--- a/Documentation/DocBook/v4l/v4l2.xml
+++ b/Documentation/DocBook/v4l/v4l2.xml
@@ -510,6 +510,7 @@ and discussions on the V4L mailing list.
&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 000000000000..06197323a8cc
--- /dev/null
+++ b/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml
@@ -0,0 +1,155 @@
+
+
+ ioctl VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP
+ &manvol;
+
+
+
+ VIDIOC_SUBDEV_G_CROP
+ VIDIOC_SUBDEV_S_CROP
+ Get or set the crop rectangle on a subdev pad
+
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ struct v4l2_subdev_crop *argp
+
+
+
+
+ int ioctl
+ int fd
+ int request
+ const struct v4l2_subdev_crop *argp
+
+
+
+
+
+ Arguments
+
+
+
+ fd
+
+ &fd;
+
+
+
+ request
+
+ VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP
+
+
+
+ argp
+
+
+
+
+
+
+
+
+ Description
+
+
+ Experimental
+ This is an experimental
+ interface and may change in the future.
+
+
+ To retrieve the current crop rectangle applications set the
+ pad field of a &v4l2-subdev-crop; to the
+ desired pad number as reported by the media API and the
+ which field to
+ V4L2_SUBDEV_FORMAT_ACTIVE. They then call the
+ VIDIOC_SUBDEV_G_CROP ioctl with a pointer to this
+ structure. The driver fills the members of the rect
+ field or returns &EINVAL; if the input arguments are invalid, or if cropping
+ is not supported on the given pad.
+
+ To change the current crop rectangle applications set both the
+ pad and which fields
+ and all members of the rect field. They then call
+ the VIDIOC_SUBDEV_S_CROP 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 VIDIOC_SUBDEV_G_CROP call.
+
+ Applications can query the device capabilities by setting the
+ which to
+ V4L2_SUBDEV_FORMAT_TRY. 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.
+
+ 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.
+
+
+ struct v4l2_subdev_crop
+
+ &cs-str;
+
+
+ __u32
+ pad
+ Pad number as reported by the media framework.
+
+
+ __u32
+ which
+ Crop rectangle to get or set, from
+ &v4l2-subdev-format-whence;.
+
+
+ &v4l2-rect;
+ rect
+ Crop rectangle boundaries, in pixels.
+
+
+ __u32
+ reserved[8]
+ Reserved for future extensions. Applications and drivers must
+ set the array to zero.
+
+
+
+