linux/drivers/media/video/gspca/mars.c
<<
>>
Prefs
   1/*
   2 *              Mars-Semi MR97311A library
   3 *              Copyright (C) 2005 <bradlch@hotmail.com>
   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#define MODULE_NAME "mars"
  23
  24#include "gspca.h"
  25#include "jpeg.h"
  26
  27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
  28MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
  29MODULE_LICENSE("GPL");
  30
  31/* specific webcam descriptor */
  32struct sd {
  33        struct gspca_dev gspca_dev;     /* !! must be the first item */
  34
  35        u8 brightness;
  36        u8 colors;
  37        u8 gamma;
  38        u8 sharpness;
  39        u8 quality;
  40#define QUALITY_MIN 40
  41#define QUALITY_MAX 70
  42#define QUALITY_DEF 50
  43
  44        u8 *jpeg_hdr;
  45};
  46
  47/* V4L2 controls supported by the driver */
  48static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
  49static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
  50static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
  51static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
  52static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
  53static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
  54static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
  55static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
  56
  57static struct ctrl sd_ctrls[] = {
  58        {
  59            {
  60                .id      = V4L2_CID_BRIGHTNESS,
  61                .type    = V4L2_CTRL_TYPE_INTEGER,
  62                .name    = "Brightness",
  63                .minimum = 0,
  64                .maximum = 30,
  65                .step    = 1,
  66#define BRIGHTNESS_DEF 15
  67                .default_value = BRIGHTNESS_DEF,
  68            },
  69            .set = sd_setbrightness,
  70            .get = sd_getbrightness,
  71        },
  72        {
  73            {
  74                .id      = V4L2_CID_SATURATION,
  75                .type    = V4L2_CTRL_TYPE_INTEGER,
  76                .name    = "Color",
  77                .minimum = 1,
  78                .maximum = 255,
  79                .step    = 1,
  80#define COLOR_DEF 200
  81                .default_value = COLOR_DEF,
  82            },
  83            .set = sd_setcolors,
  84            .get = sd_getcolors,
  85        },
  86        {
  87            {
  88                .id      = V4L2_CID_GAMMA,
  89                .type    = V4L2_CTRL_TYPE_INTEGER,
  90                .name    = "Gamma",
  91                .minimum = 0,
  92                .maximum = 3,
  93                .step    = 1,
  94#define GAMMA_DEF 1
  95                .default_value = GAMMA_DEF,
  96            },
  97            .set = sd_setgamma,
  98            .get = sd_getgamma,
  99        },
 100        {
 101            {
 102                .id      = V4L2_CID_SHARPNESS,
 103                .type    = V4L2_CTRL_TYPE_INTEGER,
 104                .name    = "Sharpness",
 105                .minimum = 0,
 106                .maximum = 2,
 107                .step    = 1,
 108#define SHARPNESS_DEF 1
 109                .default_value = SHARPNESS_DEF,
 110            },
 111            .set = sd_setsharpness,
 112            .get = sd_getsharpness,
 113        },
 114};
 115
 116static const struct v4l2_pix_format vga_mode[] = {
 117        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 118                .bytesperline = 320,
 119                .sizeimage = 320 * 240 * 3 / 8 + 590,
 120                .colorspace = V4L2_COLORSPACE_JPEG,
 121                .priv = 2},
 122        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 123                .bytesperline = 640,
 124                .sizeimage = 640 * 480 * 3 / 8 + 590,
 125                .colorspace = V4L2_COLORSPACE_JPEG,
 126                .priv = 1},
 127};
 128
 129static const __u8 mi_data[0x20] = {
 130/*       01    02   03     04    05    06    07    08 */
 131        0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00,
 132/*       09    0a   0b     0c    0d    0e    0f    10 */
 133        0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01,
 134/*       11    12   13     14    15    16    17    18 */
 135        0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02,
 136/*       19    1a   1b     1c    1d    1e    1f    20 */
 137        0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00
 138};
 139
 140/* write <len> bytes from gspca_dev->usb_buf */
 141static int reg_w(struct gspca_dev *gspca_dev,
 142                 int len)
 143{
 144        int alen, ret;
 145
 146        ret = usb_bulk_msg(gspca_dev->dev,
 147                        usb_sndbulkpipe(gspca_dev->dev, 4),
 148                        gspca_dev->usb_buf,
 149                        len,
 150                        &alen,
 151                        500);   /* timeout in milliseconds */
 152        if (ret < 0)
 153                PDEBUG(D_ERR, "reg write [%02x] error %d",
 154                        gspca_dev->usb_buf[0], ret);
 155        return ret;
 156}
 157
 158static void mi_w(struct gspca_dev *gspca_dev,
 159                 u8 addr,
 160                 u8 value)
 161{
 162        gspca_dev->usb_buf[0] = 0x1f;
 163        gspca_dev->usb_buf[1] = 0;                      /* control byte */
 164        gspca_dev->usb_buf[2] = addr;
 165        gspca_dev->usb_buf[3] = value;
 166
 167        reg_w(gspca_dev, 4);
 168}
 169
 170/* this function is called at probe time */
 171static int sd_config(struct gspca_dev *gspca_dev,
 172                        const struct usb_device_id *id)
 173{
 174        struct sd *sd = (struct sd *) gspca_dev;
 175        struct cam *cam;
 176
 177        cam = &gspca_dev->cam;
 178        cam->cam_mode = vga_mode;
 179        cam->nmodes = ARRAY_SIZE(vga_mode);
 180        sd->brightness = BRIGHTNESS_DEF;
 181        sd->colors = COLOR_DEF;
 182        sd->gamma = GAMMA_DEF;
 183        sd->sharpness = SHARPNESS_DEF;
 184        sd->quality = QUALITY_DEF;
 185        gspca_dev->nbalt = 9;           /* use the altsetting 08 */
 186        return 0;
 187}
 188
 189/* this function is called at probe and resume time */
 190static int sd_init(struct gspca_dev *gspca_dev)
 191{
 192        return 0;
 193}
 194
 195static int sd_start(struct gspca_dev *gspca_dev)
 196{
 197        struct sd *sd = (struct sd *) gspca_dev;
 198        int err_code;
 199        u8 *data;
 200        int i;
 201
 202        /* create the JPEG header */
 203        sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
 204        if (!sd->jpeg_hdr)
 205                return -ENOMEM;
 206        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 207                        0x21);          /* JPEG 422 */
 208        jpeg_set_qual(sd->jpeg_hdr, sd->quality);
 209
 210        data = gspca_dev->usb_buf;
 211
 212        data[0] = 0x01;         /* address */
 213        data[1] = 0x01;
 214        err_code = reg_w(gspca_dev, 2);
 215        if (err_code < 0)
 216                return err_code;
 217
 218        /*
 219           Initialize the MR97113 chip register
 220         */
 221        data[0] = 0x00;         /* address */
 222        data[1] = 0x0c | 0x01;  /* reg 0 */
 223        data[2] = 0x01;         /* reg 1 */
 224        data[3] = gspca_dev->width / 8;         /* h_size , reg 2 */
 225        data[4] = gspca_dev->height / 8;        /* v_size , reg 3 */
 226        data[5] = 0x30;         /* reg 4, MI, PAS5101 :
 227                                 *      0x30 for 24mhz , 0x28 for 12mhz */
 228        data[6] = 0x02;         /* reg 5, H start - was 0x04 */
 229        data[7] = sd->gamma * 0x40;     /* reg 0x06: gamma */
 230        data[8] = 0x01;         /* reg 7, V start - was 0x03 */
 231/*      if (h_size == 320 ) */
 232/*              data[9]= 0x56;   * reg 8, 24MHz, 2:1 scale down */
 233/*      else */
 234        data[9] = 0x52;         /* reg 8, 24MHz, no scale down */
 235/*jfm: from win trace*/
 236        data[10] = 0x18;
 237
 238        err_code = reg_w(gspca_dev, 11);
 239        if (err_code < 0)
 240                return err_code;
 241
 242        data[0] = 0x23;         /* address */
 243        data[1] = 0x09;         /* reg 35, append frame header */
 244
 245        err_code = reg_w(gspca_dev, 2);
 246        if (err_code < 0)
 247                return err_code;
 248
 249        data[0] = 0x3c;         /* address */
 250/*      if (gspca_dev->width == 1280) */
 251/*              data[1] = 200;   * reg 60, pc-cam frame size
 252                                 *      (unit: 4KB) 800KB */
 253/*      else */
 254        data[1] = 50;           /* 50 reg 60, pc-cam frame size
 255                                 *      (unit: 4KB) 200KB */
 256        err_code = reg_w(gspca_dev, 2);
 257        if (err_code < 0)
 258                return err_code;
 259
 260        /* auto dark-gain */
 261        data[0] = 0x5e;         /* address */
 262        data[1] = 0;            /* reg 94, Y Gain (auto) */
 263/*jfm: from win trace*/
 264                                /* reg 0x5f/0x60 (LE) = saturation */
 265                                /* h (60): xxxx x100
 266                                 * l (5f): xxxx x000 */
 267        data[2] = sd->colors << 3;
 268        data[3] = ((sd->colors >> 2) & 0xf8) | 0x04;
 269        data[4] = sd->brightness; /* reg 0x61 = brightness */
 270        data[5] = 0x00;
 271
 272        err_code = reg_w(gspca_dev, 6);
 273        if (err_code < 0)
 274                return err_code;
 275
 276        data[0] = 0x67;
 277/*jfm: from win trace*/
 278        data[1] = sd->sharpness * 4 + 3;
 279        data[2] = 0x14;
 280        err_code = reg_w(gspca_dev, 3);
 281        if (err_code < 0)
 282                return err_code;
 283
 284        data[0] = 0x69;
 285        data[1] = 0x2f;
 286        data[2] = 0x28;
 287        data[3] = 0x42;
 288        err_code = reg_w(gspca_dev, 4);
 289        if (err_code < 0)
 290                return err_code;
 291
 292        data[0] = 0x63;
 293        data[1] = 0x07;
 294        err_code = reg_w(gspca_dev, 2);
 295/*jfm: win trace - many writes here to reg 0x64*/
 296        if (err_code < 0)
 297                return err_code;
 298
 299        /* initialize the MI sensor */
 300        for (i = 0; i < sizeof mi_data; i++)
 301                mi_w(gspca_dev, i + 1, mi_data[i]);
 302
 303        data[0] = 0x00;
 304        data[1] = 0x4d;         /* ISOC transfering enable... */
 305        reg_w(gspca_dev, 2);
 306        return 0;
 307}
 308
 309static void sd_stopN(struct gspca_dev *gspca_dev)
 310{
 311        int result;
 312
 313        gspca_dev->usb_buf[0] = 1;
 314        gspca_dev->usb_buf[1] = 0;
 315        result = reg_w(gspca_dev, 2);
 316        if (result < 0)
 317                PDEBUG(D_ERR, "Camera Stop failed");
 318}
 319
 320static void sd_stop0(struct gspca_dev *gspca_dev)
 321{
 322        struct sd *sd = (struct sd *) gspca_dev;
 323
 324        kfree(sd->jpeg_hdr);
 325}
 326
 327static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 328                        struct gspca_frame *frame,      /* target */
 329                        __u8 *data,                     /* isoc packet */
 330                        int len)                        /* iso packet length */
 331{
 332        struct sd *sd = (struct sd *) gspca_dev;
 333        int p;
 334
 335        if (len < 6) {
 336/*              gspca_dev->last_packet_type = DISCARD_PACKET; */
 337                return;
 338        }
 339        for (p = 0; p < len - 6; p++) {
 340                if (data[0 + p] == 0xff
 341                    && data[1 + p] == 0xff
 342                    && data[2 + p] == 0x00
 343                    && data[3 + p] == 0xff
 344                    && data[4 + p] == 0x96) {
 345                        if (data[5 + p] == 0x64
 346                            || data[5 + p] == 0x65
 347                            || data[5 + p] == 0x66
 348                            || data[5 + p] == 0x67) {
 349                                PDEBUG(D_PACK, "sof offset: %d len: %d",
 350                                        p, len);
 351                                frame = gspca_frame_add(gspca_dev, LAST_PACKET,
 352                                                        frame, data, p);
 353
 354                                /* put the JPEG header */
 355                                gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
 356                                        sd->jpeg_hdr, JPEG_HDR_SZ);
 357                                data += p + 16;
 358                                len -= p + 16;
 359                                break;
 360                        }
 361                }
 362        }
 363        gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 364}
 365
 366static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 367{
 368        struct sd *sd = (struct sd *) gspca_dev;
 369
 370        sd->brightness = val;
 371        if (gspca_dev->streaming) {
 372                gspca_dev->usb_buf[0] = 0x61;
 373                gspca_dev->usb_buf[1] = val;
 374                reg_w(gspca_dev, 2);
 375        }
 376        return 0;
 377}
 378
 379static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
 380{
 381        struct sd *sd = (struct sd *) gspca_dev;
 382
 383        *val = sd->brightness;
 384        return 0;
 385}
 386
 387static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
 388{
 389        struct sd *sd = (struct sd *) gspca_dev;
 390
 391        sd->colors = val;
 392        if (gspca_dev->streaming) {
 393
 394                /* see sd_start */
 395                gspca_dev->usb_buf[0] = 0x5f;
 396                gspca_dev->usb_buf[1] = sd->colors << 3;
 397                gspca_dev->usb_buf[2] = ((sd->colors >> 2) & 0xf8) | 0x04;
 398                reg_w(gspca_dev, 3);
 399        }
 400        return 0;
 401}
 402
 403static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
 404{
 405        struct sd *sd = (struct sd *) gspca_dev;
 406
 407        *val = sd->colors;
 408        return 0;
 409}
 410
 411static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
 412{
 413        struct sd *sd = (struct sd *) gspca_dev;
 414
 415        sd->gamma = val;
 416        if (gspca_dev->streaming) {
 417                gspca_dev->usb_buf[0] = 0x06;
 418                gspca_dev->usb_buf[1] = val * 0x40;
 419                reg_w(gspca_dev, 2);
 420        }
 421        return 0;
 422}
 423
 424static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
 425{
 426        struct sd *sd = (struct sd *) gspca_dev;
 427
 428        *val = sd->gamma;
 429        return 0;
 430}
 431
 432static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
 433{
 434        struct sd *sd = (struct sd *) gspca_dev;
 435
 436        sd->sharpness = val;
 437        if (gspca_dev->streaming) {
 438                gspca_dev->usb_buf[0] = 0x67;
 439                gspca_dev->usb_buf[1] = val * 4 + 3;
 440                reg_w(gspca_dev, 2);
 441        }
 442        return 0;
 443}
 444
 445static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
 446{
 447        struct sd *sd = (struct sd *) gspca_dev;
 448
 449        *val = sd->sharpness;
 450        return 0;
 451}
 452
 453static int sd_set_jcomp(struct gspca_dev *gspca_dev,
 454                        struct v4l2_jpegcompression *jcomp)
 455{
 456        struct sd *sd = (struct sd *) gspca_dev;
 457
 458        if (jcomp->quality < QUALITY_MIN)
 459                sd->quality = QUALITY_MIN;
 460        else if (jcomp->quality > QUALITY_MAX)
 461                sd->quality = QUALITY_MAX;
 462        else
 463                sd->quality = jcomp->quality;
 464        if (gspca_dev->streaming)
 465                jpeg_set_qual(sd->jpeg_hdr, sd->quality);
 466        return 0;
 467}
 468
 469static int sd_get_jcomp(struct gspca_dev *gspca_dev,
 470                        struct v4l2_jpegcompression *jcomp)
 471{
 472        struct sd *sd = (struct sd *) gspca_dev;
 473
 474        memset(jcomp, 0, sizeof *jcomp);
 475        jcomp->quality = sd->quality;
 476        jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
 477                        | V4L2_JPEG_MARKER_DQT;
 478        return 0;
 479}
 480
 481/* sub-driver description */
 482static const struct sd_desc sd_desc = {
 483        .name = MODULE_NAME,
 484        .ctrls = sd_ctrls,
 485        .nctrls = ARRAY_SIZE(sd_ctrls),
 486        .config = sd_config,
 487        .init = sd_init,
 488        .start = sd_start,
 489        .stopN = sd_stopN,
 490        .stop0 = sd_stop0,
 491        .pkt_scan = sd_pkt_scan,
 492        .get_jcomp = sd_get_jcomp,
 493        .set_jcomp = sd_set_jcomp,
 494};
 495
 496/* -- module initialisation -- */
 497static const __devinitdata struct usb_device_id device_table[] = {
 498        {USB_DEVICE(0x093a, 0x050f)},
 499        {}
 500};
 501MODULE_DEVICE_TABLE(usb, device_table);
 502
 503/* -- device connect -- */
 504static int sd_probe(struct usb_interface *intf,
 505                        const struct usb_device_id *id)
 506{
 507        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 508                                THIS_MODULE);
 509}
 510
 511static struct usb_driver sd_driver = {
 512        .name = MODULE_NAME,
 513        .id_table = device_table,
 514        .probe = sd_probe,
 515        .disconnect = gspca_disconnect,
 516#ifdef CONFIG_PM
 517        .suspend = gspca_suspend,
 518        .resume = gspca_resume,
 519#endif
 520};
 521
 522/* -- module insert / remove -- */
 523static int __init sd_mod_init(void)
 524{
 525        int ret;
 526
 527        ret = usb_register(&sd_driver);
 528        if (ret < 0)
 529                return ret;
 530        PDEBUG(D_PROBE, "registered");
 531        return 0;
 532}
 533static void __exit sd_mod_exit(void)
 534{
 535        usb_deregister(&sd_driver);
 536        PDEBUG(D_PROBE, "deregistered");
 537}
 538
 539module_init(sd_mod_init);
 540module_exit(sd_mod_exit);
 541