- add new tuning option for card(
    V4L2_MPEG_VIDEO_ENCODING_H263
    ,V4L2_CID_MPEG_VIDEO_B_FRAMES)
- add framesizes&frameintervals control
- tested&realize motion detector control(
    GO7007IOC_REGION_NUMBER
    ,GO7007IOC_PIXEL_THRESOLD
    ,GO7007IOC_MOTION_THRESOLD
    ,GO7007IOC_TRIGGER
    ,GO7007IOC_REGION_CONTROL
    ,GO7007IOC_CLIP_LEFT
    ,GO7007IOC_CLIP_TOP
    ,GO7007IOC_CLIP_WIDTH
    ,GO7007IOC_CLIP_HEIGHT)

Tested with  Angelo PCI-MPG24(Adlink) with go7007&tw2804 onboard
Regards Volokh

diff -uprN -X linux-3.2.11-vanilla/Documentation/dontdiff 
linux-3.2.11-vanilla/drivers/staging/media/go7007/go7007.h 
linux-3.2.11/drivers/staging/media/go7007/go7007.h
--- linux-3.2.11-vanilla/drivers/staging/media/go7007/go7007.h  2012-03-13 
21:05:09.000000000 +0400
+++ linux-3.2.11/drivers/staging/media/go7007/go7007.h  2012-03-20 
16:17:26.095901486 +0400
@@ -21,12 +21,27 @@
  * to select between MPEG1, MPEG2, and MPEG4 */
 #define V4L2_PIX_FMT_MPEG4     v4l2_fourcc('M', 'P', 'G', '4') /* MPEG4 */
 
+/* Temporary defines until accepted in v4l2-api (videodev2.h) */
+#ifndef V4L2_MPEG_STREAM_TYPE_MPEG_ELEM
+  #define V4L2_MPEG_STREAM_TYPE_MPEG_ELEM   6 /* MPEG elementary stream */
+#endif
+#ifndef V4L2_MPEG_VIDEO_ENCODING_MPEG_4
+  #define V4L2_MPEG_VIDEO_ENCODING_MPEG_4   3
+#endif
+
+#ifndef V4L2_MPEG_VIDEO_ENCODING_H263
+  #define V4L2_MPEG_VIDEO_ENCODING_H263     4
+#endif
+
+///deprecated defs
+#if 0
 /* These will be replaced with a better interface
  * soon, so don't get too attached to them */
 #define        GO7007IOC_S_BITRATE     _IOW('V', BASE_VIDIOC_PRIVATE + 0, int)
 #define        GO7007IOC_G_BITRATE     _IOR('V', BASE_VIDIOC_PRIVATE + 1, int)
 
-enum go7007_aspect_ratio {
+enum go7007_aspect_ratio
+{
        GO7007_ASPECT_RATIO_1_1 = 0,
        GO7007_ASPECT_RATIO_4_3_NTSC = 1,
        GO7007_ASPECT_RATIO_4_3_PAL = 2,
@@ -35,7 +50,8 @@ enum go7007_aspect_ratio {
 };
 
 /* Used to set generic compression parameters */
-struct go7007_comp_params {
+struct go7007_comp_params
+{
        __u32 gop_size;
        __u32 max_b_frames;
        enum go7007_aspect_ratio aspect_ratio;
@@ -46,14 +62,16 @@ struct go7007_comp_params {
 #define GO7007_COMP_CLOSED_GOP         0x00000001
 #define GO7007_COMP_OMIT_SEQ_HEADER    0x00000002
 
-enum go7007_mpeg_video_standard {
+enum go7007_mpeg_video_standard
+{
        GO7007_MPEG_VIDEO_MPEG1 = 0,
        GO7007_MPEG_VIDEO_MPEG2 = 1,
        GO7007_MPEG_VIDEO_MPEG4 = 2,
 };
 
 /* Used to set parameters for V4L2_PIX_FMT_MPEG format */
-struct go7007_mpeg_params {
+struct go7007_mpeg_params
+{
        enum go7007_mpeg_video_standard mpeg_video_standard;
        __u32 flags;
        __u32 pali;
@@ -83,21 +101,6 @@ struct go7007_mpeg_params {
 #define GO7007_MPEG4_PROFILE_AS_L4             GO7007_MPEG_PROFILE(4, 0xf4)
 #define GO7007_MPEG4_PROFILE_AS_L5             GO7007_MPEG_PROFILE(4, 0xf5)
 
-struct go7007_md_params {
-       __u16 region;
-       __u16 trigger;
-       __u16 pixel_threshold;
-       __u16 motion_threshold;
-       __u32 reserved[8];
-};
-
-struct go7007_md_region {
-       __u16 region;
-       __u16 flags;
-       struct v4l2_clip *clips;
-       __u32 reserved[8];
-};
-
 #define        GO7007IOC_S_MPEG_PARAMS _IOWR('V', BASE_VIDIOC_PRIVATE + 2, \
                                        struct go7007_mpeg_params)
 #define        GO7007IOC_G_MPEG_PARAMS _IOR('V', BASE_VIDIOC_PRIVATE + 3, \
@@ -112,3 +115,38 @@ struct go7007_md_region {
                                        struct go7007_md_params)
 #define        GO7007IOC_S_MD_REGION   _IOW('V', BASE_VIDIOC_PRIVATE + 8, \
                                        struct go7007_md_region)
+#endif
+
+struct go7007_md_params
+{
+  __u16 region;
+  __u16 trigger;
+  __u16 pixel_threshold;
+  __u16 motion_threshold;
+  __u32 reserved[8];
+};
+
+struct go7007_md_region
+{
+  __u16 region;
+  __u16 flags;
+  struct v4l2_clip *clips;
+  __u32 reserved[8];
+};
+
+#define GO7007IOC_REGION_NUMBER V4L2_CID_PRIVATE_BASE
+#define GO7007IOC_PIXEL_THRESOLD V4L2_CID_PRIVATE_BASE+1
+#define GO7007IOC_MOTION_THRESOLD V4L2_CID_PRIVATE_BASE+2
+#define GO7007IOC_TRIGGER V4L2_CID_PRIVATE_BASE+3
+#define GO7007IOC_REGION_CONTROL V4L2_CID_PRIVATE_BASE+4
+#define GO7007IOC_CLIP_LEFT V4L2_CID_PRIVATE_BASE+5
+#define GO7007IOC_CLIP_TOP V4L2_CID_PRIVATE_BASE+6
+#define GO7007IOC_CLIP_WIDTH V4L2_CID_PRIVATE_BASE+7
+#define GO7007IOC_CLIP_HEIGHT V4L2_CID_PRIVATE_BASE+8
+
+enum RegionControl
+{
+  rcAdd=0
+  ,rcDelete=1
+  ,rcClear=2
+};
diff -uprN -X linux-3.2.11-vanilla/Documentation/dontdiff 
linux-3.2.11-vanilla/drivers/staging/media/go7007/go7007-priv.h 
linux-3.2.11/drivers/staging/media/go7007/go7007-priv.h
--- linux-3.2.11-vanilla/drivers/staging/media/go7007/go7007-priv.h     
2012-03-13 21:05:09.000000000 +0400
+++ linux-3.2.11/drivers/staging/media/go7007/go7007-priv.h     2012-03-20 
16:17:58.246497298 +0400
@@ -215,7 +215,8 @@ struct go7007 {
        } modet[4];
        unsigned char modet_map[1624];
        unsigned char active_map[216];
-
+  struct v4l2_rect fClipRegion;
+  unsigned char fCurrentRegion:2;
        /* Video streaming */
        struct go7007_buffer *active_buf;
        enum go7007_parser_state state;
diff -uprN -X linux-3.2.11-vanilla/Documentation/dontdiff 
linux-3.2.11-vanilla/drivers/staging/media/go7007/go7007-v4l2.c 
linux-3.2.11/drivers/staging/media/go7007/go7007-v4l2.c
--- linux-3.2.11-vanilla/drivers/staging/media/go7007/go7007-v4l2.c     
2012-03-13 21:05:09.000000000 +0400
+++ linux-3.2.11/drivers/staging/media/go7007/go7007-v4l2.c     2012-03-20 
16:17:51.181586119 +0400
@@ -335,114 +335,390 @@ static int set_capture_size(struct go700
        return 0;
 }
 
-#if 0
-static int clip_to_modet_map(struct go7007 *go, int region,
-               struct v4l2_clip *clip_list)
-{
-       struct v4l2_clip clip, *clip_ptr;
-       int x, y, mbnum;
-
-       /* Check if coordinates are OK and if any macroblocks are already
-        * used by other regions (besides 0) */
-       clip_ptr = clip_list;
-       while (clip_ptr) {
-               if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
-                       return -EFAULT;
-               if (clip.c.left < 0 || (clip.c.left & 0xF) ||
-                               clip.c.width <= 0 || (clip.c.width & 0xF))
-                       return -EINVAL;
-               if (clip.c.left + clip.c.width > go->width)
-                       return -EINVAL;
-               if (clip.c.top < 0 || (clip.c.top & 0xF) ||
-                               clip.c.height <= 0 || (clip.c.height & 0xF))
-                       return -EINVAL;
-               if (clip.c.top + clip.c.height > go->height)
-                       return -EINVAL;
-               for (y = 0; y < clip.c.height; y += 16)
-                       for (x = 0; x < clip.c.width; x += 16) {
-                               mbnum = (go->width >> 4) *
-                                               ((clip.c.top + y) >> 4) +
-                                       ((clip.c.left + x) >> 4);
-                               if (go->modet_map[mbnum] != 0 &&
-                                               go->modet_map[mbnum] != region)
-                                       return -EBUSY;
-                       }
-               clip_ptr = clip.next;
-       }
-
-       /* Clear old region macroblocks */
-       for (mbnum = 0; mbnum < 1624; ++mbnum)
-               if (go->modet_map[mbnum] == region)
-                       go->modet_map[mbnum] = 0;
-
-       /* Claim macroblocks in this list */
-       clip_ptr = clip_list;
-       while (clip_ptr) {
-               if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
-                       return -EFAULT;
-               for (y = 0; y < clip.c.height; y += 16)
-                       for (x = 0; x < clip.c.width; x += 16) {
-                               mbnum = (go->width >> 4) *
-                                               ((clip.c.top + y) >> 4) +
-                                       ((clip.c.left + x) >> 4);
-                               go->modet_map[mbnum] = region;
-                       }
-               clip_ptr = clip.next;
-       }
-       return 0;
+static int md_g_ctrl(struct v4l2_control *ctrl,struct go7007 *go)
+{
+  switch(ctrl->id)
+  {
+    case GO7007IOC_REGION_NUMBER:
+      ctrl->value=go->fCurrentRegion;
+      break;
+    case GO7007IOC_PIXEL_THRESOLD:
+      ctrl->value=(go->modet[go->fCurrentRegion].pixel_threshold<<1)+1;
+      break;
+    case GO7007IOC_MOTION_THRESOLD:
+      ctrl->value=(go->modet[go->fCurrentRegion].motion_threshold<<1)+1;
+      break;
+    case GO7007IOC_TRIGGER:
+      ctrl->value=(go->modet[go->fCurrentRegion].mb_threshold<<1)+1;
+      break;
+    case GO7007IOC_CLIP_LEFT:
+      ctrl->value=go->fClipRegion.left;
+      break;
+    case GO7007IOC_CLIP_TOP:
+      ctrl->value=go->fClipRegion.top;
+      break;
+    case GO7007IOC_CLIP_WIDTH:
+      ctrl->value=go->fClipRegion.width;
+      break;
+    case GO7007IOC_CLIP_HEIGHT:
+      ctrl->value=go->fClipRegion.height;
+      break;
+    case GO7007IOC_REGION_CONTROL:
+    default:
+      return -EINVAL;
+  }
+  return 0;
+}
+
+static void ClearModetMap(struct go7007 *go,char Region)
+{
+  /* Clear old region macroblocks */
+  int mbnum;
+  for(mbnum=0;mbnum<sizeof(go->modet_map);++mbnum)
+    if(go->modet_map[mbnum]==Region)
+      go->modet_map[mbnum]=0;
+}
+
+static int RectToModetMap(struct go7007 *go,char Region,struct v4l2_rect 
*Rect,int Delete)
+{
+  register int x,y,mbnum;
+  /* Check if coordinates are OK and if any macroblocks are already
+   * used by other regions (besides 0) */
+//  if(Rect)
+  if(Rect->left<0 || (Rect->left & 0xF) || Rect->width<=0 || (Rect->width & 
0xF))
+    return -EINVAL;
+  if(Rect->left+Rect->width>go->width)
+    return -EINVAL;
+  if(Rect->top<0 || (Rect->top & 0xF) || Rect->height<=0 || (Rect->height & 
0xF))
+    return -EINVAL;
+  if(Rect->top+Rect->height>go->height)
+    return -EINVAL;
+  for(y=0;y<Rect->height;y+=16)
+    for(x=0;x<Rect->width;x+=16)
+    {
+      mbnum=(go->width>>4)*((Rect->top+y)>>4)+((Rect->left+x)>>4);
+      if(go->modet_map[mbnum]!=0 && go->modet_map[mbnum]!=Region)
+        return -EBUSY;
+      else
+        go->modet_map[mbnum]=Delete ? 0 : Region;
+    }
+  return 0;
+}
+
+static int md_s_ctrl(struct v4l2_control *ctrl,struct go7007 *go)
+{
+  switch(ctrl->id)
+  {
+    case GO7007IOC_REGION_NUMBER:
+      if(ctrl->value<0 || ctrl->value>3)
+        return -EINVAL;
+      go->fCurrentRegion=ctrl->value;
+      break;
+    case GO7007IOC_PIXEL_THRESOLD:
+      if(ctrl->value<0 || ctrl->value>65535)
+        return -EINVAL;
+      go->modet[go->fCurrentRegion].pixel_threshold=ctrl->value>>1;
+      break;
+    case GO7007IOC_MOTION_THRESOLD:
+      if(ctrl->value<0 || ctrl->value>65535)
+        return -EINVAL;
+      go->modet[go->fCurrentRegion].motion_threshold=ctrl->value>>1;
+      break;
+    case GO7007IOC_TRIGGER:
+      if(ctrl->value<0 || ctrl->value>65535)
+        return -EINVAL;
+      go->modet[go->fCurrentRegion].mb_threshold=ctrl->value>>1;
+      go->modet[go->fCurrentRegion].enable=ctrl->value>0;
+      break;
+    case GO7007IOC_REGION_CONTROL:
+      if(go->fCurrentRegion<1 || go->fCurrentRegion>3)
+        return -EINVAL;
+      switch(ctrl->value)
+      {
+        case rcAdd:
+          RectToModetMap(go,go->fCurrentRegion,&go->fClipRegion,0);
+          break;
+        case rcDelete:
+          RectToModetMap(go,go->fCurrentRegion,&go->fClipRegion,1);
+          break;
+        case rcClear:
+          ClearModetMap(go,go->fCurrentRegion);
+          break;
+        default:
+          return -EINVAL;
+      }
+      break;
+    case GO7007IOC_CLIP_LEFT:
+      go->fClipRegion.top=ctrl->value;
+      break;
+    case GO7007IOC_CLIP_TOP:
+      go->fClipRegion.left=ctrl->value;
+      break;
+    case GO7007IOC_CLIP_WIDTH:
+      go->fClipRegion.width=ctrl->value;
+      break;
+    case GO7007IOC_CLIP_HEIGHT:
+      go->fClipRegion.height=ctrl->value;
+      break;
+    default:
+      return -EINVAL;
+  }
+  return 0;
+}
+
+static int vidioc_querymenu(struct file *file,void *fh,struct v4l2_querymenu 
*menuctrl)
+{
+  switch(menuctrl->id)
+  {
+    case V4L2_CID_MPEG_STREAM_TYPE:
+      switch(menuctrl->index)
+      {
+        case V4L2_MPEG_STREAM_TYPE_MPEG2_DVD:
+          strcpy(menuctrl->name,"MPEG2 DVD");
+          break;
+        case V4L2_MPEG_STREAM_TYPE_MPEG_ELEM:
+          strcpy(menuctrl->name,"MPEG ELEM");
+          break;
+        default:
+          return -EINVAL;
+      }
+      break;
+    case V4L2_CID_MPEG_VIDEO_ENCODING:
+      switch(menuctrl->index)
+      {
+        case V4L2_MPEG_VIDEO_ENCODING_MPEG_1:
+          strcpy(menuctrl->name,"MPEG1");
+          break;
+        case V4L2_MPEG_VIDEO_ENCODING_MPEG_2:
+          strcpy(menuctrl->name,"MPEG2");
+          break;
+        case V4L2_MPEG_VIDEO_ENCODING_MPEG_4:
+          strcpy(menuctrl->name,"MPEG4");
+          break;
+        case V4L2_MPEG_VIDEO_ENCODING_H263:
+          strcpy(menuctrl->name,"H263");
+          break;
+        default:
+          return -EINVAL;
+      }
+      break;
+    case V4L2_CID_MPEG_VIDEO_ASPECT:
+      switch(menuctrl->index)
+      {
+        case V4L2_MPEG_VIDEO_ASPECT_1x1:
+          strcpy(menuctrl->name,"1x1");
+          break;
+        case V4L2_MPEG_VIDEO_ASPECT_4x3:
+          strcpy(menuctrl->name,"4x3");
+          break;
+        case V4L2_MPEG_VIDEO_ASPECT_16x9:
+          strcpy(menuctrl->name,"16x9");
+          break;
+        case V4L2_MPEG_VIDEO_ASPECT_221x100:
+          strcpy(menuctrl->name,"221x100");
+//          break;
+        default:
+          return -EINVAL;
+      }
+      break;
+    case GO7007IOC_REGION_CONTROL:
+      switch(menuctrl->index)
+      {
+        case rcAdd:
+          strcpy(menuctrl->name,"Add");
+          break;
+        case rcDelete:
+          strcpy(menuctrl->name,"Delete");
+          break;
+        case rcClear:
+          strcpy(menuctrl->name,"Clear");
+          break;
+        default:
+          return -EINVAL;
+      }
+      break;
+    default:
+      return -EINVAL;
+  }
+  return 0;
+}
+
+static int md_query_ctrl(struct v4l2_queryctrl *ctrl,struct go7007 *go)
+{
+  static const u32 md_ctrls[]=
+  {
+    GO7007IOC_REGION_NUMBER
+    ,GO7007IOC_PIXEL_THRESOLD
+    ,GO7007IOC_MOTION_THRESOLD
+    ,GO7007IOC_TRIGGER
+    ,GO7007IOC_REGION_CONTROL
+    ,GO7007IOC_CLIP_LEFT
+    ,GO7007IOC_CLIP_TOP
+    ,GO7007IOC_CLIP_WIDTH
+    ,GO7007IOC_CLIP_HEIGHT
+    ,0
+  };
+
+  static const u32 *ctrl_classes[]=
+  {
+    md_ctrls
+    ,NULL
+  };
+
+  printk(KERN_INFO"Before Try md query ctrl %d",ctrl->id);
+
+  ctrl->id=v4l2_ctrl_next(ctrl_classes,ctrl->id);
+
+  printk(KERN_INFO"Try md query ctrl %d",ctrl->id);
+  switch(ctrl->id)
+  {
+    case GO7007IOC_REGION_NUMBER:
+      ctrl->type=V4L2_CTRL_TYPE_INTEGER;
+      strncpy(ctrl->name,"Region MD",sizeof(ctrl->name));
+      ctrl->minimum=0;
+      ctrl->maximum=3;
+      ctrl->step=1;
+      ctrl->default_value=0;
+      ctrl->flags=0;
+      break;
+    case GO7007IOC_PIXEL_THRESOLD:
+      ctrl->type=V4L2_CTRL_TYPE_INTEGER;
+      strncpy(ctrl->name,"Pixel Thresold",sizeof(ctrl->name));
+      ctrl->minimum=0;
+      ctrl->maximum=65535;
+      ctrl->step=1;
+      ctrl->default_value=32767;
+      ctrl->flags=0;
+      break;
+    case GO7007IOC_MOTION_THRESOLD:
+      ctrl->type=V4L2_CTRL_TYPE_INTEGER;
+      strncpy(ctrl->name,"Motion Thresold",sizeof(ctrl->name));
+      ctrl->minimum=0;
+      ctrl->maximum=65535;
+      ctrl->step=1;
+      ctrl->default_value=32767;
+      ctrl->flags=0;
+      break;
+    case GO7007IOC_TRIGGER:
+      ctrl->type=V4L2_CTRL_TYPE_INTEGER;
+      strncpy(ctrl->name,"Trigger",sizeof(ctrl->name));
+      ctrl->minimum=0;
+      ctrl->maximum=65535;
+      ctrl->step=1;
+      ctrl->default_value=32767;
+      ctrl->flags=0;
+      break;
+    case GO7007IOC_REGION_CONTROL:
+      ctrl->type=V4L2_CTRL_TYPE_MENU;//V4L2_CTRL_TYPE_BUTTON;
+      strncpy(ctrl->name,"Region Control",sizeof(ctrl->name));
+      ctrl->minimum=rcAdd;
+      ctrl->maximum=rcClear;
+      ctrl->step=1;
+      ctrl->default_value=rcAdd;
+      ctrl->flags=0;
+      break;
+    case GO7007IOC_CLIP_LEFT:
+      ctrl->type=V4L2_CTRL_TYPE_INTEGER;
+      strncpy(ctrl->name,"Left of Region",sizeof(ctrl->name));
+      ctrl->minimum=0;
+      ctrl->maximum=go->width-1;
+      ctrl->step=1;
+      ctrl->default_value=0;
+      ctrl->flags=0;
+      break;
+    case GO7007IOC_CLIP_TOP:
+      ctrl->type=V4L2_CTRL_TYPE_INTEGER;
+      strncpy(ctrl->name,"Top of Region",sizeof(ctrl->name));
+      ctrl->minimum=0;
+      ctrl->maximum=go->height-1;
+      ctrl->step=1;
+      ctrl->default_value=0;
+      ctrl->flags=0;
+      break;
+    case GO7007IOC_CLIP_WIDTH:
+      ctrl->type=V4L2_CTRL_TYPE_INTEGER;
+      strncpy(ctrl->name,"Width of Region",sizeof(ctrl->name));
+      ctrl->minimum=0;
+      ctrl->maximum=go->width;
+      ctrl->step=1;
+      ctrl->default_value=0;
+      ctrl->flags=0;
+      break;
+    case GO7007IOC_CLIP_HEIGHT:
+      ctrl->type=V4L2_CTRL_TYPE_INTEGER;
+      strncpy(ctrl->name,"Height of Region",sizeof(ctrl->name));
+      ctrl->minimum=0;
+      ctrl->maximum=go->height;
+      ctrl->step=1;
+      ctrl->default_value=0;
+      ctrl->flags=0;
+      break;
+    default:
+      return -EINVAL;
+  }
+  return 0;
 }
-#endif
 
 static int mpeg_query_ctrl(struct v4l2_queryctrl *ctrl)
 {
-       static const u32 mpeg_ctrls[] = {
-               V4L2_CID_MPEG_CLASS,
-               V4L2_CID_MPEG_STREAM_TYPE,
-               V4L2_CID_MPEG_VIDEO_ENCODING,
-               V4L2_CID_MPEG_VIDEO_ASPECT,
-               V4L2_CID_MPEG_VIDEO_GOP_SIZE,
-               V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
-               V4L2_CID_MPEG_VIDEO_BITRATE,
-               0
-       };
-       static const u32 *ctrl_classes[] = {
-               mpeg_ctrls,
-               NULL
-       };
-
-       ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id);
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_CLASS:
-               return v4l2_ctrl_query_fill(ctrl, 0, 0, 0, 0);
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               return v4l2_ctrl_query_fill(ctrl,
-                               V4L2_MPEG_STREAM_TYPE_MPEG2_DVD,
-                               V4L2_MPEG_STREAM_TYPE_MPEG_ELEM, 1,
-                               V4L2_MPEG_STREAM_TYPE_MPEG_ELEM);
-       case V4L2_CID_MPEG_VIDEO_ENCODING:
-               return v4l2_ctrl_query_fill(ctrl,
-                               V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
-                               V4L2_MPEG_VIDEO_ENCODING_MPEG_4, 1,
-                               V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
-       case V4L2_CID_MPEG_VIDEO_ASPECT:
-               return v4l2_ctrl_query_fill(ctrl,
-                               V4L2_MPEG_VIDEO_ASPECT_1x1,
-                               V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
-                               V4L2_MPEG_VIDEO_ASPECT_1x1);
-       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-               return v4l2_ctrl_query_fill(ctrl, 0, 34, 1, 15);
-       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
-               return v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0);
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-               return v4l2_ctrl_query_fill(ctrl,
-                               64000,
-                               10000000, 1,
-                               1500000);
-       default:
-               return -EINVAL;
-       }
-       return 0;
+  static const u32 mpeg_ctrls[]=
+  {
+    V4L2_CID_MPEG_CLASS
+    ,V4L2_CID_MPEG_STREAM_TYPE
+    ,V4L2_CID_MPEG_VIDEO_ENCODING
+    ,V4L2_CID_MPEG_VIDEO_ASPECT
+    ,V4L2_CID_MPEG_VIDEO_B_FRAMES
+    ,V4L2_CID_MPEG_VIDEO_GOP_SIZE
+    ,V4L2_CID_MPEG_VIDEO_GOP_CLOSURE
+    ,V4L2_CID_MPEG_VIDEO_BITRATE
+//GO7007_COMP_OMIT_SEQ_HEADER,
+//GO7007_MPEG_REPEAT_SEQHEADER
+//GO7007_MPEG_OMIT_GOP_HEADER
+    ,0
+  };
+
+  static const u32 *ctrl_classes[]=
+  {
+    mpeg_ctrls
+    ,NULL
+  };
+
+  ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id);
+
+  switch(ctrl->id)
+  {
+    case V4L2_CID_MPEG_CLASS:
+    return v4l2_ctrl_query_fill(ctrl, 0, 0, 0, 0);
+    case V4L2_CID_MPEG_STREAM_TYPE:
+    return v4l2_ctrl_query_fill(ctrl,
+        V4L2_MPEG_STREAM_TYPE_MPEG2_DVD,
+        V4L2_MPEG_STREAM_TYPE_MPEG_ELEM, 1,
+        V4L2_MPEG_STREAM_TYPE_MPEG_ELEM);
+  case V4L2_CID_MPEG_VIDEO_ENCODING:
+    return v4l2_ctrl_query_fill(ctrl,
+        V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
+        V4L2_MPEG_VIDEO_ENCODING_MPEG_4/*V4L2_MPEG_VIDEO_ENCODING_H263*/,1,
+        V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
+  case V4L2_CID_MPEG_VIDEO_ASPECT:
+    return v4l2_ctrl_query_fill(ctrl,
+        V4L2_MPEG_VIDEO_ASPECT_1x1,
+        V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
+        V4L2_MPEG_VIDEO_ASPECT_1x1);
+  case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+    return v4l2_ctrl_query_fill(ctrl, 0, 34, 1, 15);
+  case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+    return v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0);
+  case V4L2_CID_MPEG_VIDEO_BITRATE:
+    return v4l2_ctrl_query_fill(ctrl,
+        64000,
+        10000000, 1,
+        1500000);
+    case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+      return v4l2_ctrl_query_fill(ctrl,0,2,1,0);
+    default:
+      return -EINVAL;
+    }
+  return 0;
 }
 
 static int mpeg_s_ctrl(struct v4l2_control *ctrl, struct go7007 *go)
@@ -492,6 +768,9 @@ static int mpeg_s_ctrl(struct v4l2_contr
                        else*/
                                go->pali = 0xf5;
                        break;
+    case V4L2_MPEG_VIDEO_ENCODING_H263:
+      go->format=GO7007_FORMAT_H263;
+      break;
                default:
                        return -EINVAL;
                }
@@ -538,10 +817,15 @@ static int mpeg_s_ctrl(struct v4l2_contr
                        return -EINVAL;
                go->bitrate = ctrl->value;
                break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
+    case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+      if(ctrl->value<0 || ctrl->value>2)///checking
+        return -EINVAL;
+      go->ipb=ctrl->value>0;
+      break;
+    default:
+      return -EINVAL;
+  }
+  return 0;
 }
 
 static int mpeg_g_ctrl(struct v4l2_control *ctrl, struct go7007 *go)
@@ -564,6 +848,9 @@ static int mpeg_g_ctrl(struct v4l2_contr
                case GO7007_FORMAT_MPEG4:
                        ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4;
                        break;
+    case GO7007_FORMAT_H263:
+      ctrl->value=V4L2_MPEG_VIDEO_ENCODING_H263;
+      break;
                default:
                        return -EINVAL;
                }
@@ -592,10 +879,13 @@ static int mpeg_g_ctrl(struct v4l2_contr
        case V4L2_CID_MPEG_VIDEO_BITRATE:
                ctrl->value = go->bitrate;
                break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
+    case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+      ctrl->value=go->ipb ? 2 : 0;
+      break;
+    default:
+      return -EINVAL;
+  }
+  return 0;
 }
 
 static int vidioc_querycap(struct file *file, void  *priv,
@@ -605,9 +895,7 @@ static int vidioc_querycap(struct file *
 
        strlcpy(cap->driver, "go7007", sizeof(cap->driver));
        strlcpy(cap->card, go->name, sizeof(cap->card));
-#if 0
-       strlcpy(cap->bus_info, dev_name(&dev->udev->dev), 
sizeof(cap->bus_info));
-#endif
+  strlcpy(cap->bus_info,dev_name(go->dev),sizeof(cap->bus_info));
 
        cap->version = KERNEL_VERSION(0, 9, 8);
 
@@ -975,39 +1263,43 @@ static int vidioc_streamoff(struct file
        return 0;
 }
 
-static int vidioc_queryctrl(struct file *file, void *priv,
-                          struct v4l2_queryctrl *query)
+static int vidioc_queryctrl(struct file *file,void *priv,struct v4l2_queryctrl 
*query)
 {
-       struct go7007 *go = ((struct go7007_file *) priv)->go;
-       int id = query->id;
+  struct go7007 *go=((struct go7007_file *)priv)->go;
+  int id=query->id;
 
-       if (0 == call_all(&go->v4l2_dev, core, queryctrl, query))
-               return 0;
+  if(0==call_all(&go->v4l2_dev,core,queryctrl,query))
+    return 0;
 
-       query->id = id;
-       return mpeg_query_ctrl(query);
+  query->id=id;
+  if(mpeg_query_ctrl(query)==0)
+    return 0;
+  query->id=id;
+  return md_query_ctrl(query,go);
 }
 
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
+static int vidioc_g_ctrl(struct file *file,void *priv,struct v4l2_control 
*ctrl)
 {
-       struct go7007 *go = ((struct go7007_file *) priv)->go;
+  struct go7007 *go=((struct go7007_file *)priv)->go;
 
-       if (0 == call_all(&go->v4l2_dev, core, g_ctrl, ctrl))
-               return 0;
+  if(0==call_all(&go->v4l2_dev,core,g_ctrl,ctrl))
+    return 0;
 
-       return mpeg_g_ctrl(ctrl, go);
+  if(mpeg_g_ctrl(ctrl,go)==0)
+    return 0;
+  return md_g_ctrl(ctrl,go);
 }
 
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
+static int vidioc_s_ctrl(struct file *file,void *priv,struct v4l2_control 
*ctrl)
 {
-       struct go7007 *go = ((struct go7007_file *) priv)->go;
+  struct go7007 *go=((struct go7007_file *)priv)->go;
 
-       if (0 == call_all(&go->v4l2_dev, core, s_ctrl, ctrl))
-               return 0;
+  if(0==call_all(&go->v4l2_dev,core,s_ctrl,ctrl))
+    return 0;
 
-       return mpeg_s_ctrl(ctrl, go);
+  if(mpeg_s_ctrl(ctrl,go)==0)
+    return 0;
+  return md_s_ctrl(ctrl,go);
 }
 
 static int vidioc_g_parm(struct file *filp, void *priv,
@@ -1060,44 +1352,246 @@ static int vidioc_s_parm(struct file *fi
 
    The two functions bellow implements the newer ioctls
 */
-static int vidioc_enum_framesizes(struct file *filp, void *priv,
-                                 struct v4l2_frmsizeenum *fsize)
-{
-       struct go7007 *go = ((struct go7007_file *) priv)->go;
-
-       /* Return -EINVAL, if it is a TV board */
-       if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) ||
-           (go->board_info->sensor_flags & GO7007_SENSOR_TV))
-               return -EINVAL;
-
-       if (fsize->index > 0)
-               return -EINVAL;
-
-       fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-       fsize->discrete.width = go->board_info->sensor_width;
-       fsize->discrete.height = go->board_info->sensor_height;
-
-       return 0;
-}
-
-static int vidioc_enum_frameintervals(struct file *filp, void *priv,
-                                     struct v4l2_frmivalenum *fival)
+static int vidioc_enum_framesizes(struct file *filp,void *priv,struct 
v4l2_frmsizeenum *fsize)
 {
-       struct go7007 *go = ((struct go7007_file *) priv)->go;
+  struct go7007 *go=((struct go7007_file *)priv)->go;
+  /* Return -EINVAL, if it is a TV board */
+  if(go->board_info->flags & GO7007_BOARD_HAS_TUNER)
+    return -EINVAL;
+
+  if(go->board_info->sensor_flags & GO7007_SENSOR_TV)
+  {
+    switch(go->standard)
+    {
+      case GO7007_STD_NTSC:
+        switch(fsize->pixel_format)
+        {
+          case V4L2_PIX_FMT_MJPEG:
+          case V4L2_PIX_FMT_MPEG:
+            switch(fsize->index)
+            {
+              case 0:
+                fsize->type=V4L2_FRMSIZE_TYPE_DISCRETE;
+                fsize->discrete.width=720;
+                fsize->discrete.height=480;
+                break;
+              case 1:
+                fsize->type=V4L2_FRMSIZE_TYPE_DISCRETE;
+                fsize->discrete.width=640;
+                fsize->discrete.height=480;
+                break;
+              case 2:
+                fsize->type=V4L2_FRMSIZE_TYPE_DISCRETE;
+                fsize->discrete.width=352;
+                fsize->discrete.height=240;
+                break;
+              case 3:
+                fsize->type=V4L2_FRMSIZE_TYPE_DISCRETE;
+                fsize->discrete.width=320;
+                fsize->discrete.height=240;
+                break;
+              case 4:
+                fsize->type=V4L2_FRMSIZE_TYPE_DISCRETE;
+                fsize->discrete.width=176;
+                fsize->discrete.height=112;
+                break;
+              default:
+                return -EINVAL;
+            }
+            break;
+          default:
+            return -EINVAL;
+        }
+        break;
+      case GO7007_STD_PAL:
+        switch(fsize->pixel_format)
+        {
+          case V4L2_PIX_FMT_MJPEG:
+          case V4L2_PIX_FMT_MPEG:
+            switch(fsize->index)
+            {
+              case 0:
+                fsize->type=V4L2_FRMSIZE_TYPE_DISCRETE;
+                fsize->discrete.width=720;
+                fsize->discrete.height=576;
+                break;
+              case 1:
+                fsize->type=V4L2_FRMSIZE_TYPE_DISCRETE;
+                fsize->discrete.width=352;
+                fsize->discrete.height=288;
+                break;
+              case 2:
+                fsize->type=V4L2_FRMSIZE_TYPE_DISCRETE;
+                fsize->discrete.width=176;
+                fsize->discrete.height=144;
+                break;
+              default:
+                return -EINVAL;
+            }
+            break;
+          default:
+            return -EINVAL;
+        }
+        break;
+      default:
+        return -EINVAL;
+    }
+    return 0;
+  }
+
+  if (fsize->index > 0)
+    return -EINVAL;
+
+  fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+  fsize->discrete.width = go->board_info->sensor_width;
+  fsize->discrete.height = go->board_info->sensor_height;
+
+  return 0;
+}
+
+static int vidioc_enum_frameintervals(struct file *filp,void *priv,struct 
v4l2_frmivalenum *fival)
+{
+  struct go7007 *go=((struct go7007_file *)priv)->go;
+
+  /* Return -EINVAL, if it is a TV board */
+  if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER))
+    return -EINVAL;
+
+  if(go->board_info->sensor_flags & GO7007_SENSOR_TV)
+  {
+    switch(fival->pixel_format)
+    {
+      case V4L2_PIX_FMT_MJPEG:
+      case V4L2_PIX_FMT_MPEG:
+        switch(go->standard)
+        {
+          case GO7007_STD_NTSC:
+            switch(fival->index)
+            {
+              case 0:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*1;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 1:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*2;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 2:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*3;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 3:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*4;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 4:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*5;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 5:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*6;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 6:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*7;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 7:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*10;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 8:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*15;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 9:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*30;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              default:
+                return -EINVAL;
+            }
+            break;
+          case GO7007_STD_PAL:
+            switch(fival->index)
+            {
+              case 0:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*1;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 1:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*2;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 2:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*3;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 3:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*4;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 4:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*5;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 5:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*6;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 6:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*8;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 7:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*13;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              case 8:
+                fival->type=V4L2_FRMIVAL_TYPE_DISCRETE;
+                fival->discrete.numerator=1001*25;
+                fival->discrete.denominator=go->sensor_framerate;
+                break;
+              default:
+                return -EINVAL;
+            }
+            break;
+          default:
+            return -EINVAL;
+        }
+        break;
+      default:
+        return -EINVAL;
+    }
+    return 0;
+  }
+
+  if (fival->index > 0)
+    return -EINVAL;
+
+  fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+  fival->discrete.numerator = 1001;
+  fival->discrete.denominator = go->board_info->sensor_framerate;
 
-       /* Return -EINVAL, if it is a TV board */
-       if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) ||
-           (go->board_info->sensor_flags & GO7007_SENSOR_TV))
-               return -EINVAL;
-
-       if (fival->index > 0)
-               return -EINVAL;
-
-       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-       fival->discrete.numerator = 1001;
-       fival->discrete.denominator = go->board_info->sensor_framerate;
-
-       return 0;
+  return 0;
 }
 
 static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std)
@@ -1405,235 +1899,6 @@ static int vidioc_s_jpegcomp(struct file
        return 0;
 }
 
-/* FIXME:
-       Those ioctls are private, and not needed, since several standard
-       extended controls already provide streaming control.
-       So, those ioctls should be converted into vidioc_g_ext_ctrls()
-       and vidioc_s_ext_ctrls()
- */
-
-#if 0
-       /* Temporary ioctls for controlling compression characteristics */
-       case GO7007IOC_S_BITRATE:
-       {
-               int *bitrate = arg;
-
-               if (go->streaming)
-                       return -EINVAL;
-               /* Upper bound is kind of arbitrary here */
-               if (*bitrate < 64000 || *bitrate > 10000000)
-                       return -EINVAL;
-               go->bitrate = *bitrate;
-               return 0;
-       }
-       case GO7007IOC_G_BITRATE:
-       {
-               int *bitrate = arg;
-
-               *bitrate = go->bitrate;
-               return 0;
-       }
-       case GO7007IOC_S_COMP_PARAMS:
-       {
-               struct go7007_comp_params *comp = arg;
-
-               if (go->format == GO7007_FORMAT_MJPEG)
-                       return -EINVAL;
-               if (comp->gop_size > 0)
-                       go->gop_size = comp->gop_size;
-               else
-                       go->gop_size = go->sensor_framerate / 1000;
-               if (go->gop_size != 15)
-                       go->dvd_mode = 0;
-               /*go->ipb = comp->max_b_frames > 0;*/ /* completely untested */
-               if (go->board_info->sensor_flags & GO7007_SENSOR_TV) {
-                       switch (comp->aspect_ratio) {
-                       case GO7007_ASPECT_RATIO_4_3_NTSC:
-                       case GO7007_ASPECT_RATIO_4_3_PAL:
-                               go->aspect_ratio = GO7007_RATIO_4_3;
-                               break;
-                       case GO7007_ASPECT_RATIO_16_9_NTSC:
-                       case GO7007_ASPECT_RATIO_16_9_PAL:
-                               go->aspect_ratio = GO7007_RATIO_16_9;
-                               break;
-                       default:
-                               go->aspect_ratio = GO7007_RATIO_1_1;
-                               break;
-                       }
-               }
-               if (comp->flags & GO7007_COMP_OMIT_SEQ_HEADER) {
-                       go->dvd_mode = 0;
-                       go->seq_header_enable = 0;
-               } else {
-                       go->seq_header_enable = 1;
-               }
-               /* fall-through */
-       }
-       case GO7007IOC_G_COMP_PARAMS:
-       {
-               struct go7007_comp_params *comp = arg;
-
-               if (go->format == GO7007_FORMAT_MJPEG)
-                       return -EINVAL;
-               memset(comp, 0, sizeof(*comp));
-               comp->gop_size = go->gop_size;
-               comp->max_b_frames = go->ipb ? 2 : 0;
-               switch (go->aspect_ratio) {
-               case GO7007_RATIO_4_3:
-                       if (go->standard == GO7007_STD_NTSC)
-                               comp->aspect_ratio =
-                                       GO7007_ASPECT_RATIO_4_3_NTSC;
-                       else
-                               comp->aspect_ratio =
-                                       GO7007_ASPECT_RATIO_4_3_PAL;
-                       break;
-               case GO7007_RATIO_16_9:
-                       if (go->standard == GO7007_STD_NTSC)
-                               comp->aspect_ratio =
-                                       GO7007_ASPECT_RATIO_16_9_NTSC;
-                       else
-                               comp->aspect_ratio =
-                                       GO7007_ASPECT_RATIO_16_9_PAL;
-                       break;
-               default:
-                       comp->aspect_ratio = GO7007_ASPECT_RATIO_1_1;
-                       break;
-               }
-               if (go->closed_gop)
-                       comp->flags |= GO7007_COMP_CLOSED_GOP;
-               if (!go->seq_header_enable)
-                       comp->flags |= GO7007_COMP_OMIT_SEQ_HEADER;
-               return 0;
-       }
-       case GO7007IOC_S_MPEG_PARAMS:
-       {
-               struct go7007_mpeg_params *mpeg = arg;
-
-               if (go->format != GO7007_FORMAT_MPEG1 &&
-                               go->format != GO7007_FORMAT_MPEG2 &&
-                               go->format != GO7007_FORMAT_MPEG4)
-                       return -EINVAL;
-
-               if (mpeg->flags & GO7007_MPEG_FORCE_DVD_MODE) {
-                       go->format = GO7007_FORMAT_MPEG2;
-                       go->bitrate = 9800000;
-                       go->gop_size = 15;
-                       go->pali = 0x48;
-                       go->closed_gop = 1;
-                       go->repeat_seqhead = 0;
-                       go->seq_header_enable = 1;
-                       go->gop_header_enable = 1;
-                       go->dvd_mode = 1;
-               } else {
-                       switch (mpeg->mpeg_video_standard) {
-                       case GO7007_MPEG_VIDEO_MPEG1:
-                               go->format = GO7007_FORMAT_MPEG1;
-                               go->pali = 0;
-                               break;
-                       case GO7007_MPEG_VIDEO_MPEG2:
-                               go->format = GO7007_FORMAT_MPEG2;
-                               if (mpeg->pali >> 24 == 2)
-                                       go->pali = mpeg->pali & 0xff;
-                               else
-                                       go->pali = 0x48;
-                               break;
-                       case GO7007_MPEG_VIDEO_MPEG4:
-                               go->format = GO7007_FORMAT_MPEG4;
-                               if (mpeg->pali >> 24 == 4)
-                                       go->pali = mpeg->pali & 0xff;
-                               else
-                                       go->pali = 0xf5;
-                               break;
-                       default:
-                               return -EINVAL;
-                       }
-                       go->gop_header_enable =
-                               mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER
-                               ? 0 : 1;
-                       if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER)
-                               go->repeat_seqhead = 1;
-                       else
-                               go->repeat_seqhead = 0;
-                       go->dvd_mode = 0;
-               }
-               /* fall-through */
-       }
-       case GO7007IOC_G_MPEG_PARAMS:
-       {
-               struct go7007_mpeg_params *mpeg = arg;
-
-               memset(mpeg, 0, sizeof(*mpeg));
-               switch (go->format) {
-               case GO7007_FORMAT_MPEG1:
-                       mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG1;
-                       mpeg->pali = 0;
-                       break;
-               case GO7007_FORMAT_MPEG2:
-                       mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG2;
-                       mpeg->pali = GO7007_MPEG_PROFILE(2, go->pali);
-                       break;
-               case GO7007_FORMAT_MPEG4:
-                       mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG4;
-                       mpeg->pali = GO7007_MPEG_PROFILE(4, go->pali);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               if (!go->gop_header_enable)
-                       mpeg->flags |= GO7007_MPEG_OMIT_GOP_HEADER;
-               if (go->repeat_seqhead)
-                       mpeg->flags |= GO7007_MPEG_REPEAT_SEQHEADER;
-               if (go->dvd_mode)
-                       mpeg->flags |= GO7007_MPEG_FORCE_DVD_MODE;
-               return 0;
-       }
-       case GO7007IOC_S_MD_PARAMS:
-       {
-               struct go7007_md_params *mdp = arg;
-
-               if (mdp->region > 3)
-                       return -EINVAL;
-               if (mdp->trigger > 0) {
-                       go->modet[mdp->region].pixel_threshold =
-                                       mdp->pixel_threshold >> 1;
-                       go->modet[mdp->region].motion_threshold =
-                                       mdp->motion_threshold >> 1;
-                       go->modet[mdp->region].mb_threshold =
-                                       mdp->trigger >> 1;
-                       go->modet[mdp->region].enable = 1;
-               } else
-                       go->modet[mdp->region].enable = 0;
-               /* fall-through */
-       }
-       case GO7007IOC_G_MD_PARAMS:
-       {
-               struct go7007_md_params *mdp = arg;
-               int region = mdp->region;
-
-               if (mdp->region > 3)
-                       return -EINVAL;
-               memset(mdp, 0, sizeof(struct go7007_md_params));
-               mdp->region = region;
-               if (!go->modet[region].enable)
-                       return 0;
-               mdp->pixel_threshold =
-                       (go->modet[region].pixel_threshold << 1) + 1;
-               mdp->motion_threshold =
-                       (go->modet[region].motion_threshold << 1) + 1;
-               mdp->trigger =
-                       (go->modet[region].mb_threshold << 1) + 1;
-               return 0;
-       }
-       case GO7007IOC_S_MD_REGION:
-       {
-               struct go7007_md_region *region = arg;
-
-               if (region->region < 1 || region->region > 3)
-                       return -EINVAL;
-               return clip_to_modet_map(go, region->region, region->clips);
-       }
-#endif
-
 static ssize_t go7007_read(struct file *file, char __user *data,
                size_t count, loff_t *ppos)
 {
@@ -1779,7 +2044,9 @@ static const struct v4l2_ioctl_ops video
        .vidioc_g_crop            = vidioc_g_crop,
        .vidioc_s_crop            = vidioc_s_crop,
        .vidioc_g_jpegcomp        = vidioc_g_jpegcomp,
-       .vidioc_s_jpegcomp        = vidioc_s_jpegcomp,
+       .vidioc_s_jpegcomp        = vidioc_s_jpegcomp
+  ,.vidioc_querymenu=vidioc_querymenu
+  ,
 };
 
 static struct video_device go7007_template = {
@@ -1787,13 +2054,14 @@ static struct video_device go7007_templa
        .fops           = &go7007_fops,
        .release        = go7007_vfl_release,
        .ioctl_ops      = &video_ioctl_ops,
-       .tvnorms        = V4L2_STD_ALL,
+       .tvnorms        = V4L2_STD_SECAM | V4L2_STD_NTSC | 
V4L2_STD_PAL,///V4L2_STD_ALL,
        .current_norm   = V4L2_STD_NTSC,
 };
 
 int go7007_v4l2_init(struct go7007 *go)
 {
        int rv;
+  register int i;
 
        go->video_dev = video_device_alloc();
        if (go->video_dev == NULL)
@@ -1816,8 +2084,11 @@ int go7007_v4l2_init(struct go7007 *go)
        ++go->ref_count;
        printk(KERN_INFO "%s: registered device %s [v4l2]\n",
               go->video_dev->name, video_device_node_name(go->video_dev));
-
-       return 0;
+  memset(&go->fClipRegion,0,sizeof(go->fClipRegion));
+  go->fCurrentRegion=0;
+  for(i=0;i<4;i++)
+    memset(&go->modet[i],0,sizeof(go->modet[i]));
+  return 0;
 }
 
 void go7007_v4l2_remove(struct go7007 *go)
diff -uprN -X linux-3.2.11-vanilla/Documentation/dontdiff 
linux-3.2.11-vanilla/drivers/staging/media/go7007/wis-tw2804.c 
linux-3.2.11/drivers/staging/media/go7007/wis-tw2804.c
--- linux-3.2.11-vanilla/drivers/staging/media/go7007/wis-tw2804.c      
2012-03-13 21:05:09.000000000 +0400
+++ linux-3.2.11/drivers/staging/media/go7007/wis-tw2804.c      2012-03-20 
16:17:38.452746142 +0400
@@ -21,10 +21,14 @@
 #include <linux/videodev2.h>
 #include <linux/ioctl.h>
 #include <linux/slab.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-device.h>
 
 #include "wis-i2c.h"
 
-struct wis_tw2804 {
+struct wis_tw2804
+{
+  struct v4l2_subdev sd;
        int channel;
        int norm;
        int brightness;
@@ -33,7 +37,15 @@ struct wis_tw2804 {
        int hue;
 };
 
-static u8 global_registers[] = {
+static inline struct wis_tw2804 *to_state(struct v4l2_subdev *sd)
+{
+  return container_of(sd,struct wis_tw2804,sd);
+}
+
+static int tw2804_log_status(struct v4l2_subdev *sd);
+
+static u8 global_registers[]=
+{
        0x39, 0x00,
        0x3a, 0xff,
        0x3b, 0x84,
@@ -44,7 +56,8 @@ static u8 global_registers[] = {
        0xff, 0xff, /* Terminator (reg 0xff does not exist) */
 };
 
-static u8 channel_registers[] = {
+static u8 channel_registers[]=
+{
        0x01, 0xc4,
        0x02, 0xa5,
        0x03, 0x20,
@@ -105,9 +118,18 @@ static u8 channel_registers[] = {
 
 static int write_reg(struct i2c_client *client, u8 reg, u8 value, int channel)
 {
-       return i2c_smbus_write_byte_data(client, reg | (channel << 6), value);
+  int i;
+  for(i=0;i<10;i++)
+  /*return */if(i2c_smbus_write_byte_data(client,reg|(channel<<6),value)<0)
+    return -1;
+  return 0;
 }
 
+/**static u8 read_reg(struct i2c_client *client, u8 reg, int channel)
+{
+  return i2c_smbus_read_byte_data(client,reg|(channel<<6));
+}*/
+
 static int write_regs(struct i2c_client *client, u8 *regs, int channel)
 {
        int i;
@@ -119,183 +141,228 @@ static int write_regs(struct i2c_client
        return 0;
 }
 
-static int wis_tw2804_command(struct i2c_client *client,
-                               unsigned int cmd, void *arg)
+static int wis_tw2804_command(struct i2c_client *client,unsigned int cmd,void 
*arg)
 {
-       struct wis_tw2804 *dec = i2c_get_clientdata(client);
+  struct v4l2_subdev *sd=i2c_get_clientdata(client);
+  struct wis_tw2804 *dec=to_state(sd);
+  int *input;
+
+  printk(KERN_INFO"wis-tw2804: call command %d\n",cmd);
+  if(cmd==DECODER_SET_CHANNEL)
+  {
+    printk(KERN_INFO"wis-tw2804: DecoderSetChannel call command %d\n",cmd);
+
+    input=arg;
+
+    if(*input<0 || *input>3)
+    {
+      printk(KERN_ERR"wis-tw2804: channel %d is not between 0 and 
3!\n",*input);
+      return 0;
+    }
+    dec->channel=*input;
+    printk(KERN_DEBUG"wis-tw2804: initializing TW2804 channel 
%d\n",dec->channel);
+    if(dec->channel==0 && write_regs(client,global_registers,0)<0)
+    {
+      printk(KERN_ERR"wis-tw2804: error initializing TW2804 global 
registers\n");
+      return 0;
+    }
+    if(write_regs(client,channel_registers,dec->channel)<0)
+    {
+      printk(KERN_ERR"wis-tw2804: error initializing TW2804 channel 
%d\n",dec->channel);
+      return 0;
+    }
+    return 0;
+  }
+
+  if(dec->channel<0)
+  {
+    printk(KERN_DEBUG"wis-tw2804: ignoring command %08x until channel number 
is set\n",cmd);
+    return 0;
+  }
 
-       if (cmd == DECODER_SET_CHANNEL) {
-               int *input = arg;
+  return 0;
+}
 
-               if (*input < 0 || *input > 3) {
-                       printk(KERN_ERR "wis-tw2804: channel %d is not "
-                                       "between 0 and 3!\n", *input);
-                       return 0;
-               }
-               dec->channel = *input;
-               printk(KERN_DEBUG "wis-tw2804: initializing TW2804 "
-                               "channel %d\n", dec->channel);
-               if (dec->channel == 0 &&
-                               write_regs(client, global_registers, 0) < 0) {
-                       printk(KERN_ERR "wis-tw2804: error initializing "
-                                       "TW2804 global registers\n");
-                       return 0;
-               }
-               if (write_regs(client, channel_registers, dec->channel) < 0) {
-                       printk(KERN_ERR "wis-tw2804: error initializing "
-                                       "TW2804 channel %d\n", dec->channel);
-                       return 0;
-               }
-               return 0;
-       }
-
-       if (dec->channel < 0) {
-               printk(KERN_DEBUG "wis-tw2804: ignoring command %08x until "
-                               "channel number is set\n", cmd);
-               return 0;
-       }
-
-       switch (cmd) {
-       case VIDIOC_S_STD:
-       {
-               v4l2_std_id *input = arg;
-               u8 regs[] = {
-                       0x01, *input & V4L2_STD_NTSC ? 0xc4 : 0x84,
-                       0x09, *input & V4L2_STD_NTSC ? 0x07 : 0x04,
-                       0x0a, *input & V4L2_STD_NTSC ? 0xf0 : 0x20,
-                       0x0b, *input & V4L2_STD_NTSC ? 0x07 : 0x04,
-                       0x0c, *input & V4L2_STD_NTSC ? 0xf0 : 0x20,
-                       0x0d, *input & V4L2_STD_NTSC ? 0x40 : 0x4a,
-                       0x16, *input & V4L2_STD_NTSC ? 0x00 : 0x40,
-                       0x17, *input & V4L2_STD_NTSC ? 0x00 : 0x40,
-                       0x20, *input & V4L2_STD_NTSC ? 0x07 : 0x0f,
-                       0x21, *input & V4L2_STD_NTSC ? 0x07 : 0x0f,
-                       0xff,   0xff,
-               };
-               write_regs(client, regs, dec->channel);
-               dec->norm = *input;
-               break;
-       }
-       case VIDIOC_QUERYCTRL:
-       {
-               struct v4l2_queryctrl *ctrl = arg;
-
-               switch (ctrl->id) {
-               case V4L2_CID_BRIGHTNESS:
-                       ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-                       strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
-                       ctrl->minimum = 0;
-                       ctrl->maximum = 255;
-                       ctrl->step = 1;
-                       ctrl->default_value = 128;
-                       ctrl->flags = 0;
-                       break;
-               case V4L2_CID_CONTRAST:
-                       ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-                       strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
-                       ctrl->minimum = 0;
-                       ctrl->maximum = 255;
-                       ctrl->step = 1;
-                       ctrl->default_value = 128;
-                       ctrl->flags = 0;
-                       break;
-               case V4L2_CID_SATURATION:
-                       ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-                       strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
-                       ctrl->minimum = 0;
-                       ctrl->maximum = 255;
-                       ctrl->step = 1;
-                       ctrl->default_value = 128;
-                       ctrl->flags = 0;
-                       break;
-               case V4L2_CID_HUE:
-                       ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-                       strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
-                       ctrl->minimum = 0;
-                       ctrl->maximum = 255;
-                       ctrl->step = 1;
-                       ctrl->default_value = 128;
-                       ctrl->flags = 0;
-                       break;
-               }
-               break;
-       }
-       case VIDIOC_S_CTRL:
-       {
-               struct v4l2_control *ctrl = arg;
-
-               switch (ctrl->id) {
-               case V4L2_CID_BRIGHTNESS:
-                       if (ctrl->value > 255)
-                               dec->brightness = 255;
-                       else if (ctrl->value < 0)
-                               dec->brightness = 0;
-                       else
-                               dec->brightness = ctrl->value;
-                       write_reg(client, 0x12, dec->brightness, dec->channel);
-                       break;
-               case V4L2_CID_CONTRAST:
-                       if (ctrl->value > 255)
-                               dec->contrast = 255;
-                       else if (ctrl->value < 0)
-                               dec->contrast = 0;
-                       else
-                               dec->contrast = ctrl->value;
-                       write_reg(client, 0x11, dec->contrast, dec->channel);
-                       break;
-               case V4L2_CID_SATURATION:
-                       if (ctrl->value > 255)
-                               dec->saturation = 255;
-                       else if (ctrl->value < 0)
-                               dec->saturation = 0;
-                       else
-                               dec->saturation = ctrl->value;
-                       write_reg(client, 0x10, dec->saturation, dec->channel);
-                       break;
-               case V4L2_CID_HUE:
-                       if (ctrl->value > 255)
-                               dec->hue = 255;
-                       else if (ctrl->value < 0)
-                               dec->hue = 0;
-                       else
-                               dec->hue = ctrl->value;
-                       write_reg(client, 0x0f, dec->hue, dec->channel);
-                       break;
-               }
-               break;
-       }
-       case VIDIOC_G_CTRL:
-       {
-               struct v4l2_control *ctrl = arg;
-
-               switch (ctrl->id) {
-               case V4L2_CID_BRIGHTNESS:
-                       ctrl->value = dec->brightness;
-                       break;
-               case V4L2_CID_CONTRAST:
-                       ctrl->value = dec->contrast;
-                       break;
-               case V4L2_CID_SATURATION:
-                       ctrl->value = dec->saturation;
-                       break;
-               case V4L2_CID_HUE:
-                       ctrl->value = dec->hue;
-                       break;
-               }
-               break;
-       }
-       default:
-               break;
-       }
-       return 0;
+static int tw2804_log_status(struct v4l2_subdev *sd)
+{
+  struct wis_tw2804 *state=to_state(sd);
+  v4l2_info(sd, "Standard: %s\n",state->norm==V4L2_STD_NTSC ? "NTSC" : 
state->norm==V4L2_STD_PAL ? "PAL" : state->norm==V4L2_STD_SECAM ? "SECAM" : 
"unknown");
+  v4l2_info(sd,"Input: %d\n",state->channel);
+  v4l2_info(sd,"Brightness: %d\n",state->brightness);
+  v4l2_info(sd,"Contrast: %d\n",state->contrast);
+  v4l2_info(sd,"Saturation: %d\n",state->saturation);
+  v4l2_info(sd,"Hue: %d\n",state->hue);
+  return 0;
 }
 
+static int tw2804_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl 
*query)
+{
+  static const u32 user_ctrls[]=
+  {
+    V4L2_CID_USER_CLASS,
+    V4L2_CID_BRIGHTNESS,
+    V4L2_CID_CONTRAST,
+    V4L2_CID_SATURATION,
+    V4L2_CID_HUE,
+    0
+  };
+
+  static const u32 *ctrl_classes[]=
+  {
+    user_ctrls,
+    NULL
+  };
+
+  query->id=v4l2_ctrl_next(ctrl_classes,query->id);
+
+  switch (query->id)
+  {
+    case V4L2_CID_USER_CLASS:
+      return v4l2_ctrl_query_fill(query, 0, 0, 0, 0);
+    case V4L2_CID_BRIGHTNESS:
+      return v4l2_ctrl_query_fill(query, 0, 255, 1, 128);
+    case V4L2_CID_CONTRAST:
+      return v4l2_ctrl_query_fill(query, 0, 255, 1, 128);
+    case V4L2_CID_SATURATION:
+      return v4l2_ctrl_query_fill(query, 0, 255, 1, 128);
+    case V4L2_CID_HUE:
+      return v4l2_ctrl_query_fill(query, 0, 255, 1, 128);
+    default:
+      return -EINVAL;
+  }
+}
+
+static int tw2804_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+  struct wis_tw2804 *dec=to_state(sd);
+  struct i2c_client *client=v4l2_get_subdevdata(sd);
+
+  int Addr=0x00;
+  switch(ctrl->id)
+  {
+    case V4L2_CID_BRIGHTNESS:
+      Addr=0x12;
+      break;
+    case V4L2_CID_CONTRAST:
+      Addr=0x11;
+      break;
+    case V4L2_CID_SATURATION:
+      Addr=0x10;
+      break;
+    case V4L2_CID_HUE:
+      Addr=0x0f;
+      break;
+    default:
+      return -EINVAL;
+  }
+  ctrl->value=ctrl->value>255 ? 255 : (ctrl->value<0 ? 0 : ctrl->value);
+  Addr=write_reg(client,Addr,ctrl->value,dec->channel);
+  if(Addr<0)
+  {
+    printk(KERN_INFO"wis_tw2804: can`t set_ctrl 
value:id=%d;value=%d",ctrl->id,ctrl->value);
+    return Addr;
+  }
+  printk(KERN_INFO"wis_tw2804: set_ctrl 
value:id=%d;value=%d",ctrl->id,ctrl->value);
+  switch(ctrl->id)
+  {
+    case V4L2_CID_BRIGHTNESS:
+      dec->brightness=ctrl->value;
+      break;
+    case V4L2_CID_CONTRAST:
+      dec->contrast=ctrl->value;
+      break;
+    case V4L2_CID_SATURATION:
+      dec->saturation=ctrl->value;
+      break;
+    case V4L2_CID_HUE:
+      dec->hue=ctrl->value;
+      break;
+    default:
+      return -EINVAL;
+  }
+  return 0;
+}
+
+static int tw2804_g_ctrl(struct v4l2_subdev *sd,struct v4l2_control *ctrl)
+{
+  struct wis_tw2804 *state=to_state(sd);
+ /// struct i2c_client *client=v4l2_get_subdevdata(sd);
+
+  switch(ctrl->id)
+  {
+    case V4L2_CID_BRIGHTNESS:
+      ctrl->value=state->brightness;//=read_reg(client,0x12,state->channel);
+      break;
+    case V4L2_CID_CONTRAST:
+      ctrl->value=state->contrast;//=read_reg(client,0x11,state->channel);
+      break;
+    case V4L2_CID_SATURATION:
+      ctrl->value=state->saturation;//=read_reg(client,0x10,state->channel);
+      break;
+    case V4L2_CID_HUE:
+      ctrl->value=state->hue;//=read_reg(client,0x0f,state->channel);
+      break;
+    default:
+      return -EINVAL;
+  }
+  return 0;
+}
+
+static int tw2804_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+  struct wis_tw2804 *dec=to_state(sd);
+  struct i2c_client *client=v4l2_get_subdevdata(sd);
+
+///      v4l2_std_id *input=arg;
+  u8 regs[]=
+  {
+    0x01,norm&V4L2_STD_NTSC ? 0xc4 : 0x84,
+    0x09,norm&V4L2_STD_NTSC ? 0x07 : 0x04,
+    0x0a,norm&V4L2_STD_NTSC ? 0xf0 : 0x20,
+    0x0b,norm&V4L2_STD_NTSC ? 0x07 : 0x04,
+    0x0c,norm&V4L2_STD_NTSC ? 0xf0 : 0x20,
+    0x0d,norm&V4L2_STD_NTSC ? 0x40 : 0x4a,
+    0x16,norm&V4L2_STD_NTSC ? 0x00 : 0x40,
+    0x17,norm&V4L2_STD_NTSC ? 0x00 : 0x40,
+    0x20,norm&V4L2_STD_NTSC ? 0x07 : 0x0f,
+    0x21,norm&V4L2_STD_NTSC ? 0x07 : 0x0f,
+    0xff,0xff,
+  };
+  write_regs(client,regs,dec->channel);
+  dec->norm=norm;
+  return 0;
+}
+
+static const struct v4l2_subdev_core_ops tw2804_core_ops=
+{
+  .log_status=tw2804_log_status,
+  .g_ctrl=tw2804_g_ctrl,
+  .s_ctrl=tw2804_s_ctrl,
+  .queryctrl=tw2804_queryctrl,
+  .s_std=tw2804_s_std,
+};
+
+/*
+static const struct v4l2_subdev_video_ops tw2804_video_ops = {
+  .s_routing = tw2804_s_video_routing,
+  .s_fmt = tw2804_s_fmt,
+};*/
+
+static const struct v4l2_subdev_ops tw2804_ops=
+{
+  .core=&tw2804_core_ops,
+///  .audio = &s2250_audio_ops,
+///  .video = &s2250_video_ops,
+};
+
 static int wis_tw2804_probe(struct i2c_client *client,
                            const struct i2c_device_id *id)
 {
        struct i2c_adapter *adapter = client->adapter;
        struct wis_tw2804 *dec;
+  struct v4l2_subdev *sd;
 
+  printk(KERN_DEBUG "wis_tw2804 :probing %s adapter 
%s",id->name,client->adapter->name);
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
@@ -303,13 +370,15 @@ static int wis_tw2804_probe(struct i2c_c
        if (dec == NULL)
                return -ENOMEM;
 
+  sd=&dec->sd;
        dec->channel = -1;
        dec->norm = V4L2_STD_NTSC;
        dec->brightness = 128;
        dec->contrast = 128;
        dec->saturation = 128;
        dec->hue = 128;
-       i2c_set_clientdata(client, dec);
+  v4l2_i2c_subdev_init(sd,client,&tw2804_ops);
+  v4l2_info(sd,"initializing %s at address 0x%x on %s\n","tw 2804", 
client->addr, client->adapter->name);
 
        printk(KERN_DEBUG "wis-tw2804: creating TW2804 at address %d on %s\n",
                client->addr, adapter->name);
@@ -319,9 +388,10 @@ static int wis_tw2804_probe(struct i2c_c
 
 static int wis_tw2804_remove(struct i2c_client *client)
 {
-       struct wis_tw2804 *dec = i2c_get_clientdata(client);
-
-       kfree(dec);
+  struct v4l2_subdev *sd=i2c_get_clientdata(client);
+  printk(KERN_INFO"wis_tw2804: remove");
+  v4l2_device_unregister_subdev(sd);
+  kfree(to_state(sd));
        return 0;
 }
 


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to