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