w9966.c 24 KB

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