Changes:

- Add support for SN9C103 based devices. The audio capability is already
  supported but not released in this version. I will release
  it once someone donates two SN9C103 based devices.
- Implement VIDIOC_G_CTRL for TAS5110C1B and TAS51130D1B
- Replace "SN9C10[12]" strings with "SN9C10x"
- Add red, green, blue gain controls to the SN9C103
- Memory offsets are now page-aligned
- Fix typos in the documentation
- Documentation updates
- Setting bounds are checked by the core module
- Add exposure control for TAS51130D1B

Signed-off-by: Luca Risolia <[EMAIL PROTECTED]>

Greg, please apply.

Thanks.

diff -uprN -X dontdiff linux-2.6.8/CREDITS devel-2.6.8/CREDITS
--- linux-2.6.8/CREDITS 2004-08-27 17:50:01.000000000 +0200
+++ devel-2.6.8/CREDITS 2004-08-27 17:42:17.000000000 +0200
@@ -2716,7 +2716,7 @@ N: Luca Risolia
 E: [EMAIL PROTECTED]
 P: 1024D/FCE635A4 88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4
 D: V4L driver for W996[87]CF JPEG USB Dual Mode Camera Chips
-D: V4L2 driver for SN9C10[12] PC Camera Controllers
+D: V4L2 driver for SN9C10x PC Camera Controllers
 S: Via Liberta' 41/A
 S: Osio Sotto, 24046, Bergamo
 S: Italy
diff -uprN -X dontdiff linux-2.6.8/Documentation/usb/sn9c102.txt 
devel-2.6.8/Documentation/usb/sn9c102.txt
--- linux-2.6.8/Documentation/usb/sn9c102.txt   2004-08-27 17:50:05.000000000 +0200
+++ devel-2.6.8/Documentation/usb/sn9c102.txt   2004-08-28 08:06:47.000000000 +0200
@@ -1,7 +1,7 @@
 
-                        SN9C10[12] PC Camera Controllers
+                         SN9C10x PC Camera Controllers
                                 Driver for Linux
-                        ================================
+                         =============================
 
                                - Documentation -
 
@@ -49,22 +49,23 @@ Foundation, Inc., 675 Mass Ave, Cambridg
 
 3. Overview
 ===========
-This driver attempts to support the video streaming capabilities of the devices
-mounting the SONiX SN9C101 or SONiX SN9C102 PC Camera Controllers.
+This driver attempts to support the video and audio streaming capabilities of
+the devices mounting the SONiX SN9C101, SN9C102 and SN9C103 (or SUI-102) PC
+Camera Controllers.
 
 - It's worth to note that SONiX has never collaborated with me during the
-development of this project, despite of several requests for enough detailed
+development of this project, despite several requests for enough detailed
 specifications of the register tables, compression engine and video data format
 of the above chips -
 
 Up to 64 cameras can be handled at the same time. They can be connected and
 disconnected from the host many times without turning off the computer, if
-your system supports the hotplug facility.
+your system supports hotplugging.
 
 The driver relies on the Video4Linux2 and USB core modules. It has been
 designed to run properly on SMP systems as well.
 
-The latest version of the SN9C10[12] driver can be found at the following URL:
+The latest version of the SN9C10x driver can be found at the following URL:
 http://go.lamarinapunto.com/
 
 
@@ -150,17 +151,20 @@ Default:        2
 
 7. Optional device control through "sysfs"
 ==========================================
-It is possible to read and write both the SN9C10[12] and the image sensor
+It is possible to read and write both the SN9C10x and the image sensor
 registers by using the "sysfs" filesystem interface.
 
-Every time a supported device is recognized, a read-only file named "green" is
+Every time a supported device is recognized, a write-only file named "green" is
 created in the /sys/class/video4linux/videoX directory. You can set the green
 channel's gain by writing the desired value to it. The value may range from 0
-to 15.
+to 15 for SN9C101 or SN9C102 bridges, from 0 to 127 for SN9C103 bridges.
+Similarly, only for SN9C103 controllers, blue and red gain control files are
+available in the same directory, for which accepted values may range from 0 to
+127.
 
 There are other four entries in the directory above for each registered camera:
 "reg", "val", "i2c_reg" and "i2c_val". The first two files control the
-SN9C10[12] bridge, while the other two control the sensor chip. "reg" and
+SN9C10x bridge, while the other two control the sensor chip. "reg" and
 "i2c_reg" hold the values of the current register index where the following
 reading/writing operations are addressed at through "val" and "i2c_val". Their
 use is not intended for end-users, unless you know what you are doing. Note
@@ -169,19 +173,19 @@ support the standard I2C protocol. Also,
 root before writing to them.
 
 As an example, suppose we were to want to read the value contained in the
-register number 1 of the sensor register table - which usually is the product
+register number 1 of the sensor register table - which is usually the product
 identifier - of the camera registered as "/dev/video0":
 
        [EMAIL PROTECTED] #] cd /sys/class/video4linux/video0
        [EMAIL PROTECTED] #] echo 1 > i2c_reg
        [EMAIL PROTECTED] #] cat i2c_val
 
-Now let's set the green gain's register of the SN9C10[12] chip to 2:
+Now let's set the green gain's register of the SN9C10x chip to 2:
 
        [EMAIL PROTECTED] #] echo 0x11 > reg
        [EMAIL PROTECTED] #] echo 2 > val
 
-Note that the SN9C10[12] always returns 0 when some of its registers are read.
+Note that the SN9C10x always returns 0 when some of its registers are read.
 To avoid race conditions, all the I/O accesses to the files are serialized.
 
 
@@ -192,25 +196,52 @@ here. They have never collaborated with 
 
 From the point of view of a driver, what unambiguously identify a device are
 its vendor and product USB identifiers. Below is a list of known identifiers of
-devices mounting the SN9C10[12] PC camera controllers:
+devices mounting the SN9C10x PC camera controllers:
 
 Vendor ID  Product ID
 ---------  ----------
-0xc45      0x6001
-0xc45      0x6005
-0xc45      0x6009
-0xc45      0x600d
-0xc45      0x6024
-0xc45      0x6025
-0xc45      0x6028
-0xc45      0x6029
-0xc45      0x602a
-0xc45      0x602c
-0xc45      0x6030
+0x0c45     0x6001
+0x0c45     0x6005
+0x0c45     0x6009
+0x0c45     0x600d
+0x0c45     0x6024
+0x0c45     0x6025
+0x0c45     0x6028
+0x0c45     0x6029
+0x0c45     0x602a
+0x0c45     0x602b
+0x0c45     0x602c
+0x0c45     0x6030
+0x0c45     0x6080
+0x0c45     0x6082
+0x0c45     0x6083
+0x0c45     0x6088
+0x0c45     0x608a
+0x0c45     0x608b
+0x0c45     0x608c
+0x0c45     0x608e
+0x0c45     0x608f
+0x0c45     0x60a0
+0x0c45     0x60a2
+0x0c45     0x60a3
+0x0c45     0x60a8
+0x0c45     0x60aa
+0x0c45     0x60ab
+0x0c45     0x60ac
+0x0c45     0x60ae
+0x0c45     0x60af
+0x0c45     0x60b0
+0x0c45     0x60b2
+0x0c45     0x60b3
+0x0c45     0x60b8
+0x0c45     0x60ba
+0x0c45     0x60bb
+0x0c45     0x60bc
+0x0c45     0x60be
 
 The list above does NOT imply that all those devices work with this driver: up
-until now only the ones that mount the following image sensors are supported.
-Kernel messages will always tell you whether this is the case:
+until now only the ones that mount the following image sensors are supported;
+kernel messages will always tell you whether this is the case:
 
 Model       Manufacturer
 -----       ------------
@@ -224,7 +255,7 @@ listed in the above table, you may try t
 ProductID identifiers to the sn9c102_id_table[] in the file "sn9c102_sensor.h";
 then compile, load the module again and look at the kernel output.
 If this works, please send an email to me reporting the kernel messages, so
-that I will add a new entry in the list of supported devices.
+that I can add a new entry in the list of supported devices.
 
 Donations of new models for further testing and support would be much
 appreciated. I won't add official support for hardware that I don't actually
@@ -238,8 +269,8 @@ have created for this purpose, which is 
 (documentation is included there). As an example, have a look at the code in
 "sn9c102_pas106b.c", which uses the mentioned interface.
 
-At the moment, not yet supported image sensors are: HV7131[D|E1] (VGA),
-MI03 (VGA), OV7620 (VGA).
+At the moment, possible unsupported image sensors are: HV7131x series (VGA),
+MI03x series (VGA), OV7620 (VGA), OV7630 (VGA), CIS-VF10 (VGA).
 
 
 10. Notes for V4L2 application developers
@@ -254,12 +285,13 @@ device to switch to the other I/O method
 - previously mapped buffer memory must always be unmapped before calling any
 of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. The same
 number of buffers as before will be allocated again to match the size of the
-new video frames, so you have to map them again before any I/O attempts.
+new video frames, so you have to map the buffers again before any I/O attempts
+on them.
 
 Consistently with the hardware limits, this driver also supports image
 downscaling with arbitrary scaling factors from 1, 2 and 4 in both directions.
-However the V4L2 API specifications don't correctly define how the scaling
-factor can be choosen arbitrarily by the "negotiation" of the "source" and
+However, the V4L2 API specifications don't correctly define how the scaling
+factor can be chosen arbitrarily by the "negotiation" of the "source" and
 "target" rectangles. To work around this flaw, we have added the convention
 that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
 scaling factor is restored to 1.
diff -uprN -X dontdiff linux-2.6.8/drivers/usb/media/Kconfig 
devel-2.6.8/drivers/usb/media/Kconfig
--- linux-2.6.8/drivers/usb/media/Kconfig       2004-08-27 17:48:02.000000000 +0200
+++ devel-2.6.8/drivers/usb/media/Kconfig       2004-08-27 17:43:31.000000000 +0200
@@ -163,11 +163,11 @@ config USB_SE401
          module will be called se401.
 
 config USB_SN9C102
-       tristate "USB SN9C10[12] PC Camera Controller support"
+       tristate "USB SN9C10x PC Camera Controller support"
        depends on USB && VIDEO_DEV
        ---help---
-         Say Y here if you want support for cameras based on SONiX SN9C101
-         or SN9C102 PC Camera Controllers.
+         Say Y here if you want support for cameras based on SONiX SN9C101,
+         SN9C102 or SN9C103 PC Camera Controllers.
 
          See <file:Documentation/usb/sn9c102.txt> for more informations.
 
diff -uprN -X dontdiff linux-2.6.8/drivers/usb/media/sn9c102_core.c 
devel-2.6.8/drivers/usb/media/sn9c102_core.c
--- linux-2.6.8/drivers/usb/media/sn9c102_core.c        2004-08-27 17:51:02.000000000 
+0200
+++ devel-2.6.8/drivers/usb/media/sn9c102_core.c        2004-08-27 17:38:22.000000000 
+0200
@@ -1,5 +1,5 @@
 /***************************************************************************
- * V4L2 driver for SN9C10[12] PC Camera Controllers                        *
+ * V4L2 driver for SN9C10x PC Camera Controllers                           *
  *                                                                         *
  * Copyright (C) 2004 by Luca Risolia <[EMAIL PROTECTED]>       *
  *                                                                         *
@@ -169,15 +169,15 @@ static u32 sn9c102_request_buffers(struc
 
        cam->nbuffers = count;
        while (cam->nbuffers > 0) {
-               if ((buff = rvmalloc(cam->nbuffers * imagesize)))
+               if ((buff = rvmalloc(cam->nbuffers * PAGE_ALIGN(imagesize))))
                        break;
                cam->nbuffers--;
        }
 
        for (i = 0; i < cam->nbuffers; i++) {
-               cam->frame[i].bufmem = buff + i*imagesize;
+               cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize);
                cam->frame[i].buf.index = i;
-               cam->frame[i].buf.m.offset = i*imagesize;
+               cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize);
                cam->frame[i].buf.length = imagesize;
                cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                cam->frame[i].buf.sequence = 0;
@@ -388,7 +388,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102
        data[4] = data3;
        data[5] = data4;
        data[6] = data5;
-       data[7] = 0x10;
+       data[7] = 0x14;
        res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
                              0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
        if (res < 0)
@@ -1022,15 +1022,79 @@ sn9c102_store_i2c_val(struct class_devic
 static ssize_t
 sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
 {
+       struct sn9c102_device* cam;
+       enum sn9c102_bridge bridge;
        ssize_t res = 0;
        u8 value;
        ssize_t count;
 
+       if (down_interruptible(&sn9c102_sysfs_lock))
+               return -ERESTARTSYS;
+
+       cam = video_get_drvdata(to_video_device(cd));
+       if (!cam) {
+               up(&sn9c102_sysfs_lock);
+               return -ENODEV;
+       }
+
+       bridge = cam->bridge;
+
+       up(&sn9c102_sysfs_lock);
+
        value = sn9c102_strtou8(buf, len, &count);
-       if (!count || value > 0x0f)
+       if (!count)
                return -EINVAL;
 
-       if ((res = sn9c102_store_reg(cd, "0x11", 4)) >= 0)
+       switch (bridge) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+               if (value > 0x0f)
+                       return -EINVAL;
+               if ((res = sn9c102_store_reg(cd, "0x11", 4)) >= 0)
+                       res = sn9c102_store_val(cd, buf, len);
+               break;
+       case BRIDGE_SN9C103:
+               if (value > 0x7f)
+                       return -EINVAL;
+               if ((res = sn9c102_store_reg(cd, "0x04", 4)) >= 0)
+                       res = sn9c102_store_val(cd, buf, len);
+               break;
+       }
+
+       return res;
+}
+
+
+static ssize_t
+sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len)
+{
+       ssize_t res = 0;
+       u8 value;
+       ssize_t count;
+
+       value = sn9c102_strtou8(buf, len, &count);
+       if (!count || value > 0x7f)
+               return -EINVAL;
+
+       if ((res = sn9c102_store_reg(cd, "0x06", 4)) >= 0)
+               res = sn9c102_store_val(cd, buf, len);
+
+       return res;
+}
+
+
+static ssize_t
+sn9c102_store_red(struct class_device* cd, const char* buf, size_t len)
+{
+       ssize_t res = 0;
+       u8 value;
+       ssize_t count;
+
+       value = sn9c102_strtou8(buf, len, &count);
+       if (!count || value > 0x7f)
+               return -EINVAL;
+
+       if ((res = sn9c102_store_reg(cd, "0x05", 4)) >= 0)
                res = sn9c102_store_val(cd, buf, len);
 
        return res;
@@ -1046,6 +1110,8 @@ static CLASS_DEVICE_ATTR(i2c_reg, S_IRUG
 static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
                          sn9c102_show_i2c_val, sn9c102_store_i2c_val);
 static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
+static CLASS_DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);
+static CLASS_DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);
 
 
 static void sn9c102_create_sysfs(struct sn9c102_device* cam)
@@ -1054,7 +1120,12 @@ static void sn9c102_create_sysfs(struct 
 
        video_device_create_file(v4ldev, &class_device_attr_reg);
        video_device_create_file(v4ldev, &class_device_attr_val);
-       video_device_create_file(v4ldev, &class_device_attr_green);
+       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
+               video_device_create_file(v4ldev, &class_device_attr_green);
+       else if (cam->bridge == BRIDGE_SN9C103) {
+               video_device_create_file(v4ldev, &class_device_attr_blue);
+               video_device_create_file(v4ldev, &class_device_attr_red);
+       }
        if (cam->sensor->slave_write_id && cam->sensor->slave_read_id) {
                video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
                video_device_create_file(v4ldev, &class_device_attr_i2c_val);
@@ -1092,21 +1163,13 @@ static int sn9c102_set_crop(struct sn9c1
        u8 h_start = (u8)(rect->left - s->cropcap.bounds.left),
           v_start = (u8)(rect->top - s->cropcap.bounds.top),
           h_size = (u8)(rect->width / 16),
-          v_size = (u8)(rect->height / 16),
-          ae_strx = 0x00,
-          ae_stry = 0x00,
-          ae_endx = h_size / 2,
-          ae_endy = v_size / 2;
+          v_size = (u8)(rect->height / 16);
        int err = 0;
 
        err += sn9c102_write_reg(cam, h_start, 0x12);
        err += sn9c102_write_reg(cam, v_start, 0x13);
        err += sn9c102_write_reg(cam, h_size, 0x15);
        err += sn9c102_write_reg(cam, v_size, 0x16);
-       err += sn9c102_write_reg(cam, ae_strx, 0x1c);
-       err += sn9c102_write_reg(cam, ae_stry, 0x1d);
-       err += sn9c102_write_reg(cam, ae_endx, 0x1e);
-       err += sn9c102_write_reg(cam, ae_endy, 0x1f);
        if (err)
                return -EIO;
 
@@ -1636,16 +1699,21 @@ static int sn9c102_v4l2_ioctl(struct ino
                if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
                        return -EFAULT;
 
-               if ((err = s->set_ctrl(cam, &ctrl)))
-                       return err;
-
                n = sizeof(s->qctrl) / sizeof(s->qctrl[0]);
                for (i = 0; i < n; i++)
                        if (ctrl.id == s->qctrl[i].id) {
-                               s->_qctrl[i].default_value = ctrl.value;
+                               if (ctrl.value < s->qctrl[i].minimum ||
+                                   ctrl.value > s->qctrl[i].maximum)
+                                       return -ERANGE;
+                               ctrl.value -= ctrl.value % s->qctrl[i].step;
                                break;
                        }
 
+               if ((err = s->set_ctrl(cam, &ctrl)))
+                       return err;
+
+               s->_qctrl[i].default_value = ctrl.value;
+
                return 0;
        }
 
@@ -1776,7 +1844,7 @@ static int sn9c102_v4l2_ioctl(struct ino
                        DBG(1, "VIDIOC_S_CROP failed because of hardware "
                               "problems. To use the camera, close and open "
                               "/dev/video%d again.", cam->v4ldev->minor)
-                       return err;
+                       return -EIO;
                }
 
                s->pix_format.width = rect->width/scale;
@@ -1951,7 +2019,7 @@ static int sn9c102_v4l2_ioctl(struct ino
                        DBG(1, "VIDIOC_S_FMT failed because of hardware "
                               "problems. To use the camera, close and open "
                               "/dev/video%d again.", cam->v4ldev->minor)
-                       return err;
+                       return -EIO;
                }
 
                memcpy(pfmt, pix, sizeof(*pix));
@@ -2286,15 +2354,17 @@ sn9c102_usb_probe(struct usb_interface* 
 
        r = sn9c102_read_reg(cam, 0x00);
        if (r < 0 || r != 0x10) {
-               DBG(1, "Sorry, this is not a SN9C10[12] based camera "
+               DBG(1, "Sorry, this is not a SN9C10x based camera "
                       "(vid/pid 0x%04X/0x%04X)",
                    sn9c102_id_table[i].idVendor,sn9c102_id_table[i].idProduct)
                err = -ENODEV;
                goto fail;
        }
 
-       DBG(2, "SN9C10[12] PC Camera Controller detected "
-              "(vid/pid 0x%04X/0x%04X)",
+       cam->bridge = (sn9c102_id_table[i].idProduct & 0xffc0) == 0x6080 ?
+                     BRIDGE_SN9C102 : BRIDGE_SN9C103;
+
+       DBG(2, "SN9C10x PC Camera Controller detected (vid/pid 0x%04X/0x%04X)",
            sn9c102_id_table[i].idVendor, sn9c102_id_table[i].idProduct)
 
        for  (i = 0; sn9c102_sensor_table[i]; i++) {
@@ -2318,7 +2388,7 @@ sn9c102_usb_probe(struct usb_interface* 
                cam->state |= DEV_MISCONFIGURED;
        }
 
-       strcpy(cam->v4ldev->name, "SN9C10[12] PC Camera");
+       strcpy(cam->v4ldev->name, "SN9C10x PC Camera");
        cam->v4ldev->owner = THIS_MODULE;
        cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
        cam->v4ldev->hardware = VID_HARDWARE_SN9C102;
diff -uprN -X dontdiff linux-2.6.8/drivers/usb/media/sn9c102.h 
devel-2.6.8/drivers/usb/media/sn9c102.h
--- linux-2.6.8/drivers/usb/media/sn9c102.h     2004-08-27 17:51:02.000000000 +0200
+++ devel-2.6.8/drivers/usb/media/sn9c102.h     2004-08-27 17:38:30.000000000 +0200
@@ -1,5 +1,5 @@
 /***************************************************************************
- * V4L2 driver for SN9C10[12] PC Camera Controllers                        *
+ * V4L2 driver for SN9C10x PC Camera Controllers                           *
  *                                                                         *
  * Copyright (C) 2004 by Luca Risolia <[EMAIL PROTECTED]>       *
  *                                                                         *
@@ -49,12 +49,18 @@
 
 /*****************************************************************************/
 
-#define SN9C102_MODULE_NAME  "V4L2 driver for SN9C10[12] PC Camera Controllers"
+#define SN9C102_MODULE_NAME     "V4L2 driver for SN9C10x PC Camera Controllers"
 #define SN9C102_MODULE_AUTHOR   "(C) 2004 Luca Risolia"
 #define SN9C102_AUTHOR_EMAIL    "<[EMAIL PROTECTED]>"
 #define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.08"
-#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 8)
+#define SN9C102_MODULE_VERSION  "1:1.10"
+#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 10)
+
+enum sn9c102_bridge {
+       BRIDGE_SN9C101 = 0x01,
+       BRIDGE_SN9C102 = 0x02,
+       BRIDGE_SN9C103 = 0x04,
+};
 
 SN9C102_ID_TABLE;
 SN9C102_SENSOR_TABLE;
@@ -105,6 +111,7 @@ struct sn9c102_device {
 
        struct video_device* v4ldev;
 
+       enum sn9c102_bridge bridge;
        struct sn9c102_sensor* sensor;
 
        struct usb_device* usbdev;
diff -uprN -X dontdiff linux-2.6.8/drivers/usb/media/sn9c102_pas106b.c 
devel-2.6.8/drivers/usb/media/sn9c102_pas106b.c
--- linux-2.6.8/drivers/usb/media/sn9c102_pas106b.c     2004-08-27 17:51:02.000000000 
+0200
+++ devel-2.6.8/drivers/usb/media/sn9c102_pas106b.c     2004-08-27 17:38:47.000000000 
+0200
@@ -1,5 +1,5 @@
 /***************************************************************************
- * Driver for PAS106B image sensor connected to the SN9C10[12] PC Camera   *
+ * Driver for PAS106B image sensor connected to the SN9C10x PC Camera      *
  * Controllers                                                             *
  *                                                                         *
  * Copyright (C) 2004 by Luca Risolia <[EMAIL PROTECTED]>       *
@@ -100,26 +100,26 @@ static int pas106b_set_ctrl(struct sn9c1
 
        switch (ctrl->id) {
        case V4L2_CID_RED_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x0c, ctrl->value & 0x1f);
+               err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
                break;
        case V4L2_CID_BLUE_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x09, ctrl->value & 0x1f);
+               err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
                break;
        case V4L2_CID_GAIN:
-               err += sn9c102_i2c_write(cam, 0x0e, ctrl->value & 0x1f);
+               err += sn9c102_i2c_write(cam, 0x0e, ctrl->value);
                break;
        case V4L2_CID_BRIGHTNESS:
-               err += sn9c102_i2c_write(cam, 0x0d, 0x1f-(ctrl->value & 0x1f));
+               err += sn9c102_i2c_write(cam, 0x0d, 0x1f - ctrl->value);
                break;
        case V4L2_CID_CONTRAST:
-               err += sn9c102_i2c_write(cam, 0x0f, ctrl->value & 0x03);
+               err += sn9c102_i2c_write(cam, 0x0f, ctrl->value);
                break;
        default:
                return -EINVAL;
        }
        err += sn9c102_i2c_write(cam, 0x13, 0x01);
 
-       return err;
+       return err ? -EIO : 0;
 }
 
 
diff -uprN -X dontdiff linux-2.6.8/drivers/usb/media/sn9c102_pas202bcb.c 
devel-2.6.8/drivers/usb/media/sn9c102_pas202bcb.c
--- linux-2.6.8/drivers/usb/media/sn9c102_pas202bcb.c   2004-08-27 17:51:02.000000000 
+0200
+++ devel-2.6.8/drivers/usb/media/sn9c102_pas202bcb.c   2004-08-27 17:38:47.000000000 
+0200
@@ -1,5 +1,5 @@
 /***************************************************************************
- * Driver for PAS202BCB image sensor connected to the SN9C10[12] PC Camera *
+ * Driver for PAS202BCB image sensor connected to the SN9C10x PC Camera    *
  * Controllers                                                             *
  *                                                                         *
  * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio                  *
@@ -95,23 +95,23 @@ static int pas202bcb_set_ctrl(struct sn9
 
        switch (ctrl->id) {
        case V4L2_CID_RED_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x09, ctrl->value & 0x0f);
+               err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
                break;
        case V4L2_CID_BLUE_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x07, ctrl->value & 0x0f);
+               err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
                break;
        case V4L2_CID_GAIN:
-               err += sn9c102_i2c_write(cam, 0x10, ctrl->value & 0x1f);
+               err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
                break;
        case V4L2_CID_BRIGHTNESS:
-               err += sn9c102_i2c_write(cam, 0x06, 0x0f-(ctrl->value & 0x0f));
+               err += sn9c102_i2c_write(cam, 0x06, 0x0f - ctrl->value);
                break;
        default:
                return -EINVAL;
        }
        err += sn9c102_i2c_write(cam, 0x11, 0x01);
 
-       return err;
+       return err ? -EIO : 0;
 }
 
 
diff -uprN -X dontdiff linux-2.6.8/drivers/usb/media/sn9c102_sensor.h 
devel-2.6.8/drivers/usb/media/sn9c102_sensor.h
--- linux-2.6.8/drivers/usb/media/sn9c102_sensor.h      2004-08-27 17:48:03.000000000 
+0200
+++ devel-2.6.8/drivers/usb/media/sn9c102_sensor.h      2004-08-27 17:38:59.000000000 
+0200
@@ -1,5 +1,5 @@
 /***************************************************************************
- * API for image sensors connected to the SN9C10[12] PC Camera Controllers *
+ * API for image sensors connected to the SN9C10x PC Camera Controllers    *
  *                                                                         *
  * Copyright (C) 2004 by Luca Risolia <[EMAIL PROTECTED]>       *
  *                                                                         *
@@ -89,17 +89,44 @@ sn9c102_attach_sensor(struct sn9c102_dev
 /* Each SN9C10X camera has proper PID/VID identifiers. Add them here in case.*/
 #define SN9C102_ID_TABLE                                                      \
 static const struct usb_device_id sn9c102_id_table[] = {                      \
-       { USB_DEVICE(0xc45, 0x6001), }, /* TAS5110C1B */                      \
-       { USB_DEVICE(0xc45, 0x6005), }, /* TAS5110C1B */                      \
-       { USB_DEVICE(0xc45, 0x6009), }, /* PAS106B */                         \
-       { USB_DEVICE(0xc45, 0x600d), }, /* PAS106B */                         \
-       { USB_DEVICE(0xc45, 0x6024), },                                       \
-       { USB_DEVICE(0xc45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */       \
-       { USB_DEVICE(0xc45, 0x6028), }, /* PAS202BCB */                       \
-       { USB_DEVICE(0xc45, 0x6029), }, /* PAS106B */                         \
-       { USB_DEVICE(0xc45, 0x602a), }, /* HV7131[D|E1] */                    \
-       { USB_DEVICE(0xc45, 0x602c), }, /* OV7620 */                          \
-       { USB_DEVICE(0xc45, 0x6030), }, /* MI03 */                            \
+       { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */                     \
+       { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */                     \
+       { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */                        \
+       { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */                        \
+       { USB_DEVICE(0x0c45, 0x6024), },                                      \
+       { USB_DEVICE(0x0c45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */      \
+       { USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */                      \
+       { USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */                        \
+       { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131[D|E1] */                   \
+       { USB_DEVICE(0x0c45, 0x602b), },                                      \
+       { USB_DEVICE(0x0c45, 0x602c), }, /* OV7620 */                         \
+       { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */                          \
+       { USB_DEVICE(0x0c45, 0x6080), },                                      \
+       { USB_DEVICE(0x0c45, 0x6082), }, /* MI0343 and MI0360 */              \
+       { USB_DEVICE(0x0c45, 0x6083), }, /* HV7131[D|E1] */                   \
+       { USB_DEVICE(0x0c45, 0x6088), },                                      \
+       { USB_DEVICE(0x0c45, 0x608a), },                                      \
+       { USB_DEVICE(0x0c45, 0x608b), },                                      \
+       { USB_DEVICE(0x0c45, 0x608c), }, /* HV7131x */                        \
+       { USB_DEVICE(0x0c45, 0x608e), }, /* CIS-VF10 */                       \
+       { USB_DEVICE(0x0c45, 0x608f), }, /* OV7630 */                         \
+       { USB_DEVICE(0x0c45, 0x60a0), },                                      \
+       { USB_DEVICE(0x0c45, 0x60a2), },                                      \
+       { USB_DEVICE(0x0c45, 0x60a3), },                                      \
+       { USB_DEVICE(0x0c45, 0x60a8), }, /* PAS106B */                        \
+       { USB_DEVICE(0x0c45, 0x60aa), }, /* TAS5130D1B */                     \
+       { USB_DEVICE(0x0c45, 0x60ab), }, /* TAS5110C1B */                     \
+       { USB_DEVICE(0x0c45, 0x60ac), },                                      \
+       { USB_DEVICE(0x0c45, 0x60ae), },                                      \
+       { USB_DEVICE(0x0c45, 0x60af), }, /* PAS202BCB */                      \
+       { USB_DEVICE(0x0c45, 0x60b0), },                                      \
+       { USB_DEVICE(0x0c45, 0x60b2), },                                      \
+       { USB_DEVICE(0x0c45, 0x60b3), },                                      \
+       { USB_DEVICE(0x0c45, 0x60b8), },                                      \
+       { USB_DEVICE(0x0c45, 0x60ba), },                                      \
+       { USB_DEVICE(0x0c45, 0x60bb), },                                      \
+       { USB_DEVICE(0x0c45, 0x60bc), },                                      \
+       { USB_DEVICE(0x0c45, 0x60be), },                                      \
        { }                                                                   \
 };
 
@@ -173,9 +200,7 @@ struct sn9c102_sensor {
 
        /*
           These identifiers must be provided if the image sensor implements
-          the standard I2C protocol. TASC sensors don't, although they have a
-          serial interface: so this is a case where the "raw" I2C version
-          could be helpful.
+          the standard I2C protocol.
        */
        u8 slave_read_id, slave_write_id; /* reg. 0x09 */
 
@@ -214,7 +239,8 @@ struct sn9c102_sensor {
           the list above. The returned value must follow the V4L2
           specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER
           are not supported by this driver, so do not implement them. Also,
-          passed values are NOT checked to see if they are out of bounds.
+          you don't have to check whether the passed values are out of bounds,
+          given that this is done by the core module.
        */
 
        struct v4l2_cropcap cropcap;
diff -uprN -X dontdiff linux-2.6.8/drivers/usb/media/sn9c102_tas5110c1b.c 
devel-2.6.8/drivers/usb/media/sn9c102_tas5110c1b.c
--- linux-2.6.8/drivers/usb/media/sn9c102_tas5110c1b.c  2004-08-27 17:51:02.000000000 
+0200
+++ devel-2.6.8/drivers/usb/media/sn9c102_tas5110c1b.c  2004-08-27 17:39:40.000000000 
+0200
@@ -1,6 +1,6 @@
 /***************************************************************************
- * Driver for TAS5110C1B image sensor connected to the SN9C10[12] PC       *
- * Camera Controllers                                                      *
+ * Driver for TAS5110C1B image sensor connected to the SN9C10x PC Camera   *
+ * Controllers                                                             *
  *                                                                         *
  * Copyright (C) 2004 by Luca Risolia <[EMAIL PROTECTED]>       *
  *                                                                         *
@@ -24,6 +24,8 @@
 
 static struct sn9c102_sensor tas5110c1b;
 
+static struct v4l2_control tas5110c1b_gain;
+
 
 static int tas5110c1b_init(struct sn9c102_device* cam)
 {
@@ -38,25 +40,42 @@ static int tas5110c1b_init(struct sn9c10
        err += sn9c102_write_reg(cam, 0x06, 0x18);
        err += sn9c102_write_reg(cam, 0xfb, 0x19);
 
-       err += sn9c102_i2c_try_raw_write(cam, &tas5110c1b, 4, 0x11, 0x00, 0xc0,
-                                        0x80, 0, 0);
+       err += sn9c102_i2c_write(cam, 0xc0, 0x80);
 
        return err;
 }
 
 
+static int tas5110c1b_get_ctrl(struct sn9c102_device* cam, 
+                               struct v4l2_control* ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               ctrl->value = tas5110c1b_gain.value;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
 static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, 
                                const struct v4l2_control* ctrl)
 {
+       int err = 0;
+
        switch (ctrl->id) {
        case V4L2_CID_GAIN:
-               return sn9c102_i2c_try_raw_write(cam, &tas5110c1b, 4, 0x11,
-                                                0x02, 0x20,
-                                                0xff - (ctrl->value & 0xff),
-                                                0, 0);
+               if (!(err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value)))
+                       tas5110c1b_gain.value = ctrl->value;
+               break;
        default:
                return -EINVAL;
        }
+
+       return err ? -EIO : 0;
 }
 
 
@@ -85,6 +104,8 @@ static struct sn9c102_sensor tas5110c1b 
        .maintainer = "Luca Risolia <[EMAIL PROTECTED]>",
        .frequency = SN9C102_I2C_100KHZ,
        .interface = SN9C102_I2C_3WIRES,
+       .slave_read_id = 0xff, /* fictitious */
+       .slave_write_id = 0xff, /* fictitious */
        .init = &tas5110c1b_init,
        .qctrl = {
                {
@@ -92,9 +113,9 @@ static struct sn9c102_sensor tas5110c1b 
                        .type = V4L2_CTRL_TYPE_INTEGER,
                        .name = "global gain",
                        .minimum = 0x00,
-                       .maximum = 0xff,
+                       .maximum = 0xf6,
                        .step = 0x01,
-                       .default_value = 0x48,
+                       .default_value = 0x40,
                        .flags = 0,
                },
        },
@@ -113,6 +134,7 @@ static struct sn9c102_sensor tas5110c1b 
                        .height = 288,
                },
        },
+       .get_ctrl = &tas5110c1b_get_ctrl,
        .set_crop = &tas5110c1b_set_crop,
        .pix_format = {
                .width = 352,
@@ -130,7 +152,8 @@ int sn9c102_probe_tas5110c1b(struct sn9c
 
        /* At the moment, sensor detection is based on USB pid/vid */
        if (tas5110c1b.usbdev->descriptor.idProduct != 0x6001 &&
-           tas5110c1b.usbdev->descriptor.idProduct != 0x6005)
+           tas5110c1b.usbdev->descriptor.idProduct != 0x6005 &&
+           tas5110c1b.usbdev->descriptor.idProduct != 0x60ab)
                return -ENODEV;
 
        return 0;
diff -uprN -X dontdiff linux-2.6.8/drivers/usb/media/sn9c102_tas5130d1b.c 
devel-2.6.8/drivers/usb/media/sn9c102_tas5130d1b.c
--- linux-2.6.8/drivers/usb/media/sn9c102_tas5130d1b.c  2004-08-27 17:51:02.000000000 
+0200
+++ devel-2.6.8/drivers/usb/media/sn9c102_tas5130d1b.c  2004-08-27 17:39:40.000000000 
+0200
@@ -1,6 +1,6 @@
 /***************************************************************************
- * Driver for TAS5130D1B image sensor connected to the SN9C10[12] PC       *
- * Camera Controllers                                                      *
+ * Driver for TAS5130D1B image sensor connected to the SN9C10x PC Camera   *
+ * Controllers                                                             *
  *                                                                         *
  * Copyright (C) 2004 by Luca Risolia <[EMAIL PROTECTED]>       *
  *                                                                         *
@@ -24,6 +24,8 @@
 
 static struct sn9c102_sensor tas5130d1b;
 
+static struct v4l2_control tas5130d1b_gain, tas5130d1b_exposure;
+
 
 static int tas5130d1b_init(struct sn9c102_device* cam)
 {
@@ -38,25 +40,47 @@ static int tas5130d1b_init(struct sn9c10
        err += sn9c102_write_reg(cam, 0x60, 0x17);
        err += sn9c102_write_reg(cam, 0x07, 0x18);
 
-       err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0x40,
-                                        0x47, 0, 0);
-
        return err;
 }
 
 
+static int tas5130d1b_get_ctrl(struct sn9c102_device* cam, 
+                               struct v4l2_control* ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               ctrl->value = tas5130d1b_gain.value;
+               break;
+       case V4L2_CID_EXPOSURE:
+               ctrl->value = tas5130d1b_exposure.value;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
 static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, 
                                const struct v4l2_control* ctrl)
 {
+       int err = 0;
+
        switch (ctrl->id) {
        case V4L2_CID_GAIN:
-               return sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11,
-                                                0x02, 0x20,
-                                                0xff - (ctrl->value & 0xff),
-                                                0, 0);
+               if (!(err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value)))
+                       tas5130d1b_gain.value = ctrl->value;
+               break;
+       case V4L2_CID_EXPOSURE:
+               if (!(err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value)))
+                       tas5130d1b_exposure.value = ctrl->value;
+               break;
        default:
                return -EINVAL;
        }
+
+       return err ? -EIO : 0;
 }
 
 
@@ -85,6 +109,8 @@ static struct sn9c102_sensor tas5130d1b 
        .maintainer = "Luca Risolia <[EMAIL PROTECTED]>",
        .frequency = SN9C102_I2C_100KHZ,
        .interface = SN9C102_I2C_3WIRES,
+       .slave_read_id = 0xff, /* fictitious */
+       .slave_write_id = 0xff, /* fictitious */
        .init = &tas5130d1b_init,
        .qctrl = {
                {
@@ -92,12 +118,23 @@ static struct sn9c102_sensor tas5130d1b 
                        .type = V4L2_CTRL_TYPE_INTEGER,
                        .name = "global gain",
                        .minimum = 0x00,
-                       .maximum = 0xff,
+                       .maximum = 0xf6,
+                       .step = 0x02,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "exposure",
+                       .minimum = 0x00,
+                       .maximum = 0x47,
                        .step = 0x01,
                        .default_value = 0x00,
                        .flags = 0,
                },
        },
+       .get_ctrl = &tas5130d1b_get_ctrl,
        .set_ctrl = &tas5130d1b_set_ctrl,
        .cropcap = {
                .bounds = {
@@ -129,7 +166,8 @@ int sn9c102_probe_tas5130d1b(struct sn9c
        sn9c102_attach_sensor(cam, &tas5130d1b);
 
        /* At the moment, sensor detection is based on USB pid/vid */
-       if (tas5130d1b.usbdev->descriptor.idProduct != 0x6025)
+       if (tas5130d1b.usbdev->descriptor.idProduct != 0x6025 &&
+           tas5130d1b.usbdev->descriptor.idProduct != 0x60aa)
                return -ENODEV;
 
        return 0;
diff -uprN -X dontdiff linux-2.6.8/MAINTAINERS devel-2.6.8/MAINTAINERS
--- linux-2.6.8/MAINTAINERS     2004-08-27 17:52:16.000000000 +0200
+++ devel-2.6.8/MAINTAINERS     2004-08-27 17:41:49.000000000 +0200
@@ -2365,7 +2365,7 @@ L:        [EMAIL PROTECTED]
 W:     http://www.connecttech.com
 S:     Supported
 
-USB SN9C10[12] DRIVER
+USB SN9C10x DRIVER
 P:     Luca Risolia
 M:     [EMAIL PROTECTED]
 L:     [EMAIL PROTECTED]

Attachment: pgppbRxHaSDPs.pgp
Description: PGP signature

Reply via email to