aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2010-05-10 02:55:25 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-06-01 00:19:41 -0400
commitd71964fb9731412ce1f86cd7d9b71f1f94a04b0d (patch)
tree62d728ba95423cd49c114527e552809d50bc923d /drivers/media
parent483d67ff0a208b43f0b97fca91d3a142afaba7fa (diff)
V4L/DVB: c-qcam: convert to V4L2
Note: due to lack of hardware this conversion is untested. However, it is pretty straightforward so I do not expect any problems. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/Kconfig2
-rw-r--r--drivers/media/video/c-qcam.c634
2 files changed, 331 insertions, 305 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 42d198d5a87e..bdbc9d305419 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -656,7 +656,7 @@ config VIDEO_BWQCAM
656 656
657config VIDEO_CQCAM 657config VIDEO_CQCAM
658 tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)" 658 tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)"
659 depends on EXPERIMENTAL && PARPORT && VIDEO_V4L1 659 depends on EXPERIMENTAL && PARPORT && VIDEO_V4L2
660 help 660 help
661 This is the video4linux driver for the colour version of the 661 This is the video4linux driver for the colour version of the
662 Connectix QuickCam. If you have one of these cameras, say Y here, 662 Connectix QuickCam. If you have one of these cameras, say Y here,
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);