diff -urN a/Makefile b/Makefile --- a/Makefile 2004-07-18 10:27:18.000000000 -0300 +++ b/Makefile 2004-07-21 21:58:12.000000000 -0300 @@ -23,7 +23,7 @@ ifneq ($(KERNELRELEASE),) obj-m += sn9c102.o -sn9c102-objs := sn9c102_core.o sn9c102_pas106b.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o +sn9c102-objs := sn9c102_core.o sn9c102_pas106b.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o sn9c102_pas202b.o else diff -urN a/sn9c102.txt b/sn9c102.txt --- a/sn9c102.txt 2004-07-13 06:12:18.000000000 -0300 +++ b/sn9c102.txt 2004-07-24 21:25:27.000000000 -0300 @@ -249,6 +249,7 @@ Model Manufacturer ----- ------------ PAS106B PixArt Imaging Inc. +PAS202B PixArt Imaging Inc. TAS5110C1B Taiwan Advanced Sensor Corporation TAS5130D1B Taiwan Advanced Sensor Corporation @@ -271,7 +272,7 @@ (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: PAS202B (VGA), +At the moment, not yet supported image sensors are: HV7131[D|E1] (VGA), MI03 (VGA), OV7620 (VGA). diff -urN a/sn9c102_pas202b.c b/sn9c102_pas202b.c --- a/sn9c102_pas202b.c 1969-12-31 21:00:00.000000000 -0300 +++ b/sn9c102_pas202b.c 2004-07-24 21:23:37.000000000 -0300 @@ -0,0 +1,261 @@ +/*************************************************************************** + * Driver for PAS202B image sensor connected to the SN9C10[12] PC Camera * + * Controllers * + * * + * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio * + * * + * http://cadu.homelinux.com:8080/ * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * + ***************************************************************************/ + +#include +#include "sn9c102_sensor.h" + +static struct sn9c102_sensor pas202b; + +static int pas202b_init(struct sn9c102_device* cam) +{ + int err = 0; + int i = 0; + + struct cmos_regs { + int enabled; + u8 val; + }; + + + static struct cmos_regs pas202b_regs[22] = { + {0, 0x00}, /* 0x00 - Part ID */ + {0, 0x00}, /* 0x01 - Part ID / Version ID */ + {1, 0x02}, /* 0x02 - Np[5:0] */ + {1, 0x40}, /* 0x03 - Nov_by2[7:0] */ + {1, 0x12}, /* 0x04 - lpf[13:6] - Line per frame */ + {1, 0x04}, /* 0x05 - lpf[5:0] - Line per frame */ + {0, 0x04}, /* 0x06 - cgn_dk[3:0] - color gaim for dark pixel */ + {0, 0x00}, /* 0x07 - cgn_B[3:0] - color gaim for Blue pixel */ + {0, 0x00}, /* 0x08 - cgn_G[3:0] - color gaim for Green pixel */ + {0, 0x00}, /* 0x09 - cgn_R[3:0] - color gaim for Red pixel */ + {0, 0x00}, /* 0x0a - Reserved */ + {1, 0x01}, /* 0x0b - dac[8] - sign bit for DAC */ + {1, 0x2f}, /* 0x0c - dac[0:7] - Magnitude for DAC */ + {1, 0x7e}, /* 0x0d - offset_ne_by4[0:7] - Exposure time pixel offset */ + {1, 0x01}, /* 0x0e - offset_ny[0] - Exposure time: line offset */ + {1, 0xdc}, /* 0x0f - offset_ny[8:1] - Exposure time: line offset */ + {0, 0x00}, /* 0x10 - global[0:4] - PGA global gaim */ + {0, 0x00}, /* 0x11 - i2c_update_sync_flag[0] */ + {0, 0x00}, /* 0x12 - Reserved */ + {1, 0x63}, /* 0x13 - Reserved */ + {0, 0x00}, /* 0x14 - Reserved */ + {1, 0x70} /* 0x15 - Reserved */ + }; + + err += sn9c102_write_reg(cam, 0x00, 0x10); + err += sn9c102_write_reg(cam, 0x00, 0x11); + err += sn9c102_write_reg(cam, 0x00, 0x14); + err += sn9c102_write_reg(cam, 0x20, 0x17); + err += sn9c102_write_reg(cam, 0x51, 0x19); + err += sn9c102_write_reg(cam, 0x49, 0x18); + + for(i=0;i<=21;i++) { + if (pas202b_regs[i].enabled == 1) + err += sn9c102_i2c_write(cam, i, pas202b_regs[i].val); + } + + msleep(400); + + return err; +} + +static int pas202b_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_RED_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case V4L2_CID_BLUE_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case V4L2_CID_GAIN: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case V4L2_CID_BRIGHTNESS: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + case V4L2_CID_CONTRAST: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x06)) < 0) + return -EIO; + ctrl->value &= 0x0f; + return 0; + default: + return -EINVAL; + } +} + +static int pas202b_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_RED_BALANCE: + err += sn9c102_i2c_write(cam, 0x09, ctrl->value & 0x0f); + break; + case V4L2_CID_BLUE_BALANCE: + err += sn9c102_i2c_write(cam, 0x07, ctrl->value & 0x0f); + break; + case V4L2_CID_GAIN: + err += sn9c102_i2c_write(cam, 0x08, ctrl->value & 0x0f); + break; + case V4L2_CID_BRIGHTNESS: + err += sn9c102_i2c_write(cam, 0x10, ctrl->value & 0x0f); + break; + case V4L2_CID_CONTRAST: + err += sn9c102_i2c_write(cam, 0x06, ctrl->value & 0x0f); + break; + default: + return -EINVAL; + } + + return err; +} + +static int pas202b_set_crop(struct sn9c102_device* cam, + const struct v4l2_rect* rect) +{ + struct sn9c102_sensor* s = &pas202b; + int err = 0; + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0, + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 0; + + err += sn9c102_write_reg(cam, h_start, 0x12); + err += sn9c102_write_reg(cam, v_start, 0x13); + + return err; +} + +static struct sn9c102_sensor pas202b = { + .name = "PAS202B", + .maintainer = "Carlos Eduardo Medaglia Dyonisio ", + .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_2WIRES, + .slave_read_id = 0x40, + .slave_write_id = 0x40, + .init = &pas202b_init, + .qctrl = { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x04, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x06, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x01, + .flags = 0, + }, + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "darkness", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "contrast", + .minimum = 0x00, + .maximum = 0x0f, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + }, + .get_ctrl = &pas202b_get_ctrl, + .set_ctrl = &pas202b_set_ctrl, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 644, /* It _might_ be multiple of 16... */ + .height = 486, /* Ok... Just testing... :) */ + }, + .defrect = { + .left = 4, + .top = 1, + .width = 640, + .height = 480, + }, + }, + .set_crop = &pas202b_set_crop, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_SBGGR8, + .priv = 8, /* we use this field as 'bits per pixel' */ + } +}; + + +int sn9c102_probe_pas202b(struct sn9c102_device* cam) +{ + int err = 0; + + err += sn9c102_write_reg(cam, 0x40, 0x09); /* Slave ID (1000000) */ + err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */ + err += sn9c102_write_reg(cam, 0x40, 0x01); /* sensor power on */ + err += sn9c102_write_reg(cam, 0x2c, 0x17); /* sensor clock at 48 MHz */ + if (err) + return -EIO; + + sn9c102_attach_sensor(cam, &pas202b); + + if (pas202b.usbdev->descriptor.idProduct != 0x6028) + return -ENODEV; + + return 0; +} diff -urN a/sn9c102_sensor.h b/sn9c102_sensor.h --- a/sn9c102_sensor.h 2004-07-18 10:22:50.000000000 -0300 +++ b/sn9c102_sensor.h 2004-07-24 21:31:46.000000000 -0300 @@ -65,6 +65,7 @@ extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); +extern int sn9c102_probe_pas202b(struct sn9c102_device* cam); /* Add the above entries to this table. Be sure to add the entry in the right @@ -76,6 +77,7 @@ &sn9c102_probe_pas106b, /* strong detection based on SENSOR vid/pid */\ &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \ &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \ + &sn9c102_probe_pas202b, /* detection based on USB pid/vid yet... */ \ NULL, \ }; @@ -93,7 +95,7 @@ { USB_DEVICE(0xc45, 0x600d), }, /* PAS106B */ \ { USB_DEVICE(0xc45, 0x6024), }, \ { USB_DEVICE(0xc45, 0x6025), }, /* TAS5130D1B Maybe also TAS5110C1B */\ - { USB_DEVICE(0xc45, 0x6028), }, /* Maybe PAS202B */ \ + { USB_DEVICE(0xc45, 0x6028), }, /* PAS202B */ \ { USB_DEVICE(0xc45, 0x6029), }, \ { USB_DEVICE(0xc45, 0x602a), }, /* Maybe HV7131[D|E1] */ \ { USB_DEVICE(0xc45, 0x602c), }, /* Maybe OV7620 */ \