Path: blob/master/drivers/media/video/gspca/sonixj.c
17628 views
/*1* Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver2*3* Copyright (C) 2009-2010 Jean-François Moine <http://moinejf.free.fr>4* Copyright (C) 2005 Michel Xhaard [email protected]5*6* This program is free software; you can redistribute it and/or modify7* it under the terms of the GNU General Public License as published by8* the Free Software Foundation; either version 2 of the License, or9* any later version.10*11* This program is distributed in the hope that it will be useful,12* but WITHOUT ANY WARRANTY; without even the implied warranty of13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14* GNU General Public License for more details.15*16* You should have received a copy of the GNU General Public License17* along with this program; if not, write to the Free Software18* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA19*/2021#define MODULE_NAME "sonixj"2223#include <linux/input.h>24#include "gspca.h"25#include "jpeg.h"2627MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");28MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");29MODULE_LICENSE("GPL");3031/* controls */32enum e_ctrl {33BRIGHTNESS,34CONTRAST,35COLORS,36BLUE,37RED,38GAMMA,39AUTOGAIN,40HFLIP,41VFLIP,42SHARPNESS,43ILLUM,44FREQ,45NCTRLS /* number of controls */46};4748/* specific webcam descriptor */49struct sd {50struct gspca_dev gspca_dev; /* !! must be the first item */5152struct gspca_ctrl ctrls[NCTRLS];5354atomic_t avg_lum;55u32 exposure;5657struct work_struct work;58struct workqueue_struct *work_thread;5960u32 pktsz; /* (used by pkt_scan) */61u16 npkt;62s8 nchg;63s8 short_mark;6465u8 quality; /* image quality */66#define QUALITY_MIN 2567#define QUALITY_MAX 9068#define QUALITY_DEF 706970u8 reg01;71u8 reg17;72u8 reg18;73u8 flags;7475s8 ag_cnt;76#define AG_CNT_START 137778u8 bridge;79#define BRIDGE_SN9C102P 080#define BRIDGE_SN9C105 181#define BRIDGE_SN9C110 282#define BRIDGE_SN9C120 383u8 sensor; /* Type of image sensor chip */84u8 i2c_addr;8586u8 jpeg_hdr[JPEG_HDR_SZ];87};88enum sensors {89SENSOR_ADCM1700,90SENSOR_GC0307,91SENSOR_HV7131R,92SENSOR_MI0360,93SENSOR_MI0360B,94SENSOR_MO4000,95SENSOR_MT9V111,96SENSOR_OM6802,97SENSOR_OV7630,98SENSOR_OV7648,99SENSOR_OV7660,100SENSOR_PO1030,101SENSOR_PO2030N,102SENSOR_SOI768,103SENSOR_SP80708,104};105106static void qual_upd(struct work_struct *work);107108/* device flags */109#define F_PDN_INV 0x01 /* inverse pin S_PWR_DN / sn_xxx tables */110#define F_ILLUM 0x02 /* presence of illuminator */111112/* sn9c1xx definitions */113/* register 0x01 */114#define S_PWR_DN 0x01 /* sensor power down */115#define S_PDN_INV 0x02 /* inverse pin S_PWR_DN */116#define V_TX_EN 0x04 /* video transfer enable */117#define LED 0x08 /* output to pin LED */118#define SCL_SEL_OD 0x20 /* open-drain mode */119#define SYS_SEL_48M 0x40 /* system clock 0: 24MHz, 1: 48MHz */120/* register 0x17 */121#define MCK_SIZE_MASK 0x1f /* sensor master clock */122#define SEN_CLK_EN 0x20 /* enable sensor clock */123#define DEF_EN 0x80 /* defect pixel by 0: soft, 1: hard */124125/* V4L2 controls supported by the driver */126static void setbrightness(struct gspca_dev *gspca_dev);127static void setcontrast(struct gspca_dev *gspca_dev);128static void setcolors(struct gspca_dev *gspca_dev);129static void setredblue(struct gspca_dev *gspca_dev);130static void setgamma(struct gspca_dev *gspca_dev);131static void setautogain(struct gspca_dev *gspca_dev);132static void sethvflip(struct gspca_dev *gspca_dev);133static void setsharpness(struct gspca_dev *gspca_dev);134static void setillum(struct gspca_dev *gspca_dev);135static void setfreq(struct gspca_dev *gspca_dev);136137static const struct ctrl sd_ctrls[NCTRLS] = {138[BRIGHTNESS] = {139{140.id = V4L2_CID_BRIGHTNESS,141.type = V4L2_CTRL_TYPE_INTEGER,142.name = "Brightness",143.minimum = 0,144.maximum = 0xff,145.step = 1,146.default_value = 0x80,147},148.set_control = setbrightness149},150[CONTRAST] = {151{152.id = V4L2_CID_CONTRAST,153.type = V4L2_CTRL_TYPE_INTEGER,154.name = "Contrast",155.minimum = 0,156#define CONTRAST_MAX 127157.maximum = CONTRAST_MAX,158.step = 1,159.default_value = 63,160},161.set_control = setcontrast162},163[COLORS] = {164{165.id = V4L2_CID_SATURATION,166.type = V4L2_CTRL_TYPE_INTEGER,167.name = "Saturation",168.minimum = 0,169.maximum = 40,170.step = 1,171#define COLORS_DEF 25172.default_value = COLORS_DEF,173},174.set_control = setcolors175},176[BLUE] = {177{178.id = V4L2_CID_BLUE_BALANCE,179.type = V4L2_CTRL_TYPE_INTEGER,180.name = "Blue Balance",181.minimum = 24,182.maximum = 40,183.step = 1,184.default_value = 32,185},186.set_control = setredblue187},188[RED] = {189{190.id = V4L2_CID_RED_BALANCE,191.type = V4L2_CTRL_TYPE_INTEGER,192.name = "Red Balance",193.minimum = 24,194.maximum = 40,195.step = 1,196.default_value = 32,197},198.set_control = setredblue199},200[GAMMA] = {201{202.id = V4L2_CID_GAMMA,203.type = V4L2_CTRL_TYPE_INTEGER,204.name = "Gamma",205.minimum = 0,206.maximum = 40,207.step = 1,208#define GAMMA_DEF 20209.default_value = GAMMA_DEF,210},211.set_control = setgamma212},213[AUTOGAIN] = {214{215.id = V4L2_CID_AUTOGAIN,216.type = V4L2_CTRL_TYPE_BOOLEAN,217.name = "Auto Gain",218.minimum = 0,219.maximum = 1,220.step = 1,221.default_value = 1222},223.set_control = setautogain224},225[HFLIP] = {226{227.id = V4L2_CID_HFLIP,228.type = V4L2_CTRL_TYPE_BOOLEAN,229.name = "Mirror",230.minimum = 0,231.maximum = 1,232.step = 1,233.default_value = 0,234},235.set_control = sethvflip236},237[VFLIP] = {238{239.id = V4L2_CID_VFLIP,240.type = V4L2_CTRL_TYPE_BOOLEAN,241.name = "Vflip",242.minimum = 0,243.maximum = 1,244.step = 1,245.default_value = 0,246},247.set_control = sethvflip248},249[SHARPNESS] = {250{251.id = V4L2_CID_SHARPNESS,252.type = V4L2_CTRL_TYPE_INTEGER,253.name = "Sharpness",254.minimum = 0,255.maximum = 255,256.step = 1,257.default_value = 90,258},259.set_control = setsharpness260},261[ILLUM] = {262{263.id = V4L2_CID_ILLUMINATORS_1,264.type = V4L2_CTRL_TYPE_BOOLEAN,265.name = "Illuminator / infrared",266.minimum = 0,267.maximum = 1,268.step = 1,269.default_value = 0,270},271.set_control = setillum272},273/* ov7630/ov7648/ov7660 only */274[FREQ] = {275{276.id = V4L2_CID_POWER_LINE_FREQUENCY,277.type = V4L2_CTRL_TYPE_MENU,278.name = "Light frequency filter",279.minimum = 0,280.maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */281.step = 1,282.default_value = 1,283},284.set_control = setfreq285},286};287288/* table of the disabled controls */289static const __u32 ctrl_dis[] = {290[SENSOR_ADCM1700] = (1 << AUTOGAIN) |291(1 << HFLIP) |292(1 << VFLIP) |293(1 << FREQ),294295[SENSOR_GC0307] = (1 << HFLIP) |296(1 << VFLIP) |297(1 << FREQ),298299[SENSOR_HV7131R] = (1 << HFLIP) |300(1 << FREQ),301302[SENSOR_MI0360] = (1 << HFLIP) |303(1 << VFLIP) |304(1 << FREQ),305306[SENSOR_MI0360B] = (1 << HFLIP) |307(1 << VFLIP) |308(1 << FREQ),309310[SENSOR_MO4000] = (1 << HFLIP) |311(1 << VFLIP) |312(1 << FREQ),313314[SENSOR_MT9V111] = (1 << HFLIP) |315(1 << VFLIP) |316(1 << FREQ),317318[SENSOR_OM6802] = (1 << HFLIP) |319(1 << VFLIP) |320(1 << FREQ),321322[SENSOR_OV7630] = (1 << HFLIP),323324[SENSOR_OV7648] = (1 << HFLIP),325326[SENSOR_OV7660] = (1 << AUTOGAIN) |327(1 << HFLIP) |328(1 << VFLIP),329330[SENSOR_PO1030] = (1 << AUTOGAIN) |331(1 << HFLIP) |332(1 << VFLIP) |333(1 << FREQ),334335[SENSOR_PO2030N] = (1 << AUTOGAIN) |336(1 << FREQ),337338[SENSOR_SOI768] = (1 << AUTOGAIN) |339(1 << HFLIP) |340(1 << VFLIP) |341(1 << FREQ),342343[SENSOR_SP80708] = (1 << AUTOGAIN) |344(1 << HFLIP) |345(1 << VFLIP) |346(1 << FREQ),347};348349static const struct v4l2_pix_format cif_mode[] = {350{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,351.bytesperline = 352,352.sizeimage = 352 * 288 * 4 / 8 + 590,353.colorspace = V4L2_COLORSPACE_JPEG,354.priv = 0},355};356static const struct v4l2_pix_format vga_mode[] = {357{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,358.bytesperline = 160,359.sizeimage = 160 * 120 * 4 / 8 + 590,360.colorspace = V4L2_COLORSPACE_JPEG,361.priv = 2},362{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,363.bytesperline = 320,364.sizeimage = 320 * 240 * 3 / 8 + 590,365.colorspace = V4L2_COLORSPACE_JPEG,366.priv = 1},367{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,368.bytesperline = 640,369/* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */370.sizeimage = 640 * 480 * 3 / 4 + 590,371.colorspace = V4L2_COLORSPACE_JPEG,372.priv = 0},373};374375static const u8 sn_adcm1700[0x1c] = {376/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */3770x00, 0x43, 0x60, 0x00, 0x1a, 0x00, 0x00, 0x00,378/* reg8 reg9 rega regb regc regd rege regf */3790x80, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,380/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */3810x03, 0x00, 0x05, 0x01, 0x05, 0x16, 0x12, 0x42,382/* reg18 reg19 reg1a reg1b */3830x06, 0x00, 0x00, 0x00384};385386static const u8 sn_gc0307[0x1c] = {387/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */3880x00, 0x61, 0x62, 0x00, 0x1a, 0x00, 0x00, 0x00,389/* reg8 reg9 rega regb regc regd rege regf */3900x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,391/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */3920x03, 0x00, 0x03, 0x01, 0x08, 0x28, 0x1e, 0x02,393/* reg18 reg19 reg1a reg1b */3940x06, 0x00, 0x00, 0x00395};396397static const u8 sn_hv7131[0x1c] = {398/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */3990x00, 0x03, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20,400/* reg8 reg9 rega regb regc regd rege regf */4010x81, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,402/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */4030x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,404/* reg18 reg19 reg1a reg1b */4050x0a, 0x00, 0x00, 0x00406};407408static const u8 sn_mi0360[0x1c] = {409/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */4100x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,411/* reg8 reg9 rega regb regc regd rege regf */4120x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,413/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */4140x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,415/* reg18 reg19 reg1a reg1b */4160x06, 0x00, 0x00, 0x00417};418419static const u8 sn_mi0360b[0x1c] = {420/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */4210x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,422/* reg8 reg9 rega regb regc regd rege regf */4230x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,424/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */4250x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x40,426/* reg18 reg19 reg1a reg1b */4270x06, 0x00, 0x00, 0x00428};429430static const u8 sn_mo4000[0x1c] = {431/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */4320x00, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,433/* reg8 reg9 rega regb regc regd rege regf */4340x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,435/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */4360x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,437/* reg18 reg19 reg1a reg1b */4380x08, 0x00, 0x00, 0x00439};440441static const u8 sn_mt9v111[0x1c] = {442/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */4430x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,444/* reg8 reg9 rega regb regc regd rege regf */4450x81, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,446/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */4470x03, 0x00, 0x00, 0x02, 0x1c, 0x28, 0x1e, 0x40,448/* reg18 reg19 reg1a reg1b */4490x06, 0x00, 0x00, 0x00450};451452static const u8 sn_om6802[0x1c] = {453/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */4540x00, 0x23, 0x72, 0x00, 0x1a, 0x20, 0x20, 0x19,455/* reg8 reg9 rega regb regc regd rege regf */4560x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,457/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */4580x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,459/* reg18 reg19 reg1a reg1b */4600x05, 0x00, 0x00, 0x00461};462463static const u8 sn_ov7630[0x1c] = {464/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */4650x00, 0x21, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,466/* reg8 reg9 rega regb regc regd rege regf */4670x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,468/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */4690x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,470/* reg18 reg19 reg1a reg1b */4710x0b, 0x00, 0x00, 0x00472};473474static const u8 sn_ov7648[0x1c] = {475/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */4760x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,477/* reg8 reg9 rega regb regc regd rege regf */4780x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,479/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */4800x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00,481/* reg18 reg19 reg1a reg1b */4820x0b, 0x00, 0x00, 0x00483};484485static const u8 sn_ov7660[0x1c] = {486/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */4870x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,488/* reg8 reg9 rega regb regc regd rege regf */4890x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,490/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */4910x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,492/* reg18 reg19 reg1a reg1b */4930x07, 0x00, 0x00, 0x00494};495496static const u8 sn_po1030[0x1c] = {497/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */4980x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,499/* reg8 reg9 rega regb regc regd rege regf */5000x81, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,501/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */5020x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x00,503/* reg18 reg19 reg1a reg1b */5040x07, 0x00, 0x00, 0x00505};506507static const u8 sn_po2030n[0x1c] = {508/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */5090x00, 0x63, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,510/* reg8 reg9 rega regb regc regd rege regf */5110x81, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,512/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */5130x03, 0x00, 0x00, 0x01, 0x14, 0x28, 0x1e, 0x00,514/* reg18 reg19 reg1a reg1b */5150x07, 0x00, 0x00, 0x00516};517518static const u8 sn_soi768[0x1c] = {519/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */5200x00, 0x21, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,521/* reg8 reg9 rega regb regc regd rege regf */5220x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,523/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */5240x03, 0x00, 0x00, 0x01, 0x08, 0x28, 0x1e, 0x00,525/* reg18 reg19 reg1a reg1b */5260x07, 0x00, 0x00, 0x00527};528529static const u8 sn_sp80708[0x1c] = {530/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */5310x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20,532/* reg8 reg9 rega regb regc regd rege regf */5330x81, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,534/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */5350x03, 0x00, 0x00, 0x03, 0x04, 0x28, 0x1e, 0x00,536/* reg18 reg19 reg1a reg1b */5370x07, 0x00, 0x00, 0x00538};539540/* sequence specific to the sensors - !! index = SENSOR_xxx */541static const u8 *sn_tb[] = {542[SENSOR_ADCM1700] = sn_adcm1700,543[SENSOR_GC0307] = sn_gc0307,544[SENSOR_HV7131R] = sn_hv7131,545[SENSOR_MI0360] = sn_mi0360,546[SENSOR_MI0360B] = sn_mi0360b,547[SENSOR_MO4000] = sn_mo4000,548[SENSOR_MT9V111] = sn_mt9v111,549[SENSOR_OM6802] = sn_om6802,550[SENSOR_OV7630] = sn_ov7630,551[SENSOR_OV7648] = sn_ov7648,552[SENSOR_OV7660] = sn_ov7660,553[SENSOR_PO1030] = sn_po1030,554[SENSOR_PO2030N] = sn_po2030n,555[SENSOR_SOI768] = sn_soi768,556[SENSOR_SP80708] = sn_sp80708,557};558559/* default gamma table */560static const u8 gamma_def[17] = {5610x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,5620xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff563};564/* gamma for sensor ADCM1700 */565static const u8 gamma_spec_0[17] = {5660x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4,5670xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5568};569/* gamma for sensors HV7131R and MT9V111 */570static const u8 gamma_spec_1[17] = {5710x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d,5720xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5573};574/* gamma for sensor GC0307 */575static const u8 gamma_spec_2[17] = {5760x14, 0x37, 0x50, 0x6a, 0x7c, 0x8d, 0x9d, 0xab,5770xb5, 0xbf, 0xc2, 0xcb, 0xd1, 0xd6, 0xdb, 0xe1, 0xeb578};579/* gamma for sensor SP80708 */580static const u8 gamma_spec_3[17] = {5810x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab,5820xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6583};584585/* color matrix and offsets */586static const u8 reg84[] = {5870x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */5880xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */5890x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */5900x00, 0x00, 0x00 /* YUV offsets */591};592593#define DELAY 0xdd594595static const u8 adcm1700_sensor_init[][8] = {596{0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10},597{0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10}, /* reset */598{DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},599{0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},600{DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},601{0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10},602{0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10},603{0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10},604{0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10},605{0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10},606{DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},607{0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10},608{DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},609{0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10},610{0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},611{0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10},612{0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},613{}614};615static const u8 adcm1700_sensor_param1[][8] = {616{0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10}, /* exposure? */617{0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10},618619{0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},620{0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},621{0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},622{0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10},623{0xd0, 0x51, 0x1e, 0xbe, 0xd7, 0xe8, 0xbe, 0x10}, /* exposure? */624625{0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},626{0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},627{0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},628{0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10},629{}630};631static const u8 gc0307_sensor_init[][8] = {632{0xa0, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x10},633{0xa0, 0x21, 0x44, 0xa2, 0x00, 0x00, 0x00, 0x10},634{0xa0, 0x21, 0x01, 0x6a, 0x00, 0x00, 0x00, 0x10},635{0xa0, 0x21, 0x02, 0x70, 0x00, 0x00, 0x00, 0x10},636{0xa0, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},637{0xa0, 0x21, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},638{0xa0, 0x21, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},639{0xa0, 0x21, 0x11, 0x05, 0x00, 0x00, 0x00, 0x10},640{0xa0, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},641{0xa0, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10},642{0xa0, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10},643{0xa0, 0x21, 0x08, 0x02, 0x00, 0x00, 0x00, 0x10},644{0xa0, 0x21, 0x09, 0x01, 0x00, 0x00, 0x00, 0x10},645{0xa0, 0x21, 0x0a, 0xe8, 0x00, 0x00, 0x00, 0x10},646{0xa0, 0x21, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x10},647{0xa0, 0x21, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x10},648{0xa0, 0x21, 0x0d, 0x22, 0x00, 0x00, 0x00, 0x10},649{0xa0, 0x21, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x10},650{0xa0, 0x21, 0x0f, 0xb2, 0x00, 0x00, 0x00, 0x10},651{0xa0, 0x21, 0x12, 0x70, 0x00, 0x00, 0x00, 0x10},652{DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 10ms*/653{0xa0, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10},654{0xa0, 0x21, 0x15, 0xb8, 0x00, 0x00, 0x00, 0x10},655{0xa0, 0x21, 0x16, 0x13, 0x00, 0x00, 0x00, 0x10},656{0xa0, 0x21, 0x17, 0x52, 0x00, 0x00, 0x00, 0x10},657{0xa0, 0x21, 0x18, 0x50, 0x00, 0x00, 0x00, 0x10},658{0xa0, 0x21, 0x1e, 0x0d, 0x00, 0x00, 0x00, 0x10},659{0xa0, 0x21, 0x1f, 0x32, 0x00, 0x00, 0x00, 0x10},660{0xa0, 0x21, 0x61, 0x90, 0x00, 0x00, 0x00, 0x10},661{0xa0, 0x21, 0x63, 0x70, 0x00, 0x00, 0x00, 0x10},662{0xa0, 0x21, 0x65, 0x98, 0x00, 0x00, 0x00, 0x10},663{0xa0, 0x21, 0x67, 0x90, 0x00, 0x00, 0x00, 0x10},664{0xa0, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},665{0xa0, 0x21, 0x04, 0x96, 0x00, 0x00, 0x00, 0x10},666{0xa0, 0x21, 0x45, 0x27, 0x00, 0x00, 0x00, 0x10},667{0xa0, 0x21, 0x47, 0x2c, 0x00, 0x00, 0x00, 0x10},668{0xa0, 0x21, 0x43, 0x47, 0x00, 0x00, 0x00, 0x10},669{0xa0, 0x21, 0x44, 0xd8, 0x00, 0x00, 0x00, 0x10},670{}671};672static const u8 gc0307_sensor_param1[][8] = {673{0xa0, 0x21, 0x68, 0x13, 0x00, 0x00, 0x00, 0x10},674{0xd0, 0x21, 0x61, 0x80, 0x00, 0x80, 0x00, 0x10},675{0xc0, 0x21, 0x65, 0x80, 0x00, 0x80, 0x00, 0x10},676{0xc0, 0x21, 0x63, 0xa0, 0x00, 0xa6, 0x00, 0x10},677/*param3*/678{0xa0, 0x21, 0x01, 0x6e, 0x00, 0x00, 0x00, 0x10},679{0xa0, 0x21, 0x02, 0x88, 0x00, 0x00, 0x00, 0x10},680{}681};682683static const u8 hv7131r_sensor_init[][8] = {684{0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},685{0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},686{0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10},687/* {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */688{0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},689{0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10},690/* {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */691692{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},693{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},694{0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10},695{0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},696{0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10},697{0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10},698{0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */699{0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */700701{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},702{0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},703{0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},704{0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},705{0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},706707{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},708{0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},709{0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},710{0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},711{0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},712{0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10},713/* set sensor clock */714{}715};716static const u8 mi0360_sensor_init[][8] = {717{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},718{0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},719{0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},720{0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},721{0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},722{0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},723{0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},724{0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},725{0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},726{0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},727{0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},728{0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},729{0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},730{0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},731{0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},732{0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},733{0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},734{0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},735{0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},736{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},737{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},738{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},739{0xd1, 0x5d, 0x2f, 0xf7, 0xB0, 0x00, 0x04, 0x10},740{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},741{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},742{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},743{0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},744{0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},745{0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},746{0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},747{0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},748{0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},749{0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},750751{0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},752{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},753{0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},754{0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10},755{0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10},756757{0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */758{0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},759{0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10},760{0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */761762{0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10},763{0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */764/* {0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */765/* {0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */766{0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */767{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */768{}769};770static const u8 mi0360b_sensor_init[][8] = {771{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},772{0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},773{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/774{0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},775{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/776{0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},777{0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},778{0xd1, 0x5d, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},779{0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},780{0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},781{0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},782{0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},783{0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},784{0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},785{0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},786{0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},787{0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},788{0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},789{0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},790{0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},791{0xd1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},792{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},793{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},794{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},795{0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},796{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},797{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},798{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},799{0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},800{0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},801{0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},802{0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},803{0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},804{0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},805{0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},806807{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},808{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},809{0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},810{0xd1, 0x5d, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10},811{0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10},812{}813};814static const u8 mi0360b_sensor_param1[][8] = {815{0xb1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},816{0xb1, 0x5d, 0x06, 0x00, 0x53, 0x00, 0x00, 0x10},817{0xb1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10},818{0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */819820{0xd1, 0x5d, 0x2b, 0x00, 0xd1, 0x01, 0xc9, 0x10},821{0xd1, 0x5d, 0x2d, 0x00, 0xed, 0x00, 0xd1, 0x10},822{0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */823{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */824{}825};826static const u8 mo4000_sensor_init[][8] = {827{0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},828{0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},829{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},830{0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},831{0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},832{0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},833{0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},834{0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},835{0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},836{0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},837{0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},838{0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},839{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},840{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},841{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},842{0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},843{0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},844{0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},845{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},846{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},847{}848};849static const u8 mt9v111_sensor_init[][8] = {850{0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */851{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */852{0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},853{0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */854{0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */855{0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */856{0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */857{0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */858{0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */859{0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */860{0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */861{0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */862{0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */863{0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */864{0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */865{0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */866{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */867{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},868{}869};870static const u8 mt9v111_sensor_param1[][8] = {871{0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xad, 0x10}, /* G1 and B gains */872{0xd1, 0x5c, 0x2d, 0x00, 0xad, 0x00, 0x33, 0x10}, /* R and G2 gains */873{0xb1, 0x5c, 0x06, 0x00, 0x40, 0x00, 0x00, 0x10}, /* vert blanking */874{0xb1, 0x5c, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10}, /* horiz blanking */875{0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */876{}877};878static const u8 om6802_init0[2][8] = {879/*fixme: variable*/880{0xa0, 0x34, 0x29, 0x0e, 0x00, 0x00, 0x00, 0x10},881{0xa0, 0x34, 0x23, 0xb0, 0x00, 0x00, 0x00, 0x10},882};883static const u8 om6802_sensor_init[][8] = {884{0xa0, 0x34, 0xdf, 0x6d, 0x00, 0x00, 0x00, 0x10},885/* factory mode */886{0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},887/* output raw RGB */888{0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},889/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */890{0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},891/* auto-exposure speed (0) / white balance mode (auto RGB) */892/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},893* set color mode */894/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},895* max AGC value in AE */896/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},897* preset AGC */898/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},899* preset brightness */900/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},901* preset contrast */902/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},903* preset gamma */904{0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},905/* luminance mode (0x4f -> AutoExpo on) */906{0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},907/* preset shutter */908/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},909* auto frame rate */910/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */911{0xa0, 0x34, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},912{}913};914static const u8 om6802_sensor_param1[][8] = {915{0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10},916{0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10},917{0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10},918{0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10},919{}920};921static const u8 ov7630_sensor_init[][8] = {922{0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},923{0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},924{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */925{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},926{0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},927{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */928{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},929/* win: i2c_r from 00 to 80 */930{0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},931{0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},932/* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30)9330x13 was 0xc0 change to 0xc3 for auto gain and exposure */934{0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10},935{0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},936{0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},937{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},938{0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},939{0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},940{0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},941{0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},942{0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},943{0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},944{0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},945{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},946{0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},947{0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},948{0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},949{0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},950{0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},951{0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},952{0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},953{0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},954{0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},955{0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},956{0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},957{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},958{}959};960static const u8 ov7630_sensor_param1[][8] = {961{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},962{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},963/*fixme: + 0x12, 0x04*/964/* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN965* set by setvflip */966{0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},967{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},968{0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},969/* */970/* {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */971/* {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */972/* */973{0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},974/* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */975{}976};977978static const u8 ov7648_sensor_init[][8] = {979{0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},980{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */981{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */982{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},983{0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},984{0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},985{0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},986{0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},987{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},988{0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},989{0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},990{0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},991{0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},992{0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},993{0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},994{0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},995{0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},996{0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},997{0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},998{0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},999{0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},1000{0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},10011002{0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},1003/* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */1004/* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */1005/* {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */1006{}1007};1008static const u8 ov7648_sensor_param1[][8] = {1009/* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */1010/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN1011* set by setvflip */1012{0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},1013{0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},1014/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */1015/* {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, * GAIN - def */1016/* {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10}, * B R - def: 80 */1017/*...*/1018{0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */1019/* {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */1020/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */1021/* {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */1022/* {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */1023/* {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10}, * B R - def: 80 */10241025{}1026};10271028static const u8 ov7660_sensor_init[][8] = {1029{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */1030{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */1031{0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},1032/* Outformat = rawRGB */1033{0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */1034{0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},1035/* GAIN BLUE RED VREF */1036{0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},1037/* COM 1 BAVE GEAVE AECHH */1038{0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */1039{0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */1040{0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},1041/* AECH CLKRC COM7 COM8 */1042{0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */1043{0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},1044/* HSTART HSTOP VSTRT VSTOP */1045{0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */1046{0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */1047{0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},1048/* BOS GBOS GROS ROS (BGGR offset) */1049/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */1050{0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},1051/* AEW AEB VPT BBIAS */1052{0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},1053/* GbBIAS RSVD EXHCH EXHCL */1054{0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},1055/* RBIAS ADVFL ASDVFH YAVE */1056{0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},1057/* HSYST HSYEN HREF */1058{0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */1059{0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},1060/* ADC ACOM OFON TSLB */1061{0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},1062/* COM11 COM12 COM13 COM14 */1063{0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},1064/* EDGE COM15 COM16 COM17 */1065{0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */1066{0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */1067{0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */1068{0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */1069{0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */1070{0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */1071{0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */1072{0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */1073{0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */1074{0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},1075/* LCC1 LCC2 LCC3 LCC4 */1076{0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */1077{0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */1078{0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},1079/* band gap reference [0:3] DBLV */1080{0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */1081{0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */1082{0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */1083{0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */1084{0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */1085{0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */1086{0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */1087{0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */1088{0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */1089{0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */1090/* not in all ms-win traces*/1091{0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},1092{}1093};1094static const u8 ov7660_sensor_param1[][8] = {1095{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */1096/* bits[3..0]reserved */1097{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},1098{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},1099/* VREF vertical frame ctrl */1100{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},1101{0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */1102{0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */1103{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */1104{0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */1105/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */1106/****** (some exchanges in the win trace) ******/1107/*fixme:param2*/1108{0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */1109{0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */1110{0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */1111{0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */1112/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */1113/****** (some exchanges in the win trace) ******/1114/******!! startsensor KO if changed !!****/1115/*fixme: param3*/1116{0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},1117{0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},1118{0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},1119{0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},1120{}1121};11221123static const u8 po1030_sensor_init[][8] = {1124/* the sensor registers are described in m5602/m5602_po1030.h */1125{0xa1, 0x6e, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x10}, /* sensor reset */1126{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */1127{0xa1, 0x6e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x10},1128{0xa1, 0x6e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x10},1129{0xd1, 0x6e, 0x04, 0x02, 0xb1, 0x02, 0x39, 0x10},1130{0xd1, 0x6e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},1131{0xd1, 0x6e, 0x0c, 0x02, 0x7f, 0x01, 0xe0, 0x10},1132{0xd1, 0x6e, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},1133{0xd1, 0x6e, 0x16, 0x85, 0x40, 0x4a, 0x40, 0x10}, /* r/g1/b/g2 gains */1134{0xc1, 0x6e, 0x1a, 0x00, 0x80, 0x00, 0x00, 0x10},1135{0xd1, 0x6e, 0x1d, 0x08, 0x03, 0x00, 0x00, 0x10},1136{0xd1, 0x6e, 0x23, 0x00, 0xb0, 0x00, 0x94, 0x10},1137{0xd1, 0x6e, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},1138{0xb1, 0x6e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},1139{0xd1, 0x6e, 0x2d, 0x14, 0x35, 0x61, 0x84, 0x10}, /* gamma corr */1140{0xd1, 0x6e, 0x31, 0xa2, 0xbd, 0xd8, 0xff, 0x10},1141{0xd1, 0x6e, 0x35, 0x06, 0x1e, 0x12, 0x02, 0x10}, /* color matrix */1142{0xd1, 0x6e, 0x39, 0xaa, 0x53, 0x37, 0xd5, 0x10},1143{0xa1, 0x6e, 0x3d, 0xf2, 0x00, 0x00, 0x00, 0x10},1144{0xd1, 0x6e, 0x3e, 0x00, 0x00, 0x80, 0x03, 0x10},1145{0xd1, 0x6e, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},1146{0xc1, 0x6e, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},1147{0xd1, 0x6e, 0x4b, 0x02, 0xef, 0x08, 0xcd, 0x10},1148{0xd1, 0x6e, 0x4f, 0x00, 0xd0, 0x00, 0xa0, 0x10},1149{0xd1, 0x6e, 0x53, 0x01, 0xaa, 0x01, 0x40, 0x10},1150{0xd1, 0x6e, 0x5a, 0x50, 0x04, 0x30, 0x03, 0x10}, /* raw rgb bayer */1151{0xa1, 0x6e, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x10},1152{0xd1, 0x6e, 0x5f, 0x10, 0x40, 0xff, 0x00, 0x10},11531154{0xd1, 0x6e, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},1155{0xd1, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},1156{0xd1, 0x6e, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x10},1157{0xd1, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x10},1158{0xc1, 0x6e, 0x73, 0x10, 0x80, 0xeb, 0x00, 0x10},1159{}1160};1161static const u8 po1030_sensor_param1[][8] = {1162/* from ms-win traces - these values change with auto gain/expo/wb.. */1163{0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},1164{0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},1165/* mean values */1166{0xc1, 0x6e, 0x1a, 0x02, 0xd4, 0xa4, 0x00, 0x10}, /* integlines */1167{0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, /* global gain */1168{0xc1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10}, /* r/g1/b gains */11691170{0xa1, 0x6e, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x10}, /* control1 */1171{0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, /* frameheight */1172{0xa1, 0x6e, 0x07, 0xd5, 0x00, 0x00, 0x00, 0x10},1173/* {0xc1, 0x6e, 0x16, 0x49, 0x40, 0x45, 0x00, 0x10}, */1174{}1175};11761177static const u8 po2030n_sensor_init[][8] = {1178{0xa1, 0x6e, 0x1e, 0x1a, 0x00, 0x00, 0x00, 0x10},1179{0xa1, 0x6e, 0x1f, 0x99, 0x00, 0x00, 0x00, 0x10},1180{DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */1181{0xa1, 0x6e, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x10},1182{0xa1, 0x6e, 0x1f, 0x19, 0x00, 0x00, 0x00, 0x10},1183{DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */1184{0xa1, 0x6e, 0x20, 0x44, 0x00, 0x00, 0x00, 0x10},1185{0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},1186{0xa1, 0x6e, 0x05, 0x70, 0x00, 0x00, 0x00, 0x10},1187{0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},1188{0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},1189{0xd1, 0x6e, 0x08, 0x00, 0xd0, 0x00, 0x08, 0x10},1190{0xd1, 0x6e, 0x0c, 0x03, 0x50, 0x01, 0xe8, 0x10},1191{0xd1, 0x6e, 0x1d, 0x20, 0x0a, 0x19, 0x44, 0x10},1192{0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},1193{0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10},1194{0xd1, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10},1195{0xd1, 0x6e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},1196{0xd1, 0x6e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},1197{0xd1, 0x6e, 0x35, 0x00, 0x00, 0x00, 0x00, 0x10},1198{0xd1, 0x6e, 0x39, 0x00, 0x00, 0x00, 0x00, 0x10},1199{0xd1, 0x6e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x10},1200{0xd1, 0x6e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x10},1201{0xd1, 0x6e, 0x45, 0x00, 0x00, 0x00, 0x00, 0x10},1202{0xd1, 0x6e, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10},1203{0xd1, 0x6e, 0x4d, 0x00, 0x00, 0x00, 0xed, 0x10},1204{0xd1, 0x6e, 0x51, 0x17, 0x4a, 0x2f, 0xc0, 0x10},1205{0xd1, 0x6e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x10},1206{0xd1, 0x6e, 0x59, 0x00, 0x00, 0x00, 0x00, 0x10},1207{0xd1, 0x6e, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x10},1208{0xd1, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x00, 0x10},1209{0xd1, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10},1210{0xd1, 0x6e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x10},1211{0xd1, 0x6e, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10},1212{0xd1, 0x6e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x10},1213{0xd1, 0x6e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x10},1214{0xd1, 0x6e, 0x79, 0x00, 0x00, 0x00, 0x00, 0x10},1215{0xd1, 0x6e, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10},1216{0xd1, 0x6e, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10},1217{0xd1, 0x6e, 0x85, 0x00, 0x00, 0x00, 0x08, 0x10},1218{0xd1, 0x6e, 0x89, 0x01, 0xe8, 0x00, 0x01, 0x10},1219{0xa1, 0x6e, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x10},1220{0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},1221{0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10},1222{0xd1, 0x6e, 0x29, 0xe6, 0x00, 0xbd, 0x03, 0x10},1223{0xd1, 0x6e, 0x2d, 0x41, 0x38, 0x68, 0x40, 0x10},1224{0xd1, 0x6e, 0x31, 0x2b, 0x00, 0x36, 0x00, 0x10},1225{0xd1, 0x6e, 0x35, 0x30, 0x30, 0x08, 0x00, 0x10},1226{0xd1, 0x6e, 0x39, 0x00, 0x00, 0x33, 0x06, 0x10},1227{0xb1, 0x6e, 0x3d, 0x06, 0x02, 0x00, 0x00, 0x10},1228{}1229};1230static const u8 po2030n_sensor_param1[][8] = {1231{0xa1, 0x6e, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x10},1232{DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */1233{0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10},1234{0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},1235{0xd1, 0x6e, 0x16, 0x50, 0x40, 0x49, 0x40, 0x10},1236/*param2*/1237{0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},1238{0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},1239{0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10},1240{0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},1241{0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},1242{0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},1243{0xc1, 0x6e, 0x16, 0x52, 0x40, 0x48, 0x00, 0x10},1244/*after start*/1245{0xa1, 0x6e, 0x15, 0x0f, 0x00, 0x00, 0x00, 0x10},1246{DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */1247{0xa1, 0x6e, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x10},1248{DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */1249{0xa1, 0x6e, 0x1b, 0x53, 0x00, 0x00, 0x00, 0x10},1250{}1251};12521253static const u8 soi768_sensor_init[][8] = {1254{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */1255{DELAY, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 96ms */1256{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},1257{0xa1, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},1258{0xa1, 0x21, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x10},1259{0xa1, 0x21, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10},1260{}1261};1262static const u8 soi768_sensor_param1[][8] = {1263{0xa1, 0x21, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10},1264{0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},1265{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},1266{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},1267{0xb1, 0x21, 0x01, 0x7f, 0x7f, 0x00, 0x00, 0x10},1268/* */1269/* {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, */1270/* {0xa1, 0x21, 0x2d, 0x25, 0x00, 0x00, 0x00, 0x10}, */1271{0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},1272/* {0xb1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, */1273{0xa1, 0x21, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x10},1274/* the next sequence should be used for auto gain */1275{0xa1, 0x21, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10},1276/* global gain ? : 07 - change with 0x15 at the end */1277{0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */1278{0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},1279{0xb1, 0x21, 0x2d, 0x00, 0x02, 0x00, 0x00, 0x10},1280/* exposure ? : 0200 - change with 0x1e at the end */1281{}1282};12831284static const u8 sp80708_sensor_init[][8] = {1285{0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10},1286{0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10},1287{0xa1, 0x18, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},1288{0xa1, 0x18, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x10},1289{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},1290{0xa1, 0x18, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x10},1291{0xa1, 0x18, 0x10, 0x40, 0x00, 0x00, 0x00, 0x10},1292{0xa1, 0x18, 0x11, 0x4e, 0x00, 0x00, 0x00, 0x10},1293{0xa1, 0x18, 0x12, 0x53, 0x00, 0x00, 0x00, 0x10},1294{0xa1, 0x18, 0x15, 0x80, 0x00, 0x00, 0x00, 0x10},1295{0xa1, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10},1296{0xa1, 0x18, 0x19, 0x18, 0x00, 0x00, 0x00, 0x10},1297{0xa1, 0x18, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10},1298{0xa1, 0x18, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10},1299{0xa1, 0x18, 0x1c, 0x28, 0x00, 0x00, 0x00, 0x10},1300{0xa1, 0x18, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x10},1301{0xa1, 0x18, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x10},1302{0xa1, 0x18, 0x26, 0x04, 0x00, 0x00, 0x00, 0x10},1303{0xa1, 0x18, 0x27, 0x1e, 0x00, 0x00, 0x00, 0x10},1304{0xa1, 0x18, 0x28, 0x5a, 0x00, 0x00, 0x00, 0x10},1305{0xa1, 0x18, 0x29, 0x28, 0x00, 0x00, 0x00, 0x10},1306{0xa1, 0x18, 0x2a, 0x78, 0x00, 0x00, 0x00, 0x10},1307{0xa1, 0x18, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x10},1308{0xa1, 0x18, 0x2c, 0xf7, 0x00, 0x00, 0x00, 0x10},1309{0xa1, 0x18, 0x2d, 0x2d, 0x00, 0x00, 0x00, 0x10},1310{0xa1, 0x18, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x10},1311{0xa1, 0x18, 0x39, 0x42, 0x00, 0x00, 0x00, 0x10},1312{0xa1, 0x18, 0x3a, 0x67, 0x00, 0x00, 0x00, 0x10},1313{0xa1, 0x18, 0x3b, 0x87, 0x00, 0x00, 0x00, 0x10},1314{0xa1, 0x18, 0x3c, 0xa3, 0x00, 0x00, 0x00, 0x10},1315{0xa1, 0x18, 0x3d, 0xb0, 0x00, 0x00, 0x00, 0x10},1316{0xa1, 0x18, 0x3e, 0xbc, 0x00, 0x00, 0x00, 0x10},1317{0xa1, 0x18, 0x3f, 0xc8, 0x00, 0x00, 0x00, 0x10},1318{0xa1, 0x18, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x10},1319{0xa1, 0x18, 0x41, 0xdf, 0x00, 0x00, 0x00, 0x10},1320{0xa1, 0x18, 0x42, 0xea, 0x00, 0x00, 0x00, 0x10},1321{0xa1, 0x18, 0x43, 0xf5, 0x00, 0x00, 0x00, 0x10},1322{0xa1, 0x18, 0x45, 0x80, 0x00, 0x00, 0x00, 0x10},1323{0xa1, 0x18, 0x46, 0x60, 0x00, 0x00, 0x00, 0x10},1324{0xa1, 0x18, 0x47, 0x50, 0x00, 0x00, 0x00, 0x10},1325{0xa1, 0x18, 0x48, 0x30, 0x00, 0x00, 0x00, 0x10},1326{0xa1, 0x18, 0x49, 0x01, 0x00, 0x00, 0x00, 0x10},1327{0xa1, 0x18, 0x4d, 0xae, 0x00, 0x00, 0x00, 0x10},1328{0xa1, 0x18, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x10},1329{0xa1, 0x18, 0x4f, 0x66, 0x00, 0x00, 0x00, 0x10},1330{0xa1, 0x18, 0x50, 0x1c, 0x00, 0x00, 0x00, 0x10},1331{0xa1, 0x18, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10},1332{0xa1, 0x18, 0x4a, 0x30, 0x00, 0x00, 0x00, 0x10},1333{0xa1, 0x18, 0x51, 0x80, 0x00, 0x00, 0x00, 0x10},1334{0xa1, 0x18, 0x52, 0x80, 0x00, 0x00, 0x00, 0x10},1335{0xa1, 0x18, 0x53, 0x80, 0x00, 0x00, 0x00, 0x10},1336{0xa1, 0x18, 0x54, 0x80, 0x00, 0x00, 0x00, 0x10},1337{0xa1, 0x18, 0x55, 0x80, 0x00, 0x00, 0x00, 0x10},1338{0xa1, 0x18, 0x56, 0x80, 0x00, 0x00, 0x00, 0x10},1339{0xa1, 0x18, 0x57, 0xe0, 0x00, 0x00, 0x00, 0x10},1340{0xa1, 0x18, 0x58, 0xc0, 0x00, 0x00, 0x00, 0x10},1341{0xa1, 0x18, 0x59, 0xab, 0x00, 0x00, 0x00, 0x10},1342{0xa1, 0x18, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x10},1343{0xa1, 0x18, 0x5b, 0x99, 0x00, 0x00, 0x00, 0x10},1344{0xa1, 0x18, 0x5c, 0x90, 0x00, 0x00, 0x00, 0x10},1345{0xa1, 0x18, 0x5e, 0x24, 0x00, 0x00, 0x00, 0x10},1346{0xa1, 0x18, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x10},1347{0xa1, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10},1348{0xa1, 0x18, 0x61, 0x73, 0x00, 0x00, 0x00, 0x10},1349{0xa1, 0x18, 0x63, 0x42, 0x00, 0x00, 0x00, 0x10},1350{0xa1, 0x18, 0x64, 0x42, 0x00, 0x00, 0x00, 0x10},1351{0xa1, 0x18, 0x65, 0x42, 0x00, 0x00, 0x00, 0x10},1352{0xa1, 0x18, 0x66, 0x24, 0x00, 0x00, 0x00, 0x10},1353{0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10},1354{0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10},1355{0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10},1356{}1357};1358static const u8 sp80708_sensor_param1[][8] = {1359{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},1360{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},1361{0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10},1362{0xa1, 0x18, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x10},1363{0xa1, 0x18, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x10},1364{0xa1, 0x18, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},1365{0xb1, 0x18, 0x11, 0x40, 0x40, 0x00, 0x00, 0x10},1366{}1367};13681369static const u8 (*sensor_init[])[8] = {1370[SENSOR_ADCM1700] = adcm1700_sensor_init,1371[SENSOR_GC0307] = gc0307_sensor_init,1372[SENSOR_HV7131R] = hv7131r_sensor_init,1373[SENSOR_MI0360] = mi0360_sensor_init,1374[SENSOR_MI0360B] = mi0360b_sensor_init,1375[SENSOR_MO4000] = mo4000_sensor_init,1376[SENSOR_MT9V111] = mt9v111_sensor_init,1377[SENSOR_OM6802] = om6802_sensor_init,1378[SENSOR_OV7630] = ov7630_sensor_init,1379[SENSOR_OV7648] = ov7648_sensor_init,1380[SENSOR_OV7660] = ov7660_sensor_init,1381[SENSOR_PO1030] = po1030_sensor_init,1382[SENSOR_PO2030N] = po2030n_sensor_init,1383[SENSOR_SOI768] = soi768_sensor_init,1384[SENSOR_SP80708] = sp80708_sensor_init,1385};13861387/* read <len> bytes to gspca_dev->usb_buf */1388static void reg_r(struct gspca_dev *gspca_dev,1389u16 value, int len)1390{1391int ret;13921393if (gspca_dev->usb_err < 0)1394return;1395#ifdef GSPCA_DEBUG1396if (len > USB_BUF_SZ) {1397err("reg_r: buffer overflow");1398return;1399}1400#endif1401ret = usb_control_msg(gspca_dev->dev,1402usb_rcvctrlpipe(gspca_dev->dev, 0),14030,1404USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,1405value, 0,1406gspca_dev->usb_buf, len,1407500);1408PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);1409if (ret < 0) {1410err("reg_r err %d", ret);1411gspca_dev->usb_err = ret;1412}1413}14141415static void reg_w1(struct gspca_dev *gspca_dev,1416u16 value,1417u8 data)1418{1419int ret;14201421if (gspca_dev->usb_err < 0)1422return;1423PDEBUG(D_USBO, "reg_w1 [%04x] = %02x", value, data);1424gspca_dev->usb_buf[0] = data;1425ret = usb_control_msg(gspca_dev->dev,1426usb_sndctrlpipe(gspca_dev->dev, 0),14270x08,1428USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,1429value,14300,1431gspca_dev->usb_buf, 1,1432500);1433if (ret < 0) {1434err("reg_w1 err %d", ret);1435gspca_dev->usb_err = ret;1436}1437}1438static void reg_w(struct gspca_dev *gspca_dev,1439u16 value,1440const u8 *buffer,1441int len)1442{1443int ret;14441445if (gspca_dev->usb_err < 0)1446return;1447PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..",1448value, buffer[0], buffer[1]);1449#ifdef GSPCA_DEBUG1450if (len > USB_BUF_SZ) {1451err("reg_w: buffer overflow");1452return;1453}1454#endif1455memcpy(gspca_dev->usb_buf, buffer, len);1456ret = usb_control_msg(gspca_dev->dev,1457usb_sndctrlpipe(gspca_dev->dev, 0),14580x08,1459USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,1460value, 0,1461gspca_dev->usb_buf, len,1462500);1463if (ret < 0) {1464err("reg_w err %d", ret);1465gspca_dev->usb_err = ret;1466}1467}14681469/* I2C write 1 byte */1470static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)1471{1472struct sd *sd = (struct sd *) gspca_dev;1473int ret;14741475if (gspca_dev->usb_err < 0)1476return;1477PDEBUG(D_USBO, "i2c_w1 [%02x] = %02x", reg, val);1478switch (sd->sensor) {1479case SENSOR_ADCM1700:1480case SENSOR_OM6802:1481case SENSOR_GC0307: /* i2c command = a0 (100 kHz) */1482gspca_dev->usb_buf[0] = 0x80 | (2 << 4);1483break;1484default: /* i2c command = a1 (400 kHz) */1485gspca_dev->usb_buf[0] = 0x81 | (2 << 4);1486break;1487}1488gspca_dev->usb_buf[1] = sd->i2c_addr;1489gspca_dev->usb_buf[2] = reg;1490gspca_dev->usb_buf[3] = val;1491gspca_dev->usb_buf[4] = 0;1492gspca_dev->usb_buf[5] = 0;1493gspca_dev->usb_buf[6] = 0;1494gspca_dev->usb_buf[7] = 0x10;1495ret = usb_control_msg(gspca_dev->dev,1496usb_sndctrlpipe(gspca_dev->dev, 0),14970x08,1498USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,14990x08, /* value = i2c */15000,1501gspca_dev->usb_buf, 8,1502500);1503if (ret < 0) {1504err("i2c_w1 err %d", ret);1505gspca_dev->usb_err = ret;1506}1507}15081509/* I2C write 8 bytes */1510static void i2c_w8(struct gspca_dev *gspca_dev,1511const u8 *buffer)1512{1513int ret;15141515if (gspca_dev->usb_err < 0)1516return;1517PDEBUG(D_USBO, "i2c_w8 [%02x] = %02x ..",1518buffer[2], buffer[3]);1519memcpy(gspca_dev->usb_buf, buffer, 8);1520ret = usb_control_msg(gspca_dev->dev,1521usb_sndctrlpipe(gspca_dev->dev, 0),15220x08,1523USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,15240x08, 0, /* value, index */1525gspca_dev->usb_buf, 8,1526500);1527msleep(2);1528if (ret < 0) {1529err("i2c_w8 err %d", ret);1530gspca_dev->usb_err = ret;1531}1532}15331534/* sensor read 'len' (1..5) bytes in gspca_dev->usb_buf */1535static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len)1536{1537struct sd *sd = (struct sd *) gspca_dev;1538u8 mode[8];15391540switch (sd->sensor) {1541case SENSOR_ADCM1700:1542case SENSOR_OM6802:1543case SENSOR_GC0307: /* i2c command = a0 (100 kHz) */1544mode[0] = 0x80 | 0x10;1545break;1546default: /* i2c command = 91 (400 kHz) */1547mode[0] = 0x81 | 0x10;1548break;1549}1550mode[1] = sd->i2c_addr;1551mode[2] = reg;1552mode[3] = 0;1553mode[4] = 0;1554mode[5] = 0;1555mode[6] = 0;1556mode[7] = 0x10;1557i2c_w8(gspca_dev, mode);1558msleep(2);1559mode[0] = (mode[0] & 0x81) | (len << 4) | 0x02;1560mode[2] = 0;1561i2c_w8(gspca_dev, mode);1562msleep(2);1563reg_r(gspca_dev, 0x0a, 5);1564}15651566static void i2c_w_seq(struct gspca_dev *gspca_dev,1567const u8 (*data)[8])1568{1569while ((*data)[0] != 0) {1570if ((*data)[0] != DELAY)1571i2c_w8(gspca_dev, *data);1572else1573msleep((*data)[1]);1574data++;1575}1576}15771578/* check the ID of the hv7131 sensor */1579/* this sequence is needed because it activates the sensor */1580static void hv7131r_probe(struct gspca_dev *gspca_dev)1581{1582i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */1583msleep(10);1584reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */1585msleep(10);1586i2c_r(gspca_dev, 0, 5); /* read sensor id */1587if (gspca_dev->usb_buf[0] == 0x02 /* chip ID (02 is R) */1588&& gspca_dev->usb_buf[1] == 0x091589&& gspca_dev->usb_buf[2] == 0x01) {1590PDEBUG(D_PROBE, "Sensor HV7131R found");1591return;1592}1593warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x",1594gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],1595gspca_dev->usb_buf[2]);1596}15971598static void mi0360_probe(struct gspca_dev *gspca_dev)1599{1600struct sd *sd = (struct sd *) gspca_dev;1601int i, j;1602u16 val = 0;1603static const u8 probe_tb[][4][8] = {1604{ /* mi0360 */1605{0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},1606{0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},1607{0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},1608{0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}1609},1610{ /* mt9v111 */1611{0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10},1612{0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10},1613{0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},1614{}1615},1616};16171618for (i = 0; i < ARRAY_SIZE(probe_tb); i++) {1619reg_w1(gspca_dev, 0x17, 0x62);1620reg_w1(gspca_dev, 0x01, 0x08);1621for (j = 0; j < 3; j++)1622i2c_w8(gspca_dev, probe_tb[i][j]);1623msleep(2);1624reg_r(gspca_dev, 0x0a, 5);1625val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];1626if (probe_tb[i][3][0] != 0)1627i2c_w8(gspca_dev, probe_tb[i][3]);1628reg_w1(gspca_dev, 0x01, 0x29);1629reg_w1(gspca_dev, 0x17, 0x42);1630if (val != 0xffff)1631break;1632}1633if (gspca_dev->usb_err < 0)1634return;1635switch (val) {1636case 0x8221:1637PDEBUG(D_PROBE, "Sensor mi0360b");1638sd->sensor = SENSOR_MI0360B;1639break;1640case 0x823a:1641PDEBUG(D_PROBE, "Sensor mt9v111");1642sd->sensor = SENSOR_MT9V111;1643break;1644case 0x8243:1645PDEBUG(D_PROBE, "Sensor mi0360");1646break;1647default:1648PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val);1649break;1650}1651}16521653static void ov7630_probe(struct gspca_dev *gspca_dev)1654{1655struct sd *sd = (struct sd *) gspca_dev;1656u16 val;16571658/* check ov76xx */1659reg_w1(gspca_dev, 0x17, 0x62);1660reg_w1(gspca_dev, 0x01, 0x08);1661sd->i2c_addr = 0x21;1662i2c_r(gspca_dev, 0x0a, 2);1663val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];1664reg_w1(gspca_dev, 0x01, 0x29);1665reg_w1(gspca_dev, 0x17, 0x42);1666if (gspca_dev->usb_err < 0)1667return;1668if (val == 0x7628) { /* soi768 */1669sd->sensor = SENSOR_SOI768;1670/*fixme: only valid for 0c45:613e?*/1671gspca_dev->cam.input_flags =1672V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;1673PDEBUG(D_PROBE, "Sensor soi768");1674return;1675}1676PDEBUG(D_PROBE, "Sensor ov%04x", val);1677}16781679static void ov7648_probe(struct gspca_dev *gspca_dev)1680{1681struct sd *sd = (struct sd *) gspca_dev;1682u16 val;16831684/* check ov76xx */1685reg_w1(gspca_dev, 0x17, 0x62);1686reg_w1(gspca_dev, 0x01, 0x08);1687sd->i2c_addr = 0x21;1688i2c_r(gspca_dev, 0x0a, 2);1689val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];1690reg_w1(gspca_dev, 0x01, 0x29);1691reg_w1(gspca_dev, 0x17, 0x42);1692if ((val & 0xff00) == 0x7600) { /* ov76xx */1693PDEBUG(D_PROBE, "Sensor ov%04x", val);1694return;1695}16961697/* check po1030 */1698reg_w1(gspca_dev, 0x17, 0x62);1699reg_w1(gspca_dev, 0x01, 0x08);1700sd->i2c_addr = 0x6e;1701i2c_r(gspca_dev, 0x00, 2);1702val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];1703reg_w1(gspca_dev, 0x01, 0x29);1704reg_w1(gspca_dev, 0x17, 0x42);1705if (gspca_dev->usb_err < 0)1706return;1707if (val == 0x1030) { /* po1030 */1708PDEBUG(D_PROBE, "Sensor po1030");1709sd->sensor = SENSOR_PO1030;1710return;1711}1712err("Unknown sensor %04x", val);1713}17141715/* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */1716static void po2030n_probe(struct gspca_dev *gspca_dev)1717{1718struct sd *sd = (struct sd *) gspca_dev;1719u16 val;17201721/* check gc0307 */1722reg_w1(gspca_dev, 0x17, 0x62);1723reg_w1(gspca_dev, 0x01, 0x08);1724reg_w1(gspca_dev, 0x02, 0x22);1725sd->i2c_addr = 0x21;1726i2c_r(gspca_dev, 0x00, 1);1727val = gspca_dev->usb_buf[4];1728reg_w1(gspca_dev, 0x01, 0x29); /* reset */1729reg_w1(gspca_dev, 0x17, 0x42);1730if (val == 0x99) { /* gc0307 (?) */1731PDEBUG(D_PROBE, "Sensor gc0307");1732sd->sensor = SENSOR_GC0307;1733return;1734}17351736/* check po2030n */1737reg_w1(gspca_dev, 0x17, 0x62);1738reg_w1(gspca_dev, 0x01, 0x0a);1739sd->i2c_addr = 0x6e;1740i2c_r(gspca_dev, 0x00, 2);1741val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];1742reg_w1(gspca_dev, 0x01, 0x29);1743reg_w1(gspca_dev, 0x17, 0x42);1744if (gspca_dev->usb_err < 0)1745return;1746if (val == 0x2030) {1747PDEBUG(D_PROBE, "Sensor po2030n");1748/* sd->sensor = SENSOR_PO2030N; */1749} else {1750err("Unknown sensor ID %04x", val);1751}1752}17531754/* this function is called at probe time */1755static int sd_config(struct gspca_dev *gspca_dev,1756const struct usb_device_id *id)1757{1758struct sd *sd = (struct sd *) gspca_dev;1759struct cam *cam;17601761sd->bridge = id->driver_info >> 16;1762sd->sensor = id->driver_info >> 8;1763sd->flags = id->driver_info;17641765cam = &gspca_dev->cam;1766if (sd->sensor == SENSOR_ADCM1700) {1767cam->cam_mode = cif_mode;1768cam->nmodes = ARRAY_SIZE(cif_mode);1769} else {1770cam->cam_mode = vga_mode;1771cam->nmodes = ARRAY_SIZE(vga_mode);1772}1773cam->npkt = 24; /* 24 packets per ISOC message */1774cam->ctrls = sd->ctrls;17751776sd->ag_cnt = -1;1777sd->quality = QUALITY_DEF;17781779/* if USB 1.1, let some bandwidth for the audio device */1780if (gspca_dev->audio && gspca_dev->dev->speed < USB_SPEED_HIGH)1781gspca_dev->nbalt--;17821783INIT_WORK(&sd->work, qual_upd);17841785return 0;1786}17871788/* this function is called at probe and resume time */1789static int sd_init(struct gspca_dev *gspca_dev)1790{1791struct sd *sd = (struct sd *) gspca_dev;1792const u8 *sn9c1xx;1793u8 regGpio[] = { 0x29, 0x70 }; /* no audio */1794u8 regF1;17951796/* setup a selector by bridge */1797reg_w1(gspca_dev, 0xf1, 0x01);1798reg_r(gspca_dev, 0x00, 1);1799reg_w1(gspca_dev, 0xf1, 0x00);1800reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */1801regF1 = gspca_dev->usb_buf[0];1802if (gspca_dev->usb_err < 0)1803return gspca_dev->usb_err;1804PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);1805if (gspca_dev->audio)1806regGpio[1] |= 0x04; /* with audio */1807switch (sd->bridge) {1808case BRIDGE_SN9C102P:1809case BRIDGE_SN9C105:1810if (regF1 != 0x11)1811return -ENODEV;1812break;1813default:1814/* case BRIDGE_SN9C110: */1815/* case BRIDGE_SN9C120: */1816if (regF1 != 0x12)1817return -ENODEV;1818}18191820switch (sd->sensor) {1821case SENSOR_MI0360:1822mi0360_probe(gspca_dev);1823break;1824case SENSOR_OV7630:1825ov7630_probe(gspca_dev);1826break;1827case SENSOR_OV7648:1828ov7648_probe(gspca_dev);1829break;1830case SENSOR_PO2030N:1831po2030n_probe(gspca_dev);1832break;1833}18341835switch (sd->bridge) {1836case BRIDGE_SN9C102P:1837reg_w1(gspca_dev, 0x02, regGpio[1]);1838break;1839default:1840reg_w(gspca_dev, 0x01, regGpio, 2);1841break;1842}18431844if (sd->sensor == SENSOR_OM6802)1845sd->ctrls[SHARPNESS].def = 0x10;18461847/* Note we do not disable the sensor clock here (power saving mode),1848as that also disables the button on the cam. */1849reg_w1(gspca_dev, 0xf1, 0x00);18501851/* set the i2c address */1852sn9c1xx = sn_tb[sd->sensor];1853sd->i2c_addr = sn9c1xx[9];18541855gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];1856if (!(sd->flags & F_ILLUM))1857gspca_dev->ctrl_dis |= (1 << ILLUM);18581859return gspca_dev->usb_err;1860}18611862static u32 setexposure(struct gspca_dev *gspca_dev,1863u32 expo)1864{1865struct sd *sd = (struct sd *) gspca_dev;18661867switch (sd->sensor) {1868case SENSOR_GC0307: {1869int a, b;18701871/* expo = 0..255 -> a = 19..43 */1872a = 19 + expo * 25 / 256;1873i2c_w1(gspca_dev, 0x68, a);1874a -= 12;1875b = a * a * 4; /* heuristic */1876i2c_w1(gspca_dev, 0x03, b >> 8);1877i2c_w1(gspca_dev, 0x04, b);1878break;1879}1880case SENSOR_HV7131R: {1881u8 Expodoit[] =1882{ 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 };18831884Expodoit[3] = expo >> 16;1885Expodoit[4] = expo >> 8;1886Expodoit[5] = expo;1887i2c_w8(gspca_dev, Expodoit);1888break;1889}1890case SENSOR_MI0360:1891case SENSOR_MI0360B: {1892u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */1893{ 0xb1, 0x5d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x16 };1894static const u8 doit[] = /* update sensor */1895{ 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };1896static const u8 sensorgo[] = /* sensor on */1897{ 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };18981899if (expo > 0x0635)1900expo = 0x0635;1901else if (expo < 0x0001)1902expo = 0x0001;1903expoMi[3] = expo >> 8;1904expoMi[4] = expo;1905i2c_w8(gspca_dev, expoMi);1906i2c_w8(gspca_dev, doit);1907i2c_w8(gspca_dev, sensorgo);1908break;1909}1910case SENSOR_MO4000: {1911u8 expoMof[] =1912{ 0xa1, 0x21, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x10 };1913u8 expoMo10[] =1914{ 0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10 };1915static const u8 gainMo[] =1916{ 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };19171918if (expo > 0x1fff)1919expo = 0x1fff;1920else if (expo < 0x0001)1921expo = 0x0001;1922expoMof[3] = (expo & 0x03fc) >> 2;1923i2c_w8(gspca_dev, expoMof);1924expoMo10[3] = ((expo & 0x1c00) >> 10)1925| ((expo & 0x0003) << 4);1926i2c_w8(gspca_dev, expoMo10);1927i2c_w8(gspca_dev, gainMo);1928PDEBUG(D_FRAM, "set exposure %d",1929((expoMo10[3] & 0x07) << 10)1930| (expoMof[3] << 2)1931| ((expoMo10[3] & 0x30) >> 4));1932break;1933}1934case SENSOR_MT9V111: {1935u8 expo_c1[] =1936{ 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 };19371938if (expo > 0x0390)1939expo = 0x0390;1940else if (expo < 0x0060)1941expo = 0x0060;1942expo_c1[3] = expo >> 8;1943expo_c1[4] = expo;1944i2c_w8(gspca_dev, expo_c1);1945break;1946}1947case SENSOR_OM6802: {1948u8 gainOm[] =1949{ 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };1950/* preset AGC - works when AutoExpo = off */19511952if (expo > 0x03ff)1953expo = 0x03ff;1954if (expo < 0x0001)1955expo = 0x0001;1956gainOm[3] = expo >> 2;1957i2c_w8(gspca_dev, gainOm);1958reg_w1(gspca_dev, 0x96, expo >> 5);1959PDEBUG(D_FRAM, "set exposure %d", gainOm[3]);1960break;1961}1962}1963return expo;1964}19651966static void setbrightness(struct gspca_dev *gspca_dev)1967{1968struct sd *sd = (struct sd *) gspca_dev;1969unsigned int expo;1970int brightness;1971u8 k2;19721973brightness = sd->ctrls[BRIGHTNESS].val;1974k2 = (brightness - 0x80) >> 2;1975switch (sd->sensor) {1976case SENSOR_ADCM1700:1977if (k2 > 0x1f)1978k2 = 0; /* only positive Y offset */1979break;1980case SENSOR_HV7131R:1981expo = brightness << 12;1982if (expo > 0x002dc6c0)1983expo = 0x002dc6c0;1984else if (expo < 0x02a0)1985expo = 0x02a0;1986sd->exposure = setexposure(gspca_dev, expo);1987break;1988case SENSOR_MI0360:1989case SENSOR_MO4000:1990expo = brightness << 4;1991sd->exposure = setexposure(gspca_dev, expo);1992break;1993case SENSOR_MI0360B:1994expo = brightness << 2;1995sd->exposure = setexposure(gspca_dev, expo);1996break;1997case SENSOR_GC0307:1998expo = brightness;1999sd->exposure = setexposure(gspca_dev, expo);2000return; /* don't set the Y offset */2001case SENSOR_MT9V111:2002expo = brightness << 2;2003sd->exposure = setexposure(gspca_dev, expo);2004return; /* don't set the Y offset */2005case SENSOR_OM6802:2006expo = brightness << 2;2007sd->exposure = setexposure(gspca_dev, expo);2008k2 = brightness >> 3;2009break;2010}20112012reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */2013}20142015static void setcontrast(struct gspca_dev *gspca_dev)2016{2017struct sd *sd = (struct sd *) gspca_dev;2018u8 k2;2019u8 contrast[6];20202021k2 = sd->ctrls[CONTRAST].val * 0x30 / (CONTRAST_MAX + 1)2022+ 0x10; /* 10..40 */2023contrast[0] = (k2 + 1) / 2; /* red */2024contrast[1] = 0;2025contrast[2] = k2; /* green */2026contrast[3] = 0;2027contrast[4] = (k2 + 1) / 5; /* blue */2028contrast[5] = 0;2029reg_w(gspca_dev, 0x84, contrast, sizeof contrast);2030}20312032static void setcolors(struct gspca_dev *gspca_dev)2033{2034struct sd *sd = (struct sd *) gspca_dev;2035int i, v, colors;2036const s16 *uv;2037u8 reg8a[12]; /* U & V gains */2038static const s16 uv_com[6] = { /* same as reg84 in signed decimal */2039-24, -38, 64, /* UR UG UB */204062, -51, -9 /* VR VG VB */2041};2042static const s16 uv_mi0360b[6] = {2043-20, -38, 64, /* UR UG UB */204460, -51, -9 /* VR VG VB */2045};20462047colors = sd->ctrls[COLORS].val;2048if (sd->sensor == SENSOR_MI0360B)2049uv = uv_mi0360b;2050else2051uv = uv_com;2052for (i = 0; i < 6; i++) {2053v = uv[i] * colors / COLORS_DEF;2054reg8a[i * 2] = v;2055reg8a[i * 2 + 1] = (v >> 8) & 0x0f;2056}2057reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);2058}20592060static void setredblue(struct gspca_dev *gspca_dev)2061{2062struct sd *sd = (struct sd *) gspca_dev;20632064reg_w1(gspca_dev, 0x05, sd->ctrls[RED].val);2065/* reg_w1(gspca_dev, 0x07, 32); */2066reg_w1(gspca_dev, 0x06, sd->ctrls[BLUE].val);2067}20682069static void setgamma(struct gspca_dev *gspca_dev)2070{2071struct sd *sd = (struct sd *) gspca_dev;2072int i, val;2073u8 gamma[17];2074const u8 *gamma_base;2075static const u8 delta[17] = {20760x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a,20770x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x002078};20792080switch (sd->sensor) {2081case SENSOR_ADCM1700:2082gamma_base = gamma_spec_0;2083break;2084case SENSOR_HV7131R:2085case SENSOR_MI0360B:2086case SENSOR_MT9V111:2087gamma_base = gamma_spec_1;2088break;2089case SENSOR_GC0307:2090gamma_base = gamma_spec_2;2091break;2092case SENSOR_SP80708:2093gamma_base = gamma_spec_3;2094break;2095default:2096gamma_base = gamma_def;2097break;2098}20992100val = sd->ctrls[GAMMA].val;2101for (i = 0; i < sizeof gamma; i++)2102gamma[i] = gamma_base[i]2103+ delta[i] * (val - GAMMA_DEF) / 32;2104reg_w(gspca_dev, 0x20, gamma, sizeof gamma);2105}21062107static void setautogain(struct gspca_dev *gspca_dev)2108{2109struct sd *sd = (struct sd *) gspca_dev;21102111if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))2112return;2113switch (sd->sensor) {2114case SENSOR_OV7630:2115case SENSOR_OV7648: {2116u8 comb;21172118if (sd->sensor == SENSOR_OV7630)2119comb = 0xc0;2120else2121comb = 0xa0;2122if (sd->ctrls[AUTOGAIN].val)2123comb |= 0x03;2124i2c_w1(&sd->gspca_dev, 0x13, comb);2125return;2126}2127}2128if (sd->ctrls[AUTOGAIN].val)2129sd->ag_cnt = AG_CNT_START;2130else2131sd->ag_cnt = -1;2132}21332134static void sethvflip(struct gspca_dev *gspca_dev)2135{2136struct sd *sd = (struct sd *) gspca_dev;2137u8 comn;21382139switch (sd->sensor) {2140case SENSOR_HV7131R:2141comn = 0x18; /* clkdiv = 1, ablcen = 1 */2142if (sd->ctrls[VFLIP].val)2143comn |= 0x01;2144i2c_w1(gspca_dev, 0x01, comn); /* sctra */2145break;2146case SENSOR_OV7630:2147comn = 0x02;2148if (!sd->ctrls[VFLIP].val)2149comn |= 0x80;2150i2c_w1(gspca_dev, 0x75, comn);2151break;2152case SENSOR_OV7648:2153comn = 0x06;2154if (sd->ctrls[VFLIP].val)2155comn |= 0x80;2156i2c_w1(gspca_dev, 0x75, comn);2157break;2158case SENSOR_PO2030N:2159/* Reg. 0x1E: Timing Generator Control Register 2 (Tgcontrol2)2160* (reset value: 0x0A)2161* bit7: HM: Horizontal Mirror: 0: disable, 1: enable2162* bit6: VM: Vertical Mirror: 0: disable, 1: enable2163* bit5: ST: Shutter Selection: 0: electrical, 1: mechanical2164* bit4: FT: Single Frame Transfer: 0: disable, 1: enable2165* bit3-0: X2166*/2167comn = 0x0a;2168if (sd->ctrls[HFLIP].val)2169comn |= 0x80;2170if (sd->ctrls[VFLIP].val)2171comn |= 0x40;2172i2c_w1(&sd->gspca_dev, 0x1e, comn);2173break;2174}2175}21762177static void setsharpness(struct gspca_dev *gspca_dev)2178{2179struct sd *sd = (struct sd *) gspca_dev;21802181reg_w1(gspca_dev, 0x99, sd->ctrls[SHARPNESS].val);2182}21832184static void setillum(struct gspca_dev *gspca_dev)2185{2186struct sd *sd = (struct sd *) gspca_dev;21872188if (gspca_dev->ctrl_dis & (1 << ILLUM))2189return;2190switch (sd->sensor) {2191case SENSOR_ADCM1700:2192reg_w1(gspca_dev, 0x02, /* gpio */2193sd->ctrls[ILLUM].val ? 0x64 : 0x60);2194break;2195case SENSOR_MT9V111:2196reg_w1(gspca_dev, 0x02,2197sd->ctrls[ILLUM].val ? 0x77 : 0x74);2198/* should have been: */2199/* 0x55 : 0x54); * 370i */2200/* 0x66 : 0x64); * Clip */2201break;2202}2203}22042205static void setfreq(struct gspca_dev *gspca_dev)2206{2207struct sd *sd = (struct sd *) gspca_dev;22082209if (gspca_dev->ctrl_dis & (1 << FREQ))2210return;2211if (sd->sensor == SENSOR_OV7660) {2212u8 com8;22132214com8 = 0xdf; /* auto gain/wb/expo */2215switch (sd->ctrls[FREQ].val) {2216case 0: /* Banding filter disabled */2217i2c_w1(gspca_dev, 0x13, com8 | 0x20);2218break;2219case 1: /* 50 hz */2220i2c_w1(gspca_dev, 0x13, com8);2221i2c_w1(gspca_dev, 0x3b, 0x0a);2222break;2223case 2: /* 60 hz */2224i2c_w1(gspca_dev, 0x13, com8);2225i2c_w1(gspca_dev, 0x3b, 0x02);2226break;2227}2228} else {2229u8 reg2a = 0, reg2b = 0, reg2d = 0;22302231/* Get reg2a / reg2d base values */2232switch (sd->sensor) {2233case SENSOR_OV7630:2234reg2a = 0x08;2235reg2d = 0x01;2236break;2237case SENSOR_OV7648:2238reg2a = 0x11;2239reg2d = 0x81;2240break;2241}22422243switch (sd->ctrls[FREQ].val) {2244case 0: /* Banding filter disabled */2245break;2246case 1: /* 50 hz (filter on and framerate adj) */2247reg2a |= 0x80;2248reg2b = 0xac;2249reg2d |= 0x04;2250break;2251case 2: /* 60 hz (filter on, no framerate adj) */2252reg2a |= 0x80;2253reg2d |= 0x04;2254break;2255}2256i2c_w1(gspca_dev, 0x2a, reg2a);2257i2c_w1(gspca_dev, 0x2b, reg2b);2258i2c_w1(gspca_dev, 0x2d, reg2d);2259}2260}22612262static void setjpegqual(struct gspca_dev *gspca_dev)2263{2264struct sd *sd = (struct sd *) gspca_dev;22652266jpeg_set_qual(sd->jpeg_hdr, sd->quality);2267#if USB_BUF_SZ < 642268#error "No room enough in usb_buf for quantization table"2269#endif2270memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);2271usb_control_msg(gspca_dev->dev,2272usb_sndctrlpipe(gspca_dev->dev, 0),22730x08,2274USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,22750x0100, 0,2276gspca_dev->usb_buf, 64,2277500);2278memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);2279usb_control_msg(gspca_dev->dev,2280usb_sndctrlpipe(gspca_dev->dev, 0),22810x08,2282USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,22830x0140, 0,2284gspca_dev->usb_buf, 64,2285500);22862287sd->reg18 ^= 0x40;2288reg_w1(gspca_dev, 0x18, sd->reg18);2289}22902291/* JPEG quality update */2292/* This function is executed from a work queue. */2293static void qual_upd(struct work_struct *work)2294{2295struct sd *sd = container_of(work, struct sd, work);2296struct gspca_dev *gspca_dev = &sd->gspca_dev;22972298mutex_lock(&gspca_dev->usb_lock);2299PDEBUG(D_STREAM, "qual_upd %d%%", sd->quality);2300setjpegqual(gspca_dev);2301mutex_unlock(&gspca_dev->usb_lock);2302}23032304/* -- start the camera -- */2305static int sd_start(struct gspca_dev *gspca_dev)2306{2307struct sd *sd = (struct sd *) gspca_dev;2308int i;2309u8 reg01, reg17;2310u8 reg0102[2];2311const u8 *sn9c1xx;2312const u8 (*init)[8];2313const u8 *reg9a;2314int mode;2315static const u8 reg9a_def[] =2316{0x00, 0x40, 0x20, 0x00, 0x00, 0x00};2317static const u8 reg9a_spec[] =2318{0x00, 0x40, 0x38, 0x30, 0x00, 0x20};2319static const u8 regd4[] = {0x60, 0x00, 0x00};2320static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };2321static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };2322static const u8 CA_adcm1700[] =2323{ 0x14, 0xec, 0x0a, 0xf6 };2324static const u8 CA_po2030n[] =2325{ 0x1e, 0xe2, 0x14, 0xec };2326static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */2327static const u8 CE_gc0307[] =2328{ 0x32, 0xce, 0x2d, 0xd3 };2329static const u8 CE_ov76xx[] =2330{ 0x32, 0xdd, 0x32, 0xdd };2331static const u8 CE_po2030n[] =2332{ 0x14, 0xe7, 0x1e, 0xdd };23332334/* create the JPEG header */2335jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,23360x21); /* JPEG 422 */23372338/* initialize the bridge */2339sn9c1xx = sn_tb[sd->sensor];23402341/* sensor clock already enabled in sd_init */2342/* reg_w1(gspca_dev, 0xf1, 0x00); */2343reg01 = sn9c1xx[1];2344if (sd->flags & F_PDN_INV)2345reg01 ^= S_PDN_INV; /* power down inverted */2346reg_w1(gspca_dev, 0x01, reg01);23472348/* configure gpio */2349reg0102[0] = reg01;2350reg0102[1] = sn9c1xx[2];2351if (gspca_dev->audio)2352reg0102[1] |= 0x04; /* keep the audio connection */2353reg_w(gspca_dev, 0x01, reg0102, 2);2354reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);2355reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);2356switch (sd->sensor) {2357case SENSOR_GC0307:2358case SENSOR_OV7660:2359case SENSOR_PO1030:2360case SENSOR_PO2030N:2361case SENSOR_SOI768:2362case SENSOR_SP80708:2363reg9a = reg9a_spec;2364break;2365default:2366reg9a = reg9a_def;2367break;2368}2369reg_w(gspca_dev, 0x9a, reg9a, 6);23702371reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);23722373reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);23742375reg17 = sn9c1xx[0x17];2376switch (sd->sensor) {2377case SENSOR_GC0307:2378msleep(50); /*fixme: is it useful? */2379break;2380case SENSOR_OM6802:2381msleep(10);2382reg_w1(gspca_dev, 0x02, 0x73);2383reg17 |= SEN_CLK_EN;2384reg_w1(gspca_dev, 0x17, reg17);2385reg_w1(gspca_dev, 0x01, 0x22);2386msleep(100);2387reg01 = SCL_SEL_OD | S_PDN_INV;2388reg17 &= MCK_SIZE_MASK;2389reg17 |= 0x04; /* clock / 4 */2390break;2391}2392reg01 |= SYS_SEL_48M;2393reg_w1(gspca_dev, 0x01, reg01);2394reg17 |= SEN_CLK_EN;2395reg_w1(gspca_dev, 0x17, reg17);2396reg01 &= ~S_PWR_DN; /* sensor power on */2397reg_w1(gspca_dev, 0x01, reg01);2398reg01 &= ~SYS_SEL_48M;2399reg_w1(gspca_dev, 0x01, reg01);24002401switch (sd->sensor) {2402case SENSOR_HV7131R:2403hv7131r_probe(gspca_dev); /*fixme: is it useful? */2404break;2405case SENSOR_OM6802:2406msleep(10);2407reg_w1(gspca_dev, 0x01, reg01);2408i2c_w8(gspca_dev, om6802_init0[0]);2409i2c_w8(gspca_dev, om6802_init0[1]);2410msleep(15);2411reg_w1(gspca_dev, 0x02, 0x71);2412msleep(150);2413break;2414case SENSOR_SP80708:2415msleep(100);2416reg_w1(gspca_dev, 0x02, 0x62);2417break;2418}24192420/* initialize the sensor */2421i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);24222423reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);2424reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);2425reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);2426reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);2427reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);2428if (sd->sensor == SENSOR_ADCM1700) {2429reg_w1(gspca_dev, 0xd2, 0x3a); /* AE_H_SIZE = 116 */2430reg_w1(gspca_dev, 0xd3, 0x30); /* AE_V_SIZE = 96 */2431} else {2432reg_w1(gspca_dev, 0xd2, 0x6a); /* AE_H_SIZE = 212 */2433reg_w1(gspca_dev, 0xd3, 0x50); /* AE_V_SIZE = 160 */2434}2435reg_w1(gspca_dev, 0xc6, 0x00);2436reg_w1(gspca_dev, 0xc7, 0x00);2437if (sd->sensor == SENSOR_ADCM1700) {2438reg_w1(gspca_dev, 0xc8, 0x2c); /* AW_H_STOP = 352 */2439reg_w1(gspca_dev, 0xc9, 0x24); /* AW_V_STOP = 288 */2440} else {2441reg_w1(gspca_dev, 0xc8, 0x50); /* AW_H_STOP = 640 */2442reg_w1(gspca_dev, 0xc9, 0x3c); /* AW_V_STOP = 480 */2443}2444reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);2445switch (sd->sensor) {2446case SENSOR_OM6802:2447/* case SENSOR_OV7648: * fixme: sometimes */2448break;2449default:2450reg17 |= DEF_EN;2451break;2452}2453reg_w1(gspca_dev, 0x17, reg17);24542455reg_w1(gspca_dev, 0x05, 0x00); /* red */2456reg_w1(gspca_dev, 0x07, 0x00); /* green */2457reg_w1(gspca_dev, 0x06, 0x00); /* blue */2458reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);24592460setgamma(gspca_dev);24612462/*fixme: 8 times with all zeroes and 1 or 2 times with normal values */2463for (i = 0; i < 8; i++)2464reg_w(gspca_dev, 0x84, reg84, sizeof reg84);2465switch (sd->sensor) {2466case SENSOR_ADCM1700:2467case SENSOR_OV7660:2468case SENSOR_SP80708:2469reg_w1(gspca_dev, 0x9a, 0x05);2470break;2471case SENSOR_GC0307:2472case SENSOR_MT9V111:2473case SENSOR_MI0360B:2474reg_w1(gspca_dev, 0x9a, 0x07);2475break;2476case SENSOR_OV7630:2477case SENSOR_OV7648:2478reg_w1(gspca_dev, 0x9a, 0x0a);2479break;2480case SENSOR_PO2030N:2481case SENSOR_SOI768:2482reg_w1(gspca_dev, 0x9a, 0x06);2483break;2484default:2485reg_w1(gspca_dev, 0x9a, 0x08);2486break;2487}2488setsharpness(gspca_dev);24892490reg_w(gspca_dev, 0x84, reg84, sizeof reg84);2491reg_w1(gspca_dev, 0x05, 0x20); /* red */2492reg_w1(gspca_dev, 0x07, 0x20); /* green */2493reg_w1(gspca_dev, 0x06, 0x20); /* blue */24942495init = NULL;2496mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;2497reg01 |= SYS_SEL_48M | V_TX_EN;2498reg17 &= ~MCK_SIZE_MASK;2499reg17 |= 0x02; /* clock / 2 */2500switch (sd->sensor) {2501case SENSOR_ADCM1700:2502init = adcm1700_sensor_param1;2503break;2504case SENSOR_GC0307:2505init = gc0307_sensor_param1;2506break;2507case SENSOR_HV7131R:2508case SENSOR_MI0360:2509if (mode)2510reg01 |= SYS_SEL_48M; /* 320x240: clk 48Mhz */2511else2512reg01 &= ~SYS_SEL_48M; /* 640x480: clk 24Mhz */2513reg17 &= ~MCK_SIZE_MASK;2514reg17 |= 0x01; /* clock / 1 */2515break;2516case SENSOR_MI0360B:2517init = mi0360b_sensor_param1;2518break;2519case SENSOR_MO4000:2520if (mode) { /* if 320x240 */2521reg01 &= ~SYS_SEL_48M; /* clk 24Mz */2522reg17 &= ~MCK_SIZE_MASK;2523reg17 |= 0x01; /* clock / 1 */2524}2525break;2526case SENSOR_MT9V111:2527init = mt9v111_sensor_param1;2528break;2529case SENSOR_OM6802:2530init = om6802_sensor_param1;2531if (!mode) { /* if 640x480 */2532reg17 &= ~MCK_SIZE_MASK;2533reg17 |= 0x04; /* clock / 4 */2534}2535break;2536case SENSOR_OV7630:2537init = ov7630_sensor_param1;2538break;2539case SENSOR_OV7648:2540init = ov7648_sensor_param1;2541reg17 &= ~MCK_SIZE_MASK;2542reg17 |= 0x01; /* clock / 1 */2543break;2544case SENSOR_OV7660:2545init = ov7660_sensor_param1;2546break;2547case SENSOR_PO1030:2548init = po1030_sensor_param1;2549break;2550case SENSOR_PO2030N:2551init = po2030n_sensor_param1;2552break;2553case SENSOR_SOI768:2554init = soi768_sensor_param1;2555break;2556case SENSOR_SP80708:2557init = sp80708_sensor_param1;2558break;2559}25602561/* more sensor initialization - param1 */2562if (init != NULL) {2563i2c_w_seq(gspca_dev, init);2564/* init = NULL; */2565}25662567reg_w(gspca_dev, 0xc0, C0, 6);2568switch (sd->sensor) {2569case SENSOR_ADCM1700:2570case SENSOR_GC0307:2571case SENSOR_SOI768:2572reg_w(gspca_dev, 0xca, CA_adcm1700, 4);2573break;2574case SENSOR_PO2030N:2575reg_w(gspca_dev, 0xca, CA_po2030n, 4);2576break;2577default:2578reg_w(gspca_dev, 0xca, CA, 4);2579break;2580}2581switch (sd->sensor) {2582case SENSOR_ADCM1700:2583case SENSOR_OV7630:2584case SENSOR_OV7648:2585case SENSOR_OV7660:2586case SENSOR_SOI768:2587reg_w(gspca_dev, 0xce, CE_ov76xx, 4);2588break;2589case SENSOR_GC0307:2590reg_w(gspca_dev, 0xce, CE_gc0307, 4);2591break;2592case SENSOR_PO2030N:2593reg_w(gspca_dev, 0xce, CE_po2030n, 4);2594break;2595default:2596reg_w(gspca_dev, 0xce, CE, 4);2597/* ?? {0x1e, 0xdd, 0x2d, 0xe7} */2598break;2599}26002601/* here change size mode 0 -> VGA; 1 -> CIF */2602sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40;2603reg_w1(gspca_dev, 0x18, sd->reg18);2604setjpegqual(gspca_dev);26052606reg_w1(gspca_dev, 0x17, reg17);2607reg_w1(gspca_dev, 0x01, reg01);2608sd->reg01 = reg01;2609sd->reg17 = reg17;26102611sethvflip(gspca_dev);2612setbrightness(gspca_dev);2613setcontrast(gspca_dev);2614setcolors(gspca_dev);2615setautogain(gspca_dev);2616setfreq(gspca_dev);26172618sd->pktsz = sd->npkt = 0;2619sd->nchg = sd->short_mark = 0;2620sd->work_thread = create_singlethread_workqueue(MODULE_NAME);26212622return gspca_dev->usb_err;2623}26242625static void sd_stopN(struct gspca_dev *gspca_dev)2626{2627struct sd *sd = (struct sd *) gspca_dev;2628static const u8 stophv7131[] =2629{ 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };2630static const u8 stopmi0360[] =2631{ 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };2632static const u8 stopov7648[] =2633{ 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };2634static const u8 stopsoi768[] =2635{ 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };2636u8 reg01;2637u8 reg17;26382639reg01 = sd->reg01;2640reg17 = sd->reg17 & ~SEN_CLK_EN;2641switch (sd->sensor) {2642case SENSOR_ADCM1700:2643case SENSOR_GC0307:2644case SENSOR_PO2030N:2645case SENSOR_SP80708:2646reg01 |= LED;2647reg_w1(gspca_dev, 0x01, reg01);2648reg01 &= ~(LED | V_TX_EN);2649reg_w1(gspca_dev, 0x01, reg01);2650/* reg_w1(gspca_dev, 0x02, 0x??); * LED off ? */2651break;2652case SENSOR_HV7131R:2653reg01 &= ~V_TX_EN;2654reg_w1(gspca_dev, 0x01, reg01);2655i2c_w8(gspca_dev, stophv7131);2656break;2657case SENSOR_MI0360:2658case SENSOR_MI0360B:2659reg01 &= ~V_TX_EN;2660reg_w1(gspca_dev, 0x01, reg01);2661/* reg_w1(gspca_dev, 0x02, 0x40); * LED off ? */2662i2c_w8(gspca_dev, stopmi0360);2663break;2664case SENSOR_MT9V111:2665case SENSOR_OM6802:2666case SENSOR_PO1030:2667reg01 &= ~V_TX_EN;2668reg_w1(gspca_dev, 0x01, reg01);2669break;2670case SENSOR_OV7630:2671case SENSOR_OV7648:2672reg01 &= ~V_TX_EN;2673reg_w1(gspca_dev, 0x01, reg01);2674i2c_w8(gspca_dev, stopov7648);2675break;2676case SENSOR_OV7660:2677reg01 &= ~V_TX_EN;2678reg_w1(gspca_dev, 0x01, reg01);2679break;2680case SENSOR_SOI768:2681i2c_w8(gspca_dev, stopsoi768);2682break;2683}26842685reg01 |= SCL_SEL_OD;2686reg_w1(gspca_dev, 0x01, reg01);2687reg01 |= S_PWR_DN; /* sensor power down */2688reg_w1(gspca_dev, 0x01, reg01);2689reg_w1(gspca_dev, 0x17, reg17);2690reg01 &= ~SYS_SEL_48M; /* clock 24MHz */2691reg_w1(gspca_dev, 0x01, reg01);2692reg01 |= LED;2693reg_w1(gspca_dev, 0x01, reg01);2694/* Don't disable sensor clock as that disables the button on the cam */2695/* reg_w1(gspca_dev, 0xf1, 0x01); */2696}26972698/* called on streamoff with alt==0 and on disconnect */2699/* the usb_lock is held at entry - restore on exit */2700static void sd_stop0(struct gspca_dev *gspca_dev)2701{2702struct sd *sd = (struct sd *) gspca_dev;27032704if (sd->work_thread != NULL) {2705mutex_unlock(&gspca_dev->usb_lock);2706destroy_workqueue(sd->work_thread);2707mutex_lock(&gspca_dev->usb_lock);2708sd->work_thread = NULL;2709}2710}27112712static void do_autogain(struct gspca_dev *gspca_dev)2713{2714struct sd *sd = (struct sd *) gspca_dev;2715int delta;2716int expotimes;2717u8 luma_mean = 130;2718u8 luma_delta = 20;27192720/* Thanks S., without your advice, autobright should not work :) */2721if (sd->ag_cnt < 0)2722return;2723if (--sd->ag_cnt >= 0)2724return;2725sd->ag_cnt = AG_CNT_START;27262727delta = atomic_read(&sd->avg_lum);2728PDEBUG(D_FRAM, "mean lum %d", delta);2729if (delta < luma_mean - luma_delta ||2730delta > luma_mean + luma_delta) {2731switch (sd->sensor) {2732case SENSOR_GC0307:2733expotimes = sd->exposure;2734expotimes += (luma_mean - delta) >> 6;2735if (expotimes < 0)2736expotimes = 0;2737sd->exposure = setexposure(gspca_dev,2738(unsigned int) expotimes);2739break;2740case SENSOR_HV7131R:2741expotimes = sd->exposure >> 8;2742expotimes += (luma_mean - delta) >> 4;2743if (expotimes < 0)2744expotimes = 0;2745sd->exposure = setexposure(gspca_dev,2746(unsigned int) (expotimes << 8));2747break;2748case SENSOR_OM6802:2749case SENSOR_MT9V111:2750expotimes = sd->exposure;2751expotimes += (luma_mean - delta) >> 2;2752if (expotimes < 0)2753expotimes = 0;2754sd->exposure = setexposure(gspca_dev,2755(unsigned int) expotimes);2756setredblue(gspca_dev);2757break;2758default:2759/* case SENSOR_MO4000: */2760/* case SENSOR_MI0360: */2761/* case SENSOR_MI0360B: */2762expotimes = sd->exposure;2763expotimes += (luma_mean - delta) >> 6;2764if (expotimes < 0)2765expotimes = 0;2766sd->exposure = setexposure(gspca_dev,2767(unsigned int) expotimes);2768setredblue(gspca_dev);2769break;2770}2771}2772}27732774/* set the average luminosity from an isoc marker */2775static void set_lum(struct sd *sd,2776u8 *data)2777{2778int avg_lum;27792780/* w0 w1 w22781* w3 w4 w52782* w6 w7 w82783*/2784avg_lum = (data[27] << 8) + data[28] /* w3 */27852786+ (data[31] << 8) + data[32] /* w5 */27872788+ (data[23] << 8) + data[24] /* w1 */27892790+ (data[35] << 8) + data[36] /* w7 */27912792+ (data[29] << 10) + (data[30] << 2); /* w4 * 4 */2793avg_lum >>= 10;2794atomic_set(&sd->avg_lum, avg_lum);2795}27962797/* scan the URB packets */2798/* This function is run at interrupt level. */2799static void sd_pkt_scan(struct gspca_dev *gspca_dev,2800u8 *data, /* isoc packet */2801int len) /* iso packet length */2802{2803struct sd *sd = (struct sd *) gspca_dev;2804int i, new_qual;28052806/*2807* A frame ends on the marker2808* ff ff 00 c4 c4 96 ..2809* which is 62 bytes long and is followed by various information2810* including statuses and luminosity.2811*2812* A marker may be splitted on two packets.2813*2814* The 6th byte of a marker contains the bits:2815* 0x08: USB full2816* 0xc0: frame sequence2817* When the bit 'USB full' is set, the frame must be discarded;2818* this is also the case when the 2 bytes before the marker are2819* not the JPEG end of frame ('ff d9').2820*/28212822/*fixme: assumption about the following code:2823* - there can be only one marker in a packet2824*/28252826/* skip the remaining bytes of a short marker */2827i = sd->short_mark;2828if (i != 0) {2829sd->short_mark = 0;2830if (i < 0 /* if 'ff' at end of previous packet */2831&& data[0] == 0xff2832&& data[1] == 0x00)2833goto marker_found;2834if (data[0] == 0xff && data[1] == 0xff) {2835i = 0;2836goto marker_found;2837}2838len -= i;2839if (len <= 0)2840return;2841data += i;2842}28432844/* count the packets and their size */2845sd->npkt++;2846sd->pktsz += len;28472848/* search backwards if there is a marker in the packet */2849for (i = len - 1; --i >= 0; ) {2850if (data[i] != 0xff) {2851i--;2852continue;2853}2854if (data[i + 1] == 0xff) {28552856/* (there may be 'ff ff' inside a marker) */2857if (i + 2 >= len || data[i + 2] == 0x00)2858goto marker_found;2859}2860}28612862/* no marker found */2863/* add the JPEG header if first fragment */2864if (data[len - 1] == 0xff)2865sd->short_mark = -1;2866if (gspca_dev->last_packet_type == LAST_PACKET)2867gspca_frame_add(gspca_dev, FIRST_PACKET,2868sd->jpeg_hdr, JPEG_HDR_SZ);2869gspca_frame_add(gspca_dev, INTER_PACKET, data, len);2870return;28712872/* marker found */2873/* if some error, discard the frame and decrease the quality */2874marker_found:2875new_qual = 0;2876if (i > 2) {2877if (data[i - 2] != 0xff || data[i - 1] != 0xd9) {2878gspca_dev->last_packet_type = DISCARD_PACKET;2879new_qual = -3;2880}2881} else if (i + 6 < len) {2882if (data[i + 6] & 0x08) {2883gspca_dev->last_packet_type = DISCARD_PACKET;2884new_qual = -5;2885}2886}28872888gspca_frame_add(gspca_dev, LAST_PACKET, data, i);28892890/* compute the filling rate and a new JPEG quality */2891if (new_qual == 0) {2892int r;28932894r = (sd->pktsz * 100) /2895(sd->npkt *2896gspca_dev->urb[0]->iso_frame_desc[0].length);2897if (r >= 85)2898new_qual = -3;2899else if (r < 75)2900new_qual = 2;2901}2902if (new_qual != 0) {2903sd->nchg += new_qual;2904if (sd->nchg < -6 || sd->nchg >= 12) {2905sd->nchg = 0;2906new_qual += sd->quality;2907if (new_qual < QUALITY_MIN)2908new_qual = QUALITY_MIN;2909else if (new_qual > QUALITY_MAX)2910new_qual = QUALITY_MAX;2911if (new_qual != sd->quality) {2912sd->quality = new_qual;2913queue_work(sd->work_thread, &sd->work);2914}2915}2916} else {2917sd->nchg = 0;2918}2919sd->pktsz = sd->npkt = 0;29202921/* if the marker is smaller than 62 bytes,2922* memorize the number of bytes to skip in the next packet */2923if (i + 62 > len) { /* no more usable data */2924sd->short_mark = i + 62 - len;2925return;2926}2927if (sd->ag_cnt >= 0)2928set_lum(sd, data + i);29292930/* if more data, start a new frame */2931i += 62;2932if (i < len) {2933data += i;2934len -= i;2935gspca_frame_add(gspca_dev, FIRST_PACKET,2936sd->jpeg_hdr, JPEG_HDR_SZ);2937gspca_frame_add(gspca_dev, INTER_PACKET, data, len);2938}2939}29402941static int sd_get_jcomp(struct gspca_dev *gspca_dev,2942struct v4l2_jpegcompression *jcomp)2943{2944struct sd *sd = (struct sd *) gspca_dev;29452946memset(jcomp, 0, sizeof *jcomp);2947jcomp->quality = sd->quality;2948jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT2949| V4L2_JPEG_MARKER_DQT;2950return 0;2951}29522953static int sd_querymenu(struct gspca_dev *gspca_dev,2954struct v4l2_querymenu *menu)2955{2956switch (menu->id) {2957case V4L2_CID_POWER_LINE_FREQUENCY:2958switch (menu->index) {2959case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */2960strcpy((char *) menu->name, "NoFliker");2961return 0;2962case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */2963strcpy((char *) menu->name, "50 Hz");2964return 0;2965case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */2966strcpy((char *) menu->name, "60 Hz");2967return 0;2968}2969break;2970}2971return -EINVAL;2972}29732974#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)2975static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,2976u8 *data, /* interrupt packet data */2977int len) /* interrupt packet length */2978{2979int ret = -EINVAL;29802981if (len == 1 && data[0] == 1) {2982input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);2983input_sync(gspca_dev->input_dev);2984input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);2985input_sync(gspca_dev->input_dev);2986ret = 0;2987}29882989return ret;2990}2991#endif29922993/* sub-driver description */2994static const struct sd_desc sd_desc = {2995.name = MODULE_NAME,2996.ctrls = sd_ctrls,2997.nctrls = NCTRLS,2998.config = sd_config,2999.init = sd_init,3000.start = sd_start,3001.stopN = sd_stopN,3002.stop0 = sd_stop0,3003.pkt_scan = sd_pkt_scan,3004.dq_callback = do_autogain,3005.get_jcomp = sd_get_jcomp,3006.querymenu = sd_querymenu,3007#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)3008.int_pkt_scan = sd_int_pkt_scan,3009#endif3010};30113012/* -- module initialisation -- */3013#define BS(bridge, sensor) \3014.driver_info = (BRIDGE_ ## bridge << 16) \3015| (SENSOR_ ## sensor << 8)3016#define BSF(bridge, sensor, flags) \3017.driver_info = (BRIDGE_ ## bridge << 16) \3018| (SENSOR_ ## sensor << 8) \3019| (flags)3020static const struct usb_device_id device_table[] = {3021{USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},3022{USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},3023{USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, F_PDN_INV)},3024{USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, F_PDN_INV)},3025{USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},3026{USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},3027{USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},3028{USB_DEVICE(0x06f8, 0x3004), BS(SN9C105, OV7660)},3029{USB_DEVICE(0x06f8, 0x3008), BS(SN9C105, OV7660)},3030/* {USB_DEVICE(0x0c45, 0x603a), BS(SN9C102P, OV7648)}, */3031{USB_DEVICE(0x0c45, 0x6040), BS(SN9C102P, HV7131R)},3032/* {USB_DEVICE(0x0c45, 0x607a), BS(SN9C102P, OV7648)}, */3033/* {USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */3034{USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)},3035/* {USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */3036{USB_DEVICE(0x0c45, 0x60c0), BSF(SN9C105, MI0360, F_ILLUM)},3037/* or MT9V111 */3038/* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */3039/* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */3040/* {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */3041{USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)},3042{USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)},3043/* {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */3044/* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */3045/* {USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */3046{USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},3047{USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},3048{USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},3049{USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/3050{USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)}, /* /GC0305*/3051/* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */3052{USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)}, /*sn9c128*/3053{USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)}, /*sn9c128*/3054{USB_DEVICE(0x0c45, 0x610c), BS(SN9C120, HV7131R)}, /*sn9c128*/3055{USB_DEVICE(0x0c45, 0x610e), BS(SN9C120, OV7630)}, /*sn9c128*/3056/* {USB_DEVICE(0x0c45, 0x610f), BS(SN9C120, S5K53BEB)}, */3057/* {USB_DEVICE(0x0c45, 0x6122), BS(SN9C110, ICM105C)}, */3058/* {USB_DEVICE(0x0c45, 0x6123), BS(SN9C110, SanyoCCD)}, */3059{USB_DEVICE(0x0c45, 0x6128), BS(SN9C120, OM6802)}, /*sn9c325?*/3060/*bw600.inf:*/3061{USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)}, /*sn9c325?*/3062{USB_DEVICE(0x0c45, 0x612b), BS(SN9C110, ADCM1700)},3063{USB_DEVICE(0x0c45, 0x612c), BS(SN9C110, MO4000)},3064{USB_DEVICE(0x0c45, 0x612e), BS(SN9C110, OV7630)},3065/* {USB_DEVICE(0x0c45, 0x612f), BS(SN9C110, ICM105C)}, */3066{USB_DEVICE(0x0c45, 0x6130), BS(SN9C120, MI0360)},3067/* or MT9V111 / MI0360B */3068/* {USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */3069{USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)},3070{USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)},3071{USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)},3072{USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},3073{USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},3074{USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/3075/* or GC0305 / GC0307 */3076{USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/3077{USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/3078{USB_DEVICE(0x0c45, 0x614a), BSF(SN9C120, ADCM1700, F_ILLUM)},3079/* {USB_DEVICE(0x0c45, 0x614c), BS(SN9C120, GC0306)}, */ /*sn9c120b*/3080{}3081};3082MODULE_DEVICE_TABLE(usb, device_table);30833084/* -- device connect -- */3085static int sd_probe(struct usb_interface *intf,3086const struct usb_device_id *id)3087{3088return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),3089THIS_MODULE);3090}30913092static struct usb_driver sd_driver = {3093.name = MODULE_NAME,3094.id_table = device_table,3095.probe = sd_probe,3096.disconnect = gspca_disconnect,3097#ifdef CONFIG_PM3098.suspend = gspca_suspend,3099.resume = gspca_resume,3100#endif3101};31023103/* -- module insert / remove -- */3104static int __init sd_mod_init(void)3105{3106return usb_register(&sd_driver);3107}3108static void __exit sd_mod_exit(void)3109{3110usb_deregister(&sd_driver);3111}31123113module_init(sd_mod_init);3114module_exit(sd_mod_exit);311531163117