Path: blob/master/drivers/media/video/gspca/spca508.c
17590 views
/*1* SPCA508 chip based cameras subdriver2*3* Copyright (C) 2009 Jean-Francois 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*/1920#define MODULE_NAME "spca508"2122#include "gspca.h"2324MODULE_AUTHOR("Michel Xhaard <[email protected]>");25MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver");26MODULE_LICENSE("GPL");2728/* specific webcam descriptor */29struct sd {30struct gspca_dev gspca_dev; /* !! must be the first item */3132u8 brightness;3334u8 subtype;35#define CreativeVista 036#define HamaUSBSightcam 137#define HamaUSBSightcam2 238#define IntelEasyPCCamera 339#define MicroInnovationIC200 440#define ViewQuestVQ110 541};4243/* V4L2 controls supported by the driver */44static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);45static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);4647static const struct ctrl sd_ctrls[] = {48{49{50.id = V4L2_CID_BRIGHTNESS,51.type = V4L2_CTRL_TYPE_INTEGER,52.name = "Brightness",53.minimum = 0,54.maximum = 255,55.step = 1,56#define BRIGHTNESS_DEF 12857.default_value = BRIGHTNESS_DEF,58},59.set = sd_setbrightness,60.get = sd_getbrightness,61},62};6364static const struct v4l2_pix_format sif_mode[] = {65{160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,66.bytesperline = 160,67.sizeimage = 160 * 120 * 3 / 2,68.colorspace = V4L2_COLORSPACE_SRGB,69.priv = 3},70{176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,71.bytesperline = 176,72.sizeimage = 176 * 144 * 3 / 2,73.colorspace = V4L2_COLORSPACE_SRGB,74.priv = 2},75{320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,76.bytesperline = 320,77.sizeimage = 320 * 240 * 3 / 2,78.colorspace = V4L2_COLORSPACE_SRGB,79.priv = 1},80{352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,81.bytesperline = 352,82.sizeimage = 352 * 288 * 3 / 2,83.colorspace = V4L2_COLORSPACE_SRGB,84.priv = 0},85};8687/* Frame packet header offsets for the spca508 */88#define SPCA508_OFFSET_DATA 378990/*91* Initialization data: this is the first set-up data written to the92* device (before the open data).93*/94static const u16 spca508_init_data[][2] = {95{0x0000, 0x870b},9697{0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */98{0x0003, 0x8111}, /* Reset compression & memory */99{0x0000, 0x8110}, /* Disable all outputs */100/* READ {0x0000, 0x8114} -> 0000: 00 */101{0x0000, 0x8114}, /* SW GPIO data */102{0x0008, 0x8110}, /* Enable charge pump output */103{0x0002, 0x8116}, /* 200 kHz pump clock */104/* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */105{0x0003, 0x8111}, /* Reset compression & memory */106{0x0000, 0x8111}, /* Normal mode (not reset) */107{0x0098, 0x8110},108/* Enable charge pump output, sync.serial,external 2x clock */109{0x000d, 0x8114}, /* SW GPIO data */110{0x0002, 0x8116}, /* 200 kHz pump clock */111{0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */112/* --------------------------------------- */113{0x000f, 0x8402}, /* memory bank */114{0x0000, 0x8403}, /* ... address */115/* --------------------------------------- */116/* 0x88__ is Synchronous Serial Interface. */117/* TBD: This table could be expressed more compactly */118/* using spca508_write_i2c_vector(). */119/* TBD: Should see if the values in spca50x_i2c_data */120/* would work with the VQ110 instead of the values */121/* below. */122{0x00c0, 0x8804}, /* SSI slave addr */123{0x0008, 0x8802}, /* 375 Khz SSI clock */124/* READ { 0x0001, 0x8803 } -> 0000: 00 */125/* READ { 0x0001, 0x8802 } -> 0000: 08 */126{0x0008, 0x8802}, /* 375 Khz SSI clock */127{0x0012, 0x8801}, /* SSI reg addr */128{0x0080, 0x8800}, /* SSI data to write */129/* READ { 0x0001, 0x8803 } -> 0000: 00 */130/* READ { 0x0001, 0x8803 } -> 0000: 00 */131/* READ { 0x0001, 0x8802 } -> 0000: 08 */132{0x0008, 0x8802}, /* 375 Khz SSI clock */133{0x0012, 0x8801}, /* SSI reg addr */134{0x0000, 0x8800}, /* SSI data to write */135/* READ { 0x0001, 0x8803 } -> 0000: 00 */136/* READ { 0x0001, 0x8803 } -> 0000: 00 */137/* READ { 0x0001, 0x8802 } -> 0000: 08 */138{0x0008, 0x8802}, /* 375 Khz SSI clock */139{0x0011, 0x8801}, /* SSI reg addr */140{0x0040, 0x8800}, /* SSI data to write */141/* READ { 0x0001, 0x8803 } -> 0000: 00 */142/* READ { 0x0001, 0x8803 } -> 0000: 00 */143/* READ { 0x0001, 0x8802 } -> 0000: 08 */144{0x0008, 0x8802},145{0x0013, 0x8801},146{0x0000, 0x8800},147/* READ { 0x0001, 0x8803 } -> 0000: 00 */148/* READ { 0x0001, 0x8803 } -> 0000: 00 */149/* READ { 0x0001, 0x8802 } -> 0000: 08 */150{0x0008, 0x8802},151{0x0014, 0x8801},152{0x0000, 0x8800},153/* READ { 0x0001, 0x8803 } -> 0000: 00 */154/* READ { 0x0001, 0x8803 } -> 0000: 00 */155/* READ { 0x0001, 0x8802 } -> 0000: 08 */156{0x0008, 0x8802},157{0x0015, 0x8801},158{0x0001, 0x8800},159/* READ { 0x0001, 0x8803 } -> 0000: 00 */160/* READ { 0x0001, 0x8803 } -> 0000: 00 */161/* READ { 0x0001, 0x8802 } -> 0000: 08 */162{0x0008, 0x8802},163{0x0016, 0x8801},164{0x0003, 0x8800},165/* READ { 0x0001, 0x8803 } -> 0000: 00 */166/* READ { 0x0001, 0x8803 } -> 0000: 00 */167/* READ { 0x0001, 0x8802 } -> 0000: 08 */168{0x0008, 0x8802},169{0x0017, 0x8801},170{0x0036, 0x8800},171/* READ { 0x0001, 0x8803 } -> 0000: 00 */172/* READ { 0x0001, 0x8803 } -> 0000: 00 */173/* READ { 0x0001, 0x8802 } -> 0000: 08 */174{0x0008, 0x8802},175{0x0018, 0x8801},176{0x00ec, 0x8800},177/* READ { 0x0001, 0x8803 } -> 0000: 00 */178/* READ { 0x0001, 0x8803 } -> 0000: 00 */179/* READ { 0x0001, 0x8802 } -> 0000: 08 */180{0x0008, 0x8802},181{0x001a, 0x8801},182{0x0094, 0x8800},183/* READ { 0x0001, 0x8803 } -> 0000: 00 */184/* READ { 0x0001, 0x8803 } -> 0000: 00 */185/* READ { 0x0001, 0x8802 } -> 0000: 08 */186{0x0008, 0x8802},187{0x001b, 0x8801},188{0x0000, 0x8800},189/* READ { 0x0001, 0x8803 } -> 0000: 00 */190/* READ { 0x0001, 0x8803 } -> 0000: 00 */191/* READ { 0x0001, 0x8802 } -> 0000: 08 */192{0x0008, 0x8802},193{0x0027, 0x8801},194{0x00a2, 0x8800},195/* READ { 0x0001, 0x8803 } -> 0000: 00 */196/* READ { 0x0001, 0x8803 } -> 0000: 00 */197/* READ { 0x0001, 0x8802 } -> 0000: 08 */198{0x0008, 0x8802},199{0x0028, 0x8801},200{0x0040, 0x8800},201/* READ { 0x0001, 0x8803 } -> 0000: 00 */202/* READ { 0x0001, 0x8803 } -> 0000: 00 */203/* READ { 0x0001, 0x8802 } -> 0000: 08 */204{0x0008, 0x8802},205{0x002a, 0x8801},206{0x0084, 0x8800},207/* READ { 0x0001, 0x8803 } -> 0000: 00 */208/* READ { 0x0001, 0x8803 } -> 0000: 00 */209/* READ { 0x0001, 0x8802 } -> 0000: 08 */210{0x0008, 0x8802},211{0x002b, 0x8801},212{0x00a8, 0x8800},213/* READ { 0x0001, 0x8803 } -> 0000: 00 */214/* READ { 0x0001, 0x8803 } -> 0000: 00 */215/* READ { 0x0001, 0x8802 } -> 0000: 08 */216{0x0008, 0x8802},217{0x002c, 0x8801},218{0x00fe, 0x8800},219/* READ { 0x0001, 0x8803 } -> 0000: 00 */220/* READ { 0x0001, 0x8803 } -> 0000: 00 */221/* READ { 0x0001, 0x8802 } -> 0000: 08 */222{0x0008, 0x8802},223{0x002d, 0x8801},224{0x0003, 0x8800},225/* READ { 0x0001, 0x8803 } -> 0000: 00 */226/* READ { 0x0001, 0x8803 } -> 0000: 00 */227/* READ { 0x0001, 0x8802 } -> 0000: 08 */228{0x0008, 0x8802},229{0x0038, 0x8801},230{0x0083, 0x8800},231/* READ { 0x0001, 0x8803 } -> 0000: 00 */232/* READ { 0x0001, 0x8803 } -> 0000: 00 */233/* READ { 0x0001, 0x8802 } -> 0000: 08 */234{0x0008, 0x8802},235{0x0033, 0x8801},236{0x0081, 0x8800},237/* READ { 0x0001, 0x8803 } -> 0000: 00 */238/* READ { 0x0001, 0x8803 } -> 0000: 00 */239/* READ { 0x0001, 0x8802 } -> 0000: 08 */240{0x0008, 0x8802},241{0x0034, 0x8801},242{0x004a, 0x8800},243/* READ { 0x0001, 0x8803 } -> 0000: 00 */244/* READ { 0x0001, 0x8803 } -> 0000: 00 */245/* READ { 0x0001, 0x8802 } -> 0000: 08 */246{0x0008, 0x8802},247{0x0039, 0x8801},248{0x0000, 0x8800},249/* READ { 0x0001, 0x8803 } -> 0000: 00 */250/* READ { 0x0001, 0x8803 } -> 0000: 00 */251/* READ { 0x0001, 0x8802 } -> 0000: 08 */252{0x0008, 0x8802},253{0x0010, 0x8801},254{0x00a8, 0x8800},255/* READ { 0x0001, 0x8803 } -> 0000: 00 */256/* READ { 0x0001, 0x8803 } -> 0000: 00 */257/* READ { 0x0001, 0x8802 } -> 0000: 08 */258{0x0008, 0x8802},259{0x0006, 0x8801},260{0x0058, 0x8800},261/* READ { 0x0001, 0x8803 } -> 0000: 00 */262/* READ { 0x0001, 0x8803 } -> 0000: 00 */263/* READ { 0x0001, 0x8802 } -> 0000: 08 */264{0x0008, 0x8802},265{0x0000, 0x8801},266{0x0004, 0x8800},267/* READ { 0x0001, 0x8803 } -> 0000: 00 */268/* READ { 0x0001, 0x8803 } -> 0000: 00 */269/* READ { 0x0001, 0x8802 } -> 0000: 08 */270{0x0008, 0x8802},271{0x0040, 0x8801},272{0x0080, 0x8800},273/* READ { 0x0001, 0x8803 } -> 0000: 00 */274/* READ { 0x0001, 0x8803 } -> 0000: 00 */275/* READ { 0x0001, 0x8802 } -> 0000: 08 */276{0x0008, 0x8802},277{0x0041, 0x8801},278{0x000c, 0x8800},279/* READ { 0x0001, 0x8803 } -> 0000: 00 */280/* READ { 0x0001, 0x8803 } -> 0000: 00 */281/* READ { 0x0001, 0x8802 } -> 0000: 08 */282{0x0008, 0x8802},283{0x0042, 0x8801},284{0x000c, 0x8800},285/* READ { 0x0001, 0x8803 } -> 0000: 00 */286/* READ { 0x0001, 0x8803 } -> 0000: 00 */287/* READ { 0x0001, 0x8802 } -> 0000: 08 */288{0x0008, 0x8802},289{0x0043, 0x8801},290{0x0028, 0x8800},291/* READ { 0x0001, 0x8803 } -> 0000: 00 */292/* READ { 0x0001, 0x8803 } -> 0000: 00 */293/* READ { 0x0001, 0x8802 } -> 0000: 08 */294{0x0008, 0x8802},295{0x0044, 0x8801},296{0x0080, 0x8800},297/* READ { 0x0001, 0x8803 } -> 0000: 00 */298/* READ { 0x0001, 0x8803 } -> 0000: 00 */299/* READ { 0x0001, 0x8802 } -> 0000: 08 */300{0x0008, 0x8802},301{0x0045, 0x8801},302{0x0020, 0x8800},303/* READ { 0x0001, 0x8803 } -> 0000: 00 */304/* READ { 0x0001, 0x8803 } -> 0000: 00 */305/* READ { 0x0001, 0x8802 } -> 0000: 08 */306{0x0008, 0x8802},307{0x0046, 0x8801},308{0x0020, 0x8800},309/* READ { 0x0001, 0x8803 } -> 0000: 00 */310/* READ { 0x0001, 0x8803 } -> 0000: 00 */311/* READ { 0x0001, 0x8802 } -> 0000: 08 */312{0x0008, 0x8802},313{0x0047, 0x8801},314{0x0080, 0x8800},315/* READ { 0x0001, 0x8803 } -> 0000: 00 */316/* READ { 0x0001, 0x8803 } -> 0000: 00 */317/* READ { 0x0001, 0x8802 } -> 0000: 08 */318{0x0008, 0x8802},319{0x0048, 0x8801},320{0x004c, 0x8800},321/* READ { 0x0001, 0x8803 } -> 0000: 00 */322/* READ { 0x0001, 0x8803 } -> 0000: 00 */323/* READ { 0x0001, 0x8802 } -> 0000: 08 */324{0x0008, 0x8802},325{0x0049, 0x8801},326{0x0084, 0x8800},327/* READ { 0x0001, 0x8803 } -> 0000: 00 */328/* READ { 0x0001, 0x8803 } -> 0000: 00 */329/* READ { 0x0001, 0x8802 } -> 0000: 08 */330{0x0008, 0x8802},331{0x004a, 0x8801},332{0x0084, 0x8800},333/* READ { 0x0001, 0x8803 } -> 0000: 00 */334/* READ { 0x0001, 0x8803 } -> 0000: 00 */335/* READ { 0x0001, 0x8802 } -> 0000: 08 */336{0x0008, 0x8802},337{0x004b, 0x8801},338{0x0084, 0x8800},339/* READ { 0x0001, 0x8803 } -> 0000: 00 */340/* --------------------------------------- */341{0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */342{0x0000, 0x8701}, /* CKx1 clock delay adj */343{0x0000, 0x8701}, /* CKx1 clock delay adj */344{0x0001, 0x870c}, /* CKOx2 output */345/* --------------------------------------- */346{0x0080, 0x8600}, /* Line memory read counter (L) */347{0x0001, 0x8606}, /* reserved */348{0x0064, 0x8607}, /* Line memory read counter (H) 0x6480=25,728 */349{0x002a, 0x8601}, /* CDSP sharp interpolation mode,350* line sel for color sep, edge enhance enab */351{0x0000, 0x8602}, /* optical black level for user settng = 0 */352{0x0080, 0x8600}, /* Line memory read counter (L) */353{0x000a, 0x8603}, /* optical black level calc mode:354* auto; optical black offset = 10 */355{0x00df, 0x865b}, /* Horiz offset for valid pixels (L)=0xdf */356{0x0012, 0x865c}, /* Vert offset for valid lines (L)=0x12 */357358/* The following two lines seem to be the "wrong" resolution. */359/* But perhaps these indicate the actual size of the sensor */360/* rather than the size of the current video mode. */361{0x0058, 0x865d}, /* Horiz valid pixels (*4) (L) = 352 */362{0x0048, 0x865e}, /* Vert valid lines (*4) (L) = 288 */363364{0x0015, 0x8608}, /* A11 Coef ... */365{0x0030, 0x8609},366{0x00fb, 0x860a},367{0x003e, 0x860b},368{0x00ce, 0x860c},369{0x00f4, 0x860d},370{0x00eb, 0x860e},371{0x00dc, 0x860f},372{0x0039, 0x8610},373{0x0001, 0x8611}, /* R offset for white balance ... */374{0x0000, 0x8612},375{0x0001, 0x8613},376{0x0000, 0x8614},377{0x005b, 0x8651}, /* R gain for white balance ... */378{0x0040, 0x8652},379{0x0060, 0x8653},380{0x0040, 0x8654},381{0x0000, 0x8655},382{0x0001, 0x863f}, /* Fixed gamma correction enable, USB control,383* lum filter disable, lum noise clip disable */384{0x00a1, 0x8656}, /* Window1 size 256x256, Windows2 size 64x64,385* gamma look-up disable,386* new edge enhancement enable */387{0x0018, 0x8657}, /* Edge gain high thresh */388{0x0020, 0x8658}, /* Edge gain low thresh */389{0x000a, 0x8659}, /* Edge bandwidth high threshold */390{0x0005, 0x865a}, /* Edge bandwidth low threshold */391/* -------------------------------- */392{0x0030, 0x8112}, /* Video drop enable, ISO streaming enable */393/* READ { 0x0001, 0x8803 } -> 0000: 00 */394/* READ { 0x0001, 0x8802 } -> 0000: 08 */395{0xa908, 0x8802},396{0x0034, 0x8801}, /* SSI reg addr */397{0x00ca, 0x8800},398/* SSI data to write */399/* READ { 0x0001, 0x8803 } -> 0000: 00 */400/* READ { 0x0001, 0x8803 } -> 0000: 00 */401/* READ { 0x0001, 0x8802 } -> 0000: 08 */402{0x1f08, 0x8802},403{0x0006, 0x8801},404{0x0080, 0x8800},405/* READ { 0x0001, 0x8803 } -> 0000: 00 */406407/* ----- Read back coefs we wrote earlier. */408/* READ { 0x0000, 0x8608 } -> 0000: 15 */409/* READ { 0x0000, 0x8609 } -> 0000: 30 */410/* READ { 0x0000, 0x860a } -> 0000: fb */411/* READ { 0x0000, 0x860b } -> 0000: 3e */412/* READ { 0x0000, 0x860c } -> 0000: ce */413/* READ { 0x0000, 0x860d } -> 0000: f4 */414/* READ { 0x0000, 0x860e } -> 0000: eb */415/* READ { 0x0000, 0x860f } -> 0000: dc */416/* READ { 0x0000, 0x8610 } -> 0000: 39 */417/* READ { 0x0001, 0x8803 } -> 0000: 00 */418/* READ { 0x0001, 0x8802 } -> 0000: 08 */419{0xb008, 0x8802},420{0x0006, 0x8801},421{0x007d, 0x8800},422/* READ { 0x0001, 0x8803 } -> 0000: 00 */423424425/* This chunk is seemingly redundant with */426/* earlier commands (A11 Coef...), but if I disable it, */427/* the image appears too dark. Maybe there was some kind of */428/* reset since the earlier commands, so this is necessary again. */429{0x0015, 0x8608},430{0x0030, 0x8609},431{0xfffb, 0x860a},432{0x003e, 0x860b},433{0xffce, 0x860c},434{0xfff4, 0x860d},435{0xffeb, 0x860e},436{0xffdc, 0x860f},437{0x0039, 0x8610},438{0x0018, 0x8657},439440{0x0000, 0x8508}, /* Disable compression. */441/* Previous line was:442{0x0021, 0x8508}, * Enable compression. */443{0x0032, 0x850b}, /* compression stuff */444{0x0003, 0x8509}, /* compression stuff */445{0x0011, 0x850a}, /* compression stuff */446{0x0021, 0x850d}, /* compression stuff */447{0x0010, 0x850c}, /* compression stuff */448{0x0003, 0x8500}, /* *** Video mode: 160x120 */449{0x0001, 0x8501}, /* Hardware-dominated snap control */450{0x0061, 0x8656}, /* Window1 size 128x128, Windows2 size 128x128,451* gamma look-up disable,452* new edge enhancement enable */453{0x0018, 0x8617}, /* Window1 start X (*2) */454{0x0008, 0x8618}, /* Window1 start Y (*2) */455{0x0061, 0x8656}, /* Window1 size 128x128, Windows2 size 128x128,456* gamma look-up disable,457* new edge enhancement enable */458{0x0058, 0x8619}, /* Window2 start X (*2) */459{0x0008, 0x861a}, /* Window2 start Y (*2) */460{0x00ff, 0x8615}, /* High lum thresh for white balance */461{0x0000, 0x8616}, /* Low lum thresh for white balance */462{0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */463{0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */464/* READ { 0x0000, 0x8656 } -> 0000: 61 */465{0x0028, 0x8802}, /* 375 Khz SSI clock, SSI r/w sync with VSYNC */466/* READ { 0x0001, 0x8803 } -> 0000: 00 */467/* READ { 0x0001, 0x8802 } -> 0000: 28 */468{0x1f28, 0x8802}, /* 375 Khz SSI clock, SSI r/w sync with VSYNC */469{0x0010, 0x8801}, /* SSI reg addr */470{0x003e, 0x8800}, /* SSI data to write */471/* READ { 0x0001, 0x8803 } -> 0000: 00 */472{0x0028, 0x8802},473/* READ { 0x0001, 0x8803 } -> 0000: 00 */474/* READ { 0x0001, 0x8802 } -> 0000: 28 */475{0x1f28, 0x8802},476{0x0000, 0x8801},477{0x001f, 0x8800},478/* READ { 0x0001, 0x8803 } -> 0000: 00 */479{0x0001, 0x8602}, /* optical black level for user settning = 1 */480481/* Original: */482{0x0023, 0x8700}, /* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */483{0x000f, 0x8602}, /* optical black level for user settning = 15 */484485{0x0028, 0x8802},486/* READ { 0x0001, 0x8803 } -> 0000: 00 */487/* READ { 0x0001, 0x8802 } -> 0000: 28 */488{0x1f28, 0x8802},489{0x0010, 0x8801},490{0x007b, 0x8800},491/* READ { 0x0001, 0x8803 } -> 0000: 00 */492{0x002f, 0x8651}, /* R gain for white balance ... */493{0x0080, 0x8653},494/* READ { 0x0000, 0x8655 } -> 0000: 00 */495{0x0000, 0x8655},496497{0x0030, 0x8112}, /* Video drop enable, ISO streaming enable */498{0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */499/* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */500{}501};502503/*504* Initialization data for Intel EasyPC Camera CS110505*/506static const u16 spca508cs110_init_data[][2] = {507{0x0000, 0x870b}, /* Reset CTL3 */508{0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */509{0x0000, 0x8111}, /* Normal operation on reset */510{0x0090, 0x8110},511/* External Clock 2x & Synchronous Serial Interface Output */512{0x0020, 0x8112}, /* Video Drop packet enable */513{0x0000, 0x8114}, /* Software GPIO output data */514{0x0001, 0x8114},515{0x0001, 0x8114},516{0x0001, 0x8114},517{0x0003, 0x8114},518519/* Initial sequence Synchronous Serial Interface */520{0x000f, 0x8402}, /* Memory bank Address */521{0x0000, 0x8403}, /* Memory bank Address */522{0x00ba, 0x8804}, /* SSI Slave address */523{0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */524{0x0010, 0x8802}, /* 93.75kHz SSI Clock two DataByte */525526{0x0001, 0x8801},527{0x000a, 0x8805}, /* a - NWG: Dunno what this is about */528{0x0000, 0x8800},529{0x0010, 0x8802},530531{0x0002, 0x8801},532{0x0000, 0x8805},533{0x0000, 0x8800},534{0x0010, 0x8802},535536{0x0003, 0x8801},537{0x0027, 0x8805},538{0x0001, 0x8800},539{0x0010, 0x8802},540541{0x0004, 0x8801},542{0x0065, 0x8805},543{0x0001, 0x8800},544{0x0010, 0x8802},545546{0x0005, 0x8801},547{0x0003, 0x8805},548{0x0000, 0x8800},549{0x0010, 0x8802},550551{0x0006, 0x8801},552{0x001c, 0x8805},553{0x0000, 0x8800},554{0x0010, 0x8802},555556{0x0007, 0x8801},557{0x002a, 0x8805},558{0x0000, 0x8800},559{0x0010, 0x8802},560561{0x0002, 0x8704}, /* External input CKIx1 */562{0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */563{0x009a, 0x8600}, /* Line memory Read Counter (L) */564{0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */565{0x0003, 0x865c}, /* 3 Vertical Offset for Valid Lines(L) */566{0x0058, 0x865d}, /* 58 Horizontal Valid Pixel Window(L) */567568{0x0006, 0x8660}, /* Nibble data + input order */569570{0x000a, 0x8602}, /* Optical black level set to 0x0a */571{0x0000, 0x8603}, /* Optical black level Offset */572573/* {0x0000, 0x8611}, * 0 R Offset for white Balance */574/* {0x0000, 0x8612}, * 1 Gr Offset for white Balance */575/* {0x0000, 0x8613}, * 1f B Offset for white Balance */576/* {0x0000, 0x8614}, * f0 Gb Offset for white Balance */577578{0x0040, 0x8651}, /* 2b BLUE gain for white balance good at all 60 */579{0x0030, 0x8652}, /* 41 Gr Gain for white Balance (L) */580{0x0035, 0x8653}, /* 26 RED gain for white balance */581{0x0035, 0x8654}, /* 40Gb Gain for white Balance (L) */582{0x0041, 0x863f},583/* Fixed Gamma correction enabled (makes colours look better) */584585{0x0000, 0x8655},586/* High bits for white balance*****brightness control*** */587{}588};589590static const u16 spca508_sightcam_init_data[][2] = {591/* This line seems to setup the frame/canvas */592{0x000f, 0x8402},593594/* These 6 lines are needed to startup the webcam */595{0x0090, 0x8110},596{0x0001, 0x8114},597{0x0001, 0x8114},598{0x0001, 0x8114},599{0x0003, 0x8114},600{0x0080, 0x8804},601602/* This part seems to make the pictures darker? (autobrightness?) */603{0x0001, 0x8801},604{0x0004, 0x8800},605{0x0003, 0x8801},606{0x00e0, 0x8800},607{0x0004, 0x8801},608{0x00b4, 0x8800},609{0x0005, 0x8801},610{0x0000, 0x8800},611612{0x0006, 0x8801},613{0x00e0, 0x8800},614{0x0007, 0x8801},615{0x000c, 0x8800},616617/* This section is just needed, it probably618* does something like the previous section,619* but the cam won't start if it's not included.620*/621{0x0014, 0x8801},622{0x0008, 0x8800},623{0x0015, 0x8801},624{0x0067, 0x8800},625{0x0016, 0x8801},626{0x0000, 0x8800},627{0x0017, 0x8801},628{0x0020, 0x8800},629{0x0018, 0x8801},630{0x0044, 0x8800},631632/* Makes the picture darker - and the633* cam won't start if not included634*/635{0x001e, 0x8801},636{0x00ea, 0x8800},637{0x001f, 0x8801},638{0x0001, 0x8800},639{0x0003, 0x8801},640{0x00e0, 0x8800},641642/* seems to place the colors ontop of each other #1 */643{0x0006, 0x8704},644{0x0001, 0x870c},645{0x0016, 0x8600},646{0x0002, 0x8606},647648/* if not included the pictures becomes _very_ dark */649{0x0064, 0x8607},650{0x003a, 0x8601},651{0x0000, 0x8602},652653/* seems to place the colors ontop of each other #2 */654{0x0016, 0x8600},655{0x0018, 0x8617},656{0x0008, 0x8618},657{0x00a1, 0x8656},658659/* webcam won't start if not included */660{0x0007, 0x865b},661{0x0001, 0x865c},662{0x0058, 0x865d},663{0x0048, 0x865e},664665/* adjusts the colors */666{0x0049, 0x8651},667{0x0040, 0x8652},668{0x004c, 0x8653},669{0x0040, 0x8654},670{}671};672673static const u16 spca508_sightcam2_init_data[][2] = {674{0x0020, 0x8112},675676{0x000f, 0x8402},677{0x0000, 0x8403},678679{0x0008, 0x8201},680{0x0008, 0x8200},681{0x0001, 0x8200},682{0x0009, 0x8201},683{0x0008, 0x8200},684{0x0001, 0x8200},685{0x000a, 0x8201},686{0x0008, 0x8200},687{0x0001, 0x8200},688{0x000b, 0x8201},689{0x0008, 0x8200},690{0x0001, 0x8200},691{0x000c, 0x8201},692{0x0008, 0x8200},693{0x0001, 0x8200},694{0x000d, 0x8201},695{0x0008, 0x8200},696{0x0001, 0x8200},697{0x000e, 0x8201},698{0x0008, 0x8200},699{0x0001, 0x8200},700{0x0007, 0x8201},701{0x0008, 0x8200},702{0x0001, 0x8200},703{0x000f, 0x8201},704{0x0008, 0x8200},705{0x0001, 0x8200},706707{0x0018, 0x8660},708{0x0010, 0x8201},709710{0x0008, 0x8200},711{0x0001, 0x8200},712{0x0011, 0x8201},713{0x0008, 0x8200},714{0x0001, 0x8200},715716{0x0000, 0x86b0},717{0x0034, 0x86b1},718{0x0000, 0x86b2},719{0x0049, 0x86b3},720{0x0000, 0x86b4},721{0x0000, 0x86b4},722723{0x0012, 0x8201},724{0x0008, 0x8200},725{0x0001, 0x8200},726{0x0013, 0x8201},727{0x0008, 0x8200},728{0x0001, 0x8200},729730{0x0001, 0x86b0},731{0x00aa, 0x86b1},732{0x0000, 0x86b2},733{0x00e4, 0x86b3},734{0x0000, 0x86b4},735{0x0000, 0x86b4},736737{0x0018, 0x8660},738739{0x0090, 0x8110},740{0x0001, 0x8114},741{0x0001, 0x8114},742{0x0001, 0x8114},743{0x0003, 0x8114},744745{0x0080, 0x8804},746{0x0003, 0x8801},747{0x0012, 0x8800},748{0x0004, 0x8801},749{0x0005, 0x8800},750{0x0005, 0x8801},751{0x0000, 0x8800},752{0x0006, 0x8801},753{0x0000, 0x8800},754{0x0007, 0x8801},755{0x0000, 0x8800},756{0x0008, 0x8801},757{0x0005, 0x8800},758{0x000a, 0x8700},759{0x000e, 0x8801},760{0x0004, 0x8800},761{0x0005, 0x8801},762{0x0047, 0x8800},763{0x0006, 0x8801},764{0x0000, 0x8800},765{0x0007, 0x8801},766{0x00c0, 0x8800},767{0x0008, 0x8801},768{0x0003, 0x8800},769{0x0013, 0x8801},770{0x0001, 0x8800},771{0x0009, 0x8801},772{0x0000, 0x8800},773{0x000a, 0x8801},774{0x0000, 0x8800},775{0x000b, 0x8801},776{0x0000, 0x8800},777{0x000c, 0x8801},778{0x0000, 0x8800},779{0x000e, 0x8801},780{0x0004, 0x8800},781{0x000f, 0x8801},782{0x0000, 0x8800},783{0x0010, 0x8801},784{0x0006, 0x8800},785{0x0011, 0x8801},786{0x0006, 0x8800},787{0x0012, 0x8801},788{0x0000, 0x8800},789{0x0013, 0x8801},790{0x0001, 0x8800},791792{0x000a, 0x8700},793{0x0000, 0x8702},794{0x0000, 0x8703},795{0x00c2, 0x8704},796{0x0001, 0x870c},797798{0x0044, 0x8600},799{0x0002, 0x8606},800{0x0064, 0x8607},801{0x003a, 0x8601},802{0x0008, 0x8602},803{0x0044, 0x8600},804{0x0018, 0x8617},805{0x0008, 0x8618},806{0x00a1, 0x8656},807{0x0004, 0x865b},808{0x0002, 0x865c},809{0x0058, 0x865d},810{0x0048, 0x865e},811{0x0012, 0x8608},812{0x002c, 0x8609},813{0x0002, 0x860a},814{0x002c, 0x860b},815{0x00db, 0x860c},816{0x00f9, 0x860d},817{0x00f1, 0x860e},818{0x00e3, 0x860f},819{0x002c, 0x8610},820{0x006c, 0x8651},821{0x0041, 0x8652},822{0x0059, 0x8653},823{0x0040, 0x8654},824{0x00fa, 0x8611},825{0x00ff, 0x8612},826{0x00f8, 0x8613},827{0x0000, 0x8614},828{0x0001, 0x863f},829{0x0000, 0x8640},830{0x0026, 0x8641},831{0x0045, 0x8642},832{0x0060, 0x8643},833{0x0075, 0x8644},834{0x0088, 0x8645},835{0x009b, 0x8646},836{0x00b0, 0x8647},837{0x00c5, 0x8648},838{0x00d2, 0x8649},839{0x00dc, 0x864a},840{0x00e5, 0x864b},841{0x00eb, 0x864c},842{0x00f0, 0x864d},843{0x00f6, 0x864e},844{0x00fa, 0x864f},845{0x00ff, 0x8650},846{0x0060, 0x8657},847{0x0010, 0x8658},848{0x0018, 0x8659},849{0x0005, 0x865a},850{0x0018, 0x8660},851{0x0003, 0x8509},852{0x0011, 0x850a},853{0x0032, 0x850b},854{0x0010, 0x850c},855{0x0021, 0x850d},856{0x0001, 0x8500},857{0x0000, 0x8508},858{0x0012, 0x8608},859{0x002c, 0x8609},860{0x0002, 0x860a},861{0x0039, 0x860b},862{0x00d0, 0x860c},863{0x00f7, 0x860d},864{0x00ed, 0x860e},865{0x00db, 0x860f},866{0x0039, 0x8610},867{0x0012, 0x8657},868{0x000c, 0x8619},869{0x0004, 0x861a},870{0x00a1, 0x8656},871{0x00c8, 0x8615},872{0x0032, 0x8616},873874{0x0030, 0x8112},875{0x0020, 0x8112},876{0x0020, 0x8112},877{0x000f, 0x8402},878{0x0000, 0x8403},879880{0x0090, 0x8110},881{0x0001, 0x8114},882{0x0001, 0x8114},883{0x0001, 0x8114},884{0x0003, 0x8114},885{0x0080, 0x8804},886887{0x0003, 0x8801},888{0x0012, 0x8800},889{0x0004, 0x8801},890{0x0005, 0x8800},891{0x0005, 0x8801},892{0x0047, 0x8800},893{0x0006, 0x8801},894{0x0000, 0x8800},895{0x0007, 0x8801},896{0x00c0, 0x8800},897{0x0008, 0x8801},898{0x0003, 0x8800},899{0x000a, 0x8700},900{0x000e, 0x8801},901{0x0004, 0x8800},902{0x0005, 0x8801},903{0x0047, 0x8800},904{0x0006, 0x8801},905{0x0000, 0x8800},906{0x0007, 0x8801},907{0x00c0, 0x8800},908{0x0008, 0x8801},909{0x0003, 0x8800},910{0x0013, 0x8801},911{0x0001, 0x8800},912{0x0009, 0x8801},913{0x0000, 0x8800},914{0x000a, 0x8801},915{0x0000, 0x8800},916{0x000b, 0x8801},917{0x0000, 0x8800},918{0x000c, 0x8801},919{0x0000, 0x8800},920{0x000e, 0x8801},921{0x0004, 0x8800},922{0x000f, 0x8801},923{0x0000, 0x8800},924{0x0010, 0x8801},925{0x0006, 0x8800},926{0x0011, 0x8801},927{0x0006, 0x8800},928{0x0012, 0x8801},929{0x0000, 0x8800},930{0x0013, 0x8801},931{0x0001, 0x8800},932{0x000a, 0x8700},933{0x0000, 0x8702},934{0x0000, 0x8703},935{0x00c2, 0x8704},936{0x0001, 0x870c},937{0x0044, 0x8600},938{0x0002, 0x8606},939{0x0064, 0x8607},940{0x003a, 0x8601},941{0x0008, 0x8602},942{0x0044, 0x8600},943{0x0018, 0x8617},944{0x0008, 0x8618},945{0x00a1, 0x8656},946{0x0004, 0x865b},947{0x0002, 0x865c},948{0x0058, 0x865d},949{0x0048, 0x865e},950{0x0012, 0x8608},951{0x002c, 0x8609},952{0x0002, 0x860a},953{0x002c, 0x860b},954{0x00db, 0x860c},955{0x00f9, 0x860d},956{0x00f1, 0x860e},957{0x00e3, 0x860f},958{0x002c, 0x8610},959{0x006c, 0x8651},960{0x0041, 0x8652},961{0x0059, 0x8653},962{0x0040, 0x8654},963{0x00fa, 0x8611},964{0x00ff, 0x8612},965{0x00f8, 0x8613},966{0x0000, 0x8614},967{0x0001, 0x863f},968{0x0000, 0x8640},969{0x0026, 0x8641},970{0x0045, 0x8642},971{0x0060, 0x8643},972{0x0075, 0x8644},973{0x0088, 0x8645},974{0x009b, 0x8646},975{0x00b0, 0x8647},976{0x00c5, 0x8648},977{0x00d2, 0x8649},978{0x00dc, 0x864a},979{0x00e5, 0x864b},980{0x00eb, 0x864c},981{0x00f0, 0x864d},982{0x00f6, 0x864e},983{0x00fa, 0x864f},984{0x00ff, 0x8650},985{0x0060, 0x8657},986{0x0010, 0x8658},987{0x0018, 0x8659},988{0x0005, 0x865a},989{0x0018, 0x8660},990{0x0003, 0x8509},991{0x0011, 0x850a},992{0x0032, 0x850b},993{0x0010, 0x850c},994{0x0021, 0x850d},995{0x0001, 0x8500},996{0x0000, 0x8508},997998{0x0012, 0x8608},999{0x002c, 0x8609},1000{0x0002, 0x860a},1001{0x0039, 0x860b},1002{0x00d0, 0x860c},1003{0x00f7, 0x860d},1004{0x00ed, 0x860e},1005{0x00db, 0x860f},1006{0x0039, 0x8610},1007{0x0012, 0x8657},1008{0x0064, 0x8619},10091010/* This line starts it all, it is not needed here */1011/* since it has been build into the driver */1012/* jfm: don't start now */1013/* {0x0030, 0x8112}, */1014{}1015};10161017/*1018* Initialization data for Creative Webcam Vista1019*/1020static const u16 spca508_vista_init_data[][2] = {1021{0x0008, 0x8200}, /* Clear register */1022{0x0000, 0x870b}, /* Reset CTL3 */1023{0x0020, 0x8112}, /* Video Drop packet enable */1024{0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */1025{0x0000, 0x8110}, /* Disable everything */1026{0x0000, 0x8114}, /* Software GPIO output data */1027{0x0000, 0x8114},10281029{0x0003, 0x8111},1030{0x0000, 0x8111},1031{0x0090, 0x8110}, /* Enable: SSI output, External 2X clock output */1032{0x0020, 0x8112},1033{0x0000, 0x8114},1034{0x0001, 0x8114},1035{0x0001, 0x8114},1036{0x0001, 0x8114},1037{0x0003, 0x8114},10381039{0x000f, 0x8402}, /* Memory bank Address */1040{0x0000, 0x8403}, /* Memory bank Address */1041{0x00ba, 0x8804}, /* SSI Slave address */1042{0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */10431044/* READ { 0x0001, 0x8803 } -> 0000: 00 */1045/* READ { 0x0001, 0x8802 } -> 0000: 10 */1046{0x0010, 0x8802}, /* Will write 2 bytes (DATA1+DATA2) */1047{0x0020, 0x8801}, /* Register address for SSI read/write */1048{0x0044, 0x8805}, /* DATA2 */1049{0x0004, 0x8800}, /* DATA1 -> write triggered */1050/* READ { 0x0001, 0x8803 } -> 0000: 00 */10511052/* READ { 0x0001, 0x8803 } -> 0000: 00 */1053/* READ { 0x0001, 0x8802 } -> 0000: 10 */1054{0x0010, 0x8802},1055{0x0009, 0x8801},1056{0x0042, 0x8805},1057{0x0001, 0x8800},1058/* READ { 0x0001, 0x8803 } -> 0000: 00 */10591060/* READ { 0x0001, 0x8803 } -> 0000: 00 */1061/* READ { 0x0001, 0x8802 } -> 0000: 10 */1062{0x0010, 0x8802},1063{0x003c, 0x8801},1064{0x0001, 0x8805},1065{0x0000, 0x8800},1066/* READ { 0x0001, 0x8803 } -> 0000: 00 */10671068/* READ { 0x0001, 0x8803 } -> 0000: 00 */1069/* READ { 0x0001, 0x8802 } -> 0000: 10 */1070{0x0010, 0x8802},1071{0x0001, 0x8801},1072{0x000a, 0x8805},1073{0x0000, 0x8800},1074/* READ { 0x0001, 0x8803 } -> 0000: 00 */10751076/* READ { 0x0001, 0x8803 } -> 0000: 00 */1077/* READ { 0x0001, 0x8802 } -> 0000: 10 */1078{0x0010, 0x8802},1079{0x0002, 0x8801},1080{0x0000, 0x8805},1081{0x0000, 0x8800},1082/* READ { 0x0001, 0x8803 } -> 0000: 00 */10831084/* READ { 0x0001, 0x8803 } -> 0000: 00 */1085/* READ { 0x0001, 0x8802 } -> 0000: 10 */1086{0x0010, 0x8802},1087{0x0003, 0x8801},1088{0x0027, 0x8805},1089{0x0001, 0x8800},1090/* READ { 0x0001, 0x8803 } -> 0000: 00 */10911092/* READ { 0x0001, 0x8803 } -> 0000: 00 */1093/* READ { 0x0001, 0x8802 } -> 0000: 10 */1094{0x0010, 0x8802},1095{0x0004, 0x8801},1096{0x0065, 0x8805},1097{0x0001, 0x8800},1098/* READ { 0x0001, 0x8803 } -> 0000: 00 */10991100/* READ { 0x0001, 0x8803 } -> 0000: 00 */1101/* READ { 0x0001, 0x8802 } -> 0000: 10 */1102{0x0010, 0x8802},1103{0x0005, 0x8801},1104{0x0003, 0x8805},1105{0x0000, 0x8800},1106/* READ { 0x0001, 0x8803 } -> 0000: 00 */11071108/* READ { 0x0001, 0x8803 } -> 0000: 00 */1109/* READ { 0x0001, 0x8802 } -> 0000: 10 */1110{0x0010, 0x8802},1111{0x0006, 0x8801},1112{0x001c, 0x8805},1113{0x0000, 0x8800},1114/* READ { 0x0001, 0x8803 } -> 0000: 00 */11151116/* READ { 0x0001, 0x8803 } -> 0000: 00 */1117/* READ { 0x0001, 0x8802 } -> 0000: 10 */1118{0x0010, 0x8802},1119{0x0007, 0x8801},1120{0x002a, 0x8805},1121{0x0000, 0x8800},1122/* READ { 0x0001, 0x8803 } -> 0000: 00 */11231124/* READ { 0x0001, 0x8803 } -> 0000: 00 */1125/* READ { 0x0001, 0x8802 } -> 0000: 10 */1126{0x0010, 0x8802},1127{0x000e, 0x8801},1128{0x0000, 0x8805},1129{0x0000, 0x8800},1130/* READ { 0x0001, 0x8803 } -> 0000: 00 */11311132/* READ { 0x0001, 0x8803 } -> 0000: 00 */1133/* READ { 0x0001, 0x8802 } -> 0000: 10 */1134{0x0010, 0x8802},1135{0x0028, 0x8801},1136{0x002e, 0x8805},1137{0x0000, 0x8800},1138/* READ { 0x0001, 0x8803 } -> 0000: 00 */11391140/* READ { 0x0001, 0x8803 } -> 0000: 00 */1141/* READ { 0x0001, 0x8802 } -> 0000: 10 */1142{0x0010, 0x8802},1143{0x0039, 0x8801},1144{0x0013, 0x8805},1145{0x0000, 0x8800},1146/* READ { 0x0001, 0x8803 } -> 0000: 00 */11471148/* READ { 0x0001, 0x8803 } -> 0000: 00 */1149/* READ { 0x0001, 0x8802 } -> 0000: 10 */1150{0x0010, 0x8802},1151{0x003b, 0x8801},1152{0x000c, 0x8805},1153{0x0000, 0x8800},1154/* READ { 0x0001, 0x8803 } -> 0000: 00 */11551156/* READ { 0x0001, 0x8803 } -> 0000: 00 */1157/* READ { 0x0001, 0x8802 } -> 0000: 10 */1158{0x0010, 0x8802},1159{0x0035, 0x8801},1160{0x0028, 0x8805},1161{0x0000, 0x8800},1162/* READ { 0x0001, 0x8803 } -> 0000: 00 */11631164/* READ { 0x0001, 0x8803 } -> 0000: 00 */1165/* READ { 0x0001, 0x8802 } -> 0000: 10 */1166{0x0010, 0x8802},1167{0x0009, 0x8801},1168{0x0042, 0x8805},1169{0x0001, 0x8800},1170/* READ { 0x0001, 0x8803 } -> 0000: 00 */11711172{0x0050, 0x8703},1173{0x0002, 0x8704}, /* External input CKIx1 */1174{0x0001, 0x870c}, /* Select CKOx2 output */1175{0x009a, 0x8600}, /* Line memory Read Counter (L) */1176{0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */1177{0x0023, 0x8601},1178{0x0010, 0x8602},1179{0x000a, 0x8603},1180{0x009a, 0x8600},1181{0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */1182{0x0003, 0x865c}, /* Vertical offset for valid lines (L) */1183{0x0058, 0x865d}, /* Horizontal valid pixels window (L) */1184{0x0048, 0x865e}, /* Vertical valid lines window (L) */1185{0x0000, 0x865f},11861187{0x0006, 0x8660},1188/* Enable nibble data input, select nibble input order */11891190{0x0013, 0x8608}, /* A11 Coeficients for color correction */1191{0x0028, 0x8609},1192/* Note: these values are confirmed at the end of array */1193{0x0005, 0x860a}, /* ... */1194{0x0025, 0x860b},1195{0x00e1, 0x860c},1196{0x00fa, 0x860d},1197{0x00f4, 0x860e},1198{0x00e8, 0x860f},1199{0x0025, 0x8610}, /* A33 Coef. */1200{0x00fc, 0x8611}, /* White balance offset: R */1201{0x0001, 0x8612}, /* White balance offset: Gr */1202{0x00fe, 0x8613}, /* White balance offset: B */1203{0x0000, 0x8614}, /* White balance offset: Gb */12041205{0x0064, 0x8651}, /* R gain for white balance (L) */1206{0x0040, 0x8652}, /* Gr gain for white balance (L) */1207{0x0066, 0x8653}, /* B gain for white balance (L) */1208{0x0040, 0x8654}, /* Gb gain for white balance (L) */1209{0x0001, 0x863f}, /* Enable fixed gamma correction */12101211{0x00a1, 0x8656}, /* Size - Window1: 256x256, Window2: 128x128,1212* UV division: UV no change,1213* Enable New edge enhancement */1214{0x0018, 0x8657}, /* Edge gain high threshold */1215{0x0020, 0x8658}, /* Edge gain low threshold */1216{0x000a, 0x8659}, /* Edge bandwidth high threshold */1217{0x0005, 0x865a}, /* Edge bandwidth low threshold */1218{0x0064, 0x8607}, /* UV filter enable */12191220{0x0016, 0x8660},1221{0x0000, 0x86b0}, /* Bad pixels compensation address */1222{0x00dc, 0x86b1}, /* X coord for bad pixels compensation (L) */1223{0x0000, 0x86b2},1224{0x0009, 0x86b3}, /* Y coord for bad pixels compensation (L) */1225{0x0000, 0x86b4},12261227{0x0001, 0x86b0},1228{0x00f5, 0x86b1},1229{0x0000, 0x86b2},1230{0x00c6, 0x86b3},1231{0x0000, 0x86b4},12321233{0x0002, 0x86b0},1234{0x001c, 0x86b1},1235{0x0001, 0x86b2},1236{0x00d7, 0x86b3},1237{0x0000, 0x86b4},12381239{0x0003, 0x86b0},1240{0x001c, 0x86b1},1241{0x0001, 0x86b2},1242{0x00d8, 0x86b3},1243{0x0000, 0x86b4},12441245{0x0004, 0x86b0},1246{0x001d, 0x86b1},1247{0x0001, 0x86b2},1248{0x00d8, 0x86b3},1249{0x0000, 0x86b4},1250{0x001e, 0x8660},12511252/* READ { 0x0000, 0x8608 } -> 0000: 13 */1253/* READ { 0x0000, 0x8609 } -> 0000: 28 */1254/* READ { 0x0000, 0x8610 } -> 0000: 05 */1255/* READ { 0x0000, 0x8611 } -> 0000: 25 */1256/* READ { 0x0000, 0x8612 } -> 0000: e1 */1257/* READ { 0x0000, 0x8613 } -> 0000: fa */1258/* READ { 0x0000, 0x8614 } -> 0000: f4 */1259/* READ { 0x0000, 0x8615 } -> 0000: e8 */1260/* READ { 0x0000, 0x8616 } -> 0000: 25 */1261{}1262};12631264static int reg_write(struct usb_device *dev,1265u16 index, u16 value)1266{1267int ret;12681269ret = usb_control_msg(dev,1270usb_sndctrlpipe(dev, 0),12710, /* request */1272USB_TYPE_VENDOR | USB_RECIP_DEVICE,1273value, index, NULL, 0, 500);1274PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",1275index, value);1276if (ret < 0)1277err("reg write: error %d", ret);1278return ret;1279}12801281/* read 1 byte */1282/* returns: negative is error, pos or zero is data */1283static int reg_read(struct gspca_dev *gspca_dev,1284u16 index) /* wIndex */1285{1286int ret;12871288ret = usb_control_msg(gspca_dev->dev,1289usb_rcvctrlpipe(gspca_dev->dev, 0),12900, /* register */1291USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,12920, /* value */1293index,1294gspca_dev->usb_buf, 1,1295500); /* timeout */1296PDEBUG(D_USBI, "reg read i:%04x --> %02x",1297index, gspca_dev->usb_buf[0]);1298if (ret < 0) {1299err("reg_read err %d", ret);1300return ret;1301}1302return gspca_dev->usb_buf[0];1303}13041305/* send 1 or 2 bytes to the sensor via the Synchronous Serial Interface */1306static int ssi_w(struct gspca_dev *gspca_dev,1307u16 reg, u16 val)1308{1309struct usb_device *dev = gspca_dev->dev;1310int ret, retry;13111312ret = reg_write(dev, 0x8802, reg >> 8);1313if (ret < 0)1314goto out;1315ret = reg_write(dev, 0x8801, reg & 0x00ff);1316if (ret < 0)1317goto out;1318if ((reg & 0xff00) == 0x1000) { /* if 2 bytes */1319ret = reg_write(dev, 0x8805, val & 0x00ff);1320if (ret < 0)1321goto out;1322val >>= 8;1323}1324ret = reg_write(dev, 0x8800, val);1325if (ret < 0)1326goto out;13271328/* poll until not busy */1329retry = 10;1330for (;;) {1331ret = reg_read(gspca_dev, 0x8803);1332if (ret < 0)1333break;1334if (gspca_dev->usb_buf[0] == 0)1335break;1336if (--retry <= 0) {1337PDEBUG(D_ERR, "ssi_w busy %02x",1338gspca_dev->usb_buf[0]);1339ret = -1;1340break;1341}1342msleep(8);1343}13441345out:1346return ret;1347}13481349static int write_vector(struct gspca_dev *gspca_dev,1350const u16 (*data)[2])1351{1352struct usb_device *dev = gspca_dev->dev;1353int ret = 0;13541355while ((*data)[1] != 0) {1356if ((*data)[1] & 0x8000) {1357if ((*data)[1] == 0xdd00) /* delay */1358msleep((*data)[0]);1359else1360ret = reg_write(dev, (*data)[1], (*data)[0]);1361} else {1362ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]);1363}1364if (ret < 0)1365break;1366data++;1367}1368return ret;1369}13701371/* this function is called at probe time */1372static int sd_config(struct gspca_dev *gspca_dev,1373const struct usb_device_id *id)1374{1375struct sd *sd = (struct sd *) gspca_dev;1376struct cam *cam;1377const u16 (*init_data)[2];1378static const u16 (*(init_data_tb[]))[2] = {1379spca508_vista_init_data, /* CreativeVista 0 */1380spca508_sightcam_init_data, /* HamaUSBSightcam 1 */1381spca508_sightcam2_init_data, /* HamaUSBSightcam2 2 */1382spca508cs110_init_data, /* IntelEasyPCCamera 3 */1383spca508cs110_init_data, /* MicroInnovationIC200 4 */1384spca508_init_data, /* ViewQuestVQ110 5 */1385};13861387#ifdef GSPCA_DEBUG1388int data1, data2;13891390/* Read from global register the USB product and vendor IDs, just to1391* prove that we can communicate with the device. This works, which1392* confirms at we are communicating properly and that the device1393* is a 508. */1394data1 = reg_read(gspca_dev, 0x8104);1395data2 = reg_read(gspca_dev, 0x8105);1396PDEBUG(D_PROBE, "Webcam Vendor ID: 0x%02x%02x", data2, data1);13971398data1 = reg_read(gspca_dev, 0x8106);1399data2 = reg_read(gspca_dev, 0x8107);1400PDEBUG(D_PROBE, "Webcam Product ID: 0x%02x%02x", data2, data1);14011402data1 = reg_read(gspca_dev, 0x8621);1403PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);1404#endif14051406cam = &gspca_dev->cam;1407cam->cam_mode = sif_mode;1408cam->nmodes = ARRAY_SIZE(sif_mode);14091410sd->subtype = id->driver_info;1411sd->brightness = BRIGHTNESS_DEF;14121413init_data = init_data_tb[sd->subtype];1414return write_vector(gspca_dev, init_data);1415}14161417/* this function is called at probe and resume time */1418static int sd_init(struct gspca_dev *gspca_dev)1419{1420return 0;1421}14221423static int sd_start(struct gspca_dev *gspca_dev)1424{1425int mode;14261427mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;1428reg_write(gspca_dev->dev, 0x8500, mode);1429switch (mode) {1430case 0:1431case 1:1432reg_write(gspca_dev->dev, 0x8700, 0x28); /* clock */1433break;1434default:1435/* case 2: */1436/* case 3: */1437reg_write(gspca_dev->dev, 0x8700, 0x23); /* clock */1438break;1439}1440reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);1441return 0;1442}14431444static void sd_stopN(struct gspca_dev *gspca_dev)1445{1446/* Video ISO disable, Video Drop Packet enable: */1447reg_write(gspca_dev->dev, 0x8112, 0x20);1448}14491450static void sd_pkt_scan(struct gspca_dev *gspca_dev,1451u8 *data, /* isoc packet */1452int len) /* iso packet length */1453{1454switch (data[0]) {1455case 0: /* start of frame */1456gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);1457data += SPCA508_OFFSET_DATA;1458len -= SPCA508_OFFSET_DATA;1459gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);1460break;1461case 0xff: /* drop */1462break;1463default:1464data += 1;1465len -= 1;1466gspca_frame_add(gspca_dev, INTER_PACKET, data, len);1467break;1468}1469}14701471static void setbrightness(struct gspca_dev *gspca_dev)1472{1473struct sd *sd = (struct sd *) gspca_dev;1474u8 brightness = sd->brightness;14751476/* MX seem contrast */1477reg_write(gspca_dev->dev, 0x8651, brightness);1478reg_write(gspca_dev->dev, 0x8652, brightness);1479reg_write(gspca_dev->dev, 0x8653, brightness);1480reg_write(gspca_dev->dev, 0x8654, brightness);1481}14821483static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)1484{1485struct sd *sd = (struct sd *) gspca_dev;14861487sd->brightness = val;1488if (gspca_dev->streaming)1489setbrightness(gspca_dev);1490return 0;1491}14921493static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)1494{1495struct sd *sd = (struct sd *) gspca_dev;14961497*val = sd->brightness;1498return 0;1499}15001501/* sub-driver description */1502static const struct sd_desc sd_desc = {1503.name = MODULE_NAME,1504.ctrls = sd_ctrls,1505.nctrls = ARRAY_SIZE(sd_ctrls),1506.config = sd_config,1507.init = sd_init,1508.start = sd_start,1509.stopN = sd_stopN,1510.pkt_scan = sd_pkt_scan,1511};15121513/* -- module initialisation -- */1514static const struct usb_device_id device_table[] = {1515{USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},1516{USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista},1517{USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},1518{USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam},1519{USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2},1520{USB_DEVICE(0x8086, 0x0110), .driver_info = IntelEasyPCCamera},1521{}1522};1523MODULE_DEVICE_TABLE(usb, device_table);15241525/* -- device connect -- */1526static int sd_probe(struct usb_interface *intf,1527const struct usb_device_id *id)1528{1529return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),1530THIS_MODULE);1531}15321533static struct usb_driver sd_driver = {1534.name = MODULE_NAME,1535.id_table = device_table,1536.probe = sd_probe,1537.disconnect = gspca_disconnect,1538#ifdef CONFIG_PM1539.suspend = gspca_suspend,1540.resume = gspca_resume,1541#endif1542};15431544/* -- module insert / remove -- */1545static int __init sd_mod_init(void)1546{1547return usb_register(&sd_driver);1548}1549static void __exit sd_mod_exit(void)1550{1551usb_deregister(&sd_driver);1552}15531554module_init(sd_mod_init);1555module_exit(sd_mod_exit);155615571558