Merge branch 'x86/mm' into core/percpu
[linux-2.6] / drivers / media / video / w9966.c
1 /*
2         Winbond w9966cf Webcam parport driver.
3
4         Version 0.32
5
6         Copyright (C) 2001 Jakob Kemi <jakob.kemi@post.utfors.se>
7
8         This program is free software; you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation; either version 2 of the License, or
11         (at your option) any later version.
12
13         This program is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with this program; if not, write to the Free Software
20         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22 /*
23         Supported devices:
24         *Lifeview FlyCam Supra (using the Philips saa7111a chip)
25
26         Does any other model using the w9966 interface chip exist ?
27
28         Todo:
29
30         *Add a working EPP mode, since DMA ECP read isn't implemented
31         in the parport drivers. (That's why it's so sloow)
32
33         *Add support for other ccd-control chips than the saa7111
34         please send me feedback on what kind of chips you have.
35
36         *Add proper probing. I don't know what's wrong with the IEEE1284
37         parport drivers but (IEEE1284_MODE_NIBBLE|IEEE1284_DEVICE_ID)
38         and nibble read seems to be broken for some peripherals.
39
40         *Add probing for onboard SRAM, port directions etc. (if possible)
41
42         *Add support for the hardware compressed modes (maybe using v4l2)
43
44         *Fix better support for the capture window (no skewed images, v4l
45         interface to capt. window)
46
47         *Probably some bugs that I don't know of
48
49         Please support me by sending feedback!
50
51         Changes:
52
53         Alan Cox:       Removed RGB mode for kernel merge, added THIS_MODULE
54                         and owner support for newer module locks
55 */
56
57 #include <linux/module.h>
58 #include <linux/init.h>
59 #include <linux/delay.h>
60 #include <linux/videodev2.h>
61 #include <media/v4l2-common.h>
62 #include <media/v4l2-ioctl.h>
63 #include <linux/parport.h>
64
65 /*#define DEBUG*/                               /* Undef me for production */
66
67 #ifdef DEBUG
68 #define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
69 #else
70 #define DPRINTF(x...)
71 #endif
72
73 /*
74  *      Defines, simple typedefs etc.
75  */
76
77 #define W9966_DRIVERNAME        "W9966CF Webcam"
78 #define W9966_MAXCAMS           4       // Maximum number of cameras
79 #define W9966_RBUFFER           2048    // Read buffer (must be an even number)
80 #define W9966_SRAMSIZE          131072  // 128kb
81 #define W9966_SRAMID            0x02    // check w9966cf.pdf
82
83 // Empirically determined window limits
84 #define W9966_WND_MIN_X         16
85 #define W9966_WND_MIN_Y         14
86 #define W9966_WND_MAX_X         705
87 #define W9966_WND_MAX_Y         253
88 #define W9966_WND_MAX_W         (W9966_WND_MAX_X - W9966_WND_MIN_X)
89 #define W9966_WND_MAX_H         (W9966_WND_MAX_Y - W9966_WND_MIN_Y)
90
91 // Keep track of our current state
92 #define W9966_STATE_PDEV        0x01
93 #define W9966_STATE_CLAIMED     0x02
94 #define W9966_STATE_VDEV        0x04
95
96 #define W9966_I2C_W_ID          0x48
97 #define W9966_I2C_R_ID          0x49
98 #define W9966_I2C_R_DATA        0x08
99 #define W9966_I2C_R_CLOCK       0x04
100 #define W9966_I2C_W_DATA        0x02
101 #define W9966_I2C_W_CLOCK       0x01
102
103 struct w9966_dev {
104         unsigned char dev_state;
105         unsigned char i2c_state;
106         unsigned short ppmode;
107         struct parport* pport;
108         struct pardevice* pdev;
109         struct video_device vdev;
110         unsigned short width;
111         unsigned short height;
112         unsigned char brightness;
113         signed char contrast;
114         signed char color;
115         signed char hue;
116         unsigned long in_use;
117 };
118
119 /*
120  *      Module specific properties
121  */
122
123 MODULE_AUTHOR("Jakob Kemi <jakob.kemi@post.utfors.se>");
124 MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)");
125 MODULE_LICENSE("GPL");
126
127
128 #ifdef MODULE
129 static const char* pardev[] = {[0 ... W9966_MAXCAMS] = ""};
130 #else
131 static const char* pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"};
132 #endif
133 module_param_array(pardev, charp, NULL, 0);
134 MODULE_PARM_DESC(pardev, "pardev: where to search for\n\
135 \teach camera. 'aggressive' means brute-force search.\n\
136 \tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n\
137 \tcam 1 to parport3 and search every parport for cam 2 etc...");
138
139 static int parmode;
140 module_param(parmode, int, 0);
141 MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
142
143 static int video_nr = -1;
144 module_param(video_nr, int, 0);
145
146 /*
147  *      Private data
148  */
149
150 static struct w9966_dev w9966_cams[W9966_MAXCAMS];
151
152 /*
153  *      Private function declares
154  */
155
156 static inline void w9966_setState(struct w9966_dev* cam, int mask, int val);
157 static inline int  w9966_getState(struct w9966_dev* cam, int mask, int val);
158 static inline void w9966_pdev_claim(struct w9966_dev *vdev);
159 static inline void w9966_pdev_release(struct w9966_dev *vdev);
160
161 static int w9966_rReg(struct w9966_dev* cam, int reg);
162 static int w9966_wReg(struct w9966_dev* cam, int reg, int data);
163 #if 0
164 static int w9966_rReg_i2c(struct w9966_dev* cam, int reg);
165 #endif
166 static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data);
167 static int w9966_findlen(int near, int size, int maxlen);
168 static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsigned char* factor);
169 static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, int w, int h);
170
171 static int  w9966_init(struct w9966_dev* cam, struct parport* port);
172 static void w9966_term(struct w9966_dev* cam);
173
174 static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state);
175 static inline int  w9966_i2c_setscl(struct w9966_dev* cam, int state);
176 static inline int  w9966_i2c_getsda(struct w9966_dev* cam);
177 static inline int  w9966_i2c_getscl(struct w9966_dev* cam);
178 static int w9966_i2c_wbyte(struct w9966_dev* cam, int data);
179 #if 0
180 static int w9966_i2c_rbyte(struct w9966_dev* cam);
181 #endif
182
183 static long w9966_v4l_ioctl(struct file *file,
184                            unsigned int cmd, unsigned long arg);
185 static ssize_t w9966_v4l_read(struct file *file, char __user *buf,
186                               size_t count, loff_t *ppos);
187
188 static int w9966_exclusive_open(struct file *file)
189 {
190         struct w9966_dev *cam = video_drvdata(file);
191
192         return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0;
193 }
194
195 static int w9966_exclusive_release(struct file *file)
196 {
197         struct w9966_dev *cam = video_drvdata(file);
198
199         clear_bit(0, &cam->in_use);
200         return 0;
201 }
202
203 static const struct v4l2_file_operations w9966_fops = {
204         .owner          = THIS_MODULE,
205         .open           = w9966_exclusive_open,
206         .release        = w9966_exclusive_release,
207         .ioctl          = w9966_v4l_ioctl,
208         .read           = w9966_v4l_read,
209 };
210 static struct video_device w9966_template = {
211         .name           = W9966_DRIVERNAME,
212         .fops           = &w9966_fops,
213         .release        = video_device_release_empty,
214 };
215
216 /*
217  *      Private function defines
218  */
219
220
221 // Set camera phase flags, so we know what to uninit when terminating
222 static inline void w9966_setState(struct w9966_dev* cam, int mask, int val)
223 {
224         cam->dev_state = (cam->dev_state & ~mask) ^ val;
225 }
226
227 // Get camera phase flags
228 static inline int w9966_getState(struct w9966_dev* cam, int mask, int val)
229 {
230         return ((cam->dev_state & mask) == val);
231 }
232
233 // Claim parport for ourself
234 static inline void w9966_pdev_claim(struct w9966_dev* cam)
235 {
236         if (w9966_getState(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED))
237                 return;
238         parport_claim_or_block(cam->pdev);
239         w9966_setState(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED);
240 }
241
242 // Release parport for others to use
243 static inline void w9966_pdev_release(struct w9966_dev* cam)
244 {
245         if (w9966_getState(cam, W9966_STATE_CLAIMED, 0))
246                 return;
247         parport_release(cam->pdev);
248         w9966_setState(cam, W9966_STATE_CLAIMED, 0);
249 }
250
251 // Read register from W9966 interface-chip
252 // Expects a claimed pdev
253 // -1 on error, else register data (byte)
254 static int w9966_rReg(struct w9966_dev* cam, int reg)
255 {
256         // ECP, read, regtransfer, REG, REG, REG, REG, REG
257         const unsigned char addr = 0x80 | (reg & 0x1f);
258         unsigned char val;
259
260         if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
261                 return -1;
262         if (parport_write(cam->pport, &addr, 1) != 1)
263                 return -1;
264         if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
265                 return -1;
266         if (parport_read(cam->pport, &val, 1) != 1)
267                 return -1;
268
269         return val;
270 }
271
272 // Write register to W9966 interface-chip
273 // Expects a claimed pdev
274 // -1 on error
275 static int w9966_wReg(struct w9966_dev* cam, int reg, int data)
276 {
277         // ECP, write, regtransfer, REG, REG, REG, REG, REG
278         const unsigned char addr = 0xc0 | (reg & 0x1f);
279         const unsigned char val = data;
280
281         if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
282                 return -1;
283         if (parport_write(cam->pport, &addr, 1) != 1)
284                 return -1;
285         if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
286                 return -1;
287         if (parport_write(cam->pport, &val, 1) != 1)
288                 return -1;
289
290         return 0;
291 }
292
293 // Initialize camera device. Setup all internal flags, set a
294 // default video mode, setup ccd-chip, register v4l device etc..
295 // Also used for 'probing' of hardware.
296 // -1 on error
297 static int w9966_init(struct w9966_dev* cam, struct parport* port)
298 {
299         if (cam->dev_state != 0)
300                 return -1;
301
302         cam->pport = port;
303         cam->brightness = 128;
304         cam->contrast = 64;
305         cam->color = 64;
306         cam->hue = 0;
307
308 // Select requested transfer mode
309         switch(parmode)
310         {
311         default:        // Auto-detect (priority: hw-ecp, hw-epp, sw-ecp)
312         case 0:
313                 if (port->modes & PARPORT_MODE_ECP)
314                         cam->ppmode = IEEE1284_MODE_ECP;
315                 else if (port->modes & PARPORT_MODE_EPP)
316                         cam->ppmode = IEEE1284_MODE_EPP;
317                 else
318                         cam->ppmode = IEEE1284_MODE_ECP;
319                 break;
320         case 1:         // hw- or sw-ecp
321                 cam->ppmode = IEEE1284_MODE_ECP;
322                 break;
323         case 2:         // hw- or sw-epp
324                 cam->ppmode = IEEE1284_MODE_EPP;
325         break;
326         }
327
328 // Tell the parport driver that we exists
329         cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL);
330         if (cam->pdev == NULL) {
331                 DPRINTF("parport_register_device() failed\n");
332                 return -1;
333         }
334         w9966_setState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV);
335
336         w9966_pdev_claim(cam);
337
338 // Setup a default capture mode
339         if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) {
340                 DPRINTF("w9966_setup() failed.\n");
341                 return -1;
342         }
343
344         w9966_pdev_release(cam);
345
346 // Fill in the video_device struct and register us to v4l
347         memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device));
348         video_set_drvdata(&cam->vdev, cam);
349
350         if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
351                 return -1;
352
353         w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
354
355         // All ok
356         printk(
357                 "w9966cf: Found and initialized a webcam on %s.\n",
358                 cam->pport->name
359         );
360         return 0;
361 }
362
363
364 // Terminate everything gracefully
365 static void w9966_term(struct w9966_dev* cam)
366 {
367 // Unregister from v4l
368         if (w9966_getState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) {
369                 video_unregister_device(&cam->vdev);
370                 w9966_setState(cam, W9966_STATE_VDEV, 0);
371         }
372
373 // Terminate from IEEE1284 mode and release pdev block
374         if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
375                 w9966_pdev_claim(cam);
376                 parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT);
377                 w9966_pdev_release(cam);
378         }
379
380 // Unregister from parport
381         if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
382                 parport_unregister_device(cam->pdev);
383                 w9966_setState(cam, W9966_STATE_PDEV, 0);
384         }
385 }
386
387
388 // Find a good length for capture window (used both for W and H)
389 // A bit ugly but pretty functional. The capture length
390 // have to match the downscale
391 static int w9966_findlen(int near, int size, int maxlen)
392 {
393         int bestlen = size;
394         int besterr = abs(near - bestlen);
395         int len;
396
397         for(len = size+1;len < maxlen;len++)
398         {
399                 int err;
400                 if ( ((64*size) %len) != 0)
401                         continue;
402
403                 err = abs(near - len);
404
405                 // Only continue as long as we keep getting better values
406                 if (err > besterr)
407                         break;
408
409                 besterr = err;
410                 bestlen = len;
411         }
412
413         return bestlen;
414 }
415
416 // Modify capture window (if necessary)
417 // and calculate downscaling
418 // Return -1 on error
419 static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsigned char* factor)
420 {
421         int maxlen = max - min;
422         int len = *end - *beg + 1;
423         int newlen = w9966_findlen(len, size, maxlen);
424         int err = newlen - len;
425
426         // Check for bad format
427         if (newlen > maxlen || newlen < size)
428                 return -1;
429
430         // Set factor (6 bit fixed)
431         *factor = (64*size) / newlen;
432         if (*factor == 64)
433                 *factor = 0x00; // downscale is disabled
434         else
435                 *factor |= 0x80; // set downscale-enable bit
436
437         // Modify old beginning and end
438         *beg -= err / 2;
439         *end += err - (err / 2);
440
441         // Move window if outside borders
442         if (*beg < min) {
443                 *end += min - *beg;
444                 *beg += min - *beg;
445         }
446         if (*end > max) {
447                 *beg -= *end - max;
448                 *end -= *end - max;
449         }
450
451         return 0;
452 }
453
454 // Setup the cameras capture window etc.
455 // Expects a claimed pdev
456 // return -1 on error
457 static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, int w, int h)
458 {
459         unsigned int i;
460         unsigned int enh_s, enh_e;
461         unsigned char scale_x, scale_y;
462         unsigned char regs[0x1c];
463         unsigned char saa7111_regs[] = {
464                 0x21, 0x00, 0xd8, 0x23, 0x00, 0x80, 0x80, 0x00,
465                 0x88, 0x10, 0x80, 0x40, 0x40, 0x00, 0x01, 0x00,
466                 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467                 0x00, 0x00, 0x00, 0x71, 0xe7, 0x00, 0x00, 0xc0
468         };
469
470
471         if (w*h*2 > W9966_SRAMSIZE)
472         {
473                 DPRINTF("capture window exceeds SRAM size!.\n");
474                 w = 200; h = 160;       // Pick default values
475         }
476
477         w &= ~0x1;
478         if (w < 2) w = 2;
479         if (h < 1) h = 1;
480         if (w > W9966_WND_MAX_W) w = W9966_WND_MAX_W;
481         if (h > W9966_WND_MAX_H) h = W9966_WND_MAX_H;
482
483         cam->width = w;
484         cam->height = h;
485
486         enh_s = 0;
487         enh_e = w*h*2;
488
489 // Modify capture window if necessary and calculate downscaling
490         if (
491                 w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 ||
492                 w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0
493         ) return -1;
494
495         DPRINTF(
496                 "%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n",
497                 w, h, x1, x2, y1, y2, scale_x&~0x80, scale_y&~0x80
498         );
499
500 // Setup registers
501         regs[0x00] = 0x00;                      // Set normal operation
502         regs[0x01] = 0x18;                      // Capture mode
503         regs[0x02] = scale_y;                   // V-scaling
504         regs[0x03] = scale_x;                   // H-scaling
505
506         // Capture window
507         regs[0x04] = (x1 & 0x0ff);              // X-start (8 low bits)
508         regs[0x05] = (x1 & 0x300)>>8;           // X-start (2 high bits)
509         regs[0x06] = (y1 & 0x0ff);              // Y-start (8 low bits)
510         regs[0x07] = (y1 & 0x300)>>8;           // Y-start (2 high bits)
511         regs[0x08] = (x2 & 0x0ff);              // X-end (8 low bits)
512         regs[0x09] = (x2 & 0x300)>>8;           // X-end (2 high bits)
513         regs[0x0a] = (y2 & 0x0ff);              // Y-end (8 low bits)
514
515         regs[0x0c] = W9966_SRAMID;              // SRAM-banks (1x 128kb)
516
517         // Enhancement layer
518         regs[0x0d] = (enh_s& 0x000ff);          // Enh. start (0-7)
519         regs[0x0e] = (enh_s& 0x0ff00)>>8;       // Enh. start (8-15)
520         regs[0x0f] = (enh_s& 0x70000)>>16;      // Enh. start (16-17/18??)
521         regs[0x10] = (enh_e& 0x000ff);          // Enh. end (0-7)
522         regs[0x11] = (enh_e& 0x0ff00)>>8;       // Enh. end (8-15)
523         regs[0x12] = (enh_e& 0x70000)>>16;      // Enh. end (16-17/18??)
524
525         // Misc
526         regs[0x13] = 0x40;                      // VEE control (raw 4:2:2)
527         regs[0x17] = 0x00;                      // ???
528         regs[0x18] = cam->i2c_state = 0x00;     // Serial bus
529         regs[0x19] = 0xff;                      // I/O port direction control
530         regs[0x1a] = 0xff;                      // I/O port data register
531         regs[0x1b] = 0x10;                      // ???
532
533         // SAA7111 chip settings
534         saa7111_regs[0x0a] = cam->brightness;
535         saa7111_regs[0x0b] = cam->contrast;
536         saa7111_regs[0x0c] = cam->color;
537         saa7111_regs[0x0d] = cam->hue;
538
539 // Reset (ECP-fifo & serial-bus)
540         if (w9966_wReg(cam, 0x00, 0x03) == -1)
541                 return -1;
542
543 // Write regs to w9966cf chip
544         for (i = 0; i < 0x1c; i++)
545                 if (w9966_wReg(cam, i, regs[i]) == -1)
546                         return -1;
547
548 // Write regs to saa7111 chip
549         for (i = 0; i < 0x20; i++)
550                 if (w9966_wReg_i2c(cam, i, saa7111_regs[i]) == -1)
551                         return -1;
552
553         return 0;
554 }
555
556 /*
557  *      Ugly and primitive i2c protocol functions
558  */
559
560 // Sets the data line on the i2c bus.
561 // Expects a claimed pdev.
562 static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state)
563 {
564         if (state)
565                 cam->i2c_state |= W9966_I2C_W_DATA;
566         else
567                 cam->i2c_state &= ~W9966_I2C_W_DATA;
568
569         w9966_wReg(cam, 0x18, cam->i2c_state);
570         udelay(5);
571 }
572
573 // Get peripheral clock line
574 // Expects a claimed pdev.
575 static inline int w9966_i2c_getscl(struct w9966_dev* cam)
576 {
577         const unsigned char state = w9966_rReg(cam, 0x18);
578         return ((state & W9966_I2C_R_CLOCK) > 0);
579 }
580
581 // Sets the clock line on the i2c bus.
582 // Expects a claimed pdev. -1 on error
583 static inline int w9966_i2c_setscl(struct w9966_dev* cam, int state)
584 {
585         unsigned long timeout;
586
587         if (state)
588                 cam->i2c_state |= W9966_I2C_W_CLOCK;
589         else
590                 cam->i2c_state &= ~W9966_I2C_W_CLOCK;
591
592         w9966_wReg(cam, 0x18, cam->i2c_state);
593         udelay(5);
594
595         // we go to high, we also expect the peripheral to ack.
596         if (state) {
597                 timeout = jiffies + 100;
598                 while (!w9966_i2c_getscl(cam)) {
599                         if (time_after(jiffies, timeout))
600                                 return -1;
601                 }
602         }
603         return 0;
604 }
605
606 // Get peripheral data line
607 // Expects a claimed pdev.
608 static inline int w9966_i2c_getsda(struct w9966_dev* cam)
609 {
610         const unsigned char state = w9966_rReg(cam, 0x18);
611         return ((state & W9966_I2C_R_DATA) > 0);
612 }
613
614 // Write a byte with ack to the i2c bus.
615 // Expects a claimed pdev. -1 on error
616 static int w9966_i2c_wbyte(struct w9966_dev* cam, int data)
617 {
618         int i;
619         for (i = 7; i >= 0; i--)
620         {
621                 w9966_i2c_setsda(cam, (data >> i) & 0x01);
622
623                 if (w9966_i2c_setscl(cam, 1) == -1)
624                         return -1;
625                 w9966_i2c_setscl(cam, 0);
626         }
627
628         w9966_i2c_setsda(cam, 1);
629
630         if (w9966_i2c_setscl(cam, 1) == -1)
631                 return -1;
632         w9966_i2c_setscl(cam, 0);
633
634         return 0;
635 }
636
637 // Read a data byte with ack from the i2c-bus
638 // Expects a claimed pdev. -1 on error
639 #if 0
640 static int w9966_i2c_rbyte(struct w9966_dev* cam)
641 {
642         unsigned char data = 0x00;
643         int i;
644
645         w9966_i2c_setsda(cam, 1);
646
647         for (i = 0; i < 8; i++)
648         {
649                 if (w9966_i2c_setscl(cam, 1) == -1)
650                         return -1;
651                 data = data << 1;
652                 if (w9966_i2c_getsda(cam))
653                         data |= 0x01;
654
655                 w9966_i2c_setscl(cam, 0);
656         }
657         return data;
658 }
659 #endif
660
661 // Read a register from the i2c device.
662 // Expects claimed pdev. -1 on error
663 #if 0
664 static int w9966_rReg_i2c(struct w9966_dev* cam, int reg)
665 {
666         int data;
667
668         w9966_i2c_setsda(cam, 0);
669         w9966_i2c_setscl(cam, 0);
670
671         if (
672                 w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
673                 w9966_i2c_wbyte(cam, reg) == -1
674         )
675                 return -1;
676
677         w9966_i2c_setsda(cam, 1);
678         if (w9966_i2c_setscl(cam, 1) == -1)
679                 return -1;
680         w9966_i2c_setsda(cam, 0);
681         w9966_i2c_setscl(cam, 0);
682
683         if (
684                 w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1 ||
685                 (data = w9966_i2c_rbyte(cam)) == -1
686         )
687                 return -1;
688
689         w9966_i2c_setsda(cam, 0);
690
691         if (w9966_i2c_setscl(cam, 1) == -1)
692                 return -1;
693         w9966_i2c_setsda(cam, 1);
694
695         return data;
696 }
697 #endif
698
699 // Write a register to the i2c device.
700 // Expects claimed pdev. -1 on error
701 static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data)
702 {
703         w9966_i2c_setsda(cam, 0);
704         w9966_i2c_setscl(cam, 0);
705
706         if (
707                 w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
708                 w9966_i2c_wbyte(cam, reg) == -1 ||
709                 w9966_i2c_wbyte(cam, data) == -1
710         )
711                 return -1;
712
713         w9966_i2c_setsda(cam, 0);
714         if (w9966_i2c_setscl(cam, 1) == -1)
715                 return -1;
716
717         w9966_i2c_setsda(cam, 1);
718
719         return 0;
720 }
721
722 /*
723  *      Video4linux interfacing
724  */
725
726 static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
727 {
728         struct w9966_dev *cam = video_drvdata(file);
729
730         switch(cmd)
731         {
732         case VIDIOCGCAP:
733         {
734                 static struct video_capability vcap = {
735                         .name      = W9966_DRIVERNAME,
736                         .type      = VID_TYPE_CAPTURE | VID_TYPE_SCALES,
737                         .channels  = 1,
738                         .maxwidth  = W9966_WND_MAX_W,
739                         .maxheight = W9966_WND_MAX_H,
740                         .minwidth  = 2,
741                         .minheight = 1,
742                 };
743                 struct video_capability *cap = arg;
744                 *cap = vcap;
745                 return 0;
746         }
747         case VIDIOCGCHAN:
748         {
749                 struct video_channel *vch = arg;
750                 if(vch->channel != 0)   // We only support one channel (#0)
751                         return -EINVAL;
752                 memset(vch,0,sizeof(*vch));
753                 strcpy(vch->name, "CCD-input");
754                 vch->type = VIDEO_TYPE_CAMERA;
755                 return 0;
756         }
757         case VIDIOCSCHAN:
758         {
759                 struct video_channel *vch = arg;
760                 if(vch->channel != 0)
761                         return -EINVAL;
762                 return 0;
763         }
764         case VIDIOCGTUNER:
765         {
766                 struct video_tuner *vtune = arg;
767                 if(vtune->tuner != 0)
768                         return -EINVAL;
769                 strcpy(vtune->name, "no tuner");
770                 vtune->rangelow = 0;
771                 vtune->rangehigh = 0;
772                 vtune->flags = VIDEO_TUNER_NORM;
773                 vtune->mode = VIDEO_MODE_AUTO;
774                 vtune->signal = 0xffff;
775                 return 0;
776         }
777         case VIDIOCSTUNER:
778         {
779                 struct video_tuner *vtune = arg;
780                 if (vtune->tuner != 0)
781                         return -EINVAL;
782                 if (vtune->mode != VIDEO_MODE_AUTO)
783                         return -EINVAL;
784                 return 0;
785         }
786         case VIDIOCGPICT:
787         {
788                 struct video_picture vpic = {
789                         cam->brightness << 8,   // brightness
790                         (cam->hue + 128) << 8,  // hue
791                         cam->color << 9,        // color
792                         cam->contrast << 9,     // contrast
793                         0x8000,                 // whiteness
794                         16, VIDEO_PALETTE_YUV422// bpp, palette format
795                 };
796                 struct video_picture *pic = arg;
797                 *pic = vpic;
798                 return 0;
799         }
800         case VIDIOCSPICT:
801         {
802                 struct video_picture *vpic = arg;
803                 if (vpic->depth != 16 || (vpic->palette != VIDEO_PALETTE_YUV422 && vpic->palette != VIDEO_PALETTE_YUYV))
804                         return -EINVAL;
805
806                 cam->brightness = vpic->brightness >> 8;
807                 cam->hue = (vpic->hue >> 8) - 128;
808                 cam->color = vpic->colour >> 9;
809                 cam->contrast = vpic->contrast >> 9;
810
811                 w9966_pdev_claim(cam);
812
813                 if (
814                         w9966_wReg_i2c(cam, 0x0a, cam->brightness) == -1 ||
815                         w9966_wReg_i2c(cam, 0x0b, cam->contrast) == -1 ||
816                         w9966_wReg_i2c(cam, 0x0c, cam->color) == -1 ||
817                         w9966_wReg_i2c(cam, 0x0d, cam->hue) == -1
818                 ) {
819                         w9966_pdev_release(cam);
820                         return -EIO;
821                 }
822
823                 w9966_pdev_release(cam);
824                 return 0;
825         }
826         case VIDIOCSWIN:
827         {
828                 int ret;
829                 struct video_window *vwin = arg;
830
831                 if (vwin->flags != 0)
832                         return -EINVAL;
833                 if (vwin->clipcount != 0)
834                         return -EINVAL;
835                 if (vwin->width < 2 || vwin->width > W9966_WND_MAX_W)
836                         return -EINVAL;
837                 if (vwin->height < 1 || vwin->height > W9966_WND_MAX_H)
838                         return -EINVAL;
839
840                 // Update camera regs
841                 w9966_pdev_claim(cam);
842                 ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin->width, vwin->height);
843                 w9966_pdev_release(cam);
844
845                 if (ret != 0) {
846                         DPRINTF("VIDIOCSWIN: w9966_setup() failed.\n");
847                         return -EIO;
848                 }
849
850                 return 0;
851         }
852         case VIDIOCGWIN:
853         {
854                 struct video_window *vwin = arg;
855                 memset(vwin, 0, sizeof(*vwin));
856                 vwin->width = cam->width;
857                 vwin->height = cam->height;
858                 return 0;
859         }
860         // Unimplemented
861         case VIDIOCCAPTURE:
862         case VIDIOCGFBUF:
863         case VIDIOCSFBUF:
864         case VIDIOCKEY:
865         case VIDIOCGFREQ:
866         case VIDIOCSFREQ:
867         case VIDIOCGAUDIO:
868         case VIDIOCSAUDIO:
869                 return -EINVAL;
870         default:
871                 return -ENOIOCTLCMD;
872         }
873         return 0;
874 }
875
876 static long w9966_v4l_ioctl(struct file *file,
877                            unsigned int cmd, unsigned long arg)
878 {
879         return video_usercopy(file, cmd, arg, w9966_v4l_do_ioctl);
880 }
881
882 // Capture data
883 static ssize_t w9966_v4l_read(struct file *file, char  __user *buf,
884                               size_t count, loff_t *ppos)
885 {
886         struct w9966_dev *cam = video_drvdata(file);
887         unsigned char addr = 0xa0;      // ECP, read, CCD-transfer, 00000
888         unsigned char __user *dest = (unsigned char __user *)buf;
889         unsigned long dleft = count;
890         unsigned char *tbuf;
891
892         // Why would anyone want more than this??
893         if (count > cam->width * cam->height * 2)
894                 return -EINVAL;
895
896         w9966_pdev_claim(cam);
897         w9966_wReg(cam, 0x00, 0x02);    // Reset ECP-FIFO buffer
898         w9966_wReg(cam, 0x00, 0x00);    // Return to normal operation
899         w9966_wReg(cam, 0x01, 0x98);    // Enable capture
900
901         // write special capture-addr and negotiate into data transfer
902         if (
903                 (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0  )||
904                 (parport_write(cam->pport, &addr, 1) != 1                                               )||
905                 (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0  )
906         ) {
907                 w9966_pdev_release(cam);
908                 return -EFAULT;
909         }
910
911         tbuf = kmalloc(W9966_RBUFFER, GFP_KERNEL);
912         if (tbuf == NULL) {
913                 count = -ENOMEM;
914                 goto out;
915         }
916
917         while(dleft > 0)
918         {
919                 unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft;
920
921                 if (parport_read(cam->pport, tbuf, tsize) < tsize) {
922                         count = -EFAULT;
923                         goto out;
924                 }
925                 if (copy_to_user(dest, tbuf, tsize) != 0) {
926                         count = -EFAULT;
927                         goto out;
928                 }
929                 dest += tsize;
930                 dleft -= tsize;
931         }
932
933         w9966_wReg(cam, 0x01, 0x18);    // Disable capture
934
935 out:
936         kfree(tbuf);
937         w9966_pdev_release(cam);
938
939         return count;
940 }
941
942
943 // Called once for every parport on init
944 static void w9966_attach(struct parport *port)
945 {
946         int i;
947
948         for (i = 0; i < W9966_MAXCAMS; i++)
949         {
950                 if (w9966_cams[i].dev_state != 0)       // Cam is already assigned
951                         continue;
952                 if (
953                         strcmp(pardev[i], "aggressive") == 0 ||
954                         strcmp(pardev[i], port->name) == 0
955                 ) {
956                         if (w9966_init(&w9966_cams[i], port) != 0)
957                         w9966_term(&w9966_cams[i]);
958                         break;  // return
959                 }
960         }
961 }
962
963 // Called once for every parport on termination
964 static void w9966_detach(struct parport *port)
965 {
966         int i;
967         for (i = 0; i < W9966_MAXCAMS; i++)
968         if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port)
969                 w9966_term(&w9966_cams[i]);
970 }
971
972
973 static struct parport_driver w9966_ppd = {
974         .name = W9966_DRIVERNAME,
975         .attach = w9966_attach,
976         .detach = w9966_detach,
977 };
978
979 // Module entry point
980 static int __init w9966_mod_init(void)
981 {
982         int i;
983         for (i = 0; i < W9966_MAXCAMS; i++)
984                 w9966_cams[i].dev_state = 0;
985
986         return parport_register_driver(&w9966_ppd);
987 }
988
989 // Module cleanup
990 static void __exit w9966_mod_term(void)
991 {
992         parport_unregister_driver(&w9966_ppd);
993 }
994
995 module_init(w9966_mod_init);
996 module_exit(w9966_mod_term);