Revert "udp: remove redundant variable"
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / media / video / pms.c
blobe753b5e4d2ce449ba3730d3a3f17244491b9e04a
1 /*
2 * Media Vision Pro Movie Studio
3 * or
4 * "all you need is an I2C bus some RAM and a prayer"
6 * This draws heavily on code
8 * (c) Wolfgang Koehler, wolf@first.gmd.de, Dec. 1994
9 * Kiefernring 15
10 * 14478 Potsdam, Germany
12 * Most of this code is directly derived from his userspace driver.
13 * His driver works so send any reports to alan@lxorguk.ukuu.org.uk
14 * unless the userspace driver also doesn't work for you...
16 * Changes:
17 * 25-11-2009 Hans Verkuil <hverkuil@xs4all.nl>
18 * - converted to version 2 of the V4L API.
19 * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it>
20 * - pms_capture: report back -EFAULT
23 #include <linux/module.h>
24 #include <linux/delay.h>
25 #include <linux/errno.h>
26 #include <linux/fs.h>
27 #include <linux/kernel.h>
28 #include <linux/mm.h>
29 #include <linux/ioport.h>
30 #include <linux/init.h>
31 #include <linux/mutex.h>
32 #include <linux/uaccess.h>
33 #include <asm/io.h>
35 #include <linux/videodev2.h>
36 #include <media/v4l2-common.h>
37 #include <media/v4l2-ioctl.h>
38 #include <media/v4l2-device.h>
40 MODULE_LICENSE("GPL");
41 MODULE_VERSION("0.0.4");
43 #define MOTOROLA 1
44 #define PHILIPS2 2 /* SAA7191 */
45 #define PHILIPS1 3
46 #define MVVMEMORYWIDTH 0x40 /* 512 bytes */
48 struct i2c_info {
49 u8 slave;
50 u8 sub;
51 u8 data;
52 u8 hits;
55 struct pms {
56 struct v4l2_device v4l2_dev;
57 struct video_device vdev;
58 int height;
59 int width;
60 int depth;
61 int input;
62 s32 brightness, saturation, hue, contrast;
63 struct mutex lock;
64 int i2c_count;
65 struct i2c_info i2cinfo[64];
67 int decoder;
68 int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
69 v4l2_std_id std;
70 int io;
71 int data;
72 void __iomem *mem;
75 static struct pms pms_card;
78 * I/O ports and Shared Memory
81 static int io_port = 0x250;
82 module_param(io_port, int, 0);
84 static int mem_base = 0xc8000;
85 module_param(mem_base, int, 0);
87 static int video_nr = -1;
88 module_param(video_nr, int, 0);
91 static inline void mvv_write(struct pms *dev, u8 index, u8 value)
93 outw(index | (value << 8), dev->io);
96 static inline u8 mvv_read(struct pms *dev, u8 index)
98 outb(index, dev->io);
99 return inb(dev->data);
102 static int pms_i2c_stat(struct pms *dev, u8 slave)
104 int counter = 0;
105 int i;
107 outb(0x28, dev->io);
109 while ((inb(dev->data) & 0x01) == 0)
110 if (counter++ == 256)
111 break;
113 while ((inb(dev->data) & 0x01) != 0)
114 if (counter++ == 256)
115 break;
117 outb(slave, dev->io);
119 counter = 0;
120 while ((inb(dev->data) & 0x01) == 0)
121 if (counter++ == 256)
122 break;
124 while ((inb(dev->data) & 0x01) != 0)
125 if (counter++ == 256)
126 break;
128 for (i = 0; i < 12; i++) {
129 char st = inb(dev->data);
131 if ((st & 2) != 0)
132 return -1;
133 if ((st & 1) == 0)
134 break;
136 outb(0x29, dev->io);
137 return inb(dev->data);
140 static int pms_i2c_write(struct pms *dev, u16 slave, u16 sub, u16 data)
142 int skip = 0;
143 int count;
144 int i;
146 for (i = 0; i < dev->i2c_count; i++) {
147 if ((dev->i2cinfo[i].slave == slave) &&
148 (dev->i2cinfo[i].sub == sub)) {
149 if (dev->i2cinfo[i].data == data)
150 skip = 1;
151 dev->i2cinfo[i].data = data;
152 i = dev->i2c_count + 1;
156 if (i == dev->i2c_count && dev->i2c_count < 64) {
157 dev->i2cinfo[dev->i2c_count].slave = slave;
158 dev->i2cinfo[dev->i2c_count].sub = sub;
159 dev->i2cinfo[dev->i2c_count].data = data;
160 dev->i2c_count++;
163 if (skip)
164 return 0;
166 mvv_write(dev, 0x29, sub);
167 mvv_write(dev, 0x2A, data);
168 mvv_write(dev, 0x28, slave);
170 outb(0x28, dev->io);
172 count = 0;
173 while ((inb(dev->data) & 1) == 0)
174 if (count > 255)
175 break;
176 while ((inb(dev->data) & 1) != 0)
177 if (count > 255)
178 break;
180 count = inb(dev->data);
182 if (count & 2)
183 return -1;
184 return count;
187 static int pms_i2c_read(struct pms *dev, int slave, int sub)
189 int i;
191 for (i = 0; i < dev->i2c_count; i++) {
192 if (dev->i2cinfo[i].slave == slave && dev->i2cinfo[i].sub == sub)
193 return dev->i2cinfo[i].data;
195 return 0;
199 static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or)
201 u8 tmp;
203 tmp = pms_i2c_read(dev, slave, sub);
204 tmp = (tmp & and) | or;
205 pms_i2c_write(dev, slave, sub, tmp);
209 * Control functions
213 static void pms_videosource(struct pms *dev, short source)
215 switch (dev->decoder) {
216 case MOTOROLA:
217 break;
218 case PHILIPS2:
219 pms_i2c_andor(dev, 0x8a, 0x06, 0x7f, source ? 0x80 : 0);
220 break;
221 case PHILIPS1:
222 break;
224 mvv_write(dev, 0x2E, 0x31);
225 /* Was: mvv_write(dev, 0x2E, source ? 0x31 : 0x30);
226 But could not make this work correctly. Only Composite input
227 worked for me. */
230 static void pms_hue(struct pms *dev, short hue)
232 switch (dev->decoder) {
233 case MOTOROLA:
234 pms_i2c_write(dev, 0x8a, 0x00, hue);
235 break;
236 case PHILIPS2:
237 pms_i2c_write(dev, 0x8a, 0x07, hue);
238 break;
239 case PHILIPS1:
240 pms_i2c_write(dev, 0x42, 0x07, hue);
241 break;
245 static void pms_saturation(struct pms *dev, short sat)
247 switch (dev->decoder) {
248 case MOTOROLA:
249 pms_i2c_write(dev, 0x8a, 0x00, sat);
250 break;
251 case PHILIPS1:
252 pms_i2c_write(dev, 0x42, 0x12, sat);
253 break;
258 static void pms_contrast(struct pms *dev, short contrast)
260 switch (dev->decoder) {
261 case MOTOROLA:
262 pms_i2c_write(dev, 0x8a, 0x00, contrast);
263 break;
264 case PHILIPS1:
265 pms_i2c_write(dev, 0x42, 0x13, contrast);
266 break;
270 static void pms_brightness(struct pms *dev, short brightness)
272 switch (dev->decoder) {
273 case MOTOROLA:
274 pms_i2c_write(dev, 0x8a, 0x00, brightness);
275 pms_i2c_write(dev, 0x8a, 0x00, brightness);
276 pms_i2c_write(dev, 0x8a, 0x00, brightness);
277 break;
278 case PHILIPS1:
279 pms_i2c_write(dev, 0x42, 0x19, brightness);
280 break;
285 static void pms_format(struct pms *dev, short format)
287 int target;
289 dev->standard = format;
291 if (dev->decoder == PHILIPS1)
292 target = 0x42;
293 else if (dev->decoder == PHILIPS2)
294 target = 0x8a;
295 else
296 return;
298 switch (format) {
299 case 0: /* Auto */
300 pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
301 pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x80);
302 break;
303 case 1: /* NTSC */
304 pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
305 pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x40);
306 break;
307 case 2: /* PAL */
308 pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
309 pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
310 break;
311 case 3: /* SECAM */
312 pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x01);
313 pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
314 break;
318 #ifdef FOR_FUTURE_EXPANSION
321 * These features of the PMS card are not currently exposes. They
322 * could become a private v4l ioctl for PMSCONFIG or somesuch if
323 * people need it. We also don't yet use the PMS interrupt.
326 static void pms_hstart(struct pms *dev, short start)
328 switch (dev->decoder) {
329 case PHILIPS1:
330 pms_i2c_write(dev, 0x8a, 0x05, start);
331 pms_i2c_write(dev, 0x8a, 0x18, start);
332 break;
333 case PHILIPS2:
334 pms_i2c_write(dev, 0x42, 0x05, start);
335 pms_i2c_write(dev, 0x42, 0x18, start);
336 break;
341 * Bandpass filters
344 static void pms_bandpass(struct pms *dev, short pass)
346 if (dev->decoder == PHILIPS2)
347 pms_i2c_andor(dev, 0x8a, 0x06, 0xcf, (pass & 0x03) << 4);
348 else if (dev->decoder == PHILIPS1)
349 pms_i2c_andor(dev, 0x42, 0x06, 0xcf, (pass & 0x03) << 4);
352 static void pms_antisnow(struct pms *dev, short snow)
354 if (dev->decoder == PHILIPS2)
355 pms_i2c_andor(dev, 0x8a, 0x06, 0xf3, (snow & 0x03) << 2);
356 else if (dev->decoder == PHILIPS1)
357 pms_i2c_andor(dev, 0x42, 0x06, 0xf3, (snow & 0x03) << 2);
360 static void pms_sharpness(struct pms *dev, short sharp)
362 if (dev->decoder == PHILIPS2)
363 pms_i2c_andor(dev, 0x8a, 0x06, 0xfc, sharp & 0x03);
364 else if (dev->decoder == PHILIPS1)
365 pms_i2c_andor(dev, 0x42, 0x06, 0xfc, sharp & 0x03);
368 static void pms_chromaagc(struct pms *dev, short agc)
370 if (dev->decoder == PHILIPS2)
371 pms_i2c_andor(dev, 0x8a, 0x0c, 0x9f, (agc & 0x03) << 5);
372 else if (dev->decoder == PHILIPS1)
373 pms_i2c_andor(dev, 0x42, 0x0c, 0x9f, (agc & 0x03) << 5);
376 static void pms_vertnoise(struct pms *dev, short noise)
378 if (dev->decoder == PHILIPS2)
379 pms_i2c_andor(dev, 0x8a, 0x10, 0xfc, noise & 3);
380 else if (dev->decoder == PHILIPS1)
381 pms_i2c_andor(dev, 0x42, 0x10, 0xfc, noise & 3);
384 static void pms_forcecolour(struct pms *dev, short colour)
386 if (dev->decoder == PHILIPS2)
387 pms_i2c_andor(dev, 0x8a, 0x0c, 0x7f, (colour & 1) << 7);
388 else if (dev->decoder == PHILIPS1)
389 pms_i2c_andor(dev, 0x42, 0x0c, 0x7, (colour & 1) << 7);
392 static void pms_antigamma(struct pms *dev, short gamma)
394 if (dev->decoder == PHILIPS2)
395 pms_i2c_andor(dev, 0xb8, 0x00, 0x7f, (gamma & 1) << 7);
396 else if (dev->decoder == PHILIPS1)
397 pms_i2c_andor(dev, 0x42, 0x20, 0x7, (gamma & 1) << 7);
400 static void pms_prefilter(struct pms *dev, short filter)
402 if (dev->decoder == PHILIPS2)
403 pms_i2c_andor(dev, 0x8a, 0x06, 0xbf, (filter & 1) << 6);
404 else if (dev->decoder == PHILIPS1)
405 pms_i2c_andor(dev, 0x42, 0x06, 0xbf, (filter & 1) << 6);
408 static void pms_hfilter(struct pms *dev, short filter)
410 if (dev->decoder == PHILIPS2)
411 pms_i2c_andor(dev, 0xb8, 0x04, 0x1f, (filter & 7) << 5);
412 else if (dev->decoder == PHILIPS1)
413 pms_i2c_andor(dev, 0x42, 0x24, 0x1f, (filter & 7) << 5);
416 static void pms_vfilter(struct pms *dev, short filter)
418 if (dev->decoder == PHILIPS2)
419 pms_i2c_andor(dev, 0xb8, 0x08, 0x9f, (filter & 3) << 5);
420 else if (dev->decoder == PHILIPS1)
421 pms_i2c_andor(dev, 0x42, 0x28, 0x9f, (filter & 3) << 5);
424 static void pms_killcolour(struct pms *dev, short colour)
426 if (dev->decoder == PHILIPS2) {
427 pms_i2c_andor(dev, 0x8a, 0x08, 0x07, (colour & 0x1f) << 3);
428 pms_i2c_andor(dev, 0x8a, 0x09, 0x07, (colour & 0x1f) << 3);
429 } else if (dev->decoder == PHILIPS1) {
430 pms_i2c_andor(dev, 0x42, 0x08, 0x07, (colour & 0x1f) << 3);
431 pms_i2c_andor(dev, 0x42, 0x09, 0x07, (colour & 0x1f) << 3);
435 static void pms_chromagain(struct pms *dev, short chroma)
437 if (dev->decoder == PHILIPS2)
438 pms_i2c_write(dev, 0x8a, 0x11, chroma);
439 else if (dev->decoder == PHILIPS1)
440 pms_i2c_write(dev, 0x42, 0x11, chroma);
444 static void pms_spacialcompl(struct pms *dev, short data)
446 mvv_write(dev, 0x3b, data);
449 static void pms_spacialcomph(struct pms *dev, short data)
451 mvv_write(dev, 0x3a, data);
454 static void pms_vstart(struct pms *dev, short start)
456 mvv_write(dev, 0x16, start);
457 mvv_write(dev, 0x17, (start >> 8) & 0x01);
460 #endif
462 static void pms_secamcross(struct pms *dev, short cross)
464 if (dev->decoder == PHILIPS2)
465 pms_i2c_andor(dev, 0x8a, 0x0f, 0xdf, (cross & 1) << 5);
466 else if (dev->decoder == PHILIPS1)
467 pms_i2c_andor(dev, 0x42, 0x0f, 0xdf, (cross & 1) << 5);
471 static void pms_swsense(struct pms *dev, short sense)
473 if (dev->decoder == PHILIPS2) {
474 pms_i2c_write(dev, 0x8a, 0x0a, sense);
475 pms_i2c_write(dev, 0x8a, 0x0b, sense);
476 } else if (dev->decoder == PHILIPS1) {
477 pms_i2c_write(dev, 0x42, 0x0a, sense);
478 pms_i2c_write(dev, 0x42, 0x0b, sense);
483 static void pms_framerate(struct pms *dev, short frr)
485 int fps = (dev->std & V4L2_STD_525_60) ? 30 : 25;
487 if (frr == 0)
488 return;
489 fps = fps/frr;
490 mvv_write(dev, 0x14, 0x80 | fps);
491 mvv_write(dev, 0x15, 1);
494 static void pms_vert(struct pms *dev, u8 deciden, u8 decinum)
496 mvv_write(dev, 0x1c, deciden); /* Denominator */
497 mvv_write(dev, 0x1d, decinum); /* Numerator */
501 * Turn 16bit ratios into best small ratio the chipset can grok
504 static void pms_vertdeci(struct pms *dev, unsigned short decinum, unsigned short deciden)
506 /* Knock it down by / 5 once */
507 if (decinum % 5 == 0) {
508 deciden /= 5;
509 decinum /= 5;
512 * 3's
514 while (decinum % 3 == 0 && deciden % 3 == 0) {
515 deciden /= 3;
516 decinum /= 3;
519 * 2's
521 while (decinum % 2 == 0 && deciden % 2 == 0) {
522 decinum /= 2;
523 deciden /= 2;
526 * Fudgyify
528 while (deciden > 32) {
529 deciden /= 2;
530 decinum = (decinum + 1) / 2;
532 if (deciden == 32)
533 deciden--;
534 pms_vert(dev, deciden, decinum);
537 static void pms_horzdeci(struct pms *dev, short decinum, short deciden)
539 if (decinum <= 512) {
540 if (decinum % 5 == 0) {
541 decinum /= 5;
542 deciden /= 5;
544 } else {
545 decinum = 512;
546 deciden = 640; /* 768 would be ideal */
549 while (((decinum | deciden) & 1) == 0) {
550 decinum >>= 1;
551 deciden >>= 1;
553 while (deciden > 32) {
554 deciden >>= 1;
555 decinum = (decinum + 1) >> 1;
557 if (deciden == 32)
558 deciden--;
560 mvv_write(dev, 0x24, 0x80 | deciden);
561 mvv_write(dev, 0x25, decinum);
564 static void pms_resolution(struct pms *dev, short width, short height)
566 int fg_height;
568 fg_height = height;
569 if (fg_height > 280)
570 fg_height = 280;
572 mvv_write(dev, 0x18, fg_height);
573 mvv_write(dev, 0x19, fg_height >> 8);
575 if (dev->std & V4L2_STD_525_60) {
576 mvv_write(dev, 0x1a, 0xfc);
577 mvv_write(dev, 0x1b, 0x00);
578 if (height > fg_height)
579 pms_vertdeci(dev, 240, 240);
580 else
581 pms_vertdeci(dev, fg_height, 240);
582 } else {
583 mvv_write(dev, 0x1a, 0x1a);
584 mvv_write(dev, 0x1b, 0x01);
585 if (fg_height > 256)
586 pms_vertdeci(dev, 270, 270);
587 else
588 pms_vertdeci(dev, fg_height, 270);
590 mvv_write(dev, 0x12, 0);
591 mvv_write(dev, 0x13, MVVMEMORYWIDTH);
592 mvv_write(dev, 0x42, 0x00);
593 mvv_write(dev, 0x43, 0x00);
594 mvv_write(dev, 0x44, MVVMEMORYWIDTH);
596 mvv_write(dev, 0x22, width + 8);
597 mvv_write(dev, 0x23, (width + 8) >> 8);
599 if (dev->std & V4L2_STD_525_60)
600 pms_horzdeci(dev, width, 640);
601 else
602 pms_horzdeci(dev, width + 8, 768);
604 mvv_write(dev, 0x30, mvv_read(dev, 0x30) & 0xfe);
605 mvv_write(dev, 0x08, mvv_read(dev, 0x08) | 0x01);
606 mvv_write(dev, 0x01, mvv_read(dev, 0x01) & 0xfd);
607 mvv_write(dev, 0x32, 0x00);
608 mvv_write(dev, 0x33, MVVMEMORYWIDTH);
613 * Set Input
616 static void pms_vcrinput(struct pms *dev, short input)
618 if (dev->decoder == PHILIPS2)
619 pms_i2c_andor(dev, 0x8a, 0x0d, 0x7f, (input & 1) << 7);
620 else if (dev->decoder == PHILIPS1)
621 pms_i2c_andor(dev, 0x42, 0x0d, 0x7f, (input & 1) << 7);
625 static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count)
627 int y;
628 int dw = 2 * dev->width;
629 char tmp[dw + 32]; /* using a temp buffer is faster than direct */
630 int cnt = 0;
631 int len = 0;
632 unsigned char r8 = 0x5; /* value for reg8 */
634 if (rgb555)
635 r8 |= 0x20; /* else use untranslated rgb = 565 */
636 mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */
638 /* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
640 for (y = 0; y < dev->height; y++) {
641 writeb(0, dev->mem); /* synchronisiert neue Zeile */
644 * This is in truth a fifo, be very careful as if you
645 * forgot this odd things will occur 8)
648 memcpy_fromio(tmp, dev->mem, dw + 32); /* discard 16 word */
649 cnt -= dev->height;
650 while (cnt <= 0) {
652 * Don't copy too far
654 int dt = dw;
655 if (dt + len > count)
656 dt = count - len;
657 cnt += dev->height;
658 if (copy_to_user(buf, tmp + 32, dt))
659 return len ? len : -EFAULT;
660 buf += dt;
661 len += dt;
664 return len;
669 * Video4linux interfacing
672 static int pms_querycap(struct file *file, void *priv,
673 struct v4l2_capability *vcap)
675 struct pms *dev = video_drvdata(file);
677 strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver));
678 strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card));
679 strlcpy(vcap->bus_info, "ISA", sizeof(vcap->bus_info));
680 vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
681 return 0;
684 static int pms_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
686 static const char *inputs[4] = {
687 "Composite",
688 "S-Video",
689 "Composite (VCR)",
690 "S-Video (VCR)"
693 if (vin->index > 3)
694 return -EINVAL;
695 strlcpy(vin->name, inputs[vin->index], sizeof(vin->name));
696 vin->type = V4L2_INPUT_TYPE_CAMERA;
697 vin->audioset = 0;
698 vin->tuner = 0;
699 vin->std = V4L2_STD_ALL;
700 vin->status = 0;
701 return 0;
704 static int pms_g_input(struct file *file, void *fh, unsigned int *inp)
706 struct pms *dev = video_drvdata(file);
708 *inp = dev->input;
709 return 0;
712 static int pms_s_input(struct file *file, void *fh, unsigned int inp)
714 struct pms *dev = video_drvdata(file);
716 if (inp > 3)
717 return -EINVAL;
719 mutex_lock(&dev->lock);
720 dev->input = inp;
721 pms_videosource(dev, inp & 1);
722 pms_vcrinput(dev, inp >> 1);
723 mutex_unlock(&dev->lock);
724 return 0;
727 static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std)
729 struct pms *dev = video_drvdata(file);
731 *std = dev->std;
732 return 0;
735 static int pms_s_std(struct file *file, void *fh, v4l2_std_id *std)
737 struct pms *dev = video_drvdata(file);
738 int ret = 0;
740 dev->std = *std;
741 mutex_lock(&dev->lock);
742 if (dev->std & V4L2_STD_NTSC) {
743 pms_framerate(dev, 30);
744 pms_secamcross(dev, 0);
745 pms_format(dev, 1);
746 } else if (dev->std & V4L2_STD_PAL) {
747 pms_framerate(dev, 25);
748 pms_secamcross(dev, 0);
749 pms_format(dev, 2);
750 } else if (dev->std & V4L2_STD_SECAM) {
751 pms_framerate(dev, 25);
752 pms_secamcross(dev, 1);
753 pms_format(dev, 2);
754 } else {
755 ret = -EINVAL;
758 switch (v->mode) {
759 case VIDEO_MODE_AUTO:
760 pms_framerate(dev, 25);
761 pms_secamcross(dev, 0);
762 pms_format(dev, 0);
763 break;
765 mutex_unlock(&dev->lock);
766 return 0;
769 static int pms_queryctrl(struct file *file, void *priv,
770 struct v4l2_queryctrl *qc)
772 switch (qc->id) {
773 case V4L2_CID_BRIGHTNESS:
774 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 139);
775 case V4L2_CID_CONTRAST:
776 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 70);
777 case V4L2_CID_SATURATION:
778 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 64);
779 case V4L2_CID_HUE:
780 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 0);
782 return -EINVAL;
785 static int pms_g_ctrl(struct file *file, void *priv,
786 struct v4l2_control *ctrl)
788 struct pms *dev = video_drvdata(file);
789 int ret = 0;
791 switch (ctrl->id) {
792 case V4L2_CID_BRIGHTNESS:
793 ctrl->value = dev->brightness;
794 break;
795 case V4L2_CID_CONTRAST:
796 ctrl->value = dev->contrast;
797 break;
798 case V4L2_CID_SATURATION:
799 ctrl->value = dev->saturation;
800 break;
801 case V4L2_CID_HUE:
802 ctrl->value = dev->hue;
803 break;
804 default:
805 ret = -EINVAL;
806 break;
808 return ret;
811 static int pms_s_ctrl(struct file *file, void *priv,
812 struct v4l2_control *ctrl)
814 struct pms *dev = video_drvdata(file);
815 int ret = 0;
817 mutex_lock(&dev->lock);
818 switch (ctrl->id) {
819 case V4L2_CID_BRIGHTNESS:
820 dev->brightness = ctrl->value;
821 pms_brightness(dev, dev->brightness);
822 break;
823 case V4L2_CID_CONTRAST:
824 dev->contrast = ctrl->value;
825 pms_contrast(dev, dev->contrast);
826 break;
827 case V4L2_CID_SATURATION:
828 dev->saturation = ctrl->value;
829 pms_saturation(dev, dev->saturation);
830 break;
831 case V4L2_CID_HUE:
832 dev->hue = ctrl->value;
833 pms_hue(dev, dev->hue);
834 break;
835 default:
836 ret = -EINVAL;
837 break;
839 mutex_unlock(&dev->lock);
840 return ret;
843 static int pms_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
845 struct pms *dev = video_drvdata(file);
846 struct v4l2_pix_format *pix = &fmt->fmt.pix;
848 pix->width = dev->width;
849 pix->height = dev->height;
850 pix->pixelformat = dev->width == 15 ?
851 V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB565;
852 pix->field = V4L2_FIELD_NONE;
853 pix->bytesperline = 2 * dev->width;
854 pix->sizeimage = 2 * dev->width * dev->height;
855 /* Just a guess */
856 pix->colorspace = V4L2_COLORSPACE_SRGB;
857 return 0;
860 static int pms_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
862 struct v4l2_pix_format *pix = &fmt->fmt.pix;
864 if (pix->height < 16 || pix->height > 480)
865 return -EINVAL;
866 if (pix->width < 16 || pix->width > 640)
867 return -EINVAL;
868 if (pix->pixelformat != V4L2_PIX_FMT_RGB555 &&
869 pix->pixelformat != V4L2_PIX_FMT_RGB565)
870 return -EINVAL;
871 pix->field = V4L2_FIELD_NONE;
872 pix->bytesperline = 2 * pix->width;
873 pix->sizeimage = 2 * pix->width * pix->height;
874 /* Just a guess */
875 pix->colorspace = V4L2_COLORSPACE_SRGB;
876 return 0;
879 static int pms_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
881 struct pms *dev = video_drvdata(file);
882 struct v4l2_pix_format *pix = &fmt->fmt.pix;
883 int ret = pms_try_fmt_vid_cap(file, fh, fmt);
885 if (ret)
886 return ret;
887 mutex_lock(&dev->lock);
888 dev->width = pix->width;
889 dev->height = pix->height;
890 dev->depth = (pix->pixelformat == V4L2_PIX_FMT_RGB555) ? 15 : 16;
891 pms_resolution(dev, dev->width, dev->height);
892 /* Ok we figured out what to use from our wide choice */
893 mutex_unlock(&dev->lock);
894 return 0;
897 static int pms_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
899 static struct v4l2_fmtdesc formats[] = {
900 { 0, 0, 0,
901 "RGB 5:5:5", V4L2_PIX_FMT_RGB555,
902 { 0, 0, 0, 0 }
904 { 0, 0, 0,
905 "RGB 5:6:5", V4L2_PIX_FMT_RGB565,
906 { 0, 0, 0, 0 }
909 enum v4l2_buf_type type = fmt->type;
911 if (fmt->index > 1)
912 return -EINVAL;
914 *fmt = formats[fmt->index];
915 fmt->type = type;
916 return 0;
919 static ssize_t pms_read(struct file *file, char __user *buf,
920 size_t count, loff_t *ppos)
922 struct pms *dev = video_drvdata(file);
923 int len;
925 mutex_lock(&dev->lock);
926 len = pms_capture(dev, buf, (dev->depth == 15), count);
927 mutex_unlock(&dev->lock);
928 return len;
931 static const struct v4l2_file_operations pms_fops = {
932 .owner = THIS_MODULE,
933 .unlocked_ioctl = video_ioctl2,
934 .read = pms_read,
937 static const struct v4l2_ioctl_ops pms_ioctl_ops = {
938 .vidioc_querycap = pms_querycap,
939 .vidioc_g_input = pms_g_input,
940 .vidioc_s_input = pms_s_input,
941 .vidioc_enum_input = pms_enum_input,
942 .vidioc_g_std = pms_g_std,
943 .vidioc_s_std = pms_s_std,
944 .vidioc_queryctrl = pms_queryctrl,
945 .vidioc_g_ctrl = pms_g_ctrl,
946 .vidioc_s_ctrl = pms_s_ctrl,
947 .vidioc_enum_fmt_vid_cap = pms_enum_fmt_vid_cap,
948 .vidioc_g_fmt_vid_cap = pms_g_fmt_vid_cap,
949 .vidioc_s_fmt_vid_cap = pms_s_fmt_vid_cap,
950 .vidioc_try_fmt_vid_cap = pms_try_fmt_vid_cap,
954 * Probe for and initialise the Mediavision PMS
957 static int init_mediavision(struct pms *dev)
959 int id;
960 int idec, decst;
961 int i;
962 static const unsigned char i2c_defs[] = {
963 0x4c, 0x30, 0x00, 0xe8,
964 0xb6, 0xe2, 0x00, 0x00,
965 0xff, 0xff, 0x00, 0x00,
966 0x00, 0x00, 0x78, 0x98,
967 0x00, 0x00, 0x00, 0x00,
968 0x34, 0x0a, 0xf4, 0xce,
969 0xe4
972 dev->mem = ioremap(mem_base, 0x800);
973 if (!dev->mem)
974 return -ENOMEM;
976 if (!request_region(0x9a01, 1, "Mediavision PMS config")) {
977 printk(KERN_WARNING "mediavision: unable to detect: 0x9a01 in use.\n");
978 iounmap(dev->mem);
979 return -EBUSY;
981 if (!request_region(dev->io, 3, "Mediavision PMS")) {
982 printk(KERN_WARNING "mediavision: I/O port %d in use.\n", dev->io);
983 release_region(0x9a01, 1);
984 iounmap(dev->mem);
985 return -EBUSY;
987 outb(0xb8, 0x9a01); /* Unlock */
988 outb(dev->io >> 4, 0x9a01); /* Set IO port */
991 id = mvv_read(dev, 3);
992 decst = pms_i2c_stat(dev, 0x43);
994 if (decst != -1)
995 idec = 2;
996 else if (pms_i2c_stat(dev, 0xb9) != -1)
997 idec = 3;
998 else if (pms_i2c_stat(dev, 0x8b) != -1)
999 idec = 1;
1000 else
1001 idec = 0;
1003 printk(KERN_INFO "PMS type is %d\n", idec);
1004 if (idec == 0) {
1005 release_region(dev->io, 3);
1006 release_region(0x9a01, 1);
1007 iounmap(dev->mem);
1008 return -ENODEV;
1012 * Ok we have a PMS of some sort
1015 mvv_write(dev, 0x04, mem_base >> 12); /* Set the memory area */
1017 /* Ok now load the defaults */
1019 for (i = 0; i < 0x19; i++) {
1020 if (i2c_defs[i] == 0xff)
1021 pms_i2c_andor(dev, 0x8a, i, 0x07, 0x00);
1022 else
1023 pms_i2c_write(dev, 0x8a, i, i2c_defs[i]);
1026 pms_i2c_write(dev, 0xb8, 0x00, 0x12);
1027 pms_i2c_write(dev, 0xb8, 0x04, 0x00);
1028 pms_i2c_write(dev, 0xb8, 0x07, 0x00);
1029 pms_i2c_write(dev, 0xb8, 0x08, 0x00);
1030 pms_i2c_write(dev, 0xb8, 0x09, 0xff);
1031 pms_i2c_write(dev, 0xb8, 0x0a, 0x00);
1032 pms_i2c_write(dev, 0xb8, 0x0b, 0x10);
1033 pms_i2c_write(dev, 0xb8, 0x10, 0x03);
1035 mvv_write(dev, 0x01, 0x00);
1036 mvv_write(dev, 0x05, 0xa0);
1037 mvv_write(dev, 0x08, 0x25);
1038 mvv_write(dev, 0x09, 0x00);
1039 mvv_write(dev, 0x0a, 0x20 | MVVMEMORYWIDTH);
1041 mvv_write(dev, 0x10, 0x02);
1042 mvv_write(dev, 0x1e, 0x0c);
1043 mvv_write(dev, 0x1f, 0x03);
1044 mvv_write(dev, 0x26, 0x06);
1046 mvv_write(dev, 0x2b, 0x00);
1047 mvv_write(dev, 0x2c, 0x20);
1048 mvv_write(dev, 0x2d, 0x00);
1049 mvv_write(dev, 0x2f, 0x70);
1050 mvv_write(dev, 0x32, 0x00);
1051 mvv_write(dev, 0x33, MVVMEMORYWIDTH);
1052 mvv_write(dev, 0x34, 0x00);
1053 mvv_write(dev, 0x35, 0x00);
1054 mvv_write(dev, 0x3a, 0x80);
1055 mvv_write(dev, 0x3b, 0x10);
1056 mvv_write(dev, 0x20, 0x00);
1057 mvv_write(dev, 0x21, 0x00);
1058 mvv_write(dev, 0x30, 0x22);
1059 return 0;
1063 * Initialization and module stuff
1066 #ifndef MODULE
1067 static int enable;
1068 module_param(enable, int, 0);
1069 #endif
1071 static int __init pms_init(void)
1073 struct pms *dev = &pms_card;
1074 struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
1075 int res;
1077 strlcpy(v4l2_dev->name, "pms", sizeof(v4l2_dev->name));
1079 v4l2_info(v4l2_dev, "Mediavision Pro Movie Studio driver 0.03\n");
1081 #ifndef MODULE
1082 if (!enable) {
1083 v4l2_err(v4l2_dev,
1084 "PMS: not enabled, use pms.enable=1 to probe\n");
1085 return -ENODEV;
1087 #endif
1089 dev->decoder = PHILIPS2;
1090 dev->io = io_port;
1091 dev->data = io_port + 1;
1093 if (init_mediavision(dev)) {
1094 v4l2_err(v4l2_dev, "Board not found.\n");
1095 return -ENODEV;
1098 res = v4l2_device_register(NULL, v4l2_dev);
1099 if (res < 0) {
1100 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
1101 return res;
1104 strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
1105 dev->vdev.v4l2_dev = v4l2_dev;
1106 dev->vdev.fops = &pms_fops;
1107 dev->vdev.ioctl_ops = &pms_ioctl_ops;
1108 dev->vdev.release = video_device_release_empty;
1109 video_set_drvdata(&dev->vdev, dev);
1110 mutex_init(&dev->lock);
1111 dev->std = V4L2_STD_NTSC_M;
1112 dev->height = 240;
1113 dev->width = 320;
1114 dev->depth = 15;
1115 dev->brightness = 139;
1116 dev->contrast = 70;
1117 dev->hue = 0;
1118 dev->saturation = 64;
1119 pms_swsense(dev, 75);
1120 pms_resolution(dev, 320, 240);
1121 pms_videosource(dev, 0);
1122 pms_vcrinput(dev, 0);
1123 if (video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
1124 v4l2_device_unregister(&dev->v4l2_dev);
1125 release_region(dev->io, 3);
1126 release_region(0x9a01, 1);
1127 iounmap(dev->mem);
1128 return -EINVAL;
1130 return 0;
1133 static void __exit pms_exit(void)
1135 struct pms *dev = &pms_card;
1137 video_unregister_device(&dev->vdev);
1138 release_region(dev->io, 3);
1139 release_region(0x9a01, 1);
1140 iounmap(dev->mem);
1143 module_init(pms_init);
1144 module_exit(pms_exit);