Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / drivers / media / video / pms.c
blob6820c2aabd303affccde30951bd018bc7f1d5673
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@redhat.com unless the
14 * userspace driver also doesn't work for you...
16 * Changes:
17 * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it>
18 * - pms_capture: report back -EFAULT
21 #include <linux/module.h>
22 #include <linux/delay.h>
23 #include <linux/errno.h>
24 #include <linux/fs.h>
25 #include <linux/kernel.h>
26 #include <linux/slab.h>
27 #include <linux/mm.h>
28 #include <linux/ioport.h>
29 #include <linux/init.h>
30 #include <asm/io.h>
31 #include <linux/videodev.h>
32 #include <media/v4l2-common.h>
33 #include <linux/mutex.h>
35 #include <asm/uaccess.h>
38 #define MOTOROLA 1
39 #define PHILIPS2 2
40 #define PHILIPS1 3
41 #define MVVMEMORYWIDTH 0x40 /* 512 bytes */
43 struct pms_device
45 struct video_device v;
46 struct video_picture picture;
47 int height;
48 int width;
49 struct mutex lock;
52 struct i2c_info
54 u8 slave;
55 u8 sub;
56 u8 data;
57 u8 hits;
60 static int i2c_count = 0;
61 static struct i2c_info i2cinfo[64];
63 static int decoder = PHILIPS2;
64 static int standard = 0; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
67 * I/O ports and Shared Memory
70 static int io_port = 0x250;
71 static int data_port = 0x251;
72 static int mem_base = 0xC8000;
73 static void __iomem *mem;
74 static int video_nr = -1;
78 static inline void mvv_write(u8 index, u8 value)
80 outw(index|(value<<8), io_port);
83 static inline u8 mvv_read(u8 index)
85 outb(index, io_port);
86 return inb(data_port);
89 static int pms_i2c_stat(u8 slave)
91 int counter;
92 int i;
94 outb(0x28, io_port);
96 counter=0;
97 while((inb(data_port)&0x01)==0)
98 if(counter++==256)
99 break;
101 while((inb(data_port)&0x01)!=0)
102 if(counter++==256)
103 break;
105 outb(slave, io_port);
107 counter=0;
108 while((inb(data_port)&0x01)==0)
109 if(counter++==256)
110 break;
112 while((inb(data_port)&0x01)!=0)
113 if(counter++==256)
114 break;
116 for(i=0;i<12;i++)
118 char st=inb(data_port);
119 if((st&2)!=0)
120 return -1;
121 if((st&1)==0)
122 break;
124 outb(0x29, io_port);
125 return inb(data_port);
128 static int pms_i2c_write(u16 slave, u16 sub, u16 data)
130 int skip=0;
131 int count;
132 int i;
134 for(i=0;i<i2c_count;i++)
136 if((i2cinfo[i].slave==slave) &&
137 (i2cinfo[i].sub == sub))
139 if(i2cinfo[i].data==data)
140 skip=1;
141 i2cinfo[i].data=data;
142 i=i2c_count+1;
146 if(i==i2c_count && i2c_count<64)
148 i2cinfo[i2c_count].slave=slave;
149 i2cinfo[i2c_count].sub=sub;
150 i2cinfo[i2c_count].data=data;
151 i2c_count++;
154 if(skip)
155 return 0;
157 mvv_write(0x29, sub);
158 mvv_write(0x2A, data);
159 mvv_write(0x28, slave);
161 outb(0x28, io_port);
163 count=0;
164 while((inb(data_port)&1)==0)
165 if(count>255)
166 break;
167 while((inb(data_port)&1)!=0)
168 if(count>255)
169 break;
171 count=inb(data_port);
173 if(count&2)
174 return -1;
175 return count;
178 static int pms_i2c_read(int slave, int sub)
180 int i=0;
181 for(i=0;i<i2c_count;i++)
183 if(i2cinfo[i].slave==slave && i2cinfo[i].sub==sub)
184 return i2cinfo[i].data;
186 return 0;
190 static void pms_i2c_andor(int slave, int sub, int and, int or)
192 u8 tmp;
194 tmp=pms_i2c_read(slave, sub);
195 tmp = (tmp&and)|or;
196 pms_i2c_write(slave, sub, tmp);
200 * Control functions
204 static void pms_videosource(short source)
206 mvv_write(0x2E, source?0x31:0x30);
209 static void pms_hue(short hue)
211 switch(decoder)
213 case MOTOROLA:
214 pms_i2c_write(0x8A, 0x00, hue);
215 break;
216 case PHILIPS2:
217 pms_i2c_write(0x8A, 0x07, hue);
218 break;
219 case PHILIPS1:
220 pms_i2c_write(0x42, 0x07, hue);
221 break;
225 static void pms_colour(short colour)
227 switch(decoder)
229 case MOTOROLA:
230 pms_i2c_write(0x8A, 0x00, colour);
231 break;
232 case PHILIPS1:
233 pms_i2c_write(0x42, 0x12, colour);
234 break;
239 static void pms_contrast(short contrast)
241 switch(decoder)
243 case MOTOROLA:
244 pms_i2c_write(0x8A, 0x00, contrast);
245 break;
246 case PHILIPS1:
247 pms_i2c_write(0x42, 0x13, contrast);
248 break;
252 static void pms_brightness(short brightness)
254 switch(decoder)
256 case MOTOROLA:
257 pms_i2c_write(0x8A, 0x00, brightness);
258 pms_i2c_write(0x8A, 0x00, brightness);
259 pms_i2c_write(0x8A, 0x00, brightness);
260 break;
261 case PHILIPS1:
262 pms_i2c_write(0x42, 0x19, brightness);
263 break;
268 static void pms_format(short format)
270 int target;
271 standard = format;
273 if(decoder==PHILIPS1)
274 target=0x42;
275 else if(decoder==PHILIPS2)
276 target=0x8A;
277 else
278 return;
280 switch(format)
282 case 0: /* Auto */
283 pms_i2c_andor(target, 0x0D, 0xFE,0x00);
284 pms_i2c_andor(target, 0x0F, 0x3F,0x80);
285 break;
286 case 1: /* NTSC */
287 pms_i2c_andor(target, 0x0D, 0xFE, 0x00);
288 pms_i2c_andor(target, 0x0F, 0x3F, 0x40);
289 break;
290 case 2: /* PAL */
291 pms_i2c_andor(target, 0x0D, 0xFE, 0x00);
292 pms_i2c_andor(target, 0x0F, 0x3F, 0x00);
293 break;
294 case 3: /* SECAM */
295 pms_i2c_andor(target, 0x0D, 0xFE, 0x01);
296 pms_i2c_andor(target, 0x0F, 0x3F, 0x00);
297 break;
301 #ifdef FOR_FUTURE_EXPANSION
304 * These features of the PMS card are not currently exposes. They
305 * could become a private v4l ioctl for PMSCONFIG or somesuch if
306 * people need it. We also don't yet use the PMS interrupt.
309 static void pms_hstart(short start)
311 switch(decoder)
313 case PHILIPS1:
314 pms_i2c_write(0x8A, 0x05, start);
315 pms_i2c_write(0x8A, 0x18, start);
316 break;
317 case PHILIPS2:
318 pms_i2c_write(0x42, 0x05, start);
319 pms_i2c_write(0x42, 0x18, start);
320 break;
325 * Bandpass filters
328 static void pms_bandpass(short pass)
330 if(decoder==PHILIPS2)
331 pms_i2c_andor(0x8A, 0x06, 0xCF, (pass&0x03)<<4);
332 else if(decoder==PHILIPS1)
333 pms_i2c_andor(0x42, 0x06, 0xCF, (pass&0x03)<<4);
336 static void pms_antisnow(short snow)
338 if(decoder==PHILIPS2)
339 pms_i2c_andor(0x8A, 0x06, 0xF3, (snow&0x03)<<2);
340 else if(decoder==PHILIPS1)
341 pms_i2c_andor(0x42, 0x06, 0xF3, (snow&0x03)<<2);
344 static void pms_sharpness(short sharp)
346 if(decoder==PHILIPS2)
347 pms_i2c_andor(0x8A, 0x06, 0xFC, sharp&0x03);
348 else if(decoder==PHILIPS1)
349 pms_i2c_andor(0x42, 0x06, 0xFC, sharp&0x03);
352 static void pms_chromaagc(short agc)
354 if(decoder==PHILIPS2)
355 pms_i2c_andor(0x8A, 0x0C, 0x9F, (agc&0x03)<<5);
356 else if(decoder==PHILIPS1)
357 pms_i2c_andor(0x42, 0x0C, 0x9F, (agc&0x03)<<5);
360 static void pms_vertnoise(short noise)
362 if(decoder==PHILIPS2)
363 pms_i2c_andor(0x8A, 0x10, 0xFC, noise&3);
364 else if(decoder==PHILIPS1)
365 pms_i2c_andor(0x42, 0x10, 0xFC, noise&3);
368 static void pms_forcecolour(short colour)
370 if(decoder==PHILIPS2)
371 pms_i2c_andor(0x8A, 0x0C, 0x7F, (colour&1)<<7);
372 else if(decoder==PHILIPS1)
373 pms_i2c_andor(0x42, 0x0C, 0x7, (colour&1)<<7);
376 static void pms_antigamma(short gamma)
378 if(decoder==PHILIPS2)
379 pms_i2c_andor(0xB8, 0x00, 0x7F, (gamma&1)<<7);
380 else if(decoder==PHILIPS1)
381 pms_i2c_andor(0x42, 0x20, 0x7, (gamma&1)<<7);
384 static void pms_prefilter(short filter)
386 if(decoder==PHILIPS2)
387 pms_i2c_andor(0x8A, 0x06, 0xBF, (filter&1)<<6);
388 else if(decoder==PHILIPS1)
389 pms_i2c_andor(0x42, 0x06, 0xBF, (filter&1)<<6);
392 static void pms_hfilter(short filter)
394 if(decoder==PHILIPS2)
395 pms_i2c_andor(0xB8, 0x04, 0x1F, (filter&7)<<5);
396 else if(decoder==PHILIPS1)
397 pms_i2c_andor(0x42, 0x24, 0x1F, (filter&7)<<5);
400 static void pms_vfilter(short filter)
402 if(decoder==PHILIPS2)
403 pms_i2c_andor(0xB8, 0x08, 0x9F, (filter&3)<<5);
404 else if(decoder==PHILIPS1)
405 pms_i2c_andor(0x42, 0x28, 0x9F, (filter&3)<<5);
408 static void pms_killcolour(short colour)
410 if(decoder==PHILIPS2)
412 pms_i2c_andor(0x8A, 0x08, 0x07, (colour&0x1F)<<3);
413 pms_i2c_andor(0x8A, 0x09, 0x07, (colour&0x1F)<<3);
415 else if(decoder==PHILIPS1)
417 pms_i2c_andor(0x42, 0x08, 0x07, (colour&0x1F)<<3);
418 pms_i2c_andor(0x42, 0x09, 0x07, (colour&0x1F)<<3);
422 static void pms_chromagain(short chroma)
424 if(decoder==PHILIPS2)
426 pms_i2c_write(0x8A, 0x11, chroma);
428 else if(decoder==PHILIPS1)
430 pms_i2c_write(0x42, 0x11, chroma);
435 static void pms_spacialcompl(short data)
437 mvv_write(0x3B, data);
440 static void pms_spacialcomph(short data)
442 mvv_write(0x3A, data);
445 static void pms_vstart(short start)
447 mvv_write(0x16, start);
448 mvv_write(0x17, (start>>8)&0x01);
451 #endif
453 static void pms_secamcross(short cross)
455 if(decoder==PHILIPS2)
456 pms_i2c_andor(0x8A, 0x0F, 0xDF, (cross&1)<<5);
457 else if(decoder==PHILIPS1)
458 pms_i2c_andor(0x42, 0x0F, 0xDF, (cross&1)<<5);
462 static void pms_swsense(short sense)
464 if(decoder==PHILIPS2)
466 pms_i2c_write(0x8A, 0x0A, sense);
467 pms_i2c_write(0x8A, 0x0B, sense);
469 else if(decoder==PHILIPS1)
471 pms_i2c_write(0x42, 0x0A, sense);
472 pms_i2c_write(0x42, 0x0B, sense);
477 static void pms_framerate(short frr)
479 int fps=(standard==1)?30:25;
480 if(frr==0)
481 return;
482 fps=fps/frr;
483 mvv_write(0x14,0x80|fps);
484 mvv_write(0x15,1);
487 static void pms_vert(u8 deciden, u8 decinum)
489 mvv_write(0x1C, deciden); /* Denominator */
490 mvv_write(0x1D, decinum); /* Numerator */
494 * Turn 16bit ratios into best small ratio the chipset can grok
497 static void pms_vertdeci(unsigned short decinum, unsigned short deciden)
499 /* Knock it down by /5 once */
500 if(decinum%5==0)
502 deciden/=5;
503 decinum/=5;
506 * 3's
508 while(decinum%3==0 && deciden%3==0)
510 deciden/=3;
511 decinum/=3;
514 * 2's
516 while(decinum%2==0 && deciden%2==0)
518 decinum/=2;
519 deciden/=2;
522 * Fudgyify
524 while(deciden>32)
526 deciden/=2;
527 decinum=(decinum+1)/2;
529 if(deciden==32)
530 deciden--;
531 pms_vert(deciden,decinum);
534 static void pms_horzdeci(short decinum, short deciden)
536 if(decinum<=512)
538 if(decinum%5==0)
540 decinum/=5;
541 deciden/=5;
544 else
546 decinum=512;
547 deciden=640; /* 768 would be ideal */
550 while(((decinum|deciden)&1)==0)
552 decinum>>=1;
553 deciden>>=1;
555 while(deciden>32)
557 deciden>>=1;
558 decinum=(decinum+1)>>1;
560 if(deciden==32)
561 deciden--;
563 mvv_write(0x24, 0x80|deciden);
564 mvv_write(0x25, decinum);
567 static void pms_resolution(short width, short height)
569 int fg_height;
571 fg_height=height;
572 if(fg_height>280)
573 fg_height=280;
575 mvv_write(0x18, fg_height);
576 mvv_write(0x19, fg_height>>8);
578 if(standard==1)
580 mvv_write(0x1A, 0xFC);
581 mvv_write(0x1B, 0x00);
582 if(height>fg_height)
583 pms_vertdeci(240,240);
584 else
585 pms_vertdeci(fg_height,240);
587 else
589 mvv_write(0x1A, 0x1A);
590 mvv_write(0x1B, 0x01);
591 if(fg_height>256)
592 pms_vertdeci(270,270);
593 else
594 pms_vertdeci(fg_height, 270);
596 mvv_write(0x12,0);
597 mvv_write(0x13, MVVMEMORYWIDTH);
598 mvv_write(0x42, 0x00);
599 mvv_write(0x43, 0x00);
600 mvv_write(0x44, MVVMEMORYWIDTH);
602 mvv_write(0x22, width+8);
603 mvv_write(0x23, (width+8)>> 8);
605 if(standard==1)
606 pms_horzdeci(width,640);
607 else
608 pms_horzdeci(width+8, 768);
610 mvv_write(0x30, mvv_read(0x30)&0xFE);
611 mvv_write(0x08, mvv_read(0x08)|0x01);
612 mvv_write(0x01, mvv_read(0x01)&0xFD);
613 mvv_write(0x32, 0x00);
614 mvv_write(0x33, MVVMEMORYWIDTH);
619 * Set Input
622 static void pms_vcrinput(short input)
624 if(decoder==PHILIPS2)
625 pms_i2c_andor(0x8A,0x0D,0x7F,(input&1)<<7);
626 else if(decoder==PHILIPS1)
627 pms_i2c_andor(0x42,0x0D,0x7F,(input&1)<<7);
631 static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int count)
633 int y;
634 int dw = 2*dev->width;
636 char tmp[dw+32]; /* using a temp buffer is faster than direct */
637 int cnt = 0;
638 int len=0;
639 unsigned char r8 = 0x5; /* value for reg8 */
641 if (rgb555)
642 r8 |= 0x20; /* else use untranslated rgb = 565 */
643 mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */
645 /* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
647 for (y = 0; y < dev->height; y++ )
649 writeb(0, mem); /* synchronisiert neue Zeile */
652 * This is in truth a fifo, be very careful as if you
653 * forgot this odd things will occur 8)
656 memcpy_fromio(tmp, mem, dw+32); /* discard 16 word */
657 cnt -= dev->height;
658 while (cnt <= 0)
661 * Don't copy too far
663 int dt=dw;
664 if(dt+len>count)
665 dt=count-len;
666 cnt += dev->height;
667 if (copy_to_user(buf, tmp+32, dt))
668 return len ? len : -EFAULT;
669 buf += dt;
670 len += dt;
673 return len;
678 * Video4linux interfacing
681 static int pms_do_ioctl(struct inode *inode, struct file *file,
682 unsigned int cmd, void *arg)
684 struct video_device *dev = video_devdata(file);
685 struct pms_device *pd=(struct pms_device *)dev;
687 switch(cmd)
689 case VIDIOCGCAP:
691 struct video_capability *b = arg;
692 strcpy(b->name, "Mediavision PMS");
693 b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES;
694 b->channels = 4;
695 b->audios = 0;
696 b->maxwidth = 640;
697 b->maxheight = 480;
698 b->minwidth = 16;
699 b->minheight = 16;
700 return 0;
702 case VIDIOCGCHAN:
704 struct video_channel *v = arg;
705 if(v->channel<0 || v->channel>3)
706 return -EINVAL;
707 v->flags=0;
708 v->tuners=1;
709 /* Good question.. its composite or SVHS so.. */
710 v->type = VIDEO_TYPE_CAMERA;
711 switch(v->channel)
713 case 0:
714 strcpy(v->name, "Composite");break;
715 case 1:
716 strcpy(v->name, "SVideo");break;
717 case 2:
718 strcpy(v->name, "Composite(VCR)");break;
719 case 3:
720 strcpy(v->name, "SVideo(VCR)");break;
722 return 0;
724 case VIDIOCSCHAN:
726 struct video_channel *v = arg;
727 if(v->channel<0 || v->channel>3)
728 return -EINVAL;
729 mutex_lock(&pd->lock);
730 pms_videosource(v->channel&1);
731 pms_vcrinput(v->channel>>1);
732 mutex_unlock(&pd->lock);
733 return 0;
735 case VIDIOCGTUNER:
737 struct video_tuner *v = arg;
738 if(v->tuner)
739 return -EINVAL;
740 strcpy(v->name, "Format");
741 v->rangelow=0;
742 v->rangehigh=0;
743 v->flags= VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
744 switch(standard)
746 case 0:
747 v->mode = VIDEO_MODE_AUTO;
748 break;
749 case 1:
750 v->mode = VIDEO_MODE_NTSC;
751 break;
752 case 2:
753 v->mode = VIDEO_MODE_PAL;
754 break;
755 case 3:
756 v->mode = VIDEO_MODE_SECAM;
757 break;
759 return 0;
761 case VIDIOCSTUNER:
763 struct video_tuner *v = arg;
764 if(v->tuner)
765 return -EINVAL;
766 mutex_lock(&pd->lock);
767 switch(v->mode)
769 case VIDEO_MODE_AUTO:
770 pms_framerate(25);
771 pms_secamcross(0);
772 pms_format(0);
773 break;
774 case VIDEO_MODE_NTSC:
775 pms_framerate(30);
776 pms_secamcross(0);
777 pms_format(1);
778 break;
779 case VIDEO_MODE_PAL:
780 pms_framerate(25);
781 pms_secamcross(0);
782 pms_format(2);
783 break;
784 case VIDEO_MODE_SECAM:
785 pms_framerate(25);
786 pms_secamcross(1);
787 pms_format(2);
788 break;
789 default:
790 mutex_unlock(&pd->lock);
791 return -EINVAL;
793 mutex_unlock(&pd->lock);
794 return 0;
796 case VIDIOCGPICT:
798 struct video_picture *p = arg;
799 *p = pd->picture;
800 return 0;
802 case VIDIOCSPICT:
804 struct video_picture *p = arg;
805 if(!((p->palette==VIDEO_PALETTE_RGB565 && p->depth==16)
806 ||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15)))
807 return -EINVAL;
808 pd->picture= *p;
811 * Now load the card.
814 mutex_lock(&pd->lock);
815 pms_brightness(p->brightness>>8);
816 pms_hue(p->hue>>8);
817 pms_colour(p->colour>>8);
818 pms_contrast(p->contrast>>8);
819 mutex_unlock(&pd->lock);
820 return 0;
822 case VIDIOCSWIN:
824 struct video_window *vw = arg;
825 if(vw->flags)
826 return -EINVAL;
827 if(vw->clipcount)
828 return -EINVAL;
829 if(vw->height<16||vw->height>480)
830 return -EINVAL;
831 if(vw->width<16||vw->width>640)
832 return -EINVAL;
833 pd->width=vw->width;
834 pd->height=vw->height;
835 mutex_lock(&pd->lock);
836 pms_resolution(pd->width, pd->height);
837 mutex_unlock(&pd->lock); /* Ok we figured out what to use from our wide choice */
838 return 0;
840 case VIDIOCGWIN:
842 struct video_window *vw = arg;
843 memset(vw,0,sizeof(*vw));
844 vw->width=pd->width;
845 vw->height=pd->height;
846 return 0;
848 case VIDIOCKEY:
849 return 0;
850 case VIDIOCCAPTURE:
851 case VIDIOCGFBUF:
852 case VIDIOCSFBUF:
853 case VIDIOCGFREQ:
854 case VIDIOCSFREQ:
855 case VIDIOCGAUDIO:
856 case VIDIOCSAUDIO:
857 return -EINVAL;
858 default:
859 return -ENOIOCTLCMD;
861 return 0;
864 static int pms_ioctl(struct inode *inode, struct file *file,
865 unsigned int cmd, unsigned long arg)
867 return video_usercopy(inode, file, cmd, arg, pms_do_ioctl);
870 static ssize_t pms_read(struct file *file, char __user *buf,
871 size_t count, loff_t *ppos)
873 struct video_device *v = video_devdata(file);
874 struct pms_device *pd=(struct pms_device *)v;
875 int len;
877 mutex_lock(&pd->lock);
878 len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count);
879 mutex_unlock(&pd->lock);
880 return len;
883 static const struct file_operations pms_fops = {
884 .owner = THIS_MODULE,
885 .open = video_exclusive_open,
886 .release = video_exclusive_release,
887 .ioctl = pms_ioctl,
888 .compat_ioctl = v4l_compat_ioctl32,
889 .read = pms_read,
890 .llseek = no_llseek,
893 static struct video_device pms_template=
895 .owner = THIS_MODULE,
896 .name = "Mediavision PMS",
897 .type = VID_TYPE_CAPTURE,
898 .fops = &pms_fops,
901 static struct pms_device pms_device;
905 * Probe for and initialise the Mediavision PMS
908 static int init_mediavision(void)
910 int id;
911 int idec, decst;
912 int i;
914 unsigned char i2c_defs[]={
915 0x4C,0x30,0x00,0xE8,
916 0xB6,0xE2,0x00,0x00,
917 0xFF,0xFF,0x00,0x00,
918 0x00,0x00,0x78,0x98,
919 0x00,0x00,0x00,0x00,
920 0x34,0x0A,0xF4,0xCE,
921 0xE4
924 mem = ioremap(mem_base, 0x800);
925 if (!mem)
926 return -ENOMEM;
928 if (!request_region(0x9A01, 1, "Mediavision PMS config"))
930 printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n");
931 iounmap(mem);
932 return -EBUSY;
934 if (!request_region(io_port, 3, "Mediavision PMS"))
936 printk(KERN_WARNING "mediavision: I/O port %d in use.\n", io_port);
937 release_region(0x9A01, 1);
938 iounmap(mem);
939 return -EBUSY;
941 outb(0xB8, 0x9A01); /* Unlock */
942 outb(io_port>>4, 0x9A01); /* Set IO port */
945 id=mvv_read(3);
946 decst=pms_i2c_stat(0x43);
948 if(decst!=-1)
949 idec=2;
950 else if(pms_i2c_stat(0xb9)!=-1)
951 idec=3;
952 else if(pms_i2c_stat(0x8b)!=-1)
953 idec=1;
954 else
955 idec=0;
957 printk(KERN_INFO "PMS type is %d\n", idec);
958 if(idec == 0) {
959 release_region(io_port, 3);
960 release_region(0x9A01, 1);
961 iounmap(mem);
962 return -ENODEV;
966 * Ok we have a PMS of some sort
969 mvv_write(0x04, mem_base>>12); /* Set the memory area */
971 /* Ok now load the defaults */
973 for(i=0;i<0x19;i++)
975 if(i2c_defs[i]==0xFF)
976 pms_i2c_andor(0x8A, i, 0x07,0x00);
977 else
978 pms_i2c_write(0x8A, i, i2c_defs[i]);
981 pms_i2c_write(0xB8,0x00,0x12);
982 pms_i2c_write(0xB8,0x04,0x00);
983 pms_i2c_write(0xB8,0x07,0x00);
984 pms_i2c_write(0xB8,0x08,0x00);
985 pms_i2c_write(0xB8,0x09,0xFF);
986 pms_i2c_write(0xB8,0x0A,0x00);
987 pms_i2c_write(0xB8,0x0B,0x10);
988 pms_i2c_write(0xB8,0x10,0x03);
990 mvv_write(0x01, 0x00);
991 mvv_write(0x05, 0xA0);
992 mvv_write(0x08, 0x25);
993 mvv_write(0x09, 0x00);
994 mvv_write(0x0A, 0x20|MVVMEMORYWIDTH);
996 mvv_write(0x10, 0x02);
997 mvv_write(0x1E, 0x0C);
998 mvv_write(0x1F, 0x03);
999 mvv_write(0x26, 0x06);
1001 mvv_write(0x2B, 0x00);
1002 mvv_write(0x2C, 0x20);
1003 mvv_write(0x2D, 0x00);
1004 mvv_write(0x2F, 0x70);
1005 mvv_write(0x32, 0x00);
1006 mvv_write(0x33, MVVMEMORYWIDTH);
1007 mvv_write(0x34, 0x00);
1008 mvv_write(0x35, 0x00);
1009 mvv_write(0x3A, 0x80);
1010 mvv_write(0x3B, 0x10);
1011 mvv_write(0x20, 0x00);
1012 mvv_write(0x21, 0x00);
1013 mvv_write(0x30, 0x22);
1014 return 0;
1018 * Initialization and module stuff
1021 static int __init init_pms_cards(void)
1023 printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n");
1025 data_port = io_port +1;
1027 if(init_mediavision())
1029 printk(KERN_INFO "Board not found.\n");
1030 return -ENODEV;
1032 memcpy(&pms_device, &pms_template, sizeof(pms_template));
1033 mutex_init(&pms_device.lock);
1034 pms_device.height=240;
1035 pms_device.width=320;
1036 pms_swsense(75);
1037 pms_resolution(320,240);
1038 return video_register_device((struct video_device *)&pms_device, VFL_TYPE_GRABBER, video_nr);
1041 module_param(io_port, int, 0);
1042 module_param(mem_base, int, 0);
1043 module_param(video_nr, int, 0);
1044 MODULE_LICENSE("GPL");
1047 static void __exit shutdown_mediavision(void)
1049 release_region(io_port,3);
1050 release_region(0x9A01, 1);
1053 static void __exit cleanup_pms_module(void)
1055 shutdown_mediavision();
1056 video_unregister_device((struct video_device *)&pms_device);
1057 iounmap(mem);
1060 module_init(init_pms_cards);
1061 module_exit(cleanup_pms_module);