1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Sunplus spca504(abc) spca533 spca536 library 4 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr 5 * 6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> 7 */ 8 9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 11 #define MODULE_NAME "sunplus" 12 13 #include "gspca.h" 14 #include "jpeg.h" 15 16 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); 17 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver"); 18 MODULE_LICENSE("GPL"); 19 20 #define QUALITY 85 21 22 /* specific webcam descriptor */ 23 struct sd { 24 struct gspca_dev gspca_dev; /* !! must be the first item */ 25 26 bool autogain; 27 28 u8 bridge; 29 #define BRIDGE_SPCA504 0 30 #define BRIDGE_SPCA504B 1 31 #define BRIDGE_SPCA504C 2 32 #define BRIDGE_SPCA533 3 33 #define BRIDGE_SPCA536 4 34 u8 subtype; 35 #define AiptekMiniPenCam13 1 36 #define LogitechClickSmart420 2 37 #define LogitechClickSmart820 3 38 #define MegapixV4 4 39 #define MegaImageVI 5 40 41 u8 jpeg_hdr[JPEG_HDR_SZ]; 42 }; 43 44 static const struct v4l2_pix_format vga_mode[] = { 45 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 46 .bytesperline = 320, 47 .sizeimage = 320 * 240 * 3 / 8 + 590, 48 .colorspace = V4L2_COLORSPACE_JPEG, 49 .priv = 2}, 50 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 51 .bytesperline = 640, 52 .sizeimage = 640 * 480 * 3 / 8 + 590, 53 .colorspace = V4L2_COLORSPACE_JPEG, 54 .priv = 1}, 55 }; 56 57 static const struct v4l2_pix_format custom_mode[] = { 58 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 59 .bytesperline = 320, 60 .sizeimage = 320 * 240 * 3 / 8 + 590, 61 .colorspace = V4L2_COLORSPACE_JPEG, 62 .priv = 2}, 63 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 64 .bytesperline = 464, 65 .sizeimage = 464 * 480 * 3 / 8 + 590, 66 .colorspace = V4L2_COLORSPACE_JPEG, 67 .priv = 1}, 68 }; 69 70 static const struct v4l2_pix_format vga_mode2[] = { 71 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 72 .bytesperline = 176, 73 .sizeimage = 176 * 144 * 3 / 8 + 590, 74 .colorspace = V4L2_COLORSPACE_JPEG, 75 .priv = 4}, 76 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 77 .bytesperline = 320, 78 .sizeimage = 320 * 240 * 3 / 8 + 590, 79 .colorspace = V4L2_COLORSPACE_JPEG, 80 .priv = 3}, 81 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 82 .bytesperline = 352, 83 .sizeimage = 352 * 288 * 3 / 8 + 590, 84 .colorspace = V4L2_COLORSPACE_JPEG, 85 .priv = 2}, 86 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 87 .bytesperline = 640, 88 .sizeimage = 640 * 480 * 3 / 8 + 590, 89 .colorspace = V4L2_COLORSPACE_JPEG, 90 .priv = 1}, 91 }; 92 93 #define SPCA50X_OFFSET_DATA 10 94 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3 95 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4 96 #define SPCA504_PCCAM600_OFFSET_MODE 5 97 #define SPCA504_PCCAM600_OFFSET_DATA 14 98 /* Frame packet header offsets for the spca533 */ 99 #define SPCA533_OFFSET_DATA 16 100 #define SPCA533_OFFSET_FRAMSEQ 15 101 /* Frame packet header offsets for the spca536 */ 102 #define SPCA536_OFFSET_DATA 4 103 #define SPCA536_OFFSET_FRAMSEQ 1 104 105 struct cmd { 106 u8 req; 107 u16 val; 108 u16 idx; 109 }; 110 111 /* Initialisation data for the Creative PC-CAM 600 */ 112 static const struct cmd spca504_pccam600_init_data[] = { 113 /* {0xa0, 0x0000, 0x0503}, * capture mode */ 114 {0x00, 0x0000, 0x2000}, 115 {0x00, 0x0013, 0x2301}, 116 {0x00, 0x0003, 0x2000}, 117 {0x00, 0x0001, 0x21ac}, 118 {0x00, 0x0001, 0x21a6}, 119 {0x00, 0x0000, 0x21a7}, /* brightness */ 120 {0x00, 0x0020, 0x21a8}, /* contrast */ 121 {0x00, 0x0001, 0x21ac}, /* sat/hue */ 122 {0x00, 0x0000, 0x21ad}, /* hue */ 123 {0x00, 0x001a, 0x21ae}, /* saturation */ 124 {0x00, 0x0002, 0x21a3}, /* gamma */ 125 {0x30, 0x0154, 0x0008}, 126 {0x30, 0x0004, 0x0006}, 127 {0x30, 0x0258, 0x0009}, 128 {0x30, 0x0004, 0x0000}, 129 {0x30, 0x0093, 0x0004}, 130 {0x30, 0x0066, 0x0005}, 131 {0x00, 0x0000, 0x2000}, 132 {0x00, 0x0013, 0x2301}, 133 {0x00, 0x0003, 0x2000}, 134 {0x00, 0x0013, 0x2301}, 135 {0x00, 0x0003, 0x2000}, 136 }; 137 138 /* Creative PC-CAM 600 specific open data, sent before using the 139 * generic initialisation data from spca504_open_data. 140 */ 141 static const struct cmd spca504_pccam600_open_data[] = { 142 {0x00, 0x0001, 0x2501}, 143 {0x20, 0x0500, 0x0001}, /* snapshot mode */ 144 {0x00, 0x0003, 0x2880}, 145 {0x00, 0x0001, 0x2881}, 146 }; 147 148 /* Initialisation data for the logitech clicksmart 420 */ 149 static const struct cmd spca504A_clicksmart420_init_data[] = { 150 /* {0xa0, 0x0000, 0x0503}, * capture mode */ 151 {0x00, 0x0000, 0x2000}, 152 {0x00, 0x0013, 0x2301}, 153 {0x00, 0x0003, 0x2000}, 154 {0x00, 0x0001, 0x21ac}, 155 {0x00, 0x0001, 0x21a6}, 156 {0x00, 0x0000, 0x21a7}, /* brightness */ 157 {0x00, 0x0020, 0x21a8}, /* contrast */ 158 {0x00, 0x0001, 0x21ac}, /* sat/hue */ 159 {0x00, 0x0000, 0x21ad}, /* hue */ 160 {0x00, 0x001a, 0x21ae}, /* saturation */ 161 {0x00, 0x0002, 0x21a3}, /* gamma */ 162 {0x30, 0x0004, 0x000a}, 163 {0xb0, 0x0001, 0x0000}, 164 165 {0xa1, 0x0080, 0x0001}, 166 {0x30, 0x0049, 0x0000}, 167 {0x30, 0x0060, 0x0005}, 168 {0x0c, 0x0004, 0x0000}, 169 {0x00, 0x0000, 0x0000}, 170 {0x00, 0x0000, 0x2000}, 171 {0x00, 0x0013, 0x2301}, 172 {0x00, 0x0003, 0x2000}, 173 }; 174 175 /* clicksmart 420 open data ? */ 176 static const struct cmd spca504A_clicksmart420_open_data[] = { 177 {0x00, 0x0001, 0x2501}, 178 {0x20, 0x0502, 0x0000}, 179 {0x06, 0x0000, 0x0000}, 180 {0x00, 0x0004, 0x2880}, 181 {0x00, 0x0001, 0x2881}, 182 183 {0xa0, 0x0000, 0x0503}, 184 }; 185 186 static const u8 qtable_creative_pccam[2][64] = { 187 { /* Q-table Y-components */ 188 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12, 189 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11, 190 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11, 191 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13, 192 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17, 193 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c, 194 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e, 195 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e}, 196 { /* Q-table C-components */ 197 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e, 198 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 199 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 200 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 201 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 202 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 203 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 204 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e} 205 }; 206 207 /* FIXME: This Q-table is identical to the Creative PC-CAM one, 208 * except for one byte. Possibly a typo? 209 * NWG: 18/05/2003. 210 */ 211 static const u8 qtable_spca504_default[2][64] = { 212 { /* Q-table Y-components */ 213 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12, 214 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11, 215 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11, 216 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13, 217 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17, 218 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c, 219 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e, 220 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e, 221 }, 222 { /* Q-table C-components */ 223 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e, 224 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 225 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 226 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 227 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 228 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 229 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 230 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e} 231 }; 232 233 /* read <len> bytes to gspca_dev->usb_buf */ 234 static void reg_r(struct gspca_dev *gspca_dev, 235 u8 req, 236 u16 index, 237 u16 len) 238 { 239 int ret; 240 241 if (len > USB_BUF_SZ) { 242 gspca_err(gspca_dev, "reg_r: buffer overflow\n"); 243 return; 244 } 245 if (gspca_dev->usb_err < 0) 246 return; 247 ret = usb_control_msg(gspca_dev->dev, 248 usb_rcvctrlpipe(gspca_dev->dev, 0), 249 req, 250 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 251 0, /* value */ 252 index, 253 len ? gspca_dev->usb_buf : NULL, len, 254 500); 255 if (ret < 0) { 256 pr_err("reg_r err %d\n", ret); 257 gspca_dev->usb_err = ret; 258 } 259 } 260 261 /* write one byte */ 262 static void reg_w_1(struct gspca_dev *gspca_dev, 263 u8 req, 264 u16 value, 265 u16 index, 266 u16 byte) 267 { 268 int ret; 269 270 if (gspca_dev->usb_err < 0) 271 return; 272 gspca_dev->usb_buf[0] = byte; 273 ret = usb_control_msg(gspca_dev->dev, 274 usb_sndctrlpipe(gspca_dev->dev, 0), 275 req, 276 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 277 value, index, 278 gspca_dev->usb_buf, 1, 279 500); 280 if (ret < 0) { 281 pr_err("reg_w_1 err %d\n", ret); 282 gspca_dev->usb_err = ret; 283 } 284 } 285 286 /* write req / index / value */ 287 static void reg_w_riv(struct gspca_dev *gspca_dev, 288 u8 req, u16 index, u16 value) 289 { 290 struct usb_device *dev = gspca_dev->dev; 291 int ret; 292 293 if (gspca_dev->usb_err < 0) 294 return; 295 ret = usb_control_msg(dev, 296 usb_sndctrlpipe(dev, 0), 297 req, 298 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 299 value, index, NULL, 0, 500); 300 if (ret < 0) { 301 pr_err("reg_w_riv err %d\n", ret); 302 gspca_dev->usb_err = ret; 303 return; 304 } 305 gspca_dbg(gspca_dev, D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x\n", 306 req, index, value); 307 } 308 309 static void write_vector(struct gspca_dev *gspca_dev, 310 const struct cmd *data, int ncmds) 311 { 312 while (--ncmds >= 0) { 313 reg_w_riv(gspca_dev, data->req, data->idx, data->val); 314 data++; 315 } 316 } 317 318 static void setup_qtable(struct gspca_dev *gspca_dev, 319 const u8 qtable[2][64]) 320 { 321 int i; 322 323 /* loop over y components */ 324 for (i = 0; i < 64; i++) 325 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]); 326 327 /* loop over c components */ 328 for (i = 0; i < 64; i++) 329 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]); 330 } 331 332 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, 333 u8 req, u16 idx, u16 val) 334 { 335 reg_w_riv(gspca_dev, req, idx, val); 336 reg_r(gspca_dev, 0x01, 0x0001, 1); 337 gspca_dbg(gspca_dev, D_FRAM, "before wait 0x%04x\n", 338 gspca_dev->usb_buf[0]); 339 reg_w_riv(gspca_dev, req, idx, val); 340 341 msleep(200); 342 reg_r(gspca_dev, 0x01, 0x0001, 1); 343 gspca_dbg(gspca_dev, D_FRAM, "after wait 0x%04x\n", 344 gspca_dev->usb_buf[0]); 345 } 346 347 static void spca504_read_info(struct gspca_dev *gspca_dev) 348 { 349 int i; 350 u8 info[6]; 351 352 if (gspca_debug < D_STREAM) 353 return; 354 355 for (i = 0; i < 6; i++) { 356 reg_r(gspca_dev, 0, i, 1); 357 info[i] = gspca_dev->usb_buf[0]; 358 } 359 gspca_dbg(gspca_dev, D_STREAM, 360 "Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0\n", 361 info[0], info[1], info[2], 362 info[3], info[4], info[5]); 363 } 364 365 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, 366 u8 req, 367 u16 idx, u16 val, u8 endcode, u8 count) 368 { 369 u16 status; 370 371 reg_w_riv(gspca_dev, req, idx, val); 372 reg_r(gspca_dev, 0x01, 0x0001, 1); 373 if (gspca_dev->usb_err < 0) 374 return; 375 gspca_dbg(gspca_dev, D_FRAM, "Status 0x%02x Need 0x%02x\n", 376 gspca_dev->usb_buf[0], endcode); 377 if (!count) 378 return; 379 count = 200; 380 while (--count > 0) { 381 msleep(10); 382 /* gsmart mini2 write a each wait setting 1 ms is enough */ 383 /* reg_w_riv(gspca_dev, req, idx, val); */ 384 reg_r(gspca_dev, 0x01, 0x0001, 1); 385 status = gspca_dev->usb_buf[0]; 386 if (status == endcode) { 387 gspca_dbg(gspca_dev, D_FRAM, "status 0x%04x after wait %d\n", 388 status, 200 - count); 389 break; 390 } 391 } 392 } 393 394 static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev) 395 { 396 int count = 10; 397 398 while (--count > 0) { 399 reg_r(gspca_dev, 0x21, 0, 1); 400 if ((gspca_dev->usb_buf[0] & 0x01) == 0) 401 break; 402 msleep(10); 403 } 404 } 405 406 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) 407 { 408 int count = 50; 409 410 while (--count > 0) { 411 reg_r(gspca_dev, 0x21, 1, 1); 412 if (gspca_dev->usb_buf[0] != 0) { 413 reg_w_1(gspca_dev, 0x21, 0, 1, 0); 414 reg_r(gspca_dev, 0x21, 1, 1); 415 spca504B_PollingDataReady(gspca_dev); 416 break; 417 } 418 msleep(10); 419 } 420 } 421 422 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev) 423 { 424 u8 *data; 425 426 if (gspca_debug < D_STREAM) 427 return; 428 429 data = gspca_dev->usb_buf; 430 reg_r(gspca_dev, 0x20, 0, 5); 431 gspca_dbg(gspca_dev, D_STREAM, "FirmWare: %d %d %d %d %d\n", 432 data[0], data[1], data[2], data[3], data[4]); 433 reg_r(gspca_dev, 0x23, 0, 64); 434 reg_r(gspca_dev, 0x23, 1, 64); 435 } 436 437 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) 438 { 439 struct sd *sd = (struct sd *) gspca_dev; 440 u8 Size; 441 442 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; 443 switch (sd->bridge) { 444 case BRIDGE_SPCA533: 445 reg_w_riv(gspca_dev, 0x31, 0, 0); 446 spca504B_WaitCmdStatus(gspca_dev); 447 spca504B_PollingDataReady(gspca_dev); 448 spca50x_GetFirmware(gspca_dev); 449 450 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */ 451 reg_r(gspca_dev, 0x24, 8, 1); 452 453 reg_w_1(gspca_dev, 0x25, 0, 4, Size); 454 reg_r(gspca_dev, 0x25, 4, 1); /* size */ 455 spca504B_PollingDataReady(gspca_dev); 456 457 /* Init the cam width height with some values get on init ? */ 458 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00); 459 spca504B_WaitCmdStatus(gspca_dev); 460 spca504B_PollingDataReady(gspca_dev); 461 break; 462 default: 463 /* case BRIDGE_SPCA504B: */ 464 /* case BRIDGE_SPCA536: */ 465 reg_w_1(gspca_dev, 0x25, 0, 4, Size); 466 reg_r(gspca_dev, 0x25, 4, 1); /* size */ 467 reg_w_1(gspca_dev, 0x27, 0, 0, 6); 468 reg_r(gspca_dev, 0x27, 0, 1); /* type */ 469 spca504B_PollingDataReady(gspca_dev); 470 break; 471 case BRIDGE_SPCA504: 472 Size += 3; 473 if (sd->subtype == AiptekMiniPenCam13) { 474 /* spca504a aiptek */ 475 spca504A_acknowledged_command(gspca_dev, 476 0x08, Size, 0, 477 0x80 | (Size & 0x0f), 1); 478 spca504A_acknowledged_command(gspca_dev, 479 1, 3, 0, 0x9f, 0); 480 } else { 481 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0); 482 } 483 break; 484 case BRIDGE_SPCA504C: 485 /* capture mode */ 486 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00); 487 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f)); 488 break; 489 } 490 } 491 492 static void spca504_wait_status(struct gspca_dev *gspca_dev) 493 { 494 int cnt; 495 496 cnt = 256; 497 while (--cnt > 0) { 498 /* With this we get the status, when return 0 it's all ok */ 499 reg_r(gspca_dev, 0x06, 0x00, 1); 500 if (gspca_dev->usb_buf[0] == 0) 501 return; 502 msleep(10); 503 } 504 } 505 506 static void spca504B_setQtable(struct gspca_dev *gspca_dev) 507 { 508 reg_w_1(gspca_dev, 0x26, 0, 0, 3); 509 reg_r(gspca_dev, 0x26, 0, 1); 510 spca504B_PollingDataReady(gspca_dev); 511 } 512 513 static void setbrightness(struct gspca_dev *gspca_dev, s32 val) 514 { 515 struct sd *sd = (struct sd *) gspca_dev; 516 u16 reg; 517 518 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7; 519 reg_w_riv(gspca_dev, 0x00, reg, val); 520 } 521 522 static void setcontrast(struct gspca_dev *gspca_dev, s32 val) 523 { 524 struct sd *sd = (struct sd *) gspca_dev; 525 u16 reg; 526 527 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8; 528 reg_w_riv(gspca_dev, 0x00, reg, val); 529 } 530 531 static void setcolors(struct gspca_dev *gspca_dev, s32 val) 532 { 533 struct sd *sd = (struct sd *) gspca_dev; 534 u16 reg; 535 536 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae; 537 reg_w_riv(gspca_dev, 0x00, reg, val); 538 } 539 540 static void init_ctl_reg(struct gspca_dev *gspca_dev) 541 { 542 struct sd *sd = (struct sd *) gspca_dev; 543 int pollreg = 1; 544 545 switch (sd->bridge) { 546 case BRIDGE_SPCA504: 547 case BRIDGE_SPCA504C: 548 pollreg = 0; 549 /* fall through */ 550 default: 551 /* case BRIDGE_SPCA533: */ 552 /* case BRIDGE_SPCA504B: */ 553 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */ 554 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */ 555 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */ 556 break; 557 case BRIDGE_SPCA536: 558 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40); 559 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01); 560 reg_w_riv(gspca_dev, 0, 0x2089, 0x00); 561 break; 562 } 563 if (pollreg) 564 spca504B_PollingDataReady(gspca_dev); 565 } 566 567 /* this function is called at probe time */ 568 static int sd_config(struct gspca_dev *gspca_dev, 569 const struct usb_device_id *id) 570 { 571 struct sd *sd = (struct sd *) gspca_dev; 572 struct cam *cam; 573 574 cam = &gspca_dev->cam; 575 576 sd->bridge = id->driver_info >> 8; 577 sd->subtype = id->driver_info; 578 579 if (sd->subtype == AiptekMiniPenCam13) { 580 581 /* try to get the firmware as some cam answer 2.0.1.2.2 582 * and should be a spca504b then overwrite that setting */ 583 reg_r(gspca_dev, 0x20, 0, 1); 584 switch (gspca_dev->usb_buf[0]) { 585 case 1: 586 break; /* (right bridge/subtype) */ 587 case 2: 588 sd->bridge = BRIDGE_SPCA504B; 589 sd->subtype = 0; 590 break; 591 default: 592 return -ENODEV; 593 } 594 } 595 596 switch (sd->bridge) { 597 default: 598 /* case BRIDGE_SPCA504B: */ 599 /* case BRIDGE_SPCA504: */ 600 /* case BRIDGE_SPCA536: */ 601 cam->cam_mode = vga_mode; 602 cam->nmodes = ARRAY_SIZE(vga_mode); 603 break; 604 case BRIDGE_SPCA533: 605 cam->cam_mode = custom_mode; 606 if (sd->subtype == MegaImageVI) /* 320x240 only */ 607 cam->nmodes = ARRAY_SIZE(custom_mode) - 1; 608 else 609 cam->nmodes = ARRAY_SIZE(custom_mode); 610 break; 611 case BRIDGE_SPCA504C: 612 cam->cam_mode = vga_mode2; 613 cam->nmodes = ARRAY_SIZE(vga_mode2); 614 break; 615 } 616 return 0; 617 } 618 619 /* this function is called at probe and resume time */ 620 static int sd_init(struct gspca_dev *gspca_dev) 621 { 622 struct sd *sd = (struct sd *) gspca_dev; 623 624 switch (sd->bridge) { 625 case BRIDGE_SPCA504B: 626 reg_w_riv(gspca_dev, 0x1d, 0x00, 0); 627 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01); 628 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00); 629 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00); 630 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13); 631 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00); 632 /* fall through */ 633 case BRIDGE_SPCA533: 634 spca504B_PollingDataReady(gspca_dev); 635 spca50x_GetFirmware(gspca_dev); 636 break; 637 case BRIDGE_SPCA536: 638 spca50x_GetFirmware(gspca_dev); 639 reg_r(gspca_dev, 0x00, 0x5002, 1); 640 reg_w_1(gspca_dev, 0x24, 0, 0, 0); 641 reg_r(gspca_dev, 0x24, 0, 1); 642 spca504B_PollingDataReady(gspca_dev); 643 reg_w_riv(gspca_dev, 0x34, 0, 0); 644 spca504B_WaitCmdStatus(gspca_dev); 645 break; 646 case BRIDGE_SPCA504C: /* pccam600 */ 647 gspca_dbg(gspca_dev, D_STREAM, "Opening SPCA504 (PC-CAM 600)\n"); 648 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000); 649 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */ 650 spca504_wait_status(gspca_dev); 651 if (sd->subtype == LogitechClickSmart420) 652 write_vector(gspca_dev, 653 spca504A_clicksmart420_open_data, 654 ARRAY_SIZE(spca504A_clicksmart420_open_data)); 655 else 656 write_vector(gspca_dev, spca504_pccam600_open_data, 657 ARRAY_SIZE(spca504_pccam600_open_data)); 658 setup_qtable(gspca_dev, qtable_creative_pccam); 659 break; 660 default: 661 /* case BRIDGE_SPCA504: */ 662 gspca_dbg(gspca_dev, D_STREAM, "Opening SPCA504\n"); 663 if (sd->subtype == AiptekMiniPenCam13) { 664 spca504_read_info(gspca_dev); 665 666 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ 667 spca504A_acknowledged_command(gspca_dev, 0x24, 668 8, 3, 0x9e, 1); 669 /* Twice sequential need status 0xff->0x9e->0x9d */ 670 spca504A_acknowledged_command(gspca_dev, 0x24, 671 8, 3, 0x9e, 0); 672 673 spca504A_acknowledged_command(gspca_dev, 0x24, 674 0, 0, 0x9d, 1); 675 /******************************/ 676 /* spca504a aiptek */ 677 spca504A_acknowledged_command(gspca_dev, 0x08, 678 6, 0, 0x86, 1); 679 /* reg_write (dev, 0, 0x2000, 0); */ 680 /* reg_write (dev, 0, 0x2883, 1); */ 681 /* spca504A_acknowledged_command (gspca_dev, 0x08, 682 6, 0, 0x86, 1); */ 683 /* spca504A_acknowledged_command (gspca_dev, 0x24, 684 0, 0, 0x9D, 1); */ 685 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05); 686 /* L92 sno1t.txt */ 687 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05); 688 spca504A_acknowledged_command(gspca_dev, 0x01, 689 0x0f, 0, 0xff, 0); 690 } 691 /* setup qtable */ 692 reg_w_riv(gspca_dev, 0, 0x2000, 0); 693 reg_w_riv(gspca_dev, 0, 0x2883, 1); 694 setup_qtable(gspca_dev, qtable_spca504_default); 695 break; 696 } 697 return gspca_dev->usb_err; 698 } 699 700 static int sd_start(struct gspca_dev *gspca_dev) 701 { 702 struct sd *sd = (struct sd *) gspca_dev; 703 int enable; 704 705 /* create the JPEG header */ 706 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height, 707 gspca_dev->pixfmt.width, 708 0x22); /* JPEG 411 */ 709 jpeg_set_qual(sd->jpeg_hdr, QUALITY); 710 711 if (sd->bridge == BRIDGE_SPCA504B) 712 spca504B_setQtable(gspca_dev); 713 spca504B_SetSizeType(gspca_dev); 714 switch (sd->bridge) { 715 default: 716 /* case BRIDGE_SPCA504B: */ 717 /* case BRIDGE_SPCA533: */ 718 /* case BRIDGE_SPCA536: */ 719 switch (sd->subtype) { 720 case MegapixV4: 721 case LogitechClickSmart820: 722 case MegaImageVI: 723 reg_w_riv(gspca_dev, 0xf0, 0, 0); 724 spca504B_WaitCmdStatus(gspca_dev); 725 reg_r(gspca_dev, 0xf0, 4, 0); 726 spca504B_WaitCmdStatus(gspca_dev); 727 break; 728 default: 729 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00); 730 spca504B_WaitCmdStatus(gspca_dev); 731 spca504B_PollingDataReady(gspca_dev); 732 break; 733 } 734 break; 735 case BRIDGE_SPCA504: 736 if (sd->subtype == AiptekMiniPenCam13) { 737 spca504_read_info(gspca_dev); 738 739 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ 740 spca504A_acknowledged_command(gspca_dev, 0x24, 741 8, 3, 0x9e, 1); 742 /* Twice sequential need status 0xff->0x9e->0x9d */ 743 spca504A_acknowledged_command(gspca_dev, 0x24, 744 8, 3, 0x9e, 0); 745 spca504A_acknowledged_command(gspca_dev, 0x24, 746 0, 0, 0x9d, 1); 747 } else { 748 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); 749 spca504_read_info(gspca_dev); 750 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); 751 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); 752 } 753 spca504B_SetSizeType(gspca_dev); 754 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05); 755 /* L92 sno1t.txt */ 756 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05); 757 break; 758 case BRIDGE_SPCA504C: 759 if (sd->subtype == LogitechClickSmart420) { 760 write_vector(gspca_dev, 761 spca504A_clicksmart420_init_data, 762 ARRAY_SIZE(spca504A_clicksmart420_init_data)); 763 } else { 764 write_vector(gspca_dev, spca504_pccam600_init_data, 765 ARRAY_SIZE(spca504_pccam600_init_data)); 766 } 767 enable = (sd->autogain ? 0x04 : 0x01); 768 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable); 769 /* auto exposure */ 770 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable); 771 /* auto whiteness */ 772 773 /* set default exposure compensation and whiteness balance */ 774 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */ 775 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600); 776 spca504B_SetSizeType(gspca_dev); 777 break; 778 } 779 init_ctl_reg(gspca_dev); 780 return gspca_dev->usb_err; 781 } 782 783 static void sd_stopN(struct gspca_dev *gspca_dev) 784 { 785 struct sd *sd = (struct sd *) gspca_dev; 786 787 switch (sd->bridge) { 788 default: 789 /* case BRIDGE_SPCA533: */ 790 /* case BRIDGE_SPCA536: */ 791 /* case BRIDGE_SPCA504B: */ 792 reg_w_riv(gspca_dev, 0x31, 0, 0); 793 spca504B_WaitCmdStatus(gspca_dev); 794 spca504B_PollingDataReady(gspca_dev); 795 break; 796 case BRIDGE_SPCA504: 797 case BRIDGE_SPCA504C: 798 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000); 799 800 if (sd->subtype == AiptekMiniPenCam13) { 801 /* spca504a aiptek */ 802 /* spca504A_acknowledged_command(gspca_dev, 0x08, 803 6, 0, 0x86, 1); */ 804 spca504A_acknowledged_command(gspca_dev, 0x24, 805 0x00, 0x00, 0x9d, 1); 806 spca504A_acknowledged_command(gspca_dev, 0x01, 807 0x0f, 0x00, 0xff, 1); 808 } else { 809 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); 810 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000); 811 } 812 break; 813 } 814 } 815 816 static void sd_pkt_scan(struct gspca_dev *gspca_dev, 817 u8 *data, /* isoc packet */ 818 int len) /* iso packet length */ 819 { 820 struct sd *sd = (struct sd *) gspca_dev; 821 int i, sof = 0; 822 static u8 ffd9[] = {0xff, 0xd9}; 823 824 /* frames are jpeg 4.1.1 without 0xff escape */ 825 switch (sd->bridge) { 826 case BRIDGE_SPCA533: 827 if (data[0] == 0xff) { 828 if (data[1] != 0x01) { /* drop packet */ 829 /* gspca_dev->last_packet_type = DISCARD_PACKET; */ 830 return; 831 } 832 sof = 1; 833 data += SPCA533_OFFSET_DATA; 834 len -= SPCA533_OFFSET_DATA; 835 } else { 836 data += 1; 837 len -= 1; 838 } 839 break; 840 case BRIDGE_SPCA536: 841 if (data[0] == 0xff) { 842 sof = 1; 843 data += SPCA536_OFFSET_DATA; 844 len -= SPCA536_OFFSET_DATA; 845 } else { 846 data += 2; 847 len -= 2; 848 } 849 break; 850 default: 851 /* case BRIDGE_SPCA504: */ 852 /* case BRIDGE_SPCA504B: */ 853 switch (data[0]) { 854 case 0xfe: /* start of frame */ 855 sof = 1; 856 data += SPCA50X_OFFSET_DATA; 857 len -= SPCA50X_OFFSET_DATA; 858 break; 859 case 0xff: /* drop packet */ 860 /* gspca_dev->last_packet_type = DISCARD_PACKET; */ 861 return; 862 default: 863 data += 1; 864 len -= 1; 865 break; 866 } 867 break; 868 case BRIDGE_SPCA504C: 869 switch (data[0]) { 870 case 0xfe: /* start of frame */ 871 sof = 1; 872 data += SPCA504_PCCAM600_OFFSET_DATA; 873 len -= SPCA504_PCCAM600_OFFSET_DATA; 874 break; 875 case 0xff: /* drop packet */ 876 /* gspca_dev->last_packet_type = DISCARD_PACKET; */ 877 return; 878 default: 879 data += 1; 880 len -= 1; 881 break; 882 } 883 break; 884 } 885 if (sof) { /* start of frame */ 886 gspca_frame_add(gspca_dev, LAST_PACKET, 887 ffd9, 2); 888 889 /* put the JPEG header in the new frame */ 890 gspca_frame_add(gspca_dev, FIRST_PACKET, 891 sd->jpeg_hdr, JPEG_HDR_SZ); 892 } 893 894 /* add 0x00 after 0xff */ 895 i = 0; 896 do { 897 if (data[i] == 0xff) { 898 gspca_frame_add(gspca_dev, INTER_PACKET, 899 data, i + 1); 900 len -= i; 901 data += i; 902 *data = 0x00; 903 i = 0; 904 } 905 i++; 906 } while (i < len); 907 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 908 } 909 910 static int sd_s_ctrl(struct v4l2_ctrl *ctrl) 911 { 912 struct gspca_dev *gspca_dev = 913 container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 914 struct sd *sd = (struct sd *)gspca_dev; 915 916 gspca_dev->usb_err = 0; 917 918 if (!gspca_dev->streaming) 919 return 0; 920 921 switch (ctrl->id) { 922 case V4L2_CID_BRIGHTNESS: 923 setbrightness(gspca_dev, ctrl->val); 924 break; 925 case V4L2_CID_CONTRAST: 926 setcontrast(gspca_dev, ctrl->val); 927 break; 928 case V4L2_CID_SATURATION: 929 setcolors(gspca_dev, ctrl->val); 930 break; 931 case V4L2_CID_AUTOGAIN: 932 sd->autogain = ctrl->val; 933 break; 934 } 935 return gspca_dev->usb_err; 936 } 937 938 static const struct v4l2_ctrl_ops sd_ctrl_ops = { 939 .s_ctrl = sd_s_ctrl, 940 }; 941 942 static int sd_init_controls(struct gspca_dev *gspca_dev) 943 { 944 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 945 946 gspca_dev->vdev.ctrl_handler = hdl; 947 v4l2_ctrl_handler_init(hdl, 4); 948 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 949 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); 950 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 951 V4L2_CID_CONTRAST, 0, 255, 1, 0x20); 952 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 953 V4L2_CID_SATURATION, 0, 255, 1, 0x1a); 954 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 955 V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 956 957 if (hdl->error) { 958 pr_err("Could not initialize controls\n"); 959 return hdl->error; 960 } 961 return 0; 962 } 963 964 /* sub-driver description */ 965 static const struct sd_desc sd_desc = { 966 .name = MODULE_NAME, 967 .config = sd_config, 968 .init = sd_init, 969 .init_controls = sd_init_controls, 970 .start = sd_start, 971 .stopN = sd_stopN, 972 .pkt_scan = sd_pkt_scan, 973 }; 974 975 /* -- module initialisation -- */ 976 #define BS(bridge, subtype) \ 977 .driver_info = (BRIDGE_ ## bridge << 8) \ 978 | (subtype) 979 static const struct usb_device_id device_table[] = { 980 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)}, 981 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)}, 982 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)}, 983 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)}, 984 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)}, 985 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)}, 986 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)}, 987 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)}, 988 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)}, 989 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)}, 990 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)}, 991 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)}, 992 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)}, 993 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)}, 994 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)}, 995 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)}, 996 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)}, 997 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)}, 998 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)}, 999 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)}, 1000 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)}, 1001 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)}, 1002 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)}, 1003 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)}, 1004 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)}, 1005 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)}, 1006 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)}, 1007 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)}, 1008 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)}, 1009 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)}, 1010 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)}, 1011 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)}, 1012 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)}, 1013 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)}, 1014 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)}, 1015 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)}, 1016 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)}, 1017 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)}, 1018 {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)}, 1019 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)}, 1020 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)}, 1021 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)}, 1022 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)}, 1023 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)}, 1024 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)}, 1025 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)}, 1026 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)}, 1027 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)}, 1028 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)}, 1029 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)}, 1030 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)}, 1031 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)}, 1032 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)}, 1033 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)}, 1034 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)}, 1035 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)}, 1036 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)}, 1037 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)}, 1038 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)}, 1039 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)}, 1040 {} 1041 }; 1042 MODULE_DEVICE_TABLE(usb, device_table); 1043 1044 /* -- device connect -- */ 1045 static int sd_probe(struct usb_interface *intf, 1046 const struct usb_device_id *id) 1047 { 1048 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 1049 THIS_MODULE); 1050 } 1051 1052 static struct usb_driver sd_driver = { 1053 .name = MODULE_NAME, 1054 .id_table = device_table, 1055 .probe = sd_probe, 1056 .disconnect = gspca_disconnect, 1057 #ifdef CONFIG_PM 1058 .suspend = gspca_suspend, 1059 .resume = gspca_resume, 1060 .reset_resume = gspca_resume, 1061 #endif 1062 }; 1063 1064 module_usb_driver(sd_driver); 1065