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

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

DEFINITIONS

This source file includes following definitions.
  1. pac207_write_regs
  2. pac207_write_reg
  3. pac207_read_reg
  4. sd_config
  5. sd_init
  6. setcontrol
  7. sd_s_ctrl
  8. sd_init_controls
  9. sd_start
  10. sd_stopN
  11. pac207_do_auto_gain
  12. sd_pkt_scan
  13. sd_int_pkt_scan
  14. sd_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Pixart PAC207BCA library
   4  *
   5  * Copyright (C) 2008 Hans de Goede <hdegoede@redhat.com>
   6  * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
   7  * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
   8  *
   9  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
  10  */
  11 
  12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13 
  14 #define MODULE_NAME "pac207"
  15 
  16 #include <linux/input.h>
  17 #include "gspca.h"
  18 /* Include pac common sof detection functions */
  19 #include "pac_common.h"
  20 
  21 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
  22 MODULE_DESCRIPTION("Pixart PAC207");
  23 MODULE_LICENSE("GPL");
  24 
  25 #define PAC207_CTRL_TIMEOUT             100  /* ms */
  26 
  27 #define PAC207_BRIGHTNESS_MIN           0
  28 #define PAC207_BRIGHTNESS_MAX           255
  29 #define PAC207_BRIGHTNESS_DEFAULT       46
  30 #define PAC207_BRIGHTNESS_REG           0x08
  31 
  32 #define PAC207_EXPOSURE_MIN             3
  33 #define PAC207_EXPOSURE_MAX             90 /* 1 sec expo time / 1 fps */
  34 #define PAC207_EXPOSURE_DEFAULT         5 /* power on default: 3 */
  35 #define PAC207_EXPOSURE_REG             0x02
  36 
  37 #define PAC207_GAIN_MIN                 0
  38 #define PAC207_GAIN_MAX                 31
  39 #define PAC207_GAIN_DEFAULT             7 /* power on default: 9 */
  40 #define PAC207_GAIN_REG                 0x0e
  41 
  42 #define PAC207_AUTOGAIN_DEADZONE        30
  43 
  44 /* global parameters */
  45 static int led_invert;
  46 module_param(led_invert, int, 0644);
  47 MODULE_PARM_DESC(led_invert, "Invert led");
  48 
  49 /* specific webcam descriptor */
  50 struct sd {
  51         struct gspca_dev gspca_dev;             /* !! must be the first item */
  52 
  53         struct v4l2_ctrl *brightness;
  54 
  55         u8 mode;
  56         u8 sof_read;
  57         u8 header_read;
  58         u8 autogain_ignore_frames;
  59 
  60         atomic_t avg_lum;
  61 };
  62 
  63 static const struct v4l2_pix_format sif_mode[] = {
  64         {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
  65                 .bytesperline = 176,
  66                 .sizeimage = (176 + 2) * 144,
  67                         /* uncompressed, add 2 bytes / line for line header */
  68                 .colorspace = V4L2_COLORSPACE_SRGB,
  69                 .priv = 1},
  70         {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
  71                 .bytesperline = 352,
  72                         /* compressed, but only when needed (not compressed
  73                            when the framerate is low) */
  74                 .sizeimage = (352 + 2) * 288,
  75                 .colorspace = V4L2_COLORSPACE_SRGB,
  76                 .priv = 0},
  77 };
  78 
  79 static const __u8 pac207_sensor_init[][8] = {
  80         {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84},
  81         {0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
  82         {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
  83         {0x32, 0x00, 0x96, 0x00, 0xa2, 0x02, 0xaf, 0x00},
  84 };
  85 
  86 static void pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
  87         const u8 *buffer, u16 length)
  88 {
  89         struct usb_device *udev = gspca_dev->dev;
  90         int err;
  91 
  92         if (gspca_dev->usb_err < 0)
  93                 return;
  94 
  95         memcpy(gspca_dev->usb_buf, buffer, length);
  96 
  97         err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
  98                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
  99                         0x00, index,
 100                         gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
 101         if (err < 0) {
 102                 pr_err("Failed to write registers to index 0x%04X, error %d\n",
 103                        index, err);
 104                 gspca_dev->usb_err = err;
 105         }
 106 }
 107 
 108 static void pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
 109 {
 110         struct usb_device *udev = gspca_dev->dev;
 111         int err;
 112 
 113         if (gspca_dev->usb_err < 0)
 114                 return;
 115 
 116         err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
 117                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 118                         value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
 119         if (err) {
 120                 pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
 121                        index, value, err);
 122                 gspca_dev->usb_err = err;
 123         }
 124 }
 125 
 126 static int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
 127 {
 128         struct usb_device *udev = gspca_dev->dev;
 129         int res;
 130 
 131         if (gspca_dev->usb_err < 0)
 132                 return 0;
 133 
 134         res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
 135                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 136                         0x00, index,
 137                         gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
 138         if (res < 0) {
 139                 pr_err("Failed to read a register (index 0x%04X, error %d)\n",
 140                        index, res);
 141                 gspca_dev->usb_err = res;
 142                 return 0;
 143         }
 144 
 145         return gspca_dev->usb_buf[0];
 146 }
 147 
 148 /* this function is called at probe time */
 149 static int sd_config(struct gspca_dev *gspca_dev,
 150                         const struct usb_device_id *id)
 151 {
 152         struct cam *cam;
 153         u8 idreg[2];
 154 
 155         idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
 156         idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
 157         idreg[0] = ((idreg[0] & 0x0f) << 4) | ((idreg[1] & 0xf0) >> 4);
 158         idreg[1] = idreg[1] & 0x0f;
 159         gspca_dbg(gspca_dev, D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X\n",
 160                   idreg[0], idreg[1]);
 161 
 162         if (idreg[0] != 0x27) {
 163                 gspca_dbg(gspca_dev, D_PROBE, "Error invalid sensor ID!\n");
 164                 return -ENODEV;
 165         }
 166 
 167         gspca_dbg(gspca_dev, D_PROBE,
 168                   "Pixart PAC207BCA Image Processor and Control Chip detected (vid/pid 0x%04X:0x%04X)\n",
 169                   id->idVendor, id->idProduct);
 170 
 171         cam = &gspca_dev->cam;
 172         cam->cam_mode = sif_mode;
 173         cam->nmodes = ARRAY_SIZE(sif_mode);
 174 
 175         return 0;
 176 }
 177 
 178 /* this function is called at probe and resume time */
 179 static int sd_init(struct gspca_dev *gspca_dev)
 180 {
 181         u8 mode;
 182 
 183         /* mode: Image Format (Bit 0), LED (1), Compr. test mode (2) */
 184         if (led_invert)
 185                 mode = 0x02;
 186         else
 187                 mode = 0x00;
 188         pac207_write_reg(gspca_dev, 0x41, mode);
 189         pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
 190 
 191         return gspca_dev->usb_err;
 192 }
 193 
 194 static void setcontrol(struct gspca_dev *gspca_dev, u16 reg, u16 val)
 195 {
 196         pac207_write_reg(gspca_dev, reg, val);
 197         pac207_write_reg(gspca_dev, 0x13, 0x01);        /* Bit 0, auto clear */
 198         pac207_write_reg(gspca_dev, 0x1c, 0x01);        /* not documented */
 199 }
 200 
 201 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
 202 {
 203         struct gspca_dev *gspca_dev =
 204                 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 205         struct sd *sd = (struct sd *)gspca_dev;
 206 
 207         gspca_dev->usb_err = 0;
 208 
 209         if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
 210                 /* when switching to autogain set defaults to make sure
 211                    we are on a valid point of the autogain gain /
 212                    exposure knee graph, and give this change time to
 213                    take effect before doing autogain. */
 214                 gspca_dev->exposure->val    = PAC207_EXPOSURE_DEFAULT;
 215                 gspca_dev->gain->val        = PAC207_GAIN_DEFAULT;
 216                 sd->autogain_ignore_frames  = PAC_AUTOGAIN_IGNORE_FRAMES;
 217         }
 218 
 219         if (!gspca_dev->streaming)
 220                 return 0;
 221 
 222         switch (ctrl->id) {
 223         case V4L2_CID_BRIGHTNESS:
 224                 setcontrol(gspca_dev, PAC207_BRIGHTNESS_REG, ctrl->val);
 225                 break;
 226         case V4L2_CID_AUTOGAIN:
 227                 if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
 228                         setcontrol(gspca_dev, PAC207_EXPOSURE_REG,
 229                                    gspca_dev->exposure->val);
 230                 if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
 231                         setcontrol(gspca_dev, PAC207_GAIN_REG,
 232                                    gspca_dev->gain->val);
 233                 break;
 234         default:
 235                 return -EINVAL;
 236         }
 237         return gspca_dev->usb_err;
 238 }
 239 
 240 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
 241         .s_ctrl = sd_s_ctrl,
 242 };
 243 
 244 /* this function is called at probe time */
 245 static int sd_init_controls(struct gspca_dev *gspca_dev)
 246 {
 247         struct sd *sd = (struct sd *) gspca_dev;
 248         struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
 249 
 250         gspca_dev->vdev.ctrl_handler = hdl;
 251         v4l2_ctrl_handler_init(hdl, 4);
 252 
 253         sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 254                                 V4L2_CID_BRIGHTNESS,
 255                                 PAC207_BRIGHTNESS_MIN, PAC207_BRIGHTNESS_MAX,
 256                                 1, PAC207_BRIGHTNESS_DEFAULT);
 257         gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 258                                 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
 259         gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 260                                 V4L2_CID_EXPOSURE,
 261                                 PAC207_EXPOSURE_MIN, PAC207_EXPOSURE_MAX,
 262                                 1, PAC207_EXPOSURE_DEFAULT);
 263         gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 264                                 V4L2_CID_GAIN,
 265                                 PAC207_GAIN_MIN, PAC207_GAIN_MAX,
 266                                 1, PAC207_GAIN_DEFAULT);
 267         if (hdl->error) {
 268                 pr_err("Could not initialize controls\n");
 269                 return hdl->error;
 270         }
 271         v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
 272         return 0;
 273 }
 274 
 275 /* -- start the camera -- */
 276 static int sd_start(struct gspca_dev *gspca_dev)
 277 {
 278         struct sd *sd = (struct sd *) gspca_dev;
 279         __u8 mode;
 280 
 281         pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
 282         pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
 283         pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
 284         pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
 285         pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[3], 8);
 286 
 287         /* Compression Balance */
 288         if (gspca_dev->pixfmt.width == 176)
 289                 pac207_write_reg(gspca_dev, 0x4a, 0xff);
 290         else
 291                 pac207_write_reg(gspca_dev, 0x4a, 0x30);
 292         pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
 293         pac207_write_reg(gspca_dev, 0x08, v4l2_ctrl_g_ctrl(sd->brightness));
 294 
 295         /* PGA global gain (Bit 4-0) */
 296         pac207_write_reg(gspca_dev, 0x0e,
 297                 v4l2_ctrl_g_ctrl(gspca_dev->gain));
 298         pac207_write_reg(gspca_dev, 0x02,
 299                 v4l2_ctrl_g_ctrl(gspca_dev->exposure)); /* PXCK = 12MHz /n */
 300 
 301         /* mode: Image Format (Bit 0), LED (1), Compr. test mode (2) */
 302         if (led_invert)
 303                 mode = 0x00;
 304         else
 305                 mode = 0x02;
 306         if (gspca_dev->pixfmt.width == 176) {   /* 176x144 */
 307                 mode |= 0x01;
 308                 gspca_dbg(gspca_dev, D_STREAM, "pac207_start mode 176x144\n");
 309         } else {                                /* 352x288 */
 310                 gspca_dbg(gspca_dev, D_STREAM, "pac207_start mode 352x288\n");
 311         }
 312         pac207_write_reg(gspca_dev, 0x41, mode);
 313 
 314         pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
 315         pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
 316         msleep(10);
 317         pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
 318 
 319         sd->sof_read = 0;
 320         sd->autogain_ignore_frames = 0;
 321         atomic_set(&sd->avg_lum, -1);
 322         return gspca_dev->usb_err;
 323 }
 324 
 325 static void sd_stopN(struct gspca_dev *gspca_dev)
 326 {
 327         u8 mode;
 328 
 329         /* mode: Image Format (Bit 0), LED (1), Compr. test mode (2) */
 330         if (led_invert)
 331                 mode = 0x02;
 332         else
 333                 mode = 0x00;
 334         pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
 335         pac207_write_reg(gspca_dev, 0x41, mode); /* Turn off LED */
 336         pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
 337 }
 338 
 339 
 340 static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
 341 {
 342         struct sd *sd = (struct sd *) gspca_dev;
 343         int avg_lum = atomic_read(&sd->avg_lum);
 344 
 345         if (avg_lum == -1)
 346                 return;
 347 
 348         if (sd->autogain_ignore_frames > 0)
 349                 sd->autogain_ignore_frames--;
 350         else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
 351                         90, PAC207_AUTOGAIN_DEADZONE))
 352                 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
 353 }
 354 
 355 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 356                         u8 *data,
 357                         int len)
 358 {
 359         struct sd *sd = (struct sd *) gspca_dev;
 360         unsigned char *sof;
 361 
 362         sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
 363         if (sof) {
 364                 int n;
 365 
 366                 /* finish decoding current frame */
 367                 n = sof - data;
 368                 if (n > sizeof pac_sof_marker)
 369                         n -= sizeof pac_sof_marker;
 370                 else
 371                         n = 0;
 372                 gspca_frame_add(gspca_dev, LAST_PACKET,
 373                                 data, n);
 374                 sd->header_read = 0;
 375                 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
 376                 len -= sof - data;
 377                 data = sof;
 378         }
 379         if (sd->header_read < 11) {
 380                 int needed;
 381 
 382                 /* get average lumination from frame header (byte 5) */
 383                 if (sd->header_read < 5) {
 384                         needed = 5 - sd->header_read;
 385                         if (len >= needed)
 386                                 atomic_set(&sd->avg_lum, data[needed - 1]);
 387                 }
 388                 /* skip the rest of the header */
 389                 needed = 11 - sd->header_read;
 390                 if (len <= needed) {
 391                         sd->header_read += len;
 392                         return;
 393                 }
 394                 data += needed;
 395                 len -= needed;
 396                 sd->header_read = 11;
 397         }
 398 
 399         gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 400 }
 401 
 402 #if IS_ENABLED(CONFIG_INPUT)
 403 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
 404                         u8 *data,               /* interrupt packet data */
 405                         int len)                /* interrupt packet length */
 406 {
 407         int ret = -EINVAL;
 408 
 409         if (len == 2 && data[0] == 0x5a && data[1] == 0x5a) {
 410                 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
 411                 input_sync(gspca_dev->input_dev);
 412                 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
 413                 input_sync(gspca_dev->input_dev);
 414                 ret = 0;
 415         }
 416 
 417         return ret;
 418 }
 419 #endif
 420 
 421 /* sub-driver description */
 422 static const struct sd_desc sd_desc = {
 423         .name = MODULE_NAME,
 424         .config = sd_config,
 425         .init = sd_init,
 426         .init_controls = sd_init_controls,
 427         .start = sd_start,
 428         .stopN = sd_stopN,
 429         .dq_callback = pac207_do_auto_gain,
 430         .pkt_scan = sd_pkt_scan,
 431 #if IS_ENABLED(CONFIG_INPUT)
 432         .int_pkt_scan = sd_int_pkt_scan,
 433 #endif
 434 };
 435 
 436 /* -- module initialisation -- */
 437 static const struct usb_device_id device_table[] = {
 438         {USB_DEVICE(0x041e, 0x4028)},
 439         {USB_DEVICE(0x093a, 0x2460)},
 440         {USB_DEVICE(0x093a, 0x2461)},
 441         {USB_DEVICE(0x093a, 0x2463)},
 442         {USB_DEVICE(0x093a, 0x2464)},
 443         {USB_DEVICE(0x093a, 0x2468)},
 444         {USB_DEVICE(0x093a, 0x2470)},
 445         {USB_DEVICE(0x093a, 0x2471)},
 446         {USB_DEVICE(0x093a, 0x2472)},
 447         {USB_DEVICE(0x093a, 0x2474)},
 448         {USB_DEVICE(0x093a, 0x2476)},
 449         {USB_DEVICE(0x145f, 0x013a)},
 450         {USB_DEVICE(0x2001, 0xf115)},
 451         {}
 452 };
 453 MODULE_DEVICE_TABLE(usb, device_table);
 454 
 455 /* -- device connect -- */
 456 static int sd_probe(struct usb_interface *intf,
 457                         const struct usb_device_id *id)
 458 {
 459         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 460                                 THIS_MODULE);
 461 }
 462 
 463 static struct usb_driver sd_driver = {
 464         .name = MODULE_NAME,
 465         .id_table = device_table,
 466         .probe = sd_probe,
 467         .disconnect = gspca_disconnect,
 468 #ifdef CONFIG_PM
 469         .suspend = gspca_suspend,
 470         .resume = gspca_resume,
 471         .reset_resume = gspca_resume,
 472 #endif
 473 };
 474 
 475 module_usb_driver(sd_driver);

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