OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [media/] [video/] [pms.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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 doesn't work for you...
15
 *
16
 *      Changes:
17
 *      08/07/2003        Daniele Bellucci <bellucda@tiscali.it>
18
 *                        - pms_capture: report back -EFAULT
19
 */
20
 
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>
34
 
35
#include <asm/uaccess.h>
36
 
37
 
38
#define MOTOROLA        1
39
#define PHILIPS2        2
40
#define PHILIPS1        3
41
#define MVVMEMORYWIDTH  0x40            /* 512 bytes */
42
 
43
struct pms_device
44
{
45
        struct video_device v;
46
        struct video_picture picture;
47
        int height;
48
        int width;
49
        struct mutex lock;
50
};
51
 
52
struct i2c_info
53
{
54
        u8 slave;
55
        u8 sub;
56
        u8 data;
57
        u8 hits;
58
};
59
 
60
static int i2c_count            = 0;
61
static struct i2c_info i2cinfo[64];
62
 
63
static int decoder              = PHILIPS2;
64
static int standard             = 0;     /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
65
 
66
/*
67
 *      I/O ports and Shared Memory
68
 */
69
 
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;
75
 
76
 
77
 
78
static inline void mvv_write(u8 index, u8 value)
79
{
80
        outw(index|(value<<8), io_port);
81
}
82
 
83
static inline u8 mvv_read(u8 index)
84
{
85
        outb(index, io_port);
86
        return inb(data_port);
87
}
88
 
89
static int pms_i2c_stat(u8 slave)
90
{
91
        int counter;
92
        int i;
93
 
94
        outb(0x28, io_port);
95
 
96
        counter=0;
97
        while((inb(data_port)&0x01)==0)
98
                if(counter++==256)
99
                        break;
100
 
101
        while((inb(data_port)&0x01)!=0)
102
                if(counter++==256)
103
                        break;
104
 
105
        outb(slave, io_port);
106
 
107
        counter=0;
108
        while((inb(data_port)&0x01)==0)
109
                if(counter++==256)
110
                        break;
111
 
112
        while((inb(data_port)&0x01)!=0)
113
                if(counter++==256)
114
                        break;
115
 
116
        for(i=0;i<12;i++)
117
        {
118
                char st=inb(data_port);
119
                if((st&2)!=0)
120
                        return -1;
121
                if((st&1)==0)
122
                        break;
123
        }
124
        outb(0x29, io_port);
125
        return inb(data_port);
126
}
127
 
128
static int pms_i2c_write(u16 slave, u16 sub, u16 data)
129
{
130
        int skip=0;
131
        int count;
132
        int i;
133
 
134
        for(i=0;i<i2c_count;i++)
135
        {
136
                if((i2cinfo[i].slave==slave) &&
137
                   (i2cinfo[i].sub == sub))
138
                {
139
                        if(i2cinfo[i].data==data)
140
                                skip=1;
141
                        i2cinfo[i].data=data;
142
                        i=i2c_count+1;
143
                }
144
        }
145
 
146
        if(i==i2c_count && i2c_count<64)
147
        {
148
                i2cinfo[i2c_count].slave=slave;
149
                i2cinfo[i2c_count].sub=sub;
150
                i2cinfo[i2c_count].data=data;
151
                i2c_count++;
152
        }
153
 
154
        if(skip)
155
                return 0;
156
 
157
        mvv_write(0x29, sub);
158
        mvv_write(0x2A, data);
159
        mvv_write(0x28, slave);
160
 
161
        outb(0x28, io_port);
162
 
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;
170
 
171
        count=inb(data_port);
172
 
173
        if(count&2)
174
                return -1;
175
        return count;
176
}
177
 
178
static int pms_i2c_read(int slave, int sub)
179
{
180
        int i=0;
181
        for(i=0;i<i2c_count;i++)
182
        {
183
                if(i2cinfo[i].slave==slave && i2cinfo[i].sub==sub)
184
                        return i2cinfo[i].data;
185
        }
186
        return 0;
187
}
188
 
189
 
190
static void pms_i2c_andor(int slave, int sub, int and, int or)
191
{
192
        u8 tmp;
193
 
194
        tmp=pms_i2c_read(slave, sub);
195
        tmp = (tmp&and)|or;
196
        pms_i2c_write(slave, sub, tmp);
197
}
198
 
199
/*
200
 *      Control functions
201
 */
202
 
203
 
204
static void pms_videosource(short source)
205
{
206
        mvv_write(0x2E, source?0x31:0x30);
207
}
208
 
209
static void pms_hue(short hue)
210
{
211
        switch(decoder)
212
        {
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;
222
        }
223
}
224
 
225
static void pms_colour(short colour)
226
{
227
        switch(decoder)
228
        {
229
                case MOTOROLA:
230
                        pms_i2c_write(0x8A, 0x00, colour);
231
                        break;
232
                case PHILIPS1:
233
                        pms_i2c_write(0x42, 0x12, colour);
234
                        break;
235
        }
236
}
237
 
238
 
239
static void pms_contrast(short contrast)
240
{
241
        switch(decoder)
242
        {
243
                case MOTOROLA:
244
                        pms_i2c_write(0x8A, 0x00, contrast);
245
                        break;
246
                case PHILIPS1:
247
                        pms_i2c_write(0x42, 0x13, contrast);
248
                        break;
249
        }
250
}
251
 
252
static void pms_brightness(short brightness)
253
{
254
        switch(decoder)
255
        {
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;
264
        }
265
}
266
 
267
 
268
static void pms_format(short format)
269
{
270
        int target;
271
        standard = format;
272
 
273
        if(decoder==PHILIPS1)
274
                target=0x42;
275
        else if(decoder==PHILIPS2)
276
                target=0x8A;
277
        else
278
                return;
279
 
280
        switch(format)
281
        {
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;
298
        }
299
}
300
 
301
#ifdef FOR_FUTURE_EXPANSION
302
 
303
/*
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.
307
 */
308
 
309
static void pms_hstart(short start)
310
{
311
        switch(decoder)
312
        {
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;
321
        }
322
}
323
 
324
/*
325
 *      Bandpass filters
326
 */
327
 
328
static void pms_bandpass(short pass)
329
{
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);
334
}
335
 
336
static void pms_antisnow(short snow)
337
{
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);
342
}
343
 
344
static void pms_sharpness(short sharp)
345
{
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);
350
}
351
 
352
static void pms_chromaagc(short agc)
353
{
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);
358
}
359
 
360
static void pms_vertnoise(short noise)
361
{
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);
366
}
367
 
368
static void pms_forcecolour(short colour)
369
{
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);
374
}
375
 
376
static void pms_antigamma(short gamma)
377
{
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);
382
}
383
 
384
static void pms_prefilter(short filter)
385
{
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);
390
}
391
 
392
static void pms_hfilter(short filter)
393
{
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);
398
}
399
 
400
static void pms_vfilter(short filter)
401
{
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);
406
}
407
 
408
static void pms_killcolour(short colour)
409
{
410
        if(decoder==PHILIPS2)
411
        {
412
                pms_i2c_andor(0x8A, 0x08, 0x07, (colour&0x1F)<<3);
413
                pms_i2c_andor(0x8A, 0x09, 0x07, (colour&0x1F)<<3);
414
        }
415
        else if(decoder==PHILIPS1)
416
        {
417
                pms_i2c_andor(0x42, 0x08, 0x07, (colour&0x1F)<<3);
418
                pms_i2c_andor(0x42, 0x09, 0x07, (colour&0x1F)<<3);
419
        }
420
}
421
 
422
static void pms_chromagain(short chroma)
423
{
424
        if(decoder==PHILIPS2)
425
        {
426
                pms_i2c_write(0x8A, 0x11, chroma);
427
        }
428
        else if(decoder==PHILIPS1)
429
        {
430
                pms_i2c_write(0x42, 0x11, chroma);
431
        }
432
}
433
 
434
 
435
static void pms_spacialcompl(short data)
436
{
437
        mvv_write(0x3B, data);
438
}
439
 
440
static void pms_spacialcomph(short data)
441
{
442
        mvv_write(0x3A, data);
443
}
444
 
445
static void pms_vstart(short start)
446
{
447
        mvv_write(0x16, start);
448
        mvv_write(0x17, (start>>8)&0x01);
449
}
450
 
451
#endif
452
 
453
static void pms_secamcross(short cross)
454
{
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);
459
}
460
 
461
 
462
static void pms_swsense(short sense)
463
{
464
        if(decoder==PHILIPS2)
465
        {
466
                pms_i2c_write(0x8A, 0x0A, sense);
467
                pms_i2c_write(0x8A, 0x0B, sense);
468
        }
469
        else if(decoder==PHILIPS1)
470
        {
471
                pms_i2c_write(0x42, 0x0A, sense);
472
                pms_i2c_write(0x42, 0x0B, sense);
473
        }
474
}
475
 
476
 
477
static void pms_framerate(short frr)
478
{
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);
485
}
486
 
487
static void pms_vert(u8 deciden, u8 decinum)
488
{
489
        mvv_write(0x1C, deciden);       /* Denominator */
490
        mvv_write(0x1D, decinum);       /* Numerator */
491
}
492
 
493
/*
494
 *      Turn 16bit ratios into best small ratio the chipset can grok
495
 */
496
 
497
static void pms_vertdeci(unsigned short decinum, unsigned short deciden)
498
{
499
        /* Knock it down by /5 once */
500
        if(decinum%5==0)
501
        {
502
                deciden/=5;
503
                decinum/=5;
504
        }
505
        /*
506
         *      3's
507
         */
508
        while(decinum%3==0 && deciden%3==0)
509
        {
510
                deciden/=3;
511
                decinum/=3;
512
        }
513
        /*
514
         *      2's
515
         */
516
        while(decinum%2==0 && deciden%2==0)
517
        {
518
                decinum/=2;
519
                deciden/=2;
520
        }
521
        /*
522
         *      Fudgyify
523
         */
524
        while(deciden>32)
525
        {
526
                deciden/=2;
527
                decinum=(decinum+1)/2;
528
        }
529
        if(deciden==32)
530
                deciden--;
531
        pms_vert(deciden,decinum);
532
}
533
 
534
static void pms_horzdeci(short decinum, short deciden)
535
{
536
        if(decinum<=512)
537
        {
538
                if(decinum%5==0)
539
                {
540
                        decinum/=5;
541
                        deciden/=5;
542
                }
543
        }
544
        else
545
        {
546
                decinum=512;
547
                deciden=640;    /* 768 would be ideal */
548
        }
549
 
550
        while(((decinum|deciden)&1)==0)
551
        {
552
                decinum>>=1;
553
                deciden>>=1;
554
        }
555
        while(deciden>32)
556
        {
557
                deciden>>=1;
558
                decinum=(decinum+1)>>1;
559
        }
560
        if(deciden==32)
561
                deciden--;
562
 
563
        mvv_write(0x24, 0x80|deciden);
564
        mvv_write(0x25, decinum);
565
}
566
 
567
static void pms_resolution(short width, short height)
568
{
569
        int fg_height;
570
 
571
        fg_height=height;
572
        if(fg_height>280)
573
                fg_height=280;
574
 
575
        mvv_write(0x18, fg_height);
576
        mvv_write(0x19, fg_height>>8);
577
 
578
        if(standard==1)
579
        {
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);
586
        }
587
        else
588
        {
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);
595
        }
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);
601
 
602
        mvv_write(0x22, width+8);
603
        mvv_write(0x23, (width+8)>> 8);
604
 
605
        if(standard==1)
606
                pms_horzdeci(width,640);
607
        else
608
                pms_horzdeci(width+8, 768);
609
 
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);
615
}
616
 
617
 
618
/*
619
 *      Set Input
620
 */
621
 
622
static void pms_vcrinput(short input)
623
{
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);
628
}
629
 
630
 
631
static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int count)
632
{
633
        int y;
634
        int dw = 2*dev->width;
635
 
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  */
640
 
641
        if (rgb555)
642
                r8 |= 0x20; /* else use untranslated rgb = 565 */
643
        mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */
644
 
645
/*      printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
646
 
647
        for (y = 0; y < dev->height; y++ )
648
        {
649
                writeb(0, mem);  /* synchronisiert neue Zeile */
650
 
651
                /*
652
                 *      This is in truth a fifo, be very careful as if you
653
                 *      forgot this odd things will occur 8)
654
                 */
655
 
656
                memcpy_fromio(tmp, mem, dw+32); /* discard 16 word   */
657
                cnt -= dev->height;
658
                while (cnt <= 0)
659
                {
660
                        /*
661
                         *      Don't copy too far
662
                         */
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;
671
                }
672
        }
673
        return len;
674
}
675
 
676
 
677
/*
678
 *      Video4linux interfacing
679
 */
680
 
681
static int pms_do_ioctl(struct inode *inode, struct file *file,
682
                        unsigned int cmd, void *arg)
683
{
684
        struct video_device *dev = video_devdata(file);
685
        struct pms_device *pd=(struct pms_device *)dev;
686
 
687
        switch(cmd)
688
        {
689
                case VIDIOCGCAP:
690
                {
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;
701
                }
702
                case VIDIOCGCHAN:
703
                {
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)
712
                        {
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;
721
                        }
722
                        return 0;
723
                }
724
                case VIDIOCSCHAN:
725
                {
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;
734
                }
735
                case VIDIOCGTUNER:
736
                {
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)
745
                        {
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;
758
                        }
759
                        return 0;
760
                }
761
                case VIDIOCSTUNER:
762
                {
763
                        struct video_tuner *v = arg;
764
                        if(v->tuner)
765
                                return -EINVAL;
766
                        mutex_lock(&pd->lock);
767
                        switch(v->mode)
768
                        {
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;
792
                        }
793
                        mutex_unlock(&pd->lock);
794
                        return 0;
795
                }
796
                case VIDIOCGPICT:
797
                {
798
                        struct video_picture *p = arg;
799
                        *p = pd->picture;
800
                        return 0;
801
                }
802
                case VIDIOCSPICT:
803
                {
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;
809
 
810
                        /*
811
                         *      Now load the card.
812
                         */
813
 
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;
821
                }
822
                case VIDIOCSWIN:
823
                {
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;
839
                }
840
                case VIDIOCGWIN:
841
                {
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;
847
                }
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;
860
        }
861
        return 0;
862
}
863
 
864
static int pms_ioctl(struct inode *inode, struct file *file,
865
                     unsigned int cmd, unsigned long arg)
866
{
867
        return video_usercopy(inode, file, cmd, arg, pms_do_ioctl);
868
}
869
 
870
static ssize_t pms_read(struct file *file, char __user *buf,
871
                    size_t count, loff_t *ppos)
872
{
873
        struct video_device *v = video_devdata(file);
874
        struct pms_device *pd=(struct pms_device *)v;
875
        int len;
876
 
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;
881
}
882
 
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,
891
};
892
 
893
static struct video_device pms_template=
894
{
895
        .owner          = THIS_MODULE,
896
        .name           = "Mediavision PMS",
897
        .type           = VID_TYPE_CAPTURE,
898
        .fops           = &pms_fops,
899
};
900
 
901
static struct pms_device pms_device;
902
 
903
 
904
/*
905
 *      Probe for and initialise the Mediavision PMS
906
 */
907
 
908
static int init_mediavision(void)
909
{
910
        int id;
911
        int idec, decst;
912
        int i;
913
 
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
922
        };
923
 
924
        mem = ioremap(mem_base, 0x800);
925
        if (!mem)
926
                return -ENOMEM;
927
 
928
        if (!request_region(0x9A01, 1, "Mediavision PMS config"))
929
        {
930
                printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n");
931
                iounmap(mem);
932
                return -EBUSY;
933
        }
934
        if (!request_region(io_port, 3, "Mediavision PMS"))
935
        {
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;
940
        }
941
        outb(0xB8, 0x9A01);             /* Unlock */
942
        outb(io_port>>4, 0x9A01);       /* Set IO port */
943
 
944
 
945
        id=mvv_read(3);
946
        decst=pms_i2c_stat(0x43);
947
 
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;
956
 
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;
963
        }
964
 
965
        /*
966
         *      Ok we have a PMS of some sort
967
         */
968
 
969
        mvv_write(0x04, mem_base>>12);  /* Set the memory area */
970
 
971
        /* Ok now load the defaults */
972
 
973
        for(i=0;i<0x19;i++)
974
        {
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]);
979
        }
980
 
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);
989
 
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);
995
 
996
        mvv_write(0x10, 0x02);
997
        mvv_write(0x1E, 0x0C);
998
        mvv_write(0x1F, 0x03);
999
        mvv_write(0x26, 0x06);
1000
 
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;
1015
}
1016
 
1017
/*
1018
 *      Initialization and module stuff
1019
 */
1020
 
1021
static int __init init_pms_cards(void)
1022
{
1023
        printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n");
1024
 
1025
        data_port = io_port +1;
1026
 
1027
        if(init_mediavision())
1028
        {
1029
                printk(KERN_INFO "Board not found.\n");
1030
                return -ENODEV;
1031
        }
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);
1039
}
1040
 
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");
1045
 
1046
 
1047
static void __exit shutdown_mediavision(void)
1048
{
1049
        release_region(io_port,3);
1050
        release_region(0x9A01, 1);
1051
}
1052
 
1053
static void __exit cleanup_pms_module(void)
1054
{
1055
        shutdown_mediavision();
1056
        video_unregister_device((struct video_device *)&pms_device);
1057
        iounmap(mem);
1058
}
1059
 
1060
module_init(init_pms_cards);
1061
module_exit(cleanup_pms_module);
1062
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.