2008-06-30 22:50:11 +04:00
/*
* Sonix sn9c102p sn9c105 sn9c120 ( jpeg ) library
* Copyright ( C ) 2005 Michel Xhaard mxhaard @ magic . fr
*
* V4L2 by Jean - Francois Moine < http : //moinejf.free.fr>
*
* 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
* 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 . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# define MODULE_NAME "sonixj"
# include "gspca.h"
# include "jpeg.h"
2008-07-14 16:38:29 +04:00
# define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
static const char version [ ] = " 2.1.7 " ;
2008-06-30 22:50:11 +04:00
MODULE_AUTHOR ( " Michel Xhaard <mxhaard@users.sourceforge.net> " ) ;
MODULE_DESCRIPTION ( " GSPCA/SONIX JPEG USB Camera Driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev ; /* !! must be the first item */
int avg_lum ;
unsigned int exposure ;
unsigned short brightness ;
unsigned char contrast ;
unsigned char colors ;
unsigned char autogain ;
signed char ag_cnt ;
# define AG_CNT_START 13
char qindex ;
2008-07-15 12:36:30 +04:00
unsigned char bridge ;
# define BRIDGE_SN9C102P 0
# define BRIDGE_SN9C105 1
# define BRIDGE_SN9C110 2
# define BRIDGE_SN9C120 3
# define BRIDGE_SN9C325 4
2008-06-30 22:50:11 +04:00
char sensor ; /* Type of image sensor chip */
# define SENSOR_HV7131R 0
# define SENSOR_MI0360 1
# define SENSOR_MO4000 2
# define SENSOR_OV7648 3
# define SENSOR_OV7660 4
unsigned char i2c_base ;
} ;
/* V4L2 controls supported by the driver */
static int sd_setbrightness ( struct gspca_dev * gspca_dev , __s32 val ) ;
static int sd_getbrightness ( struct gspca_dev * gspca_dev , __s32 * val ) ;
static int sd_setcontrast ( struct gspca_dev * gspca_dev , __s32 val ) ;
static int sd_getcontrast ( struct gspca_dev * gspca_dev , __s32 * val ) ;
static int sd_setcolors ( struct gspca_dev * gspca_dev , __s32 val ) ;
static int sd_getcolors ( struct gspca_dev * gspca_dev , __s32 * val ) ;
static int sd_setautogain ( struct gspca_dev * gspca_dev , __s32 val ) ;
static int sd_getautogain ( struct gspca_dev * gspca_dev , __s32 * val ) ;
static struct ctrl sd_ctrls [ ] = {
{
{
. id = V4L2_CID_BRIGHTNESS ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. name = " Brightness " ,
. minimum = 0 ,
. maximum = 0xffff ,
. step = 1 ,
2008-07-04 18:16:16 +04:00
# define BRIGHTNESS_DEF 0x7fff
. default_value = BRIGHTNESS_DEF ,
2008-06-30 22:50:11 +04:00
} ,
. set = sd_setbrightness ,
. get = sd_getbrightness ,
} ,
{
{
. id = V4L2_CID_CONTRAST ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. name = " Contrast " ,
. minimum = 0 ,
. maximum = 127 ,
. step = 1 ,
2008-07-04 18:16:16 +04:00
# define CONTRAST_DEF 63
. default_value = CONTRAST_DEF ,
2008-06-30 22:50:11 +04:00
} ,
. set = sd_setcontrast ,
. get = sd_getcontrast ,
} ,
{
{
. id = V4L2_CID_SATURATION ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. name = " Color " ,
. minimum = 0 ,
. maximum = 255 ,
. step = 1 ,
2008-07-04 18:16:16 +04:00
# define COLOR_DEF 127
. default_value = COLOR_DEF ,
2008-06-30 22:50:11 +04:00
} ,
. set = sd_setcolors ,
. get = sd_getcolors ,
} ,
{
{
. id = V4L2_CID_AUTOGAIN ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
. name = " Auto Gain " ,
. minimum = 0 ,
. maximum = 1 ,
. step = 1 ,
2008-07-04 18:16:16 +04:00
# define AUTOGAIN_DEF 1
. default_value = AUTOGAIN_DEF ,
2008-06-30 22:50:11 +04:00
} ,
. set = sd_setautogain ,
. get = sd_getautogain ,
} ,
} ;
2008-07-05 18:49:20 +04:00
static struct v4l2_pix_format vga_mode [ ] = {
{ 160 , 120 , V4L2_PIX_FMT_JPEG , V4L2_FIELD_NONE ,
. bytesperline = 160 ,
. sizeimage = 160 * 120 * 3 / 8 + 590 ,
. colorspace = V4L2_COLORSPACE_JPEG ,
. priv = 2 } ,
{ 320 , 240 , V4L2_PIX_FMT_JPEG , V4L2_FIELD_NONE ,
. bytesperline = 320 ,
. sizeimage = 320 * 240 * 3 / 8 + 590 ,
. colorspace = V4L2_COLORSPACE_JPEG ,
. priv = 1 } ,
{ 640 , 480 , V4L2_PIX_FMT_JPEG , V4L2_FIELD_NONE ,
. bytesperline = 640 ,
. sizeimage = 640 * 480 * 3 / 8 + 590 ,
. colorspace = V4L2_COLORSPACE_JPEG ,
. priv = 0 } ,
2008-06-30 22:50:11 +04:00
} ;
/*Data from sn9c102p+hv71331r */
2008-07-04 18:16:16 +04:00
static const __u8 sn_hv7131 [ ] = {
2008-06-30 22:50:11 +04:00
/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
2008-07-15 18:46:06 +04:00
0x00 , 0x03 , 0x64 , 0x00 , 0x1A , 0x20 , 0x20 , 0x20 , 0xA1 , 0x11 ,
2008-06-30 22:50:11 +04:00
/* rega regb regc regd rege regf reg10 reg11 */
2008-07-15 18:46:06 +04:00
0x02 , 0x09 , 0x00 , 0x00 , 0x00 , 0x10 , 0x03 , 0x00 , /* 00 */
2008-06-30 22:50:11 +04:00
/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
2008-07-15 18:46:06 +04:00
0x00 , 0x01 , 0x03 , 0x28 , 0x1e , 0x41 , 0x0a , 0x00 , 0x00 , 0x00 ,
2008-06-30 22:50:11 +04:00
/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
2008-07-15 18:46:06 +04:00
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
2008-06-30 22:50:11 +04:00
} ;
2008-07-04 18:16:16 +04:00
static const __u8 sn_mi0360 [ ] = {
2008-06-30 22:50:11 +04:00
/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
2008-07-15 18:46:06 +04:00
0x00 , 0x61 , 0x44 , 0x00 , 0x1a , 0x20 , 0x20 , 0x20 , 0xb1 , 0x5d ,
2008-06-30 22:50:11 +04:00
/* rega regb regc regd rege regf reg10 reg11 */
2008-07-15 18:46:06 +04:00
0x07 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 , 0x03 , 0x00 ,
2008-06-30 22:50:11 +04:00
/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
2008-07-15 18:46:06 +04:00
0x00 , 0x02 , 0x0a , 0x28 , 0x1e , 0x61 , 0x06 , 0x00 , 0x00 , 0x00 ,
2008-06-30 22:50:11 +04:00
/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
2008-07-15 18:46:06 +04:00
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
2008-06-30 22:50:11 +04:00
} ;
2008-07-04 18:16:16 +04:00
static const __u8 sn_mo4000 [ ] = {
2008-06-30 22:50:11 +04:00
/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
2008-07-15 18:46:06 +04:00
0x12 , 0x23 , 0x60 , 0x00 , 0x1A , 0x00 , 0x20 , 0x18 , 0x81 ,
2008-06-30 22:50:11 +04:00
/* reg9 rega regb regc regd rege regf reg10 reg11*/
2008-07-15 18:46:06 +04:00
0x21 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x03 , 0x00 ,
2008-06-30 22:50:11 +04:00
/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
2008-07-15 18:46:06 +04:00
0x0b , 0x0f , 0x14 , 0x28 , 0x1e , 0x40 , 0x08 , 0x00 , 0x00 ,
2008-06-30 22:50:11 +04:00
/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
2008-07-15 18:46:06 +04:00
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x08 , 0x25 , 0x39 , 0x4b ,
2008-06-30 22:50:11 +04:00
0x5c , 0x6b , 0x79 , 0x87 , 0x95 , 0xa2 , 0xaf , 0xbb , 0xc7 ,
0xd3 , 0xdf , 0xea , 0xf5
} ;
2008-07-04 18:16:16 +04:00
static const __u8 sn_ov7648 [ ] = {
2008-06-30 22:50:11 +04:00
0x00 , 0x21 , 0x62 , 0x00 , 0x1a , 0x20 , 0x20 , 0x20 , 0xA1 , 0x6E , 0x18 , 0x65 ,
0x00 , 0x00 , 0x00 , 0x10 , 0x03 , 0x00 , 0x00 , 0x06 , 0x06 , 0x28 , 0x1E , 0x82 ,
0x07 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
} ;
2008-07-04 18:16:16 +04:00
static const __u8 sn_ov7660 [ ] = {
2008-06-30 22:50:11 +04:00
/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
0x00 , 0x61 , 0x40 , 0x00 , 0x1a , 0x00 , 0x00 , 0x00 , 0x81 ,
/* reg9 rega regb regc regd rege regf reg10 reg11*/
0x21 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x03 , 0x00 ,
/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
2008-07-15 18:46:06 +04:00
0x01 , 0x01 , 0x14 , 0x28 , 0x1e , 0x00 , 0x07 , 0x00 , 0x00 ,
2008-06-30 22:50:11 +04:00
/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
} ;
/* sequence specific to the sensors - !! index = SENSOR_xxx */
2008-07-04 18:16:16 +04:00
static const __u8 * sn_tb [ ] = {
2008-06-30 22:50:11 +04:00
sn_hv7131 ,
sn_mi0360 ,
sn_mo4000 ,
sn_ov7648 ,
sn_ov7660
} ;
2008-07-04 18:16:16 +04:00
static const __u8 regsn20 [ ] = {
2008-06-30 22:50:11 +04:00
0x00 , 0x2d , 0x46 , 0x5a , 0x6c , 0x7c , 0x8b , 0x99 ,
0xa6 , 0xb2 , 0xbf , 0xca , 0xd5 , 0xe0 , 0xeb , 0xf5 , 0xff
} ;
2008-07-15 18:46:06 +04:00
static const __u8 regsn20_sn9c120 [ ] = {
0x00 , 0x25 , 0x3c , 0x50 , 0x62 , 0x72 , 0x81 , 0x90 ,
0x9e , 0xab , 0xb8 , 0xc5 , 0xd1 , 0xdd , 0xe9 , 0xf4 , 0xff
} ;
2008-07-04 18:16:16 +04:00
static const __u8 regsn20_sn9c325 [ ] = {
2008-06-30 22:50:11 +04:00
0x0a , 0x3a , 0x56 , 0x6c , 0x7e , 0x8d , 0x9a , 0xa4 ,
0xaf , 0xbb , 0xc5 , 0xcd , 0xd5 , 0xde , 0xe8 , 0xed , 0xf5
} ;
2008-07-04 18:16:16 +04:00
static const __u8 reg84 [ ] = {
2008-06-30 22:50:11 +04:00
0x14 , 0x00 , 0x27 , 0x00 , 0x07 , 0x00 , 0xe5 , 0x0f ,
0xe4 , 0x0f , 0x38 , 0x00 , 0x3e , 0x00 , 0xc3 , 0x0f ,
/* 0x00, 0x00, 0x00, 0x00, 0x00 */
0xf7 , 0x0f , 0x0a , 0x00 , 0x00
} ;
2008-07-15 18:46:06 +04:00
static const __u8 reg84_sn9c120_1 [ ] = {
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x0c , 0x00 , 0x00
} ;
static const __u8 reg84_sn9c120_2 [ ] = {
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x0c , 0x02 , 0x3b
} ;
static const __u8 reg84_sn9c120_3 [ ] = {
0x14 , 0x00 , 0x27 , 0x00 , 0x08 , 0x00 , 0xeb , 0x0f ,
0xd5 , 0x0f , 0x42 , 0x00 , 0x41 , 0x00 , 0xca , 0x0f ,
0xf5 , 0x0f , 0x0c , 0x02 , 0x3b
} ;
2008-07-04 18:16:16 +04:00
static const __u8 reg84_sn9c325 [ ] = {
2008-06-30 22:50:11 +04:00
0x14 , 0x00 , 0x27 , 0x00 , 0x07 , 0x00 , 0xe4 , 0x0f ,
0xd3 , 0x0f , 0x4b , 0x00 , 0x48 , 0x00 , 0xc0 , 0x0f ,
0xf8 , 0x0f , 0x00 , 0x00 , 0x00
} ;
2008-07-04 18:16:16 +04:00
static const __u8 hv7131r_sensor_init [ ] [ 8 ] = {
2008-06-30 22:50:11 +04:00
{ 0xC1 , 0x11 , 0x01 , 0x08 , 0x01 , 0x00 , 0x00 , 0x10 } ,
{ 0xB1 , 0x11 , 0x34 , 0x17 , 0x7F , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x11 , 0x40 , 0xFF , 0x7F , 0x7F , 0x7F , 0x10 } ,
{ 0x91 , 0x11 , 0x44 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x11 , 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x11 , 0x14 , 0x01 , 0xE2 , 0x02 , 0x82 , 0x10 } ,
{ 0x91 , 0x11 , 0x18 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x01 , 0x08 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x01 , 0x08 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xC1 , 0x11 , 0x25 , 0x00 , 0x61 , 0xA8 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x30 , 0x22 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xC1 , 0x11 , 0x31 , 0x20 , 0x2E , 0x20 , 0x00 , 0x10 } ,
{ 0xC1 , 0x11 , 0x25 , 0x00 , 0xC3 , 0x50 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x30 , 0x07 , 0x00 , 0x00 , 0x00 , 0x10 } , /* gain14 */
{ 0xC1 , 0x11 , 0x31 , 0x10 , 0x10 , 0x10 , 0x00 , 0x10 } , /* r g b 101a10 */
{ 0xA1 , 0x11 , 0x01 , 0x08 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x20 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x21 , 0xD0 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x22 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x23 , 0x09 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x01 , 0x08 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x20 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x21 , 0xD0 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x22 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x11 , 0x23 , 0x10 , 0x00 , 0x00 , 0x00 , 0x10 } ,
2008-07-04 18:16:16 +04:00
{ }
2008-06-30 22:50:11 +04:00
} ;
2008-07-04 18:16:16 +04:00
static const __u8 mi0360_sensor_init [ ] [ 8 ] = {
2008-06-30 22:50:11 +04:00
{ 0xB1 , 0x5D , 0x07 , 0x00 , 0x02 , 0x00 , 0x00 , 0x10 } ,
{ 0xB1 , 0x5D , 0x0D , 0x00 , 0x01 , 0x00 , 0x00 , 0x10 } ,
{ 0xB1 , 0x5D , 0x0D , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x01 , 0x00 , 0x08 , 0x00 , 0x16 , 0x10 } ,
{ 0xD1 , 0x5D , 0x03 , 0x01 , 0xE2 , 0x02 , 0x82 , 0x10 } ,
{ 0xD1 , 0x5D , 0x05 , 0x00 , 0x09 , 0x00 , 0x53 , 0x10 } ,
{ 0xB1 , 0x5D , 0x0D , 0x00 , 0x02 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x0A , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x0C , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x0E , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x12 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x14 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x16 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x18 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x1A , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x1C , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xB1 , 0x5D , 0x32 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x20 , 0x91 , 0x01 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x22 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x24 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x26 , 0x00 , 0x00 , 0x00 , 0x24 , 0x10 } ,
{ 0xD1 , 0x5D , 0x2F , 0xF7 , 0xB0 , 0x00 , 0x04 , 0x10 } ,
{ 0xD1 , 0x5D , 0x31 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x33 , 0x00 , 0x00 , 0x01 , 0x00 , 0x10 } ,
{ 0xB1 , 0x5D , 0x3D , 0x06 , 0x8F , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x40 , 0x01 , 0xE0 , 0x00 , 0xD1 , 0x10 } ,
{ 0xB1 , 0x5D , 0x44 , 0x00 , 0x82 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x58 , 0x00 , 0x78 , 0x00 , 0x43 , 0x10 } ,
{ 0xD1 , 0x5D , 0x5A , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x5C , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x5E , 0x00 , 0x00 , 0xA3 , 0x1D , 0x10 } ,
{ 0xB1 , 0x5D , 0x62 , 0x04 , 0x11 , 0x00 , 0x00 , 0x10 } ,
{ 0xB1 , 0x5D , 0x20 , 0x91 , 0x01 , 0x00 , 0x00 , 0x10 } ,
{ 0xB1 , 0x5D , 0x20 , 0x11 , 0x01 , 0x00 , 0x00 , 0x10 } ,
{ 0xB1 , 0x5D , 0x09 , 0x00 , 0x64 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x5D , 0x2B , 0x00 , 0xA0 , 0x00 , 0xB0 , 0x10 } ,
{ 0xD1 , 0x5D , 0x2D , 0x00 , 0xA0 , 0x00 , 0xA0 , 0x10 } ,
{ 0xB1 , 0x5D , 0x0A , 0x00 , 0x02 , 0x00 , 0x00 , 0x10 } , /* sensor clck ?2 */
{ 0xB1 , 0x5D , 0x06 , 0x00 , 0x30 , 0x00 , 0x00 , 0x10 } ,
{ 0xB1 , 0x5D , 0x05 , 0x00 , 0x0A , 0x00 , 0x00 , 0x10 } ,
{ 0xB1 , 0x5D , 0x09 , 0x02 , 0x35 , 0x00 , 0x00 , 0x10 } , /* exposure 2 */
{ 0xD1 , 0x5D , 0x2B , 0x00 , 0xB9 , 0x00 , 0xE3 , 0x10 } ,
{ 0xD1 , 0x5D , 0x2D , 0x00 , 0x5f , 0x00 , 0xB9 , 0x10 } , /* 42 */
/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
{ 0xB1 , 0x5D , 0x07 , 0x00 , 0x03 , 0x00 , 0x00 , 0x10 } , /* update */
{ 0xB1 , 0x5D , 0x07 , 0x00 , 0x02 , 0x00 , 0x00 , 0x10 } , /* sensor on */
2008-07-04 18:16:16 +04:00
{ }
2008-06-30 22:50:11 +04:00
} ;
2008-07-04 18:16:16 +04:00
static const __u8 mo4000_sensor_init [ ] [ 8 ] = {
2008-06-30 22:50:11 +04:00
{ 0xa1 , 0x21 , 0x01 , 0x02 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x05 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x05 , 0x04 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x06 , 0x80 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x06 , 0x81 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x0e , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x11 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x11 , 0x20 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x11 , 0x30 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x11 , 0x38 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x11 , 0x38 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x12 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x0f , 0x20 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x10 , 0x20 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x11 , 0x38 , 0x00 , 0x00 , 0x00 , 0x10 } ,
2008-07-04 18:16:16 +04:00
{ }
2008-06-30 22:50:11 +04:00
} ;
2008-07-04 18:16:16 +04:00
static const __u8 ov7660_sensor_init [ ] [ 8 ] = {
2008-06-30 22:50:11 +04:00
{ 0xa1 , 0x21 , 0x12 , 0x80 , 0x00 , 0x00 , 0x00 , 0x10 } , /* reset SCCB */
{ 0xa1 , 0x21 , 0x12 , 0x05 , 0x00 , 0x00 , 0x00 , 0x10 } ,
/* Outformat ?? rawRGB */
{ 0xa1 , 0x21 , 0x13 , 0xb8 , 0x00 , 0x00 , 0x00 , 0x10 } , /* init COM8 */
2008-07-15 18:46:06 +04:00
{ 0xd1 , 0x21 , 0x00 , 0x01 , 0x74 , 0x92 , 0x00 , 0x10 } ,
/* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, */
2008-06-30 22:50:11 +04:00
/* GAIN BLUE RED VREF */
{ 0xd1 , 0x21 , 0x04 , 0x00 , 0x7d , 0x62 , 0x00 , 0x10 } ,
/* COM 1 BAVE GEAVE AECHH */
{ 0xb1 , 0x21 , 0x08 , 0x83 , 0x01 , 0x00 , 0x00 , 0x10 } , /* RAVE COM2 */
{ 0xd1 , 0x21 , 0x0c , 0x00 , 0x08 , 0x04 , 0x4f , 0x10 } , /* COM 3 4 5 6 */
2008-07-15 18:46:06 +04:00
{ 0xd1 , 0x21 , 0x10 , 0x7f , 0x40 , 0x05 , 0xf8 , 0x10 } ,
/* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, */
2008-06-30 22:50:11 +04:00
/* AECH CLKRC COM7 COM8 */
{ 0xc1 , 0x21 , 0x14 , 0x2c , 0x00 , 0x02 , 0x00 , 0x10 } , /* COM9 COM10 */
{ 0xd1 , 0x21 , 0x17 , 0x10 , 0x60 , 0x02 , 0x7b , 0x10 } ,
/* HSTART HSTOP VSTRT VSTOP */
{ 0xa1 , 0x21 , 0x1b , 0x02 , 0x00 , 0x00 , 0x00 , 0x10 } , /* PSHFT */
{ 0xb1 , 0x21 , 0x1e , 0x01 , 0x0e , 0x00 , 0x00 , 0x10 } , /* MVFP LAEC */
{ 0xd1 , 0x21 , 0x20 , 0x07 , 0x07 , 0x07 , 0x07 , 0x10 } ,
/* BOS GBOS GROS ROS (BGGR offset) */
2008-07-15 18:46:06 +04:00
{ 0xd1 , 0x21 , 0x24 , 0x68 , 0x58 , 0xd4 , 0x80 , 0x10 } ,
/* {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, */
2008-06-30 22:50:11 +04:00
/* AEW AEB VPT BBIAS */
{ 0xd1 , 0x21 , 0x28 , 0x80 , 0x30 , 0x00 , 0x00 , 0x10 } ,
/* GbBIAS RSVD EXHCH EXHCL */
{ 0xd1 , 0x21 , 0x2c , 0x80 , 0x00 , 0x00 , 0x62 , 0x10 } ,
/* RBIAS ADVFL ASDVFH YAVE */
{ 0xc1 , 0x21 , 0x30 , 0x08 , 0x30 , 0xb4 , 0x00 , 0x10 } ,
/* HSYST HSYEN HREF */
{ 0xd1 , 0x21 , 0x33 , 0x00 , 0x07 , 0x84 , 0x00 , 0x10 } , /* reserved */
{ 0xd1 , 0x21 , 0x37 , 0x0c , 0x02 , 0x43 , 0x00 , 0x10 } ,
/* ADC ACOM OFON TSLB */
{ 0xd1 , 0x21 , 0x3b , 0x02 , 0x6c , 0x19 , 0x0e , 0x10 } ,
/* COM11 COM12 COM13 COM14 */
{ 0xd1 , 0x21 , 0x3f , 0x41 , 0xc1 , 0x22 , 0x08 , 0x10 } ,
/* EDGE COM15 COM16 COM17 */
{ 0xd1 , 0x21 , 0x43 , 0xf0 , 0x10 , 0x78 , 0xa8 , 0x10 } , /* reserved */
{ 0xd1 , 0x21 , 0x47 , 0x60 , 0x80 , 0x00 , 0x00 , 0x10 } , /* reserved */
{ 0xd1 , 0x21 , 0x4b , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } , /* reserved */
{ 0xd1 , 0x21 , 0x4f , 0x46 , 0x36 , 0x0f , 0x17 , 0x10 } , /* MTX 1 2 3 4 */
{ 0xd1 , 0x21 , 0x53 , 0x7f , 0x96 , 0x40 , 0x40 , 0x10 } , /* MTX 5 6 7 8 */
{ 0xb1 , 0x21 , 0x57 , 0x40 , 0x0f , 0x00 , 0x00 , 0x10 } , /* MTX9 MTXS */
{ 0xd1 , 0x21 , 0x59 , 0xba , 0x9a , 0x22 , 0xb9 , 0x10 } , /* reserved */
{ 0xd1 , 0x21 , 0x5d , 0x9b , 0x10 , 0xf0 , 0x05 , 0x10 } , /* reserved */
{ 0xa1 , 0x21 , 0x61 , 0x60 , 0x00 , 0x00 , 0x00 , 0x10 } , /* reserved */
{ 0xd1 , 0x21 , 0x62 , 0x00 , 0x00 , 0x50 , 0x30 , 0x10 } ,
/* LCC1 LCC2 LCC3 LCC4 */
{ 0xa1 , 0x21 , 0x66 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } , /* LCC5 */
{ 0xd1 , 0x21 , 0x67 , 0x80 , 0x7a , 0x90 , 0x80 , 0x10 } ,
{ 0xa1 , 0x21 , 0x6b , 0x0a , 0x00 , 0x00 , 0x00 , 0x10 } ,
/* band gap reference [0..3] DBLV */
{ 0xd1 , 0x21 , 0x6c , 0x30 , 0x48 , 0x80 , 0x74 , 0x10 } , /* gamma curve */
{ 0xd1 , 0x21 , 0x70 , 0x64 , 0x60 , 0x5c , 0x58 , 0x10 } , /* gamma curve */
{ 0xd1 , 0x21 , 0x74 , 0x54 , 0x4c , 0x40 , 0x38 , 0x10 } , /* gamma curve */
{ 0xd1 , 0x21 , 0x78 , 0x34 , 0x30 , 0x2f , 0x2b , 0x10 } , /* gamma curve */
{ 0xd1 , 0x21 , 0x7c , 0x03 , 0x07 , 0x17 , 0x34 , 0x10 } , /* gamma curve */
{ 0xd1 , 0x21 , 0x80 , 0x41 , 0x4d , 0x58 , 0x63 , 0x10 } , /* gamma curve */
{ 0xd1 , 0x21 , 0x84 , 0x6e , 0x77 , 0x87 , 0x95 , 0x10 } , /* gamma curve */
{ 0xc1 , 0x21 , 0x88 , 0xaf , 0xc7 , 0xdf , 0x00 , 0x10 } , /* gamma curve */
{ 0xc1 , 0x21 , 0x8b , 0x99 , 0x99 , 0xcf , 0x00 , 0x10 } , /* reserved */
{ 0xb1 , 0x21 , 0x92 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
/****** (some exchanges in the win trace) ******/
{ 0xa1 , 0x21 , 0x1e , 0x01 , 0x00 , 0x00 , 0x00 , 0x10 } ,
/* bits[3..0]reserved */
{ 0xa1 , 0x21 , 0x1e , 0x01 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
/* VREF vertical frame ctrl */
{ 0xa1 , 0x21 , 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x10 , 0x20 , 0x00 , 0x00 , 0x00 , 0x10 } , /* 0x20 */
{ 0xa1 , 0x21 , 0x2d , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x2e , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
2008-07-15 18:46:06 +04:00
/* {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, */
{ 0xa1 , 0x21 , 0x00 , 0x0a , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xb1 , 0x21 , 0x01 , 0x78 , 0x78 , 0x00 , 0x00 , 0x10 } ,
2008-06-30 22:50:11 +04:00
/****** (some exchanges in the win trace) ******/
{ 0xa1 , 0x21 , 0x93 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } , /* dummy line hight */
{ 0xa1 , 0x21 , 0x92 , 0x25 , 0x00 , 0x00 , 0x00 , 0x10 } , /* dummy line low */
{ 0xa1 , 0x21 , 0x2a , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x2b , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
2008-07-15 18:46:06 +04:00
{ 0xa1 , 0x21 , 0x02 , 0x90 , 0x00 , 0x00 , 0x00 , 0x10 } ,
2008-06-30 22:50:11 +04:00
/****** (some exchanges in the win trace) ******/
/**********startsensor KO if changed !!****/
{ 0xa1 , 0x21 , 0x93 , 0x01 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x92 , 0xff , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x2a , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xa1 , 0x21 , 0x2b , 0xc3 , 0x00 , 0x00 , 0x00 , 0x10 } ,
/* here may start the isoc exchanges */
2008-07-04 18:16:16 +04:00
{ }
2008-06-30 22:50:11 +04:00
} ;
/* reg0x04 reg0x07 reg 0x10 */
/* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
2008-07-04 18:16:16 +04:00
static const __u8 ov7648_sensor_init [ ] [ 8 ] = {
2008-06-30 22:50:11 +04:00
{ 0xC1 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 } ,
{ 0xC1 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 } ,
{ 0xC1 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 } ,
{ 0xA1 , 0x6E , 0x3F , 0x20 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x6E , 0x3F , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x6E , 0x3E , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x6E , 0x04 , 0x02 , 0xB1 , 0x02 , 0x39 , 0x10 } ,
{ 0xD1 , 0x6E , 0x08 , 0x00 , 0x01 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x6E , 0x0C , 0x02 , 0x7F , 0x01 , 0xE0 , 0x10 } ,
{ 0xD1 , 0x6E , 0x12 , 0x03 , 0x02 , 0x00 , 0x03 , 0x10 } ,
{ 0xD1 , 0x6E , 0x16 , 0x85 , 0x40 , 0x4A , 0x40 , 0x10 } ,
{ 0xC1 , 0x6E , 0x1A , 0x00 , 0x80 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x6E , 0x1D , 0x08 , 0x03 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x6E , 0x23 , 0x00 , 0xB0 , 0x00 , 0x94 , 0x10 } ,
{ 0xD1 , 0x6E , 0x27 , 0x58 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x6E , 0x2D , 0x14 , 0x35 , 0x61 , 0x84 , 0x10 } ,
{ 0xD1 , 0x6E , 0x31 , 0xA2 , 0xBD , 0xD8 , 0xFF , 0x10 } ,
{ 0xD1 , 0x6E , 0x35 , 0x06 , 0x1E , 0x12 , 0x02 , 0x10 } ,
{ 0xD1 , 0x6E , 0x39 , 0xAA , 0x53 , 0x37 , 0xD5 , 0x10 } ,
{ 0xA1 , 0x6E , 0x3D , 0xF2 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x6E , 0x3E , 0x00 , 0x00 , 0x80 , 0x03 , 0x10 } ,
{ 0xD1 , 0x6E , 0x42 , 0x03 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xC1 , 0x6E , 0x46 , 0x00 , 0x80 , 0x80 , 0x00 , 0x10 } ,
{ 0xD1 , 0x6E , 0x4B , 0x02 , 0xEF , 0x08 , 0xCD , 0x10 } ,
{ 0xD1 , 0x6E , 0x4F , 0x00 , 0xD0 , 0x00 , 0xA0 , 0x10 } ,
{ 0xD1 , 0x6E , 0x53 , 0x01 , 0xAA , 0x01 , 0x40 , 0x10 } ,
{ 0xD1 , 0x6E , 0x5A , 0x50 , 0x04 , 0x30 , 0x03 , 0x10 } ,
{ 0xA1 , 0x6E , 0x5E , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x6E , 0x5F , 0x10 , 0x40 , 0xFF , 0x00 , 0x10 } ,
/* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
{ 0xD1 , 0x6E , 0x67 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
* This is currently setting a
* blue tint , and some things more , i leave it here for future test if
* somene is having problems with color on this sensor
{ 0xD1 , 0x6E , 0x6B , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xD1 , 0x6E , 0x6F , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xC1 , 0x6E , 0x73 , 0x10 , 0x80 , 0xEB , 0x00 , 0x10 } ,
{ 0xA1 , 0x6E , 0x1E , 0x03 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x6E , 0x15 , 0x01 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xC1 , 0x6E , 0x16 , 0x40 , 0x40 , 0x40 , 0x00 , 0x10 } ,
{ 0xA1 , 0x6E , 0x1D , 0x08 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x6E , 0x06 , 0x02 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x6E , 0x07 , 0xB5 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x6E , 0x18 , 0x6B , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x6E , 0x1D , 0x08 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x6E , 0x06 , 0x02 , 0x00 , 0x00 , 0x00 , 0x10 } ,
{ 0xA1 , 0x6E , 0x07 , 0xB8 , 0x00 , 0x00 , 0x00 , 0x10 } , */
{ 0xC1 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 } ,
{ 0xA1 , 0x6E , 0x06 , 0x03 , 0x00 , 0x00 , 0x00 , 0x10 } , /* Bright... */
{ 0xA1 , 0x6E , 0x07 , 0x66 , 0x00 , 0x00 , 0x00 , 0x10 } , /* B.. */
{ 0xC1 , 0x6E , 0x1A , 0x03 , 0x65 , 0x90 , 0x00 , 0x10 } , /* Bright/Witen....*/
/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
2008-07-04 18:16:16 +04:00
{ }
2008-06-30 22:50:11 +04:00
} ;
2008-07-04 18:16:16 +04:00
static const __u8 qtable4 [ ] = {
2008-06-30 22:50:11 +04:00
0x06 , 0x04 , 0x04 , 0x06 , 0x04 , 0x04 , 0x06 , 0x06 , 0x06 , 0x06 , 0x08 , 0x06 ,
0x06 , 0x08 , 0x0A , 0x11 ,
0x0A , 0x0A , 0x08 , 0x08 , 0x0A , 0x15 , 0x0F , 0x0F , 0x0C , 0x11 , 0x19 , 0x15 ,
0x19 , 0x19 , 0x17 , 0x15 ,
0x17 , 0x17 , 0x1B , 0x1D , 0x25 , 0x21 , 0x1B , 0x1D , 0x23 , 0x1D , 0x17 , 0x17 ,
0x21 , 0x2E , 0x21 , 0x23 ,
0x27 , 0x29 , 0x2C , 0x2C , 0x2C , 0x19 , 0x1F , 0x30 , 0x32 , 0x2E , 0x29 , 0x32 ,
0x25 , 0x29 , 0x2C , 0x29 ,
0x06 , 0x08 , 0x08 , 0x0A , 0x08 , 0x0A , 0x13 , 0x0A , 0x0A , 0x13 , 0x29 , 0x1B ,
0x17 , 0x1B , 0x29 , 0x29 ,
0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 ,
0x29 , 0x29 , 0x29 , 0x29 ,
0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 ,
0x29 , 0x29 , 0x29 , 0x29 ,
0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 , 0x29 ,
0x29 , 0x29 , 0x29 , 0x29
} ;
2008-07-14 16:38:29 +04:00
/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
static void reg_r ( struct gspca_dev * gspca_dev ,
__u16 value , int len )
2008-06-30 22:50:11 +04:00
{
2008-07-14 16:38:29 +04:00
usb_control_msg ( gspca_dev - > dev ,
usb_rcvctrlpipe ( gspca_dev - > dev , 0 ) ,
2008-06-30 22:50:11 +04:00
0 ,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE ,
value , 0 ,
2008-07-14 16:38:29 +04:00
gspca_dev - > usb_buf , len ,
2008-06-30 22:50:11 +04:00
500 ) ;
}
2008-07-14 16:38:29 +04:00
static void reg_w ( struct gspca_dev * gspca_dev ,
2008-06-30 22:50:11 +04:00
__u16 value ,
2008-07-03 18:09:12 +04:00
const __u8 * buffer ,
2008-06-30 22:50:11 +04:00
int len )
{
2008-07-14 16:38:29 +04:00
if ( len < = sizeof gspca_dev - > usb_buf ) {
memcpy ( gspca_dev - > usb_buf , buffer , len ) ;
usb_control_msg ( gspca_dev - > dev ,
usb_sndctrlpipe ( gspca_dev - > dev , 0 ) ,
2008-07-04 18:16:16 +04:00
0x08 ,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE ,
value , 0 ,
2008-07-14 16:38:29 +04:00
gspca_dev - > usb_buf , len ,
2008-07-04 18:16:16 +04:00
500 ) ;
} else {
__u8 * tmpbuf ;
tmpbuf = kmalloc ( len , GFP_KERNEL ) ;
memcpy ( tmpbuf , buffer , len ) ;
2008-07-14 16:38:29 +04:00
usb_control_msg ( gspca_dev - > dev ,
usb_sndctrlpipe ( gspca_dev - > dev , 0 ) ,
2008-07-04 18:16:16 +04:00
0x08 ,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE ,
value , 0 ,
tmpbuf , len ,
500 ) ;
kfree ( tmpbuf ) ;
2008-07-03 18:09:12 +04:00
}
2008-06-30 22:50:11 +04:00
}
2008-07-14 16:38:29 +04:00
/* I2C write 2 bytes */
2008-06-30 22:50:11 +04:00
static void i2c_w2 ( struct gspca_dev * gspca_dev ,
2008-07-04 18:16:16 +04:00
const __u8 * buffer )
2008-06-30 22:50:11 +04:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
__u8 mode [ 8 ] ;
/* is i2c ready */
2008-07-15 12:36:30 +04:00
mode [ 0 ] = 0x81 | ( 2 < < 4 ) ;
2008-06-30 22:50:11 +04:00
mode [ 1 ] = sd - > i2c_base ;
mode [ 2 ] = buffer [ 0 ] ;
mode [ 3 ] = buffer [ 1 ] ;
mode [ 4 ] = 0 ;
mode [ 5 ] = 0 ;
mode [ 6 ] = 0 ;
mode [ 7 ] = 0x10 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x08 , mode , 8 ) ;
2008-06-30 22:50:11 +04:00
}
2008-07-14 16:38:29 +04:00
/* I2C write 8 bytes */
static void i2c_w8 ( struct gspca_dev * gspca_dev ,
const __u8 * buffer )
2008-06-30 22:50:11 +04:00
{
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x08 , buffer , 8 ) ;
2008-06-30 22:50:11 +04:00
msleep ( 1 ) ;
}
2008-07-14 16:38:29 +04:00
/* read 5 bytes in gspca_dev->usb_buf */
static void i2c_r5 ( struct gspca_dev * gspca_dev , __u8 reg )
2008-06-30 22:50:11 +04:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
__u8 mode [ 8 ] ;
2008-07-15 12:36:30 +04:00
mode [ 0 ] = 0x81 | 0x10 ;
2008-06-30 22:50:11 +04:00
mode [ 1 ] = sd - > i2c_base ;
mode [ 2 ] = reg ;
mode [ 3 ] = 0 ;
mode [ 4 ] = 0 ;
mode [ 5 ] = 0 ;
mode [ 6 ] = 0 ;
mode [ 7 ] = 0x10 ;
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , mode ) ;
2008-07-15 12:36:30 +04:00
mode [ 0 ] = 0x81 | ( 5 < < 4 ) | 0x02 ;
2008-06-30 22:50:11 +04:00
mode [ 2 ] = 0 ;
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , mode ) ;
reg_r ( gspca_dev , 0x0a , 5 ) ;
2008-06-30 22:50:11 +04:00
}
static int probesensor ( struct gspca_dev * gspca_dev )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
__u8 reg02 ;
2008-07-04 18:16:16 +04:00
static const __u8 datasend [ ] = { 2 , 0 } ;
2008-06-30 22:50:11 +04:00
/* reg val1 val2 val3 val4 */
i2c_w2 ( gspca_dev , datasend ) ;
/* should write 0xa1 0x11 0x02 0x00 0x00 0x00 0x00 the 0x10 is add by i2cw */
msleep ( 10 ) ;
reg02 = 0x66 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x02 , & reg02 , 1 ) ; /* Gpio on */
2008-06-30 22:50:11 +04:00
msleep ( 10 ) ;
2008-07-14 16:38:29 +04:00
i2c_r5 ( gspca_dev , 0 ) ; /* read sensor id */
if ( gspca_dev - > usb_buf [ 0 ] = = 0x02
& & gspca_dev - > usb_buf [ 1 ] = = 0x09
& & gspca_dev - > usb_buf [ 2 ] = = 0x01
& & gspca_dev - > usb_buf [ 3 ] = = 0x00
& & gspca_dev - > usb_buf [ 4 ] = = 0x00 ) {
2008-06-30 22:50:11 +04:00
PDEBUG ( D_PROBE , " Find Sensor sn9c102P HV7131R " ) ;
sd - > sensor = SENSOR_HV7131R ;
return SENSOR_HV7131R ;
}
PDEBUG ( D_PROBE , " Find Sensor %d %d %d " ,
2008-07-14 16:38:29 +04:00
gspca_dev - > usb_buf [ 0 ] , gspca_dev - > usb_buf [ 1 ] ,
gspca_dev - > usb_buf [ 2 ] ) ;
2008-06-30 22:50:11 +04:00
PDEBUG ( D_PROBE , " Sensor sn9c102P Not found " ) ;
return - ENODEV ;
}
static int configure_gpio ( struct gspca_dev * gspca_dev ,
2008-07-04 18:16:16 +04:00
const __u8 * sn9c1xx )
2008-06-30 22:50:11 +04:00
{
struct sd * sd = ( struct sd * ) gspca_dev ;
__u8 data ;
__u8 regF1 ;
2008-07-04 18:16:16 +04:00
const __u8 * reg9a ;
static const __u8 reg9a_def [ ] =
2008-06-30 22:50:11 +04:00
{ 0x08 , 0x40 , 0x20 , 0x10 , 0x00 , 0x04 } ;
2008-07-04 18:16:16 +04:00
static const __u8 reg9a_sn9c120 [ ] = /* from win trace */
2008-06-30 22:50:11 +04:00
{ 0x00 , 0x40 , 0x38 , 0x30 , 0x00 , 0x20 } ;
2008-07-04 18:16:16 +04:00
static const __u8 reg9a_sn9c325 [ ] =
2008-06-30 22:50:11 +04:00
{ 0x0a , 0x40 , 0x38 , 0x30 , 0x00 , 0x20 } ;
regF1 = 0x00 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0xf1 , & regF1 , 1 ) ;
2008-07-15 18:46:06 +04:00
reg_w ( gspca_dev , 0x01 , & sn9c1xx [ 0 ] , 1 ) ; /*fixme:jfm was [1] en v1*/
2008-06-30 22:50:11 +04:00
/* configure gpio */
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x01 , & sn9c1xx [ 1 ] , 2 ) ;
reg_w ( gspca_dev , 0x08 , & sn9c1xx [ 8 ] , 2 ) ;
2008-07-15 18:46:06 +04:00
reg_w ( gspca_dev , 0x17 , & sn9c1xx [ 0x17 ] , 5 ) ; /* jfm was 3 */
2008-07-15 12:36:30 +04:00
switch ( sd - > bridge ) {
case BRIDGE_SN9C325 :
2008-06-30 22:50:11 +04:00
reg9a = reg9a_sn9c325 ;
break ;
2008-07-15 12:36:30 +04:00
case BRIDGE_SN9C120 :
2008-06-30 22:50:11 +04:00
reg9a = reg9a_sn9c120 ;
break ;
default :
reg9a = reg9a_def ;
break ;
}
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x9a , reg9a , 6 ) ;
2008-06-30 22:50:11 +04:00
data = 0x60 ; /*fixme:jfm 60 00 00 (3) */
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0xd4 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x03 , & sn9c1xx [ 3 ] , 0x0f ) ;
2008-06-30 22:50:11 +04:00
2008-07-15 12:36:30 +04:00
switch ( sd - > bridge ) {
case BRIDGE_SN9C120 : /* from win trace */
2008-06-30 22:50:11 +04:00
data = 0x61 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x01 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
data = 0x20 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x17 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
data = 0x60 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x01 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
break ;
2008-07-15 12:36:30 +04:00
case BRIDGE_SN9C325 :
2008-06-30 22:50:11 +04:00
data = 0x43 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x01 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
data = 0xae ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x17 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
data = 0x42 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x01 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
break ;
default :
data = 0x43 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x01 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
data = 0x61 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x17 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
data = 0x42 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x01 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
}
if ( sd - > sensor = = SENSOR_HV7131R ) {
if ( probesensor ( gspca_dev ) < 0 )
return - ENODEV ;
}
return 0 ;
}
static void hv7131R_InitSensor ( struct gspca_dev * gspca_dev )
{
int i = 0 ;
2008-07-04 18:16:16 +04:00
static const __u8 SetSensorClk [ ] = /* 0x08 Mclk */
2008-06-30 22:50:11 +04:00
{ 0xa1 , 0x11 , 0x01 , 0x18 , 0x00 , 0x00 , 0x00 , 0x10 } ;
while ( hv7131r_sensor_init [ i ] [ 0 ] ) {
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , hv7131r_sensor_init [ i ] ) ;
2008-06-30 22:50:11 +04:00
i + + ;
}
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , SetSensorClk ) ;
2008-06-30 22:50:11 +04:00
}
static void mi0360_InitSensor ( struct gspca_dev * gspca_dev )
{
int i = 0 ;
while ( mi0360_sensor_init [ i ] [ 0 ] ) {
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , mi0360_sensor_init [ i ] ) ;
2008-06-30 22:50:11 +04:00
i + + ;
}
}
static void mo4000_InitSensor ( struct gspca_dev * gspca_dev )
{
int i = 0 ;
while ( mo4000_sensor_init [ i ] [ 0 ] ) {
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , mo4000_sensor_init [ i ] ) ;
2008-06-30 22:50:11 +04:00
i + + ;
}
}
static void ov7648_InitSensor ( struct gspca_dev * gspca_dev )
{
int i = 0 ;
while ( ov7648_sensor_init [ i ] [ 0 ] ) {
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , ov7648_sensor_init [ i ] ) ;
2008-06-30 22:50:11 +04:00
i + + ;
}
}
static void ov7660_InitSensor ( struct gspca_dev * gspca_dev )
{
int i = 0 ;
while ( ov7660_sensor_init [ i ] [ 0 ] ) {
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , ov7660_sensor_init [ i ] ) ;
2008-06-30 22:50:11 +04:00
i + + ;
}
}
/* this function is called at probe time */
static int sd_config ( struct gspca_dev * gspca_dev ,
const struct usb_device_id * id )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
struct cam * cam ;
__u16 vendor ;
__u16 product ;
vendor = id - > idVendor ;
product = id - > idProduct ;
sd - > sensor = - 1 ;
switch ( vendor ) {
case 0x0458 : /* Genius */
/* switch (product) {
case 0x7025 : */
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C120 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_MI0360 ;
sd - > i2c_base = 0x5d ;
/* break;
} */
break ;
case 0x045e :
/* switch (product) {
case 0x00f5 :
case 0x00f7 : */
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C105 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OV7660 ;
sd - > i2c_base = 0x21 ;
/* break;
} */
break ;
case 0x0471 : /* Philips */
/* switch (product) {
case 0x0327 :
case 0x0328 :
case 0x0330 : */
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C105 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_MI0360 ;
sd - > i2c_base = 0x5d ;
/* break;
} */
break ;
case 0x0c45 : /* Sonix */
switch ( product ) {
case 0x6040 :
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C102P ;
2008-07-15 18:46:06 +04:00
/* sd->sensor = SENSOR_MI0360; * from BW600.inf */
/*fixme: MI0360 base=5d ? */
sd - > sensor = SENSOR_HV7131R ; /* gspcav1 value */
2008-06-30 22:50:11 +04:00
sd - > i2c_base = 0x11 ;
break ;
/* case 0x607a: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C102P ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OV7648 ;
sd - > i2c_base = 0 x ? ? ;
break ; */
case 0x607c :
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C102P ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_HV7131R ;
sd - > i2c_base = 0x11 ;
break ;
/* case 0x607e: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C102P ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OV7630 ;
sd - > i2c_base = 0 x ? ? ;
break ; */
case 0x60c0 :
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C105 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_MI0360 ;
sd - > i2c_base = 0x5d ;
break ;
/* case 0x60c8: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C105 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OM6801 ;
sd - > i2c_base = 0 x ? ? ;
break ; */
/* case 0x60cc: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C105 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_HV7131GP ;
sd - > i2c_base = 0 x ? ? ;
break ; */
case 0x60ec :
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C105 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_MO4000 ;
sd - > i2c_base = 0x21 ;
break ;
/* case 0x60ef: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C105 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_ICM105C ;
sd - > i2c_base = 0 x ? ? ;
break ; */
/* case 0x60fa: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C105 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OV7648 ;
sd - > i2c_base = 0 x ? ? ;
break ; */
case 0x60fb :
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C105 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OV7660 ;
sd - > i2c_base = 0x21 ;
break ;
case 0x60fc :
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C105 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_HV7131R ;
sd - > i2c_base = 0x11 ;
break ;
/* case 0x60fe: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C105 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OV7630 ;
sd - > i2c_base = 0 x ? ? ;
break ; */
/* case 0x6108: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C120 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OM6801 ;
sd - > i2c_base = 0 x ? ? ;
break ; */
/* case 0x6122: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C110 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_ICM105C ;
sd - > i2c_base = 0 x ? ? ;
break ; */
case 0x612a :
2008-07-15 18:46:06 +04:00
/* sd->bridge = BRIDGE_SN9C110; * in BW600.inf */
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C325 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OV7648 ;
sd - > i2c_base = 0x21 ;
2008-07-15 18:46:06 +04:00
/*fixme: sensor_init has base = 00 et 6e!*/
2008-06-30 22:50:11 +04:00
break ;
/* case 0x6123: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C110 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_SanyoCCD ;
sd - > i2c_base = 0 x ? ? ;
break ; */
case 0x612c :
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C110 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_MO4000 ;
sd - > i2c_base = 0x21 ;
break ;
/* case 0x612e: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C110 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OV7630 ;
sd - > i2c_base = 0 x ? ? ;
break ; */
/* case 0x612f: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C110 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_ICM105C ;
sd - > i2c_base = 0 x ? ? ;
break ; */
case 0x6130 :
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C120 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_MI0360 ;
sd - > i2c_base = 0x5d ;
break ;
case 0x6138 :
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C120 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_MO4000 ;
sd - > i2c_base = 0x21 ;
break ;
/* case 0x613a: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C120 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OV7648 ;
sd - > i2c_base = 0 x ? ? ;
break ; */
case 0x613b :
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C120 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OV7660 ;
sd - > i2c_base = 0x21 ;
break ;
case 0x613c :
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C120 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_HV7131R ;
sd - > i2c_base = 0x11 ;
break ;
/* case 0x613e: * from BW600.inf
2008-07-15 12:36:30 +04:00
sd - > bridge = BRIDGE_SN9C120 ;
2008-06-30 22:50:11 +04:00
sd - > sensor = SENSOR_OV7630 ;
sd - > i2c_base = 0 x ? ? ;
break ; */
}
break ;
}
if ( sd - > sensor < 0 ) {
PDEBUG ( D_ERR , " Invalid vendor/product %04x:%04x " ,
vendor , product ) ;
return - EINVAL ;
}
cam = & gspca_dev - > cam ;
cam - > dev_name = ( char * ) id - > driver_info ;
cam - > epaddr = 0x01 ;
cam - > cam_mode = vga_mode ;
cam - > nmodes = ARRAY_SIZE ( vga_mode ) ;
2008-07-04 18:16:16 +04:00
2008-06-30 22:50:11 +04:00
sd - > qindex = 4 ; /* set the quantization table */
2008-07-04 18:16:16 +04:00
sd - > brightness = BRIGHTNESS_DEF ;
sd - > contrast = CONTRAST_DEF ;
sd - > colors = COLOR_DEF ;
sd - > autogain = AUTOGAIN_DEF ;
2008-06-30 22:50:11 +04:00
return 0 ;
}
/* this function is called at open time */
static int sd_open ( struct gspca_dev * gspca_dev )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2008-07-04 18:16:16 +04:00
/* const __u8 *sn9c1xx; */
2008-06-30 22:50:11 +04:00
__u8 regF1 ;
__u8 regGpio [ ] = { 0x29 , 0x74 } ;
2008-07-15 12:36:30 +04:00
/* setup a selector by bridge */
2008-06-30 22:50:11 +04:00
regF1 = 0x01 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0xf1 , & regF1 , 1 ) ;
reg_r ( gspca_dev , 0x00 , 1 ) ; /* -> regF1 = 0x00 */
regF1 = gspca_dev - > usb_buf [ 0 ] ;
reg_w ( gspca_dev , 0xf1 , & regF1 , 1 ) ;
reg_r ( gspca_dev , 0x00 , 1 ) ;
regF1 = gspca_dev - > usb_buf [ 0 ] ;
2008-07-15 12:36:30 +04:00
switch ( sd - > bridge ) {
case BRIDGE_SN9C102P :
2008-06-30 22:50:11 +04:00
if ( regF1 ! = 0x11 )
return - ENODEV ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x02 , & regGpio [ 1 ] , 1 ) ;
2008-06-30 22:50:11 +04:00
break ;
2008-07-15 12:36:30 +04:00
case BRIDGE_SN9C105 :
2008-06-30 22:50:11 +04:00
if ( regF1 ! = 0x11 )
return - ENODEV ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x02 , regGpio , 2 ) ;
2008-06-30 22:50:11 +04:00
break ;
2008-07-15 12:36:30 +04:00
case BRIDGE_SN9C110 :
2008-06-30 22:50:11 +04:00
if ( regF1 ! = 0x12 )
return - ENODEV ;
regGpio [ 1 ] = 0x62 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x02 , & regGpio [ 1 ] , 1 ) ;
2008-06-30 22:50:11 +04:00
break ;
2008-07-15 12:36:30 +04:00
case BRIDGE_SN9C120 :
2008-06-30 22:50:11 +04:00
if ( regF1 ! = 0x12 )
return - ENODEV ;
regGpio [ 1 ] = 0x70 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x02 , regGpio , 2 ) ;
2008-06-30 22:50:11 +04:00
break ;
default :
2008-07-15 12:36:30 +04:00
/* case BRIDGE_SN9C325: */
2008-06-30 22:50:11 +04:00
if ( regF1 ! = 0x12 )
return - ENODEV ;
regGpio [ 1 ] = 0x62 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x02 , & regGpio [ 1 ] , 1 ) ;
2008-06-30 22:50:11 +04:00
break ;
}
regF1 = 0x01 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0xf1 , & regF1 , 1 ) ;
2008-06-30 22:50:11 +04:00
return 0 ;
}
static unsigned int setexposure ( struct gspca_dev * gspca_dev ,
unsigned int expo )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2008-07-04 18:16:16 +04:00
static const __u8 doit [ ] = /* update sensor */
2008-06-30 22:50:11 +04:00
{ 0xb1 , 0x5d , 0x07 , 0x00 , 0x03 , 0x00 , 0x00 , 0x10 } ;
2008-07-04 18:16:16 +04:00
static const __u8 sensorgo [ ] = /* sensor on */
2008-06-30 22:50:11 +04:00
{ 0xb1 , 0x5d , 0x07 , 0x00 , 0x02 , 0x00 , 0x00 , 0x10 } ;
2008-07-04 18:16:16 +04:00
static const __u8 gainMo [ ] =
2008-06-30 22:50:11 +04:00
{ 0xa1 , 0x21 , 0x00 , 0x10 , 0x00 , 0x00 , 0x00 , 0x1d } ;
switch ( sd - > sensor ) {
case SENSOR_HV7131R : {
__u8 Expodoit [ ] =
{ 0xc1 , 0x11 , 0x25 , 0x07 , 0x27 , 0xc0 , 0x00 , 0x16 } ;
Expodoit [ 3 ] = expo > > 16 ;
Expodoit [ 4 ] = expo > > 8 ;
Expodoit [ 5 ] = expo ;
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , Expodoit ) ;
2008-06-30 22:50:11 +04:00
break ;
}
case SENSOR_MI0360 : {
__u8 expoMi [ ] = /* exposure 0x0635 -> 4 fp/s 0x10 */
{ 0xb1 , 0x5d , 0x09 , 0x06 , 0x35 , 0x00 , 0x00 , 0x16 } ;
if ( expo > 0x0635 )
expo = 0x0635 ;
else if ( expo < 0x0001 )
expo = 0x0001 ;
expoMi [ 3 ] = expo > > 8 ;
expoMi [ 4 ] = expo ;
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , expoMi ) ;
i2c_w8 ( gspca_dev , doit ) ;
i2c_w8 ( gspca_dev , sensorgo ) ;
2008-06-30 22:50:11 +04:00
break ;
}
case SENSOR_MO4000 : {
__u8 expoMof [ ] =
{ 0xa1 , 0x21 , 0x0f , 0x20 , 0x00 , 0x00 , 0x00 , 0x10 } ;
__u8 expoMo10 [ ] =
{ 0xa1 , 0x21 , 0x10 , 0x20 , 0x00 , 0x00 , 0x00 , 0x10 } ;
if ( expo > 0x1fff )
expo = 0x1fff ;
else if ( expo < 0x0001 )
expo = 0x0001 ;
expoMof [ 3 ] = ( expo & 0x03fc ) > > 2 ;
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , expoMof ) ;
2008-06-30 22:50:11 +04:00
expoMo10 [ 3 ] = ( ( expo & 0x1c00 ) > > 10 )
| ( ( expo & 0x0003 ) < < 4 ) ;
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , expoMo10 ) ;
i2c_w8 ( gspca_dev , gainMo ) ;
2008-07-01 17:03:42 +04:00
PDEBUG ( D_CONF , " set exposure %d " ,
2008-06-30 22:50:11 +04:00
( ( expoMo10 [ 3 ] & 0x07 ) < < 10 )
| ( expoMof [ 3 ] < < 2 )
| ( ( expoMo10 [ 3 ] & 0x30 ) > > 4 ) ) ;
break ;
}
}
return expo ;
}
static void setbrightness ( struct gspca_dev * gspca_dev )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
unsigned int expo ;
__u8 k2 ;
switch ( sd - > sensor ) {
case SENSOR_HV7131R :
expo = sd - > brightness < < 4 ;
if ( expo > 0x002dc6c0 )
expo = 0x002dc6c0 ;
else if ( expo < 0x02a0 )
expo = 0x02a0 ;
sd - > exposure = setexposure ( gspca_dev , expo ) ;
break ;
case SENSOR_MI0360 :
expo = sd - > brightness > > 4 ;
sd - > exposure = setexposure ( gspca_dev , expo ) ;
break ;
case SENSOR_MO4000 :
expo = sd - > brightness > > 4 ;
sd - > exposure = setexposure ( gspca_dev , expo ) ;
break ;
case SENSOR_OV7660 :
return ; /*jfm??*/
}
k2 = sd - > brightness > > 10 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x96 , & k2 , 1 ) ;
2008-06-30 22:50:11 +04:00
}
static void setcontrast ( struct gspca_dev * gspca_dev )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
__u8 k2 ;
__u8 contrast [ ] = { 0x00 , 0x00 , 0x28 , 0x00 , 0x07 , 0x00 } ;
if ( sd - > sensor = = SENSOR_OV7660 )
return ; /*jfm??*/
k2 = sd - > contrast ;
contrast [ 2 ] = k2 ;
contrast [ 0 ] = ( k2 + 1 ) > > 1 ;
contrast [ 4 ] = ( k2 + 1 ) / 5 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x84 , contrast , 6 ) ;
2008-06-30 22:50:11 +04:00
}
static void setcolors ( struct gspca_dev * gspca_dev )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
__u8 data ;
int colour ;
colour = sd - > colors - 128 ;
if ( colour > 0 )
data = ( colour + 32 ) & 0x7f ; /* blue */
else
data = ( - colour + 32 ) & 0x7f ; /* red */
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x05 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
}
/* -- start the camera -- */
static void sd_start ( struct gspca_dev * gspca_dev )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
int i ;
__u8 data ;
__u8 reg1 ;
__u8 reg17 ;
2008-07-04 18:16:16 +04:00
const __u8 * sn9c1xx ;
2008-06-30 22:50:11 +04:00
int mode ;
2008-07-04 18:16:16 +04:00
static const __u8 DC29 [ ] = { 0x6a , 0x50 , 0x00 , 0x00 , 0x50 , 0x3c } ;
static const __u8 C0 [ ] = { 0x2d , 0x2d , 0x3a , 0x05 , 0x04 , 0x3f } ;
static const __u8 CA [ ] = { 0x28 , 0xd8 , 0x14 , 0xec } ;
static const __u8 CA_sn9c120 [ ] =
{ 0x14 , 0xec , 0x0a , 0xf6 } ; /* SN9C120 */
static const __u8 CE [ ] = { 0x32 , 0xdd , 0x2d , 0xdd } ; /* MI0360 */
static const __u8 CE_sn9c325 [ ] =
2008-06-30 22:50:11 +04:00
{ 0x32 , 0xdd , 0x32 , 0xdd } ; /* OV7648 - SN9C325 */
sn9c1xx = sn_tb [ ( int ) sd - > sensor ] ;
configure_gpio ( gspca_dev , sn9c1xx ) ;
/*fixme:jfm this sequence should appear at end of sd_start */
/* with
data = 0x44 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x01 , & data , 1 ) ; */
reg_w ( gspca_dev , 0x15 , & sn9c1xx [ 0x15 ] , 1 ) ;
reg_w ( gspca_dev , 0x16 , & sn9c1xx [ 0x16 ] , 1 ) ;
reg_w ( gspca_dev , 0x12 , & sn9c1xx [ 0x12 ] , 1 ) ;
reg_w ( gspca_dev , 0x13 , & sn9c1xx [ 0x13 ] , 1 ) ;
reg_w ( gspca_dev , 0x18 , & sn9c1xx [ 0x18 ] , 1 ) ;
reg_w ( gspca_dev , 0xd2 , & DC29 [ 0 ] , 1 ) ;
reg_w ( gspca_dev , 0xd3 , & DC29 [ 1 ] , 1 ) ;
reg_w ( gspca_dev , 0xc6 , & DC29 [ 2 ] , 1 ) ;
reg_w ( gspca_dev , 0xc7 , & DC29 [ 3 ] , 1 ) ;
reg_w ( gspca_dev , 0xc8 , & DC29 [ 4 ] , 1 ) ;
reg_w ( gspca_dev , 0xc9 , & DC29 [ 5 ] , 1 ) ;
2008-06-30 22:50:11 +04:00
/*fixme:jfm end of ending sequence */
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x18 , & sn9c1xx [ 0x18 ] , 1 ) ;
2008-07-15 18:46:06 +04:00
switch ( sd - > bridge ) {
case BRIDGE_SN9C325 :
2008-06-30 22:50:11 +04:00
data = 0xae ;
2008-07-15 18:46:06 +04:00
break ;
case BRIDGE_SN9C120 :
data = 0xa0 ;
break ;
default :
2008-06-30 22:50:11 +04:00
data = 0x60 ;
2008-07-15 18:46:06 +04:00
break ;
}
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x17 , & data , 1 ) ;
reg_w ( gspca_dev , 0x05 , & sn9c1xx [ 5 ] , 1 ) ;
reg_w ( gspca_dev , 0x07 , & sn9c1xx [ 7 ] , 1 ) ;
reg_w ( gspca_dev , 0x06 , & sn9c1xx [ 6 ] , 1 ) ;
reg_w ( gspca_dev , 0x14 , & sn9c1xx [ 0x14 ] , 1 ) ;
2008-07-15 18:46:06 +04:00
switch ( sd - > bridge ) {
case BRIDGE_SN9C325 :
reg_w ( gspca_dev , 0x20 , regsn20_sn9c325 ,
sizeof regsn20_sn9c325 ) ;
2008-06-30 22:50:11 +04:00
for ( i = 0 ; i < 8 ; i + + )
2008-07-15 18:46:06 +04:00
reg_w ( gspca_dev , 0x84 , reg84_sn9c325 ,
sizeof reg84_sn9c325 ) ;
2008-06-30 22:50:11 +04:00
data = 0x0a ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x9a , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
data = 0x60 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x99 , & data , 1 ) ;
2008-07-15 18:46:06 +04:00
break ;
case BRIDGE_SN9C120 :
reg_w ( gspca_dev , 0x20 , regsn20_sn9c120 ,
sizeof regsn20_sn9c120 ) ;
for ( i = 0 ; i < 2 ; i + + )
reg_w ( gspca_dev , 0x84 , reg84_sn9c120_1 ,
sizeof reg84_sn9c120_1 ) ;
for ( i = 0 ; i < 6 ; i + + )
reg_w ( gspca_dev , 0x84 , reg84_sn9c120_2 ,
sizeof reg84_sn9c120_2 ) ;
reg_w ( gspca_dev , 0x84 , reg84_sn9c120_3 ,
sizeof reg84_sn9c120_3 ) ;
data = 0x05 ;
reg_w ( gspca_dev , 0x9a , & data , 1 ) ;
data = 0x5b ;
reg_w ( gspca_dev , 0x99 , & data , 1 ) ;
break ;
default :
reg_w ( gspca_dev , 0x20 , regsn20 , sizeof regsn20 ) ;
2008-06-30 22:50:11 +04:00
for ( i = 0 ; i < 8 ; i + + )
2008-07-15 18:46:06 +04:00
reg_w ( gspca_dev , 0x84 , reg84 , sizeof reg84 ) ;
2008-06-30 22:50:11 +04:00
data = 0x08 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x9a , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
data = 0x59 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x99 , & data , 1 ) ;
2008-07-15 18:46:06 +04:00
break ;
2008-06-30 22:50:11 +04:00
}
2008-07-05 18:49:20 +04:00
mode = gspca_dev - > cam . cam_mode [ ( int ) gspca_dev - > curr_mode ] . priv ;
2008-06-30 22:50:11 +04:00
reg1 = 0x02 ;
reg17 = 0x61 ;
switch ( sd - > sensor ) {
case SENSOR_HV7131R :
hv7131R_InitSensor ( gspca_dev ) ;
if ( mode )
reg1 = 0x46 ; /* 320 clk 48Mhz */
else
reg1 = 0x06 ; /* 640 clk 24Mz */
break ;
case SENSOR_MI0360 :
mi0360_InitSensor ( gspca_dev ) ;
if ( mode )
reg1 = 0x46 ; /* 320 clk 48Mhz */
else
reg1 = 0x06 ; /* 640 clk 24Mz */
break ;
case SENSOR_MO4000 :
mo4000_InitSensor ( gspca_dev ) ;
if ( mode ) {
/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
reg1 = 0x06 ; /* clk 24Mz */
} else {
reg17 = 0x22 ; /* 640 MCKSIZE */
reg1 = 0x06 ; /* 640 clk 24Mz */
}
break ;
case SENSOR_OV7648 :
reg17 = 0xa2 ;
reg1 = 0x44 ;
ov7648_InitSensor ( gspca_dev ) ;
/* if (mode)
; * 320 x2 . . .
else
; * 640 x . . . */
break ;
default :
/* case SENSOR_OV7660: */
ov7660_InitSensor ( gspca_dev ) ;
if ( mode ) {
/* reg17 = 0x21; * 320 */
/* reg1 = 0x44; */
reg1 = 0x46 ;
} else {
reg17 = 0xa2 ; /* 640 */
reg1 = 0x40 ;
}
break ;
}
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0xc0 , C0 , 6 ) ;
2008-07-15 12:36:30 +04:00
switch ( sd - > bridge ) {
case BRIDGE_SN9C120 : /*jfm ?? */
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0xca , CA_sn9c120 , 4 ) ;
2008-06-30 22:50:11 +04:00
break ;
default :
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0xca , CA , 4 ) ;
2008-06-30 22:50:11 +04:00
break ;
}
2008-07-15 12:36:30 +04:00
switch ( sd - > bridge ) {
case BRIDGE_SN9C120 : /*jfm ?? */
case BRIDGE_SN9C325 :
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0xce , CE_sn9c325 , 4 ) ;
2008-06-30 22:50:11 +04:00
break ;
default :
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0xce , CE , 4 ) ;
2008-06-30 22:50:11 +04:00
/* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
break ;
}
/* here change size mode 0 -> VGA; 1 -> CIF */
data = 0x40 | sn9c1xx [ 0x18 ] | ( mode < < 4 ) ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x18 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x100 , qtable4 , 0x40 ) ;
reg_w ( gspca_dev , 0x140 , qtable4 + 0x40 , 0x40 ) ;
2008-06-30 22:50:11 +04:00
data = sn9c1xx [ 0x18 ] | ( mode < < 4 ) ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x18 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x17 , & reg17 , 1 ) ;
reg_w ( gspca_dev , 0x01 , & reg1 , 1 ) ;
2008-06-30 22:50:11 +04:00
setbrightness ( gspca_dev ) ;
setcontrast ( gspca_dev ) ;
}
static void sd_stopN ( struct gspca_dev * gspca_dev )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
2008-07-04 18:16:16 +04:00
static const __u8 stophv7131 [ ] =
2008-06-30 22:50:11 +04:00
{ 0xa1 , 0x11 , 0x02 , 0x09 , 0x00 , 0x00 , 0x00 , 0x10 } ;
2008-07-04 18:16:16 +04:00
static const __u8 stopmi0360 [ ] =
2008-06-30 22:50:11 +04:00
{ 0xb1 , 0x5d , 0x07 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ;
__u8 regF1 ;
__u8 data ;
2008-07-04 18:16:16 +04:00
const __u8 * sn9c1xx ;
2008-06-30 22:50:11 +04:00
data = 0x0b ;
switch ( sd - > sensor ) {
case SENSOR_HV7131R :
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , stophv7131 ) ;
2008-06-30 22:50:11 +04:00
data = 0x2b ;
break ;
case SENSOR_MI0360 :
2008-07-14 16:38:29 +04:00
i2c_w8 ( gspca_dev , stopmi0360 ) ;
2008-06-30 22:50:11 +04:00
data = 0x29 ;
break ;
case SENSOR_MO4000 :
break ;
case SENSOR_OV7648 :
data = 0x29 ;
break ;
default :
/* case SENSOR_OV7660: */
break ;
}
sn9c1xx = sn_tb [ ( int ) sd - > sensor ] ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0x01 , & sn9c1xx [ 1 ] , 1 ) ;
reg_w ( gspca_dev , 0x17 , & sn9c1xx [ 0x17 ] , 1 ) ;
reg_w ( gspca_dev , 0x01 , & sn9c1xx [ 1 ] , 1 ) ;
reg_w ( gspca_dev , 0x01 , & data , 1 ) ;
2008-06-30 22:50:11 +04:00
regF1 = 0x01 ;
2008-07-14 16:38:29 +04:00
reg_w ( gspca_dev , 0xf1 , & regF1 , 1 ) ;
2008-06-30 22:50:11 +04:00
}
static void sd_stop0 ( struct gspca_dev * gspca_dev )
{
}
static void sd_close ( struct gspca_dev * gspca_dev )
{
}
static void setautogain ( struct gspca_dev * gspca_dev )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
/* Thanks S., without your advice, autobright should not work :) */
int delta ;
int expotimes = 0 ;
__u8 luma_mean = 130 ;
__u8 luma_delta = 20 ;
delta = sd - > avg_lum ;
if ( delta < luma_mean - luma_delta | |
delta > luma_mean + luma_delta ) {
switch ( sd - > sensor ) {
case SENSOR_HV7131R :
expotimes = sd - > exposure > > 8 ;
expotimes + = ( luma_mean - delta ) > > 4 ;
if ( expotimes < 0 )
expotimes = 0 ;
sd - > exposure = setexposure ( gspca_dev ,
( unsigned int ) ( expotimes < < 8 ) ) ;
break ;
case SENSOR_MO4000 :
case SENSOR_MI0360 :
expotimes = sd - > exposure ;
expotimes + = ( luma_mean - delta ) > > 6 ;
if ( expotimes < 0 )
expotimes = 0 ;
sd - > exposure = setexposure ( gspca_dev ,
( unsigned int ) expotimes ) ;
setcolors ( gspca_dev ) ;
break ;
}
}
}
static void sd_pkt_scan ( struct gspca_dev * gspca_dev ,
struct gspca_frame * frame , /* target */
2008-07-04 18:16:16 +04:00
__u8 * data , /* isoc packet */
2008-06-30 22:50:11 +04:00
int len ) /* iso packet length */
{
struct sd * sd = ( struct sd * ) gspca_dev ;
int sof , avg_lum ;
sof = len - 64 ;
if ( sof > = 0 & & data [ sof ] = = 0xff & & data [ sof + 1 ] = = 0xd9 ) {
/* end of frame */
gspca_frame_add ( gspca_dev , LAST_PACKET ,
frame , data , sof + 2 ) ;
if ( sd - > ag_cnt < 0 )
return ;
if ( - - sd - > ag_cnt > = 0 )
return ;
sd - > ag_cnt = AG_CNT_START ;
/* w1 w2 w3 */
/* w4 w5 w6 */
/* w7 w8 */
/* w4 */
avg_lum = ( ( data [ sof + 29 ] < < 8 ) | data [ sof + 30 ] ) > > 6 ;
/* w6 */
avg_lum + = ( ( data [ sof + 33 ] < < 8 ) | data [ sof + 34 ] ) > > 6 ;
/* w2 */
avg_lum + = ( ( data [ sof + 25 ] < < 8 ) | data [ sof + 26 ] ) > > 6 ;
/* w8 */
avg_lum + = ( ( data [ sof + 37 ] < < 8 ) | data [ sof + 38 ] ) > > 6 ;
/* w5 */
avg_lum + = ( ( data [ sof + 31 ] < < 8 ) | data [ sof + 32 ] ) > > 4 ;
avg_lum > > = 4 ;
sd - > avg_lum = avg_lum ;
PDEBUG ( D_PACK , " mean lum %d " , avg_lum ) ;
setautogain ( gspca_dev ) ;
return ;
}
if ( gspca_dev - > last_packet_type = = LAST_PACKET ) {
/* put the JPEG 422 header */
jpeg_put_header ( gspca_dev , frame , sd - > qindex , 0x21 ) ;
}
gspca_frame_add ( gspca_dev , INTER_PACKET , frame , data , len ) ;
}
static unsigned int getexposure ( struct gspca_dev * gspca_dev )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
__u8 hexpo , mexpo , lexpo ;
switch ( sd - > sensor ) {
case SENSOR_HV7131R :
/* read sensor exposure */
2008-07-14 16:38:29 +04:00
i2c_r5 ( gspca_dev , 0x25 ) ;
return ( gspca_dev - > usb_buf [ 0 ] < < 16 )
| ( gspca_dev - > usb_buf [ 1 ] < < 8 )
| gspca_dev - > usb_buf [ 2 ] ;
2008-06-30 22:50:11 +04:00
case SENSOR_MI0360 :
/* read sensor exposure */
2008-07-14 16:38:29 +04:00
i2c_r5 ( gspca_dev , 0x09 ) ;
return ( gspca_dev - > usb_buf [ 0 ] < < 8 )
| gspca_dev - > usb_buf [ 1 ] ;
2008-06-30 22:50:11 +04:00
case SENSOR_MO4000 :
2008-07-14 16:38:29 +04:00
i2c_r5 ( gspca_dev , 0x0e ) ;
hexpo = 0 ; /* gspca_dev->usb_buf[1] & 0x07; */
mexpo = 0x40 ; /* gspca_dev->usb_buf[2] & 0xff; */
lexpo = ( gspca_dev - > usb_buf [ 1 ] & 0x30 ) > > 4 ;
2008-06-30 22:50:11 +04:00
PDEBUG ( D_CONF , " exposure %d " ,
( hexpo < < 10 ) | ( mexpo < < 2 ) | lexpo ) ;
return ( hexpo < < 10 ) | ( mexpo < < 2 ) | lexpo ;
default :
/* case SENSOR_OV7660: */
/* read sensor exposure */
2008-07-14 16:38:29 +04:00
i2c_r5 ( gspca_dev , 0x04 ) ;
hexpo = gspca_dev - > usb_buf [ 3 ] & 0x2f ;
lexpo = gspca_dev - > usb_buf [ 0 ] & 0x02 ;
i2c_r5 ( gspca_dev , 0x08 ) ;
mexpo = gspca_dev - > usb_buf [ 2 ] ;
2008-06-30 22:50:11 +04:00
return ( hexpo < < 10 ) | ( mexpo < < 2 ) | lexpo ;
}
}
static void getbrightness ( struct gspca_dev * gspca_dev )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
/* hardcoded registers seem not readable */
switch ( sd - > sensor ) {
case SENSOR_HV7131R :
/* sd->brightness = 0x7fff; */
sd - > brightness = getexposure ( gspca_dev ) > > 4 ;
break ;
case SENSOR_MI0360 :
sd - > brightness = getexposure ( gspca_dev ) < < 4 ;
break ;
case SENSOR_MO4000 :
/* sd->brightness = 0x1fff; */
sd - > brightness = getexposure ( gspca_dev ) < < 4 ;
break ;
}
}
static int sd_setbrightness ( struct gspca_dev * gspca_dev , __s32 val )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
sd - > brightness = val ;
if ( gspca_dev - > streaming )
setbrightness ( gspca_dev ) ;
return 0 ;
}
static int sd_getbrightness ( struct gspca_dev * gspca_dev , __s32 * val )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
getbrightness ( gspca_dev ) ;
* val = sd - > brightness ;
return 0 ;
}
static int sd_setcontrast ( struct gspca_dev * gspca_dev , __s32 val )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
sd - > contrast = val ;
if ( gspca_dev - > streaming )
setcontrast ( gspca_dev ) ;
return 0 ;
}
static int sd_getcontrast ( struct gspca_dev * gspca_dev , __s32 * val )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
* val = sd - > contrast ;
return 0 ;
}
static int sd_setcolors ( struct gspca_dev * gspca_dev , __s32 val )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
sd - > colors = val ;
if ( gspca_dev - > streaming )
setcolors ( gspca_dev ) ;
return 0 ;
}
static int sd_getcolors ( struct gspca_dev * gspca_dev , __s32 * val )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
* val = sd - > colors ;
return 0 ;
}
static int sd_setautogain ( struct gspca_dev * gspca_dev , __s32 val )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
sd - > autogain = val ;
if ( val )
sd - > ag_cnt = AG_CNT_START ;
else
sd - > ag_cnt = - 1 ;
return 0 ;
}
static int sd_getautogain ( struct gspca_dev * gspca_dev , __s32 * val )
{
struct sd * sd = ( struct sd * ) gspca_dev ;
* val = sd - > autogain ;
return 0 ;
}
/* sub-driver description */
2008-07-04 18:16:16 +04:00
static const struct sd_desc sd_desc = {
2008-06-30 22:50:11 +04:00
. name = MODULE_NAME ,
. ctrls = sd_ctrls ,
. nctrls = ARRAY_SIZE ( sd_ctrls ) ,
. config = sd_config ,
. open = sd_open ,
. start = sd_start ,
. stopN = sd_stopN ,
. stop0 = sd_stop0 ,
. close = sd_close ,
. pkt_scan = sd_pkt_scan ,
} ;
/* -- module initialisation -- */
# define DVNM(name) .driver_info = (kernel_ulong_t) name
2008-07-04 18:16:16 +04:00
static const __devinitdata struct usb_device_id device_table [ ] = {
2008-07-07 15:31:16 +04:00
# ifndef CONFIG_USB_SN9C102
2008-06-30 22:50:11 +04:00
{ USB_DEVICE ( 0x0458 , 0x7025 ) , DVNM ( " Genius Eye 311Q " ) } ,
{ USB_DEVICE ( 0x045e , 0x00f5 ) , DVNM ( " MicroSoft VX3000 " ) } ,
{ USB_DEVICE ( 0x045e , 0x00f7 ) , DVNM ( " MicroSoft VX1000 " ) } ,
{ USB_DEVICE ( 0x0471 , 0x0327 ) , DVNM ( " Philips SPC 600 NC " ) } ,
{ USB_DEVICE ( 0x0471 , 0x0328 ) , DVNM ( " Philips SPC 700 NC " ) } ,
2008-07-07 15:31:16 +04:00
# endif
2008-06-30 22:50:11 +04:00
{ USB_DEVICE ( 0x0471 , 0x0330 ) , DVNM ( " Philips SPC 710NC " ) } ,
{ USB_DEVICE ( 0x0c45 , 0x6040 ) , DVNM ( " Speed NVC 350K " ) } ,
{ USB_DEVICE ( 0x0c45 , 0x607c ) , DVNM ( " Sonix sn9c102p Hv7131R " ) } ,
{ USB_DEVICE ( 0x0c45 , 0x60c0 ) , DVNM ( " Sangha Sn535 " ) } ,
{ USB_DEVICE ( 0x0c45 , 0x60ec ) , DVNM ( " SN9C105+MO4000 " ) } ,
{ USB_DEVICE ( 0x0c45 , 0x60fb ) , DVNM ( " Surfer NoName " ) } ,
{ USB_DEVICE ( 0x0c45 , 0x60fc ) , DVNM ( " LG-LIC300 " ) } ,
{ USB_DEVICE ( 0x0c45 , 0x612a ) , DVNM ( " Avant Camera " ) } ,
{ USB_DEVICE ( 0x0c45 , 0x612c ) , DVNM ( " Typhoon Rasy Cam 1.3MPix " ) } ,
2008-07-07 15:31:16 +04:00
# ifndef CONFIG_USB_SN9C102
2008-06-30 22:50:11 +04:00
{ USB_DEVICE ( 0x0c45 , 0x6130 ) , DVNM ( " Sonix Pccam " ) } ,
{ USB_DEVICE ( 0x0c45 , 0x6138 ) , DVNM ( " Sn9c120 Mo4000 " ) } ,
{ USB_DEVICE ( 0x0c45 , 0x613b ) , DVNM ( " Surfer SN-206 " ) } ,
{ USB_DEVICE ( 0x0c45 , 0x613c ) , DVNM ( " Sonix Pccam168 " ) } ,
2008-07-07 15:31:16 +04:00
# endif
2008-06-30 22:50:11 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( usb , device_table ) ;
/* -- device connect -- */
static int sd_probe ( struct usb_interface * intf ,
const struct usb_device_id * id )
{
return gspca_dev_probe ( intf , id , & sd_desc , sizeof ( struct sd ) ,
THIS_MODULE ) ;
}
static struct usb_driver sd_driver = {
. name = MODULE_NAME ,
. id_table = device_table ,
. probe = sd_probe ,
. disconnect = gspca_disconnect ,
} ;
/* -- module insert / remove -- */
static int __init sd_mod_init ( void )
{
if ( usb_register ( & sd_driver ) < 0 )
return - 1 ;
info ( " v%s registered " , version ) ;
return 0 ;
}
static void __exit sd_mod_exit ( void )
{
usb_deregister ( & sd_driver ) ;
info ( " deregistered " ) ;
}
module_init ( sd_mod_init ) ;
module_exit ( sd_mod_exit ) ;