[v2] V4L - Adding Digital Video Timings APIs

Message ID 1258563824-1310-1-git-send-email-m-karicheri2@ti.com (mailing list archive)
State Superseded, archived
Headers

Commit Message

m-karicheri2@ti.com Nov. 18, 2009, 5:03 p.m. UTC
  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

m-karicheri2@ti.com Nov. 18, 2009, 5:06 p.m. UTC | #1
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
  
Hans Verkuil Nov. 18, 2009, 6:08 p.m. UTC | #2
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.
  
m-karicheri2@ti.com Nov. 18, 2009, 7:01 p.m. UTC | #3
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
  

Patch

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);
 };
 
 /*