~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/media/video/pms.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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.
 13  *      His driver works so send any reports to alan@redhat.com unless the
 14  *      userspace driver also doesnt work for you...
 15  */
 16 
 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 <linux/init.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>
 31 
 32 
 33 #define MOTOROLA        1
 34 #define PHILIPS2        2
 35 #define PHILIPS1        3
 36 #define MVVMEMORYWIDTH  0x40            /* 512 bytes */
 37 
 38 struct pms_device
 39 {
 40         struct video_device v;
 41         struct video_picture picture;
 42         int height;
 43         int width;
 44 };
 45 
 46 struct i2c_info
 47 {
 48         u8 slave;
 49         u8 sub;
 50         u8 data;
 51         u8 hits;
 52 };
 53 
 54 static int i2c_count            = 0;
 55 static struct i2c_info i2cinfo[64];
 56 
 57 static int decoder              = PHILIPS2;
 58 static int standard             = 0;    /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
 59 
 60 /*
 61  *      I/O ports and Shared Memory
 62  */
 63  
 64 static int io_port              =       0x250;
 65 static int data_port            =       0x251;
 66 static int mem_base             =       0xC8000;
 67 
 68         
 69 
 70 extern __inline__ void mvv_write(u8 index, u8 value)
 71 {
 72         outw(index|(value<<8), io_port);
 73 }
 74 
 75 extern __inline__ u8 mvv_read(u8 index)
 76 {
 77         outb(index, io_port);
 78         return inb(data_port);
 79 }
 80 
 81 static int pms_i2c_stat(u8 slave)
 82 {
 83         int counter;
 84         int i;
 85         
 86         outb(0x28, io_port);
 87         
 88         counter=0;
 89         while((inb(data_port)&0x01)==0)
 90                 if(counter++==256)
 91                         break;
 92 
 93         while((inb(data_port)&0x01)!=0)
 94                 if(counter++==256)
 95                         break;
 96                         
 97         outb(slave, io_port);
 98         
 99         counter=0;
100         while((inb(data_port)&0x01)==0)
101                 if(counter++==256)
102                         break;
103 
104         while((inb(data_port)&0x01)!=0)
105                 if(counter++==256)
106                         break;
107                         
108         for(i=0;i<12;i++)
109         {
110                 char st=inb(data_port);
111                 if((st&2)!=0)
112                         return -1;
113                 if((st&1)==0)
114                         break;
115         }
116         outb(0x29, io_port);
117         return inb(data_port);          
118 }
119 
120 static int pms_i2c_write(u16 slave, u16 sub, u16 data)
121 {
122         int skip=0;
123         int count;
124         int i;
125         
126         for(i=0;i<i2c_count;i++)
127         {
128                 if((i2cinfo[i].slave==slave) &&
129                    (i2cinfo[i].sub == sub))
130                 {
131                         if(i2cinfo[i].data==data)
132                                 skip=1;
133                         i2cinfo[i].data=data;
134                         i=i2c_count+1;
135                 }
136         }
137         
138         if(i==i2c_count && i2c_count<64)
139         {
140                 i2cinfo[i2c_count].slave=slave;
141                 i2cinfo[i2c_count].sub=sub;
142                 i2cinfo[i2c_count].data=data;
143                 i2c_count++;
144         }
145         
146         if(skip)
147                 return 0;
148                 
149         mvv_write(0x29, sub);
150         mvv_write(0x2A, data);
151         mvv_write(0x28, slave);
152         
153         outb(0x28, io_port);
154         
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;
162                         
163         count=inb(data_port);
164         
165         if(count&2)
166                 return -1;
167         return count;
168 }
169 
170 static int pms_i2c_read(int slave, int sub)
171 {
172         int i=0;
173         for(i=0;i<i2c_count;i++)
174         {
175                 if(i2cinfo[i].slave==slave && i2cinfo[i].sub==sub)
176                         return i2cinfo[i].data;
177         }
178         return 0;
179 }
180 
181 
182 static void pms_i2c_andor(int slave, int sub, int and, int or)
183 {
184         u8 tmp; 
185         
186         tmp=pms_i2c_read(slave, sub);
187         tmp = (tmp&and)|or;
188         pms_i2c_write(slave, sub, tmp);
189 }
190 
191 /*
192  *      Control functions
193  */
194  
195 
196 static void pms_videosource(short source)
197 {
198         mvv_write(0x2E, source?0x31:0x30);
199 }
200 
201 static void pms_hue(short hue)
202 {
203         switch(decoder)
204         {
205                 case MOTOROLA:
206                         pms_i2c_write(0x8A, 0x00, hue);
207                         break;
208                 case PHILIPS2:
209                         pms_i2c_write(0x8A, 0x07, hue);
210                         break;
211                 case PHILIPS1:
212                         pms_i2c_write(0x42, 0x07, hue);
213                         break;
214         }
215 }
216 
217 static void pms_colour(short colour)
218 {
219         switch(decoder)
220         {
221                 case MOTOROLA:
222                         pms_i2c_write(0x8A, 0x00, colour);
223                         break;
224                 case PHILIPS1:
225                         pms_i2c_write(0x42, 0x12, colour);
226                         break;
227         }
228 }
229  
230  
231 static void pms_contrast(short contrast)
232 {
233         switch(decoder)
234         {
235                 case MOTOROLA:
236                         pms_i2c_write(0x8A, 0x00, contrast);
237                         break;
238                 case PHILIPS1:
239                         pms_i2c_write(0x42, 0x13, contrast);
240                         break;
241         }
242 }
243 
244 static void pms_brightness(short brightness)
245 {
246         switch(decoder)
247         {
248                 case MOTOROLA:
249                         pms_i2c_write(0x8A, 0x00, brightness);
250                         pms_i2c_write(0x8A, 0x00, brightness);
251                         pms_i2c_write(0x8A, 0x00, brightness);
252                         break;
253                 case PHILIPS1:
254                         pms_i2c_write(0x42, 0x19, brightness);
255                         break;
256         }
257 }
258 
259 
260 static void pms_format(short format)
261 {
262         int target;
263         standard = format;
264         
265         if(decoder==PHILIPS1)
266                 target=0x42;
267         else if(decoder==PHILIPS2)
268                 target=0x8A;
269         else
270                 return;
271                                 
272         switch(format)
273         {
274                 case 0: /* Auto */
275                         pms_i2c_andor(target, 0x0D, 0xFE,0x00);
276                         pms_i2c_andor(target, 0x0F, 0x3F,0x80);
277                         break;
278                 case 1: /* NTSC */
279                         pms_i2c_andor(target, 0x0D, 0xFE, 0x00);
280                         pms_i2c_andor(target, 0x0F, 0x3F, 0x40);
281                         break;
282                 case 2: /* PAL */
283                         pms_i2c_andor(target, 0x0D, 0xFE, 0x00);
284                         pms_i2c_andor(target, 0x0F, 0x3F, 0x00);
285                         break;
286                 case 3: /* SECAM */
287                         pms_i2c_andor(target, 0x0D, 0xFE, 0x01);
288                         pms_i2c_andor(target, 0x0F, 0x3F, 0x00);
289                         break;
290         }
291 }
292 
293 #ifdef FOR_FUTURE_EXPANSION
294 
295 /*
296  *      These features of the PMS card are not currently exposes. They
297  *      could become a private v4l ioctl for PMSCONFIG or somesuch if 
298  *      people need it. We also don't yet use the PMS interrupt.
299  */
300 
301 static void pms_hstart(short start)
302 {
303         switch(decoder)
304         {
305                 case PHILIPS1:
306                         pms_i2c_write(0x8A, 0x05, start);
307                         pms_i2c_write(0x8A, 0x18, start);
308                         break;
309                 case PHILIPS2:
310                         pms_i2c_write(0x42, 0x05, start);
311                         pms_i2c_write(0x42, 0x18, start);
312                         break;
313         }
314 }
315 
316 /*
317  *      Bandpass filters
318  */
319  
320 static void pms_bandpass(short pass)
321 {
322         if(decoder==PHILIPS2)
323                 pms_i2c_andor(0x8A, 0x06, 0xCF, (pass&0x03)<<4);
324         else if(decoder==PHILIPS1)
325                 pms_i2c_andor(0x42, 0x06, 0xCF, (pass&0x03)<<4);
326 }
327 
328 static void pms_antisnow(short snow)
329 {
330         if(decoder==PHILIPS2)
331                 pms_i2c_andor(0x8A, 0x06, 0xF3, (snow&0x03)<<2);
332         else if(decoder==PHILIPS1)
333                 pms_i2c_andor(0x42, 0x06, 0xF3, (snow&0x03)<<2);
334 }
335 
336 static void pms_sharpness(short sharp)
337 {
338         if(decoder==PHILIPS2)
339                 pms_i2c_andor(0x8A, 0x06, 0xFC, sharp&0x03);
340         else if(decoder==PHILIPS1)
341                 pms_i2c_andor(0x42, 0x06, 0xFC, sharp&0x03);
342 }
343 
344 static void pms_chromaagc(short agc)
345 {
346         if(decoder==PHILIPS2)
347                 pms_i2c_andor(0x8A, 0x0C, 0x9F, (agc&0x03)<<5);
348         else if(decoder==PHILIPS1)
349                 pms_i2c_andor(0x42, 0x0C, 0x9F, (agc&0x03)<<5);
350 }
351 
352 static void pms_vertnoise(short noise)
353 {
354         if(decoder==PHILIPS2)
355                 pms_i2c_andor(0x8A, 0x10, 0xFC, noise&3);
356         else if(decoder==PHILIPS1)
357                 pms_i2c_andor(0x42, 0x10, 0xFC, noise&3);
358 }
359 
360 static void pms_forcecolour(short colour)
361 {
362         if(decoder==PHILIPS2)
363                 pms_i2c_andor(0x8A, 0x0C, 0x7F, (colour&1)<<7);
364         else if(decoder==PHILIPS1)
365                 pms_i2c_andor(0x42, 0x0C, 0x7, (colour&1)<<7);
366 }
367 
368 static void pms_antigamma(short gamma)
369 {
370         if(decoder==PHILIPS2)
371                 pms_i2c_andor(0xB8, 0x00, 0x7F, (gamma&1)<<7);
372         else if(decoder==PHILIPS1)
373                 pms_i2c_andor(0x42, 0x20, 0x7, (gamma&1)<<7);
374 }
375 
376 static void pms_prefilter(short filter)
377 {
378         if(decoder==PHILIPS2)
379                 pms_i2c_andor(0x8A, 0x06, 0xBF, (filter&1)<<6);
380         else if(decoder==PHILIPS1)
381                 pms_i2c_andor(0x42, 0x06, 0xBF, (filter&1)<<6);
382 }
383 
384 static void pms_hfilter(short filter)
385 {
386         if(decoder==PHILIPS2)
387                 pms_i2c_andor(0xB8, 0x04, 0x1F, (filter&7)<<5);
388         else if(decoder==PHILIPS1)
389                 pms_i2c_andor(0x42, 0x24, 0x1F, (filter&7)<<5);
390 }
391 
392 static void pms_vfilter(short filter)
393 {
394         if(decoder==PHILIPS2)
395                 pms_i2c_andor(0xB8, 0x08, 0x9F, (filter&3)<<5);
396         else if(decoder==PHILIPS1)
397                 pms_i2c_andor(0x42, 0x28, 0x9F, (filter&3)<<5);
398 }
399 
400 static void pms_killcolour(short colour)
401 {
402         if(decoder==PHILIPS2)
403         {
404                 pms_i2c_andor(0x8A, 0x08, 0x07, (colour&0x1F)<<3);
405                 pms_i2c_andor(0x8A, 0x09, 0x07, (colour&0x1F)<<3);
406         }
407         else if(decoder==PHILIPS1)
408         {
409                 pms_i2c_andor(0x42, 0x08, 0x07, (colour&0x1F)<<3);
410                 pms_i2c_andor(0x42, 0x09, 0x07, (colour&0x1F)<<3);
411         }
412 }
413 
414 static void pms_chromagain(short chroma)
415 {
416         if(decoder==PHILIPS2)
417         {
418                 pms_i2c_write(0x8A, 0x11, chroma);
419         }
420         else if(decoder==PHILIPS1)
421         {
422                 pms_i2c_write(0x42, 0x11, chroma);
423         }
424 }
425 
426 
427 static void pms_spacialcompl(short data)
428 {
429         mvv_write(0x3B, data);
430 }
431 
432 static void pms_spacialcomph(short data)
433 {
434         mvv_write(0x3A, data);
435 }
436 
437 static void pms_vstart(short start)
438 {
439         mvv_write(0x16, start);
440         mvv_write(0x17, (start>>8)&0x01);
441 }
442 
443 #endif
444 
445 static void pms_secamcross(short cross)
446 {
447         if(decoder==PHILIPS2)
448                 pms_i2c_andor(0x8A, 0x0F, 0xDF, (cross&1)<<5);
449         else if(decoder==PHILIPS1)
450                 pms_i2c_andor(0x42, 0x0F, 0xDF, (cross&1)<<5);
451 }
452 
453 
454 static void pms_swsense(short sense)
455 {
456         if(decoder==PHILIPS2)
457         {
458                 pms_i2c_write(0x8A, 0x0A, sense);
459                 pms_i2c_write(0x8A, 0x0B, sense);
460         }
461         else if(decoder==PHILIPS1)
462         {
463                 pms_i2c_write(0x42, 0x0A, sense);
464                 pms_i2c_write(0x42, 0x0B, sense);
465         }
466 }
467 
468 
469 static void pms_framerate(short frr)
470 {
471         int fps=(standard==1)?30:25;
472         if(frr==0)
473                 return;
474         fps=fps/frr;
475         mvv_write(0x14,0x80|fps);
476         mvv_write(0x15,1);
477 }
478 
479 static void pms_vert(u8 deciden, u8 decinum)
480 {
481         mvv_write(0x1C, deciden);       /* Denominator */
482         mvv_write(0x1D, decinum);       /* Numerator */
483 }
484 
485 /*
486  *      Turn 16bit ratios into best small ratio the chipset can grok
487  */
488  
489 static void pms_vertdeci(unsigned short decinum, unsigned short deciden)
490 {
491         /* Knock it down by /5 once */
492         if(decinum%5==0)
493         {
494                 deciden/=5;
495                 decinum/=5;
496         }
497         /*
498          *      3's
499          */
500         while(decinum%3==0 && deciden%3==0)
501         {
502                 deciden/=3;
503                 decinum/=3;
504         }
505         /*
506          *      2's
507          */
508         while(decinum%2==0 && deciden%2==0)
509         {
510                 decinum/=2;
511                 deciden/=2;
512         }
513         /*
514          *      Fudgyify
515          */
516         while(deciden>32)
517         {
518                 deciden/=2;
519                 decinum=(decinum+1)/2;
520         }
521         if(deciden==32)
522                 deciden--;
523         pms_vert(deciden,decinum);
524 }
525 
526 static void pms_horzdeci(short decinum, short deciden)
527 {
528         if(decinum<=512)
529         {
530                 if(decinum%5==0)
531                 {
532                         decinum/=5;
533                         deciden/=5;
534                 }
535         }
536         else
537         {
538                 decinum=512;
539                 deciden=640;    /* 768 would be ideal */
540         }
541         
542         while(((decinum|deciden)&1)==0)
543         {
544                 decinum>>=1;
545                 deciden>>=1;
546         }
547         while(deciden>32)
548         {
549                 deciden>>=1;
550                 decinum=(decinum+1)>>1;
551         }
552         if(deciden==32)
553                 deciden--;
554                 
555         mvv_write(0x24, 0x80|deciden);
556         mvv_write(0x25, decinum);
557 }
558 
559 static void pms_resolution(short width, short height)
560 {
561         int fg_height;
562         
563         fg_height=height;
564         if(fg_height>280)
565                 fg_height=280;
566                 
567         mvv_write(0x18, fg_height);
568         mvv_write(0x19, fg_height>>8);
569         
570         if(standard==1)
571         {
572                 mvv_write(0x1A, 0xFC);
573                 mvv_write(0x1B, 0x00);
574                 if(height>fg_height)
575                         pms_vertdeci(240,240);
576                 else
577                         pms_vertdeci(fg_height,240);
578         }
579         else
580         {
581                 mvv_write(0x1A, 0x1A);
582                 mvv_write(0x1B, 0x01);
583                 if(fg_height>256)
584                         pms_vertdeci(270,270);
585                 else
586                         pms_vertdeci(fg_height, 270);
587         }
588         mvv_write(0x12,0);
589         mvv_write(0x13, MVVMEMORYWIDTH);
590         mvv_write(0x42, 0x00);
591         mvv_write(0x43, 0x00);
592         mvv_write(0x44, MVVMEMORYWIDTH);
593         
594         mvv_write(0x22, width+8);
595         mvv_write(0x23, (width+8)>> 8);
596 
597         if(standard==1)
598                 pms_horzdeci(width,640);
599         else
600                 pms_horzdeci(width+8, 768);
601 
602         mvv_write(0x30, mvv_read(0x30)&0xFE);
603         mvv_write(0x08, mvv_read(0x08)|0x01);
604         mvv_write(0x01, mvv_read(0x01)&0xFD);
605         mvv_write(0x32, 0x00);
606         mvv_write(0x33, MVVMEMORYWIDTH);
607 }
608 
609 
610 /*
611  *      Set Input
612  */
613  
614 static void pms_vcrinput(short input)
615 {
616         if(decoder==PHILIPS2)
617                 pms_i2c_andor(0x8A,0x0D,0x7F,(input&1)<<7);
618         else if(decoder==PHILIPS1)
619                 pms_i2c_andor(0x42,0x0D,0x7F,(input&1)<<7);
620 }
621 
622 
623 static int pms_capture(struct pms_device *dev, char *buf, int rgb555, int count)
624 {
625         int y;
626         int dw = 2*dev->width;
627         u32 src = mem_base;
628 
629         char tmp[dw+32]; /* using a temp buffer is faster than direct  */
630         int cnt = 0;
631         int len=0;
632         unsigned char r8 = 0x5;  /* value for reg8  */
633 
634         if (rgb555)
635                 r8 |= 0x20; /* else use untranslated rgb = 565 */
636         mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */
637 
638 /*      printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
639   
640         for (y = 0; y < dev->height; y++ ) 
641         {
642                 isa_writeb(0, src);  /* synchronisiert neue Zeile */
643                 
644                 /*
645                  *      This is in truth a fifo, be very careful as if you
646                  *      forgot this odd things will occur 8)
647                  */
648                  
649                 isa_memcpy_fromio(tmp, src, dw+32); /* discard 16 word   */
650                 cnt -= dev->height;
651                 while (cnt <= 0) 
652                 { 
653                         /*
654                          *      Don't copy too far
655                          */
656                         int dt=dw;
657                         if(dt+len>count)
658                                 dt=count-len;
659                         cnt += dev->height;
660                         copy_to_user(buf, tmp+32, dt);
661                         buf += dt;    
662                         len += dt;
663                 }
664         }
665         return len;
666 }
667 
668 
669 /*
670  *      Video4linux interfacing
671  */
672 
673 static int pms_open(struct video_device *dev, int flags)
674 {
675         MOD_INC_USE_COUNT;
676         return 0;
677 }
678 
679 static void pms_close(struct video_device *dev)
680 {
681         MOD_DEC_USE_COUNT;
682 }
683 
684 static long pms_write(struct video_device *v, const char *buf, unsigned long count, int noblock)
685 {
686         return -EINVAL;
687 }
688 
689 static int pms_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
690 {
691         struct pms_device *pd=(struct pms_device *)dev;
692         
693         switch(cmd)
694         {
695                 case VIDIOCGCAP:
696                 {
697                         struct video_capability b;
698                         strcpy(b.name, "Mediavision PMS");
699                         b.type = VID_TYPE_CAPTURE|VID_TYPE_SCALES;
700                         b.channels = 4;
701                         b.audios = 0;
702                         b.maxwidth = 640;
703                         b.maxheight = 480;
704                         b.minwidth = 16;
705                         b.minheight = 16;
706                         if(copy_to_user(arg, &b,sizeof(b)))
707                                 return -EFAULT;
708                         return 0;
709                 }
710                 case VIDIOCGCHAN:
711                 {
712                         struct video_channel v;
713                         if(copy_from_user(&v, arg, sizeof(v)))
714                                 return -EFAULT;
715                         if(v.channel<0 || v.channel>3)
716                                 return -EINVAL;
717                         v.flags=0;
718                         v.tuners=1;
719                         /* Good question.. its composite or SVHS so.. */
720                         v.type = VIDEO_TYPE_CAMERA;
721                         switch(v.channel)
722                         {
723                                 case 0:
724                                         strcpy(v.name, "Composite");break;
725                                 case 1:
726                                         strcpy(v.name, "SVideo");break;
727                                 case 2:
728                                         strcpy(v.name, "Composite(VCR)");break;
729                                 case 3:
730                                         strcpy(v.name, "SVideo(VCR)");break;
731                         }
732                         if(copy_to_user(arg, &v, sizeof(v)))
733                                 return -EFAULT;
734                         return 0;
735                 }
736                 case VIDIOCSCHAN:
737                 {
738                         int v;
739                         if(copy_from_user(&v, arg,sizeof(v)))
740                                 return -EFAULT;
741                         if(v<0 || v>3)
742                                 return -EINVAL;
743                         pms_videosource(v&1);
744                         pms_vcrinput(v>>1);
745                         return 0;
746                 }
747                 case VIDIOCGTUNER:
748                 {
749                         struct video_tuner v;
750                         if(copy_from_user(&v, arg, sizeof(v))!=0)
751                                 return -EFAULT;
752                         if(v.tuner)
753                                 return -EINVAL;
754                         strcpy(v.name, "Format");
755                         v.rangelow=0;
756                         v.rangehigh=0;
757                         v.flags= VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
758                         switch(standard)
759                         {
760                                 case 0:
761                                         v.mode = VIDEO_MODE_AUTO;
762                                         break;
763                                 case 1:
764                                         v.mode = VIDEO_MODE_NTSC;
765                                         break;
766                                 case 2:
767                                         v.mode = VIDEO_MODE_PAL;
768                                         break;
769                                 case 3:
770                                         v.mode = VIDEO_MODE_SECAM;
771                                         break;
772                         }
773                         if(copy_to_user(arg,&v,sizeof(v))!=0)
774                                 return -EFAULT;
775                         return 0;
776                 }
777                 case VIDIOCSTUNER:
778                 {
779                         struct video_tuner v;
780                         if(copy_from_user(&v, arg, sizeof(v))!=0)
781                                 return -EFAULT;
782                         if(v.tuner)
783                                 return -EINVAL;
784                         switch(v.mode)
785                         {
786                                 case VIDEO_MODE_AUTO:
787                                         pms_framerate(25);
788                                         pms_secamcross(0);
789                                         pms_format(0);
790                                         break;
791                                 case VIDEO_MODE_NTSC:
792                                         pms_framerate(30);
793                                         pms_secamcross(0);
794                                         pms_format(1);
795                                         break;
796                                 case VIDEO_MODE_PAL:
797                                         pms_framerate(25);
798                                         pms_secamcross(0);
799                                         pms_format(2);
800                                         break;
801                                 case VIDEO_MODE_SECAM:
802                                         pms_framerate(25);
803                                         pms_secamcross(1);
804                                         pms_format(2);
805                                         break;
806                                 default:
807                                         return -EINVAL;
808                         }
809                         return 0;
810                 }
811                 case VIDIOCGPICT:
812                 {
813                         struct video_picture p=pd->picture;
814                         if(copy_to_user(arg, &p, sizeof(p)))
815                                 return -EFAULT;
816                         return 0;
817                 }
818                 case VIDIOCSPICT:
819                 {
820                         struct video_picture p;
821                         if(copy_from_user(&p, arg, sizeof(p)))
822                                 return -EFAULT;
823                         if(!((p.palette==VIDEO_PALETTE_RGB565 && p.depth==16)
824                             ||(p.palette==VIDEO_PALETTE_RGB555 && p.depth==15)))
825                                 return -EINVAL;
826                         pd->picture=p;
827                         
828                         /*
829                          *      Now load the card.
830                          */
831 
832                         pms_brightness(p.brightness>>8);
833                         pms_hue(p.hue>>8);
834                         pms_colour(p.colour>>8);
835                         pms_contrast(p.contrast>>8);    
836                         return 0;
837                 }
838                 case VIDIOCSWIN:
839                 {
840                         struct video_window vw;
841                         if(copy_from_user(&vw, arg,sizeof(vw)))
842                                 return -EFAULT;
843                         if(vw.flags)
844                                 return -EINVAL;
845                         if(vw.clipcount)
846                                 return -EINVAL;
847                         if(vw.height<16||vw.height>480)
848                                 return -EINVAL;
849                         if(vw.width<16||vw.width>640)
850                                 return -EINVAL;
851                         pd->width=vw.width;
852                         pd->height=vw.height;
853                         pms_resolution(pd->width, pd->height);
854                         /* Ok we figured out what to use from our wide choice */
855                         return 0;
856                 }
857                 case VIDIOCGWIN:
858                 {
859                         struct video_window vw;
860                         vw.x=0;
861                         vw.y=0;
862                         vw.width=pd->width;
863                         vw.height=pd->height;
864                         vw.chromakey=0;
865                         vw.flags=0;
866                         if(copy_to_user(arg, &vw, sizeof(vw)))
867                                 return -EFAULT;
868                         return 0;
869                 }
870                 case VIDIOCCAPTURE:
871                         return -EINVAL;
872                 case VIDIOCGFBUF:
873                         return -EINVAL;
874                 case VIDIOCSFBUF:
875                         return -EINVAL;
876                 case VIDIOCKEY:
877                         return 0;
878                 case VIDIOCGFREQ:
879                         return -EINVAL;
880                 case VIDIOCSFREQ:
881                         return -EINVAL;
882                 case VIDIOCGAUDIO:
883                         return -EINVAL;
884                 case VIDIOCSAUDIO:
885                         return -EINVAL;
886                 default:
887                         return -ENOIOCTLCMD;
888         }
889         return 0;
890 }
891 
892 static long pms_read(struct video_device *v, char *buf, unsigned long count,  int noblock)
893 {
894         struct pms_device *pd=(struct pms_device *)v;
895         int len;
896         
897         /* FIXME: semaphore this */
898         len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count);
899         return len;
900 }
901 
902  
903 struct video_device pms_template=
904 {
905         name:           "Mediavision PMS",
906         type:           VID_TYPE_CAPTURE,
907         hardware:       VID_HARDWARE_PMS,
908         open:           pms_open,
909         close:          pms_close,
910         read:           pms_read,
911         write:          pms_write,
912         ioctl:          pms_ioctl,
913 };
914 
915 struct pms_device pms_device;
916 
917 
918 /*
919  *      Probe for and initialise the Mediavision PMS
920  */
921  
922 static int init_mediavision(void)
923 {
924         int id;
925         int idec, decst;
926         int i;
927                 
928         unsigned char i2c_defs[]={
929                 0x4C,0x30,0x00,0xE8,
930                 0xB6,0xE2,0x00,0x00,
931                 0xFF,0xFF,0x00,0x00,
932                 0x00,0x00,0x78,0x98,
933                 0x00,0x00,0x00,0x00,
934                 0x34,0x0A,0xF4,0xCE,
935                 0xE4
936         };
937         
938         if(check_region(0x9A01,1))
939         {
940                 printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n");
941                 return -EBUSY;
942         }
943         if(check_region(io_port,3))
944         {
945                 printk(KERN_WARNING "mediavision: I/O port %d in use.\n", io_port);
946                 return -EBUSY;
947         }
948         outb(0xB8, 0x9A01);             /* Unlock */
949         outb(io_port>>4, 0x9A01);       /* Set IO port */
950         
951         
952         id=mvv_read(3);
953         decst=pms_i2c_stat(0x43);
954         
955         if(decst!=-1)
956                 idec=2;
957         else if(pms_i2c_stat(0xb9)!=-1)
958                 idec=3;
959         else if(pms_i2c_stat(0x8b)!=-1)
960                 idec=1;
961         else 
962                 idec=0;
963 
964         printk(KERN_INFO "PMS type is %d\n", idec);             
965         if(idec==0)
966                 return -ENODEV; 
967 
968         /*
969          *      Ok we have a PMS of some sort
970          */
971          
972         request_region(io_port,3, "Mediavision PMS");
973         request_region(0x9A01, 1, "Mediavision PMS config");
974         
975         mvv_write(0x04, mem_base>>12);  /* Set the memory area */
976         
977         /* Ok now load the defaults */
978         
979         for(i=0;i<0x19;i++)
980         {
981                 if(i2c_defs[i]==0xFF)
982                         pms_i2c_andor(0x8A, i, 0x07,0x00);
983                 else
984                         pms_i2c_write(0x8A, i, i2c_defs[i]);
985         }
986         
987         pms_i2c_write(0xB8,0x00,0x12);
988         pms_i2c_write(0xB8,0x04,0x00);
989         pms_i2c_write(0xB8,0x07,0x00);
990         pms_i2c_write(0xB8,0x08,0x00);
991         pms_i2c_write(0xB8,0x09,0xFF);
992         pms_i2c_write(0xB8,0x0A,0x00);
993         pms_i2c_write(0xB8,0x0B,0x10);
994         pms_i2c_write(0xB8,0x10,0x03);
995         
996         mvv_write(0x01, 0x00);
997         mvv_write(0x05, 0xA0);
998         mvv_write(0x08, 0x25);
999         mvv_write(0x09, 0x00);
1000         mvv_write(0x0A, 0x20|MVVMEMORYWIDTH);   
1001         
1002         mvv_write(0x10, 0x02);
1003         mvv_write(0x1E, 0x0C);
1004         mvv_write(0x1F, 0x03);
1005         mvv_write(0x26, 0x06);
1006         
1007         mvv_write(0x2B, 0x00);
1008         mvv_write(0x2C, 0x20);
1009         mvv_write(0x2D, 0x00);
1010         mvv_write(0x2F, 0x70);
1011         mvv_write(0x32, 0x00);
1012         mvv_write(0x33, MVVMEMORYWIDTH);
1013         mvv_write(0x34, 0x00);
1014         mvv_write(0x35, 0x00);
1015         mvv_write(0x3A, 0x80);
1016         mvv_write(0x3B, 0x10);
1017         mvv_write(0x20, 0x00);
1018         mvv_write(0x21, 0x00);
1019         mvv_write(0x30, 0x22);
1020         return 0;
1021 }
1022 
1023 /*
1024  *      Initialization and module stuff
1025  */
1026  
1027 static int __init init_pms_cards(void)
1028 {
1029         printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n");
1030         
1031         data_port = io_port +1;
1032         
1033         if(init_mediavision())
1034         {
1035                 printk(KERN_INFO "Board not found.\n");
1036                 return -ENODEV;
1037         }
1038         memcpy(&pms_device, &pms_template, sizeof(pms_template));
1039         pms_device.height=240;
1040         pms_device.width=320;
1041         pms_swsense(75);
1042         pms_resolution(320,240);
1043         return video_register_device((struct video_device *)&pms_device, VFL_TYPE_GRABBER);
1044 }
1045 
1046 MODULE_PARM(io_port,"i");
1047 MODULE_PARM(mem_base,"i");
1048 
1049 static void __exit shutdown_mediavision(void)
1050 {
1051         release_region(io_port,3);
1052         release_region(0x9A01, 1);
1053 }
1054 
1055 static void __exit cleanup_pms_module(void)
1056 {
1057         shutdown_mediavision();
1058         video_unregister_device((struct video_device *)&pms_device);
1059 }
1060 
1061 module_init(init_pms_cards);
1062 module_exit(cleanup_pms_module);
1063 
1064 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.