Merge branch 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel...
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / media / parport / c-qcam.c
CommitLineData
1da177e4
LT
1/*
2 * Video4Linux Colour QuickCam driver
3 * Copyright 1997-2000 Philip Blundell <philb@gnu.org>
4 *
5 * Module parameters:
6 *
7 * parport=auto -- probe all parports (default)
8 * parport=0 -- parport0 becomes qcam1
9 * parport=2,0,1 -- parports 2,0,1 are tried in that order
10 *
11 * probe=0 -- do no probing, assume camera is present
12 * probe=1 -- use IEEE-1284 autoprobe data only (default)
13 * probe=2 -- probe aggressively for cameras
14 *
15 * force_rgb=1 -- force data format to RGB (default is BGR)
16 *
17 * The parport parameter controls which parports will be scanned.
18 * Scanning all parports causes some printers to print a garbage page.
d56410e0 19 * -- March 14, 1999 Billy Donahue <billy@escape.com>
1da177e4
LT
20 *
21 * Fixed data format to BGR, added force_rgb parameter. Added missing
22 * parport_unregister_driver() on module removal.
23 * -- May 28, 2000 Claudio Matsuoka <claudio@conectiva.com>
24 */
25
26#include <linux/module.h>
27#include <linux/delay.h>
28#include <linux/errno.h>
29#include <linux/fs.h>
30#include <linux/init.h>
31#include <linux/kernel.h>
32#include <linux/slab.h>
33#include <linux/mm.h>
34#include <linux/parport.h>
35#include <linux/sched.h>
3593cab5 36#include <linux/mutex.h>
168c626c 37#include <linux/jiffies.h>
d71964fb 38#include <linux/videodev2.h>
1da177e4 39#include <asm/uaccess.h>
d71964fb
HV
40#include <media/v4l2-device.h>
41#include <media/v4l2-common.h>
42#include <media/v4l2-ioctl.h>
34caed8b
HV
43#include <media/v4l2-fh.h>
44#include <media/v4l2-ctrls.h>
45#include <media/v4l2-event.h>
1da177e4 46
d71964fb
HV
47struct qcam {
48 struct v4l2_device v4l2_dev;
1da177e4 49 struct video_device vdev;
34caed8b 50 struct v4l2_ctrl_handler hdl;
1da177e4
LT
51 struct pardevice *pdev;
52 struct parport *pport;
53 int width, height;
54 int ccd_width, ccd_height;
55 int mode;
56 int contrast, brightness, whitebal;
57 int top, left;
58 unsigned int bidirectional;
3593cab5 59 struct mutex lock;
1da177e4
LT
60};
61
62/* cameras maximum */
63#define MAX_CAMS 4
64
65/* The three possible QuickCam modes */
66#define QC_MILLIONS 0x18
67#define QC_BILLIONS 0x10
68#define QC_THOUSANDS 0x08 /* with VIDEC compression (not supported) */
69
70/* The three possible decimations */
71#define QC_DECIMATION_1 0
72#define QC_DECIMATION_2 2
73#define QC_DECIMATION_4 4
74
d71964fb 75#define BANNER "Colour QuickCam for Video4Linux v0.06"
1da177e4
LT
76
77static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
78static int probe = 2;
90ab5ee9 79static bool force_rgb;
1da177e4
LT
80static int video_nr = -1;
81
d71964fb
HV
82/* FIXME: parport=auto would never have worked, surely? --RR */
83MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
84 "probe=<0|1|2> for camera detection method\n"
85 "force_rgb=<0|1> for RGB data format (default BGR)");
86module_param_array(parport, int, NULL, 0);
87module_param(probe, int, 0);
88module_param(force_rgb, bool, 0);
89module_param(video_nr, int, 0);
90
91static struct qcam *qcams[MAX_CAMS];
92static unsigned int num_cams;
93
94static inline void qcam_set_ack(struct qcam *qcam, unsigned int i)
1da177e4
LT
95{
96 /* note: the QC specs refer to the PCAck pin by voltage, not
97 software level. PC ports have builtin inverters. */
51224aa4 98 parport_frob_control(qcam->pport, 8, i ? 8 : 0);
1da177e4
LT
99}
100
d71964fb 101static inline unsigned int qcam_ready1(struct qcam *qcam)
1da177e4 102{
51224aa4 103 return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0;
1da177e4
LT
104}
105
d71964fb 106static inline unsigned int qcam_ready2(struct qcam *qcam)
1da177e4 107{
51224aa4 108 return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0;
1da177e4
LT
109}
110
d71964fb 111static unsigned int qcam_await_ready1(struct qcam *qcam, int value)
1da177e4 112{
d71964fb 113 struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
1da177e4
LT
114 unsigned long oldjiffies = jiffies;
115 unsigned int i;
116
168c626c 117 for (oldjiffies = jiffies;
51224aa4 118 time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
1da177e4
LT
119 if (qcam_ready1(qcam) == value)
120 return 0;
121
d56410e0 122 /* If the camera didn't respond within 1/25 second, poll slowly
1da177e4 123 for a while. */
51224aa4 124 for (i = 0; i < 50; i++) {
1da177e4
LT
125 if (qcam_ready1(qcam) == value)
126 return 0;
127 msleep_interruptible(100);
128 }
129
130 /* Probably somebody pulled the plug out. Not much we can do. */
d71964fb 131 v4l2_err(v4l2_dev, "ready1 timeout (%d) %x %x\n", value,
1da177e4
LT
132 parport_read_status(qcam->pport),
133 parport_read_control(qcam->pport));
134 return 1;
135}
136
d71964fb 137static unsigned int qcam_await_ready2(struct qcam *qcam, int value)
1da177e4 138{
d71964fb 139 struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
1da177e4
LT
140 unsigned long oldjiffies = jiffies;
141 unsigned int i;
142
168c626c 143 for (oldjiffies = jiffies;
51224aa4 144 time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
1da177e4
LT
145 if (qcam_ready2(qcam) == value)
146 return 0;
147
d56410e0 148 /* If the camera didn't respond within 1/25 second, poll slowly
1da177e4 149 for a while. */
51224aa4 150 for (i = 0; i < 50; i++) {
1da177e4
LT
151 if (qcam_ready2(qcam) == value)
152 return 0;
153 msleep_interruptible(100);
154 }
155
156 /* Probably somebody pulled the plug out. Not much we can do. */
d71964fb 157 v4l2_err(v4l2_dev, "ready2 timeout (%d) %x %x %x\n", value,
1da177e4
LT
158 parport_read_status(qcam->pport),
159 parport_read_control(qcam->pport),
160 parport_read_data(qcam->pport));
161 return 1;
162}
163
d71964fb 164static int qcam_read_data(struct qcam *qcam)
1da177e4
LT
165{
166 unsigned int idata;
51224aa4 167
1da177e4 168 qcam_set_ack(qcam, 0);
51224aa4
HV
169 if (qcam_await_ready1(qcam, 1))
170 return -1;
1da177e4
LT
171 idata = parport_read_status(qcam->pport) & 0xf0;
172 qcam_set_ack(qcam, 1);
51224aa4
HV
173 if (qcam_await_ready1(qcam, 0))
174 return -1;
175 idata |= parport_read_status(qcam->pport) >> 4;
1da177e4
LT
176 return idata;
177}
178
d71964fb 179static int qcam_write_data(struct qcam *qcam, unsigned int data)
1da177e4 180{
d71964fb 181 struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
1da177e4 182 unsigned int idata;
51224aa4 183
1da177e4
LT
184 parport_write_data(qcam->pport, data);
185 idata = qcam_read_data(qcam);
51224aa4 186 if (data != idata) {
d71964fb 187 v4l2_warn(v4l2_dev, "sent %x but received %x\n", data,
1da177e4
LT
188 idata);
189 return 1;
d56410e0 190 }
1da177e4
LT
191 return 0;
192}
193
d71964fb 194static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data)
1da177e4
LT
195{
196 if (qcam_write_data(qcam, cmd))
197 return -1;
198 if (qcam_write_data(qcam, data))
199 return -1;
200 return 0;
201}
202
d71964fb 203static inline int qcam_get(struct qcam *qcam, unsigned int cmd)
1da177e4
LT
204{
205 if (qcam_write_data(qcam, cmd))
206 return -1;
207 return qcam_read_data(qcam);
208}
209
d71964fb 210static int qc_detect(struct qcam *qcam)
1da177e4
LT
211{
212 unsigned int stat, ostat, i, count = 0;
213
214 /* The probe routine below is not very reliable. The IEEE-1284
215 probe takes precedence. */
216 /* XXX Currently parport provides no way to distinguish between
217 "the IEEE probe was not done" and "the probe was done, but
218 no device was found". Fix this one day. */
219 if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA
220 && qcam->pport->probe_info[0].model
d56410e0 221 && !strcmp(qcam->pdev->port->probe_info[0].model,
1da177e4
LT
222 "Color QuickCam 2.0")) {
223 printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n");
224 return 1;
225 }
d56410e0 226
1da177e4
LT
227 if (probe < 2)
228 return 0;
229
230 parport_write_control(qcam->pport, 0xc);
231
232 /* look for a heartbeat */
233 ostat = stat = parport_read_status(qcam->pport);
51224aa4 234 for (i = 0; i < 250; i++) {
1da177e4
LT
235 mdelay(1);
236 stat = parport_read_status(qcam->pport);
51224aa4
HV
237 if (ostat != stat) {
238 if (++count >= 3)
239 return 1;
1da177e4
LT
240 ostat = stat;
241 }
242 }
243
244 /* Reset the camera and try again */
245 parport_write_control(qcam->pport, 0xc);
246 parport_write_control(qcam->pport, 0x8);
247 mdelay(1);
248 parport_write_control(qcam->pport, 0xc);
249 mdelay(1);
250 count = 0;
251
252 ostat = stat = parport_read_status(qcam->pport);
51224aa4 253 for (i = 0; i < 250; i++) {
1da177e4
LT
254 mdelay(1);
255 stat = parport_read_status(qcam->pport);
51224aa4
HV
256 if (ostat != stat) {
257 if (++count >= 3)
258 return 1;
1da177e4
LT
259 ostat = stat;
260 }
261 }
262
263 /* no (or flatline) camera, give up */
264 return 0;
265}
266
d71964fb 267static void qc_reset(struct qcam *qcam)
1da177e4
LT
268{
269 parport_write_control(qcam->pport, 0xc);
270 parport_write_control(qcam->pport, 0x8);
271 mdelay(1);
272 parport_write_control(qcam->pport, 0xc);
d56410e0 273 mdelay(1);
1da177e4
LT
274}
275
276/* Reset the QuickCam and program for brightness, contrast,
277 * white-balance, and resolution. */
278
d71964fb 279static void qc_setup(struct qcam *qcam)
1da177e4 280{
d71964fb 281 qc_reset(qcam);
1da177e4 282
51224aa4 283 /* Set the brightness. */
d71964fb 284 qcam_set(qcam, 11, qcam->brightness);
1da177e4
LT
285
286 /* Set the height and width. These refer to the actual
287 CCD area *before* applying the selected decimation. */
d71964fb
HV
288 qcam_set(qcam, 17, qcam->ccd_height);
289 qcam_set(qcam, 19, qcam->ccd_width / 2);
1da177e4
LT
290
291 /* Set top and left. */
d71964fb
HV
292 qcam_set(qcam, 0xd, qcam->top);
293 qcam_set(qcam, 0xf, qcam->left);
1da177e4
LT
294
295 /* Set contrast and white balance. */
d71964fb
HV
296 qcam_set(qcam, 0x19, qcam->contrast);
297 qcam_set(qcam, 0x1f, qcam->whitebal);
d56410e0 298
1da177e4 299 /* Set the speed. */
d71964fb 300 qcam_set(qcam, 45, 2);
1da177e4
LT
301}
302
d56410e0 303/* Read some bytes from the camera and put them in the buffer.
1da177e4
LT
304 nbytes should be a multiple of 3, because bidirectional mode gives
305 us three bytes at a time. */
306
d71964fb 307static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes)
1da177e4
LT
308{
309 unsigned int bytes = 0;
310
d71964fb
HV
311 qcam_set_ack(qcam, 0);
312 if (qcam->bidirectional) {
1da177e4 313 /* It's a bidirectional port */
51224aa4 314 while (bytes < nbytes) {
1da177e4
LT
315 unsigned int lo1, hi1, lo2, hi2;
316 unsigned char r, g, b;
317
d71964fb 318 if (qcam_await_ready2(qcam, 1))
51224aa4 319 return bytes;
d71964fb
HV
320 lo1 = parport_read_data(qcam->pport) >> 1;
321 hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
322 qcam_set_ack(qcam, 1);
323 if (qcam_await_ready2(qcam, 0))
51224aa4 324 return bytes;
d71964fb
HV
325 lo2 = parport_read_data(qcam->pport) >> 1;
326 hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
327 qcam_set_ack(qcam, 0);
51224aa4
HV
328 r = lo1 | ((hi1 & 1) << 7);
329 g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1);
330 b = lo2 | ((hi2 & 1) << 7);
1da177e4
LT
331 if (force_rgb) {
332 buf[bytes++] = r;
333 buf[bytes++] = g;
334 buf[bytes++] = b;
335 } else {
336 buf[bytes++] = b;
337 buf[bytes++] = g;
338 buf[bytes++] = r;
339 }
340 }
51224aa4 341 } else {
1da177e4
LT
342 /* It's a unidirectional port */
343 int i = 0, n = bytes;
344 unsigned char rgb[3];
345
51224aa4 346 while (bytes < nbytes) {
1da177e4
LT
347 unsigned int hi, lo;
348
d71964fb 349 if (qcam_await_ready1(qcam, 1))
51224aa4 350 return bytes;
d71964fb
HV
351 hi = (parport_read_status(qcam->pport) & 0xf0);
352 qcam_set_ack(qcam, 1);
353 if (qcam_await_ready1(qcam, 0))
51224aa4 354 return bytes;
d71964fb
HV
355 lo = (parport_read_status(qcam->pport) & 0xf0);
356 qcam_set_ack(qcam, 0);
1da177e4
LT
357 /* flip some bits */
358 rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
359 if (i >= 2) {
360get_fragment:
361 if (force_rgb) {
362 buf[n++] = rgb[0];
363 buf[n++] = rgb[1];
364 buf[n++] = rgb[2];
365 } else {
366 buf[n++] = rgb[2];
367 buf[n++] = rgb[1];
368 buf[n++] = rgb[0];
369 }
370 }
371 }
372 if (i) {
373 i = 0;
374 goto get_fragment;
375 }
376 }
377 return bytes;
378}
379
380#define BUFSZ 150
381
d71964fb 382static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len)
1da177e4 383{
d71964fb 384 struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
8173090a 385 unsigned lines, pixelsperline;
d71964fb 386 unsigned int is_bi_dir = qcam->bidirectional;
1da177e4
LT
387 size_t wantlen, outptr = 0;
388 char tmpbuf[BUFSZ];
389
390 if (!access_ok(VERIFY_WRITE, buf, len))
391 return -EFAULT;
392
393 /* Wait for camera to become ready */
51224aa4 394 for (;;) {
d71964fb 395 int i = qcam_get(qcam, 41);
51224aa4 396
1da177e4 397 if (i == -1) {
d71964fb 398 qc_setup(qcam);
1da177e4
LT
399 return -EIO;
400 }
401 if ((i & 0x80) == 0)
402 break;
51224aa4 403 schedule();
1da177e4
LT
404 }
405
d71964fb 406 if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1))
1da177e4 407 return -EIO;
d56410e0 408
d71964fb
HV
409 lines = qcam->height;
410 pixelsperline = qcam->width;
1da177e4 411
51224aa4 412 if (is_bi_dir) {
1da177e4 413 /* Turn the port around */
d71964fb 414 parport_data_reverse(qcam->pport);
1da177e4 415 mdelay(3);
d71964fb
HV
416 qcam_set_ack(qcam, 0);
417 if (qcam_await_ready1(qcam, 1)) {
418 qc_setup(qcam);
1da177e4
LT
419 return -EIO;
420 }
d71964fb
HV
421 qcam_set_ack(qcam, 1);
422 if (qcam_await_ready1(qcam, 0)) {
423 qc_setup(qcam);
1da177e4
LT
424 return -EIO;
425 }
426 }
427
428 wantlen = lines * pixelsperline * 24 / 8;
429
51224aa4 430 while (wantlen) {
1da177e4 431 size_t t, s;
51224aa4
HV
432
433 s = (wantlen > BUFSZ) ? BUFSZ : wantlen;
d71964fb 434 t = qcam_read_bytes(qcam, tmpbuf, s);
51224aa4 435 if (outptr < len) {
1da177e4 436 size_t sz = len - outptr;
51224aa4
HV
437
438 if (sz > t)
439 sz = t;
440 if (__copy_to_user(buf + outptr, tmpbuf, sz))
1da177e4
LT
441 break;
442 outptr += sz;
443 }
444 wantlen -= t;
445 if (t < s)
446 break;
447 cond_resched();
448 }
449
450 len = outptr;
451
51224aa4 452 if (wantlen) {
d71964fb 453 v4l2_err(v4l2_dev, "short read.\n");
1da177e4 454 if (is_bi_dir)
d71964fb
HV
455 parport_data_forward(qcam->pport);
456 qc_setup(qcam);
1da177e4
LT
457 return len;
458 }
459
51224aa4 460 if (is_bi_dir) {
1da177e4 461 int l;
51224aa4 462
1da177e4 463 do {
d71964fb 464 l = qcam_read_bytes(qcam, tmpbuf, 3);
1da177e4
LT
465 cond_resched();
466 } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
467 if (force_rgb) {
468 if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
d71964fb 469 v4l2_err(v4l2_dev, "bad EOF\n");
1da177e4
LT
470 } else {
471 if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
d71964fb 472 v4l2_err(v4l2_dev, "bad EOF\n");
1da177e4 473 }
d71964fb
HV
474 qcam_set_ack(qcam, 0);
475 if (qcam_await_ready1(qcam, 1)) {
476 v4l2_err(v4l2_dev, "no ack after EOF\n");
477 parport_data_forward(qcam->pport);
478 qc_setup(qcam);
1da177e4
LT
479 return len;
480 }
d71964fb 481 parport_data_forward(qcam->pport);
1da177e4 482 mdelay(3);
d71964fb
HV
483 qcam_set_ack(qcam, 1);
484 if (qcam_await_ready1(qcam, 0)) {
485 v4l2_err(v4l2_dev, "no ack to port turnaround\n");
486 qc_setup(qcam);
1da177e4
LT
487 return len;
488 }
51224aa4 489 } else {
1da177e4 490 int l;
51224aa4 491
1da177e4 492 do {
d71964fb 493 l = qcam_read_bytes(qcam, tmpbuf, 1);
1da177e4
LT
494 cond_resched();
495 } while (l && tmpbuf[0] == 0x7e);
d71964fb 496 l = qcam_read_bytes(qcam, tmpbuf + 1, 2);
1da177e4
LT
497 if (force_rgb) {
498 if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
d71964fb 499 v4l2_err(v4l2_dev, "bad EOF\n");
1da177e4
LT
500 } else {
501 if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
d71964fb 502 v4l2_err(v4l2_dev, "bad EOF\n");
1da177e4
LT
503 }
504 }
505
d71964fb 506 qcam_write_data(qcam, 0);
1da177e4
LT
507 return len;
508}
509
510/*
511 * Video4linux interfacing
512 */
513
d71964fb
HV
514static int qcam_querycap(struct file *file, void *priv,
515 struct v4l2_capability *vcap)
1da177e4 516{
d71964fb 517 struct qcam *qcam = video_drvdata(file);
d56410e0 518
d71964fb
HV
519 strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
520 strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card));
521 strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
34caed8b
HV
522 vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
523 vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
d71964fb
HV
524 return 0;
525}
51224aa4 526
d71964fb
HV
527static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
528{
529 if (vin->index > 0)
530 return -EINVAL;
531 strlcpy(vin->name, "Camera", sizeof(vin->name));
532 vin->type = V4L2_INPUT_TYPE_CAMERA;
533 vin->audioset = 0;
534 vin->tuner = 0;
535 vin->std = 0;
536 vin->status = 0;
537 return 0;
538}
51224aa4 539
d71964fb
HV
540static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
541{
542 *inp = 0;
543 return 0;
544}
545
546static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
547{
548 return (inp > 0) ? -EINVAL : 0;
549}
550
d71964fb
HV
551static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
552{
553 struct qcam *qcam = video_drvdata(file);
554 struct v4l2_pix_format *pix = &fmt->fmt.pix;
555
556 pix->width = qcam->width;
557 pix->height = qcam->height;
558 pix->pixelformat = V4L2_PIX_FMT_RGB24;
559 pix->field = V4L2_FIELD_NONE;
560 pix->bytesperline = 3 * qcam->width;
561 pix->sizeimage = 3 * qcam->width * qcam->height;
562 /* Just a guess */
563 pix->colorspace = V4L2_COLORSPACE_SRGB;
564 return 0;
565}
566
567static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
568{
569 struct v4l2_pix_format *pix = &fmt->fmt.pix;
570
571 if (pix->height < 60 || pix->width < 80) {
572 pix->height = 60;
573 pix->width = 80;
574 } else if (pix->height < 120 || pix->width < 160) {
575 pix->height = 120;
576 pix->width = 160;
577 } else {
578 pix->height = 240;
579 pix->width = 320;
51224aa4 580 }
d71964fb
HV
581 pix->pixelformat = V4L2_PIX_FMT_RGB24;
582 pix->field = V4L2_FIELD_NONE;
583 pix->bytesperline = 3 * pix->width;
584 pix->sizeimage = 3 * pix->width * pix->height;
585 /* Just a guess */
586 pix->colorspace = V4L2_COLORSPACE_SRGB;
587 return 0;
588}
589
590static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
591{
592 struct qcam *qcam = video_drvdata(file);
593 struct v4l2_pix_format *pix = &fmt->fmt.pix;
594 int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
595
596 if (ret)
597 return ret;
598 switch (pix->height) {
599 case 60:
600 qcam->mode = QC_DECIMATION_4;
601 break;
602 case 120:
603 qcam->mode = QC_DECIMATION_2;
604 break;
51224aa4 605 default:
d71964fb
HV
606 qcam->mode = QC_DECIMATION_1;
607 break;
1da177e4 608 }
d71964fb
HV
609
610 mutex_lock(&qcam->lock);
611 qcam->mode |= QC_MILLIONS;
612 qcam->height = pix->height;
613 qcam->width = pix->width;
614 parport_claim_or_block(qcam->pdev);
615 qc_setup(qcam);
616 parport_release(qcam->pdev);
617 mutex_unlock(&qcam->lock);
1da177e4
LT
618 return 0;
619}
620
d71964fb 621static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
1da177e4 622{
d71964fb
HV
623 static struct v4l2_fmtdesc formats[] = {
624 { 0, 0, 0,
625 "RGB 8:8:8", V4L2_PIX_FMT_RGB24,
626 { 0, 0, 0, 0 }
627 },
628 };
629 enum v4l2_buf_type type = fmt->type;
630
631 if (fmt->index > 0)
632 return -EINVAL;
633
634 *fmt = formats[fmt->index];
635 fmt->type = type;
636 return 0;
1da177e4
LT
637}
638
639static ssize_t qcam_read(struct file *file, char __user *buf,
640 size_t count, loff_t *ppos)
641{
d71964fb 642 struct qcam *qcam = video_drvdata(file);
1da177e4
LT
643 int len;
644
3593cab5 645 mutex_lock(&qcam->lock);
1da177e4
LT
646 parport_claim_or_block(qcam->pdev);
647 /* Probably should have a semaphore against multiple users */
51224aa4 648 len = qc_capture(qcam, buf, count);
1da177e4 649 parport_release(qcam->pdev);
3593cab5 650 mutex_unlock(&qcam->lock);
1da177e4
LT
651 return len;
652}
653
34caed8b
HV
654static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
655{
656 struct qcam *qcam =
657 container_of(ctrl->handler, struct qcam, hdl);
658 int ret = 0;
659
660 mutex_lock(&qcam->lock);
661 switch (ctrl->id) {
662 case V4L2_CID_BRIGHTNESS:
663 qcam->brightness = ctrl->val;
664 break;
665 case V4L2_CID_CONTRAST:
666 qcam->contrast = ctrl->val;
667 break;
668 case V4L2_CID_GAMMA:
669 qcam->whitebal = ctrl->val;
670 break;
671 default:
672 ret = -EINVAL;
673 break;
674 }
675 if (ret == 0) {
676 parport_claim_or_block(qcam->pdev);
677 qc_setup(qcam);
678 parport_release(qcam->pdev);
679 }
680 mutex_unlock(&qcam->lock);
681 return ret;
682}
683
bec43661 684static const struct v4l2_file_operations qcam_fops = {
1da177e4 685 .owner = THIS_MODULE,
34caed8b
HV
686 .open = v4l2_fh_open,
687 .release = v4l2_fh_release,
688 .poll = v4l2_ctrl_poll,
61df3c9b 689 .unlocked_ioctl = video_ioctl2,
1da177e4 690 .read = qcam_read,
1da177e4
LT
691};
692
d71964fb
HV
693static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
694 .vidioc_querycap = qcam_querycap,
695 .vidioc_g_input = qcam_g_input,
696 .vidioc_s_input = qcam_s_input,
697 .vidioc_enum_input = qcam_enum_input,
34caed8b 698 .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap,
d71964fb
HV
699 .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
700 .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
701 .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap,
34caed8b
HV
702 .vidioc_log_status = v4l2_ctrl_log_status,
703 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
704 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
705};
706
707static const struct v4l2_ctrl_ops qcam_ctrl_ops = {
708 .s_ctrl = qcam_s_ctrl,
1da177e4
LT
709};
710
711/* Initialize the QuickCam driver control structure. */
712
d71964fb 713static struct qcam *qcam_init(struct parport *port)
1da177e4 714{
d71964fb
HV
715 struct qcam *qcam;
716 struct v4l2_device *v4l2_dev;
d56410e0 717
d71964fb
HV
718 qcam = kzalloc(sizeof(*qcam), GFP_KERNEL);
719 if (qcam == NULL)
1da177e4
LT
720 return NULL;
721
d71964fb
HV
722 v4l2_dev = &qcam->v4l2_dev;
723 strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name));
724
725 if (v4l2_device_register(NULL, v4l2_dev) < 0) {
726 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
ee893e9a 727 kfree(qcam);
d71964fb
HV
728 return NULL;
729 }
730
34caed8b
HV
731 v4l2_ctrl_handler_init(&qcam->hdl, 3);
732 v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
733 V4L2_CID_BRIGHTNESS, 0, 255, 1, 240);
734 v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
735 V4L2_CID_CONTRAST, 0, 255, 1, 192);
736 v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
737 V4L2_CID_GAMMA, 0, 255, 1, 128);
738 if (qcam->hdl.error) {
739 v4l2_err(v4l2_dev, "couldn't register controls\n");
740 v4l2_ctrl_handler_free(&qcam->hdl);
741 kfree(qcam);
742 return NULL;
743 }
744
d71964fb
HV
745 qcam->pport = port;
746 qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
1da177e4
LT
747 NULL, 0, NULL);
748
d71964fb 749 qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
1da177e4 750
d71964fb
HV
751 if (qcam->pdev == NULL) {
752 v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
34caed8b 753 v4l2_ctrl_handler_free(&qcam->hdl);
d71964fb 754 kfree(qcam);
1da177e4
LT
755 return NULL;
756 }
d56410e0 757
d71964fb
HV
758 strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name));
759 qcam->vdev.v4l2_dev = v4l2_dev;
760 qcam->vdev.fops = &qcam_fops;
761 qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
762 qcam->vdev.release = video_device_release_empty;
34caed8b
HV
763 qcam->vdev.ctrl_handler = &qcam->hdl;
764 set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
d71964fb
HV
765 video_set_drvdata(&qcam->vdev, qcam);
766
767 mutex_init(&qcam->lock);
768 qcam->width = qcam->ccd_width = 320;
769 qcam->height = qcam->ccd_height = 240;
770 qcam->mode = QC_MILLIONS | QC_DECIMATION_1;
771 qcam->contrast = 192;
772 qcam->brightness = 240;
773 qcam->whitebal = 128;
774 qcam->top = 1;
775 qcam->left = 14;
776 return qcam;
1da177e4
LT
777}
778
1da177e4
LT
779static int init_cqcam(struct parport *port)
780{
d71964fb
HV
781 struct qcam *qcam;
782 struct v4l2_device *v4l2_dev;
1da177e4 783
51224aa4 784 if (parport[0] != -1) {
1da177e4
LT
785 /* The user gave specific instructions */
786 int i, found = 0;
51224aa4
HV
787
788 for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) {
1da177e4
LT
789 if (parport[0] == port->number)
790 found = 1;
791 }
792 if (!found)
793 return -ENODEV;
794 }
795
796 if (num_cams == MAX_CAMS)
797 return -ENOSPC;
798
799 qcam = qcam_init(port);
51224aa4 800 if (qcam == NULL)
1da177e4 801 return -ENODEV;
d56410e0 802
d71964fb
HV
803 v4l2_dev = &qcam->v4l2_dev;
804
1da177e4
LT
805 parport_claim_or_block(qcam->pdev);
806
807 qc_reset(qcam);
d56410e0 808
51224aa4 809 if (probe && qc_detect(qcam) == 0) {
1da177e4
LT
810 parport_release(qcam->pdev);
811 parport_unregister_device(qcam->pdev);
812 kfree(qcam);
813 return -ENODEV;
814 }
815
816 qc_setup(qcam);
817
818 parport_release(qcam->pdev);
d56410e0 819
dc60de33 820 if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
d71964fb 821 v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n",
1da177e4
LT
822 qcam->pport->name);
823 parport_unregister_device(qcam->pdev);
824 kfree(qcam);
825 return -ENODEV;
826 }
827
d71964fb 828 v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n",
38c7c036 829 video_device_node_name(&qcam->vdev), qcam->pport->name);
d56410e0 830
1da177e4
LT
831 qcams[num_cams++] = qcam;
832
833 return 0;
834}
835
d71964fb 836static void close_cqcam(struct qcam *qcam)
1da177e4
LT
837{
838 video_unregister_device(&qcam->vdev);
34caed8b 839 v4l2_ctrl_handler_free(&qcam->hdl);
1da177e4
LT
840 parport_unregister_device(qcam->pdev);
841 kfree(qcam);
842}
843
844static void cq_attach(struct parport *port)
845{
846 init_cqcam(port);
847}
848
849static void cq_detach(struct parport *port)
850{
851 /* Write this some day. */
852}
853
854static struct parport_driver cqcam_driver = {
855 .name = "cqcam",
856 .attach = cq_attach,
857 .detach = cq_detach,
858};
859
51224aa4 860static int __init cqcam_init(void)
1da177e4 861{
d71964fb 862 printk(KERN_INFO BANNER "\n");
1da177e4
LT
863
864 return parport_register_driver(&cqcam_driver);
865}
866
51224aa4 867static void __exit cqcam_cleanup(void)
1da177e4
LT
868{
869 unsigned int i;
870
871 for (i = 0; i < num_cams; i++)
872 close_cqcam(qcams[i]);
873
874 parport_unregister_driver(&cqcam_driver);
875}
876
877MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
878MODULE_DESCRIPTION(BANNER);
879MODULE_LICENSE("GPL");
1990d50b 880MODULE_VERSION("0.0.4");
1da177e4 881
1da177e4
LT
882module_init(cqcam_init);
883module_exit(cqcam_cleanup);