]> git.ipfire.org Git - people/arne_f/kernel.git/blame - drivers/media/video/pms.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[people/arne_f/kernel.git] / drivers / media / video / pms.c
CommitLineData
1da177e4
LT
1/*
2 * Media Vision Pro Movie Studio
3 * or
4 * "all you need is an I2C bus some RAM and a prayer"
5 *
6 * This draws heavily on code
7 *
8 * (c) Wolfgang Koehler, wolf@first.gmd.de, Dec. 1994
9 * Kiefernring 15
10 * 14478 Potsdam, Germany
11 *
12 * Most of this code is directly derived from his userspace driver.
d9b01449
AC
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...
d56410e0 15 *
1da177e4 16 * Changes:
feba2f81
HV
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
1da177e4
LT
21 */
22
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>
1da177e4
LT
28#include <linux/mm.h>
29#include <linux/ioport.h>
30#include <linux/init.h>
feba2f81
HV
31#include <linux/version.h>
32#include <linux/mutex.h>
262ab9ac 33#include <linux/uaccess.h>
1da177e4 34#include <asm/io.h>
feba2f81
HV
35
36#include <linux/videodev2.h>
5e87efa3 37#include <media/v4l2-common.h>
35ea11ff 38#include <media/v4l2-ioctl.h>
1ce7981b 39#include <media/v4l2-device.h>
1da177e4 40
1ce7981b
HV
41MODULE_LICENSE("GPL");
42
1da177e4
LT
43
44#define MOTOROLA 1
feba2f81 45#define PHILIPS2 2 /* SAA7191 */
1da177e4
LT
46#define PHILIPS1 3
47#define MVVMEMORYWIDTH 0x40 /* 512 bytes */
48
1ce7981b 49struct i2c_info {
1da177e4
LT
50 u8 slave;
51 u8 sub;
52 u8 data;
53 u8 hits;
54};
55
1ce7981b
HV
56struct pms {
57 struct v4l2_device v4l2_dev;
58 struct video_device vdev;
1ce7981b
HV
59 int height;
60 int width;
feba2f81
HV
61 int depth;
62 int input;
63 s32 brightness, saturation, hue, contrast;
1ce7981b
HV
64 unsigned long in_use;
65 struct mutex lock;
66 int i2c_count;
67 struct i2c_info i2cinfo[64];
68
69 int decoder;
70 int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
feba2f81 71 v4l2_std_id std;
1ce7981b
HV
72 int io;
73 int data;
74 void __iomem *mem;
75};
1da177e4 76
1ce7981b 77static struct pms pms_card;
1da177e4
LT
78
79/*
80 * I/O ports and Shared Memory
81 */
d56410e0 82
1ce7981b
HV
83static int io_port = 0x250;
84module_param(io_port, int, 0);
85
86static int mem_base = 0xc8000;
87module_param(mem_base, int, 0);
1da177e4 88
1ce7981b
HV
89static int video_nr = -1;
90module_param(video_nr, int, 0);
d56410e0 91
1da177e4 92
1ce7981b 93static inline void mvv_write(struct pms *dev, u8 index, u8 value)
1da177e4 94{
1ce7981b 95 outw(index | (value << 8), dev->io);
1da177e4
LT
96}
97
1ce7981b 98static inline u8 mvv_read(struct pms *dev, u8 index)
1da177e4 99{
1ce7981b
HV
100 outb(index, dev->io);
101 return inb(dev->data);
1da177e4
LT
102}
103
1ce7981b 104static int pms_i2c_stat(struct pms *dev, u8 slave)
1da177e4 105{
1ce7981b 106 int counter = 0;
1da177e4 107 int i;
d56410e0 108
1ce7981b 109 outb(0x28, dev->io);
d56410e0 110
1ce7981b
HV
111 while ((inb(dev->data) & 0x01) == 0)
112 if (counter++ == 256)
1da177e4
LT
113 break;
114
1ce7981b
HV
115 while ((inb(dev->data) & 0x01) != 0)
116 if (counter++ == 256)
1da177e4 117 break;
d56410e0 118
1ce7981b 119 outb(slave, dev->io);
d56410e0 120
1ce7981b
HV
121 counter = 0;
122 while ((inb(dev->data) & 0x01) == 0)
123 if (counter++ == 256)
1da177e4
LT
124 break;
125
1ce7981b
HV
126 while ((inb(dev->data) & 0x01) != 0)
127 if (counter++ == 256)
1da177e4 128 break;
d56410e0 129
1ce7981b
HV
130 for (i = 0; i < 12; i++) {
131 char st = inb(dev->data);
132
133 if ((st & 2) != 0)
1da177e4 134 return -1;
1ce7981b 135 if ((st & 1) == 0)
1da177e4
LT
136 break;
137 }
1ce7981b
HV
138 outb(0x29, dev->io);
139 return inb(dev->data);
1da177e4
LT
140}
141
1ce7981b 142static int pms_i2c_write(struct pms *dev, u16 slave, u16 sub, u16 data)
1da177e4 143{
1ce7981b 144 int skip = 0;
1da177e4
LT
145 int count;
146 int i;
d56410e0 147
1ce7981b
HV
148 for (i = 0; i < dev->i2c_count; i++) {
149 if ((dev->i2cinfo[i].slave == slave) &&
150 (dev->i2cinfo[i].sub == sub)) {
151 if (dev->i2cinfo[i].data == data)
152 skip = 1;
153 dev->i2cinfo[i].data = data;
154 i = dev->i2c_count + 1;
1da177e4
LT
155 }
156 }
d56410e0 157
1ce7981b
HV
158 if (i == dev->i2c_count && dev->i2c_count < 64) {
159 dev->i2cinfo[dev->i2c_count].slave = slave;
160 dev->i2cinfo[dev->i2c_count].sub = sub;
161 dev->i2cinfo[dev->i2c_count].data = data;
162 dev->i2c_count++;
1da177e4 163 }
d56410e0 164
1ce7981b 165 if (skip)
1da177e4 166 return 0;
d56410e0 167
1ce7981b
HV
168 mvv_write(dev, 0x29, sub);
169 mvv_write(dev, 0x2A, data);
170 mvv_write(dev, 0x28, slave);
d56410e0 171
1ce7981b 172 outb(0x28, dev->io);
d56410e0 173
1ce7981b
HV
174 count = 0;
175 while ((inb(dev->data) & 1) == 0)
176 if (count > 255)
1da177e4 177 break;
1ce7981b
HV
178 while ((inb(dev->data) & 1) != 0)
179 if (count > 255)
1da177e4 180 break;
d56410e0 181
1ce7981b 182 count = inb(dev->data);
d56410e0 183
1ce7981b 184 if (count & 2)
1da177e4
LT
185 return -1;
186 return count;
187}
188
1ce7981b 189static int pms_i2c_read(struct pms *dev, int slave, int sub)
1da177e4 190{
1ce7981b
HV
191 int i;
192
193 for (i = 0; i < dev->i2c_count; i++) {
194 if (dev->i2cinfo[i].slave == slave && dev->i2cinfo[i].sub == sub)
195 return dev->i2cinfo[i].data;
1da177e4
LT
196 }
197 return 0;
198}
199
200
1ce7981b 201static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or)
1da177e4 202{
d56410e0
MCC
203 u8 tmp;
204
1ce7981b
HV
205 tmp = pms_i2c_read(dev, slave, sub);
206 tmp = (tmp & and) | or;
207 pms_i2c_write(dev, slave, sub, tmp);
1da177e4
LT
208}
209
210/*
211 * Control functions
212 */
d56410e0 213
1da177e4 214
1ce7981b 215static void pms_videosource(struct pms *dev, short source)
1da177e4 216{
feba2f81
HV
217 switch (dev->decoder) {
218 case MOTOROLA:
219 break;
220 case PHILIPS2:
221 pms_i2c_andor(dev, 0x8a, 0x06, 0x7f, source ? 0x80 : 0);
222 break;
223 case PHILIPS1:
224 break;
225 }
226 mvv_write(dev, 0x2E, 0x31);
227 /* Was: mvv_write(dev, 0x2E, source ? 0x31 : 0x30);
228 But could not make this work correctly. Only Composite input
229 worked for me. */
1da177e4
LT
230}
231
1ce7981b 232static void pms_hue(struct pms *dev, short hue)
1da177e4 233{
1ce7981b
HV
234 switch (dev->decoder) {
235 case MOTOROLA:
236 pms_i2c_write(dev, 0x8a, 0x00, hue);
237 break;
238 case PHILIPS2:
239 pms_i2c_write(dev, 0x8a, 0x07, hue);
240 break;
241 case PHILIPS1:
242 pms_i2c_write(dev, 0x42, 0x07, hue);
243 break;
1da177e4
LT
244 }
245}
246
feba2f81 247static void pms_saturation(struct pms *dev, short sat)
1da177e4 248{
1ce7981b
HV
249 switch (dev->decoder) {
250 case MOTOROLA:
feba2f81 251 pms_i2c_write(dev, 0x8a, 0x00, sat);
1ce7981b
HV
252 break;
253 case PHILIPS1:
feba2f81 254 pms_i2c_write(dev, 0x42, 0x12, sat);
1ce7981b 255 break;
1da177e4
LT
256 }
257}
d56410e0
MCC
258
259
1ce7981b 260static void pms_contrast(struct pms *dev, short contrast)
1da177e4 261{
1ce7981b
HV
262 switch (dev->decoder) {
263 case MOTOROLA:
264 pms_i2c_write(dev, 0x8a, 0x00, contrast);
265 break;
266 case PHILIPS1:
267 pms_i2c_write(dev, 0x42, 0x13, contrast);
268 break;
1da177e4
LT
269 }
270}
271
1ce7981b 272static void pms_brightness(struct pms *dev, short brightness)
1da177e4 273{
1ce7981b
HV
274 switch (dev->decoder) {
275 case MOTOROLA:
276 pms_i2c_write(dev, 0x8a, 0x00, brightness);
277 pms_i2c_write(dev, 0x8a, 0x00, brightness);
278 pms_i2c_write(dev, 0x8a, 0x00, brightness);
279 break;
280 case PHILIPS1:
281 pms_i2c_write(dev, 0x42, 0x19, brightness);
282 break;
1da177e4
LT
283 }
284}
285
286
1ce7981b 287static void pms_format(struct pms *dev, short format)
1da177e4
LT
288{
289 int target;
d56410e0 290
1ce7981b
HV
291 dev->standard = format;
292
293 if (dev->decoder == PHILIPS1)
294 target = 0x42;
295 else if (dev->decoder == PHILIPS2)
296 target = 0x8a;
1da177e4
LT
297 else
298 return;
d56410e0 299
1ce7981b
HV
300 switch (format) {
301 case 0: /* Auto */
302 pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
303 pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x80);
304 break;
305 case 1: /* NTSC */
306 pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
307 pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x40);
308 break;
309 case 2: /* PAL */
310 pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
311 pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
312 break;
313 case 3: /* SECAM */
314 pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x01);
315 pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
316 break;
1da177e4
LT
317 }
318}
319
320#ifdef FOR_FUTURE_EXPANSION
321
322/*
323 * These features of the PMS card are not currently exposes. They
d56410e0 324 * could become a private v4l ioctl for PMSCONFIG or somesuch if
1da177e4
LT
325 * people need it. We also don't yet use the PMS interrupt.
326 */
327
1ce7981b 328static void pms_hstart(struct pms *dev, short start)
1da177e4 329{
1ce7981b
HV
330 switch (dev->decoder) {
331 case PHILIPS1:
332 pms_i2c_write(dev, 0x8a, 0x05, start);
333 pms_i2c_write(dev, 0x8a, 0x18, start);
334 break;
335 case PHILIPS2:
336 pms_i2c_write(dev, 0x42, 0x05, start);
337 pms_i2c_write(dev, 0x42, 0x18, start);
338 break;
1da177e4
LT
339 }
340}
341
342/*
343 * Bandpass filters
344 */
d56410e0 345
1ce7981b 346static void pms_bandpass(struct pms *dev, short pass)
1da177e4 347{
1ce7981b
HV
348 if (dev->decoder == PHILIPS2)
349 pms_i2c_andor(dev, 0x8a, 0x06, 0xcf, (pass & 0x03) << 4);
350 else if (dev->decoder == PHILIPS1)
351 pms_i2c_andor(dev, 0x42, 0x06, 0xcf, (pass & 0x03) << 4);
1da177e4
LT
352}
353
1ce7981b 354static void pms_antisnow(struct pms *dev, short snow)
1da177e4 355{
1ce7981b
HV
356 if (dev->decoder == PHILIPS2)
357 pms_i2c_andor(dev, 0x8a, 0x06, 0xf3, (snow & 0x03) << 2);
358 else if (dev->decoder == PHILIPS1)
359 pms_i2c_andor(dev, 0x42, 0x06, 0xf3, (snow & 0x03) << 2);
1da177e4
LT
360}
361
1ce7981b 362static void pms_sharpness(struct pms *dev, short sharp)
1da177e4 363{
1ce7981b
HV
364 if (dev->decoder == PHILIPS2)
365 pms_i2c_andor(dev, 0x8a, 0x06, 0xfc, sharp & 0x03);
366 else if (dev->decoder == PHILIPS1)
367 pms_i2c_andor(dev, 0x42, 0x06, 0xfc, sharp & 0x03);
1da177e4
LT
368}
369
1ce7981b 370static void pms_chromaagc(struct pms *dev, short agc)
1da177e4 371{
1ce7981b
HV
372 if (dev->decoder == PHILIPS2)
373 pms_i2c_andor(dev, 0x8a, 0x0c, 0x9f, (agc & 0x03) << 5);
374 else if (dev->decoder == PHILIPS1)
375 pms_i2c_andor(dev, 0x42, 0x0c, 0x9f, (agc & 0x03) << 5);
1da177e4
LT
376}
377
1ce7981b 378static void pms_vertnoise(struct pms *dev, short noise)
1da177e4 379{
1ce7981b
HV
380 if (dev->decoder == PHILIPS2)
381 pms_i2c_andor(dev, 0x8a, 0x10, 0xfc, noise & 3);
382 else if (dev->decoder == PHILIPS1)
383 pms_i2c_andor(dev, 0x42, 0x10, 0xfc, noise & 3);
1da177e4
LT
384}
385
1ce7981b 386static void pms_forcecolour(struct pms *dev, short colour)
1da177e4 387{
1ce7981b
HV
388 if (dev->decoder == PHILIPS2)
389 pms_i2c_andor(dev, 0x8a, 0x0c, 0x7f, (colour & 1) << 7);
390 else if (dev->decoder == PHILIPS1)
391 pms_i2c_andor(dev, 0x42, 0x0c, 0x7, (colour & 1) << 7);
1da177e4
LT
392}
393
1ce7981b 394static void pms_antigamma(struct pms *dev, short gamma)
1da177e4 395{
1ce7981b
HV
396 if (dev->decoder == PHILIPS2)
397 pms_i2c_andor(dev, 0xb8, 0x00, 0x7f, (gamma & 1) << 7);
398 else if (dev->decoder == PHILIPS1)
399 pms_i2c_andor(dev, 0x42, 0x20, 0x7, (gamma & 1) << 7);
1da177e4
LT
400}
401
1ce7981b 402static void pms_prefilter(struct pms *dev, short filter)
1da177e4 403{
1ce7981b
HV
404 if (dev->decoder == PHILIPS2)
405 pms_i2c_andor(dev, 0x8a, 0x06, 0xbf, (filter & 1) << 6);
406 else if (dev->decoder == PHILIPS1)
407 pms_i2c_andor(dev, 0x42, 0x06, 0xbf, (filter & 1) << 6);
1da177e4
LT
408}
409
1ce7981b 410static void pms_hfilter(struct pms *dev, short filter)
1da177e4 411{
1ce7981b
HV
412 if (dev->decoder == PHILIPS2)
413 pms_i2c_andor(dev, 0xb8, 0x04, 0x1f, (filter & 7) << 5);
414 else if (dev->decoder == PHILIPS1)
415 pms_i2c_andor(dev, 0x42, 0x24, 0x1f, (filter & 7) << 5);
1da177e4
LT
416}
417
1ce7981b 418static void pms_vfilter(struct pms *dev, short filter)
1da177e4 419{
1ce7981b
HV
420 if (dev->decoder == PHILIPS2)
421 pms_i2c_andor(dev, 0xb8, 0x08, 0x9f, (filter & 3) << 5);
422 else if (dev->decoder == PHILIPS1)
423 pms_i2c_andor(dev, 0x42, 0x28, 0x9f, (filter & 3) << 5);
1da177e4
LT
424}
425
1ce7981b 426static void pms_killcolour(struct pms *dev, short colour)
1da177e4 427{
1ce7981b
HV
428 if (dev->decoder == PHILIPS2) {
429 pms_i2c_andor(dev, 0x8a, 0x08, 0x07, (colour & 0x1f) << 3);
430 pms_i2c_andor(dev, 0x8a, 0x09, 0x07, (colour & 0x1f) << 3);
431 } else if (dev->decoder == PHILIPS1) {
432 pms_i2c_andor(dev, 0x42, 0x08, 0x07, (colour & 0x1f) << 3);
433 pms_i2c_andor(dev, 0x42, 0x09, 0x07, (colour & 0x1f) << 3);
1da177e4
LT
434 }
435}
436
1ce7981b 437static void pms_chromagain(struct pms *dev, short chroma)
1da177e4 438{
1ce7981b
HV
439 if (dev->decoder == PHILIPS2)
440 pms_i2c_write(dev, 0x8a, 0x11, chroma);
441 else if (dev->decoder == PHILIPS1)
442 pms_i2c_write(dev, 0x42, 0x11, chroma);
1da177e4
LT
443}
444
445
1ce7981b 446static void pms_spacialcompl(struct pms *dev, short data)
1da177e4 447{
1ce7981b 448 mvv_write(dev, 0x3b, data);
1da177e4
LT
449}
450
1ce7981b 451static void pms_spacialcomph(struct pms *dev, short data)
1da177e4 452{
1ce7981b 453 mvv_write(dev, 0x3a, data);
1da177e4
LT
454}
455
1ce7981b 456static void pms_vstart(struct pms *dev, short start)
1da177e4 457{
1ce7981b
HV
458 mvv_write(dev, 0x16, start);
459 mvv_write(dev, 0x17, (start >> 8) & 0x01);
1da177e4
LT
460}
461
462#endif
463
1ce7981b 464static void pms_secamcross(struct pms *dev, short cross)
1da177e4 465{
1ce7981b
HV
466 if (dev->decoder == PHILIPS2)
467 pms_i2c_andor(dev, 0x8a, 0x0f, 0xdf, (cross & 1) << 5);
468 else if (dev->decoder == PHILIPS1)
469 pms_i2c_andor(dev, 0x42, 0x0f, 0xdf, (cross & 1) << 5);
1da177e4
LT
470}
471
472
1ce7981b 473static void pms_swsense(struct pms *dev, short sense)
1da177e4 474{
1ce7981b
HV
475 if (dev->decoder == PHILIPS2) {
476 pms_i2c_write(dev, 0x8a, 0x0a, sense);
477 pms_i2c_write(dev, 0x8a, 0x0b, sense);
478 } else if (dev->decoder == PHILIPS1) {
479 pms_i2c_write(dev, 0x42, 0x0a, sense);
480 pms_i2c_write(dev, 0x42, 0x0b, sense);
1da177e4
LT
481 }
482}
483
484
1ce7981b 485static void pms_framerate(struct pms *dev, short frr)
1da177e4 486{
feba2f81 487 int fps = (dev->std & V4L2_STD_525_60) ? 30 : 25;
1ce7981b
HV
488
489 if (frr == 0)
1da177e4 490 return;
1ce7981b
HV
491 fps = fps/frr;
492 mvv_write(dev, 0x14, 0x80 | fps);
493 mvv_write(dev, 0x15, 1);
1da177e4
LT
494}
495
1ce7981b 496static void pms_vert(struct pms *dev, u8 deciden, u8 decinum)
1da177e4 497{
1ce7981b
HV
498 mvv_write(dev, 0x1c, deciden); /* Denominator */
499 mvv_write(dev, 0x1d, decinum); /* Numerator */
1da177e4
LT
500}
501
502/*
503 * Turn 16bit ratios into best small ratio the chipset can grok
504 */
d56410e0 505
1ce7981b 506static void pms_vertdeci(struct pms *dev, unsigned short decinum, unsigned short deciden)
1da177e4 507{
1ce7981b
HV
508 /* Knock it down by / 5 once */
509 if (decinum % 5 == 0) {
510 deciden /= 5;
511 decinum /= 5;
1da177e4
LT
512 }
513 /*
514 * 3's
515 */
1ce7981b
HV
516 while (decinum % 3 == 0 && deciden % 3 == 0) {
517 deciden /= 3;
518 decinum /= 3;
1da177e4
LT
519 }
520 /*
521 * 2's
522 */
1ce7981b
HV
523 while (decinum % 2 == 0 && deciden % 2 == 0) {
524 decinum /= 2;
525 deciden /= 2;
1da177e4
LT
526 }
527 /*
528 * Fudgyify
529 */
1ce7981b
HV
530 while (deciden > 32) {
531 deciden /= 2;
532 decinum = (decinum + 1) / 2;
1da177e4 533 }
1ce7981b 534 if (deciden == 32)
1da177e4 535 deciden--;
1ce7981b 536 pms_vert(dev, deciden, decinum);
1da177e4
LT
537}
538
1ce7981b 539static void pms_horzdeci(struct pms *dev, short decinum, short deciden)
1da177e4 540{
1ce7981b
HV
541 if (decinum <= 512) {
542 if (decinum % 5 == 0) {
543 decinum /= 5;
544 deciden /= 5;
1da177e4 545 }
1ce7981b
HV
546 } else {
547 decinum = 512;
548 deciden = 640; /* 768 would be ideal */
1da177e4 549 }
d56410e0 550
1ce7981b
HV
551 while (((decinum | deciden) & 1) == 0) {
552 decinum >>= 1;
553 deciden >>= 1;
1da177e4 554 }
1ce7981b
HV
555 while (deciden > 32) {
556 deciden >>= 1;
557 decinum = (decinum + 1) >> 1;
1da177e4 558 }
1ce7981b 559 if (deciden == 32)
1da177e4 560 deciden--;
d56410e0 561
1ce7981b
HV
562 mvv_write(dev, 0x24, 0x80 | deciden);
563 mvv_write(dev, 0x25, decinum);
1da177e4
LT
564}
565
1ce7981b 566static void pms_resolution(struct pms *dev, short width, short height)
1da177e4
LT
567{
568 int fg_height;
d56410e0 569
1ce7981b
HV
570 fg_height = height;
571 if (fg_height > 280)
572 fg_height = 280;
d56410e0 573
1ce7981b
HV
574 mvv_write(dev, 0x18, fg_height);
575 mvv_write(dev, 0x19, fg_height >> 8);
d56410e0 576
feba2f81 577 if (dev->std & V4L2_STD_525_60) {
1ce7981b
HV
578 mvv_write(dev, 0x1a, 0xfc);
579 mvv_write(dev, 0x1b, 0x00);
580 if (height > fg_height)
581 pms_vertdeci(dev, 240, 240);
1da177e4 582 else
1ce7981b
HV
583 pms_vertdeci(dev, fg_height, 240);
584 } else {
585 mvv_write(dev, 0x1a, 0x1a);
586 mvv_write(dev, 0x1b, 0x01);
587 if (fg_height > 256)
588 pms_vertdeci(dev, 270, 270);
1da177e4 589 else
1ce7981b 590 pms_vertdeci(dev, fg_height, 270);
1da177e4 591 }
1ce7981b
HV
592 mvv_write(dev, 0x12, 0);
593 mvv_write(dev, 0x13, MVVMEMORYWIDTH);
594 mvv_write(dev, 0x42, 0x00);
595 mvv_write(dev, 0x43, 0x00);
596 mvv_write(dev, 0x44, MVVMEMORYWIDTH);
d56410e0 597
1ce7981b
HV
598 mvv_write(dev, 0x22, width + 8);
599 mvv_write(dev, 0x23, (width + 8) >> 8);
1da177e4 600
feba2f81 601 if (dev->std & V4L2_STD_525_60)
1ce7981b 602 pms_horzdeci(dev, width, 640);
1da177e4 603 else
1ce7981b 604 pms_horzdeci(dev, width + 8, 768);
1da177e4 605
1ce7981b
HV
606 mvv_write(dev, 0x30, mvv_read(dev, 0x30) & 0xfe);
607 mvv_write(dev, 0x08, mvv_read(dev, 0x08) | 0x01);
608 mvv_write(dev, 0x01, mvv_read(dev, 0x01) & 0xfd);
609 mvv_write(dev, 0x32, 0x00);
610 mvv_write(dev, 0x33, MVVMEMORYWIDTH);
1da177e4
LT
611}
612
613
614/*
615 * Set Input
616 */
d56410e0 617
1ce7981b 618static void pms_vcrinput(struct pms *dev, short input)
1da177e4 619{
1ce7981b
HV
620 if (dev->decoder == PHILIPS2)
621 pms_i2c_andor(dev, 0x8a, 0x0d, 0x7f, (input & 1) << 7);
622 else if (dev->decoder == PHILIPS1)
623 pms_i2c_andor(dev, 0x42, 0x0d, 0x7f, (input & 1) << 7);
1da177e4
LT
624}
625
626
1ce7981b 627static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count)
1da177e4
LT
628{
629 int y;
1ce7981b
HV
630 int dw = 2 * dev->width;
631 char tmp[dw + 32]; /* using a temp buffer is faster than direct */
1da177e4 632 int cnt = 0;
1ce7981b 633 int len = 0;
1da177e4
LT
634 unsigned char r8 = 0x5; /* value for reg8 */
635
636 if (rgb555)
637 r8 |= 0x20; /* else use untranslated rgb = 565 */
1ce7981b 638 mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */
1da177e4
LT
639
640/* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
d56410e0 641
1ce7981b
HV
642 for (y = 0; y < dev->height; y++) {
643 writeb(0, dev->mem); /* synchronisiert neue Zeile */
d56410e0 644
1da177e4
LT
645 /*
646 * This is in truth a fifo, be very careful as if you
647 * forgot this odd things will occur 8)
648 */
d56410e0 649
1ce7981b 650 memcpy_fromio(tmp, dev->mem, dw + 32); /* discard 16 word */
1da177e4 651 cnt -= dev->height;
1ce7981b 652 while (cnt <= 0) {
1da177e4
LT
653 /*
654 * Don't copy too far
655 */
1ce7981b
HV
656 int dt = dw;
657 if (dt + len > count)
658 dt = count - len;
1da177e4 659 cnt += dev->height;
1ce7981b 660 if (copy_to_user(buf, tmp + 32, dt))
1da177e4 661 return len ? len : -EFAULT;
d56410e0 662 buf += dt;
1da177e4
LT
663 len += dt;
664 }
665 }
666 return len;
667}
668
669
670/*
671 * Video4linux interfacing
672 */
673
feba2f81
HV
674static int pms_querycap(struct file *file, void *priv,
675 struct v4l2_capability *vcap)
1da177e4 676{
1ce7981b
HV
677 struct pms *dev = video_drvdata(file);
678
feba2f81
HV
679 strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver));
680 strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card));
681 strlcpy(vcap->bus_info, "ISA", sizeof(vcap->bus_info));
682 vcap->version = KERNEL_VERSION(0, 0, 3);
683 vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
684 return 0;
685}
1ce7981b 686
feba2f81
HV
687static int pms_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
688{
689 static const char *inputs[4] = {
690 "Composite",
691 "S-Video",
692 "Composite (VCR)",
693 "S-Video (VCR)"
694 };
1ce7981b 695
feba2f81
HV
696 if (vin->index > 3)
697 return -EINVAL;
698 strlcpy(vin->name, inputs[vin->index], sizeof(vin->name));
699 vin->type = V4L2_INPUT_TYPE_CAMERA;
700 vin->audioset = 0;
701 vin->tuner = 0;
702 vin->std = V4L2_STD_ALL;
703 vin->status = 0;
704 return 0;
705}
1ce7981b 706
feba2f81
HV
707static int pms_g_input(struct file *file, void *fh, unsigned int *inp)
708{
709 struct pms *dev = video_drvdata(file);
1ce7981b 710
feba2f81
HV
711 *inp = dev->input;
712 return 0;
713}
714
715static int pms_s_input(struct file *file, void *fh, unsigned int inp)
716{
717 struct pms *dev = video_drvdata(file);
718
719 if (inp > 3)
720 return -EINVAL;
721
722 mutex_lock(&dev->lock);
723 dev->input = inp;
724 pms_videosource(dev, inp & 1);
725 pms_vcrinput(dev, inp >> 1);
726 mutex_unlock(&dev->lock);
727 return 0;
728}
729
730static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std)
731{
732 struct pms *dev = video_drvdata(file);
733
734 *std = dev->std;
735 return 0;
736}
737
738static int pms_s_std(struct file *file, void *fh, v4l2_std_id *std)
739{
740 struct pms *dev = video_drvdata(file);
741 int ret = 0;
742
743 dev->std = *std;
744 mutex_lock(&dev->lock);
745 if (dev->std & V4L2_STD_NTSC) {
746 pms_framerate(dev, 30);
747 pms_secamcross(dev, 0);
748 pms_format(dev, 1);
749 } else if (dev->std & V4L2_STD_PAL) {
750 pms_framerate(dev, 25);
751 pms_secamcross(dev, 0);
752 pms_format(dev, 2);
753 } else if (dev->std & V4L2_STD_SECAM) {
754 pms_framerate(dev, 25);
755 pms_secamcross(dev, 1);
756 pms_format(dev, 2);
757 } else {
758 ret = -EINVAL;
1ce7981b 759 }
feba2f81
HV
760 /*
761 switch (v->mode) {
762 case VIDEO_MODE_AUTO:
763 pms_framerate(dev, 25);
764 pms_secamcross(dev, 0);
765 pms_format(dev, 0);
766 break;
767 }*/
768 mutex_unlock(&dev->lock);
769 return 0;
770}
771
772static int pms_queryctrl(struct file *file, void *priv,
773 struct v4l2_queryctrl *qc)
774{
775 switch (qc->id) {
776 case V4L2_CID_BRIGHTNESS:
777 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 139);
778 case V4L2_CID_CONTRAST:
779 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 70);
780 case V4L2_CID_SATURATION:
781 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 64);
782 case V4L2_CID_HUE:
783 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 0);
1ce7981b 784 }
feba2f81
HV
785 return -EINVAL;
786}
1ce7981b 787
feba2f81
HV
788static int pms_g_ctrl(struct file *file, void *priv,
789 struct v4l2_control *ctrl)
790{
791 struct pms *dev = video_drvdata(file);
792 int ret = 0;
793
794 switch (ctrl->id) {
795 case V4L2_CID_BRIGHTNESS:
796 ctrl->value = dev->brightness;
797 break;
798 case V4L2_CID_CONTRAST:
799 ctrl->value = dev->contrast;
800 break;
801 case V4L2_CID_SATURATION:
802 ctrl->value = dev->saturation;
803 break;
804 case V4L2_CID_HUE:
805 ctrl->value = dev->hue;
806 break;
807 default:
808 ret = -EINVAL;
809 break;
1ce7981b 810 }
feba2f81
HV
811 return ret;
812}
813
814static int pms_s_ctrl(struct file *file, void *priv,
815 struct v4l2_control *ctrl)
816{
817 struct pms *dev = video_drvdata(file);
818 int ret = 0;
819
820 mutex_lock(&dev->lock);
821 switch (ctrl->id) {
822 case V4L2_CID_BRIGHTNESS:
823 dev->brightness = ctrl->value;
824 pms_brightness(dev, dev->brightness);
825 break;
826 case V4L2_CID_CONTRAST:
827 dev->contrast = ctrl->value;
828 pms_contrast(dev, dev->contrast);
829 break;
830 case V4L2_CID_SATURATION:
831 dev->saturation = ctrl->value;
832 pms_saturation(dev, dev->saturation);
833 break;
834 case V4L2_CID_HUE:
835 dev->hue = ctrl->value;
836 pms_hue(dev, dev->hue);
837 break;
1ce7981b 838 default:
feba2f81
HV
839 ret = -EINVAL;
840 break;
1da177e4 841 }
feba2f81
HV
842 mutex_unlock(&dev->lock);
843 return ret;
844}
845
846static int pms_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
847{
848 struct pms *dev = video_drvdata(file);
849 struct v4l2_pix_format *pix = &fmt->fmt.pix;
850
851 pix->width = dev->width;
852 pix->height = dev->height;
853 pix->pixelformat = dev->width == 15 ?
854 V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB565;
855 pix->field = V4L2_FIELD_NONE;
856 pix->bytesperline = 2 * dev->width;
857 pix->sizeimage = 2 * dev->width * dev->height;
858 /* Just a guess */
859 pix->colorspace = V4L2_COLORSPACE_SRGB;
860 return 0;
861}
862
863static int pms_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
864{
865 struct v4l2_pix_format *pix = &fmt->fmt.pix;
866
867 if (pix->height < 16 || pix->height > 480)
868 return -EINVAL;
869 if (pix->width < 16 || pix->width > 640)
870 return -EINVAL;
871 if (pix->pixelformat != V4L2_PIX_FMT_RGB555 &&
872 pix->pixelformat != V4L2_PIX_FMT_RGB565)
873 return -EINVAL;
874 pix->field = V4L2_FIELD_NONE;
875 pix->bytesperline = 2 * pix->width;
876 pix->sizeimage = 2 * pix->width * pix->height;
877 /* Just a guess */
878 pix->colorspace = V4L2_COLORSPACE_SRGB;
1da177e4
LT
879 return 0;
880}
881
feba2f81 882static int pms_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
1da177e4 883{
feba2f81
HV
884 struct pms *dev = video_drvdata(file);
885 struct v4l2_pix_format *pix = &fmt->fmt.pix;
886 int ret = pms_try_fmt_vid_cap(file, fh, fmt);
887
888 if (ret)
889 return ret;
890 mutex_lock(&dev->lock);
891 dev->width = pix->width;
892 dev->height = pix->height;
893 dev->depth = (pix->pixelformat == V4L2_PIX_FMT_RGB555) ? 15 : 16;
894 pms_resolution(dev, dev->width, dev->height);
895 /* Ok we figured out what to use from our wide choice */
896 mutex_unlock(&dev->lock);
897 return 0;
898}
899
900static int pms_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
901{
902 static struct v4l2_fmtdesc formats[] = {
903 { 0, 0, 0,
904 "RGB 5:5:5", V4L2_PIX_FMT_RGB555,
905 { 0, 0, 0, 0 }
906 },
907 { 0, 0, 0,
908 "RGB 5:6:5", V4L2_PIX_FMT_RGB565,
909 { 0, 0, 0, 0 }
910 },
911 };
912 enum v4l2_buf_type type = fmt->type;
913
914 if (fmt->index > 1)
915 return -EINVAL;
916
917 *fmt = formats[fmt->index];
918 fmt->type = type;
919 return 0;
1da177e4
LT
920}
921
922static ssize_t pms_read(struct file *file, char __user *buf,
923 size_t count, loff_t *ppos)
924{
1ce7981b 925 struct pms *dev = video_drvdata(file);
1da177e4 926 int len;
d56410e0 927
1ce7981b 928 mutex_lock(&dev->lock);
feba2f81 929 len = pms_capture(dev, buf, (dev->depth == 15), count);
1ce7981b 930 mutex_unlock(&dev->lock);
1da177e4
LT
931 return len;
932}
933
bec43661 934static int pms_exclusive_open(struct file *file)
7d43cd53 935{
1ce7981b 936 struct pms *dev = video_drvdata(file);
7d43cd53 937
1ce7981b 938 return test_and_set_bit(0, &dev->in_use) ? -EBUSY : 0;
7d43cd53
HV
939}
940
bec43661 941static int pms_exclusive_release(struct file *file)
7d43cd53 942{
1ce7981b 943 struct pms *dev = video_drvdata(file);
7d43cd53 944
1ce7981b 945 clear_bit(0, &dev->in_use);
7d43cd53
HV
946 return 0;
947}
948
bec43661 949static const struct v4l2_file_operations pms_fops = {
1da177e4 950 .owner = THIS_MODULE,
7d43cd53
HV
951 .open = pms_exclusive_open,
952 .release = pms_exclusive_release,
feba2f81 953 .ioctl = video_ioctl2,
1da177e4 954 .read = pms_read,
1da177e4
LT
955};
956
feba2f81
HV
957static const struct v4l2_ioctl_ops pms_ioctl_ops = {
958 .vidioc_querycap = pms_querycap,
959 .vidioc_g_input = pms_g_input,
960 .vidioc_s_input = pms_s_input,
961 .vidioc_enum_input = pms_enum_input,
962 .vidioc_g_std = pms_g_std,
963 .vidioc_s_std = pms_s_std,
964 .vidioc_queryctrl = pms_queryctrl,
965 .vidioc_g_ctrl = pms_g_ctrl,
966 .vidioc_s_ctrl = pms_s_ctrl,
967 .vidioc_enum_fmt_vid_cap = pms_enum_fmt_vid_cap,
968 .vidioc_g_fmt_vid_cap = pms_g_fmt_vid_cap,
969 .vidioc_s_fmt_vid_cap = pms_s_fmt_vid_cap,
970 .vidioc_try_fmt_vid_cap = pms_try_fmt_vid_cap,
971};
1da177e4
LT
972
973/*
974 * Probe for and initialise the Mediavision PMS
975 */
d56410e0 976
1ce7981b 977static int init_mediavision(struct pms *dev)
1da177e4
LT
978{
979 int id;
980 int idec, decst;
981 int i;
1ce7981b
HV
982 static const unsigned char i2c_defs[] = {
983 0x4c, 0x30, 0x00, 0xe8,
984 0xb6, 0xe2, 0x00, 0x00,
985 0xff, 0xff, 0x00, 0x00,
986 0x00, 0x00, 0x78, 0x98,
987 0x00, 0x00, 0x00, 0x00,
988 0x34, 0x0a, 0xf4, 0xce,
989 0xe4
1da177e4
LT
990 };
991
1ce7981b
HV
992 dev->mem = ioremap(mem_base, 0x800);
993 if (!dev->mem)
1da177e4 994 return -ENOMEM;
d56410e0 995
1ce7981b
HV
996 if (!request_region(0x9a01, 1, "Mediavision PMS config")) {
997 printk(KERN_WARNING "mediavision: unable to detect: 0x9a01 in use.\n");
998 iounmap(dev->mem);
1da177e4
LT
999 return -EBUSY;
1000 }
1ce7981b
HV
1001 if (!request_region(dev->io, 3, "Mediavision PMS")) {
1002 printk(KERN_WARNING "mediavision: I/O port %d in use.\n", dev->io);
1003 release_region(0x9a01, 1);
1004 iounmap(dev->mem);
1da177e4
LT
1005 return -EBUSY;
1006 }
1ce7981b
HV
1007 outb(0xb8, 0x9a01); /* Unlock */
1008 outb(dev->io >> 4, 0x9a01); /* Set IO port */
d56410e0
MCC
1009
1010
1ce7981b
HV
1011 id = mvv_read(dev, 3);
1012 decst = pms_i2c_stat(dev, 0x43);
d56410e0 1013
1ce7981b
HV
1014 if (decst != -1)
1015 idec = 2;
1016 else if (pms_i2c_stat(dev, 0xb9) != -1)
1017 idec = 3;
1018 else if (pms_i2c_stat(dev, 0x8b) != -1)
1019 idec = 1;
d56410e0 1020 else
1ce7981b 1021 idec = 0;
1da177e4
LT
1022
1023 printk(KERN_INFO "PMS type is %d\n", idec);
1ce7981b
HV
1024 if (idec == 0) {
1025 release_region(dev->io, 3);
1026 release_region(0x9a01, 1);
1027 iounmap(dev->mem);
1da177e4
LT
1028 return -ENODEV;
1029 }
1030
1031 /*
1032 * Ok we have a PMS of some sort
1033 */
d56410e0 1034
1ce7981b 1035 mvv_write(dev, 0x04, mem_base >> 12); /* Set the memory area */
d56410e0 1036
1da177e4 1037 /* Ok now load the defaults */
d56410e0 1038
1ce7981b
HV
1039 for (i = 0; i < 0x19; i++) {
1040 if (i2c_defs[i] == 0xff)
1041 pms_i2c_andor(dev, 0x8a, i, 0x07, 0x00);
1da177e4 1042 else
1ce7981b 1043 pms_i2c_write(dev, 0x8a, i, i2c_defs[i]);
1da177e4 1044 }
d56410e0 1045
1ce7981b
HV
1046 pms_i2c_write(dev, 0xb8, 0x00, 0x12);
1047 pms_i2c_write(dev, 0xb8, 0x04, 0x00);
1048 pms_i2c_write(dev, 0xb8, 0x07, 0x00);
1049 pms_i2c_write(dev, 0xb8, 0x08, 0x00);
1050 pms_i2c_write(dev, 0xb8, 0x09, 0xff);
1051 pms_i2c_write(dev, 0xb8, 0x0a, 0x00);
1052 pms_i2c_write(dev, 0xb8, 0x0b, 0x10);
1053 pms_i2c_write(dev, 0xb8, 0x10, 0x03);
1054
1055 mvv_write(dev, 0x01, 0x00);
1056 mvv_write(dev, 0x05, 0xa0);
1057 mvv_write(dev, 0x08, 0x25);
1058 mvv_write(dev, 0x09, 0x00);
1059 mvv_write(dev, 0x0a, 0x20 | MVVMEMORYWIDTH);
1060
1061 mvv_write(dev, 0x10, 0x02);
1062 mvv_write(dev, 0x1e, 0x0c);
1063 mvv_write(dev, 0x1f, 0x03);
1064 mvv_write(dev, 0x26, 0x06);
1065
1066 mvv_write(dev, 0x2b, 0x00);
1067 mvv_write(dev, 0x2c, 0x20);
1068 mvv_write(dev, 0x2d, 0x00);
1069 mvv_write(dev, 0x2f, 0x70);
1070 mvv_write(dev, 0x32, 0x00);
1071 mvv_write(dev, 0x33, MVVMEMORYWIDTH);
1072 mvv_write(dev, 0x34, 0x00);
1073 mvv_write(dev, 0x35, 0x00);
1074 mvv_write(dev, 0x3a, 0x80);
1075 mvv_write(dev, 0x3b, 0x10);
1076 mvv_write(dev, 0x20, 0x00);
1077 mvv_write(dev, 0x21, 0x00);
1078 mvv_write(dev, 0x30, 0x22);
1da177e4
LT
1079 return 0;
1080}
1081
1082/*
1083 * Initialization and module stuff
1084 */
d56410e0 1085
b54ff939
RH
1086#ifndef MODULE
1087static int enable;
1088module_param(enable, int, 0);
1089#endif
1090
1ce7981b 1091static int __init pms_init(void)
1da177e4 1092{
1ce7981b
HV
1093 struct pms *dev = &pms_card;
1094 struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
1095 int res;
1096
1097 strlcpy(v4l2_dev->name, "pms", sizeof(v4l2_dev->name));
1098
1099 v4l2_info(v4l2_dev, "Mediavision Pro Movie Studio driver 0.03\n");
d56410e0 1100
b54ff939
RH
1101#ifndef MODULE
1102 if (!enable) {
1ce7981b
HV
1103 v4l2_err(v4l2_dev,
1104 "PMS: not enabled, use pms.enable=1 to probe\n");
b54ff939
RH
1105 return -ENODEV;
1106 }
1107#endif
1108
1ce7981b
HV
1109 dev->decoder = PHILIPS2;
1110 dev->io = io_port;
1111 dev->data = io_port + 1;
d56410e0 1112
1ce7981b
HV
1113 if (init_mediavision(dev)) {
1114 v4l2_err(v4l2_dev, "Board not found.\n");
1da177e4
LT
1115 return -ENODEV;
1116 }
1da177e4 1117
1ce7981b
HV
1118 res = v4l2_device_register(NULL, v4l2_dev);
1119 if (res < 0) {
1120 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
1121 return res;
1122 }
1da177e4 1123
1ce7981b
HV
1124 strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
1125 dev->vdev.v4l2_dev = v4l2_dev;
1126 dev->vdev.fops = &pms_fops;
feba2f81 1127 dev->vdev.ioctl_ops = &pms_ioctl_ops;
1ce7981b
HV
1128 dev->vdev.release = video_device_release_empty;
1129 video_set_drvdata(&dev->vdev, dev);
1130 mutex_init(&dev->lock);
feba2f81 1131 dev->std = V4L2_STD_NTSC_M;
1ce7981b
HV
1132 dev->height = 240;
1133 dev->width = 320;
feba2f81
HV
1134 dev->depth = 15;
1135 dev->brightness = 139;
1136 dev->contrast = 70;
1137 dev->hue = 0;
1138 dev->saturation = 64;
1ce7981b
HV
1139 pms_swsense(dev, 75);
1140 pms_resolution(dev, 320, 240);
1141 pms_videosource(dev, 0);
1142 pms_vcrinput(dev, 0);
1143 if (video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
1144 v4l2_device_unregister(&dev->v4l2_dev);
1145 release_region(dev->io, 3);
1146 release_region(0x9a01, 1);
1147 iounmap(dev->mem);
1148 return -EINVAL;
1149 }
1150 return 0;
1da177e4
LT
1151}
1152
1ce7981b 1153static void __exit pms_exit(void)
1da177e4 1154{
1ce7981b 1155 struct pms *dev = &pms_card;
1da177e4 1156
1ce7981b
HV
1157 video_unregister_device(&dev->vdev);
1158 release_region(dev->io, 3);
1159 release_region(0x9a01, 1);
1160 iounmap(dev->mem);
1161}
1da177e4 1162
1ce7981b
HV
1163module_init(pms_init);
1164module_exit(pms_exit);