From patchwork Fri Jan 8 22:25:47 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: TJ X-Patchwork-Id: 71876 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.2) with ESMTP id o08MPSdr031281 for ; Fri, 8 Jan 2010 22:25:28 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754125Ab0AHWZ2 (ORCPT ); Fri, 8 Jan 2010 17:25:28 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754151Ab0AHWZ1 (ORCPT ); Fri, 8 Jan 2010 17:25:27 -0500 Received: from mail-yw0-f176.google.com ([209.85.211.176]:33899 "EHLO mail-yw0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752959Ab0AHWZZ (ORCPT ); Fri, 8 Jan 2010 17:25:25 -0500 Received: by ywh6 with SMTP id 6so19923670ywh.4 for ; Fri, 08 Jan 2010 14:25:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:subject:references:in-reply-to :content-type; bh=c57xp5gTSxTJhU8FNCygAksqRgi866WI8mP/t+jjpXQ=; b=N7q1p7qgnUAX7Td3gZAi56E5wG3S39gb/9O1JFgcz87zEzrn1NxbKip6HBF/iLAoFl Y2lNwq+wrgf8X4u5mPmMhXNW1+eXuQGMOBqmz0CwTKS2RV28CYp0KqZ2/nUu1Qw0dCZy VfFYD3ZG7sNZiVq6Z2LfD1dbJh0e8Zj2Fld/A= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject:references :in-reply-to:content-type; b=J1D9OfZyLnx3P4ejat094MpcJRjhYzh5TNnjuHBFRIOc1jcewc9GoD8F+4sbXYzeZQ Sgps52Rnj5y5Lq8iHrhlR7+F2U5IAyqQns4ZLjva08DXKWEo2yABs39A9ayLLSTV6JkH 7peG1pk1W79/gJFVs42DLM+um4kCNiP88yDDA= Received: by 10.101.165.38 with SMTP id s38mr12838244ano.31.1262989524045; Fri, 08 Jan 2010 14:25:24 -0800 (PST) Received: from ?10.10.10.232? ([207.90.4.12]) by mx.google.com with ESMTPS id 4sm8133629ywd.44.2010.01.08.14.25.21 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 08 Jan 2010 14:25:22 -0800 (PST) Message-ID: <4B47B0EB.6000102@gmail.com> Date: Fri, 08 Jan 2010 17:25:47 -0500 From: TJ User-Agent: Thunderbird 2.0.0.23 (X11/20091103) MIME-Version: 1.0 To: Jarod Wilson , "linux-media@vger.kernel.org" Subject: Re: go7007 driver -- which program you use for capture References: <4B47828B.9050000@gmail.com> In-Reply-To: Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org 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 +#include +#include +#include +#include + +#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");