linux/drivers/media/video/gspca/ov534_9.c
<<
>>
Prefs
   1/*
   2 * ov534-ov965x gspca driver
   3 *
   4 * Copyright (C) 2009-2010 Jean-Francois Moine http://moinejf.free.fr
   5 * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
   6 * Copyright (C) 2008 Jim Paris <jim@jtan.com>
   7 *
   8 * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
   9 * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
  10 * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation; either version 2 of the License, or
  15 * any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20 * GNU General Public License for more details.
  21 *
  22 * You should have received a copy of the GNU General Public License
  23 * along with this program; if not, write to the Free Software
  24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  25 */
  26
  27#define MODULE_NAME "ov534_9"
  28
  29#include "gspca.h"
  30
  31#define OV534_REG_ADDRESS       0xf1    /* sensor address */
  32#define OV534_REG_SUBADDR       0xf2
  33#define OV534_REG_WRITE         0xf3
  34#define OV534_REG_READ          0xf4
  35#define OV534_REG_OPERATION     0xf5
  36#define OV534_REG_STATUS        0xf6
  37
  38#define OV534_OP_WRITE_3        0x37
  39#define OV534_OP_WRITE_2        0x33
  40#define OV534_OP_READ_2         0xf9
  41
  42#define CTRL_TIMEOUT 500
  43
  44MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
  45MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
  46MODULE_LICENSE("GPL");
  47
  48/* specific webcam descriptor */
  49struct sd {
  50        struct gspca_dev gspca_dev;     /* !! must be the first item */
  51        __u32 last_pts;
  52        u8 last_fid;
  53
  54        u8 brightness;
  55        u8 contrast;
  56        u8 autogain;
  57        u8 exposure;
  58        s8 sharpness;
  59        u8 satur;
  60        u8 freq;
  61};
  62
  63/* V4L2 controls supported by the driver */
  64static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
  65static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
  66static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
  67static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
  68static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
  69static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
  70static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
  71static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
  72static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
  73static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
  74static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val);
  75static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val);
  76static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
  77static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
  78
  79static const struct ctrl sd_ctrls[] = {
  80    {                                                   /* 0 */
  81        {
  82                .id      = V4L2_CID_BRIGHTNESS,
  83                .type    = V4L2_CTRL_TYPE_INTEGER,
  84                .name    = "Brightness",
  85                .minimum = 0,
  86                .maximum = 15,
  87                .step    = 1,
  88#define BRIGHTNESS_DEF 7
  89                .default_value = BRIGHTNESS_DEF,
  90        },
  91        .set = sd_setbrightness,
  92        .get = sd_getbrightness,
  93    },
  94    {                                                   /* 1 */
  95        {
  96                .id      = V4L2_CID_CONTRAST,
  97                .type    = V4L2_CTRL_TYPE_INTEGER,
  98                .name    = "Contrast",
  99                .minimum = 0,
 100                .maximum = 15,
 101                .step    = 1,
 102#define CONTRAST_DEF 3
 103                .default_value = CONTRAST_DEF,
 104        },
 105        .set = sd_setcontrast,
 106        .get = sd_getcontrast,
 107    },
 108    {                                                   /* 2 */
 109        {
 110                .id      = V4L2_CID_AUTOGAIN,
 111                .type    = V4L2_CTRL_TYPE_BOOLEAN,
 112                .name    = "Autogain",
 113                .minimum = 0,
 114                .maximum = 1,
 115                .step    = 1,
 116#define AUTOGAIN_DEF 1
 117                .default_value = AUTOGAIN_DEF,
 118        },
 119        .set = sd_setautogain,
 120        .get = sd_getautogain,
 121    },
 122#define EXPO_IDX 3
 123    {                                                   /* 3 */
 124        {
 125                .id      = V4L2_CID_EXPOSURE,
 126                .type    = V4L2_CTRL_TYPE_INTEGER,
 127                .name    = "Exposure",
 128                .minimum = 0,
 129                .maximum = 3,
 130                .step    = 1,
 131#define EXPO_DEF 0
 132                .default_value = EXPO_DEF,
 133        },
 134        .set = sd_setexposure,
 135        .get = sd_getexposure,
 136    },
 137    {                                                   /* 4 */
 138        {
 139                .id      = V4L2_CID_SHARPNESS,
 140                .type    = V4L2_CTRL_TYPE_INTEGER,
 141                .name    = "Sharpness",
 142                .minimum = -1,          /* -1 = auto */
 143                .maximum = 4,
 144                .step    = 1,
 145#define SHARPNESS_DEF -1
 146                .default_value = SHARPNESS_DEF,
 147        },
 148        .set = sd_setsharpness,
 149        .get = sd_getsharpness,
 150    },
 151    {                                                   /* 5 */
 152        {
 153                .id      = V4L2_CID_SATURATION,
 154                .type    = V4L2_CTRL_TYPE_INTEGER,
 155                .name    = "Saturation",
 156                .minimum = 0,
 157                .maximum = 4,
 158                .step    = 1,
 159#define SATUR_DEF 2
 160                .default_value = SATUR_DEF,
 161        },
 162        .set = sd_setsatur,
 163        .get = sd_getsatur,
 164    },
 165    {
 166        {
 167                .id      = V4L2_CID_POWER_LINE_FREQUENCY,
 168                .type    = V4L2_CTRL_TYPE_MENU,
 169                .name    = "Light frequency filter",
 170                .minimum = 0,
 171                .maximum = 2,   /* 0: 0, 1: 50Hz, 2:60Hz */
 172                .step    = 1,
 173#define FREQ_DEF 0
 174                .default_value = FREQ_DEF,
 175        },
 176        .set = sd_setfreq,
 177        .get = sd_getfreq,
 178    },
 179};
 180
 181static const struct v4l2_pix_format ov965x_mode[] = {
 182#define QVGA_MODE 0
 183        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 184                .bytesperline = 320,
 185                .sizeimage = 320 * 240 * 3 / 8 + 590,
 186                .colorspace = V4L2_COLORSPACE_JPEG},
 187#define VGA_MODE 1
 188        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 189                .bytesperline = 640,
 190                .sizeimage = 640 * 480 * 3 / 8 + 590,
 191                .colorspace = V4L2_COLORSPACE_JPEG},
 192#define SVGA_MODE 2
 193        {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 194                .bytesperline = 800,
 195                .sizeimage = 800 * 600 * 3 / 8 + 590,
 196                .colorspace = V4L2_COLORSPACE_JPEG},
 197#define XGA_MODE 3
 198        {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 199                .bytesperline = 1024,
 200                .sizeimage = 1024 * 768 * 3 / 8 + 590,
 201                .colorspace = V4L2_COLORSPACE_JPEG},
 202#define SXGA_MODE 4
 203        {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 204                .bytesperline = 1280,
 205                .sizeimage = 1280 * 1024 * 3 / 8 + 590,
 206                .colorspace = V4L2_COLORSPACE_JPEG},
 207};
 208
 209static const u8 bridge_init[][2] = {
 210        {0x88, 0xf8},
 211        {0x89, 0xff},
 212        {0x76, 0x03},
 213        {0x92, 0x03},
 214        {0x95, 0x10},
 215        {0xe2, 0x00},
 216        {0xe7, 0x3e},
 217        {0x8d, 0x1c},
 218        {0x8e, 0x00},
 219        {0x8f, 0x00},
 220        {0x1f, 0x00},
 221        {0xc3, 0xf9},
 222        {0x89, 0xff},
 223        {0x88, 0xf8},
 224        {0x76, 0x03},
 225        {0x92, 0x01},
 226        {0x93, 0x18},
 227        {0x1c, 0x0a},
 228        {0x1d, 0x48},
 229        {0xc0, 0x50},
 230        {0xc1, 0x3c},
 231        {0x34, 0x05},
 232        {0xc2, 0x0c},
 233        {0xc3, 0xf9},
 234        {0x34, 0x05},
 235        {0xe7, 0x2e},
 236        {0x31, 0xf9},
 237        {0x35, 0x02},
 238        {0xd9, 0x10},
 239        {0x25, 0x42},
 240        {0x94, 0x11},
 241};
 242
 243static const u8 sensor_init[][2] = {
 244        {0x12, 0x80},   /* com7 - SSCB reset */
 245        {0x00, 0x00},   /* gain */
 246        {0x01, 0x80},   /* blue */
 247        {0x02, 0x80},   /* red */
 248        {0x03, 0x1b},   /* vref */
 249        {0x04, 0x03},   /* com1 - exposure low bits */
 250        {0x0b, 0x57},   /* ver */
 251        {0x0e, 0x61},   /* com5 */
 252        {0x0f, 0x42},   /* com6 */
 253        {0x11, 0x00},   /* clkrc */
 254        {0x12, 0x02},   /* com7 - 15fps VGA YUYV */
 255        {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
 256        {0x14, 0x28},   /* com9 */
 257        {0x16, 0x24},   /* reg16 */
 258        {0x17, 0x1d},   /* hstart*/
 259        {0x18, 0xbd},   /* hstop */
 260        {0x19, 0x01},   /* vstrt */
 261        {0x1a, 0x81},   /* vstop*/
 262        {0x1e, 0x04},   /* mvfp */
 263        {0x24, 0x3c},   /* aew */
 264        {0x25, 0x36},   /* aeb */
 265        {0x26, 0x71},   /* vpt */
 266        {0x27, 0x08},   /* bbias */
 267        {0x28, 0x08},   /* gbbias */
 268        {0x29, 0x15},   /* gr com */
 269        {0x2a, 0x00},   /* exhch */
 270        {0x2b, 0x00},   /* exhcl */
 271        {0x2c, 0x08},   /* rbias */
 272        {0x32, 0xff},   /* href */
 273        {0x33, 0x00},   /* chlf */
 274        {0x34, 0x3f},   /* aref1 */
 275        {0x35, 0x00},   /* aref2 */
 276        {0x36, 0xf8},   /* aref3 */
 277        {0x38, 0x72},   /* adc2 */
 278        {0x39, 0x57},   /* aref4 */
 279        {0x3a, 0x80},   /* tslb - yuyv */
 280        {0x3b, 0xc4},   /* com11 - night mode 1/4 frame rate */
 281        {0x3d, 0x99},   /* com13 */
 282        {0x3f, 0xc1},   /* edge */
 283        {0x40, 0xc0},   /* com15 */
 284        {0x41, 0x40},   /* com16 */
 285        {0x42, 0xc0},   /* com17 */
 286        {0x43, 0x0a},   /* rsvd */
 287        {0x44, 0xf0},
 288        {0x45, 0x46},
 289        {0x46, 0x62},
 290        {0x47, 0x2a},
 291        {0x48, 0x3c},
 292        {0x4a, 0xfc},
 293        {0x4b, 0xfc},
 294        {0x4c, 0x7f},
 295        {0x4d, 0x7f},
 296        {0x4e, 0x7f},
 297        {0x4f, 0x98},   /* matrix */
 298        {0x50, 0x98},
 299        {0x51, 0x00},
 300        {0x52, 0x28},
 301        {0x53, 0x70},
 302        {0x54, 0x98},
 303        {0x58, 0x1a},   /* matrix coef sign */
 304        {0x59, 0x85},   /* AWB control */
 305        {0x5a, 0xa9},
 306        {0x5b, 0x64},
 307        {0x5c, 0x84},
 308        {0x5d, 0x53},
 309        {0x5e, 0x0e},
 310        {0x5f, 0xf0},   /* AWB blue limit */
 311        {0x60, 0xf0},   /* AWB red limit */
 312        {0x61, 0xf0},   /* AWB green limit */
 313        {0x62, 0x00},   /* lcc1 */
 314        {0x63, 0x00},   /* lcc2 */
 315        {0x64, 0x02},   /* lcc3 */
 316        {0x65, 0x16},   /* lcc4 */
 317        {0x66, 0x01},   /* lcc5 */
 318        {0x69, 0x02},   /* hv */
 319        {0x6b, 0x5a},   /* dbvl */
 320        {0x6c, 0x04},
 321        {0x6d, 0x55},
 322        {0x6e, 0x00},
 323        {0x6f, 0x9d},
 324        {0x70, 0x21},   /* dnsth */
 325        {0x71, 0x78},
 326        {0x72, 0x00},   /* poidx */
 327        {0x73, 0x01},   /* pckdv */
 328        {0x74, 0x3a},   /* xindx */
 329        {0x75, 0x35},   /* yindx */
 330        {0x76, 0x01},
 331        {0x77, 0x02},
 332        {0x7a, 0x12},   /* gamma curve */
 333        {0x7b, 0x08},
 334        {0x7c, 0x16},
 335        {0x7d, 0x30},
 336        {0x7e, 0x5e},
 337        {0x7f, 0x72},
 338        {0x80, 0x82},
 339        {0x81, 0x8e},
 340        {0x82, 0x9a},
 341        {0x83, 0xa4},
 342        {0x84, 0xac},
 343        {0x85, 0xb8},
 344        {0x86, 0xc3},
 345        {0x87, 0xd6},
 346        {0x88, 0xe6},
 347        {0x89, 0xf2},
 348        {0x8a, 0x03},
 349        {0x8c, 0x89},   /* com19 */
 350        {0x14, 0x28},   /* com9 */
 351        {0x90, 0x7d},
 352        {0x91, 0x7b},
 353        {0x9d, 0x03},   /* lcc6 */
 354        {0x9e, 0x04},   /* lcc7 */
 355        {0x9f, 0x7a},
 356        {0xa0, 0x79},
 357        {0xa1, 0x40},   /* aechm */
 358        {0xa4, 0x50},   /* com21 */
 359        {0xa5, 0x68},   /* com26 */
 360        {0xa6, 0x4a},   /* AWB green */
 361        {0xa8, 0xc1},   /* refa8 */
 362        {0xa9, 0xef},   /* refa9 */
 363        {0xaa, 0x92},
 364        {0xab, 0x04},
 365        {0xac, 0x80},   /* black level control */
 366        {0xad, 0x80},
 367        {0xae, 0x80},
 368        {0xaf, 0x80},
 369        {0xb2, 0xf2},
 370        {0xb3, 0x20},
 371        {0xb4, 0x20},   /* ctrlb4 */
 372        {0xb5, 0x00},
 373        {0xb6, 0xaf},
 374        {0xbb, 0xae},
 375        {0xbc, 0x7f},   /* ADC channel offsets */
 376        {0xdb, 0x7f},
 377        {0xbe, 0x7f},
 378        {0xbf, 0x7f},
 379        {0xc0, 0xe2},
 380        {0xc1, 0xc0},
 381        {0xc2, 0x01},
 382        {0xc3, 0x4e},
 383        {0xc6, 0x85},
 384        {0xc7, 0x80},   /* com24 */
 385        {0xc9, 0xe0},
 386        {0xca, 0xe8},
 387        {0xcb, 0xf0},
 388        {0xcc, 0xd8},
 389        {0xcd, 0xf1},
 390        {0x4f, 0x98},   /* matrix */
 391        {0x50, 0x98},
 392        {0x51, 0x00},
 393        {0x52, 0x28},
 394        {0x53, 0x70},
 395        {0x54, 0x98},
 396        {0x58, 0x1a},
 397        {0xff, 0x41},   /* read 41, write ff 00 */
 398        {0x41, 0x40},   /* com16 */
 399
 400        {0xc5, 0x03},   /* 60 Hz banding filter */
 401        {0x6a, 0x02},   /* 50 Hz banding filter */
 402
 403        {0x12, 0x62},   /* com7 - 30fps VGA YUV */
 404        {0x36, 0xfa},   /* aref3 */
 405        {0x69, 0x0a},   /* hv */
 406        {0x8c, 0x89},   /* com22 */
 407        {0x14, 0x28},   /* com9 */
 408        {0x3e, 0x0c},
 409        {0x41, 0x40},   /* com16 */
 410        {0x72, 0x00},
 411        {0x73, 0x00},
 412        {0x74, 0x3a},
 413        {0x75, 0x35},
 414        {0x76, 0x01},
 415        {0xc7, 0x80},
 416        {0x03, 0x12},   /* vref */
 417        {0x17, 0x16},   /* hstart */
 418        {0x18, 0x02},   /* hstop */
 419        {0x19, 0x01},   /* vstrt */
 420        {0x1a, 0x3d},   /* vstop */
 421        {0x32, 0xff},   /* href */
 422        {0xc0, 0xaa},
 423};
 424
 425static const u8 bridge_init_2[][2] = {
 426        {0x94, 0xaa},
 427        {0xf1, 0x60},
 428        {0xe5, 0x04},
 429        {0xc0, 0x50},
 430        {0xc1, 0x3c},
 431        {0x8c, 0x00},
 432        {0x8d, 0x1c},
 433        {0x34, 0x05},
 434
 435        {0xc2, 0x0c},
 436        {0xc3, 0xf9},
 437        {0xda, 0x01},
 438        {0x50, 0x00},
 439        {0x51, 0xa0},
 440        {0x52, 0x3c},
 441        {0x53, 0x00},
 442        {0x54, 0x00},
 443        {0x55, 0x00},
 444        {0x57, 0x00},
 445        {0x5c, 0x00},
 446        {0x5a, 0xa0},
 447        {0x5b, 0x78},
 448        {0x35, 0x02},
 449        {0xd9, 0x10},
 450        {0x94, 0x11},
 451};
 452
 453static const u8 sensor_init_2[][2] = {
 454        {0x3b, 0xc4},
 455        {0x1e, 0x04},   /* mvfp */
 456        {0x13, 0xe0},   /* com8 */
 457        {0x00, 0x00},   /* gain */
 458        {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
 459        {0x11, 0x03},   /* clkrc */
 460        {0x6b, 0x5a},   /* dblv */
 461        {0x6a, 0x05},
 462        {0xc5, 0x07},
 463        {0xa2, 0x4b},
 464        {0xa3, 0x3e},
 465        {0x2d, 0x00},
 466        {0xff, 0x42},   /* read 42, write ff 00 */
 467        {0x42, 0xc0},   /* com17 */
 468        {0x2d, 0x00},
 469        {0xff, 0x42},   /* read 42, write ff 00 */
 470        {0x42, 0xc1},   /* com17 */
 471/* sharpness */
 472        {0x3f, 0x01},
 473        {0xff, 0x42},   /* read 42, write ff 00 */
 474        {0x42, 0xc1},   /* com17 */
 475/* saturation */
 476        {0x4f, 0x98},   /* matrix */
 477        {0x50, 0x98},
 478        {0x51, 0x00},
 479        {0x52, 0x28},
 480        {0x53, 0x70},
 481        {0x54, 0x98},
 482        {0x58, 0x1a},
 483        {0xff, 0x41},   /* read 41, write ff 00 */
 484        {0x41, 0x40},   /* com16 */
 485/* contrast */
 486        {0x56, 0x40},
 487/* brightness */
 488        {0x55, 0x8f},
 489/* expo */
 490        {0x10, 0x25},   /* aech - exposure high bits */
 491        {0xff, 0x13},   /* read 13, write ff 00 */
 492        {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
 493};
 494
 495static const u8 sensor_start_1_vga[][2] = {     /* same for qvga */
 496        {0x12, 0x62},   /* com7 - 30fps VGA YUV */
 497        {0x36, 0xfa},   /* aref3 */
 498        {0x69, 0x0a},   /* hv */
 499        {0x8c, 0x89},   /* com22 */
 500        {0x14, 0x28},   /* com9 */
 501        {0x3e, 0x0c},   /* com14 */
 502        {0x41, 0x40},   /* com16 */
 503        {0x72, 0x00},
 504        {0x73, 0x00},
 505        {0x74, 0x3a},
 506        {0x75, 0x35},
 507        {0x76, 0x01},
 508        {0xc7, 0x80},   /* com24 */
 509        {0x03, 0x12},   /* vref */
 510        {0x17, 0x16},   /* hstart */
 511        {0x18, 0x02},   /* hstop */
 512        {0x19, 0x01},   /* vstrt */
 513        {0x1a, 0x3d},   /* vstop */
 514        {0x32, 0xff},   /* href */
 515        {0xc0, 0xaa},
 516};
 517
 518static const u8 sensor_start_1_svga[][2] = {
 519        {0x12, 0x02},   /* com7 - YUYV - VGA 15 full resolution */
 520        {0x36, 0xf8},   /* aref3 */
 521        {0x69, 0x02},   /* hv */
 522        {0x8c, 0x0d},   /* com22 */
 523        {0x3e, 0x0c},   /* com14 */
 524        {0x41, 0x40},   /* com16 */
 525        {0x72, 0x00},
 526        {0x73, 0x01},
 527        {0x74, 0x3a},
 528        {0x75, 0x35},
 529        {0x76, 0x01},
 530        {0xc7, 0x80},   /* com24 */
 531        {0x03, 0x1b},   /* vref */
 532        {0x17, 0x1d},   /* hstart */
 533        {0x18, 0xbd},   /* hstop */
 534        {0x19, 0x01},   /* vstrt */
 535        {0x1a, 0x81},   /* vstop */
 536        {0x32, 0xff},   /* href */
 537        {0xc0, 0xe2},
 538};
 539
 540static const u8 sensor_start_1_xga[][2] = {
 541        {0x12, 0x02},   /* com7 */
 542        {0x36, 0xf8},   /* aref3 */
 543        {0x69, 0x02},   /* hv */
 544        {0x8c, 0x89},   /* com22 */
 545        {0x14, 0x28},   /* com9 */
 546        {0x3e, 0x0c},   /* com14 */
 547        {0x41, 0x40},   /* com16 */
 548        {0x72, 0x00},
 549        {0x73, 0x01},
 550        {0x74, 0x3a},
 551        {0x75, 0x35},
 552        {0x76, 0x01},
 553        {0xc7, 0x80},   /* com24 */
 554        {0x03, 0x1b},   /* vref */
 555        {0x17, 0x1d},   /* hstart */
 556        {0x18, 0xbd},   /* hstop */
 557        {0x19, 0x01},   /* vstrt */
 558        {0x1a, 0x81},   /* vstop */
 559        {0x32, 0xff},   /* href */
 560        {0xc0, 0xe2},
 561};
 562
 563static const u8 sensor_start_1_sxga[][2] = {
 564        {0x12, 0x02},   /* com7 */
 565        {0x36, 0xf8},   /* aref3 */
 566        {0x69, 0x02},   /* hv */
 567        {0x8c, 0x89},   /* com22 */
 568        {0x14, 0x28},   /* com9 */
 569        {0x3e, 0x0c},   /* com14 */
 570        {0x41, 0x40},   /* com16 */
 571        {0x72, 0x00},
 572        {0x73, 0x01},
 573        {0x74, 0x3a},
 574        {0x75, 0x35},
 575        {0x76, 0x01},
 576        {0xc7, 0x80},   /* com24 */
 577        {0x03, 0x1b},   /* vref */
 578        {0x17, 0x1d},   /* hstart */
 579        {0x18, 0x02},   /* hstop */
 580        {0x19, 0x01},   /* vstrt */
 581        {0x1a, 0x81},   /* vstop */
 582        {0x32, 0xff},   /* href */
 583        {0xc0, 0xe2},
 584};
 585
 586static const u8 bridge_start_qvga[][2] = {
 587        {0x94, 0xaa},
 588        {0xf1, 0x60},
 589        {0xe5, 0x04},
 590        {0xc0, 0x50},
 591        {0xc1, 0x3c},
 592        {0x8c, 0x00},
 593        {0x8d, 0x1c},
 594        {0x34, 0x05},
 595
 596        {0xc2, 0x4c},
 597        {0xc3, 0xf9},
 598        {0xda, 0x00},
 599        {0x50, 0x00},
 600        {0x51, 0xa0},
 601        {0x52, 0x78},
 602        {0x53, 0x00},
 603        {0x54, 0x00},
 604        {0x55, 0x00},
 605        {0x57, 0x00},
 606        {0x5c, 0x00},
 607        {0x5a, 0x50},
 608        {0x5b, 0x3c},
 609        {0x35, 0x02},
 610        {0xd9, 0x10},
 611        {0x94, 0x11},
 612};
 613
 614static const u8 bridge_start_vga[][2] = {
 615        {0x94, 0xaa},
 616        {0xf1, 0x60},
 617        {0xe5, 0x04},
 618        {0xc0, 0x50},
 619        {0xc1, 0x3c},
 620        {0x8c, 0x00},
 621        {0x8d, 0x1c},
 622        {0x34, 0x05},
 623        {0xc2, 0x0c},
 624        {0xc3, 0xf9},
 625        {0xda, 0x01},
 626        {0x50, 0x00},
 627        {0x51, 0xa0},
 628        {0x52, 0x3c},
 629        {0x53, 0x00},
 630        {0x54, 0x00},
 631        {0x55, 0x00},
 632        {0x57, 0x00},
 633        {0x5c, 0x00},
 634        {0x5a, 0xa0},
 635        {0x5b, 0x78},
 636        {0x35, 0x02},
 637        {0xd9, 0x10},
 638        {0x94, 0x11},
 639};
 640
 641static const u8 bridge_start_svga[][2] = {
 642        {0x94, 0xaa},
 643        {0xf1, 0x60},
 644        {0xe5, 0x04},
 645        {0xc0, 0xa0},
 646        {0xc1, 0x80},
 647        {0x8c, 0x00},
 648        {0x8d, 0x1c},
 649        {0x34, 0x05},
 650        {0xc2, 0x4c},
 651        {0xc3, 0xf9},
 652        {0x50, 0x00},
 653        {0x51, 0x40},
 654        {0x52, 0x00},
 655        {0x53, 0x00},
 656        {0x54, 0x00},
 657        {0x55, 0x88},
 658        {0x57, 0x00},
 659        {0x5c, 0x00},
 660        {0x5a, 0xc8},
 661        {0x5b, 0x96},
 662        {0x35, 0x02},
 663        {0xd9, 0x10},
 664        {0xda, 0x00},
 665        {0x94, 0x11},
 666};
 667
 668static const u8 bridge_start_xga[][2] = {
 669        {0x94, 0xaa},
 670        {0xf1, 0x60},
 671        {0xe5, 0x04},
 672        {0xc0, 0xa0},
 673        {0xc1, 0x80},
 674        {0x8c, 0x00},
 675        {0x8d, 0x1c},
 676        {0x34, 0x05},
 677        {0xc2, 0x4c},
 678        {0xc3, 0xf9},
 679        {0x50, 0x00},
 680        {0x51, 0x40},
 681        {0x52, 0x00},
 682        {0x53, 0x00},
 683        {0x54, 0x00},
 684        {0x55, 0x88},
 685        {0x57, 0x00},
 686        {0x5c, 0x01},
 687        {0x5a, 0x00},
 688        {0x5b, 0xc0},
 689        {0x35, 0x02},
 690        {0xd9, 0x10},
 691        {0xda, 0x01},
 692        {0x94, 0x11},
 693};
 694
 695static const u8 bridge_start_sxga[][2] = {
 696        {0x94, 0xaa},
 697        {0xf1, 0x60},
 698        {0xe5, 0x04},
 699        {0xc0, 0xa0},
 700        {0xc1, 0x80},
 701        {0x8c, 0x00},
 702        {0x8d, 0x1c},
 703        {0x34, 0x05},
 704        {0xc2, 0x0c},
 705        {0xc3, 0xf9},
 706        {0xda, 0x00},
 707        {0x35, 0x02},
 708        {0xd9, 0x10},
 709        {0x94, 0x11},
 710};
 711
 712static const u8 sensor_start_2_qvga[][2] = {
 713        {0x3b, 0xe4},   /* com11 - night mode 1/4 frame rate */
 714        {0x1e, 0x04},   /* mvfp */
 715        {0x13, 0xe0},   /* com8 */
 716        {0x00, 0x00},
 717        {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
 718        {0x11, 0x01},   /* clkrc */
 719        {0x6b, 0x5a},   /* dblv */
 720        {0x6a, 0x02},   /* 50 Hz banding filter */
 721        {0xc5, 0x03},   /* 60 Hz banding filter */
 722        {0xa2, 0x96},   /* bd50 */
 723        {0xa3, 0x7d},   /* bd60 */
 724
 725        {0xff, 0x13},   /* read 13, write ff 00 */
 726        {0x13, 0xe7},
 727        {0x3a, 0x80},   /* tslb - yuyv */
 728};
 729
 730static const u8 sensor_start_2_vga[][2] = {
 731        {0x3b, 0xc4},   /* com11 - night mode 1/4 frame rate */
 732        {0x1e, 0x04},   /* mvfp */
 733        {0x13, 0xe0},   /* com8 */
 734        {0x00, 0x00},
 735        {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
 736        {0x11, 0x03},   /* clkrc */
 737        {0x6b, 0x5a},   /* dblv */
 738        {0x6a, 0x05},   /* 50 Hz banding filter */
 739        {0xc5, 0x07},   /* 60 Hz banding filter */
 740        {0xa2, 0x4b},   /* bd50 */
 741        {0xa3, 0x3e},   /* bd60 */
 742
 743        {0x2d, 0x00},   /* advfl */
 744};
 745
 746static const u8 sensor_start_2_svga[][2] = {    /* same for xga */
 747        {0x3b, 0xc4},   /* com11 - night mode 1/4 frame rate */
 748        {0x1e, 0x04},   /* mvfp */
 749        {0x13, 0xe0},   /* com8 */
 750        {0x00, 0x00},
 751        {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
 752        {0x11, 0x01},   /* clkrc */
 753        {0x6b, 0x5a},   /* dblv */
 754        {0x6a, 0x0c},   /* 50 Hz banding filter */
 755        {0xc5, 0x0f},   /* 60 Hz banding filter */
 756        {0xa2, 0x4e},   /* bd50 */
 757        {0xa3, 0x41},   /* bd60 */
 758};
 759
 760static const u8 sensor_start_2_sxga[][2] = {
 761        {0x13, 0xe0},   /* com8 */
 762        {0x00, 0x00},
 763        {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
 764        {0x3b, 0xc4},   /* com11 - night mode 1/4 frame rate */
 765        {0x1e, 0x04},   /* mvfp */
 766        {0x11, 0x01},   /* clkrc */
 767        {0x6b, 0x5a},   /* dblv */
 768        {0x6a, 0x0c},   /* 50 Hz banding filter */
 769        {0xc5, 0x0f},   /* 60 Hz banding filter */
 770        {0xa2, 0x4e},   /* bd50 */
 771        {0xa3, 0x41},   /* bd60 */
 772};
 773
 774static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
 775{
 776        struct usb_device *udev = gspca_dev->dev;
 777        int ret;
 778
 779        if (gspca_dev->usb_err < 0)
 780                return;
 781        gspca_dev->usb_buf[0] = val;
 782        ret = usb_control_msg(udev,
 783                              usb_sndctrlpipe(udev, 0),
 784                              0x01,
 785                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 786                              0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 787        if (ret < 0) {
 788                PDEBUG(D_ERR, "reg_w failed %d", ret);
 789                gspca_dev->usb_err = ret;
 790        }
 791}
 792
 793static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val)
 794{
 795        PDEBUG(D_USBO, "reg_w [%04x] = %02x", reg, val);
 796        reg_w_i(gspca_dev, reg, val);
 797}
 798
 799static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)
 800{
 801        struct usb_device *udev = gspca_dev->dev;
 802        int ret;
 803
 804        if (gspca_dev->usb_err < 0)
 805                return 0;
 806        ret = usb_control_msg(udev,
 807                              usb_rcvctrlpipe(udev, 0),
 808                              0x01,
 809                              USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 810                              0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 811        PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]);
 812        if (ret < 0) {
 813                PDEBUG(D_ERR, "reg_r err %d", ret);
 814                gspca_dev->usb_err = ret;
 815        }
 816        return gspca_dev->usb_buf[0];
 817}
 818
 819static int sccb_check_status(struct gspca_dev *gspca_dev)
 820{
 821        u8 data;
 822        int i;
 823
 824        for (i = 0; i < 5; i++) {
 825                data = reg_r(gspca_dev, OV534_REG_STATUS);
 826
 827                switch (data) {
 828                case 0x00:
 829                        return 1;
 830                case 0x04:
 831                        return 0;
 832                case 0x03:
 833                        break;
 834                default:
 835                        PDEBUG(D_USBI|D_USBO,
 836                                "sccb status 0x%02x, attempt %d/5",
 837                                data, i + 1);
 838                }
 839        }
 840        return 0;
 841}
 842
 843static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
 844{
 845        PDEBUG(D_USBO, "sccb_write [%02x] = %02x", reg, val);
 846        reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg);
 847        reg_w_i(gspca_dev, OV534_REG_WRITE, val);
 848        reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
 849
 850        if (!sccb_check_status(gspca_dev))
 851                PDEBUG(D_ERR, "sccb_write failed");
 852}
 853
 854static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
 855{
 856        reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
 857        reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
 858        if (!sccb_check_status(gspca_dev))
 859                PDEBUG(D_ERR, "sccb_read failed 1");
 860
 861        reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
 862        if (!sccb_check_status(gspca_dev))
 863                PDEBUG(D_ERR, "sccb_read failed 2");
 864
 865        return reg_r(gspca_dev, OV534_REG_READ);
 866}
 867
 868/* output a bridge sequence (reg - val) */
 869static void reg_w_array(struct gspca_dev *gspca_dev,
 870                        const u8 (*data)[2], int len)
 871{
 872        while (--len >= 0) {
 873                reg_w(gspca_dev, (*data)[0], (*data)[1]);
 874                data++;
 875        }
 876}
 877
 878/* output a sensor sequence (reg - val) */
 879static void sccb_w_array(struct gspca_dev *gspca_dev,
 880                        const u8 (*data)[2], int len)
 881{
 882        while (--len >= 0) {
 883                if ((*data)[0] != 0xff) {
 884                        sccb_write(gspca_dev, (*data)[0], (*data)[1]);
 885                } else {
 886                        sccb_read(gspca_dev, (*data)[1]);
 887                        sccb_write(gspca_dev, 0xff, 0x00);
 888                }
 889                data++;
 890        }
 891}
 892
 893/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
 894 * (direction and output)? */
 895static void set_led(struct gspca_dev *gspca_dev, int status)
 896{
 897        u8 data;
 898
 899        PDEBUG(D_CONF, "led status: %d", status);
 900
 901        data = reg_r(gspca_dev, 0x21);
 902        data |= 0x80;
 903        reg_w(gspca_dev, 0x21, data);
 904
 905        data = reg_r(gspca_dev, 0x23);
 906        if (status)
 907                data |= 0x80;
 908        else
 909                data &= ~0x80;
 910
 911        reg_w(gspca_dev, 0x23, data);
 912
 913        if (!status) {
 914                data = reg_r(gspca_dev, 0x21);
 915                data &= ~0x80;
 916                reg_w(gspca_dev, 0x21, data);
 917        }
 918}
 919
 920static void setbrightness(struct gspca_dev *gspca_dev)
 921{
 922        struct sd *sd = (struct sd *) gspca_dev;
 923        u8 val;
 924
 925        val = sd->brightness;
 926        if (val < 8)
 927                val = 15 - val;         /* f .. 8 */
 928        else
 929                val = val - 8;          /* 0 .. 7 */
 930        sccb_write(gspca_dev, 0x55,     /* brtn - brightness adjustment */
 931                        0x0f | (val << 4));
 932}
 933
 934static void setcontrast(struct gspca_dev *gspca_dev)
 935{
 936        struct sd *sd = (struct sd *) gspca_dev;
 937
 938        sccb_write(gspca_dev, 0x56,     /* cnst1 - contrast 1 ctrl coeff */
 939                        sd->contrast << 4);
 940}
 941
 942static void setautogain(struct gspca_dev *gspca_dev)
 943{
 944        struct sd *sd = (struct sd *) gspca_dev;
 945        u8 val;
 946
 947/*fixme: should adjust agc/awb/aec by different controls */
 948        val = sd->autogain;
 949        val = sccb_read(gspca_dev, 0x13);               /* com8 */
 950        sccb_write(gspca_dev, 0xff, 0x00);
 951        if (sd->autogain)
 952                val |= 0x05;            /* agc & aec */
 953        else
 954                val &= 0xfa;
 955        sccb_write(gspca_dev, 0x13, val);
 956}
 957
 958static void setexposure(struct gspca_dev *gspca_dev)
 959{
 960        struct sd *sd = (struct sd *) gspca_dev;
 961        u8 val;
 962        static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
 963
 964        sccb_write(gspca_dev, 0x10,                     /* aec[9:2] */
 965                        expo[sd->exposure]);
 966
 967        val = sccb_read(gspca_dev, 0x13);               /* com8 */
 968        sccb_write(gspca_dev, 0xff, 0x00);
 969        sccb_write(gspca_dev, 0x13, val);
 970
 971        val = sccb_read(gspca_dev, 0xa1);               /* aech */
 972        sccb_write(gspca_dev, 0xff, 0x00);
 973        sccb_write(gspca_dev, 0xa1, val & 0xe0);        /* aec[15:10] = 0 */
 974}
 975
 976static void setsharpness(struct gspca_dev *gspca_dev)
 977{
 978        struct sd *sd = (struct sd *) gspca_dev;
 979        s8 val;
 980
 981        val = sd->sharpness;
 982        if (val < 0) {                          /* auto */
 983                val = sccb_read(gspca_dev, 0x42);       /* com17 */
 984                sccb_write(gspca_dev, 0xff, 0x00);
 985                sccb_write(gspca_dev, 0x42, val | 0x40);
 986                                /* Edge enhancement strength auto adjust */
 987                return;
 988        }
 989        if (val != 0)
 990                val = 1 << (val - 1);
 991        sccb_write(gspca_dev, 0x3f,     /* edge - edge enhance. factor */
 992                        val);
 993        val = sccb_read(gspca_dev, 0x42);               /* com17 */
 994        sccb_write(gspca_dev, 0xff, 0x00);
 995        sccb_write(gspca_dev, 0x42, val & 0xbf);
 996}
 997
 998static void setsatur(struct gspca_dev *gspca_dev)
 999{
1000        struct sd *sd = (struct sd *) gspca_dev;
1001        u8 val1, val2, val3;
1002        static const u8 matrix[5][2] = {
1003                {0x14, 0x38},
1004                {0x1e, 0x54},
1005                {0x28, 0x70},
1006                {0x32, 0x8c},
1007                {0x48, 0x90}
1008        };
1009
1010        val1 = matrix[sd->satur][0];
1011        val2 = matrix[sd->satur][1];
1012        val3 = val1 + val2;
1013        sccb_write(gspca_dev, 0x4f, val3);      /* matrix coeff */
1014        sccb_write(gspca_dev, 0x50, val3);
1015        sccb_write(gspca_dev, 0x51, 0x00);
1016        sccb_write(gspca_dev, 0x52, val1);
1017        sccb_write(gspca_dev, 0x53, val2);
1018        sccb_write(gspca_dev, 0x54, val3);
1019        sccb_write(gspca_dev, 0x58, 0x1a);      /* mtxs - coeff signs */
1020
1021        val1 = sccb_read(gspca_dev, 0x41);      /* com16 */
1022        sccb_write(gspca_dev, 0xff, 0x00);
1023        sccb_write(gspca_dev, 0x41, val1);
1024}
1025
1026static void setfreq(struct gspca_dev *gspca_dev)
1027{
1028        struct sd *sd = (struct sd *) gspca_dev;
1029        u8 val;
1030
1031        val = sccb_read(gspca_dev, 0x13);               /* com8 */
1032        sccb_write(gspca_dev, 0xff, 0x00);
1033        if (sd->freq == 0) {
1034                sccb_write(gspca_dev, 0x13, val & 0xdf);
1035                return;
1036        }
1037        sccb_write(gspca_dev, 0x13, val | 0x20);
1038
1039        val = sccb_read(gspca_dev, 0x42);               /* com17 */
1040        sccb_write(gspca_dev, 0xff, 0x00);
1041        if (sd->freq == 1)
1042                val |= 0x01;
1043        else
1044                val &= 0xfe;
1045        sccb_write(gspca_dev, 0x42, val);
1046}
1047
1048/* this function is called at probe time */
1049static int sd_config(struct gspca_dev *gspca_dev,
1050                     const struct usb_device_id *id)
1051{
1052        struct sd *sd = (struct sd *) gspca_dev;
1053        struct cam *cam;
1054
1055        cam = &gspca_dev->cam;
1056
1057        cam->cam_mode = ov965x_mode;
1058        cam->nmodes = ARRAY_SIZE(ov965x_mode);
1059
1060        sd->brightness = BRIGHTNESS_DEF;
1061        sd->contrast = CONTRAST_DEF;
1062#if AUTOGAIN_DEF != 0
1063        sd->autogain = AUTOGAIN_DEF;
1064        gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
1065#endif
1066#if EXPO_DEF != 0
1067        sd->exposure = EXPO_DEF;
1068#endif
1069#if SHARPNESS_DEF != 0
1070        sd->sharpness = SHARPNESS_DEF;
1071#endif
1072        sd->satur = SATUR_DEF;
1073        sd->freq = FREQ_DEF;
1074
1075        return 0;
1076}
1077
1078/* this function is called at probe and resume time */
1079static int sd_init(struct gspca_dev *gspca_dev)
1080{
1081        u16 sensor_id;
1082
1083        /* reset bridge */
1084        reg_w(gspca_dev, 0xe7, 0x3a);
1085        reg_w(gspca_dev, 0xe0, 0x08);
1086        msleep(100);
1087
1088        /* initialize the sensor address */
1089        reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60);
1090
1091        /* reset sensor */
1092        sccb_write(gspca_dev, 0x12, 0x80);
1093        msleep(10);
1094
1095        /* probe the sensor */
1096        sccb_read(gspca_dev, 0x0a);
1097        sensor_id = sccb_read(gspca_dev, 0x0a) << 8;
1098        sccb_read(gspca_dev, 0x0b);
1099        sensor_id |= sccb_read(gspca_dev, 0x0b);
1100        PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
1101
1102        /* initialize */
1103        reg_w_array(gspca_dev, bridge_init,
1104                        ARRAY_SIZE(bridge_init));
1105        sccb_w_array(gspca_dev, sensor_init,
1106                        ARRAY_SIZE(sensor_init));
1107        reg_w_array(gspca_dev, bridge_init_2,
1108                        ARRAY_SIZE(bridge_init_2));
1109        sccb_w_array(gspca_dev, sensor_init_2,
1110                        ARRAY_SIZE(sensor_init_2));
1111        reg_w(gspca_dev, 0xe0, 0x00);
1112        reg_w(gspca_dev, 0xe0, 0x01);
1113        set_led(gspca_dev, 0);
1114        reg_w(gspca_dev, 0xe0, 0x00);
1115
1116        return gspca_dev->usb_err;
1117}
1118
1119static int sd_start(struct gspca_dev *gspca_dev)
1120{
1121        switch (gspca_dev->curr_mode) {
1122        case QVGA_MODE:                 /* 320x240 */
1123                sccb_w_array(gspca_dev, sensor_start_1_vga,
1124                                ARRAY_SIZE(sensor_start_1_vga));
1125                reg_w_array(gspca_dev, bridge_start_qvga,
1126                                ARRAY_SIZE(bridge_start_qvga));
1127                sccb_w_array(gspca_dev, sensor_start_2_qvga,
1128                                ARRAY_SIZE(sensor_start_2_qvga));
1129                break;
1130        case VGA_MODE:                  /* 640x480 */
1131                sccb_w_array(gspca_dev, sensor_start_1_vga,
1132                                ARRAY_SIZE(sensor_start_1_vga));
1133                reg_w_array(gspca_dev, bridge_start_vga,
1134                                ARRAY_SIZE(bridge_start_vga));
1135                sccb_w_array(gspca_dev, sensor_start_2_vga,
1136                                ARRAY_SIZE(sensor_start_2_vga));
1137                break;
1138        case SVGA_MODE:                 /* 800x600 */
1139                sccb_w_array(gspca_dev, sensor_start_1_svga,
1140                                ARRAY_SIZE(sensor_start_1_svga));
1141                reg_w_array(gspca_dev, bridge_start_svga,
1142                                ARRAY_SIZE(bridge_start_svga));
1143                sccb_w_array(gspca_dev, sensor_start_2_svga,
1144                                ARRAY_SIZE(sensor_start_2_svga));
1145                break;
1146        case XGA_MODE:                  /* 1024x768 */
1147                sccb_w_array(gspca_dev, sensor_start_1_xga,
1148                                ARRAY_SIZE(sensor_start_1_xga));
1149                reg_w_array(gspca_dev, bridge_start_xga,
1150                                ARRAY_SIZE(bridge_start_xga));
1151                sccb_w_array(gspca_dev, sensor_start_2_svga,
1152                                ARRAY_SIZE(sensor_start_2_svga));
1153                break;
1154        default:
1155/*      case SXGA_MODE:                  * 1280x1024 */
1156                sccb_w_array(gspca_dev, sensor_start_1_sxga,
1157                                ARRAY_SIZE(sensor_start_1_sxga));
1158                reg_w_array(gspca_dev, bridge_start_sxga,
1159                                ARRAY_SIZE(bridge_start_sxga));
1160                sccb_w_array(gspca_dev, sensor_start_2_sxga,
1161                                ARRAY_SIZE(sensor_start_2_sxga));
1162                break;
1163        }
1164        setfreq(gspca_dev);
1165        setautogain(gspca_dev);
1166        setbrightness(gspca_dev);
1167        setcontrast(gspca_dev);
1168        setexposure(gspca_dev);
1169        setsharpness(gspca_dev);
1170        setsatur(gspca_dev);
1171
1172        reg_w(gspca_dev, 0xe0, 0x00);
1173        reg_w(gspca_dev, 0xe0, 0x00);
1174        set_led(gspca_dev, 1);
1175        return gspca_dev->usb_err;
1176}
1177
1178static void sd_stopN(struct gspca_dev *gspca_dev)
1179{
1180        reg_w(gspca_dev, 0xe0, 0x01);
1181        set_led(gspca_dev, 0);
1182        reg_w(gspca_dev, 0xe0, 0x00);
1183}
1184
1185/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
1186#define UVC_STREAM_EOH  (1 << 7)
1187#define UVC_STREAM_ERR  (1 << 6)
1188#define UVC_STREAM_STI  (1 << 5)
1189#define UVC_STREAM_RES  (1 << 4)
1190#define UVC_STREAM_SCR  (1 << 3)
1191#define UVC_STREAM_PTS  (1 << 2)
1192#define UVC_STREAM_EOF  (1 << 1)
1193#define UVC_STREAM_FID  (1 << 0)
1194
1195static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1196                        u8 *data, int len)
1197{
1198        struct sd *sd = (struct sd *) gspca_dev;
1199        __u32 this_pts;
1200        u8 this_fid;
1201        int remaining_len = len;
1202
1203        do {
1204                len = min(remaining_len, 2040);
1205
1206                /* Payloads are prefixed with a UVC-style header.  We
1207                   consider a frame to start when the FID toggles, or the PTS
1208                   changes.  A frame ends when EOF is set, and we've received
1209                   the correct number of bytes. */
1210
1211                /* Verify UVC header.  Header length is always 12 */
1212                if (data[0] != 12 || len < 12) {
1213                        PDEBUG(D_PACK, "bad header");
1214                        goto discard;
1215                }
1216
1217                /* Check errors */
1218                if (data[1] & UVC_STREAM_ERR) {
1219                        PDEBUG(D_PACK, "payload error");
1220                        goto discard;
1221                }
1222
1223                /* Extract PTS and FID */
1224                if (!(data[1] & UVC_STREAM_PTS)) {
1225                        PDEBUG(D_PACK, "PTS not present");
1226                        goto discard;
1227                }
1228                this_pts = (data[5] << 24) | (data[4] << 16)
1229                                                | (data[3] << 8) | data[2];
1230                this_fid = data[1] & UVC_STREAM_FID;
1231
1232                /* If PTS or FID has changed, start a new frame. */
1233                if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
1234                        if (gspca_dev->last_packet_type == INTER_PACKET)
1235                                gspca_frame_add(gspca_dev, LAST_PACKET,
1236                                                NULL, 0);
1237                        sd->last_pts = this_pts;
1238                        sd->last_fid = this_fid;
1239                        gspca_frame_add(gspca_dev, FIRST_PACKET,
1240                                        data + 12, len - 12);
1241                /* If this packet is marked as EOF, end the frame */
1242                } else if (data[1] & UVC_STREAM_EOF) {
1243                        sd->last_pts = 0;
1244                        gspca_frame_add(gspca_dev, LAST_PACKET,
1245                                        data + 12, len - 12);
1246                } else {
1247
1248                        /* Add the data from this payload */
1249                        gspca_frame_add(gspca_dev, INTER_PACKET,
1250                                        data + 12, len - 12);
1251                }
1252
1253                /* Done this payload */
1254                goto scan_next;
1255
1256discard:
1257                /* Discard data until a new frame starts. */
1258                gspca_dev->last_packet_type = DISCARD_PACKET;
1259
1260scan_next:
1261                remaining_len -= len;
1262                data += len;
1263        } while (remaining_len > 0);
1264}
1265
1266/* controls */
1267static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1268{
1269        struct sd *sd = (struct sd *) gspca_dev;
1270
1271        sd->brightness = val;
1272        if (gspca_dev->streaming)
1273                setbrightness(gspca_dev);
1274        return gspca_dev->usb_err;
1275}
1276
1277static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1278{
1279        struct sd *sd = (struct sd *) gspca_dev;
1280
1281        *val = sd->brightness;
1282        return 0;
1283}
1284
1285static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1286{
1287        struct sd *sd = (struct sd *) gspca_dev;
1288
1289        sd->contrast = val;
1290        if (gspca_dev->streaming)
1291                setcontrast(gspca_dev);
1292        return gspca_dev->usb_err;
1293}
1294
1295static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1296{
1297        struct sd *sd = (struct sd *) gspca_dev;
1298
1299        *val = sd->contrast;
1300        return 0;
1301}
1302
1303static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1304{
1305        struct sd *sd = (struct sd *) gspca_dev;
1306
1307        sd->autogain = val;
1308
1309        if (gspca_dev->streaming) {
1310                if (val)
1311                        gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
1312                else
1313                        gspca_dev->ctrl_inac &= ~(1 << EXPO_IDX);
1314                setautogain(gspca_dev);
1315        }
1316        return gspca_dev->usb_err;
1317}
1318
1319static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1320{
1321        struct sd *sd = (struct sd *) gspca_dev;
1322
1323        *val = sd->autogain;
1324        return 0;
1325}
1326
1327static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1328{
1329        struct sd *sd = (struct sd *) gspca_dev;
1330
1331        sd->exposure = val;
1332        if (gspca_dev->streaming)
1333                setexposure(gspca_dev);
1334        return gspca_dev->usb_err;
1335}
1336
1337static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1338{
1339        struct sd *sd = (struct sd *) gspca_dev;
1340
1341        *val = sd->exposure;
1342        return 0;
1343}
1344
1345static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1346{
1347        struct sd *sd = (struct sd *) gspca_dev;
1348
1349        sd->sharpness = val;
1350        if (gspca_dev->streaming)
1351                setsharpness(gspca_dev);
1352        return gspca_dev->usb_err;
1353}
1354
1355static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1356{
1357        struct sd *sd = (struct sd *) gspca_dev;
1358
1359        *val = sd->sharpness;
1360        return 0;
1361}
1362
1363static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val)
1364{
1365        struct sd *sd = (struct sd *) gspca_dev;
1366
1367        sd->satur = val;
1368        if (gspca_dev->streaming)
1369                setsatur(gspca_dev);
1370        return gspca_dev->usb_err;
1371}
1372
1373static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val)
1374{
1375        struct sd *sd = (struct sd *) gspca_dev;
1376
1377        *val = sd->satur;
1378        return 0;
1379}
1380static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1381{
1382        struct sd *sd = (struct sd *) gspca_dev;
1383
1384        sd->freq = val;
1385        if (gspca_dev->streaming)
1386                setfreq(gspca_dev);
1387        return gspca_dev->usb_err;
1388}
1389
1390static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1391{
1392        struct sd *sd = (struct sd *) gspca_dev;
1393
1394        *val = sd->freq;
1395        return 0;
1396}
1397
1398static int sd_querymenu(struct gspca_dev *gspca_dev,
1399                        struct v4l2_querymenu *menu)
1400{
1401        switch (menu->id) {
1402        case V4L2_CID_POWER_LINE_FREQUENCY:
1403                switch (menu->index) {
1404                case 0:         /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1405                        strcpy((char *) menu->name, "NoFliker");
1406                        return 0;
1407                case 1:         /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1408                        strcpy((char *) menu->name, "50 Hz");
1409                        return 0;
1410                case 2:         /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1411                        strcpy((char *) menu->name, "60 Hz");
1412                        return 0;
1413                }
1414                break;
1415        }
1416        return -EINVAL;
1417}
1418
1419/* sub-driver description */
1420static const struct sd_desc sd_desc = {
1421        .name     = MODULE_NAME,
1422        .ctrls    = sd_ctrls,
1423        .nctrls   = ARRAY_SIZE(sd_ctrls),
1424        .config   = sd_config,
1425        .init     = sd_init,
1426        .start    = sd_start,
1427        .stopN    = sd_stopN,
1428        .pkt_scan = sd_pkt_scan,
1429        .querymenu = sd_querymenu,
1430};
1431
1432/* -- module initialisation -- */
1433static const __devinitdata struct usb_device_id device_table[] = {
1434        {USB_DEVICE(0x06f8, 0x3003)},
1435        {}
1436};
1437
1438MODULE_DEVICE_TABLE(usb, device_table);
1439
1440/* -- device connect -- */
1441static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
1442{
1443        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1444                                THIS_MODULE);
1445}
1446
1447static struct usb_driver sd_driver = {
1448        .name       = MODULE_NAME,
1449        .id_table   = device_table,
1450        .probe      = sd_probe,
1451        .disconnect = gspca_disconnect,
1452#ifdef CONFIG_PM
1453        .suspend    = gspca_suspend,
1454        .resume     = gspca_resume,
1455#endif
1456};
1457
1458/* -- module insert / remove -- */
1459static int __init sd_mod_init(void)
1460{
1461        int ret;
1462
1463        ret = usb_register(&sd_driver);
1464        if (ret < 0)
1465                return ret;
1466        PDEBUG(D_PROBE, "registered");
1467        return 0;
1468}
1469
1470static void __exit sd_mod_exit(void)
1471{
1472        usb_deregister(&sd_driver);
1473        PDEBUG(D_PROBE, "deregistered");
1474}
1475
1476module_init(sd_mod_init);
1477module_exit(sd_mod_exit);
1478
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.