1 /* 2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher 3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland 4 * Copyright (c) 2002, 2003 Tuukka Toivonen 5 * Copyright (c) 2008 Erik Andrén 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 * P/N 861037: Sensor HDCS1000 ASIC STV0600 22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express 24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam 25 * P/N 861075-0040: Sensor HDCS1000 ASIC 26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB 27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web 28 */ 29 30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 31 32 #include "stv06xx_vv6410.h" 33 34 static struct v4l2_pix_format vv6410_mode[] = { 35 { 36 356, 37 292, 38 V4L2_PIX_FMT_SGRBG8, 39 V4L2_FIELD_NONE, 40 .sizeimage = 356 * 292, 41 .bytesperline = 356, 42 .colorspace = V4L2_COLORSPACE_SRGB, 43 .priv = 0 44 } 45 }; 46 47 static int vv6410_s_ctrl(struct v4l2_ctrl *ctrl) 48 { 49 struct gspca_dev *gspca_dev = 50 container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 51 int err = -EINVAL; 52 53 switch (ctrl->id) { 54 case V4L2_CID_HFLIP: 55 err = vv6410_set_hflip(gspca_dev, ctrl->val); 56 break; 57 case V4L2_CID_VFLIP: 58 err = vv6410_set_vflip(gspca_dev, ctrl->val); 59 break; 60 case V4L2_CID_GAIN: 61 err = vv6410_set_analog_gain(gspca_dev, ctrl->val); 62 break; 63 case V4L2_CID_EXPOSURE: 64 err = vv6410_set_exposure(gspca_dev, ctrl->val); 65 break; 66 } 67 return err; 68 } 69 70 static const struct v4l2_ctrl_ops vv6410_ctrl_ops = { 71 .s_ctrl = vv6410_s_ctrl, 72 }; 73 74 static int vv6410_probe(struct sd *sd) 75 { 76 u16 data; 77 int err; 78 79 err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data); 80 if (err < 0) 81 return -ENODEV; 82 83 if (data != 0x19) 84 return -ENODEV; 85 86 pr_info("vv6410 sensor detected\n"); 87 88 sd->gspca_dev.cam.cam_mode = vv6410_mode; 89 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(vv6410_mode); 90 return 0; 91 } 92 93 static int vv6410_init_controls(struct sd *sd) 94 { 95 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler; 96 97 v4l2_ctrl_handler_init(hdl, 4); 98 v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops, 99 V4L2_CID_HFLIP, 0, 1, 1, 0); 100 v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops, 101 V4L2_CID_VFLIP, 0, 1, 1, 0); 102 v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops, 103 V4L2_CID_EXPOSURE, 0, 32768, 1, 20000); 104 v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops, 105 V4L2_CID_GAIN, 0, 15, 1, 10); 106 return hdl->error; 107 } 108 109 static int vv6410_init(struct sd *sd) 110 { 111 int err = 0, i; 112 113 for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) 114 stv06xx_write_bridge(sd, stv_bridge_init[i].addr, stv_bridge_init[i].data); 115 116 if (err < 0) 117 return err; 118 119 err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init, 120 ARRAY_SIZE(vv6410_sensor_init)); 121 return (err < 0) ? err : 0; 122 } 123 124 static int vv6410_start(struct sd *sd) 125 { 126 int err; 127 struct cam *cam = &sd->gspca_dev.cam; 128 u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv; 129 130 if (priv & VV6410_SUBSAMPLE) { 131 PDEBUG(D_CONF, "Enabling subsampling"); 132 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02); 133 stv06xx_write_bridge(sd, STV_X_CTRL, 0x06); 134 135 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10); 136 } else { 137 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01); 138 stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a); 139 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x00); 140 141 } 142 143 /* Turn on LED */ 144 err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON); 145 if (err < 0) 146 return err; 147 148 err = stv06xx_write_sensor(sd, VV6410_SETUP0, 0); 149 if (err < 0) 150 return err; 151 152 PDEBUG(D_STREAM, "Starting stream"); 153 154 return 0; 155 } 156 157 static int vv6410_stop(struct sd *sd) 158 { 159 int err; 160 161 /* Turn off LED */ 162 err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF); 163 if (err < 0) 164 return err; 165 166 err = stv06xx_write_sensor(sd, VV6410_SETUP0, VV6410_LOW_POWER_MODE); 167 if (err < 0) 168 return err; 169 170 PDEBUG(D_STREAM, "Halting stream"); 171 172 return (err < 0) ? err : 0; 173 } 174 175 static int vv6410_dump(struct sd *sd) 176 { 177 u8 i; 178 int err = 0; 179 180 pr_info("Dumping all vv6410 sensor registers\n"); 181 for (i = 0; i < 0xff && !err; i++) { 182 u16 data; 183 err = stv06xx_read_sensor(sd, i, &data); 184 pr_info("Register 0x%x contained 0x%x\n", i, data); 185 } 186 return (err < 0) ? err : 0; 187 } 188 189 static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val) 190 { 191 int err; 192 u16 i2c_data; 193 struct sd *sd = (struct sd *) gspca_dev; 194 195 err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data); 196 if (err < 0) 197 return err; 198 199 if (val) 200 i2c_data |= VV6410_HFLIP; 201 else 202 i2c_data &= ~VV6410_HFLIP; 203 204 PDEBUG(D_V4L2, "Set horizontal flip to %d", val); 205 err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data); 206 207 return (err < 0) ? err : 0; 208 } 209 210 static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val) 211 { 212 int err; 213 u16 i2c_data; 214 struct sd *sd = (struct sd *) gspca_dev; 215 216 err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data); 217 if (err < 0) 218 return err; 219 220 if (val) 221 i2c_data |= VV6410_VFLIP; 222 else 223 i2c_data &= ~VV6410_VFLIP; 224 225 PDEBUG(D_V4L2, "Set vertical flip to %d", val); 226 err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data); 227 228 return (err < 0) ? err : 0; 229 } 230 231 static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val) 232 { 233 int err; 234 struct sd *sd = (struct sd *) gspca_dev; 235 236 PDEBUG(D_V4L2, "Set analog gain to %d", val); 237 err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf)); 238 239 return (err < 0) ? err : 0; 240 } 241 242 static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val) 243 { 244 int err; 245 struct sd *sd = (struct sd *) gspca_dev; 246 unsigned int fine, coarse; 247 248 val = (val * val >> 14) + val / 4; 249 250 fine = val % VV6410_CIF_LINELENGTH; 251 coarse = min(512, val / VV6410_CIF_LINELENGTH); 252 253 PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d", 254 coarse, fine); 255 256 err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8); 257 if (err < 0) 258 goto out; 259 260 err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff); 261 if (err < 0) 262 goto out; 263 264 err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8); 265 if (err < 0) 266 goto out; 267 268 err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff); 269 270 out: 271 return err; 272 } 273