Path: blob/master/drivers/media/video/gspca/spca505.c
17602 views
/*1* SPCA505 chip based cameras initialization data2*3* V4L2 by Jean-Francis Moine <http://moinejf.free.fr>4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA18*19*/2021#define MODULE_NAME "spca505"2223#include "gspca.h"2425MODULE_AUTHOR("Michel Xhaard <[email protected]>");26MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");27MODULE_LICENSE("GPL");2829/* specific webcam descriptor */30struct sd {31struct gspca_dev gspca_dev; /* !! must be the first item */3233u8 brightness;3435u8 subtype;36#define IntelPCCameraPro 037#define Nxultra 138};3940/* V4L2 controls supported by the driver */41static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);42static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);4344static const struct ctrl sd_ctrls[] = {45{46{47.id = V4L2_CID_BRIGHTNESS,48.type = V4L2_CTRL_TYPE_INTEGER,49.name = "Brightness",50.minimum = 0,51.maximum = 255,52.step = 1,53#define BRIGHTNESS_DEF 12754.default_value = BRIGHTNESS_DEF,55},56.set = sd_setbrightness,57.get = sd_getbrightness,58},59};6061static const struct v4l2_pix_format vga_mode[] = {62{160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,63.bytesperline = 160,64.sizeimage = 160 * 120 * 3 / 2,65.colorspace = V4L2_COLORSPACE_SRGB,66.priv = 4},67{176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,68.bytesperline = 176,69.sizeimage = 176 * 144 * 3 / 2,70.colorspace = V4L2_COLORSPACE_SRGB,71.priv = 3},72{320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,73.bytesperline = 320,74.sizeimage = 320 * 240 * 3 / 2,75.colorspace = V4L2_COLORSPACE_SRGB,76.priv = 2},77{352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,78.bytesperline = 352,79.sizeimage = 352 * 288 * 3 / 2,80.colorspace = V4L2_COLORSPACE_SRGB,81.priv = 1},82{640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,83.bytesperline = 640,84.sizeimage = 640 * 480 * 3 / 2,85.colorspace = V4L2_COLORSPACE_SRGB,86.priv = 0},87};8889#define SPCA50X_OFFSET_DATA 109091#define SPCA50X_REG_USB 0x02 /* spca505 501 */9293#define SPCA50X_USB_CTRL 0x00 /* spca505 */94#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */9596#define SPCA50X_REG_GLOBAL 0x03 /* spca505 */97#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */98#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */99100#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */101#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */102#define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */103104/* Image format and compression control */105#define SPCA50X_REG_COMPRESS 0x04106107/*108* Data to initialize a SPCA505. Common to the CCD and external modes109*/110static const u8 spca505_init_data[][3] = {111/* bmRequest,value,index */112{SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},113/* Sensor reset */114{SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},115{SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},116/* Block USB reset */117{SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0},118119{0x05, 0x01, 0x10},120/* Maybe power down some stuff */121{0x05, 0x0f, 0x11},122123/* Setup internal CCD ? */124{0x06, 0x10, 0x08},125{0x06, 0x00, 0x09},126{0x06, 0x00, 0x0a},127{0x06, 0x00, 0x0b},128{0x06, 0x10, 0x0c},129{0x06, 0x00, 0x0d},130{0x06, 0x00, 0x0e},131{0x06, 0x00, 0x0f},132{0x06, 0x10, 0x10},133{0x06, 0x02, 0x11},134{0x06, 0x00, 0x12},135{0x06, 0x04, 0x13},136{0x06, 0x02, 0x14},137{0x06, 0x8a, 0x51},138{0x06, 0x40, 0x52},139{0x06, 0xb6, 0x53},140{0x06, 0x3d, 0x54},141{}142};143144/*145* Data to initialize the camera using the internal CCD146*/147static const u8 spca505_open_data_ccd[][3] = {148/* bmRequest,value,index */149/* Internal CCD data set */150{0x03, 0x04, 0x01},151/* This could be a reset */152{0x03, 0x00, 0x01},153154/* Setup compression and image registers. 0x6 and 0x7 seem to be155related to H&V hold, and are resolution mode specific */156{0x04, 0x10, 0x01},157/* DIFF(0x50), was (0x10) */158{0x04, 0x00, 0x04},159{0x04, 0x00, 0x05},160{0x04, 0x20, 0x06},161{0x04, 0x20, 0x07},162163{0x08, 0x0a, 0x00},164/* DIFF (0x4a), was (0xa) */165166{0x05, 0x00, 0x10},167{0x05, 0x00, 0x11},168{0x05, 0x00, 0x00},169/* DIFF not written */170{0x05, 0x00, 0x01},171/* DIFF not written */172{0x05, 0x00, 0x02},173/* DIFF not written */174{0x05, 0x00, 0x03},175/* DIFF not written */176{0x05, 0x00, 0x04},177/* DIFF not written */178{0x05, 0x80, 0x05},179/* DIFF not written */180{0x05, 0xe0, 0x06},181/* DIFF not written */182{0x05, 0x20, 0x07},183/* DIFF not written */184{0x05, 0xa0, 0x08},185/* DIFF not written */186{0x05, 0x0, 0x12},187/* DIFF not written */188{0x05, 0x02, 0x0f},189/* DIFF not written */190{0x05, 0x10, 0x46},191/* DIFF not written */192{0x05, 0x8, 0x4a},193/* DIFF not written */194195{0x03, 0x08, 0x03},196/* DIFF (0x3,0x28,0x3) */197{0x03, 0x08, 0x01},198{0x03, 0x0c, 0x03},199/* DIFF not written */200{0x03, 0x21, 0x00},201/* DIFF (0x39) */202203/* Extra block copied from init to hopefully ensure CCD is in a sane state */204{0x06, 0x10, 0x08},205{0x06, 0x00, 0x09},206{0x06, 0x00, 0x0a},207{0x06, 0x00, 0x0b},208{0x06, 0x10, 0x0c},209{0x06, 0x00, 0x0d},210{0x06, 0x00, 0x0e},211{0x06, 0x00, 0x0f},212{0x06, 0x10, 0x10},213{0x06, 0x02, 0x11},214{0x06, 0x00, 0x12},215{0x06, 0x04, 0x13},216{0x06, 0x02, 0x14},217{0x06, 0x8a, 0x51},218{0x06, 0x40, 0x52},219{0x06, 0xb6, 0x53},220{0x06, 0x3d, 0x54},221/* End of extra block */222223{0x06, 0x3f, 0x1},224/* Block skipped */225{0x06, 0x10, 0x02},226{0x06, 0x64, 0x07},227{0x06, 0x10, 0x08},228{0x06, 0x00, 0x09},229{0x06, 0x00, 0x0a},230{0x06, 0x00, 0x0b},231{0x06, 0x10, 0x0c},232{0x06, 0x00, 0x0d},233{0x06, 0x00, 0x0e},234{0x06, 0x00, 0x0f},235{0x06, 0x10, 0x10},236{0x06, 0x02, 0x11},237{0x06, 0x00, 0x12},238{0x06, 0x04, 0x13},239{0x06, 0x02, 0x14},240{0x06, 0x8a, 0x51},241{0x06, 0x40, 0x52},242{0x06, 0xb6, 0x53},243{0x06, 0x3d, 0x54},244{0x06, 0x60, 0x57},245{0x06, 0x20, 0x58},246{0x06, 0x15, 0x59},247{0x06, 0x05, 0x5a},248249{0x05, 0x01, 0xc0},250{0x05, 0x10, 0xcb},251{0x05, 0x80, 0xc1},252/* */253{0x05, 0x0, 0xc2},254/* 4 was 0 */255{0x05, 0x00, 0xca},256{0x05, 0x80, 0xc1},257/* */258{0x05, 0x04, 0xc2},259{0x05, 0x00, 0xca},260{0x05, 0x0, 0xc1},261/* */262{0x05, 0x00, 0xc2},263{0x05, 0x00, 0xca},264{0x05, 0x40, 0xc1},265/* */266{0x05, 0x17, 0xc2},267{0x05, 0x00, 0xca},268{0x05, 0x80, 0xc1},269/* */270{0x05, 0x06, 0xc2},271{0x05, 0x00, 0xca},272{0x05, 0x80, 0xc1},273/* */274{0x05, 0x04, 0xc2},275{0x05, 0x00, 0xca},276277{0x03, 0x4c, 0x3},278{0x03, 0x18, 0x1},279280{0x06, 0x70, 0x51},281{0x06, 0xbe, 0x53},282{0x06, 0x71, 0x57},283{0x06, 0x20, 0x58},284{0x06, 0x05, 0x59},285{0x06, 0x15, 0x5a},286287{0x04, 0x00, 0x08},288/* Compress = OFF (0x1 to turn on) */289{0x04, 0x12, 0x09},290{0x04, 0x21, 0x0a},291{0x04, 0x10, 0x0b},292{0x04, 0x21, 0x0c},293{0x04, 0x05, 0x00},294/* was 5 (Image Type ? ) */295{0x04, 0x00, 0x01},296297{0x06, 0x3f, 0x01},298299{0x04, 0x00, 0x04},300{0x04, 0x00, 0x05},301{0x04, 0x40, 0x06},302{0x04, 0x40, 0x07},303304{0x06, 0x1c, 0x17},305{0x06, 0xe2, 0x19},306{0x06, 0x1c, 0x1b},307{0x06, 0xe2, 0x1d},308{0x06, 0xaa, 0x1f},309{0x06, 0x70, 0x20},310311{0x05, 0x01, 0x10},312{0x05, 0x00, 0x11},313{0x05, 0x01, 0x00},314{0x05, 0x05, 0x01},315{0x05, 0x00, 0xc1},316/* */317{0x05, 0x00, 0xc2},318{0x05, 0x00, 0xca},319320{0x06, 0x70, 0x51},321{0x06, 0xbe, 0x53},322{}323};324325/*326* Made by Tomasz Zablocki ([email protected])327* SPCA505b chip based cameras initialization data328*/329/* jfm */330#define initial_brightness 0x7f /* 0x0(white)-0xff(black) */331/* #define initial_brightness 0x0 //0x0(white)-0xff(black) */332/*333* Data to initialize a SPCA505. Common to the CCD and external modes334*/335static const u8 spca505b_init_data[][3] = {336/* start */337{0x02, 0x00, 0x00}, /* init */338{0x02, 0x00, 0x01},339{0x02, 0x00, 0x02},340{0x02, 0x00, 0x03},341{0x02, 0x00, 0x04},342{0x02, 0x00, 0x05},343{0x02, 0x00, 0x06},344{0x02, 0x00, 0x07},345{0x02, 0x00, 0x08},346{0x02, 0x00, 0x09},347{0x03, 0x00, 0x00},348{0x03, 0x00, 0x01},349{0x03, 0x00, 0x02},350{0x03, 0x00, 0x03},351{0x03, 0x00, 0x04},352{0x03, 0x00, 0x05},353{0x03, 0x00, 0x06},354{0x04, 0x00, 0x00},355{0x04, 0x00, 0x02},356{0x04, 0x00, 0x04},357{0x04, 0x00, 0x05},358{0x04, 0x00, 0x06},359{0x04, 0x00, 0x07},360{0x04, 0x00, 0x08},361{0x04, 0x00, 0x09},362{0x04, 0x00, 0x0a},363{0x04, 0x00, 0x0b},364{0x04, 0x00, 0x0c},365{0x07, 0x00, 0x00},366{0x07, 0x00, 0x03},367{0x08, 0x00, 0x00},368{0x08, 0x00, 0x01},369{0x08, 0x00, 0x02},370{0x06, 0x18, 0x08},371{0x06, 0xfc, 0x09},372{0x06, 0xfc, 0x0a},373{0x06, 0xfc, 0x0b},374{0x06, 0x18, 0x0c},375{0x06, 0xfc, 0x0d},376{0x06, 0xfc, 0x0e},377{0x06, 0xfc, 0x0f},378{0x06, 0x18, 0x10},379{0x06, 0xfe, 0x12},380{0x06, 0x00, 0x11},381{0x06, 0x00, 0x14},382{0x06, 0x00, 0x13},383{0x06, 0x28, 0x51},384{0x06, 0xff, 0x53},385{0x02, 0x00, 0x08},386387{0x03, 0x00, 0x03},388{0x03, 0x10, 0x03},389{}390};391392/*393* Data to initialize the camera using the internal CCD394*/395static const u8 spca505b_open_data_ccd[][3] = {396397/* {0x02,0x00,0x00}, */398{0x03, 0x04, 0x01}, /* rst */399{0x03, 0x00, 0x01},400{0x03, 0x00, 0x00},401{0x03, 0x21, 0x00},402{0x03, 0x00, 0x04},403{0x03, 0x00, 0x03},404{0x03, 0x18, 0x03},405{0x03, 0x08, 0x01},406{0x03, 0x1c, 0x03},407{0x03, 0x5c, 0x03},408{0x03, 0x5c, 0x03},409{0x03, 0x18, 0x01},410411/* same as 505 */412{0x04, 0x10, 0x01},413{0x04, 0x00, 0x04},414{0x04, 0x00, 0x05},415{0x04, 0x20, 0x06},416{0x04, 0x20, 0x07},417418{0x08, 0x0a, 0x00},419420{0x05, 0x00, 0x10},421{0x05, 0x00, 0x11},422{0x05, 0x00, 0x12},423{0x05, 0x6f, 0x00},424{0x05, initial_brightness >> 6, 0x00},425{0x05, (initial_brightness << 2) & 0xff, 0x01},426{0x05, 0x00, 0x02},427{0x05, 0x01, 0x03},428{0x05, 0x00, 0x04},429{0x05, 0x03, 0x05},430{0x05, 0xe0, 0x06},431{0x05, 0x20, 0x07},432{0x05, 0xa0, 0x08},433{0x05, 0x00, 0x12},434{0x05, 0x02, 0x0f},435{0x05, 0x80, 0x14}, /* max exposure off (0=on) */436{0x05, 0x01, 0xb0},437{0x05, 0x01, 0xbf},438{0x03, 0x02, 0x06},439{0x05, 0x10, 0x46},440{0x05, 0x08, 0x4a},441442{0x06, 0x00, 0x01},443{0x06, 0x10, 0x02},444{0x06, 0x64, 0x07},445{0x06, 0x18, 0x08},446{0x06, 0xfc, 0x09},447{0x06, 0xfc, 0x0a},448{0x06, 0xfc, 0x0b},449{0x04, 0x00, 0x01},450{0x06, 0x18, 0x0c},451{0x06, 0xfc, 0x0d},452{0x06, 0xfc, 0x0e},453{0x06, 0xfc, 0x0f},454{0x06, 0x11, 0x10}, /* contrast */455{0x06, 0x00, 0x11},456{0x06, 0xfe, 0x12},457{0x06, 0x00, 0x13},458{0x06, 0x00, 0x14},459{0x06, 0x9d, 0x51},460{0x06, 0x40, 0x52},461{0x06, 0x7c, 0x53},462{0x06, 0x40, 0x54},463{0x06, 0x02, 0x57},464{0x06, 0x03, 0x58},465{0x06, 0x15, 0x59},466{0x06, 0x05, 0x5a},467{0x06, 0x03, 0x56},468{0x06, 0x02, 0x3f},469{0x06, 0x00, 0x40},470{0x06, 0x39, 0x41},471{0x06, 0x69, 0x42},472{0x06, 0x87, 0x43},473{0x06, 0x9e, 0x44},474{0x06, 0xb1, 0x45},475{0x06, 0xbf, 0x46},476{0x06, 0xcc, 0x47},477{0x06, 0xd5, 0x48},478{0x06, 0xdd, 0x49},479{0x06, 0xe3, 0x4a},480{0x06, 0xe8, 0x4b},481{0x06, 0xed, 0x4c},482{0x06, 0xf2, 0x4d},483{0x06, 0xf7, 0x4e},484{0x06, 0xfc, 0x4f},485{0x06, 0xff, 0x50},486487{0x05, 0x01, 0xc0},488{0x05, 0x10, 0xcb},489{0x05, 0x40, 0xc1},490{0x05, 0x04, 0xc2},491{0x05, 0x00, 0xca},492{0x05, 0x40, 0xc1},493{0x05, 0x09, 0xc2},494{0x05, 0x00, 0xca},495{0x05, 0xc0, 0xc1},496{0x05, 0x09, 0xc2},497{0x05, 0x00, 0xca},498{0x05, 0x40, 0xc1},499{0x05, 0x59, 0xc2},500{0x05, 0x00, 0xca},501{0x04, 0x00, 0x01},502{0x05, 0x80, 0xc1},503{0x05, 0xec, 0xc2},504{0x05, 0x0, 0xca},505506{0x06, 0x02, 0x57},507{0x06, 0x01, 0x58},508{0x06, 0x15, 0x59},509{0x06, 0x0a, 0x5a},510{0x06, 0x01, 0x57},511{0x06, 0x8a, 0x03},512{0x06, 0x0a, 0x6c},513{0x06, 0x30, 0x01},514{0x06, 0x20, 0x02},515{0x06, 0x00, 0x03},516517{0x05, 0x8c, 0x25},518519{0x06, 0x4d, 0x51}, /* maybe saturation (4d) */520{0x06, 0x84, 0x53}, /* making green (84) */521{0x06, 0x00, 0x57}, /* sharpness (1) */522{0x06, 0x18, 0x08},523{0x06, 0xfc, 0x09},524{0x06, 0xfc, 0x0a},525{0x06, 0xfc, 0x0b},526{0x06, 0x18, 0x0c}, /* maybe hue (18) */527{0x06, 0xfc, 0x0d},528{0x06, 0xfc, 0x0e},529{0x06, 0xfc, 0x0f},530{0x06, 0x18, 0x10}, /* maybe contrast (18) */531532{0x05, 0x01, 0x02},533534{0x04, 0x00, 0x08}, /* compression */535{0x04, 0x12, 0x09},536{0x04, 0x21, 0x0a},537{0x04, 0x10, 0x0b},538{0x04, 0x21, 0x0c},539{0x04, 0x1d, 0x00}, /* imagetype (1d) */540{0x04, 0x41, 0x01}, /* hardware snapcontrol */541542{0x04, 0x00, 0x04},543{0x04, 0x00, 0x05},544{0x04, 0x10, 0x06},545{0x04, 0x10, 0x07},546{0x04, 0x40, 0x06},547{0x04, 0x40, 0x07},548{0x04, 0x00, 0x04},549{0x04, 0x00, 0x05},550551{0x06, 0x1c, 0x17},552{0x06, 0xe2, 0x19},553{0x06, 0x1c, 0x1b},554{0x06, 0xe2, 0x1d},555{0x06, 0x5f, 0x1f},556{0x06, 0x32, 0x20},557558{0x05, initial_brightness >> 6, 0x00},559{0x05, (initial_brightness << 2) & 0xff, 0x01},560{0x05, 0x06, 0xc1},561{0x05, 0x58, 0xc2},562{0x05, 0x00, 0xca},563{0x05, 0x00, 0x11},564{}565};566567static int reg_write(struct usb_device *dev,568u16 req, u16 index, u16 value)569{570int ret;571572ret = usb_control_msg(dev,573usb_sndctrlpipe(dev, 0),574req,575USB_TYPE_VENDOR | USB_RECIP_DEVICE,576value, index, NULL, 0, 500);577PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",578req, index, value, ret);579if (ret < 0)580err("reg write: error %d", ret);581return ret;582}583584/* returns: negative is error, pos or zero is data */585static int reg_read(struct gspca_dev *gspca_dev,586u16 req, /* bRequest */587u16 index) /* wIndex */588{589int ret;590591ret = usb_control_msg(gspca_dev->dev,592usb_rcvctrlpipe(gspca_dev->dev, 0),593req,594USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,5950, /* value */596index,597gspca_dev->usb_buf, 2,598500); /* timeout */599if (ret < 0)600return ret;601return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];602}603604static int write_vector(struct gspca_dev *gspca_dev,605const u8 data[][3])606{607struct usb_device *dev = gspca_dev->dev;608int ret, i = 0;609610while (data[i][0] != 0) {611ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);612if (ret < 0)613return ret;614i++;615}616return 0;617}618619/* this function is called at probe time */620static int sd_config(struct gspca_dev *gspca_dev,621const struct usb_device_id *id)622{623struct sd *sd = (struct sd *) gspca_dev;624struct cam *cam;625626cam = &gspca_dev->cam;627cam->cam_mode = vga_mode;628sd->subtype = id->driver_info;629if (sd->subtype != IntelPCCameraPro)630cam->nmodes = ARRAY_SIZE(vga_mode);631else /* no 640x480 for IntelPCCameraPro */632cam->nmodes = ARRAY_SIZE(vga_mode) - 1;633sd->brightness = BRIGHTNESS_DEF;634635return 0;636}637638/* this function is called at probe and resume time */639static int sd_init(struct gspca_dev *gspca_dev)640{641struct sd *sd = (struct sd *) gspca_dev;642643if (write_vector(gspca_dev,644sd->subtype == Nxultra645? spca505b_init_data646: spca505_init_data))647return -EIO;648return 0;649}650651static void setbrightness(struct gspca_dev *gspca_dev)652{653struct sd *sd = (struct sd *) gspca_dev;654u8 brightness = sd->brightness;655656reg_write(gspca_dev->dev, 0x05, 0x00, (255 - brightness) >> 6);657reg_write(gspca_dev->dev, 0x05, 0x01, (255 - brightness) << 2);658}659660static int sd_start(struct gspca_dev *gspca_dev)661{662struct sd *sd = (struct sd *) gspca_dev;663struct usb_device *dev = gspca_dev->dev;664int ret, mode;665static u8 mode_tb[][3] = {666/* r00 r06 r07 */667{0x00, 0x10, 0x10}, /* 640x480 */668{0x01, 0x1a, 0x1a}, /* 352x288 */669{0x02, 0x1c, 0x1d}, /* 320x240 */670{0x04, 0x34, 0x34}, /* 176x144 */671{0x05, 0x40, 0x40} /* 160x120 */672};673674if (sd->subtype == Nxultra)675write_vector(gspca_dev, spca505b_open_data_ccd);676else677write_vector(gspca_dev, spca505_open_data_ccd);678ret = reg_read(gspca_dev, 0x06, 0x16);679680if (ret < 0) {681PDEBUG(D_ERR|D_CONF,682"register read failed err: %d",683ret);684return ret;685}686if (ret != 0x0101) {687err("After vector read returns 0x%04x should be 0x0101",688ret);689}690691ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a);692if (ret < 0)693return ret;694reg_write(gspca_dev->dev, 0x05, 0xc2, 0x12);695696/* necessary because without it we can see stream697* only once after loading module */698/* stopping usb registers Tomasz change */699reg_write(dev, 0x02, 0x00, 0x00);700701mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;702reg_write(dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);703reg_write(dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);704reg_write(dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);705706ret = reg_write(dev, SPCA50X_REG_USB,707SPCA50X_USB_CTRL,708SPCA50X_CUSB_ENABLE);709710setbrightness(gspca_dev);711712return ret;713}714715static void sd_stopN(struct gspca_dev *gspca_dev)716{717/* Disable ISO packet machine */718reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);719}720721/* called on streamoff with alt 0 and on disconnect */722static void sd_stop0(struct gspca_dev *gspca_dev)723{724if (!gspca_dev->present)725return;726727/* This maybe reset or power control */728reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);729reg_write(gspca_dev->dev, 0x03, 0x01, 0x00);730reg_write(gspca_dev->dev, 0x03, 0x00, 0x01);731reg_write(gspca_dev->dev, 0x05, 0x10, 0x01);732reg_write(gspca_dev->dev, 0x05, 0x11, 0x0f);733}734735static void sd_pkt_scan(struct gspca_dev *gspca_dev,736u8 *data, /* isoc packet */737int len) /* iso packet length */738{739switch (data[0]) {740case 0: /* start of frame */741gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);742data += SPCA50X_OFFSET_DATA;743len -= SPCA50X_OFFSET_DATA;744gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);745break;746case 0xff: /* drop */747break;748default:749data += 1;750len -= 1;751gspca_frame_add(gspca_dev, INTER_PACKET, data, len);752break;753}754}755756static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)757{758struct sd *sd = (struct sd *) gspca_dev;759760sd->brightness = val;761if (gspca_dev->streaming)762setbrightness(gspca_dev);763return 0;764}765766static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)767{768struct sd *sd = (struct sd *) gspca_dev;769770*val = sd->brightness;771return 0;772}773774/* sub-driver description */775static const struct sd_desc sd_desc = {776.name = MODULE_NAME,777.ctrls = sd_ctrls,778.nctrls = ARRAY_SIZE(sd_ctrls),779.config = sd_config,780.init = sd_init,781.start = sd_start,782.stopN = sd_stopN,783.stop0 = sd_stop0,784.pkt_scan = sd_pkt_scan,785};786787/* -- module initialisation -- */788static const struct usb_device_id device_table[] = {789{USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},790{USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},791/*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */792{}793};794MODULE_DEVICE_TABLE(usb, device_table);795796/* -- device connect -- */797static int sd_probe(struct usb_interface *intf,798const struct usb_device_id *id)799{800return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),801THIS_MODULE);802}803804static struct usb_driver sd_driver = {805.name = MODULE_NAME,806.id_table = device_table,807.probe = sd_probe,808.disconnect = gspca_disconnect,809#ifdef CONFIG_PM810.suspend = gspca_suspend,811.resume = gspca_resume,812#endif813};814815/* -- module insert / remove -- */816static int __init sd_mod_init(void)817{818return usb_register(&sd_driver);819}820static void __exit sd_mod_exit(void)821{822usb_deregister(&sd_driver);823}824825module_init(sd_mod_init);826module_exit(sd_mod_exit);827828829