1/* 2 Winbond w9966cf Webcam parport driver. 3 4 Copyright (C) 2001 Jakob Kemi <jakob.kemi@telia.com> 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20/* 21 Supported devices: 22 * Lifeview Flycam Supra (Philips saa7111a chip) 23 24 * Mikrotek Eyestar2 (Sanyo lc99053 chip) 25 Very rudimentary support, total lack of ccd-control chip settings. 26 Only green video data and no image properties (brightness, etc..) 27 If anyone can parse the Japanese data-sheet for the Sanyo lc99053 28 chip, feel free to help. 29 <http://service.semic.sanyo.co.jp/semi/ds_pdf_j/LC99053.pdf> 30 Thanks to Steven Griffiths <steve@sgriff.com> and 31 James Murray <jsm@jsm-net.demon.co.uk> for testing. 32 33 Todo: 34 * Add a working EPP mode (Is this a parport or a w9966 issue?) 35 * Add proper probing. IEEE1284 probing of w9966 chips haven't 36 worked since parport drivers changed in 2.4.x. 37 * Probe for onboard SRAM, port directions etc. (possible?) 38 39 Changes: 40 41 Alan Cox: Removed RGB mode for kernel merge, added THIS_MODULE 42 and owner support for newer module locks 43*/ 44 45#include <linux/module.h> 46#include <linux/init.h> 47#include <linux/delay.h> 48#include <linux/videodev.h> 49#include <linux/parport.h> 50#include <linux/types.h> 51#include <linux/slab.h> 52 53//#define DEBUG // Define for debug output. 54 55#ifdef DEBUG 56# define DPRINTF(f, a...) \ 57 do { \ 58 printk ("%s%s, %d (DEBUG) %s(): ", \ 59 KERN_DEBUG, __FILE__, __LINE__, __func__); \ 60 printk (f, ##a); \ 61 } while (0) 62# define DASSERT(x) \ 63 do { \ 64 if (!x) \ 65 DPRINTF("Assertion failed at line %d.\n", __LINE__); \ 66 } while (0) 67#else 68# define DPRINTF(f, a...) do {} while(0) 69# define DASSERT(f, a...) do {} while(0) 70#endif 71 72/* 73 * Defines, simple typedefs etc. 74 */ 75 76#define W9966_DRIVERNAME "w9966cf" 77#define W9966_MAXCAMS 4 // Maximum number of cameras 78#define W9966_RBUFFER 8096 // Read buffer (must be an even number) 79 80#define W9966_WND_MIN_W 2 81#define W9966_WND_MIN_H 1 82 83// Keep track of our current state 84#define W9966_STATE_PDEV 0x01 // pdev registered 85#define W9966_STATE_CLAIMED 0x02 // pdev claimed 86#define W9966_STATE_VDEV 0x04 // vdev registered 87#define W9966_STATE_BUFFER 0x08 // buffer allocated 88#define W9966_STATE_DETECTED 0x10 // model identified 89 90#define W9966_SAA7111_ID 0x24 // I2C device id 91 92#define W9966_I2C_UDELAY 5 93#define W9966_I2C_TIMEOUT 100 94#define W9966_I2C_R_DATA 0x08 95#define W9966_I2C_R_CLOCK 0x04 96#define W9966_I2C_W_DATA 0x02 97#define W9966_I2C_W_CLOCK 0x01 98 99#define MAX(a, b) ((a > b) ? a : b) 100#define MIN(a, b) ((a > b) ? b : a) 101 102struct w9966_dev { 103 struct video_device vdev; 104 struct parport* pport; 105 struct pardevice* pdev; 106 int ppmode; 107 108 u8* buffer; 109 u8 dev_state; 110 u8 i2c_state; 111 u16 width; 112 u16 height; 113 114 // Image properties 115 u8 brightness; 116 s8 contrast; 117 s8 color; 118 s8 hue; 119 120 // Model specific: 121 const char* name; 122 u32 sramsize; 123 u8 sramid; // reg 0x0c, bank layout 124 u8 cmask; // reg 0x01, for polarity 125 u16 min_x, max_x; // Capture window limits 126 u16 min_y, max_y; 127 int (*image)(struct w9966_dev* cam); 128}; 129 130/* 131 * Module properties 132 */ 133 134MODULE_AUTHOR("Jakob Kemi <jakob.kemi@telia.com>"); 135MODULE_DESCRIPTION("Winbond w9966cf webcam driver (Flycam Supra and others)"); 136MODULE_LICENSE("GPL"); 137 138 139static const char* pardev[] = {[0 ... W9966_MAXCAMS-1] = "auto"}; 140MODULE_PARM(pardev, "0-" __MODULE_STRING(W9966_MAXCAMS) "s"); 141MODULE_PARM_DESC(pardev,"\n\ 142<auto|name|none[,...]> Where to find cameras.\n\ 143 auto = probe all parports for camera (default)\n\ 144 name = name of parport (eg parport0)\n\ 145 none = don't use this camera\n\ 146You can specify all cameras this way, for example:\n\ 147 pardev=parport2,auto,none,parport0 would search for cam1 on parport2, search\n\ 148 for cam2 on all parports, skip cam3 and search for cam4 on parport0"); 149 150static int parmode = 1; 151MODULE_PARM(parmode, "i"); 152MODULE_PARM_DESC(parmode, "\n<0|1|2|3> transfer mode (0=auto, 1=ecp(default), 2=epp, 3=forced hw-ecp)"); 153 154static int video_nr[] = {[0 ... W9966_MAXCAMS-1] = -1}; 155MODULE_PARM(video_nr, "0-" __MODULE_STRING(W9966_MAXCAMS) "i"); 156MODULE_PARM_DESC(video_nr,"\n\ 157<-1|n[,...]> Specify V4L minor mode number.\n\ 158 -1 = use next available (default)\n\ 159 n = use minor number n (integer >= 0)\n\ 160You can specify all cameras this way, for example:\n\ 161 video_nr=-1,2,-1 would assign minor number 2 for cam2 and use auto for cam1,\n\ 162 cam3 and cam4"); 163 164/* 165 * Private data 166 */ 167 168static struct w9966_dev* w9966_cams; 169 170/* 171 * Private function declarations 172 */ 173 174static inline void w9966_flag_set(struct w9966_dev* cam, int flag) { 175 cam->dev_state |= flag;} 176 177static inline void w9966_flag_clear(struct w9966_dev* cam, int flag) { 178 cam->dev_state &= ~flag;} 179 180static inline int w9966_flag_test(struct w9966_dev* cam, int flag) { 181 return (cam->dev_state & flag);} 182 183static inline int w9966_pdev_claim(struct w9966_dev *vdev); 184static inline void w9966_pdev_release(struct w9966_dev *vdev); 185 186static int w9966_rreg(struct w9966_dev* cam, int reg); 187static int w9966_wreg(struct w9966_dev* cam, int reg, int data); 188 189static int w9966_init(struct w9966_dev* cam, struct parport* port, int vidnr); 190static void w9966_term(struct w9966_dev* cam); 191static int w9966_setup(struct w9966_dev* cam); 192static int w9966_findlen(int near, int size, int maxlen); 193static int w9966_calcscale(int size, int min, int max, 194 int* beg, int* end, u8* factor); 195static int w9966_window(struct w9966_dev* cam, int x1, int y1, 196 int x2, int y2, int w, int h); 197 198static int w9966_saa7111_init(struct w9966_dev* cam); 199static int w9966_saa7111_image(struct w9966_dev* cam); 200static int w9966_lc99053_init(struct w9966_dev* cam); 201static int w9966_lc99053_image(struct w9966_dev* cam); 202 203static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state); 204static inline int w9966_i2c_setscl(struct w9966_dev* cam, int state); 205static inline int w9966_i2c_getsda(struct w9966_dev* cam); 206static inline int w9966_i2c_getscl(struct w9966_dev* cam); 207static int w9966_i2c_wbyte(struct w9966_dev* cam, int data); 208static int w9966_i2c_rbyte(struct w9966_dev* cam); 209static int w9966_i2c_rreg(struct w9966_dev* cam, int device, int reg); 210static int w9966_i2c_wreg(struct w9966_dev* cam, int device, int reg, int data); 211 212static int w9966_v4l_open(struct video_device *vdev, int mode); 213static void w9966_v4l_close(struct video_device *vdev); 214static int w9966_v4l_ioctl(struct video_device *vdev, 215 unsigned int cmd, void *arg); 216static long w9966_v4l_read(struct video_device *vdev, 217 char *buf, unsigned long count, int noblock); 218 219/* 220 * Private function definitions 221 */ 222 223// Claim parport for ourself 224// 1 on success, else 0 225static inline int w9966_pdev_claim(struct w9966_dev* cam) 226{ 227 if (w9966_flag_test(cam, W9966_STATE_CLAIMED)) 228 return 1; 229 if (parport_claim_or_block(cam->pdev) < 0) 230 return 0; 231 w9966_flag_set(cam, W9966_STATE_CLAIMED); 232 return 1; 233} 234 235// Release parport for others to use 236static inline void w9966_pdev_release(struct w9966_dev* cam) 237{ 238 if (!w9966_flag_test(cam, W9966_STATE_CLAIMED)) 239 return; 240 parport_release(cam->pdev); 241 w9966_flag_clear(cam, W9966_STATE_CLAIMED); 242} 243 244// Read register from w9966 interface-chip 245// Expects a claimed pdev 246// -1 on error, else register data (byte) 247static int w9966_rreg(struct w9966_dev* cam, int reg) 248{ 249 // ECP, read, regtransfer, REG, REG, REG, REG, REG 250 const u8 addr = 0x80 | (reg & 0x1f); 251 u8 val; 252 253 if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0 || 254 parport_write(cam->pport, &addr, 1) != 1 || 255 parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0 || 256 parport_read(cam->pport, &val, 1) != 1) 257 return -1; 258 259 return val; 260} 261 262// Write register to w9966 interface-chip 263// Expects a claimed pdev 264// 1 on success, else 0 265static int w9966_wreg(struct w9966_dev* cam, int reg, int data) 266{ 267 // ECP, write, regtransfer, REG, REG, REG, REG, REG 268 const u8 addr = 0xc0 | (reg & 0x1f); 269 const u8 val = data; 270 271 if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0 || 272 parport_write(cam->pport, &addr, 1) != 1 || 273 parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0 || 274 parport_write(cam->pport, &val, 1) != 1) 275 return 0; 276 277 return 1; 278} 279 280// Initialize camera device. Setup all internal flags, set a 281// default video mode, setup ccd-chip, register v4l device etc.. 282// Also used for 'probing' of hardware. 283// 1 on success, else 0 284static int w9966_init(struct w9966_dev* cam, struct parport* port, int vidnr) 285{ 286 if (cam->dev_state != 0) 287 return 0; 288 289 cam->pport = port; 290 cam->brightness = 128; 291 cam->contrast = 64; 292 cam->color = 64; 293 cam->hue = 0; 294 295 // Select requested transfer mode 296 switch(parmode) 297 { 298 default: // Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) 299 case 0: 300 if (port->modes & PARPORT_MODE_ECP) 301 cam->ppmode = IEEE1284_MODE_ECP; 302 else if (port->modes & PARPORT_MODE_EPP) 303 cam->ppmode = IEEE1284_MODE_EPP; 304 else 305 cam->ppmode = IEEE1284_MODE_ECPSWE; 306 break; 307 case 1: // hw- or sw-ecp 308 if (port->modes & PARPORT_MODE_ECP) 309 cam->ppmode = IEEE1284_MODE_ECP; 310 else 311 cam->ppmode = IEEE1284_MODE_ECPSWE; 312 break; 313 case 2: // hw- or sw-epp 314 if (port->modes & PARPORT_MODE_EPP) 315 cam->ppmode = IEEE1284_MODE_EPP; 316 else 317 cam->ppmode = IEEE1284_MODE_EPPSWE; 318 break; 319 case 3: // hw-ecp 320 cam->ppmode = IEEE1284_MODE_ECP; 321 break; 322 } 323 324 // Tell the parport driver that we exists 325 cam->pdev = parport_register_device( 326 port, W9966_DRIVERNAME, NULL, NULL, NULL, 0, NULL); 327 328 if (cam->pdev == NULL) { 329 DPRINTF("parport_register_device() failed.\n"); 330 return 0; 331 } 332 w9966_flag_set(cam, W9966_STATE_PDEV); 333 334 // Claim parport 335 if (!w9966_pdev_claim(cam)) { 336 DPRINTF("w9966_pdev_claim() failed.\n"); 337 return 0; 338 } 339 340 // Perform initial w9966 setup 341 if (!w9966_setup(cam)) { 342 DPRINTF("w9966_setup() failed.\n"); 343 return 0; 344 } 345 346 // Detect model 347 if (!w9966_saa7111_init(cam)) { 348 DPRINTF("w9966_saa7111_init() failed.\n"); 349 return 0; 350 } 351 if (!w9966_lc99053_init(cam)) { 352 DPRINTF("w9966_lc99053_init() failed.\n"); 353 return 0; 354 } 355 if (!w9966_flag_test(cam, W9966_STATE_DETECTED)) { 356 DPRINTF("Camera model not identified.\n"); 357 return 0; 358 } 359 360 // Setup w9966 with a default capture mode (QCIF res.) 361 if (!w9966_window(cam, 0, 0, 1023, 1023, 176, 144)) { 362 DPRINTF("w9966_window() failed.\n"); 363 return 0; 364 } 365 w9966_pdev_release(cam); 366 367 // Fill in the video_device struct and register us to v4l 368 memset(&cam->vdev, 0, sizeof(struct video_device)); 369 strcpy(cam->vdev.name, W9966_DRIVERNAME); 370 cam->vdev.type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; 371 cam->vdev.hardware = VID_HARDWARE_W9966; 372 cam->vdev.open = &w9966_v4l_open; 373 cam->vdev.close = &w9966_v4l_close; 374 cam->vdev.read = &w9966_v4l_read; 375 cam->vdev.ioctl = &w9966_v4l_ioctl; 376 cam->vdev.priv = (void*)cam; 377 cam->vdev.owner = THIS_MODULE; 378 379 if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, vidnr) == -1) { 380 DPRINTF("video_register_device() failed (minor: %d).\n", vidnr); 381 return 0; 382 } 383 w9966_flag_set(cam, W9966_STATE_VDEV); 384 385 // All ok 386 printk("w9966: Found and initialized %s on %s.\n", 387 cam->name, cam->pport->name); 388 return 1; 389} 390 391// Terminate everything gracefully 392static void w9966_term(struct w9966_dev* cam) 393{ 394 // Delete allocated buffer 395 if (w9966_flag_test(cam, W9966_STATE_BUFFER)) 396 kfree(cam->buffer); 397 398 // Unregister from v4l 399 if (w9966_flag_test(cam, W9966_STATE_VDEV)) 400 video_unregister_device(&cam->vdev); 401 402 // Terminate from IEEE1284 mode and unregister from parport 403 if (w9966_flag_test(cam, W9966_STATE_PDEV)) { 404 if (w9966_pdev_claim(cam)) 405 parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT); 406 407 w9966_pdev_release(cam); 408 parport_unregister_device(cam->pdev); 409 } 410 411 cam->dev_state = 0x00; 412} 413 414// Do initial setup for the w9966 chip, init i2c bus, etc. 415// this is generic for all models 416// expects a claimed pdev 417// 1 on success, else 0 418static int w9966_setup(struct w9966_dev* cam) 419{ 420 const u8 i2c = cam->i2c_state = W9966_I2C_W_DATA | W9966_I2C_W_CLOCK; 421 const u8 regs[] = { 422 0x40, // 0x13 - VEE control (raw 4:2:2) 423 0x00, 0x00, 0x00, // 0x14 - 0x16 424 0x00, // 0x17 - ??? 425 i2c, // 0x18 - Serial bus 426 0xff, // 0x19 - I/O port direction control 427 0xff, // 0x1a - I/O port data register 428 0x10 // 0x1b - ??? 429 }; 430 int i; 431 432 DASSERT(w9966_flag_test(cam, W9966_STATE_CLAIMED)); 433 434 // Reset (ECP-fifo & serial-bus) 435 if (!w9966_wreg(cam, 0x00, 0x03) || 436 !w9966_wreg(cam, 0x00, 0x00)) 437 return 0; 438 439 // Write regs to w9966cf chip 440 for (i = 0x13; i < 0x1c; i++) 441 if (!w9966_wreg(cam, i, regs[i-0x13])) 442 return 0; 443 444 return 1; 445} 446 447// Find a good length for capture window (used both for W and H) 448// A bit ugly but pretty functional. The capture length 449// have to match the downscale 450static int w9966_findlen(int near, int size, int maxlen) 451{ 452 int bestlen = size; 453 int besterr = abs(near - bestlen); 454 int len; 455 456 for(len = size+1; len < maxlen; len++) 457 { 458 int err; 459 if ( ((64*size) %len) != 0) 460 continue; 461 462 err = abs(near - len); 463 464 // Only continue as long as we keep getting better values 465 if (err > besterr) 466 break; 467 468 besterr = err; 469 bestlen = len; 470 } 471 472 return bestlen; 473} 474 475// Modify capture window (if necessary) 476// and calculate downscaling 477// 1 on success, else 0 478static int w9966_calcscale(int size, int min, int max, int* beg, int* end, u8* factor) 479{ 480 const int maxlen = max - min; 481 const int len = *end - *beg + 1; 482 const int newlen = w9966_findlen(len, size, maxlen); 483 const int err = newlen - len; 484 485 // Check for bad format 486 if (newlen > maxlen || newlen < size) 487 return 0; 488 489 // Set factor (6 bit fixed) 490 *factor = (64*size) / newlen; 491 if (*factor == 64) 492 *factor = 0x00; // downscale is disabled 493 else 494 *factor |= 0x80; // set downscale-enable bit 495 496 // Modify old beginning and end 497 *beg -= err / 2; 498 *end += err - (err / 2); 499 500 // Move window if outside borders 501 if (*beg < min) { 502 *end += min - *beg; 503 *beg += min - *beg; 504 } 505 if (*end > max) { 506 *beg -= *end - max; 507 *end -= *end - max; 508 } 509 510 return 1; 511} 512 513// Setup the w9966 capture window and also set SRAM settings 514// expects a claimed pdev and detected camera model 515// 1 on success, else 0 516static int w9966_window(struct w9966_dev* cam, int x1, int y1, int x2, int y2, int w, int h) 517{ 518 unsigned int enh_s, enh_e; 519 u8 scale_x, scale_y; 520 u8 regs[0x13]; 521 int i; 522 523 // Modify width and height to match capture window and SRAM 524 w = MAX(W9966_WND_MIN_W, w); 525 h = MAX(W9966_WND_MIN_H, h); 526 w = MIN(cam->max_x - cam->min_x, w); 527 h = MIN(cam->max_y - cam->min_y, h); 528 w &= ~0x1; 529 if (w*h*2 > cam->sramsize) 530 h = cam->sramsize / (w*2); 531 532 cam->width = w; 533 cam->height = h; 534 535 enh_s = 0; 536 enh_e = w*h*2; 537 538 // Calculate downscaling 539 if (!w9966_calcscale(w, cam->min_x, cam->max_x, &x1, &x2, &scale_x) || 540 !w9966_calcscale(h, cam->min_y, cam->max_y, &y1, &y2, &scale_y)) 541 return 0; 542 543 DPRINTF("%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n", 544 w, h, x1, x2, y1, y2, scale_x&~0x80, scale_y&~0x80); 545 546 // Setup registers 547 regs[0x00] = 0x00; // Set normal operation 548 regs[0x01] = cam->cmask; // Capture mode 549 regs[0x02] = scale_y; // V-scaling 550 regs[0x03] = scale_x; // H-scaling 551 552 // Capture window 553 regs[0x04] = (x1 & 0x0ff); // X-start (8 low bits) 554 regs[0x05] = (x1 & 0x300)>>8; // X-start (2 high bits) 555 regs[0x06] = (y1 & 0x0ff); // Y-start (8 low bits) 556 regs[0x07] = (y1 & 0x300)>>8; // Y-start (2 high bits) 557 regs[0x08] = (x2 & 0x0ff); // X-end (8 low bits) 558 regs[0x09] = (x2 & 0x300)>>8; // X-end (2 high bits) 559 regs[0x0a] = (y2 & 0x0ff); // Y-end (8 low bits) 560 561 regs[0x0c] = cam->sramid; // SRAM layout 562 563 // Enhancement layer 564 regs[0x0d] = (enh_s& 0x000ff); // Enh. start (0-7) 565 regs[0x0e] = (enh_s& 0x0ff00)>>8; // Enh. start (8-15) 566 regs[0x0f] = (enh_s& 0x70000)>>16; // Enh. start (16-17/18??) 567 regs[0x10] = (enh_e& 0x000ff); // Enh. end (0-7) 568 regs[0x11] = (enh_e& 0x0ff00)>>8; // Enh. end (8-15) 569 regs[0x12] = (enh_e& 0x70000)>>16; // Enh. end (16-17/18??) 570 571 // Write regs to w9966cf chip 572 for (i = 0x01; i < 0x13; i++) 573 if (!w9966_wreg(cam, i, regs[i])) 574 return 0; 575 576 return 1; 577} 578 579// Detect and initialize saa7111 ccd-controller chip. 580// expects a claimed parport 581// expected to always return 1 unless error is _fatal_ 582// 1 on success, else 0 583static int w9966_saa7111_init(struct w9966_dev* cam) 584{ 585 // saa7111 regs 0x00 trough 0x12 586 const u8 regs[] = { 587 0x00, // not written 588 0x00, 0xd8, 0x23, 0x00, 0x80, 0x80, 0x00, 0x88, 0x10, 589 cam->brightness, // 0x0a 590 cam->contrast, // 0x0b 591 cam->color, // 0x0c 592 cam->hue, // 0x0d 593 0x01, 0x00, 0x48, 0x0c, 0x00, 594 }; 595 int i; 596 597 if (w9966_flag_test(cam, W9966_STATE_DETECTED)) 598 return 1; 599 600 // Write regs to saa7111 chip 601 for (i = 1; i < 0x13; i++) 602 if (!w9966_i2c_wreg(cam, W9966_SAA7111_ID, i, regs[i])) 603 return 1; 604 605 // Read back regs 606 for (i = 1; i < 0x13; i++) 607 if (w9966_i2c_rreg(cam, W9966_SAA7111_ID, i) != regs[i]) 608 return 1; 609 610 // Fill in model specific data 611 cam->name = "Lifeview Flycam Supra"; 612 cam->sramsize = 128 << 10; // 128 kib 613 cam->sramid = 0x02; // see w9966.pdf 614 615 cam->cmask = 0x18; // normal polarity 616 cam->min_x = 16; // empirically determined 617 cam->max_x = 705; 618 cam->min_y = 14; 619 cam->max_y = 253; 620 cam->image = &w9966_saa7111_image; 621 622 DPRINTF("Found and initialized a saa7111 chip.\n"); 623 w9966_flag_set(cam, W9966_STATE_DETECTED); 624 625 return 1; 626} 627 628// Setup image properties (brightness, hue, etc.) for the saa7111 chip 629// expects a claimed parport 630// 1 on success, else 0 631static int w9966_saa7111_image(struct w9966_dev* cam) 632{ 633 if (!w9966_i2c_wreg(cam, W9966_SAA7111_ID, 0x0a, cam->brightness) || 634 !w9966_i2c_wreg(cam, W9966_SAA7111_ID, 0x0b, cam->contrast) || 635 !w9966_i2c_wreg(cam, W9966_SAA7111_ID, 0x0c, cam->color) || 636 !w9966_i2c_wreg(cam, W9966_SAA7111_ID, 0x0d, cam->hue)) 637 return 0; 638 639 return 1; 640} 641 642// Detect and initialize lc99053 ccd-controller chip. 643// expects a claimed parport 644// this is currently a hack, no detection is done, we just assume an Eyestar2 645// 1 on success, else 0 646static int w9966_lc99053_init(struct w9966_dev* cam) 647{ 648 if (w9966_flag_test(cam, W9966_STATE_DETECTED)) 649 return 1; 650 651 // Fill in model specific data 652 cam->name = "Microtek Eyestar2"; 653 cam->sramsize = 128 << 10; // 128 kib 654 cam->sramid = 0x02; // w9966cf.pdf 655 656 cam->cmask = 0x10; // reverse polarity 657 cam->min_x = 16; // empirically determined 658 cam->max_x = 705; 659 cam->min_y = 14; 660 cam->max_y = 253; 661 cam->image = &w9966_lc99053_image; 662 663 DPRINTF("Found and initialized a lc99053 chip.\n"); 664 w9966_flag_set(cam, W9966_STATE_DETECTED); 665 666 return 1; 667} 668 669// Setup image properties (brightness, hue, etc.) for the lc99053 chip 670// expects a claimed parport 671// 1 on success, else 0 672static int w9966_lc99053_image(struct w9966_dev* cam) 673{ 674 return 1; 675} 676 677/* 678 * Ugly and primitive i2c protocol functions 679 */ 680 681// Sets the data line on the i2c bus. 682// Expects a claimed pdev. 683static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state) 684{ 685 if (state) 686 cam->i2c_state |= W9966_I2C_W_DATA; 687 else 688 cam->i2c_state &= ~W9966_I2C_W_DATA; 689 690 w9966_wreg(cam, 0x18, cam->i2c_state); 691 udelay(W9966_I2C_UDELAY); 692} 693 694// Sets the clock line on the i2c bus. 695// Expects a claimed pdev. 696// 1 on success, else 0 697static inline int w9966_i2c_setscl(struct w9966_dev* cam, int state) 698{ 699 if (state) 700 cam->i2c_state |= W9966_I2C_W_CLOCK; 701 else 702 cam->i2c_state &= ~W9966_I2C_W_CLOCK; 703 704 w9966_wreg(cam, 0x18, cam->i2c_state); 705 udelay(W9966_I2C_UDELAY); 706 707 // when we go to high, we also expect the peripheral to ack. 708 if (state) { 709 const int timeout = jiffies + W9966_I2C_TIMEOUT; 710 while (!w9966_i2c_getscl(cam)) { 711 if (time_after(jiffies, timeout)) 712 return 0; 713 } 714 } 715 return 1; 716} 717 718// Get peripheral data line 719// Expects a claimed pdev. 720static inline int w9966_i2c_getsda(struct w9966_dev* cam) 721{ 722 const u8 pins = w9966_rreg(cam, 0x18); 723 return ((pins & W9966_I2C_R_DATA) > 0); 724} 725 726// Get peripheral clock line 727// Expects a claimed pdev. 728static inline int w9966_i2c_getscl(struct w9966_dev* cam) 729{ 730 const u8 pins = w9966_rreg(cam, 0x18); 731 return ((pins & W9966_I2C_R_CLOCK) > 0); 732} 733 734// Write a byte with ack to the i2c bus. 735// Expects a claimed pdev. 736// 1 on success, else 0 737static int w9966_i2c_wbyte(struct w9966_dev* cam, int data) 738{ 739 int i; 740 for (i = 7; i >= 0; i--) { 741 w9966_i2c_setsda(cam, (data >> i) & 0x01); 742 743 if (!w9966_i2c_setscl(cam, 1) || 744 !w9966_i2c_setscl(cam, 0)) 745 return 0; 746 } 747 w9966_i2c_setsda(cam, 1); 748 749 if (!w9966_i2c_setscl(cam, 1) || 750 !w9966_i2c_setscl(cam, 0)) 751 return 0; 752 753 return 1; 754} 755 756// Read a data byte with ack from the i2c-bus 757// Expects a claimed pdev. -1 on error 758static int w9966_i2c_rbyte(struct w9966_dev* cam) 759{ 760 u8 data = 0x00; 761 int i; 762 763 w9966_i2c_setsda(cam, 1); 764 765 for (i = 0; i < 8; i++) 766 { 767 if (!w9966_i2c_setscl(cam, 1)) 768 return -1; 769 data = data << 1; 770 if (w9966_i2c_getsda(cam)) 771 data |= 0x01; 772 773 w9966_i2c_setscl(cam, 0); 774 } 775 return data; 776} 777 778// Read a register from the i2c device. 779// Expects claimed pdev. -1 on error 780static int w9966_i2c_rreg(struct w9966_dev* cam, int device, int reg) 781{ 782 int data; 783 784 w9966_i2c_setsda(cam, 0); 785 w9966_i2c_setscl(cam, 0); 786 787 if (!w9966_i2c_wbyte(cam, device << 1) || 788 !w9966_i2c_wbyte(cam, reg)) 789 return -1; 790 791 w9966_i2c_setsda(cam, 1); 792 if (!w9966_i2c_setscl(cam, 1)) 793 return -1; 794 795 w9966_i2c_setsda(cam, 0); 796 w9966_i2c_setscl(cam, 0); 797 798 if (!w9966_i2c_wbyte(cam, (device << 1) | 1) || 799 (data = w9966_i2c_rbyte(cam)) == -1) 800 return -1; 801 802 w9966_i2c_setsda(cam, 0); 803 804 if (!w9966_i2c_setscl(cam, 1)) 805 return -1; 806 807 w9966_i2c_setsda(cam, 1); 808 809 return data; 810} 811 812// Write a register to the i2c device. 813// Expects claimed pdev. 814// 1 on success, else 0 815static int w9966_i2c_wreg(struct w9966_dev* cam, int device, int reg, int data) 816{ 817 w9966_i2c_setsda(cam, 0); 818 w9966_i2c_setscl(cam, 0); 819 820 if (!w9966_i2c_wbyte(cam, device << 1) || 821 !w9966_i2c_wbyte(cam, reg) || 822 !w9966_i2c_wbyte(cam, data)) 823 return 0; 824 825 w9966_i2c_setsda(cam, 0); 826 if (!w9966_i2c_setscl(cam, 1)) 827 return 0; 828 829 w9966_i2c_setsda(cam, 1); 830 831 return 1; 832} 833 834/* 835 * Video4linux interface 836 */ 837 838static int w9966_v4l_open(struct video_device *vdev, int flags) 839{ 840 struct w9966_dev *cam = (struct w9966_dev*)vdev->priv; 841 842 // Claim parport 843 if (!w9966_pdev_claim(cam)) { 844 DPRINTF("Unable to claim parport"); 845 return -EFAULT; 846 } 847 848 // Allocate read buffer 849 cam->buffer = (u8*)kmalloc(W9966_RBUFFER, GFP_KERNEL); 850 if (cam->buffer == NULL) { 851 w9966_pdev_release(cam); 852 return -ENOMEM; 853 } 854 w9966_flag_set(cam, W9966_STATE_BUFFER); 855 856 return 0; 857} 858 859static void w9966_v4l_close(struct video_device *vdev) 860{ 861 struct w9966_dev *cam = (struct w9966_dev*)vdev->priv; 862 863 // Free read buffer 864 if (w9966_flag_test(cam, W9966_STATE_BUFFER)) { 865 kfree(cam->buffer); 866 w9966_flag_clear(cam, W9966_STATE_BUFFER); 867 } 868 869 // release parport 870 w9966_pdev_release(cam); 871} 872 873// expects a claimed parport 874static int w9966_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) 875{ 876 struct w9966_dev *cam = (struct w9966_dev*)vdev->priv; 877 878 switch(cmd) 879 { 880 case VIDIOCGCAP: 881 { 882 struct video_capability vcap = { 883 W9966_DRIVERNAME, // name 884 VID_TYPE_CAPTURE | VID_TYPE_SCALES, // type 885 1, 0, // vid, aud channels 886 cam->max_x - cam->min_x, 887 cam->max_y - cam->min_y, 888 W9966_WND_MIN_W, 889 W9966_WND_MIN_H 890 }; 891 892 if(copy_to_user(arg, &vcap, sizeof(vcap)) != 0) 893 return -EFAULT; 894 895 return 0; 896 } 897 case VIDIOCGCHAN: 898 { 899 struct video_channel vch; 900 if(copy_from_user(&vch, arg, sizeof(vch)) != 0) 901 return -EFAULT; 902 903 if(vch.channel != 0) // We only support one channel (#0) 904 return -EINVAL; 905 906 strcpy(vch.name, "CCD-input"); 907 vch.flags = 0; // We have no tuner or audio 908 vch.tuners = 0; 909 vch.type = VIDEO_TYPE_CAMERA; 910 vch.norm = 0; // ??? 911 912 if(copy_to_user(arg, &vch, sizeof(vch)) != 0) 913 return -EFAULT; 914 915 return 0; 916 } 917 case VIDIOCSCHAN: 918 { 919 struct video_channel vch; 920 if(copy_from_user(&vch, arg, sizeof(vch) ) != 0) 921 return -EFAULT; 922 923 if(vch.channel != 0) 924 return -EINVAL; 925 926 return 0; 927 } 928 case VIDIOCGTUNER: 929 { 930 struct video_tuner vtune; 931 if(copy_from_user(&vtune, arg, sizeof(vtune)) != 0) 932 return -EFAULT; 933 934 if(vtune.tuner != 0); 935 return -EINVAL; 936 937 strcpy(vtune.name, "no tuner"); 938 vtune.rangelow = 0; 939 vtune.rangehigh = 0; 940 vtune.flags = VIDEO_TUNER_NORM; 941 vtune.mode = VIDEO_MODE_AUTO; 942 vtune.signal = 0xffff; 943 944 if(copy_to_user(arg, &vtune, sizeof(vtune)) != 0) 945 return -EFAULT; 946 947 return 0; 948 } 949 case VIDIOCSTUNER: 950 { 951 struct video_tuner vtune; 952 if (copy_from_user(&vtune, arg, sizeof(vtune)) != 0) 953 return -EFAULT; 954 955 if (vtune.tuner != 0) 956 return -EINVAL; 957 958 if (vtune.mode != VIDEO_MODE_AUTO) 959 return -EINVAL; 960 961 return 0; 962 } 963 case VIDIOCGPICT: 964 { 965 struct video_picture vpic = { 966 cam->brightness << 8, // brightness 967 (cam->hue + 128) << 8, // hue 968 cam->color << 9, // color 969 cam->contrast << 9, // contrast 970 0x8000, // whiteness 971 16, VIDEO_PALETTE_YUV422// bpp, palette format 972 }; 973 974 if(copy_to_user(arg, &vpic, sizeof(vpic)) != 0) 975 return -EFAULT; 976 977 return 0; 978 } 979 case VIDIOCSPICT: 980 { 981 struct video_picture vpic; 982 if(copy_from_user(&vpic, arg, sizeof(vpic)) != 0) 983 return -EFAULT; 984 985 if (vpic.depth != 16 || vpic.palette != VIDEO_PALETTE_YUV422) 986 return -EINVAL; 987 988 cam->brightness = vpic.brightness >> 8; 989 cam->hue = (vpic.hue >> 8) - 128; 990 cam->color = vpic.colour >> 9; 991 cam->contrast = vpic.contrast >> 9; 992 993 if (!cam->image(cam)) 994 return -EFAULT; 995 996 return 0; 997 } 998 case VIDIOCSWIN: 999 { 1000 struct video_window vwin; 1001 1002 if (copy_from_user(&vwin, arg, sizeof(vwin)) != 0) 1003 return -EFAULT; 1004 if ( 1005 vwin.flags != 0 || 1006 vwin.clipcount != 0) 1007 return -EINVAL; 1008 1009 if (vwin.width > cam->max_x - cam->min_x || 1010 vwin.height > cam->max_y - cam->min_y || 1011 vwin.width < W9966_WND_MIN_W || 1012 vwin.height < W9966_WND_MIN_H) 1013 return -EINVAL; 1014 1015 // Update camera regs 1016 if (!w9966_window(cam, 0, 0, 1023, 1023, vwin.width, vwin.height)) 1017 return -EFAULT; 1018 1019 return 0; 1020 } 1021 case VIDIOCGWIN: 1022 { 1023 struct video_window vwin; 1024 memset(&vwin, 0, sizeof(vwin)); 1025 1026 vwin.width = cam->width; 1027 vwin.height = cam->height; 1028 1029 if(copy_to_user(arg, &vwin, sizeof(vwin)) != 0) 1030 return -EFAULT; 1031 1032 return 0; 1033 } 1034 // Unimplemented 1035 case VIDIOCCAPTURE: 1036 case VIDIOCGFBUF: 1037 case VIDIOCSFBUF: 1038 case VIDIOCKEY: 1039 case VIDIOCGFREQ: 1040 case VIDIOCSFREQ: 1041 case VIDIOCGAUDIO: 1042 case VIDIOCSAUDIO: 1043 return -EINVAL; 1044 default: 1045 return -ENOIOCTLCMD; 1046 } 1047 return 0; 1048} 1049 1050// Capture data 1051// expects a claimed parport and allocated read buffer 1052static long w9966_v4l_read(struct video_device *vdev, char *buf, unsigned long count, int noblock) 1053{ 1054 struct w9966_dev *cam = (struct w9966_dev *)vdev->priv; 1055 const u8 addr = 0xa0; // ECP, read, CCD-transfer, 00000 1056 u8* dest = (u8*)buf; 1057 unsigned long dleft = count; 1058 1059 // Why would anyone want more than this?? 1060 if (count > cam->width * cam->height * 2) 1061 count = cam->width * cam->height * 2; 1062 1063 w9966_wreg(cam, 0x00, 0x02); // Reset ECP-FIFO buffer 1064 w9966_wreg(cam, 0x00, 0x00); // Return to normal operation 1065 w9966_wreg(cam, 0x01, cam->cmask | 0x80); // Enable capture 1066 1067 // write special capture-addr and negotiate into data transfer 1068 if (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0 || 1069 parport_write(cam->pport, &addr, 1) != 1 || 1070 parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0) { 1071 DPRINTF("Unable to write capture-addr.\n"); 1072 return -EFAULT; 1073 } 1074 1075 while(dleft > 0) 1076 { 1077 const size_t tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft; 1078 1079 if (parport_read(cam->pport, cam->buffer, tsize) < tsize) 1080 return -EFAULT; 1081 1082 if (copy_to_user(dest, cam->buffer, tsize) != 0) 1083 return -EFAULT; 1084 1085 dest += tsize; 1086 dleft -= tsize; 1087 } 1088 1089 w9966_wreg(cam, 0x01, cam->cmask); // Disable capture 1090 1091 return count; 1092} 1093 1094// Called once for every parport on init 1095static void w9966_attach(struct parport *port) 1096{ 1097 int i; 1098 1099 for (i = 0; i < W9966_MAXCAMS; i++) { 1100 if (strcmp(pardev[i], "none") == 0 || // Skip if 'none' or if 1101 w9966_cams[i].dev_state != 0) // cam already assigned 1102 continue; 1103 1104 if (strcmp(pardev[i], "auto") == 0 || 1105 strcmp(pardev[i], port->name) == 0) { 1106 if (!w9966_init(&w9966_cams[i], port, video_nr[i])) 1107 w9966_term(&w9966_cams[i]); 1108 break; // return 1109 } 1110 } 1111} 1112 1113// Called once for every parport on termination 1114static void w9966_detach(struct parport *port) 1115{ 1116 int i; 1117 for (i = 0; i < W9966_MAXCAMS; i++) 1118 if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port) 1119 w9966_term(&w9966_cams[i]); 1120} 1121 1122 1123static struct parport_driver w9966_ppd = { 1124 W9966_DRIVERNAME, 1125 w9966_attach, 1126 w9966_detach, 1127 NULL 1128}; 1129 1130// Module entry point 1131static int __init w9966_mod_init(void) 1132{ 1133 int i, err; 1134 1135 w9966_cams = kmalloc( 1136 sizeof(struct w9966_dev) * W9966_MAXCAMS, GFP_KERNEL); 1137 1138 if (!w9966_cams) 1139 return -ENOMEM; 1140 1141 for (i = 0; i < W9966_MAXCAMS; i++) 1142 w9966_cams[i].dev_state = 0; 1143 1144 // Register parport driver 1145 if ((err = parport_register_driver(&w9966_ppd)) != 0) { 1146 kfree(w9966_cams); 1147 w9966_cams = 0; 1148 return err; 1149 } 1150 1151 return 0; 1152} 1153 1154// Module cleanup 1155static void __exit w9966_mod_term(void) 1156{ 1157 if (w9966_cams) 1158 kfree(w9966_cams); 1159 1160 parport_unregister_driver(&w9966_ppd); 1161} 1162 1163module_init(w9966_mod_init); 1164module_exit(w9966_mod_term); 1165