1*0c0d06caSMauro Carvalho Chehab /* 2*0c0d06caSMauro Carvalho Chehab * Sonix sn9c201 sn9c202 library 3*0c0d06caSMauro Carvalho Chehab * 4*0c0d06caSMauro Carvalho Chehab * Copyright (C) 2012 Jean-Francois Moine <http://moinejf.free.fr> 5*0c0d06caSMauro Carvalho Chehab * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com> 6*0c0d06caSMauro Carvalho Chehab * Copyright (C) 2009 Brian Johnson <brijohn@gmail.com> 7*0c0d06caSMauro Carvalho Chehab * 8*0c0d06caSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 9*0c0d06caSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 10*0c0d06caSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 11*0c0d06caSMauro Carvalho Chehab * any later version. 12*0c0d06caSMauro Carvalho Chehab * 13*0c0d06caSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 14*0c0d06caSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*0c0d06caSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*0c0d06caSMauro Carvalho Chehab * GNU General Public License for more details. 17*0c0d06caSMauro Carvalho Chehab * 18*0c0d06caSMauro Carvalho Chehab * You should have received a copy of the GNU General Public License 19*0c0d06caSMauro Carvalho Chehab * along with this program; if not, write to the Free Software 20*0c0d06caSMauro Carvalho Chehab * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21*0c0d06caSMauro Carvalho Chehab */ 22*0c0d06caSMauro Carvalho Chehab 23*0c0d06caSMauro Carvalho Chehab #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 24*0c0d06caSMauro Carvalho Chehab 25*0c0d06caSMauro Carvalho Chehab #include <linux/input.h> 26*0c0d06caSMauro Carvalho Chehab 27*0c0d06caSMauro Carvalho Chehab #include "gspca.h" 28*0c0d06caSMauro Carvalho Chehab #include "jpeg.h" 29*0c0d06caSMauro Carvalho Chehab 30*0c0d06caSMauro Carvalho Chehab #include <media/v4l2-chip-ident.h> 31*0c0d06caSMauro Carvalho Chehab #include <linux/dmi.h> 32*0c0d06caSMauro Carvalho Chehab 33*0c0d06caSMauro Carvalho Chehab MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, " 34*0c0d06caSMauro Carvalho Chehab "microdia project <microdia@googlegroups.com>"); 35*0c0d06caSMauro Carvalho Chehab MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver"); 36*0c0d06caSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 37*0c0d06caSMauro Carvalho Chehab 38*0c0d06caSMauro Carvalho Chehab /* 39*0c0d06caSMauro Carvalho Chehab * Pixel format private data 40*0c0d06caSMauro Carvalho Chehab */ 41*0c0d06caSMauro Carvalho Chehab #define SCALE_MASK 0x0f 42*0c0d06caSMauro Carvalho Chehab #define SCALE_160x120 0 43*0c0d06caSMauro Carvalho Chehab #define SCALE_320x240 1 44*0c0d06caSMauro Carvalho Chehab #define SCALE_640x480 2 45*0c0d06caSMauro Carvalho Chehab #define SCALE_1280x1024 3 46*0c0d06caSMauro Carvalho Chehab #define MODE_RAW 0x10 47*0c0d06caSMauro Carvalho Chehab #define MODE_JPEG 0x20 48*0c0d06caSMauro Carvalho Chehab #define MODE_SXGA 0x80 49*0c0d06caSMauro Carvalho Chehab 50*0c0d06caSMauro Carvalho Chehab #define SENSOR_OV9650 0 51*0c0d06caSMauro Carvalho Chehab #define SENSOR_OV9655 1 52*0c0d06caSMauro Carvalho Chehab #define SENSOR_SOI968 2 53*0c0d06caSMauro Carvalho Chehab #define SENSOR_OV7660 3 54*0c0d06caSMauro Carvalho Chehab #define SENSOR_OV7670 4 55*0c0d06caSMauro Carvalho Chehab #define SENSOR_MT9V011 5 56*0c0d06caSMauro Carvalho Chehab #define SENSOR_MT9V111 6 57*0c0d06caSMauro Carvalho Chehab #define SENSOR_MT9V112 7 58*0c0d06caSMauro Carvalho Chehab #define SENSOR_MT9M001 8 59*0c0d06caSMauro Carvalho Chehab #define SENSOR_MT9M111 9 60*0c0d06caSMauro Carvalho Chehab #define SENSOR_MT9M112 10 61*0c0d06caSMauro Carvalho Chehab #define SENSOR_HV7131R 11 62*0c0d06caSMauro Carvalho Chehab #define SENSOR_MT9VPRB 12 63*0c0d06caSMauro Carvalho Chehab 64*0c0d06caSMauro Carvalho Chehab /* camera flags */ 65*0c0d06caSMauro Carvalho Chehab #define HAS_NO_BUTTON 0x1 66*0c0d06caSMauro Carvalho Chehab #define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */ 67*0c0d06caSMauro Carvalho Chehab #define FLIP_DETECT 0x4 68*0c0d06caSMauro Carvalho Chehab 69*0c0d06caSMauro Carvalho Chehab /* specific webcam descriptor */ 70*0c0d06caSMauro Carvalho Chehab struct sd { 71*0c0d06caSMauro Carvalho Chehab struct gspca_dev gspca_dev; 72*0c0d06caSMauro Carvalho Chehab 73*0c0d06caSMauro Carvalho Chehab struct { /* color control cluster */ 74*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *brightness; 75*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *contrast; 76*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *saturation; 77*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *hue; 78*0c0d06caSMauro Carvalho Chehab }; 79*0c0d06caSMauro Carvalho Chehab struct { /* blue/red balance control cluster */ 80*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *blue; 81*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *red; 82*0c0d06caSMauro Carvalho Chehab }; 83*0c0d06caSMauro Carvalho Chehab struct { /* h/vflip control cluster */ 84*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *hflip; 85*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *vflip; 86*0c0d06caSMauro Carvalho Chehab }; 87*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *gamma; 88*0c0d06caSMauro Carvalho Chehab struct { /* autogain and exposure or gain control cluster */ 89*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *autogain; 90*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *exposure; 91*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *gain; 92*0c0d06caSMauro Carvalho Chehab }; 93*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl *jpegqual; 94*0c0d06caSMauro Carvalho Chehab 95*0c0d06caSMauro Carvalho Chehab struct work_struct work; 96*0c0d06caSMauro Carvalho Chehab struct workqueue_struct *work_thread; 97*0c0d06caSMauro Carvalho Chehab 98*0c0d06caSMauro Carvalho Chehab u32 pktsz; /* (used by pkt_scan) */ 99*0c0d06caSMauro Carvalho Chehab u16 npkt; 100*0c0d06caSMauro Carvalho Chehab s8 nchg; 101*0c0d06caSMauro Carvalho Chehab u8 fmt; /* (used for JPEG QTAB update */ 102*0c0d06caSMauro Carvalho Chehab 103*0c0d06caSMauro Carvalho Chehab #define MIN_AVG_LUM 80 104*0c0d06caSMauro Carvalho Chehab #define MAX_AVG_LUM 130 105*0c0d06caSMauro Carvalho Chehab atomic_t avg_lum; 106*0c0d06caSMauro Carvalho Chehab u8 old_step; 107*0c0d06caSMauro Carvalho Chehab u8 older_step; 108*0c0d06caSMauro Carvalho Chehab u8 exposure_step; 109*0c0d06caSMauro Carvalho Chehab 110*0c0d06caSMauro Carvalho Chehab u8 i2c_addr; 111*0c0d06caSMauro Carvalho Chehab u8 i2c_intf; 112*0c0d06caSMauro Carvalho Chehab u8 sensor; 113*0c0d06caSMauro Carvalho Chehab u8 hstart; 114*0c0d06caSMauro Carvalho Chehab u8 vstart; 115*0c0d06caSMauro Carvalho Chehab 116*0c0d06caSMauro Carvalho Chehab u8 jpeg_hdr[JPEG_HDR_SZ]; 117*0c0d06caSMauro Carvalho Chehab 118*0c0d06caSMauro Carvalho Chehab u8 flags; 119*0c0d06caSMauro Carvalho Chehab }; 120*0c0d06caSMauro Carvalho Chehab 121*0c0d06caSMauro Carvalho Chehab static void qual_upd(struct work_struct *work); 122*0c0d06caSMauro Carvalho Chehab 123*0c0d06caSMauro Carvalho Chehab struct i2c_reg_u8 { 124*0c0d06caSMauro Carvalho Chehab u8 reg; 125*0c0d06caSMauro Carvalho Chehab u8 val; 126*0c0d06caSMauro Carvalho Chehab }; 127*0c0d06caSMauro Carvalho Chehab 128*0c0d06caSMauro Carvalho Chehab struct i2c_reg_u16 { 129*0c0d06caSMauro Carvalho Chehab u8 reg; 130*0c0d06caSMauro Carvalho Chehab u16 val; 131*0c0d06caSMauro Carvalho Chehab }; 132*0c0d06caSMauro Carvalho Chehab 133*0c0d06caSMauro Carvalho Chehab static const struct dmi_system_id flip_dmi_table[] = { 134*0c0d06caSMauro Carvalho Chehab { 135*0c0d06caSMauro Carvalho Chehab .ident = "MSI MS-1034", 136*0c0d06caSMauro Carvalho Chehab .matches = { 137*0c0d06caSMauro Carvalho Chehab DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."), 138*0c0d06caSMauro Carvalho Chehab DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"), 139*0c0d06caSMauro Carvalho Chehab DMI_MATCH(DMI_PRODUCT_VERSION, "0341") 140*0c0d06caSMauro Carvalho Chehab } 141*0c0d06caSMauro Carvalho Chehab }, 142*0c0d06caSMauro Carvalho Chehab { 143*0c0d06caSMauro Carvalho Chehab .ident = "MSI MS-1632", 144*0c0d06caSMauro Carvalho Chehab .matches = { 145*0c0d06caSMauro Carvalho Chehab DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), 146*0c0d06caSMauro Carvalho Chehab DMI_MATCH(DMI_BOARD_NAME, "MS-1632") 147*0c0d06caSMauro Carvalho Chehab } 148*0c0d06caSMauro Carvalho Chehab }, 149*0c0d06caSMauro Carvalho Chehab { 150*0c0d06caSMauro Carvalho Chehab .ident = "MSI MS-1633X", 151*0c0d06caSMauro Carvalho Chehab .matches = { 152*0c0d06caSMauro Carvalho Chehab DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), 153*0c0d06caSMauro Carvalho Chehab DMI_MATCH(DMI_BOARD_NAME, "MS-1633X") 154*0c0d06caSMauro Carvalho Chehab } 155*0c0d06caSMauro Carvalho Chehab }, 156*0c0d06caSMauro Carvalho Chehab { 157*0c0d06caSMauro Carvalho Chehab .ident = "MSI MS-1635X", 158*0c0d06caSMauro Carvalho Chehab .matches = { 159*0c0d06caSMauro Carvalho Chehab DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), 160*0c0d06caSMauro Carvalho Chehab DMI_MATCH(DMI_BOARD_NAME, "MS-1635X") 161*0c0d06caSMauro Carvalho Chehab } 162*0c0d06caSMauro Carvalho Chehab }, 163*0c0d06caSMauro Carvalho Chehab { 164*0c0d06caSMauro Carvalho Chehab .ident = "ASUSTeK W7J", 165*0c0d06caSMauro Carvalho Chehab .matches = { 166*0c0d06caSMauro Carvalho Chehab DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), 167*0c0d06caSMauro Carvalho Chehab DMI_MATCH(DMI_BOARD_NAME, "W7J ") 168*0c0d06caSMauro Carvalho Chehab } 169*0c0d06caSMauro Carvalho Chehab }, 170*0c0d06caSMauro Carvalho Chehab {} 171*0c0d06caSMauro Carvalho Chehab }; 172*0c0d06caSMauro Carvalho Chehab 173*0c0d06caSMauro Carvalho Chehab static const struct v4l2_pix_format vga_mode[] = { 174*0c0d06caSMauro Carvalho Chehab {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 175*0c0d06caSMauro Carvalho Chehab .bytesperline = 160, 176*0c0d06caSMauro Carvalho Chehab .sizeimage = 160 * 120 * 4 / 8 + 590, 177*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_JPEG, 178*0c0d06caSMauro Carvalho Chehab .priv = SCALE_160x120 | MODE_JPEG}, 179*0c0d06caSMauro Carvalho Chehab {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 180*0c0d06caSMauro Carvalho Chehab .bytesperline = 160, 181*0c0d06caSMauro Carvalho Chehab .sizeimage = 160 * 120, 182*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 183*0c0d06caSMauro Carvalho Chehab .priv = SCALE_160x120 | MODE_RAW}, 184*0c0d06caSMauro Carvalho Chehab {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 185*0c0d06caSMauro Carvalho Chehab .bytesperline = 160, 186*0c0d06caSMauro Carvalho Chehab .sizeimage = 240 * 120, 187*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 188*0c0d06caSMauro Carvalho Chehab .priv = SCALE_160x120}, 189*0c0d06caSMauro Carvalho Chehab {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 190*0c0d06caSMauro Carvalho Chehab .bytesperline = 320, 191*0c0d06caSMauro Carvalho Chehab .sizeimage = 320 * 240 * 4 / 8 + 590, 192*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_JPEG, 193*0c0d06caSMauro Carvalho Chehab .priv = SCALE_320x240 | MODE_JPEG}, 194*0c0d06caSMauro Carvalho Chehab {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 195*0c0d06caSMauro Carvalho Chehab .bytesperline = 320, 196*0c0d06caSMauro Carvalho Chehab .sizeimage = 320 * 240 , 197*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 198*0c0d06caSMauro Carvalho Chehab .priv = SCALE_320x240 | MODE_RAW}, 199*0c0d06caSMauro Carvalho Chehab {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 200*0c0d06caSMauro Carvalho Chehab .bytesperline = 320, 201*0c0d06caSMauro Carvalho Chehab .sizeimage = 480 * 240 , 202*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 203*0c0d06caSMauro Carvalho Chehab .priv = SCALE_320x240}, 204*0c0d06caSMauro Carvalho Chehab {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 205*0c0d06caSMauro Carvalho Chehab .bytesperline = 640, 206*0c0d06caSMauro Carvalho Chehab .sizeimage = 640 * 480 * 4 / 8 + 590, 207*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_JPEG, 208*0c0d06caSMauro Carvalho Chehab .priv = SCALE_640x480 | MODE_JPEG}, 209*0c0d06caSMauro Carvalho Chehab {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 210*0c0d06caSMauro Carvalho Chehab .bytesperline = 640, 211*0c0d06caSMauro Carvalho Chehab .sizeimage = 640 * 480, 212*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 213*0c0d06caSMauro Carvalho Chehab .priv = SCALE_640x480 | MODE_RAW}, 214*0c0d06caSMauro Carvalho Chehab {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 215*0c0d06caSMauro Carvalho Chehab .bytesperline = 640, 216*0c0d06caSMauro Carvalho Chehab .sizeimage = 960 * 480, 217*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 218*0c0d06caSMauro Carvalho Chehab .priv = SCALE_640x480}, 219*0c0d06caSMauro Carvalho Chehab }; 220*0c0d06caSMauro Carvalho Chehab 221*0c0d06caSMauro Carvalho Chehab static const struct v4l2_pix_format sxga_mode[] = { 222*0c0d06caSMauro Carvalho Chehab {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 223*0c0d06caSMauro Carvalho Chehab .bytesperline = 160, 224*0c0d06caSMauro Carvalho Chehab .sizeimage = 160 * 120 * 4 / 8 + 590, 225*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_JPEG, 226*0c0d06caSMauro Carvalho Chehab .priv = SCALE_160x120 | MODE_JPEG}, 227*0c0d06caSMauro Carvalho Chehab {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 228*0c0d06caSMauro Carvalho Chehab .bytesperline = 160, 229*0c0d06caSMauro Carvalho Chehab .sizeimage = 160 * 120, 230*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 231*0c0d06caSMauro Carvalho Chehab .priv = SCALE_160x120 | MODE_RAW}, 232*0c0d06caSMauro Carvalho Chehab {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 233*0c0d06caSMauro Carvalho Chehab .bytesperline = 160, 234*0c0d06caSMauro Carvalho Chehab .sizeimage = 240 * 120, 235*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 236*0c0d06caSMauro Carvalho Chehab .priv = SCALE_160x120}, 237*0c0d06caSMauro Carvalho Chehab {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 238*0c0d06caSMauro Carvalho Chehab .bytesperline = 320, 239*0c0d06caSMauro Carvalho Chehab .sizeimage = 320 * 240 * 4 / 8 + 590, 240*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_JPEG, 241*0c0d06caSMauro Carvalho Chehab .priv = SCALE_320x240 | MODE_JPEG}, 242*0c0d06caSMauro Carvalho Chehab {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 243*0c0d06caSMauro Carvalho Chehab .bytesperline = 320, 244*0c0d06caSMauro Carvalho Chehab .sizeimage = 320 * 240 , 245*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 246*0c0d06caSMauro Carvalho Chehab .priv = SCALE_320x240 | MODE_RAW}, 247*0c0d06caSMauro Carvalho Chehab {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 248*0c0d06caSMauro Carvalho Chehab .bytesperline = 320, 249*0c0d06caSMauro Carvalho Chehab .sizeimage = 480 * 240 , 250*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 251*0c0d06caSMauro Carvalho Chehab .priv = SCALE_320x240}, 252*0c0d06caSMauro Carvalho Chehab {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 253*0c0d06caSMauro Carvalho Chehab .bytesperline = 640, 254*0c0d06caSMauro Carvalho Chehab .sizeimage = 640 * 480 * 4 / 8 + 590, 255*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_JPEG, 256*0c0d06caSMauro Carvalho Chehab .priv = SCALE_640x480 | MODE_JPEG}, 257*0c0d06caSMauro Carvalho Chehab {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 258*0c0d06caSMauro Carvalho Chehab .bytesperline = 640, 259*0c0d06caSMauro Carvalho Chehab .sizeimage = 640 * 480, 260*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 261*0c0d06caSMauro Carvalho Chehab .priv = SCALE_640x480 | MODE_RAW}, 262*0c0d06caSMauro Carvalho Chehab {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 263*0c0d06caSMauro Carvalho Chehab .bytesperline = 640, 264*0c0d06caSMauro Carvalho Chehab .sizeimage = 960 * 480, 265*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 266*0c0d06caSMauro Carvalho Chehab .priv = SCALE_640x480}, 267*0c0d06caSMauro Carvalho Chehab {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 268*0c0d06caSMauro Carvalho Chehab .bytesperline = 1280, 269*0c0d06caSMauro Carvalho Chehab .sizeimage = 1280 * 1024, 270*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 271*0c0d06caSMauro Carvalho Chehab .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, 272*0c0d06caSMauro Carvalho Chehab }; 273*0c0d06caSMauro Carvalho Chehab 274*0c0d06caSMauro Carvalho Chehab static const struct v4l2_pix_format mono_mode[] = { 275*0c0d06caSMauro Carvalho Chehab {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, 276*0c0d06caSMauro Carvalho Chehab .bytesperline = 160, 277*0c0d06caSMauro Carvalho Chehab .sizeimage = 160 * 120, 278*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 279*0c0d06caSMauro Carvalho Chehab .priv = SCALE_160x120 | MODE_RAW}, 280*0c0d06caSMauro Carvalho Chehab {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, 281*0c0d06caSMauro Carvalho Chehab .bytesperline = 320, 282*0c0d06caSMauro Carvalho Chehab .sizeimage = 320 * 240 , 283*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 284*0c0d06caSMauro Carvalho Chehab .priv = SCALE_320x240 | MODE_RAW}, 285*0c0d06caSMauro Carvalho Chehab {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, 286*0c0d06caSMauro Carvalho Chehab .bytesperline = 640, 287*0c0d06caSMauro Carvalho Chehab .sizeimage = 640 * 480, 288*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 289*0c0d06caSMauro Carvalho Chehab .priv = SCALE_640x480 | MODE_RAW}, 290*0c0d06caSMauro Carvalho Chehab {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, 291*0c0d06caSMauro Carvalho Chehab .bytesperline = 1280, 292*0c0d06caSMauro Carvalho Chehab .sizeimage = 1280 * 1024, 293*0c0d06caSMauro Carvalho Chehab .colorspace = V4L2_COLORSPACE_SRGB, 294*0c0d06caSMauro Carvalho Chehab .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, 295*0c0d06caSMauro Carvalho Chehab }; 296*0c0d06caSMauro Carvalho Chehab 297*0c0d06caSMauro Carvalho Chehab static const s16 hsv_red_x[] = { 298*0c0d06caSMauro Carvalho Chehab 41, 44, 46, 48, 50, 52, 54, 56, 299*0c0d06caSMauro Carvalho Chehab 58, 60, 62, 64, 66, 68, 70, 72, 300*0c0d06caSMauro Carvalho Chehab 74, 76, 78, 80, 81, 83, 85, 87, 301*0c0d06caSMauro Carvalho Chehab 88, 90, 92, 93, 95, 97, 98, 100, 302*0c0d06caSMauro Carvalho Chehab 101, 102, 104, 105, 107, 108, 109, 110, 303*0c0d06caSMauro Carvalho Chehab 112, 113, 114, 115, 116, 117, 118, 119, 304*0c0d06caSMauro Carvalho Chehab 120, 121, 122, 123, 123, 124, 125, 125, 305*0c0d06caSMauro Carvalho Chehab 126, 127, 127, 128, 128, 129, 129, 129, 306*0c0d06caSMauro Carvalho Chehab 130, 130, 130, 130, 131, 131, 131, 131, 307*0c0d06caSMauro Carvalho Chehab 131, 131, 131, 131, 130, 130, 130, 130, 308*0c0d06caSMauro Carvalho Chehab 129, 129, 129, 128, 128, 127, 127, 126, 309*0c0d06caSMauro Carvalho Chehab 125, 125, 124, 123, 122, 122, 121, 120, 310*0c0d06caSMauro Carvalho Chehab 119, 118, 117, 116, 115, 114, 112, 111, 311*0c0d06caSMauro Carvalho Chehab 110, 109, 107, 106, 105, 103, 102, 101, 312*0c0d06caSMauro Carvalho Chehab 99, 98, 96, 94, 93, 91, 90, 88, 313*0c0d06caSMauro Carvalho Chehab 86, 84, 83, 81, 79, 77, 75, 74, 314*0c0d06caSMauro Carvalho Chehab 72, 70, 68, 66, 64, 62, 60, 58, 315*0c0d06caSMauro Carvalho Chehab 56, 54, 52, 49, 47, 45, 43, 41, 316*0c0d06caSMauro Carvalho Chehab 39, 36, 34, 32, 30, 28, 25, 23, 317*0c0d06caSMauro Carvalho Chehab 21, 19, 16, 14, 12, 9, 7, 5, 318*0c0d06caSMauro Carvalho Chehab 3, 0, -1, -3, -6, -8, -10, -12, 319*0c0d06caSMauro Carvalho Chehab -15, -17, -19, -22, -24, -26, -28, -30, 320*0c0d06caSMauro Carvalho Chehab -33, -35, -37, -39, -41, -44, -46, -48, 321*0c0d06caSMauro Carvalho Chehab -50, -52, -54, -56, -58, -60, -62, -64, 322*0c0d06caSMauro Carvalho Chehab -66, -68, -70, -72, -74, -76, -78, -80, 323*0c0d06caSMauro Carvalho Chehab -81, -83, -85, -87, -88, -90, -92, -93, 324*0c0d06caSMauro Carvalho Chehab -95, -97, -98, -100, -101, -102, -104, -105, 325*0c0d06caSMauro Carvalho Chehab -107, -108, -109, -110, -112, -113, -114, -115, 326*0c0d06caSMauro Carvalho Chehab -116, -117, -118, -119, -120, -121, -122, -123, 327*0c0d06caSMauro Carvalho Chehab -123, -124, -125, -125, -126, -127, -127, -128, 328*0c0d06caSMauro Carvalho Chehab -128, -128, -128, -128, -128, -128, -128, -128, 329*0c0d06caSMauro Carvalho Chehab -128, -128, -128, -128, -128, -128, -128, -128, 330*0c0d06caSMauro Carvalho Chehab -128, -128, -128, -128, -128, -128, -128, -128, 331*0c0d06caSMauro Carvalho Chehab -128, -127, -127, -126, -125, -125, -124, -123, 332*0c0d06caSMauro Carvalho Chehab -122, -122, -121, -120, -119, -118, -117, -116, 333*0c0d06caSMauro Carvalho Chehab -115, -114, -112, -111, -110, -109, -107, -106, 334*0c0d06caSMauro Carvalho Chehab -105, -103, -102, -101, -99, -98, -96, -94, 335*0c0d06caSMauro Carvalho Chehab -93, -91, -90, -88, -86, -84, -83, -81, 336*0c0d06caSMauro Carvalho Chehab -79, -77, -75, -74, -72, -70, -68, -66, 337*0c0d06caSMauro Carvalho Chehab -64, -62, -60, -58, -56, -54, -52, -49, 338*0c0d06caSMauro Carvalho Chehab -47, -45, -43, -41, -39, -36, -34, -32, 339*0c0d06caSMauro Carvalho Chehab -30, -28, -25, -23, -21, -19, -16, -14, 340*0c0d06caSMauro Carvalho Chehab -12, -9, -7, -5, -3, 0, 1, 3, 341*0c0d06caSMauro Carvalho Chehab 6, 8, 10, 12, 15, 17, 19, 22, 342*0c0d06caSMauro Carvalho Chehab 24, 26, 28, 30, 33, 35, 37, 39, 41 343*0c0d06caSMauro Carvalho Chehab }; 344*0c0d06caSMauro Carvalho Chehab 345*0c0d06caSMauro Carvalho Chehab static const s16 hsv_red_y[] = { 346*0c0d06caSMauro Carvalho Chehab 82, 80, 78, 76, 74, 73, 71, 69, 347*0c0d06caSMauro Carvalho Chehab 67, 65, 63, 61, 58, 56, 54, 52, 348*0c0d06caSMauro Carvalho Chehab 50, 48, 46, 44, 41, 39, 37, 35, 349*0c0d06caSMauro Carvalho Chehab 32, 30, 28, 26, 23, 21, 19, 16, 350*0c0d06caSMauro Carvalho Chehab 14, 12, 10, 7, 5, 3, 0, -1, 351*0c0d06caSMauro Carvalho Chehab -3, -6, -8, -10, -13, -15, -17, -19, 352*0c0d06caSMauro Carvalho Chehab -22, -24, -26, -29, -31, -33, -35, -38, 353*0c0d06caSMauro Carvalho Chehab -40, -42, -44, -46, -48, -51, -53, -55, 354*0c0d06caSMauro Carvalho Chehab -57, -59, -61, -63, -65, -67, -69, -71, 355*0c0d06caSMauro Carvalho Chehab -73, -75, -77, -79, -81, -82, -84, -86, 356*0c0d06caSMauro Carvalho Chehab -88, -89, -91, -93, -94, -96, -98, -99, 357*0c0d06caSMauro Carvalho Chehab -101, -102, -104, -105, -106, -108, -109, -110, 358*0c0d06caSMauro Carvalho Chehab -112, -113, -114, -115, -116, -117, -119, -120, 359*0c0d06caSMauro Carvalho Chehab -120, -121, -122, -123, -124, -125, -126, -126, 360*0c0d06caSMauro Carvalho Chehab -127, -128, -128, -128, -128, -128, -128, -128, 361*0c0d06caSMauro Carvalho Chehab -128, -128, -128, -128, -128, -128, -128, -128, 362*0c0d06caSMauro Carvalho Chehab -128, -128, -128, -128, -128, -128, -128, -128, 363*0c0d06caSMauro Carvalho Chehab -128, -128, -128, -128, -128, -128, -128, -128, 364*0c0d06caSMauro Carvalho Chehab -127, -127, -126, -125, -125, -124, -123, -122, 365*0c0d06caSMauro Carvalho Chehab -121, -120, -119, -118, -117, -116, -115, -114, 366*0c0d06caSMauro Carvalho Chehab -113, -111, -110, -109, -107, -106, -105, -103, 367*0c0d06caSMauro Carvalho Chehab -102, -100, -99, -97, -96, -94, -92, -91, 368*0c0d06caSMauro Carvalho Chehab -89, -87, -85, -84, -82, -80, -78, -76, 369*0c0d06caSMauro Carvalho Chehab -74, -73, -71, -69, -67, -65, -63, -61, 370*0c0d06caSMauro Carvalho Chehab -58, -56, -54, -52, -50, -48, -46, -44, 371*0c0d06caSMauro Carvalho Chehab -41, -39, -37, -35, -32, -30, -28, -26, 372*0c0d06caSMauro Carvalho Chehab -23, -21, -19, -16, -14, -12, -10, -7, 373*0c0d06caSMauro Carvalho Chehab -5, -3, 0, 1, 3, 6, 8, 10, 374*0c0d06caSMauro Carvalho Chehab 13, 15, 17, 19, 22, 24, 26, 29, 375*0c0d06caSMauro Carvalho Chehab 31, 33, 35, 38, 40, 42, 44, 46, 376*0c0d06caSMauro Carvalho Chehab 48, 51, 53, 55, 57, 59, 61, 63, 377*0c0d06caSMauro Carvalho Chehab 65, 67, 69, 71, 73, 75, 77, 79, 378*0c0d06caSMauro Carvalho Chehab 81, 82, 84, 86, 88, 89, 91, 93, 379*0c0d06caSMauro Carvalho Chehab 94, 96, 98, 99, 101, 102, 104, 105, 380*0c0d06caSMauro Carvalho Chehab 106, 108, 109, 110, 112, 113, 114, 115, 381*0c0d06caSMauro Carvalho Chehab 116, 117, 119, 120, 120, 121, 122, 123, 382*0c0d06caSMauro Carvalho Chehab 124, 125, 126, 126, 127, 128, 128, 129, 383*0c0d06caSMauro Carvalho Chehab 129, 130, 130, 131, 131, 131, 131, 132, 384*0c0d06caSMauro Carvalho Chehab 132, 132, 132, 132, 132, 132, 132, 132, 385*0c0d06caSMauro Carvalho Chehab 132, 132, 132, 131, 131, 131, 130, 130, 386*0c0d06caSMauro Carvalho Chehab 130, 129, 129, 128, 127, 127, 126, 125, 387*0c0d06caSMauro Carvalho Chehab 125, 124, 123, 122, 121, 120, 119, 118, 388*0c0d06caSMauro Carvalho Chehab 117, 116, 115, 114, 113, 111, 110, 109, 389*0c0d06caSMauro Carvalho Chehab 107, 106, 105, 103, 102, 100, 99, 97, 390*0c0d06caSMauro Carvalho Chehab 96, 94, 92, 91, 89, 87, 85, 84, 82 391*0c0d06caSMauro Carvalho Chehab }; 392*0c0d06caSMauro Carvalho Chehab 393*0c0d06caSMauro Carvalho Chehab static const s16 hsv_green_x[] = { 394*0c0d06caSMauro Carvalho Chehab -124, -124, -125, -125, -125, -125, -125, -125, 395*0c0d06caSMauro Carvalho Chehab -125, -126, -126, -125, -125, -125, -125, -125, 396*0c0d06caSMauro Carvalho Chehab -125, -124, -124, -124, -123, -123, -122, -122, 397*0c0d06caSMauro Carvalho Chehab -121, -121, -120, -120, -119, -118, -117, -117, 398*0c0d06caSMauro Carvalho Chehab -116, -115, -114, -113, -112, -111, -110, -109, 399*0c0d06caSMauro Carvalho Chehab -108, -107, -105, -104, -103, -102, -100, -99, 400*0c0d06caSMauro Carvalho Chehab -98, -96, -95, -93, -92, -91, -89, -87, 401*0c0d06caSMauro Carvalho Chehab -86, -84, -83, -81, -79, -77, -76, -74, 402*0c0d06caSMauro Carvalho Chehab -72, -70, -69, -67, -65, -63, -61, -59, 403*0c0d06caSMauro Carvalho Chehab -57, -55, -53, -51, -49, -47, -45, -43, 404*0c0d06caSMauro Carvalho Chehab -41, -39, -37, -35, -33, -30, -28, -26, 405*0c0d06caSMauro Carvalho Chehab -24, -22, -20, -18, -15, -13, -11, -9, 406*0c0d06caSMauro Carvalho Chehab -7, -4, -2, 0, 1, 3, 6, 8, 407*0c0d06caSMauro Carvalho Chehab 10, 12, 14, 17, 19, 21, 23, 25, 408*0c0d06caSMauro Carvalho Chehab 27, 29, 32, 34, 36, 38, 40, 42, 409*0c0d06caSMauro Carvalho Chehab 44, 46, 48, 50, 52, 54, 56, 58, 410*0c0d06caSMauro Carvalho Chehab 60, 62, 64, 66, 68, 70, 71, 73, 411*0c0d06caSMauro Carvalho Chehab 75, 77, 78, 80, 82, 83, 85, 87, 412*0c0d06caSMauro Carvalho Chehab 88, 90, 91, 93, 94, 96, 97, 98, 413*0c0d06caSMauro Carvalho Chehab 100, 101, 102, 104, 105, 106, 107, 108, 414*0c0d06caSMauro Carvalho Chehab 109, 111, 112, 113, 113, 114, 115, 116, 415*0c0d06caSMauro Carvalho Chehab 117, 118, 118, 119, 120, 120, 121, 122, 416*0c0d06caSMauro Carvalho Chehab 122, 123, 123, 124, 124, 124, 125, 125, 417*0c0d06caSMauro Carvalho Chehab 125, 125, 125, 125, 125, 126, 126, 125, 418*0c0d06caSMauro Carvalho Chehab 125, 125, 125, 125, 125, 124, 124, 124, 419*0c0d06caSMauro Carvalho Chehab 123, 123, 122, 122, 121, 121, 120, 120, 420*0c0d06caSMauro Carvalho Chehab 119, 118, 117, 117, 116, 115, 114, 113, 421*0c0d06caSMauro Carvalho Chehab 112, 111, 110, 109, 108, 107, 105, 104, 422*0c0d06caSMauro Carvalho Chehab 103, 102, 100, 99, 98, 96, 95, 93, 423*0c0d06caSMauro Carvalho Chehab 92, 91, 89, 87, 86, 84, 83, 81, 424*0c0d06caSMauro Carvalho Chehab 79, 77, 76, 74, 72, 70, 69, 67, 425*0c0d06caSMauro Carvalho Chehab 65, 63, 61, 59, 57, 55, 53, 51, 426*0c0d06caSMauro Carvalho Chehab 49, 47, 45, 43, 41, 39, 37, 35, 427*0c0d06caSMauro Carvalho Chehab 33, 30, 28, 26, 24, 22, 20, 18, 428*0c0d06caSMauro Carvalho Chehab 15, 13, 11, 9, 7, 4, 2, 0, 429*0c0d06caSMauro Carvalho Chehab -1, -3, -6, -8, -10, -12, -14, -17, 430*0c0d06caSMauro Carvalho Chehab -19, -21, -23, -25, -27, -29, -32, -34, 431*0c0d06caSMauro Carvalho Chehab -36, -38, -40, -42, -44, -46, -48, -50, 432*0c0d06caSMauro Carvalho Chehab -52, -54, -56, -58, -60, -62, -64, -66, 433*0c0d06caSMauro Carvalho Chehab -68, -70, -71, -73, -75, -77, -78, -80, 434*0c0d06caSMauro Carvalho Chehab -82, -83, -85, -87, -88, -90, -91, -93, 435*0c0d06caSMauro Carvalho Chehab -94, -96, -97, -98, -100, -101, -102, -104, 436*0c0d06caSMauro Carvalho Chehab -105, -106, -107, -108, -109, -111, -112, -113, 437*0c0d06caSMauro Carvalho Chehab -113, -114, -115, -116, -117, -118, -118, -119, 438*0c0d06caSMauro Carvalho Chehab -120, -120, -121, -122, -122, -123, -123, -124, -124 439*0c0d06caSMauro Carvalho Chehab }; 440*0c0d06caSMauro Carvalho Chehab 441*0c0d06caSMauro Carvalho Chehab static const s16 hsv_green_y[] = { 442*0c0d06caSMauro Carvalho Chehab -100, -99, -98, -97, -95, -94, -93, -91, 443*0c0d06caSMauro Carvalho Chehab -90, -89, -87, -86, -84, -83, -81, -80, 444*0c0d06caSMauro Carvalho Chehab -78, -76, -75, -73, -71, -70, -68, -66, 445*0c0d06caSMauro Carvalho Chehab -64, -63, -61, -59, -57, -55, -53, -51, 446*0c0d06caSMauro Carvalho Chehab -49, -48, -46, -44, -42, -40, -38, -36, 447*0c0d06caSMauro Carvalho Chehab -34, -32, -30, -27, -25, -23, -21, -19, 448*0c0d06caSMauro Carvalho Chehab -17, -15, -13, -11, -9, -7, -4, -2, 449*0c0d06caSMauro Carvalho Chehab 0, 1, 3, 5, 7, 9, 11, 14, 450*0c0d06caSMauro Carvalho Chehab 16, 18, 20, 22, 24, 26, 28, 30, 451*0c0d06caSMauro Carvalho Chehab 32, 34, 36, 38, 40, 42, 44, 46, 452*0c0d06caSMauro Carvalho Chehab 48, 50, 52, 54, 56, 58, 59, 61, 453*0c0d06caSMauro Carvalho Chehab 63, 65, 67, 68, 70, 72, 74, 75, 454*0c0d06caSMauro Carvalho Chehab 77, 78, 80, 82, 83, 85, 86, 88, 455*0c0d06caSMauro Carvalho Chehab 89, 90, 92, 93, 95, 96, 97, 98, 456*0c0d06caSMauro Carvalho Chehab 100, 101, 102, 103, 104, 105, 106, 107, 457*0c0d06caSMauro Carvalho Chehab 108, 109, 110, 111, 112, 112, 113, 114, 458*0c0d06caSMauro Carvalho Chehab 115, 115, 116, 116, 117, 117, 118, 118, 459*0c0d06caSMauro Carvalho Chehab 119, 119, 119, 120, 120, 120, 120, 120, 460*0c0d06caSMauro Carvalho Chehab 121, 121, 121, 121, 121, 121, 120, 120, 461*0c0d06caSMauro Carvalho Chehab 120, 120, 120, 119, 119, 119, 118, 118, 462*0c0d06caSMauro Carvalho Chehab 117, 117, 116, 116, 115, 114, 114, 113, 463*0c0d06caSMauro Carvalho Chehab 112, 111, 111, 110, 109, 108, 107, 106, 464*0c0d06caSMauro Carvalho Chehab 105, 104, 103, 102, 100, 99, 98, 97, 465*0c0d06caSMauro Carvalho Chehab 95, 94, 93, 91, 90, 89, 87, 86, 466*0c0d06caSMauro Carvalho Chehab 84, 83, 81, 80, 78, 76, 75, 73, 467*0c0d06caSMauro Carvalho Chehab 71, 70, 68, 66, 64, 63, 61, 59, 468*0c0d06caSMauro Carvalho Chehab 57, 55, 53, 51, 49, 48, 46, 44, 469*0c0d06caSMauro Carvalho Chehab 42, 40, 38, 36, 34, 32, 30, 27, 470*0c0d06caSMauro Carvalho Chehab 25, 23, 21, 19, 17, 15, 13, 11, 471*0c0d06caSMauro Carvalho Chehab 9, 7, 4, 2, 0, -1, -3, -5, 472*0c0d06caSMauro Carvalho Chehab -7, -9, -11, -14, -16, -18, -20, -22, 473*0c0d06caSMauro Carvalho Chehab -24, -26, -28, -30, -32, -34, -36, -38, 474*0c0d06caSMauro Carvalho Chehab -40, -42, -44, -46, -48, -50, -52, -54, 475*0c0d06caSMauro Carvalho Chehab -56, -58, -59, -61, -63, -65, -67, -68, 476*0c0d06caSMauro Carvalho Chehab -70, -72, -74, -75, -77, -78, -80, -82, 477*0c0d06caSMauro Carvalho Chehab -83, -85, -86, -88, -89, -90, -92, -93, 478*0c0d06caSMauro Carvalho Chehab -95, -96, -97, -98, -100, -101, -102, -103, 479*0c0d06caSMauro Carvalho Chehab -104, -105, -106, -107, -108, -109, -110, -111, 480*0c0d06caSMauro Carvalho Chehab -112, -112, -113, -114, -115, -115, -116, -116, 481*0c0d06caSMauro Carvalho Chehab -117, -117, -118, -118, -119, -119, -119, -120, 482*0c0d06caSMauro Carvalho Chehab -120, -120, -120, -120, -121, -121, -121, -121, 483*0c0d06caSMauro Carvalho Chehab -121, -121, -120, -120, -120, -120, -120, -119, 484*0c0d06caSMauro Carvalho Chehab -119, -119, -118, -118, -117, -117, -116, -116, 485*0c0d06caSMauro Carvalho Chehab -115, -114, -114, -113, -112, -111, -111, -110, 486*0c0d06caSMauro Carvalho Chehab -109, -108, -107, -106, -105, -104, -103, -102, -100 487*0c0d06caSMauro Carvalho Chehab }; 488*0c0d06caSMauro Carvalho Chehab 489*0c0d06caSMauro Carvalho Chehab static const s16 hsv_blue_x[] = { 490*0c0d06caSMauro Carvalho Chehab 112, 113, 114, 114, 115, 116, 117, 117, 491*0c0d06caSMauro Carvalho Chehab 118, 118, 119, 119, 120, 120, 120, 121, 492*0c0d06caSMauro Carvalho Chehab 121, 121, 122, 122, 122, 122, 122, 122, 493*0c0d06caSMauro Carvalho Chehab 122, 122, 122, 122, 122, 122, 121, 121, 494*0c0d06caSMauro Carvalho Chehab 121, 120, 120, 120, 119, 119, 118, 118, 495*0c0d06caSMauro Carvalho Chehab 117, 116, 116, 115, 114, 113, 113, 112, 496*0c0d06caSMauro Carvalho Chehab 111, 110, 109, 108, 107, 106, 105, 104, 497*0c0d06caSMauro Carvalho Chehab 103, 102, 100, 99, 98, 97, 95, 94, 498*0c0d06caSMauro Carvalho Chehab 93, 91, 90, 88, 87, 85, 84, 82, 499*0c0d06caSMauro Carvalho Chehab 80, 79, 77, 76, 74, 72, 70, 69, 500*0c0d06caSMauro Carvalho Chehab 67, 65, 63, 61, 60, 58, 56, 54, 501*0c0d06caSMauro Carvalho Chehab 52, 50, 48, 46, 44, 42, 40, 38, 502*0c0d06caSMauro Carvalho Chehab 36, 34, 32, 30, 28, 26, 24, 22, 503*0c0d06caSMauro Carvalho Chehab 19, 17, 15, 13, 11, 9, 7, 5, 504*0c0d06caSMauro Carvalho Chehab 2, 0, -1, -3, -5, -7, -9, -12, 505*0c0d06caSMauro Carvalho Chehab -14, -16, -18, -20, -22, -24, -26, -28, 506*0c0d06caSMauro Carvalho Chehab -31, -33, -35, -37, -39, -41, -43, -45, 507*0c0d06caSMauro Carvalho Chehab -47, -49, -51, -53, -54, -56, -58, -60, 508*0c0d06caSMauro Carvalho Chehab -62, -64, -66, -67, -69, -71, -73, -74, 509*0c0d06caSMauro Carvalho Chehab -76, -78, -79, -81, -83, -84, -86, -87, 510*0c0d06caSMauro Carvalho Chehab -89, -90, -92, -93, -94, -96, -97, -98, 511*0c0d06caSMauro Carvalho Chehab -99, -101, -102, -103, -104, -105, -106, -107, 512*0c0d06caSMauro Carvalho Chehab -108, -109, -110, -111, -112, -113, -114, -114, 513*0c0d06caSMauro Carvalho Chehab -115, -116, -117, -117, -118, -118, -119, -119, 514*0c0d06caSMauro Carvalho Chehab -120, -120, -120, -121, -121, -121, -122, -122, 515*0c0d06caSMauro Carvalho Chehab -122, -122, -122, -122, -122, -122, -122, -122, 516*0c0d06caSMauro Carvalho Chehab -122, -122, -121, -121, -121, -120, -120, -120, 517*0c0d06caSMauro Carvalho Chehab -119, -119, -118, -118, -117, -116, -116, -115, 518*0c0d06caSMauro Carvalho Chehab -114, -113, -113, -112, -111, -110, -109, -108, 519*0c0d06caSMauro Carvalho Chehab -107, -106, -105, -104, -103, -102, -100, -99, 520*0c0d06caSMauro Carvalho Chehab -98, -97, -95, -94, -93, -91, -90, -88, 521*0c0d06caSMauro Carvalho Chehab -87, -85, -84, -82, -80, -79, -77, -76, 522*0c0d06caSMauro Carvalho Chehab -74, -72, -70, -69, -67, -65, -63, -61, 523*0c0d06caSMauro Carvalho Chehab -60, -58, -56, -54, -52, -50, -48, -46, 524*0c0d06caSMauro Carvalho Chehab -44, -42, -40, -38, -36, -34, -32, -30, 525*0c0d06caSMauro Carvalho Chehab -28, -26, -24, -22, -19, -17, -15, -13, 526*0c0d06caSMauro Carvalho Chehab -11, -9, -7, -5, -2, 0, 1, 3, 527*0c0d06caSMauro Carvalho Chehab 5, 7, 9, 12, 14, 16, 18, 20, 528*0c0d06caSMauro Carvalho Chehab 22, 24, 26, 28, 31, 33, 35, 37, 529*0c0d06caSMauro Carvalho Chehab 39, 41, 43, 45, 47, 49, 51, 53, 530*0c0d06caSMauro Carvalho Chehab 54, 56, 58, 60, 62, 64, 66, 67, 531*0c0d06caSMauro Carvalho Chehab 69, 71, 73, 74, 76, 78, 79, 81, 532*0c0d06caSMauro Carvalho Chehab 83, 84, 86, 87, 89, 90, 92, 93, 533*0c0d06caSMauro Carvalho Chehab 94, 96, 97, 98, 99, 101, 102, 103, 534*0c0d06caSMauro Carvalho Chehab 104, 105, 106, 107, 108, 109, 110, 111, 112 535*0c0d06caSMauro Carvalho Chehab }; 536*0c0d06caSMauro Carvalho Chehab 537*0c0d06caSMauro Carvalho Chehab static const s16 hsv_blue_y[] = { 538*0c0d06caSMauro Carvalho Chehab -11, -13, -15, -17, -19, -21, -23, -25, 539*0c0d06caSMauro Carvalho Chehab -27, -29, -31, -33, -35, -37, -39, -41, 540*0c0d06caSMauro Carvalho Chehab -43, -45, -46, -48, -50, -52, -54, -55, 541*0c0d06caSMauro Carvalho Chehab -57, -59, -61, -62, -64, -66, -67, -69, 542*0c0d06caSMauro Carvalho Chehab -71, -72, -74, -75, -77, -78, -80, -81, 543*0c0d06caSMauro Carvalho Chehab -83, -84, -86, -87, -88, -90, -91, -92, 544*0c0d06caSMauro Carvalho Chehab -93, -95, -96, -97, -98, -99, -100, -101, 545*0c0d06caSMauro Carvalho Chehab -102, -103, -104, -105, -106, -106, -107, -108, 546*0c0d06caSMauro Carvalho Chehab -109, -109, -110, -111, -111, -112, -112, -113, 547*0c0d06caSMauro Carvalho Chehab -113, -114, -114, -114, -115, -115, -115, -115, 548*0c0d06caSMauro Carvalho Chehab -116, -116, -116, -116, -116, -116, -116, -116, 549*0c0d06caSMauro Carvalho Chehab -116, -115, -115, -115, -115, -114, -114, -114, 550*0c0d06caSMauro Carvalho Chehab -113, -113, -112, -112, -111, -111, -110, -110, 551*0c0d06caSMauro Carvalho Chehab -109, -108, -108, -107, -106, -105, -104, -103, 552*0c0d06caSMauro Carvalho Chehab -102, -101, -100, -99, -98, -97, -96, -95, 553*0c0d06caSMauro Carvalho Chehab -94, -93, -91, -90, -89, -88, -86, -85, 554*0c0d06caSMauro Carvalho Chehab -84, -82, -81, -79, -78, -76, -75, -73, 555*0c0d06caSMauro Carvalho Chehab -71, -70, -68, -67, -65, -63, -62, -60, 556*0c0d06caSMauro Carvalho Chehab -58, -56, -55, -53, -51, -49, -47, -45, 557*0c0d06caSMauro Carvalho Chehab -44, -42, -40, -38, -36, -34, -32, -30, 558*0c0d06caSMauro Carvalho Chehab -28, -26, -24, -22, -20, -18, -16, -14, 559*0c0d06caSMauro Carvalho Chehab -12, -10, -8, -6, -4, -2, 0, 1, 560*0c0d06caSMauro Carvalho Chehab 3, 5, 7, 9, 11, 13, 15, 17, 561*0c0d06caSMauro Carvalho Chehab 19, 21, 23, 25, 27, 29, 31, 33, 562*0c0d06caSMauro Carvalho Chehab 35, 37, 39, 41, 43, 45, 46, 48, 563*0c0d06caSMauro Carvalho Chehab 50, 52, 54, 55, 57, 59, 61, 62, 564*0c0d06caSMauro Carvalho Chehab 64, 66, 67, 69, 71, 72, 74, 75, 565*0c0d06caSMauro Carvalho Chehab 77, 78, 80, 81, 83, 84, 86, 87, 566*0c0d06caSMauro Carvalho Chehab 88, 90, 91, 92, 93, 95, 96, 97, 567*0c0d06caSMauro Carvalho Chehab 98, 99, 100, 101, 102, 103, 104, 105, 568*0c0d06caSMauro Carvalho Chehab 106, 106, 107, 108, 109, 109, 110, 111, 569*0c0d06caSMauro Carvalho Chehab 111, 112, 112, 113, 113, 114, 114, 114, 570*0c0d06caSMauro Carvalho Chehab 115, 115, 115, 115, 116, 116, 116, 116, 571*0c0d06caSMauro Carvalho Chehab 116, 116, 116, 116, 116, 115, 115, 115, 572*0c0d06caSMauro Carvalho Chehab 115, 114, 114, 114, 113, 113, 112, 112, 573*0c0d06caSMauro Carvalho Chehab 111, 111, 110, 110, 109, 108, 108, 107, 574*0c0d06caSMauro Carvalho Chehab 106, 105, 104, 103, 102, 101, 100, 99, 575*0c0d06caSMauro Carvalho Chehab 98, 97, 96, 95, 94, 93, 91, 90, 576*0c0d06caSMauro Carvalho Chehab 89, 88, 86, 85, 84, 82, 81, 79, 577*0c0d06caSMauro Carvalho Chehab 78, 76, 75, 73, 71, 70, 68, 67, 578*0c0d06caSMauro Carvalho Chehab 65, 63, 62, 60, 58, 56, 55, 53, 579*0c0d06caSMauro Carvalho Chehab 51, 49, 47, 45, 44, 42, 40, 38, 580*0c0d06caSMauro Carvalho Chehab 36, 34, 32, 30, 28, 26, 24, 22, 581*0c0d06caSMauro Carvalho Chehab 20, 18, 16, 14, 12, 10, 8, 6, 582*0c0d06caSMauro Carvalho Chehab 4, 2, 0, -1, -3, -5, -7, -9, -11 583*0c0d06caSMauro Carvalho Chehab }; 584*0c0d06caSMauro Carvalho Chehab 585*0c0d06caSMauro Carvalho Chehab static const u16 i2c_ident[] = { 586*0c0d06caSMauro Carvalho Chehab V4L2_IDENT_OV9650, 587*0c0d06caSMauro Carvalho Chehab V4L2_IDENT_OV9655, 588*0c0d06caSMauro Carvalho Chehab V4L2_IDENT_SOI968, 589*0c0d06caSMauro Carvalho Chehab V4L2_IDENT_OV7660, 590*0c0d06caSMauro Carvalho Chehab V4L2_IDENT_OV7670, 591*0c0d06caSMauro Carvalho Chehab V4L2_IDENT_MT9V011, 592*0c0d06caSMauro Carvalho Chehab V4L2_IDENT_MT9V111, 593*0c0d06caSMauro Carvalho Chehab V4L2_IDENT_MT9V112, 594*0c0d06caSMauro Carvalho Chehab V4L2_IDENT_MT9M001C12ST, 595*0c0d06caSMauro Carvalho Chehab V4L2_IDENT_MT9M111, 596*0c0d06caSMauro Carvalho Chehab V4L2_IDENT_MT9M112, 597*0c0d06caSMauro Carvalho Chehab V4L2_IDENT_HV7131R, 598*0c0d06caSMauro Carvalho Chehab [SENSOR_MT9VPRB] = V4L2_IDENT_UNKNOWN, 599*0c0d06caSMauro Carvalho Chehab }; 600*0c0d06caSMauro Carvalho Chehab 601*0c0d06caSMauro Carvalho Chehab static const u16 bridge_init[][2] = { 602*0c0d06caSMauro Carvalho Chehab {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c}, 603*0c0d06caSMauro Carvalho Chehab {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40}, 604*0c0d06caSMauro Carvalho Chehab {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10}, 605*0c0d06caSMauro Carvalho Chehab {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00}, 606*0c0d06caSMauro Carvalho Chehab {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50}, 607*0c0d06caSMauro Carvalho Chehab {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50}, 608*0c0d06caSMauro Carvalho Chehab {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04}, 609*0c0d06caSMauro Carvalho Chehab {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05}, 610*0c0d06caSMauro Carvalho Chehab {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00}, 611*0c0d06caSMauro Carvalho Chehab {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d}, 612*0c0d06caSMauro Carvalho Chehab {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04}, 613*0c0d06caSMauro Carvalho Chehab {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8}, 614*0c0d06caSMauro Carvalho Chehab {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32}, 615*0c0d06caSMauro Carvalho Chehab {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd}, 616*0c0d06caSMauro Carvalho Chehab {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01}, 617*0c0d06caSMauro Carvalho Chehab {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f}, 618*0c0d06caSMauro Carvalho Chehab {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f}, 619*0c0d06caSMauro Carvalho Chehab {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01}, 620*0c0d06caSMauro Carvalho Chehab {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80}, 621*0c0d06caSMauro Carvalho Chehab {0x1007, 0x00} 622*0c0d06caSMauro Carvalho Chehab }; 623*0c0d06caSMauro Carvalho Chehab 624*0c0d06caSMauro Carvalho Chehab /* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */ 625*0c0d06caSMauro Carvalho Chehab static const u8 ov_gain[] = { 626*0c0d06caSMauro Carvalho Chehab 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */, 627*0c0d06caSMauro Carvalho Chehab 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */, 628*0c0d06caSMauro Carvalho Chehab 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */, 629*0c0d06caSMauro Carvalho Chehab 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */, 630*0c0d06caSMauro Carvalho Chehab 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */, 631*0c0d06caSMauro Carvalho Chehab 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */, 632*0c0d06caSMauro Carvalho Chehab 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */, 633*0c0d06caSMauro Carvalho Chehab 0x70 /* 8x */ 634*0c0d06caSMauro Carvalho Chehab }; 635*0c0d06caSMauro Carvalho Chehab 636*0c0d06caSMauro Carvalho Chehab /* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */ 637*0c0d06caSMauro Carvalho Chehab static const u16 micron1_gain[] = { 638*0c0d06caSMauro Carvalho Chehab /* 1x 1.25x 1.5x 1.75x */ 639*0c0d06caSMauro Carvalho Chehab 0x0020, 0x0028, 0x0030, 0x0038, 640*0c0d06caSMauro Carvalho Chehab /* 2x 2.25x 2.5x 2.75x */ 641*0c0d06caSMauro Carvalho Chehab 0x00a0, 0x00a4, 0x00a8, 0x00ac, 642*0c0d06caSMauro Carvalho Chehab /* 3x 3.25x 3.5x 3.75x */ 643*0c0d06caSMauro Carvalho Chehab 0x00b0, 0x00b4, 0x00b8, 0x00bc, 644*0c0d06caSMauro Carvalho Chehab /* 4x 4.25x 4.5x 4.75x */ 645*0c0d06caSMauro Carvalho Chehab 0x00c0, 0x00c4, 0x00c8, 0x00cc, 646*0c0d06caSMauro Carvalho Chehab /* 5x 5.25x 5.5x 5.75x */ 647*0c0d06caSMauro Carvalho Chehab 0x00d0, 0x00d4, 0x00d8, 0x00dc, 648*0c0d06caSMauro Carvalho Chehab /* 6x 6.25x 6.5x 6.75x */ 649*0c0d06caSMauro Carvalho Chehab 0x00e0, 0x00e4, 0x00e8, 0x00ec, 650*0c0d06caSMauro Carvalho Chehab /* 7x 7.25x 7.5x 7.75x */ 651*0c0d06caSMauro Carvalho Chehab 0x00f0, 0x00f4, 0x00f8, 0x00fc, 652*0c0d06caSMauro Carvalho Chehab /* 8x */ 653*0c0d06caSMauro Carvalho Chehab 0x01c0 654*0c0d06caSMauro Carvalho Chehab }; 655*0c0d06caSMauro Carvalho Chehab 656*0c0d06caSMauro Carvalho Chehab /* mt9m001 sensor uses a different gain formula then other micron sensors */ 657*0c0d06caSMauro Carvalho Chehab /* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */ 658*0c0d06caSMauro Carvalho Chehab static const u16 micron2_gain[] = { 659*0c0d06caSMauro Carvalho Chehab /* 1x 1.25x 1.5x 1.75x */ 660*0c0d06caSMauro Carvalho Chehab 0x0008, 0x000a, 0x000c, 0x000e, 661*0c0d06caSMauro Carvalho Chehab /* 2x 2.25x 2.5x 2.75x */ 662*0c0d06caSMauro Carvalho Chehab 0x0010, 0x0012, 0x0014, 0x0016, 663*0c0d06caSMauro Carvalho Chehab /* 3x 3.25x 3.5x 3.75x */ 664*0c0d06caSMauro Carvalho Chehab 0x0018, 0x001a, 0x001c, 0x001e, 665*0c0d06caSMauro Carvalho Chehab /* 4x 4.25x 4.5x 4.75x */ 666*0c0d06caSMauro Carvalho Chehab 0x0020, 0x0051, 0x0052, 0x0053, 667*0c0d06caSMauro Carvalho Chehab /* 5x 5.25x 5.5x 5.75x */ 668*0c0d06caSMauro Carvalho Chehab 0x0054, 0x0055, 0x0056, 0x0057, 669*0c0d06caSMauro Carvalho Chehab /* 6x 6.25x 6.5x 6.75x */ 670*0c0d06caSMauro Carvalho Chehab 0x0058, 0x0059, 0x005a, 0x005b, 671*0c0d06caSMauro Carvalho Chehab /* 7x 7.25x 7.5x 7.75x */ 672*0c0d06caSMauro Carvalho Chehab 0x005c, 0x005d, 0x005e, 0x005f, 673*0c0d06caSMauro Carvalho Chehab /* 8x */ 674*0c0d06caSMauro Carvalho Chehab 0x0060 675*0c0d06caSMauro Carvalho Chehab }; 676*0c0d06caSMauro Carvalho Chehab 677*0c0d06caSMauro Carvalho Chehab /* Gain = .5 + bit[7:0] / 16 */ 678*0c0d06caSMauro Carvalho Chehab static const u8 hv7131r_gain[] = { 679*0c0d06caSMauro Carvalho Chehab 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */, 680*0c0d06caSMauro Carvalho Chehab 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */, 681*0c0d06caSMauro Carvalho Chehab 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */, 682*0c0d06caSMauro Carvalho Chehab 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */, 683*0c0d06caSMauro Carvalho Chehab 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */, 684*0c0d06caSMauro Carvalho Chehab 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */, 685*0c0d06caSMauro Carvalho Chehab 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */, 686*0c0d06caSMauro Carvalho Chehab 0x78 /* 8x */ 687*0c0d06caSMauro Carvalho Chehab }; 688*0c0d06caSMauro Carvalho Chehab 689*0c0d06caSMauro Carvalho Chehab static const struct i2c_reg_u8 soi968_init[] = { 690*0c0d06caSMauro Carvalho Chehab {0x0c, 0x00}, {0x0f, 0x1f}, 691*0c0d06caSMauro Carvalho Chehab {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00}, 692*0c0d06caSMauro Carvalho Chehab {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c}, 693*0c0d06caSMauro Carvalho Chehab {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff}, 694*0c0d06caSMauro Carvalho Chehab {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20}, 695*0c0d06caSMauro Carvalho Chehab {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e}, 696*0c0d06caSMauro Carvalho Chehab {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13}, 697*0c0d06caSMauro Carvalho Chehab {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79}, 698*0c0d06caSMauro Carvalho Chehab {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40}, 699*0c0d06caSMauro Carvalho Chehab {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32}, 700*0c0d06caSMauro Carvalho Chehab {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80}, 701*0c0d06caSMauro Carvalho Chehab }; 702*0c0d06caSMauro Carvalho Chehab 703*0c0d06caSMauro Carvalho Chehab static const struct i2c_reg_u8 ov7660_init[] = { 704*0c0d06caSMauro Carvalho Chehab {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3}, 705*0c0d06caSMauro Carvalho Chehab {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40}, 706*0c0d06caSMauro Carvalho Chehab {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a}, 707*0c0d06caSMauro Carvalho Chehab /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using 708*0c0d06caSMauro Carvalho Chehab 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */ 709*0c0d06caSMauro Carvalho Chehab {0x17, 0x10}, {0x18, 0x61}, 710*0c0d06caSMauro Carvalho Chehab {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43}, 711*0c0d06caSMauro Carvalho Chehab {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0x00}, 712*0c0d06caSMauro Carvalho Chehab {0x2e, 0x00}, {0x01, 0x78}, {0x02, 0x50}, 713*0c0d06caSMauro Carvalho Chehab }; 714*0c0d06caSMauro Carvalho Chehab 715*0c0d06caSMauro Carvalho Chehab static const struct i2c_reg_u8 ov7670_init[] = { 716*0c0d06caSMauro Carvalho Chehab {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01}, 717*0c0d06caSMauro Carvalho Chehab {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00}, 718*0c0d06caSMauro Carvalho Chehab {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0}, 719*0c0d06caSMauro Carvalho Chehab {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00}, 720*0c0d06caSMauro Carvalho Chehab {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07}, 721*0c0d06caSMauro Carvalho Chehab {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75}, 722*0c0d06caSMauro Carvalho Chehab {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8}, 723*0c0d06caSMauro Carvalho Chehab {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5}, 724*0c0d06caSMauro Carvalho Chehab {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27}, 725*0c0d06caSMauro Carvalho Chehab {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b}, 726*0c0d06caSMauro Carvalho Chehab {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a}, 727*0c0d06caSMauro Carvalho Chehab {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00}, 728*0c0d06caSMauro Carvalho Chehab {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00}, 729*0c0d06caSMauro Carvalho Chehab {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80}, 730*0c0d06caSMauro Carvalho Chehab {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82}, 731*0c0d06caSMauro Carvalho Chehab {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20}, 732*0c0d06caSMauro Carvalho Chehab {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c}, 733*0c0d06caSMauro Carvalho Chehab {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66}, 734*0c0d06caSMauro Carvalho Chehab {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11}, 735*0c0d06caSMauro Carvalho Chehab {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40}, 736*0c0d06caSMauro Carvalho Chehab {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02}, 737*0c0d06caSMauro Carvalho Chehab {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a}, 738*0c0d06caSMauro Carvalho Chehab {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08}, 739*0c0d06caSMauro Carvalho Chehab {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04}, 740*0c0d06caSMauro Carvalho Chehab {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30}, 741*0c0d06caSMauro Carvalho Chehab {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88}, 742*0c0d06caSMauro Carvalho Chehab {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30}, 743*0c0d06caSMauro Carvalho Chehab {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99}, 744*0c0d06caSMauro Carvalho Chehab {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0}, 745*0c0d06caSMauro Carvalho Chehab {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e}, 746*0c0d06caSMauro Carvalho Chehab {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01}, 747*0c0d06caSMauro Carvalho Chehab {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20}, 748*0c0d06caSMauro Carvalho Chehab {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0}, 749*0c0d06caSMauro Carvalho Chehab {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30}, 750*0c0d06caSMauro Carvalho Chehab {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06}, 751*0c0d06caSMauro Carvalho Chehab {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a}, 752*0c0d06caSMauro Carvalho Chehab {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a}, 753*0c0d06caSMauro Carvalho Chehab {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84}, 754*0c0d06caSMauro Carvalho Chehab {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d}, 755*0c0d06caSMauro Carvalho Chehab {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d}, 756*0c0d06caSMauro Carvalho Chehab {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00}, 757*0c0d06caSMauro Carvalho Chehab {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, 758*0c0d06caSMauro Carvalho Chehab {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60}, 759*0c0d06caSMauro Carvalho Chehab {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, 760*0c0d06caSMauro Carvalho Chehab {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e}, 761*0c0d06caSMauro Carvalho Chehab {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56}, 762*0c0d06caSMauro Carvalho Chehab {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03}, 763*0c0d06caSMauro Carvalho Chehab {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47}, 764*0c0d06caSMauro Carvalho Chehab {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74}, 765*0c0d06caSMauro Carvalho Chehab {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2}, 766*0c0d06caSMauro Carvalho Chehab {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00}, 767*0c0d06caSMauro Carvalho Chehab {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a}, 768*0c0d06caSMauro Carvalho Chehab {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00}, 769*0c0d06caSMauro Carvalho Chehab {0x93, 0x00}, 770*0c0d06caSMauro Carvalho Chehab }; 771*0c0d06caSMauro Carvalho Chehab 772*0c0d06caSMauro Carvalho Chehab static const struct i2c_reg_u8 ov9650_init[] = { 773*0c0d06caSMauro Carvalho Chehab {0x00, 0x00}, {0x01, 0x78}, 774*0c0d06caSMauro Carvalho Chehab {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03}, 775*0c0d06caSMauro Carvalho Chehab {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00}, 776*0c0d06caSMauro Carvalho Chehab {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00}, 777*0c0d06caSMauro Carvalho Chehab {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c}, 778*0c0d06caSMauro Carvalho Chehab {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2}, 779*0c0d06caSMauro Carvalho Chehab {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07}, 780*0c0d06caSMauro Carvalho Chehab {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00}, 781*0c0d06caSMauro Carvalho Chehab {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04}, 782*0c0d06caSMauro Carvalho Chehab {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68}, 783*0c0d06caSMauro Carvalho Chehab {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80}, 784*0c0d06caSMauro Carvalho Chehab {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00}, 785*0c0d06caSMauro Carvalho Chehab {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00}, 786*0c0d06caSMauro Carvalho Chehab {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30}, 787*0c0d06caSMauro Carvalho Chehab {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf}, 788*0c0d06caSMauro Carvalho Chehab {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00}, 789*0c0d06caSMauro Carvalho Chehab {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01}, 790*0c0d06caSMauro Carvalho Chehab {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19}, 791*0c0d06caSMauro Carvalho Chehab {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1}, 792*0c0d06caSMauro Carvalho Chehab {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80}, 793*0c0d06caSMauro Carvalho Chehab {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00}, 794*0c0d06caSMauro Carvalho Chehab {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20}, 795*0c0d06caSMauro Carvalho Chehab {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf}, 796*0c0d06caSMauro Carvalho Chehab {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88}, 797*0c0d06caSMauro Carvalho Chehab {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00}, 798*0c0d06caSMauro Carvalho Chehab {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8}, 799*0c0d06caSMauro Carvalho Chehab {0xaa, 0x92}, {0xab, 0x0a}, 800*0c0d06caSMauro Carvalho Chehab }; 801*0c0d06caSMauro Carvalho Chehab 802*0c0d06caSMauro Carvalho Chehab static const struct i2c_reg_u8 ov9655_init[] = { 803*0c0d06caSMauro Carvalho Chehab {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba}, 804*0c0d06caSMauro Carvalho Chehab {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08}, 805*0c0d06caSMauro Carvalho Chehab {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d}, 806*0c0d06caSMauro Carvalho Chehab {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57}, 807*0c0d06caSMauro Carvalho Chehab {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19}, 808*0c0d06caSMauro Carvalho Chehab {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80}, 809*0c0d06caSMauro Carvalho Chehab {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c}, 810*0c0d06caSMauro Carvalho Chehab {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc}, 811*0c0d06caSMauro Carvalho Chehab {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05}, 812*0c0d06caSMauro Carvalho Chehab {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e}, 813*0c0d06caSMauro Carvalho Chehab {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, 814*0c0d06caSMauro Carvalho Chehab {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, 815*0c0d06caSMauro Carvalho Chehab {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, 816*0c0d06caSMauro Carvalho Chehab {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, 817*0c0d06caSMauro Carvalho Chehab {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, 818*0c0d06caSMauro Carvalho Chehab {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01}, 819*0c0d06caSMauro Carvalho Chehab {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0}, 820*0c0d06caSMauro Carvalho Chehab {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00}, 821*0c0d06caSMauro Carvalho Chehab {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61}, 822*0c0d06caSMauro Carvalho Chehab {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a}, 823*0c0d06caSMauro Carvalho Chehab {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01}, 824*0c0d06caSMauro Carvalho Chehab {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a}, 825*0c0d06caSMauro Carvalho Chehab {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c}, 826*0c0d06caSMauro Carvalho Chehab {0x04, 0x03}, {0x00, 0x13}, 827*0c0d06caSMauro Carvalho Chehab }; 828*0c0d06caSMauro Carvalho Chehab 829*0c0d06caSMauro Carvalho Chehab static const struct i2c_reg_u16 mt9v112_init[] = { 830*0c0d06caSMauro Carvalho Chehab {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020}, 831*0c0d06caSMauro Carvalho Chehab {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b}, 832*0c0d06caSMauro Carvalho Chehab {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001}, 833*0c0d06caSMauro Carvalho Chehab {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a}, 834*0c0d06caSMauro Carvalho Chehab {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58}, 835*0c0d06caSMauro Carvalho Chehab {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001}, 836*0c0d06caSMauro Carvalho Chehab {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020}, 837*0c0d06caSMauro Carvalho Chehab {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020}, 838*0c0d06caSMauro Carvalho Chehab {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020}, 839*0c0d06caSMauro Carvalho Chehab {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c}, 840*0c0d06caSMauro Carvalho Chehab {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2}, 841*0c0d06caSMauro Carvalho Chehab {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0}, 842*0c0d06caSMauro Carvalho Chehab {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020}, 843*0c0d06caSMauro Carvalho Chehab {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c}, 844*0c0d06caSMauro Carvalho Chehab {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae}, 845*0c0d06caSMauro Carvalho Chehab {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae}, 846*0c0d06caSMauro Carvalho Chehab }; 847*0c0d06caSMauro Carvalho Chehab 848*0c0d06caSMauro Carvalho Chehab static const struct i2c_reg_u16 mt9v111_init[] = { 849*0c0d06caSMauro Carvalho Chehab {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000}, 850*0c0d06caSMauro Carvalho Chehab {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0}, 851*0c0d06caSMauro Carvalho Chehab {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e}, 852*0c0d06caSMauro Carvalho Chehab {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016}, 853*0c0d06caSMauro Carvalho Chehab {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004}, 854*0c0d06caSMauro Carvalho Chehab {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008}, 855*0c0d06caSMauro Carvalho Chehab {0x0e, 0x0008}, {0x20, 0x0000} 856*0c0d06caSMauro Carvalho Chehab }; 857*0c0d06caSMauro Carvalho Chehab 858*0c0d06caSMauro Carvalho Chehab static const struct i2c_reg_u16 mt9v011_init[] = { 859*0c0d06caSMauro Carvalho Chehab {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000}, 860*0c0d06caSMauro Carvalho Chehab {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1}, 861*0c0d06caSMauro Carvalho Chehab {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006}, 862*0c0d06caSMauro Carvalho Chehab {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000}, 863*0c0d06caSMauro Carvalho Chehab {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000}, 864*0c0d06caSMauro Carvalho Chehab {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000}, 865*0c0d06caSMauro Carvalho Chehab {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000}, 866*0c0d06caSMauro Carvalho Chehab {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000}, 867*0c0d06caSMauro Carvalho Chehab {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000}, 868*0c0d06caSMauro Carvalho Chehab {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000}, 869*0c0d06caSMauro Carvalho Chehab {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000}, 870*0c0d06caSMauro Carvalho Chehab {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000}, 871*0c0d06caSMauro Carvalho Chehab {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024}, 872*0c0d06caSMauro Carvalho Chehab {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000}, 873*0c0d06caSMauro Carvalho Chehab {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100}, 874*0c0d06caSMauro Carvalho Chehab {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1}, 875*0c0d06caSMauro Carvalho Chehab {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000}, 876*0c0d06caSMauro Carvalho Chehab {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000}, 877*0c0d06caSMauro Carvalho Chehab {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000}, 878*0c0d06caSMauro Carvalho Chehab {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101}, 879*0c0d06caSMauro Carvalho Chehab {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003}, 880*0c0d06caSMauro Carvalho Chehab {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0}, 881*0c0d06caSMauro Carvalho Chehab {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000}, 882*0c0d06caSMauro Carvalho Chehab {0x06, 0x0029}, {0x05, 0x0009}, 883*0c0d06caSMauro Carvalho Chehab }; 884*0c0d06caSMauro Carvalho Chehab 885*0c0d06caSMauro Carvalho Chehab static const struct i2c_reg_u16 mt9m001_init[] = { 886*0c0d06caSMauro Carvalho Chehab {0x0d, 0x0001}, 887*0c0d06caSMauro Carvalho Chehab {0x0d, 0x0000}, 888*0c0d06caSMauro Carvalho Chehab {0x04, 0x0500}, /* hres = 1280 */ 889*0c0d06caSMauro Carvalho Chehab {0x03, 0x0400}, /* vres = 1024 */ 890*0c0d06caSMauro Carvalho Chehab {0x20, 0x1100}, 891*0c0d06caSMauro Carvalho Chehab {0x06, 0x0010}, 892*0c0d06caSMauro Carvalho Chehab {0x2b, 0x0024}, 893*0c0d06caSMauro Carvalho Chehab {0x2e, 0x0024}, 894*0c0d06caSMauro Carvalho Chehab {0x35, 0x0024}, 895*0c0d06caSMauro Carvalho Chehab {0x2d, 0x0020}, 896*0c0d06caSMauro Carvalho Chehab {0x2c, 0x0020}, 897*0c0d06caSMauro Carvalho Chehab {0x09, 0x0ad4}, 898*0c0d06caSMauro Carvalho Chehab {0x35, 0x0057}, 899*0c0d06caSMauro Carvalho Chehab }; 900*0c0d06caSMauro Carvalho Chehab 901*0c0d06caSMauro Carvalho Chehab static const struct i2c_reg_u16 mt9m111_init[] = { 902*0c0d06caSMauro Carvalho Chehab {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008}, 903*0c0d06caSMauro Carvalho Chehab {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300}, 904*0c0d06caSMauro Carvalho Chehab {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e}, 905*0c0d06caSMauro Carvalho Chehab {0xf0, 0x0000}, 906*0c0d06caSMauro Carvalho Chehab }; 907*0c0d06caSMauro Carvalho Chehab 908*0c0d06caSMauro Carvalho Chehab static const struct i2c_reg_u16 mt9m112_init[] = { 909*0c0d06caSMauro Carvalho Chehab {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008}, 910*0c0d06caSMauro Carvalho Chehab {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300}, 911*0c0d06caSMauro Carvalho Chehab {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e}, 912*0c0d06caSMauro Carvalho Chehab {0xf0, 0x0000}, 913*0c0d06caSMauro Carvalho Chehab }; 914*0c0d06caSMauro Carvalho Chehab 915*0c0d06caSMauro Carvalho Chehab static const struct i2c_reg_u8 hv7131r_init[] = { 916*0c0d06caSMauro Carvalho Chehab {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08}, 917*0c0d06caSMauro Carvalho Chehab {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0}, 918*0c0d06caSMauro Carvalho Chehab {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08}, 919*0c0d06caSMauro Carvalho Chehab {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07}, 920*0c0d06caSMauro Carvalho Chehab {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62}, 921*0c0d06caSMauro Carvalho Chehab {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10}, 922*0c0d06caSMauro Carvalho Chehab {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00}, 923*0c0d06caSMauro Carvalho Chehab {0x23, 0x09}, {0x01, 0x08}, 924*0c0d06caSMauro Carvalho Chehab }; 925*0c0d06caSMauro Carvalho Chehab 926*0c0d06caSMauro Carvalho Chehab static void reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length) 927*0c0d06caSMauro Carvalho Chehab { 928*0c0d06caSMauro Carvalho Chehab struct usb_device *dev = gspca_dev->dev; 929*0c0d06caSMauro Carvalho Chehab int result; 930*0c0d06caSMauro Carvalho Chehab 931*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 932*0c0d06caSMauro Carvalho Chehab return; 933*0c0d06caSMauro Carvalho Chehab result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 934*0c0d06caSMauro Carvalho Chehab 0x00, 935*0c0d06caSMauro Carvalho Chehab USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 936*0c0d06caSMauro Carvalho Chehab reg, 937*0c0d06caSMauro Carvalho Chehab 0x00, 938*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_buf, 939*0c0d06caSMauro Carvalho Chehab length, 940*0c0d06caSMauro Carvalho Chehab 500); 941*0c0d06caSMauro Carvalho Chehab if (unlikely(result < 0 || result != length)) { 942*0c0d06caSMauro Carvalho Chehab pr_err("Read register %02x failed %d\n", reg, result); 943*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_err = result; 944*0c0d06caSMauro Carvalho Chehab } 945*0c0d06caSMauro Carvalho Chehab } 946*0c0d06caSMauro Carvalho Chehab 947*0c0d06caSMauro Carvalho Chehab static void reg_w(struct gspca_dev *gspca_dev, u16 reg, 948*0c0d06caSMauro Carvalho Chehab const u8 *buffer, int length) 949*0c0d06caSMauro Carvalho Chehab { 950*0c0d06caSMauro Carvalho Chehab struct usb_device *dev = gspca_dev->dev; 951*0c0d06caSMauro Carvalho Chehab int result; 952*0c0d06caSMauro Carvalho Chehab 953*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 954*0c0d06caSMauro Carvalho Chehab return; 955*0c0d06caSMauro Carvalho Chehab memcpy(gspca_dev->usb_buf, buffer, length); 956*0c0d06caSMauro Carvalho Chehab result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 957*0c0d06caSMauro Carvalho Chehab 0x08, 958*0c0d06caSMauro Carvalho Chehab USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 959*0c0d06caSMauro Carvalho Chehab reg, 960*0c0d06caSMauro Carvalho Chehab 0x00, 961*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_buf, 962*0c0d06caSMauro Carvalho Chehab length, 963*0c0d06caSMauro Carvalho Chehab 500); 964*0c0d06caSMauro Carvalho Chehab if (unlikely(result < 0 || result != length)) { 965*0c0d06caSMauro Carvalho Chehab pr_err("Write register %02x failed %d\n", reg, result); 966*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_err = result; 967*0c0d06caSMauro Carvalho Chehab } 968*0c0d06caSMauro Carvalho Chehab } 969*0c0d06caSMauro Carvalho Chehab 970*0c0d06caSMauro Carvalho Chehab static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) 971*0c0d06caSMauro Carvalho Chehab { 972*0c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, reg, &value, 1); 973*0c0d06caSMauro Carvalho Chehab } 974*0c0d06caSMauro Carvalho Chehab 975*0c0d06caSMauro Carvalho Chehab static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) 976*0c0d06caSMauro Carvalho Chehab { 977*0c0d06caSMauro Carvalho Chehab int i; 978*0c0d06caSMauro Carvalho Chehab 979*0c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x10c0, buffer, 8); 980*0c0d06caSMauro Carvalho Chehab for (i = 0; i < 5; i++) { 981*0c0d06caSMauro Carvalho Chehab reg_r(gspca_dev, 0x10c0, 1); 982*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 983*0c0d06caSMauro Carvalho Chehab return; 984*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_buf[0] & 0x04) { 985*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_buf[0] & 0x08) { 986*0c0d06caSMauro Carvalho Chehab pr_err("i2c_w error\n"); 987*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_err = -EIO; 988*0c0d06caSMauro Carvalho Chehab } 989*0c0d06caSMauro Carvalho Chehab return; 990*0c0d06caSMauro Carvalho Chehab } 991*0c0d06caSMauro Carvalho Chehab msleep(10); 992*0c0d06caSMauro Carvalho Chehab } 993*0c0d06caSMauro Carvalho Chehab pr_err("i2c_w reg %02x no response\n", buffer[2]); 994*0c0d06caSMauro Carvalho Chehab /* gspca_dev->usb_err = -EIO; fixme: may occur */ 995*0c0d06caSMauro Carvalho Chehab } 996*0c0d06caSMauro Carvalho Chehab 997*0c0d06caSMauro Carvalho Chehab static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) 998*0c0d06caSMauro Carvalho Chehab { 999*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1000*0c0d06caSMauro Carvalho Chehab u8 row[8]; 1001*0c0d06caSMauro Carvalho Chehab 1002*0c0d06caSMauro Carvalho Chehab /* 1003*0c0d06caSMauro Carvalho Chehab * from the point of view of the bridge, the length 1004*0c0d06caSMauro Carvalho Chehab * includes the address 1005*0c0d06caSMauro Carvalho Chehab */ 1006*0c0d06caSMauro Carvalho Chehab row[0] = sd->i2c_intf | (2 << 4); 1007*0c0d06caSMauro Carvalho Chehab row[1] = sd->i2c_addr; 1008*0c0d06caSMauro Carvalho Chehab row[2] = reg; 1009*0c0d06caSMauro Carvalho Chehab row[3] = val; 1010*0c0d06caSMauro Carvalho Chehab row[4] = 0x00; 1011*0c0d06caSMauro Carvalho Chehab row[5] = 0x00; 1012*0c0d06caSMauro Carvalho Chehab row[6] = 0x00; 1013*0c0d06caSMauro Carvalho Chehab row[7] = 0x10; 1014*0c0d06caSMauro Carvalho Chehab 1015*0c0d06caSMauro Carvalho Chehab i2c_w(gspca_dev, row); 1016*0c0d06caSMauro Carvalho Chehab } 1017*0c0d06caSMauro Carvalho Chehab 1018*0c0d06caSMauro Carvalho Chehab static void i2c_w1_buf(struct gspca_dev *gspca_dev, 1019*0c0d06caSMauro Carvalho Chehab const struct i2c_reg_u8 *buf, int sz) 1020*0c0d06caSMauro Carvalho Chehab { 1021*0c0d06caSMauro Carvalho Chehab while (--sz >= 0) { 1022*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, buf->reg, buf->val); 1023*0c0d06caSMauro Carvalho Chehab buf++; 1024*0c0d06caSMauro Carvalho Chehab } 1025*0c0d06caSMauro Carvalho Chehab } 1026*0c0d06caSMauro Carvalho Chehab 1027*0c0d06caSMauro Carvalho Chehab static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) 1028*0c0d06caSMauro Carvalho Chehab { 1029*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1030*0c0d06caSMauro Carvalho Chehab u8 row[8]; 1031*0c0d06caSMauro Carvalho Chehab 1032*0c0d06caSMauro Carvalho Chehab /* 1033*0c0d06caSMauro Carvalho Chehab * from the point of view of the bridge, the length 1034*0c0d06caSMauro Carvalho Chehab * includes the address 1035*0c0d06caSMauro Carvalho Chehab */ 1036*0c0d06caSMauro Carvalho Chehab row[0] = sd->i2c_intf | (3 << 4); 1037*0c0d06caSMauro Carvalho Chehab row[1] = sd->i2c_addr; 1038*0c0d06caSMauro Carvalho Chehab row[2] = reg; 1039*0c0d06caSMauro Carvalho Chehab row[3] = val >> 8; 1040*0c0d06caSMauro Carvalho Chehab row[4] = val; 1041*0c0d06caSMauro Carvalho Chehab row[5] = 0x00; 1042*0c0d06caSMauro Carvalho Chehab row[6] = 0x00; 1043*0c0d06caSMauro Carvalho Chehab row[7] = 0x10; 1044*0c0d06caSMauro Carvalho Chehab 1045*0c0d06caSMauro Carvalho Chehab i2c_w(gspca_dev, row); 1046*0c0d06caSMauro Carvalho Chehab } 1047*0c0d06caSMauro Carvalho Chehab 1048*0c0d06caSMauro Carvalho Chehab static void i2c_w2_buf(struct gspca_dev *gspca_dev, 1049*0c0d06caSMauro Carvalho Chehab const struct i2c_reg_u16 *buf, int sz) 1050*0c0d06caSMauro Carvalho Chehab { 1051*0c0d06caSMauro Carvalho Chehab while (--sz >= 0) { 1052*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, buf->reg, buf->val); 1053*0c0d06caSMauro Carvalho Chehab buf++; 1054*0c0d06caSMauro Carvalho Chehab } 1055*0c0d06caSMauro Carvalho Chehab } 1056*0c0d06caSMauro Carvalho Chehab 1057*0c0d06caSMauro Carvalho Chehab static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) 1058*0c0d06caSMauro Carvalho Chehab { 1059*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1060*0c0d06caSMauro Carvalho Chehab u8 row[8]; 1061*0c0d06caSMauro Carvalho Chehab 1062*0c0d06caSMauro Carvalho Chehab row[0] = sd->i2c_intf | (1 << 4); 1063*0c0d06caSMauro Carvalho Chehab row[1] = sd->i2c_addr; 1064*0c0d06caSMauro Carvalho Chehab row[2] = reg; 1065*0c0d06caSMauro Carvalho Chehab row[3] = 0; 1066*0c0d06caSMauro Carvalho Chehab row[4] = 0; 1067*0c0d06caSMauro Carvalho Chehab row[5] = 0; 1068*0c0d06caSMauro Carvalho Chehab row[6] = 0; 1069*0c0d06caSMauro Carvalho Chehab row[7] = 0x10; 1070*0c0d06caSMauro Carvalho Chehab i2c_w(gspca_dev, row); 1071*0c0d06caSMauro Carvalho Chehab row[0] = sd->i2c_intf | (1 << 4) | 0x02; 1072*0c0d06caSMauro Carvalho Chehab row[2] = 0; 1073*0c0d06caSMauro Carvalho Chehab i2c_w(gspca_dev, row); 1074*0c0d06caSMauro Carvalho Chehab reg_r(gspca_dev, 0x10c2, 5); 1075*0c0d06caSMauro Carvalho Chehab *val = gspca_dev->usb_buf[4]; 1076*0c0d06caSMauro Carvalho Chehab } 1077*0c0d06caSMauro Carvalho Chehab 1078*0c0d06caSMauro Carvalho Chehab static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) 1079*0c0d06caSMauro Carvalho Chehab { 1080*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1081*0c0d06caSMauro Carvalho Chehab u8 row[8]; 1082*0c0d06caSMauro Carvalho Chehab 1083*0c0d06caSMauro Carvalho Chehab row[0] = sd->i2c_intf | (1 << 4); 1084*0c0d06caSMauro Carvalho Chehab row[1] = sd->i2c_addr; 1085*0c0d06caSMauro Carvalho Chehab row[2] = reg; 1086*0c0d06caSMauro Carvalho Chehab row[3] = 0; 1087*0c0d06caSMauro Carvalho Chehab row[4] = 0; 1088*0c0d06caSMauro Carvalho Chehab row[5] = 0; 1089*0c0d06caSMauro Carvalho Chehab row[6] = 0; 1090*0c0d06caSMauro Carvalho Chehab row[7] = 0x10; 1091*0c0d06caSMauro Carvalho Chehab i2c_w(gspca_dev, row); 1092*0c0d06caSMauro Carvalho Chehab row[0] = sd->i2c_intf | (2 << 4) | 0x02; 1093*0c0d06caSMauro Carvalho Chehab row[2] = 0; 1094*0c0d06caSMauro Carvalho Chehab i2c_w(gspca_dev, row); 1095*0c0d06caSMauro Carvalho Chehab reg_r(gspca_dev, 0x10c2, 5); 1096*0c0d06caSMauro Carvalho Chehab *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; 1097*0c0d06caSMauro Carvalho Chehab } 1098*0c0d06caSMauro Carvalho Chehab 1099*0c0d06caSMauro Carvalho Chehab static void ov9650_init_sensor(struct gspca_dev *gspca_dev) 1100*0c0d06caSMauro Carvalho Chehab { 1101*0c0d06caSMauro Carvalho Chehab u16 id; 1102*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1103*0c0d06caSMauro Carvalho Chehab 1104*0c0d06caSMauro Carvalho Chehab i2c_r2(gspca_dev, 0x1c, &id); 1105*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1106*0c0d06caSMauro Carvalho Chehab return; 1107*0c0d06caSMauro Carvalho Chehab 1108*0c0d06caSMauro Carvalho Chehab if (id != 0x7fa2) { 1109*0c0d06caSMauro Carvalho Chehab pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id); 1110*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_err = -ENODEV; 1111*0c0d06caSMauro Carvalho Chehab return; 1112*0c0d06caSMauro Carvalho Chehab } 1113*0c0d06caSMauro Carvalho Chehab 1114*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ 1115*0c0d06caSMauro Carvalho Chehab msleep(200); 1116*0c0d06caSMauro Carvalho Chehab i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init)); 1117*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1118*0c0d06caSMauro Carvalho Chehab pr_err("OV9650 sensor initialization failed\n"); 1119*0c0d06caSMauro Carvalho Chehab sd->hstart = 1; 1120*0c0d06caSMauro Carvalho Chehab sd->vstart = 7; 1121*0c0d06caSMauro Carvalho Chehab } 1122*0c0d06caSMauro Carvalho Chehab 1123*0c0d06caSMauro Carvalho Chehab static void ov9655_init_sensor(struct gspca_dev *gspca_dev) 1124*0c0d06caSMauro Carvalho Chehab { 1125*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1126*0c0d06caSMauro Carvalho Chehab 1127*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ 1128*0c0d06caSMauro Carvalho Chehab msleep(200); 1129*0c0d06caSMauro Carvalho Chehab i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init)); 1130*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1131*0c0d06caSMauro Carvalho Chehab pr_err("OV9655 sensor initialization failed\n"); 1132*0c0d06caSMauro Carvalho Chehab 1133*0c0d06caSMauro Carvalho Chehab sd->hstart = 1; 1134*0c0d06caSMauro Carvalho Chehab sd->vstart = 2; 1135*0c0d06caSMauro Carvalho Chehab } 1136*0c0d06caSMauro Carvalho Chehab 1137*0c0d06caSMauro Carvalho Chehab static void soi968_init_sensor(struct gspca_dev *gspca_dev) 1138*0c0d06caSMauro Carvalho Chehab { 1139*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1140*0c0d06caSMauro Carvalho Chehab 1141*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ 1142*0c0d06caSMauro Carvalho Chehab msleep(200); 1143*0c0d06caSMauro Carvalho Chehab i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init)); 1144*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1145*0c0d06caSMauro Carvalho Chehab pr_err("SOI968 sensor initialization failed\n"); 1146*0c0d06caSMauro Carvalho Chehab 1147*0c0d06caSMauro Carvalho Chehab sd->hstart = 60; 1148*0c0d06caSMauro Carvalho Chehab sd->vstart = 11; 1149*0c0d06caSMauro Carvalho Chehab } 1150*0c0d06caSMauro Carvalho Chehab 1151*0c0d06caSMauro Carvalho Chehab static void ov7660_init_sensor(struct gspca_dev *gspca_dev) 1152*0c0d06caSMauro Carvalho Chehab { 1153*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1154*0c0d06caSMauro Carvalho Chehab 1155*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ 1156*0c0d06caSMauro Carvalho Chehab msleep(200); 1157*0c0d06caSMauro Carvalho Chehab i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init)); 1158*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1159*0c0d06caSMauro Carvalho Chehab pr_err("OV7660 sensor initialization failed\n"); 1160*0c0d06caSMauro Carvalho Chehab sd->hstart = 3; 1161*0c0d06caSMauro Carvalho Chehab sd->vstart = 3; 1162*0c0d06caSMauro Carvalho Chehab } 1163*0c0d06caSMauro Carvalho Chehab 1164*0c0d06caSMauro Carvalho Chehab static void ov7670_init_sensor(struct gspca_dev *gspca_dev) 1165*0c0d06caSMauro Carvalho Chehab { 1166*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1167*0c0d06caSMauro Carvalho Chehab 1168*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ 1169*0c0d06caSMauro Carvalho Chehab msleep(200); 1170*0c0d06caSMauro Carvalho Chehab i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init)); 1171*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1172*0c0d06caSMauro Carvalho Chehab pr_err("OV7670 sensor initialization failed\n"); 1173*0c0d06caSMauro Carvalho Chehab 1174*0c0d06caSMauro Carvalho Chehab sd->hstart = 0; 1175*0c0d06caSMauro Carvalho Chehab sd->vstart = 1; 1176*0c0d06caSMauro Carvalho Chehab } 1177*0c0d06caSMauro Carvalho Chehab 1178*0c0d06caSMauro Carvalho Chehab static void mt9v_init_sensor(struct gspca_dev *gspca_dev) 1179*0c0d06caSMauro Carvalho Chehab { 1180*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1181*0c0d06caSMauro Carvalho Chehab u16 value; 1182*0c0d06caSMauro Carvalho Chehab 1183*0c0d06caSMauro Carvalho Chehab sd->i2c_addr = 0x5d; 1184*0c0d06caSMauro Carvalho Chehab i2c_r2(gspca_dev, 0xff, &value); 1185*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err >= 0 1186*0c0d06caSMauro Carvalho Chehab && value == 0x8243) { 1187*0c0d06caSMauro Carvalho Chehab i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init)); 1188*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) { 1189*0c0d06caSMauro Carvalho Chehab pr_err("MT9V011 sensor initialization failed\n"); 1190*0c0d06caSMauro Carvalho Chehab return; 1191*0c0d06caSMauro Carvalho Chehab } 1192*0c0d06caSMauro Carvalho Chehab sd->hstart = 2; 1193*0c0d06caSMauro Carvalho Chehab sd->vstart = 2; 1194*0c0d06caSMauro Carvalho Chehab sd->sensor = SENSOR_MT9V011; 1195*0c0d06caSMauro Carvalho Chehab pr_info("MT9V011 sensor detected\n"); 1196*0c0d06caSMauro Carvalho Chehab return; 1197*0c0d06caSMauro Carvalho Chehab } 1198*0c0d06caSMauro Carvalho Chehab 1199*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_err = 0; 1200*0c0d06caSMauro Carvalho Chehab sd->i2c_addr = 0x5c; 1201*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, 0x01, 0x0004); 1202*0c0d06caSMauro Carvalho Chehab i2c_r2(gspca_dev, 0xff, &value); 1203*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err >= 0 1204*0c0d06caSMauro Carvalho Chehab && value == 0x823a) { 1205*0c0d06caSMauro Carvalho Chehab i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init)); 1206*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) { 1207*0c0d06caSMauro Carvalho Chehab pr_err("MT9V111 sensor initialization failed\n"); 1208*0c0d06caSMauro Carvalho Chehab return; 1209*0c0d06caSMauro Carvalho Chehab } 1210*0c0d06caSMauro Carvalho Chehab sd->hstart = 2; 1211*0c0d06caSMauro Carvalho Chehab sd->vstart = 2; 1212*0c0d06caSMauro Carvalho Chehab sd->sensor = SENSOR_MT9V111; 1213*0c0d06caSMauro Carvalho Chehab pr_info("MT9V111 sensor detected\n"); 1214*0c0d06caSMauro Carvalho Chehab return; 1215*0c0d06caSMauro Carvalho Chehab } 1216*0c0d06caSMauro Carvalho Chehab 1217*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_err = 0; 1218*0c0d06caSMauro Carvalho Chehab sd->i2c_addr = 0x5d; 1219*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, 0xf0, 0x0000); 1220*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) { 1221*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_err = 0; 1222*0c0d06caSMauro Carvalho Chehab sd->i2c_addr = 0x48; 1223*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, 0xf0, 0x0000); 1224*0c0d06caSMauro Carvalho Chehab } 1225*0c0d06caSMauro Carvalho Chehab i2c_r2(gspca_dev, 0x00, &value); 1226*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err >= 0 1227*0c0d06caSMauro Carvalho Chehab && value == 0x1229) { 1228*0c0d06caSMauro Carvalho Chehab i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init)); 1229*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) { 1230*0c0d06caSMauro Carvalho Chehab pr_err("MT9V112 sensor initialization failed\n"); 1231*0c0d06caSMauro Carvalho Chehab return; 1232*0c0d06caSMauro Carvalho Chehab } 1233*0c0d06caSMauro Carvalho Chehab sd->hstart = 6; 1234*0c0d06caSMauro Carvalho Chehab sd->vstart = 2; 1235*0c0d06caSMauro Carvalho Chehab sd->sensor = SENSOR_MT9V112; 1236*0c0d06caSMauro Carvalho Chehab pr_info("MT9V112 sensor detected\n"); 1237*0c0d06caSMauro Carvalho Chehab return; 1238*0c0d06caSMauro Carvalho Chehab } 1239*0c0d06caSMauro Carvalho Chehab 1240*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_err = -ENODEV; 1241*0c0d06caSMauro Carvalho Chehab } 1242*0c0d06caSMauro Carvalho Chehab 1243*0c0d06caSMauro Carvalho Chehab static void mt9m112_init_sensor(struct gspca_dev *gspca_dev) 1244*0c0d06caSMauro Carvalho Chehab { 1245*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1246*0c0d06caSMauro Carvalho Chehab 1247*0c0d06caSMauro Carvalho Chehab i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init)); 1248*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1249*0c0d06caSMauro Carvalho Chehab pr_err("MT9M112 sensor initialization failed\n"); 1250*0c0d06caSMauro Carvalho Chehab 1251*0c0d06caSMauro Carvalho Chehab sd->hstart = 0; 1252*0c0d06caSMauro Carvalho Chehab sd->vstart = 2; 1253*0c0d06caSMauro Carvalho Chehab } 1254*0c0d06caSMauro Carvalho Chehab 1255*0c0d06caSMauro Carvalho Chehab static void mt9m111_init_sensor(struct gspca_dev *gspca_dev) 1256*0c0d06caSMauro Carvalho Chehab { 1257*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1258*0c0d06caSMauro Carvalho Chehab 1259*0c0d06caSMauro Carvalho Chehab i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init)); 1260*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1261*0c0d06caSMauro Carvalho Chehab pr_err("MT9M111 sensor initialization failed\n"); 1262*0c0d06caSMauro Carvalho Chehab 1263*0c0d06caSMauro Carvalho Chehab sd->hstart = 0; 1264*0c0d06caSMauro Carvalho Chehab sd->vstart = 2; 1265*0c0d06caSMauro Carvalho Chehab } 1266*0c0d06caSMauro Carvalho Chehab 1267*0c0d06caSMauro Carvalho Chehab static void mt9m001_init_sensor(struct gspca_dev *gspca_dev) 1268*0c0d06caSMauro Carvalho Chehab { 1269*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1270*0c0d06caSMauro Carvalho Chehab u16 id; 1271*0c0d06caSMauro Carvalho Chehab 1272*0c0d06caSMauro Carvalho Chehab i2c_r2(gspca_dev, 0x00, &id); 1273*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1274*0c0d06caSMauro Carvalho Chehab return; 1275*0c0d06caSMauro Carvalho Chehab 1276*0c0d06caSMauro Carvalho Chehab /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ 1277*0c0d06caSMauro Carvalho Chehab switch (id) { 1278*0c0d06caSMauro Carvalho Chehab case 0x8411: 1279*0c0d06caSMauro Carvalho Chehab case 0x8421: 1280*0c0d06caSMauro Carvalho Chehab pr_info("MT9M001 color sensor detected\n"); 1281*0c0d06caSMauro Carvalho Chehab break; 1282*0c0d06caSMauro Carvalho Chehab case 0x8431: 1283*0c0d06caSMauro Carvalho Chehab pr_info("MT9M001 mono sensor detected\n"); 1284*0c0d06caSMauro Carvalho Chehab break; 1285*0c0d06caSMauro Carvalho Chehab default: 1286*0c0d06caSMauro Carvalho Chehab pr_err("No MT9M001 chip detected, ID = %x\n\n", id); 1287*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_err = -ENODEV; 1288*0c0d06caSMauro Carvalho Chehab return; 1289*0c0d06caSMauro Carvalho Chehab } 1290*0c0d06caSMauro Carvalho Chehab 1291*0c0d06caSMauro Carvalho Chehab i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init)); 1292*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1293*0c0d06caSMauro Carvalho Chehab pr_err("MT9M001 sensor initialization failed\n"); 1294*0c0d06caSMauro Carvalho Chehab 1295*0c0d06caSMauro Carvalho Chehab sd->hstart = 1; 1296*0c0d06caSMauro Carvalho Chehab sd->vstart = 1; 1297*0c0d06caSMauro Carvalho Chehab } 1298*0c0d06caSMauro Carvalho Chehab 1299*0c0d06caSMauro Carvalho Chehab static void hv7131r_init_sensor(struct gspca_dev *gspca_dev) 1300*0c0d06caSMauro Carvalho Chehab { 1301*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1302*0c0d06caSMauro Carvalho Chehab 1303*0c0d06caSMauro Carvalho Chehab i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init)); 1304*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1305*0c0d06caSMauro Carvalho Chehab pr_err("HV7131R Sensor initialization failed\n"); 1306*0c0d06caSMauro Carvalho Chehab 1307*0c0d06caSMauro Carvalho Chehab sd->hstart = 0; 1308*0c0d06caSMauro Carvalho Chehab sd->vstart = 1; 1309*0c0d06caSMauro Carvalho Chehab } 1310*0c0d06caSMauro Carvalho Chehab 1311*0c0d06caSMauro Carvalho Chehab static void set_cmatrix(struct gspca_dev *gspca_dev, 1312*0c0d06caSMauro Carvalho Chehab s32 brightness, s32 contrast, s32 satur, s32 hue) 1313*0c0d06caSMauro Carvalho Chehab { 1314*0c0d06caSMauro Carvalho Chehab s32 hue_coord, hue_index = 180 + hue; 1315*0c0d06caSMauro Carvalho Chehab u8 cmatrix[21]; 1316*0c0d06caSMauro Carvalho Chehab 1317*0c0d06caSMauro Carvalho Chehab memset(cmatrix, 0, sizeof cmatrix); 1318*0c0d06caSMauro Carvalho Chehab cmatrix[2] = (contrast * 0x25 / 0x100) + 0x26; 1319*0c0d06caSMauro Carvalho Chehab cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; 1320*0c0d06caSMauro Carvalho Chehab cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; 1321*0c0d06caSMauro Carvalho Chehab cmatrix[18] = brightness - 0x80; 1322*0c0d06caSMauro Carvalho Chehab 1323*0c0d06caSMauro Carvalho Chehab hue_coord = (hsv_red_x[hue_index] * satur) >> 8; 1324*0c0d06caSMauro Carvalho Chehab cmatrix[6] = hue_coord; 1325*0c0d06caSMauro Carvalho Chehab cmatrix[7] = (hue_coord >> 8) & 0x0f; 1326*0c0d06caSMauro Carvalho Chehab 1327*0c0d06caSMauro Carvalho Chehab hue_coord = (hsv_red_y[hue_index] * satur) >> 8; 1328*0c0d06caSMauro Carvalho Chehab cmatrix[8] = hue_coord; 1329*0c0d06caSMauro Carvalho Chehab cmatrix[9] = (hue_coord >> 8) & 0x0f; 1330*0c0d06caSMauro Carvalho Chehab 1331*0c0d06caSMauro Carvalho Chehab hue_coord = (hsv_green_x[hue_index] * satur) >> 8; 1332*0c0d06caSMauro Carvalho Chehab cmatrix[10] = hue_coord; 1333*0c0d06caSMauro Carvalho Chehab cmatrix[11] = (hue_coord >> 8) & 0x0f; 1334*0c0d06caSMauro Carvalho Chehab 1335*0c0d06caSMauro Carvalho Chehab hue_coord = (hsv_green_y[hue_index] * satur) >> 8; 1336*0c0d06caSMauro Carvalho Chehab cmatrix[12] = hue_coord; 1337*0c0d06caSMauro Carvalho Chehab cmatrix[13] = (hue_coord >> 8) & 0x0f; 1338*0c0d06caSMauro Carvalho Chehab 1339*0c0d06caSMauro Carvalho Chehab hue_coord = (hsv_blue_x[hue_index] * satur) >> 8; 1340*0c0d06caSMauro Carvalho Chehab cmatrix[14] = hue_coord; 1341*0c0d06caSMauro Carvalho Chehab cmatrix[15] = (hue_coord >> 8) & 0x0f; 1342*0c0d06caSMauro Carvalho Chehab 1343*0c0d06caSMauro Carvalho Chehab hue_coord = (hsv_blue_y[hue_index] * satur) >> 8; 1344*0c0d06caSMauro Carvalho Chehab cmatrix[16] = hue_coord; 1345*0c0d06caSMauro Carvalho Chehab cmatrix[17] = (hue_coord >> 8) & 0x0f; 1346*0c0d06caSMauro Carvalho Chehab 1347*0c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x10e1, cmatrix, 21); 1348*0c0d06caSMauro Carvalho Chehab } 1349*0c0d06caSMauro Carvalho Chehab 1350*0c0d06caSMauro Carvalho Chehab static void set_gamma(struct gspca_dev *gspca_dev, s32 val) 1351*0c0d06caSMauro Carvalho Chehab { 1352*0c0d06caSMauro Carvalho Chehab u8 gamma[17]; 1353*0c0d06caSMauro Carvalho Chehab u8 gval = val * 0xb8 / 0x100; 1354*0c0d06caSMauro Carvalho Chehab 1355*0c0d06caSMauro Carvalho Chehab gamma[0] = 0x0a; 1356*0c0d06caSMauro Carvalho Chehab gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8); 1357*0c0d06caSMauro Carvalho Chehab gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8); 1358*0c0d06caSMauro Carvalho Chehab gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8); 1359*0c0d06caSMauro Carvalho Chehab gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8); 1360*0c0d06caSMauro Carvalho Chehab gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8); 1361*0c0d06caSMauro Carvalho Chehab gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8); 1362*0c0d06caSMauro Carvalho Chehab gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8); 1363*0c0d06caSMauro Carvalho Chehab gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8); 1364*0c0d06caSMauro Carvalho Chehab gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8); 1365*0c0d06caSMauro Carvalho Chehab gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8); 1366*0c0d06caSMauro Carvalho Chehab gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8); 1367*0c0d06caSMauro Carvalho Chehab gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8); 1368*0c0d06caSMauro Carvalho Chehab gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8); 1369*0c0d06caSMauro Carvalho Chehab gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8); 1370*0c0d06caSMauro Carvalho Chehab gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8); 1371*0c0d06caSMauro Carvalho Chehab gamma[16] = 0xf5; 1372*0c0d06caSMauro Carvalho Chehab 1373*0c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x1190, gamma, 17); 1374*0c0d06caSMauro Carvalho Chehab } 1375*0c0d06caSMauro Carvalho Chehab 1376*0c0d06caSMauro Carvalho Chehab static void set_redblue(struct gspca_dev *gspca_dev, s32 blue, s32 red) 1377*0c0d06caSMauro Carvalho Chehab { 1378*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x118c, red); 1379*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x118f, blue); 1380*0c0d06caSMauro Carvalho Chehab } 1381*0c0d06caSMauro Carvalho Chehab 1382*0c0d06caSMauro Carvalho Chehab static void set_hvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip) 1383*0c0d06caSMauro Carvalho Chehab { 1384*0c0d06caSMauro Carvalho Chehab u8 value, tslb; 1385*0c0d06caSMauro Carvalho Chehab u16 value2; 1386*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1387*0c0d06caSMauro Carvalho Chehab 1388*0c0d06caSMauro Carvalho Chehab if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) { 1389*0c0d06caSMauro Carvalho Chehab hflip = !hflip; 1390*0c0d06caSMauro Carvalho Chehab vflip = !vflip; 1391*0c0d06caSMauro Carvalho Chehab } 1392*0c0d06caSMauro Carvalho Chehab 1393*0c0d06caSMauro Carvalho Chehab switch (sd->sensor) { 1394*0c0d06caSMauro Carvalho Chehab case SENSOR_OV7660: 1395*0c0d06caSMauro Carvalho Chehab value = 0x01; 1396*0c0d06caSMauro Carvalho Chehab if (hflip) 1397*0c0d06caSMauro Carvalho Chehab value |= 0x20; 1398*0c0d06caSMauro Carvalho Chehab if (vflip) { 1399*0c0d06caSMauro Carvalho Chehab value |= 0x10; 1400*0c0d06caSMauro Carvalho Chehab sd->vstart = 2; 1401*0c0d06caSMauro Carvalho Chehab } else { 1402*0c0d06caSMauro Carvalho Chehab sd->vstart = 3; 1403*0c0d06caSMauro Carvalho Chehab } 1404*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x1182, sd->vstart); 1405*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x1e, value); 1406*0c0d06caSMauro Carvalho Chehab break; 1407*0c0d06caSMauro Carvalho Chehab case SENSOR_OV9650: 1408*0c0d06caSMauro Carvalho Chehab i2c_r1(gspca_dev, 0x1e, &value); 1409*0c0d06caSMauro Carvalho Chehab value &= ~0x30; 1410*0c0d06caSMauro Carvalho Chehab tslb = 0x01; 1411*0c0d06caSMauro Carvalho Chehab if (hflip) 1412*0c0d06caSMauro Carvalho Chehab value |= 0x20; 1413*0c0d06caSMauro Carvalho Chehab if (vflip) { 1414*0c0d06caSMauro Carvalho Chehab value |= 0x10; 1415*0c0d06caSMauro Carvalho Chehab tslb = 0x49; 1416*0c0d06caSMauro Carvalho Chehab } 1417*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x1e, value); 1418*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x3a, tslb); 1419*0c0d06caSMauro Carvalho Chehab break; 1420*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9V111: 1421*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9V011: 1422*0c0d06caSMauro Carvalho Chehab i2c_r2(gspca_dev, 0x20, &value2); 1423*0c0d06caSMauro Carvalho Chehab value2 &= ~0xc0a0; 1424*0c0d06caSMauro Carvalho Chehab if (hflip) 1425*0c0d06caSMauro Carvalho Chehab value2 |= 0x8080; 1426*0c0d06caSMauro Carvalho Chehab if (vflip) 1427*0c0d06caSMauro Carvalho Chehab value2 |= 0x4020; 1428*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, 0x20, value2); 1429*0c0d06caSMauro Carvalho Chehab break; 1430*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9M112: 1431*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9M111: 1432*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9V112: 1433*0c0d06caSMauro Carvalho Chehab i2c_r2(gspca_dev, 0x20, &value2); 1434*0c0d06caSMauro Carvalho Chehab value2 &= ~0x0003; 1435*0c0d06caSMauro Carvalho Chehab if (hflip) 1436*0c0d06caSMauro Carvalho Chehab value2 |= 0x0002; 1437*0c0d06caSMauro Carvalho Chehab if (vflip) 1438*0c0d06caSMauro Carvalho Chehab value2 |= 0x0001; 1439*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, 0x20, value2); 1440*0c0d06caSMauro Carvalho Chehab break; 1441*0c0d06caSMauro Carvalho Chehab case SENSOR_HV7131R: 1442*0c0d06caSMauro Carvalho Chehab i2c_r1(gspca_dev, 0x01, &value); 1443*0c0d06caSMauro Carvalho Chehab value &= ~0x03; 1444*0c0d06caSMauro Carvalho Chehab if (vflip) 1445*0c0d06caSMauro Carvalho Chehab value |= 0x01; 1446*0c0d06caSMauro Carvalho Chehab if (hflip) 1447*0c0d06caSMauro Carvalho Chehab value |= 0x02; 1448*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x01, value); 1449*0c0d06caSMauro Carvalho Chehab break; 1450*0c0d06caSMauro Carvalho Chehab } 1451*0c0d06caSMauro Carvalho Chehab } 1452*0c0d06caSMauro Carvalho Chehab 1453*0c0d06caSMauro Carvalho Chehab static void set_exposure(struct gspca_dev *gspca_dev, s32 expo) 1454*0c0d06caSMauro Carvalho Chehab { 1455*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1456*0c0d06caSMauro Carvalho Chehab u8 exp[8] = {sd->i2c_intf, sd->i2c_addr, 1457*0c0d06caSMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; 1458*0c0d06caSMauro Carvalho Chehab int expo2; 1459*0c0d06caSMauro Carvalho Chehab 1460*0c0d06caSMauro Carvalho Chehab if (gspca_dev->streaming) 1461*0c0d06caSMauro Carvalho Chehab exp[7] = 0x1e; 1462*0c0d06caSMauro Carvalho Chehab 1463*0c0d06caSMauro Carvalho Chehab switch (sd->sensor) { 1464*0c0d06caSMauro Carvalho Chehab case SENSOR_OV7660: 1465*0c0d06caSMauro Carvalho Chehab case SENSOR_OV7670: 1466*0c0d06caSMauro Carvalho Chehab case SENSOR_OV9655: 1467*0c0d06caSMauro Carvalho Chehab case SENSOR_OV9650: 1468*0c0d06caSMauro Carvalho Chehab if (expo > 547) 1469*0c0d06caSMauro Carvalho Chehab expo2 = 547; 1470*0c0d06caSMauro Carvalho Chehab else 1471*0c0d06caSMauro Carvalho Chehab expo2 = expo; 1472*0c0d06caSMauro Carvalho Chehab exp[0] |= (2 << 4); 1473*0c0d06caSMauro Carvalho Chehab exp[2] = 0x10; /* AECH */ 1474*0c0d06caSMauro Carvalho Chehab exp[3] = expo2 >> 2; 1475*0c0d06caSMauro Carvalho Chehab exp[7] = 0x10; 1476*0c0d06caSMauro Carvalho Chehab i2c_w(gspca_dev, exp); 1477*0c0d06caSMauro Carvalho Chehab exp[2] = 0x04; /* COM1 */ 1478*0c0d06caSMauro Carvalho Chehab exp[3] = expo2 & 0x0003; 1479*0c0d06caSMauro Carvalho Chehab exp[7] = 0x10; 1480*0c0d06caSMauro Carvalho Chehab i2c_w(gspca_dev, exp); 1481*0c0d06caSMauro Carvalho Chehab expo -= expo2; 1482*0c0d06caSMauro Carvalho Chehab exp[7] = 0x1e; 1483*0c0d06caSMauro Carvalho Chehab exp[0] |= (3 << 4); 1484*0c0d06caSMauro Carvalho Chehab exp[2] = 0x2d; /* ADVFL & ADVFH */ 1485*0c0d06caSMauro Carvalho Chehab exp[3] = expo; 1486*0c0d06caSMauro Carvalho Chehab exp[4] = expo >> 8; 1487*0c0d06caSMauro Carvalho Chehab break; 1488*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9M001: 1489*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9V112: 1490*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9V011: 1491*0c0d06caSMauro Carvalho Chehab exp[0] |= (3 << 4); 1492*0c0d06caSMauro Carvalho Chehab exp[2] = 0x09; 1493*0c0d06caSMauro Carvalho Chehab exp[3] = expo >> 8; 1494*0c0d06caSMauro Carvalho Chehab exp[4] = expo; 1495*0c0d06caSMauro Carvalho Chehab break; 1496*0c0d06caSMauro Carvalho Chehab case SENSOR_HV7131R: 1497*0c0d06caSMauro Carvalho Chehab exp[0] |= (4 << 4); 1498*0c0d06caSMauro Carvalho Chehab exp[2] = 0x25; 1499*0c0d06caSMauro Carvalho Chehab exp[3] = expo >> 5; 1500*0c0d06caSMauro Carvalho Chehab exp[4] = expo << 3; 1501*0c0d06caSMauro Carvalho Chehab exp[5] = 0; 1502*0c0d06caSMauro Carvalho Chehab break; 1503*0c0d06caSMauro Carvalho Chehab default: 1504*0c0d06caSMauro Carvalho Chehab return; 1505*0c0d06caSMauro Carvalho Chehab } 1506*0c0d06caSMauro Carvalho Chehab i2c_w(gspca_dev, exp); 1507*0c0d06caSMauro Carvalho Chehab } 1508*0c0d06caSMauro Carvalho Chehab 1509*0c0d06caSMauro Carvalho Chehab static void set_gain(struct gspca_dev *gspca_dev, s32 g) 1510*0c0d06caSMauro Carvalho Chehab { 1511*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1512*0c0d06caSMauro Carvalho Chehab u8 gain[8] = {sd->i2c_intf, sd->i2c_addr, 1513*0c0d06caSMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; 1514*0c0d06caSMauro Carvalho Chehab 1515*0c0d06caSMauro Carvalho Chehab if (gspca_dev->streaming) 1516*0c0d06caSMauro Carvalho Chehab gain[7] = 0x15; /* or 1d ? */ 1517*0c0d06caSMauro Carvalho Chehab 1518*0c0d06caSMauro Carvalho Chehab switch (sd->sensor) { 1519*0c0d06caSMauro Carvalho Chehab case SENSOR_OV7660: 1520*0c0d06caSMauro Carvalho Chehab case SENSOR_OV7670: 1521*0c0d06caSMauro Carvalho Chehab case SENSOR_SOI968: 1522*0c0d06caSMauro Carvalho Chehab case SENSOR_OV9655: 1523*0c0d06caSMauro Carvalho Chehab case SENSOR_OV9650: 1524*0c0d06caSMauro Carvalho Chehab gain[0] |= (2 << 4); 1525*0c0d06caSMauro Carvalho Chehab gain[3] = ov_gain[g]; 1526*0c0d06caSMauro Carvalho Chehab break; 1527*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9V011: 1528*0c0d06caSMauro Carvalho Chehab gain[0] |= (3 << 4); 1529*0c0d06caSMauro Carvalho Chehab gain[2] = 0x35; 1530*0c0d06caSMauro Carvalho Chehab gain[3] = micron1_gain[g] >> 8; 1531*0c0d06caSMauro Carvalho Chehab gain[4] = micron1_gain[g]; 1532*0c0d06caSMauro Carvalho Chehab break; 1533*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9V112: 1534*0c0d06caSMauro Carvalho Chehab gain[0] |= (3 << 4); 1535*0c0d06caSMauro Carvalho Chehab gain[2] = 0x2f; 1536*0c0d06caSMauro Carvalho Chehab gain[3] = micron1_gain[g] >> 8; 1537*0c0d06caSMauro Carvalho Chehab gain[4] = micron1_gain[g]; 1538*0c0d06caSMauro Carvalho Chehab break; 1539*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9M001: 1540*0c0d06caSMauro Carvalho Chehab gain[0] |= (3 << 4); 1541*0c0d06caSMauro Carvalho Chehab gain[2] = 0x2f; 1542*0c0d06caSMauro Carvalho Chehab gain[3] = micron2_gain[g] >> 8; 1543*0c0d06caSMauro Carvalho Chehab gain[4] = micron2_gain[g]; 1544*0c0d06caSMauro Carvalho Chehab break; 1545*0c0d06caSMauro Carvalho Chehab case SENSOR_HV7131R: 1546*0c0d06caSMauro Carvalho Chehab gain[0] |= (2 << 4); 1547*0c0d06caSMauro Carvalho Chehab gain[2] = 0x30; 1548*0c0d06caSMauro Carvalho Chehab gain[3] = hv7131r_gain[g]; 1549*0c0d06caSMauro Carvalho Chehab break; 1550*0c0d06caSMauro Carvalho Chehab default: 1551*0c0d06caSMauro Carvalho Chehab return; 1552*0c0d06caSMauro Carvalho Chehab } 1553*0c0d06caSMauro Carvalho Chehab i2c_w(gspca_dev, gain); 1554*0c0d06caSMauro Carvalho Chehab } 1555*0c0d06caSMauro Carvalho Chehab 1556*0c0d06caSMauro Carvalho Chehab static void set_quality(struct gspca_dev *gspca_dev, s32 val) 1557*0c0d06caSMauro Carvalho Chehab { 1558*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1559*0c0d06caSMauro Carvalho Chehab 1560*0c0d06caSMauro Carvalho Chehab jpeg_set_qual(sd->jpeg_hdr, val); 1561*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */ 1562*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */ 1563*0c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); 1564*0c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); 1565*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */ 1566*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x10e0, sd->fmt); 1567*0c0d06caSMauro Carvalho Chehab sd->fmt ^= 0x0c; /* invert QTAB use + write */ 1568*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x10e0, sd->fmt); 1569*0c0d06caSMauro Carvalho Chehab } 1570*0c0d06caSMauro Carvalho Chehab 1571*0c0d06caSMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG 1572*0c0d06caSMauro Carvalho Chehab static int sd_dbg_g_register(struct gspca_dev *gspca_dev, 1573*0c0d06caSMauro Carvalho Chehab struct v4l2_dbg_register *reg) 1574*0c0d06caSMauro Carvalho Chehab { 1575*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1576*0c0d06caSMauro Carvalho Chehab 1577*0c0d06caSMauro Carvalho Chehab switch (reg->match.type) { 1578*0c0d06caSMauro Carvalho Chehab case V4L2_CHIP_MATCH_HOST: 1579*0c0d06caSMauro Carvalho Chehab if (reg->match.addr != 0) 1580*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1581*0c0d06caSMauro Carvalho Chehab if (reg->reg < 0x1000 || reg->reg > 0x11ff) 1582*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1583*0c0d06caSMauro Carvalho Chehab reg_r(gspca_dev, reg->reg, 1); 1584*0c0d06caSMauro Carvalho Chehab reg->val = gspca_dev->usb_buf[0]; 1585*0c0d06caSMauro Carvalho Chehab return gspca_dev->usb_err; 1586*0c0d06caSMauro Carvalho Chehab case V4L2_CHIP_MATCH_I2C_ADDR: 1587*0c0d06caSMauro Carvalho Chehab if (reg->match.addr != sd->i2c_addr) 1588*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1589*0c0d06caSMauro Carvalho Chehab if (sd->sensor >= SENSOR_MT9V011 && 1590*0c0d06caSMauro Carvalho Chehab sd->sensor <= SENSOR_MT9M112) { 1591*0c0d06caSMauro Carvalho Chehab i2c_r2(gspca_dev, reg->reg, (u16 *) ®->val); 1592*0c0d06caSMauro Carvalho Chehab } else { 1593*0c0d06caSMauro Carvalho Chehab i2c_r1(gspca_dev, reg->reg, (u8 *) ®->val); 1594*0c0d06caSMauro Carvalho Chehab } 1595*0c0d06caSMauro Carvalho Chehab return gspca_dev->usb_err; 1596*0c0d06caSMauro Carvalho Chehab } 1597*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1598*0c0d06caSMauro Carvalho Chehab } 1599*0c0d06caSMauro Carvalho Chehab 1600*0c0d06caSMauro Carvalho Chehab static int sd_dbg_s_register(struct gspca_dev *gspca_dev, 1601*0c0d06caSMauro Carvalho Chehab struct v4l2_dbg_register *reg) 1602*0c0d06caSMauro Carvalho Chehab { 1603*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1604*0c0d06caSMauro Carvalho Chehab 1605*0c0d06caSMauro Carvalho Chehab switch (reg->match.type) { 1606*0c0d06caSMauro Carvalho Chehab case V4L2_CHIP_MATCH_HOST: 1607*0c0d06caSMauro Carvalho Chehab if (reg->match.addr != 0) 1608*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1609*0c0d06caSMauro Carvalho Chehab if (reg->reg < 0x1000 || reg->reg > 0x11ff) 1610*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1611*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, reg->reg, reg->val); 1612*0c0d06caSMauro Carvalho Chehab return gspca_dev->usb_err; 1613*0c0d06caSMauro Carvalho Chehab case V4L2_CHIP_MATCH_I2C_ADDR: 1614*0c0d06caSMauro Carvalho Chehab if (reg->match.addr != sd->i2c_addr) 1615*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1616*0c0d06caSMauro Carvalho Chehab if (sd->sensor >= SENSOR_MT9V011 && 1617*0c0d06caSMauro Carvalho Chehab sd->sensor <= SENSOR_MT9M112) { 1618*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, reg->reg, reg->val); 1619*0c0d06caSMauro Carvalho Chehab } else { 1620*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, reg->reg, reg->val); 1621*0c0d06caSMauro Carvalho Chehab } 1622*0c0d06caSMauro Carvalho Chehab return gspca_dev->usb_err; 1623*0c0d06caSMauro Carvalho Chehab } 1624*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1625*0c0d06caSMauro Carvalho Chehab } 1626*0c0d06caSMauro Carvalho Chehab #endif 1627*0c0d06caSMauro Carvalho Chehab 1628*0c0d06caSMauro Carvalho Chehab static int sd_chip_ident(struct gspca_dev *gspca_dev, 1629*0c0d06caSMauro Carvalho Chehab struct v4l2_dbg_chip_ident *chip) 1630*0c0d06caSMauro Carvalho Chehab { 1631*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1632*0c0d06caSMauro Carvalho Chehab 1633*0c0d06caSMauro Carvalho Chehab switch (chip->match.type) { 1634*0c0d06caSMauro Carvalho Chehab case V4L2_CHIP_MATCH_HOST: 1635*0c0d06caSMauro Carvalho Chehab if (chip->match.addr != 0) 1636*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1637*0c0d06caSMauro Carvalho Chehab chip->revision = 0; 1638*0c0d06caSMauro Carvalho Chehab chip->ident = V4L2_IDENT_SN9C20X; 1639*0c0d06caSMauro Carvalho Chehab return 0; 1640*0c0d06caSMauro Carvalho Chehab case V4L2_CHIP_MATCH_I2C_ADDR: 1641*0c0d06caSMauro Carvalho Chehab if (chip->match.addr != sd->i2c_addr) 1642*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1643*0c0d06caSMauro Carvalho Chehab chip->revision = 0; 1644*0c0d06caSMauro Carvalho Chehab chip->ident = i2c_ident[sd->sensor]; 1645*0c0d06caSMauro Carvalho Chehab return 0; 1646*0c0d06caSMauro Carvalho Chehab } 1647*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1648*0c0d06caSMauro Carvalho Chehab } 1649*0c0d06caSMauro Carvalho Chehab 1650*0c0d06caSMauro Carvalho Chehab static int sd_config(struct gspca_dev *gspca_dev, 1651*0c0d06caSMauro Carvalho Chehab const struct usb_device_id *id) 1652*0c0d06caSMauro Carvalho Chehab { 1653*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1654*0c0d06caSMauro Carvalho Chehab struct cam *cam; 1655*0c0d06caSMauro Carvalho Chehab 1656*0c0d06caSMauro Carvalho Chehab cam = &gspca_dev->cam; 1657*0c0d06caSMauro Carvalho Chehab cam->needs_full_bandwidth = 1; 1658*0c0d06caSMauro Carvalho Chehab 1659*0c0d06caSMauro Carvalho Chehab sd->sensor = id->driver_info >> 8; 1660*0c0d06caSMauro Carvalho Chehab sd->i2c_addr = id->driver_info; 1661*0c0d06caSMauro Carvalho Chehab sd->flags = id->driver_info >> 16; 1662*0c0d06caSMauro Carvalho Chehab sd->i2c_intf = 0x80; /* i2c 100 Kb/s */ 1663*0c0d06caSMauro Carvalho Chehab 1664*0c0d06caSMauro Carvalho Chehab switch (sd->sensor) { 1665*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9M112: 1666*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9M111: 1667*0c0d06caSMauro Carvalho Chehab case SENSOR_OV9650: 1668*0c0d06caSMauro Carvalho Chehab case SENSOR_SOI968: 1669*0c0d06caSMauro Carvalho Chehab cam->cam_mode = sxga_mode; 1670*0c0d06caSMauro Carvalho Chehab cam->nmodes = ARRAY_SIZE(sxga_mode); 1671*0c0d06caSMauro Carvalho Chehab break; 1672*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9M001: 1673*0c0d06caSMauro Carvalho Chehab cam->cam_mode = mono_mode; 1674*0c0d06caSMauro Carvalho Chehab cam->nmodes = ARRAY_SIZE(mono_mode); 1675*0c0d06caSMauro Carvalho Chehab break; 1676*0c0d06caSMauro Carvalho Chehab case SENSOR_HV7131R: 1677*0c0d06caSMauro Carvalho Chehab sd->i2c_intf = 0x81; /* i2c 400 Kb/s */ 1678*0c0d06caSMauro Carvalho Chehab /* fall thru */ 1679*0c0d06caSMauro Carvalho Chehab default: 1680*0c0d06caSMauro Carvalho Chehab cam->cam_mode = vga_mode; 1681*0c0d06caSMauro Carvalho Chehab cam->nmodes = ARRAY_SIZE(vga_mode); 1682*0c0d06caSMauro Carvalho Chehab break; 1683*0c0d06caSMauro Carvalho Chehab } 1684*0c0d06caSMauro Carvalho Chehab 1685*0c0d06caSMauro Carvalho Chehab sd->old_step = 0; 1686*0c0d06caSMauro Carvalho Chehab sd->older_step = 0; 1687*0c0d06caSMauro Carvalho Chehab sd->exposure_step = 16; 1688*0c0d06caSMauro Carvalho Chehab 1689*0c0d06caSMauro Carvalho Chehab INIT_WORK(&sd->work, qual_upd); 1690*0c0d06caSMauro Carvalho Chehab 1691*0c0d06caSMauro Carvalho Chehab return 0; 1692*0c0d06caSMauro Carvalho Chehab } 1693*0c0d06caSMauro Carvalho Chehab 1694*0c0d06caSMauro Carvalho Chehab static int sd_s_ctrl(struct v4l2_ctrl *ctrl) 1695*0c0d06caSMauro Carvalho Chehab { 1696*0c0d06caSMauro Carvalho Chehab struct gspca_dev *gspca_dev = 1697*0c0d06caSMauro Carvalho Chehab container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 1698*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *)gspca_dev; 1699*0c0d06caSMauro Carvalho Chehab 1700*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_err = 0; 1701*0c0d06caSMauro Carvalho Chehab 1702*0c0d06caSMauro Carvalho Chehab if (!gspca_dev->streaming) 1703*0c0d06caSMauro Carvalho Chehab return 0; 1704*0c0d06caSMauro Carvalho Chehab 1705*0c0d06caSMauro Carvalho Chehab switch (ctrl->id) { 1706*0c0d06caSMauro Carvalho Chehab /* color control cluster */ 1707*0c0d06caSMauro Carvalho Chehab case V4L2_CID_BRIGHTNESS: 1708*0c0d06caSMauro Carvalho Chehab set_cmatrix(gspca_dev, sd->brightness->val, 1709*0c0d06caSMauro Carvalho Chehab sd->contrast->val, sd->saturation->val, sd->hue->val); 1710*0c0d06caSMauro Carvalho Chehab break; 1711*0c0d06caSMauro Carvalho Chehab case V4L2_CID_GAMMA: 1712*0c0d06caSMauro Carvalho Chehab set_gamma(gspca_dev, ctrl->val); 1713*0c0d06caSMauro Carvalho Chehab break; 1714*0c0d06caSMauro Carvalho Chehab /* blue/red balance cluster */ 1715*0c0d06caSMauro Carvalho Chehab case V4L2_CID_BLUE_BALANCE: 1716*0c0d06caSMauro Carvalho Chehab set_redblue(gspca_dev, sd->blue->val, sd->red->val); 1717*0c0d06caSMauro Carvalho Chehab break; 1718*0c0d06caSMauro Carvalho Chehab /* h/vflip cluster */ 1719*0c0d06caSMauro Carvalho Chehab case V4L2_CID_HFLIP: 1720*0c0d06caSMauro Carvalho Chehab set_hvflip(gspca_dev, sd->hflip->val, sd->vflip->val); 1721*0c0d06caSMauro Carvalho Chehab break; 1722*0c0d06caSMauro Carvalho Chehab /* standalone exposure control */ 1723*0c0d06caSMauro Carvalho Chehab case V4L2_CID_EXPOSURE: 1724*0c0d06caSMauro Carvalho Chehab set_exposure(gspca_dev, ctrl->val); 1725*0c0d06caSMauro Carvalho Chehab break; 1726*0c0d06caSMauro Carvalho Chehab /* standalone gain control */ 1727*0c0d06caSMauro Carvalho Chehab case V4L2_CID_GAIN: 1728*0c0d06caSMauro Carvalho Chehab set_gain(gspca_dev, ctrl->val); 1729*0c0d06caSMauro Carvalho Chehab break; 1730*0c0d06caSMauro Carvalho Chehab /* autogain + exposure or gain control cluster */ 1731*0c0d06caSMauro Carvalho Chehab case V4L2_CID_AUTOGAIN: 1732*0c0d06caSMauro Carvalho Chehab if (sd->sensor == SENSOR_SOI968) 1733*0c0d06caSMauro Carvalho Chehab set_gain(gspca_dev, sd->gain->val); 1734*0c0d06caSMauro Carvalho Chehab else 1735*0c0d06caSMauro Carvalho Chehab set_exposure(gspca_dev, sd->exposure->val); 1736*0c0d06caSMauro Carvalho Chehab break; 1737*0c0d06caSMauro Carvalho Chehab case V4L2_CID_JPEG_COMPRESSION_QUALITY: 1738*0c0d06caSMauro Carvalho Chehab set_quality(gspca_dev, ctrl->val); 1739*0c0d06caSMauro Carvalho Chehab break; 1740*0c0d06caSMauro Carvalho Chehab } 1741*0c0d06caSMauro Carvalho Chehab return gspca_dev->usb_err; 1742*0c0d06caSMauro Carvalho Chehab } 1743*0c0d06caSMauro Carvalho Chehab 1744*0c0d06caSMauro Carvalho Chehab static const struct v4l2_ctrl_ops sd_ctrl_ops = { 1745*0c0d06caSMauro Carvalho Chehab .s_ctrl = sd_s_ctrl, 1746*0c0d06caSMauro Carvalho Chehab }; 1747*0c0d06caSMauro Carvalho Chehab 1748*0c0d06caSMauro Carvalho Chehab static int sd_init_controls(struct gspca_dev *gspca_dev) 1749*0c0d06caSMauro Carvalho Chehab { 1750*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1751*0c0d06caSMauro Carvalho Chehab struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 1752*0c0d06caSMauro Carvalho Chehab 1753*0c0d06caSMauro Carvalho Chehab gspca_dev->vdev.ctrl_handler = hdl; 1754*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_handler_init(hdl, 13); 1755*0c0d06caSMauro Carvalho Chehab 1756*0c0d06caSMauro Carvalho Chehab sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1757*0c0d06caSMauro Carvalho Chehab V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); 1758*0c0d06caSMauro Carvalho Chehab sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1759*0c0d06caSMauro Carvalho Chehab V4L2_CID_CONTRAST, 0, 255, 1, 127); 1760*0c0d06caSMauro Carvalho Chehab sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1761*0c0d06caSMauro Carvalho Chehab V4L2_CID_SATURATION, 0, 255, 1, 127); 1762*0c0d06caSMauro Carvalho Chehab sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1763*0c0d06caSMauro Carvalho Chehab V4L2_CID_HUE, -180, 180, 1, 0); 1764*0c0d06caSMauro Carvalho Chehab 1765*0c0d06caSMauro Carvalho Chehab sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1766*0c0d06caSMauro Carvalho Chehab V4L2_CID_GAMMA, 0, 255, 1, 0x10); 1767*0c0d06caSMauro Carvalho Chehab 1768*0c0d06caSMauro Carvalho Chehab sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1769*0c0d06caSMauro Carvalho Chehab V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0x28); 1770*0c0d06caSMauro Carvalho Chehab sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1771*0c0d06caSMauro Carvalho Chehab V4L2_CID_RED_BALANCE, 0, 127, 1, 0x28); 1772*0c0d06caSMauro Carvalho Chehab 1773*0c0d06caSMauro Carvalho Chehab if (sd->sensor != SENSOR_OV9655 && sd->sensor != SENSOR_SOI968 && 1774*0c0d06caSMauro Carvalho Chehab sd->sensor != SENSOR_OV7670 && sd->sensor != SENSOR_MT9M001 && 1775*0c0d06caSMauro Carvalho Chehab sd->sensor != SENSOR_MT9VPRB) { 1776*0c0d06caSMauro Carvalho Chehab sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1777*0c0d06caSMauro Carvalho Chehab V4L2_CID_HFLIP, 0, 1, 1, 0); 1778*0c0d06caSMauro Carvalho Chehab sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1779*0c0d06caSMauro Carvalho Chehab V4L2_CID_VFLIP, 0, 1, 1, 0); 1780*0c0d06caSMauro Carvalho Chehab } 1781*0c0d06caSMauro Carvalho Chehab 1782*0c0d06caSMauro Carvalho Chehab if (sd->sensor != SENSOR_SOI968 && sd->sensor != SENSOR_MT9VPRB && 1783*0c0d06caSMauro Carvalho Chehab sd->sensor != SENSOR_MT9M112 && sd->sensor != SENSOR_MT9M111 && 1784*0c0d06caSMauro Carvalho Chehab sd->sensor != SENSOR_MT9V111) 1785*0c0d06caSMauro Carvalho Chehab sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1786*0c0d06caSMauro Carvalho Chehab V4L2_CID_EXPOSURE, 0, 0x1780, 1, 0x33); 1787*0c0d06caSMauro Carvalho Chehab 1788*0c0d06caSMauro Carvalho Chehab if (sd->sensor != SENSOR_MT9VPRB && sd->sensor != SENSOR_MT9M112 && 1789*0c0d06caSMauro Carvalho Chehab sd->sensor != SENSOR_MT9M111 && sd->sensor != SENSOR_MT9V111) { 1790*0c0d06caSMauro Carvalho Chehab sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1791*0c0d06caSMauro Carvalho Chehab V4L2_CID_GAIN, 0, 28, 1, 0); 1792*0c0d06caSMauro Carvalho Chehab sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1793*0c0d06caSMauro Carvalho Chehab V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 1794*0c0d06caSMauro Carvalho Chehab } 1795*0c0d06caSMauro Carvalho Chehab 1796*0c0d06caSMauro Carvalho Chehab sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1797*0c0d06caSMauro Carvalho Chehab V4L2_CID_JPEG_COMPRESSION_QUALITY, 50, 90, 1, 80); 1798*0c0d06caSMauro Carvalho Chehab if (hdl->error) { 1799*0c0d06caSMauro Carvalho Chehab pr_err("Could not initialize controls\n"); 1800*0c0d06caSMauro Carvalho Chehab return hdl->error; 1801*0c0d06caSMauro Carvalho Chehab } 1802*0c0d06caSMauro Carvalho Chehab 1803*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_cluster(4, &sd->brightness); 1804*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_cluster(2, &sd->blue); 1805*0c0d06caSMauro Carvalho Chehab if (sd->hflip) 1806*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_cluster(2, &sd->hflip); 1807*0c0d06caSMauro Carvalho Chehab if (sd->autogain) { 1808*0c0d06caSMauro Carvalho Chehab if (sd->sensor == SENSOR_SOI968) 1809*0c0d06caSMauro Carvalho Chehab /* this sensor doesn't have the exposure control and 1810*0c0d06caSMauro Carvalho Chehab autogain is clustered with gain instead. This works 1811*0c0d06caSMauro Carvalho Chehab because sd->exposure == NULL. */ 1812*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_auto_cluster(3, &sd->autogain, 0, false); 1813*0c0d06caSMauro Carvalho Chehab else 1814*0c0d06caSMauro Carvalho Chehab /* Otherwise autogain is clustered with exposure. */ 1815*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false); 1816*0c0d06caSMauro Carvalho Chehab } 1817*0c0d06caSMauro Carvalho Chehab return 0; 1818*0c0d06caSMauro Carvalho Chehab } 1819*0c0d06caSMauro Carvalho Chehab 1820*0c0d06caSMauro Carvalho Chehab static int sd_init(struct gspca_dev *gspca_dev) 1821*0c0d06caSMauro Carvalho Chehab { 1822*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1823*0c0d06caSMauro Carvalho Chehab int i; 1824*0c0d06caSMauro Carvalho Chehab u8 value; 1825*0c0d06caSMauro Carvalho Chehab u8 i2c_init[9] = 1826*0c0d06caSMauro Carvalho Chehab {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}; 1827*0c0d06caSMauro Carvalho Chehab 1828*0c0d06caSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(bridge_init); i++) { 1829*0c0d06caSMauro Carvalho Chehab value = bridge_init[i][1]; 1830*0c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, bridge_init[i][0], &value, 1); 1831*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) { 1832*0c0d06caSMauro Carvalho Chehab pr_err("Device initialization failed\n"); 1833*0c0d06caSMauro Carvalho Chehab return gspca_dev->usb_err; 1834*0c0d06caSMauro Carvalho Chehab } 1835*0c0d06caSMauro Carvalho Chehab } 1836*0c0d06caSMauro Carvalho Chehab 1837*0c0d06caSMauro Carvalho Chehab if (sd->flags & LED_REVERSE) 1838*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x1006, 0x00); 1839*0c0d06caSMauro Carvalho Chehab else 1840*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x1006, 0x20); 1841*0c0d06caSMauro Carvalho Chehab 1842*0c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x10c0, i2c_init, 9); 1843*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) { 1844*0c0d06caSMauro Carvalho Chehab pr_err("Device initialization failed\n"); 1845*0c0d06caSMauro Carvalho Chehab return gspca_dev->usb_err; 1846*0c0d06caSMauro Carvalho Chehab } 1847*0c0d06caSMauro Carvalho Chehab 1848*0c0d06caSMauro Carvalho Chehab switch (sd->sensor) { 1849*0c0d06caSMauro Carvalho Chehab case SENSOR_OV9650: 1850*0c0d06caSMauro Carvalho Chehab ov9650_init_sensor(gspca_dev); 1851*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1852*0c0d06caSMauro Carvalho Chehab break; 1853*0c0d06caSMauro Carvalho Chehab pr_info("OV9650 sensor detected\n"); 1854*0c0d06caSMauro Carvalho Chehab break; 1855*0c0d06caSMauro Carvalho Chehab case SENSOR_OV9655: 1856*0c0d06caSMauro Carvalho Chehab ov9655_init_sensor(gspca_dev); 1857*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1858*0c0d06caSMauro Carvalho Chehab break; 1859*0c0d06caSMauro Carvalho Chehab pr_info("OV9655 sensor detected\n"); 1860*0c0d06caSMauro Carvalho Chehab break; 1861*0c0d06caSMauro Carvalho Chehab case SENSOR_SOI968: 1862*0c0d06caSMauro Carvalho Chehab soi968_init_sensor(gspca_dev); 1863*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1864*0c0d06caSMauro Carvalho Chehab break; 1865*0c0d06caSMauro Carvalho Chehab pr_info("SOI968 sensor detected\n"); 1866*0c0d06caSMauro Carvalho Chehab break; 1867*0c0d06caSMauro Carvalho Chehab case SENSOR_OV7660: 1868*0c0d06caSMauro Carvalho Chehab ov7660_init_sensor(gspca_dev); 1869*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1870*0c0d06caSMauro Carvalho Chehab break; 1871*0c0d06caSMauro Carvalho Chehab pr_info("OV7660 sensor detected\n"); 1872*0c0d06caSMauro Carvalho Chehab break; 1873*0c0d06caSMauro Carvalho Chehab case SENSOR_OV7670: 1874*0c0d06caSMauro Carvalho Chehab ov7670_init_sensor(gspca_dev); 1875*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1876*0c0d06caSMauro Carvalho Chehab break; 1877*0c0d06caSMauro Carvalho Chehab pr_info("OV7670 sensor detected\n"); 1878*0c0d06caSMauro Carvalho Chehab break; 1879*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9VPRB: 1880*0c0d06caSMauro Carvalho Chehab mt9v_init_sensor(gspca_dev); 1881*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1882*0c0d06caSMauro Carvalho Chehab break; 1883*0c0d06caSMauro Carvalho Chehab pr_info("MT9VPRB sensor detected\n"); 1884*0c0d06caSMauro Carvalho Chehab break; 1885*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9M111: 1886*0c0d06caSMauro Carvalho Chehab mt9m111_init_sensor(gspca_dev); 1887*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1888*0c0d06caSMauro Carvalho Chehab break; 1889*0c0d06caSMauro Carvalho Chehab pr_info("MT9M111 sensor detected\n"); 1890*0c0d06caSMauro Carvalho Chehab break; 1891*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9M112: 1892*0c0d06caSMauro Carvalho Chehab mt9m112_init_sensor(gspca_dev); 1893*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1894*0c0d06caSMauro Carvalho Chehab break; 1895*0c0d06caSMauro Carvalho Chehab pr_info("MT9M112 sensor detected\n"); 1896*0c0d06caSMauro Carvalho Chehab break; 1897*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9M001: 1898*0c0d06caSMauro Carvalho Chehab mt9m001_init_sensor(gspca_dev); 1899*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1900*0c0d06caSMauro Carvalho Chehab break; 1901*0c0d06caSMauro Carvalho Chehab break; 1902*0c0d06caSMauro Carvalho Chehab case SENSOR_HV7131R: 1903*0c0d06caSMauro Carvalho Chehab hv7131r_init_sensor(gspca_dev); 1904*0c0d06caSMauro Carvalho Chehab if (gspca_dev->usb_err < 0) 1905*0c0d06caSMauro Carvalho Chehab break; 1906*0c0d06caSMauro Carvalho Chehab pr_info("HV7131R sensor detected\n"); 1907*0c0d06caSMauro Carvalho Chehab break; 1908*0c0d06caSMauro Carvalho Chehab default: 1909*0c0d06caSMauro Carvalho Chehab pr_err("Unsupported sensor\n"); 1910*0c0d06caSMauro Carvalho Chehab gspca_dev->usb_err = -ENODEV; 1911*0c0d06caSMauro Carvalho Chehab } 1912*0c0d06caSMauro Carvalho Chehab return gspca_dev->usb_err; 1913*0c0d06caSMauro Carvalho Chehab } 1914*0c0d06caSMauro Carvalho Chehab 1915*0c0d06caSMauro Carvalho Chehab static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) 1916*0c0d06caSMauro Carvalho Chehab { 1917*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 1918*0c0d06caSMauro Carvalho Chehab u8 value; 1919*0c0d06caSMauro Carvalho Chehab 1920*0c0d06caSMauro Carvalho Chehab switch (sd->sensor) { 1921*0c0d06caSMauro Carvalho Chehab case SENSOR_SOI968: 1922*0c0d06caSMauro Carvalho Chehab if (mode & MODE_SXGA) { 1923*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x17, 0x1d); 1924*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x18, 0xbd); 1925*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x19, 0x01); 1926*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x1a, 0x81); 1927*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x12, 0x00); 1928*0c0d06caSMauro Carvalho Chehab sd->hstart = 140; 1929*0c0d06caSMauro Carvalho Chehab sd->vstart = 19; 1930*0c0d06caSMauro Carvalho Chehab } else { 1931*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x17, 0x13); 1932*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x18, 0x63); 1933*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x19, 0x01); 1934*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x1a, 0x79); 1935*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x12, 0x40); 1936*0c0d06caSMauro Carvalho Chehab sd->hstart = 60; 1937*0c0d06caSMauro Carvalho Chehab sd->vstart = 11; 1938*0c0d06caSMauro Carvalho Chehab } 1939*0c0d06caSMauro Carvalho Chehab break; 1940*0c0d06caSMauro Carvalho Chehab case SENSOR_OV9650: 1941*0c0d06caSMauro Carvalho Chehab if (mode & MODE_SXGA) { 1942*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x17, 0x1b); 1943*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x18, 0xbc); 1944*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x19, 0x01); 1945*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x1a, 0x82); 1946*0c0d06caSMauro Carvalho Chehab i2c_r1(gspca_dev, 0x12, &value); 1947*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x12, value & 0x07); 1948*0c0d06caSMauro Carvalho Chehab } else { 1949*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x17, 0x24); 1950*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x18, 0xc5); 1951*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x19, 0x00); 1952*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x1a, 0x3c); 1953*0c0d06caSMauro Carvalho Chehab i2c_r1(gspca_dev, 0x12, &value); 1954*0c0d06caSMauro Carvalho Chehab i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40); 1955*0c0d06caSMauro Carvalho Chehab } 1956*0c0d06caSMauro Carvalho Chehab break; 1957*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9M112: 1958*0c0d06caSMauro Carvalho Chehab case SENSOR_MT9M111: 1959*0c0d06caSMauro Carvalho Chehab if (mode & MODE_SXGA) { 1960*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, 0xf0, 0x0002); 1961*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, 0xc8, 0x970b); 1962*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, 0xf0, 0x0000); 1963*0c0d06caSMauro Carvalho Chehab } else { 1964*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, 0xf0, 0x0002); 1965*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, 0xc8, 0x8000); 1966*0c0d06caSMauro Carvalho Chehab i2c_w2(gspca_dev, 0xf0, 0x0000); 1967*0c0d06caSMauro Carvalho Chehab } 1968*0c0d06caSMauro Carvalho Chehab break; 1969*0c0d06caSMauro Carvalho Chehab } 1970*0c0d06caSMauro Carvalho Chehab } 1971*0c0d06caSMauro Carvalho Chehab 1972*0c0d06caSMauro Carvalho Chehab static int sd_isoc_init(struct gspca_dev *gspca_dev) 1973*0c0d06caSMauro Carvalho Chehab { 1974*0c0d06caSMauro Carvalho Chehab struct usb_interface *intf; 1975*0c0d06caSMauro Carvalho Chehab u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv; 1976*0c0d06caSMauro Carvalho Chehab 1977*0c0d06caSMauro Carvalho Chehab /* 1978*0c0d06caSMauro Carvalho Chehab * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth 1979*0c0d06caSMauro Carvalho Chehab * than our regular bandwidth calculations reserve, so we force the 1980*0c0d06caSMauro Carvalho Chehab * use of a specific altsetting when using the SN9C20X_I420 fmt. 1981*0c0d06caSMauro Carvalho Chehab */ 1982*0c0d06caSMauro Carvalho Chehab if (!(flags & (MODE_RAW | MODE_JPEG))) { 1983*0c0d06caSMauro Carvalho Chehab intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); 1984*0c0d06caSMauro Carvalho Chehab 1985*0c0d06caSMauro Carvalho Chehab if (intf->num_altsetting != 9) { 1986*0c0d06caSMauro Carvalho Chehab pr_warn("sn9c20x camera with unknown number of alt " 1987*0c0d06caSMauro Carvalho Chehab "settings (%d), please report!\n", 1988*0c0d06caSMauro Carvalho Chehab intf->num_altsetting); 1989*0c0d06caSMauro Carvalho Chehab gspca_dev->alt = intf->num_altsetting; 1990*0c0d06caSMauro Carvalho Chehab return 0; 1991*0c0d06caSMauro Carvalho Chehab } 1992*0c0d06caSMauro Carvalho Chehab 1993*0c0d06caSMauro Carvalho Chehab switch (gspca_dev->width) { 1994*0c0d06caSMauro Carvalho Chehab case 160: /* 160x120 */ 1995*0c0d06caSMauro Carvalho Chehab gspca_dev->alt = 2; 1996*0c0d06caSMauro Carvalho Chehab break; 1997*0c0d06caSMauro Carvalho Chehab case 320: /* 320x240 */ 1998*0c0d06caSMauro Carvalho Chehab gspca_dev->alt = 6; 1999*0c0d06caSMauro Carvalho Chehab break; 2000*0c0d06caSMauro Carvalho Chehab default: /* >= 640x480 */ 2001*0c0d06caSMauro Carvalho Chehab gspca_dev->alt = 9; 2002*0c0d06caSMauro Carvalho Chehab break; 2003*0c0d06caSMauro Carvalho Chehab } 2004*0c0d06caSMauro Carvalho Chehab } 2005*0c0d06caSMauro Carvalho Chehab 2006*0c0d06caSMauro Carvalho Chehab return 0; 2007*0c0d06caSMauro Carvalho Chehab } 2008*0c0d06caSMauro Carvalho Chehab 2009*0c0d06caSMauro Carvalho Chehab #define HW_WIN(mode, hstart, vstart) \ 2010*0c0d06caSMauro Carvalho Chehab ((const u8 []){hstart, 0, vstart, 0, \ 2011*0c0d06caSMauro Carvalho Chehab (mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \ 2012*0c0d06caSMauro Carvalho Chehab (mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)}) 2013*0c0d06caSMauro Carvalho Chehab 2014*0c0d06caSMauro Carvalho Chehab #define CLR_WIN(width, height) \ 2015*0c0d06caSMauro Carvalho Chehab ((const u8 [])\ 2016*0c0d06caSMauro Carvalho Chehab {0, width >> 2, 0, height >> 1,\ 2017*0c0d06caSMauro Carvalho Chehab ((width >> 10) & 0x01) | ((height >> 8) & 0x6)}) 2018*0c0d06caSMauro Carvalho Chehab 2019*0c0d06caSMauro Carvalho Chehab static int sd_start(struct gspca_dev *gspca_dev) 2020*0c0d06caSMauro Carvalho Chehab { 2021*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 2022*0c0d06caSMauro Carvalho Chehab int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; 2023*0c0d06caSMauro Carvalho Chehab int width = gspca_dev->width; 2024*0c0d06caSMauro Carvalho Chehab int height = gspca_dev->height; 2025*0c0d06caSMauro Carvalho Chehab u8 fmt, scale = 0; 2026*0c0d06caSMauro Carvalho Chehab 2027*0c0d06caSMauro Carvalho Chehab jpeg_define(sd->jpeg_hdr, height, width, 2028*0c0d06caSMauro Carvalho Chehab 0x21); 2029*0c0d06caSMauro Carvalho Chehab jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual)); 2030*0c0d06caSMauro Carvalho Chehab 2031*0c0d06caSMauro Carvalho Chehab if (mode & MODE_RAW) 2032*0c0d06caSMauro Carvalho Chehab fmt = 0x2d; 2033*0c0d06caSMauro Carvalho Chehab else if (mode & MODE_JPEG) 2034*0c0d06caSMauro Carvalho Chehab fmt = 0x24; 2035*0c0d06caSMauro Carvalho Chehab else 2036*0c0d06caSMauro Carvalho Chehab fmt = 0x2f; /* YUV 420 */ 2037*0c0d06caSMauro Carvalho Chehab sd->fmt = fmt; 2038*0c0d06caSMauro Carvalho Chehab 2039*0c0d06caSMauro Carvalho Chehab switch (mode & SCALE_MASK) { 2040*0c0d06caSMauro Carvalho Chehab case SCALE_1280x1024: 2041*0c0d06caSMauro Carvalho Chehab scale = 0xc0; 2042*0c0d06caSMauro Carvalho Chehab pr_info("Set 1280x1024\n"); 2043*0c0d06caSMauro Carvalho Chehab break; 2044*0c0d06caSMauro Carvalho Chehab case SCALE_640x480: 2045*0c0d06caSMauro Carvalho Chehab scale = 0x80; 2046*0c0d06caSMauro Carvalho Chehab pr_info("Set 640x480\n"); 2047*0c0d06caSMauro Carvalho Chehab break; 2048*0c0d06caSMauro Carvalho Chehab case SCALE_320x240: 2049*0c0d06caSMauro Carvalho Chehab scale = 0x90; 2050*0c0d06caSMauro Carvalho Chehab pr_info("Set 320x240\n"); 2051*0c0d06caSMauro Carvalho Chehab break; 2052*0c0d06caSMauro Carvalho Chehab case SCALE_160x120: 2053*0c0d06caSMauro Carvalho Chehab scale = 0xa0; 2054*0c0d06caSMauro Carvalho Chehab pr_info("Set 160x120\n"); 2055*0c0d06caSMauro Carvalho Chehab break; 2056*0c0d06caSMauro Carvalho Chehab } 2057*0c0d06caSMauro Carvalho Chehab 2058*0c0d06caSMauro Carvalho Chehab configure_sensor_output(gspca_dev, mode); 2059*0c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); 2060*0c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); 2061*0c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5); 2062*0c0d06caSMauro Carvalho Chehab reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6); 2063*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x1189, scale); 2064*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x10e0, fmt); 2065*0c0d06caSMauro Carvalho Chehab 2066*0c0d06caSMauro Carvalho Chehab set_cmatrix(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness), 2067*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_g_ctrl(sd->contrast), 2068*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_g_ctrl(sd->saturation), 2069*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_g_ctrl(sd->hue)); 2070*0c0d06caSMauro Carvalho Chehab set_gamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma)); 2071*0c0d06caSMauro Carvalho Chehab set_redblue(gspca_dev, v4l2_ctrl_g_ctrl(sd->blue), 2072*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_g_ctrl(sd->red)); 2073*0c0d06caSMauro Carvalho Chehab if (sd->gain) 2074*0c0d06caSMauro Carvalho Chehab set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain)); 2075*0c0d06caSMauro Carvalho Chehab if (sd->exposure) 2076*0c0d06caSMauro Carvalho Chehab set_exposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure)); 2077*0c0d06caSMauro Carvalho Chehab if (sd->hflip) 2078*0c0d06caSMauro Carvalho Chehab set_hvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 2079*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_g_ctrl(sd->vflip)); 2080*0c0d06caSMauro Carvalho Chehab 2081*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x1007, 0x20); 2082*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x1061, 0x03); 2083*0c0d06caSMauro Carvalho Chehab 2084*0c0d06caSMauro Carvalho Chehab /* if JPEG, prepare the compression quality update */ 2085*0c0d06caSMauro Carvalho Chehab if (mode & MODE_JPEG) { 2086*0c0d06caSMauro Carvalho Chehab sd->pktsz = sd->npkt = 0; 2087*0c0d06caSMauro Carvalho Chehab sd->nchg = 0; 2088*0c0d06caSMauro Carvalho Chehab sd->work_thread = 2089*0c0d06caSMauro Carvalho Chehab create_singlethread_workqueue(KBUILD_MODNAME); 2090*0c0d06caSMauro Carvalho Chehab } 2091*0c0d06caSMauro Carvalho Chehab 2092*0c0d06caSMauro Carvalho Chehab return gspca_dev->usb_err; 2093*0c0d06caSMauro Carvalho Chehab } 2094*0c0d06caSMauro Carvalho Chehab 2095*0c0d06caSMauro Carvalho Chehab static void sd_stopN(struct gspca_dev *gspca_dev) 2096*0c0d06caSMauro Carvalho Chehab { 2097*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x1007, 0x00); 2098*0c0d06caSMauro Carvalho Chehab reg_w1(gspca_dev, 0x1061, 0x01); 2099*0c0d06caSMauro Carvalho Chehab } 2100*0c0d06caSMauro Carvalho Chehab 2101*0c0d06caSMauro Carvalho Chehab /* called on streamoff with alt==0 and on disconnect */ 2102*0c0d06caSMauro Carvalho Chehab /* the usb_lock is held at entry - restore on exit */ 2103*0c0d06caSMauro Carvalho Chehab static void sd_stop0(struct gspca_dev *gspca_dev) 2104*0c0d06caSMauro Carvalho Chehab { 2105*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 2106*0c0d06caSMauro Carvalho Chehab 2107*0c0d06caSMauro Carvalho Chehab if (sd->work_thread != NULL) { 2108*0c0d06caSMauro Carvalho Chehab mutex_unlock(&gspca_dev->usb_lock); 2109*0c0d06caSMauro Carvalho Chehab destroy_workqueue(sd->work_thread); 2110*0c0d06caSMauro Carvalho Chehab mutex_lock(&gspca_dev->usb_lock); 2111*0c0d06caSMauro Carvalho Chehab sd->work_thread = NULL; 2112*0c0d06caSMauro Carvalho Chehab } 2113*0c0d06caSMauro Carvalho Chehab } 2114*0c0d06caSMauro Carvalho Chehab 2115*0c0d06caSMauro Carvalho Chehab static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) 2116*0c0d06caSMauro Carvalho Chehab { 2117*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 2118*0c0d06caSMauro Carvalho Chehab s32 cur_exp = v4l2_ctrl_g_ctrl(sd->exposure); 2119*0c0d06caSMauro Carvalho Chehab s32 max = sd->exposure->maximum - sd->exposure_step; 2120*0c0d06caSMauro Carvalho Chehab s32 min = sd->exposure->minimum + sd->exposure_step; 2121*0c0d06caSMauro Carvalho Chehab s16 new_exp; 2122*0c0d06caSMauro Carvalho Chehab 2123*0c0d06caSMauro Carvalho Chehab /* 2124*0c0d06caSMauro Carvalho Chehab * some hardcoded values are present 2125*0c0d06caSMauro Carvalho Chehab * like those for maximal/minimal exposure 2126*0c0d06caSMauro Carvalho Chehab * and exposure steps 2127*0c0d06caSMauro Carvalho Chehab */ 2128*0c0d06caSMauro Carvalho Chehab if (avg_lum < MIN_AVG_LUM) { 2129*0c0d06caSMauro Carvalho Chehab if (cur_exp > max) 2130*0c0d06caSMauro Carvalho Chehab return; 2131*0c0d06caSMauro Carvalho Chehab 2132*0c0d06caSMauro Carvalho Chehab new_exp = cur_exp + sd->exposure_step; 2133*0c0d06caSMauro Carvalho Chehab if (new_exp > max) 2134*0c0d06caSMauro Carvalho Chehab new_exp = max; 2135*0c0d06caSMauro Carvalho Chehab if (new_exp < min) 2136*0c0d06caSMauro Carvalho Chehab new_exp = min; 2137*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_s_ctrl(sd->exposure, new_exp); 2138*0c0d06caSMauro Carvalho Chehab 2139*0c0d06caSMauro Carvalho Chehab sd->older_step = sd->old_step; 2140*0c0d06caSMauro Carvalho Chehab sd->old_step = 1; 2141*0c0d06caSMauro Carvalho Chehab 2142*0c0d06caSMauro Carvalho Chehab if (sd->old_step ^ sd->older_step) 2143*0c0d06caSMauro Carvalho Chehab sd->exposure_step /= 2; 2144*0c0d06caSMauro Carvalho Chehab else 2145*0c0d06caSMauro Carvalho Chehab sd->exposure_step += 2; 2146*0c0d06caSMauro Carvalho Chehab } 2147*0c0d06caSMauro Carvalho Chehab if (avg_lum > MAX_AVG_LUM) { 2148*0c0d06caSMauro Carvalho Chehab if (cur_exp < min) 2149*0c0d06caSMauro Carvalho Chehab return; 2150*0c0d06caSMauro Carvalho Chehab new_exp = cur_exp - sd->exposure_step; 2151*0c0d06caSMauro Carvalho Chehab if (new_exp > max) 2152*0c0d06caSMauro Carvalho Chehab new_exp = max; 2153*0c0d06caSMauro Carvalho Chehab if (new_exp < min) 2154*0c0d06caSMauro Carvalho Chehab new_exp = min; 2155*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_s_ctrl(sd->exposure, new_exp); 2156*0c0d06caSMauro Carvalho Chehab sd->older_step = sd->old_step; 2157*0c0d06caSMauro Carvalho Chehab sd->old_step = 0; 2158*0c0d06caSMauro Carvalho Chehab 2159*0c0d06caSMauro Carvalho Chehab if (sd->old_step ^ sd->older_step) 2160*0c0d06caSMauro Carvalho Chehab sd->exposure_step /= 2; 2161*0c0d06caSMauro Carvalho Chehab else 2162*0c0d06caSMauro Carvalho Chehab sd->exposure_step += 2; 2163*0c0d06caSMauro Carvalho Chehab } 2164*0c0d06caSMauro Carvalho Chehab } 2165*0c0d06caSMauro Carvalho Chehab 2166*0c0d06caSMauro Carvalho Chehab static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) 2167*0c0d06caSMauro Carvalho Chehab { 2168*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 2169*0c0d06caSMauro Carvalho Chehab s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain); 2170*0c0d06caSMauro Carvalho Chehab 2171*0c0d06caSMauro Carvalho Chehab if (avg_lum < MIN_AVG_LUM && cur_gain < sd->gain->maximum) 2172*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_s_ctrl(sd->gain, cur_gain + 1); 2173*0c0d06caSMauro Carvalho Chehab if (avg_lum > MAX_AVG_LUM && cur_gain > sd->gain->minimum) 2174*0c0d06caSMauro Carvalho Chehab v4l2_ctrl_s_ctrl(sd->gain, cur_gain - 1); 2175*0c0d06caSMauro Carvalho Chehab } 2176*0c0d06caSMauro Carvalho Chehab 2177*0c0d06caSMauro Carvalho Chehab static void sd_dqcallback(struct gspca_dev *gspca_dev) 2178*0c0d06caSMauro Carvalho Chehab { 2179*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 2180*0c0d06caSMauro Carvalho Chehab int avg_lum; 2181*0c0d06caSMauro Carvalho Chehab 2182*0c0d06caSMauro Carvalho Chehab if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain)) 2183*0c0d06caSMauro Carvalho Chehab return; 2184*0c0d06caSMauro Carvalho Chehab 2185*0c0d06caSMauro Carvalho Chehab avg_lum = atomic_read(&sd->avg_lum); 2186*0c0d06caSMauro Carvalho Chehab if (sd->sensor == SENSOR_SOI968) 2187*0c0d06caSMauro Carvalho Chehab do_autogain(gspca_dev, avg_lum); 2188*0c0d06caSMauro Carvalho Chehab else 2189*0c0d06caSMauro Carvalho Chehab do_autoexposure(gspca_dev, avg_lum); 2190*0c0d06caSMauro Carvalho Chehab } 2191*0c0d06caSMauro Carvalho Chehab 2192*0c0d06caSMauro Carvalho Chehab /* JPEG quality update */ 2193*0c0d06caSMauro Carvalho Chehab /* This function is executed from a work queue. */ 2194*0c0d06caSMauro Carvalho Chehab static void qual_upd(struct work_struct *work) 2195*0c0d06caSMauro Carvalho Chehab { 2196*0c0d06caSMauro Carvalho Chehab struct sd *sd = container_of(work, struct sd, work); 2197*0c0d06caSMauro Carvalho Chehab struct gspca_dev *gspca_dev = &sd->gspca_dev; 2198*0c0d06caSMauro Carvalho Chehab s32 qual = v4l2_ctrl_g_ctrl(sd->jpegqual); 2199*0c0d06caSMauro Carvalho Chehab 2200*0c0d06caSMauro Carvalho Chehab mutex_lock(&gspca_dev->usb_lock); 2201*0c0d06caSMauro Carvalho Chehab PDEBUG(D_STREAM, "qual_upd %d%%", qual); 2202*0c0d06caSMauro Carvalho Chehab set_quality(gspca_dev, qual); 2203*0c0d06caSMauro Carvalho Chehab mutex_unlock(&gspca_dev->usb_lock); 2204*0c0d06caSMauro Carvalho Chehab } 2205*0c0d06caSMauro Carvalho Chehab 2206*0c0d06caSMauro Carvalho Chehab #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) 2207*0c0d06caSMauro Carvalho Chehab static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, 2208*0c0d06caSMauro Carvalho Chehab u8 *data, /* interrupt packet */ 2209*0c0d06caSMauro Carvalho Chehab int len) /* interrupt packet length */ 2210*0c0d06caSMauro Carvalho Chehab { 2211*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 2212*0c0d06caSMauro Carvalho Chehab 2213*0c0d06caSMauro Carvalho Chehab if (!(sd->flags & HAS_NO_BUTTON) && len == 1) { 2214*0c0d06caSMauro Carvalho Chehab input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); 2215*0c0d06caSMauro Carvalho Chehab input_sync(gspca_dev->input_dev); 2216*0c0d06caSMauro Carvalho Chehab input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); 2217*0c0d06caSMauro Carvalho Chehab input_sync(gspca_dev->input_dev); 2218*0c0d06caSMauro Carvalho Chehab return 0; 2219*0c0d06caSMauro Carvalho Chehab } 2220*0c0d06caSMauro Carvalho Chehab return -EINVAL; 2221*0c0d06caSMauro Carvalho Chehab } 2222*0c0d06caSMauro Carvalho Chehab #endif 2223*0c0d06caSMauro Carvalho Chehab 2224*0c0d06caSMauro Carvalho Chehab /* check the JPEG compression */ 2225*0c0d06caSMauro Carvalho Chehab static void transfer_check(struct gspca_dev *gspca_dev, 2226*0c0d06caSMauro Carvalho Chehab u8 *data) 2227*0c0d06caSMauro Carvalho Chehab { 2228*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 2229*0c0d06caSMauro Carvalho Chehab int new_qual, r; 2230*0c0d06caSMauro Carvalho Chehab 2231*0c0d06caSMauro Carvalho Chehab new_qual = 0; 2232*0c0d06caSMauro Carvalho Chehab 2233*0c0d06caSMauro Carvalho Chehab /* if USB error, discard the frame and decrease the quality */ 2234*0c0d06caSMauro Carvalho Chehab if (data[6] & 0x08) { /* USB FIFO full */ 2235*0c0d06caSMauro Carvalho Chehab gspca_dev->last_packet_type = DISCARD_PACKET; 2236*0c0d06caSMauro Carvalho Chehab new_qual = -5; 2237*0c0d06caSMauro Carvalho Chehab } else { 2238*0c0d06caSMauro Carvalho Chehab 2239*0c0d06caSMauro Carvalho Chehab /* else, compute the filling rate and a new JPEG quality */ 2240*0c0d06caSMauro Carvalho Chehab r = (sd->pktsz * 100) / 2241*0c0d06caSMauro Carvalho Chehab (sd->npkt * 2242*0c0d06caSMauro Carvalho Chehab gspca_dev->urb[0]->iso_frame_desc[0].length); 2243*0c0d06caSMauro Carvalho Chehab if (r >= 85) 2244*0c0d06caSMauro Carvalho Chehab new_qual = -3; 2245*0c0d06caSMauro Carvalho Chehab else if (r < 75) 2246*0c0d06caSMauro Carvalho Chehab new_qual = 2; 2247*0c0d06caSMauro Carvalho Chehab } 2248*0c0d06caSMauro Carvalho Chehab if (new_qual != 0) { 2249*0c0d06caSMauro Carvalho Chehab sd->nchg += new_qual; 2250*0c0d06caSMauro Carvalho Chehab if (sd->nchg < -6 || sd->nchg >= 12) { 2251*0c0d06caSMauro Carvalho Chehab /* Note: we are in interrupt context, so we can't 2252*0c0d06caSMauro Carvalho Chehab use v4l2_ctrl_g/s_ctrl here. Access the value 2253*0c0d06caSMauro Carvalho Chehab directly instead. */ 2254*0c0d06caSMauro Carvalho Chehab s32 curqual = sd->jpegqual->cur.val; 2255*0c0d06caSMauro Carvalho Chehab sd->nchg = 0; 2256*0c0d06caSMauro Carvalho Chehab new_qual += curqual; 2257*0c0d06caSMauro Carvalho Chehab if (new_qual < sd->jpegqual->minimum) 2258*0c0d06caSMauro Carvalho Chehab new_qual = sd->jpegqual->minimum; 2259*0c0d06caSMauro Carvalho Chehab else if (new_qual > sd->jpegqual->maximum) 2260*0c0d06caSMauro Carvalho Chehab new_qual = sd->jpegqual->maximum; 2261*0c0d06caSMauro Carvalho Chehab if (new_qual != curqual) { 2262*0c0d06caSMauro Carvalho Chehab sd->jpegqual->cur.val = new_qual; 2263*0c0d06caSMauro Carvalho Chehab queue_work(sd->work_thread, &sd->work); 2264*0c0d06caSMauro Carvalho Chehab } 2265*0c0d06caSMauro Carvalho Chehab } 2266*0c0d06caSMauro Carvalho Chehab } else { 2267*0c0d06caSMauro Carvalho Chehab sd->nchg = 0; 2268*0c0d06caSMauro Carvalho Chehab } 2269*0c0d06caSMauro Carvalho Chehab sd->pktsz = sd->npkt = 0; 2270*0c0d06caSMauro Carvalho Chehab } 2271*0c0d06caSMauro Carvalho Chehab 2272*0c0d06caSMauro Carvalho Chehab static void sd_pkt_scan(struct gspca_dev *gspca_dev, 2273*0c0d06caSMauro Carvalho Chehab u8 *data, /* isoc packet */ 2274*0c0d06caSMauro Carvalho Chehab int len) /* iso packet length */ 2275*0c0d06caSMauro Carvalho Chehab { 2276*0c0d06caSMauro Carvalho Chehab struct sd *sd = (struct sd *) gspca_dev; 2277*0c0d06caSMauro Carvalho Chehab int avg_lum, is_jpeg; 2278*0c0d06caSMauro Carvalho Chehab static const u8 frame_header[] = 2279*0c0d06caSMauro Carvalho Chehab {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; 2280*0c0d06caSMauro Carvalho Chehab 2281*0c0d06caSMauro Carvalho Chehab is_jpeg = (sd->fmt & 0x03) == 0; 2282*0c0d06caSMauro Carvalho Chehab if (len >= 64 && memcmp(data, frame_header, 6) == 0) { 2283*0c0d06caSMauro Carvalho Chehab avg_lum = ((data[35] >> 2) & 3) | 2284*0c0d06caSMauro Carvalho Chehab (data[20] << 2) | 2285*0c0d06caSMauro Carvalho Chehab (data[19] << 10); 2286*0c0d06caSMauro Carvalho Chehab avg_lum += ((data[35] >> 4) & 3) | 2287*0c0d06caSMauro Carvalho Chehab (data[22] << 2) | 2288*0c0d06caSMauro Carvalho Chehab (data[21] << 10); 2289*0c0d06caSMauro Carvalho Chehab avg_lum += ((data[35] >> 6) & 3) | 2290*0c0d06caSMauro Carvalho Chehab (data[24] << 2) | 2291*0c0d06caSMauro Carvalho Chehab (data[23] << 10); 2292*0c0d06caSMauro Carvalho Chehab avg_lum += (data[36] & 3) | 2293*0c0d06caSMauro Carvalho Chehab (data[26] << 2) | 2294*0c0d06caSMauro Carvalho Chehab (data[25] << 10); 2295*0c0d06caSMauro Carvalho Chehab avg_lum += ((data[36] >> 2) & 3) | 2296*0c0d06caSMauro Carvalho Chehab (data[28] << 2) | 2297*0c0d06caSMauro Carvalho Chehab (data[27] << 10); 2298*0c0d06caSMauro Carvalho Chehab avg_lum += ((data[36] >> 4) & 3) | 2299*0c0d06caSMauro Carvalho Chehab (data[30] << 2) | 2300*0c0d06caSMauro Carvalho Chehab (data[29] << 10); 2301*0c0d06caSMauro Carvalho Chehab avg_lum += ((data[36] >> 6) & 3) | 2302*0c0d06caSMauro Carvalho Chehab (data[32] << 2) | 2303*0c0d06caSMauro Carvalho Chehab (data[31] << 10); 2304*0c0d06caSMauro Carvalho Chehab avg_lum += ((data[44] >> 4) & 3) | 2305*0c0d06caSMauro Carvalho Chehab (data[34] << 2) | 2306*0c0d06caSMauro Carvalho Chehab (data[33] << 10); 2307*0c0d06caSMauro Carvalho Chehab avg_lum >>= 9; 2308*0c0d06caSMauro Carvalho Chehab atomic_set(&sd->avg_lum, avg_lum); 2309*0c0d06caSMauro Carvalho Chehab 2310*0c0d06caSMauro Carvalho Chehab if (is_jpeg) 2311*0c0d06caSMauro Carvalho Chehab transfer_check(gspca_dev, data); 2312*0c0d06caSMauro Carvalho Chehab 2313*0c0d06caSMauro Carvalho Chehab gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 2314*0c0d06caSMauro Carvalho Chehab len -= 64; 2315*0c0d06caSMauro Carvalho Chehab if (len == 0) 2316*0c0d06caSMauro Carvalho Chehab return; 2317*0c0d06caSMauro Carvalho Chehab data += 64; 2318*0c0d06caSMauro Carvalho Chehab } 2319*0c0d06caSMauro Carvalho Chehab if (gspca_dev->last_packet_type == LAST_PACKET) { 2320*0c0d06caSMauro Carvalho Chehab if (is_jpeg) { 2321*0c0d06caSMauro Carvalho Chehab gspca_frame_add(gspca_dev, FIRST_PACKET, 2322*0c0d06caSMauro Carvalho Chehab sd->jpeg_hdr, JPEG_HDR_SZ); 2323*0c0d06caSMauro Carvalho Chehab gspca_frame_add(gspca_dev, INTER_PACKET, 2324*0c0d06caSMauro Carvalho Chehab data, len); 2325*0c0d06caSMauro Carvalho Chehab } else { 2326*0c0d06caSMauro Carvalho Chehab gspca_frame_add(gspca_dev, FIRST_PACKET, 2327*0c0d06caSMauro Carvalho Chehab data, len); 2328*0c0d06caSMauro Carvalho Chehab } 2329*0c0d06caSMauro Carvalho Chehab } else { 2330*0c0d06caSMauro Carvalho Chehab /* if JPEG, count the packets and their size */ 2331*0c0d06caSMauro Carvalho Chehab if (is_jpeg) { 2332*0c0d06caSMauro Carvalho Chehab sd->npkt++; 2333*0c0d06caSMauro Carvalho Chehab sd->pktsz += len; 2334*0c0d06caSMauro Carvalho Chehab } 2335*0c0d06caSMauro Carvalho Chehab gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 2336*0c0d06caSMauro Carvalho Chehab } 2337*0c0d06caSMauro Carvalho Chehab } 2338*0c0d06caSMauro Carvalho Chehab 2339*0c0d06caSMauro Carvalho Chehab /* sub-driver description */ 2340*0c0d06caSMauro Carvalho Chehab static const struct sd_desc sd_desc = { 2341*0c0d06caSMauro Carvalho Chehab .name = KBUILD_MODNAME, 2342*0c0d06caSMauro Carvalho Chehab .config = sd_config, 2343*0c0d06caSMauro Carvalho Chehab .init = sd_init, 2344*0c0d06caSMauro Carvalho Chehab .init_controls = sd_init_controls, 2345*0c0d06caSMauro Carvalho Chehab .isoc_init = sd_isoc_init, 2346*0c0d06caSMauro Carvalho Chehab .start = sd_start, 2347*0c0d06caSMauro Carvalho Chehab .stopN = sd_stopN, 2348*0c0d06caSMauro Carvalho Chehab .stop0 = sd_stop0, 2349*0c0d06caSMauro Carvalho Chehab .pkt_scan = sd_pkt_scan, 2350*0c0d06caSMauro Carvalho Chehab #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) 2351*0c0d06caSMauro Carvalho Chehab .int_pkt_scan = sd_int_pkt_scan, 2352*0c0d06caSMauro Carvalho Chehab #endif 2353*0c0d06caSMauro Carvalho Chehab .dq_callback = sd_dqcallback, 2354*0c0d06caSMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG 2355*0c0d06caSMauro Carvalho Chehab .set_register = sd_dbg_s_register, 2356*0c0d06caSMauro Carvalho Chehab .get_register = sd_dbg_g_register, 2357*0c0d06caSMauro Carvalho Chehab #endif 2358*0c0d06caSMauro Carvalho Chehab .get_chip_ident = sd_chip_ident, 2359*0c0d06caSMauro Carvalho Chehab }; 2360*0c0d06caSMauro Carvalho Chehab 2361*0c0d06caSMauro Carvalho Chehab #define SN9C20X(sensor, i2c_addr, flags) \ 2362*0c0d06caSMauro Carvalho Chehab .driver_info = ((flags & 0xff) << 16) \ 2363*0c0d06caSMauro Carvalho Chehab | (SENSOR_ ## sensor << 8) \ 2364*0c0d06caSMauro Carvalho Chehab | (i2c_addr) 2365*0c0d06caSMauro Carvalho Chehab 2366*0c0d06caSMauro Carvalho Chehab static const struct usb_device_id device_table[] = { 2367*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)}, 2368*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)}, 2369*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, 2370*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)}, 2371*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)}, 2372*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, 2373*0c0d06caSMauro Carvalho Chehab (FLIP_DETECT | HAS_NO_BUTTON))}, 2374*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)}, 2375*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)}, 2376*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)}, 2377*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)}, 2378*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)}, 2379*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)}, 2380*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)}, 2381*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)}, 2382*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)}, 2383*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)}, 2384*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)}, 2385*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)}, 2386*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)}, 2387*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)}, 2388*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)}, 2389*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)}, 2390*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)}, 2391*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)}, 2392*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)}, 2393*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)}, 2394*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)}, 2395*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)}, 2396*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)}, 2397*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)}, 2398*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)}, 2399*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)}, 2400*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)}, 2401*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)}, 2402*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)}, 2403*0c0d06caSMauro Carvalho Chehab {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)}, 2404*0c0d06caSMauro Carvalho Chehab {} 2405*0c0d06caSMauro Carvalho Chehab }; 2406*0c0d06caSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, device_table); 2407*0c0d06caSMauro Carvalho Chehab 2408*0c0d06caSMauro Carvalho Chehab /* -- device connect -- */ 2409*0c0d06caSMauro Carvalho Chehab static int sd_probe(struct usb_interface *intf, 2410*0c0d06caSMauro Carvalho Chehab const struct usb_device_id *id) 2411*0c0d06caSMauro Carvalho Chehab { 2412*0c0d06caSMauro Carvalho Chehab return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 2413*0c0d06caSMauro Carvalho Chehab THIS_MODULE); 2414*0c0d06caSMauro Carvalho Chehab } 2415*0c0d06caSMauro Carvalho Chehab 2416*0c0d06caSMauro Carvalho Chehab static struct usb_driver sd_driver = { 2417*0c0d06caSMauro Carvalho Chehab .name = KBUILD_MODNAME, 2418*0c0d06caSMauro Carvalho Chehab .id_table = device_table, 2419*0c0d06caSMauro Carvalho Chehab .probe = sd_probe, 2420*0c0d06caSMauro Carvalho Chehab .disconnect = gspca_disconnect, 2421*0c0d06caSMauro Carvalho Chehab #ifdef CONFIG_PM 2422*0c0d06caSMauro Carvalho Chehab .suspend = gspca_suspend, 2423*0c0d06caSMauro Carvalho Chehab .resume = gspca_resume, 2424*0c0d06caSMauro Carvalho Chehab .reset_resume = gspca_resume, 2425*0c0d06caSMauro Carvalho Chehab #endif 2426*0c0d06caSMauro Carvalho Chehab }; 2427*0c0d06caSMauro Carvalho Chehab 2428*0c0d06caSMauro Carvalho Chehab module_usb_driver(sd_driver); 2429