linux/drivers/media/video/gspca/t613.c
<<
>>
Prefs
   1/*
   2 * T613 subdriver
   3 *
   4 * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 *
  20 *Notes: * t613  + tas5130A
  21 *      * Focus to light do not balance well as in win.
  22 *        Quality in win is not good, but its kinda better.
  23 *       * Fix some "extraneous bytes", most of apps will show the image anyway
  24 *       * Gamma table, is there, but its really doing something?
  25 *       * 7~8 Fps, its ok, max on win its 10.
  26 *                      Costantino Leandro
  27 */
  28
  29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  30
  31#define MODULE_NAME "t613"
  32
  33#include <linux/slab.h>
  34#include "gspca.h"
  35
  36#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
  37
  38MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
  39MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
  40MODULE_LICENSE("GPL");
  41
  42struct sd {
  43        struct gspca_dev gspca_dev;     /* !! must be the first item */
  44
  45        u8 brightness;
  46        u8 contrast;
  47        u8 colors;
  48        u8 autogain;
  49        u8 gamma;
  50        u8 sharpness;
  51        u8 freq;
  52        u8 red_gain;
  53        u8 blue_gain;
  54        u8 green_gain;
  55        u8 awb; /* set default r/g/b and activate */
  56        u8 mirror;
  57        u8 effect;
  58
  59        u8 sensor;
  60};
  61enum sensors {
  62        SENSOR_OM6802,
  63        SENSOR_OTHER,
  64        SENSOR_TAS5130A,
  65        SENSOR_LT168G,          /* must verify if this is the actual model */
  66};
  67
  68/* V4L2 controls supported by the driver */
  69static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
  70static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
  71static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
  72static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
  73static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
  74static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
  75static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
  76static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
  77static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
  78static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
  79static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
  80static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
  81static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
  82static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
  83
  84static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val);
  85static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val);
  86static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val);
  87static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val);
  88static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val);
  89static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val);
  90static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
  91static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
  92
  93static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val);
  94static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val);
  95static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
  96static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
  97
  98static const struct ctrl sd_ctrls[] = {
  99        {
 100         {
 101          .id = V4L2_CID_BRIGHTNESS,
 102          .type = V4L2_CTRL_TYPE_INTEGER,
 103          .name = "Brightness",
 104          .minimum = 0,
 105          .maximum = 14,
 106          .step = 1,
 107#define BRIGHTNESS_DEF 8
 108          .default_value = BRIGHTNESS_DEF,
 109          },
 110         .set = sd_setbrightness,
 111         .get = sd_getbrightness,
 112         },
 113        {
 114         {
 115          .id = V4L2_CID_CONTRAST,
 116          .type = V4L2_CTRL_TYPE_INTEGER,
 117          .name = "Contrast",
 118          .minimum = 0,
 119          .maximum = 0x0d,
 120          .step = 1,
 121#define CONTRAST_DEF 0x07
 122          .default_value = CONTRAST_DEF,
 123          },
 124         .set = sd_setcontrast,
 125         .get = sd_getcontrast,
 126         },
 127        {
 128         {
 129          .id = V4L2_CID_SATURATION,
 130          .type = V4L2_CTRL_TYPE_INTEGER,
 131          .name = "Color",
 132          .minimum = 0,
 133          .maximum = 0x0f,
 134          .step = 1,
 135#define COLORS_DEF 0x05
 136          .default_value = COLORS_DEF,
 137          },
 138         .set = sd_setcolors,
 139         .get = sd_getcolors,
 140         },
 141#define GAMMA_MAX 16
 142#define GAMMA_DEF 10
 143        {
 144         {
 145          .id = V4L2_CID_GAMMA, /* (gamma on win) */
 146          .type = V4L2_CTRL_TYPE_INTEGER,
 147          .name = "Gamma",
 148          .minimum = 0,
 149          .maximum = GAMMA_MAX - 1,
 150          .step = 1,
 151          .default_value = GAMMA_DEF,
 152          },
 153         .set = sd_setgamma,
 154         .get = sd_getgamma,
 155         },
 156        {
 157         {
 158          .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight,
 159                                 * some apps dont bring up the
 160                                 * backligth_compensation control) */
 161          .type = V4L2_CTRL_TYPE_INTEGER,
 162          .name = "Low Light",
 163          .minimum = 0,
 164          .maximum = 1,
 165          .step = 1,
 166#define AUTOGAIN_DEF 0x01
 167          .default_value = AUTOGAIN_DEF,
 168          },
 169         .set = sd_setlowlight,
 170         .get = sd_getlowlight,
 171         },
 172        {
 173         {
 174          .id = V4L2_CID_HFLIP,
 175          .type = V4L2_CTRL_TYPE_BOOLEAN,
 176          .name = "Mirror Image",
 177          .minimum = 0,
 178          .maximum = 1,
 179          .step = 1,
 180#define MIRROR_DEF 0
 181          .default_value = MIRROR_DEF,
 182          },
 183         .set = sd_setmirror,
 184         .get = sd_getmirror
 185        },
 186        {
 187         {
 188          .id = V4L2_CID_POWER_LINE_FREQUENCY,
 189          .type = V4L2_CTRL_TYPE_MENU,
 190          .name = "Light Frequency Filter",
 191          .minimum = 1,         /* 1 -> 0x50, 2->0x60 */
 192          .maximum = 2,
 193          .step = 1,
 194#define FREQ_DEF 1
 195          .default_value = FREQ_DEF,
 196          },
 197         .set = sd_setfreq,
 198         .get = sd_getfreq},
 199
 200        {
 201         {
 202          .id =  V4L2_CID_AUTO_WHITE_BALANCE,
 203          .type = V4L2_CTRL_TYPE_INTEGER,
 204          .name = "Auto White Balance",
 205          .minimum = 0,
 206          .maximum = 1,
 207          .step = 1,
 208#define AWB_DEF 0
 209          .default_value = AWB_DEF,
 210          },
 211         .set = sd_setawb,
 212         .get = sd_getawb
 213        },
 214        {
 215         {
 216          .id = V4L2_CID_SHARPNESS,
 217          .type = V4L2_CTRL_TYPE_INTEGER,
 218          .name = "Sharpness",
 219          .minimum = 0,
 220          .maximum = 15,
 221          .step = 1,
 222#define SHARPNESS_DEF 0x06
 223          .default_value = SHARPNESS_DEF,
 224          },
 225         .set = sd_setsharpness,
 226         .get = sd_getsharpness,
 227         },
 228        {
 229         {
 230          .id = V4L2_CID_EFFECTS,
 231          .type = V4L2_CTRL_TYPE_MENU,
 232          .name = "Webcam Effects",
 233          .minimum = 0,
 234          .maximum = 4,
 235          .step = 1,
 236#define EFFECTS_DEF 0
 237          .default_value = EFFECTS_DEF,
 238          },
 239         .set = sd_seteffect,
 240         .get = sd_geteffect
 241        },
 242        {
 243         {
 244            .id      = V4L2_CID_BLUE_BALANCE,
 245            .type    = V4L2_CTRL_TYPE_INTEGER,
 246            .name    = "Blue Balance",
 247            .minimum = 0x10,
 248            .maximum = 0x40,
 249            .step    = 1,
 250#define BLUE_GAIN_DEF 0x20
 251            .default_value = BLUE_GAIN_DEF,
 252         },
 253        .set = sd_setblue_gain,
 254        .get = sd_getblue_gain,
 255        },
 256        {
 257         {
 258            .id      = V4L2_CID_RED_BALANCE,
 259            .type    = V4L2_CTRL_TYPE_INTEGER,
 260            .name    = "Red Balance",
 261            .minimum = 0x10,
 262            .maximum = 0x40,
 263            .step    = 1,
 264#define RED_GAIN_DEF 0x20
 265            .default_value = RED_GAIN_DEF,
 266         },
 267        .set = sd_setred_gain,
 268        .get = sd_getred_gain,
 269        },
 270        {
 271         {
 272            .id      = V4L2_CID_GAIN,
 273            .type    = V4L2_CTRL_TYPE_INTEGER,
 274            .name    = "Gain",
 275            .minimum = 0x10,
 276            .maximum = 0x40,
 277            .step    = 1,
 278#define GAIN_DEF  0x20
 279            .default_value = GAIN_DEF,
 280         },
 281        .set = sd_setgain,
 282        .get = sd_getgain,
 283        },
 284};
 285
 286static const struct v4l2_pix_format vga_mode_t16[] = {
 287        {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 288                .bytesperline = 160,
 289                .sizeimage = 160 * 120 * 4 / 8 + 590,
 290                .colorspace = V4L2_COLORSPACE_JPEG,
 291                .priv = 4},
 292        {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 293                .bytesperline = 176,
 294                .sizeimage = 176 * 144 * 3 / 8 + 590,
 295                .colorspace = V4L2_COLORSPACE_JPEG,
 296                .priv = 3},
 297        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 298                .bytesperline = 320,
 299                .sizeimage = 320 * 240 * 3 / 8 + 590,
 300                .colorspace = V4L2_COLORSPACE_JPEG,
 301                .priv = 2},
 302        {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 303                .bytesperline = 352,
 304                .sizeimage = 352 * 288 * 3 / 8 + 590,
 305                .colorspace = V4L2_COLORSPACE_JPEG,
 306                .priv = 1},
 307        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 308                .bytesperline = 640,
 309                .sizeimage = 640 * 480 * 3 / 8 + 590,
 310                .colorspace = V4L2_COLORSPACE_JPEG,
 311                .priv = 0},
 312};
 313
 314/* sensor specific data */
 315struct additional_sensor_data {
 316        const u8 n3[6];
 317        const u8 *n4, n4sz;
 318        const u8 reg80, reg8e;
 319        const u8 nset8[6];
 320        const u8 data1[10];
 321        const u8 data2[9];
 322        const u8 data3[9];
 323        const u8 data5[6];
 324        const u8 stream[4];
 325};
 326
 327static const u8 n4_om6802[] = {
 328        0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
 329        0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
 330        0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
 331        0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
 332        0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
 333        0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
 334        0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
 335        0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
 336        0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
 337};
 338static const u8 n4_other[] = {
 339        0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
 340        0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
 341        0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
 342        0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
 343        0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
 344        0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
 345        0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
 346        0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
 347};
 348static const u8 n4_tas5130a[] = {
 349        0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
 350        0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
 351        0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
 352        0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
 353        0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
 354        0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
 355        0xc6, 0xda
 356};
 357static const u8 n4_lt168g[] = {
 358        0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
 359        0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
 360        0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
 361        0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
 362        0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
 363        0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
 364        0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
 365        0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
 366        0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
 367};
 368
 369static const struct additional_sensor_data sensor_data[] = {
 370[SENSOR_OM6802] = {
 371        .n3 =
 372                {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
 373        .n4 = n4_om6802,
 374        .n4sz = sizeof n4_om6802,
 375        .reg80 = 0x3c,
 376        .reg8e = 0x33,
 377        .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
 378        .data1 =
 379                {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
 380                 0xb3, 0xfc},
 381        .data2 =
 382                {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
 383                 0xff},
 384        .data3 =
 385                {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
 386                 0xff},
 387        .data5 =        /* this could be removed later */
 388                {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
 389        .stream =
 390                {0x0b, 0x04, 0x0a, 0x78},
 391    },
 392[SENSOR_OTHER] = {
 393        .n3 =
 394                {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
 395        .n4 = n4_other,
 396        .n4sz = sizeof n4_other,
 397        .reg80 = 0xac,
 398        .reg8e = 0xb8,
 399        .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
 400        .data1 =
 401                {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
 402                 0xe8, 0xfc},
 403        .data2 =
 404                {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
 405                 0xd9},
 406        .data3 =
 407                {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
 408                 0xd9},
 409        .data5 =
 410                {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
 411        .stream =
 412                {0x0b, 0x04, 0x0a, 0x00},
 413    },
 414[SENSOR_TAS5130A] = {
 415        .n3 =
 416                {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
 417        .n4 = n4_tas5130a,
 418        .n4sz = sizeof n4_tas5130a,
 419        .reg80 = 0x3c,
 420        .reg8e = 0xb4,
 421        .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
 422        .data1 =
 423                {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
 424                 0xc8, 0xfc},
 425        .data2 =
 426                {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
 427                 0xe0},
 428        .data3 =
 429                {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
 430                 0xe0},
 431        .data5 =
 432                {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
 433        .stream =
 434                {0x0b, 0x04, 0x0a, 0x40},
 435    },
 436[SENSOR_LT168G] = {
 437        .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
 438        .n4 = n4_lt168g,
 439        .n4sz = sizeof n4_lt168g,
 440        .reg80 = 0x7c,
 441        .reg8e = 0xb3,
 442        .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
 443        .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
 444                 0xb0, 0xf4},
 445        .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
 446                 0xff},
 447        .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
 448                 0xff},
 449        .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
 450        .stream = {0x0b, 0x04, 0x0a, 0x28},
 451    },
 452};
 453
 454#define MAX_EFFECTS 7
 455/* easily done by soft, this table could be removed,
 456 * i keep it here just in case */
 457static char *effects_control[MAX_EFFECTS] = {
 458        "Normal",
 459        "Emboss",               /* disabled */
 460        "Monochrome",
 461        "Sepia",
 462        "Sketch",
 463        "Sun Effect",           /* disabled */
 464        "Negative",
 465};
 466static const u8 effects_table[MAX_EFFECTS][6] = {
 467        {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00},   /* Normal */
 468        {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04},   /* Repujar */
 469        {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20},   /* Monochrome */
 470        {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80},   /* Sepia */
 471        {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02},   /* Croquis */
 472        {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10},   /* Sun Effect */
 473        {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40},   /* Negative */
 474};
 475
 476static const u8 gamma_table[GAMMA_MAX][17] = {
 477/* gamma table from cam1690.ini */
 478        {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21,        /* 0 */
 479         0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
 480         0xff},
 481        {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d,        /* 1 */
 482         0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
 483         0xff},
 484        {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35,        /* 2 */
 485         0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
 486         0xff},
 487        {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f,        /* 3 */
 488         0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
 489         0xff},
 490        {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a,        /* 4 */
 491         0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
 492         0xff},
 493        {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58,        /* 5 */
 494         0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
 495         0xff},
 496        {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67,        /* 6 */
 497         0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
 498         0xff},
 499        {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,        /* 7 */
 500         0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
 501         0xff},
 502        {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79,        /* 8 */
 503         0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
 504         0xff},
 505        {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84,        /* 9 */
 506         0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
 507         0xff},
 508        {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e,        /* 10 */
 509         0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
 510         0xff},
 511        {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b,        /* 11 */
 512         0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
 513         0xff},
 514        {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8,        /* 12 */
 515         0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
 516         0xff},
 517        {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7,        /* 13 */
 518         0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
 519         0xff},
 520        {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6,        /* 14 */
 521         0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
 522         0xff},
 523        {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8,        /* 15 */
 524         0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
 525         0xff}
 526};
 527
 528static const u8 tas5130a_sensor_init[][8] = {
 529        {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
 530        {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
 531        {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
 532};
 533
 534static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
 535
 536/* read 1 byte */
 537static u8 reg_r(struct gspca_dev *gspca_dev,
 538                   u16 index)
 539{
 540        usb_control_msg(gspca_dev->dev,
 541                        usb_rcvctrlpipe(gspca_dev->dev, 0),
 542                        0,              /* request */
 543                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 544                        0,              /* value */
 545                        index,
 546                        gspca_dev->usb_buf, 1, 500);
 547        return gspca_dev->usb_buf[0];
 548}
 549
 550static void reg_w(struct gspca_dev *gspca_dev,
 551                  u16 index)
 552{
 553        usb_control_msg(gspca_dev->dev,
 554                        usb_sndctrlpipe(gspca_dev->dev, 0),
 555                        0,
 556                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 557                        0, index,
 558                        NULL, 0, 500);
 559}
 560
 561static void reg_w_buf(struct gspca_dev *gspca_dev,
 562                  const u8 *buffer, u16 len)
 563{
 564        if (len <= USB_BUF_SZ) {
 565                memcpy(gspca_dev->usb_buf, buffer, len);
 566                usb_control_msg(gspca_dev->dev,
 567                                usb_sndctrlpipe(gspca_dev->dev, 0),
 568                                0,
 569                           USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 570                                0x01, 0,
 571                                gspca_dev->usb_buf, len, 500);
 572        } else {
 573                u8 *tmpbuf;
 574
 575                tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
 576                if (!tmpbuf) {
 577                        pr_err("Out of memory\n");
 578                        return;
 579                }
 580                usb_control_msg(gspca_dev->dev,
 581                                usb_sndctrlpipe(gspca_dev->dev, 0),
 582                                0,
 583                           USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 584                                0x01, 0,
 585                                tmpbuf, len, 500);
 586                kfree(tmpbuf);
 587        }
 588}
 589
 590/* write values to consecutive registers */
 591static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
 592                        u8 reg,
 593                        const u8 *buffer, u16 len)
 594{
 595        int i;
 596        u8 *p, *tmpbuf;
 597
 598        if (len * 2 <= USB_BUF_SZ) {
 599                p = tmpbuf = gspca_dev->usb_buf;
 600        } else {
 601                p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
 602                if (!tmpbuf) {
 603                        pr_err("Out of memory\n");
 604                        return;
 605                }
 606        }
 607        i = len;
 608        while (--i >= 0) {
 609                *p++ = reg++;
 610                *p++ = *buffer++;
 611        }
 612        usb_control_msg(gspca_dev->dev,
 613                        usb_sndctrlpipe(gspca_dev->dev, 0),
 614                        0,
 615                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 616                        0x01, 0,
 617                        tmpbuf, len * 2, 500);
 618        if (len * 2 > USB_BUF_SZ)
 619                kfree(tmpbuf);
 620}
 621
 622static void om6802_sensor_init(struct gspca_dev *gspca_dev)
 623{
 624        int i;
 625        const u8 *p;
 626        u8 byte;
 627        u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
 628        static const u8 sensor_init[] = {
 629                0xdf, 0x6d,
 630                0xdd, 0x18,
 631                0x5a, 0xe0,
 632                0x5c, 0x07,
 633                0x5d, 0xb0,
 634                0x5e, 0x1e,
 635                0x60, 0x71,
 636                0xef, 0x00,
 637                0xe9, 0x00,
 638                0xea, 0x00,
 639                0x90, 0x24,
 640                0x91, 0xb2,
 641                0x82, 0x32,
 642                0xfd, 0x41,
 643                0x00                    /* table end */
 644        };
 645
 646        reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
 647        msleep(100);
 648        i = 4;
 649        while (--i > 0) {
 650                byte = reg_r(gspca_dev, 0x0060);
 651                if (!(byte & 0x01))
 652                        break;
 653                msleep(100);
 654        }
 655        byte = reg_r(gspca_dev, 0x0063);
 656        if (byte != 0x17) {
 657                pr_err("Bad sensor reset %02x\n", byte);
 658                /* continue? */
 659        }
 660
 661        p = sensor_init;
 662        while (*p != 0) {
 663                val[1] = *p++;
 664                val[3] = *p++;
 665                if (*p == 0)
 666                        reg_w(gspca_dev, 0x3c80);
 667                reg_w_buf(gspca_dev, val, sizeof val);
 668                i = 4;
 669                while (--i >= 0) {
 670                        msleep(15);
 671                        byte = reg_r(gspca_dev, 0x60);
 672                        if (!(byte & 0x01))
 673                                break;
 674                }
 675        }
 676        msleep(15);
 677        reg_w(gspca_dev, 0x3c80);
 678}
 679
 680/* this function is called at probe time */
 681static int sd_config(struct gspca_dev *gspca_dev,
 682                     const struct usb_device_id *id)
 683{
 684        struct sd *sd = (struct sd *) gspca_dev;
 685        struct cam *cam;
 686
 687        cam = &gspca_dev->cam;
 688
 689        cam->cam_mode = vga_mode_t16;
 690        cam->nmodes = ARRAY_SIZE(vga_mode_t16);
 691
 692        sd->brightness = BRIGHTNESS_DEF;
 693        sd->contrast = CONTRAST_DEF;
 694        sd->colors = COLORS_DEF;
 695        sd->gamma = GAMMA_DEF;
 696        sd->autogain = AUTOGAIN_DEF;
 697        sd->mirror = MIRROR_DEF;
 698        sd->freq = FREQ_DEF;
 699        sd->awb = AWB_DEF;
 700        sd->sharpness = SHARPNESS_DEF;
 701        sd->effect = EFFECTS_DEF;
 702        sd->red_gain = RED_GAIN_DEF;
 703        sd->blue_gain = BLUE_GAIN_DEF;
 704        sd->green_gain = GAIN_DEF * 3 - RED_GAIN_DEF - BLUE_GAIN_DEF;
 705
 706        return 0;
 707}
 708
 709static void setbrightness(struct gspca_dev *gspca_dev)
 710{
 711        struct sd *sd = (struct sd *) gspca_dev;
 712        unsigned int brightness;
 713        u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
 714
 715        brightness = sd->brightness;
 716        if (brightness < 7) {
 717                set6[1] = 0x26;
 718                set6[3] = 0x70 - brightness * 0x10;
 719        } else {
 720                set6[3] = 0x00 + ((brightness - 7) * 0x10);
 721        }
 722
 723        reg_w_buf(gspca_dev, set6, sizeof set6);
 724}
 725
 726static void setcontrast(struct gspca_dev *gspca_dev)
 727{
 728        struct sd *sd = (struct sd *) gspca_dev;
 729        unsigned int contrast = sd->contrast;
 730        u16 reg_to_write;
 731
 732        if (contrast < 7)
 733                reg_to_write = 0x8ea9 - contrast * 0x200;
 734        else
 735                reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
 736
 737        reg_w(gspca_dev, reg_to_write);
 738}
 739
 740static void setcolors(struct gspca_dev *gspca_dev)
 741{
 742        struct sd *sd = (struct sd *) gspca_dev;
 743        u16 reg_to_write;
 744
 745        reg_to_write = 0x80bb + sd->colors * 0x100;     /* was 0xc0 */
 746        reg_w(gspca_dev, reg_to_write);
 747}
 748
 749static void setgamma(struct gspca_dev *gspca_dev)
 750{
 751        struct sd *sd = (struct sd *) gspca_dev;
 752
 753        PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
 754        reg_w_ixbuf(gspca_dev, 0x90,
 755                gamma_table[sd->gamma], sizeof gamma_table[0]);
 756}
 757
 758static void setRGB(struct gspca_dev *gspca_dev)
 759{
 760        struct sd *sd = (struct sd *) gspca_dev;
 761        u8 all_gain_reg[6] =
 762                {0x87, 0x00, 0x88, 0x00, 0x89, 0x00};
 763
 764        all_gain_reg[1] = sd->red_gain;
 765        all_gain_reg[3] = sd->blue_gain;
 766        all_gain_reg[5] = sd->green_gain;
 767        reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
 768}
 769
 770/* Generic fnc for r/b balance, exposure and awb */
 771static void setawb(struct gspca_dev *gspca_dev)
 772{
 773        struct sd *sd = (struct sd *) gspca_dev;
 774        u16 reg80;
 775
 776        reg80 = (sensor_data[sd->sensor].reg80 << 8) | 0x80;
 777
 778        /* on awb leave defaults values */
 779        if (!sd->awb) {
 780                /* shoud we wait here.. */
 781                /* update and reset RGB gains with webcam values */
 782                sd->red_gain = reg_r(gspca_dev, 0x0087);
 783                sd->blue_gain = reg_r(gspca_dev, 0x0088);
 784                sd->green_gain = reg_r(gspca_dev, 0x0089);
 785                reg80 &= ~0x0400;               /* AWB off */
 786        }
 787        reg_w(gspca_dev, reg80);
 788        reg_w(gspca_dev, reg80);
 789}
 790
 791static void init_gains(struct gspca_dev *gspca_dev)
 792{
 793        struct sd *sd = (struct sd *) gspca_dev;
 794        u16 reg80;
 795        u8 all_gain_reg[8] =
 796                {0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00};
 797
 798        all_gain_reg[1] = sd->red_gain;
 799        all_gain_reg[3] = sd->blue_gain;
 800        all_gain_reg[5] = sd->green_gain;
 801        reg80 = sensor_data[sd->sensor].reg80;
 802        if (!sd->awb)
 803                reg80 &= ~0x04;
 804        all_gain_reg[7] = reg80;
 805        reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
 806
 807        reg_w(gspca_dev, (sd->red_gain  << 8) + 0x87);
 808        reg_w(gspca_dev, (sd->blue_gain << 8) + 0x88);
 809        reg_w(gspca_dev, (sd->green_gain  << 8) + 0x89);
 810}
 811
 812static void setsharpness(struct gspca_dev *gspca_dev)
 813{
 814        struct sd *sd = (struct sd *) gspca_dev;
 815        u16 reg_to_write;
 816
 817        reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
 818
 819        reg_w(gspca_dev, reg_to_write);
 820}
 821
 822static void setfreq(struct gspca_dev *gspca_dev)
 823{
 824        struct sd *sd = (struct sd *) gspca_dev;
 825        u8 reg66;
 826        u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
 827
 828        switch (sd->sensor) {
 829        case SENSOR_LT168G:
 830                if (sd->freq != 0)
 831                        freq[3] = 0xa8;
 832                reg66 = 0x41;
 833                break;
 834        case SENSOR_OM6802:
 835                reg66 = 0xca;
 836                break;
 837        default:
 838                reg66 = 0x40;
 839                break;
 840        }
 841        switch (sd->freq) {
 842        case 0:                         /* no flicker */
 843                freq[3] = 0xf0;
 844                break;
 845        case 2:                         /* 60Hz */
 846                reg66 &= ~0x40;
 847                break;
 848        }
 849        freq[1] = reg66;
 850
 851        reg_w_buf(gspca_dev, freq, sizeof freq);
 852}
 853
 854/* this function is called at probe and resume time */
 855static int sd_init(struct gspca_dev *gspca_dev)
 856{
 857        /* some of this registers are not really neded, because
 858         * they are overriden by setbrigthness, setcontrast, etc,
 859         * but wont hurt anyway, and can help someone with similar webcam
 860         * to see the initial parameters.*/
 861        struct sd *sd = (struct sd *) gspca_dev;
 862        const struct additional_sensor_data *sensor;
 863        int i;
 864        u16 sensor_id;
 865        u8 test_byte = 0;
 866
 867        static const u8 read_indexs[] =
 868                { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
 869                  0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
 870        static const u8 n1[] =
 871                        {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
 872        static const u8 n2[] =
 873                        {0x08, 0x00};
 874
 875        sensor_id = (reg_r(gspca_dev, 0x06) << 8)
 876                        | reg_r(gspca_dev, 0x07);
 877        switch (sensor_id & 0xff0f) {
 878        case 0x0801:
 879                PDEBUG(D_PROBE, "sensor tas5130a");
 880                sd->sensor = SENSOR_TAS5130A;
 881                break;
 882        case 0x0802:
 883                PDEBUG(D_PROBE, "sensor lt168g");
 884                sd->sensor = SENSOR_LT168G;
 885                break;
 886        case 0x0803:
 887                PDEBUG(D_PROBE, "sensor 'other'");
 888                sd->sensor = SENSOR_OTHER;
 889                break;
 890        case 0x0807:
 891                PDEBUG(D_PROBE, "sensor om6802");
 892                sd->sensor = SENSOR_OM6802;
 893                break;
 894        default:
 895                pr_err("unknown sensor %04x\n", sensor_id);
 896                return -EINVAL;
 897        }
 898
 899        if (sd->sensor == SENSOR_OM6802) {
 900                reg_w_buf(gspca_dev, n1, sizeof n1);
 901                i = 5;
 902                while (--i >= 0) {
 903                        reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
 904                        test_byte = reg_r(gspca_dev, 0x0063);
 905                        msleep(100);
 906                        if (test_byte == 0x17)
 907                                break;          /* OK */
 908                }
 909                if (i < 0) {
 910                        pr_err("Bad sensor reset %02x\n", test_byte);
 911                        return -EIO;
 912                }
 913                reg_w_buf(gspca_dev, n2, sizeof n2);
 914        }
 915
 916        i = 0;
 917        while (read_indexs[i] != 0x00) {
 918                test_byte = reg_r(gspca_dev, read_indexs[i]);
 919                PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
 920                       test_byte);
 921                i++;
 922        }
 923
 924        sensor = &sensor_data[sd->sensor];
 925        reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
 926        reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
 927
 928        if (sd->sensor == SENSOR_LT168G) {
 929                test_byte = reg_r(gspca_dev, 0x80);
 930                PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
 931                       test_byte);
 932                reg_w(gspca_dev, 0x6c80);
 933        }
 934
 935        reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
 936        reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
 937        reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
 938
 939        reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
 940        reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
 941        reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
 942
 943        setbrightness(gspca_dev);
 944        setcontrast(gspca_dev);
 945        setgamma(gspca_dev);
 946        setcolors(gspca_dev);
 947        setsharpness(gspca_dev);
 948        init_gains(gspca_dev);
 949        setfreq(gspca_dev);
 950
 951        reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
 952        reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
 953        reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
 954
 955        if (sd->sensor == SENSOR_LT168G) {
 956                test_byte = reg_r(gspca_dev, 0x80);
 957                PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
 958                       test_byte);
 959                reg_w(gspca_dev, 0x6c80);
 960        }
 961
 962        reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
 963        reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
 964        reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
 965
 966        return 0;
 967}
 968
 969static void setmirror(struct gspca_dev *gspca_dev)
 970{
 971        struct sd *sd = (struct sd *) gspca_dev;
 972        u8 hflipcmd[8] =
 973                {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
 974
 975        if (sd->mirror)
 976                hflipcmd[3] = 0x01;
 977
 978        reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
 979}
 980
 981static void seteffect(struct gspca_dev *gspca_dev)
 982{
 983        struct sd *sd = (struct sd *) gspca_dev;
 984
 985        reg_w_buf(gspca_dev, effects_table[sd->effect],
 986                                sizeof effects_table[0]);
 987        if (sd->effect == 1 || sd->effect == 5) {
 988                PDEBUG(D_CONF,
 989                       "This effect have been disabled for webcam \"safety\"");
 990                return;
 991        }
 992
 993        if (sd->effect == 1 || sd->effect == 4)
 994                reg_w(gspca_dev, 0x4aa6);
 995        else
 996                reg_w(gspca_dev, 0xfaa6);
 997}
 998
 999/* Is this really needed?
1000 * i added some module parameters for test with some users */
1001static void poll_sensor(struct gspca_dev *gspca_dev)
1002{
1003        static const u8 poll1[] =
1004                {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
1005                 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
1006                 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
1007                 0x60, 0x14};
1008        static const u8 poll2[] =
1009                {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
1010                 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
1011        static const u8 noise03[] =     /* (some differences / ms-drv) */
1012                {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
1013                 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
1014                 0xc2, 0x80, 0xc3, 0x10};
1015
1016        PDEBUG(D_STREAM, "[Sensor requires polling]");
1017        reg_w_buf(gspca_dev, poll1, sizeof poll1);
1018        reg_w_buf(gspca_dev, poll2, sizeof poll2);
1019        reg_w_buf(gspca_dev, noise03, sizeof noise03);
1020}
1021
1022static int sd_start(struct gspca_dev *gspca_dev)
1023{
1024        struct sd *sd = (struct sd *) gspca_dev;
1025        const struct additional_sensor_data *sensor;
1026        int i, mode;
1027        u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1028        static const u8 t3[] =
1029                { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
1030
1031        mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1032        switch (mode) {
1033        case 0:         /* 640x480 (0x00) */
1034                break;
1035        case 1:         /* 352x288 */
1036                t2[1] = 0x40;
1037                break;
1038        case 2:         /* 320x240 */
1039                t2[1] = 0x10;
1040                break;
1041        case 3:         /* 176x144 */
1042                t2[1] = 0x50;
1043                break;
1044        default:
1045/*      case 4:          * 160x120 */
1046                t2[1] = 0x20;
1047                break;
1048        }
1049
1050        switch (sd->sensor) {
1051        case SENSOR_OM6802:
1052                om6802_sensor_init(gspca_dev);
1053                break;
1054        case SENSOR_TAS5130A:
1055                i = 0;
1056                for (;;) {
1057                        reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1058                                         sizeof tas5130a_sensor_init[0]);
1059                        if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1060                                break;
1061                        i++;
1062                }
1063                reg_w(gspca_dev, 0x3c80);
1064                /* just in case and to keep sync with logs (for mine) */
1065                reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1066                                 sizeof tas5130a_sensor_init[0]);
1067                reg_w(gspca_dev, 0x3c80);
1068                break;
1069        }
1070        sensor = &sensor_data[sd->sensor];
1071        setfreq(gspca_dev);
1072        reg_r(gspca_dev, 0x0012);
1073        reg_w_buf(gspca_dev, t2, sizeof t2);
1074        reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
1075        reg_w(gspca_dev, 0x0013);
1076        msleep(15);
1077        reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1078        reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1079
1080        if (sd->sensor == SENSOR_OM6802)
1081                poll_sensor(gspca_dev);
1082
1083        return 0;
1084}
1085
1086static void sd_stopN(struct gspca_dev *gspca_dev)
1087{
1088        struct sd *sd = (struct sd *) gspca_dev;
1089
1090        reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1091                        sizeof sensor_data[sd->sensor].stream);
1092        reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1093                        sizeof sensor_data[sd->sensor].stream);
1094        if (sd->sensor == SENSOR_OM6802) {
1095                msleep(20);
1096                reg_w(gspca_dev, 0x0309);
1097        }
1098}
1099
1100static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1101                        u8 *data,                       /* isoc packet */
1102                        int len)                        /* iso packet length */
1103{
1104        int pkt_type;
1105
1106        if (data[0] == 0x5a) {
1107                /* Control Packet, after this came the header again,
1108                 * but extra bytes came in the packet before this,
1109                 * sometimes an EOF arrives, sometimes not... */
1110                return;
1111        }
1112        data += 2;
1113        len -= 2;
1114        if (data[0] == 0xff && data[1] == 0xd8)
1115                pkt_type = FIRST_PACKET;
1116        else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
1117                pkt_type = LAST_PACKET;
1118        else
1119                pkt_type = INTER_PACKET;
1120        gspca_frame_add(gspca_dev, pkt_type, data, len);
1121}
1122
1123static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val)
1124{
1125        struct sd *sd = (struct sd *) gspca_dev;
1126
1127        sd->blue_gain = val;
1128        if (gspca_dev->streaming)
1129                reg_w(gspca_dev, (val << 8) + 0x88);
1130        return 0;
1131}
1132
1133static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val)
1134{
1135        struct sd *sd = (struct sd *) gspca_dev;
1136
1137        *val = sd->blue_gain;
1138        return 0;
1139}
1140
1141static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val)
1142{
1143        struct sd *sd = (struct sd *) gspca_dev;
1144
1145        sd->red_gain = val;
1146        if (gspca_dev->streaming)
1147                reg_w(gspca_dev, (val << 8) + 0x87);
1148
1149        return 0;
1150}
1151
1152static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val)
1153{
1154        struct sd *sd = (struct sd *) gspca_dev;
1155
1156        *val = sd->red_gain;
1157        return 0;
1158}
1159
1160static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1161{
1162        struct sd *sd = (struct sd *) gspca_dev;
1163        u16 psg, nsg;
1164
1165        psg = sd->red_gain + sd->blue_gain + sd->green_gain;
1166        nsg = val * 3;
1167        sd->red_gain = sd->red_gain * nsg / psg;
1168        if (sd->red_gain > 0x40)
1169                sd->red_gain = 0x40;
1170        else if (sd->red_gain < 0x10)
1171                sd->red_gain = 0x10;
1172        sd->blue_gain = sd->blue_gain * nsg / psg;
1173        if (sd->blue_gain > 0x40)
1174                sd->blue_gain = 0x40;
1175        else if (sd->blue_gain < 0x10)
1176                sd->blue_gain = 0x10;
1177        sd->green_gain = sd->green_gain * nsg / psg;
1178        if (sd->green_gain > 0x40)
1179                sd->green_gain = 0x40;
1180        else if (sd->green_gain < 0x10)
1181                sd->green_gain = 0x10;
1182
1183        if (gspca_dev->streaming)
1184                setRGB(gspca_dev);
1185        return 0;
1186}
1187
1188static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1189{
1190        struct sd *sd = (struct sd *) gspca_dev;
1191
1192        *val = (sd->red_gain + sd->blue_gain + sd->green_gain) / 3;
1193        return 0;
1194}
1195
1196static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1197{
1198        struct sd *sd = (struct sd *) gspca_dev;
1199
1200        sd->brightness = val;
1201        if (gspca_dev->streaming)
1202                setbrightness(gspca_dev);
1203        return 0;
1204}
1205
1206static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1207{
1208        struct sd *sd = (struct sd *) gspca_dev;
1209
1210        *val = sd->brightness;
1211        return *val;
1212}
1213
1214static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
1215{
1216        struct sd *sd = (struct sd *) gspca_dev;
1217
1218        sd->awb = val;
1219        if (gspca_dev->streaming)
1220                setawb(gspca_dev);
1221        return 0;
1222}
1223
1224static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
1225{
1226        struct sd *sd = (struct sd *) gspca_dev;
1227
1228        *val = sd->awb;
1229        return *val;
1230}
1231
1232static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
1233{
1234        struct sd *sd = (struct sd *) gspca_dev;
1235
1236        sd->mirror = val;
1237        if (gspca_dev->streaming)
1238                setmirror(gspca_dev);
1239        return 0;
1240}
1241
1242static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
1243{
1244        struct sd *sd = (struct sd *) gspca_dev;
1245
1246        *val = sd->mirror;
1247        return *val;
1248}
1249
1250static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1251{
1252        struct sd *sd = (struct sd *) gspca_dev;
1253
1254        sd->effect = val;
1255        if (gspca_dev->streaming)
1256                seteffect(gspca_dev);
1257        return 0;
1258}
1259
1260static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1261{
1262        struct sd *sd = (struct sd *) gspca_dev;
1263
1264        *val = sd->effect;
1265        return *val;
1266}
1267
1268static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1269{
1270        struct sd *sd = (struct sd *) gspca_dev;
1271
1272        sd->contrast = val;
1273        if (gspca_dev->streaming)
1274                setcontrast(gspca_dev);
1275        return 0;
1276}
1277
1278static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1279{
1280        struct sd *sd = (struct sd *) gspca_dev;
1281
1282        *val = sd->contrast;
1283        return *val;
1284}
1285
1286static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1287{
1288        struct sd *sd = (struct sd *) gspca_dev;
1289
1290        sd->colors = val;
1291        if (gspca_dev->streaming)
1292                setcolors(gspca_dev);
1293        return 0;
1294}
1295
1296static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1297{
1298        struct sd *sd = (struct sd *) gspca_dev;
1299
1300        *val = sd->colors;
1301        return 0;
1302}
1303
1304static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1305{
1306        struct sd *sd = (struct sd *) gspca_dev;
1307
1308        sd->gamma = val;
1309        if (gspca_dev->streaming)
1310                setgamma(gspca_dev);
1311        return 0;
1312}
1313
1314static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1315{
1316        struct sd *sd = (struct sd *) gspca_dev;
1317
1318        *val = sd->gamma;
1319        return 0;
1320}
1321
1322static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1323{
1324        struct sd *sd = (struct sd *) gspca_dev;
1325
1326        sd->freq = val;
1327        if (gspca_dev->streaming)
1328                setfreq(gspca_dev);
1329        return 0;
1330}
1331
1332static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1333{
1334        struct sd *sd = (struct sd *) gspca_dev;
1335
1336        *val = sd->freq;
1337        return 0;
1338}
1339
1340static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1341{
1342        struct sd *sd = (struct sd *) gspca_dev;
1343
1344        sd->sharpness = val;
1345        if (gspca_dev->streaming)
1346                setsharpness(gspca_dev);
1347        return 0;
1348}
1349
1350static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1351{
1352        struct sd *sd = (struct sd *) gspca_dev;
1353
1354        *val = sd->sharpness;
1355        return 0;
1356}
1357
1358/* Low Light set  here......*/
1359static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1360{
1361        struct sd *sd = (struct sd *) gspca_dev;
1362
1363        sd->autogain = val;
1364        if (val != 0)
1365                reg_w(gspca_dev, 0xf48e);
1366        else
1367                reg_w(gspca_dev, 0xb48e);
1368        return 0;
1369}
1370
1371static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1372{
1373        struct sd *sd = (struct sd *) gspca_dev;
1374
1375        *val = sd->autogain;
1376        return 0;
1377}
1378
1379static int sd_querymenu(struct gspca_dev *gspca_dev,
1380                        struct v4l2_querymenu *menu)
1381{
1382        static const char *freq_nm[3] = {"NoFliker", "50 Hz", "60 Hz"};
1383
1384        switch (menu->id) {
1385        case V4L2_CID_POWER_LINE_FREQUENCY:
1386                if ((unsigned) menu->index >= ARRAY_SIZE(freq_nm))
1387                        break;
1388                strcpy((char *) menu->name, freq_nm[menu->index]);
1389                return 0;
1390        case V4L2_CID_EFFECTS:
1391                if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1392                        strlcpy((char *) menu->name,
1393                                effects_control[menu->index],
1394                                sizeof menu->name);
1395                        return 0;
1396                }
1397                break;
1398        }
1399        return -EINVAL;
1400}
1401
1402/* sub-driver description */
1403static const struct sd_desc sd_desc = {
1404        .name = MODULE_NAME,
1405        .ctrls = sd_ctrls,
1406        .nctrls = ARRAY_SIZE(sd_ctrls),
1407        .config = sd_config,
1408        .init = sd_init,
1409        .start = sd_start,
1410        .stopN = sd_stopN,
1411        .pkt_scan = sd_pkt_scan,
1412        .querymenu = sd_querymenu,
1413};
1414
1415/* -- module initialisation -- */
1416static const struct usb_device_id device_table[] = {
1417        {USB_DEVICE(0x17a1, 0x0128)},
1418        {}
1419};
1420MODULE_DEVICE_TABLE(usb, device_table);
1421
1422/* -- device connect -- */
1423static int sd_probe(struct usb_interface *intf,
1424                    const struct usb_device_id *id)
1425{
1426        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1427                               THIS_MODULE);
1428}
1429
1430static struct usb_driver sd_driver = {
1431        .name = MODULE_NAME,
1432        .id_table = device_table,
1433        .probe = sd_probe,
1434        .disconnect = gspca_disconnect,
1435#ifdef CONFIG_PM
1436        .suspend = gspca_suspend,
1437        .resume = gspca_resume,
1438#endif
1439};
1440
1441/* -- module insert / remove -- */
1442static int __init sd_mod_init(void)
1443{
1444        return usb_register(&sd_driver);
1445}
1446static void __exit sd_mod_exit(void)
1447{
1448        usb_deregister(&sd_driver);
1449}
1450
1451module_init(sd_mod_init);
1452module_exit(sd_mod_exit);
1453
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.