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