linux/drivers/media/video/gspca/pac7311.c
<<
>>
Prefs
   1/*
   2 *              Pixart PAC7311 library
   3 *              Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
   4 *
   5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 */
  21
  22/* Some documentation about various registers as determined by trial and error.
  23   When the register addresses differ between the 7202 and the 7311 the 2
  24   different addresses are written as 7302addr/7311addr, when one of the 2
  25   addresses is a - sign that register description is not valid for the
  26   matching IC.
  27
  28   Register page 1:
  29
  30   Address      Description
  31   -/0x08       Unknown compressor related, must always be 8 except when not
  32                in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
  33   -/0x1b       Auto white balance related, bit 0 is AWB enable (inverted)
  34                bits 345 seem to toggle per color gains on/off (inverted)
  35   0x78         Global control, bit 6 controls the LED (inverted)
  36   -/0x80       JPEG compression ratio ? Best not touched
  37
  38   Register page 3/4:
  39
  40   Address      Description
  41   0x02         Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
  42                the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
  43   -/0x0f       Master gain 1-245, low value = high gain
  44   0x10/-       Master gain 0-31
  45   -/0x10       Another gain 0-15, limited influence (1-2x gain I guess)
  46   0x21         Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
  47   -/0x27       Seems to toggle various gains on / off, Setting bit 7 seems to
  48                completely disable the analog amplification block. Set to 0x68
  49                for max gain, 0x14 for minimal gain.
  50*/
  51
  52#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  53
  54#define MODULE_NAME "pac7311"
  55
  56#include <linux/input.h>
  57#include "gspca.h"
  58
  59MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
  60MODULE_DESCRIPTION("Pixart PAC7311");
  61MODULE_LICENSE("GPL");
  62
  63/* specific webcam descriptor for pac7311 */
  64struct sd {
  65        struct gspca_dev gspca_dev;             /* !! must be the first item */
  66
  67        unsigned char contrast;
  68        unsigned char gain;
  69        unsigned char exposure;
  70        unsigned char autogain;
  71        __u8 hflip;
  72        __u8 vflip;
  73
  74        u8 sof_read;
  75        u8 autogain_ignore_frames;
  76
  77        atomic_t avg_lum;
  78};
  79
  80/* V4L2 controls supported by the driver */
  81static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
  82static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
  83static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
  84static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
  85static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
  86static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
  87static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
  88static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
  89static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
  90static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
  91static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
  92static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
  93
  94static const struct ctrl sd_ctrls[] = {
  95/* This control is for both the 7302 and the 7311 */
  96        {
  97            {
  98                .id      = V4L2_CID_CONTRAST,
  99                .type    = V4L2_CTRL_TYPE_INTEGER,
 100                .name    = "Contrast",
 101                .minimum = 0,
 102#define CONTRAST_MAX 255
 103                .maximum = CONTRAST_MAX,
 104                .step    = 1,
 105#define CONTRAST_DEF 127
 106                .default_value = CONTRAST_DEF,
 107            },
 108            .set = sd_setcontrast,
 109            .get = sd_getcontrast,
 110        },
 111/* All controls below are for both the 7302 and the 7311 */
 112        {
 113            {
 114                .id      = V4L2_CID_GAIN,
 115                .type    = V4L2_CTRL_TYPE_INTEGER,
 116                .name    = "Gain",
 117                .minimum = 0,
 118#define GAIN_MAX 255
 119                .maximum = GAIN_MAX,
 120                .step    = 1,
 121#define GAIN_DEF 127
 122#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
 123                .default_value = GAIN_DEF,
 124            },
 125            .set = sd_setgain,
 126            .get = sd_getgain,
 127        },
 128        {
 129            {
 130                .id      = V4L2_CID_EXPOSURE,
 131                .type    = V4L2_CTRL_TYPE_INTEGER,
 132                .name    = "Exposure",
 133                .minimum = 0,
 134#define EXPOSURE_MAX 255
 135                .maximum = EXPOSURE_MAX,
 136                .step    = 1,
 137#define EXPOSURE_DEF  16 /*  32 ms / 30 fps */
 138#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
 139                .default_value = EXPOSURE_DEF,
 140            },
 141            .set = sd_setexposure,
 142            .get = sd_getexposure,
 143        },
 144        {
 145            {
 146                .id      = V4L2_CID_AUTOGAIN,
 147                .type    = V4L2_CTRL_TYPE_BOOLEAN,
 148                .name    = "Auto Gain",
 149                .minimum = 0,
 150                .maximum = 1,
 151                .step    = 1,
 152#define AUTOGAIN_DEF 1
 153                .default_value = AUTOGAIN_DEF,
 154            },
 155            .set = sd_setautogain,
 156            .get = sd_getautogain,
 157        },
 158        {
 159            {
 160                .id      = V4L2_CID_HFLIP,
 161                .type    = V4L2_CTRL_TYPE_BOOLEAN,
 162                .name    = "Mirror",
 163                .minimum = 0,
 164                .maximum = 1,
 165                .step    = 1,
 166#define HFLIP_DEF 0
 167                .default_value = HFLIP_DEF,
 168            },
 169            .set = sd_sethflip,
 170            .get = sd_gethflip,
 171        },
 172        {
 173            {
 174                .id      = V4L2_CID_VFLIP,
 175                .type    = V4L2_CTRL_TYPE_BOOLEAN,
 176                .name    = "Vflip",
 177                .minimum = 0,
 178                .maximum = 1,
 179                .step    = 1,
 180#define VFLIP_DEF 0
 181                .default_value = VFLIP_DEF,
 182            },
 183            .set = sd_setvflip,
 184            .get = sd_getvflip,
 185        },
 186};
 187
 188static const struct v4l2_pix_format vga_mode[] = {
 189        {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
 190                .bytesperline = 160,
 191                .sizeimage = 160 * 120 * 3 / 8 + 590,
 192                .colorspace = V4L2_COLORSPACE_JPEG,
 193                .priv = 2},
 194        {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
 195                .bytesperline = 320,
 196                .sizeimage = 320 * 240 * 3 / 8 + 590,
 197                .colorspace = V4L2_COLORSPACE_JPEG,
 198                .priv = 1},
 199        {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
 200                .bytesperline = 640,
 201                .sizeimage = 640 * 480 * 3 / 8 + 590,
 202                .colorspace = V4L2_COLORSPACE_JPEG,
 203                .priv = 0},
 204};
 205
 206#define LOAD_PAGE4              254
 207#define END_OF_SEQUENCE         0
 208
 209/* pac 7311 */
 210static const __u8 init_7311[] = {
 211        0x78, 0x40,     /* Bit_0=start stream, Bit_6=LED */
 212        0x78, 0x40,     /* Bit_0=start stream, Bit_6=LED */
 213        0x78, 0x44,     /* Bit_0=start stream, Bit_6=LED */
 214        0xff, 0x04,
 215        0x27, 0x80,
 216        0x28, 0xca,
 217        0x29, 0x53,
 218        0x2a, 0x0e,
 219        0xff, 0x01,
 220        0x3e, 0x20,
 221};
 222
 223static const __u8 start_7311[] = {
 224/*      index, len, [value]* */
 225        0xff, 1,        0x01,           /* page 1 */
 226        0x02, 43,       0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
 227                        0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
 228                        0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
 229                        0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
 230                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 231                        0x00, 0x00, 0x00,
 232        0x3e, 42,       0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
 233                        0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
 234                        0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
 235                        0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
 236                        0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
 237                        0xd0, 0xff,
 238        0x78, 6,        0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
 239        0x7f, 18,       0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
 240                        0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
 241                        0x18, 0x20,
 242        0x96, 3,        0x01, 0x08, 0x04,
 243        0xa0, 4,        0x44, 0x44, 0x44, 0x04,
 244        0xf0, 13,       0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
 245                        0x3f, 0x00, 0x0a, 0x01, 0x00,
 246        0xff, 1,        0x04,           /* page 4 */
 247        0, LOAD_PAGE4,                  /* load the page 4 */
 248        0x11, 1,        0x01,
 249        0, END_OF_SEQUENCE              /* end of sequence */
 250};
 251
 252#define SKIP            0xaa
 253/* page 4 - the value SKIP says skip the index - see reg_w_page() */
 254static const __u8 page4_7311[] = {
 255        SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
 256        0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
 257        0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
 258        0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
 259        SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
 260        0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
 261        0x23, 0x28, 0x04, 0x11, 0x00, 0x00
 262};
 263
 264static void reg_w_buf(struct gspca_dev *gspca_dev,
 265                  __u8 index,
 266                  const u8 *buffer, int len)
 267{
 268        int ret;
 269
 270        if (gspca_dev->usb_err < 0)
 271                return;
 272        memcpy(gspca_dev->usb_buf, buffer, len);
 273        ret = usb_control_msg(gspca_dev->dev,
 274                        usb_sndctrlpipe(gspca_dev->dev, 0),
 275                        0,              /* request */
 276                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 277                        0,              /* value */
 278                        index, gspca_dev->usb_buf, len,
 279                        500);
 280        if (ret < 0) {
 281                pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
 282                       index, ret);
 283                gspca_dev->usb_err = ret;
 284        }
 285}
 286
 287
 288static void reg_w(struct gspca_dev *gspca_dev,
 289                  __u8 index,
 290                  __u8 value)
 291{
 292        int ret;
 293
 294        if (gspca_dev->usb_err < 0)
 295                return;
 296        gspca_dev->usb_buf[0] = value;
 297        ret = usb_control_msg(gspca_dev->dev,
 298                        usb_sndctrlpipe(gspca_dev->dev, 0),
 299                        0,                      /* request */
 300                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 301                        0, index, gspca_dev->usb_buf, 1,
 302                        500);
 303        if (ret < 0) {
 304                pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
 305                       index, value, ret);
 306                gspca_dev->usb_err = ret;
 307        }
 308}
 309
 310static void reg_w_seq(struct gspca_dev *gspca_dev,
 311                const __u8 *seq, int len)
 312{
 313        while (--len >= 0) {
 314                reg_w(gspca_dev, seq[0], seq[1]);
 315                seq += 2;
 316        }
 317}
 318
 319/* load the beginning of a page */
 320static void reg_w_page(struct gspca_dev *gspca_dev,
 321                        const __u8 *page, int len)
 322{
 323        int index;
 324        int ret = 0;
 325
 326        if (gspca_dev->usb_err < 0)
 327                return;
 328        for (index = 0; index < len; index++) {
 329                if (page[index] == SKIP)                /* skip this index */
 330                        continue;
 331                gspca_dev->usb_buf[0] = page[index];
 332                ret = usb_control_msg(gspca_dev->dev,
 333                                usb_sndctrlpipe(gspca_dev->dev, 0),
 334                                0,                      /* request */
 335                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 336                                0, index, gspca_dev->usb_buf, 1,
 337                                500);
 338                if (ret < 0) {
 339                        pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
 340                               index, page[index], ret);
 341                        gspca_dev->usb_err = ret;
 342                        break;
 343                }
 344        }
 345}
 346
 347/* output a variable sequence */
 348static void reg_w_var(struct gspca_dev *gspca_dev,
 349                        const __u8 *seq,
 350                        const __u8 *page4, unsigned int page4_len)
 351{
 352        int index, len;
 353
 354        for (;;) {
 355                index = *seq++;
 356                len = *seq++;
 357                switch (len) {
 358                case END_OF_SEQUENCE:
 359                        return;
 360                case LOAD_PAGE4:
 361                        reg_w_page(gspca_dev, page4, page4_len);
 362                        break;
 363                default:
 364                        if (len > USB_BUF_SZ) {
 365                                PDEBUG(D_ERR|D_STREAM,
 366                                        "Incorrect variable sequence");
 367                                return;
 368                        }
 369                        while (len > 0) {
 370                                if (len < 8) {
 371                                        reg_w_buf(gspca_dev,
 372                                                index, seq, len);
 373                                        seq += len;
 374                                        break;
 375                                }
 376                                reg_w_buf(gspca_dev, index, seq, 8);
 377                                seq += 8;
 378                                index += 8;
 379                                len -= 8;
 380                        }
 381                }
 382        }
 383        /* not reached */
 384}
 385
 386/* this function is called at probe time for pac7311 */
 387static int sd_config(struct gspca_dev *gspca_dev,
 388                        const struct usb_device_id *id)
 389{
 390        struct sd *sd = (struct sd *) gspca_dev;
 391        struct cam *cam;
 392
 393        cam = &gspca_dev->cam;
 394
 395        PDEBUG(D_CONF, "Find Sensor PAC7311");
 396        cam->cam_mode = vga_mode;
 397        cam->nmodes = ARRAY_SIZE(vga_mode);
 398
 399        sd->contrast = CONTRAST_DEF;
 400        sd->gain = GAIN_DEF;
 401        sd->exposure = EXPOSURE_DEF;
 402        sd->autogain = AUTOGAIN_DEF;
 403        sd->hflip = HFLIP_DEF;
 404        sd->vflip = VFLIP_DEF;
 405        return 0;
 406}
 407
 408/* This function is used by pac7311 only */
 409static void setcontrast(struct gspca_dev *gspca_dev)
 410{
 411        struct sd *sd = (struct sd *) gspca_dev;
 412
 413        reg_w(gspca_dev, 0xff, 0x04);
 414        reg_w(gspca_dev, 0x10, sd->contrast >> 4);
 415        /* load registers to sensor (Bit 0, auto clear) */
 416        reg_w(gspca_dev, 0x11, 0x01);
 417}
 418
 419static void setgain(struct gspca_dev *gspca_dev)
 420{
 421        struct sd *sd = (struct sd *) gspca_dev;
 422        int gain = GAIN_MAX - sd->gain;
 423
 424        if (gain < 1)
 425                gain = 1;
 426        else if (gain > 245)
 427                gain = 245;
 428        reg_w(gspca_dev, 0xff, 0x04);                   /* page 4 */
 429        reg_w(gspca_dev, 0x0e, 0x00);
 430        reg_w(gspca_dev, 0x0f, gain);
 431
 432        /* load registers to sensor (Bit 0, auto clear) */
 433        reg_w(gspca_dev, 0x11, 0x01);
 434}
 435
 436static void setexposure(struct gspca_dev *gspca_dev)
 437{
 438        struct sd *sd = (struct sd *) gspca_dev;
 439        __u8 reg;
 440
 441        /* register 2 of frame 3/4 contains the clock divider configuring the
 442           no fps according to the formula: 60 / reg. sd->exposure is the
 443           desired exposure time in ms. */
 444        reg = 120 * sd->exposure / 1000;
 445        if (reg < 2)
 446                reg = 2;
 447        else if (reg > 63)
 448                reg = 63;
 449
 450        reg_w(gspca_dev, 0xff, 0x04);                   /* page 4 */
 451        reg_w(gspca_dev, 0x02, reg);
 452
 453        /* Page 1 register 8 must always be 0x08 except when not in
 454           640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
 455        reg_w(gspca_dev, 0xff, 0x01);
 456        if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
 457                        reg <= 3) {
 458                reg_w(gspca_dev, 0x08, 0x09);
 459        } else {
 460                reg_w(gspca_dev, 0x08, 0x08);
 461        }
 462
 463        /* load registers to sensor (Bit 0, auto clear) */
 464        reg_w(gspca_dev, 0x11, 0x01);
 465}
 466
 467static void sethvflip(struct gspca_dev *gspca_dev)
 468{
 469        struct sd *sd = (struct sd *) gspca_dev;
 470        __u8 data;
 471
 472        reg_w(gspca_dev, 0xff, 0x04);                   /* page 4 */
 473        data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00);
 474        reg_w(gspca_dev, 0x21, data);
 475
 476        /* load registers to sensor (Bit 0, auto clear) */
 477        reg_w(gspca_dev, 0x11, 0x01);
 478}
 479
 480/* this function is called at probe and resume time for pac7311 */
 481static int sd_init(struct gspca_dev *gspca_dev)
 482{
 483        reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
 484        return gspca_dev->usb_err;
 485}
 486
 487static int sd_start(struct gspca_dev *gspca_dev)
 488{
 489        struct sd *sd = (struct sd *) gspca_dev;
 490
 491        sd->sof_read = 0;
 492
 493        reg_w_var(gspca_dev, start_7311,
 494                page4_7311, sizeof(page4_7311));
 495        setcontrast(gspca_dev);
 496        setgain(gspca_dev);
 497        setexposure(gspca_dev);
 498        sethvflip(gspca_dev);
 499
 500        /* set correct resolution */
 501        switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
 502        case 2:                                 /* 160x120 pac7311 */
 503                reg_w(gspca_dev, 0xff, 0x01);
 504                reg_w(gspca_dev, 0x17, 0x20);
 505                reg_w(gspca_dev, 0x87, 0x10);
 506                break;
 507        case 1:                                 /* 320x240 pac7311 */
 508                reg_w(gspca_dev, 0xff, 0x01);
 509                reg_w(gspca_dev, 0x17, 0x30);
 510                reg_w(gspca_dev, 0x87, 0x11);
 511                break;
 512        case 0:                                 /* 640x480 */
 513                reg_w(gspca_dev, 0xff, 0x01);
 514                reg_w(gspca_dev, 0x17, 0x00);
 515                reg_w(gspca_dev, 0x87, 0x12);
 516                break;
 517        }
 518
 519        sd->sof_read = 0;
 520        sd->autogain_ignore_frames = 0;
 521        atomic_set(&sd->avg_lum, -1);
 522
 523        /* start stream */
 524        reg_w(gspca_dev, 0xff, 0x01);
 525        reg_w(gspca_dev, 0x78, 0x05);
 526
 527        return gspca_dev->usb_err;
 528}
 529
 530static void sd_stopN(struct gspca_dev *gspca_dev)
 531{
 532        reg_w(gspca_dev, 0xff, 0x04);
 533        reg_w(gspca_dev, 0x27, 0x80);
 534        reg_w(gspca_dev, 0x28, 0xca);
 535        reg_w(gspca_dev, 0x29, 0x53);
 536        reg_w(gspca_dev, 0x2a, 0x0e);
 537        reg_w(gspca_dev, 0xff, 0x01);
 538        reg_w(gspca_dev, 0x3e, 0x20);
 539        reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
 540        reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
 541        reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
 542}
 543
 544/* called on streamoff with alt 0 and on disconnect for 7311 */
 545static void sd_stop0(struct gspca_dev *gspca_dev)
 546{
 547}
 548
 549/* Include pac common sof detection functions */
 550#include "pac_common.h"
 551
 552static void do_autogain(struct gspca_dev *gspca_dev)
 553{
 554        struct sd *sd = (struct sd *) gspca_dev;
 555        int avg_lum = atomic_read(&sd->avg_lum);
 556        int desired_lum, deadzone;
 557
 558        if (avg_lum == -1)
 559                return;
 560
 561        desired_lum = 200;
 562        deadzone = 20;
 563
 564        if (sd->autogain_ignore_frames > 0)
 565                sd->autogain_ignore_frames--;
 566        else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
 567                        deadzone, GAIN_KNEE, EXPOSURE_KNEE))
 568                sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
 569}
 570
 571/* JPEG header, part 1 */
 572static const unsigned char pac_jpeg_header1[] = {
 573  0xff, 0xd8,           /* SOI: Start of Image */
 574
 575  0xff, 0xc0,           /* SOF0: Start of Frame (Baseline DCT) */
 576  0x00, 0x11,           /* length = 17 bytes (including this length field) */
 577  0x08                  /* Precision: 8 */
 578  /* 2 bytes is placed here: number of image lines */
 579  /* 2 bytes is placed here: samples per line */
 580};
 581
 582/* JPEG header, continued */
 583static const unsigned char pac_jpeg_header2[] = {
 584  0x03,                 /* Number of image components: 3 */
 585  0x01, 0x21, 0x00,     /* ID=1, Subsampling 1x1, Quantization table: 0 */
 586  0x02, 0x11, 0x01,     /* ID=2, Subsampling 2x1, Quantization table: 1 */
 587  0x03, 0x11, 0x01,     /* ID=3, Subsampling 2x1, Quantization table: 1 */
 588
 589  0xff, 0xda,           /* SOS: Start Of Scan */
 590  0x00, 0x0c,           /* length = 12 bytes (including this length field) */
 591  0x03,                 /* number of components: 3 */
 592  0x01, 0x00,           /* selector 1, table 0x00 */
 593  0x02, 0x11,           /* selector 2, table 0x11 */
 594  0x03, 0x11,           /* selector 3, table 0x11 */
 595  0x00, 0x3f,           /* Spectral selection: 0 .. 63 */
 596  0x00                  /* Successive approximation: 0 */
 597};
 598
 599static void pac_start_frame(struct gspca_dev *gspca_dev,
 600                __u16 lines, __u16 samples_per_line)
 601{
 602        unsigned char tmpbuf[4];
 603
 604        gspca_frame_add(gspca_dev, FIRST_PACKET,
 605                pac_jpeg_header1, sizeof(pac_jpeg_header1));
 606
 607        tmpbuf[0] = lines >> 8;
 608        tmpbuf[1] = lines & 0xff;
 609        tmpbuf[2] = samples_per_line >> 8;
 610        tmpbuf[3] = samples_per_line & 0xff;
 611
 612        gspca_frame_add(gspca_dev, INTER_PACKET,
 613                tmpbuf, sizeof(tmpbuf));
 614        gspca_frame_add(gspca_dev, INTER_PACKET,
 615                pac_jpeg_header2, sizeof(pac_jpeg_header2));
 616}
 617
 618/* this function is run at interrupt level */
 619static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 620                        u8 *data,                       /* isoc packet */
 621                        int len)                        /* iso packet length */
 622{
 623        struct sd *sd = (struct sd *) gspca_dev;
 624        u8 *image;
 625        unsigned char *sof;
 626
 627        sof = pac_find_sof(&sd->sof_read, data, len);
 628        if (sof) {
 629                int n, lum_offset, footer_length;
 630
 631                /* 6 bytes after the FF D9 EOF marker a number of lumination
 632                   bytes are send corresponding to different parts of the
 633                   image, the 14th and 15th byte after the EOF seem to
 634                   correspond to the center of the image */
 635                lum_offset = 24 + sizeof pac_sof_marker;
 636                footer_length = 26;
 637
 638                /* Finish decoding current frame */
 639                n = (sof - data) - (footer_length + sizeof pac_sof_marker);
 640                if (n < 0) {
 641                        gspca_dev->image_len += n;
 642                        n = 0;
 643                } else {
 644                        gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
 645                }
 646                image = gspca_dev->image;
 647                if (image != NULL
 648                 && image[gspca_dev->image_len - 2] == 0xff
 649                 && image[gspca_dev->image_len - 1] == 0xd9)
 650                        gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
 651
 652                n = sof - data;
 653                len -= n;
 654                data = sof;
 655
 656                /* Get average lumination */
 657                if (gspca_dev->last_packet_type == LAST_PACKET &&
 658                                n >= lum_offset)
 659                        atomic_set(&sd->avg_lum, data[-lum_offset] +
 660                                                data[-lum_offset + 1]);
 661                else
 662                        atomic_set(&sd->avg_lum, -1);
 663
 664                /* Start the new frame with the jpeg header */
 665                pac_start_frame(gspca_dev,
 666                        gspca_dev->height, gspca_dev->width);
 667        }
 668        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 669}
 670
 671static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
 672{
 673        struct sd *sd = (struct sd *) gspca_dev;
 674
 675        sd->contrast = val;
 676        if (gspca_dev->streaming)
 677                setcontrast(gspca_dev);
 678        return gspca_dev->usb_err;
 679}
 680
 681static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
 682{
 683        struct sd *sd = (struct sd *) gspca_dev;
 684
 685        *val = sd->contrast;
 686        return 0;
 687}
 688
 689static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
 690{
 691        struct sd *sd = (struct sd *) gspca_dev;
 692
 693        sd->gain = val;
 694        if (gspca_dev->streaming)
 695                setgain(gspca_dev);
 696        return gspca_dev->usb_err;
 697}
 698
 699static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
 700{
 701        struct sd *sd = (struct sd *) gspca_dev;
 702
 703        *val = sd->gain;
 704        return 0;
 705}
 706
 707static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
 708{
 709        struct sd *sd = (struct sd *) gspca_dev;
 710
 711        sd->exposure = val;
 712        if (gspca_dev->streaming)
 713                setexposure(gspca_dev);
 714        return gspca_dev->usb_err;
 715}
 716
 717static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
 718{
 719        struct sd *sd = (struct sd *) gspca_dev;
 720
 721        *val = sd->exposure;
 722        return 0;
 723}
 724
 725static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
 726{
 727        struct sd *sd = (struct sd *) gspca_dev;
 728
 729        sd->autogain = val;
 730        /* when switching to autogain set defaults to make sure
 731           we are on a valid point of the autogain gain /
 732           exposure knee graph, and give this change time to
 733           take effect before doing autogain. */
 734        if (sd->autogain) {
 735                sd->exposure = EXPOSURE_DEF;
 736                sd->gain = GAIN_DEF;
 737                if (gspca_dev->streaming) {
 738                        sd->autogain_ignore_frames =
 739                                PAC_AUTOGAIN_IGNORE_FRAMES;
 740                        setexposure(gspca_dev);
 741                        setgain(gspca_dev);
 742                }
 743        }
 744
 745        return gspca_dev->usb_err;
 746}
 747
 748static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
 749{
 750        struct sd *sd = (struct sd *) gspca_dev;
 751
 752        *val = sd->autogain;
 753        return 0;
 754}
 755
 756static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
 757{
 758        struct sd *sd = (struct sd *) gspca_dev;
 759
 760        sd->hflip = val;
 761        if (gspca_dev->streaming)
 762                sethvflip(gspca_dev);
 763        return gspca_dev->usb_err;
 764}
 765
 766static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
 767{
 768        struct sd *sd = (struct sd *) gspca_dev;
 769
 770        *val = sd->hflip;
 771        return 0;
 772}
 773
 774static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
 775{
 776        struct sd *sd = (struct sd *) gspca_dev;
 777
 778        sd->vflip = val;
 779        if (gspca_dev->streaming)
 780                sethvflip(gspca_dev);
 781        return gspca_dev->usb_err;
 782}
 783
 784static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
 785{
 786        struct sd *sd = (struct sd *) gspca_dev;
 787
 788        *val = sd->vflip;
 789        return 0;
 790}
 791
 792#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
 793static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
 794                        u8 *data,               /* interrupt packet data */
 795                        int len)                /* interrupt packet length */
 796{
 797        int ret = -EINVAL;
 798        u8 data0, data1;
 799
 800        if (len == 2) {
 801                data0 = data[0];
 802                data1 = data[1];
 803                if ((data0 == 0x00 && data1 == 0x11) ||
 804                    (data0 == 0x22 && data1 == 0x33) ||
 805                    (data0 == 0x44 && data1 == 0x55) ||
 806                    (data0 == 0x66 && data1 == 0x77) ||
 807                    (data0 == 0x88 && data1 == 0x99) ||
 808                    (data0 == 0xaa && data1 == 0xbb) ||
 809                    (data0 == 0xcc && data1 == 0xdd) ||
 810                    (data0 == 0xee && data1 == 0xff)) {
 811                        input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
 812                        input_sync(gspca_dev->input_dev);
 813                        input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
 814                        input_sync(gspca_dev->input_dev);
 815                        ret = 0;
 816                }
 817        }
 818
 819        return ret;
 820}
 821#endif
 822
 823/* sub-driver description for pac7311 */
 824static const struct sd_desc sd_desc = {
 825        .name = MODULE_NAME,
 826        .ctrls = sd_ctrls,
 827        .nctrls = ARRAY_SIZE(sd_ctrls),
 828        .config = sd_config,
 829        .init = sd_init,
 830        .start = sd_start,
 831        .stopN = sd_stopN,
 832        .stop0 = sd_stop0,
 833        .pkt_scan = sd_pkt_scan,
 834        .dq_callback = do_autogain,
 835#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
 836        .int_pkt_scan = sd_int_pkt_scan,
 837#endif
 838};
 839
 840/* -- module initialisation -- */
 841static const struct usb_device_id device_table[] = {
 842        {USB_DEVICE(0x093a, 0x2600)},
 843        {USB_DEVICE(0x093a, 0x2601)},
 844        {USB_DEVICE(0x093a, 0x2603)},
 845        {USB_DEVICE(0x093a, 0x2608)},
 846        {USB_DEVICE(0x093a, 0x260e)},
 847        {USB_DEVICE(0x093a, 0x260f)},
 848        {}
 849};
 850MODULE_DEVICE_TABLE(usb, device_table);
 851
 852/* -- device connect -- */
 853static int sd_probe(struct usb_interface *intf,
 854                        const struct usb_device_id *id)
 855{
 856        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 857                                THIS_MODULE);
 858}
 859
 860static struct usb_driver sd_driver = {
 861        .name = MODULE_NAME,
 862        .id_table = device_table,
 863        .probe = sd_probe,
 864        .disconnect = gspca_disconnect,
 865#ifdef CONFIG_PM
 866        .suspend = gspca_suspend,
 867        .resume = gspca_resume,
 868#endif
 869};
 870
 871module_usb_driver(sd_driver);
 872
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.