[PATCH] go7007 patch for 3.2.x

volokh volokh at telros.ru
Tue Mar 20 15:30:51 UTC 2012


please reply this at linux-media at vger.kernel.org I`ve some trouble

- 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;
 }
 






More information about the devel mailing list