diff mbox

go7007 driver -- which program you use for capture

Message ID 4B47B0EB.6000102@gmail.com (mailing list archive)
State Changes Requested
Headers show

Commit Message

TJ Jan. 8, 2010, 10:25 p.m. UTC
None
diff mbox

Patch

diff -U 3 -H -d -I' ' -x' .*' -r -N -- linux-2.6.32-gentoo/drivers/staging/go7007/Kconfig linux-2.6.32-gentoo_DX2/drivers/staging/go7007/Kconfig
--- linux-2.6.32-gentoo/drivers/staging/go7007/Kconfig	2010-01-08 16:20:20.000000000 -0500
+++ linux-2.6.32-gentoo_DX2/drivers/staging/go7007/Kconfig	2010-01-08 10:24:34.000000000 -0500
@@ -77,6 +77,16 @@ 
 	  To compile this driver as a module, choose M here: the
 	  module will be called wis-tw9903
 
+config VIDEO_GO7007_TW9906
+	tristate "TW9906 subdev support"
+	depends on VIDEO_GO7007
+	default N
+	---help---
+	  This is a video4linux driver for the TW9906 sub-device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wis-tw9906
+
 config VIDEO_GO7007_UDA1342
 	tristate "UDA1342 subdev support"
 	depends on VIDEO_GO7007
diff -U 3 -H -d -I' ' -x' .*' -r -N -- linux-2.6.32-gentoo/drivers/staging/go7007/go7007-driver.c linux-2.6.32-gentoo_DX2/drivers/staging/go7007/go7007-driver.c
--- linux-2.6.32-gentoo/drivers/staging/go7007/go7007-driver.c	2010-01-08 16:20:20.000000000 -0500
+++ linux-2.6.32-gentoo_DX2/drivers/staging/go7007/go7007-driver.c	2010-01-08 10:24:34.000000000 -0500
@@ -170,6 +171,17 @@ 
 		/* Set GPIO pin 0 to be an output (audio clock control) */
 		go7007_write_addr(go, 0x3c82, 0x0001);
 		go7007_write_addr(go, 0x3c80, 0x00fe);
+		break;
+	case GO7007_BOARDID_ADS_USBAV_709:
+		/* GPIO pin 0: audio clock control */
+		/*      pin 2: TW9906 reset */
+		/*      pin 3: capture LED */
+		go7007_write_addr(go, 0x3c82, 0x000d);
+		go7007_write_addr(go, 0x3c80, 0x00f2);
+		break;
+	default:
+		/* No special setup */
+		break;
 	}
 	return 0;
 }
@@ -212,6 +224,9 @@ 
 	case I2C_DRIVERID_WIS_TW9903:
 		modname = "wis-tw9903";
 		break;
+	case I2C_DRIVERID_WIS_TW9906:
+		modname = "wis-tw9906";
+		break;
 	case I2C_DRIVERID_WIS_TW2804:
 		modname = "wis-tw2804";
 		break;
@@ -269,6 +284,12 @@ 
 		go->i2c_adapter_online = 1;
 	}
 	if (go->i2c_adapter_online) {
+		if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) {
+			/* Reset the TW9906 */
+			go7007_write_addr(go, 0x3c82, 0x0009);
+			msleep(50);
+			go7007_write_addr(go, 0x3c82, 0x000d);
+		}
 		for (i = 0; i < go->board_info->num_i2c_devs; ++i)
 			init_i2c_module(&go->i2c_adapter,
 					go->board_info->i2c_devs[i].type,
diff -U 3 -H -d -I' ' -x' .*' -r -N -- linux-2.6.32-gentoo/drivers/staging/go7007/go7007-usb.c linux-2.6.32-gentoo_DX2/drivers/staging/go7007/go7007-usb.c
--- linux-2.6.32-gentoo/drivers/staging/go7007/go7007-usb.c	2010-01-08 16:20:20.000000000 -0500
+++ linux-2.6.32-gentoo_DX2/drivers/staging/go7007/go7007-usb.c	2010-01-08 10:24:34.000000000 -0500
@@ -444,6 +444,44 @@ 
 	},
 };
 
+static struct go7007_usb_board board_ads_usbav_709 = {
+	.flags		= GO7007_USB_EZUSB,
+	.main_info	= {
+		.firmware	 = "go7007tv.bin",
+		.flags		 = GO7007_BOARD_HAS_AUDIO |
+					GO7007_BOARD_USE_ONBOARD_I2C,
+		.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
+					GO7007_AUDIO_I2S_MASTER |
+					GO7007_AUDIO_WORD_16,
+		.audio_rate	 = 48000,
+		.audio_bclk_div	 = 8,
+		.audio_main_div	 = 2,
+		.hpi_buffer_cap  = 7,
+		.sensor_flags	 = GO7007_SENSOR_656 |
+					GO7007_SENSOR_TV |
+					GO7007_SENSOR_VBI,
+		.num_i2c_devs	 = 1,
+		.i2c_devs	 = {
+			{
+				.type	= "wis_tw9906",
+				.id	= I2C_DRIVERID_WIS_TW9906,
+				.addr	= 0x44,
+			},
+		},
+		.num_inputs	 = 2,
+		.inputs 	 = {
+			{
+				.video_input	= 0,
+				.name		= "Composite",
+			},
+			{
+				.video_input	= 10,
+				.name		= "S-Video",
+			},
+		},
+	},
+};
+
 static struct usb_device_id go7007_usb_id_table[] = {
 	{
 		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
@@ -545,6 +583,14 @@ 
 		.bcdDevice_hi	= 0x1,
 		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250,
 	},
+	{
+		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+		.idVendor	= 0x06e1,  /* Vendor ID of ADS Technologies */
+		.idProduct	= 0x0709,  /* Product ID of DVD Xpress DX2 */
+		.bcdDevice_lo	= 0x204,
+		.bcdDevice_hi	= 0x204,
+		.driver_info	= (kernel_ulong_t)GO7007_BOARDID_ADS_USBAV_709,
+	},
 	{ }					/* Terminating entry */
 };
 
@@ -1023,6 +1069,10 @@ 
 		name = "Sensoray 2250/2251";
 		board = &board_sensoray_2250;
 		break;
+	case GO7007_BOARDID_ADS_USBAV_709:
+		name = "ADS Tech DVD Xpress DX2";
+		board = &board_ads_usbav_709;
+		break;
 	default:
 		printk(KERN_ERR "go7007-usb: unknown board ID %d!\n",
 				(unsigned int)id->driver_info);
diff -U 3 -H -d -I' ' -x' .*' -r -N -- linux-2.6.32-gentoo/drivers/staging/go7007/go7007-v4l2.c linux-2.6.32-gentoo_DX2/drivers/staging/go7007/go7007-v4l2.c
--- linux-2.6.32-gentoo/drivers/staging/go7007/go7007-v4l2.c	2010-01-08 16:20:20.000000000 -0500
+++ linux-2.6.32-gentoo_DX2/drivers/staging/go7007/go7007-v4l2.c	2010-01-08 16:50:34.000000000 -0500
@@ -43,9 +43,39 @@ 
 #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
+#define V4L2_MPEG_VIDEO_ENCODING_MPEG_4   2
+#endif
+#ifndef V4L2_MPEG_VIDEO_ENCODING_NONE
+#define V4L2_MPEG_VIDEO_ENCODING_NONE     3
 #endif
 
+/* Must be sorted from low to high control ID! */
+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 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[] = {
+	user_ctrls,
+	mpeg_ctrls,
+	NULL
+};
+
 static void deactivate_buffer(struct go7007_buffer *gobuf)
 {
 	int i;
@@ -387,23 +417,6 @@ 
 
 static int mpeg_queryctrl(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);
@@ -415,8 +428,8 @@ 
 	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);
+				V4L2_MPEG_VIDEO_ENCODING_NONE, 1,
+				V4L2_MPEG_VIDEO_ENCODING_NONE);
 	case V4L2_CID_MPEG_VIDEO_ASPECT:
 		return v4l2_ctrl_query_fill(ctrl,
 				V4L2_MPEG_VIDEO_ASPECT_1x1,
@@ -556,6 +570,9 @@ 
 		case GO7007_FORMAT_MPEG4:
 			ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4;
 			break;
+		case GO7007_FORMAT_MJPEG:
+			ctrl->value = V4L2_MPEG_VIDEO_ENCODING_NONE;
+			break;
 		default:
 			return -EINVAL;
 		}
@@ -858,7 +875,6 @@ 
 	return retval;
 }
 
-
 static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 {
 	struct go7007_file *gofh = priv;
@@ -977,11 +993,61 @@ 
 	if (!go->i2c_adapter_online)
 		return -EIO;
 
+	query->id = v4l2_ctrl_next(ctrl_classes, query->id);
+
 	i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, query);
 
 	return (!query->name[0]) ? mpeg_queryctrl(query) : 0;
 }
 
+const char **go7007_ctrl_get_menu(void *priv, u32 id)
+{
+    static const char *mpeg_stream_type[] = {
+	"",
+	"",
+	"",
+	"MPEG-2 DVD-compatible Stream",
+	"",
+	"",
+	"MPEG-2 Elementary Stream",
+	NULL
+    };
+    static const char *mpeg_video_encoding[] = {
+	"MPEG-1",
+	"MPEG-2",
+	"MPEG-4",
+	"None (Motion-JPEG)",
+        NULL
+    };
+    static const char *mpeg_video_aspect[] = {
+	"1x1",
+	"4x3",
+	"16x9",
+        NULL
+    };
+
+    switch (id) {
+        case V4L2_CID_MPEG_VIDEO_ENCODING:
+	    return mpeg_video_encoding;
+        case V4L2_CID_MPEG_VIDEO_ASPECT:
+	    return mpeg_video_aspect;
+        case V4L2_CID_MPEG_STREAM_TYPE:
+	    return mpeg_stream_type;
+        default:
+	    return NULL;
+    }
+}
+
+int vidioc_querymenu(struct file *file, void *priv, struct v4l2_querymenu *qmenu)
+{
+    struct v4l2_queryctrl qctrl;
+
+    qctrl.id = qmenu->id;
+    vidioc_queryctrl(file, priv, &qctrl);
+    
+    return v4l2_ctrl_query_menu(qmenu, &qctrl, go7007_ctrl_get_menu(priv, qmenu->id));
+}
+
 static int vidioc_g_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
@@ -1020,6 +1086,46 @@ 
 	return 0;
 }
 
+int vidioc_g_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *c)
+{
+	struct v4l2_control ctrl;
+
+	int i;
+	int err = 0;
+
+	for (i = 0; i < c->count; i++) {
+		ctrl.id = c->controls[i].id;
+		ctrl.value = c->controls[i].value;
+		err = vidioc_g_ctrl(file, priv, &ctrl);
+		c->controls[i].value = ctrl.value;
+		if (err) {
+			c->error_idx = i;
+			break;
+		}
+	}
+	return err;
+}
+
+int vidioc_s_ext_ctrls(struct file *file, void *priv, struct v4l2_ext_controls *c)
+{
+	struct v4l2_control ctrl;
+
+	int i;
+	int err = 0;
+
+	for (i = 0; i < c->count; i++) {
+		ctrl.id = c->controls[i].id;
+		ctrl.value = c->controls[i].value;
+		err = vidioc_s_ctrl(file, priv, &ctrl);
+		c->controls[i].value = ctrl.value;
+		if (err) {
+			c->error_idx = i;
+			break;
+		}
+	}
+	return err;
+}
+
 static int vidioc_g_parm(struct file *filp, void *priv,
 		struct v4l2_streamparm *parm)
 {
@@ -1440,7 +1546,13 @@ 
 	and vidioc_s_ext_ctrls()
  */
 
-#if 0
+static long go7007_prop_ioctl(struct file *file,
+		unsigned int cmd, void *arg)
+{
+	struct go7007 *go = ((struct go7007_file *) file->private_data)->go;
+
+	switch (cmd) {
+#if 1
 	/* Temporary ioctls for controlling compression characteristics */
 	case GO7007IOC_S_BITRATE:
 	{
@@ -1578,10 +1690,9 @@ 
 			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->repeat_seqhead =
+				mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER
+				? 1 : 0;
 			go->dvd_mode = 0;
 		}
 		/* fall-through */
@@ -1661,6 +1772,25 @@ 
 		return clip_to_modet_map(go, region->region, region->clips);
 	}
 #endif
+	}
+	return -EINVAL;
+}
+
+
+static long go7007_ioctl(struct file *file,
+		unsigned int cmd, unsigned long arg)
+{
+	struct go7007 *go = ((struct go7007_file *) file->private_data)->go;
+	int retval;
+
+	if (go->status != STATUS_ONLINE)
+		return -EIO;
+
+	retval = video_ioctl2(file, cmd, arg);
+	if (retval < 0)
+		retval = video_usercopy(file, cmd, arg, (v4l2_kioctl)go7007_prop_ioctl);
+        return retval;
+}
 
 static ssize_t go7007_read(struct file *file, char __user *data,
 		size_t count, loff_t *ppos)
Files linux-2.6.32-gentoo/drivers/staging/go7007/go7007-v4l2.o and linux-2.6.32-gentoo_DX2/drivers/staging/go7007/go7007-v4l2.o differ
Files linux-2.6.32-gentoo/drivers/staging/go7007/go7007.ko and linux-2.6.32-gentoo_DX2/drivers/staging/go7007/go7007.ko differ
Files linux-2.6.32-gentoo/drivers/staging/go7007/go7007.o and linux-2.6.32-gentoo_DX2/drivers/staging/go7007/go7007.o differ
diff -U 3 -H -d -I' ' -x' .*' -r -N -- linux-2.6.32-gentoo/drivers/staging/go7007/s2250-board.c linux-2.6.32-gentoo_DX2/drivers/staging/go7007/s2250-board.c
--- linux-2.6.32-gentoo/drivers/staging/go7007/s2250-board.c	2010-01-08 16:20:20.000000000 -0500
+++ linux-2.6.32-gentoo_DX2/drivers/staging/go7007/s2250-board.c	2010-01-08 10:24:34.000000000 -0500
@@ -357,32 +357,18 @@ 
 	case VIDIOC_QUERYCTRL:
 	{
 		struct v4l2_queryctrl *ctrl = arg;
-		static const u32 user_ctrls[] = {
-			V4L2_CID_BRIGHTNESS,
-			V4L2_CID_CONTRAST,
-			V4L2_CID_SATURATION,
-			V4L2_CID_HUE,
-			0
-		};
-		static const u32 *ctrl_classes[] = {
-			user_ctrls,
-			NULL
-		};
 
-		ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id);
 		switch (ctrl->id) {
+		case V4L2_CID_USER_CLASS:
+			return v4l2_ctrl_query_fill(ctrl, 0, 0, 0, 0);
 		case V4L2_CID_BRIGHTNESS:
-			v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
-			break;
+			return v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
 		case V4L2_CID_CONTRAST:
-			v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
-			break;
+			return v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
 		case V4L2_CID_SATURATION:
-			v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
-			break;
+			return v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
 		case V4L2_CID_HUE:
-			v4l2_ctrl_query_fill(ctrl, -50, 50, 1, 0);
-			break;
+			return v4l2_ctrl_query_fill(ctrl, -50, 50, 1, 0);
 		default:
 			ctrl->name[0] = '\0';
 			return -EINVAL;
diff -U 3 -H -d -I' ' -x' .*' -r -N -- linux-2.6.32-gentoo/drivers/staging/go7007/wis-i2c.h linux-2.6.32-gentoo_DX2/drivers/staging/go7007/wis-i2c.h
--- linux-2.6.32-gentoo/drivers/staging/go7007/wis-i2c.h	2010-01-08 16:20:20.000000000 -0500
+++ linux-2.6.32-gentoo_DX2/drivers/staging/go7007/wis-i2c.h	2010-01-08 10:24:34.000000000 -0500
@@ -24,6 +24,7 @@ 
 #define	I2C_DRIVERID_WIS_OV7640		0xf0f5
 #define	I2C_DRIVERID_WIS_TW2804		0xf0f6
 #define	I2C_DRIVERID_S2250		0xf0f7
+#define	I2C_DRIVERID_WIS_TW9906		0xf0f9
 
 /* Flag to indicate that the client needs to be accessed with SCCB semantics */
 /* We re-use the I2C_M_TEN value so the flag passes through the masks in the
diff -U 3 -H -d -I' ' -x' .*' -r -N -- linux-2.6.32-gentoo/drivers/staging/go7007/wis-saa7113.c linux-2.6.32-gentoo_DX2/drivers/staging/go7007/wis-saa7113.c
--- linux-2.6.32-gentoo/drivers/staging/go7007/wis-saa7113.c	2010-01-08 16:20:20.000000000 -0500
+++ linux-2.6.32-gentoo_DX2/drivers/staging/go7007/wis-saa7113.c	2010-01-08 10:24:34.000000000 -0500
@@ -152,42 +152,19 @@ 
 		struct v4l2_queryctrl *ctrl = arg;
 
 		switch (ctrl->id) {
+		case V4L2_CID_USER_CLASS:
+			return v4l2_ctrl_query_fill(ctrl, 0, 0, 0, 0);
 		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;
+			return v4l2_ctrl_query_fill(ctrl, 0, 255, 1, 128);
 		case V4L2_CID_CONTRAST:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 71;
-			ctrl->flags = 0;
-			break;
+			return v4l2_ctrl_query_fill(ctrl, 0, 127, 1, 71);
 		case V4L2_CID_SATURATION:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 64;
-			ctrl->flags = 0;
-			break;
+			return v4l2_ctrl_query_fill(ctrl, 0, 127, 1, 64);
 		case V4L2_CID_HUE:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
-			ctrl->minimum = -128;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 0;
-			ctrl->flags = 0;
-			break;
+			return v4l2_ctrl_query_fill(ctrl, -128, 127, 1, 0);
+		default:
+			ctrl->name[0] = '\0';
+			return -EINVAL;
 		}
 		break;
 	}
diff -U 3 -H -d -I' ' -x' .*' -r -N -- linux-2.6.32-gentoo/drivers/staging/go7007/wis-saa7115.c linux-2.6.32-gentoo_DX2/drivers/staging/go7007/wis-saa7115.c
--- linux-2.6.32-gentoo/drivers/staging/go7007/wis-saa7115.c	2010-01-08 16:20:20.000000000 -0500
+++ linux-2.6.32-gentoo_DX2/drivers/staging/go7007/wis-saa7115.c	2010-01-08 10:24:34.000000000 -0500
@@ -285,42 +285,19 @@ 
 		struct v4l2_queryctrl *ctrl = arg;
 
 		switch (ctrl->id) {
+		case V4L2_CID_USER_CLASS:
+			return v4l2_ctrl_query_fill(ctrl, 0, 0, 0, 0);
 		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;
+			return v4l2_ctrl_query_fill(ctrl, 0, 255, 1, 128);
 		case V4L2_CID_CONTRAST:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 64;
-			ctrl->flags = 0;
-			break;
+			return v4l2_ctrl_query_fill(ctrl, 0, 127, 1, 64);
 		case V4L2_CID_SATURATION:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 64;
-			ctrl->flags = 0;
-			break;
+			return v4l2_ctrl_query_fill(ctrl, 0, 127, 1, 64);
 		case V4L2_CID_HUE:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
-			ctrl->minimum = -128;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 0;
-			ctrl->flags = 0;
-			break;
+			return v4l2_ctrl_query_fill(ctrl, -128, 127, 1, 0);
+		default:
+			ctrl->name[0] = '\0';
+			return -EINVAL;
 		}
 		break;
 	}
diff -U 3 -H -d -I' ' -x' .*' -r -N -- linux-2.6.32-gentoo/drivers/staging/go7007/wis-tw2804.c linux-2.6.32-gentoo_DX2/drivers/staging/go7007/wis-tw2804.c
--- linux-2.6.32-gentoo/drivers/staging/go7007/wis-tw2804.c	2010-01-08 16:20:20.000000000 -0500
+++ linux-2.6.32-gentoo_DX2/drivers/staging/go7007/wis-tw2804.c	2010-01-08 10:24:34.000000000 -0500
@@ -182,42 +182,19 @@ 
 		struct v4l2_queryctrl *ctrl = arg;
 
 		switch (ctrl->id) {
+		case V4L2_CID_USER_CLASS:
+			return v4l2_ctrl_query_fill(ctrl, 0, 0, 0, 0);
 		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;
+			return v4l2_ctrl_query_fill(ctrl, 0, 255, 1, 128);
 		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;
+			return v4l2_ctrl_query_fill(ctrl, 0, 255, 1, 128);
 		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;
+			return v4l2_ctrl_query_fill(ctrl, 0, 255, 1, 128);
 		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;
+			return v4l2_ctrl_query_fill(ctrl, 0, 255, 1, 128);
+		default:
+			ctrl->name[0] = '\0';
+			return -EINVAL;
 		}
 		break;
 	}
diff -U 3 -H -d -I' ' -x' .*' -r -N -- linux-2.6.32-gentoo/drivers/staging/go7007/wis-tw9903.c linux-2.6.32-gentoo_DX2/drivers/staging/go7007/wis-tw9903.c
--- linux-2.6.32-gentoo/drivers/staging/go7007/wis-tw9903.c	2010-01-08 16:20:20.000000000 -0500
+++ linux-2.6.32-gentoo_DX2/drivers/staging/go7007/wis-tw9903.c	2010-01-08 10:24:34.000000000 -0500
@@ -152,45 +152,23 @@ 
 		struct v4l2_queryctrl *ctrl = arg;
 
 		switch (ctrl->id) {
+		case V4L2_CID_USER_CLASS:
+			return v4l2_ctrl_query_fill(ctrl, 0, 0, 0, 0);
 		case V4L2_CID_BRIGHTNESS:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
-			ctrl->minimum = -128;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 0x00;
-			ctrl->flags = 0;
-			break;
+			return v4l2_ctrl_query_fill(ctrl, -128, 127, 1, 0x0);
 		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 = 0x60;
-			ctrl->flags = 0;
-			break;
-#if 0
-		/* I don't understand how the Chroma Gain registers work... */
+			return v4l2_ctrl_query_fill(ctrl, 0, 255, 1, 0x60);
 		case V4L2_CID_SATURATION:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
-			ctrl->minimum = 0;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 64;
-			ctrl->flags = 0;
-			break;
-#endif
+		{
+			int ret = v4l2_ctrl_query_fill(ctrl, 0, 127, 1, 64);
+			ctrl->flags |= V4L2_CTRL_FLAG_DISABLED; // I don't understand how the Chroma Gain registers work...
+			return ret;
+		}
 		case V4L2_CID_HUE:
-			ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-			strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
-			ctrl->minimum = -128;
-			ctrl->maximum = 127;
-			ctrl->step = 1;
-			ctrl->default_value = 0;
-			ctrl->flags = 0;
-			break;
+			return v4l2_ctrl_query_fill(ctrl, -128, 127, 1, 0);
+		default:
+			ctrl->name[0] = '\0';
+			return -EINVAL;
 		}
 		break;
 	}
diff -U 3 -H -d -I' ' -x' .*' -r -N -- linux-2.6.32-gentoo/drivers/staging/go7007/wis-tw9906.c linux-2.6.32-gentoo_DX2/drivers/staging/go7007/wis-tw9906.c
--- linux-2.6.32-gentoo/drivers/staging/go7007/wis-tw9906.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.32-gentoo_DX2/drivers/staging/go7007/wis-tw9906.c	2010-01-08 10:24:34.000000000 -0500
@@ -0,0 +1,261 @@ 
+/*
+ * Copyright (C) 2005-2006 Micronas USA Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+
+#include "wis-i2c.h"
+
+struct wis_tw9906 {
+	int norm;
+	int brightness;
+	int contrast;
+	int hue;
+};
+
+static u8 initial_registers[] =
+{
+	0x02, 0x40, /* input 0, composite */
+	0x03, 0xa2, /* correct digital format */
+	0x05, 0x81, /* or 0x01 for PAL */
+	0x07, 0x02, /* window */
+	0x08, 0x14, /* window */
+	0x09, 0xf0, /* window */
+	0x0a, 0x10, /* window */
+	0x0b, 0xd0, /* window */
+	0x0d, 0x00, /* scaling */
+	0x0e, 0x11, /* scaling */
+	0x0f, 0x00, /* scaling */
+	0x10, 0x00, /* brightness */
+	0x11, 0x60, /* contrast */
+	0x12, 0x11, /* sharpness */
+	0x13, 0x7e, /* U gain */
+	0x14, 0x7e, /* V gain */
+	0x15, 0x00, /* hue */
+	0x19, 0x57, /* vbi */
+	0x1a, 0x0f,
+	0x1b, 0x40,
+	0x29, 0x03,
+	0x55, 0x00,
+	0x6b, 0x26,
+	0x6c, 0x36,
+	0x6d, 0xf0,
+	0x6e, 0x41,
+	0x6f, 0x13,
+	0xad, 0x70,
+	0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
+};
+
+static int write_reg(struct i2c_client *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static int write_regs(struct i2c_client *client, u8 *regs)
+{
+	int i;
+
+	for (i = 0; regs[i] != 0x00; i += 2)
+		if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
+			return -1;
+	return 0;
+}
+
+static int wis_tw9906_command(struct i2c_client *client,
+				unsigned int cmd, void *arg)
+{
+	struct wis_tw9906 *dec = i2c_get_clientdata(client);
+
+	switch (cmd) {
+	case VIDIOC_S_INPUT:
+	{
+		int *input = arg;
+
+		i2c_smbus_write_byte_data(client, 0x02, 0x40 | (*input << 1));
+		break;
+	}
+	case VIDIOC_S_STD:
+	{
+		v4l2_std_id *input = arg;
+		u8 regs[] = {
+			0x05, *input & V4L2_STD_NTSC ? 0x81 : 0x01,
+			0x07, *input & V4L2_STD_NTSC ? 0x02 : 0x12,
+			0x08, *input & V4L2_STD_NTSC ? 0x14 : 0x18,
+			0x09, *input & V4L2_STD_NTSC ? 0xf0 : 0x20,
+			0,	0,
+		};
+		write_regs(client, regs);
+		dec->norm = *input;
+		break;
+	}
+	case VIDIOC_QUERYCTRL:
+	{
+		struct v4l2_queryctrl *ctrl = arg;
+
+		switch (ctrl->id) {
+		case V4L2_CID_USER_CLASS:
+			return v4l2_ctrl_query_fill(ctrl, 0, 0, 0, 0);
+		case V4L2_CID_BRIGHTNESS:
+			return v4l2_ctrl_query_fill(ctrl, -128, 127, 1, 0x0);
+		case V4L2_CID_CONTRAST:
+			return v4l2_ctrl_query_fill(ctrl, 0, 255, 1, 0x60);
+		case V4L2_CID_SATURATION:
+		{
+			int ret = v4l2_ctrl_query_fill(ctrl, 0, 127, 1, 64);
+			ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+			return ret;
+		}
+		case V4L2_CID_HUE:
+			return v4l2_ctrl_query_fill(ctrl, -128, 127, 1, 0);
+		default:
+			ctrl->name[0] = '\0';
+			return -EINVAL;
+		}
+		break;
+	}
+	case VIDIOC_S_CTRL:
+	{
+		struct v4l2_control *ctrl = arg;
+
+		switch (ctrl->id) {
+		case V4L2_CID_BRIGHTNESS:
+			if (ctrl->value > 127)
+				dec->brightness = 127;
+			else if (ctrl->value < -128)
+				dec->brightness = -128;
+			else
+				dec->brightness = ctrl->value;
+			write_reg(client, 0x10, dec->brightness);
+			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);
+			break;
+		case V4L2_CID_HUE:
+			if (ctrl->value > 127)
+				dec->hue = 127;
+			else if (ctrl->value < -128)
+				dec->hue = -128;
+			else
+				dec->hue = ctrl->value;
+			write_reg(client, 0x15, dec->hue);
+			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_HUE:
+			ctrl->value = dec->hue;
+			break;
+		}
+		break;
+	}
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int wis_tw9906_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	struct wis_tw9906 *dec;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	dec = kmalloc(sizeof(struct wis_tw9906), GFP_KERNEL);
+	if (dec == NULL)
+		return -ENOMEM;
+
+	dec->norm = V4L2_STD_NTSC;
+	dec->brightness = 0;
+	dec->contrast = 0x60;
+	dec->hue = 0;
+	i2c_set_clientdata(client, dec);
+
+	printk(KERN_DEBUG
+		"wis-tw9906: initializing TW9906 at address %d on %s\n",
+		client->addr, adapter->name);
+
+	if (write_regs(client, initial_registers) < 0) {
+		printk(KERN_ERR "wis-tw9906: error initializing TW9906\n");
+		kfree(dec);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int wis_tw9906_remove(struct i2c_client *client)
+{
+
+	struct wis_tw9906 *dec = i2c_get_clientdata(client);
+
+	i2c_set_clientdata(client, NULL);
+	kfree(dec);
+	return 0;
+}
+
+static struct i2c_device_id wis_tw9906_id[] = {
+	{ "wis_tw9906", 0 },
+	{ }
+};
+
+static struct i2c_driver wis_tw9906_driver = {
+	.driver = {
+		.name	= "WIS TW9906 I2C driver",
+	},
+	.probe		= wis_tw9906_probe,
+	.remove		= wis_tw9906_remove,
+	.command	= wis_tw9906_command,
+	.id_table	= wis_tw9906_id,
+};
+
+static int __init wis_tw9906_init(void)
+{
+	return i2c_add_driver(&wis_tw9906_driver);
+}
+
+static void __exit wis_tw9906_cleanup(void)
+{
+	i2c_del_driver(&wis_tw9906_driver);
+}
+
+module_init(wis_tw9906_init);
+module_exit(wis_tw9906_cleanup);
+
+MODULE_LICENSE("GPL v2");