root/drivers/media/usb/gspca/mars.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. reg_w
  2. mi_w
  3. setbrightness
  4. setcolors
  5. setgamma
  6. setsharpness
  7. setilluminators
  8. mars_s_ctrl
  9. sd_init_controls
  10. sd_config
  11. sd_init
  12. sd_start
  13. sd_stopN
  14. sd_pkt_scan
  15. sd_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *              Mars-Semi MR97311A library
   4  *              Copyright (C) 2005 <bradlch@hotmail.com>
   5  *
   6  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
   7  */
   8 
   9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  10 
  11 #define MODULE_NAME "mars"
  12 
  13 #include "gspca.h"
  14 #include "jpeg.h"
  15 
  16 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
  17 MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
  18 MODULE_LICENSE("GPL");
  19 
  20 #define QUALITY 50
  21 
  22 /* specific webcam descriptor */
  23 struct sd {
  24         struct gspca_dev gspca_dev;     /* !! must be the first item */
  25 
  26         struct v4l2_ctrl *brightness;
  27         struct v4l2_ctrl *saturation;
  28         struct v4l2_ctrl *sharpness;
  29         struct v4l2_ctrl *gamma;
  30         struct { /* illuminator control cluster */
  31                 struct v4l2_ctrl *illum_top;
  32                 struct v4l2_ctrl *illum_bottom;
  33         };
  34         u8 jpeg_hdr[JPEG_HDR_SZ];
  35 };
  36 
  37 /* V4L2 controls supported by the driver */
  38 static void setbrightness(struct gspca_dev *gspca_dev, s32 val);
  39 static void setcolors(struct gspca_dev *gspca_dev, s32 val);
  40 static void setgamma(struct gspca_dev *gspca_dev, s32 val);
  41 static void setsharpness(struct gspca_dev *gspca_dev, s32 val);
  42 
  43 static const struct v4l2_pix_format vga_mode[] = {
  44         {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  45                 .bytesperline = 320,
  46                 .sizeimage = 320 * 240 * 3 / 8 + 590,
  47                 .colorspace = V4L2_COLORSPACE_JPEG,
  48                 .priv = 2},
  49         {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  50                 .bytesperline = 640,
  51                 .sizeimage = 640 * 480 * 3 / 8 + 590,
  52                 .colorspace = V4L2_COLORSPACE_JPEG,
  53                 .priv = 1},
  54 };
  55 
  56 static const __u8 mi_data[0x20] = {
  57 /*       01    02   03     04    05    06    07    08 */
  58         0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00,
  59 /*       09    0a   0b     0c    0d    0e    0f    10 */
  60         0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01,
  61 /*       11    12   13     14    15    16    17    18 */
  62         0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02,
  63 /*       19    1a   1b     1c    1d    1e    1f    20 */
  64         0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00
  65 };
  66 
  67 /* write <len> bytes from gspca_dev->usb_buf */
  68 static void reg_w(struct gspca_dev *gspca_dev,
  69                  int len)
  70 {
  71         int alen, ret;
  72 
  73         if (gspca_dev->usb_err < 0)
  74                 return;
  75 
  76         ret = usb_bulk_msg(gspca_dev->dev,
  77                         usb_sndbulkpipe(gspca_dev->dev, 4),
  78                         gspca_dev->usb_buf,
  79                         len,
  80                         &alen,
  81                         500);   /* timeout in milliseconds */
  82         if (ret < 0) {
  83                 pr_err("reg write [%02x] error %d\n",
  84                        gspca_dev->usb_buf[0], ret);
  85                 gspca_dev->usb_err = ret;
  86         }
  87 }
  88 
  89 static void mi_w(struct gspca_dev *gspca_dev,
  90                  u8 addr,
  91                  u8 value)
  92 {
  93         gspca_dev->usb_buf[0] = 0x1f;
  94         gspca_dev->usb_buf[1] = 0;                      /* control byte */
  95         gspca_dev->usb_buf[2] = addr;
  96         gspca_dev->usb_buf[3] = value;
  97 
  98         reg_w(gspca_dev, 4);
  99 }
 100 
 101 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
 102 {
 103         gspca_dev->usb_buf[0] = 0x61;
 104         gspca_dev->usb_buf[1] = val;
 105         reg_w(gspca_dev, 2);
 106 }
 107 
 108 static void setcolors(struct gspca_dev *gspca_dev, s32 val)
 109 {
 110         gspca_dev->usb_buf[0] = 0x5f;
 111         gspca_dev->usb_buf[1] = val << 3;
 112         gspca_dev->usb_buf[2] = ((val >> 2) & 0xf8) | 0x04;
 113         reg_w(gspca_dev, 3);
 114 }
 115 
 116 static void setgamma(struct gspca_dev *gspca_dev, s32 val)
 117 {
 118         gspca_dev->usb_buf[0] = 0x06;
 119         gspca_dev->usb_buf[1] = val * 0x40;
 120         reg_w(gspca_dev, 2);
 121 }
 122 
 123 static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
 124 {
 125         gspca_dev->usb_buf[0] = 0x67;
 126         gspca_dev->usb_buf[1] = val * 4 + 3;
 127         reg_w(gspca_dev, 2);
 128 }
 129 
 130 static void setilluminators(struct gspca_dev *gspca_dev, bool top, bool bottom)
 131 {
 132         /* both are off if not streaming */
 133         gspca_dev->usb_buf[0] = 0x22;
 134         if (top)
 135                 gspca_dev->usb_buf[1] = 0x76;
 136         else if (bottom)
 137                 gspca_dev->usb_buf[1] = 0x7a;
 138         else
 139                 gspca_dev->usb_buf[1] = 0x7e;
 140         reg_w(gspca_dev, 2);
 141 }
 142 
 143 static int mars_s_ctrl(struct v4l2_ctrl *ctrl)
 144 {
 145         struct gspca_dev *gspca_dev =
 146                 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 147         struct sd *sd = (struct sd *)gspca_dev;
 148 
 149         gspca_dev->usb_err = 0;
 150 
 151         if (ctrl->id == V4L2_CID_ILLUMINATORS_1) {
 152                 /* only one can be on at a time */
 153                 if (ctrl->is_new && ctrl->val)
 154                         sd->illum_bottom->val = 0;
 155                 if (sd->illum_bottom->is_new && sd->illum_bottom->val)
 156                         sd->illum_top->val = 0;
 157         }
 158 
 159         if (!gspca_dev->streaming)
 160                 return 0;
 161 
 162         switch (ctrl->id) {
 163         case V4L2_CID_BRIGHTNESS:
 164                 setbrightness(gspca_dev, ctrl->val);
 165                 break;
 166         case V4L2_CID_SATURATION:
 167                 setcolors(gspca_dev, ctrl->val);
 168                 break;
 169         case V4L2_CID_GAMMA:
 170                 setgamma(gspca_dev, ctrl->val);
 171                 break;
 172         case V4L2_CID_ILLUMINATORS_1:
 173                 setilluminators(gspca_dev, sd->illum_top->val,
 174                                            sd->illum_bottom->val);
 175                 break;
 176         case V4L2_CID_SHARPNESS:
 177                 setsharpness(gspca_dev, ctrl->val);
 178                 break;
 179         default:
 180                 return -EINVAL;
 181         }
 182         return gspca_dev->usb_err;
 183 }
 184 
 185 static const struct v4l2_ctrl_ops mars_ctrl_ops = {
 186         .s_ctrl = mars_s_ctrl,
 187 };
 188 
 189 /* this function is called at probe time */
 190 static int sd_init_controls(struct gspca_dev *gspca_dev)
 191 {
 192         struct sd *sd = (struct sd *) gspca_dev;
 193         struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
 194 
 195         gspca_dev->vdev.ctrl_handler = hdl;
 196         v4l2_ctrl_handler_init(hdl, 6);
 197         sd->brightness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
 198                         V4L2_CID_BRIGHTNESS, 0, 30, 1, 15);
 199         sd->saturation = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
 200                         V4L2_CID_SATURATION, 0, 255, 1, 200);
 201         sd->gamma = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
 202                         V4L2_CID_GAMMA, 0, 3, 1, 1);
 203         sd->sharpness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
 204                         V4L2_CID_SHARPNESS, 0, 2, 1, 1);
 205         sd->illum_top = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
 206                         V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
 207         sd->illum_top->flags |= V4L2_CTRL_FLAG_UPDATE;
 208         sd->illum_bottom = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
 209                         V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0);
 210         sd->illum_bottom->flags |= V4L2_CTRL_FLAG_UPDATE;
 211         if (hdl->error) {
 212                 pr_err("Could not initialize controls\n");
 213                 return hdl->error;
 214         }
 215         v4l2_ctrl_cluster(2, &sd->illum_top);
 216         return 0;
 217 }
 218 
 219 /* this function is called at probe time */
 220 static int sd_config(struct gspca_dev *gspca_dev,
 221                         const struct usb_device_id *id)
 222 {
 223         struct cam *cam;
 224 
 225         cam = &gspca_dev->cam;
 226         cam->cam_mode = vga_mode;
 227         cam->nmodes = ARRAY_SIZE(vga_mode);
 228         return 0;
 229 }
 230 
 231 /* this function is called at probe and resume time */
 232 static int sd_init(struct gspca_dev *gspca_dev)
 233 {
 234         return 0;
 235 }
 236 
 237 static int sd_start(struct gspca_dev *gspca_dev)
 238 {
 239         struct sd *sd = (struct sd *) gspca_dev;
 240         u8 *data;
 241         int i;
 242 
 243         /* create the JPEG header */
 244         jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
 245                         gspca_dev->pixfmt.width,
 246                         0x21);          /* JPEG 422 */
 247         jpeg_set_qual(sd->jpeg_hdr, QUALITY);
 248 
 249         data = gspca_dev->usb_buf;
 250 
 251         data[0] = 0x01;         /* address */
 252         data[1] = 0x01;
 253         reg_w(gspca_dev, 2);
 254 
 255         /*
 256            Initialize the MR97113 chip register
 257          */
 258         data[0] = 0x00;         /* address */
 259         data[1] = 0x0c | 0x01;  /* reg 0 */
 260         data[2] = 0x01;         /* reg 1 */
 261         data[3] = gspca_dev->pixfmt.width / 8;  /* h_size , reg 2 */
 262         data[4] = gspca_dev->pixfmt.height / 8; /* v_size , reg 3 */
 263         data[5] = 0x30;         /* reg 4, MI, PAS5101 :
 264                                  *      0x30 for 24mhz , 0x28 for 12mhz */
 265         data[6] = 0x02;         /* reg 5, H start - was 0x04 */
 266         data[7] = v4l2_ctrl_g_ctrl(sd->gamma) * 0x40;   /* reg 0x06: gamma */
 267         data[8] = 0x01;         /* reg 7, V start - was 0x03 */
 268 /*      if (h_size == 320 ) */
 269 /*              data[9]= 0x56;   * reg 8, 24MHz, 2:1 scale down */
 270 /*      else */
 271         data[9] = 0x52;         /* reg 8, 24MHz, no scale down */
 272 /*jfm: from win trace*/
 273         data[10] = 0x18;
 274 
 275         reg_w(gspca_dev, 11);
 276 
 277         data[0] = 0x23;         /* address */
 278         data[1] = 0x09;         /* reg 35, append frame header */
 279 
 280         reg_w(gspca_dev, 2);
 281 
 282         data[0] = 0x3c;         /* address */
 283 /*      if (gspca_dev->width == 1280) */
 284 /*              data[1] = 200;   * reg 60, pc-cam frame size
 285                                  *      (unit: 4KB) 800KB */
 286 /*      else */
 287         data[1] = 50;           /* 50 reg 60, pc-cam frame size
 288                                  *      (unit: 4KB) 200KB */
 289         reg_w(gspca_dev, 2);
 290 
 291         /* auto dark-gain */
 292         data[0] = 0x5e;         /* address */
 293         data[1] = 0;            /* reg 94, Y Gain (auto) */
 294 /*jfm: from win trace*/
 295                                 /* reg 0x5f/0x60 (LE) = saturation */
 296                                 /* h (60): xxxx x100
 297                                  * l (5f): xxxx x000 */
 298         data[2] = v4l2_ctrl_g_ctrl(sd->saturation) << 3;
 299         data[3] = ((v4l2_ctrl_g_ctrl(sd->saturation) >> 2) & 0xf8) | 0x04;
 300         data[4] = v4l2_ctrl_g_ctrl(sd->brightness); /* reg 0x61 = brightness */
 301         data[5] = 0x00;
 302 
 303         reg_w(gspca_dev, 6);
 304 
 305         data[0] = 0x67;
 306 /*jfm: from win trace*/
 307         data[1] = v4l2_ctrl_g_ctrl(sd->sharpness) * 4 + 3;
 308         data[2] = 0x14;
 309         reg_w(gspca_dev, 3);
 310 
 311         data[0] = 0x69;
 312         data[1] = 0x2f;
 313         data[2] = 0x28;
 314         data[3] = 0x42;
 315         reg_w(gspca_dev, 4);
 316 
 317         data[0] = 0x63;
 318         data[1] = 0x07;
 319         reg_w(gspca_dev, 2);
 320 /*jfm: win trace - many writes here to reg 0x64*/
 321 
 322         /* initialize the MI sensor */
 323         for (i = 0; i < sizeof mi_data; i++)
 324                 mi_w(gspca_dev, i + 1, mi_data[i]);
 325 
 326         data[0] = 0x00;
 327         data[1] = 0x4d;         /* ISOC transferring enable... */
 328         reg_w(gspca_dev, 2);
 329 
 330         setilluminators(gspca_dev, v4l2_ctrl_g_ctrl(sd->illum_top),
 331                                    v4l2_ctrl_g_ctrl(sd->illum_bottom));
 332 
 333         return gspca_dev->usb_err;
 334 }
 335 
 336 static void sd_stopN(struct gspca_dev *gspca_dev)
 337 {
 338         struct sd *sd = (struct sd *) gspca_dev;
 339 
 340         if (v4l2_ctrl_g_ctrl(sd->illum_top) ||
 341             v4l2_ctrl_g_ctrl(sd->illum_bottom)) {
 342                 setilluminators(gspca_dev, false, false);
 343                 msleep(20);
 344         }
 345 
 346         gspca_dev->usb_buf[0] = 1;
 347         gspca_dev->usb_buf[1] = 0;
 348         reg_w(gspca_dev, 2);
 349 }
 350 
 351 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 352                         u8 *data,                       /* isoc packet */
 353                         int len)                        /* iso packet length */
 354 {
 355         struct sd *sd = (struct sd *) gspca_dev;
 356         int p;
 357 
 358         if (len < 6) {
 359 /*              gspca_dev->last_packet_type = DISCARD_PACKET; */
 360                 return;
 361         }
 362         for (p = 0; p < len - 6; p++) {
 363                 if (data[0 + p] == 0xff
 364                     && data[1 + p] == 0xff
 365                     && data[2 + p] == 0x00
 366                     && data[3 + p] == 0xff
 367                     && data[4 + p] == 0x96) {
 368                         if (data[5 + p] == 0x64
 369                             || data[5 + p] == 0x65
 370                             || data[5 + p] == 0x66
 371                             || data[5 + p] == 0x67) {
 372                                 gspca_dbg(gspca_dev, D_PACK, "sof offset: %d len: %d\n",
 373                                           p, len);
 374                                 gspca_frame_add(gspca_dev, LAST_PACKET,
 375                                                 data, p);
 376 
 377                                 /* put the JPEG header */
 378                                 gspca_frame_add(gspca_dev, FIRST_PACKET,
 379                                         sd->jpeg_hdr, JPEG_HDR_SZ);
 380                                 data += p + 16;
 381                                 len -= p + 16;
 382                                 break;
 383                         }
 384                 }
 385         }
 386         gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 387 }
 388 
 389 /* sub-driver description */
 390 static const struct sd_desc sd_desc = {
 391         .name = MODULE_NAME,
 392         .config = sd_config,
 393         .init = sd_init,
 394         .init_controls = sd_init_controls,
 395         .start = sd_start,
 396         .stopN = sd_stopN,
 397         .pkt_scan = sd_pkt_scan,
 398 };
 399 
 400 /* -- module initialisation -- */
 401 static const struct usb_device_id device_table[] = {
 402         {USB_DEVICE(0x093a, 0x050f)},
 403         {}
 404 };
 405 MODULE_DEVICE_TABLE(usb, device_table);
 406 
 407 /* -- device connect -- */
 408 static int sd_probe(struct usb_interface *intf,
 409                         const struct usb_device_id *id)
 410 {
 411         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 412                                 THIS_MODULE);
 413 }
 414 
 415 static struct usb_driver sd_driver = {
 416         .name = MODULE_NAME,
 417         .id_table = device_table,
 418         .probe = sd_probe,
 419         .disconnect = gspca_disconnect,
 420 #ifdef CONFIG_PM
 421         .suspend = gspca_suspend,
 422         .resume = gspca_resume,
 423         .reset_resume = gspca_resume,
 424 #endif
 425 };
 426 
 427 module_usb_driver(sd_driver);

/* [<][>][^][v][top][bottom][index][help] */