aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/c-qcam.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/c-qcam.c')
-rw-r--r--drivers/media/video/c-qcam.c634
1 files changed, 330 insertions, 304 deletions
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 8f1dd88b32a6..6e4b19698c13 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -33,15 +33,17 @@
33#include <linux/mm.h> 33#include <linux/mm.h>
34#include <linux/parport.h> 34#include <linux/parport.h>
35#include <linux/sched.h> 35#include <linux/sched.h>
36#include <linux/videodev.h>
37#include <media/v4l2-common.h>
38#include <media/v4l2-ioctl.h>
39#include <linux/mutex.h> 36#include <linux/mutex.h>
40#include <linux/jiffies.h> 37#include <linux/jiffies.h>
41 38#include <linux/version.h>
39#include <linux/videodev2.h>
42#include <asm/uaccess.h> 40#include <asm/uaccess.h>
41#include <media/v4l2-device.h>
42#include <media/v4l2-common.h>
43#include <media/v4l2-ioctl.h>
43 44
44struct qcam_device { 45struct qcam {
46 struct v4l2_device v4l2_dev;
45 struct video_device vdev; 47 struct video_device vdev;
46 struct pardevice *pdev; 48 struct pardevice *pdev;
47 struct parport *pport; 49 struct parport *pport;
@@ -51,7 +53,6 @@ struct qcam_device {
51 int contrast, brightness, whitebal; 53 int contrast, brightness, whitebal;
52 int top, left; 54 int top, left;
53 unsigned int bidirectional; 55 unsigned int bidirectional;
54 unsigned long in_use;
55 struct mutex lock; 56 struct mutex lock;
56}; 57};
57 58
@@ -68,33 +69,45 @@ struct qcam_device {
68#define QC_DECIMATION_2 2 69#define QC_DECIMATION_2 2
69#define QC_DECIMATION_4 4 70#define QC_DECIMATION_4 4
70 71
71#define BANNER "Colour QuickCam for Video4Linux v0.05" 72#define BANNER "Colour QuickCam for Video4Linux v0.06"
72 73
73static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 }; 74static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
74static int probe = 2; 75static int probe = 2;
75static int force_rgb; 76static int force_rgb;
76static int video_nr = -1; 77static int video_nr = -1;
77 78
78static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i) 79/* FIXME: parport=auto would never have worked, surely? --RR */
80MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
81 "probe=<0|1|2> for camera detection method\n"
82 "force_rgb=<0|1> for RGB data format (default BGR)");
83module_param_array(parport, int, NULL, 0);
84module_param(probe, int, 0);
85module_param(force_rgb, bool, 0);
86module_param(video_nr, int, 0);
87
88static struct qcam *qcams[MAX_CAMS];
89static unsigned int num_cams;
90
91static inline void qcam_set_ack(struct qcam *qcam, unsigned int i)
79{ 92{
80 /* note: the QC specs refer to the PCAck pin by voltage, not 93 /* note: the QC specs refer to the PCAck pin by voltage, not
81 software level. PC ports have builtin inverters. */ 94 software level. PC ports have builtin inverters. */
82 parport_frob_control(qcam->pport, 8, i ? 8 : 0); 95 parport_frob_control(qcam->pport, 8, i ? 8 : 0);
83} 96}
84 97
85static inline unsigned int qcam_ready1(struct qcam_device *qcam) 98static inline unsigned int qcam_ready1(struct qcam *qcam)
86{ 99{
87 return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0; 100 return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0;
88} 101}
89 102
90static inline unsigned int qcam_ready2(struct qcam_device *qcam) 103static inline unsigned int qcam_ready2(struct qcam *qcam)
91{ 104{
92 return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0; 105 return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0;
93} 106}
94 107
95static unsigned int qcam_await_ready1(struct qcam_device *qcam, 108static unsigned int qcam_await_ready1(struct qcam *qcam, int value)
96 int value)
97{ 109{
110 struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
98 unsigned long oldjiffies = jiffies; 111 unsigned long oldjiffies = jiffies;
99 unsigned int i; 112 unsigned int i;
100 113
@@ -112,14 +125,15 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
112 } 125 }
113 126
114 /* Probably somebody pulled the plug out. Not much we can do. */ 127 /* Probably somebody pulled the plug out. Not much we can do. */
115 printk(KERN_ERR "c-qcam: ready1 timeout (%d) %x %x\n", value, 128 v4l2_err(v4l2_dev, "ready1 timeout (%d) %x %x\n", value,
116 parport_read_status(qcam->pport), 129 parport_read_status(qcam->pport),
117 parport_read_control(qcam->pport)); 130 parport_read_control(qcam->pport));
118 return 1; 131 return 1;
119} 132}
120 133
121static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) 134static unsigned int qcam_await_ready2(struct qcam *qcam, int value)
122{ 135{
136 struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
123 unsigned long oldjiffies = jiffies; 137 unsigned long oldjiffies = jiffies;
124 unsigned int i; 138 unsigned int i;
125 139
@@ -137,14 +151,14 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
137 } 151 }
138 152
139 /* Probably somebody pulled the plug out. Not much we can do. */ 153 /* Probably somebody pulled the plug out. Not much we can do. */
140 printk(KERN_ERR "c-qcam: ready2 timeout (%d) %x %x %x\n", value, 154 v4l2_err(v4l2_dev, "ready2 timeout (%d) %x %x %x\n", value,
141 parport_read_status(qcam->pport), 155 parport_read_status(qcam->pport),
142 parport_read_control(qcam->pport), 156 parport_read_control(qcam->pport),
143 parport_read_data(qcam->pport)); 157 parport_read_data(qcam->pport));
144 return 1; 158 return 1;
145} 159}
146 160
147static int qcam_read_data(struct qcam_device *qcam) 161static int qcam_read_data(struct qcam *qcam)
148{ 162{
149 unsigned int idata; 163 unsigned int idata;
150 164
@@ -159,21 +173,22 @@ static int qcam_read_data(struct qcam_device *qcam)
159 return idata; 173 return idata;
160} 174}
161 175
162static int qcam_write_data(struct qcam_device *qcam, unsigned int data) 176static int qcam_write_data(struct qcam *qcam, unsigned int data)
163{ 177{
178 struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
164 unsigned int idata; 179 unsigned int idata;
165 180
166 parport_write_data(qcam->pport, data); 181 parport_write_data(qcam->pport, data);
167 idata = qcam_read_data(qcam); 182 idata = qcam_read_data(qcam);
168 if (data != idata) { 183 if (data != idata) {
169 printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, 184 v4l2_warn(v4l2_dev, "sent %x but received %x\n", data,
170 idata); 185 idata);
171 return 1; 186 return 1;
172 } 187 }
173 return 0; 188 return 0;
174} 189}
175 190
176static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned int data) 191static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data)
177{ 192{
178 if (qcam_write_data(qcam, cmd)) 193 if (qcam_write_data(qcam, cmd))
179 return -1; 194 return -1;
@@ -182,14 +197,14 @@ static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned
182 return 0; 197 return 0;
183} 198}
184 199
185static inline int qcam_get(struct qcam_device *qcam, unsigned int cmd) 200static inline int qcam_get(struct qcam *qcam, unsigned int cmd)
186{ 201{
187 if (qcam_write_data(qcam, cmd)) 202 if (qcam_write_data(qcam, cmd))
188 return -1; 203 return -1;
189 return qcam_read_data(qcam); 204 return qcam_read_data(qcam);
190} 205}
191 206
192static int qc_detect(struct qcam_device *qcam) 207static int qc_detect(struct qcam *qcam)
193{ 208{
194 unsigned int stat, ostat, i, count = 0; 209 unsigned int stat, ostat, i, count = 0;
195 210
@@ -246,7 +261,7 @@ static int qc_detect(struct qcam_device *qcam)
246 return 0; 261 return 0;
247} 262}
248 263
249static void qc_reset(struct qcam_device *qcam) 264static void qc_reset(struct qcam *qcam)
250{ 265{
251 parport_write_control(qcam->pport, 0xc); 266 parport_write_control(qcam->pport, 0xc);
252 parport_write_control(qcam->pport, 0x8); 267 parport_write_control(qcam->pport, 0x8);
@@ -258,55 +273,55 @@ static void qc_reset(struct qcam_device *qcam)
258/* Reset the QuickCam and program for brightness, contrast, 273/* Reset the QuickCam and program for brightness, contrast,
259 * white-balance, and resolution. */ 274 * white-balance, and resolution. */
260 275
261static void qc_setup(struct qcam_device *q) 276static void qc_setup(struct qcam *qcam)
262{ 277{
263 qc_reset(q); 278 qc_reset(qcam);
264 279
265 /* Set the brightness. */ 280 /* Set the brightness. */
266 qcam_set(q, 11, q->brightness); 281 qcam_set(qcam, 11, qcam->brightness);
267 282
268 /* Set the height and width. These refer to the actual 283 /* Set the height and width. These refer to the actual
269 CCD area *before* applying the selected decimation. */ 284 CCD area *before* applying the selected decimation. */
270 qcam_set(q, 17, q->ccd_height); 285 qcam_set(qcam, 17, qcam->ccd_height);
271 qcam_set(q, 19, q->ccd_width / 2); 286 qcam_set(qcam, 19, qcam->ccd_width / 2);
272 287
273 /* Set top and left. */ 288 /* Set top and left. */
274 qcam_set(q, 0xd, q->top); 289 qcam_set(qcam, 0xd, qcam->top);
275 qcam_set(q, 0xf, q->left); 290 qcam_set(qcam, 0xf, qcam->left);
276 291
277 /* Set contrast and white balance. */ 292 /* Set contrast and white balance. */
278 qcam_set(q, 0x19, q->contrast); 293 qcam_set(qcam, 0x19, qcam->contrast);
279 qcam_set(q, 0x1f, q->whitebal); 294 qcam_set(qcam, 0x1f, qcam->whitebal);
280 295
281 /* Set the speed. */ 296 /* Set the speed. */
282 qcam_set(q, 45, 2); 297 qcam_set(qcam, 45, 2);
283} 298}
284 299
285/* Read some bytes from the camera and put them in the buffer. 300/* Read some bytes from the camera and put them in the buffer.
286 nbytes should be a multiple of 3, because bidirectional mode gives 301 nbytes should be a multiple of 3, because bidirectional mode gives
287 us three bytes at a time. */ 302 us three bytes at a time. */
288 303
289static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, unsigned int nbytes) 304static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes)
290{ 305{
291 unsigned int bytes = 0; 306 unsigned int bytes = 0;
292 307
293 qcam_set_ack(q, 0); 308 qcam_set_ack(qcam, 0);
294 if (q->bidirectional) { 309 if (qcam->bidirectional) {
295 /* It's a bidirectional port */ 310 /* It's a bidirectional port */
296 while (bytes < nbytes) { 311 while (bytes < nbytes) {
297 unsigned int lo1, hi1, lo2, hi2; 312 unsigned int lo1, hi1, lo2, hi2;
298 unsigned char r, g, b; 313 unsigned char r, g, b;
299 314
300 if (qcam_await_ready2(q, 1)) 315 if (qcam_await_ready2(qcam, 1))
301 return bytes; 316 return bytes;
302 lo1 = parport_read_data(q->pport) >> 1; 317 lo1 = parport_read_data(qcam->pport) >> 1;
303 hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; 318 hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
304 qcam_set_ack(q, 1); 319 qcam_set_ack(qcam, 1);
305 if (qcam_await_ready2(q, 0)) 320 if (qcam_await_ready2(qcam, 0))
306 return bytes; 321 return bytes;
307 lo2 = parport_read_data(q->pport) >> 1; 322 lo2 = parport_read_data(qcam->pport) >> 1;
308 hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; 323 hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
309 qcam_set_ack(q, 0); 324 qcam_set_ack(qcam, 0);
310 r = lo1 | ((hi1 & 1) << 7); 325 r = lo1 | ((hi1 & 1) << 7);
311 g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1); 326 g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1);
312 b = lo2 | ((hi2 & 1) << 7); 327 b = lo2 | ((hi2 & 1) << 7);
@@ -328,14 +343,14 @@ static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, u
328 while (bytes < nbytes) { 343 while (bytes < nbytes) {
329 unsigned int hi, lo; 344 unsigned int hi, lo;
330 345
331 if (qcam_await_ready1(q, 1)) 346 if (qcam_await_ready1(qcam, 1))
332 return bytes; 347 return bytes;
333 hi = (parport_read_status(q->pport) & 0xf0); 348 hi = (parport_read_status(qcam->pport) & 0xf0);
334 qcam_set_ack(q, 1); 349 qcam_set_ack(qcam, 1);
335 if (qcam_await_ready1(q, 0)) 350 if (qcam_await_ready1(qcam, 0))
336 return bytes; 351 return bytes;
337 lo = (parport_read_status(q->pport) & 0xf0); 352 lo = (parport_read_status(qcam->pport) & 0xf0);
338 qcam_set_ack(q, 0); 353 qcam_set_ack(qcam, 0);
339 /* flip some bits */ 354 /* flip some bits */
340 rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88; 355 rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
341 if (i >= 2) { 356 if (i >= 2) {
@@ -361,10 +376,11 @@ get_fragment:
361 376
362#define BUFSZ 150 377#define BUFSZ 150
363 378
364static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len) 379static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len)
365{ 380{
381 struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
366 unsigned lines, pixelsperline, bitsperxfer; 382 unsigned lines, pixelsperline, bitsperxfer;
367 unsigned int is_bi_dir = q->bidirectional; 383 unsigned int is_bi_dir = qcam->bidirectional;
368 size_t wantlen, outptr = 0; 384 size_t wantlen, outptr = 0;
369 char tmpbuf[BUFSZ]; 385 char tmpbuf[BUFSZ];
370 386
@@ -373,10 +389,10 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
373 389
374 /* Wait for camera to become ready */ 390 /* Wait for camera to become ready */
375 for (;;) { 391 for (;;) {
376 int i = qcam_get(q, 41); 392 int i = qcam_get(qcam, 41);
377 393
378 if (i == -1) { 394 if (i == -1) {
379 qc_setup(q); 395 qc_setup(qcam);
380 return -EIO; 396 return -EIO;
381 } 397 }
382 if ((i & 0x80) == 0) 398 if ((i & 0x80) == 0)
@@ -384,25 +400,25 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
384 schedule(); 400 schedule();
385 } 401 }
386 402
387 if (qcam_set(q, 7, (q->mode | (is_bi_dir ? 1 : 0)) + 1)) 403 if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1))
388 return -EIO; 404 return -EIO;
389 405
390 lines = q->height; 406 lines = qcam->height;
391 pixelsperline = q->width; 407 pixelsperline = qcam->width;
392 bitsperxfer = (is_bi_dir) ? 24 : 8; 408 bitsperxfer = (is_bi_dir) ? 24 : 8;
393 409
394 if (is_bi_dir) { 410 if (is_bi_dir) {
395 /* Turn the port around */ 411 /* Turn the port around */
396 parport_data_reverse(q->pport); 412 parport_data_reverse(qcam->pport);
397 mdelay(3); 413 mdelay(3);
398 qcam_set_ack(q, 0); 414 qcam_set_ack(qcam, 0);
399 if (qcam_await_ready1(q, 1)) { 415 if (qcam_await_ready1(qcam, 1)) {
400 qc_setup(q); 416 qc_setup(qcam);
401 return -EIO; 417 return -EIO;
402 } 418 }
403 qcam_set_ack(q, 1); 419 qcam_set_ack(qcam, 1);
404 if (qcam_await_ready1(q, 0)) { 420 if (qcam_await_ready1(qcam, 0)) {
405 qc_setup(q); 421 qc_setup(qcam);
406 return -EIO; 422 return -EIO;
407 } 423 }
408 } 424 }
@@ -413,7 +429,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
413 size_t t, s; 429 size_t t, s;
414 430
415 s = (wantlen > BUFSZ) ? BUFSZ : wantlen; 431 s = (wantlen > BUFSZ) ? BUFSZ : wantlen;
416 t = qcam_read_bytes(q, tmpbuf, s); 432 t = qcam_read_bytes(qcam, tmpbuf, s);
417 if (outptr < len) { 433 if (outptr < len) {
418 size_t sz = len - outptr; 434 size_t sz = len - outptr;
419 435
@@ -432,10 +448,10 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
432 len = outptr; 448 len = outptr;
433 449
434 if (wantlen) { 450 if (wantlen) {
435 printk(KERN_ERR "qcam: short read.\n"); 451 v4l2_err(v4l2_dev, "short read.\n");
436 if (is_bi_dir) 452 if (is_bi_dir)
437 parport_data_forward(q->pport); 453 parport_data_forward(qcam->pport);
438 qc_setup(q); 454 qc_setup(qcam);
439 return len; 455 return len;
440 } 456 }
441 457
@@ -443,49 +459,49 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
443 int l; 459 int l;
444 460
445 do { 461 do {
446 l = qcam_read_bytes(q, tmpbuf, 3); 462 l = qcam_read_bytes(qcam, tmpbuf, 3);
447 cond_resched(); 463 cond_resched();
448 } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e)); 464 } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
449 if (force_rgb) { 465 if (force_rgb) {
450 if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) 466 if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
451 printk(KERN_ERR "qcam: bad EOF\n"); 467 v4l2_err(v4l2_dev, "bad EOF\n");
452 } else { 468 } else {
453 if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) 469 if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
454 printk(KERN_ERR "qcam: bad EOF\n"); 470 v4l2_err(v4l2_dev, "bad EOF\n");
455 } 471 }
456 qcam_set_ack(q, 0); 472 qcam_set_ack(qcam, 0);
457 if (qcam_await_ready1(q, 1)) { 473 if (qcam_await_ready1(qcam, 1)) {
458 printk(KERN_ERR "qcam: no ack after EOF\n"); 474 v4l2_err(v4l2_dev, "no ack after EOF\n");
459 parport_data_forward(q->pport); 475 parport_data_forward(qcam->pport);
460 qc_setup(q); 476 qc_setup(qcam);
461 return len; 477 return len;
462 } 478 }
463 parport_data_forward(q->pport); 479 parport_data_forward(qcam->pport);
464 mdelay(3); 480 mdelay(3);
465 qcam_set_ack(q, 1); 481 qcam_set_ack(qcam, 1);
466 if (qcam_await_ready1(q, 0)) { 482 if (qcam_await_ready1(qcam, 0)) {
467 printk(KERN_ERR "qcam: no ack to port turnaround\n"); 483 v4l2_err(v4l2_dev, "no ack to port turnaround\n");
468 qc_setup(q); 484 qc_setup(qcam);
469 return len; 485 return len;
470 } 486 }
471 } else { 487 } else {
472 int l; 488 int l;
473 489
474 do { 490 do {
475 l = qcam_read_bytes(q, tmpbuf, 1); 491 l = qcam_read_bytes(qcam, tmpbuf, 1);
476 cond_resched(); 492 cond_resched();
477 } while (l && tmpbuf[0] == 0x7e); 493 } while (l && tmpbuf[0] == 0x7e);
478 l = qcam_read_bytes(q, tmpbuf + 1, 2); 494 l = qcam_read_bytes(qcam, tmpbuf + 1, 2);
479 if (force_rgb) { 495 if (force_rgb) {
480 if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) 496 if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
481 printk(KERN_ERR "qcam: bad EOF\n"); 497 v4l2_err(v4l2_dev, "bad EOF\n");
482 } else { 498 } else {
483 if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) 499 if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
484 printk(KERN_ERR "qcam: bad EOF\n"); 500 v4l2_err(v4l2_dev, "bad EOF\n");
485 } 501 }
486 } 502 }
487 503
488 qcam_write_data(q, 0); 504 qcam_write_data(qcam, 0);
489 return len; 505 return len;
490} 506}
491 507
@@ -493,184 +509,202 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
493 * Video4linux interfacing 509 * Video4linux interfacing
494 */ 510 */
495 511
496static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) 512static int qcam_querycap(struct file *file, void *priv,
513 struct v4l2_capability *vcap)
497{ 514{
498 struct video_device *dev = video_devdata(file); 515 struct qcam *qcam = video_drvdata(file);
499 struct qcam_device *qcam = (struct qcam_device *)dev;
500 516
501 switch (cmd) { 517 strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
502 case VIDIOCGCAP: 518 strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card));
503 { 519 strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
504 struct video_capability *b = arg; 520 vcap->version = KERNEL_VERSION(0, 0, 3);
521 vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
522 return 0;
523}
505 524
506 strcpy(b->name, "Quickcam"); 525static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
507 b->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; 526{
508 b->channels = 1; 527 if (vin->index > 0)
509 b->audios = 0; 528 return -EINVAL;
510 b->maxwidth = 320; 529 strlcpy(vin->name, "Camera", sizeof(vin->name));
511 b->maxheight = 240; 530 vin->type = V4L2_INPUT_TYPE_CAMERA;
512 b->minwidth = 80; 531 vin->audioset = 0;
513 b->minheight = 60; 532 vin->tuner = 0;
514 return 0; 533 vin->std = 0;
515 } 534 vin->status = 0;
516 case VIDIOCGCHAN: 535 return 0;
517 { 536}
518 struct video_channel *v = arg;
519
520 if (v->channel != 0)
521 return -EINVAL;
522 v->flags = 0;
523 v->tuners = 0;
524 /* Good question.. its composite or SVHS so.. */
525 v->type = VIDEO_TYPE_CAMERA;
526 strcpy(v->name, "Camera");
527 return 0;
528 }
529 case VIDIOCSCHAN:
530 {
531 struct video_channel *v = arg;
532 537
533 if (v->channel != 0) 538static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
534 return -EINVAL; 539{
535 return 0; 540 *inp = 0;
536 } 541 return 0;
537 case VIDIOCGTUNER: 542}
538 { 543
539 struct video_tuner *v = arg; 544static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
540 545{
541 if (v->tuner) 546 return (inp > 0) ? -EINVAL : 0;
542 return -EINVAL; 547}
543 memset(v, 0, sizeof(*v)); 548
544 strcpy(v->name, "Format"); 549static int qcam_queryctrl(struct file *file, void *priv,
545 v->mode = VIDEO_MODE_AUTO; 550 struct v4l2_queryctrl *qc)
546 return 0; 551{
552 switch (qc->id) {
553 case V4L2_CID_BRIGHTNESS:
554 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 240);
555 case V4L2_CID_CONTRAST:
556 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192);
557 case V4L2_CID_GAMMA:
558 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
547 } 559 }
548 case VIDIOCSTUNER: 560 return -EINVAL;
549 { 561}
550 struct video_tuner *v = arg; 562
551 563static int qcam_g_ctrl(struct file *file, void *priv,
552 if (v->tuner) 564 struct v4l2_control *ctrl)
553 return -EINVAL; 565{
554 if (v->mode != VIDEO_MODE_AUTO) 566 struct qcam *qcam = video_drvdata(file);
555 return -EINVAL; 567 int ret = 0;
556 return 0; 568
569 switch (ctrl->id) {
570 case V4L2_CID_BRIGHTNESS:
571 ctrl->value = qcam->brightness;
572 break;
573 case V4L2_CID_CONTRAST:
574 ctrl->value = qcam->contrast;
575 break;
576 case V4L2_CID_GAMMA:
577 ctrl->value = qcam->whitebal;
578 break;
579 default:
580 ret = -EINVAL;
581 break;
557 } 582 }
558 case VIDIOCGPICT: 583 return ret;
559 { 584}
560 struct video_picture *p = arg; 585
561 586static int qcam_s_ctrl(struct file *file, void *priv,
562 p->colour = 0x8000; 587 struct v4l2_control *ctrl)
563 p->hue = 0x8000; 588{
564 p->brightness = qcam->brightness << 8; 589 struct qcam *qcam = video_drvdata(file);
565 p->contrast = qcam->contrast << 8; 590 int ret = 0;
566 p->whiteness = qcam->whitebal << 8; 591
567 p->depth = 24; 592 mutex_lock(&qcam->lock);
568 p->palette = VIDEO_PALETTE_RGB24; 593 switch (ctrl->id) {
569 return 0; 594 case V4L2_CID_BRIGHTNESS:
595 qcam->brightness = ctrl->value;
596 break;
597 case V4L2_CID_CONTRAST:
598 qcam->contrast = ctrl->value;
599 break;
600 case V4L2_CID_GAMMA:
601 qcam->whitebal = ctrl->value;
602 break;
603 default:
604 ret = -EINVAL;
605 break;
570 } 606 }
571 case VIDIOCSPICT: 607 if (ret == 0) {
572 {
573 struct video_picture *p = arg;
574
575 /*
576 * Sanity check args
577 */
578 if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24)
579 return -EINVAL;
580
581 /*
582 * Now load the camera.
583 */
584 qcam->brightness = p->brightness >> 8;
585 qcam->contrast = p->contrast >> 8;
586 qcam->whitebal = p->whiteness >> 8;
587
588 mutex_lock(&qcam->lock);
589 parport_claim_or_block(qcam->pdev); 608 parport_claim_or_block(qcam->pdev);
590 qc_setup(qcam); 609 qc_setup(qcam);
591 parport_release(qcam->pdev); 610 parport_release(qcam->pdev);
592 mutex_unlock(&qcam->lock);
593 return 0;
594 } 611 }
595 case VIDIOCSWIN: 612 mutex_unlock(&qcam->lock);
596 { 613 return ret;
597 struct video_window *vw = arg; 614}
598
599 if (vw->flags)
600 return -EINVAL;
601 if (vw->clipcount)
602 return -EINVAL;
603 if (vw->height < 60 || vw->height > 240)
604 return -EINVAL;
605 if (vw->width < 80 || vw->width > 320)
606 return -EINVAL;
607
608 qcam->width = 80;
609 qcam->height = 60;
610 qcam->mode = QC_DECIMATION_4;
611 615
612 if (vw->width >= 160 && vw->height >= 120) { 616static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
613 qcam->width = 160; 617{
614 qcam->height = 120; 618 struct qcam *qcam = video_drvdata(file);
615 qcam->mode = QC_DECIMATION_2; 619 struct v4l2_pix_format *pix = &fmt->fmt.pix;
616 } 620
617 if (vw->width >= 320 && vw->height >= 240) { 621 pix->width = qcam->width;
618 qcam->width = 320; 622 pix->height = qcam->height;
619 qcam->height = 240; 623 pix->pixelformat = V4L2_PIX_FMT_RGB24;
620 qcam->mode = QC_DECIMATION_1; 624 pix->field = V4L2_FIELD_NONE;
621 } 625 pix->bytesperline = 3 * qcam->width;
622 qcam->mode |= QC_MILLIONS; 626 pix->sizeimage = 3 * qcam->width * qcam->height;
623#if 0 627 /* Just a guess */
624 if (vw->width >= 640 && vw->height >= 480) { 628 pix->colorspace = V4L2_COLORSPACE_SRGB;
625 qcam->width = 640; 629 return 0;
626 qcam->height = 480; 630}
627 qcam->mode = QC_BILLIONS | QC_DECIMATION_1; 631
628 } 632static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
629#endif 633{
630 /* Ok we figured out what to use from our 634 struct v4l2_pix_format *pix = &fmt->fmt.pix;
631 wide choice */ 635
632 mutex_lock(&qcam->lock); 636 if (pix->height < 60 || pix->width < 80) {
633 parport_claim_or_block(qcam->pdev); 637 pix->height = 60;
634 qc_setup(qcam); 638 pix->width = 80;
635 parport_release(qcam->pdev); 639 } else if (pix->height < 120 || pix->width < 160) {
636 mutex_unlock(&qcam->lock); 640 pix->height = 120;
637 return 0; 641 pix->width = 160;
638 } 642 } else {
639 case VIDIOCGWIN: 643 pix->height = 240;
640 { 644 pix->width = 320;
641 struct video_window *vw = arg;
642 memset(vw, 0, sizeof(*vw));
643 vw->width = qcam->width;
644 vw->height = qcam->height;
645 return 0;
646 } 645 }
647 case VIDIOCKEY: 646 pix->pixelformat = V4L2_PIX_FMT_RGB24;
648 return 0; 647 pix->field = V4L2_FIELD_NONE;
649 case VIDIOCCAPTURE: 648 pix->bytesperline = 3 * pix->width;
650 case VIDIOCGFBUF: 649 pix->sizeimage = 3 * pix->width * pix->height;
651 case VIDIOCSFBUF: 650 /* Just a guess */
652 case VIDIOCGFREQ: 651 pix->colorspace = V4L2_COLORSPACE_SRGB;
653 case VIDIOCSFREQ: 652 return 0;
654 case VIDIOCGAUDIO: 653}
655 case VIDIOCSAUDIO: 654
656 return -EINVAL; 655static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
656{
657 struct qcam *qcam = video_drvdata(file);
658 struct v4l2_pix_format *pix = &fmt->fmt.pix;
659 int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
660
661 if (ret)
662 return ret;
663 switch (pix->height) {
664 case 60:
665 qcam->mode = QC_DECIMATION_4;
666 break;
667 case 120:
668 qcam->mode = QC_DECIMATION_2;
669 break;
657 default: 670 default:
658 return -ENOIOCTLCMD; 671 qcam->mode = QC_DECIMATION_1;
672 break;
659 } 673 }
674
675 mutex_lock(&qcam->lock);
676 qcam->mode |= QC_MILLIONS;
677 qcam->height = pix->height;
678 qcam->width = pix->width;
679 parport_claim_or_block(qcam->pdev);
680 qc_setup(qcam);
681 parport_release(qcam->pdev);
682 mutex_unlock(&qcam->lock);
660 return 0; 683 return 0;
661} 684}
662 685
663static long qcam_ioctl(struct file *file, 686static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
664 unsigned int cmd, unsigned long arg)
665{ 687{
666 return video_usercopy(file, cmd, arg, qcam_do_ioctl); 688 static struct v4l2_fmtdesc formats[] = {
689 { 0, 0, 0,
690 "RGB 8:8:8", V4L2_PIX_FMT_RGB24,
691 { 0, 0, 0, 0 }
692 },
693 };
694 enum v4l2_buf_type type = fmt->type;
695
696 if (fmt->index > 0)
697 return -EINVAL;
698
699 *fmt = formats[fmt->index];
700 fmt->type = type;
701 return 0;
667} 702}
668 703
669static ssize_t qcam_read(struct file *file, char __user *buf, 704static ssize_t qcam_read(struct file *file, char __user *buf,
670 size_t count, loff_t *ppos) 705 size_t count, loff_t *ppos)
671{ 706{
672 struct video_device *v = video_devdata(file); 707 struct qcam *qcam = video_drvdata(file);
673 struct qcam_device *qcam = (struct qcam_device *)v;
674 int len; 708 int len;
675 709
676 mutex_lock(&qcam->lock); 710 mutex_lock(&qcam->lock);
@@ -682,81 +716,80 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
682 return len; 716 return len;
683} 717}
684 718
685static int qcam_exclusive_open(struct file *file)
686{
687 struct video_device *dev = video_devdata(file);
688 struct qcam_device *qcam = (struct qcam_device *)dev;
689
690 return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
691}
692
693static int qcam_exclusive_release(struct file *file)
694{
695 struct video_device *dev = video_devdata(file);
696 struct qcam_device *qcam = (struct qcam_device *)dev;
697
698 clear_bit(0, &qcam->in_use);
699 return 0;
700}
701
702/* video device template */
703static const struct v4l2_file_operations qcam_fops = { 719static const struct v4l2_file_operations qcam_fops = {
704 .owner = THIS_MODULE, 720 .owner = THIS_MODULE,
705 .open = qcam_exclusive_open, 721 .ioctl = video_ioctl2,
706 .release = qcam_exclusive_release,
707 .ioctl = qcam_ioctl,
708 .read = qcam_read, 722 .read = qcam_read,
709}; 723};
710 724
711static struct video_device qcam_template = { 725static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
712 .name = "Colour QuickCam", 726 .vidioc_querycap = qcam_querycap,
713 .fops = &qcam_fops, 727 .vidioc_g_input = qcam_g_input,
714 .release = video_device_release_empty, 728 .vidioc_s_input = qcam_s_input,
729 .vidioc_enum_input = qcam_enum_input,
730 .vidioc_queryctrl = qcam_queryctrl,
731 .vidioc_g_ctrl = qcam_g_ctrl,
732 .vidioc_s_ctrl = qcam_s_ctrl,
733 .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap,
734 .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
735 .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
736 .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap,
715}; 737};
716 738
717/* Initialize the QuickCam driver control structure. */ 739/* Initialize the QuickCam driver control structure. */
718 740
719static struct qcam_device *qcam_init(struct parport *port) 741static struct qcam *qcam_init(struct parport *port)
720{ 742{
721 struct qcam_device *q; 743 struct qcam *qcam;
744 struct v4l2_device *v4l2_dev;
722 745
723 q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); 746 qcam = kzalloc(sizeof(*qcam), GFP_KERNEL);
724 if (q == NULL) 747 if (qcam == NULL)
725 return NULL; 748 return NULL;
726 749
727 q->pport = port; 750 v4l2_dev = &qcam->v4l2_dev;
728 q->pdev = parport_register_device(port, "c-qcam", NULL, NULL, 751 strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name));
752
753 if (v4l2_device_register(NULL, v4l2_dev) < 0) {
754 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
755 return NULL;
756 }
757
758 qcam->pport = port;
759 qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
729 NULL, 0, NULL); 760 NULL, 0, NULL);
730 761
731 q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0; 762 qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
732 763
733 if (q->pdev == NULL) { 764 if (qcam->pdev == NULL) {
734 printk(KERN_ERR "c-qcam: couldn't register for %s.\n", 765 v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
735 port->name); 766 kfree(qcam);
736 kfree(q);
737 return NULL; 767 return NULL;
738 } 768 }
739 769
740 memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); 770 strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name));
741 771 qcam->vdev.v4l2_dev = v4l2_dev;
742 mutex_init(&q->lock); 772 qcam->vdev.fops = &qcam_fops;
743 q->width = q->ccd_width = 320; 773 qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
744 q->height = q->ccd_height = 240; 774 qcam->vdev.release = video_device_release_empty;
745 q->mode = QC_MILLIONS | QC_DECIMATION_1; 775 video_set_drvdata(&qcam->vdev, qcam);
746 q->contrast = 192; 776
747 q->brightness = 240; 777 mutex_init(&qcam->lock);
748 q->whitebal = 128; 778 qcam->width = qcam->ccd_width = 320;
749 q->top = 1; 779 qcam->height = qcam->ccd_height = 240;
750 q->left = 14; 780 qcam->mode = QC_MILLIONS | QC_DECIMATION_1;
751 return q; 781 qcam->contrast = 192;
782 qcam->brightness = 240;
783 qcam->whitebal = 128;
784 qcam->top = 1;
785 qcam->left = 14;
786 return qcam;
752} 787}
753 788
754static struct qcam_device *qcams[MAX_CAMS];
755static unsigned int num_cams;
756
757static int init_cqcam(struct parport *port) 789static int init_cqcam(struct parport *port)
758{ 790{
759 struct qcam_device *qcam; 791 struct qcam *qcam;
792 struct v4l2_device *v4l2_dev;
760 793
761 if (parport[0] != -1) { 794 if (parport[0] != -1) {
762 /* The user gave specific instructions */ 795 /* The user gave specific instructions */
@@ -777,6 +810,8 @@ static int init_cqcam(struct parport *port)
777 if (qcam == NULL) 810 if (qcam == NULL)
778 return -ENODEV; 811 return -ENODEV;
779 812
813 v4l2_dev = &qcam->v4l2_dev;
814
780 parport_claim_or_block(qcam->pdev); 815 parport_claim_or_block(qcam->pdev);
781 816
782 qc_reset(qcam); 817 qc_reset(qcam);
@@ -793,14 +828,14 @@ static int init_cqcam(struct parport *port)
793 parport_release(qcam->pdev); 828 parport_release(qcam->pdev);
794 829
795 if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { 830 if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
796 printk(KERN_ERR "Unable to register Colour QuickCam on %s\n", 831 v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n",
797 qcam->pport->name); 832 qcam->pport->name);
798 parport_unregister_device(qcam->pdev); 833 parport_unregister_device(qcam->pdev);
799 kfree(qcam); 834 kfree(qcam);
800 return -ENODEV; 835 return -ENODEV;
801 } 836 }
802 837
803 printk(KERN_INFO "%s: Colour QuickCam found on %s\n", 838 v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n",
804 video_device_node_name(&qcam->vdev), qcam->pport->name); 839 video_device_node_name(&qcam->vdev), qcam->pport->name);
805 840
806 qcams[num_cams++] = qcam; 841 qcams[num_cams++] = qcam;
@@ -808,7 +843,7 @@ static int init_cqcam(struct parport *port)
808 return 0; 843 return 0;
809} 844}
810 845
811static void close_cqcam(struct qcam_device *qcam) 846static void close_cqcam(struct qcam *qcam)
812{ 847{
813 video_unregister_device(&qcam->vdev); 848 video_unregister_device(&qcam->vdev);
814 parport_unregister_device(qcam->pdev); 849 parport_unregister_device(qcam->pdev);
@@ -833,7 +868,7 @@ static struct parport_driver cqcam_driver = {
833 868
834static int __init cqcam_init(void) 869static int __init cqcam_init(void)
835{ 870{
836 printk(BANNER "\n"); 871 printk(KERN_INFO BANNER "\n");
837 872
838 return parport_register_driver(&cqcam_driver); 873 return parport_register_driver(&cqcam_driver);
839} 874}
@@ -852,14 +887,5 @@ MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
852MODULE_DESCRIPTION(BANNER); 887MODULE_DESCRIPTION(BANNER);
853MODULE_LICENSE("GPL"); 888MODULE_LICENSE("GPL");
854 889
855/* FIXME: parport=auto would never have worked, surely? --RR */
856MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
857 "probe=<0|1|2> for camera detection method\n"
858 "force_rgb=<0|1> for RGB data format (default BGR)");
859module_param_array(parport, int, NULL, 0);
860module_param(probe, int, 0);
861module_param(force_rgb, bool, 0);
862module_param(video_nr, int, 0);
863
864module_init(cqcam_init); 890module_init(cqcam_init);
865module_exit(cqcam_cleanup); 891module_exit(cqcam_cleanup);