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