linux/drivers/media/video/gspca/ov534.c
<<
>>
Prefs
   1/*
   2 * ov534-ov7xxx gspca driver
   3 *
   4 * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
   5 * Copyright (C) 2008 Jim Paris <jim@jtan.com>
   6 * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr
   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 * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr
  13 * PS3 Eye camera - brightness, contrast, awb, agc, aec controls
  14 *                  added by Max Thrun <bear24rw@gmail.com>
  15 *
  16 * This program is free software; you can redistribute it and/or modify
  17 * it under the terms of the GNU General Public License as published by
  18 * the Free Software Foundation; either version 2 of the License, or
  19 * any later version.
  20 *
  21 * This program is distributed in the hope that it will be useful,
  22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24 * GNU General Public License for more details.
  25 *
  26 * You should have received a copy of the GNU General Public License
  27 * along with this program; if not, write to the Free Software
  28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  29 */
  30
  31#define MODULE_NAME "ov534"
  32
  33#include "gspca.h"
  34
  35#define OV534_REG_ADDRESS       0xf1    /* sensor address */
  36#define OV534_REG_SUBADDR       0xf2
  37#define OV534_REG_WRITE         0xf3
  38#define OV534_REG_READ          0xf4
  39#define OV534_REG_OPERATION     0xf5
  40#define OV534_REG_STATUS        0xf6
  41
  42#define OV534_OP_WRITE_3        0x37
  43#define OV534_OP_WRITE_2        0x33
  44#define OV534_OP_READ_2         0xf9
  45
  46#define CTRL_TIMEOUT 500
  47
  48MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
  49MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver");
  50MODULE_LICENSE("GPL");
  51
  52/* controls */
  53enum e_ctrl {
  54        BRIGHTNESS,
  55        CONTRAST,
  56        GAIN,
  57        EXPOSURE,
  58        AGC,
  59        AWB,
  60        AEC,
  61        SHARPNESS,
  62        HFLIP,
  63        VFLIP,
  64        COLORS,
  65        LIGHTFREQ,
  66        NCTRLS          /* number of controls */
  67};
  68
  69/* specific webcam descriptor */
  70struct sd {
  71        struct gspca_dev gspca_dev;     /* !! must be the first item */
  72
  73        struct gspca_ctrl ctrls[NCTRLS];
  74
  75        __u32 last_pts;
  76        u16 last_fid;
  77        u8 frame_rate;
  78
  79        u8 sensor;
  80};
  81enum sensors {
  82        SENSOR_OV767x,
  83        SENSOR_OV772x,
  84        NSENSORS
  85};
  86
  87/* V4L2 controls supported by the driver */
  88static void setbrightness(struct gspca_dev *gspca_dev);
  89static void setcontrast(struct gspca_dev *gspca_dev);
  90static void setgain(struct gspca_dev *gspca_dev);
  91static void setexposure(struct gspca_dev *gspca_dev);
  92static int sd_setagc(struct gspca_dev *gspca_dev, __s32 val);
  93static void setawb(struct gspca_dev *gspca_dev);
  94static void setaec(struct gspca_dev *gspca_dev);
  95static void setsharpness(struct gspca_dev *gspca_dev);
  96static void sethvflip(struct gspca_dev *gspca_dev);
  97static void setcolors(struct gspca_dev *gspca_dev);
  98static void setlightfreq(struct gspca_dev *gspca_dev);
  99
 100static int sd_start(struct gspca_dev *gspca_dev);
 101static void sd_stopN(struct gspca_dev *gspca_dev);
 102
 103static const struct ctrl sd_ctrls[] = {
 104[BRIGHTNESS] = {
 105                {
 106                        .id      = V4L2_CID_BRIGHTNESS,
 107                        .type    = V4L2_CTRL_TYPE_INTEGER,
 108                        .name    = "Brightness",
 109                        .minimum = 0,
 110                        .maximum = 255,
 111                        .step    = 1,
 112                        .default_value = 0,
 113                },
 114                .set_control = setbrightness
 115        },
 116[CONTRAST] = {
 117                {
 118                        .id      = V4L2_CID_CONTRAST,
 119                        .type    = V4L2_CTRL_TYPE_INTEGER,
 120                        .name    = "Contrast",
 121                        .minimum = 0,
 122                        .maximum = 255,
 123                        .step    = 1,
 124                        .default_value = 32,
 125                },
 126                .set_control = setcontrast
 127        },
 128[GAIN] = {
 129                {
 130                        .id      = V4L2_CID_GAIN,
 131                        .type    = V4L2_CTRL_TYPE_INTEGER,
 132                        .name    = "Main Gain",
 133                        .minimum = 0,
 134                        .maximum = 63,
 135                        .step    = 1,
 136                        .default_value = 20,
 137                },
 138                .set_control = setgain
 139        },
 140[EXPOSURE] = {
 141                {
 142                        .id      = V4L2_CID_EXPOSURE,
 143                        .type    = V4L2_CTRL_TYPE_INTEGER,
 144                        .name    = "Exposure",
 145                        .minimum = 0,
 146                        .maximum = 255,
 147                        .step    = 1,
 148                        .default_value = 120,
 149                },
 150                .set_control = setexposure
 151        },
 152[AGC] = {
 153                {
 154                        .id      = V4L2_CID_AUTOGAIN,
 155                        .type    = V4L2_CTRL_TYPE_BOOLEAN,
 156                        .name    = "Auto Gain",
 157                        .minimum = 0,
 158                        .maximum = 1,
 159                        .step    = 1,
 160                        .default_value = 1,
 161                },
 162                .set = sd_setagc
 163        },
 164[AWB] = {
 165                {
 166                        .id      = V4L2_CID_AUTO_WHITE_BALANCE,
 167                        .type    = V4L2_CTRL_TYPE_BOOLEAN,
 168                        .name    = "Auto White Balance",
 169                        .minimum = 0,
 170                        .maximum = 1,
 171                        .step    = 1,
 172                        .default_value = 1,
 173                },
 174                .set_control = setawb
 175        },
 176[AEC] = {
 177                {
 178                        .id      = V4L2_CID_EXPOSURE_AUTO,
 179                        .type    = V4L2_CTRL_TYPE_BOOLEAN,
 180                        .name    = "Auto Exposure",
 181                        .minimum = 0,
 182                        .maximum = 1,
 183                        .step    = 1,
 184                        .default_value = 1,
 185                },
 186                .set_control = setaec
 187        },
 188[SHARPNESS] = {
 189                {
 190                        .id      = V4L2_CID_SHARPNESS,
 191                        .type    = V4L2_CTRL_TYPE_INTEGER,
 192                        .name    = "Sharpness",
 193                        .minimum = 0,
 194                        .maximum = 63,
 195                        .step    = 1,
 196                        .default_value = 0,
 197                },
 198                .set_control = setsharpness
 199        },
 200[HFLIP] = {
 201                {
 202                        .id      = V4L2_CID_HFLIP,
 203                        .type    = V4L2_CTRL_TYPE_BOOLEAN,
 204                        .name    = "HFlip",
 205                        .minimum = 0,
 206                        .maximum = 1,
 207                        .step    = 1,
 208                        .default_value = 0,
 209                },
 210                .set_control = sethvflip
 211        },
 212[VFLIP] = {
 213                {
 214                        .id      = V4L2_CID_VFLIP,
 215                        .type    = V4L2_CTRL_TYPE_BOOLEAN,
 216                        .name    = "VFlip",
 217                        .minimum = 0,
 218                        .maximum = 1,
 219                        .step    = 1,
 220                        .default_value = 0,
 221                },
 222                .set_control = sethvflip
 223        },
 224[COLORS] = {
 225                {
 226                        .id      = V4L2_CID_SATURATION,
 227                        .type    = V4L2_CTRL_TYPE_INTEGER,
 228                        .name    = "Saturation",
 229                        .minimum = 0,
 230                        .maximum = 6,
 231                        .step    = 1,
 232                        .default_value = 3,
 233                },
 234                .set_control = setcolors
 235        },
 236[LIGHTFREQ] = {
 237                {
 238                        .id      = V4L2_CID_POWER_LINE_FREQUENCY,
 239                        .type    = V4L2_CTRL_TYPE_MENU,
 240                        .name    = "Light Frequency Filter",
 241                        .minimum = 0,
 242                        .maximum = 1,
 243                        .step    = 1,
 244                        .default_value = 0,
 245                },
 246                .set_control = setlightfreq
 247        },
 248};
 249
 250static const struct v4l2_pix_format ov772x_mode[] = {
 251        {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
 252         .bytesperline = 320 * 2,
 253         .sizeimage = 320 * 240 * 2,
 254         .colorspace = V4L2_COLORSPACE_SRGB,
 255         .priv = 1},
 256        {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
 257         .bytesperline = 640 * 2,
 258         .sizeimage = 640 * 480 * 2,
 259         .colorspace = V4L2_COLORSPACE_SRGB,
 260         .priv = 0},
 261};
 262static const struct v4l2_pix_format ov767x_mode[] = {
 263        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 264                .bytesperline = 320,
 265                .sizeimage = 320 * 240 * 3 / 8 + 590,
 266                .colorspace = V4L2_COLORSPACE_JPEG},
 267        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 268                .bytesperline = 640,
 269                .sizeimage = 640 * 480 * 3 / 8 + 590,
 270                .colorspace = V4L2_COLORSPACE_JPEG},
 271};
 272
 273static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30};
 274static const u8 vga_rates[] = {60, 50, 40, 30, 15};
 275
 276static const struct framerates ov772x_framerates[] = {
 277        { /* 320x240 */
 278                .rates = qvga_rates,
 279                .nrates = ARRAY_SIZE(qvga_rates),
 280        },
 281        { /* 640x480 */
 282                .rates = vga_rates,
 283                .nrates = ARRAY_SIZE(vga_rates),
 284        },
 285};
 286
 287struct reg_array {
 288        const u8 (*val)[2];
 289        int len;
 290};
 291
 292static const u8 bridge_init_767x[][2] = {
 293/* comments from the ms-win file apollo7670.set */
 294/* str1 */
 295        {0xf1, 0x42},
 296        {0x88, 0xf8},
 297        {0x89, 0xff},
 298        {0x76, 0x03},
 299        {0x92, 0x03},
 300        {0x95, 0x10},
 301        {0xe2, 0x00},
 302        {0xe7, 0x3e},
 303        {0x8d, 0x1c},
 304        {0x8e, 0x00},
 305        {0x8f, 0x00},
 306        {0x1f, 0x00},
 307        {0xc3, 0xf9},
 308        {0x89, 0xff},
 309        {0x88, 0xf8},
 310        {0x76, 0x03},
 311        {0x92, 0x01},
 312        {0x93, 0x18},
 313        {0x1c, 0x00},
 314        {0x1d, 0x48},
 315        {0x1d, 0x00},
 316        {0x1d, 0xff},
 317        {0x1d, 0x02},
 318        {0x1d, 0x58},
 319        {0x1d, 0x00},
 320        {0x1c, 0x0a},
 321        {0x1d, 0x0a},
 322        {0x1d, 0x0e},
 323        {0xc0, 0x50},   /* HSize 640 */
 324        {0xc1, 0x3c},   /* VSize 480 */
 325        {0x34, 0x05},   /* enable Audio Suspend mode */
 326        {0xc2, 0x0c},   /* Input YUV */
 327        {0xc3, 0xf9},   /* enable PRE */
 328        {0x34, 0x05},   /* enable Audio Suspend mode */
 329        {0xe7, 0x2e},   /* this solves failure of "SuspendResumeTest" */
 330        {0x31, 0xf9},   /* enable 1.8V Suspend */
 331        {0x35, 0x02},   /* turn on JPEG */
 332        {0xd9, 0x10},
 333        {0x25, 0x42},   /* GPIO[8]:Input */
 334        {0x94, 0x11},   /* If the default setting is loaded when
 335                         * system boots up, this flag is closed here */
 336};
 337static const u8 sensor_init_767x[][2] = {
 338        {0x12, 0x80},
 339        {0x11, 0x03},
 340        {0x3a, 0x04},
 341        {0x12, 0x00},
 342        {0x17, 0x13},
 343        {0x18, 0x01},
 344        {0x32, 0xb6},
 345        {0x19, 0x02},
 346        {0x1a, 0x7a},
 347        {0x03, 0x0a},
 348        {0x0c, 0x00},
 349        {0x3e, 0x00},
 350        {0x70, 0x3a},
 351        {0x71, 0x35},
 352        {0x72, 0x11},
 353        {0x73, 0xf0},
 354        {0xa2, 0x02},
 355        {0x7a, 0x2a},   /* set Gamma=1.6 below */
 356        {0x7b, 0x12},
 357        {0x7c, 0x1d},
 358        {0x7d, 0x2d},
 359        {0x7e, 0x45},
 360        {0x7f, 0x50},
 361        {0x80, 0x59},
 362        {0x81, 0x62},
 363        {0x82, 0x6b},
 364        {0x83, 0x73},
 365        {0x84, 0x7b},
 366        {0x85, 0x8a},
 367        {0x86, 0x98},
 368        {0x87, 0xb2},
 369        {0x88, 0xca},
 370        {0x89, 0xe0},
 371        {0x13, 0xe0},
 372        {0x00, 0x00},
 373        {0x10, 0x00},
 374        {0x0d, 0x40},
 375        {0x14, 0x38},   /* gain max 16x */
 376        {0xa5, 0x05},
 377        {0xab, 0x07},
 378        {0x24, 0x95},
 379        {0x25, 0x33},
 380        {0x26, 0xe3},
 381        {0x9f, 0x78},
 382        {0xa0, 0x68},
 383        {0xa1, 0x03},
 384        {0xa6, 0xd8},
 385        {0xa7, 0xd8},
 386        {0xa8, 0xf0},
 387        {0xa9, 0x90},
 388        {0xaa, 0x94},
 389        {0x13, 0xe5},
 390        {0x0e, 0x61},
 391        {0x0f, 0x4b},
 392        {0x16, 0x02},
 393        {0x21, 0x02},
 394        {0x22, 0x91},
 395        {0x29, 0x07},
 396        {0x33, 0x0b},
 397        {0x35, 0x0b},
 398        {0x37, 0x1d},
 399        {0x38, 0x71},
 400        {0x39, 0x2a},
 401        {0x3c, 0x78},
 402        {0x4d, 0x40},
 403        {0x4e, 0x20},
 404        {0x69, 0x00},
 405        {0x6b, 0x4a},
 406        {0x74, 0x10},
 407        {0x8d, 0x4f},
 408        {0x8e, 0x00},
 409        {0x8f, 0x00},
 410        {0x90, 0x00},
 411        {0x91, 0x00},
 412        {0x96, 0x00},
 413        {0x9a, 0x80},
 414        {0xb0, 0x84},
 415        {0xb1, 0x0c},
 416        {0xb2, 0x0e},
 417        {0xb3, 0x82},
 418        {0xb8, 0x0a},
 419        {0x43, 0x0a},
 420        {0x44, 0xf0},
 421        {0x45, 0x34},
 422        {0x46, 0x58},
 423        {0x47, 0x28},
 424        {0x48, 0x3a},
 425        {0x59, 0x88},
 426        {0x5a, 0x88},
 427        {0x5b, 0x44},
 428        {0x5c, 0x67},
 429        {0x5d, 0x49},
 430        {0x5e, 0x0e},
 431        {0x6c, 0x0a},
 432        {0x6d, 0x55},
 433        {0x6e, 0x11},
 434        {0x6f, 0x9f},
 435        {0x6a, 0x40},
 436        {0x01, 0x40},
 437        {0x02, 0x40},
 438        {0x13, 0xe7},
 439        {0x4f, 0x80},
 440        {0x50, 0x80},
 441        {0x51, 0x00},
 442        {0x52, 0x22},
 443        {0x53, 0x5e},
 444        {0x54, 0x80},
 445        {0x58, 0x9e},
 446        {0x41, 0x08},
 447        {0x3f, 0x00},
 448        {0x75, 0x04},
 449        {0x76, 0xe1},
 450        {0x4c, 0x00},
 451        {0x77, 0x01},
 452        {0x3d, 0xc2},
 453        {0x4b, 0x09},
 454        {0xc9, 0x60},
 455        {0x41, 0x38},   /* jfm: auto sharpness + auto de-noise  */
 456        {0x56, 0x40},
 457        {0x34, 0x11},
 458        {0x3b, 0xc2},
 459        {0xa4, 0x8a},   /* Night mode trigger point */
 460        {0x96, 0x00},
 461        {0x97, 0x30},
 462        {0x98, 0x20},
 463        {0x99, 0x20},
 464        {0x9a, 0x84},
 465        {0x9b, 0x29},
 466        {0x9c, 0x03},
 467        {0x9d, 0x4c},
 468        {0x9e, 0x3f},
 469        {0x78, 0x04},
 470        {0x79, 0x01},
 471        {0xc8, 0xf0},
 472        {0x79, 0x0f},
 473        {0xc8, 0x00},
 474        {0x79, 0x10},
 475        {0xc8, 0x7e},
 476        {0x79, 0x0a},
 477        {0xc8, 0x80},
 478        {0x79, 0x0b},
 479        {0xc8, 0x01},
 480        {0x79, 0x0c},
 481        {0xc8, 0x0f},
 482        {0x79, 0x0d},
 483        {0xc8, 0x20},
 484        {0x79, 0x09},
 485        {0xc8, 0x80},
 486        {0x79, 0x02},
 487        {0xc8, 0xc0},
 488        {0x79, 0x03},
 489        {0xc8, 0x20},
 490        {0x79, 0x26},
 491};
 492static const u8 bridge_start_vga_767x[][2] = {
 493/* str59 JPG */
 494        {0x94, 0xaa},
 495        {0xf1, 0x42},
 496        {0xe5, 0x04},
 497        {0xc0, 0x50},
 498        {0xc1, 0x3c},
 499        {0xc2, 0x0c},
 500        {0x35, 0x02},   /* turn on JPEG */
 501        {0xd9, 0x10},
 502        {0xda, 0x00},   /* for higher clock rate(30fps) */
 503        {0x34, 0x05},   /* enable Audio Suspend mode */
 504        {0xc3, 0xf9},   /* enable PRE */
 505        {0x8c, 0x00},   /* CIF VSize LSB[2:0] */
 506        {0x8d, 0x1c},   /* output YUV */
 507/*      {0x34, 0x05},    * enable Audio Suspend mode (?) */
 508        {0x50, 0x00},   /* H/V divider=0 */
 509        {0x51, 0xa0},   /* input H=640/4 */
 510        {0x52, 0x3c},   /* input V=480/4 */
 511        {0x53, 0x00},   /* offset X=0 */
 512        {0x54, 0x00},   /* offset Y=0 */
 513        {0x55, 0x00},   /* H/V size[8]=0 */
 514        {0x57, 0x00},   /* H-size[9]=0 */
 515        {0x5c, 0x00},   /* output size[9:8]=0 */
 516        {0x5a, 0xa0},   /* output H=640/4 */
 517        {0x5b, 0x78},   /* output V=480/4 */
 518        {0x1c, 0x0a},
 519        {0x1d, 0x0a},
 520        {0x94, 0x11},
 521};
 522static const u8 sensor_start_vga_767x[][2] = {
 523        {0x11, 0x01},
 524        {0x1e, 0x04},
 525        {0x19, 0x02},
 526        {0x1a, 0x7a},
 527};
 528static const u8 bridge_start_qvga_767x[][2] = {
 529/* str86 JPG */
 530        {0x94, 0xaa},
 531        {0xf1, 0x42},
 532        {0xe5, 0x04},
 533        {0xc0, 0x80},
 534        {0xc1, 0x60},
 535        {0xc2, 0x0c},
 536        {0x35, 0x02},   /* turn on JPEG */
 537        {0xd9, 0x10},
 538        {0xc0, 0x50},   /* CIF HSize 640 */
 539        {0xc1, 0x3c},   /* CIF VSize 480 */
 540        {0x8c, 0x00},   /* CIF VSize LSB[2:0] */
 541        {0x8d, 0x1c},   /* output YUV */
 542        {0x34, 0x05},   /* enable Audio Suspend mode */
 543        {0xc2, 0x4c},   /* output YUV and Enable DCW */
 544        {0xc3, 0xf9},   /* enable PRE */
 545        {0x1c, 0x00},   /* indirect addressing */
 546        {0x1d, 0x48},   /* output YUV422 */
 547        {0x50, 0x89},   /* H/V divider=/2; plus DCW AVG */
 548        {0x51, 0xa0},   /* DCW input H=640/4 */
 549        {0x52, 0x78},   /* DCW input V=480/4 */
 550        {0x53, 0x00},   /* offset X=0 */
 551        {0x54, 0x00},   /* offset Y=0 */
 552        {0x55, 0x00},   /* H/V size[8]=0 */
 553        {0x57, 0x00},   /* H-size[9]=0 */
 554        {0x5c, 0x00},   /* DCW output size[9:8]=0 */
 555        {0x5a, 0x50},   /* DCW output H=320/4 */
 556        {0x5b, 0x3c},   /* DCW output V=240/4 */
 557        {0x1c, 0x0a},
 558        {0x1d, 0x0a},
 559        {0x94, 0x11},
 560};
 561static const u8 sensor_start_qvga_767x[][2] = {
 562        {0x11, 0x01},
 563        {0x1e, 0x04},
 564        {0x19, 0x02},
 565        {0x1a, 0x7a},
 566};
 567
 568static const u8 bridge_init_772x[][2] = {
 569        { 0xc2, 0x0c },
 570        { 0x88, 0xf8 },
 571        { 0xc3, 0x69 },
 572        { 0x89, 0xff },
 573        { 0x76, 0x03 },
 574        { 0x92, 0x01 },
 575        { 0x93, 0x18 },
 576        { 0x94, 0x10 },
 577        { 0x95, 0x10 },
 578        { 0xe2, 0x00 },
 579        { 0xe7, 0x3e },
 580
 581        { 0x96, 0x00 },
 582
 583        { 0x97, 0x20 },
 584        { 0x97, 0x20 },
 585        { 0x97, 0x20 },
 586        { 0x97, 0x0a },
 587        { 0x97, 0x3f },
 588        { 0x97, 0x4a },
 589        { 0x97, 0x20 },
 590        { 0x97, 0x15 },
 591        { 0x97, 0x0b },
 592
 593        { 0x8e, 0x40 },
 594        { 0x1f, 0x81 },
 595        { 0x34, 0x05 },
 596        { 0xe3, 0x04 },
 597        { 0x88, 0x00 },
 598        { 0x89, 0x00 },
 599        { 0x76, 0x00 },
 600        { 0xe7, 0x2e },
 601        { 0x31, 0xf9 },
 602        { 0x25, 0x42 },
 603        { 0x21, 0xf0 },
 604
 605        { 0x1c, 0x00 },
 606        { 0x1d, 0x40 },
 607        { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */
 608        { 0x1d, 0x00 }, /* payload size */
 609
 610        { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */
 611        { 0x1d, 0x58 }, /* frame size */
 612        { 0x1d, 0x00 }, /* frame size */
 613
 614        { 0x1c, 0x0a },
 615        { 0x1d, 0x08 }, /* turn on UVC header */
 616        { 0x1d, 0x0e }, /* .. */
 617
 618        { 0x8d, 0x1c },
 619        { 0x8e, 0x80 },
 620        { 0xe5, 0x04 },
 621
 622        { 0xc0, 0x50 },
 623        { 0xc1, 0x3c },
 624        { 0xc2, 0x0c },
 625};
 626static const u8 sensor_init_772x[][2] = {
 627        { 0x12, 0x80 },
 628        { 0x11, 0x01 },
 629/*fixme: better have a delay?*/
 630        { 0x11, 0x01 },
 631        { 0x11, 0x01 },
 632        { 0x11, 0x01 },
 633        { 0x11, 0x01 },
 634        { 0x11, 0x01 },
 635        { 0x11, 0x01 },
 636        { 0x11, 0x01 },
 637        { 0x11, 0x01 },
 638        { 0x11, 0x01 },
 639        { 0x11, 0x01 },
 640
 641        { 0x3d, 0x03 },
 642        { 0x17, 0x26 },
 643        { 0x18, 0xa0 },
 644        { 0x19, 0x07 },
 645        { 0x1a, 0xf0 },
 646        { 0x32, 0x00 },
 647        { 0x29, 0xa0 },
 648        { 0x2c, 0xf0 },
 649        { 0x65, 0x20 },
 650        { 0x11, 0x01 },
 651        { 0x42, 0x7f },
 652        { 0x63, 0xaa },         /* AWB - was e0 */
 653        { 0x64, 0xff },
 654        { 0x66, 0x00 },
 655        { 0x13, 0xf0 },         /* com8 */
 656        { 0x0d, 0x41 },
 657        { 0x0f, 0xc5 },
 658        { 0x14, 0x11 },
 659
 660        { 0x22, 0x7f },
 661        { 0x23, 0x03 },
 662        { 0x24, 0x40 },
 663        { 0x25, 0x30 },
 664        { 0x26, 0xa1 },
 665        { 0x2a, 0x00 },
 666        { 0x2b, 0x00 },
 667        { 0x6b, 0xaa },
 668        { 0x13, 0xff },         /* AWB */
 669
 670        { 0x90, 0x05 },
 671        { 0x91, 0x01 },
 672        { 0x92, 0x03 },
 673        { 0x93, 0x00 },
 674        { 0x94, 0x60 },
 675        { 0x95, 0x3c },
 676        { 0x96, 0x24 },
 677        { 0x97, 0x1e },
 678        { 0x98, 0x62 },
 679        { 0x99, 0x80 },
 680        { 0x9a, 0x1e },
 681        { 0x9b, 0x08 },
 682        { 0x9c, 0x20 },
 683        { 0x9e, 0x81 },
 684
 685        { 0xa6, 0x04 },
 686        { 0x7e, 0x0c },
 687        { 0x7f, 0x16 },
 688        { 0x80, 0x2a },
 689        { 0x81, 0x4e },
 690        { 0x82, 0x61 },
 691        { 0x83, 0x6f },
 692        { 0x84, 0x7b },
 693        { 0x85, 0x86 },
 694        { 0x86, 0x8e },
 695        { 0x87, 0x97 },
 696        { 0x88, 0xa4 },
 697        { 0x89, 0xaf },
 698        { 0x8a, 0xc5 },
 699        { 0x8b, 0xd7 },
 700        { 0x8c, 0xe8 },
 701        { 0x8d, 0x20 },
 702
 703        { 0x0c, 0x90 },
 704
 705        { 0x2b, 0x00 },
 706        { 0x22, 0x7f },
 707        { 0x23, 0x03 },
 708        { 0x11, 0x01 },
 709        { 0x0c, 0xd0 },
 710        { 0x64, 0xff },
 711        { 0x0d, 0x41 },
 712
 713        { 0x14, 0x41 },
 714        { 0x0e, 0xcd },
 715        { 0xac, 0xbf },
 716        { 0x8e, 0x00 },         /* De-noise threshold */
 717        { 0x0c, 0xd0 }
 718};
 719static const u8 bridge_start_vga_772x[][2] = {
 720        {0x1c, 0x00},
 721        {0x1d, 0x40},
 722        {0x1d, 0x02},
 723        {0x1d, 0x00},
 724        {0x1d, 0x02},
 725        {0x1d, 0x58},
 726        {0x1d, 0x00},
 727        {0xc0, 0x50},
 728        {0xc1, 0x3c},
 729};
 730static const u8 sensor_start_vga_772x[][2] = {
 731        {0x12, 0x00},
 732        {0x17, 0x26},
 733        {0x18, 0xa0},
 734        {0x19, 0x07},
 735        {0x1a, 0xf0},
 736        {0x29, 0xa0},
 737        {0x2c, 0xf0},
 738        {0x65, 0x20},
 739};
 740static const u8 bridge_start_qvga_772x[][2] = {
 741        {0x1c, 0x00},
 742        {0x1d, 0x40},
 743        {0x1d, 0x02},
 744        {0x1d, 0x00},
 745        {0x1d, 0x01},
 746        {0x1d, 0x4b},
 747        {0x1d, 0x00},
 748        {0xc0, 0x28},
 749        {0xc1, 0x1e},
 750};
 751static const u8 sensor_start_qvga_772x[][2] = {
 752        {0x12, 0x40},
 753        {0x17, 0x3f},
 754        {0x18, 0x50},
 755        {0x19, 0x03},
 756        {0x1a, 0x78},
 757        {0x29, 0x50},
 758        {0x2c, 0x78},
 759        {0x65, 0x2f},
 760};
 761
 762static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
 763{
 764        struct usb_device *udev = gspca_dev->dev;
 765        int ret;
 766
 767        if (gspca_dev->usb_err < 0)
 768                return;
 769
 770        PDEBUG(D_USBO, "SET 01 0000 %04x %02x", reg, val);
 771        gspca_dev->usb_buf[0] = val;
 772        ret = usb_control_msg(udev,
 773                              usb_sndctrlpipe(udev, 0),
 774                              0x01,
 775                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 776                              0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 777        if (ret < 0) {
 778                err("write failed %d", ret);
 779                gspca_dev->usb_err = ret;
 780        }
 781}
 782
 783static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
 784{
 785        struct usb_device *udev = gspca_dev->dev;
 786        int ret;
 787
 788        if (gspca_dev->usb_err < 0)
 789                return 0;
 790        ret = usb_control_msg(udev,
 791                              usb_rcvctrlpipe(udev, 0),
 792                              0x01,
 793                              USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 794                              0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 795        PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]);
 796        if (ret < 0) {
 797                err("read failed %d", ret);
 798                gspca_dev->usb_err = ret;
 799        }
 800        return gspca_dev->usb_buf[0];
 801}
 802
 803/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
 804 * (direction and output)? */
 805static void ov534_set_led(struct gspca_dev *gspca_dev, int status)
 806{
 807        u8 data;
 808
 809        PDEBUG(D_CONF, "led status: %d", status);
 810
 811        data = ov534_reg_read(gspca_dev, 0x21);
 812        data |= 0x80;
 813        ov534_reg_write(gspca_dev, 0x21, data);
 814
 815        data = ov534_reg_read(gspca_dev, 0x23);
 816        if (status)
 817                data |= 0x80;
 818        else
 819                data &= ~0x80;
 820
 821        ov534_reg_write(gspca_dev, 0x23, data);
 822
 823        if (!status) {
 824                data = ov534_reg_read(gspca_dev, 0x21);
 825                data &= ~0x80;
 826                ov534_reg_write(gspca_dev, 0x21, data);
 827        }
 828}
 829
 830static int sccb_check_status(struct gspca_dev *gspca_dev)
 831{
 832        u8 data;
 833        int i;
 834
 835        for (i = 0; i < 5; i++) {
 836                data = ov534_reg_read(gspca_dev, OV534_REG_STATUS);
 837
 838                switch (data) {
 839                case 0x00:
 840                        return 1;
 841                case 0x04:
 842                        return 0;
 843                case 0x03:
 844                        break;
 845                default:
 846                        PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5",
 847                               data, i + 1);
 848                }
 849        }
 850        return 0;
 851}
 852
 853static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
 854{
 855        PDEBUG(D_USBO, "sccb write: %02x %02x", reg, val);
 856        ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
 857        ov534_reg_write(gspca_dev, OV534_REG_WRITE, val);
 858        ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
 859
 860        if (!sccb_check_status(gspca_dev)) {
 861                err("sccb_reg_write failed");
 862                gspca_dev->usb_err = -EIO;
 863        }
 864}
 865
 866static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
 867{
 868        ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
 869        ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
 870        if (!sccb_check_status(gspca_dev))
 871                err("sccb_reg_read failed 1");
 872
 873        ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
 874        if (!sccb_check_status(gspca_dev))
 875                err("sccb_reg_read failed 2");
 876
 877        return ov534_reg_read(gspca_dev, OV534_REG_READ);
 878}
 879
 880/* output a bridge sequence (reg - val) */
 881static void reg_w_array(struct gspca_dev *gspca_dev,
 882                        const u8 (*data)[2], int len)
 883{
 884        while (--len >= 0) {
 885                ov534_reg_write(gspca_dev, (*data)[0], (*data)[1]);
 886                data++;
 887        }
 888}
 889
 890/* output a sensor sequence (reg - val) */
 891static void sccb_w_array(struct gspca_dev *gspca_dev,
 892                        const u8 (*data)[2], int len)
 893{
 894        while (--len >= 0) {
 895                if ((*data)[0] != 0xff) {
 896                        sccb_reg_write(gspca_dev, (*data)[0], (*data)[1]);
 897                } else {
 898                        sccb_reg_read(gspca_dev, (*data)[1]);
 899                        sccb_reg_write(gspca_dev, 0xff, 0x00);
 900                }
 901                data++;
 902        }
 903}
 904
 905/* ov772x specific controls */
 906static void set_frame_rate(struct gspca_dev *gspca_dev)
 907{
 908        struct sd *sd = (struct sd *) gspca_dev;
 909        int i;
 910        struct rate_s {
 911                u8 fps;
 912                u8 r11;
 913                u8 r0d;
 914                u8 re5;
 915        };
 916        const struct rate_s *r;
 917        static const struct rate_s rate_0[] = { /* 640x480 */
 918                {60, 0x01, 0xc1, 0x04},
 919                {50, 0x01, 0x41, 0x02},
 920                {40, 0x02, 0xc1, 0x04},
 921                {30, 0x04, 0x81, 0x02},
 922                {15, 0x03, 0x41, 0x04},
 923        };
 924        static const struct rate_s rate_1[] = { /* 320x240 */
 925                {125, 0x02, 0x81, 0x02},
 926                {100, 0x02, 0xc1, 0x04},
 927                {75, 0x03, 0xc1, 0x04},
 928                {60, 0x04, 0xc1, 0x04},
 929                {50, 0x02, 0x41, 0x04},
 930                {40, 0x03, 0x41, 0x04},
 931                {30, 0x04, 0x41, 0x04},
 932        };
 933
 934        if (sd->sensor != SENSOR_OV772x)
 935                return;
 936        if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) {
 937                r = rate_0;
 938                i = ARRAY_SIZE(rate_0);
 939        } else {
 940                r = rate_1;
 941                i = ARRAY_SIZE(rate_1);
 942        }
 943        while (--i > 0) {
 944                if (sd->frame_rate >= r->fps)
 945                        break;
 946                r++;
 947        }
 948
 949        sccb_reg_write(gspca_dev, 0x11, r->r11);
 950        sccb_reg_write(gspca_dev, 0x0d, r->r0d);
 951        ov534_reg_write(gspca_dev, 0xe5, r->re5);
 952
 953        PDEBUG(D_PROBE, "frame_rate: %d", r->fps);
 954}
 955
 956static void setbrightness(struct gspca_dev *gspca_dev)
 957{
 958        struct sd *sd = (struct sd *) gspca_dev;
 959        int val;
 960
 961        val = sd->ctrls[BRIGHTNESS].val;
 962        if (sd->sensor == SENSOR_OV767x) {
 963                if (val < 0)
 964                        val = 0x80 - val;
 965                sccb_reg_write(gspca_dev, 0x55, val);   /* bright */
 966        } else {
 967                sccb_reg_write(gspca_dev, 0x9b, val);
 968        }
 969}
 970
 971static void setcontrast(struct gspca_dev *gspca_dev)
 972{
 973        struct sd *sd = (struct sd *) gspca_dev;
 974        u8 val;
 975
 976        val = sd->ctrls[CONTRAST].val;
 977        if (sd->sensor == SENSOR_OV767x)
 978                sccb_reg_write(gspca_dev, 0x56, val);   /* contras */
 979        else
 980                sccb_reg_write(gspca_dev, 0x9c, val);
 981}
 982
 983static void setgain(struct gspca_dev *gspca_dev)
 984{
 985        struct sd *sd = (struct sd *) gspca_dev;
 986        u8 val;
 987
 988        if (sd->ctrls[AGC].val)
 989                return;
 990
 991        val = sd->ctrls[GAIN].val;
 992        switch (val & 0x30) {
 993        case 0x00:
 994                val &= 0x0f;
 995                break;
 996        case 0x10:
 997                val &= 0x0f;
 998                val |= 0x30;
 999                break;
1000        case 0x20:
1001                val &= 0x0f;
1002                val |= 0x70;
1003                break;
1004        default:
1005/*      case 0x30: */
1006                val &= 0x0f;
1007                val |= 0xf0;
1008                break;
1009        }
1010        sccb_reg_write(gspca_dev, 0x00, val);
1011}
1012
1013static void setexposure(struct gspca_dev *gspca_dev)
1014{
1015        struct sd *sd = (struct sd *) gspca_dev;
1016        u8 val;
1017
1018        if (sd->ctrls[AEC].val)
1019                return;
1020
1021        val = sd->ctrls[EXPOSURE].val;
1022        if (sd->sensor == SENSOR_OV767x) {
1023
1024                /* set only aec[9:2] */
1025                sccb_reg_write(gspca_dev, 0x10, val);   /* aech */
1026        } else {
1027
1028                /* 'val' is one byte and represents half of the exposure value
1029                 * we are going to set into registers, a two bytes value:
1030                 *
1031                 *    MSB: ((u16) val << 1) >> 8   == val >> 7
1032                 *    LSB: ((u16) val << 1) & 0xff == val << 1
1033                 */
1034                sccb_reg_write(gspca_dev, 0x08, val >> 7);
1035                sccb_reg_write(gspca_dev, 0x10, val << 1);
1036        }
1037}
1038
1039static void setagc(struct gspca_dev *gspca_dev)
1040{
1041        struct sd *sd = (struct sd *) gspca_dev;
1042
1043        if (sd->ctrls[AGC].val) {
1044                sccb_reg_write(gspca_dev, 0x13,
1045                                sccb_reg_read(gspca_dev, 0x13) | 0x04);
1046                sccb_reg_write(gspca_dev, 0x64,
1047                                sccb_reg_read(gspca_dev, 0x64) | 0x03);
1048        } else {
1049                sccb_reg_write(gspca_dev, 0x13,
1050                                sccb_reg_read(gspca_dev, 0x13) & ~0x04);
1051                sccb_reg_write(gspca_dev, 0x64,
1052                                sccb_reg_read(gspca_dev, 0x64) & ~0x03);
1053
1054                setgain(gspca_dev);
1055        }
1056}
1057
1058static void setawb(struct gspca_dev *gspca_dev)
1059{
1060        struct sd *sd = (struct sd *) gspca_dev;
1061
1062        if (sd->ctrls[AWB].val) {
1063                sccb_reg_write(gspca_dev, 0x13,
1064                                sccb_reg_read(gspca_dev, 0x13) | 0x02);
1065                if (sd->sensor == SENSOR_OV772x)
1066                        sccb_reg_write(gspca_dev, 0x63,
1067                                sccb_reg_read(gspca_dev, 0x63) | 0xc0);
1068        } else {
1069                sccb_reg_write(gspca_dev, 0x13,
1070                                sccb_reg_read(gspca_dev, 0x13) & ~0x02);
1071                if (sd->sensor == SENSOR_OV772x)
1072                        sccb_reg_write(gspca_dev, 0x63,
1073                                sccb_reg_read(gspca_dev, 0x63) & ~0xc0);
1074        }
1075}
1076
1077static void setaec(struct gspca_dev *gspca_dev)
1078{
1079        struct sd *sd = (struct sd *) gspca_dev;
1080        u8 data;
1081
1082        data = sd->sensor == SENSOR_OV767x ?
1083                        0x05 :          /* agc + aec */
1084                        0x01;           /* agc */
1085        if (sd->ctrls[AEC].val)
1086                sccb_reg_write(gspca_dev, 0x13,
1087                                sccb_reg_read(gspca_dev, 0x13) | data);
1088        else {
1089                sccb_reg_write(gspca_dev, 0x13,
1090                                sccb_reg_read(gspca_dev, 0x13) & ~data);
1091                if (sd->sensor == SENSOR_OV767x)
1092                        sd->ctrls[EXPOSURE].val =
1093                                sccb_reg_read(gspca_dev, 10);   /* aech */
1094                else
1095                        setexposure(gspca_dev);
1096        }
1097}
1098
1099static void setsharpness(struct gspca_dev *gspca_dev)
1100{
1101        struct sd *sd = (struct sd *) gspca_dev;
1102        u8 val;
1103
1104        val = sd->ctrls[SHARPNESS].val;
1105        sccb_reg_write(gspca_dev, 0x91, val);   /* Auto de-noise threshold */
1106        sccb_reg_write(gspca_dev, 0x8e, val);   /* De-noise threshold */
1107}
1108
1109static void sethvflip(struct gspca_dev *gspca_dev)
1110{
1111        struct sd *sd = (struct sd *) gspca_dev;
1112        u8 val;
1113
1114        if (sd->sensor == SENSOR_OV767x) {
1115                val = sccb_reg_read(gspca_dev, 0x1e);   /* mvfp */
1116                val &= ~0x30;
1117                if (sd->ctrls[HFLIP].val)
1118                        val |= 0x20;
1119                if (sd->ctrls[VFLIP].val)
1120                        val |= 0x10;
1121                sccb_reg_write(gspca_dev, 0x1e, val);
1122        } else {
1123                val = sccb_reg_read(gspca_dev, 0x0c);
1124                val &= ~0xc0;
1125                if (sd->ctrls[HFLIP].val == 0)
1126                        val |= 0x40;
1127                if (sd->ctrls[VFLIP].val == 0)
1128                        val |= 0x80;
1129                sccb_reg_write(gspca_dev, 0x0c, val);
1130        }
1131}
1132
1133static void setcolors(struct gspca_dev *gspca_dev)
1134{
1135        struct sd *sd = (struct sd *) gspca_dev;
1136        u8 val;
1137        int i;
1138        static u8 color_tb[][6] = {
1139                {0x42, 0x42, 0x00, 0x11, 0x30, 0x41},
1140                {0x52, 0x52, 0x00, 0x16, 0x3c, 0x52},
1141                {0x66, 0x66, 0x00, 0x1b, 0x4b, 0x66},
1142                {0x80, 0x80, 0x00, 0x22, 0x5e, 0x80},
1143                {0x9a, 0x9a, 0x00, 0x29, 0x71, 0x9a},
1144                {0xb8, 0xb8, 0x00, 0x31, 0x87, 0xb8},
1145                {0xdd, 0xdd, 0x00, 0x3b, 0xa2, 0xdd},
1146        };
1147
1148        val = sd->ctrls[COLORS].val;
1149        for (i = 0; i < ARRAY_SIZE(color_tb[0]); i++)
1150                sccb_reg_write(gspca_dev, 0x4f + i, color_tb[val][i]);
1151}
1152
1153static void setlightfreq(struct gspca_dev *gspca_dev)
1154{
1155        struct sd *sd = (struct sd *) gspca_dev;
1156        u8 val;
1157
1158        val = sd->ctrls[LIGHTFREQ].val ? 0x9e : 0x00;
1159        if (sd->sensor == SENSOR_OV767x) {
1160                sccb_reg_write(gspca_dev, 0x2a, 0x00);
1161                if (val)
1162                        val = 0x9d;     /* insert dummy to 25fps for 50Hz */
1163        }
1164        sccb_reg_write(gspca_dev, 0x2b, val);
1165}
1166
1167
1168/* this function is called at probe time */
1169static int sd_config(struct gspca_dev *gspca_dev,
1170                     const struct usb_device_id *id)
1171{
1172        struct sd *sd = (struct sd *) gspca_dev;
1173        struct cam *cam;
1174
1175        cam = &gspca_dev->cam;
1176
1177        cam->ctrls = sd->ctrls;
1178
1179        /* the auto white balance control works only when auto gain is set */
1180        if (sd_ctrls[AGC].qctrl.default_value == 0)
1181                gspca_dev->ctrl_inac |= (1 << AWB);
1182
1183        cam->cam_mode = ov772x_mode;
1184        cam->nmodes = ARRAY_SIZE(ov772x_mode);
1185
1186        sd->frame_rate = 30;
1187
1188        return 0;
1189}
1190
1191/* this function is called at probe and resume time */
1192static int sd_init(struct gspca_dev *gspca_dev)
1193{
1194        struct sd *sd = (struct sd *) gspca_dev;
1195        u16 sensor_id;
1196        static const struct reg_array bridge_init[NSENSORS] = {
1197        [SENSOR_OV767x] = {bridge_init_767x, ARRAY_SIZE(bridge_init_767x)},
1198        [SENSOR_OV772x] = {bridge_init_772x, ARRAY_SIZE(bridge_init_772x)},
1199        };
1200        static const struct reg_array sensor_init[NSENSORS] = {
1201        [SENSOR_OV767x] = {sensor_init_767x, ARRAY_SIZE(sensor_init_767x)},
1202        [SENSOR_OV772x] = {sensor_init_772x, ARRAY_SIZE(sensor_init_772x)},
1203        };
1204
1205        /* reset bridge */
1206        ov534_reg_write(gspca_dev, 0xe7, 0x3a);
1207        ov534_reg_write(gspca_dev, 0xe0, 0x08);
1208        msleep(100);
1209
1210        /* initialize the sensor address */
1211        ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, 0x42);
1212
1213        /* reset sensor */
1214        sccb_reg_write(gspca_dev, 0x12, 0x80);
1215        msleep(10);
1216
1217        /* probe the sensor */
1218        sccb_reg_read(gspca_dev, 0x0a);
1219        sensor_id = sccb_reg_read(gspca_dev, 0x0a) << 8;
1220        sccb_reg_read(gspca_dev, 0x0b);
1221        sensor_id |= sccb_reg_read(gspca_dev, 0x0b);
1222        PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
1223
1224        if ((sensor_id & 0xfff0) == 0x7670) {
1225                sd->sensor = SENSOR_OV767x;
1226                gspca_dev->ctrl_dis = (1 << GAIN) |
1227                                        (1 << AGC) |
1228                                        (1 << SHARPNESS);       /* auto */
1229                sd->ctrls[BRIGHTNESS].min = -127;
1230                sd->ctrls[BRIGHTNESS].max = 127;
1231                sd->ctrls[BRIGHTNESS].def = 0;
1232                sd->ctrls[CONTRAST].max = 0x80;
1233                sd->ctrls[CONTRAST].def = 0x40;
1234                sd->ctrls[EXPOSURE].min = 0x08;
1235                sd->ctrls[EXPOSURE].max = 0x60;
1236                sd->ctrls[EXPOSURE].def = 0x13;
1237                sd->ctrls[SHARPNESS].max = 9;
1238                sd->ctrls[SHARPNESS].def = 4;
1239                sd->ctrls[HFLIP].def = 1;
1240                gspca_dev->cam.cam_mode = ov767x_mode;
1241                gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode);
1242        } else {
1243                sd->sensor = SENSOR_OV772x;
1244                gspca_dev->ctrl_dis = (1 << COLORS);
1245                gspca_dev->cam.bulk = 1;
1246                gspca_dev->cam.bulk_size = 16384;
1247                gspca_dev->cam.bulk_nurbs = 2;
1248                gspca_dev->cam.mode_framerates = ov772x_framerates;
1249        }
1250
1251        /* initialize */
1252        reg_w_array(gspca_dev, bridge_init[sd->sensor].val,
1253                        bridge_init[sd->sensor].len);
1254        ov534_set_led(gspca_dev, 1);
1255        sccb_w_array(gspca_dev, sensor_init[sd->sensor].val,
1256                        sensor_init[sd->sensor].len);
1257        if (sd->sensor == SENSOR_OV767x)
1258                sd_start(gspca_dev);
1259        sd_stopN(gspca_dev);
1260/*      set_frame_rate(gspca_dev);      */
1261
1262        return gspca_dev->usb_err;
1263}
1264
1265static int sd_start(struct gspca_dev *gspca_dev)
1266{
1267        struct sd *sd = (struct sd *) gspca_dev;
1268        int mode;
1269        static const struct reg_array bridge_start[NSENSORS][2] = {
1270        [SENSOR_OV767x] = {{bridge_start_qvga_767x,
1271                                        ARRAY_SIZE(bridge_start_qvga_767x)},
1272                        {bridge_start_vga_767x,
1273                                        ARRAY_SIZE(bridge_start_vga_767x)}},
1274        [SENSOR_OV772x] = {{bridge_start_qvga_772x,
1275                                        ARRAY_SIZE(bridge_start_qvga_772x)},
1276                        {bridge_start_vga_772x,
1277                                        ARRAY_SIZE(bridge_start_vga_772x)}},
1278        };
1279        static const struct reg_array sensor_start[NSENSORS][2] = {
1280        [SENSOR_OV767x] = {{sensor_start_qvga_767x,
1281                                        ARRAY_SIZE(sensor_start_qvga_767x)},
1282                        {sensor_start_vga_767x,
1283                                        ARRAY_SIZE(sensor_start_vga_767x)}},
1284        [SENSOR_OV772x] = {{sensor_start_qvga_772x,
1285                                        ARRAY_SIZE(sensor_start_qvga_772x)},
1286                        {sensor_start_vga_772x,
1287                                        ARRAY_SIZE(sensor_start_vga_772x)}},
1288        };
1289
1290        /* (from ms-win trace) */
1291        if (sd->sensor == SENSOR_OV767x)
1292                sccb_reg_write(gspca_dev, 0x1e, 0x04);
1293                                        /* black sun enable ? */
1294
1295        mode = gspca_dev->curr_mode;    /* 0: 320x240, 1: 640x480 */
1296        reg_w_array(gspca_dev, bridge_start[sd->sensor][mode].val,
1297                                bridge_start[sd->sensor][mode].len);
1298        sccb_w_array(gspca_dev, sensor_start[sd->sensor][mode].val,
1299                                sensor_start[sd->sensor][mode].len);
1300
1301        set_frame_rate(gspca_dev);
1302
1303        if (!(gspca_dev->ctrl_dis & (1 << AGC)))
1304                setagc(gspca_dev);
1305        setawb(gspca_dev);
1306        setaec(gspca_dev);
1307        if (!(gspca_dev->ctrl_dis & (1 << GAIN)))
1308                setgain(gspca_dev);
1309        setexposure(gspca_dev);
1310        setbrightness(gspca_dev);
1311        setcontrast(gspca_dev);
1312        if (!(gspca_dev->ctrl_dis & (1 << SHARPNESS)))
1313                setsharpness(gspca_dev);
1314        sethvflip(gspca_dev);
1315        if (!(gspca_dev->ctrl_dis & (1 << COLORS)))
1316                setcolors(gspca_dev);
1317        setlightfreq(gspca_dev);
1318
1319        ov534_set_led(gspca_dev, 1);
1320        ov534_reg_write(gspca_dev, 0xe0, 0x00);
1321        return gspca_dev->usb_err;
1322}
1323
1324static void sd_stopN(struct gspca_dev *gspca_dev)
1325{
1326        ov534_reg_write(gspca_dev, 0xe0, 0x09);
1327        ov534_set_led(gspca_dev, 0);
1328}
1329
1330/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
1331#define UVC_STREAM_EOH  (1 << 7)
1332#define UVC_STREAM_ERR  (1 << 6)
1333#define UVC_STREAM_STI  (1 << 5)
1334#define UVC_STREAM_RES  (1 << 4)
1335#define UVC_STREAM_SCR  (1 << 3)
1336#define UVC_STREAM_PTS  (1 << 2)
1337#define UVC_STREAM_EOF  (1 << 1)
1338#define UVC_STREAM_FID  (1 << 0)
1339
1340static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1341                        u8 *data, int len)
1342{
1343        struct sd *sd = (struct sd *) gspca_dev;
1344        __u32 this_pts;
1345        u16 this_fid;
1346        int remaining_len = len;
1347        int payload_len;
1348
1349        payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
1350        do {
1351                len = min(remaining_len, payload_len);
1352
1353                /* Payloads are prefixed with a UVC-style header.  We
1354                   consider a frame to start when the FID toggles, or the PTS
1355                   changes.  A frame ends when EOF is set, and we've received
1356                   the correct number of bytes. */
1357
1358                /* Verify UVC header.  Header length is always 12 */
1359                if (data[0] != 12 || len < 12) {
1360                        PDEBUG(D_PACK, "bad header");
1361                        goto discard;
1362                }
1363
1364                /* Check errors */
1365                if (data[1] & UVC_STREAM_ERR) {
1366                        PDEBUG(D_PACK, "payload error");
1367                        goto discard;
1368                }
1369
1370                /* Extract PTS and FID */
1371                if (!(data[1] & UVC_STREAM_PTS)) {
1372                        PDEBUG(D_PACK, "PTS not present");
1373                        goto discard;
1374                }
1375                this_pts = (data[5] << 24) | (data[4] << 16)
1376                                                | (data[3] << 8) | data[2];
1377                this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0;
1378
1379                /* If PTS or FID has changed, start a new frame. */
1380                if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
1381                        if (gspca_dev->last_packet_type == INTER_PACKET)
1382                                gspca_frame_add(gspca_dev, LAST_PACKET,
1383                                                NULL, 0);
1384                        sd->last_pts = this_pts;
1385                        sd->last_fid = this_fid;
1386                        gspca_frame_add(gspca_dev, FIRST_PACKET,
1387                                        data + 12, len - 12);
1388                /* If this packet is marked as EOF, end the frame */
1389                } else if (data[1] & UVC_STREAM_EOF) {
1390                        sd->last_pts = 0;
1391                        if (gspca_dev->pixfmt == V4L2_PIX_FMT_YUYV
1392                         && gspca_dev->image_len + len - 12 !=
1393                                   gspca_dev->width * gspca_dev->height * 2) {
1394                                PDEBUG(D_PACK, "wrong sized frame");
1395                                goto discard;
1396                        }
1397                        gspca_frame_add(gspca_dev, LAST_PACKET,
1398                                        data + 12, len - 12);
1399                } else {
1400
1401                        /* Add the data from this payload */
1402                        gspca_frame_add(gspca_dev, INTER_PACKET,
1403                                        data + 12, len - 12);
1404                }
1405
1406                /* Done this payload */
1407                goto scan_next;
1408
1409discard:
1410                /* Discard data until a new frame starts. */
1411                gspca_dev->last_packet_type = DISCARD_PACKET;
1412
1413scan_next:
1414                remaining_len -= len;
1415                data += len;
1416        } while (remaining_len > 0);
1417}
1418
1419static int sd_setagc(struct gspca_dev *gspca_dev, __s32 val)
1420{
1421        struct sd *sd = (struct sd *) gspca_dev;
1422
1423        sd->ctrls[AGC].val = val;
1424
1425        /* the auto white balance control works only
1426         * when auto gain is set */
1427        if (val) {
1428                gspca_dev->ctrl_inac &= ~(1 << AWB);
1429        } else {
1430                gspca_dev->ctrl_inac |= (1 << AWB);
1431                if (sd->ctrls[AWB].val) {
1432                        sd->ctrls[AWB].val = 0;
1433                        if (gspca_dev->streaming)
1434                                setawb(gspca_dev);
1435                }
1436        }
1437        if (gspca_dev->streaming)
1438                setagc(gspca_dev);
1439        return gspca_dev->usb_err;
1440}
1441
1442static int sd_querymenu(struct gspca_dev *gspca_dev,
1443                struct v4l2_querymenu *menu)
1444{
1445        switch (menu->id) {
1446        case V4L2_CID_POWER_LINE_FREQUENCY:
1447                switch (menu->index) {
1448                case 0:         /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1449                        strcpy((char *) menu->name, "Disabled");
1450                        return 0;
1451                case 1:         /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1452                        strcpy((char *) menu->name, "50 Hz");
1453                        return 0;
1454                }
1455                break;
1456        }
1457
1458        return -EINVAL;
1459}
1460
1461/* get stream parameters (framerate) */
1462static void sd_get_streamparm(struct gspca_dev *gspca_dev,
1463                             struct v4l2_streamparm *parm)
1464{
1465        struct v4l2_captureparm *cp = &parm->parm.capture;
1466        struct v4l2_fract *tpf = &cp->timeperframe;
1467        struct sd *sd = (struct sd *) gspca_dev;
1468
1469        cp->capability |= V4L2_CAP_TIMEPERFRAME;
1470        tpf->numerator = 1;
1471        tpf->denominator = sd->frame_rate;
1472}
1473
1474/* set stream parameters (framerate) */
1475static void sd_set_streamparm(struct gspca_dev *gspca_dev,
1476                             struct v4l2_streamparm *parm)
1477{
1478        struct v4l2_captureparm *cp = &parm->parm.capture;
1479        struct v4l2_fract *tpf = &cp->timeperframe;
1480        struct sd *sd = (struct sd *) gspca_dev;
1481
1482        /* Set requested framerate */
1483        sd->frame_rate = tpf->denominator / tpf->numerator;
1484        if (gspca_dev->streaming)
1485                set_frame_rate(gspca_dev);
1486
1487        /* Return the actual framerate */
1488        tpf->numerator = 1;
1489        tpf->denominator = sd->frame_rate;
1490}
1491
1492/* sub-driver description */
1493static const struct sd_desc sd_desc = {
1494        .name     = MODULE_NAME,
1495        .ctrls    = sd_ctrls,
1496        .nctrls   = ARRAY_SIZE(sd_ctrls),
1497        .config   = sd_config,
1498        .init     = sd_init,
1499        .start    = sd_start,
1500        .stopN    = sd_stopN,
1501        .pkt_scan = sd_pkt_scan,
1502        .querymenu = sd_querymenu,
1503        .get_streamparm = sd_get_streamparm,
1504        .set_streamparm = sd_set_streamparm,
1505};
1506
1507/* -- module initialisation -- */
1508static const struct usb_device_id device_table[] = {
1509        {USB_DEVICE(0x1415, 0x2000)},
1510        {USB_DEVICE(0x06f8, 0x3002)},
1511        {}
1512};
1513
1514MODULE_DEVICE_TABLE(usb, device_table);
1515
1516/* -- device connect -- */
1517static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
1518{
1519        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1520                                THIS_MODULE);
1521}
1522
1523static struct usb_driver sd_driver = {
1524        .name       = MODULE_NAME,
1525        .id_table   = device_table,
1526        .probe      = sd_probe,
1527        .disconnect = gspca_disconnect,
1528#ifdef CONFIG_PM
1529        .suspend    = gspca_suspend,
1530        .resume     = gspca_resume,
1531#endif
1532};
1533
1534/* -- module insert / remove -- */
1535static int __init sd_mod_init(void)
1536{
1537        return usb_register(&sd_driver);
1538}
1539
1540static void __exit sd_mod_exit(void)
1541{
1542        usb_deregister(&sd_driver);
1543}
1544
1545module_init(sd_mod_init);
1546module_exit(sd_mod_exit);
1547