2008-06-30 22:50:11 +04:00
/*
* SPCA505 chip based cameras initialization data
*
* V4L2 by Jean - Francis 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
*
*/
2011-08-22 02:56:57 +04:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2008-06-30 22:50:11 +04:00
# define MODULE_NAME "spca505"
# include "gspca.h"
MODULE_AUTHOR ( " Michel Xhaard <mxhaard@users.sourceforge.net> " ) ;
MODULE_DESCRIPTION ( " GSPCA/SPCA505 USB Camera Driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev ; /* !! must be the first item */
2009-01-22 20:56:42 +03:00
u8 subtype ;
2008-06-30 22:50:11 +04:00
# define IntelPCCameraPro 0
# define Nxultra 1
} ;
2008-12-29 13:49:41 +03:00
static const struct v4l2_pix_format vga_mode [ ] = {
2008-07-26 15:02:47 +04:00
{ 160 , 120 , V4L2_PIX_FMT_SPCA505 , V4L2_FIELD_NONE ,
2008-07-30 12:47:54 +04:00
. bytesperline = 160 ,
2008-07-26 15:02:47 +04:00
. sizeimage = 160 * 120 * 3 / 2 ,
2008-07-05 18:49:20 +04:00
. colorspace = V4L2_COLORSPACE_SRGB ,
2009-01-23 20:42:03 +03:00
. priv = 4 } ,
2008-07-26 15:02:47 +04:00
{ 176 , 144 , V4L2_PIX_FMT_SPCA505 , V4L2_FIELD_NONE ,
2008-07-30 12:47:54 +04:00
. bytesperline = 176 ,
2008-07-26 15:02:47 +04:00
. sizeimage = 176 * 144 * 3 / 2 ,
2008-07-05 18:49:20 +04:00
. colorspace = V4L2_COLORSPACE_SRGB ,
2009-01-23 20:42:03 +03:00
. priv = 3 } ,
2008-07-26 15:02:47 +04:00
{ 320 , 240 , V4L2_PIX_FMT_SPCA505 , V4L2_FIELD_NONE ,
2008-07-30 12:47:54 +04:00
. bytesperline = 320 ,
2008-07-26 15:02:47 +04:00
. sizeimage = 320 * 240 * 3 / 2 ,
2008-07-05 18:49:20 +04:00
. colorspace = V4L2_COLORSPACE_SRGB ,
. priv = 2 } ,
2008-07-26 15:02:47 +04:00
{ 352 , 288 , V4L2_PIX_FMT_SPCA505 , V4L2_FIELD_NONE ,
2008-07-30 12:47:54 +04:00
. bytesperline = 352 ,
2008-07-26 15:02:47 +04:00
. sizeimage = 352 * 288 * 3 / 2 ,
2008-07-05 18:49:20 +04:00
. colorspace = V4L2_COLORSPACE_SRGB ,
. priv = 1 } ,
2008-07-26 15:02:47 +04:00
{ 640 , 480 , V4L2_PIX_FMT_SPCA505 , V4L2_FIELD_NONE ,
2008-07-30 12:47:54 +04:00
. bytesperline = 640 ,
2008-07-26 15:02:47 +04:00
. sizeimage = 640 * 480 * 3 / 2 ,
2008-07-05 18:49:20 +04:00
. colorspace = V4L2_COLORSPACE_SRGB ,
. priv = 0 } ,
2008-06-30 22:50:11 +04:00
} ;
# define SPCA50X_OFFSET_DATA 10
# define SPCA50X_REG_USB 0x02 /* spca505 501 */
# define SPCA50X_USB_CTRL 0x00 /* spca505 */
# define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
2009-01-23 20:42:03 +03:00
2008-06-30 22:50:11 +04:00
# define SPCA50X_REG_GLOBAL 0x03 /* spca505 */
# define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
# define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
# define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
# define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
# define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */
2009-01-23 20:42:03 +03:00
/* Image format and compression control */
# define SPCA50X_REG_COMPRESS 0x04
2008-06-30 22:50:11 +04:00
/*
* Data to initialize a SPCA505 . Common to the CCD and external modes
*/
2009-01-22 20:56:42 +03:00
static const u8 spca505_init_data [ ] [ 3 ] = {
/* bmRequest,value,index */
2008-06-30 22:50:11 +04:00
{ SPCA50X_REG_GLOBAL , SPCA50X_GMISC3_SAA7113RST , SPCA50X_GLOBAL_MISC3 } ,
/* Sensor reset */
2009-01-22 20:56:42 +03:00
{ SPCA50X_REG_GLOBAL , 0x00 , SPCA50X_GLOBAL_MISC3 } ,
{ SPCA50X_REG_GLOBAL , 0x00 , SPCA50X_GLOBAL_MISC1 } ,
2008-06-30 22:50:11 +04:00
/* Block USB reset */
2009-01-22 20:56:42 +03:00
{ SPCA50X_REG_GLOBAL , SPCA50X_GMISC0_IDSEL , SPCA50X_GLOBAL_MISC0 } ,
2008-06-30 22:50:11 +04:00
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x01 , 0x10 } ,
2008-06-30 22:50:11 +04:00
/* Maybe power down some stuff */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x0f , 0x11 } ,
2008-06-30 22:50:11 +04:00
/* Setup internal CCD ? */
2009-01-22 20:56:42 +03:00
{ 0x06 , 0x10 , 0x08 } ,
{ 0x06 , 0x00 , 0x09 } ,
{ 0x06 , 0x00 , 0x0a } ,
{ 0x06 , 0x00 , 0x0b } ,
{ 0x06 , 0x10 , 0x0c } ,
{ 0x06 , 0x00 , 0x0d } ,
{ 0x06 , 0x00 , 0x0e } ,
{ 0x06 , 0x00 , 0x0f } ,
{ 0x06 , 0x10 , 0x10 } ,
{ 0x06 , 0x02 , 0x11 } ,
{ 0x06 , 0x00 , 0x12 } ,
{ 0x06 , 0x04 , 0x13 } ,
{ 0x06 , 0x02 , 0x14 } ,
{ 0x06 , 0x8a , 0x51 } ,
{ 0x06 , 0x40 , 0x52 } ,
{ 0x06 , 0xb6 , 0x53 } ,
{ 0x06 , 0x3d , 0x54 } ,
2008-06-30 22:50:11 +04:00
{ }
} ;
/*
* Data to initialize the camera using the internal CCD
*/
2009-01-22 20:56:42 +03:00
static const u8 spca505_open_data_ccd [ ] [ 3 ] = {
/* bmRequest,value,index */
2008-06-30 22:50:11 +04:00
/* Internal CCD data set */
2009-01-22 20:56:42 +03:00
{ 0x03 , 0x04 , 0x01 } ,
2008-06-30 22:50:11 +04:00
/* This could be a reset */
2009-01-22 20:56:42 +03:00
{ 0x03 , 0x00 , 0x01 } ,
2008-06-30 22:50:11 +04:00
/* Setup compression and image registers. 0x6 and 0x7 seem to be
related to H & V hold , and are resolution mode specific */
2009-01-22 20:56:42 +03:00
{ 0x04 , 0x10 , 0x01 } ,
2008-06-30 22:50:11 +04:00
/* DIFF(0x50), was (0x10) */
2009-01-22 20:56:42 +03:00
{ 0x04 , 0x00 , 0x04 } ,
{ 0x04 , 0x00 , 0x05 } ,
{ 0x04 , 0x20 , 0x06 } ,
{ 0x04 , 0x20 , 0x07 } ,
2008-06-30 22:50:11 +04:00
2009-01-22 20:56:42 +03:00
{ 0x08 , 0x0a , 0x00 } ,
2008-06-30 22:50:11 +04:00
/* DIFF (0x4a), was (0xa) */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x00 , 0x10 } ,
{ 0x05 , 0x00 , 0x11 } ,
{ 0x05 , 0x00 , 0x00 } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x00 , 0x01 } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x00 , 0x02 } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x00 , 0x03 } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x00 , 0x04 } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x80 , 0x05 } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0xe0 , 0x06 } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x20 , 0x07 } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0xa0 , 0x08 } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x0 , 0x12 } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x02 , 0x0f } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x10 , 0x46 } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x8 , 0x4a } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x03 , 0x08 , 0x03 } ,
2008-06-30 22:50:11 +04:00
/* DIFF (0x3,0x28,0x3) */
2009-01-22 20:56:42 +03:00
{ 0x03 , 0x08 , 0x01 } ,
{ 0x03 , 0x0c , 0x03 } ,
2008-06-30 22:50:11 +04:00
/* DIFF not written */
2009-01-22 20:56:42 +03:00
{ 0x03 , 0x21 , 0x00 } ,
2008-06-30 22:50:11 +04:00
/* DIFF (0x39) */
/* Extra block copied from init to hopefully ensure CCD is in a sane state */
2009-01-22 20:56:42 +03:00
{ 0x06 , 0x10 , 0x08 } ,
{ 0x06 , 0x00 , 0x09 } ,
{ 0x06 , 0x00 , 0x0a } ,
{ 0x06 , 0x00 , 0x0b } ,
{ 0x06 , 0x10 , 0x0c } ,
{ 0x06 , 0x00 , 0x0d } ,
{ 0x06 , 0x00 , 0x0e } ,
{ 0x06 , 0x00 , 0x0f } ,
{ 0x06 , 0x10 , 0x10 } ,
{ 0x06 , 0x02 , 0x11 } ,
{ 0x06 , 0x00 , 0x12 } ,
{ 0x06 , 0x04 , 0x13 } ,
{ 0x06 , 0x02 , 0x14 } ,
{ 0x06 , 0x8a , 0x51 } ,
{ 0x06 , 0x40 , 0x52 } ,
{ 0x06 , 0xb6 , 0x53 } ,
{ 0x06 , 0x3d , 0x54 } ,
2008-06-30 22:50:11 +04:00
/* End of extra block */
2009-01-22 20:56:42 +03:00
{ 0x06 , 0x3f , 0x1 } ,
2008-06-30 22:50:11 +04:00
/* Block skipped */
2009-01-22 20:56:42 +03:00
{ 0x06 , 0x10 , 0x02 } ,
{ 0x06 , 0x64 , 0x07 } ,
{ 0x06 , 0x10 , 0x08 } ,
{ 0x06 , 0x00 , 0x09 } ,
{ 0x06 , 0x00 , 0x0a } ,
{ 0x06 , 0x00 , 0x0b } ,
{ 0x06 , 0x10 , 0x0c } ,
{ 0x06 , 0x00 , 0x0d } ,
{ 0x06 , 0x00 , 0x0e } ,
{ 0x06 , 0x00 , 0x0f } ,
{ 0x06 , 0x10 , 0x10 } ,
{ 0x06 , 0x02 , 0x11 } ,
{ 0x06 , 0x00 , 0x12 } ,
{ 0x06 , 0x04 , 0x13 } ,
{ 0x06 , 0x02 , 0x14 } ,
{ 0x06 , 0x8a , 0x51 } ,
{ 0x06 , 0x40 , 0x52 } ,
{ 0x06 , 0xb6 , 0x53 } ,
{ 0x06 , 0x3d , 0x54 } ,
{ 0x06 , 0x60 , 0x57 } ,
{ 0x06 , 0x20 , 0x58 } ,
{ 0x06 , 0x15 , 0x59 } ,
{ 0x06 , 0x05 , 0x5a } ,
{ 0x05 , 0x01 , 0xc0 } ,
{ 0x05 , 0x10 , 0xcb } ,
{ 0x05 , 0x80 , 0xc1 } ,
2008-06-30 22:50:11 +04:00
/* */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x0 , 0xc2 } ,
2008-06-30 22:50:11 +04:00
/* 4 was 0 */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x00 , 0xca } ,
{ 0x05 , 0x80 , 0xc1 } ,
2008-06-30 22:50:11 +04:00
/* */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x04 , 0xc2 } ,
{ 0x05 , 0x00 , 0xca } ,
{ 0x05 , 0x0 , 0xc1 } ,
2008-06-30 22:50:11 +04:00
/* */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x00 , 0xc2 } ,
{ 0x05 , 0x00 , 0xca } ,
{ 0x05 , 0x40 , 0xc1 } ,
2008-06-30 22:50:11 +04:00
/* */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x17 , 0xc2 } ,
{ 0x05 , 0x00 , 0xca } ,
{ 0x05 , 0x80 , 0xc1 } ,
2008-06-30 22:50:11 +04:00
/* */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x06 , 0xc2 } ,
{ 0x05 , 0x00 , 0xca } ,
{ 0x05 , 0x80 , 0xc1 } ,
2008-06-30 22:50:11 +04:00
/* */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x04 , 0xc2 } ,
{ 0x05 , 0x00 , 0xca } ,
2008-06-30 22:50:11 +04:00
2009-01-22 20:56:42 +03:00
{ 0x03 , 0x4c , 0x3 } ,
{ 0x03 , 0x18 , 0x1 } ,
2008-06-30 22:50:11 +04:00
2009-01-22 20:56:42 +03:00
{ 0x06 , 0x70 , 0x51 } ,
{ 0x06 , 0xbe , 0x53 } ,
{ 0x06 , 0x71 , 0x57 } ,
{ 0x06 , 0x20 , 0x58 } ,
{ 0x06 , 0x05 , 0x59 } ,
{ 0x06 , 0x15 , 0x5a } ,
2008-06-30 22:50:11 +04:00
2009-01-22 20:56:42 +03:00
{ 0x04 , 0x00 , 0x08 } ,
2008-06-30 22:50:11 +04:00
/* Compress = OFF (0x1 to turn on) */
2009-01-22 20:56:42 +03:00
{ 0x04 , 0x12 , 0x09 } ,
{ 0x04 , 0x21 , 0x0a } ,
{ 0x04 , 0x10 , 0x0b } ,
{ 0x04 , 0x21 , 0x0c } ,
{ 0x04 , 0x05 , 0x00 } ,
2008-06-30 22:50:11 +04:00
/* was 5 (Image Type ? ) */
2009-01-22 20:56:42 +03:00
{ 0x04 , 0x00 , 0x01 } ,
{ 0x06 , 0x3f , 0x01 } ,
{ 0x04 , 0x00 , 0x04 } ,
{ 0x04 , 0x00 , 0x05 } ,
{ 0x04 , 0x40 , 0x06 } ,
{ 0x04 , 0x40 , 0x07 } ,
{ 0x06 , 0x1c , 0x17 } ,
{ 0x06 , 0xe2 , 0x19 } ,
{ 0x06 , 0x1c , 0x1b } ,
{ 0x06 , 0xe2 , 0x1d } ,
{ 0x06 , 0xaa , 0x1f } ,
{ 0x06 , 0x70 , 0x20 } ,
{ 0x05 , 0x01 , 0x10 } ,
{ 0x05 , 0x00 , 0x11 } ,
{ 0x05 , 0x01 , 0x00 } ,
{ 0x05 , 0x05 , 0x01 } ,
{ 0x05 , 0x00 , 0xc1 } ,
2008-06-30 22:50:11 +04:00
/* */
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x00 , 0xc2 } ,
{ 0x05 , 0x00 , 0xca } ,
2008-06-30 22:50:11 +04:00
2009-01-22 20:56:42 +03:00
{ 0x06 , 0x70 , 0x51 } ,
{ 0x06 , 0xbe , 0x53 } ,
2008-06-30 22:50:11 +04:00
{ }
} ;
/*
2009-01-22 20:56:42 +03:00
* Made by Tomasz Zablocki ( skalamandra @ poczta . onet . pl )
2008-06-30 22:50:11 +04:00
* SPCA505b chip based cameras initialization data
*/
/* jfm */
# define initial_brightness 0x7f /* 0x0(white)-0xff(black) */
/* #define initial_brightness 0x0 //0x0(white)-0xff(black) */
/*
* Data to initialize a SPCA505 . Common to the CCD and external modes
*/
2009-01-22 20:56:42 +03:00
static const u8 spca505b_init_data [ ] [ 3 ] = {
2008-06-30 22:50:11 +04:00
/* start */
{ 0x02 , 0x00 , 0x00 } , /* init */
{ 0x02 , 0x00 , 0x01 } ,
{ 0x02 , 0x00 , 0x02 } ,
{ 0x02 , 0x00 , 0x03 } ,
{ 0x02 , 0x00 , 0x04 } ,
{ 0x02 , 0x00 , 0x05 } ,
{ 0x02 , 0x00 , 0x06 } ,
{ 0x02 , 0x00 , 0x07 } ,
{ 0x02 , 0x00 , 0x08 } ,
{ 0x02 , 0x00 , 0x09 } ,
{ 0x03 , 0x00 , 0x00 } ,
{ 0x03 , 0x00 , 0x01 } ,
{ 0x03 , 0x00 , 0x02 } ,
{ 0x03 , 0x00 , 0x03 } ,
{ 0x03 , 0x00 , 0x04 } ,
{ 0x03 , 0x00 , 0x05 } ,
{ 0x03 , 0x00 , 0x06 } ,
{ 0x04 , 0x00 , 0x00 } ,
{ 0x04 , 0x00 , 0x02 } ,
{ 0x04 , 0x00 , 0x04 } ,
{ 0x04 , 0x00 , 0x05 } ,
{ 0x04 , 0x00 , 0x06 } ,
{ 0x04 , 0x00 , 0x07 } ,
{ 0x04 , 0x00 , 0x08 } ,
{ 0x04 , 0x00 , 0x09 } ,
{ 0x04 , 0x00 , 0x0a } ,
{ 0x04 , 0x00 , 0x0b } ,
{ 0x04 , 0x00 , 0x0c } ,
{ 0x07 , 0x00 , 0x00 } ,
{ 0x07 , 0x00 , 0x03 } ,
{ 0x08 , 0x00 , 0x00 } ,
{ 0x08 , 0x00 , 0x01 } ,
{ 0x08 , 0x00 , 0x02 } ,
{ 0x06 , 0x18 , 0x08 } ,
{ 0x06 , 0xfc , 0x09 } ,
{ 0x06 , 0xfc , 0x0a } ,
{ 0x06 , 0xfc , 0x0b } ,
{ 0x06 , 0x18 , 0x0c } ,
{ 0x06 , 0xfc , 0x0d } ,
{ 0x06 , 0xfc , 0x0e } ,
{ 0x06 , 0xfc , 0x0f } ,
{ 0x06 , 0x18 , 0x10 } ,
{ 0x06 , 0xfe , 0x12 } ,
{ 0x06 , 0x00 , 0x11 } ,
{ 0x06 , 0x00 , 0x14 } ,
{ 0x06 , 0x00 , 0x13 } ,
{ 0x06 , 0x28 , 0x51 } ,
{ 0x06 , 0xff , 0x53 } ,
{ 0x02 , 0x00 , 0x08 } ,
{ 0x03 , 0x00 , 0x03 } ,
{ 0x03 , 0x10 , 0x03 } ,
{ }
} ;
/*
* Data to initialize the camera using the internal CCD
*/
2009-01-22 20:56:42 +03:00
static const u8 spca505b_open_data_ccd [ ] [ 3 ] = {
2008-06-30 22:50:11 +04:00
/* {0x02,0x00,0x00}, */
{ 0x03 , 0x04 , 0x01 } , /* rst */
{ 0x03 , 0x00 , 0x01 } ,
{ 0x03 , 0x00 , 0x00 } ,
{ 0x03 , 0x21 , 0x00 } ,
{ 0x03 , 0x00 , 0x04 } ,
{ 0x03 , 0x00 , 0x03 } ,
{ 0x03 , 0x18 , 0x03 } ,
{ 0x03 , 0x08 , 0x01 } ,
{ 0x03 , 0x1c , 0x03 } ,
{ 0x03 , 0x5c , 0x03 } ,
{ 0x03 , 0x5c , 0x03 } ,
{ 0x03 , 0x18 , 0x01 } ,
/* same as 505 */
{ 0x04 , 0x10 , 0x01 } ,
{ 0x04 , 0x00 , 0x04 } ,
{ 0x04 , 0x00 , 0x05 } ,
{ 0x04 , 0x20 , 0x06 } ,
{ 0x04 , 0x20 , 0x07 } ,
{ 0x08 , 0x0a , 0x00 } ,
{ 0x05 , 0x00 , 0x10 } ,
{ 0x05 , 0x00 , 0x11 } ,
{ 0x05 , 0x00 , 0x12 } ,
{ 0x05 , 0x6f , 0x00 } ,
2009-02-02 22:25:38 +03:00
{ 0x05 , initial_brightness > > 6 , 0x00 } ,
{ 0x05 , ( initial_brightness < < 2 ) & 0xff , 0x01 } ,
2008-06-30 22:50:11 +04:00
{ 0x05 , 0x00 , 0x02 } ,
{ 0x05 , 0x01 , 0x03 } ,
{ 0x05 , 0x00 , 0x04 } ,
{ 0x05 , 0x03 , 0x05 } ,
{ 0x05 , 0xe0 , 0x06 } ,
{ 0x05 , 0x20 , 0x07 } ,
{ 0x05 , 0xa0 , 0x08 } ,
{ 0x05 , 0x00 , 0x12 } ,
{ 0x05 , 0x02 , 0x0f } ,
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x80 , 0x14 } , /* max exposure off (0=on) */
2008-06-30 22:50:11 +04:00
{ 0x05 , 0x01 , 0xb0 } ,
{ 0x05 , 0x01 , 0xbf } ,
{ 0x03 , 0x02 , 0x06 } ,
{ 0x05 , 0x10 , 0x46 } ,
{ 0x05 , 0x08 , 0x4a } ,
{ 0x06 , 0x00 , 0x01 } ,
{ 0x06 , 0x10 , 0x02 } ,
{ 0x06 , 0x64 , 0x07 } ,
{ 0x06 , 0x18 , 0x08 } ,
{ 0x06 , 0xfc , 0x09 } ,
{ 0x06 , 0xfc , 0x0a } ,
{ 0x06 , 0xfc , 0x0b } ,
{ 0x04 , 0x00 , 0x01 } ,
{ 0x06 , 0x18 , 0x0c } ,
{ 0x06 , 0xfc , 0x0d } ,
{ 0x06 , 0xfc , 0x0e } ,
{ 0x06 , 0xfc , 0x0f } ,
{ 0x06 , 0x11 , 0x10 } , /* contrast */
{ 0x06 , 0x00 , 0x11 } ,
{ 0x06 , 0xfe , 0x12 } ,
{ 0x06 , 0x00 , 0x13 } ,
{ 0x06 , 0x00 , 0x14 } ,
{ 0x06 , 0x9d , 0x51 } ,
{ 0x06 , 0x40 , 0x52 } ,
{ 0x06 , 0x7c , 0x53 } ,
{ 0x06 , 0x40 , 0x54 } ,
{ 0x06 , 0x02 , 0x57 } ,
{ 0x06 , 0x03 , 0x58 } ,
{ 0x06 , 0x15 , 0x59 } ,
{ 0x06 , 0x05 , 0x5a } ,
{ 0x06 , 0x03 , 0x56 } ,
{ 0x06 , 0x02 , 0x3f } ,
{ 0x06 , 0x00 , 0x40 } ,
{ 0x06 , 0x39 , 0x41 } ,
{ 0x06 , 0x69 , 0x42 } ,
{ 0x06 , 0x87 , 0x43 } ,
{ 0x06 , 0x9e , 0x44 } ,
{ 0x06 , 0xb1 , 0x45 } ,
{ 0x06 , 0xbf , 0x46 } ,
{ 0x06 , 0xcc , 0x47 } ,
{ 0x06 , 0xd5 , 0x48 } ,
{ 0x06 , 0xdd , 0x49 } ,
{ 0x06 , 0xe3 , 0x4a } ,
{ 0x06 , 0xe8 , 0x4b } ,
{ 0x06 , 0xed , 0x4c } ,
{ 0x06 , 0xf2 , 0x4d } ,
{ 0x06 , 0xf7 , 0x4e } ,
{ 0x06 , 0xfc , 0x4f } ,
{ 0x06 , 0xff , 0x50 } ,
{ 0x05 , 0x01 , 0xc0 } ,
{ 0x05 , 0x10 , 0xcb } ,
{ 0x05 , 0x40 , 0xc1 } ,
{ 0x05 , 0x04 , 0xc2 } ,
{ 0x05 , 0x00 , 0xca } ,
{ 0x05 , 0x40 , 0xc1 } ,
{ 0x05 , 0x09 , 0xc2 } ,
{ 0x05 , 0x00 , 0xca } ,
{ 0x05 , 0xc0 , 0xc1 } ,
{ 0x05 , 0x09 , 0xc2 } ,
{ 0x05 , 0x00 , 0xca } ,
{ 0x05 , 0x40 , 0xc1 } ,
{ 0x05 , 0x59 , 0xc2 } ,
{ 0x05 , 0x00 , 0xca } ,
{ 0x04 , 0x00 , 0x01 } ,
{ 0x05 , 0x80 , 0xc1 } ,
{ 0x05 , 0xec , 0xc2 } ,
{ 0x05 , 0x0 , 0xca } ,
{ 0x06 , 0x02 , 0x57 } ,
{ 0x06 , 0x01 , 0x58 } ,
{ 0x06 , 0x15 , 0x59 } ,
{ 0x06 , 0x0a , 0x5a } ,
{ 0x06 , 0x01 , 0x57 } ,
{ 0x06 , 0x8a , 0x03 } ,
{ 0x06 , 0x0a , 0x6c } ,
{ 0x06 , 0x30 , 0x01 } ,
{ 0x06 , 0x20 , 0x02 } ,
{ 0x06 , 0x00 , 0x03 } ,
{ 0x05 , 0x8c , 0x25 } ,
{ 0x06 , 0x4d , 0x51 } , /* maybe saturation (4d) */
{ 0x06 , 0x84 , 0x53 } , /* making green (84) */
{ 0x06 , 0x00 , 0x57 } , /* sharpness (1) */
{ 0x06 , 0x18 , 0x08 } ,
{ 0x06 , 0xfc , 0x09 } ,
{ 0x06 , 0xfc , 0x0a } ,
{ 0x06 , 0xfc , 0x0b } ,
{ 0x06 , 0x18 , 0x0c } , /* maybe hue (18) */
{ 0x06 , 0xfc , 0x0d } ,
{ 0x06 , 0xfc , 0x0e } ,
{ 0x06 , 0xfc , 0x0f } ,
{ 0x06 , 0x18 , 0x10 } , /* maybe contrast (18) */
{ 0x05 , 0x01 , 0x02 } ,
{ 0x04 , 0x00 , 0x08 } , /* compression */
{ 0x04 , 0x12 , 0x09 } ,
{ 0x04 , 0x21 , 0x0a } ,
{ 0x04 , 0x10 , 0x0b } ,
{ 0x04 , 0x21 , 0x0c } ,
{ 0x04 , 0x1d , 0x00 } , /* imagetype (1d) */
{ 0x04 , 0x41 , 0x01 } , /* hardware snapcontrol */
{ 0x04 , 0x00 , 0x04 } ,
{ 0x04 , 0x00 , 0x05 } ,
{ 0x04 , 0x10 , 0x06 } ,
{ 0x04 , 0x10 , 0x07 } ,
{ 0x04 , 0x40 , 0x06 } ,
{ 0x04 , 0x40 , 0x07 } ,
{ 0x04 , 0x00 , 0x04 } ,
{ 0x04 , 0x00 , 0x05 } ,
{ 0x06 , 0x1c , 0x17 } ,
{ 0x06 , 0xe2 , 0x19 } ,
{ 0x06 , 0x1c , 0x1b } ,
{ 0x06 , 0xe2 , 0x1d } ,
{ 0x06 , 0x5f , 0x1f } ,
{ 0x06 , 0x32 , 0x20 } ,
2009-02-02 22:25:38 +03:00
{ 0x05 , initial_brightness > > 6 , 0x00 } ,
{ 0x05 , ( initial_brightness < < 2 ) & 0xff , 0x01 } ,
2008-06-30 22:50:11 +04:00
{ 0x05 , 0x06 , 0xc1 } ,
{ 0x05 , 0x58 , 0xc2 } ,
2009-01-22 20:56:42 +03:00
{ 0x05 , 0x00 , 0xca } ,
{ 0x05 , 0x00 , 0x11 } ,
2008-06-30 22:50:11 +04:00
{ }
} ;
2013-02-04 20:17:55 +04:00
static int reg_write ( struct gspca_dev * gspca_dev ,
2009-01-22 20:56:42 +03:00
u16 req , u16 index , u16 value )
2008-06-30 22:50:11 +04:00
{
int ret ;
2013-02-04 20:17:55 +04:00
struct usb_device * dev = gspca_dev - > dev ;
2008-06-30 22:50:11 +04:00
ret = usb_control_msg ( dev ,
usb_sndctrlpipe ( dev , 0 ) ,
2009-01-22 20:56:42 +03:00
req ,
2008-06-30 22:50:11 +04:00
USB_TYPE_VENDOR | USB_RECIP_DEVICE ,
value , index , NULL , 0 , 500 ) ;
2009-01-22 20:56:42 +03:00
PDEBUG ( D_USBO , " reg write: 0x%02x,0x%02x:0x%02x, %d " ,
req , index , value , ret ) ;
2008-06-30 22:50:11 +04:00
if ( ret < 0 )
2011-08-22 02:56:57 +04:00
pr_err ( " reg write: error %d \n " , ret ) ;
2008-06-30 22:50:11 +04:00
return ret ;
}
/* returns: negative is error, pos or zero is data */
2008-07-14 16:38:29 +04:00
static int reg_read ( struct gspca_dev * gspca_dev ,
2009-01-22 20:56:42 +03:00
u16 req , /* bRequest */
u16 index ) /* wIndex */
2008-06-30 22:50:11 +04:00
{
int ret ;
2008-07-14 16:38:29 +04:00
ret = usb_control_msg ( gspca_dev - > dev ,
usb_rcvctrlpipe ( gspca_dev - > dev , 0 ) ,
2009-01-22 20:56:42 +03:00
req ,
2008-06-30 22:50:11 +04:00
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE ,
2009-01-22 20:56:42 +03:00
0 , /* value */
index ,
gspca_dev - > usb_buf , 2 ,
2008-06-30 22:50:11 +04:00
500 ) ; /* timeout */
2009-01-22 20:56:42 +03:00
if ( ret < 0 )
return ret ;
2008-07-14 16:38:29 +04:00
return ( gspca_dev - > usb_buf [ 1 ] < < 8 ) + gspca_dev - > usb_buf [ 0 ] ;
2008-06-30 22:50:11 +04:00
}
static int write_vector ( struct gspca_dev * gspca_dev ,
2009-01-22 20:56:42 +03:00
const u8 data [ ] [ 3 ] )
2008-06-30 22:50:11 +04:00
{
int ret , i = 0 ;
2009-01-22 20:56:42 +03:00
while ( data [ i ] [ 0 ] ! = 0 ) {
2013-02-04 20:17:55 +04:00
ret = reg_write ( gspca_dev , data [ i ] [ 0 ] , data [ i ] [ 2 ] ,
data [ i ] [ 1 ] ) ;
2009-01-22 20:56:42 +03:00
if ( ret < 0 )
2008-06-30 22:50:11 +04:00
return ret ;
i + + ;
}
return 0 ;
}
/* 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 ;
cam = & gspca_dev - > cam ;
cam - > cam_mode = vga_mode ;
2008-07-25 15:53:03 +04:00
sd - > subtype = id - > driver_info ;
2008-06-30 22:50:11 +04:00
if ( sd - > subtype ! = IntelPCCameraPro )
2009-01-22 20:56:42 +03:00
cam - > nmodes = ARRAY_SIZE ( vga_mode ) ;
2008-06-30 22:50:11 +04:00
else /* no 640x480 for IntelPCCameraPro */
2009-01-22 20:56:42 +03:00
cam - > nmodes = ARRAY_SIZE ( vga_mode ) - 1 ;
2008-06-30 22:50:11 +04:00
return 0 ;
}
2008-09-04 00:12:16 +04:00
/* this function is called at probe and resume time */
static int sd_init ( struct gspca_dev * gspca_dev )
2008-06-30 22:50:11 +04:00
{
2009-05-29 11:46:12 +04:00
struct sd * sd = ( struct sd * ) gspca_dev ;
if ( write_vector ( gspca_dev ,
sd - > subtype = = Nxultra
? spca505b_init_data
: spca505_init_data ) )
return - EIO ;
2008-06-30 22:50:11 +04:00
return 0 ;
}
2012-05-16 14:41:33 +04:00
static void setbrightness ( struct gspca_dev * gspca_dev , s32 brightness )
2009-01-23 20:42:03 +03:00
{
2013-02-04 20:17:55 +04:00
reg_write ( gspca_dev , 0x05 , 0x00 , ( 255 - brightness ) > > 6 ) ;
reg_write ( gspca_dev , 0x05 , 0x01 , ( 255 - brightness ) < < 2 ) ;
2009-01-23 20:42:03 +03:00
}
2008-09-20 13:39:08 +04:00
static int sd_start ( struct gspca_dev * gspca_dev )
2008-06-30 22:50:11 +04:00
{
2009-01-24 21:42:50 +03:00
struct sd * sd = ( struct sd * ) gspca_dev ;
2009-01-23 20:42:03 +03:00
int ret , mode ;
static u8 mode_tb [ ] [ 3 ] = {
/* r00 r06 r07 */
{ 0x00 , 0x10 , 0x10 } , /* 640x480 */
{ 0x01 , 0x1a , 0x1a } , /* 352x288 */
{ 0x02 , 0x1c , 0x1d } , /* 320x240 */
{ 0x04 , 0x34 , 0x34 } , /* 176x144 */
{ 0x05 , 0x40 , 0x40 } /* 160x120 */
} ;
2008-06-30 22:50:11 +04:00
2009-01-24 21:42:50 +03:00
if ( sd - > subtype = = Nxultra )
write_vector ( gspca_dev , spca505b_open_data_ccd ) ;
else
write_vector ( gspca_dev , spca505_open_data_ccd ) ;
ret = reg_read ( gspca_dev , 0x06 , 0x16 ) ;
if ( ret < 0 ) {
2013-02-04 20:17:55 +04:00
PERR ( " register read failed err: %d " , ret ) ;
2009-01-24 21:42:50 +03:00
return ret ;
}
if ( ret ! = 0x0101 ) {
2011-08-22 02:56:57 +04:00
pr_err ( " After vector read returns 0x%04x should be 0x0101 \n " ,
ret ) ;
2009-01-24 21:42:50 +03:00
}
2013-02-04 20:17:55 +04:00
ret = reg_write ( gspca_dev , 0x06 , 0x16 , 0x0a ) ;
2009-01-24 21:42:50 +03:00
if ( ret < 0 )
return ret ;
2013-02-04 20:17:55 +04:00
reg_write ( gspca_dev , 0x05 , 0xc2 , 0x12 ) ;
2009-01-24 21:42:50 +03:00
2008-06-30 22:50:11 +04:00
/* necessary because without it we can see stream
* only once after loading module */
/* stopping usb registers Tomasz change */
2013-02-04 20:17:55 +04:00
reg_write ( gspca_dev , 0x02 , 0x00 , 0x00 ) ;
2009-01-23 20:42:03 +03:00
mode = gspca_dev - > cam . cam_mode [ ( int ) gspca_dev - > curr_mode ] . priv ;
2013-02-04 20:17:55 +04:00
reg_write ( gspca_dev , SPCA50X_REG_COMPRESS , 0x00 , mode_tb [ mode ] [ 0 ] ) ;
reg_write ( gspca_dev , SPCA50X_REG_COMPRESS , 0x06 , mode_tb [ mode ] [ 1 ] ) ;
reg_write ( gspca_dev , SPCA50X_REG_COMPRESS , 0x07 , mode_tb [ mode ] [ 2 ] ) ;
2009-01-23 20:42:03 +03:00
2013-02-04 20:17:55 +04:00
return reg_write ( gspca_dev , SPCA50X_REG_USB ,
2008-06-30 22:50:11 +04:00
SPCA50X_USB_CTRL ,
SPCA50X_CUSB_ENABLE ) ;
}
static void sd_stopN ( struct gspca_dev * gspca_dev )
{
/* Disable ISO packet machine */
2013-02-04 20:17:55 +04:00
reg_write ( gspca_dev , 0x02 , 0x00 , 0x00 ) ;
2008-06-30 22:50:11 +04:00
}
2008-11-18 12:33:08 +03:00
/* called on streamoff with alt 0 and on disconnect */
2008-06-30 22:50:11 +04:00
static void sd_stop0 ( struct gspca_dev * gspca_dev )
{
2008-11-18 12:33:08 +03:00
if ( ! gspca_dev - > present )
return ;
2008-06-30 22:50:11 +04:00
/* This maybe reset or power control */
2013-02-04 20:17:55 +04:00
reg_write ( gspca_dev , 0x03 , 0x03 , 0x20 ) ;
reg_write ( gspca_dev , 0x03 , 0x01 , 0x00 ) ;
reg_write ( gspca_dev , 0x03 , 0x00 , 0x01 ) ;
reg_write ( gspca_dev , 0x05 , 0x10 , 0x01 ) ;
reg_write ( gspca_dev , 0x05 , 0x11 , 0x0f ) ;
2008-06-30 22:50:11 +04:00
}
static void sd_pkt_scan ( struct gspca_dev * gspca_dev ,
2009-01-22 20:56:42 +03:00
u8 * data , /* isoc packet */
2008-06-30 22:50:11 +04:00
int len ) /* iso packet length */
{
switch ( data [ 0 ] ) {
case 0 : /* start of frame */
2009-11-13 15:21:03 +03:00
gspca_frame_add ( gspca_dev , LAST_PACKET , NULL , 0 ) ;
2008-06-30 22:50:11 +04:00
data + = SPCA50X_OFFSET_DATA ;
len - = SPCA50X_OFFSET_DATA ;
2009-11-13 15:21:03 +03:00
gspca_frame_add ( gspca_dev , FIRST_PACKET , data , len ) ;
2008-07-26 15:02:47 +04:00
break ;
2008-06-30 22:50:11 +04:00
case 0xff : /* drop */
2008-07-26 15:02:47 +04:00
break ;
default :
data + = 1 ;
len - = 1 ;
2009-11-13 15:21:03 +03:00
gspca_frame_add ( gspca_dev , INTER_PACKET , data , len ) ;
2008-07-26 15:02:47 +04:00
break ;
2008-06-30 22:50:11 +04:00
}
}
2012-05-16 14:41:33 +04:00
static int sd_s_ctrl ( struct v4l2_ctrl * ctrl )
2008-06-30 22:50:11 +04:00
{
2012-05-16 14:41:33 +04:00
struct gspca_dev * gspca_dev =
container_of ( ctrl - > handler , struct gspca_dev , ctrl_handler ) ;
2008-06-30 22:50:11 +04:00
2012-05-16 14:41:33 +04:00
gspca_dev - > usb_err = 0 ;
if ( ! gspca_dev - > streaming )
return 0 ;
switch ( ctrl - > id ) {
case V4L2_CID_BRIGHTNESS :
setbrightness ( gspca_dev , ctrl - > val ) ;
break ;
}
return gspca_dev - > usb_err ;
2008-06-30 22:50:11 +04:00
}
2012-05-16 14:41:33 +04:00
static const struct v4l2_ctrl_ops sd_ctrl_ops = {
. s_ctrl = sd_s_ctrl ,
} ;
static int sd_init_controls ( struct gspca_dev * gspca_dev )
2008-06-30 22:50:11 +04:00
{
2012-05-16 14:41:33 +04:00
struct v4l2_ctrl_handler * hdl = & gspca_dev - > ctrl_handler ;
2008-06-30 22:50:11 +04:00
2012-05-16 14:41:33 +04:00
gspca_dev - > vdev . ctrl_handler = hdl ;
v4l2_ctrl_handler_init ( hdl , 5 ) ;
v4l2_ctrl_new_std ( hdl , & sd_ctrl_ops ,
V4L2_CID_BRIGHTNESS , 0 , 255 , 1 , 127 ) ;
if ( hdl - > error ) {
pr_err ( " Could not initialize controls \n " ) ;
return hdl - > error ;
}
2008-06-30 22:50:11 +04:00
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 ,
. config = sd_config ,
2012-05-16 14:41:33 +04:00
. init_controls = sd_init_controls ,
2008-09-04 00:12:16 +04:00
. init = sd_init ,
2008-06-30 22:50:11 +04:00
. start = sd_start ,
. stopN = sd_stopN ,
. stop0 = sd_stop0 ,
. pkt_scan = sd_pkt_scan ,
} ;
/* -- module initialisation -- */
2011-01-13 11:20:29 +03:00
static const struct usb_device_id device_table [ ] = {
2008-07-26 21:30:01 +04:00
{ USB_DEVICE ( 0x041e , 0x401d ) , . driver_info = Nxultra } ,
{ USB_DEVICE ( 0x0733 , 0x0430 ) , . driver_info = IntelPCCameraPro } ,
2008-07-25 15:53:03 +04:00
/*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
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 )
{
2008-07-01 17:03:42 +04:00
return gspca_dev_probe ( intf , id , & sd_desc , sizeof ( struct sd ) ,
2008-06-30 22:50:11 +04:00
THIS_MODULE ) ;
}
static struct usb_driver sd_driver = {
. name = MODULE_NAME ,
. id_table = device_table ,
. probe = sd_probe ,
. disconnect = gspca_disconnect ,
2008-09-03 23:48:10 +04:00
# ifdef CONFIG_PM
. suspend = gspca_suspend ,
. resume = gspca_resume ,
2012-06-30 13:44:47 +04:00
. reset_resume = gspca_resume ,
2008-09-03 23:48:10 +04:00
# endif
2008-06-30 22:50:11 +04:00
} ;
2011-11-18 21:46:12 +04:00
module_usb_driver ( sd_driver ) ;