linux/drivers/media/usb/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
  17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  18
  19#define MODULE_NAME "stk014"
  20
  21#include "gspca.h"
  22#include "jpeg.h"
  23
  24MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
  25MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
  26MODULE_LICENSE("GPL");
  27
  28#define QUALITY 50
  29
  30/* specific webcam descriptor */
  31struct sd {
  32        struct gspca_dev gspca_dev;     /* !! must be the first item */
  33        u8 jpeg_hdr[JPEG_HDR_SZ];
  34};
  35
  36static const struct v4l2_pix_format vga_mode[] = {
  37        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  38                .bytesperline = 320,
  39                .sizeimage = 320 * 240 * 3 / 8 + 590,
  40                .colorspace = V4L2_COLORSPACE_JPEG,
  41                .priv = 1},
  42        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  43                .bytesperline = 640,
  44                .sizeimage = 640 * 480 * 3 / 8 + 590,
  45                .colorspace = V4L2_COLORSPACE_JPEG,
  46                .priv = 0},
  47};
  48
  49/* -- read a register -- */
  50static u8 reg_r(struct gspca_dev *gspca_dev,
  51                        __u16 index)
  52{
  53        struct usb_device *dev = gspca_dev->dev;
  54        int ret;
  55
  56        if (gspca_dev->usb_err < 0)
  57                return 0;
  58        ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  59                        0x00,
  60                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  61                        0x00,
  62                        index,
  63                        gspca_dev->usb_buf, 1,
  64                        500);
  65        if (ret < 0) {
  66                pr_err("reg_r err %d\n", ret);
  67                gspca_dev->usb_err = ret;
  68                return 0;
  69        }
  70        return gspca_dev->usb_buf[0];
  71}
  72
  73/* -- write a register -- */
  74static void reg_w(struct gspca_dev *gspca_dev,
  75                        __u16 index, __u16 value)
  76{
  77        struct usb_device *dev = gspca_dev->dev;
  78        int ret;
  79
  80        if (gspca_dev->usb_err < 0)
  81                return;
  82        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
  83                        0x01,
  84                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  85                        value,
  86                        index,
  87                        NULL,
  88                        0,
  89                        500);
  90        if (ret < 0) {
  91                pr_err("reg_w err %d\n", ret);
  92                gspca_dev->usb_err = ret;
  93        }
  94}
  95
  96/* -- get a bulk value (4 bytes) -- */
  97static void rcv_val(struct gspca_dev *gspca_dev,
  98                        int ads)
  99{
 100        struct usb_device *dev = gspca_dev->dev;
 101        int alen, ret;
 102
 103        reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
 104        reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
 105        reg_w(gspca_dev, 0x636, ads & 0xff);
 106        reg_w(gspca_dev, 0x637, 0);
 107        reg_w(gspca_dev, 0x638, 4);     /* len & 0xff */
 108        reg_w(gspca_dev, 0x639, 0);     /* len >> 8 */
 109        reg_w(gspca_dev, 0x63a, 0);
 110        reg_w(gspca_dev, 0x63b, 0);
 111        reg_w(gspca_dev, 0x630, 5);
 112        if (gspca_dev->usb_err < 0)
 113                return;
 114        ret = usb_bulk_msg(dev,
 115                        usb_rcvbulkpipe(dev, 0x05),
 116                        gspca_dev->usb_buf,
 117                        4,              /* length */
 118                        &alen,
 119                        500);           /* timeout in milliseconds */
 120        if (ret < 0) {
 121                pr_err("rcv_val err %d\n", ret);
 122                gspca_dev->usb_err = ret;
 123        }
 124}
 125
 126/* -- send a bulk value -- */
 127static void snd_val(struct gspca_dev *gspca_dev,
 128                        int ads,
 129                        unsigned int val)
 130{
 131        struct usb_device *dev = gspca_dev->dev;
 132        int alen, ret;
 133        __u8 seq = 0;
 134
 135        if (ads == 0x003f08) {
 136                reg_r(gspca_dev, 0x0704);
 137                seq = reg_r(gspca_dev, 0x0705);
 138                reg_r(gspca_dev, 0x0650);
 139                reg_w(gspca_dev, 0x654, seq);
 140        } else {
 141                reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
 142        }
 143        reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
 144        reg_w(gspca_dev, 0x656, ads & 0xff);
 145        reg_w(gspca_dev, 0x657, 0);
 146        reg_w(gspca_dev, 0x658, 0x04);  /* size */
 147        reg_w(gspca_dev, 0x659, 0);
 148        reg_w(gspca_dev, 0x65a, 0);
 149        reg_w(gspca_dev, 0x65b, 0);
 150        reg_w(gspca_dev, 0x650, 5);
 151        if (gspca_dev->usb_err < 0)
 152                return;
 153        gspca_dev->usb_buf[0] = val >> 24;
 154        gspca_dev->usb_buf[1] = val >> 16;
 155        gspca_dev->usb_buf[2] = val >> 8;
 156        gspca_dev->usb_buf[3] = val;
 157        ret = usb_bulk_msg(dev,
 158                        usb_sndbulkpipe(dev, 6),
 159                        gspca_dev->usb_buf,
 160                        4,
 161                        &alen,
 162                        500);   /* timeout in milliseconds */
 163        if (ret < 0) {
 164                pr_err("snd_val err %d\n", ret);
 165                gspca_dev->usb_err = ret;
 166        } else {
 167                if (ads == 0x003f08) {
 168                        seq += 4;
 169                        seq &= 0x3f;
 170                        reg_w(gspca_dev, 0x705, seq);
 171                }
 172        }
 173}
 174
 175/* set a camera parameter */
 176static void set_par(struct gspca_dev *gspca_dev,
 177                   int parval)
 178{
 179        snd_val(gspca_dev, 0x003f08, parval);
 180}
 181
 182static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
 183{
 184        int parval;
 185
 186        parval = 0x06000000             /* whiteness */
 187                + (val << 16);
 188        set_par(gspca_dev, parval);
 189}
 190
 191static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
 192{
 193        int parval;
 194
 195        parval = 0x07000000             /* contrast */
 196                + (val << 16);
 197        set_par(gspca_dev, parval);
 198}
 199
 200static void setcolors(struct gspca_dev *gspca_dev, s32 val)
 201{
 202        int parval;
 203
 204        parval = 0x08000000             /* saturation */
 205                + (val << 16);
 206        set_par(gspca_dev, parval);
 207}
 208
 209static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
 210{
 211        set_par(gspca_dev, val == 1
 212                        ? 0x33640000            /* 50 Hz */
 213                        : 0x33780000);          /* 60 Hz */
 214}
 215
 216/* this function is called at probe time */
 217static int sd_config(struct gspca_dev *gspca_dev,
 218                        const struct usb_device_id *id)
 219{
 220        gspca_dev->cam.cam_mode = vga_mode;
 221        gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
 222        return 0;
 223}
 224
 225/* this function is called at probe and resume time */
 226static int sd_init(struct gspca_dev *gspca_dev)
 227{
 228        u8 ret;
 229
 230        /* check if the device responds */
 231        usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 232        ret = reg_r(gspca_dev, 0x0740);
 233        if (gspca_dev->usb_err >= 0) {
 234                if (ret != 0xff) {
 235                        pr_err("init reg: 0x%02x\n", ret);
 236                        gspca_dev->usb_err = -EIO;
 237                }
 238        }
 239        return gspca_dev->usb_err;
 240}
 241
 242/* -- start the camera -- */
 243static int sd_start(struct gspca_dev *gspca_dev)
 244{
 245        struct sd *sd = (struct sd *) gspca_dev;
 246        int ret, value;
 247
 248        /* create the JPEG header */
 249        jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
 250                        gspca_dev->pixfmt.width,
 251                        0x22);          /* JPEG 411 */
 252        jpeg_set_qual(sd->jpeg_hdr, QUALITY);
 253
 254        /* work on alternate 1 */
 255        usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 256
 257        set_par(gspca_dev, 0x10000000);
 258        set_par(gspca_dev, 0x00000000);
 259        set_par(gspca_dev, 0x8002e001);
 260        set_par(gspca_dev, 0x14000000);
 261        if (gspca_dev->pixfmt.width > 320)
 262                value = 0x8002e001;             /* 640x480 */
 263        else
 264                value = 0x4001f000;             /* 320x240 */
 265        set_par(gspca_dev, value);
 266        ret = usb_set_interface(gspca_dev->dev,
 267                                        gspca_dev->iface,
 268                                        gspca_dev->alt);
 269        if (ret < 0) {
 270                pr_err("set intf %d %d failed\n",
 271                       gspca_dev->iface, gspca_dev->alt);
 272                gspca_dev->usb_err = ret;
 273                goto out;
 274        }
 275        reg_r(gspca_dev, 0x0630);
 276        rcv_val(gspca_dev, 0x000020);   /* << (value ff ff ff ff) */
 277        reg_r(gspca_dev, 0x0650);
 278        snd_val(gspca_dev, 0x000020, 0xffffffff);
 279        reg_w(gspca_dev, 0x0620, 0);
 280        reg_w(gspca_dev, 0x0630, 0);
 281        reg_w(gspca_dev, 0x0640, 0);
 282        reg_w(gspca_dev, 0x0650, 0);
 283        reg_w(gspca_dev, 0x0660, 0);
 284        set_par(gspca_dev, 0x09800000);         /* Red ? */
 285        set_par(gspca_dev, 0x0a800000);         /* Green ? */
 286        set_par(gspca_dev, 0x0b800000);         /* Blue ? */
 287        set_par(gspca_dev, 0x0d030000);         /* Gamma ? */
 288
 289        /* start the video flow */
 290        set_par(gspca_dev, 0x01000000);
 291        set_par(gspca_dev, 0x01000000);
 292        if (gspca_dev->usb_err >= 0)
 293                PDEBUG(D_STREAM, "camera started alt: 0x%02x",
 294                                gspca_dev->alt);
 295out:
 296        return gspca_dev->usb_err;
 297}
 298
 299static void sd_stopN(struct gspca_dev *gspca_dev)
 300{
 301        struct usb_device *dev = gspca_dev->dev;
 302
 303        set_par(gspca_dev, 0x02000000);
 304        set_par(gspca_dev, 0x02000000);
 305        usb_set_interface(dev, gspca_dev->iface, 1);
 306        reg_r(gspca_dev, 0x0630);
 307        rcv_val(gspca_dev, 0x000020);   /* << (value ff ff ff ff) */
 308        reg_r(gspca_dev, 0x0650);
 309        snd_val(gspca_dev, 0x000020, 0xffffffff);
 310        reg_w(gspca_dev, 0x0620, 0);
 311        reg_w(gspca_dev, 0x0630, 0);
 312        reg_w(gspca_dev, 0x0640, 0);
 313        reg_w(gspca_dev, 0x0650, 0);
 314        reg_w(gspca_dev, 0x0660, 0);
 315        PDEBUG(D_STREAM, "camera stopped");
 316}
 317
 318static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 319                        u8 *data,                       /* isoc packet */
 320                        int len)                        /* iso packet length */
 321{
 322        struct sd *sd = (struct sd *) gspca_dev;
 323        static unsigned char ffd9[] = {0xff, 0xd9};
 324
 325        /* a frame starts with:
 326         *      - 0xff 0xfe
 327         *      - 0x08 0x00     - length (little endian ?!)
 328         *      - 4 bytes = size of whole frame (BE - including header)
 329         *      - 0x00 0x0c
 330         *      - 0xff 0xd8
 331         *      - ..    JPEG image with escape sequences (ff 00)
 332         *              (without ending - ff d9)
 333         */
 334        if (data[0] == 0xff && data[1] == 0xfe) {
 335                gspca_frame_add(gspca_dev, LAST_PACKET,
 336                                ffd9, 2);
 337
 338                /* put the JPEG 411 header */
 339                gspca_frame_add(gspca_dev, FIRST_PACKET,
 340                        sd->jpeg_hdr, JPEG_HDR_SZ);
 341
 342                /* beginning of the frame */
 343#define STKHDRSZ 12
 344                data += STKHDRSZ;
 345                len -= STKHDRSZ;
 346        }
 347        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 348}
 349
 350static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
 351{
 352        struct gspca_dev *gspca_dev =
 353                container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 354
 355        gspca_dev->usb_err = 0;
 356
 357        if (!gspca_dev->streaming)
 358                return 0;
 359
 360        switch (ctrl->id) {
 361        case V4L2_CID_BRIGHTNESS:
 362                setbrightness(gspca_dev, ctrl->val);
 363                break;
 364        case V4L2_CID_CONTRAST:
 365                setcontrast(gspca_dev, ctrl->val);
 366                break;
 367        case V4L2_CID_SATURATION:
 368                setcolors(gspca_dev, ctrl->val);
 369                break;
 370        case V4L2_CID_POWER_LINE_FREQUENCY:
 371                setlightfreq(gspca_dev, ctrl->val);
 372                break;
 373        }
 374        return gspca_dev->usb_err;
 375}
 376
 377static const struct v4l2_ctrl_ops sd_ctrl_ops = {
 378        .s_ctrl = sd_s_ctrl,
 379};
 380
 381static int sd_init_controls(struct gspca_dev *gspca_dev)
 382{
 383        struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
 384
 385        gspca_dev->vdev.ctrl_handler = hdl;
 386        v4l2_ctrl_handler_init(hdl, 4);
 387        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 388                        V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
 389        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 390                        V4L2_CID_CONTRAST, 0, 255, 1, 127);
 391        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 392                        V4L2_CID_SATURATION, 0, 255, 1, 127);
 393        v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
 394                        V4L2_CID_POWER_LINE_FREQUENCY,
 395                        V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
 396                        V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
 397
 398        if (hdl->error) {
 399                pr_err("Could not initialize controls\n");
 400                return hdl->error;
 401        }
 402        return 0;
 403}
 404
 405/* sub-driver description */
 406static const struct sd_desc sd_desc = {
 407        .name = MODULE_NAME,
 408        .config = sd_config,
 409        .init = sd_init,
 410        .init_controls = sd_init_controls,
 411        .start = sd_start,
 412        .stopN = sd_stopN,
 413        .pkt_scan = sd_pkt_scan,
 414};
 415
 416/* -- module initialisation -- */
 417static const struct usb_device_id device_table[] = {
 418        {USB_DEVICE(0x05e1, 0x0893)},
 419        {}
 420};
 421MODULE_DEVICE_TABLE(usb, device_table);
 422
 423/* -- device connect -- */
 424static int sd_probe(struct usb_interface *intf,
 425                        const struct usb_device_id *id)
 426{
 427        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 428                                THIS_MODULE);
 429}
 430
 431static struct usb_driver sd_driver = {
 432        .name = MODULE_NAME,
 433        .id_table = device_table,
 434        .probe = sd_probe,
 435        .disconnect = gspca_disconnect,
 436#ifdef CONFIG_PM
 437        .suspend = gspca_suspend,
 438        .resume = gspca_resume,
 439        .reset_resume = gspca_resume,
 440#endif
 441};
 442
 443module_usb_driver(sd_driver);
 444