Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * Pixart PAC207BCA library
  3  *
  4  * Copyright (C) 2008 Hans de Goede <hdgoede@redhat.com>
  5  * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
  6  * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
  7  *
  8  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
  9  *
 10  * This program is free software; you can redistribute it and/or modify
 11  * it under the terms of the GNU General Public License as published by
 12  * the Free Software Foundation; either version 2 of the License, or
 13  * (at your option) any later version.
 14  *
 15  * This program is distributed in the hope that it will be useful,
 16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18  * GNU General Public License for more details.
 19  *
 20  * You should have received a copy of the GNU General Public License
 21  * along with this program; if not, write to the Free Software
 22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23  *
 24  */
 25 
 26 #define MODULE_NAME "pac207"
 27 
 28 #include "gspca.h"
 29 
 30 MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>");
 31 MODULE_DESCRIPTION("Pixart PAC207");
 32 MODULE_LICENSE("GPL");
 33 
 34 #define PAC207_CTRL_TIMEOUT             100  /* ms */
 35 
 36 #define PAC207_BRIGHTNESS_MIN           0
 37 #define PAC207_BRIGHTNESS_MAX           255
 38 #define PAC207_BRIGHTNESS_DEFAULT       4 /* power on default: 4 */
 39 
 40 /* An exposure value of 4 also works (3 does not) but then we need to lower
 41    the compression balance setting when in 352x288 mode, otherwise the usb
 42    bandwidth is not enough and packets get dropped resulting in corrupt
 43    frames. The problem with this is that when the compression balance gets
 44    lowered below 0x80, the pac207 starts using a different compression
 45    algorithm for some lines, these lines get prefixed with a 0x2dd2 prefix
 46    and currently we do not know how to decompress these lines, so for now
 47    we use a minimum exposure value of 5 */
 48 #define PAC207_EXPOSURE_MIN             5
 49 #define PAC207_EXPOSURE_MAX             26
 50 #define PAC207_EXPOSURE_DEFAULT         5 /* power on default: 3 ?? */
 51 #define PAC207_EXPOSURE_KNEE            11 /* 4 = 30 fps, 11 = 8, 15 = 6 */
 52 
 53 #define PAC207_GAIN_MIN                 0
 54 #define PAC207_GAIN_MAX                 31
 55 #define PAC207_GAIN_DEFAULT             9 /* power on default: 9 */
 56 #define PAC207_GAIN_KNEE                20
 57 
 58 #define PAC207_AUTOGAIN_DEADZONE        30
 59 
 60 /* specific webcam descriptor */
 61 struct sd {
 62         struct gspca_dev gspca_dev;             /* !! must be the first item */
 63 
 64         u8 mode;
 65 
 66         u8 brightness;
 67         u8 exposure;
 68         u8 autogain;
 69         u8 gain;
 70 
 71         u8 sof_read;
 72         u8 header_read;
 73         u8 autogain_ignore_frames;
 74 
 75         atomic_t avg_lum;
 76 };
 77 
 78 /* V4L2 controls supported by the driver */
 79 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
 80 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
 81 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
 82 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
 83 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
 84 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
 85 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
 86 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
 87 
 88 static struct ctrl sd_ctrls[] = {
 89 #define SD_BRIGHTNESS 0
 90         {
 91             {
 92                 .id      = V4L2_CID_BRIGHTNESS,
 93                 .type    = V4L2_CTRL_TYPE_INTEGER,
 94                 .name    = "Brightness",
 95                 .minimum = PAC207_BRIGHTNESS_MIN,
 96                 .maximum = PAC207_BRIGHTNESS_MAX,
 97                 .step = 1,
 98                 .default_value = PAC207_BRIGHTNESS_DEFAULT,
 99                 .flags = 0,
100             },
101             .set = sd_setbrightness,
102             .get = sd_getbrightness,
103         },
104 #define SD_EXPOSURE 1
105         {
106             {
107                 .id = V4L2_CID_EXPOSURE,
108                 .type = V4L2_CTRL_TYPE_INTEGER,
109                 .name = "exposure",
110                 .minimum = PAC207_EXPOSURE_MIN,
111                 .maximum = PAC207_EXPOSURE_MAX,
112                 .step = 1,
113                 .default_value = PAC207_EXPOSURE_DEFAULT,
114                 .flags = 0,
115             },
116             .set = sd_setexposure,
117             .get = sd_getexposure,
118         },
119 #define SD_AUTOGAIN 2
120         {
121             {
122                 .id       = V4L2_CID_AUTOGAIN,
123                 .type   = V4L2_CTRL_TYPE_BOOLEAN,
124                 .name   = "Auto Gain",
125                 .minimum = 0,
126                 .maximum = 1,
127                 .step   = 1,
128 #define AUTOGAIN_DEF 1
129                 .default_value = AUTOGAIN_DEF,
130                 .flags = 0,
131             },
132             .set = sd_setautogain,
133             .get = sd_getautogain,
134         },
135 #define SD_GAIN 3
136         {
137             {
138                 .id = V4L2_CID_GAIN,
139                 .type = V4L2_CTRL_TYPE_INTEGER,
140                 .name = "gain",
141                 .minimum = PAC207_GAIN_MIN,
142                 .maximum = PAC207_GAIN_MAX,
143                 .step = 1,
144                 .default_value = PAC207_GAIN_DEFAULT,
145                 .flags = 0,
146             },
147             .set = sd_setgain,
148             .get = sd_getgain,
149         },
150 };
151 
152 static const struct v4l2_pix_format sif_mode[] = {
153         {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
154                 .bytesperline = 176,
155                 .sizeimage = (176 + 2) * 144,
156                         /* uncompressed, add 2 bytes / line for line header */
157                 .colorspace = V4L2_COLORSPACE_SRGB,
158                 .priv = 1},
159         {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
160                 .bytesperline = 352,
161                         /* compressed, but only when needed (not compressed
162                            when the framerate is low) */
163                 .sizeimage = (352 + 2) * 288,
164                 .colorspace = V4L2_COLORSPACE_SRGB,
165                 .priv = 0},
166 };
167 
168 static const __u8 pac207_sensor_init[][8] = {
169         {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0},
170         {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
171         {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
172         {0x00, 0x00, 0x32, 0x00, 0x96, 0x00, 0xa2, 0x02},
173         {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00},
174 };
175 
176                         /* 48 reg_72 Rate Control end BalSize_4a =0x36 */
177 static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 };
178 
179 static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
180         const u8 *buffer, u16 length)
181 {
182         struct usb_device *udev = gspca_dev->dev;
183         int err;
184 
185         memcpy(gspca_dev->usb_buf, buffer, length);
186 
187         err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
188                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
189                         0x00, index,
190                         gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
191         if (err < 0)
192                 PDEBUG(D_ERR,
193                         "Failed to write registers to index 0x%04X, error %d)",
194                         index, err);
195 
196         return err;
197 }
198 
199 
200 static int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
201 {
202         struct usb_device *udev = gspca_dev->dev;
203         int err;
204 
205         err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
206                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
207                         value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
208         if (err)
209                 PDEBUG(D_ERR, "Failed to write a register (index 0x%04X,"
210                         " value 0x%02X, error %d)", index, value, err);
211 
212         return err;
213 }
214 
215 static int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
216 {
217         struct usb_device *udev = gspca_dev->dev;
218         int res;
219 
220         res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
221                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
222                         0x00, index,
223                         gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
224         if (res < 0) {
225                 PDEBUG(D_ERR,
226                         "Failed to read a register (index 0x%04X, error %d)",
227                         index, res);
228                 return res;
229         }
230 
231         return gspca_dev->usb_buf[0];
232 }
233 
234 /* this function is called at probe time */
235 static int sd_config(struct gspca_dev *gspca_dev,
236                         const struct usb_device_id *id)
237 {
238         struct sd *sd = (struct sd *) gspca_dev;
239         struct cam *cam;
240         u8 idreg[2];
241 
242         idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
243         idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
244         idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4);
245         idreg[1] = idreg[1] & 0x0f;
246         PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
247                 idreg[0], idreg[1]);
248 
249         if (idreg[0] != 0x27) {
250                 PDEBUG(D_PROBE, "Error invalid sensor ID!");
251                 return -ENODEV;
252         }
253 
254         PDEBUG(D_PROBE,
255                 "Pixart PAC207BCA Image Processor and Control Chip detected"
256                 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
257 
258         cam = &gspca_dev->cam;
259         cam->cam_mode = sif_mode;
260         cam->nmodes = ARRAY_SIZE(sif_mode);
261         sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
262         sd->exposure = PAC207_EXPOSURE_DEFAULT;
263         sd->gain = PAC207_GAIN_DEFAULT;
264         sd->autogain = AUTOGAIN_DEF;
265 
266         return 0;
267 }
268 
269 /* this function is called at probe and resume time */
270 static int sd_init(struct gspca_dev *gspca_dev)
271 {
272         pac207_write_reg(gspca_dev, 0x41, 0x00);
273                                 /* Bit_0=Image Format,
274                                  * Bit_1=LED,
275                                  * Bit_2=Compression test mode enable */
276         pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
277         pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
278 
279         return 0;
280 }
281 
282 /* -- start the camera -- */
283 static int sd_start(struct gspca_dev *gspca_dev)
284 {
285         struct sd *sd = (struct sd *) gspca_dev;
286         __u8 mode;
287 
288         pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
289         pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
290         pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
291         pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
292         pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8);
293         pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8);
294         pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4);
295 
296         /* Compression Balance */
297         if (gspca_dev->width == 176)
298                 pac207_write_reg(gspca_dev, 0x4a, 0xff);
299         else
300                 pac207_write_reg(gspca_dev, 0x4a, 0x88);
301         pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
302         pac207_write_reg(gspca_dev, 0x08, sd->brightness);
303 
304         /* PGA global gain (Bit 4-0) */
305         pac207_write_reg(gspca_dev, 0x0e, sd->gain);
306         pac207_write_reg(gspca_dev, 0x02, sd->exposure); /* PXCK = 12MHz /n */
307 
308         mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
309         if (gspca_dev->width == 176) {  /* 176x144 */
310                 mode |= 0x01;
311                 PDEBUG(D_STREAM, "pac207_start mode 176x144");
312         } else {                                /* 352x288 */
313                 PDEBUG(D_STREAM, "pac207_start mode 352x288");
314         }
315         pac207_write_reg(gspca_dev, 0x41, mode);
316 
317         pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
318         pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
319         msleep(10);
320         pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
321 
322         sd->sof_read = 0;
323         sd->autogain_ignore_frames = 0;
324         atomic_set(&sd->avg_lum, -1);
325         return 0;
326 }
327 
328 static void sd_stopN(struct gspca_dev *gspca_dev)
329 {
330         pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
331         pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
332         pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
333 }
334 
335 /* Include pac common sof detection functions */
336 #include "pac_common.h"
337 
338 static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
339 {
340         struct sd *sd = (struct sd *) gspca_dev;
341         int avg_lum = atomic_read(&sd->avg_lum);
342 
343         if (avg_lum == -1)
344                 return;
345 
346         if (sd->autogain_ignore_frames > 0)
347                 sd->autogain_ignore_frames--;
348         else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
349                         100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE,
350                         PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
351                 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
352 }
353 
354 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
355                         struct gspca_frame *frame,
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, 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                 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
373                                         data, n);
374                 sd->header_read = 0;
375                 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, 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, frame, data, len);
400 }
401 
402 static void setbrightness(struct gspca_dev *gspca_dev)
403 {
404         struct sd *sd = (struct sd *) gspca_dev;
405 
406         pac207_write_reg(gspca_dev, 0x08, sd->brightness);
407         pac207_write_reg(gspca_dev, 0x13, 0x01);        /* Bit 0, auto clear */
408         pac207_write_reg(gspca_dev, 0x1c, 0x01);        /* not documented */
409 }
410 
411 static void setexposure(struct gspca_dev *gspca_dev)
412 {
413         struct sd *sd = (struct sd *) gspca_dev;
414 
415         pac207_write_reg(gspca_dev, 0x02, sd->exposure);
416         pac207_write_reg(gspca_dev, 0x13, 0x01);        /* Bit 0, auto clear */
417         pac207_write_reg(gspca_dev, 0x1c, 0x01);        /* not documented */
418 }
419 
420 static void setgain(struct gspca_dev *gspca_dev)
421 {
422         struct sd *sd = (struct sd *) gspca_dev;
423 
424         pac207_write_reg(gspca_dev, 0x0e, sd->gain);
425         pac207_write_reg(gspca_dev, 0x13, 0x01);        /* Bit 0, auto clear */
426         pac207_write_reg(gspca_dev, 0x1c, 0x01);        /* not documented */
427 }
428 
429 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
430 {
431         struct sd *sd = (struct sd *) gspca_dev;
432 
433         sd->brightness = val;
434         if (gspca_dev->streaming)
435                 setbrightness(gspca_dev);
436         return 0;
437 }
438 
439 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
440 {
441         struct sd *sd = (struct sd *) gspca_dev;
442 
443         *val = sd->brightness;
444         return 0;
445 }
446 
447 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
448 {
449         struct sd *sd = (struct sd *) gspca_dev;
450 
451         sd->exposure = val;
452         if (gspca_dev->streaming)
453                 setexposure(gspca_dev);
454         return 0;
455 }
456 
457 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
458 {
459         struct sd *sd = (struct sd *) gspca_dev;
460 
461         *val = sd->exposure;
462         return 0;
463 }
464 
465 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
466 {
467         struct sd *sd = (struct sd *) gspca_dev;
468 
469         sd->gain = val;
470         if (gspca_dev->streaming)
471                 setgain(gspca_dev);
472         return 0;
473 }
474 
475 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
476 {
477         struct sd *sd = (struct sd *) gspca_dev;
478 
479         *val = sd->gain;
480         return 0;
481 }
482 
483 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
484 {
485         struct sd *sd = (struct sd *) gspca_dev;
486 
487         sd->autogain = val;
488         /* when switching to autogain set defaults to make sure
489            we are on a valid point of the autogain gain /
490            exposure knee graph, and give this change time to
491            take effect before doing autogain. */
492         if (sd->autogain) {
493                 sd->exposure = PAC207_EXPOSURE_DEFAULT;
494                 sd->gain = PAC207_GAIN_DEFAULT;
495                 if (gspca_dev->streaming) {
496                         sd->autogain_ignore_frames =
497                                 PAC_AUTOGAIN_IGNORE_FRAMES;
498                         setexposure(gspca_dev);
499                         setgain(gspca_dev);
500                 }
501         }
502 
503         return 0;
504 }
505 
506 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
507 {
508         struct sd *sd = (struct sd *) gspca_dev;
509 
510         *val = sd->autogain;
511         return 0;
512 }
513 
514 /* sub-driver description */
515 static const struct sd_desc sd_desc = {
516         .name = MODULE_NAME,
517         .ctrls = sd_ctrls,
518         .nctrls = ARRAY_SIZE(sd_ctrls),
519         .config = sd_config,
520         .init = sd_init,
521         .start = sd_start,
522         .stopN = sd_stopN,
523         .dq_callback = pac207_do_auto_gain,
524         .pkt_scan = sd_pkt_scan,
525 };
526 
527 /* -- module initialisation -- */
528 static const __devinitdata struct usb_device_id device_table[] = {
529         {USB_DEVICE(0x041e, 0x4028)},
530         {USB_DEVICE(0x093a, 0x2460)},
531         {USB_DEVICE(0x093a, 0x2461)},
532         {USB_DEVICE(0x093a, 0x2463)},
533         {USB_DEVICE(0x093a, 0x2464)},
534         {USB_DEVICE(0x093a, 0x2468)},
535         {USB_DEVICE(0x093a, 0x2470)},
536         {USB_DEVICE(0x093a, 0x2471)},
537         {USB_DEVICE(0x093a, 0x2472)},
538         {USB_DEVICE(0x093a, 0x2474)},
539         {USB_DEVICE(0x093a, 0x2476)},
540         {USB_DEVICE(0x145f, 0x013a)},
541         {USB_DEVICE(0x2001, 0xf115)},
542         {}
543 };
544 MODULE_DEVICE_TABLE(usb, device_table);
545 
546 /* -- device connect -- */
547 static int sd_probe(struct usb_interface *intf,
548                         const struct usb_device_id *id)
549 {
550         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
551                                 THIS_MODULE);
552 }
553 
554 static struct usb_driver sd_driver = {
555         .name = MODULE_NAME,
556         .id_table = device_table,
557         .probe = sd_probe,
558         .disconnect = gspca_disconnect,
559 #ifdef CONFIG_PM
560         .suspend = gspca_suspend,
561         .resume = gspca_resume,
562 #endif
563 };
564 
565 /* -- module insert / remove -- */
566 static int __init sd_mod_init(void)
567 {
568         int ret;
569         ret = usb_register(&sd_driver);
570         if (ret < 0)
571                 return ret;
572         PDEBUG(D_PROBE, "registered");
573         return 0;
574 }
575 static void __exit sd_mod_exit(void)
576 {
577         usb_deregister(&sd_driver);
578         PDEBUG(D_PROBE, "deregistered");
579 }
580 
581 module_init(sd_mod_init);
582 module_exit(sd_mod_exit);
583 
  This page was automatically generated by the LXR engine.