w9966.c 23 KB

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