1/* 2 * Quickcam cameras initialization data 3 * 4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21#define MODULE_NAME "tv8532" 22 23#include "gspca.h" 24 25MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); 26MODULE_DESCRIPTION("TV8532 USB Camera Driver"); 27MODULE_LICENSE("GPL"); 28 29/* specific webcam descriptor */ 30struct sd { 31 struct gspca_dev gspca_dev; /* !! must be the first item */ 32 33 __u16 exposure; 34 __u16 gain; 35 36 __u8 packet; 37}; 38 39/* V4L2 controls supported by the driver */ 40static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); 41static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); 42static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); 43static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); 44 45static const struct ctrl sd_ctrls[] = { 46 { 47 { 48 .id = V4L2_CID_EXPOSURE, 49 .type = V4L2_CTRL_TYPE_INTEGER, 50 .name = "Exposure", 51 .minimum = 1, 52 .maximum = 0x18f, 53 .step = 1, 54#define EXPOSURE_DEF 0x18f 55 .default_value = EXPOSURE_DEF, 56 }, 57 .set = sd_setexposure, 58 .get = sd_getexposure, 59 }, 60 { 61 { 62 .id = V4L2_CID_GAIN, 63 .type = V4L2_CTRL_TYPE_INTEGER, 64 .name = "Gain", 65 .minimum = 0, 66 .maximum = 0x7ff, 67 .step = 1, 68#define GAIN_DEF 0x100 69 .default_value = GAIN_DEF, 70 }, 71 .set = sd_setgain, 72 .get = sd_getgain, 73 }, 74}; 75 76static const struct v4l2_pix_format sif_mode[] = { 77 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 78 .bytesperline = 176, 79 .sizeimage = 176 * 144, 80 .colorspace = V4L2_COLORSPACE_SRGB, 81 .priv = 1}, 82 {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 83 .bytesperline = 352, 84 .sizeimage = 352 * 288, 85 .colorspace = V4L2_COLORSPACE_SRGB, 86 .priv = 0}, 87}; 88 89/* TV-8532A (ICM532A) registers (LE) */ 90#define R00_PART_CONTROL 0x00 91#define LATENT_CHANGE 0x80 92#define EXPO_CHANGE 0x04 93#define R01_TIMING_CONTROL_LOW 0x01 94#define CMD_EEprom_Open 0x30 95#define CMD_EEprom_Close 0x29 96#define R03_TABLE_ADDR 0x03 97#define R04_WTRAM_DATA_L 0x04 98#define R05_WTRAM_DATA_M 0x05 99#define R06_WTRAM_DATA_H 0x06 100#define R07_TABLE_LEN 0x07 101#define R08_RAM_WRITE_ACTION 0x08 102#define R0C_AD_WIDTHL 0x0c 103#define R0D_AD_WIDTHH 0x0d 104#define R0E_AD_HEIGHTL 0x0e 105#define R0F_AD_HEIGHTH 0x0f 106#define R10_AD_COL_BEGINL 0x10 107#define R11_AD_COL_BEGINH 0x11 108#define MIRROR 0x04 /* [10] */ 109#define R14_AD_ROW_BEGINL 0x14 110#define R15_AD_ROWBEGINH 0x15 111#define R1C_AD_EXPOSE_TIMEL 0x1c 112#define R20_GAIN_G1L 0x20 113#define R21_GAIN_G1H 0x21 114#define R22_GAIN_RL 0x22 115#define R23_GAIN_RH 0x23 116#define R24_GAIN_BL 0x24 117#define R25_GAIN_BH 0x25 118#define R26_GAIN_G2L 0x26 119#define R27_GAIN_G2H 0x27 120#define R28_QUANT 0x28 121#define R29_LINE 0x29 122#define R2C_POLARITY 0x2c 123#define R2D_POINT 0x2d 124#define R2E_POINTH 0x2e 125#define R2F_POINTB 0x2f 126#define R30_POINTBH 0x30 127#define R31_UPD 0x31 128#define R2A_HIGH_BUDGET 0x2a 129#define R2B_LOW_BUDGET 0x2b 130#define R34_VID 0x34 131#define R35_VIDH 0x35 132#define R36_PID 0x36 133#define R37_PIDH 0x37 134#define R39_Test1 0x39 /* GPIO */ 135#define R3B_Test3 0x3B /* GPIO */ 136#define R83_AD_IDH 0x83 137#define R91_AD_SLOPEREG 0x91 138#define R94_AD_BITCONTROL 0x94 139 140static const u8 eeprom_data[][3] = { 141/* dataH dataM dataL */ 142 {0x01, 0x00, 0x01}, 143 {0x01, 0x80, 0x11}, 144 {0x05, 0x00, 0x14}, 145 {0x05, 0x00, 0x1c}, 146 {0x0d, 0x00, 0x1e}, 147 {0x05, 0x00, 0x1f}, 148 {0x05, 0x05, 0x19}, 149 {0x05, 0x01, 0x1b}, 150 {0x05, 0x09, 0x1e}, 151 {0x0d, 0x89, 0x2e}, 152 {0x05, 0x89, 0x2f}, 153 {0x05, 0x0d, 0xd9}, 154 {0x05, 0x09, 0xf1}, 155}; 156 157 158/* write 1 byte */ 159static void reg_w1(struct gspca_dev *gspca_dev, 160 __u16 index, __u8 value) 161{ 162 gspca_dev->usb_buf[0] = value; 163 usb_control_msg(gspca_dev->dev, 164 usb_sndctrlpipe(gspca_dev->dev, 0), 165 0x02, 166 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 167 0, /* value */ 168 index, gspca_dev->usb_buf, 1, 500); 169} 170 171/* write 2 bytes */ 172static void reg_w2(struct gspca_dev *gspca_dev, 173 u16 index, u16 value) 174{ 175 gspca_dev->usb_buf[0] = value; 176 gspca_dev->usb_buf[1] = value >> 8; 177 usb_control_msg(gspca_dev->dev, 178 usb_sndctrlpipe(gspca_dev->dev, 0), 179 0x02, 180 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 181 0, /* value */ 182 index, gspca_dev->usb_buf, 2, 500); 183} 184 185static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev) 186{ 187 int i; 188 189 reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Open); 190 for (i = 0; i < ARRAY_SIZE(eeprom_data); i++) { 191 reg_w1(gspca_dev, R03_TABLE_ADDR, i); 192 reg_w1(gspca_dev, R04_WTRAM_DATA_L, eeprom_data[i][2]); 193 reg_w1(gspca_dev, R05_WTRAM_DATA_M, eeprom_data[i][1]); 194 reg_w1(gspca_dev, R06_WTRAM_DATA_H, eeprom_data[i][0]); 195 reg_w1(gspca_dev, R08_RAM_WRITE_ACTION, 0); 196 } 197 reg_w1(gspca_dev, R07_TABLE_LEN, i); 198 reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close); 199} 200 201/* this function is called at probe time */ 202static int sd_config(struct gspca_dev *gspca_dev, 203 const struct usb_device_id *id) 204{ 205 struct sd *sd = (struct sd *) gspca_dev; 206 struct cam *cam; 207 208 cam = &gspca_dev->cam; 209 cam->cam_mode = sif_mode; 210 cam->nmodes = ARRAY_SIZE(sif_mode); 211 212 sd->exposure = EXPOSURE_DEF; 213 sd->gain = GAIN_DEF; 214 return 0; 215} 216 217static void tv_8532_setReg(struct gspca_dev *gspca_dev) 218{ 219 reg_w1(gspca_dev, R3B_Test3, 0x0a); /* Test0Sel = 10 */ 220 /******************************************************/ 221 reg_w1(gspca_dev, R0E_AD_HEIGHTL, 0x90); 222 reg_w1(gspca_dev, R0F_AD_HEIGHTH, 0x01); 223 reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, 0x018f); 224 reg_w1(gspca_dev, R10_AD_COL_BEGINL, 0x44); 225 /* begin active line */ 226 reg_w1(gspca_dev, R11_AD_COL_BEGINH, 0x00); 227 /* mirror and digital gain */ 228 reg_w1(gspca_dev, R14_AD_ROW_BEGINL, 0x0a); 229 230 reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x02); 231 reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00); 232 reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); 233 /* = 0x84 */ 234} 235 236/* this function is called at probe and resume time */ 237static int sd_init(struct gspca_dev *gspca_dev) 238{ 239 tv_8532WriteEEprom(gspca_dev); 240 241 return 0; 242} 243 244static void setexposure(struct gspca_dev *gspca_dev) 245{ 246 struct sd *sd = (struct sd *) gspca_dev; 247 248 reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, sd->exposure); 249 reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); 250 /* 0x84 */ 251} 252 253static void setgain(struct gspca_dev *gspca_dev) 254{ 255 struct sd *sd = (struct sd *) gspca_dev; 256 257 reg_w2(gspca_dev, R20_GAIN_G1L, sd->gain); 258 reg_w2(gspca_dev, R22_GAIN_RL, sd->gain); 259 reg_w2(gspca_dev, R24_GAIN_BL, sd->gain); 260 reg_w2(gspca_dev, R26_GAIN_G2L, sd->gain); 261} 262 263/* -- start the camera -- */ 264static int sd_start(struct gspca_dev *gspca_dev) 265{ 266 struct sd *sd = (struct sd *) gspca_dev; 267 268 reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8); /* 0x20; 0x0c */ 269 reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03); 270 271 /************************************************/ 272 reg_w1(gspca_dev, R28_QUANT, 0x90); 273 /* 0x72 compressed mode 0x28 */ 274 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { 275 /* 176x144 */ 276 reg_w1(gspca_dev, R29_LINE, 0x41); 277 /* CIF - 2 lines/packet */ 278 } else { 279 /* 352x288 */ 280 reg_w1(gspca_dev, R29_LINE, 0x81); 281 /* CIF - 2 lines/packet */ 282 } 283 /************************************************/ 284 reg_w1(gspca_dev, R2C_POLARITY, 0x10); /* slow clock */ 285 reg_w1(gspca_dev, R2D_POINT, 0x14); 286 reg_w1(gspca_dev, R2E_POINTH, 0x01); 287 reg_w1(gspca_dev, R2F_POINTB, 0x12); 288 reg_w1(gspca_dev, R30_POINTBH, 0x01); 289 290 tv_8532_setReg(gspca_dev); 291 292 setexposure(gspca_dev); 293 setgain(gspca_dev); 294 295 /************************************************/ 296 reg_w1(gspca_dev, R31_UPD, 0x01); /* update registers */ 297 msleep(200); 298 reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ 299 300 gspca_dev->empty_packet = 0; /* check the empty packets */ 301 sd->packet = 0; /* ignore the first packets */ 302 303 return 0; 304} 305 306static void sd_stopN(struct gspca_dev *gspca_dev) 307{ 308 reg_w1(gspca_dev, R3B_Test3, 0x0b); /* Test0Sel = 11 = GPIO */ 309} 310 311static void sd_pkt_scan(struct gspca_dev *gspca_dev, 312 u8 *data, /* isoc packet */ 313 int len) /* iso packet length */ 314{ 315 struct sd *sd = (struct sd *) gspca_dev; 316 int packet_type0, packet_type1; 317 318 packet_type0 = packet_type1 = INTER_PACKET; 319 if (gspca_dev->empty_packet) { 320 gspca_dev->empty_packet = 0; 321 sd->packet = gspca_dev->height / 2; 322 packet_type0 = FIRST_PACKET; 323 } else if (sd->packet == 0) 324 return; /* 2 more lines in 352x288 ! */ 325 sd->packet--; 326 if (sd->packet == 0) 327 packet_type1 = LAST_PACKET; 328 329 /* each packet contains: 330 * - header 2 bytes 331 * - RGRG line 332 * - 4 bytes 333 * - GBGB line 334 * - 4 bytes 335 */ 336 gspca_frame_add(gspca_dev, packet_type0, 337 data + 2, gspca_dev->width); 338 gspca_frame_add(gspca_dev, packet_type1, 339 data + gspca_dev->width + 5, gspca_dev->width); 340} 341 342static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) 343{ 344 struct sd *sd = (struct sd *) gspca_dev; 345 346 sd->exposure = val; 347 if (gspca_dev->streaming) 348 setexposure(gspca_dev); 349 return 0; 350} 351 352static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) 353{ 354 struct sd *sd = (struct sd *) gspca_dev; 355 356 *val = sd->exposure; 357 return 0; 358} 359 360static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) 361{ 362 struct sd *sd = (struct sd *) gspca_dev; 363 364 sd->gain = val; 365 if (gspca_dev->streaming) 366 setgain(gspca_dev); 367 return 0; 368} 369 370static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) 371{ 372 struct sd *sd = (struct sd *) gspca_dev; 373 374 *val = sd->gain; 375 return 0; 376} 377 378/* sub-driver description */ 379static const struct sd_desc sd_desc = { 380 .name = MODULE_NAME, 381 .ctrls = sd_ctrls, 382 .nctrls = ARRAY_SIZE(sd_ctrls), 383 .config = sd_config, 384 .init = sd_init, 385 .start = sd_start, 386 .stopN = sd_stopN, 387 .pkt_scan = sd_pkt_scan, 388}; 389 390/* -- module initialisation -- */ 391static const __devinitdata struct usb_device_id device_table[] = { 392 {USB_DEVICE(0x046d, 0x0920)}, 393 {USB_DEVICE(0x046d, 0x0921)}, 394 {USB_DEVICE(0x0545, 0x808b)}, 395 {USB_DEVICE(0x0545, 0x8333)}, 396 {USB_DEVICE(0x0923, 0x010f)}, 397 {} 398}; 399 400MODULE_DEVICE_TABLE(usb, device_table); 401 402/* -- device connect -- */ 403static int sd_probe(struct usb_interface *intf, 404 const struct usb_device_id *id) 405{ 406 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 407 THIS_MODULE); 408} 409 410static struct usb_driver sd_driver = { 411 .name = MODULE_NAME, 412 .id_table = device_table, 413 .probe = sd_probe, 414 .disconnect = gspca_disconnect, 415#ifdef CONFIG_PM 416 .suspend = gspca_suspend, 417 .resume = gspca_resume, 418#endif 419}; 420 421/* -- module insert / remove -- */ 422static int __init sd_mod_init(void) 423{ 424 int ret; 425 ret = usb_register(&sd_driver); 426 if (ret < 0) 427 return ret; 428 PDEBUG(D_PROBE, "registered"); 429 return 0; 430} 431 432static void __exit sd_mod_exit(void) 433{ 434 usb_deregister(&sd_driver); 435 PDEBUG(D_PROBE, "deregistered"); 436} 437 438module_init(sd_mod_init); 439module_exit(sd_mod_exit); 440