[v2] V4L - Adding Digital Video Timings APIs
Commit Message
From: Muralidharan Karicheri <m-karicheri2@ti.com>
This is the second version of the digital video timings APIs implementation.
This adds comment from previous version. I would like to have this
merged to 2.6.33
This adds the above APIs to the v4l2 core. This is based on version v1.2
of the RFC titled "V4L - Support for video timings at the input/output interface"
Following new ioctls are added:-
- VIDIOC_ENUM_DV_PRESETS
- VIDIOC_S_DV_PRESET
- VIDIOC_G_DV_PRESET
- VIDIOC_QUERY_DV_PRESET
- VIDIOC_S_DV_TIMINGS
- VIDIOC_G_DV_TIMINGS
Please refer to the RFC for the details. This code was tested using vpfe
capture driver on TI's DM365. Following is the test configuration used :-
Blue Ray HD DVD source -> TVP7002 -> DM365 (VPFE) ->DDR
A draft version of the TVP7002 driver (currently being reviewed in the mailing
list) was used that supports V4L2_DV_1080I60 & V4L2_DV_720P60 presets.
A loopback video capture application was used for testing these APIs. This calls
following IOCTLS :-
- verify the new v4l2_input capabilities flag added
- Enumerate available presets using VIDIOC_ENUM_DV_PRESETS
- Set one of the supported preset using VIDIOC_S_DV_PRESET
- Get current preset using VIDIOC_G_DV_PRESET
- Detect current preset using VIDIOC_QUERY_DV_PRESET
- Using stub functions in tvp7002, verify VIDIOC_S_DV_TIMINGS
and VIDIOC_G_DV_TIMINGS ioctls are received at the sub device.
TODOs :
- Test it on a 64bit platform - I need help here since I don't have the platform.
- Add documentation (I will send another patch for this today).
- Update v4l2-apps for the new ioctl (will send another patch after
compilation issue is resolved)
Please review this and let me know your comments.
Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
Reviewed-by: Hans Verkuil <hverkuil@xs4all.nl>
---
Applies to V4L-DVB linux-next branch
drivers/media/video/v4l2-compat-ioctl32.c | 7 ++
drivers/media/video/v4l2-ioctl.c | 148 +++++++++++++++++++++++++++++
include/linux/videodev2.h | 136 ++++++++++++++++++++++++++-
include/media/v4l2-ioctl.h | 15 +++
include/media/v4l2-subdev.h | 21 ++++
5 files changed, 325 insertions(+), 2 deletions(-)
Comments
I will be sending the patch for documentation today.
FYI.
Murali Karicheri
Software Design Engineer
Texas Instruments Inc.
Germantown, MD 20874
email: m-karicheri2@ti.com
>-----Original Message-----
>From: Karicheri, Muralidharan
>Sent: Wednesday, November 18, 2009 12:04 PM
>To: linux-media@vger.kernel.org; hverkuil@xs4all.nl
>Cc: davinci-linux-open-source@linux.davincidsp.com; Karicheri, Muralidharan
>Subject: [PATCH v2] V4L - Adding Digital Video Timings APIs
>
>From: Muralidharan Karicheri <m-karicheri2@ti.com>
>
>This is the second version of the digital video timings APIs implementation.
>This adds comment from previous version. I would like to have this
>merged to 2.6.33
>
>This adds the above APIs to the v4l2 core. This is based on version v1.2
>of the RFC titled "V4L - Support for video timings at the input/output
>interface"
>Following new ioctls are added:-
>
> - VIDIOC_ENUM_DV_PRESETS
> - VIDIOC_S_DV_PRESET
> - VIDIOC_G_DV_PRESET
> - VIDIOC_QUERY_DV_PRESET
> - VIDIOC_S_DV_TIMINGS
> - VIDIOC_G_DV_TIMINGS
>
>Please refer to the RFC for the details. This code was tested using vpfe
>capture driver on TI's DM365. Following is the test configuration used :-
>
>Blue Ray HD DVD source -> TVP7002 -> DM365 (VPFE) ->DDR
>
>A draft version of the TVP7002 driver (currently being reviewed in the
>mailing
>list) was used that supports V4L2_DV_1080I60 & V4L2_DV_720P60 presets.
>
>A loopback video capture application was used for testing these APIs. This
>calls
>following IOCTLS :-
>
> - verify the new v4l2_input capabilities flag added
> - Enumerate available presets using VIDIOC_ENUM_DV_PRESETS
> - Set one of the supported preset using VIDIOC_S_DV_PRESET
> - Get current preset using VIDIOC_G_DV_PRESET
> - Detect current preset using VIDIOC_QUERY_DV_PRESET
> - Using stub functions in tvp7002, verify VIDIOC_S_DV_TIMINGS
> and VIDIOC_G_DV_TIMINGS ioctls are received at the sub device.
>
>TODOs :
>
> - Test it on a 64bit platform - I need help here since I don't have the
>platform.
> - Add documentation (I will send another patch for this today).
> - Update v4l2-apps for the new ioctl (will send another patch after
> compilation issue is resolved)
>
>Please review this and let me know your comments.
>
>Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
>Reviewed-by: Hans Verkuil <hverkuil@xs4all.nl>
>---
>Applies to V4L-DVB linux-next branch
>
> drivers/media/video/v4l2-compat-ioctl32.c | 7 ++
> drivers/media/video/v4l2-ioctl.c | 148
>+++++++++++++++++++++++++++++
> include/linux/videodev2.h | 136
>++++++++++++++++++++++++++-
> include/media/v4l2-ioctl.h | 15 +++
> include/media/v4l2-subdev.h | 21 ++++
> 5 files changed, 325 insertions(+), 2 deletions(-)
>
>diff --git a/drivers/media/video/v4l2-compat-ioctl32.c
>b/drivers/media/video/v4l2-compat-ioctl32.c
>index 997975d..9277448 100644
>--- a/drivers/media/video/v4l2-compat-ioctl32.c
>+++ b/drivers/media/video/v4l2-compat-ioctl32.c
>@@ -1077,6 +1077,13 @@ long v4l2_compat_ioctl32(struct file *file, unsigned
>int cmd, unsigned long arg)
> case VIDIOC_DBG_G_REGISTER:
> case VIDIOC_DBG_G_CHIP_IDENT:
> case VIDIOC_S_HW_FREQ_SEEK:
>+ case VIDIOC_ENUM_DV_PRESETS:
>+ case VIDIOC_S_DV_PRESET:
>+ case VIDIOC_G_DV_PRESET:
>+ case VIDIOC_QUERY_DV_PRESET:
>+ case VIDIOC_S_DV_TIMINGS:
>+ case VIDIOC_G_DV_TIMINGS:
>+
> ret = do_video_ioctl(file, cmd, arg);
> break;
>
>diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-
>ioctl.c
>index 30cc334..9593720 100644
>--- a/drivers/media/video/v4l2-ioctl.c
>+++ b/drivers/media/video/v4l2-ioctl.c
>@@ -284,6 +284,12 @@ static const char *v4l2_ioctls[] = {
> [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
> [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
> #endif
>+ [_IOC_NR(VIDIOC_ENUM_DV_PRESETS)] = "VIDIOC_ENUM_DV_PRESETS",
>+ [_IOC_NR(VIDIOC_S_DV_PRESET)] = "VIDIOC_S_DV_PRESET",
>+ [_IOC_NR(VIDIOC_G_DV_PRESET)] = "VIDIOC_G_DV_PRESET",
>+ [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET",
>+ [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS",
>+ [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS",
> };
> #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
>
>@@ -1135,6 +1141,19 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_input *p = arg;
>
>+ /**
>+ * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
>+ * CAP_STD here based on ioctl handler provided by the
>+ * driver. If the driver doesn't support these
>+ * for a specific input, it must override these flags.
>+ */
>+ if (ops->vidioc_s_std)
>+ p->capabilities |= V4L2_IN_CAP_STD;
>+ if (ops->vidioc_s_dv_preset)
>+ p->capabilities |= V4L2_IN_CAP_PRESETS;
>+ if (ops->vidioc_s_dv_timings)
>+ p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
>+
> if (!ops->vidioc_enum_input)
> break;
>
>@@ -1179,6 +1198,19 @@ static long __video_do_ioctl(struct file *file,
> if (!ops->vidioc_enum_output)
> break;
>
>+ /**
>+ * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
>+ * CAP_STD here based on ioctl handler provided by the
>+ * driver. If the driver doesn't support these
>+ * for a specific output , it must override these flags.
>+ */
>+ if (ops->vidioc_s_std)
>+ p->capabilities |= V4L2_OUT_CAP_STD;
>+ if (ops->vidioc_s_dv_preset)
>+ p->capabilities |= V4L2_OUT_CAP_PRESETS;
>+ if (ops->vidioc_s_dv_timings)
>+ p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS;
>+
> ret = ops->vidioc_enum_output(file, fh, p);
> if (!ret)
> dbgarg(cmd, "index=%d, name=%s, type=%d, "
>@@ -1794,6 +1826,122 @@ static long __video_do_ioctl(struct file *file,
> }
> break;
> }
>+ case VIDIOC_ENUM_DV_PRESETS:
>+ {
>+ struct v4l2_dv_enum_preset *p = arg;
>+
>+ if (!ops->vidioc_enum_dv_presets)
>+ break;
>+
>+ ret = ops->vidioc_enum_dv_presets(file, fh, p);
>+ if (!ret)
>+ dbgarg(cmd,
>+ "index=%d, preset=%d, name=%s, width=%d,"
>+ " height=%d ",
>+ p->index, p->preset, p->name, p->width,
>+ p->height);
>+ break;
>+ }
>+ case VIDIOC_S_DV_PRESET:
>+ {
>+ struct v4l2_dv_preset *p = arg;
>+
>+ if (!ops->vidioc_s_dv_preset)
>+ break;
>+
>+ dbgarg(cmd, "preset=%d\n", p->preset);
>+ ret = ops->vidioc_s_dv_preset(file, fh, p);
>+ break;
>+ }
>+ case VIDIOC_G_DV_PRESET:
>+ {
>+ struct v4l2_dv_preset *p = arg;
>+
>+ if (!ops->vidioc_g_dv_preset)
>+ break;
>+
>+ ret = ops->vidioc_g_dv_preset(file, fh, p);
>+ if (!ret)
>+ dbgarg(cmd, "preset=%d\n", p->preset);
>+ break;
>+ }
>+ case VIDIOC_QUERY_DV_PRESET:
>+ {
>+ struct v4l2_dv_preset *p = arg;
>+
>+ if (!ops->vidioc_query_dv_preset)
>+ break;
>+
>+ ret = ops->vidioc_query_dv_preset(file, fh, p);
>+ if (!ret)
>+ dbgarg(cmd, "preset=%d\n", p->preset);
>+ break;
>+ }
>+ case VIDIOC_S_DV_TIMINGS:
>+ {
>+ struct v4l2_dv_timings *p = arg;
>+
>+ if (!ops->vidioc_s_dv_timings)
>+ break;
>+
>+ dbgarg(cmd, "type=%d", p->type);
>+ switch (p->type) {
>+ case V4L2_DV_BT_656_1120:
>+ dbgarg2("interlaced=%d, pixelclock=%lld,"
>+ " width=%d, height=%d, polarities=%x,"
>+ " hfrontporch=%d, hsync=%d, hbackporch=%d,"
>+ " vfrontporch=%d, vsync=%d, vbackporch=%d,"
>+ " il_vfrontporch=%d, il_vsync=%d,"
>+ " il_vbackporch=%d\n",
>+ p->bt.interlaced, p->bt.pixelclock,
>+ p->bt.width, p->bt.height, p->bt.polarities,
>+ p->bt.hfrontporch, p->bt.hsync,
>+ p->bt.hbackporch, p->bt.vfrontporch,
>+ p->bt.vsync, p->bt.vbackporch,
>+ p->bt.il_vfrontporch, p->bt.il_vsync,
>+ p->bt.il_vbackporch);
>+ ret = ops->vidioc_s_dv_timings(file, fh, p);
>+ break;
>+ default:
>+ dbgarg2("- Unknown type!\n");
>+ break;
>+ }
>+ break;
>+ }
>+ case VIDIOC_G_DV_TIMINGS:
>+ {
>+ struct v4l2_dv_timings *p = arg;
>+
>+ if (!ops->vidioc_g_dv_timings)
>+ break;
>+
>+ dbgarg(cmd, "type=%d", p->type);
>+ ret = ops->vidioc_g_dv_timings(file, fh, p);
>+ if (!ret) {
>+ switch (p->type) {
>+ case V4L2_DV_BT_656_1120:
>+ dbgarg2("interlaced=%d, pixelclock=%lld,"
>+ " width=%d, height=%d, polarities=%x,"
>+ " hfrontporch=%d, hsync=%d,"
>+ " hbackporch=%d, vfrontporch=%d,"
>+ " vsync=%d, vbackporch=%d,"
>+ " il_vfrontporch=%d, il_vsync=%d,"
>+ " il_vbackporch=%d\n",
>+ p->bt.interlaced, p->bt.pixelclock,
>+ p->bt.width, p->bt.height,
>+ p->bt.polarities, p->bt.hfrontporch,
>+ p->bt.hsync, p->bt.hbackporch,
>+ p->bt.vfrontporch, p->bt.vsync,
>+ p->bt.vbackporch, p->bt.il_vfrontporch,
>+ p->bt.il_vsync, p->bt.il_vbackporch);
>+ break;
>+ default:
>+ dbgarg2("- Unknown type!\n");
>+ break;
>+ }
>+ }
>+ break;
>+ }
>
> default:
> {
>diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
>index cfde111..5bcc4ab 100644
>--- a/include/linux/videodev2.h
>+++ b/include/linux/videodev2.h
>@@ -731,6 +731,119 @@ struct v4l2_standard {
> };
>
> /*
>+ * V I D E O T I M I N G S D V P R E S E T
>+ */
>+struct v4l2_dv_preset {
>+ __u32 preset;
>+ __u32 reserved[4];
>+};
>+
>+/*
>+ * D V P R E S E T S E N U M E R A T I O N
>+ */
>+struct v4l2_dv_enum_preset {
>+ __u32 index;
>+ __u32 preset;
>+ __u8 name[32]; /* Name of the preset timing */
>+ __u32 width;
>+ __u32 height;
>+ __u32 reserved[4];
>+};
>+
>+/*
>+ * D V P R E S E T V A L U E S
>+ */
>+#define V4L2_DV_PRESET_BASE 0x00000000
>+#define V4L2_DV_INVALID (V4L2_DV_PRESET_BASE + 0)
>+/* BT.1362 */
>+#define V4L2_DV_480P59_94 (V4L2_DV_PRESET_BASE + 1)
>+/* BT.1362 */
>+#define V4L2_DV_576P50 (V4L2_DV_PRESET_BASE + 2)
>+/* SMPTE 296M */
>+#define V4L2_DV_720P24 (V4L2_DV_PRESET_BASE + 3)
>+/* SMPTE 296M */
>+#define V4L2_DV_720P25 (V4L2_DV_PRESET_BASE + 4)
>+/* SMPTE 296M */
>+#define V4L2_DV_720P30 (V4L2_DV_PRESET_BASE + 5)
>+/* SMPTE 296M */
>+#define V4L2_DV_720P50 (V4L2_DV_PRESET_BASE + 6)
>+/* SMPTE 274M */
>+#define V4L2_DV_720P59_94 (V4L2_DV_PRESET_BASE + 7)
>+/* SMPTE 274M/296M */
>+#define V4L2_DV_720P60 (V4L2_DV_PRESET_BASE + 8)
>+/* BT.1120/ SMPTE 274M */
>+#define V4L2_DV_1080I29_97 (V4L2_DV_PRESET_BASE + 9)
>+/* BT.1120/ SMPTE 274M */
>+#define V4L2_DV_1080I30 (V4L2_DV_PRESET_BASE + 10)
>+/* BT.1120 */
>+#define V4L2_DV_1080I25 (V4L2_DV_PRESET_BASE + 11)
>+/* SMPTE 296M */
>+#define V4L2_DV_1080I50 (V4L2_DV_PRESET_BASE + 12)
>+/* SMPTE 296M */
>+#define V4L2_DV_1080I60 (V4L2_DV_PRESET_BASE + 13)
>+/* SMPTE 296M */
>+#define V4L2_DV_1080P24 (V4L2_DV_PRESET_BASE + 14)
>+/* SMPTE 296M */
>+#define V4L2_DV_1080P25 (V4L2_DV_PRESET_BASE + 15)
>+/* SMPTE 296M */
>+#define V4L2_DV_1080P30 (V4L2_DV_PRESET_BASE + 16)
>+/* BT.1120 */
>+#define V4L2_DV_1080P50 (V4L2_DV_PRESET_BASE + 17)
>+/* BT.1120 */
>+#define V4L2_DV_1080P60 (V4L2_DV_PRESET_BASE + 18)
>+
>+/*
>+ * D V B T T I M I N G S
>+ */
>+
>+/* BT.656/BT.1120 timing data */
>+struct v4l2_bt_timings {
>+ __u32 width; /* width in pixels */
>+ __u32 height; /* height in lines */
>+ __u32 interlaced; /* Interlaced or progressive */
>+ __u32 polarities; /* Positive or negative polarity */
>+ __u64 pixelclock; /* Pixel clock in HZ. Ex. 74.25MHz->74250000 */
>+ __u32 hfrontporch; /* Horizpontal front porch in pixels */
>+ __u32 hsync; /* Horizontal Sync length in pixels */
>+ __u32 hbackporch; /* Horizontal back porch in pixels */
>+ __u32 vfrontporch; /* Vertical front porch in pixels */
>+ __u32 vsync; /* Vertical Sync length in lines */
>+ __u32 vbackporch; /* Vertical back porch in lines */
>+ __u32 il_vfrontporch; /* Vertical front porch for bottom field of
>+ * interlaced field formats
>+ */
>+ __u32 il_vsync; /* Vertical sync length for bottom field of
>+ * interlaced field formats
>+ */
>+ __u32 il_vbackporch; /* Vertical back porch for bottom field of
>+ * interlaced field formats
>+ */
>+ __u32 reserved[16];
>+};
>+
>+/* Interlaced or progressive format */
>+#define V4L2_DV_PROGRESSIVE 0
>+#define V4L2_DV_INTERLACED 1
>+
>+/* Polarities. If bit is not set, it is assumed to be negative polarity */
>+#define V4L2_DV_VSYNC_POS_POL 0x00000001
>+#define V4L2_DV_HSYNC_POS_POL 0x00000002
>+
>+/* BT.656/1120 timing type */
>+enum v4l2_dv_timings_type {
>+ V4L2_DV_BT_656_1120,
>+};
>+
>+/* DV timings */
>+struct v4l2_dv_timings {
>+ enum v4l2_dv_timings_type type;
>+ union {
>+ struct v4l2_bt_timings bt;
>+ __u32 reserved[32];
>+ };
>+};
>+
>+/*
> * V I D E O I N P U T S
> */
> struct v4l2_input {
>@@ -741,7 +854,8 @@ struct v4l2_input {
> __u32 tuner; /* Associated tuner */
> v4l2_std_id std;
> __u32 status;
>- __u32 reserved[4];
>+ __u32 capabilities;
>+ __u32 reserved[3];
> };
>
> /* Values for the 'type' field */
>@@ -772,6 +886,11 @@ struct v4l2_input {
> #define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */
> #define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */
>
>+/* capabilities flags */
>+#define V4L2_IN_CAP_PRESETS 0x00000001 /* Supports DV_PRESETS */
>+#define V4L2_IN_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports Custom timings
>*/
>+#define V4L2_IN_CAP_STD 0x00000004 /* Supports STD */
>+
> /*
> * V I D E O O U T P U T S
> */
>@@ -782,13 +901,19 @@ struct v4l2_output {
> __u32 audioset; /* Associated audios (bitfield) */
> __u32 modulator; /* Associated modulator */
> v4l2_std_id std;
>- __u32 reserved[4];
>+ __u32 capabilities;
>+ __u32 reserved[3];
> };
> /* Values for the 'type' field */
> #define V4L2_OUTPUT_TYPE_MODULATOR 1
> #define V4L2_OUTPUT_TYPE_ANALOG 2
> #define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3
>
>+/* capabilities flags */
>+#define V4L2_OUT_CAP_PRESETS 0x00000001 /* Supports DV_PRESETS */
>+#define V4L2_OUT_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports Custom
>timings */
>+#define V4L2_OUT_CAP_STD 0x00000004 /* Supports STD */
>+
> /*
> * C O N T R O L S
> */
>@@ -1621,6 +1746,13 @@ struct v4l2_dbg_chip_ident {
> #endif
>
> #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct
>v4l2_hw_freq_seek)
>+#define VIDIOC_ENUM_DV_PRESETS _IOWR('V', 83, struct
>v4l2_dv_enum_preset)
>+#define VIDIOC_S_DV_PRESET _IOWR('V', 84, struct v4l2_dv_preset)
>+#define VIDIOC_G_DV_PRESET _IOWR('V', 85, struct v4l2_dv_preset)
>+#define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct v4l2_dv_preset)
>+#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings)
>+#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings)
>+
> /* Reminder: when adding new ioctls please add support for them to
> drivers/media/video/v4l2-compat-ioctl32.c as well! */
>
>diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
>index 7a4529d..e8ba0f2 100644
>--- a/include/media/v4l2-ioctl.h
>+++ b/include/media/v4l2-ioctl.h
>@@ -239,6 +239,21 @@ struct v4l2_ioctl_ops {
> int (*vidioc_enum_frameintervals) (struct file *file, void *fh,
> struct v4l2_frmivalenum *fival);
>
>+ /* DV Timings IOCTLs */
>+ int (*vidioc_enum_dv_presets) (struct file *file, void *fh,
>+ struct v4l2_dv_enum_preset *preset);
>+
>+ int (*vidioc_s_dv_preset) (struct file *file, void *fh,
>+ struct v4l2_dv_preset *preset);
>+ int (*vidioc_g_dv_preset) (struct file *file, void *fh,
>+ struct v4l2_dv_preset *preset);
>+ int (*vidioc_query_dv_preset) (struct file *file, void *fh,
>+ struct v4l2_dv_preset *qpreset);
>+ int (*vidioc_s_dv_timings) (struct file *file, void *fh,
>+ struct v4l2_dv_timings *timings);
>+ int (*vidioc_g_dv_timings) (struct file *file, void *fh,
>+ struct v4l2_dv_timings *timings);
>+
> /* For other private ioctls */
> long (*vidioc_default) (struct file *file, void *fh,
> int cmd, void *arg);
>diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
>index 88c13d6..92634da 100644
>--- a/include/media/v4l2-subdev.h
>+++ b/include/media/v4l2-subdev.h
>@@ -217,6 +217,19 @@ struct v4l2_subdev_audio_ops {
>
> s_routing: see s_routing in audio_ops, except this version is for video
> devices.
>+
>+ s_dv_preset: set dv (Digital Video) preset in the sub device. Similar
>to
>+ s_std()
>+
>+ query_dv_preset: query dv preset in the sub device. This is similar to
>+ querystd()
>+
>+ s_dv_timings(): Set custom dv timings in the sub device. This is used
>+ when sub device is capable of setting detailed timing information
>+ in the hardware to generate/detect the video signal.
>+
>+ g_dv_timings(): Get custom dv timings in the sub device.
>+
> */
> struct v4l2_subdev_video_ops {
> int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32
>config);
>@@ -240,6 +253,14 @@ struct v4l2_subdev_video_ops {
> int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
> int (*enum_framesizes)(struct v4l2_subdev *sd, struct
>v4l2_frmsizeenum *fsize);
> int (*enum_frameintervals)(struct v4l2_subdev *sd, struct
>v4l2_frmivalenum *fival);
>+ int (*s_dv_preset)(struct v4l2_subdev *sd,
>+ struct v4l2_dv_preset *preset);
>+ int (*query_dv_preset)(struct v4l2_subdev *sd,
>+ struct v4l2_dv_preset *preset);
>+ int (*s_dv_timings)(struct v4l2_subdev *sd,
>+ struct v4l2_dv_timings *timings);
>+ int (*g_dv_timings)(struct v4l2_subdev *sd,
>+ struct v4l2_dv_timings *timings);
> };
>
> /*
>--
>1.6.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wednesday 18 November 2009 18:03:44 m-karicheri2@ti.com wrote:
> From: Muralidharan Karicheri <m-karicheri2@ti.com>
>
> This is the second version of the digital video timings APIs implementation.
> This adds comment from previous version. I would like to have this
> merged to 2.6.33
Me too :-)
> This adds the above APIs to the v4l2 core. This is based on version v1.2
> of the RFC titled "V4L - Support for video timings at the input/output interface"
> Following new ioctls are added:-
>
> - VIDIOC_ENUM_DV_PRESETS
> - VIDIOC_S_DV_PRESET
> - VIDIOC_G_DV_PRESET
> - VIDIOC_QUERY_DV_PRESET
> - VIDIOC_S_DV_TIMINGS
> - VIDIOC_G_DV_TIMINGS
>
> Please refer to the RFC for the details. This code was tested using vpfe
> capture driver on TI's DM365. Following is the test configuration used :-
>
> Blue Ray HD DVD source -> TVP7002 -> DM365 (VPFE) ->DDR
>
> A draft version of the TVP7002 driver (currently being reviewed in the mailing
> list) was used that supports V4L2_DV_1080I60 & V4L2_DV_720P60 presets.
>
> A loopback video capture application was used for testing these APIs. This calls
> following IOCTLS :-
>
> - verify the new v4l2_input capabilities flag added
> - Enumerate available presets using VIDIOC_ENUM_DV_PRESETS
> - Set one of the supported preset using VIDIOC_S_DV_PRESET
> - Get current preset using VIDIOC_G_DV_PRESET
> - Detect current preset using VIDIOC_QUERY_DV_PRESET
> - Using stub functions in tvp7002, verify VIDIOC_S_DV_TIMINGS
> and VIDIOC_G_DV_TIMINGS ioctls are received at the sub device.
>
> TODOs :
>
> - Test it on a 64bit platform - I need help here since I don't have the platform.
It compiles without warnings :-)
> - Add documentation (I will send another patch for this today).
> - Update v4l2-apps for the new ioctl (will send another patch after
> compilation issue is resolved)
>
> Please review this and let me know your comments.
I found a few small things, see comments below.
> Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
> Reviewed-by: Hans Verkuil <hverkuil@xs4all.nl>
> ---
> Applies to V4L-DVB linux-next branch
>
> drivers/media/video/v4l2-compat-ioctl32.c | 7 ++
> drivers/media/video/v4l2-ioctl.c | 148 +++++++++++++++++++++++++++++
> include/linux/videodev2.h | 136 ++++++++++++++++++++++++++-
> include/media/v4l2-ioctl.h | 15 +++
> include/media/v4l2-subdev.h | 21 ++++
> 5 files changed, 325 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
> index 997975d..9277448 100644
> --- a/drivers/media/video/v4l2-compat-ioctl32.c
> +++ b/drivers/media/video/v4l2-compat-ioctl32.c
> @@ -1077,6 +1077,13 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
> case VIDIOC_DBG_G_REGISTER:
> case VIDIOC_DBG_G_CHIP_IDENT:
> case VIDIOC_S_HW_FREQ_SEEK:
> + case VIDIOC_ENUM_DV_PRESETS:
> + case VIDIOC_S_DV_PRESET:
> + case VIDIOC_G_DV_PRESET:
> + case VIDIOC_QUERY_DV_PRESET:
> + case VIDIOC_S_DV_TIMINGS:
> + case VIDIOC_G_DV_TIMINGS:
> +
No need for this extra empty line.
> ret = do_video_ioctl(file, cmd, arg);
> break;
>
> diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
> index 30cc334..9593720 100644
> --- a/drivers/media/video/v4l2-ioctl.c
> +++ b/drivers/media/video/v4l2-ioctl.c
> @@ -284,6 +284,12 @@ static const char *v4l2_ioctls[] = {
> [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
> [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
> #endif
> + [_IOC_NR(VIDIOC_ENUM_DV_PRESETS)] = "VIDIOC_ENUM_DV_PRESETS",
> + [_IOC_NR(VIDIOC_S_DV_PRESET)] = "VIDIOC_S_DV_PRESET",
> + [_IOC_NR(VIDIOC_G_DV_PRESET)] = "VIDIOC_G_DV_PRESET",
> + [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET",
> + [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS",
> + [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS",
> };
> #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
>
> @@ -1135,6 +1141,19 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_input *p = arg;
>
> + /**
> + * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
> + * CAP_STD here based on ioctl handler provided by the
> + * driver. If the driver doesn't support these
> + * for a specific input, it must override these flags.
> + */
> + if (ops->vidioc_s_std)
> + p->capabilities |= V4L2_IN_CAP_STD;
> + if (ops->vidioc_s_dv_preset)
> + p->capabilities |= V4L2_IN_CAP_PRESETS;
> + if (ops->vidioc_s_dv_timings)
> + p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
> +
> if (!ops->vidioc_enum_input)
> break;
>
> @@ -1179,6 +1198,19 @@ static long __video_do_ioctl(struct file *file,
> if (!ops->vidioc_enum_output)
> break;
>
> + /**
> + * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
> + * CAP_STD here based on ioctl handler provided by the
> + * driver. If the driver doesn't support these
> + * for a specific output , it must override these flags.
Nitpick: remove space before comma.
> + */
> + if (ops->vidioc_s_std)
> + p->capabilities |= V4L2_OUT_CAP_STD;
> + if (ops->vidioc_s_dv_preset)
> + p->capabilities |= V4L2_OUT_CAP_PRESETS;
> + if (ops->vidioc_s_dv_timings)
> + p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS;
> +
> ret = ops->vidioc_enum_output(file, fh, p);
> if (!ret)
> dbgarg(cmd, "index=%d, name=%s, type=%d, "
> @@ -1794,6 +1826,122 @@ static long __video_do_ioctl(struct file *file,
> }
> break;
> }
> + case VIDIOC_ENUM_DV_PRESETS:
> + {
> + struct v4l2_dv_enum_preset *p = arg;
> +
> + if (!ops->vidioc_enum_dv_presets)
> + break;
> +
> + ret = ops->vidioc_enum_dv_presets(file, fh, p);
> + if (!ret)
> + dbgarg(cmd,
> + "index=%d, preset=%d, name=%s, width=%d,"
> + " height=%d ",
> + p->index, p->preset, p->name, p->width,
> + p->height);
> + break;
> + }
> + case VIDIOC_S_DV_PRESET:
> + {
> + struct v4l2_dv_preset *p = arg;
> +
> + if (!ops->vidioc_s_dv_preset)
> + break;
> +
> + dbgarg(cmd, "preset=%d\n", p->preset);
> + ret = ops->vidioc_s_dv_preset(file, fh, p);
> + break;
> + }
> + case VIDIOC_G_DV_PRESET:
> + {
> + struct v4l2_dv_preset *p = arg;
> +
> + if (!ops->vidioc_g_dv_preset)
> + break;
> +
> + ret = ops->vidioc_g_dv_preset(file, fh, p);
> + if (!ret)
> + dbgarg(cmd, "preset=%d\n", p->preset);
> + break;
> + }
> + case VIDIOC_QUERY_DV_PRESET:
> + {
> + struct v4l2_dv_preset *p = arg;
> +
> + if (!ops->vidioc_query_dv_preset)
> + break;
> +
> + ret = ops->vidioc_query_dv_preset(file, fh, p);
> + if (!ret)
> + dbgarg(cmd, "preset=%d\n", p->preset);
> + break;
> + }
> + case VIDIOC_S_DV_TIMINGS:
> + {
> + struct v4l2_dv_timings *p = arg;
> +
> + if (!ops->vidioc_s_dv_timings)
> + break;
> +
> + dbgarg(cmd, "type=%d", p->type);
> + switch (p->type) {
> + case V4L2_DV_BT_656_1120:
> + dbgarg2("interlaced=%d, pixelclock=%lld,"
Rather than break up the debug line, I would suggest removing the 'type=' debug
line and prefix this one with "bt-656/1120: ".
> + " width=%d, height=%d, polarities=%x,"
> + " hfrontporch=%d, hsync=%d, hbackporch=%d,"
> + " vfrontporch=%d, vsync=%d, vbackporch=%d,"
> + " il_vfrontporch=%d, il_vsync=%d,"
> + " il_vbackporch=%d\n",
> + p->bt.interlaced, p->bt.pixelclock,
> + p->bt.width, p->bt.height, p->bt.polarities,
> + p->bt.hfrontporch, p->bt.hsync,
> + p->bt.hbackporch, p->bt.vfrontporch,
> + p->bt.vsync, p->bt.vbackporch,
> + p->bt.il_vfrontporch, p->bt.il_vsync,
> + p->bt.il_vbackporch);
> + ret = ops->vidioc_s_dv_timings(file, fh, p);
> + break;
> + default:
> + dbgarg2("- Unknown type!\n");
This will then become "Unknown type %d!\n".
> + break;
> + }
> + break;
> + }
> + case VIDIOC_G_DV_TIMINGS:
> + {
> + struct v4l2_dv_timings *p = arg;
> +
> + if (!ops->vidioc_g_dv_timings)
> + break;
> +
> + dbgarg(cmd, "type=%d", p->type);
Ditto.
> + ret = ops->vidioc_g_dv_timings(file, fh, p);
> + if (!ret) {
> + switch (p->type) {
> + case V4L2_DV_BT_656_1120:
> + dbgarg2("interlaced=%d, pixelclock=%lld,"
> + " width=%d, height=%d, polarities=%x,"
> + " hfrontporch=%d, hsync=%d,"
> + " hbackporch=%d, vfrontporch=%d,"
> + " vsync=%d, vbackporch=%d,"
> + " il_vfrontporch=%d, il_vsync=%d,"
> + " il_vbackporch=%d\n",
> + p->bt.interlaced, p->bt.pixelclock,
> + p->bt.width, p->bt.height,
> + p->bt.polarities, p->bt.hfrontporch,
> + p->bt.hsync, p->bt.hbackporch,
> + p->bt.vfrontporch, p->bt.vsync,
> + p->bt.vbackporch, p->bt.il_vfrontporch,
> + p->bt.il_vsync, p->bt.il_vbackporch);
> + break;
> + default:
> + dbgarg2("- Unknown type!\n");
> + break;
> + }
> + }
> + break;
> + }
>
> default:
> {
> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> index cfde111..5bcc4ab 100644
> --- a/include/linux/videodev2.h
> +++ b/include/linux/videodev2.h
> @@ -731,6 +731,119 @@ struct v4l2_standard {
> };
>
> /*
> + * V I D E O T I M I N G S D V P R E S E T
> + */
> +struct v4l2_dv_preset {
> + __u32 preset;
> + __u32 reserved[4];
> +};
> +
> +/*
> + * D V P R E S E T S E N U M E R A T I O N
> + */
> +struct v4l2_dv_enum_preset {
> + __u32 index;
> + __u32 preset;
> + __u8 name[32]; /* Name of the preset timing */
> + __u32 width;
> + __u32 height;
> + __u32 reserved[4];
> +};
> +
> +/*
> + * D V P R E S E T V A L U E S
> + */
> +#define V4L2_DV_PRESET_BASE 0x00000000
Why do we need a PRESET_BASE define? I'd just start counting at 0.
> +#define V4L2_DV_INVALID (V4L2_DV_PRESET_BASE + 0)
> +/* BT.1362 */
Append this define at the end of the previous line. Without the PRESET_BASE
there is enough room for it.
> +#define V4L2_DV_480P59_94 (V4L2_DV_PRESET_BASE + 1)
> +/* BT.1362 */
> +#define V4L2_DV_576P50 (V4L2_DV_PRESET_BASE + 2)
> +/* SMPTE 296M */
> +#define V4L2_DV_720P24 (V4L2_DV_PRESET_BASE + 3)
> +/* SMPTE 296M */
> +#define V4L2_DV_720P25 (V4L2_DV_PRESET_BASE + 4)
> +/* SMPTE 296M */
> +#define V4L2_DV_720P30 (V4L2_DV_PRESET_BASE + 5)
> +/* SMPTE 296M */
> +#define V4L2_DV_720P50 (V4L2_DV_PRESET_BASE + 6)
> +/* SMPTE 274M */
> +#define V4L2_DV_720P59_94 (V4L2_DV_PRESET_BASE + 7)
> +/* SMPTE 274M/296M */
> +#define V4L2_DV_720P60 (V4L2_DV_PRESET_BASE + 8)
> +/* BT.1120/ SMPTE 274M */
> +#define V4L2_DV_1080I29_97 (V4L2_DV_PRESET_BASE + 9)
> +/* BT.1120/ SMPTE 274M */
> +#define V4L2_DV_1080I30 (V4L2_DV_PRESET_BASE + 10)
> +/* BT.1120 */
> +#define V4L2_DV_1080I25 (V4L2_DV_PRESET_BASE + 11)
> +/* SMPTE 296M */
> +#define V4L2_DV_1080I50 (V4L2_DV_PRESET_BASE + 12)
> +/* SMPTE 296M */
> +#define V4L2_DV_1080I60 (V4L2_DV_PRESET_BASE + 13)
> +/* SMPTE 296M */
> +#define V4L2_DV_1080P24 (V4L2_DV_PRESET_BASE + 14)
> +/* SMPTE 296M */
> +#define V4L2_DV_1080P25 (V4L2_DV_PRESET_BASE + 15)
> +/* SMPTE 296M */
> +#define V4L2_DV_1080P30 (V4L2_DV_PRESET_BASE + 16)
> +/* BT.1120 */
> +#define V4L2_DV_1080P50 (V4L2_DV_PRESET_BASE + 17)
> +/* BT.1120 */
> +#define V4L2_DV_1080P60 (V4L2_DV_PRESET_BASE + 18)
> +
> +/*
> + * D V B T T I M I N G S
> + */
> +
> +/* BT.656/BT.1120 timing data */
> +struct v4l2_bt_timings {
> + __u32 width; /* width in pixels */
> + __u32 height; /* height in lines */
> + __u32 interlaced; /* Interlaced or progressive */
> + __u32 polarities; /* Positive or negative polarity */
> + __u64 pixelclock; /* Pixel clock in HZ. Ex. 74.25MHz->74250000 */
> + __u32 hfrontporch; /* Horizpontal front porch in pixels */
> + __u32 hsync; /* Horizontal Sync length in pixels */
> + __u32 hbackporch; /* Horizontal back porch in pixels */
> + __u32 vfrontporch; /* Vertical front porch in pixels */
> + __u32 vsync; /* Vertical Sync length in lines */
> + __u32 vbackporch; /* Vertical back porch in lines */
> + __u32 il_vfrontporch; /* Vertical front porch for bottom field of
> + * interlaced field formats
> + */
> + __u32 il_vsync; /* Vertical sync length for bottom field of
> + * interlaced field formats
> + */
> + __u32 il_vbackporch; /* Vertical back porch for bottom field of
> + * interlaced field formats
> + */
> + __u32 reserved[16];
> +};
> +
> +/* Interlaced or progressive format */
> +#define V4L2_DV_PROGRESSIVE 0
> +#define V4L2_DV_INTERLACED 1
> +
> +/* Polarities. If bit is not set, it is assumed to be negative polarity */
> +#define V4L2_DV_VSYNC_POS_POL 0x00000001
> +#define V4L2_DV_HSYNC_POS_POL 0x00000002
> +
> +/* BT.656/1120 timing type */
> +enum v4l2_dv_timings_type {
> + V4L2_DV_BT_656_1120,
> +};
I forgot something: we shouldn't use enums as that can give problems on some
architectures (ARM being one of them, I believe). So this should become a
define and the type field below a __u32.
> +
> +/* DV timings */
> +struct v4l2_dv_timings {
> + enum v4l2_dv_timings_type type;
> + union {
> + struct v4l2_bt_timings bt;
> + __u32 reserved[32];
> + };
> +};
> +
> +/*
> * V I D E O I N P U T S
> */
> struct v4l2_input {
> @@ -741,7 +854,8 @@ struct v4l2_input {
> __u32 tuner; /* Associated tuner */
> v4l2_std_id std;
> __u32 status;
> - __u32 reserved[4];
> + __u32 capabilities;
> + __u32 reserved[3];
> };
>
> /* Values for the 'type' field */
> @@ -772,6 +886,11 @@ struct v4l2_input {
> #define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */
> #define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */
>
> +/* capabilities flags */
> +#define V4L2_IN_CAP_PRESETS 0x00000001 /* Supports DV_PRESETS */
> +#define V4L2_IN_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports Custom timings */
> +#define V4L2_IN_CAP_STD 0x00000004 /* Supports STD */
I suggest changing the comments to "Supports S_DV_PRESET",
"Support S_DV_TIMINGS" and "Support S_STD". That's a bit more consistent and
it is also clear that the capability refers to whether an ioctl is supported
or not for that particular input.
> +
> /*
> * V I D E O O U T P U T S
> */
> @@ -782,13 +901,19 @@ struct v4l2_output {
> __u32 audioset; /* Associated audios (bitfield) */
> __u32 modulator; /* Associated modulator */
> v4l2_std_id std;
> - __u32 reserved[4];
> + __u32 capabilities;
> + __u32 reserved[3];
> };
> /* Values for the 'type' field */
> #define V4L2_OUTPUT_TYPE_MODULATOR 1
> #define V4L2_OUTPUT_TYPE_ANALOG 2
> #define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3
>
> +/* capabilities flags */
> +#define V4L2_OUT_CAP_PRESETS 0x00000001 /* Supports DV_PRESETS */
> +#define V4L2_OUT_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports Custom timings */
> +#define V4L2_OUT_CAP_STD 0x00000004 /* Supports STD */
Ditto.
> +
> /*
> * C O N T R O L S
> */
> @@ -1621,6 +1746,13 @@ struct v4l2_dbg_chip_ident {
> #endif
>
> #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek)
> +#define VIDIOC_ENUM_DV_PRESETS _IOWR('V', 83, struct v4l2_dv_enum_preset)
> +#define VIDIOC_S_DV_PRESET _IOWR('V', 84, struct v4l2_dv_preset)
> +#define VIDIOC_G_DV_PRESET _IOWR('V', 85, struct v4l2_dv_preset)
> +#define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct v4l2_dv_preset)
> +#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings)
> +#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings)
> +
> /* Reminder: when adding new ioctls please add support for them to
> drivers/media/video/v4l2-compat-ioctl32.c as well! */
>
> diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
> index 7a4529d..e8ba0f2 100644
> --- a/include/media/v4l2-ioctl.h
> +++ b/include/media/v4l2-ioctl.h
> @@ -239,6 +239,21 @@ struct v4l2_ioctl_ops {
> int (*vidioc_enum_frameintervals) (struct file *file, void *fh,
> struct v4l2_frmivalenum *fival);
>
> + /* DV Timings IOCTLs */
> + int (*vidioc_enum_dv_presets) (struct file *file, void *fh,
> + struct v4l2_dv_enum_preset *preset);
> +
> + int (*vidioc_s_dv_preset) (struct file *file, void *fh,
> + struct v4l2_dv_preset *preset);
> + int (*vidioc_g_dv_preset) (struct file *file, void *fh,
> + struct v4l2_dv_preset *preset);
> + int (*vidioc_query_dv_preset) (struct file *file, void *fh,
> + struct v4l2_dv_preset *qpreset);
> + int (*vidioc_s_dv_timings) (struct file *file, void *fh,
> + struct v4l2_dv_timings *timings);
> + int (*vidioc_g_dv_timings) (struct file *file, void *fh,
> + struct v4l2_dv_timings *timings);
> +
> /* For other private ioctls */
> long (*vidioc_default) (struct file *file, void *fh,
> int cmd, void *arg);
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index 88c13d6..92634da 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -217,6 +217,19 @@ struct v4l2_subdev_audio_ops {
>
> s_routing: see s_routing in audio_ops, except this version is for video
> devices.
> +
> + s_dv_preset: set dv (Digital Video) preset in the sub device. Similar to
> + s_std()
> +
> + query_dv_preset: query dv preset in the sub device. This is similar to
> + querystd()
> +
> + s_dv_timings(): Set custom dv timings in the sub device. This is used
> + when sub device is capable of setting detailed timing information
> + in the hardware to generate/detect the video signal.
> +
> + g_dv_timings(): Get custom dv timings in the sub device.
> +
> */
> struct v4l2_subdev_video_ops {
> int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
> @@ -240,6 +253,14 @@ struct v4l2_subdev_video_ops {
> int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
> int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize);
> int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival);
> + int (*s_dv_preset)(struct v4l2_subdev *sd,
> + struct v4l2_dv_preset *preset);
> + int (*query_dv_preset)(struct v4l2_subdev *sd,
> + struct v4l2_dv_preset *preset);
> + int (*s_dv_timings)(struct v4l2_subdev *sd,
> + struct v4l2_dv_timings *timings);
> + int (*g_dv_timings)(struct v4l2_subdev *sd,
> + struct v4l2_dv_timings *timings);
> };
>
> /*
Regards,
Hans
PS: If I have time (no guarantees!), then I'll try to do some 64-bit testing
this weekend.
Hans,
Thanks for reviewing this. I will try to send an updated patch today.
BTW, I have posted the documentation patch to the list for review.
Murali Karicheri
Software Design Engineer
Texas Instruments Inc.
Germantown, MD 20874
phone: 301-407-9583
email: m-karicheri2@ti.com
>-----Original Message-----
>From: Hans Verkuil [mailto:hverkuil@xs4all.nl]
>Sent: Wednesday, November 18, 2009 1:09 PM
>To: Karicheri, Muralidharan
>Cc: linux-media@vger.kernel.org; davinci-linux-open-
>source@linux.davincidsp.com
>Subject: Re: [PATCH v2] V4L - Adding Digital Video Timings APIs
>
>On Wednesday 18 November 2009 18:03:44 m-karicheri2@ti.com wrote:
>> From: Muralidharan Karicheri <m-karicheri2@ti.com>
>>
>> This is the second version of the digital video timings APIs
>implementation.
>> This adds comment from previous version. I would like to have this
>> merged to 2.6.33
>
>Me too :-)
>
>> This adds the above APIs to the v4l2 core. This is based on version v1.2
>> of the RFC titled "V4L - Support for video timings at the input/output
>interface"
>> Following new ioctls are added:-
>>
>> - VIDIOC_ENUM_DV_PRESETS
>> - VIDIOC_S_DV_PRESET
>> - VIDIOC_G_DV_PRESET
>> - VIDIOC_QUERY_DV_PRESET
>> - VIDIOC_S_DV_TIMINGS
>> - VIDIOC_G_DV_TIMINGS
>>
>> Please refer to the RFC for the details. This code was tested using vpfe
>> capture driver on TI's DM365. Following is the test configuration used :-
>>
>> Blue Ray HD DVD source -> TVP7002 -> DM365 (VPFE) ->DDR
>>
>> A draft version of the TVP7002 driver (currently being reviewed in the
>mailing
>> list) was used that supports V4L2_DV_1080I60 & V4L2_DV_720P60 presets.
>>
>> A loopback video capture application was used for testing these APIs.
>This calls
>> following IOCTLS :-
>>
>> - verify the new v4l2_input capabilities flag added
>> - Enumerate available presets using VIDIOC_ENUM_DV_PRESETS
>> - Set one of the supported preset using VIDIOC_S_DV_PRESET
>> - Get current preset using VIDIOC_G_DV_PRESET
>> - Detect current preset using VIDIOC_QUERY_DV_PRESET
>> - Using stub functions in tvp7002, verify VIDIOC_S_DV_TIMINGS
>> and VIDIOC_G_DV_TIMINGS ioctls are received at the sub device.
>>
>> TODOs :
>>
>> - Test it on a 64bit platform - I need help here since I don't have the
>platform.
>
>It compiles without warnings :-)
>
>> - Add documentation (I will send another patch for this today).
>> - Update v4l2-apps for the new ioctl (will send another patch after
>> compilation issue is resolved)
>>
>> Please review this and let me know your comments.
>
>I found a few small things, see comments below.
>
>> Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
>> Reviewed-by: Hans Verkuil <hverkuil@xs4all.nl>
>> ---
>> Applies to V4L-DVB linux-next branch
>>
>> drivers/media/video/v4l2-compat-ioctl32.c | 7 ++
>> drivers/media/video/v4l2-ioctl.c | 148
>+++++++++++++++++++++++++++++
>> include/linux/videodev2.h | 136
>++++++++++++++++++++++++++-
>> include/media/v4l2-ioctl.h | 15 +++
>> include/media/v4l2-subdev.h | 21 ++++
>> 5 files changed, 325 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/media/video/v4l2-compat-ioctl32.c
>b/drivers/media/video/v4l2-compat-ioctl32.c
>> index 997975d..9277448 100644
>> --- a/drivers/media/video/v4l2-compat-ioctl32.c
>> +++ b/drivers/media/video/v4l2-compat-ioctl32.c
>> @@ -1077,6 +1077,13 @@ long v4l2_compat_ioctl32(struct file *file,
>unsigned int cmd, unsigned long arg)
>> case VIDIOC_DBG_G_REGISTER:
>> case VIDIOC_DBG_G_CHIP_IDENT:
>> case VIDIOC_S_HW_FREQ_SEEK:
>> + case VIDIOC_ENUM_DV_PRESETS:
>> + case VIDIOC_S_DV_PRESET:
>> + case VIDIOC_G_DV_PRESET:
>> + case VIDIOC_QUERY_DV_PRESET:
>> + case VIDIOC_S_DV_TIMINGS:
>> + case VIDIOC_G_DV_TIMINGS:
>> +
>
>No need for this extra empty line.
>
>> ret = do_video_ioctl(file, cmd, arg);
>> break;
>>
>> diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-
>ioctl.c
>> index 30cc334..9593720 100644
>> --- a/drivers/media/video/v4l2-ioctl.c
>> +++ b/drivers/media/video/v4l2-ioctl.c
>> @@ -284,6 +284,12 @@ static const char *v4l2_ioctls[] = {
>> [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
>> [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
>> #endif
>> + [_IOC_NR(VIDIOC_ENUM_DV_PRESETS)] = "VIDIOC_ENUM_DV_PRESETS",
>> + [_IOC_NR(VIDIOC_S_DV_PRESET)] = "VIDIOC_S_DV_PRESET",
>> + [_IOC_NR(VIDIOC_G_DV_PRESET)] = "VIDIOC_G_DV_PRESET",
>> + [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET",
>> + [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS",
>> + [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS",
>> };
>> #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
>>
>> @@ -1135,6 +1141,19 @@ static long __video_do_ioctl(struct file *file,
>> {
>> struct v4l2_input *p = arg;
>>
>> + /**
>> + * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
>> + * CAP_STD here based on ioctl handler provided by the
>> + * driver. If the driver doesn't support these
>> + * for a specific input, it must override these flags.
>> + */
>> + if (ops->vidioc_s_std)
>> + p->capabilities |= V4L2_IN_CAP_STD;
>> + if (ops->vidioc_s_dv_preset)
>> + p->capabilities |= V4L2_IN_CAP_PRESETS;
>> + if (ops->vidioc_s_dv_timings)
>> + p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
>> +
>> if (!ops->vidioc_enum_input)
>> break;
>>
>> @@ -1179,6 +1198,19 @@ static long __video_do_ioctl(struct file *file,
>> if (!ops->vidioc_enum_output)
>> break;
>>
>> + /**
>> + * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
>> + * CAP_STD here based on ioctl handler provided by the
>> + * driver. If the driver doesn't support these
>> + * for a specific output , it must override these flags.
>
>Nitpick: remove space before comma.
>
>> + */
>> + if (ops->vidioc_s_std)
>> + p->capabilities |= V4L2_OUT_CAP_STD;
>> + if (ops->vidioc_s_dv_preset)
>> + p->capabilities |= V4L2_OUT_CAP_PRESETS;
>> + if (ops->vidioc_s_dv_timings)
>> + p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS;
>> +
>> ret = ops->vidioc_enum_output(file, fh, p);
>> if (!ret)
>> dbgarg(cmd, "index=%d, name=%s, type=%d, "
>> @@ -1794,6 +1826,122 @@ static long __video_do_ioctl(struct file *file,
>> }
>> break;
>> }
>> + case VIDIOC_ENUM_DV_PRESETS:
>> + {
>> + struct v4l2_dv_enum_preset *p = arg;
>> +
>> + if (!ops->vidioc_enum_dv_presets)
>> + break;
>> +
>> + ret = ops->vidioc_enum_dv_presets(file, fh, p);
>> + if (!ret)
>> + dbgarg(cmd,
>> + "index=%d, preset=%d, name=%s, width=%d,"
>> + " height=%d ",
>> + p->index, p->preset, p->name, p->width,
>> + p->height);
>> + break;
>> + }
>> + case VIDIOC_S_DV_PRESET:
>> + {
>> + struct v4l2_dv_preset *p = arg;
>> +
>> + if (!ops->vidioc_s_dv_preset)
>> + break;
>> +
>> + dbgarg(cmd, "preset=%d\n", p->preset);
>> + ret = ops->vidioc_s_dv_preset(file, fh, p);
>> + break;
>> + }
>> + case VIDIOC_G_DV_PRESET:
>> + {
>> + struct v4l2_dv_preset *p = arg;
>> +
>> + if (!ops->vidioc_g_dv_preset)
>> + break;
>> +
>> + ret = ops->vidioc_g_dv_preset(file, fh, p);
>> + if (!ret)
>> + dbgarg(cmd, "preset=%d\n", p->preset);
>> + break;
>> + }
>> + case VIDIOC_QUERY_DV_PRESET:
>> + {
>> + struct v4l2_dv_preset *p = arg;
>> +
>> + if (!ops->vidioc_query_dv_preset)
>> + break;
>> +
>> + ret = ops->vidioc_query_dv_preset(file, fh, p);
>> + if (!ret)
>> + dbgarg(cmd, "preset=%d\n", p->preset);
>> + break;
>> + }
>> + case VIDIOC_S_DV_TIMINGS:
>> + {
>> + struct v4l2_dv_timings *p = arg;
>> +
>> + if (!ops->vidioc_s_dv_timings)
>> + break;
>> +
>> + dbgarg(cmd, "type=%d", p->type);
>> + switch (p->type) {
>> + case V4L2_DV_BT_656_1120:
>> + dbgarg2("interlaced=%d, pixelclock=%lld,"
>
>Rather than break up the debug line, I would suggest removing the 'type='
>debug
>line and prefix this one with "bt-656/1120: ".
>
>> + " width=%d, height=%d, polarities=%x,"
>> + " hfrontporch=%d, hsync=%d, hbackporch=%d,"
>> + " vfrontporch=%d, vsync=%d, vbackporch=%d,"
>> + " il_vfrontporch=%d, il_vsync=%d,"
>> + " il_vbackporch=%d\n",
>> + p->bt.interlaced, p->bt.pixelclock,
>> + p->bt.width, p->bt.height, p->bt.polarities,
>> + p->bt.hfrontporch, p->bt.hsync,
>> + p->bt.hbackporch, p->bt.vfrontporch,
>> + p->bt.vsync, p->bt.vbackporch,
>> + p->bt.il_vfrontporch, p->bt.il_vsync,
>> + p->bt.il_vbackporch);
>> + ret = ops->vidioc_s_dv_timings(file, fh, p);
>> + break;
>> + default:
>> + dbgarg2("- Unknown type!\n");
>
>This will then become "Unknown type %d!\n".
>
>> + break;
>> + }
>> + break;
>> + }
>> + case VIDIOC_G_DV_TIMINGS:
>> + {
>> + struct v4l2_dv_timings *p = arg;
>> +
>> + if (!ops->vidioc_g_dv_timings)
>> + break;
>> +
>> + dbgarg(cmd, "type=%d", p->type);
>
>Ditto.
>
>> + ret = ops->vidioc_g_dv_timings(file, fh, p);
>> + if (!ret) {
>> + switch (p->type) {
>> + case V4L2_DV_BT_656_1120:
>> + dbgarg2("interlaced=%d, pixelclock=%lld,"
>> + " width=%d, height=%d, polarities=%x,"
>> + " hfrontporch=%d, hsync=%d,"
>> + " hbackporch=%d, vfrontporch=%d,"
>> + " vsync=%d, vbackporch=%d,"
>> + " il_vfrontporch=%d, il_vsync=%d,"
>> + " il_vbackporch=%d\n",
>> + p->bt.interlaced, p->bt.pixelclock,
>> + p->bt.width, p->bt.height,
>> + p->bt.polarities, p->bt.hfrontporch,
>> + p->bt.hsync, p->bt.hbackporch,
>> + p->bt.vfrontporch, p->bt.vsync,
>> + p->bt.vbackporch, p->bt.il_vfrontporch,
>> + p->bt.il_vsync, p->bt.il_vbackporch);
>> + break;
>> + default:
>> + dbgarg2("- Unknown type!\n");
>> + break;
>> + }
>> + }
>> + break;
>> + }
>>
>> default:
>> {
>> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
>> index cfde111..5bcc4ab 100644
>> --- a/include/linux/videodev2.h
>> +++ b/include/linux/videodev2.h
>> @@ -731,6 +731,119 @@ struct v4l2_standard {
>> };
>>
>> /*
>> + * V I D E O T I M I N G S D V P R E S E T
>> + */
>> +struct v4l2_dv_preset {
>> + __u32 preset;
>> + __u32 reserved[4];
>> +};
>> +
>> +/*
>> + * D V P R E S E T S E N U M E R A T I O N
>> + */
>> +struct v4l2_dv_enum_preset {
>> + __u32 index;
>> + __u32 preset;
>> + __u8 name[32]; /* Name of the preset timing */
>> + __u32 width;
>> + __u32 height;
>> + __u32 reserved[4];
>> +};
>> +
>> +/*
>> + * D V P R E S E T V A L U E S
>> + */
>> +#define V4L2_DV_PRESET_BASE 0x00000000
>
>Why do we need a PRESET_BASE define? I'd just start counting at 0.
>
>> +#define V4L2_DV_INVALID (V4L2_DV_PRESET_BASE + 0)
>> +/* BT.1362 */
>
>Append this define at the end of the previous line. Without the PRESET_BASE
>there is enough room for it.
>
>> +#define V4L2_DV_480P59_94 (V4L2_DV_PRESET_BASE + 1)
>> +/* BT.1362 */
>> +#define V4L2_DV_576P50 (V4L2_DV_PRESET_BASE + 2)
>> +/* SMPTE 296M */
>> +#define V4L2_DV_720P24 (V4L2_DV_PRESET_BASE + 3)
>> +/* SMPTE 296M */
>> +#define V4L2_DV_720P25 (V4L2_DV_PRESET_BASE + 4)
>> +/* SMPTE 296M */
>> +#define V4L2_DV_720P30 (V4L2_DV_PRESET_BASE + 5)
>> +/* SMPTE 296M */
>> +#define V4L2_DV_720P50 (V4L2_DV_PRESET_BASE + 6)
>> +/* SMPTE 274M */
>> +#define V4L2_DV_720P59_94 (V4L2_DV_PRESET_BASE + 7)
>> +/* SMPTE 274M/296M */
>> +#define V4L2_DV_720P60 (V4L2_DV_PRESET_BASE + 8)
>> +/* BT.1120/ SMPTE 274M */
>> +#define V4L2_DV_1080I29_97 (V4L2_DV_PRESET_BASE + 9)
>> +/* BT.1120/ SMPTE 274M */
>> +#define V4L2_DV_1080I30 (V4L2_DV_PRESET_BASE + 10)
>> +/* BT.1120 */
>> +#define V4L2_DV_1080I25 (V4L2_DV_PRESET_BASE + 11)
>> +/* SMPTE 296M */
>> +#define V4L2_DV_1080I50 (V4L2_DV_PRESET_BASE + 12)
>> +/* SMPTE 296M */
>> +#define V4L2_DV_1080I60 (V4L2_DV_PRESET_BASE + 13)
>> +/* SMPTE 296M */
>> +#define V4L2_DV_1080P24 (V4L2_DV_PRESET_BASE + 14)
>> +/* SMPTE 296M */
>> +#define V4L2_DV_1080P25 (V4L2_DV_PRESET_BASE + 15)
>> +/* SMPTE 296M */
>> +#define V4L2_DV_1080P30 (V4L2_DV_PRESET_BASE + 16)
>> +/* BT.1120 */
>> +#define V4L2_DV_1080P50 (V4L2_DV_PRESET_BASE + 17)
>> +/* BT.1120 */
>> +#define V4L2_DV_1080P60 (V4L2_DV_PRESET_BASE + 18)
>> +
>> +/*
>> + * D V B T T I M I N G S
>> + */
>> +
>> +/* BT.656/BT.1120 timing data */
>> +struct v4l2_bt_timings {
>> + __u32 width; /* width in pixels */
>> + __u32 height; /* height in lines */
>> + __u32 interlaced; /* Interlaced or progressive */
>> + __u32 polarities; /* Positive or negative polarity */
>> + __u64 pixelclock; /* Pixel clock in HZ. Ex. 74.25MHz->74250000 */
>> + __u32 hfrontporch; /* Horizpontal front porch in pixels */
>> + __u32 hsync; /* Horizontal Sync length in pixels */
>> + __u32 hbackporch; /* Horizontal back porch in pixels */
>> + __u32 vfrontporch; /* Vertical front porch in pixels */
>> + __u32 vsync; /* Vertical Sync length in lines */
>> + __u32 vbackporch; /* Vertical back porch in lines */
>> + __u32 il_vfrontporch; /* Vertical front porch for bottom field of
>> + * interlaced field formats
>> + */
>> + __u32 il_vsync; /* Vertical sync length for bottom field of
>> + * interlaced field formats
>> + */
>> + __u32 il_vbackporch; /* Vertical back porch for bottom field of
>> + * interlaced field formats
>> + */
>> + __u32 reserved[16];
>> +};
>> +
>> +/* Interlaced or progressive format */
>> +#define V4L2_DV_PROGRESSIVE 0
>> +#define V4L2_DV_INTERLACED 1
>> +
>> +/* Polarities. If bit is not set, it is assumed to be negative polarity
>*/
>> +#define V4L2_DV_VSYNC_POS_POL 0x00000001
>> +#define V4L2_DV_HSYNC_POS_POL 0x00000002
>> +
>> +/* BT.656/1120 timing type */
>> +enum v4l2_dv_timings_type {
>> + V4L2_DV_BT_656_1120,
>> +};
>
>I forgot something: we shouldn't use enums as that can give problems on
>some
>architectures (ARM being one of them, I believe). So this should become a
>define and the type field below a __u32.
>
>> +
>> +/* DV timings */
>> +struct v4l2_dv_timings {
>> + enum v4l2_dv_timings_type type;
>> + union {
>> + struct v4l2_bt_timings bt;
>> + __u32 reserved[32];
>> + };
>> +};
>> +
>> +/*
>> * V I D E O I N P U T S
>> */
>> struct v4l2_input {
>> @@ -741,7 +854,8 @@ struct v4l2_input {
>> __u32 tuner; /* Associated tuner */
>> v4l2_std_id std;
>> __u32 status;
>> - __u32 reserved[4];
>> + __u32 capabilities;
>> + __u32 reserved[3];
>> };
>>
>> /* Values for the 'type' field */
>> @@ -772,6 +886,11 @@ struct v4l2_input {
>> #define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied
>*/
>> #define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */
>>
>> +/* capabilities flags */
>> +#define V4L2_IN_CAP_PRESETS 0x00000001 /* Supports DV_PRESETS
>*/
>> +#define V4L2_IN_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports Custom
>timings */
>> +#define V4L2_IN_CAP_STD 0x00000004 /* Supports STD */
>
>I suggest changing the comments to "Supports S_DV_PRESET",
>"Support S_DV_TIMINGS" and "Support S_STD". That's a bit more consistent
>and
>it is also clear that the capability refers to whether an ioctl is
>supported
>or not for that particular input.
>
>> +
>> /*
>> * V I D E O O U T P U T S
>> */
>> @@ -782,13 +901,19 @@ struct v4l2_output {
>> __u32 audioset; /* Associated audios (bitfield) */
>> __u32 modulator; /* Associated modulator */
>> v4l2_std_id std;
>> - __u32 reserved[4];
>> + __u32 capabilities;
>> + __u32 reserved[3];
>> };
>> /* Values for the 'type' field */
>> #define V4L2_OUTPUT_TYPE_MODULATOR 1
>> #define V4L2_OUTPUT_TYPE_ANALOG 2
>> #define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3
>>
>> +/* capabilities flags */
>> +#define V4L2_OUT_CAP_PRESETS 0x00000001 /* Supports DV_PRESETS
>*/
>> +#define V4L2_OUT_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports Custom
>timings */
>> +#define V4L2_OUT_CAP_STD 0x00000004 /* Supports STD */
>
>Ditto.
>
>> +
>> /*
>> * C O N T R O L S
>> */
>> @@ -1621,6 +1746,13 @@ struct v4l2_dbg_chip_ident {
>> #endif
>>
>> #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct
>v4l2_hw_freq_seek)
>> +#define VIDIOC_ENUM_DV_PRESETS _IOWR('V', 83, struct
>v4l2_dv_enum_preset)
>> +#define VIDIOC_S_DV_PRESET _IOWR('V', 84, struct v4l2_dv_preset)
>> +#define VIDIOC_G_DV_PRESET _IOWR('V', 85, struct v4l2_dv_preset)
>> +#define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct v4l2_dv_preset)
>> +#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings)
>> +#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings)
>> +
>> /* Reminder: when adding new ioctls please add support for them to
>> drivers/media/video/v4l2-compat-ioctl32.c as well! */
>>
>> diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
>> index 7a4529d..e8ba0f2 100644
>> --- a/include/media/v4l2-ioctl.h
>> +++ b/include/media/v4l2-ioctl.h
>> @@ -239,6 +239,21 @@ struct v4l2_ioctl_ops {
>> int (*vidioc_enum_frameintervals) (struct file *file, void *fh,
>> struct v4l2_frmivalenum *fival);
>>
>> + /* DV Timings IOCTLs */
>> + int (*vidioc_enum_dv_presets) (struct file *file, void *fh,
>> + struct v4l2_dv_enum_preset *preset);
>> +
>> + int (*vidioc_s_dv_preset) (struct file *file, void *fh,
>> + struct v4l2_dv_preset *preset);
>> + int (*vidioc_g_dv_preset) (struct file *file, void *fh,
>> + struct v4l2_dv_preset *preset);
>> + int (*vidioc_query_dv_preset) (struct file *file, void *fh,
>> + struct v4l2_dv_preset *qpreset);
>> + int (*vidioc_s_dv_timings) (struct file *file, void *fh,
>> + struct v4l2_dv_timings *timings);
>> + int (*vidioc_g_dv_timings) (struct file *file, void *fh,
>> + struct v4l2_dv_timings *timings);
>> +
>> /* For other private ioctls */
>> long (*vidioc_default) (struct file *file, void *fh,
>> int cmd, void *arg);
>> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
>> index 88c13d6..92634da 100644
>> --- a/include/media/v4l2-subdev.h
>> +++ b/include/media/v4l2-subdev.h
>> @@ -217,6 +217,19 @@ struct v4l2_subdev_audio_ops {
>>
>> s_routing: see s_routing in audio_ops, except this version is for
>video
>> devices.
>> +
>> + s_dv_preset: set dv (Digital Video) preset in the sub device. Similar
>to
>> + s_std()
>> +
>> + query_dv_preset: query dv preset in the sub device. This is similar
>to
>> + querystd()
>> +
>> + s_dv_timings(): Set custom dv timings in the sub device. This is used
>> + when sub device is capable of setting detailed timing information
>> + in the hardware to generate/detect the video signal.
>> +
>> + g_dv_timings(): Get custom dv timings in the sub device.
>> +
>> */
>> struct v4l2_subdev_video_ops {
>> int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32
>config);
>> @@ -240,6 +253,14 @@ struct v4l2_subdev_video_ops {
>> int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
>> int (*enum_framesizes)(struct v4l2_subdev *sd, struct
>v4l2_frmsizeenum *fsize);
>> int (*enum_frameintervals)(struct v4l2_subdev *sd, struct
>v4l2_frmivalenum *fival);
>> + int (*s_dv_preset)(struct v4l2_subdev *sd,
>> + struct v4l2_dv_preset *preset);
>> + int (*query_dv_preset)(struct v4l2_subdev *sd,
>> + struct v4l2_dv_preset *preset);
>> + int (*s_dv_timings)(struct v4l2_subdev *sd,
>> + struct v4l2_dv_timings *timings);
>> + int (*g_dv_timings)(struct v4l2_subdev *sd,
>> + struct v4l2_dv_timings *timings);
>> };
>>
>> /*
>
>Regards,
>
> Hans
>
>PS: If I have time (no guarantees!), then I'll try to do some 64-bit
>testing
>this weekend.
>
>--
>Hans Verkuil - video4linux developer - sponsored by TANDBERG Telecom
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
@@ -1077,6 +1077,13 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
case VIDIOC_DBG_G_REGISTER:
case VIDIOC_DBG_G_CHIP_IDENT:
case VIDIOC_S_HW_FREQ_SEEK:
+ case VIDIOC_ENUM_DV_PRESETS:
+ case VIDIOC_S_DV_PRESET:
+ case VIDIOC_G_DV_PRESET:
+ case VIDIOC_QUERY_DV_PRESET:
+ case VIDIOC_S_DV_TIMINGS:
+ case VIDIOC_G_DV_TIMINGS:
+
ret = do_video_ioctl(file, cmd, arg);
break;
@@ -284,6 +284,12 @@ static const char *v4l2_ioctls[] = {
[_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
[_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
#endif
+ [_IOC_NR(VIDIOC_ENUM_DV_PRESETS)] = "VIDIOC_ENUM_DV_PRESETS",
+ [_IOC_NR(VIDIOC_S_DV_PRESET)] = "VIDIOC_S_DV_PRESET",
+ [_IOC_NR(VIDIOC_G_DV_PRESET)] = "VIDIOC_G_DV_PRESET",
+ [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET",
+ [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS",
+ [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS",
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
@@ -1135,6 +1141,19 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_input *p = arg;
+ /**
+ * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
+ * CAP_STD here based on ioctl handler provided by the
+ * driver. If the driver doesn't support these
+ * for a specific input, it must override these flags.
+ */
+ if (ops->vidioc_s_std)
+ p->capabilities |= V4L2_IN_CAP_STD;
+ if (ops->vidioc_s_dv_preset)
+ p->capabilities |= V4L2_IN_CAP_PRESETS;
+ if (ops->vidioc_s_dv_timings)
+ p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
+
if (!ops->vidioc_enum_input)
break;
@@ -1179,6 +1198,19 @@ static long __video_do_ioctl(struct file *file,
if (!ops->vidioc_enum_output)
break;
+ /**
+ * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
+ * CAP_STD here based on ioctl handler provided by the
+ * driver. If the driver doesn't support these
+ * for a specific output , it must override these flags.
+ */
+ if (ops->vidioc_s_std)
+ p->capabilities |= V4L2_OUT_CAP_STD;
+ if (ops->vidioc_s_dv_preset)
+ p->capabilities |= V4L2_OUT_CAP_PRESETS;
+ if (ops->vidioc_s_dv_timings)
+ p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS;
+
ret = ops->vidioc_enum_output(file, fh, p);
if (!ret)
dbgarg(cmd, "index=%d, name=%s, type=%d, "
@@ -1794,6 +1826,122 @@ static long __video_do_ioctl(struct file *file,
}
break;
}
+ case VIDIOC_ENUM_DV_PRESETS:
+ {
+ struct v4l2_dv_enum_preset *p = arg;
+
+ if (!ops->vidioc_enum_dv_presets)
+ break;
+
+ ret = ops->vidioc_enum_dv_presets(file, fh, p);
+ if (!ret)
+ dbgarg(cmd,
+ "index=%d, preset=%d, name=%s, width=%d,"
+ " height=%d ",
+ p->index, p->preset, p->name, p->width,
+ p->height);
+ break;
+ }
+ case VIDIOC_S_DV_PRESET:
+ {
+ struct v4l2_dv_preset *p = arg;
+
+ if (!ops->vidioc_s_dv_preset)
+ break;
+
+ dbgarg(cmd, "preset=%d\n", p->preset);
+ ret = ops->vidioc_s_dv_preset(file, fh, p);
+ break;
+ }
+ case VIDIOC_G_DV_PRESET:
+ {
+ struct v4l2_dv_preset *p = arg;
+
+ if (!ops->vidioc_g_dv_preset)
+ break;
+
+ ret = ops->vidioc_g_dv_preset(file, fh, p);
+ if (!ret)
+ dbgarg(cmd, "preset=%d\n", p->preset);
+ break;
+ }
+ case VIDIOC_QUERY_DV_PRESET:
+ {
+ struct v4l2_dv_preset *p = arg;
+
+ if (!ops->vidioc_query_dv_preset)
+ break;
+
+ ret = ops->vidioc_query_dv_preset(file, fh, p);
+ if (!ret)
+ dbgarg(cmd, "preset=%d\n", p->preset);
+ break;
+ }
+ case VIDIOC_S_DV_TIMINGS:
+ {
+ struct v4l2_dv_timings *p = arg;
+
+ if (!ops->vidioc_s_dv_timings)
+ break;
+
+ dbgarg(cmd, "type=%d", p->type);
+ switch (p->type) {
+ case V4L2_DV_BT_656_1120:
+ dbgarg2("interlaced=%d, pixelclock=%lld,"
+ " width=%d, height=%d, polarities=%x,"
+ " hfrontporch=%d, hsync=%d, hbackporch=%d,"
+ " vfrontporch=%d, vsync=%d, vbackporch=%d,"
+ " il_vfrontporch=%d, il_vsync=%d,"
+ " il_vbackporch=%d\n",
+ p->bt.interlaced, p->bt.pixelclock,
+ p->bt.width, p->bt.height, p->bt.polarities,
+ p->bt.hfrontporch, p->bt.hsync,
+ p->bt.hbackporch, p->bt.vfrontporch,
+ p->bt.vsync, p->bt.vbackporch,
+ p->bt.il_vfrontporch, p->bt.il_vsync,
+ p->bt.il_vbackporch);
+ ret = ops->vidioc_s_dv_timings(file, fh, p);
+ break;
+ default:
+ dbgarg2("- Unknown type!\n");
+ break;
+ }
+ break;
+ }
+ case VIDIOC_G_DV_TIMINGS:
+ {
+ struct v4l2_dv_timings *p = arg;
+
+ if (!ops->vidioc_g_dv_timings)
+ break;
+
+ dbgarg(cmd, "type=%d", p->type);
+ ret = ops->vidioc_g_dv_timings(file, fh, p);
+ if (!ret) {
+ switch (p->type) {
+ case V4L2_DV_BT_656_1120:
+ dbgarg2("interlaced=%d, pixelclock=%lld,"
+ " width=%d, height=%d, polarities=%x,"
+ " hfrontporch=%d, hsync=%d,"
+ " hbackporch=%d, vfrontporch=%d,"
+ " vsync=%d, vbackporch=%d,"
+ " il_vfrontporch=%d, il_vsync=%d,"
+ " il_vbackporch=%d\n",
+ p->bt.interlaced, p->bt.pixelclock,
+ p->bt.width, p->bt.height,
+ p->bt.polarities, p->bt.hfrontporch,
+ p->bt.hsync, p->bt.hbackporch,
+ p->bt.vfrontporch, p->bt.vsync,
+ p->bt.vbackporch, p->bt.il_vfrontporch,
+ p->bt.il_vsync, p->bt.il_vbackporch);
+ break;
+ default:
+ dbgarg2("- Unknown type!\n");
+ break;
+ }
+ }
+ break;
+ }
default:
{
@@ -731,6 +731,119 @@ struct v4l2_standard {
};
/*
+ * V I D E O T I M I N G S D V P R E S E T
+ */
+struct v4l2_dv_preset {
+ __u32 preset;
+ __u32 reserved[4];
+};
+
+/*
+ * D V P R E S E T S E N U M E R A T I O N
+ */
+struct v4l2_dv_enum_preset {
+ __u32 index;
+ __u32 preset;
+ __u8 name[32]; /* Name of the preset timing */
+ __u32 width;
+ __u32 height;
+ __u32 reserved[4];
+};
+
+/*
+ * D V P R E S E T V A L U E S
+ */
+#define V4L2_DV_PRESET_BASE 0x00000000
+#define V4L2_DV_INVALID (V4L2_DV_PRESET_BASE + 0)
+/* BT.1362 */
+#define V4L2_DV_480P59_94 (V4L2_DV_PRESET_BASE + 1)
+/* BT.1362 */
+#define V4L2_DV_576P50 (V4L2_DV_PRESET_BASE + 2)
+/* SMPTE 296M */
+#define V4L2_DV_720P24 (V4L2_DV_PRESET_BASE + 3)
+/* SMPTE 296M */
+#define V4L2_DV_720P25 (V4L2_DV_PRESET_BASE + 4)
+/* SMPTE 296M */
+#define V4L2_DV_720P30 (V4L2_DV_PRESET_BASE + 5)
+/* SMPTE 296M */
+#define V4L2_DV_720P50 (V4L2_DV_PRESET_BASE + 6)
+/* SMPTE 274M */
+#define V4L2_DV_720P59_94 (V4L2_DV_PRESET_BASE + 7)
+/* SMPTE 274M/296M */
+#define V4L2_DV_720P60 (V4L2_DV_PRESET_BASE + 8)
+/* BT.1120/ SMPTE 274M */
+#define V4L2_DV_1080I29_97 (V4L2_DV_PRESET_BASE + 9)
+/* BT.1120/ SMPTE 274M */
+#define V4L2_DV_1080I30 (V4L2_DV_PRESET_BASE + 10)
+/* BT.1120 */
+#define V4L2_DV_1080I25 (V4L2_DV_PRESET_BASE + 11)
+/* SMPTE 296M */
+#define V4L2_DV_1080I50 (V4L2_DV_PRESET_BASE + 12)
+/* SMPTE 296M */
+#define V4L2_DV_1080I60 (V4L2_DV_PRESET_BASE + 13)
+/* SMPTE 296M */
+#define V4L2_DV_1080P24 (V4L2_DV_PRESET_BASE + 14)
+/* SMPTE 296M */
+#define V4L2_DV_1080P25 (V4L2_DV_PRESET_BASE + 15)
+/* SMPTE 296M */
+#define V4L2_DV_1080P30 (V4L2_DV_PRESET_BASE + 16)
+/* BT.1120 */
+#define V4L2_DV_1080P50 (V4L2_DV_PRESET_BASE + 17)
+/* BT.1120 */
+#define V4L2_DV_1080P60 (V4L2_DV_PRESET_BASE + 18)
+
+/*
+ * D V B T T I M I N G S
+ */
+
+/* BT.656/BT.1120 timing data */
+struct v4l2_bt_timings {
+ __u32 width; /* width in pixels */
+ __u32 height; /* height in lines */
+ __u32 interlaced; /* Interlaced or progressive */
+ __u32 polarities; /* Positive or negative polarity */
+ __u64 pixelclock; /* Pixel clock in HZ. Ex. 74.25MHz->74250000 */
+ __u32 hfrontporch; /* Horizpontal front porch in pixels */
+ __u32 hsync; /* Horizontal Sync length in pixels */
+ __u32 hbackporch; /* Horizontal back porch in pixels */
+ __u32 vfrontporch; /* Vertical front porch in pixels */
+ __u32 vsync; /* Vertical Sync length in lines */
+ __u32 vbackporch; /* Vertical back porch in lines */
+ __u32 il_vfrontporch; /* Vertical front porch for bottom field of
+ * interlaced field formats
+ */
+ __u32 il_vsync; /* Vertical sync length for bottom field of
+ * interlaced field formats
+ */
+ __u32 il_vbackporch; /* Vertical back porch for bottom field of
+ * interlaced field formats
+ */
+ __u32 reserved[16];
+};
+
+/* Interlaced or progressive format */
+#define V4L2_DV_PROGRESSIVE 0
+#define V4L2_DV_INTERLACED 1
+
+/* Polarities. If bit is not set, it is assumed to be negative polarity */
+#define V4L2_DV_VSYNC_POS_POL 0x00000001
+#define V4L2_DV_HSYNC_POS_POL 0x00000002
+
+/* BT.656/1120 timing type */
+enum v4l2_dv_timings_type {
+ V4L2_DV_BT_656_1120,
+};
+
+/* DV timings */
+struct v4l2_dv_timings {
+ enum v4l2_dv_timings_type type;
+ union {
+ struct v4l2_bt_timings bt;
+ __u32 reserved[32];
+ };
+};
+
+/*
* V I D E O I N P U T S
*/
struct v4l2_input {
@@ -741,7 +854,8 @@ struct v4l2_input {
__u32 tuner; /* Associated tuner */
v4l2_std_id std;
__u32 status;
- __u32 reserved[4];
+ __u32 capabilities;
+ __u32 reserved[3];
};
/* Values for the 'type' field */
@@ -772,6 +886,11 @@ struct v4l2_input {
#define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */
#define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */
+/* capabilities flags */
+#define V4L2_IN_CAP_PRESETS 0x00000001 /* Supports DV_PRESETS */
+#define V4L2_IN_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports Custom timings */
+#define V4L2_IN_CAP_STD 0x00000004 /* Supports STD */
+
/*
* V I D E O O U T P U T S
*/
@@ -782,13 +901,19 @@ struct v4l2_output {
__u32 audioset; /* Associated audios (bitfield) */
__u32 modulator; /* Associated modulator */
v4l2_std_id std;
- __u32 reserved[4];
+ __u32 capabilities;
+ __u32 reserved[3];
};
/* Values for the 'type' field */
#define V4L2_OUTPUT_TYPE_MODULATOR 1
#define V4L2_OUTPUT_TYPE_ANALOG 2
#define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3
+/* capabilities flags */
+#define V4L2_OUT_CAP_PRESETS 0x00000001 /* Supports DV_PRESETS */
+#define V4L2_OUT_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports Custom timings */
+#define V4L2_OUT_CAP_STD 0x00000004 /* Supports STD */
+
/*
* C O N T R O L S
*/
@@ -1621,6 +1746,13 @@ struct v4l2_dbg_chip_ident {
#endif
#define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek)
+#define VIDIOC_ENUM_DV_PRESETS _IOWR('V', 83, struct v4l2_dv_enum_preset)
+#define VIDIOC_S_DV_PRESET _IOWR('V', 84, struct v4l2_dv_preset)
+#define VIDIOC_G_DV_PRESET _IOWR('V', 85, struct v4l2_dv_preset)
+#define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct v4l2_dv_preset)
+#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings)
+#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings)
+
/* Reminder: when adding new ioctls please add support for them to
drivers/media/video/v4l2-compat-ioctl32.c as well! */
@@ -239,6 +239,21 @@ struct v4l2_ioctl_ops {
int (*vidioc_enum_frameintervals) (struct file *file, void *fh,
struct v4l2_frmivalenum *fival);
+ /* DV Timings IOCTLs */
+ int (*vidioc_enum_dv_presets) (struct file *file, void *fh,
+ struct v4l2_dv_enum_preset *preset);
+
+ int (*vidioc_s_dv_preset) (struct file *file, void *fh,
+ struct v4l2_dv_preset *preset);
+ int (*vidioc_g_dv_preset) (struct file *file, void *fh,
+ struct v4l2_dv_preset *preset);
+ int (*vidioc_query_dv_preset) (struct file *file, void *fh,
+ struct v4l2_dv_preset *qpreset);
+ int (*vidioc_s_dv_timings) (struct file *file, void *fh,
+ struct v4l2_dv_timings *timings);
+ int (*vidioc_g_dv_timings) (struct file *file, void *fh,
+ struct v4l2_dv_timings *timings);
+
/* For other private ioctls */
long (*vidioc_default) (struct file *file, void *fh,
int cmd, void *arg);
@@ -217,6 +217,19 @@ struct v4l2_subdev_audio_ops {
s_routing: see s_routing in audio_ops, except this version is for video
devices.
+
+ s_dv_preset: set dv (Digital Video) preset in the sub device. Similar to
+ s_std()
+
+ query_dv_preset: query dv preset in the sub device. This is similar to
+ querystd()
+
+ s_dv_timings(): Set custom dv timings in the sub device. This is used
+ when sub device is capable of setting detailed timing information
+ in the hardware to generate/detect the video signal.
+
+ g_dv_timings(): Get custom dv timings in the sub device.
+
*/
struct v4l2_subdev_video_ops {
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
@@ -240,6 +253,14 @@ struct v4l2_subdev_video_ops {
int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize);
int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival);
+ int (*s_dv_preset)(struct v4l2_subdev *sd,
+ struct v4l2_dv_preset *preset);
+ int (*query_dv_preset)(struct v4l2_subdev *sd,
+ struct v4l2_dv_preset *preset);
+ int (*s_dv_timings)(struct v4l2_subdev *sd,
+ struct v4l2_dv_timings *timings);
+ int (*g_dv_timings)(struct v4l2_subdev *sd,
+ struct v4l2_dv_timings *timings);
};
/*