Import 2.1.81
[davej-history.git] / drivers / char / pms.c
blob2ef2f5ccb07eedce5d6f7259065a42ae2bee38d0
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@cymru.net unless the
14 * userspace driver also doesnt work for you...
17 #include <linux/module.h>
18 #include <linux/config.h>
19 #include <linux/delay.h>
20 #include <linux/errno.h>
21 #include <linux/fs.h>
22 #include <linux/kernel.h>
23 #include <linux/malloc.h>
24 #include <linux/mm.h>
25 #include <linux/ioport.h>
26 #include <asm/io.h>
27 #include <linux/sched.h>
28 #include <linux/videodev.h>
29 #include <linux/version.h>
30 #include <asm/uaccess.h>
33 #define MOTOROLA 1
34 #define PHILIPS2 2
35 #define PHILIPS1 3
36 #define MVVMEMORYWIDTH 0x40 /* 512 bytes */
38 struct pms_device
40 struct video_device v;
41 struct video_picture picture;
42 int height;
43 int width;
46 struct i2c_info
48 u8 slave;
49 u8 sub;
50 u8 data;
51 u8 hits;
54 static int i2c_count = 0;
55 static struct i2c_info i2cinfo[64];
57 static int decoder = PHILIPS2;
58 static int standard = 0; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
61 * I/O ports and Shared Memory
64 static int io_port = 0x250;
65 static int data_port = 0x251;
66 static int mem_base = 0xC8000;
70 extern __inline__ void mvv_write(u8 index, u8 value)
72 outw(index|(value<<8), io_port);
75 extern __inline__ u8 mvv_read(u8 index)
77 outb(index, io_port);
78 return inb(data_port);
81 extern int i2c_stat(u8 slave)
83 int counter;
84 int i;
86 outb(0x28, io_port);
88 counter=0;
89 while((inb(data_port)&0x01)==0)
90 if(counter++==256)
91 break;
93 while((inb(data_port)&0x01)!=0)
94 if(counter++==256)
95 break;
97 outb(slave, io_port);
99 counter=0;
100 while((inb(data_port)&0x01)==0)
101 if(counter++==256)
102 break;
104 while((inb(data_port)&0x01)!=0)
105 if(counter++==256)
106 break;
108 for(i=0;i<12;i++)
110 char st=inb(data_port);
111 if((st&2)!=0)
112 return -1;
113 if((st&1)==0)
114 break;
116 outb(0x29, io_port);
117 return inb(data_port);
120 int i2c_write(u16 slave, u16 sub, u16 data)
122 int skip=0;
123 int count;
124 int i;
126 for(i=0;i<i2c_count;i++)
128 if((i2cinfo[i].slave==slave) &&
129 (i2cinfo[i].sub == sub))
131 if(i2cinfo[i].data==data)
132 skip=1;
133 i2cinfo[i].data=data;
134 i=i2c_count+1;
138 if(i==i2c_count && i2c_count<64)
140 i2cinfo[i2c_count].slave=slave;
141 i2cinfo[i2c_count].sub=sub;
142 i2cinfo[i2c_count].data=data;
143 i2c_count++;
146 if(skip)
147 return 0;
149 mvv_write(0x29, sub);
150 mvv_write(0x2A, data);
151 mvv_write(0x28, slave);
153 outb(0x28, io_port);
155 count=0;
156 while((inb(data_port)&1)==0)
157 if(count>255)
158 break;
159 while((inb(data_port)&1)!=0)
160 if(count>255)
161 break;
163 count=inb(data_port);
165 if(count&2)
166 return -1;
167 return count;
170 int i2c_read(int slave, int sub)
172 int i=0;
173 for(i=0;i<i2c_count;i++)
175 if(i2cinfo[i].slave==slave && i2cinfo[i].sub==sub)
176 return i2cinfo[i].data;
178 return 0;
182 void i2c_andor(int slave, int sub, int and, int or)
184 u8 tmp;
186 tmp=i2c_read(slave, sub);
187 tmp = (tmp&and)|or;
188 i2c_write(slave, sub, tmp);
192 * Control functions
196 static void pms_videosource(short source)
198 mvv_write(0x2E, source?0x31:0x30);
201 static void pms_hue(short hue)
203 switch(decoder)
205 case MOTOROLA:
206 i2c_write(0x8A, 0x00, hue);
207 break;
208 case PHILIPS2:
209 i2c_write(0x8A, 0x07, hue);
210 break;
211 case PHILIPS1:
212 i2c_write(0x42, 0x07, hue);
213 break;
217 static void pms_colour(short colour)
219 switch(decoder)
221 case MOTOROLA:
222 i2c_write(0x8A, 0x00, colour);
223 break;
224 case PHILIPS1:
225 i2c_write(0x42, 012, colour);
226 break;
231 static void pms_contrast(short contrast)
233 switch(decoder)
235 case MOTOROLA:
236 i2c_write(0x8A, 0x00, contrast);
237 break;
238 case PHILIPS1:
239 i2c_write(0x42, 0x13, contrast);
240 break;
244 static void pms_brightness(short brightness)
246 switch(decoder)
248 case MOTOROLA:
249 i2c_write(0x8A, 0x00, brightness);
250 i2c_write(0x8A, 0x00, brightness);
251 i2c_write(0x8A, 0x00, brightness);
252 break;
253 case PHILIPS1:
254 i2c_write(0x42, 0x19, brightness);
255 break;
259 static void pms_hstart(short start)
261 switch(decoder)
263 case PHILIPS1:
264 i2c_write(0x8A, 0x05, start);
265 i2c_write(0x8A, 0x18, start);
266 break;
267 case PHILIPS2:
268 i2c_write(0x42, 0x05, start);
269 i2c_write(0x42, 0x18, start);
270 break;
274 static void pms_format(short format)
276 int target;
277 standard = format;
279 if(decoder==PHILIPS1)
280 target=0x42;
281 else if(decoder==PHILIPS2)
282 target=0x8A;
283 else
284 return;
286 switch(format)
288 case 0: /* Auto */
289 i2c_andor(target, 0x0D, 0xFE,0x00);
290 i2c_andor(target, 0x0F, 0x3F,0x80);
291 break;
292 case 1: /* NTSC */
293 i2c_andor(target, 0x0D, 0xFE, 0x00);
294 i2c_andor(target, 0x0F, 0x3F, 0x40);
295 break;
296 case 2: /* PAL */
297 i2c_andor(target, 0x0D, 0xFE, 0x00);
298 i2c_andor(target, 0x0F, 0x3F, 0x00);
299 break;
300 case 3: /* SECAM */
301 i2c_andor(target, 0x0D, 0xFE, 0x01);
302 i2c_andor(target, 0x0F, 0x3F, 0x00);
303 break;
308 * Bandpass filters
311 static void pms_bandpass(short pass)
313 if(decoder==PHILIPS2)
314 i2c_andor(0x8A, 0x06, 0xCF, (pass&0x03)<<4);
315 else if(decoder==PHILIPS1)
316 i2c_andor(0x42, 0x06, 0xCF, (pass&0x03)<<4);
319 static void pms_antisnow(short snow)
321 if(decoder==PHILIPS2)
322 i2c_andor(0x8A, 0x06, 0xF3, (snow&0x03)<<2);
323 else if(decoder==PHILIPS1)
324 i2c_andor(0x42, 0x06, 0xF3, (snow&0x03)<<2);
327 static void pms_sharpness(short sharp)
329 if(decoder==PHILIPS2)
330 i2c_andor(0x8A, 0x06, 0xFC, sharp&0x03);
331 else if(decoder==PHILIPS1)
332 i2c_andor(0x42, 0x06, 0xFC, sharp&0x03);
335 static void pms_chromaagc(short agc)
337 if(decoder==PHILIPS2)
338 i2c_andor(0x8A, 0x0C, 0x9F, (agc&0x03)<<5);
339 else if(decoder==PHILIPS1)
340 i2c_andor(0x42, 0x0C, 0x9F, (agc&0x03)<<5);
343 static void pms_vertnoise(short noise)
345 if(decoder==PHILIPS2)
346 i2c_andor(0x8A, 0x10, 0xFC, noise&3);
347 else if(decoder==PHILIPS1)
348 i2c_andor(0x42, 0x10, 0xFC, noise&3);
351 static void pms_secamcross(short cross)
353 if(decoder==PHILIPS2)
354 i2c_andor(0x8A, 0x0F, 0xDF, (cross&1)<<5);
355 else if(decoder==PHILIPS1)
356 i2c_andor(0x42, 0x0F, 0xDF, (cross&1)<<5);
359 static void pms_forcecolour(short colour)
361 if(decoder==PHILIPS2)
362 i2c_andor(0x8A, 0x0C, 0x7F, (colour&1)<<7);
363 else if(decoder==PHILIPS1)
364 i2c_andor(0x42, 0x0C, 0x7, (colour&1)<<7);
367 static void pms_antigamma(short gamma)
369 if(decoder==PHILIPS2)
370 i2c_andor(0xB8, 0x00, 0x7F, (gamma&1)<<7);
371 else if(decoder==PHILIPS1)
372 i2c_andor(0x42, 0x20, 0x7, (gamma&1)<<7);
375 static void pms_prefilter(short filter)
377 if(decoder==PHILIPS2)
378 i2c_andor(0x8A, 0x06, 0xBF, (filter&1)<<6);
379 else if(decoder==PHILIPS1)
380 i2c_andor(0x42, 0x06, 0xBF, (filter&1)<<6);
383 static void pms_hfilter(short filter)
385 if(decoder==PHILIPS2)
386 i2c_andor(0xB8, 0x04, 0x1F, (filter&7)<<5);
387 else if(decoder==PHILIPS1)
388 i2c_andor(0x42, 0x24, 0x1F, (filter&7)<<5);
391 static void pms_vfilter(short filter)
393 if(decoder==PHILIPS2)
394 i2c_andor(0xB8, 0x08, 0x9F, (filter&3)<<5);
395 else if(decoder==PHILIPS1)
396 i2c_andor(0x42, 0x28, 0x9F, (filter&3)<<5);
399 static void pms_killcolour(short colour)
401 if(decoder==PHILIPS2)
403 i2c_andor(0x8A, 0x08, 0x07, (colour&0x1F)<<3);
404 i2c_andor(0x8A, 0x09, 0x07, (colour&0x1F)<<3);
406 else if(decoder==PHILIPS1)
408 i2c_andor(0x42, 0x08, 0x07, (colour&0x1F)<<3);
409 i2c_andor(0x42, 0x09, 0x07, (colour&0x1F)<<3);
413 static void pms_swsense(short sense)
415 if(decoder==PHILIPS2)
417 i2c_write(0x8A, 0x0A, sense);
418 i2c_write(0x8A, 0x0B, sense);
420 else if(decoder==PHILIPS1)
422 i2c_write(0x42, 0x0A, sense);
423 i2c_write(0x42, 0x0B, sense);
427 static void pms_chromagain(short chroma)
429 if(decoder==PHILIPS2)
431 i2c_write(0x8A, 0x11, chroma);
433 else if(decoder==PHILIPS1)
435 i2c_write(0x42, 0x11, chroma);
440 static void pms_spacialcompl(short data)
442 mvv_write(0x3B, data);
445 static void pms_spacialcomph(short data)
447 mvv_write(0x3A, data);
450 static void pms_framerate(short frr)
452 int fps=(standard==1)?30:25;
453 if(frr==0)
454 return;
455 fps=fps/frr;
456 mvv_write(0x14,0x80|fps);
457 mvv_write(0x15,1);
460 static void pms_vert(u8 deciden, u8 decinum)
462 mvv_write(0x1C, deciden); /* Denominator */
463 mvv_write(0x1D, decinum); /* Numerator */
467 * Turn 16bit ratios into best small ratio the chipset can grok
470 static void pms_vertdeci(unsigned short decinum, unsigned short deciden)
472 /* Knock it down by /5 once */
473 if(decinum%5==0)
475 deciden/=5;
476 decinum/=5;
479 * 3's
481 while(decinum%3==0 && deciden%3==0)
483 deciden/=3;
484 decinum/=3;
487 * 2's
489 while(decinum%2==0 && deciden%2==0)
491 decinum/=2;
492 deciden/=2;
495 * Fudgyify
497 while(deciden>32)
499 deciden/=2;
500 decinum=(decinum+1)/2;
502 if(deciden==32)
503 deciden--;
504 pms_vert(deciden,decinum);
507 static void pms_horzdeci(short decinum, short deciden)
509 if(decinum<=512)
511 if(decinum%5==0)
513 decinum/=5;
514 deciden/=5;
517 else
519 decinum=512;
520 deciden=640; /* 768 would be ideal */
523 while(((decinum|deciden)&1)==0)
525 decinum>>=1;
526 deciden>>=1;
528 while(deciden>32)
530 deciden>>=1;
531 decinum=(decinum+1)>>1;
533 if(deciden==32)
534 deciden--;
536 mvv_write(0x24, 0x80|deciden);
537 mvv_write(0x25, decinum);
540 static void pms_resolution(short width, short height)
542 int fg_height;
544 fg_height=height;
545 if(fg_height>280)
546 fg_height=280;
548 mvv_write(0x18, fg_height);
549 mvv_write(0x19, fg_height>>8);
551 if(standard==1)
553 mvv_write(0x1A, 0xFC);
554 mvv_write(0x1B, 0x00);
555 if(height>fg_height)
556 pms_vertdeci(240,240);
557 else
558 pms_vertdeci(fg_height,240);
560 else
562 mvv_write(0x1A, 0x1A);
563 mvv_write(0x1B, 0x01);
564 if(fg_height>256)
565 pms_vertdeci(270,270);
566 else
567 pms_vertdeci(fg_height, 270);
569 mvv_write(0x12,0);
570 mvv_write(0x13, MVVMEMORYWIDTH);
571 mvv_write(0x42, 0x00);
572 mvv_write(0x43, 0x00);
573 mvv_write(0x44, MVVMEMORYWIDTH);
575 mvv_write(0x22, width+8);
576 mvv_write(0x23, (width+8)>> 8);
578 if(standard==1)
579 pms_horzdeci(width,640);
580 else
581 pms_horzdeci(width+8, 768);
583 mvv_write(0x30, mvv_read(0x30)&0xFE);
584 mvv_write(0x08, mvv_read(0x08)|0x01);
585 mvv_write(0x01, mvv_read(0x01)&0xFD);
586 mvv_write(0x32, 0x00);
587 mvv_write(0x33, MVVMEMORYWIDTH);
590 static void pms_vstart(short start)
592 mvv_write(0x16, start);
593 mvv_write(0x17, (start>>8)&0x01);
597 * Set Input
600 static void pms_vcrinput(short input)
602 if(decoder==PHILIPS2)
603 i2c_andor(0x8A,0x0D,0x7F,(input&1)<<7);
604 else if(decoder==PHILIPS1)
605 i2c_andor(0x42,0x0D,0x7F,(input&1)<<7);
609 static int pms_capture(struct pms_device *dev, char *buf, int rgb555, int count)
611 int y;
612 int dw = 2*dev->width;
613 char *src = (char *)bus_to_virt(mem_base);
615 char tmp[dw+32]; /* using a temp buffer is faster than direct */
616 int cnt = 0;
617 int len=0;
618 unsigned char r8 = 0x5; /* value for reg8 */
620 if (rgb555)
621 r8 |= 0x20; /* else use untranslated rgb = 565 */
622 mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */
624 /* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
626 for (y = 0; y < dev->height; y++ )
628 *src = 0; /* synchronisiert neue Zeile */
629 memcpy(tmp, src, dw+32); /* discard 16 word */
630 cnt -= dev->height;
631 while (cnt <= 0)
634 * Dont copy too far
636 int dt=dw;
637 if(dt+len>count)
638 dt=count-len;
639 cnt += dev->height;
640 copy_to_user(buf, tmp+32, dt);
641 buf += dt;
642 len += dt;
645 return len;
650 * Video4linux interfacing
653 static int pms_open(struct video_device *dev, int flags)
655 MOD_INC_USE_COUNT;
656 return 0;
659 static void pms_close(struct video_device *dev)
661 MOD_DEC_USE_COUNT;
664 static int pms_init_done(struct video_device *dev)
666 return 0;
669 static long pms_write(struct video_device *v, const char *buf, unsigned long count, int noblock)
671 return -EINVAL;
674 static int pms_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
676 struct pms_device *pd=(struct pms_device *)dev;
678 switch(cmd)
680 case VIDIOCGCAP:
682 struct video_capability b;
683 strcpy(b.name, "Mediavision PMS");
684 b.type = VID_TYPE_CAPTURE|VID_TYPE_SCALES;
685 b.channels = 4;
686 b.audios = 0;
687 b.maxwidth = 640;
688 b.maxheight = 480;
689 b.minwidth = 16;
690 b.minheight = 16;
691 if(copy_to_user(arg, &b,sizeof(b)))
692 return -EFAULT;
693 return 0;
695 case VIDIOCGCHAN:
697 struct video_channel v;
698 if(copy_from_user(&v, arg, sizeof(v)))
699 return -EFAULT;
700 if(v.channel<0 || v.channel>3)
701 return -EINVAL;
702 v.flags=0;
703 v.tuners=1;
704 /* Good question.. its composite or SVHS so.. */
705 v.type = VIDEO_TYPE_CAMERA;
706 switch(v.channel)
708 case 0:
709 strcpy(v.name, "Composite");break;
710 case 1:
711 strcpy(v.name, "SVideo");break;
712 case 2:
713 strcpy(v.name, "Composite(VCR)");break;
714 case 3:
715 strcpy(v.name, "SVideo(VCR)");break;
717 if(copy_to_user(arg, &v, sizeof(v)))
718 return -EFAULT;
719 return 0;
721 case VIDIOCSCHAN:
723 int v;
724 if(copy_from_user(&v, arg,sizeof(v)))
725 return -EFAULT;
726 if(v<0 || v>3)
727 return -EINVAL;
728 pms_videosource(v&1);
729 pms_vcrinput(v>>1);
730 return 0;
732 case VIDIOCGTUNER:
734 struct video_tuner v;
735 if(copy_from_user(&v, arg, sizeof(v))!=0)
736 return -EFAULT;
737 if(v.tuner)
738 return -EINVAL;
739 strcpy(v.name, "Format");
740 v.rangelow=0;
741 v.rangehigh=0;
742 v.flags= VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
743 switch(standard)
745 case 0:
746 v.mode = VIDEO_MODE_AUTO;
747 break;
748 case 1:
749 v.mode = VIDEO_MODE_NTSC;
750 break;
751 case 2:
752 v.mode = VIDEO_MODE_PAL;
753 break;
754 case 3:
755 v.mode = VIDEO_MODE_SECAM;
756 break;
758 if(copy_to_user(arg,&v,sizeof(v))!=0)
759 return -EFAULT;
760 return 0;
762 case VIDIOCSTUNER:
764 struct video_tuner v;
765 if(copy_from_user(&v, arg, sizeof(v))!=0)
766 return -EFAULT;
767 if(v.tuner)
768 return -EINVAL;
769 switch(v.mode)
771 case VIDEO_MODE_AUTO:
772 pms_framerate(25);
773 pms_secamcross(0);
774 pms_format(0);
775 break;
776 case VIDEO_MODE_NTSC:
777 pms_framerate(30);
778 pms_secamcross(0);
779 pms_format(1);
780 break;
781 case VIDEO_MODE_PAL:
782 pms_framerate(25);
783 pms_secamcross(0);
784 pms_format(2);
785 break;
786 case VIDEO_MODE_SECAM:
787 pms_framerate(25);
788 pms_secamcross(1);
789 pms_format(2);
790 break;
791 default:
792 return -EINVAL;
794 return 0;
796 case VIDIOCGPICT:
798 struct video_picture p=pd->picture;
799 if(copy_to_user(arg, &p, sizeof(p)))
800 return -EFAULT;
801 return 0;
803 case VIDIOCSPICT:
805 struct video_picture p;
806 if(copy_from_user(&p, arg, sizeof(p)))
807 return -EFAULT;
808 if(!((p.palette==VIDEO_PALETTE_RGB565 && p.depth==16)
809 ||(p.palette==VIDEO_PALETTE_RGB555 && p.depth==15)))
810 return -EINVAL;
811 pd->picture=p;
814 * Now load the card.
817 pms_brightness(p.brightness>>8);
818 pms_hue(p.hue>>8);
819 pms_colour(p.colour>>8);
820 pms_contrast(p.contrast>>8);
821 return 0;
823 case VIDIOCSWIN:
825 struct video_window vw;
826 if(copy_from_user(&vw, arg,sizeof(vw)))
827 return -EFAULT;
828 if(vw.flags)
829 return -EINVAL;
830 if(vw.clipcount)
831 return -EINVAL;
832 if(vw.height<16||vw.height>480)
833 return -EINVAL;
834 if(vw.width<16||vw.width>640)
835 return -EINVAL;
836 pd->width=vw.width;
837 pd->height=vw.height;
838 pms_resolution(pd->width, pd->height);
839 /* Ok we figured out what to use from our wide choice */
840 return 0;
842 case VIDIOCGWIN:
844 struct video_window vw;
845 vw.x=0;
846 vw.y=0;
847 vw.width=pd->width;
848 vw.height=pd->height;
849 vw.chromakey=0;
850 vw.flags=0;
851 if(copy_to_user(arg, &vw, sizeof(vw)))
852 return -EFAULT;
853 return 0;
855 case VIDIOCCAPTURE:
856 return -EINVAL;
857 case VIDIOCGFBUF:
858 return -EINVAL;
859 case VIDIOCSFBUF:
860 return -EINVAL;
861 case VIDIOCKEY:
862 return 0;
863 case VIDIOCGFREQ:
864 return -EINVAL;
865 case VIDIOCSFREQ:
866 return -EINVAL;
867 case VIDIOCGAUDIO:
868 return -EINVAL;
869 case VIDIOCSAUDIO:
870 return -EINVAL;
871 default:
872 return -ENOIOCTLCMD;
874 return 0;
877 static long pms_read(struct video_device *v, char *buf, unsigned long count, int noblock)
879 struct pms_device *pd=(struct pms_device *)v;
880 int len;
882 /* FIXME: semaphore this */
883 len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count);
884 return len;
888 struct video_device pms_template=
890 "Mediavision PMS",
891 VID_TYPE_CAPTURE,
892 VID_HARDWARE_PMS,
893 pms_open,
894 pms_close,
895 pms_read,
896 pms_write,
897 pms_ioctl,
898 NULL,
899 pms_init_done,
900 NULL,
905 struct pms_device pms_device;
909 * Probe for and initialise the Mediavision PMS
912 static int init_mediavision(void)
914 int id;
915 int idec, decst;
916 int i;
918 unsigned char i2c_defs[]={
919 0x4C,0x30,0x00,0xE8,
920 0xB6,0xE2,0x00,0x00,
921 0xFF,0xFF,0x00,0x00,
922 0x00,0x00,0x78,0x98,
923 0x00,0x00,0x00,0x00,
924 0x34,0x0A,0xF4,0xCE,
925 0xE4
928 if(check_region(0x9A01,1))
930 printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n");
931 return -EBUSY;
933 if(check_region(io_port,3))
935 printk(KERN_WARNING "mediavision: I/O port %d in use.\n", io_port);
936 return -EBUSY;
938 outb(0xB8, 0x9A01); /* Unlock */
939 outb(io_port>>4, 0x9A01); /* Set IO port */
942 id=mvv_read(3);
943 decst=i2c_stat(0x43);
945 if(decst!=-1)
946 idec=2;
947 else if(i2c_stat(0xb9)!=-1)
948 idec=3;
949 else if(i2c_stat(0x8b)!=-1)
950 idec=1;
951 else
952 idec=0;
954 printk(KERN_INFO "PMS type is %d\n", idec);
955 if(idec==0)
956 return -ENODEV;
959 * Ok we have a PMS of some sort
962 request_region(io_port,3, "Mediavision PMS");
963 request_region(0x9A01, 1, "Mediavision PMS config");
965 mvv_write(0x04, mem_base>>12); /* Set the memory area */
967 /* Ok now load the defaults */
969 for(i=0;i<0x19;i++)
971 if(i2c_defs[i]==0xFF)
972 i2c_andor(0x8A, i, 0x07,0x00);
973 else
974 i2c_write(0x8A, i, i2c_defs[i]);
977 i2c_write(0xB8,0x00,0x12);
978 i2c_write(0xB8,0x04,0x00);
979 i2c_write(0xB8,0x07,0x00);
980 i2c_write(0xB8,0x08,0x00);
981 i2c_write(0xB8,0x09,0xFF);
982 i2c_write(0xB8,0x0A,0x00);
983 i2c_write(0xB8,0x0B,0x10);
984 i2c_write(0xB8,0x10,0x03);
986 mvv_write(0x01, 0x00);
987 mvv_write(0x05, 0xA0);
988 mvv_write(0x08, 0x25);
989 mvv_write(0x09, 0x00);
990 mvv_write(0x0A, 0x20|MVVMEMORYWIDTH);
992 mvv_write(0x10, 0x02);
993 mvv_write(0x1E, 0x0C);
994 mvv_write(0x1F, 0x03);
995 mvv_write(0x26, 0x06);
997 mvv_write(0x2B, 0x00);
998 mvv_write(0x2C, 0x20);
999 mvv_write(0x2D, 0x00);
1000 mvv_write(0x2F, 0x70);
1001 mvv_write(0x32, 0x00);
1002 mvv_write(0x33, MVVMEMORYWIDTH);
1003 mvv_write(0x34, 0x00);
1004 mvv_write(0x35, 0x00);
1005 mvv_write(0x3A, 0x80);
1006 mvv_write(0x3B, 0x10);
1007 mvv_write(0x20, 0x00);
1008 mvv_write(0x21, 0x00);
1009 mvv_write(0x30, 0x22);
1010 return 0;
1013 static void shutdown_mediavision(void)
1015 release_region(io_port,3);
1016 release_region(0x9A01, 1);
1020 * Module stuff
1023 #ifdef MODULE
1025 MODULE_PARM(io_port,"i");
1026 MODULE_PARM(mem_base,"i");
1028 int init_module(void)
1030 printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n");
1032 data_port = io_port +1;
1034 if(init_mediavision())
1036 printk(KERN_INFO "Board not found.\n");
1037 return -ENODEV;
1039 memcpy(&pms_device, &pms_template, sizeof(pms_template));
1040 pms_device.height=240;
1041 pms_device.width=320;
1042 pms_swsense(75);
1043 pms_resolution(320,240);
1044 return video_register_device((struct video_device *)&pms_device);
1047 void cleanup_module(void)
1049 shutdown_mediavision();
1050 video_unregister_device((struct video_device *)&pms_device);
1053 #endif