1822 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ov534-ov9xxx gspca driver4 *5 * Copyright (C) 2009-2011 Jean-Francois Moine http://moinejf.free.fr6 * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>7 * Copyright (C) 2008 Jim Paris <jim@jtan.com>8 *9 * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>10 * USB protocol reverse engineered by Jim Paris <jim@jtan.com>11 * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/12 */13 14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt15 16#define MODULE_NAME "ov534_9"17 18#include "gspca.h"19 20#define OV534_REG_ADDRESS 0xf1 /* sensor address */21#define OV534_REG_SUBADDR 0xf222#define OV534_REG_WRITE 0xf323#define OV534_REG_READ 0xf424#define OV534_REG_OPERATION 0xf525#define OV534_REG_STATUS 0xf626 27#define OV534_OP_WRITE_3 0x3728#define OV534_OP_WRITE_2 0x3329#define OV534_OP_READ_2 0xf930 31#define CTRL_TIMEOUT 50032 33MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");34MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");35MODULE_LICENSE("GPL");36 37/* specific webcam descriptor */38struct sd {39 struct gspca_dev gspca_dev; /* !! must be the first item */40 __u32 last_pts;41 u8 last_fid;42 43 u8 sensor;44};45enum sensors {46 SENSOR_OV965x, /* ov9657 */47 SENSOR_OV971x, /* ov9712 */48 SENSOR_OV562x, /* ov5621 */49 SENSOR_OV361x, /* ov3610 */50 NSENSORS51};52 53static const struct v4l2_pix_format ov965x_mode[] = {54#define QVGA_MODE 055 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,56 .bytesperline = 320,57 .sizeimage = 320 * 240 * 3 / 8 + 590,58 .colorspace = V4L2_COLORSPACE_JPEG},59#define VGA_MODE 160 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,61 .bytesperline = 640,62 .sizeimage = 640 * 480 * 3 / 8 + 590,63 .colorspace = V4L2_COLORSPACE_JPEG},64#define SVGA_MODE 265 {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,66 .bytesperline = 800,67 .sizeimage = 800 * 600 * 3 / 8 + 590,68 .colorspace = V4L2_COLORSPACE_JPEG},69#define XGA_MODE 370 {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,71 .bytesperline = 1024,72 .sizeimage = 1024 * 768 * 3 / 8 + 590,73 .colorspace = V4L2_COLORSPACE_JPEG},74#define SXGA_MODE 475 {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,76 .bytesperline = 1280,77 .sizeimage = 1280 * 1024 * 3 / 8 + 590,78 .colorspace = V4L2_COLORSPACE_JPEG},79};80 81static const struct v4l2_pix_format ov971x_mode[] = {82 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,83 .bytesperline = 640,84 .sizeimage = 640 * 480,85 .colorspace = V4L2_COLORSPACE_SRGB86 }87};88 89static const struct v4l2_pix_format ov562x_mode[] = {90 {2592, 1680, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,91 .bytesperline = 2592,92 .sizeimage = 2592 * 1680,93 .colorspace = V4L2_COLORSPACE_SRGB94 }95};96 97enum ov361x {98 ov361x_2048 = 0,99 ov361x_1600,100 ov361x_1024,101 ov361x_640,102 ov361x_320,103 ov361x_160,104 ov361x_last105};106 107static const struct v4l2_pix_format ov361x_mode[] = {108 {0x800, 0x600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,109 .bytesperline = 0x800,110 .sizeimage = 0x800 * 0x600,111 .colorspace = V4L2_COLORSPACE_SRGB},112 {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,113 .bytesperline = 1600,114 .sizeimage = 1600 * 1200,115 .colorspace = V4L2_COLORSPACE_SRGB},116 {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,117 .bytesperline = 768,118 .sizeimage = 1024 * 768,119 .colorspace = V4L2_COLORSPACE_SRGB},120 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,121 .bytesperline = 640,122 .sizeimage = 640 * 480,123 .colorspace = V4L2_COLORSPACE_SRGB},124 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,125 .bytesperline = 320,126 .sizeimage = 320 * 240,127 .colorspace = V4L2_COLORSPACE_SRGB},128 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,129 .bytesperline = 160,130 .sizeimage = 160 * 120,131 .colorspace = V4L2_COLORSPACE_SRGB}132};133 134static const u8 ov361x_start_2048[][2] = {135 {0x12, 0x80},136 {0x13, 0xcf},137 {0x14, 0x40},138 {0x15, 0x00},139 {0x01, 0x80},140 {0x02, 0x80},141 {0x04, 0x70},142 {0x0d, 0x40},143 {0x0f, 0x47},144 {0x11, 0x81},145 {0x32, 0x36},146 {0x33, 0x0c},147 {0x34, 0x00},148 {0x35, 0x90},149 {0x12, 0x00},150 {0x17, 0x10},151 {0x18, 0x90},152 {0x19, 0x00},153 {0x1a, 0xc0},154};155static const u8 ov361x_bridge_start_2048[][2] = {156 {0xf1, 0x60},157 {0x88, 0x00},158 {0x89, 0x08},159 {0x8a, 0x00},160 {0x8b, 0x06},161 {0x8c, 0x01},162 {0x8d, 0x10},163 {0x1c, 0x00},164 {0x1d, 0x48},165 {0x1d, 0x00},166 {0x1d, 0xff},167 {0x1c, 0x0a},168 {0x1d, 0x2e},169 {0x1d, 0x1e},170};171 172static const u8 ov361x_start_1600[][2] = {173 {0x12, 0x80},174 {0x13, 0xcf},175 {0x14, 0x40},176 {0x15, 0x00},177 {0x01, 0x80},178 {0x02, 0x80},179 {0x04, 0x70},180 {0x0d, 0x40},181 {0x0f, 0x47},182 {0x11, 0x81},183 {0x32, 0x36},184 {0x33, 0x0C},185 {0x34, 0x00},186 {0x35, 0x90},187 {0x12, 0x00},188 {0x17, 0x10},189 {0x18, 0x90},190 {0x19, 0x00},191 {0x1a, 0xc0},192};193static const u8 ov361x_bridge_start_1600[][2] = {194 {0xf1, 0x60}, /* Hsize[7:0] */195 {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */196 {0x89, 0x08}, /* Vsize[7:0] */197 {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */198 {0x8b, 0x06}, /* for Iso */199 {0x8c, 0x01}, /* RAW input */200 {0x8d, 0x10},201 {0x1c, 0x00}, /* RAW output, Iso transfer */202 {0x1d, 0x48},203 {0x1d, 0x00},204 {0x1d, 0xff},205 {0x1c, 0x0a}, /* turn off JPEG, Iso mode */206 {0x1d, 0x2e}, /* for Iso */207 {0x1d, 0x1e},208};209 210static const u8 ov361x_start_1024[][2] = {211 {0x12, 0x80},212 {0x13, 0xcf},213 {0x14, 0x40},214 {0x15, 0x00},215 {0x01, 0x80},216 {0x02, 0x80},217 {0x04, 0x70},218 {0x0d, 0x40},219 {0x0f, 0x47},220 {0x11, 0x81},221 {0x32, 0x36},222 {0x33, 0x0C},223 {0x34, 0x00},224 {0x35, 0x90},225 {0x12, 0x40},226 {0x17, 0x1f},227 {0x18, 0x5f},228 {0x19, 0x00},229 {0x1a, 0x68},230};231static const u8 ov361x_bridge_start_1024[][2] = {232 {0xf1, 0x60}, /* Hsize[7:0] */233 {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */234 {0x89, 0x04}, /* Vsize[7:0] */235 {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */236 {0x8b, 0x03}, /* for Iso */237 {0x8c, 0x01}, /* RAW input */238 {0x8d, 0x10},239 {0x1c, 0x00}, /* RAW output, Iso transfer */240 {0x1d, 0x48},241 {0x1d, 0x00},242 {0x1d, 0xff},243 {0x1c, 0x0a}, /* turn off JPEG, Iso mode */244 {0x1d, 0x2e}, /* for Iso */245 {0x1d, 0x1e},246};247 248static const u8 ov361x_start_640[][2] = {249 {0x12, 0x80},250 {0x13, 0xcf},251 {0x14, 0x40},252 {0x15, 0x00},253 {0x01, 0x80},254 {0x02, 0x80},255 {0x04, 0x70},256 {0x0d, 0x40},257 {0x0f, 0x47},258 {0x11, 0x81},259 {0x32, 0x36},260 {0x33, 0x0C},261 {0x34, 0x00},262 {0x35, 0x90},263 {0x12, 0x40},264 {0x17, 0x1f},265 {0x18, 0x5f},266 {0x19, 0x00},267 {0x1a, 0x68},268};269 270static const u8 ov361x_bridge_start_640[][2] = {271 {0xf1, 0x60}, /* Hsize[7:0]*/272 {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */273 {0x89, 0x04}, /* Vsize[7:0] */274 {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */275 {0x8b, 0x03}, /* for Iso */276 {0x8c, 0x01}, /* RAW input */277 {0x8d, 0x10},278 {0x1c, 0x00}, /* RAW output, Iso transfer */279 {0x1d, 0x48},280 {0x1d, 0x00},281 {0x1d, 0xff},282 {0x1c, 0x0a}, /* turn off JPEG, Iso mode */283 {0x1d, 0x2e}, /* for Iso */284 {0x1d, 0x1e},285};286 287static const u8 ov361x_start_320[][2] = {288 {0x12, 0x80},289 {0x13, 0xcf},290 {0x14, 0x40},291 {0x15, 0x00},292 {0x01, 0x80},293 {0x02, 0x80},294 {0x04, 0x70},295 {0x0d, 0x40},296 {0x0f, 0x47},297 {0x11, 0x81},298 {0x32, 0x36},299 {0x33, 0x0C},300 {0x34, 0x00},301 {0x35, 0x90},302 {0x12, 0x40},303 {0x17, 0x1f},304 {0x18, 0x5f},305 {0x19, 0x00},306 {0x1a, 0x68},307};308 309static const u8 ov361x_bridge_start_320[][2] = {310 {0xf1, 0x60}, /* Hsize[7:0] */311 {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */312 {0x89, 0x04}, /* Vsize[7:0] */313 {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */314 {0x8b, 0x03}, /* for Iso */315 {0x8c, 0x01}, /* RAW input */316 {0x8d, 0x10},317 {0x1c, 0x00}, /* RAW output, Iso transfer; */318 {0x1d, 0x48},319 {0x1d, 0x00},320 {0x1d, 0xff},321 {0x1c, 0x0a}, /* turn off JPEG, Iso mode */322 {0x1d, 0x2e}, /* for Iso */323 {0x1d, 0x1e},324};325 326static const u8 ov361x_start_160[][2] = {327 {0x12, 0x80},328 {0x13, 0xcf},329 {0x14, 0x40},330 {0x15, 0x00},331 {0x01, 0x80},332 {0x02, 0x80},333 {0x04, 0x70},334 {0x0d, 0x40},335 {0x0f, 0x47},336 {0x11, 0x81},337 {0x32, 0x36},338 {0x33, 0x0C},339 {0x34, 0x00},340 {0x35, 0x90},341 {0x12, 0x40},342 {0x17, 0x1f},343 {0x18, 0x5f},344 {0x19, 0x00},345 {0x1a, 0x68},346};347 348static const u8 ov361x_bridge_start_160[][2] = {349 {0xf1, 0x60}, /* Hsize[7:0] */350 {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */351 {0x89, 0x04}, /* Vsize[7:0] */352 {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */353 {0x8b, 0x03}, /* for Iso */354 {0x8c, 0x01}, /* RAW input */355 {0x8d, 0x10},356 {0x1c, 0x00}, /* RAW output, Iso transfer */357 {0x1d, 0x48},358 {0x1d, 0x00},359 {0x1d, 0xff},360 {0x1c, 0x0a}, /* turn off JPEG, Iso mode */361 {0x1d, 0x2e}, /* for Iso */362 {0x1d, 0x1e},363};364 365static const u8 bridge_init[][2] = {366 {0x88, 0xf8},367 {0x89, 0xff},368 {0x76, 0x03},369 {0x92, 0x03},370 {0x95, 0x10},371 {0xe2, 0x00},372 {0xe7, 0x3e},373 {0x8d, 0x1c},374 {0x8e, 0x00},375 {0x8f, 0x00},376 {0x1f, 0x00},377 {0xc3, 0xf9},378 {0x89, 0xff},379 {0x88, 0xf8},380 {0x76, 0x03},381 {0x92, 0x01},382 {0x93, 0x18},383 {0x1c, 0x0a},384 {0x1d, 0x48},385 {0xc0, 0x50},386 {0xc1, 0x3c},387 {0x34, 0x05},388 {0xc2, 0x0c},389 {0xc3, 0xf9},390 {0x34, 0x05},391 {0xe7, 0x2e},392 {0x31, 0xf9},393 {0x35, 0x02},394 {0xd9, 0x10},395 {0x25, 0x42},396 {0x94, 0x11},397};398 399static const u8 ov965x_init[][2] = {400 {0x12, 0x80}, /* com7 - SSCB reset */401 {0x00, 0x00}, /* gain */402 {0x01, 0x80}, /* blue */403 {0x02, 0x80}, /* red */404 {0x03, 0x1b}, /* vref */405 {0x04, 0x03}, /* com1 - exposure low bits */406 {0x0b, 0x57}, /* ver */407 {0x0e, 0x61}, /* com5 */408 {0x0f, 0x42}, /* com6 */409 {0x11, 0x00}, /* clkrc */410 {0x12, 0x02}, /* com7 - 15fps VGA YUYV */411 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */412 {0x14, 0x28}, /* com9 */413 {0x16, 0x24}, /* reg16 */414 {0x17, 0x1d}, /* hstart*/415 {0x18, 0xbd}, /* hstop */416 {0x19, 0x01}, /* vstrt */417 {0x1a, 0x81}, /* vstop*/418 {0x1e, 0x04}, /* mvfp */419 {0x24, 0x3c}, /* aew */420 {0x25, 0x36}, /* aeb */421 {0x26, 0x71}, /* vpt */422 {0x27, 0x08}, /* bbias */423 {0x28, 0x08}, /* gbbias */424 {0x29, 0x15}, /* gr com */425 {0x2a, 0x00}, /* exhch */426 {0x2b, 0x00}, /* exhcl */427 {0x2c, 0x08}, /* rbias */428 {0x32, 0xff}, /* href */429 {0x33, 0x00}, /* chlf */430 {0x34, 0x3f}, /* aref1 */431 {0x35, 0x00}, /* aref2 */432 {0x36, 0xf8}, /* aref3 */433 {0x38, 0x72}, /* adc2 */434 {0x39, 0x57}, /* aref4 */435 {0x3a, 0x80}, /* tslb - yuyv */436 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */437 {0x3d, 0x99}, /* com13 */438 {0x3f, 0xc1}, /* edge */439 {0x40, 0xc0}, /* com15 */440 {0x41, 0x40}, /* com16 */441 {0x42, 0xc0}, /* com17 */442 {0x43, 0x0a}, /* rsvd */443 {0x44, 0xf0},444 {0x45, 0x46},445 {0x46, 0x62},446 {0x47, 0x2a},447 {0x48, 0x3c},448 {0x4a, 0xfc},449 {0x4b, 0xfc},450 {0x4c, 0x7f},451 {0x4d, 0x7f},452 {0x4e, 0x7f},453 {0x4f, 0x98}, /* matrix */454 {0x50, 0x98},455 {0x51, 0x00},456 {0x52, 0x28},457 {0x53, 0x70},458 {0x54, 0x98},459 {0x58, 0x1a}, /* matrix coef sign */460 {0x59, 0x85}, /* AWB control */461 {0x5a, 0xa9},462 {0x5b, 0x64},463 {0x5c, 0x84},464 {0x5d, 0x53},465 {0x5e, 0x0e},466 {0x5f, 0xf0}, /* AWB blue limit */467 {0x60, 0xf0}, /* AWB red limit */468 {0x61, 0xf0}, /* AWB green limit */469 {0x62, 0x00}, /* lcc1 */470 {0x63, 0x00}, /* lcc2 */471 {0x64, 0x02}, /* lcc3 */472 {0x65, 0x16}, /* lcc4 */473 {0x66, 0x01}, /* lcc5 */474 {0x69, 0x02}, /* hv */475 {0x6b, 0x5a}, /* dbvl */476 {0x6c, 0x04},477 {0x6d, 0x55},478 {0x6e, 0x00},479 {0x6f, 0x9d},480 {0x70, 0x21}, /* dnsth */481 {0x71, 0x78},482 {0x72, 0x00}, /* poidx */483 {0x73, 0x01}, /* pckdv */484 {0x74, 0x3a}, /* xindx */485 {0x75, 0x35}, /* yindx */486 {0x76, 0x01},487 {0x77, 0x02},488 {0x7a, 0x12}, /* gamma curve */489 {0x7b, 0x08},490 {0x7c, 0x16},491 {0x7d, 0x30},492 {0x7e, 0x5e},493 {0x7f, 0x72},494 {0x80, 0x82},495 {0x81, 0x8e},496 {0x82, 0x9a},497 {0x83, 0xa4},498 {0x84, 0xac},499 {0x85, 0xb8},500 {0x86, 0xc3},501 {0x87, 0xd6},502 {0x88, 0xe6},503 {0x89, 0xf2},504 {0x8a, 0x03},505 {0x8c, 0x89}, /* com19 */506 {0x14, 0x28}, /* com9 */507 {0x90, 0x7d},508 {0x91, 0x7b},509 {0x9d, 0x03}, /* lcc6 */510 {0x9e, 0x04}, /* lcc7 */511 {0x9f, 0x7a},512 {0xa0, 0x79},513 {0xa1, 0x40}, /* aechm */514 {0xa4, 0x50}, /* com21 */515 {0xa5, 0x68}, /* com26 */516 {0xa6, 0x4a}, /* AWB green */517 {0xa8, 0xc1}, /* refa8 */518 {0xa9, 0xef}, /* refa9 */519 {0xaa, 0x92},520 {0xab, 0x04},521 {0xac, 0x80}, /* black level control */522 {0xad, 0x80},523 {0xae, 0x80},524 {0xaf, 0x80},525 {0xb2, 0xf2},526 {0xb3, 0x20},527 {0xb4, 0x20}, /* ctrlb4 */528 {0xb5, 0x00},529 {0xb6, 0xaf},530 {0xbb, 0xae},531 {0xbc, 0x7f}, /* ADC channel offsets */532 {0xdb, 0x7f},533 {0xbe, 0x7f},534 {0xbf, 0x7f},535 {0xc0, 0xe2},536 {0xc1, 0xc0},537 {0xc2, 0x01},538 {0xc3, 0x4e},539 {0xc6, 0x85},540 {0xc7, 0x80}, /* com24 */541 {0xc9, 0xe0},542 {0xca, 0xe8},543 {0xcb, 0xf0},544 {0xcc, 0xd8},545 {0xcd, 0xf1},546 {0x4f, 0x98}, /* matrix */547 {0x50, 0x98},548 {0x51, 0x00},549 {0x52, 0x28},550 {0x53, 0x70},551 {0x54, 0x98},552 {0x58, 0x1a},553 {0xff, 0x41}, /* read 41, write ff 00 */554 {0x41, 0x40}, /* com16 */555 556 {0xc5, 0x03}, /* 60 Hz banding filter */557 {0x6a, 0x02}, /* 50 Hz banding filter */558 559 {0x12, 0x62}, /* com7 - 30fps VGA YUV */560 {0x36, 0xfa}, /* aref3 */561 {0x69, 0x0a}, /* hv */562 {0x8c, 0x89}, /* com22 */563 {0x14, 0x28}, /* com9 */564 {0x3e, 0x0c},565 {0x41, 0x40}, /* com16 */566 {0x72, 0x00},567 {0x73, 0x00},568 {0x74, 0x3a},569 {0x75, 0x35},570 {0x76, 0x01},571 {0xc7, 0x80},572 {0x03, 0x12}, /* vref */573 {0x17, 0x16}, /* hstart */574 {0x18, 0x02}, /* hstop */575 {0x19, 0x01}, /* vstrt */576 {0x1a, 0x3d}, /* vstop */577 {0x32, 0xff}, /* href */578 {0xc0, 0xaa},579};580 581static const u8 bridge_init_2[][2] = {582 {0x94, 0xaa},583 {0xf1, 0x60},584 {0xe5, 0x04},585 {0xc0, 0x50},586 {0xc1, 0x3c},587 {0x8c, 0x00},588 {0x8d, 0x1c},589 {0x34, 0x05},590 591 {0xc2, 0x0c},592 {0xc3, 0xf9},593 {0xda, 0x01},594 {0x50, 0x00},595 {0x51, 0xa0},596 {0x52, 0x3c},597 {0x53, 0x00},598 {0x54, 0x00},599 {0x55, 0x00},600 {0x57, 0x00},601 {0x5c, 0x00},602 {0x5a, 0xa0},603 {0x5b, 0x78},604 {0x35, 0x02},605 {0xd9, 0x10},606 {0x94, 0x11},607};608 609static const u8 ov965x_init_2[][2] = {610 {0x3b, 0xc4},611 {0x1e, 0x04}, /* mvfp */612 {0x13, 0xe0}, /* com8 */613 {0x00, 0x00}, /* gain */614 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */615 {0x11, 0x03}, /* clkrc */616 {0x6b, 0x5a}, /* dblv */617 {0x6a, 0x05},618 {0xc5, 0x07},619 {0xa2, 0x4b},620 {0xa3, 0x3e},621 {0x2d, 0x00},622 {0xff, 0x42}, /* read 42, write ff 00 */623 {0x42, 0xc0}, /* com17 */624 {0x2d, 0x00},625 {0xff, 0x42}, /* read 42, write ff 00 */626 {0x42, 0xc1}, /* com17 */627/* sharpness */628 {0x3f, 0x01},629 {0xff, 0x42}, /* read 42, write ff 00 */630 {0x42, 0xc1}, /* com17 */631/* saturation */632 {0x4f, 0x98}, /* matrix */633 {0x50, 0x98},634 {0x51, 0x00},635 {0x52, 0x28},636 {0x53, 0x70},637 {0x54, 0x98},638 {0x58, 0x1a},639 {0xff, 0x41}, /* read 41, write ff 00 */640 {0x41, 0x40}, /* com16 */641/* contrast */642 {0x56, 0x40},643/* brightness */644 {0x55, 0x8f},645/* expo */646 {0x10, 0x25}, /* aech - exposure high bits */647 {0xff, 0x13}, /* read 13, write ff 00 */648 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */649};650 651static const u8 ov971x_init[][2] = {652 {0x12, 0x80},653 {0x09, 0x10},654 {0x1e, 0x07},655 {0x5f, 0x18},656 {0x69, 0x04},657 {0x65, 0x2a},658 {0x68, 0x0a},659 {0x39, 0x28},660 {0x4d, 0x90},661 {0xc1, 0x80},662 {0x0c, 0x30},663 {0x6d, 0x02},664 {0x96, 0xf1},665 {0xbc, 0x68},666 {0x12, 0x00},667 {0x3b, 0x00},668 {0x97, 0x80},669 {0x17, 0x25},670 {0x18, 0xa2},671 {0x19, 0x01},672 {0x1a, 0xca},673 {0x03, 0x0a},674 {0x32, 0x07},675 {0x98, 0x40}, /*{0x98, 0x00},*/676 {0x99, 0xA0}, /*{0x99, 0x00},*/677 {0x9a, 0x01}, /*{0x9a, 0x00},*/678 {0x57, 0x00},679 {0x58, 0x78}, /*{0x58, 0xc8},*/680 {0x59, 0x50}, /*{0x59, 0xa0},*/681 {0x4c, 0x13},682 {0x4b, 0x36},683 {0x3d, 0x3c},684 {0x3e, 0x03},685 {0xbd, 0x50}, /*{0xbd, 0xa0},*/686 {0xbe, 0x78}, /*{0xbe, 0xc8},*/687 {0x4e, 0x55},688 {0x4f, 0x55},689 {0x50, 0x55},690 {0x51, 0x55},691 {0x24, 0x55},692 {0x25, 0x40},693 {0x26, 0xa1},694 {0x5c, 0x59},695 {0x5d, 0x00},696 {0x11, 0x00},697 {0x2a, 0x98},698 {0x2b, 0x06},699 {0x2d, 0x00},700 {0x2e, 0x00},701 {0x13, 0xa5},702 {0x14, 0x40},703 {0x4a, 0x00},704 {0x49, 0xce},705 {0x22, 0x03},706 {0x09, 0x00}707};708 709static const u8 ov965x_start_1_vga[][2] = { /* same for qvga */710 {0x12, 0x62}, /* com7 - 30fps VGA YUV */711 {0x36, 0xfa}, /* aref3 */712 {0x69, 0x0a}, /* hv */713 {0x8c, 0x89}, /* com22 */714 {0x14, 0x28}, /* com9 */715 {0x3e, 0x0c}, /* com14 */716 {0x41, 0x40}, /* com16 */717 {0x72, 0x00},718 {0x73, 0x00},719 {0x74, 0x3a},720 {0x75, 0x35},721 {0x76, 0x01},722 {0xc7, 0x80}, /* com24 */723 {0x03, 0x12}, /* vref */724 {0x17, 0x16}, /* hstart */725 {0x18, 0x02}, /* hstop */726 {0x19, 0x01}, /* vstrt */727 {0x1a, 0x3d}, /* vstop */728 {0x32, 0xff}, /* href */729 {0xc0, 0xaa},730};731 732static const u8 ov965x_start_1_svga[][2] = {733 {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */734 {0x36, 0xf8}, /* aref3 */735 {0x69, 0x02}, /* hv */736 {0x8c, 0x0d}, /* com22 */737 {0x3e, 0x0c}, /* com14 */738 {0x41, 0x40}, /* com16 */739 {0x72, 0x00},740 {0x73, 0x01},741 {0x74, 0x3a},742 {0x75, 0x35},743 {0x76, 0x01},744 {0xc7, 0x80}, /* com24 */745 {0x03, 0x1b}, /* vref */746 {0x17, 0x1d}, /* hstart */747 {0x18, 0xbd}, /* hstop */748 {0x19, 0x01}, /* vstrt */749 {0x1a, 0x81}, /* vstop */750 {0x32, 0xff}, /* href */751 {0xc0, 0xe2},752};753 754static const u8 ov965x_start_1_xga[][2] = {755 {0x12, 0x02}, /* com7 */756 {0x36, 0xf8}, /* aref3 */757 {0x69, 0x02}, /* hv */758 {0x8c, 0x89}, /* com22 */759 {0x14, 0x28}, /* com9 */760 {0x3e, 0x0c}, /* com14 */761 {0x41, 0x40}, /* com16 */762 {0x72, 0x00},763 {0x73, 0x01},764 {0x74, 0x3a},765 {0x75, 0x35},766 {0x76, 0x01},767 {0xc7, 0x80}, /* com24 */768 {0x03, 0x1b}, /* vref */769 {0x17, 0x1d}, /* hstart */770 {0x18, 0xbd}, /* hstop */771 {0x19, 0x01}, /* vstrt */772 {0x1a, 0x81}, /* vstop */773 {0x32, 0xff}, /* href */774 {0xc0, 0xe2},775};776 777static const u8 ov965x_start_1_sxga[][2] = {778 {0x12, 0x02}, /* com7 */779 {0x36, 0xf8}, /* aref3 */780 {0x69, 0x02}, /* hv */781 {0x8c, 0x89}, /* com22 */782 {0x14, 0x28}, /* com9 */783 {0x3e, 0x0c}, /* com14 */784 {0x41, 0x40}, /* com16 */785 {0x72, 0x00},786 {0x73, 0x01},787 {0x74, 0x3a},788 {0x75, 0x35},789 {0x76, 0x01},790 {0xc7, 0x80}, /* com24 */791 {0x03, 0x1b}, /* vref */792 {0x17, 0x1d}, /* hstart */793 {0x18, 0x02}, /* hstop */794 {0x19, 0x01}, /* vstrt */795 {0x1a, 0x81}, /* vstop */796 {0x32, 0xff}, /* href */797 {0xc0, 0xe2},798};799 800static const u8 bridge_start_qvga[][2] = {801 {0x94, 0xaa},802 {0xf1, 0x60},803 {0xe5, 0x04},804 {0xc0, 0x50},805 {0xc1, 0x3c},806 {0x8c, 0x00},807 {0x8d, 0x1c},808 {0x34, 0x05},809 810 {0xc2, 0x4c},811 {0xc3, 0xf9},812 {0xda, 0x00},813 {0x50, 0x00},814 {0x51, 0xa0},815 {0x52, 0x78},816 {0x53, 0x00},817 {0x54, 0x00},818 {0x55, 0x00},819 {0x57, 0x00},820 {0x5c, 0x00},821 {0x5a, 0x50},822 {0x5b, 0x3c},823 {0x35, 0x02},824 {0xd9, 0x10},825 {0x94, 0x11},826};827 828static const u8 bridge_start_vga[][2] = {829 {0x94, 0xaa},830 {0xf1, 0x60},831 {0xe5, 0x04},832 {0xc0, 0x50},833 {0xc1, 0x3c},834 {0x8c, 0x00},835 {0x8d, 0x1c},836 {0x34, 0x05},837 {0xc2, 0x0c},838 {0xc3, 0xf9},839 {0xda, 0x01},840 {0x50, 0x00},841 {0x51, 0xa0},842 {0x52, 0x3c},843 {0x53, 0x00},844 {0x54, 0x00},845 {0x55, 0x00},846 {0x57, 0x00},847 {0x5c, 0x00},848 {0x5a, 0xa0},849 {0x5b, 0x78},850 {0x35, 0x02},851 {0xd9, 0x10},852 {0x94, 0x11},853};854 855static const u8 bridge_start_svga[][2] = {856 {0x94, 0xaa},857 {0xf1, 0x60},858 {0xe5, 0x04},859 {0xc0, 0xa0},860 {0xc1, 0x80},861 {0x8c, 0x00},862 {0x8d, 0x1c},863 {0x34, 0x05},864 {0xc2, 0x4c},865 {0xc3, 0xf9},866 {0x50, 0x00},867 {0x51, 0x40},868 {0x52, 0x00},869 {0x53, 0x00},870 {0x54, 0x00},871 {0x55, 0x88},872 {0x57, 0x00},873 {0x5c, 0x00},874 {0x5a, 0xc8},875 {0x5b, 0x96},876 {0x35, 0x02},877 {0xd9, 0x10},878 {0xda, 0x00},879 {0x94, 0x11},880};881 882static const u8 bridge_start_xga[][2] = {883 {0x94, 0xaa},884 {0xf1, 0x60},885 {0xe5, 0x04},886 {0xc0, 0xa0},887 {0xc1, 0x80},888 {0x8c, 0x00},889 {0x8d, 0x1c},890 {0x34, 0x05},891 {0xc2, 0x4c},892 {0xc3, 0xf9},893 {0x50, 0x00},894 {0x51, 0x40},895 {0x52, 0x00},896 {0x53, 0x00},897 {0x54, 0x00},898 {0x55, 0x88},899 {0x57, 0x00},900 {0x5c, 0x01},901 {0x5a, 0x00},902 {0x5b, 0xc0},903 {0x35, 0x02},904 {0xd9, 0x10},905 {0xda, 0x01},906 {0x94, 0x11},907};908 909static const u8 bridge_start_sxga[][2] = {910 {0x94, 0xaa},911 {0xf1, 0x60},912 {0xe5, 0x04},913 {0xc0, 0xa0},914 {0xc1, 0x80},915 {0x8c, 0x00},916 {0x8d, 0x1c},917 {0x34, 0x05},918 {0xc2, 0x0c},919 {0xc3, 0xf9},920 {0xda, 0x00},921 {0x35, 0x02},922 {0xd9, 0x10},923 {0x94, 0x11},924};925 926static const u8 ov965x_start_2_qvga[][2] = {927 {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */928 {0x1e, 0x04}, /* mvfp */929 {0x13, 0xe0}, /* com8 */930 {0x00, 0x00},931 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */932 {0x11, 0x01}, /* clkrc */933 {0x6b, 0x5a}, /* dblv */934 {0x6a, 0x02}, /* 50 Hz banding filter */935 {0xc5, 0x03}, /* 60 Hz banding filter */936 {0xa2, 0x96}, /* bd50 */937 {0xa3, 0x7d}, /* bd60 */938 939 {0xff, 0x13}, /* read 13, write ff 00 */940 {0x13, 0xe7},941 {0x3a, 0x80}, /* tslb - yuyv */942};943 944static const u8 ov965x_start_2_vga[][2] = {945 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */946 {0x1e, 0x04}, /* mvfp */947 {0x13, 0xe0}, /* com8 */948 {0x00, 0x00},949 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */950 {0x11, 0x03}, /* clkrc */951 {0x6b, 0x5a}, /* dblv */952 {0x6a, 0x05}, /* 50 Hz banding filter */953 {0xc5, 0x07}, /* 60 Hz banding filter */954 {0xa2, 0x4b}, /* bd50 */955 {0xa3, 0x3e}, /* bd60 */956 957 {0x2d, 0x00}, /* advfl */958};959 960static const u8 ov965x_start_2_svga[][2] = { /* same for xga */961 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */962 {0x1e, 0x04}, /* mvfp */963 {0x13, 0xe0}, /* com8 */964 {0x00, 0x00},965 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */966 {0x11, 0x01}, /* clkrc */967 {0x6b, 0x5a}, /* dblv */968 {0x6a, 0x0c}, /* 50 Hz banding filter */969 {0xc5, 0x0f}, /* 60 Hz banding filter */970 {0xa2, 0x4e}, /* bd50 */971 {0xa3, 0x41}, /* bd60 */972};973 974static const u8 ov965x_start_2_sxga[][2] = {975 {0x13, 0xe0}, /* com8 */976 {0x00, 0x00},977 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */978 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */979 {0x1e, 0x04}, /* mvfp */980 {0x11, 0x01}, /* clkrc */981 {0x6b, 0x5a}, /* dblv */982 {0x6a, 0x0c}, /* 50 Hz banding filter */983 {0xc5, 0x0f}, /* 60 Hz banding filter */984 {0xa2, 0x4e}, /* bd50 */985 {0xa3, 0x41}, /* bd60 */986};987 988static const u8 ov562x_init[][2] = {989 {0x88, 0x20},990 {0x89, 0x0a},991 {0x8a, 0x90},992 {0x8b, 0x06},993 {0x8c, 0x01},994 {0x8d, 0x10},995 {0x1c, 0x00},996 {0x1d, 0x48},997 {0x1d, 0x00},998 {0x1d, 0xff},999 {0x1c, 0x0a},1000 {0x1d, 0x2e},1001 {0x1d, 0x1e},1002};1003 1004static const u8 ov562x_init_2[][2] = {1005 {0x12, 0x80},1006 {0x11, 0x41},1007 {0x13, 0x00},1008 {0x10, 0x1e},1009 {0x3b, 0x07},1010 {0x5b, 0x40},1011 {0x39, 0x07},1012 {0x53, 0x02},1013 {0x54, 0x60},1014 {0x04, 0x20},1015 {0x27, 0x04},1016 {0x3d, 0x40},1017 {0x36, 0x00},1018 {0xc5, 0x04},1019 {0x4e, 0x00},1020 {0x4f, 0x93},1021 {0x50, 0x7b},1022 {0xca, 0x0c},1023 {0xcb, 0x0f},1024 {0x39, 0x07},1025 {0x4a, 0x10},1026 {0x3e, 0x0a},1027 {0x3d, 0x00},1028 {0x0c, 0x38},1029 {0x38, 0x90},1030 {0x46, 0x30},1031 {0x4f, 0x93},1032 {0x50, 0x7b},1033 {0xab, 0x00},1034 {0xca, 0x0c},1035 {0xcb, 0x0f},1036 {0x37, 0x02},1037 {0x44, 0x48},1038 {0x8d, 0x44},1039 {0x2a, 0x00},1040 {0x2b, 0x00},1041 {0x32, 0x00},1042 {0x38, 0x90},1043 {0x53, 0x02},1044 {0x54, 0x60},1045 {0x12, 0x00},1046 {0x17, 0x12},1047 {0x18, 0xb4},1048 {0x19, 0x0c},1049 {0x1a, 0xf4},1050 {0x03, 0x4a},1051 {0x89, 0x20},1052 {0x83, 0x80},1053 {0xb7, 0x9d},1054 {0xb6, 0x11},1055 {0xb5, 0x55},1056 {0xb4, 0x00},1057 {0xa9, 0xf0},1058 {0xa8, 0x0a},1059 {0xb8, 0xf0},1060 {0xb9, 0xf0},1061 {0xba, 0xf0},1062 {0x81, 0x07},1063 {0x63, 0x44},1064 {0x13, 0xc7},1065 {0x14, 0x60},1066 {0x33, 0x75},1067 {0x2c, 0x00},1068 {0x09, 0x00},1069 {0x35, 0x30},1070 {0x27, 0x04},1071 {0x3c, 0x07},1072 {0x3a, 0x0a},1073 {0x3b, 0x07},1074 {0x01, 0x40},1075 {0x02, 0x40},1076 {0x16, 0x40},1077 {0x52, 0xb0},1078 {0x51, 0x83},1079 {0x21, 0xbb},1080 {0x22, 0x10},1081 {0x23, 0x03},1082 {0x35, 0x38},1083 {0x20, 0x90},1084 {0x28, 0x30},1085 {0x73, 0xe1},1086 {0x6c, 0x00},1087 {0x6d, 0x80},1088 {0x6e, 0x00},1089 {0x70, 0x04},1090 {0x71, 0x00},1091 {0x8d, 0x04},1092 {0x64, 0x00},1093 {0x65, 0x00},1094 {0x66, 0x00},1095 {0x67, 0x00},1096 {0x68, 0x00},1097 {0x69, 0x00},1098 {0x6a, 0x00},1099 {0x6b, 0x00},1100 {0x71, 0x94},1101 {0x74, 0x20},1102 {0x80, 0x09},1103 {0x85, 0xc0},1104};1105 1106static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)1107{1108 struct usb_device *udev = gspca_dev->dev;1109 int ret;1110 1111 if (gspca_dev->usb_err < 0)1112 return;1113 gspca_dev->usb_buf[0] = val;1114 ret = usb_control_msg(udev,1115 usb_sndctrlpipe(udev, 0),1116 0x01,1117 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,1118 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);1119 if (ret < 0) {1120 pr_err("reg_w failed %d\n", ret);1121 gspca_dev->usb_err = ret;1122 }1123}1124 1125static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val)1126{1127 gspca_dbg(gspca_dev, D_USBO, "reg_w [%04x] = %02x\n", reg, val);1128 reg_w_i(gspca_dev, reg, val);1129}1130 1131static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)1132{1133 struct usb_device *udev = gspca_dev->dev;1134 int ret;1135 1136 if (gspca_dev->usb_err < 0)1137 return 0;1138 ret = usb_control_msg(udev,1139 usb_rcvctrlpipe(udev, 0),1140 0x01,1141 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,1142 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);1143 gspca_dbg(gspca_dev, D_USBI, "reg_r [%04x] -> %02x\n",1144 reg, gspca_dev->usb_buf[0]);1145 if (ret < 0) {1146 pr_err("reg_r err %d\n", ret);1147 gspca_dev->usb_err = ret;1148 return 0;1149 }1150 return gspca_dev->usb_buf[0];1151}1152 1153static int sccb_check_status(struct gspca_dev *gspca_dev)1154{1155 u8 data;1156 int i;1157 1158 for (i = 0; i < 5; i++) {1159 msleep(20);1160 data = reg_r(gspca_dev, OV534_REG_STATUS);1161 1162 switch (data) {1163 case 0x00:1164 return 1;1165 case 0x04:1166 return 0;1167 case 0x03:1168 break;1169 default:1170 gspca_dbg(gspca_dev, D_USBI|D_USBO,1171 "sccb status 0x%02x, attempt %d/5\n",1172 data, i + 1);1173 }1174 }1175 return 0;1176}1177 1178static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)1179{1180 gspca_dbg(gspca_dev, D_USBO, "sccb_write [%02x] = %02x\n", reg, val);1181 reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg);1182 reg_w_i(gspca_dev, OV534_REG_WRITE, val);1183 reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);1184 1185 if (!sccb_check_status(gspca_dev))1186 pr_err("sccb_write failed\n");1187}1188 1189static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)1190{1191 reg_w(gspca_dev, OV534_REG_SUBADDR, reg);1192 reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);1193 if (!sccb_check_status(gspca_dev))1194 pr_err("sccb_read failed 1\n");1195 1196 reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);1197 if (!sccb_check_status(gspca_dev))1198 pr_err("sccb_read failed 2\n");1199 1200 return reg_r(gspca_dev, OV534_REG_READ);1201}1202 1203/* output a bridge sequence (reg - val) */1204static void reg_w_array(struct gspca_dev *gspca_dev,1205 const u8 (*data)[2], int len)1206{1207 while (--len >= 0) {1208 reg_w(gspca_dev, (*data)[0], (*data)[1]);1209 data++;1210 }1211}1212 1213/* output a sensor sequence (reg - val) */1214static void sccb_w_array(struct gspca_dev *gspca_dev,1215 const u8 (*data)[2], int len)1216{1217 while (--len >= 0) {1218 if ((*data)[0] != 0xff) {1219 sccb_write(gspca_dev, (*data)[0], (*data)[1]);1220 } else {1221 sccb_read(gspca_dev, (*data)[1]);1222 sccb_write(gspca_dev, 0xff, 0x00);1223 }1224 data++;1225 }1226}1227 1228/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.1229 * (direction and output)? */1230static void set_led(struct gspca_dev *gspca_dev, int status)1231{1232 u8 data;1233 1234 gspca_dbg(gspca_dev, D_CONF, "led status: %d\n", status);1235 1236 data = reg_r(gspca_dev, 0x21);1237 data |= 0x80;1238 reg_w(gspca_dev, 0x21, data);1239 1240 data = reg_r(gspca_dev, 0x23);1241 if (status)1242 data |= 0x80;1243 else1244 data &= ~0x80;1245 1246 reg_w(gspca_dev, 0x23, data);1247 1248 if (!status) {1249 data = reg_r(gspca_dev, 0x21);1250 data &= ~0x80;1251 reg_w(gspca_dev, 0x21, data);1252 }1253}1254 1255static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)1256{1257 struct sd *sd = (struct sd *) gspca_dev;1258 u8 val;1259 s8 sval;1260 1261 if (sd->sensor == SENSOR_OV562x) {1262 sval = brightness;1263 val = 0x76;1264 val += sval;1265 sccb_write(gspca_dev, 0x24, val);1266 val = 0x6a;1267 val += sval;1268 sccb_write(gspca_dev, 0x25, val);1269 if (sval < -40)1270 val = 0x71;1271 else if (sval < 20)1272 val = 0x94;1273 else1274 val = 0xe6;1275 sccb_write(gspca_dev, 0x26, val);1276 } else {1277 val = brightness;1278 if (val < 8)1279 val = 15 - val; /* f .. 8 */1280 else1281 val = val - 8; /* 0 .. 7 */1282 sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */1283 0x0f | (val << 4));1284 }1285}1286 1287static void setcontrast(struct gspca_dev *gspca_dev, s32 val)1288{1289 sccb_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */1290 val << 4);1291}1292 1293static void setautogain(struct gspca_dev *gspca_dev, s32 autogain)1294{1295 u8 val;1296 1297/*fixme: should adjust agc/awb/aec by different controls */1298 val = sccb_read(gspca_dev, 0x13); /* com8 */1299 sccb_write(gspca_dev, 0xff, 0x00);1300 if (autogain)1301 val |= 0x05; /* agc & aec */1302 else1303 val &= 0xfa;1304 sccb_write(gspca_dev, 0x13, val);1305}1306 1307static void setexposure(struct gspca_dev *gspca_dev, s32 exposure)1308{1309 static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};1310 u8 val;1311 1312 sccb_write(gspca_dev, 0x10, expo[exposure]); /* aec[9:2] */1313 1314 val = sccb_read(gspca_dev, 0x13); /* com8 */1315 sccb_write(gspca_dev, 0xff, 0x00);1316 sccb_write(gspca_dev, 0x13, val);1317 1318 val = sccb_read(gspca_dev, 0xa1); /* aech */1319 sccb_write(gspca_dev, 0xff, 0x00);1320 sccb_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */1321}1322 1323static void setsharpness(struct gspca_dev *gspca_dev, s32 val)1324{1325 if (val < 0) { /* auto */1326 val = sccb_read(gspca_dev, 0x42); /* com17 */1327 sccb_write(gspca_dev, 0xff, 0x00);1328 sccb_write(gspca_dev, 0x42, val | 0x40);1329 /* Edge enhancement strength auto adjust */1330 return;1331 }1332 if (val != 0)1333 val = 1 << (val - 1);1334 sccb_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */1335 val);1336 val = sccb_read(gspca_dev, 0x42); /* com17 */1337 sccb_write(gspca_dev, 0xff, 0x00);1338 sccb_write(gspca_dev, 0x42, val & 0xbf);1339}1340 1341static void setsatur(struct gspca_dev *gspca_dev, s32 val)1342{1343 u8 val1, val2, val3;1344 static const u8 matrix[5][2] = {1345 {0x14, 0x38},1346 {0x1e, 0x54},1347 {0x28, 0x70},1348 {0x32, 0x8c},1349 {0x48, 0x90}1350 };1351 1352 val1 = matrix[val][0];1353 val2 = matrix[val][1];1354 val3 = val1 + val2;1355 sccb_write(gspca_dev, 0x4f, val3); /* matrix coeff */1356 sccb_write(gspca_dev, 0x50, val3);1357 sccb_write(gspca_dev, 0x51, 0x00);1358 sccb_write(gspca_dev, 0x52, val1);1359 sccb_write(gspca_dev, 0x53, val2);1360 sccb_write(gspca_dev, 0x54, val3);1361 sccb_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */1362 1363 val1 = sccb_read(gspca_dev, 0x41); /* com16 */1364 sccb_write(gspca_dev, 0xff, 0x00);1365 sccb_write(gspca_dev, 0x41, val1);1366}1367 1368static void setlightfreq(struct gspca_dev *gspca_dev, s32 freq)1369{1370 u8 val;1371 1372 val = sccb_read(gspca_dev, 0x13); /* com8 */1373 sccb_write(gspca_dev, 0xff, 0x00);1374 if (freq == 0) {1375 sccb_write(gspca_dev, 0x13, val & 0xdf);1376 return;1377 }1378 sccb_write(gspca_dev, 0x13, val | 0x20);1379 1380 val = sccb_read(gspca_dev, 0x42); /* com17 */1381 sccb_write(gspca_dev, 0xff, 0x00);1382 if (freq == 1)1383 val |= 0x01;1384 else1385 val &= 0xfe;1386 sccb_write(gspca_dev, 0x42, val);1387}1388 1389/* this function is called at probe time */1390static int sd_config(struct gspca_dev *gspca_dev,1391 const struct usb_device_id *id)1392{1393 return 0;1394}1395 1396/* this function is called at probe and resume time */1397static int sd_init(struct gspca_dev *gspca_dev)1398{1399 struct sd *sd = (struct sd *) gspca_dev;1400 u16 sensor_id;1401 1402 /* reset bridge */1403 reg_w(gspca_dev, 0xe7, 0x3a);1404 reg_w(gspca_dev, 0xe0, 0x08);1405 msleep(100);1406 1407 /* initialize the sensor address */1408 reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60);1409 1410 /* reset sensor */1411 sccb_write(gspca_dev, 0x12, 0x80);1412 msleep(10);1413 1414 /* probe the sensor */1415 sccb_read(gspca_dev, 0x0a);1416 sensor_id = sccb_read(gspca_dev, 0x0a) << 8;1417 sccb_read(gspca_dev, 0x0b);1418 sensor_id |= sccb_read(gspca_dev, 0x0b);1419 gspca_dbg(gspca_dev, D_PROBE, "Sensor ID: %04x\n", sensor_id);1420 1421 /* initialize */1422 if ((sensor_id & 0xfff0) == 0x9650) {1423 sd->sensor = SENSOR_OV965x;1424 1425 gspca_dev->cam.cam_mode = ov965x_mode;1426 gspca_dev->cam.nmodes = ARRAY_SIZE(ov965x_mode);1427 1428 reg_w_array(gspca_dev, bridge_init,1429 ARRAY_SIZE(bridge_init));1430 sccb_w_array(gspca_dev, ov965x_init,1431 ARRAY_SIZE(ov965x_init));1432 reg_w_array(gspca_dev, bridge_init_2,1433 ARRAY_SIZE(bridge_init_2));1434 sccb_w_array(gspca_dev, ov965x_init_2,1435 ARRAY_SIZE(ov965x_init_2));1436 reg_w(gspca_dev, 0xe0, 0x00);1437 reg_w(gspca_dev, 0xe0, 0x01);1438 set_led(gspca_dev, 0);1439 reg_w(gspca_dev, 0xe0, 0x00);1440 } else if ((sensor_id & 0xfff0) == 0x9710) {1441 const char *p;1442 int l;1443 1444 sd->sensor = SENSOR_OV971x;1445 1446 gspca_dev->cam.cam_mode = ov971x_mode;1447 gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode);1448 1449 gspca_dev->cam.bulk = 1;1450 gspca_dev->cam.bulk_size = 16384;1451 gspca_dev->cam.bulk_nurbs = 2;1452 1453 sccb_w_array(gspca_dev, ov971x_init,1454 ARRAY_SIZE(ov971x_init));1455 1456 /* set video format on bridge processor */1457 /* access bridge processor's video format registers at: 0x00 */1458 reg_w(gspca_dev, 0x1c, 0x00);1459 /*set register: 0x00 is 'RAW8', 0x40 is 'YUV422' (YUYV?)*/1460 reg_w(gspca_dev, 0x1d, 0x00);1461 1462 /* Will W. specific stuff1463 * set VSYNC to1464 * output (0x1f) if first webcam1465 * input (0x17) if 2nd or 3rd webcam */1466 p = video_device_node_name(&gspca_dev->vdev);1467 l = strlen(p) - 1;1468 if (p[l] == '0')1469 reg_w(gspca_dev, 0x56, 0x1f);1470 else1471 reg_w(gspca_dev, 0x56, 0x17);1472 } else if ((sensor_id & 0xfff0) == 0x5620) {1473 sd->sensor = SENSOR_OV562x;1474 gspca_dev->cam.cam_mode = ov562x_mode;1475 gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode);1476 1477 reg_w_array(gspca_dev, ov562x_init,1478 ARRAY_SIZE(ov562x_init));1479 sccb_w_array(gspca_dev, ov562x_init_2,1480 ARRAY_SIZE(ov562x_init_2));1481 reg_w(gspca_dev, 0xe0, 0x00);1482 } else if ((sensor_id & 0xfff0) == 0x3610) {1483 sd->sensor = SENSOR_OV361x;1484 gspca_dev->cam.cam_mode = ov361x_mode;1485 gspca_dev->cam.nmodes = ARRAY_SIZE(ov361x_mode);1486 reg_w(gspca_dev, 0xe7, 0x3a);1487 reg_w(gspca_dev, 0xf1, 0x60);1488 sccb_write(gspca_dev, 0x12, 0x80);1489 } else {1490 pr_err("Unknown sensor %04x", sensor_id);1491 return -EINVAL;1492 }1493 1494 return gspca_dev->usb_err;1495}1496 1497static int sd_start_ov361x(struct gspca_dev *gspca_dev)1498{1499 sccb_write(gspca_dev, 0x12, 0x80);1500 msleep(20);1501 switch (gspca_dev->curr_mode % (ov361x_last)) {1502 case ov361x_2048:1503 reg_w_array(gspca_dev, ov361x_bridge_start_2048,1504 ARRAY_SIZE(ov361x_bridge_start_2048));1505 sccb_w_array(gspca_dev, ov361x_start_2048,1506 ARRAY_SIZE(ov361x_start_2048));1507 break;1508 case ov361x_1600:1509 reg_w_array(gspca_dev, ov361x_bridge_start_1600,1510 ARRAY_SIZE(ov361x_bridge_start_1600));1511 sccb_w_array(gspca_dev, ov361x_start_1600,1512 ARRAY_SIZE(ov361x_start_1600));1513 break;1514 case ov361x_1024:1515 reg_w_array(gspca_dev, ov361x_bridge_start_1024,1516 ARRAY_SIZE(ov361x_bridge_start_1024));1517 sccb_w_array(gspca_dev, ov361x_start_1024,1518 ARRAY_SIZE(ov361x_start_1024));1519 break;1520 case ov361x_640:1521 reg_w_array(gspca_dev, ov361x_bridge_start_640,1522 ARRAY_SIZE(ov361x_bridge_start_640));1523 sccb_w_array(gspca_dev, ov361x_start_640,1524 ARRAY_SIZE(ov361x_start_640));1525 break;1526 case ov361x_320:1527 reg_w_array(gspca_dev, ov361x_bridge_start_320,1528 ARRAY_SIZE(ov361x_bridge_start_320));1529 sccb_w_array(gspca_dev, ov361x_start_320,1530 ARRAY_SIZE(ov361x_start_320));1531 break;1532 case ov361x_160:1533 reg_w_array(gspca_dev, ov361x_bridge_start_160,1534 ARRAY_SIZE(ov361x_bridge_start_160));1535 sccb_w_array(gspca_dev, ov361x_start_160,1536 ARRAY_SIZE(ov361x_start_160));1537 break;1538 }1539 reg_w(gspca_dev, 0xe0, 0x00); /* start transfer */1540 1541 return gspca_dev->usb_err;1542}1543 1544static int sd_start(struct gspca_dev *gspca_dev)1545{1546 struct sd *sd = (struct sd *) gspca_dev;1547 1548 if (sd->sensor == SENSOR_OV971x)1549 return gspca_dev->usb_err;1550 if (sd->sensor == SENSOR_OV562x)1551 return gspca_dev->usb_err;1552 if (sd->sensor == SENSOR_OV361x)1553 return sd_start_ov361x(gspca_dev);1554 1555 switch (gspca_dev->curr_mode) {1556 case QVGA_MODE: /* 320x240 */1557 sccb_w_array(gspca_dev, ov965x_start_1_vga,1558 ARRAY_SIZE(ov965x_start_1_vga));1559 reg_w_array(gspca_dev, bridge_start_qvga,1560 ARRAY_SIZE(bridge_start_qvga));1561 sccb_w_array(gspca_dev, ov965x_start_2_qvga,1562 ARRAY_SIZE(ov965x_start_2_qvga));1563 break;1564 case VGA_MODE: /* 640x480 */1565 sccb_w_array(gspca_dev, ov965x_start_1_vga,1566 ARRAY_SIZE(ov965x_start_1_vga));1567 reg_w_array(gspca_dev, bridge_start_vga,1568 ARRAY_SIZE(bridge_start_vga));1569 sccb_w_array(gspca_dev, ov965x_start_2_vga,1570 ARRAY_SIZE(ov965x_start_2_vga));1571 break;1572 case SVGA_MODE: /* 800x600 */1573 sccb_w_array(gspca_dev, ov965x_start_1_svga,1574 ARRAY_SIZE(ov965x_start_1_svga));1575 reg_w_array(gspca_dev, bridge_start_svga,1576 ARRAY_SIZE(bridge_start_svga));1577 sccb_w_array(gspca_dev, ov965x_start_2_svga,1578 ARRAY_SIZE(ov965x_start_2_svga));1579 break;1580 case XGA_MODE: /* 1024x768 */1581 sccb_w_array(gspca_dev, ov965x_start_1_xga,1582 ARRAY_SIZE(ov965x_start_1_xga));1583 reg_w_array(gspca_dev, bridge_start_xga,1584 ARRAY_SIZE(bridge_start_xga));1585 sccb_w_array(gspca_dev, ov965x_start_2_svga,1586 ARRAY_SIZE(ov965x_start_2_svga));1587 break;1588 default:1589/* case SXGA_MODE: * 1280x1024 */1590 sccb_w_array(gspca_dev, ov965x_start_1_sxga,1591 ARRAY_SIZE(ov965x_start_1_sxga));1592 reg_w_array(gspca_dev, bridge_start_sxga,1593 ARRAY_SIZE(bridge_start_sxga));1594 sccb_w_array(gspca_dev, ov965x_start_2_sxga,1595 ARRAY_SIZE(ov965x_start_2_sxga));1596 break;1597 }1598 1599 reg_w(gspca_dev, 0xe0, 0x00);1600 reg_w(gspca_dev, 0xe0, 0x00);1601 set_led(gspca_dev, 1);1602 return gspca_dev->usb_err;1603}1604 1605static void sd_stopN(struct gspca_dev *gspca_dev)1606{1607 if (((struct sd *)gspca_dev)->sensor == SENSOR_OV361x) {1608 reg_w(gspca_dev, 0xe0, 0x01); /* stop transfer */1609 /* reg_w(gspca_dev, 0x31, 0x09); */1610 return;1611 }1612 reg_w(gspca_dev, 0xe0, 0x01);1613 set_led(gspca_dev, 0);1614 reg_w(gspca_dev, 0xe0, 0x00);1615}1616 1617/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */1618#define UVC_STREAM_EOH (1 << 7)1619#define UVC_STREAM_ERR (1 << 6)1620#define UVC_STREAM_STI (1 << 5)1621#define UVC_STREAM_RES (1 << 4)1622#define UVC_STREAM_SCR (1 << 3)1623#define UVC_STREAM_PTS (1 << 2)1624#define UVC_STREAM_EOF (1 << 1)1625#define UVC_STREAM_FID (1 << 0)1626 1627static void sd_pkt_scan(struct gspca_dev *gspca_dev,1628 u8 *data, int len)1629{1630 struct sd *sd = (struct sd *) gspca_dev;1631 __u32 this_pts;1632 u8 this_fid;1633 int remaining_len = len;1634 int payload_len;1635 1636 payload_len = gspca_dev->cam.bulk ? 2048 : 2040;1637 do {1638 len = min(remaining_len, payload_len);1639 1640 /* Payloads are prefixed with a UVC-style header. We1641 consider a frame to start when the FID toggles, or the PTS1642 changes. A frame ends when EOF is set, and we've received1643 the correct number of bytes. */1644 1645 /* Verify UVC header. Header length is always 12 */1646 if (data[0] != 12 || len < 12) {1647 gspca_dbg(gspca_dev, D_PACK, "bad header\n");1648 goto discard;1649 }1650 1651 /* Check errors */1652 if (data[1] & UVC_STREAM_ERR) {1653 gspca_dbg(gspca_dev, D_PACK, "payload error\n");1654 goto discard;1655 }1656 1657 /* Extract PTS and FID */1658 if (!(data[1] & UVC_STREAM_PTS)) {1659 gspca_dbg(gspca_dev, D_PACK, "PTS not present\n");1660 goto discard;1661 }1662 this_pts = (data[5] << 24) | (data[4] << 16)1663 | (data[3] << 8) | data[2];1664 this_fid = data[1] & UVC_STREAM_FID;1665 1666 /* If PTS or FID has changed, start a new frame. */1667 if (this_pts != sd->last_pts || this_fid != sd->last_fid) {1668 if (gspca_dev->last_packet_type == INTER_PACKET)1669 gspca_frame_add(gspca_dev, LAST_PACKET,1670 NULL, 0);1671 sd->last_pts = this_pts;1672 sd->last_fid = this_fid;1673 gspca_frame_add(gspca_dev, FIRST_PACKET,1674 data + 12, len - 12);1675 /* If this packet is marked as EOF, end the frame */1676 } else if (data[1] & UVC_STREAM_EOF) {1677 sd->last_pts = 0;1678 gspca_frame_add(gspca_dev, LAST_PACKET,1679 data + 12, len - 12);1680 } else {1681 1682 /* Add the data from this payload */1683 gspca_frame_add(gspca_dev, INTER_PACKET,1684 data + 12, len - 12);1685 }1686 1687 /* Done this payload */1688 goto scan_next;1689 1690discard:1691 /* Discard data until a new frame starts. */1692 gspca_dev->last_packet_type = DISCARD_PACKET;1693 1694scan_next:1695 remaining_len -= len;1696 data += len;1697 } while (remaining_len > 0);1698}1699 1700static int sd_s_ctrl(struct v4l2_ctrl *ctrl)1701{1702 struct gspca_dev *gspca_dev =1703 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);1704 1705 gspca_dev->usb_err = 0;1706 1707 if (!gspca_dev->streaming)1708 return 0;1709 1710 switch (ctrl->id) {1711 case V4L2_CID_BRIGHTNESS:1712 setbrightness(gspca_dev, ctrl->val);1713 break;1714 case V4L2_CID_CONTRAST:1715 setcontrast(gspca_dev, ctrl->val);1716 break;1717 case V4L2_CID_SATURATION:1718 setsatur(gspca_dev, ctrl->val);1719 break;1720 case V4L2_CID_POWER_LINE_FREQUENCY:1721 setlightfreq(gspca_dev, ctrl->val);1722 break;1723 case V4L2_CID_SHARPNESS:1724 setsharpness(gspca_dev, ctrl->val);1725 break;1726 case V4L2_CID_AUTOGAIN:1727 if (ctrl->is_new)1728 setautogain(gspca_dev, ctrl->val);1729 if (!ctrl->val && gspca_dev->exposure->is_new)1730 setexposure(gspca_dev, gspca_dev->exposure->val);1731 break;1732 }1733 return gspca_dev->usb_err;1734}1735 1736static const struct v4l2_ctrl_ops sd_ctrl_ops = {1737 .s_ctrl = sd_s_ctrl,1738};1739 1740static int sd_init_controls(struct gspca_dev *gspca_dev)1741{1742 struct sd *sd = (struct sd *)gspca_dev;1743 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;1744 1745 if (sd->sensor == SENSOR_OV971x)1746 return 0;1747 if (sd->sensor == SENSOR_OV361x)1748 return 0;1749 gspca_dev->vdev.ctrl_handler = hdl;1750 v4l2_ctrl_handler_init(hdl, 7);1751 if (sd->sensor == SENSOR_OV562x) {1752 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1753 V4L2_CID_BRIGHTNESS, -90, 90, 1, 0);1754 } else {1755 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1756 V4L2_CID_BRIGHTNESS, 0, 15, 1, 7);1757 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1758 V4L2_CID_CONTRAST, 0, 15, 1, 3);1759 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1760 V4L2_CID_SATURATION, 0, 4, 1, 2);1761 /* -1 = auto */1762 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1763 V4L2_CID_SHARPNESS, -1, 4, 1, -1);1764 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1765 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);1766 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1767 V4L2_CID_EXPOSURE, 0, 3, 1, 0);1768 v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,1769 V4L2_CID_POWER_LINE_FREQUENCY,1770 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);1771 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);1772 }1773 1774 if (hdl->error) {1775 pr_err("Could not initialize controls\n");1776 return hdl->error;1777 }1778 return 0;1779}1780 1781/* sub-driver description */1782static const struct sd_desc sd_desc = {1783 .name = MODULE_NAME,1784 .config = sd_config,1785 .init = sd_init,1786 .init_controls = sd_init_controls,1787 .start = sd_start,1788 .stopN = sd_stopN,1789 .pkt_scan = sd_pkt_scan,1790};1791 1792/* -- module initialisation -- */1793static const struct usb_device_id device_table[] = {1794 {USB_DEVICE(0x05a9, 0x8065)},1795 {USB_DEVICE(0x06f8, 0x3003)},1796 {USB_DEVICE(0x05a9, 0x1550)},1797 {}1798};1799 1800MODULE_DEVICE_TABLE(usb, device_table);1801 1802/* -- device connect -- */1803static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)1804{1805 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),1806 THIS_MODULE);1807}1808 1809static struct usb_driver sd_driver = {1810 .name = MODULE_NAME,1811 .id_table = device_table,1812 .probe = sd_probe,1813 .disconnect = gspca_disconnect,1814#ifdef CONFIG_PM1815 .suspend = gspca_suspend,1816 .resume = gspca_resume,1817 .reset_resume = gspca_resume,1818#endif1819};1820 1821module_usb_driver(sd_driver);1822