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/* controls */
  31enum e_ctrl {
  32        BRIGHTNESS,
  33        CONTRAST,
  34        COLORS,
  35        LIGHTFREQ,
  36        NCTRLS          /* number of controls */
  37};
  38
  39/* specific webcam descriptor */
  40struct sd {
  41        struct gspca_dev gspca_dev;     /* !! must be the first item */
  42
  43        struct gspca_ctrl ctrls[NCTRLS];
  44
  45        u8 quality;
  46#define QUALITY_MIN 70
  47#define QUALITY_MAX 95
  48#define QUALITY_DEF 88
  49
  50        u8 jpeg_hdr[JPEG_HDR_SZ];
  51};
  52
  53/* V4L2 controls supported by the driver */
  54static void setbrightness(struct gspca_dev *gspca_dev);
  55static void setcontrast(struct gspca_dev *gspca_dev);
  56static void setcolors(struct gspca_dev *gspca_dev);
  57static void setlightfreq(struct gspca_dev *gspca_dev);
  58
  59static const struct ctrl sd_ctrls[NCTRLS] = {
  60[BRIGHTNESS] = {
  61            {
  62                .id      = V4L2_CID_BRIGHTNESS,
  63                .type    = V4L2_CTRL_TYPE_INTEGER,
  64                .name    = "Brightness",
  65                .minimum = 0,
  66                .maximum = 255,
  67                .step    = 1,
  68                .default_value = 127,
  69            },
  70            .set_control = setbrightness
  71        },
  72[CONTRAST] = {
  73            {
  74                .id      = V4L2_CID_CONTRAST,
  75                .type    = V4L2_CTRL_TYPE_INTEGER,
  76                .name    = "Contrast",
  77                .minimum = 0,
  78                .maximum = 255,
  79                .step    = 1,
  80                .default_value = 127,
  81            },
  82            .set_control = setcontrast
  83        },
  84[COLORS] = {
  85            {
  86                .id      = V4L2_CID_SATURATION,
  87                .type    = V4L2_CTRL_TYPE_INTEGER,
  88                .name    = "Color",
  89                .minimum = 0,
  90                .maximum = 255,
  91                .step    = 1,
  92                .default_value = 127,
  93            },
  94            .set_control = setcolors
  95        },
  96[LIGHTFREQ] = {
  97            {
  98                .id      = V4L2_CID_POWER_LINE_FREQUENCY,
  99                .type    = V4L2_CTRL_TYPE_MENU,
 100                .name    = "Light frequency filter",
 101                .minimum = 1,
 102                .maximum = 2,   /* 0: 0, 1: 50Hz, 2:60Hz */
 103                .step    = 1,
 104                .default_value = 1,
 105            },
 106            .set_control = setlightfreq
 107        },
 108};
 109
 110static const struct v4l2_pix_format vga_mode[] = {
 111        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 112                .bytesperline = 320,
 113                .sizeimage = 320 * 240 * 3 / 8 + 590,
 114                .colorspace = V4L2_COLORSPACE_JPEG,
 115                .priv = 1},
 116        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 117                .bytesperline = 640,
 118                .sizeimage = 640 * 480 * 3 / 8 + 590,
 119                .colorspace = V4L2_COLORSPACE_JPEG,
 120                .priv = 0},
 121};
 122
 123/* -- read a register -- */
 124static u8 reg_r(struct gspca_dev *gspca_dev,
 125                        __u16 index)
 126{
 127        struct usb_device *dev = gspca_dev->dev;
 128        int ret;
 129
 130        if (gspca_dev->usb_err < 0)
 131                return 0;
 132        ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 133                        0x00,
 134                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 135                        0x00,
 136                        index,
 137                        gspca_dev->usb_buf, 1,
 138                        500);
 139        if (ret < 0) {
 140                err("reg_r err %d", ret);
 141                gspca_dev->usb_err = ret;
 142                return 0;
 143        }
 144        return gspca_dev->usb_buf[0];
 145}
 146
 147/* -- write a register -- */
 148static void reg_w(struct gspca_dev *gspca_dev,
 149                        __u16 index, __u16 value)
 150{
 151        struct usb_device *dev = gspca_dev->dev;
 152        int ret;
 153
 154        if (gspca_dev->usb_err < 0)
 155                return;
 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                err("reg_w err %d", ret);
 166                gspca_dev->usb_err = ret;
 167        }
 168}
 169
 170/* -- get a bulk value (4 bytes) -- */
 171static void rcv_val(struct gspca_dev *gspca_dev,
 172                        int ads)
 173{
 174        struct usb_device *dev = gspca_dev->dev;
 175        int alen, ret;
 176
 177        reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
 178        reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
 179        reg_w(gspca_dev, 0x636, ads & 0xff);
 180        reg_w(gspca_dev, 0x637, 0);
 181        reg_w(gspca_dev, 0x638, 4);     /* len & 0xff */
 182        reg_w(gspca_dev, 0x639, 0);     /* len >> 8 */
 183        reg_w(gspca_dev, 0x63a, 0);
 184        reg_w(gspca_dev, 0x63b, 0);
 185        reg_w(gspca_dev, 0x630, 5);
 186        if (gspca_dev->usb_err < 0)
 187                return;
 188        ret = usb_bulk_msg(dev,
 189                        usb_rcvbulkpipe(dev, 0x05),
 190                        gspca_dev->usb_buf,
 191                        4,              /* length */
 192                        &alen,
 193                        500);           /* timeout in milliseconds */
 194        if (ret < 0) {
 195                err("rcv_val err %d", ret);
 196                gspca_dev->usb_err = ret;
 197        }
 198}
 199
 200/* -- send a bulk value -- */
 201static void snd_val(struct gspca_dev *gspca_dev,
 202                        int ads,
 203                        unsigned int val)
 204{
 205        struct usb_device *dev = gspca_dev->dev;
 206        int alen, ret;
 207        __u8 seq = 0;
 208
 209        if (ads == 0x003f08) {
 210                reg_r(gspca_dev, 0x0704);
 211                seq = reg_r(gspca_dev, 0x0705);
 212                reg_r(gspca_dev, 0x0650);
 213                reg_w(gspca_dev, 0x654, seq);
 214        } else {
 215                reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
 216        }
 217        reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
 218        reg_w(gspca_dev, 0x656, ads & 0xff);
 219        reg_w(gspca_dev, 0x657, 0);
 220        reg_w(gspca_dev, 0x658, 0x04);  /* size */
 221        reg_w(gspca_dev, 0x659, 0);
 222        reg_w(gspca_dev, 0x65a, 0);
 223        reg_w(gspca_dev, 0x65b, 0);
 224        reg_w(gspca_dev, 0x650, 5);
 225        if (gspca_dev->usb_err < 0)
 226                return;
 227        gspca_dev->usb_buf[0] = val >> 24;
 228        gspca_dev->usb_buf[1] = val >> 16;
 229        gspca_dev->usb_buf[2] = val >> 8;
 230        gspca_dev->usb_buf[3] = val;
 231        ret = usb_bulk_msg(dev,
 232                        usb_sndbulkpipe(dev, 6),
 233                        gspca_dev->usb_buf,
 234                        4,
 235                        &alen,
 236                        500);   /* timeout in milliseconds */
 237        if (ret < 0) {
 238                err("snd_val err %d", ret);
 239                gspca_dev->usb_err = ret;
 240        } else {
 241                if (ads == 0x003f08) {
 242                        seq += 4;
 243                        seq &= 0x3f;
 244                        reg_w(gspca_dev, 0x705, seq);
 245                }
 246        }
 247}
 248
 249/* set a camera parameter */
 250static void set_par(struct gspca_dev *gspca_dev,
 251                   int parval)
 252{
 253        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->ctrls[BRIGHTNESS].val << 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->ctrls[CONTRAST].val << 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->ctrls[COLORS].val << 16);
 283        set_par(gspca_dev, parval);
 284}
 285
 286static void setlightfreq(struct gspca_dev *gspca_dev)
 287{
 288        struct sd *sd = (struct sd *) gspca_dev;
 289
 290        set_par(gspca_dev, sd->ctrls[LIGHTFREQ].val == 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        gspca_dev->cam.ctrls = sd->ctrls;
 304        sd->quality = QUALITY_DEF;
 305        return 0;
 306}
 307
 308/* this function is called at probe and resume time */
 309static int sd_init(struct gspca_dev *gspca_dev)
 310{
 311        u8 ret;
 312
 313        /* check if the device responds */
 314        usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 315        ret = reg_r(gspca_dev, 0x0740);
 316        if (gspca_dev->usb_err >= 0) {
 317                if (ret != 0xff) {
 318                        err("init reg: 0x%02x", ret);
 319                        gspca_dev->usb_err = -EIO;
 320                }
 321        }
 322        return gspca_dev->usb_err;
 323}
 324
 325/* -- start the camera -- */
 326static int sd_start(struct gspca_dev *gspca_dev)
 327{
 328        struct sd *sd = (struct sd *) gspca_dev;
 329        int ret, value;
 330
 331        /* create the JPEG header */
 332        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 333                        0x22);          /* JPEG 411 */
 334        jpeg_set_qual(sd->jpeg_hdr, sd->quality);
 335
 336        /* work on alternate 1 */
 337        usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 338
 339        set_par(gspca_dev, 0x10000000);
 340        set_par(gspca_dev, 0x00000000);
 341        set_par(gspca_dev, 0x8002e001);
 342        set_par(gspca_dev, 0x14000000);
 343        if (gspca_dev->width > 320)
 344                value = 0x8002e001;             /* 640x480 */
 345        else
 346                value = 0x4001f000;             /* 320x240 */
 347        set_par(gspca_dev, value);
 348        ret = usb_set_interface(gspca_dev->dev,
 349                                        gspca_dev->iface,
 350                                        gspca_dev->alt);
 351        if (ret < 0) {
 352                err("set intf %d %d failed",
 353                        gspca_dev->iface, gspca_dev->alt);
 354                gspca_dev->usb_err = ret;
 355                goto out;
 356        }
 357         reg_r(gspca_dev, 0x0630);
 358        rcv_val(gspca_dev, 0x000020);   /* << (value ff ff ff ff) */
 359        reg_r(gspca_dev, 0x0650);
 360        snd_val(gspca_dev, 0x000020, 0xffffffff);
 361        reg_w(gspca_dev, 0x0620, 0);
 362        reg_w(gspca_dev, 0x0630, 0);
 363        reg_w(gspca_dev, 0x0640, 0);
 364        reg_w(gspca_dev, 0x0650, 0);
 365        reg_w(gspca_dev, 0x0660, 0);
 366        setbrightness(gspca_dev);               /* whiteness */
 367        setcontrast(gspca_dev);                 /* contrast */
 368        setcolors(gspca_dev);                   /* saturation */
 369        set_par(gspca_dev, 0x09800000);         /* Red ? */
 370        set_par(gspca_dev, 0x0a800000);         /* Green ? */
 371        set_par(gspca_dev, 0x0b800000);         /* Blue ? */
 372        set_par(gspca_dev, 0x0d030000);         /* Gamma ? */
 373        setlightfreq(gspca_dev);
 374
 375        /* start the video flow */
 376        set_par(gspca_dev, 0x01000000);
 377        set_par(gspca_dev, 0x01000000);
 378        if (gspca_dev->usb_err >= 0)
 379                PDEBUG(D_STREAM, "camera started alt: 0x%02x",
 380                                gspca_dev->alt);
 381out:
 382        return gspca_dev->usb_err;
 383}
 384
 385static void sd_stopN(struct gspca_dev *gspca_dev)
 386{
 387        struct usb_device *dev = gspca_dev->dev;
 388
 389        set_par(gspca_dev, 0x02000000);
 390        set_par(gspca_dev, 0x02000000);
 391        usb_set_interface(dev, gspca_dev->iface, 1);
 392        reg_r(gspca_dev, 0x0630);
 393        rcv_val(gspca_dev, 0x000020);   /* << (value ff ff ff ff) */
 394        reg_r(gspca_dev, 0x0650);
 395        snd_val(gspca_dev, 0x000020, 0xffffffff);
 396        reg_w(gspca_dev, 0x0620, 0);
 397        reg_w(gspca_dev, 0x0630, 0);
 398        reg_w(gspca_dev, 0x0640, 0);
 399        reg_w(gspca_dev, 0x0650, 0);
 400        reg_w(gspca_dev, 0x0660, 0);
 401        PDEBUG(D_STREAM, "camera stopped");
 402}
 403
 404static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 405                        u8 *data,                       /* isoc packet */
 406                        int len)                        /* iso packet length */
 407{
 408        struct sd *sd = (struct sd *) gspca_dev;
 409        static unsigned char ffd9[] = {0xff, 0xd9};
 410
 411        /* a frame starts with:
 412         *      - 0xff 0xfe
 413         *      - 0x08 0x00     - length (little endian ?!)
 414         *      - 4 bytes = size of whole frame (BE - including header)
 415         *      - 0x00 0x0c
 416         *      - 0xff 0xd8
 417         *      - ..    JPEG image with escape sequences (ff 00)
 418         *              (without ending - ff d9)
 419         */
 420        if (data[0] == 0xff && data[1] == 0xfe) {
 421                gspca_frame_add(gspca_dev, LAST_PACKET,
 422                                ffd9, 2);
 423
 424                /* put the JPEG 411 header */
 425                gspca_frame_add(gspca_dev, FIRST_PACKET,
 426                        sd->jpeg_hdr, JPEG_HDR_SZ);
 427
 428                /* beginning of the frame */
 429#define STKHDRSZ 12
 430                data += STKHDRSZ;
 431                len -= STKHDRSZ;
 432        }
 433        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 434}
 435
 436static int sd_querymenu(struct gspca_dev *gspca_dev,
 437                        struct v4l2_querymenu *menu)
 438{
 439        switch (menu->id) {
 440        case V4L2_CID_POWER_LINE_FREQUENCY:
 441                switch (menu->index) {
 442                case 1:         /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
 443                        strcpy((char *) menu->name, "50 Hz");
 444                        return 0;
 445                case 2:         /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
 446                        strcpy((char *) menu->name, "60 Hz");
 447                        return 0;
 448                }
 449                break;
 450        }
 451        return -EINVAL;
 452}
 453
 454static int sd_set_jcomp(struct gspca_dev *gspca_dev,
 455                        struct v4l2_jpegcompression *jcomp)
 456{
 457        struct sd *sd = (struct sd *) gspca_dev;
 458
 459        if (jcomp->quality < QUALITY_MIN)
 460                sd->quality = QUALITY_MIN;
 461        else if (jcomp->quality > QUALITY_MAX)
 462                sd->quality = QUALITY_MAX;
 463        else
 464                sd->quality = jcomp->quality;
 465        if (gspca_dev->streaming)
 466                jpeg_set_qual(sd->jpeg_hdr, sd->quality);
 467        return gspca_dev->usb_err;
 468}
 469
 470static int sd_get_jcomp(struct gspca_dev *gspca_dev,
 471                        struct v4l2_jpegcompression *jcomp)
 472{
 473        struct sd *sd = (struct sd *) gspca_dev;
 474
 475        memset(jcomp, 0, sizeof *jcomp);
 476        jcomp->quality = sd->quality;
 477        jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
 478                        | V4L2_JPEG_MARKER_DQT;
 479        return 0;
 480}
 481
 482/* sub-driver description */
 483static const struct sd_desc sd_desc = {
 484        .name = MODULE_NAME,
 485        .ctrls = sd_ctrls,
 486        .nctrls = NCTRLS,
 487        .config = sd_config,
 488        .init = sd_init,
 489        .start = sd_start,
 490        .stopN = sd_stopN,
 491        .pkt_scan = sd_pkt_scan,
 492        .querymenu = sd_querymenu,
 493        .get_jcomp = sd_get_jcomp,
 494        .set_jcomp = sd_set_jcomp,
 495};
 496
 497/* -- module initialisation -- */
 498static const struct usb_device_id device_table[] = {
 499        {USB_DEVICE(0x05e1, 0x0893)},
 500        {}
 501};
 502MODULE_DEVICE_TABLE(usb, device_table);
 503
 504/* -- device connect -- */
 505static int sd_probe(struct usb_interface *intf,
 506                        const struct usb_device_id *id)
 507{
 508        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 509                                THIS_MODULE);
 510}
 511
 512static struct usb_driver sd_driver = {
 513        .name = MODULE_NAME,
 514        .id_table = device_table,
 515        .probe = sd_probe,
 516        .disconnect = gspca_disconnect,
 517#ifdef CONFIG_PM
 518        .suspend = gspca_suspend,
 519        .resume = gspca_resume,
 520#endif
 521};
 522
 523/* -- module insert / remove -- */
 524static int __init sd_mod_init(void)
 525{
 526        return usb_register(&sd_driver);
 527}
 528static void __exit sd_mod_exit(void)
 529{
 530        usb_deregister(&sd_driver);
 531}
 532
 533module_init(sd_mod_init);
 534module_exit(sd_mod_exit);
 535