From: Muralidharan Karicheri <m-kariche...@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-kariche...@ti.com>
Reviewed-by: Hans Verkuil <hverk...@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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to