Path: blob/master/drivers/media/video/gspca/spca506.c
17602 views
/*1* SPCA506 chip based cameras function2* M Xhaard 15/04/2004 based on different work Mark Taylor and others3* and my own snoopy file on a pv-321c donate by a german compagny4* "Firma Frank Gmbh" from Saarbruecken5*6* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>7*8* This program is free software; you can redistribute it and/or modify9* it under the terms of the GNU General Public License as published by10* the Free Software Foundation; either version 2 of the License, or11* any later version.12*13* This program is distributed in the hope that it will be useful,14* but WITHOUT ANY WARRANTY; without even the implied warranty of15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the16* GNU General Public License for more details.17*18* You should have received a copy of the GNU General Public License19* along with this program; if not, write to the Free Software20* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA21*/2223#define MODULE_NAME "spca506"2425#include "gspca.h"2627MODULE_AUTHOR("Michel Xhaard <[email protected]>");28MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver");29MODULE_LICENSE("GPL");3031/* specific webcam descriptor */32struct sd {33struct gspca_dev gspca_dev; /* !! must be the first item */3435unsigned char brightness;36unsigned char contrast;37unsigned char colors;38unsigned char hue;39char norme;40char channel;41};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);46static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);47static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);48static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);49static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);50static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);51static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);5253static const struct ctrl sd_ctrls[] = {54#define SD_BRIGHTNESS 055{56{57.id = V4L2_CID_BRIGHTNESS,58.type = V4L2_CTRL_TYPE_INTEGER,59.name = "Brightness",60.minimum = 0,61.maximum = 0xff,62.step = 1,63.default_value = 0x80,64},65.set = sd_setbrightness,66.get = sd_getbrightness,67},68#define SD_CONTRAST 169{70{71.id = V4L2_CID_CONTRAST,72.type = V4L2_CTRL_TYPE_INTEGER,73.name = "Contrast",74.minimum = 0,75.maximum = 0xff,76.step = 1,77.default_value = 0x47,78},79.set = sd_setcontrast,80.get = sd_getcontrast,81},82#define SD_COLOR 283{84{85.id = V4L2_CID_SATURATION,86.type = V4L2_CTRL_TYPE_INTEGER,87.name = "Saturation",88.minimum = 0,89.maximum = 0xff,90.step = 1,91.default_value = 0x40,92},93.set = sd_setcolors,94.get = sd_getcolors,95},96#define SD_HUE 397{98{99.id = V4L2_CID_HUE,100.type = V4L2_CTRL_TYPE_INTEGER,101.name = "Hue",102.minimum = 0,103.maximum = 0xff,104.step = 1,105.default_value = 0,106},107.set = sd_sethue,108.get = sd_gethue,109},110};111112static const struct v4l2_pix_format vga_mode[] = {113{160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,114.bytesperline = 160,115.sizeimage = 160 * 120 * 3 / 2,116.colorspace = V4L2_COLORSPACE_SRGB,117.priv = 5},118{176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,119.bytesperline = 176,120.sizeimage = 176 * 144 * 3 / 2,121.colorspace = V4L2_COLORSPACE_SRGB,122.priv = 4},123{320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,124.bytesperline = 320,125.sizeimage = 320 * 240 * 3 / 2,126.colorspace = V4L2_COLORSPACE_SRGB,127.priv = 2},128{352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,129.bytesperline = 352,130.sizeimage = 352 * 288 * 3 / 2,131.colorspace = V4L2_COLORSPACE_SRGB,132.priv = 1},133{640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,134.bytesperline = 640,135.sizeimage = 640 * 480 * 3 / 2,136.colorspace = V4L2_COLORSPACE_SRGB,137.priv = 0},138};139140#define SPCA50X_OFFSET_DATA 10141142#define SAA7113_bright 0x0a /* defaults 0x80 */143#define SAA7113_contrast 0x0b /* defaults 0x47 */144#define SAA7113_saturation 0x0c /* defaults 0x40 */145#define SAA7113_hue 0x0d /* defaults 0x00 */146#define SAA7113_I2C_BASE_WRITE 0x4a147148/* read 'len' bytes to gspca_dev->usb_buf */149static void reg_r(struct gspca_dev *gspca_dev,150__u16 req,151__u16 index,152__u16 length)153{154usb_control_msg(gspca_dev->dev,155usb_rcvctrlpipe(gspca_dev->dev, 0),156req,157USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,1580, /* value */159index, gspca_dev->usb_buf, length,160500);161}162163static void reg_w(struct usb_device *dev,164__u16 req,165__u16 value,166__u16 index)167{168usb_control_msg(dev,169usb_sndctrlpipe(dev, 0),170req,171USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,172value, index,173NULL, 0, 500);174}175176static void spca506_Initi2c(struct gspca_dev *gspca_dev)177{178reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);179}180181static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur,182__u16 reg)183{184int retry = 60;185186reg_w(gspca_dev->dev, 0x07, reg, 0x0001);187reg_w(gspca_dev->dev, 0x07, valeur, 0x0000);188while (retry--) {189reg_r(gspca_dev, 0x07, 0x0003, 2);190if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00)191break;192}193}194195static void spca506_SetNormeInput(struct gspca_dev *gspca_dev,196__u16 norme,197__u16 channel)198{199struct sd *sd = (struct sd *) gspca_dev;200/* fixme: check if channel == 0..3 and 6..9 (8 values) */201__u8 setbit0 = 0x00;202__u8 setbit1 = 0x00;203__u8 videomask = 0x00;204205PDEBUG(D_STREAM, "** Open Set Norme **");206spca506_Initi2c(gspca_dev);207/* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */208/* Composite channel bit1 -> 1 S-video bit 1 -> 0 */209/* and exclude SAA7113 reserved channel set default 0 otherwise */210if (norme & V4L2_STD_NTSC)211setbit0 = 0x01;212if (channel == 4 || channel == 5 || channel > 9)213channel = 0;214if (channel < 4)215setbit1 = 0x02;216videomask = (0x48 | setbit0 | setbit1);217reg_w(gspca_dev->dev, 0x08, videomask, 0x0000);218spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02);219220if (norme & V4L2_STD_NTSC)221spca506_WriteI2c(gspca_dev, 0x33, 0x0e);222/* Chrominance Control NTSC N */223else if (norme & V4L2_STD_SECAM)224spca506_WriteI2c(gspca_dev, 0x53, 0x0e);225/* Chrominance Control SECAM */226else227spca506_WriteI2c(gspca_dev, 0x03, 0x0e);228/* Chrominance Control PAL BGHIV */229230sd->norme = norme;231sd->channel = channel;232PDEBUG(D_STREAM, "Set Video Byte to 0x%2x", videomask);233PDEBUG(D_STREAM, "Set Norme: %08x Channel %d", norme, channel);234}235236static void spca506_GetNormeInput(struct gspca_dev *gspca_dev,237__u16 *norme, __u16 *channel)238{239struct sd *sd = (struct sd *) gspca_dev;240241/* Read the register is not so good value change so242we use your own copy in spca50x struct */243*norme = sd->norme;244*channel = sd->channel;245PDEBUG(D_STREAM, "Get Norme: %d Channel %d", *norme, *channel);246}247248static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code,249__u16 xmult, __u16 ymult)250{251struct usb_device *dev = gspca_dev->dev;252253PDEBUG(D_STREAM, "** SetSize **");254reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000);255/* Soft snap 0x40 Hard 0x41 */256reg_w(dev, 0x04, 0x41, 0x0001);257reg_w(dev, 0x04, 0x00, 0x0002);258/* reserved */259reg_w(dev, 0x04, 0x00, 0x0003);260261/* reserved */262reg_w(dev, 0x04, 0x00, 0x0004);263/* reserved */264reg_w(dev, 0x04, 0x01, 0x0005);265/* reserced */266reg_w(dev, 0x04, xmult, 0x0006);267/* reserved */268reg_w(dev, 0x04, ymult, 0x0007);269/* compression 1 */270reg_w(dev, 0x04, 0x00, 0x0008);271/* T=64 -> 2 */272reg_w(dev, 0x04, 0x00, 0x0009);273/* threshold2D */274reg_w(dev, 0x04, 0x21, 0x000a);275/* quantization */276reg_w(dev, 0x04, 0x00, 0x000b);277}278279/* this function is called at probe time */280static int sd_config(struct gspca_dev *gspca_dev,281const struct usb_device_id *id)282{283struct sd *sd = (struct sd *) gspca_dev;284struct cam *cam;285286cam = &gspca_dev->cam;287cam->cam_mode = vga_mode;288cam->nmodes = ARRAY_SIZE(vga_mode);289sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;290sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;291sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;292sd->hue = sd_ctrls[SD_HUE].qctrl.default_value;293return 0;294}295296/* this function is called at probe and resume time */297static int sd_init(struct gspca_dev *gspca_dev)298{299struct usb_device *dev = gspca_dev->dev;300301reg_w(dev, 0x03, 0x00, 0x0004);302reg_w(dev, 0x03, 0xFF, 0x0003);303reg_w(dev, 0x03, 0x00, 0x0000);304reg_w(dev, 0x03, 0x1c, 0x0001);305reg_w(dev, 0x03, 0x18, 0x0001);306/* Init on PAL and composite input0 */307spca506_SetNormeInput(gspca_dev, 0, 0);308reg_w(dev, 0x03, 0x1c, 0x0001);309reg_w(dev, 0x03, 0x18, 0x0001);310reg_w(dev, 0x05, 0x00, 0x0000);311reg_w(dev, 0x05, 0xef, 0x0001);312reg_w(dev, 0x05, 0x00, 0x00c1);313reg_w(dev, 0x05, 0x00, 0x00c2);314reg_w(dev, 0x06, 0x18, 0x0002);315reg_w(dev, 0x06, 0xf5, 0x0011);316reg_w(dev, 0x06, 0x02, 0x0012);317reg_w(dev, 0x06, 0xfb, 0x0013);318reg_w(dev, 0x06, 0x00, 0x0014);319reg_w(dev, 0x06, 0xa4, 0x0051);320reg_w(dev, 0x06, 0x40, 0x0052);321reg_w(dev, 0x06, 0x71, 0x0053);322reg_w(dev, 0x06, 0x40, 0x0054);323/************************************************/324reg_w(dev, 0x03, 0x00, 0x0004);325reg_w(dev, 0x03, 0x00, 0x0003);326reg_w(dev, 0x03, 0x00, 0x0004);327reg_w(dev, 0x03, 0xFF, 0x0003);328reg_w(dev, 0x02, 0x00, 0x0000);329reg_w(dev, 0x03, 0x60, 0x0000);330reg_w(dev, 0x03, 0x18, 0x0001);331/* for a better reading mx :) */332/*sdca506_WriteI2c(value,register) */333spca506_Initi2c(gspca_dev);334spca506_WriteI2c(gspca_dev, 0x08, 0x01);335spca506_WriteI2c(gspca_dev, 0xc0, 0x02);336/* input composite video */337spca506_WriteI2c(gspca_dev, 0x33, 0x03);338spca506_WriteI2c(gspca_dev, 0x00, 0x04);339spca506_WriteI2c(gspca_dev, 0x00, 0x05);340spca506_WriteI2c(gspca_dev, 0x0d, 0x06);341spca506_WriteI2c(gspca_dev, 0xf0, 0x07);342spca506_WriteI2c(gspca_dev, 0x98, 0x08);343spca506_WriteI2c(gspca_dev, 0x03, 0x09);344spca506_WriteI2c(gspca_dev, 0x80, 0x0a);345spca506_WriteI2c(gspca_dev, 0x47, 0x0b);346spca506_WriteI2c(gspca_dev, 0x48, 0x0c);347spca506_WriteI2c(gspca_dev, 0x00, 0x0d);348spca506_WriteI2c(gspca_dev, 0x03, 0x0e); /* Chroma Pal adjust */349spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);350spca506_WriteI2c(gspca_dev, 0x00, 0x10);351spca506_WriteI2c(gspca_dev, 0x0c, 0x11);352spca506_WriteI2c(gspca_dev, 0xb8, 0x12);353spca506_WriteI2c(gspca_dev, 0x01, 0x13);354spca506_WriteI2c(gspca_dev, 0x00, 0x14);355spca506_WriteI2c(gspca_dev, 0x00, 0x15);356spca506_WriteI2c(gspca_dev, 0x00, 0x16);357spca506_WriteI2c(gspca_dev, 0x00, 0x17);358spca506_WriteI2c(gspca_dev, 0x00, 0x18);359spca506_WriteI2c(gspca_dev, 0x00, 0x19);360spca506_WriteI2c(gspca_dev, 0x00, 0x1a);361spca506_WriteI2c(gspca_dev, 0x00, 0x1b);362spca506_WriteI2c(gspca_dev, 0x00, 0x1c);363spca506_WriteI2c(gspca_dev, 0x00, 0x1d);364spca506_WriteI2c(gspca_dev, 0x00, 0x1e);365spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);366spca506_WriteI2c(gspca_dev, 0x02, 0x40);367spca506_WriteI2c(gspca_dev, 0xff, 0x41);368spca506_WriteI2c(gspca_dev, 0xff, 0x42);369spca506_WriteI2c(gspca_dev, 0xff, 0x43);370spca506_WriteI2c(gspca_dev, 0xff, 0x44);371spca506_WriteI2c(gspca_dev, 0xff, 0x45);372spca506_WriteI2c(gspca_dev, 0xff, 0x46);373spca506_WriteI2c(gspca_dev, 0xff, 0x47);374spca506_WriteI2c(gspca_dev, 0xff, 0x48);375spca506_WriteI2c(gspca_dev, 0xff, 0x49);376spca506_WriteI2c(gspca_dev, 0xff, 0x4a);377spca506_WriteI2c(gspca_dev, 0xff, 0x4b);378spca506_WriteI2c(gspca_dev, 0xff, 0x4c);379spca506_WriteI2c(gspca_dev, 0xff, 0x4d);380spca506_WriteI2c(gspca_dev, 0xff, 0x4e);381spca506_WriteI2c(gspca_dev, 0xff, 0x4f);382spca506_WriteI2c(gspca_dev, 0xff, 0x50);383spca506_WriteI2c(gspca_dev, 0xff, 0x51);384spca506_WriteI2c(gspca_dev, 0xff, 0x52);385spca506_WriteI2c(gspca_dev, 0xff, 0x53);386spca506_WriteI2c(gspca_dev, 0xff, 0x54);387spca506_WriteI2c(gspca_dev, 0xff, 0x55);388spca506_WriteI2c(gspca_dev, 0xff, 0x56);389spca506_WriteI2c(gspca_dev, 0xff, 0x57);390spca506_WriteI2c(gspca_dev, 0x00, 0x58);391spca506_WriteI2c(gspca_dev, 0x54, 0x59);392spca506_WriteI2c(gspca_dev, 0x07, 0x5a);393spca506_WriteI2c(gspca_dev, 0x83, 0x5b);394spca506_WriteI2c(gspca_dev, 0x00, 0x5c);395spca506_WriteI2c(gspca_dev, 0x00, 0x5d);396spca506_WriteI2c(gspca_dev, 0x00, 0x5e);397spca506_WriteI2c(gspca_dev, 0x00, 0x5f);398spca506_WriteI2c(gspca_dev, 0x00, 0x60);399spca506_WriteI2c(gspca_dev, 0x05, 0x61);400spca506_WriteI2c(gspca_dev, 0x9f, 0x62);401PDEBUG(D_STREAM, "** Close Init *");402return 0;403}404405static int sd_start(struct gspca_dev *gspca_dev)406{407struct usb_device *dev = gspca_dev->dev;408__u16 norme;409__u16 channel;410411/**************************************/412reg_w(dev, 0x03, 0x00, 0x0004);413reg_w(dev, 0x03, 0x00, 0x0003);414reg_w(dev, 0x03, 0x00, 0x0004);415reg_w(dev, 0x03, 0xFF, 0x0003);416reg_w(dev, 0x02, 0x00, 0x0000);417reg_w(dev, 0x03, 0x60, 0x0000);418reg_w(dev, 0x03, 0x18, 0x0001);419420/*sdca506_WriteI2c(value,register) */421spca506_Initi2c(gspca_dev);422spca506_WriteI2c(gspca_dev, 0x08, 0x01); /* Increment Delay */423/* spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */424spca506_WriteI2c(gspca_dev, 0x33, 0x03);425/* Analog Input Control 2 */426spca506_WriteI2c(gspca_dev, 0x00, 0x04);427/* Analog Input Control 3 */428spca506_WriteI2c(gspca_dev, 0x00, 0x05);429/* Analog Input Control 4 */430spca506_WriteI2c(gspca_dev, 0x0d, 0x06);431/* Horizontal Sync Start 0xe9-0x0d */432spca506_WriteI2c(gspca_dev, 0xf0, 0x07);433/* Horizontal Sync Stop 0x0d-0xf0 */434435spca506_WriteI2c(gspca_dev, 0x98, 0x08); /* Sync Control */436/* Defaults value */437spca506_WriteI2c(gspca_dev, 0x03, 0x09); /* Luminance Control */438spca506_WriteI2c(gspca_dev, 0x80, 0x0a);439/* Luminance Brightness */440spca506_WriteI2c(gspca_dev, 0x47, 0x0b); /* Luminance Contrast */441spca506_WriteI2c(gspca_dev, 0x48, 0x0c);442/* Chrominance Saturation */443spca506_WriteI2c(gspca_dev, 0x00, 0x0d);444/* Chrominance Hue Control */445spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);446/* Chrominance Gain Control */447/**************************************/448spca506_WriteI2c(gspca_dev, 0x00, 0x10);449/* Format/Delay Control */450spca506_WriteI2c(gspca_dev, 0x0c, 0x11); /* Output Control 1 */451spca506_WriteI2c(gspca_dev, 0xb8, 0x12); /* Output Control 2 */452spca506_WriteI2c(gspca_dev, 0x01, 0x13); /* Output Control 3 */453spca506_WriteI2c(gspca_dev, 0x00, 0x14); /* reserved */454spca506_WriteI2c(gspca_dev, 0x00, 0x15); /* VGATE START */455spca506_WriteI2c(gspca_dev, 0x00, 0x16); /* VGATE STOP */456spca506_WriteI2c(gspca_dev, 0x00, 0x17); /* VGATE Control (MSB) */457spca506_WriteI2c(gspca_dev, 0x00, 0x18);458spca506_WriteI2c(gspca_dev, 0x00, 0x19);459spca506_WriteI2c(gspca_dev, 0x00, 0x1a);460spca506_WriteI2c(gspca_dev, 0x00, 0x1b);461spca506_WriteI2c(gspca_dev, 0x00, 0x1c);462spca506_WriteI2c(gspca_dev, 0x00, 0x1d);463spca506_WriteI2c(gspca_dev, 0x00, 0x1e);464spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);465spca506_WriteI2c(gspca_dev, 0x02, 0x40);466spca506_WriteI2c(gspca_dev, 0xff, 0x41);467spca506_WriteI2c(gspca_dev, 0xff, 0x42);468spca506_WriteI2c(gspca_dev, 0xff, 0x43);469spca506_WriteI2c(gspca_dev, 0xff, 0x44);470spca506_WriteI2c(gspca_dev, 0xff, 0x45);471spca506_WriteI2c(gspca_dev, 0xff, 0x46);472spca506_WriteI2c(gspca_dev, 0xff, 0x47);473spca506_WriteI2c(gspca_dev, 0xff, 0x48);474spca506_WriteI2c(gspca_dev, 0xff, 0x49);475spca506_WriteI2c(gspca_dev, 0xff, 0x4a);476spca506_WriteI2c(gspca_dev, 0xff, 0x4b);477spca506_WriteI2c(gspca_dev, 0xff, 0x4c);478spca506_WriteI2c(gspca_dev, 0xff, 0x4d);479spca506_WriteI2c(gspca_dev, 0xff, 0x4e);480spca506_WriteI2c(gspca_dev, 0xff, 0x4f);481spca506_WriteI2c(gspca_dev, 0xff, 0x50);482spca506_WriteI2c(gspca_dev, 0xff, 0x51);483spca506_WriteI2c(gspca_dev, 0xff, 0x52);484spca506_WriteI2c(gspca_dev, 0xff, 0x53);485spca506_WriteI2c(gspca_dev, 0xff, 0x54);486spca506_WriteI2c(gspca_dev, 0xff, 0x55);487spca506_WriteI2c(gspca_dev, 0xff, 0x56);488spca506_WriteI2c(gspca_dev, 0xff, 0x57);489spca506_WriteI2c(gspca_dev, 0x00, 0x58);490spca506_WriteI2c(gspca_dev, 0x54, 0x59);491spca506_WriteI2c(gspca_dev, 0x07, 0x5a);492spca506_WriteI2c(gspca_dev, 0x83, 0x5b);493spca506_WriteI2c(gspca_dev, 0x00, 0x5c);494spca506_WriteI2c(gspca_dev, 0x00, 0x5d);495spca506_WriteI2c(gspca_dev, 0x00, 0x5e);496spca506_WriteI2c(gspca_dev, 0x00, 0x5f);497spca506_WriteI2c(gspca_dev, 0x00, 0x60);498spca506_WriteI2c(gspca_dev, 0x05, 0x61);499spca506_WriteI2c(gspca_dev, 0x9f, 0x62);500/**************************************/501reg_w(dev, 0x05, 0x00, 0x0003);502reg_w(dev, 0x05, 0x00, 0x0004);503reg_w(dev, 0x03, 0x10, 0x0001);504reg_w(dev, 0x03, 0x78, 0x0000);505switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {506case 0:507spca506_Setsize(gspca_dev, 0, 0x10, 0x10);508break;509case 1:510spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a);511break;512case 2:513spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c);514break;515case 4:516spca506_Setsize(gspca_dev, 4, 0x34, 0x34);517break;518default:519/* case 5: */520spca506_Setsize(gspca_dev, 5, 0x40, 0x40);521break;522}523524/* compress setting and size */525/* set i2c luma */526reg_w(dev, 0x02, 0x01, 0x0000);527reg_w(dev, 0x03, 0x12, 0x0000);528reg_r(gspca_dev, 0x04, 0x0001, 2);529PDEBUG(D_STREAM, "webcam started");530spca506_GetNormeInput(gspca_dev, &norme, &channel);531spca506_SetNormeInput(gspca_dev, norme, channel);532return 0;533}534535static void sd_stopN(struct gspca_dev *gspca_dev)536{537struct usb_device *dev = gspca_dev->dev;538539reg_w(dev, 0x02, 0x00, 0x0000);540reg_w(dev, 0x03, 0x00, 0x0004);541reg_w(dev, 0x03, 0x00, 0x0003);542}543544static void sd_pkt_scan(struct gspca_dev *gspca_dev,545u8 *data, /* isoc packet */546int len) /* iso packet length */547{548switch (data[0]) {549case 0: /* start of frame */550gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);551data += SPCA50X_OFFSET_DATA;552len -= SPCA50X_OFFSET_DATA;553gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);554break;555case 0xff: /* drop */556/* gspca_dev->last_packet_type = DISCARD_PACKET; */557break;558default:559data += 1;560len -= 1;561gspca_frame_add(gspca_dev, INTER_PACKET, data, len);562break;563}564}565566static void setbrightness(struct gspca_dev *gspca_dev)567{568struct sd *sd = (struct sd *) gspca_dev;569570spca506_Initi2c(gspca_dev);571spca506_WriteI2c(gspca_dev, sd->brightness, SAA7113_bright);572spca506_WriteI2c(gspca_dev, 0x01, 0x09);573}574575static void setcontrast(struct gspca_dev *gspca_dev)576{577struct sd *sd = (struct sd *) gspca_dev;578579spca506_Initi2c(gspca_dev);580spca506_WriteI2c(gspca_dev, sd->contrast, SAA7113_contrast);581spca506_WriteI2c(gspca_dev, 0x01, 0x09);582}583584static void setcolors(struct gspca_dev *gspca_dev)585{586struct sd *sd = (struct sd *) gspca_dev;587588spca506_Initi2c(gspca_dev);589spca506_WriteI2c(gspca_dev, sd->colors, SAA7113_saturation);590spca506_WriteI2c(gspca_dev, 0x01, 0x09);591}592593static void sethue(struct gspca_dev *gspca_dev)594{595struct sd *sd = (struct sd *) gspca_dev;596597spca506_Initi2c(gspca_dev);598spca506_WriteI2c(gspca_dev, sd->hue, SAA7113_hue);599spca506_WriteI2c(gspca_dev, 0x01, 0x09);600}601602static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)603{604struct sd *sd = (struct sd *) gspca_dev;605606sd->brightness = val;607if (gspca_dev->streaming)608setbrightness(gspca_dev);609return 0;610}611612static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)613{614struct sd *sd = (struct sd *) gspca_dev;615616*val = sd->brightness;617return 0;618}619620static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)621{622struct sd *sd = (struct sd *) gspca_dev;623624sd->contrast = val;625if (gspca_dev->streaming)626setcontrast(gspca_dev);627return 0;628}629630static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)631{632struct sd *sd = (struct sd *) gspca_dev;633634*val = sd->contrast;635return 0;636}637638static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)639{640struct sd *sd = (struct sd *) gspca_dev;641642sd->colors = val;643if (gspca_dev->streaming)644setcolors(gspca_dev);645return 0;646}647648static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)649{650struct sd *sd = (struct sd *) gspca_dev;651652*val = sd->colors;653return 0;654}655656static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)657{658struct sd *sd = (struct sd *) gspca_dev;659660sd->hue = val;661if (gspca_dev->streaming)662sethue(gspca_dev);663return 0;664}665666static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)667{668struct sd *sd = (struct sd *) gspca_dev;669670*val = sd->hue;671return 0;672}673674/* sub-driver description */675static const struct sd_desc sd_desc = {676.name = MODULE_NAME,677.ctrls = sd_ctrls,678.nctrls = ARRAY_SIZE(sd_ctrls),679.config = sd_config,680.init = sd_init,681.start = sd_start,682.stopN = sd_stopN,683.pkt_scan = sd_pkt_scan,684};685686/* -- module initialisation -- */687static const struct usb_device_id device_table[] __devinitconst = {688{USB_DEVICE(0x06e1, 0xa190)},689/*fixme: may be IntelPCCameraPro BRIDGE_SPCA505690{USB_DEVICE(0x0733, 0x0430)}, */691{USB_DEVICE(0x0734, 0x043b)},692{USB_DEVICE(0x99fa, 0x8988)},693{}694};695MODULE_DEVICE_TABLE(usb, device_table);696697/* -- device connect -- */698static int __devinit sd_probe(struct usb_interface *intf,699const struct usb_device_id *id)700{701return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),702THIS_MODULE);703}704705static struct usb_driver sd_driver = {706.name = MODULE_NAME,707.id_table = device_table,708.probe = sd_probe,709.disconnect = gspca_disconnect,710#ifdef CONFIG_PM711.suspend = gspca_suspend,712.resume = gspca_resume,713#endif714};715716/* -- module insert / remove -- */717static int __init sd_mod_init(void)718{719int ret;720ret = usb_register(&sd_driver);721if (ret < 0)722return ret;723PDEBUG(D_PROBE, "registered");724return 0;725}726static void __exit sd_mod_exit(void)727{728usb_deregister(&sd_driver);729PDEBUG(D_PROBE, "deregistered");730}731732module_init(sd_mod_init);733module_exit(sd_mod_exit);734735736