linux/drivers/media/video/gspca/stk014.c
<<
>>
Prefs
   1/*
   2 * Syntek DV4000 (STK014) subdriver
   3 *
   4 * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 */
  20
  21#define MODULE_NAME "stk014"
  22
  23#include "gspca.h"
  24#include "jpeg.h"
  25
  26MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
  27MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
  28MODULE_LICENSE("GPL");
  29
  30/* specific webcam descriptor */
  31struct sd {
  32        struct gspca_dev gspca_dev;     /* !! must be the first item */
  33
  34        unsigned char brightness;
  35        unsigned char contrast;
  36        unsigned char colors;
  37        unsigned char lightfreq;
  38        u8 quality;
  39#define QUALITY_MIN 60
  40#define QUALITY_MAX 95
  41#define QUALITY_DEF 80
  42
  43        u8 *jpeg_hdr;
  44};
  45
  46/* V4L2 controls supported by the driver */
  47static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
  48static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
  49static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
  50static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
  51static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
  52static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
  53static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
  54static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
  55
  56static struct ctrl sd_ctrls[] = {
  57        {
  58            {
  59                .id      = V4L2_CID_BRIGHTNESS,
  60                .type    = V4L2_CTRL_TYPE_INTEGER,
  61                .name    = "Brightness",
  62                .minimum = 0,
  63                .maximum = 255,
  64                .step    = 1,
  65#define BRIGHTNESS_DEF 127
  66                .default_value = BRIGHTNESS_DEF,
  67            },
  68            .set = sd_setbrightness,
  69            .get = sd_getbrightness,
  70        },
  71        {
  72            {
  73                .id      = V4L2_CID_CONTRAST,
  74                .type    = V4L2_CTRL_TYPE_INTEGER,
  75                .name    = "Contrast",
  76                .minimum = 0,
  77                .maximum = 255,
  78                .step    = 1,
  79#define CONTRAST_DEF 127
  80                .default_value = CONTRAST_DEF,
  81            },
  82            .set = sd_setcontrast,
  83            .get = sd_getcontrast,
  84        },
  85        {
  86            {
  87                .id      = V4L2_CID_SATURATION,
  88                .type    = V4L2_CTRL_TYPE_INTEGER,
  89                .name    = "Color",
  90                .minimum = 0,
  91                .maximum = 255,
  92                .step    = 1,
  93#define COLOR_DEF 127
  94                .default_value = COLOR_DEF,
  95            },
  96            .set = sd_setcolors,
  97            .get = sd_getcolors,
  98        },
  99        {
 100            {
 101                .id      = V4L2_CID_POWER_LINE_FREQUENCY,
 102                .type    = V4L2_CTRL_TYPE_MENU,
 103                .name    = "Light frequency filter",
 104                .minimum = 1,
 105                .maximum = 2,   /* 0: 0, 1: 50Hz, 2:60Hz */
 106                .step    = 1,
 107#define FREQ_DEF 1
 108                .default_value = FREQ_DEF,
 109            },
 110            .set = sd_setfreq,
 111            .get = sd_getfreq,
 112        },
 113};
 114
 115static const struct v4l2_pix_format vga_mode[] = {
 116        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 117                .bytesperline = 320,
 118                .sizeimage = 320 * 240 * 3 / 8 + 590,
 119                .colorspace = V4L2_COLORSPACE_JPEG,
 120                .priv = 1},
 121        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 122                .bytesperline = 640,
 123                .sizeimage = 640 * 480 * 3 / 8 + 590,
 124                .colorspace = V4L2_COLORSPACE_JPEG,
 125                .priv = 0},
 126};
 127
 128/* -- read a register -- */
 129static int reg_r(struct gspca_dev *gspca_dev,
 130                        __u16 index)
 131{
 132        struct usb_device *dev = gspca_dev->dev;
 133        int ret;
 134
 135        ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 136                        0x00,
 137                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 138                        0x00,
 139                        index,
 140                        gspca_dev->usb_buf, 1,
 141                        500);
 142        if (ret < 0) {
 143                PDEBUG(D_ERR, "reg_r err %d", ret);
 144                return ret;
 145        }
 146        return gspca_dev->usb_buf[0];
 147}
 148
 149/* -- write a register -- */
 150static int reg_w(struct gspca_dev *gspca_dev,
 151                        __u16 index, __u16 value)
 152{
 153        struct usb_device *dev = gspca_dev->dev;
 154        int ret;
 155
 156        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 157                        0x01,
 158                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 159                        value,
 160                        index,
 161                        NULL,
 162                        0,
 163                        500);
 164        if (ret < 0)
 165                PDEBUG(D_ERR, "reg_w err %d", ret);
 166        return ret;
 167}
 168
 169/* -- get a bulk value (4 bytes) -- */
 170static int rcv_val(struct gspca_dev *gspca_dev,
 171                        int ads)
 172{
 173        struct usb_device *dev = gspca_dev->dev;
 174        int alen, ret;
 175
 176        reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
 177        reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
 178        reg_w(gspca_dev, 0x636, ads & 0xff);
 179        reg_w(gspca_dev, 0x637, 0);
 180        reg_w(gspca_dev, 0x638, 4);     /* len & 0xff */
 181        reg_w(gspca_dev, 0x639, 0);     /* len >> 8 */
 182        reg_w(gspca_dev, 0x63a, 0);
 183        reg_w(gspca_dev, 0x63b, 0);
 184        reg_w(gspca_dev, 0x630, 5);
 185        ret = usb_bulk_msg(dev,
 186                        usb_rcvbulkpipe(dev, 0x05),
 187                        gspca_dev->usb_buf,
 188                        4,              /* length */
 189                        &alen,
 190                        500);           /* timeout in milliseconds */
 191        return ret;
 192}
 193
 194/* -- send a bulk value -- */
 195static int snd_val(struct gspca_dev *gspca_dev,
 196                        int ads,
 197                        unsigned int val)
 198{
 199        struct usb_device *dev = gspca_dev->dev;
 200        int alen, ret;
 201        __u8 seq = 0;
 202
 203        if (ads == 0x003f08) {
 204                ret = reg_r(gspca_dev, 0x0704);
 205                if (ret < 0)
 206                        goto ko;
 207                ret = reg_r(gspca_dev, 0x0705);
 208                if (ret < 0)
 209                        goto ko;
 210                seq = ret;              /* keep the sequence number */
 211                ret = reg_r(gspca_dev, 0x0650);
 212                if (ret < 0)
 213                        goto ko;
 214                reg_w(gspca_dev, 0x654, seq);
 215        } else {
 216                reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
 217        }
 218        reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
 219        reg_w(gspca_dev, 0x656, ads & 0xff);
 220        reg_w(gspca_dev, 0x657, 0);
 221        reg_w(gspca_dev, 0x658, 0x04);  /* size */
 222        reg_w(gspca_dev, 0x659, 0);
 223        reg_w(gspca_dev, 0x65a, 0);
 224        reg_w(gspca_dev, 0x65b, 0);
 225        reg_w(gspca_dev, 0x650, 5);
 226        gspca_dev->usb_buf[0] = val >> 24;
 227        gspca_dev->usb_buf[1] = val >> 16;
 228        gspca_dev->usb_buf[2] = val >> 8;
 229        gspca_dev->usb_buf[3] = val;
 230        ret = usb_bulk_msg(dev,
 231                        usb_sndbulkpipe(dev, 6),
 232                        gspca_dev->usb_buf,
 233                        4,
 234                        &alen,
 235                        500);   /* timeout in milliseconds */
 236        if (ret < 0)
 237                goto ko;
 238        if (ads == 0x003f08) {
 239                seq += 4;
 240                seq &= 0x3f;
 241                reg_w(gspca_dev, 0x705, seq);
 242        }
 243        return ret;
 244ko:
 245        PDEBUG(D_ERR, "snd_val err %d", ret);
 246        return ret;
 247}
 248
 249/* set a camera parameter */
 250static int set_par(struct gspca_dev *gspca_dev,
 251                   int parval)
 252{
 253        return snd_val(gspca_dev, 0x003f08, parval);
 254}
 255
 256static void setbrightness(struct gspca_dev *gspca_dev)
 257{
 258        struct sd *sd = (struct sd *) gspca_dev;
 259        int parval;
 260
 261        parval = 0x06000000             /* whiteness */
 262                + (sd->brightness << 16);
 263        set_par(gspca_dev, parval);
 264}
 265
 266static void setcontrast(struct gspca_dev *gspca_dev)
 267{
 268        struct sd *sd = (struct sd *) gspca_dev;
 269        int parval;
 270
 271        parval = 0x07000000             /* contrast */
 272                + (sd->contrast << 16);
 273        set_par(gspca_dev, parval);
 274}
 275
 276static void setcolors(struct gspca_dev *gspca_dev)
 277{
 278        struct sd *sd = (struct sd *) gspca_dev;
 279        int parval;
 280
 281        parval = 0x08000000             /* saturation */
 282                + (sd->colors << 16);
 283        set_par(gspca_dev, parval);
 284}
 285
 286static void setfreq(struct gspca_dev *gspca_dev)
 287{
 288        struct sd *sd = (struct sd *) gspca_dev;
 289
 290        set_par(gspca_dev, sd->lightfreq == 1
 291                        ? 0x33640000            /* 50 Hz */
 292                        : 0x33780000);          /* 60 Hz */
 293}
 294
 295/* this function is called at probe time */
 296static int sd_config(struct gspca_dev *gspca_dev,
 297                        const struct usb_device_id *id)
 298{
 299        struct sd *sd = (struct sd *) gspca_dev;
 300
 301        gspca_dev->cam.cam_mode = vga_mode;
 302        gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
 303        sd->brightness = BRIGHTNESS_DEF;
 304        sd->contrast = CONTRAST_DEF;
 305        sd->colors = COLOR_DEF;
 306        sd->lightfreq = FREQ_DEF;
 307        sd->quality = QUALITY_DEF;
 308        return 0;
 309}
 310
 311/* this function is called at probe and resume time */
 312static int sd_init(struct gspca_dev *gspca_dev)
 313{
 314        int ret;
 315
 316        /* check if the device responds */
 317        usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 318        ret = reg_r(gspca_dev, 0x0740);
 319        if (ret < 0)
 320                return ret;
 321        if (ret != 0xff) {
 322                PDEBUG(D_ERR|D_STREAM, "init reg: 0x%02x", ret);
 323                return -1;
 324        }
 325        return 0;
 326}
 327
 328/* -- start the camera -- */
 329static int sd_start(struct gspca_dev *gspca_dev)
 330{
 331        struct sd *sd = (struct sd *) gspca_dev;
 332        int ret, value;
 333
 334        /* create the JPEG header */
 335        sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
 336        if (!sd->jpeg_hdr)
 337                return -ENOMEM;
 338        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 339                        0x22);          /* JPEG 411 */
 340        jpeg_set_qual(sd->jpeg_hdr, sd->quality);
 341
 342        /* work on alternate 1 */
 343        usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 344
 345        set_par(gspca_dev, 0x10000000);
 346        set_par(gspca_dev, 0x00000000);
 347        set_par(gspca_dev, 0x8002e001);
 348        set_par(gspca_dev, 0x14000000);
 349        if (gspca_dev->width > 320)
 350                value = 0x8002e001;             /* 640x480 */
 351        else
 352                value = 0x4001f000;             /* 320x240 */
 353        set_par(gspca_dev, value);
 354        ret = usb_set_interface(gspca_dev->dev,
 355                                        gspca_dev->iface,
 356                                        gspca_dev->alt);
 357        if (ret < 0) {
 358                PDEBUG(D_ERR|D_STREAM, "set intf %d %d failed",
 359                        gspca_dev->iface, gspca_dev->alt);
 360                goto out;
 361        }
 362        ret = reg_r(gspca_dev, 0x0630);
 363        if (ret < 0)
 364                goto out;
 365        rcv_val(gspca_dev, 0x000020);   /* << (value ff ff ff ff) */
 366        ret = reg_r(gspca_dev, 0x0650);
 367        if (ret < 0)
 368                goto out;
 369        snd_val(gspca_dev, 0x000020, 0xffffffff);
 370        reg_w(gspca_dev, 0x0620, 0);
 371        reg_w(gspca_dev, 0x0630, 0);
 372        reg_w(gspca_dev, 0x0640, 0);
 373        reg_w(gspca_dev, 0x0650, 0);
 374        reg_w(gspca_dev, 0x0660, 0);
 375        setbrightness(gspca_dev);               /* whiteness */
 376        setcontrast(gspca_dev);                 /* contrast */
 377        setcolors(gspca_dev);                   /* saturation */
 378        set_par(gspca_dev, 0x09800000);         /* Red ? */
 379        set_par(gspca_dev, 0x0a800000);         /* Green ? */
 380        set_par(gspca_dev, 0x0b800000);         /* Blue ? */
 381        set_par(gspca_dev, 0x0d030000);         /* Gamma ? */
 382        setfreq(gspca_dev);                     /* light frequency */
 383
 384        /* start the video flow */
 385        set_par(gspca_dev, 0x01000000);
 386        set_par(gspca_dev, 0x01000000);
 387        PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
 388        return 0;
 389out:
 390        PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret);
 391        return ret;
 392}
 393
 394static void sd_stopN(struct gspca_dev *gspca_dev)
 395{
 396        struct usb_device *dev = gspca_dev->dev;
 397
 398        set_par(gspca_dev, 0x02000000);
 399        set_par(gspca_dev, 0x02000000);
 400        usb_set_interface(dev, gspca_dev->iface, 1);
 401        reg_r(gspca_dev, 0x0630);
 402        rcv_val(gspca_dev, 0x000020);   /* << (value ff ff ff ff) */
 403        reg_r(gspca_dev, 0x0650);
 404        snd_val(gspca_dev, 0x000020, 0xffffffff);
 405        reg_w(gspca_dev, 0x0620, 0);
 406        reg_w(gspca_dev, 0x0630, 0);
 407        reg_w(gspca_dev, 0x0640, 0);
 408        reg_w(gspca_dev, 0x0650, 0);
 409        reg_w(gspca_dev, 0x0660, 0);
 410        PDEBUG(D_STREAM, "camera stopped");
 411}
 412
 413static void sd_stop0(struct gspca_dev *gspca_dev)
 414{
 415        struct sd *sd = (struct sd *) gspca_dev;
 416
 417        kfree(sd->jpeg_hdr);
 418}
 419
 420static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 421                        struct gspca_frame *frame,      /* target */
 422                        __u8 *data,                     /* isoc packet */
 423                        int len)                        /* iso packet length */
 424{
 425        struct sd *sd = (struct sd *) gspca_dev;
 426        static unsigned char ffd9[] = {0xff, 0xd9};
 427
 428        /* a frame starts with:
 429         *      - 0xff 0xfe
 430         *      - 0x08 0x00     - length (little endian ?!)
 431         *      - 4 bytes = size of whole frame (BE - including header)
 432         *      - 0x00 0x0c
 433         *      - 0xff 0xd8
 434         *      - ..    JPEG image with escape sequences (ff 00)
 435         *              (without ending - ff d9)
 436         */
 437        if (data[0] == 0xff && data[1] == 0xfe) {
 438                frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
 439                                        ffd9, 2);
 440
 441                /* put the JPEG 411 header */
 442                gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
 443                        sd->jpeg_hdr, JPEG_HDR_SZ);
 444
 445                /* beginning of the frame */
 446#define STKHDRSZ 12
 447                data += STKHDRSZ;
 448                len -= STKHDRSZ;
 449        }
 450        gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 451}
 452
 453static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 454{
 455        struct sd *sd = (struct sd *) gspca_dev;
 456
 457        sd->brightness = val;
 458        if (gspca_dev->streaming)
 459                setbrightness(gspca_dev);
 460        return 0;
 461}
 462
 463static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
 464{
 465        struct sd *sd = (struct sd *) gspca_dev;
 466
 467        *val = sd->brightness;
 468        return 0;
 469}
 470
 471static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
 472{
 473        struct sd *sd = (struct sd *) gspca_dev;
 474
 475        sd->contrast = val;
 476        if (gspca_dev->streaming)
 477                setcontrast(gspca_dev);
 478        return 0;
 479}
 480
 481static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
 482{
 483        struct sd *sd = (struct sd *) gspca_dev;
 484
 485        *val = sd->contrast;
 486        return 0;
 487}
 488
 489static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
 490{
 491        struct sd *sd = (struct sd *) gspca_dev;
 492
 493        sd->colors = val;
 494        if (gspca_dev->streaming)
 495                setcolors(gspca_dev);
 496        return 0;
 497}
 498
 499static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
 500{
 501        struct sd *sd = (struct sd *) gspca_dev;
 502
 503        *val = sd->colors;
 504        return 0;
 505}
 506
 507static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
 508{
 509        struct sd *sd = (struct sd *) gspca_dev;
 510
 511        sd->lightfreq = val;
 512        if (gspca_dev->streaming)
 513                setfreq(gspca_dev);
 514        return 0;
 515}
 516
 517static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
 518{
 519        struct sd *sd = (struct sd *) gspca_dev;
 520
 521        *val = sd->lightfreq;
 522        return 0;
 523}
 524
 525static int sd_querymenu(struct gspca_dev *gspca_dev,
 526                        struct v4l2_querymenu *menu)
 527{
 528        switch (menu->id) {
 529        case V4L2_CID_POWER_LINE_FREQUENCY:
 530                switch (menu->index) {
 531                case 1:         /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
 532                        strcpy((char *) menu->name, "50 Hz");
 533                        return 0;
 534                case 2:         /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
 535                        strcpy((char *) menu->name, "60 Hz");
 536                        return 0;
 537                }
 538                break;
 539        }
 540        return -EINVAL;
 541}
 542
 543static int sd_set_jcomp(struct gspca_dev *gspca_dev,
 544                        struct v4l2_jpegcompression *jcomp)
 545{
 546        struct sd *sd = (struct sd *) gspca_dev;
 547
 548        if (jcomp->quality < QUALITY_MIN)
 549                sd->quality = QUALITY_MIN;
 550        else if (jcomp->quality > QUALITY_MAX)
 551                sd->quality = QUALITY_MAX;
 552        else
 553                sd->quality = jcomp->quality;
 554        if (gspca_dev->streaming)
 555                jpeg_set_qual(sd->jpeg_hdr, sd->quality);
 556        return 0;
 557}
 558
 559static int sd_get_jcomp(struct gspca_dev *gspca_dev,
 560                        struct v4l2_jpegcompression *jcomp)
 561{
 562        struct sd *sd = (struct sd *) gspca_dev;
 563
 564        memset(jcomp, 0, sizeof *jcomp);
 565        jcomp->quality = sd->quality;
 566        jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
 567                        | V4L2_JPEG_MARKER_DQT;
 568        return 0;
 569}
 570
 571/* sub-driver description */
 572static const struct sd_desc sd_desc = {
 573        .name = MODULE_NAME,
 574        .ctrls = sd_ctrls,
 575        .nctrls = ARRAY_SIZE(sd_ctrls),
 576        .config = sd_config,
 577        .init = sd_init,
 578        .start = sd_start,
 579        .stopN = sd_stopN,
 580        .stop0 = sd_stop0,
 581        .pkt_scan = sd_pkt_scan,
 582        .querymenu = sd_querymenu,
 583        .get_jcomp = sd_get_jcomp,
 584        .set_jcomp = sd_set_jcomp,
 585};
 586
 587/* -- module initialisation -- */
 588static const __devinitdata struct usb_device_id device_table[] = {
 589        {USB_DEVICE(0x05e1, 0x0893)},
 590        {}
 591};
 592MODULE_DEVICE_TABLE(usb, device_table);
 593
 594/* -- device connect -- */
 595static int sd_probe(struct usb_interface *intf,
 596                        const struct usb_device_id *id)
 597{
 598        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 599                                THIS_MODULE);
 600}
 601
 602static struct usb_driver sd_driver = {
 603        .name = MODULE_NAME,
 604        .id_table = device_table,
 605        .probe = sd_probe,
 606        .disconnect = gspca_disconnect,
 607#ifdef CONFIG_PM
 608        .suspend = gspca_suspend,
 609        .resume = gspca_resume,
 610#endif
 611};
 612
 613/* -- module insert / remove -- */
 614static int __init sd_mod_init(void)
 615{
 616        int ret;
 617        ret = usb_register(&sd_driver);
 618        if (ret < 0)
 619                return ret;
 620        info("registered");
 621        return 0;
 622}
 623static void __exit sd_mod_exit(void)
 624{
 625        usb_deregister(&sd_driver);
 626        info("deregistered");
 627}
 628
 629module_init(sd_mod_init);
 630module_exit(sd_mod_exit);
 631