1 /*
2  * Matrox MGA G200/G400 YUV Video Interface module Version 0.1.0
3  * BES == Back End Scaler
4  *
5  * Copyright (C) 1999 Aaron Holtzman
6  *
7  * Module skeleton based on gutted agpgart module by
8  * Jeff Hartmann <slicer@ionet.net>
9  * YUY2 support (see config.format) added by A'rpi/ESP-team
10  * double buffering added by A'rpi/ESP-team
11  * brightness/contrast introduced by eyck
12  * multiple card support by Attila Kinali <attila@kinali.ch>
13  *
14  * This file is part of mga_vid.
15  *
16  * mga_vid is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * mga_vid is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License along
27  * with mga_vid; if not, write to the Free Software Foundation, Inc.,
28  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29  */
30 
31 //It's entirely possible this major conflicts with something else
32 //use the 'major' parameter to override the default major number (178)
33 /* mknod /dev/mga_vid c 178 0 */
34 
35 //#define CRTC2
36 
37 // Set this value, if autodetection fails! (video ram size in megabytes)
38 // #define MGA_MEMORY_SIZE 16
39 
40 //#define MGA_ALLOW_IRQ
41 
42 #define MGA_VSYNC_POS 2
43 
44 #include <linux/config.h>
45 #include <linux/version.h>
46 #include <linux/module.h>
47 #include <linux/types.h>
48 #include <linux/kernel.h>
49 #include <linux/sched.h>
50 #include <linux/mm.h>
51 #include <linux/string.h>
52 #include <linux/errno.h>
53 
54 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
55 #include <linux/malloc.h>
56 #else
57 #include <linux/slab.h>
58 #endif
59 
60 #include <linux/pci.h>
61 #include <linux/ioport.h>
62 #include <linux/init.h>
63 
64 #include "mga_vid.h"
65 
66 #ifdef CONFIG_MTRR
67 #include <asm/mtrr.h>
68 #endif
69 
70 #ifdef CONFIG_DEVFS_FS
71 #include <linux/devfs_fs_kernel.h>
72 #endif
73 
74 #include <asm/uaccess.h>
75 #include <asm/system.h>
76 #include <asm/io.h>
77 
78 #define TRUE 1
79 #define FALSE 0
80 
81 #define DEFAULT_MGA_VID_MAJOR 178
82 
83 #ifndef PCI_DEVICE_ID_MATROX_G200_PCI
84 #define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520
85 #endif
86 
87 #ifndef PCI_DEVICE_ID_MATROX_G200_AGP
88 #define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521
89 #endif
90 
91 #ifndef PCI_DEVICE_ID_MATROX_G400
92 #define PCI_DEVICE_ID_MATROX_G400 0x0525
93 #endif
94 
95 #ifndef PCI_DEVICE_ID_MATROX_G550
96 #define PCI_DEVICE_ID_MATROX_G550 0x2527
97 #endif
98 
99 #ifndef PCI_SUBSYSTEM_ID_MATROX_G400_DH_16MB
100 #define PCI_SUBSYSTEM_ID_MATROX_G400_DH_16MB 0x2159
101 #endif
102 
103 #ifndef PCI_SUBSYSTEM_ID_MATROX_G400_16MB_SGRAM
104 #define PCI_SUBSYSTEM_ID_MATROX_G400_16MB_SGRAM 0x19d8
105 #endif
106 
107 #ifndef PCI_SUBSYSTEM_ID_MATROX_G400_16MB_SDRAM
108 #define PCI_SUBSYSTEM_ID_MATROX_G400_16MB_SDRAM 0x0328
109 #endif
110 
111 MODULE_AUTHOR("Aaron Holtzman <aholtzma@engr.uvic.ca>");
112 #ifdef MODULE_LICENSE
113 MODULE_LICENSE("GPL");
114 #endif
115 
116 #define PARAM_BRIGHTNESS "brightness="
117 #define PARAM_CONTRAST "contrast="
118 #define PARAM_BLACKIE "blackie="
119 
120 // set PARAM_BUFF_SIZE to just below 4k because some kernel versions
121 // store additional information in the memory page which leads to
122 // the allocation of an additional page if exactly 4k is used
123 #define PARAM_BUFF_SIZE 4000
124 
125 #ifndef min
126 #define min(x,y) (((x)<(y))?(x):(y))
127 #endif
128 
129 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
130 #include <linux/ctype.h>
131 
simple_strtoul(const char * cp,char ** endp,unsigned int base)132 static unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
133 {
134     unsigned long result = 0,value;
135 
136     if (!base) {
137         base = 10;
138         if (*cp == '0') {
139             base = 8;
140             cp++;
141             if ((*cp == 'x') && isxdigit(cp[1])) {
142                 cp++;
143                 base = 16;
144             }
145         }
146     }
147     while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
148                                                                ? toupper(*cp) : *cp)-'A'+10) < base) {
149         result = result*base + value;
150         cp++;
151     }
152     if (endp)
153         *endp = (char *)cp;
154     return result;
155 }
156 
simple_strtol(const char * cp,char ** endp,unsigned int base)157 static long simple_strtol(const char *cp,char **endp,unsigned int base)
158 {
159     if(*cp=='-')
160         return -simple_strtoul(cp+1,endp,base);
161     return simple_strtoul(cp,endp,base);
162 }
163 #endif
164 
165 
166 typedef struct bes_registers_s
167 {
168     //BES Control
169     uint32_t besctl;
170     //BES Global control
171     uint32_t besglobctl;
172     //Luma control (brightness and contrast)
173     uint32_t beslumactl;
174     //Line pitch
175     uint32_t bespitch;
176 
177     //Buffer A-1 Chroma 3 plane org
178     uint32_t besa1c3org;
179     //Buffer A-1 Chroma org
180     uint32_t besa1corg;
181     //Buffer A-1 Luma org
182     uint32_t besa1org;
183 
184     //Buffer A-2 Chroma 3 plane org
185     uint32_t besa2c3org;
186     //Buffer A-2 Chroma org
187     uint32_t besa2corg;
188     //Buffer A-2 Luma org
189     uint32_t besa2org;
190 
191     //Buffer B-1 Chroma 3 plane org
192     uint32_t besb1c3org;
193     //Buffer B-1 Chroma org
194     uint32_t besb1corg;
195     //Buffer B-1 Luma org
196     uint32_t besb1org;
197 
198     //Buffer B-2 Chroma 3 plane org
199     uint32_t besb2c3org;
200     //Buffer B-2 Chroma org
201     uint32_t besb2corg;
202     //Buffer B-2 Luma org
203     uint32_t besb2org;
204 
205     //BES Horizontal coord
206     uint32_t beshcoord;
207     //BES Horizontal inverse scaling [5.14]
208     uint32_t beshiscal;
209     //BES Horizontal source start [10.14] (for scaling)
210     uint32_t beshsrcst;
211     //BES Horizontal source ending [10.14] (for scaling)
212     uint32_t beshsrcend;
213     //BES Horizontal source last
214     uint32_t beshsrclst;
215 
216 
217     //BES Vertical coord
218     uint32_t besvcoord;
219     //BES Vertical inverse scaling [5.14]
220     uint32_t besviscal;
221     //BES Field 1 vertical source last position
222     uint32_t besv1srclst;
223     //BES Field 1 weight start
224     uint32_t besv1wght;
225     //BES Field 2 vertical source last position
226     uint32_t besv2srclst;
227     //BES Field 2 weight start
228     uint32_t besv2wght;
229 
230 
231     //configurable stuff
232     int blackie;
233 
234 } bes_registers_t;
235 
236 #ifdef CRTC2
237 typedef struct crtc2_registers_s
238 {
239     uint32_t c2ctl;
240     uint32_t c2datactl;
241     uint32_t c2misc;
242     uint32_t c2hparam;
243     uint32_t c2hsync;
244     uint32_t c2offset;
245     uint32_t c2pl2startadd0;
246     uint32_t c2pl2startadd1;
247     uint32_t c2pl3startadd0;
248     uint32_t c2pl3startadd1;
249     uint32_t c2preload;
250     uint32_t c2spicstartadd0;
251     uint32_t c2spicstartadd1;
252     uint32_t c2startadd0;
253     uint32_t c2startadd1;
254     uint32_t c2subpiclut;
255     uint32_t c2vcount;
256     uint32_t c2vparam;
257     uint32_t c2vsync;
258 } crtc2_registers_t;
259 #endif
260 
261 
262 
263 
264 
265 //All register offsets are converted to word aligned offsets (32 bit)
266 //because we want all our register accesses to be 32 bits
267 #define VCOUNT      0x1e20
268 
269 #define PALWTADD      0x3c00 // Index register for X_DATAREG port
270 #define X_DATAREG     0x3c0a
271 
272 #define XMULCTRL      0x19
273 #define BPP_8         0x00
274 #define BPP_15        0x01
275 #define BPP_16        0x02
276 #define BPP_24        0x03
277 #define BPP_32_DIR    0x04
278 #define BPP_32_PAL    0x07
279 
280 #define XCOLMSK       0x40
281 #define X_COLKEY      0x42
282 #define XKEYOPMODE    0x51
283 #define XCOLMSK0RED   0x52
284 #define XCOLMSK0GREEN 0x53
285 #define XCOLMSK0BLUE  0x54
286 #define XCOLKEY0RED   0x55
287 #define XCOLKEY0GREEN 0x56
288 #define XCOLKEY0BLUE  0x57
289 
290 #ifdef CRTC2
291 
292 /*CRTC2 registers*/
293 #define XMISCCTRL  0x1e
294 #define C2CTL       0x3c10
295 #define C2DATACTL   0x3c4c
296 #define C2MISC      0x3c44
297 #define C2HPARAM    0x3c14
298 #define C2HSYNC     0x3c18
299 #define C2OFFSET    0x3c40
300 #define C2PL2STARTADD0 0x3c30  // like BESA1CORG
301 #define C2PL2STARTADD1 0x3c34  // like BESA2CORG
302 #define C2PL3STARTADD0 0x3c38  // like BESA1C3ORG
303 #define C2PL3STARTADD1 0x3c3c  // like BESA2C3ORG
304 #define C2PRELOAD   0x3c24
305 #define C2SPICSTARTADD0 0x3c54
306 #define C2SPICSTARTADD1 0x3c58
307 #define C2STARTADD0 0x3c28  // like BESA1ORG
308 #define C2STARTADD1 0x3c2c  // like BESA2ORG
309 #define C2SUBPICLUT 0x3c50
310 #define C2VCOUNT    0x3c48
311 #define C2VPARAM    0x3c1c
312 #define C2VSYNC     0x3c20
313 
314 #endif
315 
316 // Backend Scaler registers
317 #define BESCTL      0x3d20
318 #define BESGLOBCTL  0x3dc0
319 #define BESLUMACTL  0x3d40
320 #define BESPITCH    0x3d24
321 
322 #define BESA1C3ORG  0x3d60
323 #define BESA1CORG   0x3d10
324 #define BESA1ORG    0x3d00
325 
326 #define BESA2C3ORG  0x3d64
327 #define BESA2CORG   0x3d14
328 #define BESA2ORG    0x3d04
329 
330 #define BESB1C3ORG  0x3d68
331 #define BESB1CORG   0x3d18
332 #define BESB1ORG    0x3d08
333 
334 #define BESB2C3ORG  0x3d6C
335 #define BESB2CORG   0x3d1C
336 #define BESB2ORG    0x3d0C
337 
338 #define BESHCOORD   0x3d28
339 #define BESHISCAL   0x3d30
340 #define BESHSRCEND  0x3d3C
341 #define BESHSRCLST  0x3d50
342 #define BESHSRCST   0x3d38
343 #define BESV1WGHT   0x3d48
344 #define BESV2WGHT   0x3d4c
345 #define BESV1SRCLST 0x3d54
346 #define BESV2SRCLST 0x3d58
347 #define BESVISCAL   0x3d34
348 #define BESVCOORD   0x3d2c
349 #define BESSTATUS   0x3dc4
350 
351 #define CRTCX       0x1fd4
352 #define CRTCD       0x1fd5
353 #define IEN         0x1e1c
354 #define ICLEAR      0x1e18
355 #define STATUS      0x1e14
356 
357 
358 // global devfs handle for /dev/mga_vid
359 #ifdef CONFIG_DEVFS_FS
360 static devfs_handle_t dev_handle = NULL;
361 #endif
362 
363 // card local config
364 typedef struct mga_card_s {
365 
366 // local devfs handle for /dev/mga_vidX
367 #ifdef CONFIG_DEVFS_FS
368     devfs_handle_t dev_handle;
369 #endif
370 
371     uint8_t *param_buff; // buffer for read()
372     uint32_t param_buff_size;
373     uint32_t param_buff_len;
374     bes_registers_t regs;
375 #ifdef CRTC2
376     crtc2_registers_t cregs;
377 #endif
378     uint32_t vid_in_use;
379     uint32_t is_g400;
380     uint32_t vid_src_ready;
381     uint32_t vid_overlay_on;
382 
383     uint8_t *mmio_base;
384     uint32_t mem_base;
385     int src_base;   // YUV buffer position in video memory
386     uint32_t ram_size;      // how much megabytes videoram we have
387     uint32_t top_reserved;  // reserved space for console font (matroxfb + fastfont)
388 
389     int brightness; // initial brightness
390     int contrast;   // initial contrast
391 
392     struct pci_dev *pci_dev;
393 
394     mga_vid_config_t config;
395     int configured; // set to 1 when the card is configured over ioctl
396 
397     int colkey_saved;
398     int colkey_on;
399     unsigned char colkey_color[4];
400     unsigned char colkey_mask[4];
401 
402     int irq; // = -1
403     int next_frame;
404 } mga_card_t;
405 
406 #define MGA_MAX_CARDS 16
407 // this is used as init value for the parameter arrays
408 // it should have exactly MGA_MAX_CARDS elements
409 #define MGA_MAX_CARDS_INIT_ARRAY {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
410 static unsigned int mga_cards_num=0;
411 static mga_card_t * mga_cards[MGA_MAX_CARDS] = MGA_MAX_CARDS_INIT_ARRAY;
412 
413 // module parameters
414 static int major = DEFAULT_MGA_VID_MAJOR;
415 static int mga_ram_size[MGA_MAX_CARDS] = MGA_MAX_CARDS_INIT_ARRAY;
416 static int mga_brightness[MGA_MAX_CARDS] = MGA_MAX_CARDS_INIT_ARRAY;
417 static int mga_contrast[MGA_MAX_CARDS] = MGA_MAX_CARDS_INIT_ARRAY;
418 static int mga_top_reserved[MGA_MAX_CARDS] = MGA_MAX_CARDS_INIT_ARRAY;
419 
420 MODULE_PARM(mga_ram_size, "1-" __MODULE_STRING(MGA_MAX_CARDS) "i");
421 MODULE_PARM(mga_top_reserved, "1-" __MODULE_STRING(MGA_MAX_CARDS) "i");
422 MODULE_PARM(mga_brightness, "1-" __MODULE_STRING(MGA_MAX_CARDS) "i");
423 MODULE_PARM(mga_contrast, "1-" __MODULE_STRING(MGA_MAX_CARDS) "i");
424 MODULE_PARM(major, "i");
425 
426 #ifdef CRTC2
crtc2_frame_sel(mga_card_t * card,int frame)427 static void crtc2_frame_sel(mga_card_t * card, int frame)
428 {
429 switch(frame) {
430 case 0:
431     card->cregs.c2pl2startadd0=card->regs.besa1corg;
432     card->cregs.c2pl3startadd0=card->regs.besa1c3org;
433     card->cregs.c2startadd0=card->regs.besa1org;
434     break;
435 case 1:
436     card->cregs.c2pl2startadd0=card->regs.besa2corg;
437     card->cregs.c2pl3startadd0=card->regs.besa2c3org;
438     card->cregs.c2startadd0=card->regs.besa2org;
439     break;
440 case 2:
441     card->cregs.c2pl2startadd0=card->regs.besb1corg;
442     card->cregs.c2pl3startadd0=card->regs.besb1c3org;
443     card->cregs.c2startadd0=card->regs.besb1org;
444     break;
445 case 3:
446     card->cregs.c2pl2startadd0=card->regs.besb2corg;
447     card->cregs.c2pl3startadd0=card->regs.besb2c3org;
448     card->cregs.c2startadd0=card->regs.besb2org;
449     break;
450 }
451     writel(card->cregs.c2startadd0, card->mmio_base + C2STARTADD0);
452     writel(card->cregs.c2pl2startadd0, card->mmio_base + C2PL2STARTADD0);
453     writel(card->cregs.c2pl3startadd0, card->mmio_base + C2PL3STARTADD0);
454 }
455 #endif
456 
mga_vid_frame_sel(mga_card_t * card,int frame)457 static void mga_vid_frame_sel(mga_card_t * card, int frame)
458 {
459     if ( card->irq != -1 ) {
460     card->next_frame=frame;
461     } else {
462 
463     //we don't need the vcount protection as we're only hitting
464     //one register (and it doesn't seem to be double buffered)
465     card->regs.besctl = (card->regs.besctl & ~0x07000000) + (frame << 25);
466     writel( card->regs.besctl, card->mmio_base + BESCTL );
467 
468 //  writel( card->regs.besglobctl + ((readl(card->mmio_base + VCOUNT)+2)<<16),
469     writel( card->regs.besglobctl + (MGA_VSYNC_POS<<16),
470             card->mmio_base + BESGLOBCTL);
471 #ifdef CRTC2
472     crtc2_frame_sel(card, frame);
473 #endif
474 
475     }
476 }
477 
478 
mga_vid_write_regs(mga_card_t * card,int restore)479 static void mga_vid_write_regs(mga_card_t * card, int restore)
480 {
481     //Make sure internal registers don't get updated until we're done
482     writel( (readl(card->mmio_base + VCOUNT)-1)<<16,
483             card->mmio_base + BESGLOBCTL);
484 
485     // color or coordinate keying
486 
487     if(restore && card->colkey_saved){
488         // restore it
489         card->colkey_saved=0;
490 
491 #ifdef MP_DEBUG
492         printk("mga_vid: Restoring colorkey (ON: %d  %02X:%02X:%02X)\n",
493                card->colkey_on,card->colkey_color[0],card->colkey_color[1],card->colkey_color[2]);
494 #endif
495 
496         // Set color key registers:
497         writeb( XKEYOPMODE, card->mmio_base + PALWTADD);
498         writeb( card->colkey_on, card->mmio_base + X_DATAREG);
499 
500         writeb( XCOLKEY0RED, card->mmio_base + PALWTADD);
501         writeb( card->colkey_color[0], card->mmio_base + X_DATAREG);
502         writeb( XCOLKEY0GREEN, card->mmio_base + PALWTADD);
503         writeb( card->colkey_color[1], card->mmio_base + X_DATAREG);
504         writeb( XCOLKEY0BLUE, card->mmio_base + PALWTADD);
505         writeb( card->colkey_color[2], card->mmio_base + X_DATAREG);
506         writeb( X_COLKEY, card->mmio_base + PALWTADD);
507         writeb( card->colkey_color[3], card->mmio_base + X_DATAREG);
508 
509         writeb( XCOLMSK0RED, card->mmio_base + PALWTADD);
510         writeb( card->colkey_mask[0], card->mmio_base + X_DATAREG);
511         writeb( XCOLMSK0GREEN, card->mmio_base + PALWTADD);
512         writeb( card->colkey_mask[1], card->mmio_base + X_DATAREG);
513         writeb( XCOLMSK0BLUE, card->mmio_base + PALWTADD);
514         writeb( card->colkey_mask[2], card->mmio_base + X_DATAREG);
515         writeb( XCOLMSK, card->mmio_base + PALWTADD);
516         writeb( card->colkey_mask[3], card->mmio_base + X_DATAREG);
517 
518     } else if(!card->colkey_saved){
519         // save it
520         card->colkey_saved=1;
521         // Get color key registers:
522         writeb( XKEYOPMODE, card->mmio_base + PALWTADD);
523         card->colkey_on=(unsigned char)readb(card->mmio_base + X_DATAREG) & 1;
524 
525         writeb( XCOLKEY0RED, card->mmio_base + PALWTADD);
526         card->colkey_color[0]=(unsigned char)readb(card->mmio_base + X_DATAREG);
527         writeb( XCOLKEY0GREEN, card->mmio_base + PALWTADD);
528         card->colkey_color[1]=(unsigned char)readb(card->mmio_base + X_DATAREG);
529         writeb( XCOLKEY0BLUE, card->mmio_base + PALWTADD);
530         card->colkey_color[2]=(unsigned char)readb(card->mmio_base + X_DATAREG);
531         writeb( X_COLKEY, card->mmio_base + PALWTADD);
532         card->colkey_color[3]=(unsigned char)readb(card->mmio_base + X_DATAREG);
533 
534         writeb( XCOLMSK0RED, card->mmio_base + PALWTADD);
535         card->colkey_mask[0]=(unsigned char)readb(card->mmio_base + X_DATAREG);
536         writeb( XCOLMSK0GREEN, card->mmio_base + PALWTADD);
537         card->colkey_mask[1]=(unsigned char)readb(card->mmio_base + X_DATAREG);
538         writeb( XCOLMSK0BLUE, card->mmio_base + PALWTADD);
539         card->colkey_mask[2]=(unsigned char)readb(card->mmio_base + X_DATAREG);
540         writeb( XCOLMSK, card->mmio_base + PALWTADD);
541         card->colkey_mask[3]=(unsigned char)readb(card->mmio_base + X_DATAREG);
542 
543 #ifdef MP_DEBUG
544         printk("mga_vid: Saved colorkey (ON: %d  %02X:%02X:%02X)\n",
545                card->colkey_on, card->colkey_color[0], card->colkey_color[1], card->colkey_color[2]);
546 #endif
547 
548     }
549 
550     if(!restore){
551         writeb( XKEYOPMODE, card->mmio_base + PALWTADD);
552         writeb( card->config.colkey_on, card->mmio_base + X_DATAREG);
553         if ( card->config.colkey_on )
554         {
555             uint32_t r=0, g=0, b=0;
556 
557             writeb( XMULCTRL, card->mmio_base + PALWTADD);
558             switch (readb (card->mmio_base + X_DATAREG))
559             {
560             case BPP_8:
561                 /* Need to look up the color index, just using color 0 for now. */
562                 break;
563 
564             case BPP_15:
565                 r = card->config.colkey_red   >> 3;
566                 g = card->config.colkey_green >> 3;
567                 b = card->config.colkey_blue  >> 3;
568                 break;
569 
570             case BPP_16:
571                 r = card->config.colkey_red   >> 3;
572                 g = card->config.colkey_green >> 2;
573                 b = card->config.colkey_blue  >> 3;
574                 break;
575 
576             case BPP_24:
577             case BPP_32_DIR:
578             case BPP_32_PAL:
579                 r = card->config.colkey_red;
580                 g = card->config.colkey_green;
581                 b = card->config.colkey_blue;
582                 break;
583             }
584 
585             // Disable color keying on alpha channel
586             writeb( XCOLMSK, card->mmio_base + PALWTADD);
587             writeb( 0x00, card->mmio_base + X_DATAREG);
588             writeb( X_COLKEY, card->mmio_base + PALWTADD);
589             writeb( 0x00, card->mmio_base + X_DATAREG);
590 
591 
592             // Set up color key registers
593             writeb( XCOLKEY0RED, card->mmio_base + PALWTADD);
594             writeb( r, card->mmio_base + X_DATAREG);
595             writeb( XCOLKEY0GREEN, card->mmio_base + PALWTADD);
596             writeb( g, card->mmio_base + X_DATAREG);
597             writeb( XCOLKEY0BLUE, card->mmio_base + PALWTADD);
598             writeb( b, card->mmio_base + X_DATAREG);
599 
600             // Set up color key mask registers
601             writeb( XCOLMSK0RED, card->mmio_base + PALWTADD);
602             writeb( 0xff, card->mmio_base + X_DATAREG);
603             writeb( XCOLMSK0GREEN, card->mmio_base + PALWTADD);
604             writeb( 0xff, card->mmio_base + X_DATAREG);
605             writeb( XCOLMSK0BLUE, card->mmio_base + PALWTADD);
606             writeb( 0xff, card->mmio_base + X_DATAREG);
607         }
608     }
609 
610     // Backend Scaler
611     writel( card->regs.besctl,      card->mmio_base + BESCTL);
612     if(card->is_g400)
613         writel( card->regs.beslumactl,  card->mmio_base + BESLUMACTL);
614     writel( card->regs.bespitch,    card->mmio_base + BESPITCH);
615 
616     writel( card->regs.besa1org,    card->mmio_base + BESA1ORG);
617     writel( card->regs.besa1corg,   card->mmio_base + BESA1CORG);
618     writel( card->regs.besa2org,    card->mmio_base + BESA2ORG);
619     writel( card->regs.besa2corg,   card->mmio_base + BESA2CORG);
620     writel( card->regs.besb1org,    card->mmio_base + BESB1ORG);
621     writel( card->regs.besb1corg,   card->mmio_base + BESB1CORG);
622     writel( card->regs.besb2org,    card->mmio_base + BESB2ORG);
623     writel( card->regs.besb2corg,   card->mmio_base + BESB2CORG);
624     if(card->is_g400)
625     {
626         writel( card->regs.besa1c3org,  card->mmio_base + BESA1C3ORG);
627         writel( card->regs.besa2c3org,  card->mmio_base + BESA2C3ORG);
628         writel( card->regs.besb1c3org,  card->mmio_base + BESB1C3ORG);
629         writel( card->regs.besb2c3org,  card->mmio_base + BESB2C3ORG);
630     }
631 
632     writel( card->regs.beshcoord,   card->mmio_base + BESHCOORD);
633     writel( card->regs.beshiscal,   card->mmio_base + BESHISCAL);
634     writel( card->regs.beshsrcst,   card->mmio_base + BESHSRCST);
635     writel( card->regs.beshsrcend,  card->mmio_base + BESHSRCEND);
636     writel( card->regs.beshsrclst,  card->mmio_base + BESHSRCLST);
637 
638     writel( card->regs.besvcoord,   card->mmio_base + BESVCOORD);
639     writel( card->regs.besviscal,   card->mmio_base + BESVISCAL);
640 
641     writel( card->regs.besv1srclst, card->mmio_base + BESV1SRCLST);
642     writel( card->regs.besv1wght,   card->mmio_base + BESV1WGHT);
643     writel( card->regs.besv2srclst, card->mmio_base + BESV2SRCLST);
644     writel( card->regs.besv2wght,   card->mmio_base + BESV2WGHT);
645 
646     //update the registers somewhere between 1 and 2 frames from now.
647     writel( card->regs.besglobctl + ((readl(card->mmio_base + VCOUNT)+2)<<16),
648             card->mmio_base + BESGLOBCTL);
649 
650 #if 0
651     printk(KERN_DEBUG "mga_vid: wrote BES registers\n");
652     printk(KERN_DEBUG "mga_vid: BESCTL = 0x%08x\n",
653            readl(card->mmio_base + BESCTL));
654     printk(KERN_DEBUG "mga_vid: BESGLOBCTL = 0x%08x\n",
655            readl(card->mmio_base + BESGLOBCTL));
656     printk(KERN_DEBUG "mga_vid: BESSTATUS= 0x%08x\n",
657            readl(card->mmio_base + BESSTATUS));
658 #endif
659 #ifdef CRTC2
660 //  printk("c2ctl:0x%08x c2datactl:0x%08x\n", readl(card->mmio_base + C2CTL), readl(card->mmio_base + C2DATACTL));
661 //  printk("c2misc:0x%08x\n", readl(card->mmio_base + C2MISC));
662 //  printk("c2ctl:0x%08x c2datactl:0x%08x\n", card->cregs.c2ctl, card->cregs.c2datactl);
663 
664 //  writel(card->cregs.c2ctl,       card->mmio_base + C2CTL);
665 
666     writel(((readl(card->mmio_base + C2CTL) & ~0x03e00000) + (card->cregs.c2ctl & 0x03e00000)), card->mmio_base + C2CTL);
667     writel(((readl(card->mmio_base + C2DATACTL) & ~0x000000ff) + (card->cregs.c2datactl & 0x000000ff)), card->mmio_base + C2DATACTL);
668     // ctrc2
669     // disable CRTC2 acording to specs
670 //  writel(card->cregs.c2ctl & 0xfffffff0, card->mmio_base + C2CTL);
671  // je to treba ???
672 //  writeb((readb(card->mmio_base + XMISCCTRL) & 0x19) | 0xa2, card->mmio_base + XMISCCTRL); // MAFC - mfcsel & vdoutsel
673 //  writeb((readb(card->mmio_base + XMISCCTRL) & 0x19) | 0x92, card->mmio_base + XMISCCTRL);
674 //  writeb((readb(card->mmio_base + XMISCCTRL) & ~0xe9) + 0xa2, card->mmio_base + XMISCCTRL);
675 //  writel(card->cregs.c2datactl, card->mmio_base + C2DATACTL);
676 //  writel(card->cregs.c2hparam, card->mmio_base + C2HPARAM);
677 //  writel(card->cregs.c2hsync, card->mmio_base + C2HSYNC);
678 //  writel(card->cregs.c2vparam, card->mmio_base + C2VPARAM);
679 //  writel(card->cregs.c2vsync, card->mmio_base + C2VSYNC);
680     writel(card->cregs.c2misc, card->mmio_base + C2MISC);
681 
682 #ifdef MP_DEBUG
683     printk("c2offset = %d\n",card->cregs.c2offset);
684 #endif
685 
686     writel(card->cregs.c2offset, card->mmio_base + C2OFFSET);
687     writel(card->cregs.c2startadd0, card->mmio_base + C2STARTADD0);
688 //  writel(card->cregs.c2startadd1, card->mmio_base + C2STARTADD1);
689     writel(card->cregs.c2pl2startadd0, card->mmio_base + C2PL2STARTADD0);
690 //  writel(card->cregs.c2pl2startadd1, card->mmio_base + C2PL2STARTADD1);
691     writel(card->cregs.c2pl3startadd0, card->mmio_base + C2PL3STARTADD0);
692 //  writel(card->cregs.c2pl3startadd1, card->mmio_base + C2PL3STARTADD1);
693     writel(card->cregs.c2spicstartadd0, card->mmio_base + C2SPICSTARTADD0);
694 //  writel(card->cregs.c2spicstartadd1, card->mmio_base + C2SPICSTARTADD1);
695 //  writel(card->cregs.c2subpiclut, card->mmio_base + C2SUBPICLUT);
696 //  writel(card->cregs.c2preload, card->mmio_base + C2PRELOAD);
697     // finaly enable everything
698 //  writel(card->cregs.c2ctl,       card->mmio_base + C2CTL);
699 //  printk("c2ctl:0x%08x c2datactl:0x%08x\n",readl(card->mmio_base + C2CTL),readl(card->mmio_base + C2DATACTL));
700 //  printk("c2misc:0x%08x\n", readl(card->mmio_base + C2MISC));
701 #endif
702 }
703 
mga_vid_set_config(mga_card_t * card)704 static int mga_vid_set_config(mga_card_t * card)
705 {
706     int x, y, sw, sh, dw, dh;
707     int besleft, bestop, ifactor, ofsleft, ofstop, baseadrofs, weight, weights;
708     mga_vid_config_t *config = &card->config;
709     int frame_size = card->config.frame_size;
710 
711 #ifdef CRTC2
712 #define right_margin 0
713 #define left_margin 18
714 #define hsync_len 46
715 #define lower_margin 10
716 #define vsync_len 4
717 #define upper_margin 39
718 
719     unsigned int hdispend = (config->src_width + 31) & ~31;
720     unsigned int hsyncstart = hdispend + (right_margin & ~7);
721     unsigned int hsyncend = hsyncstart + (hsync_len & ~7);
722     unsigned int htotal = hsyncend + (left_margin & ~7);
723     unsigned int vdispend = config->src_height;
724     unsigned int vsyncstart = vdispend + lower_margin;
725     unsigned int vsyncend = vsyncstart + vsync_len;
726     unsigned int vtotal = vsyncend + upper_margin;
727 #endif
728     x  = config->x_org;
729     y  = config->y_org;
730     sw = config->src_width;
731     sh = config->src_height;
732     dw = config->dest_width;
733     dh = config->dest_height;
734 
735 #ifdef MP_DEBUG
736     printk(KERN_DEBUG "mga_vid: Setting up a %dx%d+%d+%d video window (src %dx%d) format %X\n",
737            dw, dh, x, y, sw, sh, config->format);
738 #endif
739 
740     if(sw<4 || sh<4 || dw<4 || dh<4){
741         printk(KERN_ERR "mga_vid: Invalid src/dest dimenstions\n");
742         return -1;
743     }
744 
745     //FIXME check that window is valid and inside desktop
746 
747     //Setup the BES registers for a three plane 4:2:0 video source
748 
749     card->regs.besglobctl = 0;
750 
751     switch(config->format){
752     case MGA_VID_FORMAT_YV12:
753     case MGA_VID_FORMAT_I420:
754     case MGA_VID_FORMAT_IYUV:
755         card->regs.besctl = 1           // BES enabled
756                             + (0<<6)    // even start polarity
757                             + (1<<10)   // x filtering enabled
758                             + (1<<11)   // y filtering enabled
759                             + (1<<16)   // chroma upsampling
760                             + (1<<17)   // 4:2:0 mode
761                             + (1<<18);  // dither enabled
762 #if 0
763         if(card->is_g400)
764         {
765             //zoom disabled, zoom filter disabled, 420 3 plane format, proc amp
766             //disabled, rgb mode disabled
767             card->regs.besglobctl = (1<<5);
768         }
769         else
770         {
771             //zoom disabled, zoom filter disabled, Cb samples in 0246, Cr
772             //in 1357, BES register update on besvcnt
773             card->regs.besglobctl = 0;
774         }
775 #endif
776         break;
777 
778     case MGA_VID_FORMAT_YUY2:
779         card->regs.besctl = 1           // BES enabled
780                             + (0<<6)    // even start polarity
781                             + (1<<10)   // x filtering enabled
782                             + (1<<11)   // y filtering enabled
783                             + (1<<16)   // chroma upsampling
784                             + (0<<17)   // 4:2:2 mode
785                             + (1<<18);  // dither enabled
786 
787         card->regs.besglobctl = 0;      // YUY2 format selected
788         break;
789 
790     case MGA_VID_FORMAT_UYVY:
791         card->regs.besctl = 1           // BES enabled
792                             + (0<<6)    // even start polarity
793                             + (1<<10)   // x filtering enabled
794                             + (1<<11)   // y filtering enabled
795                             + (1<<16)   // chroma upsampling
796                             + (0<<17)   // 4:2:2 mode
797                             + (1<<18);  // dither enabled
798 
799         card->regs.besglobctl = 1<<6;        // UYVY format selected
800         break;
801 
802     default:
803         printk(KERN_ERR "mga_vid: Unsupported pixel format: 0x%X\n",config->format);
804         return -1;
805 }
806 
807     // setting black&white mode
808     card->regs.besctl|=(card->regs.blackie<<20);
809 
810     //Enable contrast and brightness control
811     card->regs.besglobctl |= (1<<5) + (1<<7);
812 
813     // brightness (-128..127) && contrast (0..255)
814     card->regs.beslumactl = (card->brightness << 16) | ((card->contrast+0x80)&0xFFFF);
815 
816     //Setup destination window boundaries
817     besleft = x > 0 ? x : 0;
818     bestop = y > 0 ? y : 0;
819     card->regs.beshcoord = (besleft<<16) + (x + dw-1);
820     card->regs.besvcoord = (bestop<<16) + (y + dh-1);
821 
822     //Setup source dimensions
823     card->regs.beshsrclst  = (sw - 1) << 16;
824     card->regs.bespitch = (sw + 31) & ~31 ;
825 
826     //Setup horizontal scaling
827     ifactor = ((sw-1)<<14)/(dw-1);
828     ofsleft = besleft - x;
829 
830     card->regs.beshiscal = ifactor<<2;
831     card->regs.beshsrcst = (ofsleft*ifactor)<<2;
832     card->regs.beshsrcend = card->regs.beshsrcst + (((dw - ofsleft - 1) * ifactor) << 2);
833 
834     //Setup vertical scaling
835     ifactor = ((sh-1)<<14)/(dh-1);
836     ofstop = bestop - y;
837 
838     card->regs.besviscal = ifactor<<2;
839 
840     baseadrofs = ( (ofstop * card->regs.besviscal) >>16) * card->regs.bespitch;
841     //frame_size = ((sw + 31) & ~31) * sh + (((sw + 31) & ~31) * sh) / 2;
842     card->regs.besa1org = (uint32_t) card->src_base + baseadrofs;
843     card->regs.besa2org = (uint32_t) card->src_base + baseadrofs + 1*frame_size;
844     card->regs.besb1org = (uint32_t) card->src_base + baseadrofs + 2*frame_size;
845     card->regs.besb2org = (uint32_t) card->src_base + baseadrofs + 3*frame_size;
846 
847     if(config->format==MGA_VID_FORMAT_YV12
848        ||config->format==MGA_VID_FORMAT_IYUV
849        ||config->format==MGA_VID_FORMAT_I420
850         ){
851         // planar YUV frames:
852         if (card->is_g400)
853             baseadrofs = ( ( (ofstop * card->regs.besviscal ) / 4 ) >> 16 ) * card->regs.bespitch;
854         else
855             baseadrofs = ( ( ( ofstop * card->regs.besviscal ) / 2 ) >> 16 ) * card->regs.bespitch;
856 
857         if(config->format==MGA_VID_FORMAT_YV12 || !card->is_g400){
858             card->regs.besa1corg = (uint32_t) card->src_base + baseadrofs + card->regs.bespitch * sh ;
859             card->regs.besa2corg = (uint32_t) card->src_base + baseadrofs + 1*frame_size + card->regs.bespitch * sh;
860             card->regs.besb1corg = (uint32_t) card->src_base + baseadrofs + 2*frame_size + card->regs.bespitch * sh;
861             card->regs.besb2corg = (uint32_t) card->src_base + baseadrofs + 3*frame_size + card->regs.bespitch * sh;
862             card->regs.besa1c3org = card->regs.besa1corg + ( (card->regs.bespitch * sh) / 4);
863             card->regs.besa2c3org = card->regs.besa2corg + ( (card->regs.bespitch * sh) / 4);
864             card->regs.besb1c3org = card->regs.besb1corg + ( (card->regs.bespitch * sh) / 4);
865             card->regs.besb2c3org = card->regs.besb2corg + ( (card->regs.bespitch * sh) / 4);
866         } else {
867             card->regs.besa1c3org = (uint32_t) card->src_base + baseadrofs + card->regs.bespitch * sh ;
868             card->regs.besa2c3org = (uint32_t) card->src_base + baseadrofs + 1*frame_size + card->regs.bespitch * sh;
869             card->regs.besb1c3org = (uint32_t) card->src_base + baseadrofs + 2*frame_size + card->regs.bespitch * sh;
870             card->regs.besb2c3org = (uint32_t) card->src_base + baseadrofs + 3*frame_size + card->regs.bespitch * sh;
871             card->regs.besa1corg = card->regs.besa1c3org + ((card->regs.bespitch * sh) / 4);
872             card->regs.besa2corg = card->regs.besa2c3org + ((card->regs.bespitch * sh) / 4);
873             card->regs.besb1corg = card->regs.besb1c3org + ((card->regs.bespitch * sh) / 4);
874             card->regs.besb2corg = card->regs.besb2c3org + ((card->regs.bespitch * sh) / 4);
875         }
876     }
877 
878     weight = ofstop * (card->regs.besviscal >> 2);
879     weights = weight < 0 ? 1 : 0;
880     card->regs.besv2wght = card->regs.besv1wght = (weights << 16) + ((weight & 0x3FFF) << 2);
881     card->regs.besv2srclst = card->regs.besv1srclst = sh - 1 - (((ofstop * card->regs.besviscal) >> 16) & 0x03FF);
882 
883 #ifdef CRTC2
884     // pridat hlavni registry - tj. casovani ...
885 
886 
887     switch(config->format){
888     case MGA_VID_FORMAT_YV12:
889     case MGA_VID_FORMAT_I420:
890     case MGA_VID_FORMAT_IYUV:
891         card->cregs.c2ctl = 1           // CRTC2 enabled
892                             + (1<<1)    // external clock
893                             + (0<<2)    // external clock
894                             + (1<<3)    // pixel clock enable - not needed ???
895                             + (0<<4)    // high prioryty req
896                             + (1<<5)    // high prioryty req
897                             + (0<<6)    // high prioryty req
898                             + (1<<8)    // high prioryty req max
899                             + (0<<9)    // high prioryty req max
900                             + (0<<10)   // high prioryty req max
901                             + (0<<20)   // CRTC1 to DAC
902                             + (1<<21)   // 420 mode
903                             + (1<<22)   // 420 mode
904                             + (1<<23)   // 420 mode
905                             + (0<<24)   // single chroma line for 420 mode - need to be corrected
906                             + (0<<25)   /*/ interlace mode - need to be corrected*/
907                             + (0<<26)   // field legth polariry
908                             + (0<<27)   // field identification polariry
909                             + (1<<28)   // VIDRST detection mode
910                             + (0<<29)   // VIDRST detection mode
911                             + (1<<30)   // Horizontal counter preload
912                             + (1<<31)   // Vertical counter preload
913                             ;
914         card->cregs.c2datactl = 1       // disable dither - propably not needed, we are already in YUV mode
915                             + (1<<1)    // Y filter enable
916                             + (1<<2)    // CbCr filter enable
917                             + (0<<3)    // subpicture enable (disabled)
918                             + (0<<4)    // NTSC enable (disabled - PAL)
919                             + (0<<5)    // C2 static subpicture enable (disabled)
920                             + (0<<6)    // C2 subpicture offset division (disabled)
921                             + (0<<7)    // 422 subformat selection !
922 /*                          + (0<<8)    // 15 bpp high alpha
923                             + (0<<9)    // 15 bpp high alpha
924                             + (0<<10)   // 15 bpp high alpha
925                             + (0<<11)   // 15 bpp high alpha
926                             + (0<<12)   // 15 bpp high alpha
927                             + (0<<13)   // 15 bpp high alpha
928                             + (0<<14)   // 15 bpp high alpha
929                             + (0<<15)   // 15 bpp high alpha
930                             + (0<<16)   // 15 bpp low alpha
931                             + (0<<17)   // 15 bpp low alpha
932                             + (0<<18)   // 15 bpp low alpha
933                             + (0<<19)   // 15 bpp low alpha
934                             + (0<<20)   // 15 bpp low alpha
935                             + (0<<21)   // 15 bpp low alpha
936                             + (0<<22)   // 15 bpp low alpha
937                             + (0<<23)   // 15 bpp low alpha
938                             + (0<<24)   // static subpicture key
939                             + (0<<25)   // static subpicture key
940                             + (0<<26)   // static subpicture key
941                             + (0<<27)   // static subpicture key
942                             + (0<<28)   // static subpicture key
943 */                          ;
944         break;
945 
946     case MGA_VID_FORMAT_YUY2:
947         card->cregs.c2ctl = 1           // CRTC2 enabled
948                             + (1<<1)    // external clock
949                             + (0<<2)    // external clock
950                             + (1<<3)    // pixel clock enable - not needed ???
951                             + (0<<4)    // high prioryty req - acc to spec
952                             + (1<<5)    // high prioryty req
953                             + (0<<6)    // high prioryty req
954                                         // 7 reserved
955                             + (1<<8)    // high prioryty req max
956                             + (0<<9)    // high prioryty req max
957                             + (0<<10)   // high prioryty req max
958                                         // 11-19 reserved
959                             + (0<<20)   // CRTC1 to DAC
960                             + (1<<21)   // 422 mode
961                             + (0<<22)   // 422 mode
962                             + (1<<23)   // 422 mode
963                             + (0<<24)   // single chroma line for 420 mode - need to be corrected
964                             + (0<<25)   /*/ interlace mode - need to be corrected*/
965                             + (0<<26)   // field legth polariry
966                             + (0<<27)   // field identification polariry
967                             + (1<<28)   // VIDRST detection mode
968                             + (0<<29)   // VIDRST detection mode
969                             + (1<<30)   // Horizontal counter preload
970                             + (1<<31)   // Vertical counter preload
971                             ;
972         card->cregs.c2datactl = 1       // disable dither - propably not needed, we are already in YUV mode
973                             + (1<<1)    // Y filter enable
974                             + (1<<2)    // CbCr filter enable
975                             + (0<<3)    // subpicture enable (disabled)
976                             + (0<<4)    // NTSC enable (disabled - PAL)
977                             + (0<<5)    // C2 static subpicture enable (disabled)
978                             + (0<<6)    // C2 subpicture offset division (disabled)
979                             + (0<<7)    // 422 subformat selection !
980 /*                          + (0<<8)    // 15 bpp high alpha
981                             + (0<<9)    // 15 bpp high alpha
982                             + (0<<10)   // 15 bpp high alpha
983                             + (0<<11)   // 15 bpp high alpha
984                             + (0<<12)   // 15 bpp high alpha
985                             + (0<<13)   // 15 bpp high alpha
986                             + (0<<14)   // 15 bpp high alpha
987                             + (0<<15)   // 15 bpp high alpha
988                             + (0<<16)   // 15 bpp low alpha
989                             + (0<<17)   // 15 bpp low alpha
990                             + (0<<18)   // 15 bpp low alpha
991                             + (0<<19)   // 15 bpp low alpha
992                             + (0<<20)   // 15 bpp low alpha
993                             + (0<<21)   // 15 bpp low alpha
994                             + (0<<22)   // 15 bpp low alpha
995                             + (0<<23)   // 15 bpp low alpha
996                             + (0<<24)   // static subpicture key
997                             + (0<<25)   // static subpicture key
998                             + (0<<26)   // static subpicture key
999                             + (0<<27)   // static subpicture key
1000                             + (0<<28)   // static subpicture key
1001 */                              ;
1002           break;
1003 
1004     case MGA_VID_FORMAT_UYVY:
1005         card->cregs.c2ctl = 1           // CRTC2 enabled
1006                             + (1<<1)    // external clock
1007                             + (0<<2)    // external clock
1008                             + (1<<3)    // pixel clock enable - not needed ???
1009                             + (0<<4)    // high prioryty req
1010                             + (1<<5)    // high prioryty req
1011                             + (0<<6)    // high prioryty req
1012                             + (1<<8)    // high prioryty req max
1013                             + (0<<9)    // high prioryty req max
1014                             + (0<<10)   // high prioryty req max
1015                             + (0<<20)   // CRTC1 to DAC
1016                             + (1<<21)   // 422 mode
1017                             + (0<<22)   // 422 mode
1018                             + (1<<23)   // 422 mode
1019                             + (1<<24)   // single chroma line for 420 mode - need to be corrected
1020                             + (1<<25)   /*/ interlace mode - need to be corrected*/
1021                             + (0<<26)   // field legth polariry
1022                             + (0<<27)   // field identification polariry
1023                             + (1<<28)   // VIDRST detection mode
1024                             + (0<<29)   // VIDRST detection mode
1025                             + (1<<30)   // Horizontal counter preload
1026                             + (1<<31)   // Vertical counter preload
1027                             ;
1028         card->cregs.c2datactl = 0       // enable dither - propably not needed, we are already in YUV mode
1029                             + (1<<1)    // Y filter enable
1030                             + (1<<2)    // CbCr filter enable
1031                             + (0<<3)    // subpicture enable (disabled)
1032                             + (0<<4)    // NTSC enable (disabled - PAL)
1033                             + (0<<5)    // C2 static subpicture enable (disabled)
1034                             + (0<<6)    // C2 subpicture offset division (disabled)
1035                             + (1<<7)    // 422 subformat selection !
1036 /*                          + (0<<8)    // 15 bpp high alpha
1037                             + (0<<9)    // 15 bpp high alpha
1038                             + (0<<10)   // 15 bpp high alpha
1039                             + (0<<11)   // 15 bpp high alpha
1040                             + (0<<12)   // 15 bpp high alpha
1041                             + (0<<13)   // 15 bpp high alpha
1042                             + (0<<14)   // 15 bpp high alpha
1043                             + (0<<15)   // 15 bpp high alpha
1044                             + (0<<16)   // 15 bpp low alpha
1045                             + (0<<17)   // 15 bpp low alpha
1046                             + (0<<18)   // 15 bpp low alpha
1047                             + (0<<19)   // 15 bpp low alpha
1048                             + (0<<20)   // 15 bpp low alpha
1049                             + (0<<21)   // 15 bpp low alpha
1050                             + (0<<22)   // 15 bpp low alpha
1051                             + (0<<23)   // 15 bpp low alpha
1052                             + (0<<24)   // static subpicture key
1053                             + (0<<25)   // static subpicture key
1054                             + (0<<26)   // static subpicture key
1055                             + (0<<27)   // static subpicture key
1056                             + (0<<28)   // static subpicture key
1057 */                          ;
1058         break;
1059 
1060     default:
1061         printk(KERN_ERR "mga_vid: Unsupported pixel format: 0x%X\n",config->format);
1062         return -1;
1063     }
1064 
1065     card->cregs.c2hparam = ( (hdispend - 8) << 16) | (htotal - 8);
1066     card->cregs.c2hsync = ( (hsyncend - 8) << 16) | (hsyncstart - 8);
1067 
1068     card->cregs.c2misc = 0        // CRTCV2 656 togg f0
1069                          + (0<<1) // CRTCV2 656 togg f0
1070                          + (0<<2) // CRTCV2 656 togg f0
1071                          + (0<<4) // CRTCV2 656 togg f1
1072                          + (0<<5) // CRTCV2 656 togg f1
1073                          + (0<<6) // CRTCV2 656 togg f1
1074                          + (0<<8) // Hsync active high
1075                          + (0<<9) // Vsync active high
1076                          // 16-27 c2vlinecomp - nevim co tam dat
1077                          ;
1078     card->cregs.c2offset=(card->regs.bespitch << 1);
1079 
1080     card->cregs.c2pl2startadd0=card->regs.besa1corg;
1081 //  card->cregs.c2pl2startadd1=card->regs.besa2corg;
1082     card->cregs.c2pl3startadd0=card->regs.besa1c3org;
1083 //  card->cregs.c2pl3startadd1=card->regs.besa2c3org;
1084 
1085     card->cregs.c2preload=(vsyncstart << 16) | (hsyncstart); // from
1086 
1087     card->cregs.c2spicstartadd0=0; // not used
1088 //  card->cregs.c2spicstartadd1=0; // not used
1089 
1090     card->cregs.c2startadd0=card->regs.besa1org;
1091 //  card->cregs.c2startadd1=card->regs.besa2org;
1092 
1093     card->cregs.c2subpiclut=0; //not used
1094 
1095     card->cregs.c2vparam = ( (vdispend - 1) << 16) | (vtotal - 1);
1096     card->cregs.c2vsync  = ( (vsyncend - 1) << 16) | (vsyncstart - 1);
1097 
1098 
1099 #endif
1100 
1101     mga_vid_write_regs(card, 0);
1102     return 0;
1103 }
1104 
1105 #ifdef MGA_ALLOW_IRQ
1106 
enable_irq(mga_card_t * card)1107 static void enable_irq(mga_card_t * card){
1108     long int cc;
1109 
1110     cc = readl(card->mmio_base + IEN);
1111 //  printk(KERN_ALERT "*** !!! IRQREG = %d\n", (int)(cc&0xff));
1112 
1113     writeb(0x11, card->mmio_base + CRTCX);
1114 
1115     writeb(0x20, card->mmio_base + CRTCD);  /* clear 0, enable off */
1116     writeb(0x00, card->mmio_base + CRTCD);  /* enable on */
1117     writeb(0x10, card->mmio_base + CRTCD);  /* clear = 1 */
1118 
1119     writel(card->regs.besglobctl , card->mmio_base + BESGLOBCTL);
1120 }
1121 
disable_irq(mga_card_t * card)1122 static void disable_irq(mga_card_t * card){
1123     writeb(0x11, card->mmio_base + CRTCX);
1124     writeb(0x20, card->mmio_base + CRTCD);  /* clear 0, enable off */
1125 }
1126 
mga_handle_irq(int irq,void * dev_id,struct pt_regs * pregs)1127 static void mga_handle_irq(int irq, void *dev_id, struct pt_regs *pregs) {
1128 //  static int frame=0;
1129 //  static int counter=0;
1130     long int cc;
1131     mga_card_t * card = dev_id;
1132 
1133 //  printk(KERN_DEBUG "vcount = %d\n",readl(mga_mmio_base + VCOUNT));
1134 
1135     //printk("mga_interrupt #%d\n", irq);
1136 
1137     // check whether the interrupt is really for us (irq sharing)
1138     if ( irq != -1 ) {
1139         cc = readl(card->mmio_base + STATUS);
1140         if ( ! (cc & 0x10) ) return;  /* vsyncpen */
1141 //      debug_irqcnt++;
1142     }
1143 
1144 //  if ( debug_irqignore ) {
1145 //      debug_irqignore = 0;
1146 
1147 //  frame=(frame+1)&1;
1148     card->regs.besctl = (card->regs.besctl & ~0x07000000) + (card->next_frame << 25);
1149     writel( card->regs.besctl, card->mmio_base + BESCTL );
1150 
1151 #ifdef CRTC2
1152 // sem pridat vyber obrazku !!!!
1153 // i han echt kei ahnig was das obe heisse söll
1154     crtc2_frame_sel(card->next_frame);
1155 #endif
1156 
1157 #if 0
1158     ++counter;
1159     if(!(counter&63)){
1160         printk("mga irq counter = %d\n",counter);
1161     }
1162 #endif
1163 
1164 //  } else {
1165 //      debug_irqignore = 1;
1166 //  }
1167 
1168     if ( irq != -1 ) {
1169         writeb( 0x11, card->mmio_base + CRTCX);
1170         writeb( 0, card->mmio_base + CRTCD );
1171         writeb( 0x10, card->mmio_base + CRTCD );
1172     }
1173 
1174 //  writel( card->regs.besglobctl, card->mmio_base + BESGLOBCTL);
1175 
1176     return;
1177 }
1178 
1179 #endif
1180 
mga_vid_ioctl(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg)1181 static int mga_vid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
1182 {
1183     int frame, result;
1184     uint32_t tmp;
1185     mga_card_t * card = (mga_card_t *) file->private_data;
1186 
1187     switch(cmd)
1188     {
1189     case MGA_VID_GET_VERSION:
1190         tmp = MGA_VID_VERSION;
1191         if (copy_to_user((uint32_t *) arg, &tmp, sizeof(uint32_t))) {
1192             printk(KERN_ERR "mga_vid: failed copy %p to userspace %p\n", &tmp, (uint32_t *) arg);
1193             return -EFAULT;
1194         }
1195         break;
1196 
1197     case MGA_VID_CONFIG:
1198         //FIXME remove
1199 //      printk(KERN_DEBUG "mga_vid: vcount = %d\n",readl(card->mmio_base + VCOUNT));
1200 #ifdef MP_DEBUG
1201         printk(KERN_DEBUG "mga_vid: mmio_base = %p\n",card->mmio_base);
1202         printk(KERN_DEBUG "mga_vid: mem_base = %08x\n",card->mem_base);
1203         //FIXME remove
1204 
1205         printk(KERN_DEBUG "mga_vid: Received configuration\n");
1206 #endif
1207 
1208         if(copy_from_user(&card->config,(mga_vid_config_t*) arg,sizeof(mga_vid_config_t)))
1209         {
1210             printk(KERN_ERR "mga_vid: failed copy from userspace\n");
1211             return -EFAULT;
1212         }
1213         if(card->config.version != MGA_VID_VERSION){
1214             printk(KERN_ERR "mga_vid: incompatible version! driver: %X  requested: %X\n",MGA_VID_VERSION,card->config.version);
1215             return -EFAULT;
1216         }
1217 
1218         if(card->config.frame_size==0 || card->config.frame_size>1024*768*2){
1219             printk(KERN_ERR "mga_vid: illegal frame_size: %d\n",card->config.frame_size);
1220             return -EFAULT;
1221         }
1222 
1223         if(card->config.num_frames<1 || card->config.num_frames>4){
1224             printk(KERN_ERR "mga_vid: illegal num_frames: %d\n",card->config.num_frames);
1225             return -EFAULT;
1226         }
1227 
1228         card->src_base = (card->ram_size * 0x100000 - card->config.num_frames * card->config.frame_size - card->top_reserved);
1229         if(card->src_base<0){
1230             printk(KERN_ERR "mga_vid: not enough memory for frames!\n");
1231             return -EFAULT;
1232         }
1233         card->src_base &= (~0xFFFF); // 64k boundary
1234 #ifdef MP_DEBUG
1235         printk(KERN_DEBUG "mga YUV buffer base: 0x%X\n", card->src_base);
1236 #endif
1237 
1238         if (card->is_g400)
1239             card->config.card_type = MGA_G400;
1240         else
1241             card->config.card_type = MGA_G200;
1242 
1243         card->config.ram_size = card->ram_size;
1244 
1245         if (copy_to_user((mga_vid_config_t *) arg, &card->config, sizeof(mga_vid_config_t)))
1246         {
1247             printk(KERN_ERR "mga_vid: failed copy to userspace\n");
1248             return -EFAULT;
1249         }
1250 
1251         result = mga_vid_set_config(card);
1252         if(!result) card->configured=1;
1253         return result;
1254         break;
1255 
1256     case MGA_VID_ON:
1257 #ifdef MP_DEBUG
1258         printk(KERN_DEBUG "mga_vid: Video ON\n");
1259 #endif
1260         card->vid_src_ready = 1;
1261         if(card->vid_overlay_on)
1262         {
1263             card->regs.besctl |= 1;
1264             mga_vid_write_regs(card, 0);
1265         }
1266 #ifdef MGA_ALLOW_IRQ
1267         if ( card->irq != -1 ) enable_irq(card);
1268 #endif
1269         card->next_frame=0;
1270         break;
1271 
1272     case MGA_VID_OFF:
1273 #ifdef MP_DEBUG
1274         printk(KERN_DEBUG "mga_vid: Video OFF (ioctl)\n");
1275 #endif
1276         card->vid_src_ready = 0;
1277 #ifdef MGA_ALLOW_IRQ
1278         if ( card->irq != -1 ) disable_irq(card);
1279 #endif
1280         card->regs.besctl &= ~1;
1281         card->regs.besglobctl &= ~(1<<6);  // UYVY format selected
1282         mga_vid_write_regs(card, 0);
1283         break;
1284 
1285     case MGA_VID_FSEL:
1286         if(copy_from_user(&frame,(int *) arg,sizeof(int)))
1287         {
1288             printk(KERN_ERR "mga_vid: FSEL failed copy from userspace\n");
1289             return -EFAULT;
1290         }
1291 
1292         mga_vid_frame_sel(card, frame);
1293         break;
1294 
1295     case MGA_VID_GET_LUMA:
1296         //tmp = card->regs.beslumactl;
1297         //tmp = (tmp&0xFFFF0000) | (((tmp&0xFFFF) - 0x80)&0xFFFF);
1298         tmp = (card->brightness << 16) | (card->contrast&0xFFFF);
1299 
1300         if (copy_to_user((uint32_t *) arg, &tmp, sizeof(uint32_t)))
1301         {
1302             printk(KERN_ERR "mga_vid: failed copy %p to userspace %p\n",
1303                    &tmp, (uint32_t *) arg);
1304             return -EFAULT;
1305         }
1306         break;
1307 
1308     case MGA_VID_SET_LUMA:
1309         tmp = arg;
1310         card->brightness=tmp>>16; card->contrast=tmp&0xFFFF;
1311         //card->regs.beslumactl = (tmp&0xFFFF0000) | ((tmp + 0x80)&0xFFFF);
1312         card->regs.beslumactl = (card->brightness << 16) | ((card->contrast+0x80)&0xFFFF);
1313         mga_vid_write_regs(card, 0);
1314         break;
1315 
1316     default:
1317         printk(KERN_ERR "mga_vid: Invalid ioctl\n");
1318         return -EINVAL;
1319     }
1320 
1321     return 0;
1322 }
1323 
1324 static void cards_init(mga_card_t * card, struct pci_dev * dev, int card_number, int is_g400);
1325 
1326 // returns the number of found cards
mga_vid_find_card(void)1327 static int mga_vid_find_card(void)
1328 {
1329     struct pci_dev *dev = NULL;
1330     char *mga_dev_name;
1331     mga_card_t * card;
1332 
1333     while((dev = pci_find_device(PCI_VENDOR_ID_MATROX, PCI_ANY_ID, dev)))
1334     {
1335         mga_dev_name = "";
1336         mga_cards_num++;
1337         if(mga_cards_num == MGA_MAX_CARDS)
1338         {
1339             printk(KERN_WARNING "mga_vid: Trying to initialize more than %d cards\n",MGA_MAX_CARDS);
1340             mga_cards_num--;
1341             break;
1342         }
1343 
1344         card = kmalloc(sizeof(mga_card_t), GFP_KERNEL);
1345         if(!card)
1346         {
1347             printk(KERN_ERR "mga_vid: memory allocation failed\n");
1348             mga_cards_num--;
1349             break;
1350         }
1351 
1352         mga_cards[mga_cards_num - 1] = card;
1353 
1354         switch(dev->device) {
1355         case PCI_DEVICE_ID_MATROX_G550:
1356             mga_dev_name = "MGA G550";
1357             printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, dev->name);
1358             cards_init(card, dev, mga_cards_num - 1, 1);
1359             break;
1360         case PCI_DEVICE_ID_MATROX_G400:
1361             mga_dev_name = "MGA G400/G450";
1362             printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, dev->name);
1363             cards_init(card, dev, mga_cards_num - 1, 1);
1364             break;
1365         case PCI_DEVICE_ID_MATROX_G200_AGP:
1366             mga_dev_name = "MGA G200 AGP";
1367             printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, dev->name);
1368             cards_init(card, dev, mga_cards_num - 1, 0);
1369             break;
1370         case PCI_DEVICE_ID_MATROX_G200_PCI:
1371             mga_dev_name = "MGA G200";
1372             printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, dev->name);
1373             cards_init(card, dev, mga_cards_num - 1, 0);
1374             break;
1375         default:
1376             mga_cards_num--;
1377             printk(KERN_INFO "mga_vid: ignoring matrox device (%d) at %s [%s]\n", dev->device, dev->slot_name, dev->name);
1378             break;
1379         }
1380     }
1381 
1382     if(!mga_cards_num)
1383     {
1384         printk(KERN_ERR "mga_vid: No supported cards found\n");
1385     } else {
1386         printk(KERN_INFO "mga_vid: %d supported cards found\n", mga_cards_num);
1387     }
1388 
1389     return mga_cards_num;
1390 }
1391 
mga_param_buff_fill(mga_card_t * card)1392 static void mga_param_buff_fill( mga_card_t * card )
1393 {
1394     unsigned len;
1395     unsigned size = card->param_buff_size;
1396     char * buf = card->param_buff;
1397     len = 0;
1398     len += snprintf(&buf[len],size-len,"Interface version: %04X\n",MGA_VID_VERSION);
1399     len += snprintf(&buf[len],size-len,"Memory: %x:%dM\n",card->mem_base,(unsigned int) card->ram_size);
1400     len += snprintf(&buf[len],size-len,"MMIO: %p\n",card->mmio_base);
1401     len += snprintf(&buf[len],size-len,"Configurable stuff:\n");
1402     len += snprintf(&buf[len],size-len,"~~~~~~~~~~~~~~~~~~~\n");
1403     len += snprintf(&buf[len],size-len,PARAM_BRIGHTNESS"%d\n",card->brightness);
1404     len += snprintf(&buf[len],size-len,PARAM_CONTRAST"%d\n",card->contrast);
1405     len += snprintf(&buf[len],size-len,PARAM_BLACKIE"%s\n",card->regs.blackie?"on":"off");
1406     card->param_buff_len = len;
1407     // check boundaries of mga_param_buff before writing to it!!!
1408 }
1409 
1410 
mga_vid_read(struct file * file,char * buf,size_t count,loff_t * ppos)1411 static ssize_t mga_vid_read(struct file *file, char *buf, size_t count, loff_t *ppos)
1412 {
1413     uint32_t size;
1414     mga_card_t * card = (mga_card_t *) file->private_data;
1415 
1416     if(!card->param_buff) return -ESPIPE;
1417     if(!(*ppos)) mga_param_buff_fill(card);
1418     if(*ppos >= card->param_buff_len) return 0;
1419     size = min(count,card->param_buff_len-(uint32_t)(*ppos));
1420     memcpy(buf,card->param_buff,size);
1421     *ppos += size;
1422     return size;
1423 }
1424 
mga_vid_write(struct file * file,const char * buf,size_t count,loff_t * ppos)1425 static ssize_t mga_vid_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
1426 {
1427     mga_card_t * card = (mga_card_t *) file->private_data;
1428 
1429     if(memcmp(buf,PARAM_BRIGHTNESS,min(count,strlen(PARAM_BRIGHTNESS))) == 0)
1430     {
1431         short brightness;
1432         brightness=simple_strtol(&buf[strlen(PARAM_BRIGHTNESS)],NULL,10);
1433         if (brightness>127 || brightness<-128) { brightness=0;}
1434 //          printk(KERN_DEBUG "mga_vid: brightness modified ( %d ) \n",brightness);
1435         card->brightness=brightness;
1436     } else
1437         if(memcmp(buf,PARAM_CONTRAST,min(count,strlen(PARAM_CONTRAST))) == 0)
1438         {
1439             short contrast;
1440             contrast=simple_strtol(&buf[strlen(PARAM_CONTRAST)],NULL,10);
1441             if (contrast>127 || contrast<-128) { contrast=0;}
1442 //              printk(KERN_DEBUG "mga_vid: contrast modified ( %d ) \n",contrast);
1443             card->contrast=contrast;
1444         } else
1445 
1446             if(memcmp(buf,PARAM_BLACKIE,min(count,strlen(PARAM_BLACKIE))) == 0)
1447             {
1448                 short blackie;
1449                 blackie=simple_strtol(&buf[strlen(PARAM_BLACKIE)],NULL,10);
1450 //              printk(KERN_DEBUG "mga_vid: shadow mode: ( %d ) \n",blackie);
1451                 card->regs.blackie=(blackie>0)?1:0;
1452             } else count = -EIO;
1453     // TODO: reset settings
1454     return count;
1455 }
1456 
mga_vid_mmap(struct file * file,struct vm_area_struct * vma)1457 static int mga_vid_mmap(struct file *file, struct vm_area_struct *vma)
1458 {
1459     mga_card_t * card = (mga_card_t *) file->private_data;
1460 
1461 #ifdef MP_DEBUG
1462     printk(KERN_DEBUG "mga_vid: mapping video memory into userspace\n");
1463 #endif
1464 
1465     if(!card->configured)
1466     {
1467         printk(KERN_ERR "mga_vid: card is not configured, cannot mmap\n");
1468         return -EAGAIN;
1469     }
1470 
1471     if(remap_page_range(vma->vm_start, card->mem_base + card->src_base,
1472                         vma->vm_end - vma->vm_start, vma->vm_page_prot))
1473     {
1474         printk(KERN_ERR "mga_vid: error mapping video memory\n");
1475         return -EAGAIN;
1476     }
1477 
1478     return 0;
1479 }
1480 
mga_vid_release(struct inode * inode,struct file * file)1481 static int mga_vid_release(struct inode *inode, struct file *file)
1482 {
1483     mga_card_t * card;
1484 
1485     //Close the window just in case
1486 #ifdef MP_DEBUG
1487     printk(KERN_DEBUG "mga_vid: Video OFF (release)\n");
1488 #endif
1489 
1490     card = (mga_card_t *) file->private_data;
1491 
1492     card->vid_src_ready = 0;
1493     card->regs.besctl &= ~1;
1494     card->regs.besglobctl &= ~(1<<6);  // UYVY format selected
1495 //  card->config.colkey_on=0; //!!!
1496     mga_vid_write_regs(card, 1);
1497     card->vid_in_use = 0;
1498 
1499     MOD_DEC_USE_COUNT;
1500     return 0;
1501 }
1502 
mga_vid_lseek(struct file * file,long long offset,int origin)1503 static long long mga_vid_lseek(struct file *file, long long offset, int origin)
1504 {
1505     return -ESPIPE;
1506 }
1507 
mga_vid_open(struct inode * inode,struct file * file)1508 static int mga_vid_open(struct inode *inode, struct file *file)
1509 {
1510     mga_card_t * card;
1511 
1512     int minor = MINOR(inode->i_rdev);
1513 
1514     if(!file->private_data)
1515     {
1516         // we are not using devfs, use the minor
1517         // number to specify the card we are using
1518 
1519         // we don't have that many cards
1520         if(minor >= mga_cards_num)
1521             return -ENXIO;
1522 
1523         file->private_data = mga_cards[minor];
1524 #ifdef MP_DEBUG
1525         printk(KERN_DEBUG "mga_vid: Not using devfs\n");
1526 #endif
1527     }
1528 #ifdef MP_DEBUG
1529     else {
1530         printk(KERN_DEBUG "mga_vid: Using devfs\n");
1531     }
1532 #endif
1533 
1534     card = (mga_card_t *) file->private_data;
1535 
1536     if(card->vid_in_use == 1)
1537         return -EBUSY;
1538 
1539     card->vid_in_use = 1;
1540     MOD_INC_USE_COUNT;
1541     return 0;
1542 }
1543 
1544 #if LINUX_VERSION_CODE >= 0x020400
1545 static struct file_operations mga_vid_fops =
1546 {
1547     llseek:         mga_vid_lseek,
1548     read:           mga_vid_read,
1549     write:          mga_vid_write,
1550     ioctl:          mga_vid_ioctl,
1551     mmap:           mga_vid_mmap,
1552     open:           mga_vid_open,
1553     release:        mga_vid_release
1554 };
1555 #else
1556 static struct file_operations mga_vid_fops =
1557 {
1558     mga_vid_lseek,
1559     mga_vid_read,
1560     mga_vid_write,
1561     NULL,
1562     NULL,
1563     mga_vid_ioctl,
1564     mga_vid_mmap,
1565     mga_vid_open,
1566     NULL,
1567     mga_vid_release
1568 };
1569 #endif
1570 
cards_init(mga_card_t * card,struct pci_dev * dev,int card_number,int is_g400)1571 static void cards_init(mga_card_t * card, struct pci_dev * dev, int card_number, int is_g400)
1572 {
1573     unsigned int card_option;
1574 // temp buffer for device filename creation used only by devfs
1575 #ifdef CONFIG_DEVFS_FS
1576     char buffer[16];
1577 #endif
1578 
1579     memset(card,0,sizeof(mga_card_t));
1580     card->irq = -1;
1581 
1582     card->pci_dev = dev;
1583     card->irq = dev->irq;
1584     card->is_g400 = is_g400;
1585 
1586     card->param_buff = kmalloc(PARAM_BUFF_SIZE,GFP_KERNEL);
1587     if(card->param_buff) card->param_buff_size = PARAM_BUFF_SIZE;
1588 
1589     card->brightness = mga_brightness[card_number];
1590     card->contrast = mga_contrast[card_number];
1591     card->top_reserved = mga_top_reserved[card_number];
1592 
1593 #if LINUX_VERSION_CODE >= 0x020300
1594     card->mmio_base = ioremap_nocache(dev->resource[1].start,0x4000);
1595     card->mem_base =  dev->resource[0].start;
1596 #else
1597     card->mmio_base = ioremap_nocache(dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK,0x4000);
1598     card->mem_base =  dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
1599 #endif
1600     printk(KERN_INFO "mga_vid: MMIO at 0x%p IRQ: %d  framebuffer: 0x%08X\n", card->mmio_base, card->irq, card->mem_base);
1601 
1602     pci_read_config_dword(dev,  0x40, &card_option);
1603     printk(KERN_INFO "mga_vid: OPTION word: 0x%08X  mem: 0x%02X  %s\n", card_option,
1604            (card_option>>10)&0x17, ((card_option>>14)&1)?"SGRAM":"SDRAM");
1605 
1606     if (mga_ram_size[card_number]) {
1607         printk(KERN_INFO "mga_vid: RAMSIZE forced to %d MB\n", mga_ram_size[card_number]);
1608         card->ram_size=mga_ram_size[card_number];
1609     } else {
1610 
1611 #ifdef MGA_MEMORY_SIZE
1612         card->ram_size = MGA_MEMORY_SIZE;
1613         printk(KERN_INFO "mga_vid: hard-coded RAMSIZE is %d MB\n", (unsigned int) card->ram_size);
1614 #else
1615         if (card->is_g400){
1616             switch((card_option>>10)&0x17){
1617                 // SDRAM:
1618             case 0x00:
1619             case 0x04:  card->ram_size = 16; break;
1620             case 0x03:
1621             case 0x05:  card->ram_size = 32; break;
1622                 // SGRAM:
1623             case 0x10:
1624             case 0x14:  card->ram_size = 32; break;
1625             case 0x11:
1626             case 0x12:  card->ram_size = 16; break;
1627             default:
1628                 card->ram_size = 16;
1629                 printk(KERN_INFO "mga_vid: Couldn't detect RAMSIZE, assuming 16MB!");
1630             }
1631             /* Check for buggy 16MB cards reporting 32 MB */
1632             if(card->ram_size != 16 &&
1633                (dev->subsystem_device == PCI_SUBSYSTEM_ID_MATROX_G400_16MB_SDRAM ||
1634                 dev->subsystem_device == PCI_SUBSYSTEM_ID_MATROX_G400_16MB_SGRAM ||
1635                 dev->subsystem_device == PCI_SUBSYSTEM_ID_MATROX_G400_DH_16MB))
1636             {
1637                 printk(KERN_INFO "mga_vid: Detected 16MB card reporting %d MB RAMSIZE, overriding\n", card->ram_size);
1638                 card->ram_size = 16;
1639             }
1640         }else{
1641             switch((card_option>>10)&0x17){
1642 //              case 0x10:
1643 //              case 0x13:  card->ram_size = 8; break;
1644             default: card->ram_size = 8;
1645             }
1646         }
1647 #if 0
1648 //      printk("List resources -----------\n");
1649         for(temp=0;temp<DEVICE_COUNT_RESOURCE;temp++){
1650             struct resource *res=&dev->resource[temp];
1651             if(res->flags){
1652                 int size=(1+res->end-res->start)>>20;
1653                 printk(KERN_DEBUG "res %d:  start: 0x%X   end: 0x%X  (%d MB) flags=0x%X\n",temp,res->start,res->end,size,res->flags);
1654                 if(res->flags&(IORESOURCE_MEM|IORESOURCE_PREFETCH)){
1655                     if(size>card->ram_size && size<=64) card->ram_size=size;
1656                 }
1657             }
1658         }
1659 #endif
1660         printk(KERN_INFO "mga_vid: detected RAMSIZE is %d MB\n", (unsigned int) card->ram_size);
1661 #endif
1662     }
1663 
1664 
1665 #ifdef MGA_ALLOW_IRQ
1666     if ( card->irq != -1 ) {
1667         int tmp = request_irq(card->irq, mga_handle_irq, SA_INTERRUPT | SA_SHIRQ, "Syncfb Time Base", card);
1668         if ( tmp ) {
1669             printk(KERN_INFO "syncfb (mga): cannot register irq %d (Err: %d)\n", card->irq, tmp);
1670             card->irq=-1;
1671         } else {
1672             printk(KERN_DEBUG "syncfb (mga): registered irq %d\n", card->irq);
1673         }
1674     } else {
1675         printk(KERN_INFO "syncfb (mga): No valid irq was found\n");
1676         card->irq=-1;
1677     }
1678 #else
1679     printk(KERN_INFO "syncfb (mga): IRQ disabled in mga_vid.c\n");
1680     card->irq=-1;
1681 #endif
1682 
1683     // register devfs, let the kernel give us major and minor numbers
1684 #ifdef CONFIG_DEVFS_FS
1685     snprintf(buffer, 16, "mga_vid%d", card_number);
1686     card->dev_handle = devfs_register(NULL, buffer, DEVFS_FL_AUTO_DEVNUM,
1687                                       0, 0,
1688                                       S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IFCHR,
1689                                       &mga_vid_fops, card);
1690 #endif
1691 }
1692 
1693 /*
1694  * Main Initialization Function
1695  */
1696 
mga_vid_initialize(void)1697 static int mga_vid_initialize(void)
1698 {
1699     int i;
1700 
1701 //  printk(KERN_INFO "Matrox MGA G200/G400 YUV Video interface v0.01 (c) Aaron Holtzman \n");
1702     printk(KERN_INFO "Matrox MGA G200/G400/G450/G550 YUV Video interface v2.01 (c) Aaron Holtzman & A'rpi\n");
1703 
1704     for(i = 0; i < MGA_MAX_CARDS; i++)
1705     {
1706         if (mga_ram_size[i]) {
1707             if (mga_ram_size[i]<4 || mga_ram_size[i]>64) {
1708                 printk(KERN_ERR "mga_vid: invalid RAMSIZE: %d MB\n", mga_ram_size[i]);
1709                 return -EINVAL;
1710             }
1711         }
1712     }
1713 
1714     if(register_chrdev(major, "mga_vid", &mga_vid_fops))
1715     {
1716         printk(KERN_ERR "mga_vid: unable to get major: %d\n", major);
1717         return -EIO;
1718     }
1719 
1720     if (!mga_vid_find_card())
1721     {
1722         printk(KERN_ERR "mga_vid: no supported devices found\n");
1723         unregister_chrdev(major, "mga_vid");
1724         return -EINVAL;
1725     }
1726 #ifdef CONFIG_DEVFS_FS
1727     else {
1728         // we assume that this always succeedes
1729         dev_handle = devfs_register(NULL, "mga_vid", DEVFS_FL_AUTO_DEVNUM,
1730                                     0,0,
1731                                     S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IFCHR,
1732                                     &mga_vid_fops, mga_cards[0]);
1733     }
1734 #endif
1735 
1736     return 0;
1737 }
1738 
init_module(void)1739 int init_module(void)
1740 {
1741     return mga_vid_initialize();
1742 }
1743 
cleanup_module(void)1744 void cleanup_module(void)
1745 {
1746     int i;
1747     mga_card_t * card;
1748 
1749     for (i = 0; i < MGA_MAX_CARDS; i++)
1750     {
1751         card = mga_cards[i];
1752         if(card)
1753         {
1754 #ifdef MGA_ALLOW_IRQ
1755             if (card->irq != -1)
1756                 free_irq(card->irq, &(card->irq));
1757 #endif
1758 
1759             if(card->mmio_base)
1760                 iounmap(card->mmio_base);
1761             if(card->param_buff)
1762                 kfree(card->param_buff);
1763 #ifdef CONFIG_DEVFS_FS
1764             if(card->dev_handle) devfs_unregister(card->dev_handle);
1765 #endif
1766 
1767             kfree(card);
1768             mga_cards[i]=NULL;
1769         }
1770     }
1771 
1772     //FIXME turn off BES
1773     printk(KERN_INFO "mga_vid: Cleaning up module\n");
1774 #ifdef CONFIG_DEVFS_FS
1775     if(dev_handle) devfs_unregister(dev_handle);
1776 #endif
1777     unregister_chrdev(major, "mga_vid");
1778 }
1779