Import 2.3.5
[davej-history.git] / drivers / char / pms.c
blob72653aa1975e6c295347b214cc45724d4a5e6f40
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 doesnt work for you...
17 #include <linux/module.h>
18 #include <linux/delay.h>
19 #include <linux/errno.h>
20 #include <linux/fs.h>
21 #include <linux/kernel.h>
22 #include <linux/malloc.h>
23 #include <linux/mm.h>
24 #include <linux/ioport.h>
25 #include <asm/io.h>
26 #include <linux/sched.h>
27 #include <linux/videodev.h>
28 #include <linux/version.h>
29 #include <asm/uaccess.h>
32 #define MOTOROLA 1
33 #define PHILIPS2 2
34 #define PHILIPS1 3
35 #define MVVMEMORYWIDTH 0x40 /* 512 bytes */
37 struct pms_device
39 struct video_device v;
40 struct video_picture picture;
41 int height;
42 int width;
45 struct i2c_info
47 u8 slave;
48 u8 sub;
49 u8 data;
50 u8 hits;
53 static int i2c_count = 0;
54 static struct i2c_info i2cinfo[64];
56 static int decoder = PHILIPS2;
57 static int standard = 0; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
60 * I/O ports and Shared Memory
63 static int io_port = 0x250;
64 static int data_port = 0x251;
65 static int mem_base = 0xC8000;
69 extern __inline__ void mvv_write(u8 index, u8 value)
71 outw(index|(value<<8), io_port);
74 extern __inline__ u8 mvv_read(u8 index)
76 outb(index, io_port);
77 return inb(data_port);
80 static int pms_i2c_stat(u8 slave)
82 int counter;
83 int i;
85 outb(0x28, io_port);
87 counter=0;
88 while((inb(data_port)&0x01)==0)
89 if(counter++==256)
90 break;
92 while((inb(data_port)&0x01)!=0)
93 if(counter++==256)
94 break;
96 outb(slave, io_port);
98 counter=0;
99 while((inb(data_port)&0x01)==0)
100 if(counter++==256)
101 break;
103 while((inb(data_port)&0x01)!=0)
104 if(counter++==256)
105 break;
107 for(i=0;i<12;i++)
109 char st=inb(data_port);
110 if((st&2)!=0)
111 return -1;
112 if((st&1)==0)
113 break;
115 outb(0x29, io_port);
116 return inb(data_port);
119 static int pms_i2c_write(u16 slave, u16 sub, u16 data)
121 int skip=0;
122 int count;
123 int i;
125 for(i=0;i<i2c_count;i++)
127 if((i2cinfo[i].slave==slave) &&
128 (i2cinfo[i].sub == sub))
130 if(i2cinfo[i].data==data)
131 skip=1;
132 i2cinfo[i].data=data;
133 i=i2c_count+1;
137 if(i==i2c_count && i2c_count<64)
139 i2cinfo[i2c_count].slave=slave;
140 i2cinfo[i2c_count].sub=sub;
141 i2cinfo[i2c_count].data=data;
142 i2c_count++;
145 if(skip)
146 return 0;
148 mvv_write(0x29, sub);
149 mvv_write(0x2A, data);
150 mvv_write(0x28, slave);
152 outb(0x28, io_port);
154 count=0;
155 while((inb(data_port)&1)==0)
156 if(count>255)
157 break;
158 while((inb(data_port)&1)!=0)
159 if(count>255)
160 break;
162 count=inb(data_port);
164 if(count&2)
165 return -1;
166 return count;
169 static int pms_i2c_read(int slave, int sub)
171 int i=0;
172 for(i=0;i<i2c_count;i++)
174 if(i2cinfo[i].slave==slave && i2cinfo[i].sub==sub)
175 return i2cinfo[i].data;
177 return 0;
181 static void pms_i2c_andor(int slave, int sub, int and, int or)
183 u8 tmp;
185 tmp=pms_i2c_read(slave, sub);
186 tmp = (tmp&and)|or;
187 pms_i2c_write(slave, sub, tmp);
191 * Control functions
195 static void pms_videosource(short source)
197 mvv_write(0x2E, source?0x31:0x30);
200 static void pms_hue(short hue)
202 switch(decoder)
204 case MOTOROLA:
205 pms_i2c_write(0x8A, 0x00, hue);
206 break;
207 case PHILIPS2:
208 pms_i2c_write(0x8A, 0x07, hue);
209 break;
210 case PHILIPS1:
211 pms_i2c_write(0x42, 0x07, hue);
212 break;
216 static void pms_colour(short colour)
218 switch(decoder)
220 case MOTOROLA:
221 pms_i2c_write(0x8A, 0x00, colour);
222 break;
223 case PHILIPS1:
224 pms_i2c_write(0x42, 0x12, colour);
225 break;
230 static void pms_contrast(short contrast)
232 switch(decoder)
234 case MOTOROLA:
235 pms_i2c_write(0x8A, 0x00, contrast);
236 break;
237 case PHILIPS1:
238 pms_i2c_write(0x42, 0x13, contrast);
239 break;
243 static void pms_brightness(short brightness)
245 switch(decoder)
247 case MOTOROLA:
248 pms_i2c_write(0x8A, 0x00, brightness);
249 pms_i2c_write(0x8A, 0x00, brightness);
250 pms_i2c_write(0x8A, 0x00, brightness);
251 break;
252 case PHILIPS1:
253 pms_i2c_write(0x42, 0x19, brightness);
254 break;
259 static void pms_format(short format)
261 int target;
262 standard = format;
264 if(decoder==PHILIPS1)
265 target=0x42;
266 else if(decoder==PHILIPS2)
267 target=0x8A;
268 else
269 return;
271 switch(format)
273 case 0: /* Auto */
274 pms_i2c_andor(target, 0x0D, 0xFE,0x00);
275 pms_i2c_andor(target, 0x0F, 0x3F,0x80);
276 break;
277 case 1: /* NTSC */
278 pms_i2c_andor(target, 0x0D, 0xFE, 0x00);
279 pms_i2c_andor(target, 0x0F, 0x3F, 0x40);
280 break;
281 case 2: /* PAL */
282 pms_i2c_andor(target, 0x0D, 0xFE, 0x00);
283 pms_i2c_andor(target, 0x0F, 0x3F, 0x00);
284 break;
285 case 3: /* SECAM */
286 pms_i2c_andor(target, 0x0D, 0xFE, 0x01);
287 pms_i2c_andor(target, 0x0F, 0x3F, 0x00);
288 break;
292 #ifdef FOR_FUTURE_EXPANSION
295 * These features of the PMS card are not currently exposes. They
296 * could become a private v4l ioctl for PMSCONFIG or somesuch if
297 * people need it. We also don't yet use the PMS interrupt.
300 static void pms_hstart(short start)
302 switch(decoder)
304 case PHILIPS1:
305 pms_i2c_write(0x8A, 0x05, start);
306 pms_i2c_write(0x8A, 0x18, start);
307 break;
308 case PHILIPS2:
309 pms_i2c_write(0x42, 0x05, start);
310 pms_i2c_write(0x42, 0x18, start);
311 break;
316 * Bandpass filters
319 static void pms_bandpass(short pass)
321 if(decoder==PHILIPS2)
322 pms_i2c_andor(0x8A, 0x06, 0xCF, (pass&0x03)<<4);
323 else if(decoder==PHILIPS1)
324 pms_i2c_andor(0x42, 0x06, 0xCF, (pass&0x03)<<4);
327 static void pms_antisnow(short snow)
329 if(decoder==PHILIPS2)
330 pms_i2c_andor(0x8A, 0x06, 0xF3, (snow&0x03)<<2);
331 else if(decoder==PHILIPS1)
332 pms_i2c_andor(0x42, 0x06, 0xF3, (snow&0x03)<<2);
335 static void pms_sharpness(short sharp)
337 if(decoder==PHILIPS2)
338 pms_i2c_andor(0x8A, 0x06, 0xFC, sharp&0x03);
339 else if(decoder==PHILIPS1)
340 pms_i2c_andor(0x42, 0x06, 0xFC, sharp&0x03);
343 static void pms_chromaagc(short agc)
345 if(decoder==PHILIPS2)
346 pms_i2c_andor(0x8A, 0x0C, 0x9F, (agc&0x03)<<5);
347 else if(decoder==PHILIPS1)
348 pms_i2c_andor(0x42, 0x0C, 0x9F, (agc&0x03)<<5);
351 static void pms_vertnoise(short noise)
353 if(decoder==PHILIPS2)
354 pms_i2c_andor(0x8A, 0x10, 0xFC, noise&3);
355 else if(decoder==PHILIPS1)
356 pms_i2c_andor(0x42, 0x10, 0xFC, noise&3);
359 static void pms_forcecolour(short colour)
361 if(decoder==PHILIPS2)
362 pms_i2c_andor(0x8A, 0x0C, 0x7F, (colour&1)<<7);
363 else if(decoder==PHILIPS1)
364 pms_i2c_andor(0x42, 0x0C, 0x7, (colour&1)<<7);
367 static void pms_antigamma(short gamma)
369 if(decoder==PHILIPS2)
370 pms_i2c_andor(0xB8, 0x00, 0x7F, (gamma&1)<<7);
371 else if(decoder==PHILIPS1)
372 pms_i2c_andor(0x42, 0x20, 0x7, (gamma&1)<<7);
375 static void pms_prefilter(short filter)
377 if(decoder==PHILIPS2)
378 pms_i2c_andor(0x8A, 0x06, 0xBF, (filter&1)<<6);
379 else if(decoder==PHILIPS1)
380 pms_i2c_andor(0x42, 0x06, 0xBF, (filter&1)<<6);
383 static void pms_hfilter(short filter)
385 if(decoder==PHILIPS2)
386 pms_i2c_andor(0xB8, 0x04, 0x1F, (filter&7)<<5);
387 else if(decoder==PHILIPS1)
388 pms_i2c_andor(0x42, 0x24, 0x1F, (filter&7)<<5);
391 static void pms_vfilter(short filter)
393 if(decoder==PHILIPS2)
394 pms_i2c_andor(0xB8, 0x08, 0x9F, (filter&3)<<5);
395 else if(decoder==PHILIPS1)
396 pms_i2c_andor(0x42, 0x28, 0x9F, (filter&3)<<5);
399 static void pms_killcolour(short colour)
401 if(decoder==PHILIPS2)
403 pms_i2c_andor(0x8A, 0x08, 0x07, (colour&0x1F)<<3);
404 pms_i2c_andor(0x8A, 0x09, 0x07, (colour&0x1F)<<3);
406 else if(decoder==PHILIPS1)
408 pms_i2c_andor(0x42, 0x08, 0x07, (colour&0x1F)<<3);
409 pms_i2c_andor(0x42, 0x09, 0x07, (colour&0x1F)<<3);
413 static void pms_chromagain(short chroma)
415 if(decoder==PHILIPS2)
417 pms_i2c_write(0x8A, 0x11, chroma);
419 else if(decoder==PHILIPS1)
421 pms_i2c_write(0x42, 0x11, chroma);
426 static void pms_spacialcompl(short data)
428 mvv_write(0x3B, data);
431 static void pms_spacialcomph(short data)
433 mvv_write(0x3A, data);
436 static void pms_vstart(short start)
438 mvv_write(0x16, start);
439 mvv_write(0x17, (start>>8)&0x01);
442 #endif
444 static void pms_secamcross(short cross)
446 if(decoder==PHILIPS2)
447 pms_i2c_andor(0x8A, 0x0F, 0xDF, (cross&1)<<5);
448 else if(decoder==PHILIPS1)
449 pms_i2c_andor(0x42, 0x0F, 0xDF, (cross&1)<<5);
453 static void pms_swsense(short sense)
455 if(decoder==PHILIPS2)
457 pms_i2c_write(0x8A, 0x0A, sense);
458 pms_i2c_write(0x8A, 0x0B, sense);
460 else if(decoder==PHILIPS1)
462 pms_i2c_write(0x42, 0x0A, sense);
463 pms_i2c_write(0x42, 0x0B, sense);
468 static void pms_framerate(short frr)
470 int fps=(standard==1)?30:25;
471 if(frr==0)
472 return;
473 fps=fps/frr;
474 mvv_write(0x14,0x80|fps);
475 mvv_write(0x15,1);
478 static void pms_vert(u8 deciden, u8 decinum)
480 mvv_write(0x1C, deciden); /* Denominator */
481 mvv_write(0x1D, decinum); /* Numerator */
485 * Turn 16bit ratios into best small ratio the chipset can grok
488 static void pms_vertdeci(unsigned short decinum, unsigned short deciden)
490 /* Knock it down by /5 once */
491 if(decinum%5==0)
493 deciden/=5;
494 decinum/=5;
497 * 3's
499 while(decinum%3==0 && deciden%3==0)
501 deciden/=3;
502 decinum/=3;
505 * 2's
507 while(decinum%2==0 && deciden%2==0)
509 decinum/=2;
510 deciden/=2;
513 * Fudgyify
515 while(deciden>32)
517 deciden/=2;
518 decinum=(decinum+1)/2;
520 if(deciden==32)
521 deciden--;
522 pms_vert(deciden,decinum);
525 static void pms_horzdeci(short decinum, short deciden)
527 if(decinum<=512)
529 if(decinum%5==0)
531 decinum/=5;
532 deciden/=5;
535 else
537 decinum=512;
538 deciden=640; /* 768 would be ideal */
541 while(((decinum|deciden)&1)==0)
543 decinum>>=1;
544 deciden>>=1;
546 while(deciden>32)
548 deciden>>=1;
549 decinum=(decinum+1)>>1;
551 if(deciden==32)
552 deciden--;
554 mvv_write(0x24, 0x80|deciden);
555 mvv_write(0x25, decinum);
558 static void pms_resolution(short width, short height)
560 int fg_height;
562 fg_height=height;
563 if(fg_height>280)
564 fg_height=280;
566 mvv_write(0x18, fg_height);
567 mvv_write(0x19, fg_height>>8);
569 if(standard==1)
571 mvv_write(0x1A, 0xFC);
572 mvv_write(0x1B, 0x00);
573 if(height>fg_height)
574 pms_vertdeci(240,240);
575 else
576 pms_vertdeci(fg_height,240);
578 else
580 mvv_write(0x1A, 0x1A);
581 mvv_write(0x1B, 0x01);
582 if(fg_height>256)
583 pms_vertdeci(270,270);
584 else
585 pms_vertdeci(fg_height, 270);
587 mvv_write(0x12,0);
588 mvv_write(0x13, MVVMEMORYWIDTH);
589 mvv_write(0x42, 0x00);
590 mvv_write(0x43, 0x00);
591 mvv_write(0x44, MVVMEMORYWIDTH);
593 mvv_write(0x22, width+8);
594 mvv_write(0x23, (width+8)>> 8);
596 if(standard==1)
597 pms_horzdeci(width,640);
598 else
599 pms_horzdeci(width+8, 768);
601 mvv_write(0x30, mvv_read(0x30)&0xFE);
602 mvv_write(0x08, mvv_read(0x08)|0x01);
603 mvv_write(0x01, mvv_read(0x01)&0xFD);
604 mvv_write(0x32, 0x00);
605 mvv_write(0x33, MVVMEMORYWIDTH);
610 * Set Input
613 static void pms_vcrinput(short input)
615 if(decoder==PHILIPS2)
616 pms_i2c_andor(0x8A,0x0D,0x7F,(input&1)<<7);
617 else if(decoder==PHILIPS1)
618 pms_i2c_andor(0x42,0x0D,0x7F,(input&1)<<7);
622 static int pms_capture(struct pms_device *dev, char *buf, int rgb555, int count)
624 int y;
625 int dw = 2*dev->width;
626 char *src = (char *)bus_to_virt(mem_base);
628 char tmp[dw+32]; /* using a temp buffer is faster than direct */
629 int cnt = 0;
630 int len=0;
631 unsigned char r8 = 0x5; /* value for reg8 */
633 if (rgb555)
634 r8 |= 0x20; /* else use untranslated rgb = 565 */
635 mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */
637 /* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
639 for (y = 0; y < dev->height; y++ )
641 *src = 0; /* synchronisiert neue Zeile */
642 memcpy(tmp, src, dw+32); /* discard 16 word */
643 cnt -= dev->height;
644 while (cnt <= 0)
647 * Don't copy too far
649 int dt=dw;
650 if(dt+len>count)
651 dt=count-len;
652 cnt += dev->height;
653 copy_to_user(buf, tmp+32, dt);
654 buf += dt;
655 len += dt;
658 return len;
663 * Video4linux interfacing
666 static int pms_open(struct video_device *dev, int flags)
668 MOD_INC_USE_COUNT;
669 return 0;
672 static void pms_close(struct video_device *dev)
674 MOD_DEC_USE_COUNT;
677 static int pms_init_done(struct video_device *dev)
679 return 0;
682 static long pms_write(struct video_device *v, const char *buf, unsigned long count, int noblock)
684 return -EINVAL;
687 static int pms_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
689 struct pms_device *pd=(struct pms_device *)dev;
691 switch(cmd)
693 case VIDIOCGCAP:
695 struct video_capability b;
696 strcpy(b.name, "Mediavision PMS");
697 b.type = VID_TYPE_CAPTURE|VID_TYPE_SCALES;
698 b.channels = 4;
699 b.audios = 0;
700 b.maxwidth = 640;
701 b.maxheight = 480;
702 b.minwidth = 16;
703 b.minheight = 16;
704 if(copy_to_user(arg, &b,sizeof(b)))
705 return -EFAULT;
706 return 0;
708 case VIDIOCGCHAN:
710 struct video_channel v;
711 if(copy_from_user(&v, arg, sizeof(v)))
712 return -EFAULT;
713 if(v.channel<0 || v.channel>3)
714 return -EINVAL;
715 v.flags=0;
716 v.tuners=1;
717 /* Good question.. its composite or SVHS so.. */
718 v.type = VIDEO_TYPE_CAMERA;
719 switch(v.channel)
721 case 0:
722 strcpy(v.name, "Composite");break;
723 case 1:
724 strcpy(v.name, "SVideo");break;
725 case 2:
726 strcpy(v.name, "Composite(VCR)");break;
727 case 3:
728 strcpy(v.name, "SVideo(VCR)");break;
730 if(copy_to_user(arg, &v, sizeof(v)))
731 return -EFAULT;
732 return 0;
734 case VIDIOCSCHAN:
736 int v;
737 if(copy_from_user(&v, arg,sizeof(v)))
738 return -EFAULT;
739 if(v<0 || v>3)
740 return -EINVAL;
741 pms_videosource(v&1);
742 pms_vcrinput(v>>1);
743 return 0;
745 case VIDIOCGTUNER:
747 struct video_tuner v;
748 if(copy_from_user(&v, arg, sizeof(v))!=0)
749 return -EFAULT;
750 if(v.tuner)
751 return -EINVAL;
752 strcpy(v.name, "Format");
753 v.rangelow=0;
754 v.rangehigh=0;
755 v.flags= VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
756 switch(standard)
758 case 0:
759 v.mode = VIDEO_MODE_AUTO;
760 break;
761 case 1:
762 v.mode = VIDEO_MODE_NTSC;
763 break;
764 case 2:
765 v.mode = VIDEO_MODE_PAL;
766 break;
767 case 3:
768 v.mode = VIDEO_MODE_SECAM;
769 break;
771 if(copy_to_user(arg,&v,sizeof(v))!=0)
772 return -EFAULT;
773 return 0;
775 case VIDIOCSTUNER:
777 struct video_tuner v;
778 if(copy_from_user(&v, arg, sizeof(v))!=0)
779 return -EFAULT;
780 if(v.tuner)
781 return -EINVAL;
782 switch(v.mode)
784 case VIDEO_MODE_AUTO:
785 pms_framerate(25);
786 pms_secamcross(0);
787 pms_format(0);
788 break;
789 case VIDEO_MODE_NTSC:
790 pms_framerate(30);
791 pms_secamcross(0);
792 pms_format(1);
793 break;
794 case VIDEO_MODE_PAL:
795 pms_framerate(25);
796 pms_secamcross(0);
797 pms_format(2);
798 break;
799 case VIDEO_MODE_SECAM:
800 pms_framerate(25);
801 pms_secamcross(1);
802 pms_format(2);
803 break;
804 default:
805 return -EINVAL;
807 return 0;
809 case VIDIOCGPICT:
811 struct video_picture p=pd->picture;
812 if(copy_to_user(arg, &p, sizeof(p)))
813 return -EFAULT;
814 return 0;
816 case VIDIOCSPICT:
818 struct video_picture p;
819 if(copy_from_user(&p, arg, sizeof(p)))
820 return -EFAULT;
821 if(!((p.palette==VIDEO_PALETTE_RGB565 && p.depth==16)
822 ||(p.palette==VIDEO_PALETTE_RGB555 && p.depth==15)))
823 return -EINVAL;
824 pd->picture=p;
827 * Now load the card.
830 pms_brightness(p.brightness>>8);
831 pms_hue(p.hue>>8);
832 pms_colour(p.colour>>8);
833 pms_contrast(p.contrast>>8);
834 return 0;
836 case VIDIOCSWIN:
838 struct video_window vw;
839 if(copy_from_user(&vw, arg,sizeof(vw)))
840 return -EFAULT;
841 if(vw.flags)
842 return -EINVAL;
843 if(vw.clipcount)
844 return -EINVAL;
845 if(vw.height<16||vw.height>480)
846 return -EINVAL;
847 if(vw.width<16||vw.width>640)
848 return -EINVAL;
849 pd->width=vw.width;
850 pd->height=vw.height;
851 pms_resolution(pd->width, pd->height);
852 /* Ok we figured out what to use from our wide choice */
853 return 0;
855 case VIDIOCGWIN:
857 struct video_window vw;
858 vw.x=0;
859 vw.y=0;
860 vw.width=pd->width;
861 vw.height=pd->height;
862 vw.chromakey=0;
863 vw.flags=0;
864 if(copy_to_user(arg, &vw, sizeof(vw)))
865 return -EFAULT;
866 return 0;
868 case VIDIOCCAPTURE:
869 return -EINVAL;
870 case VIDIOCGFBUF:
871 return -EINVAL;
872 case VIDIOCSFBUF:
873 return -EINVAL;
874 case VIDIOCKEY:
875 return 0;
876 case VIDIOCGFREQ:
877 return -EINVAL;
878 case VIDIOCSFREQ:
879 return -EINVAL;
880 case VIDIOCGAUDIO:
881 return -EINVAL;
882 case VIDIOCSAUDIO:
883 return -EINVAL;
884 default:
885 return -ENOIOCTLCMD;
887 return 0;
890 static long pms_read(struct video_device *v, char *buf, unsigned long count, int noblock)
892 struct pms_device *pd=(struct pms_device *)v;
893 int len;
895 /* FIXME: semaphore this */
896 len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count);
897 return len;
901 struct video_device pms_template=
903 "Mediavision PMS",
904 VID_TYPE_CAPTURE,
905 VID_HARDWARE_PMS,
906 pms_open,
907 pms_close,
908 pms_read,
909 pms_write,
910 NULL, /* FIXME - we can use POLL on this board with the irq */
911 pms_ioctl,
912 NULL,
913 pms_init_done,
914 NULL,
919 struct pms_device pms_device;
923 * Probe for and initialise the Mediavision PMS
926 static int init_mediavision(void)
928 int id;
929 int idec, decst;
930 int i;
932 unsigned char i2c_defs[]={
933 0x4C,0x30,0x00,0xE8,
934 0xB6,0xE2,0x00,0x00,
935 0xFF,0xFF,0x00,0x00,
936 0x00,0x00,0x78,0x98,
937 0x00,0x00,0x00,0x00,
938 0x34,0x0A,0xF4,0xCE,
939 0xE4
942 if(check_region(0x9A01,1))
944 printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n");
945 return -EBUSY;
947 if(check_region(io_port,3))
949 printk(KERN_WARNING "mediavision: I/O port %d in use.\n", io_port);
950 return -EBUSY;
952 outb(0xB8, 0x9A01); /* Unlock */
953 outb(io_port>>4, 0x9A01); /* Set IO port */
956 id=mvv_read(3);
957 decst=pms_i2c_stat(0x43);
959 if(decst!=-1)
960 idec=2;
961 else if(pms_i2c_stat(0xb9)!=-1)
962 idec=3;
963 else if(pms_i2c_stat(0x8b)!=-1)
964 idec=1;
965 else
966 idec=0;
968 printk(KERN_INFO "PMS type is %d\n", idec);
969 if(idec==0)
970 return -ENODEV;
973 * Ok we have a PMS of some sort
976 request_region(io_port,3, "Mediavision PMS");
977 request_region(0x9A01, 1, "Mediavision PMS config");
979 mvv_write(0x04, mem_base>>12); /* Set the memory area */
981 /* Ok now load the defaults */
983 for(i=0;i<0x19;i++)
985 if(i2c_defs[i]==0xFF)
986 pms_i2c_andor(0x8A, i, 0x07,0x00);
987 else
988 pms_i2c_write(0x8A, i, i2c_defs[i]);
991 pms_i2c_write(0xB8,0x00,0x12);
992 pms_i2c_write(0xB8,0x04,0x00);
993 pms_i2c_write(0xB8,0x07,0x00);
994 pms_i2c_write(0xB8,0x08,0x00);
995 pms_i2c_write(0xB8,0x09,0xFF);
996 pms_i2c_write(0xB8,0x0A,0x00);
997 pms_i2c_write(0xB8,0x0B,0x10);
998 pms_i2c_write(0xB8,0x10,0x03);
1000 mvv_write(0x01, 0x00);
1001 mvv_write(0x05, 0xA0);
1002 mvv_write(0x08, 0x25);
1003 mvv_write(0x09, 0x00);
1004 mvv_write(0x0A, 0x20|MVVMEMORYWIDTH);
1006 mvv_write(0x10, 0x02);
1007 mvv_write(0x1E, 0x0C);
1008 mvv_write(0x1F, 0x03);
1009 mvv_write(0x26, 0x06);
1011 mvv_write(0x2B, 0x00);
1012 mvv_write(0x2C, 0x20);
1013 mvv_write(0x2D, 0x00);
1014 mvv_write(0x2F, 0x70);
1015 mvv_write(0x32, 0x00);
1016 mvv_write(0x33, MVVMEMORYWIDTH);
1017 mvv_write(0x34, 0x00);
1018 mvv_write(0x35, 0x00);
1019 mvv_write(0x3A, 0x80);
1020 mvv_write(0x3B, 0x10);
1021 mvv_write(0x20, 0x00);
1022 mvv_write(0x21, 0x00);
1023 mvv_write(0x30, 0x22);
1024 return 0;
1027 static void shutdown_mediavision(void)
1029 release_region(io_port,3);
1030 release_region(0x9A01, 1);
1034 * Module stuff
1037 #ifdef MODULE
1038 int init_module(void)
1039 #else
1040 int init_pms_cards(struct video_init *v)
1041 #endif
1043 printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n");
1045 data_port = io_port +1;
1047 if(init_mediavision())
1049 printk(KERN_INFO "Board not found.\n");
1050 return -ENODEV;
1052 memcpy(&pms_device, &pms_template, sizeof(pms_template));
1053 pms_device.height=240;
1054 pms_device.width=320;
1055 pms_swsense(75);
1056 pms_resolution(320,240);
1057 return video_register_device((struct video_device *)&pms_device, VFL_TYPE_GRABBER);
1060 #ifdef MODULE
1062 MODULE_PARM(io_port,"i");
1063 MODULE_PARM(mem_base,"i");
1065 void cleanup_module(void)
1067 shutdown_mediavision();
1068 video_unregister_device((struct video_device *)&pms_device);
1071 #endif