3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
5 * (c) 1998,1999 Petr Vandrovec <vandrove@vc.cvut.cz>
7 * Version: 1.19 1999/08/05
9 * MTRR stuff: 1998 Tom Rini <tmrini@ntplx.net>
11 * Contributors: "menion?" <menion@mindless.com>
12 * Betatesting, fixes, ideas
14 * "Kurt Garloff" <garloff@kg1.ping.de>
15 * Betatesting, fixes, ideas, videomodes, videomodes timmings
17 * "Tom Rini" <trini@disparity.net>
18 * MTRR stuff, PPC cleanups, betatesting, fixes, ideas
20 * "Bibek Sahu" <scorpio@dodds.net>
21 * Access device through readb|w|l and write b|w|l
22 * Extensive debugging stuff
24 * "Daniel Haun" <haund@usa.net>
25 * Testing, hardware cursor fixes
27 * "Scott Wood" <sawst46+@pitt.edu>
30 * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
33 * "Kelly French" <targon@hazmat.com>
34 * "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
35 * Betatesting, bug reporting
37 * "Pablo Bianucci" <pbian@pccp.com.ar>
38 * Fixes, ideas, betatesting
40 * "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
41 * Fixes, enhandcements, ideas, betatesting
43 * "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
44 * PPC betatesting, PPC support, backward compatibility
46 * "Paul Womar" <Paul@pwomar.demon.co.uk>
47 * "Owen Waller" <O.Waller@ee.qub.ac.uk>
50 * "Thomas Pornin" <pornin@bolet.ens.fr>
53 * "Pieter van Leuven" <pvl@iae.nl>
54 * "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
57 * "H. Peter Arvin" <hpa@transmeta.com>
60 * "Cort Dougan" <cort@cs.nmt.edu>
61 * CHRP fixes and PReP cleanup
63 * "Mark Vojkovich" <mvojkovi@ucsd.edu>
66 * (following author is not in any relation with this code, but his code
67 * is included in this driver)
69 * Based on framebuffer driver for VBE 2.0 compliant graphic boards
70 * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
72 * (following author is not in any relation with this code, but his ideas
73 * were used when writting this driver)
75 * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
79 /* general, but fairly heavy, debugging */
82 /* heavy debugging: */
83 /* -- logs putc[s], so everytime a char is displayed, it's logged */
84 #undef MATROXFB_DEBUG_HEAVY
86 /* This one _could_ cause infinite loops */
87 /* It _does_ cause lots and lots of messages during idle loops */
88 #undef MATROXFB_DEBUG_LOOP
90 /* Debug register calls, too? */
91 #undef MATROXFB_DEBUG_REG
93 /* Log reentrancy attempts - you must have printstate() patch applied */
94 #undef MATROXFB_DEBUG_REENTER
95 /* you must define DEBUG_REENTER to get debugged CONSOLEBH... */
96 #undef MATROXFB_DEBUG_CONSOLEBH
98 #include <linux/config.h>
99 #include <linux/module.h>
100 #include <linux/kernel.h>
101 #include <linux/errno.h>
102 #include <linux/string.h>
103 #include <linux/mm.h>
104 #include <linux/tty.h>
105 #include <linux/malloc.h>
106 #include <linux/delay.h>
107 #include <linux/fb.h>
108 #include <linux/console.h>
109 #include <linux/selection.h>
110 #include <linux/ioport.h>
111 #include <linux/init.h>
112 #include <linux/timer.h>
113 #include <linux/pci.h>
114 #include <linux/spinlock.h>
117 #include <asm/unaligned.h>
119 #include <asm/mtrr.h>
122 #include <video/fbcon.h>
123 #include <video/fbcon-cfb4.h>
124 #include <video/fbcon-cfb8.h>
125 #include <video/fbcon-cfb16.h>
126 #include <video/fbcon-cfb24.h>
127 #include <video/fbcon-cfb32.h>
129 #if defined(CONFIG_FB_OF)
130 #if defined(CONFIG_FB_COMPAT_XPMAC)
131 #include <asm/vc_ioctl.h>
133 #include <asm/prom.h>
134 #include <asm/pci-bridge.h>
135 #include <video/macmodes.h>
138 /* always compile support for 32MB... It cost almost nothing */
139 #define CONFIG_FB_MATROX_32MB
141 #define FBCON_HAS_VGATEXT
143 #ifdef MATROXFB_DEBUG
146 #define DBG(x) printk(KERN_DEBUG "matroxfb: %s\n", (x));
148 #ifdef MATROXFB_DEBUG_HEAVY
149 #define DBG_HEAVY(x) DBG(x)
150 #else /* MATROXFB_DEBUG_HEAVY */
151 #define DBG_HEAVY(x) /* DBG_HEAVY */
152 #endif /* MATROXFB_DEBUG_HEAVY */
154 #ifdef MATROXFB_DEBUG_LOOP
155 #define DBG_LOOP(x) DBG(x)
156 #else /* MATROXFB_DEBUG_LOOP */
157 #define DBG_LOOP(x) /* DBG_LOOP */
158 #endif /* MATROXFB_DEBUG_LOOP */
160 #ifdef MATROXFB_DEBUG_REG
161 #define DBG_REG(x) DBG(x)
162 #else /* MATROXFB_DEBUG_REG */
163 #define DBG_REG(x) /* DBG_REG */
164 #endif /* MATROXFB_DEBUG_REG */
166 #else /* MATROXFB_DEBUG */
168 #define DBG(x) /* DBG */
169 #define DBG_HEAVY(x) /* DBG_HEAVY */
170 #define DBG_REG(x) /* DBG_REG */
171 #define DBG_LOOP(x) /* DBG_LOOP */
173 #endif /* MATROXFB_DEBUG */
176 #ifndef ioremap_nocache
177 #define ioremap_nocache(X,Y) ioremap(X,Y)
181 #if defined(__alpha__) || defined(__m68k__)
183 #define MEMCPYTOIO_WORKS
186 /* recheck __ppc__, maybe that __ppc__ needs MEMCPYTOIO_WRITEL */
187 /* I benchmarked PII/350MHz with G200... MEMCPY, MEMCPYTOIO and WRITEL are on same speed ( <2% diff) */
188 /* so that means that G200 speed (or AGP speed?) is our limit... I do not have benchmark to test, how */
189 /* much of PCI bandwidth is used during transfers... */
190 #if defined(__i386__)
191 #define MEMCPYTOIO_MEMCPY
193 #define MEMCPYTOIO_WRITEL
198 #error "Sorry, I have no idea how to do this on sparc... There is mapioaddr... With bus_type parameter..."
201 #if defined(__m68k__)
202 #define MAP_BUSTOVIRT
208 #define dprintk(X...) printk(X)
210 #define dprintk(X...)
213 #ifndef PCI_SS_VENDOR_ID_SIEMENS_NIXDORF
214 #define PCI_SS_VENDOR_ID_SIEMENS_NIXDORF 0x110A
216 #ifndef PCI_SS_VENDOR_ID_MATROX
217 #define PCI_SS_VENDOR_ID_MATROX PCI_VENDOR_ID_MATROX
219 #ifndef PCI_DEVICE_ID_MATROX_G200_PCI
220 #define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520
222 #ifndef PCI_DEVICE_ID_MATROX_G200_AGP
223 #define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521
225 #ifndef PCI_DEVICE_ID_MATROX_G100
226 #define PCI_DEVICE_ID_MATROX_G100 0x1000
228 #ifndef PCI_DEVICE_ID_MATROX_G100_AGP
229 #define PCI_DEVICE_ID_MATROX_G100_AGP 0x1001
231 #ifndef PCI_DEVICE_ID_MATROX_G400_AGP
232 #define PCI_DEVICE_ID_MATROX_G400_AGP 0x0525
235 #ifndef PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP
236 #define PCI_SS_ID_MATROX_GENERIC 0xFF00
237 #define PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP 0xFF01
238 #define PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP 0xFF02
239 #define PCI_SS_ID_MATROX_MILLENIUM_G200_AGP 0xFF03
240 #define PCI_SS_ID_MATROX_MARVEL_G200_AGP 0xFF04
241 #define PCI_SS_ID_MATROX_MGA_G100_PCI 0xFF05
242 #define PCI_SS_ID_MATROX_MGA_G100_AGP 0x1001
243 #define PCI_SS_ID_SIEMENS_MGA_G100_AGP 0x001E /* 30 */
244 #define PCI_SS_ID_SIEMENS_MGA_G200_AGP 0x0032 /* 50 */
247 #define MX_VISUAL_TRUECOLOR FB_VISUAL_DIRECTCOLOR
248 #define MX_VISUAL_DIRECTCOLOR FB_VISUAL_TRUECOLOR
249 #define MX_VISUAL_PSEUDOCOLOR FB_VISUAL_PSEUDOCOLOR
251 #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
253 /* G100, G200 and Mystique have (almost) same DAC */
255 #if defined(CONFIG_FB_MATROX_MYSTIQUE) || defined(CONFIG_FB_MATROX_G100)
256 #define NEED_DAC1064 1
264 static inline unsigned int mga_readb(vaddr_t va
, unsigned int offs
) {
265 return readb(va
.vaddr
+ offs
);
268 static inline unsigned int mga_readw(vaddr_t va
, unsigned int offs
) {
269 return readw(va
.vaddr
+ offs
);
272 static inline u_int32_t
mga_readl(vaddr_t va
, unsigned int offs
) {
273 return readl(va
.vaddr
+ offs
);
276 static inline void mga_writeb(vaddr_t va
, unsigned int offs
, u_int8_t value
) {
277 writeb(value
, va
.vaddr
+ offs
);
280 static inline void mga_writew(vaddr_t va
, unsigned int offs
, u_int16_t value
) {
281 writew(value
, va
.vaddr
+ offs
);
284 static inline void mga_writel(vaddr_t va
, unsigned int offs
, u_int32_t value
) {
285 writel(value
, va
.vaddr
+ offs
);
288 static inline unsigned int mga_readb(vaddr_t va
, unsigned int offs
) {
289 return *(volatile u_int8_t
*)(va
.vaddr
+ offs
);
292 static inline unsigned int mga_readw(vaddr_t va
, unsigned int offs
) {
293 return *(volatile u_int16_t
*)(va
.vaddr
+ offs
);
296 static inline u_int32_t
mga_readl(vaddr_t va
, unsigned int offs
) {
297 return *(volatile u_int32_t
*)(va
.vaddr
+ offs
);
300 static inline void mga_writeb(vaddr_t va
, unsigned int offs
, u_int8_t value
) {
301 *(volatile u_int8_t
*)(va
.vaddr
+ offs
) = value
;
304 static inline void mga_writew(vaddr_t va
, unsigned int offs
, u_int16_t value
) {
305 *(volatile u_int16_t
*)(va
.vaddr
+ offs
) = value
;
308 static inline void mga_writel(vaddr_t va
, unsigned int offs
, u_int32_t value
) {
309 *(volatile u_int32_t
*)(va
.vaddr
+ offs
) = value
;
313 static inline void mga_memcpy_toio(vaddr_t va
, unsigned int offs
, const void* src
, int len
) {
314 #ifdef MEMCPYTOIO_WORKS
315 memcpy_toio(va
.vaddr
+ offs
, src
, len
);
316 #elif defined(MEMCPYTOIO_WRITEL)
317 #define srcd ((const u_int32_t*)src)
320 mga_writel(va
, offs
, get_unaligned(srcd
++));
326 mga_writel(va
, offs
, *srcd
++);
335 memcpy(&tmp
, src
, len
);
336 mga_writel(va
, offs
, tmp
);
338 #elif defined(MEMCPYTOIO_MEMCPY)
339 memcpy(va
.vaddr
+ offs
, src
, len
);
341 #error "Sorry, do not know how to write block of data to device"
345 static inline void vaddr_add(vaddr_t
* va
, unsigned long offs
) {
349 static inline void* vaddr_va(vaddr_t va
) {
353 #define MGA_IOREMAP_NORMAL 0
354 #define MGA_IOREMAP_NOCACHE 1
356 #define MGA_IOREMAP_FB MGA_IOREMAP_NOCACHE
357 #define MGA_IOREMAP_MMIO MGA_IOREMAP_NOCACHE
358 static inline int mga_ioremap(unsigned long phys
, unsigned long size
, int flags
, vaddr_t
* virt
) {
360 if (flags
& MGA_IOREMAP_NOCACHE
)
361 virt
->vaddr
= ioremap_nocache(phys
, size
);
363 virt
->vaddr
= ioremap(phys
, size
);
366 virt
->vaddr
= bus_to_virt(phys
);
368 #error "Your architecture does not have neither ioremap nor bus_to_virt... Giving up"
371 return (virt
->vaddr
== 0); /* 0, !0... 0, error_code in future */
374 static inline void mga_iounmap(vaddr_t va
) {
382 unsigned int final_bppShift
;
383 unsigned int cmap_len
;
389 void (*putc
)(u_int32_t
, u_int32_t
, struct display
*, int, int, int);
390 void (*putcs
)(u_int32_t
, u_int32_t
, struct display
*, const unsigned short*, int, int, int);
394 unsigned int pixclock
;
395 unsigned int HDisplay
;
396 unsigned int HSyncStart
;
397 unsigned int HSyncEnd
;
399 unsigned int VDisplay
;
400 unsigned int VSyncStart
;
401 unsigned int VSyncEnd
;
408 struct matrox_fb_info
;
410 #define MATROX_2MB_WITH_4MB_ADDON
412 struct matrox_pll_features
{
413 unsigned int vco_freq_min
;
414 unsigned int ref_freq
;
415 unsigned int feed_div_min
;
416 unsigned int feed_div_max
;
417 unsigned int in_div_min
;
418 unsigned int in_div_max
;
419 unsigned int post_shift_max
;
422 struct matrox_DAC1064_features
{
424 unsigned int cursorimage
;
427 struct matrox_accel_features
{
431 /* current hardware status */
432 struct matrox_hw_state
{
433 u_int32_t MXoptionReg
;
434 unsigned char DACclk
[6];
435 unsigned char DACreg
[64];
436 unsigned char MiscOutReg
;
437 unsigned char DACpal
[768];
438 unsigned char CRTC
[25];
439 unsigned char CRTCEXT
[9];
440 unsigned char SEQ
[5];
441 /* unused for MGA mode, but who knows... */
442 unsigned char GCTL
[9];
443 /* unused for MGA mode, but who knows... */
444 unsigned char ATTR
[21];
447 struct matrox_accel_data
{
448 #ifdef CONFIG_FB_MATROX_MILLENIUM
449 unsigned char ramdac_rev
;
451 u_int32_t m_dwg_rect
;
455 #ifdef CONFIG_FB_MATROX_MULTIHEAD
456 #define ACCESS_FBINFO2(info, x) (info->x)
457 #define ACCESS_FBINFO(x) ACCESS_FBINFO2(minfo,x)
461 #define WPMINFO struct matrox_fb_info* minfo,
462 #define CPMINFO const struct matrox_fb_info* minfo,
463 #define PMINFO minfo,
465 static inline struct matrox_fb_info
* mxinfo(const struct display
* p
) {
466 return (struct matrox_fb_info
*)p
->fb_info
;
469 #define PMXINFO(p) mxinfo(p),
470 #define MINFO_FROM(x) struct matrox_fb_info* minfo = x
471 #define MINFO_FROM_DISP(x) MINFO_FROM(mxinfo(x))
475 struct matrox_fb_info global_mxinfo
;
476 struct display global_disp
;
478 #define ACCESS_FBINFO(x) (global_mxinfo.x)
479 #define ACCESS_FBINFO2(info, x) (global_mxinfo.x)
481 #define MINFO (&global_mxinfo)
488 static inline struct matrox_fb_info
* mxinfo(const struct display
* p
) {
489 return &global_mxinfo
;
494 #define MINFO_FROM(x)
495 #define MINFO_FROM_DISP(x)
499 struct matrox_switch
{
500 int (*preinit
)(WPMINFO
struct matrox_hw_state
*);
501 void (*reset
)(WPMINFO
struct matrox_hw_state
*);
502 int (*init
)(CPMINFO
struct matrox_hw_state
*, struct my_timming
*, struct display
*);
503 void (*restore
)(WPMINFO
struct matrox_hw_state
*, struct matrox_hw_state
*, struct display
*);
506 struct matrox_fb_info
{
507 /* fb_info must be first */
508 struct fb_info fbcon
;
510 struct matrox_fb_info
* next_fb
;
512 struct matroxfb_par curr
;
513 struct matrox_hw_state hw1
;
514 struct matrox_hw_state hw2
;
515 struct matrox_hw_state
* newhw
;
516 struct matrox_hw_state
* currenthw
;
518 struct matrox_accel_data accel
;
520 struct pci_dev
* pcidev
;
523 unsigned long base
; /* physical */
524 vaddr_t vbase
; /* CPU view */
526 unsigned int len_usable
;
530 unsigned long base
; /* physical */
531 vaddr_t vbase
; /* CPU view */
535 unsigned int max_pixel_clock
;
537 struct matrox_switch
* hw_switch
;
539 struct display
* currcon_display
;
542 struct matrox_pll_features pll
;
543 struct matrox_DAC1064_features DAC1064
;
544 struct matrox_accel_features accel
;
562 unsigned int mgabase
;
582 #ifdef CONFIG_FB_MATROX_32MB
589 unsigned int vgastep
;
590 unsigned int vgastepdisp
;
591 unsigned int textmode
;
592 unsigned int textstep
;
593 unsigned int textvram
; /* character cells */
594 unsigned int ydstorg
; /* offset in bytes from video start to usable memory */
595 /* 0 except for 6MB Millenium */
597 struct display_switch dispsw
;
607 struct timer_list timer
;
609 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
611 #ifdef FBCON_HAS_CFB16
614 #ifdef FBCON_HAS_CFB24
617 #ifdef FBCON_HAS_CFB32
622 struct { unsigned red
, green
, blue
, transp
; } palette
[256];
623 #if defined(CONFIG_FB_OF) && defined(CONFIG_FB_COMPAT_XPMAC)
624 char matrox_name
[32];
628 #if defined(CONFIG_FB_OF)
629 unsigned char nvram_read_byte(int);
630 int matrox_of_init(struct device_node
*dp
);
631 static int default_vmode
= VMODE_NVRAM
;
632 static int default_cmode
= CMODE_NVRAM
;
635 #define curr_ydstorg(x) ACCESS_FBINFO2(x, curr.ydstorg.pixels)
637 #define PCI_OPTION_REG 0x40
638 #define PCI_MGA_INDEX 0x44
639 #define PCI_MGA_DATA 0x48
641 #define M_DWGCTL 0x1C00
642 #define M_MACCESS 0x1C04
643 #define M_CTLWTST 0x1C08
645 #define M_PLNWT 0x1C1C
647 #define M_BCOL 0x1C20
648 #define M_FCOL 0x1C24
660 #define M_CXBNDRY 0x1C80
661 #define M_FXBNDRY 0x1C84
662 #define M_YDSTLEN 0x1C88
663 #define M_PITCH 0x1C8C
664 #define M_YDST 0x1C90
665 #define M_YDSTORG 0x1C94
666 #define M_YTOP 0x1C98
667 #define M_YBOT 0x1C9C
670 #define M_CACHEFLUSH 0x1FFF
672 #define M_EXEC 0x0100
674 #define M_DWG_TRAP 0x04
675 #define M_DWG_BITBLT 0x08
676 #define M_DWG_ILOAD 0x09
678 #define M_DWG_LINEAR 0x0080
679 #define M_DWG_SOLID 0x0800
680 #define M_DWG_ARZERO 0x1000
681 #define M_DWG_SGNZERO 0x2000
682 #define M_DWG_SHIFTZERO 0x4000
684 #define M_DWG_REPLACE 0x000C0000
685 #define M_DWG_REPLACE2 (M_DWG_REPLACE | 0x40)
686 #define M_DWG_XOR 0x00060010
688 #define M_DWG_BFCOL 0x04000000
689 #define M_DWG_BMONOWF 0x08000000
691 #define M_DWG_TRANSC 0x40000000
693 #define M_FIFOSTATUS 0x1E10
694 #define M_STATUS 0x1E14
698 #define M_VCOUNT 0x1E20
700 #define M_RESET 0x1E40
702 #define M_AGP2PLL 0x1E4C
704 #define M_OPMODE 0x1E54
705 #define M_OPMODE_DMA_GEN_WRITE 0x00
706 #define M_OPMODE_DMA_BLIT 0x04
707 #define M_OPMODE_DMA_VECTOR_WRITE 0x08
708 #define M_OPMODE_DMA_LE 0x0000 /* little endian - no transformation */
709 #define M_OPMODE_DMA_BE_8BPP 0x0000
710 #define M_OPMODE_DMA_BE_16BPP 0x0100
711 #define M_OPMODE_DMA_BE_32BPP 0x0200
712 #define M_OPMODE_DIR_LE 0x000000 /* little endian - no transformation */
713 #define M_OPMODE_DIR_BE_8BPP 0x000000
714 #define M_OPMODE_DIR_BE_16BPP 0x010000
715 #define M_OPMODE_DIR_BE_32BPP 0x020000
717 #define M_ATTR_INDEX 0x1FC0
718 #define M_ATTR_DATA 0x1FC1
720 #define M_MISC_REG 0x1FC2
721 #define M_3C2_RD 0x1FC2
723 #define M_SEQ_INDEX 0x1FC4
724 #define M_SEQ_DATA 0x1FC5
726 #define M_MISC_REG_READ 0x1FCC
728 #define M_GRAPHICS_INDEX 0x1FCE
729 #define M_GRAPHICS_DATA 0x1FCF
731 #define M_CRTC_INDEX 0x1FD4
733 #define M_ATTR_RESET 0x1FDA
734 #define M_3DA_WR 0x1FDA
736 #define M_EXTVGA_INDEX 0x1FDE
737 #define M_EXTVGA_DATA 0x1FDF
740 #define M_SRCORG 0x2CB4
742 #define M_RAMDAC_BASE 0x3C00
744 /* fortunately, same on TVP3026 and MGA1064 */
745 #define M_DAC_REG (M_RAMDAC_BASE+0)
746 #define M_DAC_VAL (M_RAMDAC_BASE+1)
747 #define M_PALETTE_MASK (M_RAMDAC_BASE+2)
749 #define M_X_INDEX 0x00
750 #define M_X_DATAREG 0x0A
752 #define DAC_XGENIOCTRL 0x2A
753 #define DAC_XGENIODATA 0x2B
755 #ifdef CONFIG_FB_MATROX_MILLENIUM
756 #define TVP3026_INDEX 0x00
757 #define TVP3026_PALWRADD 0x00
758 #define TVP3026_PALDATA 0x01
759 #define TVP3026_PIXRDMSK 0x02
760 #define TVP3026_PALRDADD 0x03
761 #define TVP3026_CURCOLWRADD 0x04
762 #define TVP3026_CLOVERSCAN 0x00
763 #define TVP3026_CLCOLOR0 0x01
764 #define TVP3026_CLCOLOR1 0x02
765 #define TVP3026_CLCOLOR2 0x03
766 #define TVP3026_CURCOLDATA 0x05
767 #define TVP3026_CURCOLRDADD 0x07
768 #define TVP3026_CURCTRL 0x09
769 #define TVP3026_X_DATAREG 0x0A
770 #define TVP3026_CURRAMDATA 0x0B
771 #define TVP3026_CURPOSXL 0x0C
772 #define TVP3026_CURPOSXH 0x0D
773 #define TVP3026_CURPOSYL 0x0E
774 #define TVP3026_CURPOSYH 0x0F
776 #define TVP3026_XSILICONREV 0x01
777 #define TVP3026_XCURCTRL 0x06
778 #define TVP3026_XCURCTRL_DIS 0x00 /* transparent, transparent, transparent, transparent */
779 #define TVP3026_XCURCTRL_3COLOR 0x01 /* transparent, 0, 1, 2 */
780 #define TVP3026_XCURCTRL_XGA 0x02 /* 0, 1, transparent, complement */
781 #define TVP3026_XCURCTRL_XWIN 0x03 /* transparent, transparent, 0, 1 */
782 #define TVP3026_XCURCTRL_BLANK2048 0x00
783 #define TVP3026_XCURCTRL_BLANK4096 0x10
784 #define TVP3026_XCURCTRL_INTERLACED 0x20
785 #define TVP3026_XCURCTRL_ODD 0x00 /* ext.signal ODD/\EVEN */
786 #define TVP3026_XCURCTRL_EVEN 0x40 /* ext.signal EVEN/\ODD */
787 #define TVP3026_XCURCTRL_INDIRECT 0x00
788 #define TVP3026_XCURCTRL_DIRECT 0x80
789 #define TVP3026_XLATCHCTRL 0x0F
790 #define TVP3026_XLATCHCTRL_1_1 0x06
791 #define TVP3026_XLATCHCTRL_2_1 0x07
792 #define TVP3026_XLATCHCTRL_4_1 0x06
793 #define TVP3026_XLATCHCTRL_8_1 0x06
794 #define TVP3026_XLATCHCTRL_16_1 0x06
795 #define TVP3026A_XLATCHCTRL_4_3 0x06 /* ??? do not understand... but it works... !!! */
796 #define TVP3026A_XLATCHCTRL_8_3 0x07
797 #define TVP3026B_XLATCHCTRL_4_3 0x08
798 #define TVP3026B_XLATCHCTRL_8_3 0x06 /* ??? do not understand... but it works... !!! */
799 #define TVP3026_XTRUECOLORCTRL 0x18
800 #define TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_ACCEL 0x00
801 #define TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_TVP 0x20
802 #define TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR 0x80
803 #define TVP3026_XTRUECOLORCTRL_TRUECOLOR 0x40 /* paletized */
804 #define TVP3026_XTRUECOLORCTRL_DIRECTCOLOR 0x00
805 #define TVP3026_XTRUECOLORCTRL_24_ALTERNATE 0x08 /* 5:4/5:2 instead of 4:3/8:3 */
806 #define TVP3026_XTRUECOLORCTRL_RGB_888 0x16 /* 4:3/8:3 (or 5:4/5:2) */
807 #define TVP3026_XTRUECOLORCTRL_BGR_888 0x17
808 #define TVP3026_XTRUECOLORCTRL_ORGB_8888 0x06
809 #define TVP3026_XTRUECOLORCTRL_BGRO_8888 0x07
810 #define TVP3026_XTRUECOLORCTRL_RGB_565 0x05
811 #define TVP3026_XTRUECOLORCTRL_ORGB_1555 0x04
812 #define TVP3026_XTRUECOLORCTRL_RGB_664 0x03
813 #define TVP3026_XTRUECOLORCTRL_RGBO_4444 0x01
814 #define TVP3026_XMUXCTRL 0x19
815 #define TVP3026_XMUXCTRL_MEMORY_8BIT 0x01 /* - */
816 #define TVP3026_XMUXCTRL_MEMORY_16BIT 0x02 /* - */
817 #define TVP3026_XMUXCTRL_MEMORY_32BIT 0x03 /* 2MB RAM, 512K * 4 */
818 #define TVP3026_XMUXCTRL_MEMORY_64BIT 0x04 /* >2MB RAM, 512K * 8 & more */
819 #define TVP3026_XMUXCTRL_PIXEL_4BIT 0x40 /* L0,H0,L1,H1... */
820 #define TVP3026_XMUXCTRL_PIXEL_4BIT_SWAPPED 0x60 /* H0,L0,H1,L1... */
821 #define TVP3026_XMUXCTRL_PIXEL_8BIT 0x48
822 #define TVP3026_XMUXCTRL_PIXEL_16BIT 0x50
823 #define TVP3026_XMUXCTRL_PIXEL_32BIT 0x58
824 #define TVP3026_XMUXCTRL_VGA 0x98 /* VGA MEMORY, 8BIT PIXEL */
825 #define TVP3026_XCLKCTRL 0x1A
826 #define TVP3026_XCLKCTRL_DIV1 0x00
827 #define TVP3026_XCLKCTRL_DIV2 0x10
828 #define TVP3026_XCLKCTRL_DIV4 0x20
829 #define TVP3026_XCLKCTRL_DIV8 0x30
830 #define TVP3026_XCLKCTRL_DIV16 0x40
831 #define TVP3026_XCLKCTRL_DIV32 0x50
832 #define TVP3026_XCLKCTRL_DIV64 0x60
833 #define TVP3026_XCLKCTRL_CLKSTOPPED 0x70
834 #define TVP3026_XCLKCTRL_SRC_CLK0 0x00
835 #define TVP3026_XCLKCTRL_SRC_CLK1 0x01
836 #define TVP3026_XCLKCTRL_SRC_CLK2 0x02 /* CLK2 is TTL source*/
837 #define TVP3026_XCLKCTRL_SRC_NCLK2 0x03 /* not CLK2 is TTL source */
838 #define TVP3026_XCLKCTRL_SRC_ECLK2 0x04 /* CLK2 and not CLK2 is ECL source */
839 #define TVP3026_XCLKCTRL_SRC_PLL 0x05
840 #define TVP3026_XCLKCTRL_SRC_DIS 0x06 /* disable & poweroff internal clock */
841 #define TVP3026_XCLKCTRL_SRC_CLK0VGA 0x07
842 #define TVP3026_XPALETTEPAGE 0x1C
843 #define TVP3026_XGENCTRL 0x1D
844 #define TVP3026_XGENCTRL_HSYNC_POS 0x00
845 #define TVP3026_XGENCTRL_HSYNC_NEG 0x01
846 #define TVP3026_XGENCTRL_VSYNC_POS 0x00
847 #define TVP3026_XGENCTRL_VSYNC_NEG 0x02
848 #define TVP3026_XGENCTRL_LITTLE_ENDIAN 0x00
849 #define TVP3026_XGENCTRL_BIG_ENDIAN 0x08
850 #define TVP3026_XGENCTRL_BLACK_0IRE 0x00
851 #define TVP3026_XGENCTRL_BLACK_75IRE 0x10
852 #define TVP3026_XGENCTRL_NO_SYNC_ON_GREEN 0x00
853 #define TVP3026_XGENCTRL_SYNC_ON_GREEN 0x20
854 #define TVP3026_XGENCTRL_OVERSCAN_DIS 0x00
855 #define TVP3026_XGENCTRL_OVERSCAN_EN 0x40
856 #define TVP3026_XMISCCTRL 0x1E
857 #define TVP3026_XMISCCTRL_DAC_PUP 0x00
858 #define TVP3026_XMISCCTRL_DAC_PDOWN 0x01
859 #define TVP3026_XMISCCTRL_DAC_EXT 0x00 /* or 8, bit 3 is ignored */
860 #define TVP3026_XMISCCTRL_DAC_6BIT 0x04
861 #define TVP3026_XMISCCTRL_DAC_8BIT 0x0C
862 #define TVP3026_XMISCCTRL_PSEL_DIS 0x00
863 #define TVP3026_XMISCCTRL_PSEL_EN 0x10
864 #define TVP3026_XMISCCTRL_PSEL_LOW 0x00 /* PSEL high selects directcolor */
865 #define TVP3026_XMISCCTRL_PSEL_HIGH 0x20 /* PSEL high selects truecolor or pseudocolor */
866 #define TVP3026_XGENIOCTRL 0x2A
867 #define TVP3026_XGENIODATA 0x2B
868 #define TVP3026_XPLLADDR 0x2C
869 #define TVP3026_XPLLADDR_X(LOOP,MCLK,PIX) (((LOOP)<<4) | ((MCLK)<<2) | (PIX))
870 #define TVP3026_XPLLDATA_N 0x00
871 #define TVP3026_XPLLDATA_M 0x01
872 #define TVP3026_XPLLDATA_P 0x02
873 #define TVP3026_XPLLDATA_STAT 0x03
874 #define TVP3026_XPIXPLLDATA 0x2D
875 #define TVP3026_XMEMPLLDATA 0x2E
876 #define TVP3026_XLOOPPLLDATA 0x2F
877 #define TVP3026_XCOLKEYOVRMIN 0x30
878 #define TVP3026_XCOLKEYOVRMAX 0x31
879 #define TVP3026_XCOLKEYREDMIN 0x32
880 #define TVP3026_XCOLKEYREDMAX 0x33
881 #define TVP3026_XCOLKEYGREENMIN 0x34
882 #define TVP3026_XCOLKEYGREENMAX 0x35
883 #define TVP3026_XCOLKEYBLUEMIN 0x36
884 #define TVP3026_XCOLKEYBLUEMAX 0x37
885 #define TVP3026_XCOLKEYCTRL 0x38
886 #define TVP3026_XCOLKEYCTRL_OVR_EN 0x01
887 #define TVP3026_XCOLKEYCTRL_RED_EN 0x02
888 #define TVP3026_XCOLKEYCTRL_GREEN_EN 0x04
889 #define TVP3026_XCOLKEYCTRL_BLUE_EN 0x08
890 #define TVP3026_XCOLKEYCTRL_NEGATE 0x10
891 #define TVP3026_XCOLKEYCTRL_ZOOM1 0x00
892 #define TVP3026_XCOLKEYCTRL_ZOOM2 0x20
893 #define TVP3026_XCOLKEYCTRL_ZOOM4 0x40
894 #define TVP3026_XCOLKEYCTRL_ZOOM8 0x60
895 #define TVP3026_XCOLKEYCTRL_ZOOM16 0x80
896 #define TVP3026_XCOLKEYCTRL_ZOOM32 0xA0
897 #define TVP3026_XMEMPLLCTRL 0x39
898 #define TVP3026_XMEMPLLCTRL_DIV(X) (((X)-1)>>1) /* 2,4,6,8,10,12,14,16, division applied to LOOP PLL after divide by 2^P */
899 #define TVP3026_XMEMPLLCTRL_STROBEMKC4 0x08
900 #define TVP3026_XMEMPLLCTRL_MCLK_DOTCLOCK 0x00 /* MKC4 */
901 #define TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL 0x10 /* MKC4 */
902 #define TVP3026_XMEMPLLCTRL_RCLK_PIXPLL 0x00
903 #define TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL 0x20
904 #define TVP3026_XMEMPLLCTRL_RCLK_DOTDIVN 0x40 /* dot clock divided by loop pclk N prescaler */
905 #define TVP3026_XSENSETEST 0x3A
906 #define TVP3026_XTESTMODEDATA 0x3B
907 #define TVP3026_XCRCREML 0x3C
908 #define TVP3026_XCRCREMH 0x3D
909 #define TVP3026_XCRCBITSEL 0x3E
910 #define TVP3026_XID 0x3F
916 #define DAC1064_OPT_SCLK_PCI 0x00
917 #define DAC1064_OPT_SCLK_PLL 0x01
918 #define DAC1064_OPT_SCLK_EXT 0x02
919 #define DAC1064_OPT_SCLK_MASK 0x03
920 #define DAC1064_OPT_GDIV1 0x04 /* maybe it is GDIV2 on G100 ?! */
921 #define DAC1064_OPT_GDIV3 0x00
922 #define DAC1064_OPT_MDIV1 0x08
923 #define DAC1064_OPT_MDIV2 0x00
924 #define DAC1064_OPT_RESERVED 0x10
926 #define M1064_INDEX 0x00
927 #define M1064_PALWRADD 0x00
928 #define M1064_PALDATA 0x01
929 #define M1064_PIXRDMSK 0x02
930 #define M1064_PALRDADD 0x03
931 #define M1064_X_DATAREG 0x0A
932 #define M1064_CURPOSXL 0x0C /* can be accessed as DWORD */
933 #define M1064_CURPOSXH 0x0D
934 #define M1064_CURPOSYL 0x0E
935 #define M1064_CURPOSYH 0x0F
937 #define M1064_XCURADDL 0x04
938 #define M1064_XCURADDH 0x05
939 #define M1064_XCURCTRL 0x06
940 #define M1064_XCURCTRL_DIS 0x00 /* transparent, transparent, transparent, transparent */
941 #define M1064_XCURCTRL_3COLOR 0x01 /* transparent, 0, 1, 2 */
942 #define M1064_XCURCTRL_XGA 0x02 /* 0, 1, transparent, complement */
943 #define M1064_XCURCTRL_XWIN 0x03 /* transparent, transparent, 0, 1 */
944 #define M1064_XCURCOL0RED 0x08
945 #define M1064_XCURCOL0GREEN 0x09
946 #define M1064_XCURCOL0BLUE 0x0A
947 #define M1064_XCURCOL1RED 0x0C
948 #define M1064_XCURCOL1GREEN 0x0D
949 #define M1064_XCURCOL1BLUE 0x0E
950 #define M1064_XCURCOL2RED 0x10
951 #define M1064_XCURCOL2GREEN 0x11
952 #define M1064_XCURCOL2BLUE 0x12
953 #define DAC1064_XVREFCTRL 0x18
954 #define DAC1064_XVREFCTRL_INTERNAL 0x3F
955 #define DAC1064_XVREFCTRL_EXTERNAL 0x00
956 #define DAC1064_XVREFCTRL_G100_DEFAULT 0x03
957 #define M1064_XMULCTRL 0x19
958 #define M1064_XMULCTRL_DEPTH_8BPP 0x00 /* 8 bpp paletized */
959 #define M1064_XMULCTRL_DEPTH_15BPP_1BPP 0x01 /* 15 bpp paletized + 1 bpp overlay */
960 #define M1064_XMULCTRL_DEPTH_16BPP 0x02 /* 16 bpp paletized */
961 #define M1064_XMULCTRL_DEPTH_24BPP 0x03 /* 24 bpp paletized */
962 #define M1064_XMULCTRL_DEPTH_24BPP_8BPP 0x04 /* 24 bpp direct + 8 bpp overlay paletized */
963 #define M1064_XMULCTRL_2G8V16 0x05 /* 15 bpp video direct, half xres, 8bpp paletized */
964 #define M1064_XMULCTRL_G16V16 0x06 /* 15 bpp video, 15bpp graphics, one of them paletized */
965 #define M1064_XMULCTRL_DEPTH_32BPP 0x07 /* 24 bpp paletized + 8 bpp unused */
966 #define M1064_XMULCTRL_GRAPHICS_PALETIZED 0x00
967 #define M1064_XMULCTRL_VIDEO_PALETIZED 0x08
968 #define M1064_XPIXCLKCTRL 0x1A
969 #define M1064_XPIXCLKCTRL_SRC_PCI 0x00
970 #define M1064_XPIXCLKCTRL_SRC_PLL 0x01
971 #define M1064_XPIXCLKCTRL_SRC_EXT 0x02
972 #define M1064_XPIXCLKCTRL_SRC_MASK 0x03
973 #define M1064_XPIXCLKCTRL_EN 0x00
974 #define M1064_XPIXCLKCTRL_DIS 0x04
975 #define M1064_XPIXCLKCTRL_PLL_DOWN 0x00
976 #define M1064_XPIXCLKCTRL_PLL_UP 0x08
977 #define M1064_XGENCTRL 0x1D
978 #define M1064_XGENCTRL_VS_0 0x00
979 #define M1064_XGENCTRL_VS_1 0x01
980 #define M1064_XGENCTRL_ALPHA_DIS 0x00
981 #define M1064_XGENCTRL_ALPHA_EN 0x02
982 #define M1064_XGENCTRL_BLACK_0IRE 0x00
983 #define M1064_XGENCTRL_BLACK_75IRE 0x10
984 #define M1064_XGENCTRL_SYNC_ON_GREEN 0x00
985 #define M1064_XGENCTRL_NO_SYNC_ON_GREEN 0x20
986 #define M1064_XGENCTRL_SYNC_ON_GREEN_MASK 0x20
987 #define M1064_XMISCCTRL 0x1E
988 #define M1064_XMISCCTRL_DAC_DIS 0x00
989 #define M1064_XMISCCTRL_DAC_EN 0x01
990 #define M1064_XMISCCTRL_MFC_VGA 0x00
991 #define M1064_XMISCCTRL_MFC_MAFC 0x02
992 #define M1064_XMISCCTRL_MFC_DIS 0x06
993 #define M1064_XMISCCTRL_DAC_6BIT 0x00
994 #define M1064_XMISCCTRL_DAC_8BIT 0x08
995 #define M1064_XMISCCTRL_LUT_DIS 0x00
996 #define M1064_XMISCCTRL_LUT_EN 0x10
997 #define M1064_XGENIOCTRL 0x2A
998 #define M1064_XGENIODATA 0x2B
999 #define DAC1064_XSYSPLLM 0x2C
1000 #define DAC1064_XSYSPLLN 0x2D
1001 #define DAC1064_XSYSPLLP 0x2E
1002 #define DAC1064_XSYSPLLSTAT 0x2F
1003 #define M1064_XZOOMCTRL 0x38
1004 #define M1064_XZOOMCTRL_1 0x00
1005 #define M1064_XZOOMCTRL_2 0x01
1006 #define M1064_XZOOMCTRL_4 0x03
1007 #define M1064_XSENSETEST 0x3A
1008 #define M1064_XSENSETEST_BCOMP 0x01
1009 #define M1064_XSENSETEST_GCOMP 0x02
1010 #define M1064_XSENSETEST_RCOMP 0x04
1011 #define M1064_XSENSETEST_PDOWN 0x00
1012 #define M1064_XSENSETEST_PUP 0x80
1013 #define M1064_XCRCREML 0x3C
1014 #define M1064_XCRCREMH 0x3D
1015 #define M1064_XCRCBITSEL 0x3E
1016 #define M1064_XCOLKEYMASKL 0x40
1017 #define M1064_XCOLKEYMASKH 0x41
1018 #define M1064_XCOLKEYL 0x42
1019 #define M1064_XCOLKEYH 0x43
1020 #define M1064_XPIXPLLAM 0x44
1021 #define M1064_XPIXPLLAN 0x45
1022 #define M1064_XPIXPLLAP 0x46
1023 #define M1064_XPIXPLLBM 0x48
1024 #define M1064_XPIXPLLBN 0x49
1025 #define M1064_XPIXPLLBP 0x4A
1026 #define M1064_XPIXPLLCM 0x4C
1027 #define M1064_XPIXPLLCN 0x4D
1028 #define M1064_XPIXPLLCP 0x4E
1029 #define M1064_XPIXPLLSTAT 0x4F
1033 #ifdef __LITTLE_ENDIAN
1034 #define MX_OPTION_BSWAP 0x00000000
1036 #define M_OPMODE_4BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
1037 #define M_OPMODE_8BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
1038 #define M_OPMODE_16BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
1039 #define M_OPMODE_24BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
1040 #define M_OPMODE_32BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
1043 #define MX_OPTION_BSWAP 0x80000000
1045 #define M_OPMODE_4BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT) /* TODO */
1046 #define M_OPMODE_8BPP (M_OPMODE_DMA_BE_8BPP | M_OPMODE_DIR_BE_8BPP | M_OPMODE_DMA_BLIT)
1047 #define M_OPMODE_16BPP (M_OPMODE_DMA_BE_16BPP | M_OPMODE_DIR_BE_16BPP | M_OPMODE_DMA_BLIT)
1048 #define M_OPMODE_24BPP (M_OPMODE_DMA_BE_8BPP | M_OPMODE_DIR_BE_8BPP | M_OPMODE_DMA_BLIT) /* TODO, ?32 */
1049 #define M_OPMODE_32BPP (M_OPMODE_DMA_BE_32BPP | M_OPMODE_DIR_BE_32BPP | M_OPMODE_DMA_BLIT)
1051 #error "Byte ordering have to be defined. Cannot continue."
1055 #define mga_inb(addr) mga_readb(ACCESS_FBINFO(mmio.vbase), (addr))
1056 #define mga_inl(addr) mga_readl(ACCESS_FBINFO(mmio.vbase), (addr))
1057 #define mga_outb(addr,val) mga_writeb(ACCESS_FBINFO(mmio.vbase), (addr), (val))
1058 #define mga_outw(addr,val) mga_writew(ACCESS_FBINFO(mmio.vbase), (addr), (val))
1059 #define mga_outl(addr,val) mga_writel(ACCESS_FBINFO(mmio.vbase), (addr), (val))
1060 #define mga_readr(port,idx) (mga_outb((port),(idx)), mga_inb((port)+1))
1061 #ifdef __LITTLE_ENDIAN
1062 #define mga_setr(addr,port,val) mga_outw(addr, ((val)<<8) | (port))
1064 #define mga_setr(addr,port,val) do { mga_outb(addr, port); mga_outb((addr)+1, val); } while (0)
1067 #ifdef __LITTLE_ENDIAN
1068 #define mga_fifo(n) do {} while (mga_inb(M_FIFOSTATUS) < (n))
1070 #define mga_fifo(n) do {} while ((mga_inl(M_FIFOSTATUS) & 0xFF) < (n))
1073 #define WaitTillIdle() do {} while (mga_inl(M_STATUS) & 0x10000)
1076 #ifdef CONFIG_FB_MATROX_MILLENIUM
1077 #define isInterleave(x) (x->interleave)
1078 #define isMillenium(x) (x->millenium)
1079 #define isMilleniumII(x) (x->milleniumII)
1081 #define isInterleave(x) (0)
1082 #define isMillenium(x) (0)
1083 #define isMilleniumII(x) (0)
1086 #ifdef MATROXFB_DEBUG_REENTER
1087 static atomic_t guard_counter
= ATOMIC_INIT(1);
1088 static atomic_t guard_printing
= ATOMIC_INIT(1);
1089 static void guard_start(void) {
1090 if (atomic_dec_and_test(&guard_counter
)) { /* first level */
1091 if (!(bh_mask
& (1 << CONSOLE_BH
))) /* and CONSOLE_BH disabled */
1093 /* otherwise it is first level with CONSOLE_BH enabled -
1094 - if we are __sti or SMP, reentering from console_bh possible */
1095 atomic_dec(&guard_printing
); /* disable reentrancy warning */
1096 printk(KERN_DEBUG
"matroxfb entered without CONSOLE_BH disabled\n");
1100 atomic_inc(&guard_printing
);
1103 /* real reentering... You should be already warned by code above */
1104 if (atomic_dec_and_test(&guard_printing
)) {
1109 atomic_inc(&guard_printing
);
1112 static inline void guard_end(void) {
1113 atomic_inc(&guard_counter
);
1116 #define CRITBEGIN guard_start();
1117 #define CRITEND guard_end();
1126 #define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l))
1128 static void matrox_cfbX_init(WPMINFO
struct display
* p
) {
1133 DBG("matrox_cfbX_init")
1135 mpitch
= p
->var
.xres_virtual
;
1137 if (p
->type
== FB_TYPE_TEXT
) {
1138 maccess
= 0x00000000;
1139 mpitch
= (mpitch
>> 4) | 0x8000; /* set something */
1140 mopmode
= M_OPMODE_8BPP
;
1142 switch (p
->var
.bits_per_pixel
) {
1143 case 4: maccess
= 0x00000000; /* accelerate as 8bpp video */
1144 mpitch
= (mpitch
>> 1) | 0x8000; /* disable linearization */
1145 mopmode
= M_OPMODE_4BPP
;
1147 case 8: maccess
= 0x00000000;
1148 mopmode
= M_OPMODE_8BPP
;
1150 case 16: if (p
->var
.green
.length
== 5)
1151 maccess
= 0xC0000001;
1153 maccess
= 0x40000001;
1154 mopmode
= M_OPMODE_16BPP
;
1156 case 24: maccess
= 0x00000003;
1157 mopmode
= M_OPMODE_24BPP
;
1159 case 32: maccess
= 0x00000002;
1160 mopmode
= M_OPMODE_32BPP
;
1162 default: maccess
= 0x00000000;
1163 mopmode
= 0x00000000;
1164 break; /* turn off acceleration!!! */
1168 mga_outl(M_PITCH
, mpitch
);
1169 mga_outl(M_YDSTORG
, curr_ydstorg(MINFO
));
1170 if (ACCESS_FBINFO(capable
.plnwt
))
1171 mga_outl(M_PLNWT
, -1);
1172 mga_outl(M_OPMODE
, mopmode
);
1173 mga_outl(M_CXBNDRY
, 0xFFFF0000);
1174 mga_outl(M_YTOP
, 0);
1175 mga_outl(M_YBOT
, 0x01FFFFFF);
1176 mga_outl(M_MACCESS
, maccess
);
1177 ACCESS_FBINFO(accel
.m_dwg_rect
) = M_DWG_TRAP
| M_DWG_SOLID
| M_DWG_ARZERO
| M_DWG_SGNZERO
| M_DWG_SHIFTZERO
;
1178 if (isMilleniumII(MINFO
)) ACCESS_FBINFO(accel
.m_dwg_rect
) |= M_DWG_TRANSC
;
1179 ACCESS_FBINFO(accel
.m_opmode
) = mopmode
;
1182 static void matrox_cfbX_bmove(struct display
* p
, int sy
, int sx
, int dy
, int dx
, int height
, int width
) {
1183 int pixx
= p
->var
.xres_virtual
, start
, end
;
1186 DBG("matrox_cfbX_bmove")
1192 width
*= fontwidth(p
);
1193 height
*= fontheight(p
);
1194 sy
*= fontheight(p
);
1195 dy
*= fontheight(p
);
1196 if ((dy
< sy
) || ((dy
== sy
) && (dx
<= sx
))) {
1198 mga_outl(M_DWGCTL
, M_DWG_BITBLT
| M_DWG_SHIFTZERO
| M_DWG_SGNZERO
|
1199 M_DWG_BFCOL
| M_DWG_REPLACE
);
1200 mga_outl(M_AR5
, pixx
);
1202 start
= sy
*pixx
+sx
+curr_ydstorg(MINFO
);
1206 mga_outl(M_DWGCTL
, M_DWG_BITBLT
| M_DWG_SHIFTZERO
| M_DWG_BFCOL
| M_DWG_REPLACE
);
1208 mga_outl(M_AR5
, -pixx
);
1210 end
= (sy
+height
-1)*pixx
+sx
+curr_ydstorg(MINFO
);
1215 mga_outl(M_AR0
, end
);
1216 mga_outl(M_AR3
, start
);
1217 mga_outl(M_FXBNDRY
, ((dx
+width
)<<16) | dx
);
1218 mga_ydstlen(dy
, height
);
1224 #ifdef FBCON_HAS_CFB4
1225 static void matrox_cfb4_bmove(struct display
* p
, int sy
, int sx
, int dy
, int dx
, int height
, int width
) {
1226 int pixx
, start
, end
;
1228 /* both (sx or dx or width) and fontwidth() are odd, so their multiply is
1229 also odd, that means that we cannot use acceleration */
1231 DBG("matrox_cfb4_bmove")
1235 if ((sx
| dx
| width
) & fontwidth(p
) & 1) {
1236 fbcon_cfb4_bmove(p
, sy
, sx
, dy
, dx
, height
, width
);
1241 width
*= fontwidth(p
);
1242 height
*= fontheight(p
);
1243 sy
*= fontheight(p
);
1244 dy
*= fontheight(p
);
1245 pixx
= p
->var
.xres_virtual
>> 1;
1249 if ((dy
< sy
) || ((dy
== sy
) && (dx
<= sx
))) {
1251 mga_outl(M_AR5
, pixx
);
1252 mga_outl(M_DWGCTL
, M_DWG_BITBLT
| M_DWG_SHIFTZERO
| M_DWG_SGNZERO
|
1253 M_DWG_BFCOL
| M_DWG_REPLACE
);
1255 start
= sy
*pixx
+sx
+curr_ydstorg(MINFO
);
1260 mga_outl(M_AR5
, -pixx
);
1261 mga_outl(M_DWGCTL
, M_DWG_BITBLT
| M_DWG_SHIFTZERO
| M_DWG_BFCOL
| M_DWG_REPLACE
);
1263 end
= (sy
+height
-1)*pixx
+sx
+curr_ydstorg(MINFO
);
1268 mga_outl(M_AR0
, end
);
1269 mga_outl(M_AR3
, start
);
1270 mga_outl(M_FXBNDRY
, ((dx
+width
)<<16) | dx
);
1271 mga_outl(M_YDST
, dy
*pixx
>> 5);
1272 mga_outl(M_LEN
| M_EXEC
, height
);
1279 static void matroxfb_accel_clear(CPMINFO u_int32_t color
, int sy
, int sx
, int height
,
1282 DBG("matroxfb_accel_clear")
1287 mga_outl(M_DWGCTL
, ACCESS_FBINFO(accel
.m_dwg_rect
) | M_DWG_REPLACE
);
1288 mga_outl(M_FCOL
, color
);
1289 mga_outl(M_FXBNDRY
, ((sx
+ width
) << 16) | sx
);
1290 mga_ydstlen(sy
, height
);
1296 static void matrox_cfbX_clear(u_int32_t color
, struct display
* p
, int sy
, int sx
, int height
, int width
) {
1298 DBG("matrox_cfbX_clear")
1300 matroxfb_accel_clear(PMXINFO(p
) color
, sy
* fontheight(p
), sx
* fontwidth(p
),
1301 height
* fontheight(p
), width
* fontwidth(p
));
1304 #ifdef FBCON_HAS_CFB4
1305 static void matrox_cfb4_clear(struct vc_data
* conp
, struct display
* p
, int sy
, int sx
, int height
, int width
) {
1310 DBG("matrox_cfb4_clear")
1315 bgx
= attr_bgcol_ec(p
, conp
);
1319 sy
*= fontheight(p
);
1321 height
*= fontheight(p
);
1322 width
*= fontwidth(p
);
1336 mga_outl(M_DWGCTL
, ACCESS_FBINFO(accel
.m_dwg_rect
) | M_DWG_REPLACE2
);
1337 mga_outl(M_FCOL
, bgx
);
1338 mga_outl(M_FXBNDRY
, ((sx
+ width
) << 16) | sx
);
1339 mga_outl(M_YDST
, sy
* p
->var
.xres_virtual
>> 6);
1340 mga_outl(M_LEN
| M_EXEC
, height
);
1344 u_int32_t step
= p
->var
.xres_virtual
>> 1;
1345 vaddr_t vbase
= ACCESS_FBINFO(video
.vbase
);
1347 unsigned int uaddr
= sy
* step
+ sx
- 1;
1349 u_int8_t bgx2
= bgx
& 0xF0;
1350 for (loop
= height
; loop
> 0; loop
--) {
1351 mga_writeb(vbase
, uaddr
, (mga_readb(vbase
, uaddr
) & 0x0F) | bgx2
);
1356 unsigned int uaddr
= sy
* step
+ sx
+ width
;
1358 u_int8_t bgx2
= bgx
& 0x0F;
1359 for (loop
= height
; loop
> 0; loop
--) {
1360 mga_writeb(vbase
, uaddr
, (mga_readb(vbase
, uaddr
) & 0xF0) | bgx2
);
1370 #ifdef FBCON_HAS_CFB8
1371 static void matrox_cfb8_clear(struct vc_data
* conp
, struct display
* p
, int sy
, int sx
, int height
, int width
) {
1374 DBG("matrox_cfb8_clear")
1376 bgx
= attr_bgcol_ec(p
, conp
);
1379 matrox_cfbX_clear(bgx
, p
, sy
, sx
, height
, width
);
1383 #ifdef FBCON_HAS_CFB16
1384 static void matrox_cfb16_clear(struct vc_data
* conp
, struct display
* p
, int sy
, int sx
, int height
, int width
) {
1387 DBG("matrox_cfb16_clear")
1389 bgx
= ((u_int16_t
*)p
->dispsw_data
)[attr_bgcol_ec(p
, conp
)];
1390 matrox_cfbX_clear((bgx
<< 16) | bgx
, p
, sy
, sx
, height
, width
);
1394 #if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
1395 static void matrox_cfb32_clear(struct vc_data
* conp
, struct display
* p
, int sy
, int sx
, int height
, int width
) {
1398 DBG("matrox_cfb32_clear")
1400 bgx
= ((u_int32_t
*)p
->dispsw_data
)[attr_bgcol_ec(p
, conp
)];
1401 matrox_cfbX_clear(bgx
, p
, sy
, sx
, height
, width
);
1405 static void matrox_cfbX_fastputc(u_int32_t fgx
, u_int32_t bgx
, struct display
* p
, int c
, int yy
, int xx
) {
1406 unsigned int charcell
;
1410 charcell
= fontwidth(p
) * fontheight(p
);
1411 yy
*= fontheight(p
);
1417 mga_outl(M_DWGCTL
, M_DWG_BITBLT
| M_DWG_SGNZERO
| M_DWG_SHIFTZERO
| M_DWG_BMONOWF
| M_DWG_LINEAR
| M_DWG_REPLACE
);
1419 mga_outl(M_FCOL
, fgx
);
1420 mga_outl(M_BCOL
, bgx
);
1421 mga_outl(M_FXBNDRY
, ((xx
+ fontwidth(p
) - 1) << 16) | xx
);
1422 ar3
= ACCESS_FBINFO(fastfont
.mgabase
) + (c
& p
->charmask
) * charcell
;
1423 mga_outl(M_AR3
, ar3
);
1424 mga_outl(M_AR0
, (ar3
+ charcell
- 1) & 0x0003FFFF);
1425 mga_ydstlen(yy
, fontheight(p
));
1431 static void matrox_cfbX_putc(u_int32_t fgx
, u_int32_t bgx
, struct display
* p
, int c
, int yy
, int xx
) {
1436 DBG_HEAVY("matrox_cfbX_putc");
1438 yy
*= fontheight(p
);
1445 mga_outl(M_OPMODE
, M_OPMODE_8BPP
);
1449 ar0
= fontwidth(p
) - 1;
1450 mga_outl(M_FXBNDRY
, ((xx
+ar0
)<<16) | xx
);
1451 if (fontwidth(p
) <= 8)
1453 else if (fontwidth(p
) <= 16)
1457 if (fontwidth(p
) == step
<< 3) {
1458 size_t charcell
= fontheight(p
)*step
;
1459 /* TODO: Align charcell to 4B for BE */
1460 mga_outl(M_DWGCTL
, M_DWG_ILOAD
| M_DWG_SGNZERO
| M_DWG_SHIFTZERO
| M_DWG_BMONOWF
| M_DWG_LINEAR
| M_DWG_REPLACE
);
1461 mga_outl(M_FCOL
, fgx
);
1462 mga_outl(M_BCOL
, bgx
);
1464 mga_outl(M_AR0
, fontheight(p
)*fontwidth(p
)-1);
1465 mga_ydstlen(yy
, fontheight(p
));
1466 mga_memcpy_toio(ACCESS_FBINFO(mmio
.vbase
), 0, p
->fontdata
+(c
&p
->charmask
)*charcell
, charcell
);
1468 u8
* chardata
= p
->fontdata
+(c
&p
->charmask
)*fontheight(p
)*step
;
1471 mga_outl(M_DWGCTL
, M_DWG_ILOAD
| M_DWG_SGNZERO
| M_DWG_SHIFTZERO
| M_DWG_BMONOWF
| M_DWG_REPLACE
);
1472 mga_outl(M_FCOL
, fgx
);
1473 mga_outl(M_BCOL
, bgx
);
1476 mga_outl(M_AR0
, ar0
);
1477 mga_ydstlen(yy
, fontheight(p
));
1481 for (i
= fontheight(p
); i
> 0; i
--) {
1482 #ifdef __LITTLE_ENDIAN
1483 mga_outl(0, *chardata
++);
1485 mga_outl(0, (*chardata
++) << 24);
1490 for (i
= fontheight(p
); i
> 0; i
--) {
1491 #ifdef __LITTLE_ENDIAN
1492 mga_outl(0, *(u_int16_t
*)chardata
);
1494 mga_outl(0, (*(u_int16_t
*)chardata
) << 16);
1500 mga_memcpy_toio(ACCESS_FBINFO(mmio
.vbase
), 0, chardata
, fontheight(p
) * 4);
1506 mga_outl(M_OPMODE
, ACCESS_FBINFO(accel
.m_opmode
));
1511 #ifdef FBCON_HAS_CFB8
1512 static void matrox_cfb8_putc(struct vc_data
* conp
, struct display
* p
, int c
, int yy
, int xx
) {
1516 DBG_HEAVY("matroxfb_cfb8_putc");
1518 fgx
= attr_fgcol(p
, c
);
1519 bgx
= attr_bgcol(p
, c
);
1524 ACCESS_FBINFO(curr
.putc
)(fgx
, bgx
, p
, c
, yy
, xx
);
1528 #ifdef FBCON_HAS_CFB16
1529 static void matrox_cfb16_putc(struct vc_data
* conp
, struct display
* p
, int c
, int yy
, int xx
) {
1533 DBG_HEAVY("matroxfb_cfb16_putc");
1535 fgx
= ((u_int16_t
*)p
->dispsw_data
)[attr_fgcol(p
, c
)];
1536 bgx
= ((u_int16_t
*)p
->dispsw_data
)[attr_bgcol(p
, c
)];
1539 ACCESS_FBINFO(curr
.putc
)(fgx
, bgx
, p
, c
, yy
, xx
);
1543 #if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
1544 static void matrox_cfb32_putc(struct vc_data
* conp
, struct display
* p
, int c
, int yy
, int xx
) {
1548 DBG_HEAVY("matroxfb_cfb32_putc");
1550 fgx
= ((u_int32_t
*)p
->dispsw_data
)[attr_fgcol(p
, c
)];
1551 bgx
= ((u_int32_t
*)p
->dispsw_data
)[attr_bgcol(p
, c
)];
1552 ACCESS_FBINFO(curr
.putc
)(fgx
, bgx
, p
, c
, yy
, xx
);
1556 static void matrox_cfbX_fastputcs(u_int32_t fgx
, u_int32_t bgx
, struct display
* p
, const unsigned short* s
, int count
, int yy
, int xx
) {
1557 unsigned int charcell
;
1560 yy
*= fontheight(p
);
1562 charcell
= fontwidth(p
) * fontheight(p
);
1567 mga_outl(M_DWGCTL
, M_DWG_BITBLT
| M_DWG_SGNZERO
| M_DWG_SHIFTZERO
| M_DWG_BMONOWF
| M_DWG_LINEAR
| M_DWG_REPLACE
);
1568 mga_outl(M_FCOL
, fgx
);
1569 mga_outl(M_BCOL
, bgx
);
1571 u_int32_t ar3
= ACCESS_FBINFO(fastfont
.mgabase
) + (scr_readw(s
++) & p
->charmask
)*charcell
;
1574 mga_outl(M_FXBNDRY
, ((xx
+ fontwidth(p
) - 1) << 16) | xx
);
1575 mga_outl(M_AR3
, ar3
);
1576 mga_outl(M_AR0
, (ar3
+ charcell
- 1) & 0x0003FFFF);
1577 mga_ydstlen(yy
, fontheight(p
));
1585 static void matrox_cfbX_putcs(u_int32_t fgx
, u_int32_t bgx
, struct display
* p
, const unsigned short* s
, int count
, int yy
, int xx
) {
1596 DBG_HEAVY("matroxfb_cfbX_putcs");
1598 yy
*= fontheight(p
);
1600 if (fontwidth(p
) <= 8)
1602 else if (fontwidth(p
) <= 16)
1606 charcell
= fontheight(p
)*step
;
1607 xlen
= (charcell
+ 3) & ~3;
1608 ydstlen
= (yy
<< 16) | fontheight(p
);
1609 if (fontwidth(p
) == step
<< 3) {
1610 ar0
= fontheight(p
)*fontwidth(p
) - 1;
1613 ar0
= fontwidth(p
) - 1;
1621 mga_outl(M_OPMODE
, M_OPMODE_8BPP
);
1626 mga_outl(M_DWGCTL
, M_DWG_ILOAD
| M_DWG_SGNZERO
| M_DWG_SHIFTZERO
| M_DWG_BMONOWF
| M_DWG_LINEAR
| M_DWG_REPLACE
);
1628 mga_outl(M_DWGCTL
, M_DWG_ILOAD
| M_DWG_SGNZERO
| M_DWG_SHIFTZERO
| M_DWG_BMONOWF
| M_DWG_REPLACE
);
1629 mga_outl(M_FCOL
, fgx
);
1630 mga_outl(M_BCOL
, bgx
);
1631 fxbndry
= ((xx
+ fontwidth(p
) - 1) << 16) | xx
;
1632 mmio
= ACCESS_FBINFO(mmio
.vbase
);
1634 u_int8_t
* chardata
= p
->fontdata
+ (scr_readw(s
++) & p
->charmask
)*charcell
;
1637 mga_writel(mmio
, M_FXBNDRY
, fxbndry
);
1638 mga_writel(mmio
, M_AR0
, ar0
);
1639 mga_writel(mmio
, M_AR3
, 0);
1641 mga_writel(mmio
, M_YDSTLEN
| M_EXEC
, ydstlen
);
1642 mga_memcpy_toio(mmio
, 0, chardata
, xlen
);
1644 mga_writel(mmio
, M_AR5
, 0);
1645 mga_writel(mmio
, M_YDSTLEN
| M_EXEC
, ydstlen
);
1648 u_int8_t
* charend
= chardata
+ charcell
;
1649 for (; chardata
!= charend
; chardata
++) {
1650 #ifdef __LITTLE_ENDIAN
1651 mga_writel(mmio
, 0, *chardata
);
1653 mga_writel(mmio
, 0, (*chardata
) << 24);
1659 u_int8_t
* charend
= chardata
+ charcell
;
1660 for (; chardata
!= charend
; chardata
+= 2) {
1661 #ifdef __LITTLE_ENDIAN
1662 mga_writel(mmio
, 0, *(u_int16_t
*)chardata
);
1664 mga_writel(mmio
, 0, (*(u_int16_t
*)chardata
) << 16);
1670 mga_memcpy_toio(mmio
, 0, chardata
, charcell
);
1674 fxbndry
+= fontwidth(p
) + (fontwidth(p
) << 16);
1678 mga_outl(M_OPMODE
, ACCESS_FBINFO(accel
.m_opmode
));
1683 #ifdef FBCON_HAS_CFB8
1684 static void matrox_cfb8_putcs(struct vc_data
* conp
, struct display
* p
, const unsigned short* s
, int count
, int yy
, int xx
) {
1688 DBG_HEAVY("matroxfb_cfb8_putcs");
1690 fgx
= attr_fgcol(p
, scr_readw(s
));
1691 bgx
= attr_bgcol(p
, scr_readw(s
));
1696 ACCESS_FBINFO(curr
.putcs
)(fgx
, bgx
, p
, s
, count
, yy
, xx
);
1700 #ifdef FBCON_HAS_CFB16
1701 static void matrox_cfb16_putcs(struct vc_data
* conp
, struct display
* p
, const unsigned short* s
, int count
, int yy
, int xx
) {
1705 DBG_HEAVY("matroxfb_cfb16_putcs");
1707 fgx
= ((u_int16_t
*)p
->dispsw_data
)[attr_fgcol(p
, scr_readw(s
))];
1708 bgx
= ((u_int16_t
*)p
->dispsw_data
)[attr_bgcol(p
, scr_readw(s
))];
1711 ACCESS_FBINFO(curr
.putcs
)(fgx
, bgx
, p
, s
, count
, yy
, xx
);
1715 #if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
1716 static void matrox_cfb32_putcs(struct vc_data
* conp
, struct display
* p
, const unsigned short* s
, int count
, int yy
, int xx
) {
1720 DBG_HEAVY("matroxfb_cfb32_putcs");
1722 fgx
= ((u_int32_t
*)p
->dispsw_data
)[attr_fgcol(p
, scr_readw(s
))];
1723 bgx
= ((u_int32_t
*)p
->dispsw_data
)[attr_bgcol(p
, scr_readw(s
))];
1724 ACCESS_FBINFO(curr
.putcs
)(fgx
, bgx
, p
, s
, count
, yy
, xx
);
1728 #ifdef FBCON_HAS_CFB4
1729 static void matrox_cfb4_revc(struct display
* p
, int xx
, int yy
) {
1732 DBG_LOOP("matroxfb_cfb4_revc");
1734 if (fontwidth(p
) & 1) {
1735 fbcon_cfb4_revc(p
, xx
, yy
);
1738 yy
*= fontheight(p
);
1740 xx
|= (xx
+ fontwidth(p
)) << 16;
1746 mga_outl(M_DWGCTL
, ACCESS_FBINFO(accel
.m_dwg_rect
) | M_DWG_XOR
);
1747 mga_outl(M_FCOL
, 0xFFFFFFFF);
1748 mga_outl(M_FXBNDRY
, xx
);
1749 mga_outl(M_YDST
, yy
* p
->var
.xres_virtual
>> 6);
1750 mga_outl(M_LEN
| M_EXEC
, fontheight(p
));
1757 #ifdef FBCON_HAS_CFB8
1758 static void matrox_cfb8_revc(struct display
* p
, int xx
, int yy
) {
1761 DBG_LOOP("matrox_cfb8_revc")
1763 yy
*= fontheight(p
);
1769 mga_outl(M_DWGCTL
, ACCESS_FBINFO(accel
.m_dwg_rect
) | M_DWG_XOR
);
1770 mga_outl(M_FCOL
, 0x0F0F0F0F);
1771 mga_outl(M_FXBNDRY
, ((xx
+ fontwidth(p
)) << 16) | xx
);
1772 mga_ydstlen(yy
, fontheight(p
));
1779 static void matrox_cfbX_revc(struct display
* p
, int xx
, int yy
) {
1782 DBG_LOOP("matrox_cfbX_revc")
1784 yy
*= fontheight(p
);
1790 mga_outl(M_DWGCTL
, ACCESS_FBINFO(accel
.m_dwg_rect
) | M_DWG_XOR
);
1791 mga_outl(M_FCOL
, 0xFFFFFFFF);
1792 mga_outl(M_FXBNDRY
, ((xx
+ fontwidth(p
)) << 16) | xx
);
1793 mga_ydstlen(yy
, fontheight(p
));
1799 static void matrox_cfbX_clear_margins(struct vc_data
* conp
, struct display
* p
, int bottom_only
) {
1800 unsigned int bottom_height
, right_width
;
1801 unsigned int bottom_start
, right_start
;
1802 unsigned int cell_h
, cell_w
;
1804 DBG("matrox_cfbX_clear_margins")
1806 cell_w
= fontwidth(p
);
1807 if (!cell_w
) return; /* PARANOID */
1808 right_width
= p
->var
.xres
% cell_w
;
1809 right_start
= p
->var
.xres
- right_width
;
1810 if (!bottom_only
&& right_width
) {
1811 /* clear whole right margin, not only visible portion */
1812 matroxfb_accel_clear( PMXINFO(p
)
1813 /* color */ 0x00000000,
1815 /* x */ p
->var
.xoffset
+ right_start
,
1816 /* height */ p
->var
.yres_virtual
,
1817 /* width */ right_width
);
1819 cell_h
= fontheight(p
);
1820 if (!cell_h
) return; /* PARANOID */
1821 bottom_height
= p
->var
.yres
% cell_h
;
1822 if (bottom_height
) {
1823 bottom_start
= p
->var
.yres
- bottom_height
;
1824 matroxfb_accel_clear( PMXINFO(p
)
1825 /* color */ 0x00000000,
1826 /* y */ p
->var
.yoffset
+ bottom_start
,
1827 /* x */ p
->var
.xoffset
,
1828 /* height */ bottom_height
,
1829 /* width */ right_start
);
1833 static void outDAC(CPMINFO
int reg
, int val
) {
1835 mga_outb(M_RAMDAC_BASE
+M_X_INDEX
, reg
);
1836 mga_outb(M_RAMDAC_BASE
+M_X_DATAREG
, val
);
1839 static int inDAC(CPMINFO
int reg
) {
1841 mga_outb(M_RAMDAC_BASE
+M_X_INDEX
, reg
);
1842 return mga_inb(M_RAMDAC_BASE
+M_X_DATAREG
);
1845 #define outTi3026 outDAC
1846 #define inTi3026 inDAC
1847 #define outDAC1064 outDAC
1848 #define inDAC1064 inDAC
1850 static void matroxfb_createcursorshape(WPMINFO
struct display
* p
, int vmode
) {
1852 unsigned int cu
, cd
;
1856 if (vmode
& FB_VMODE_DOUBLE
)
1861 switch (ACCESS_FBINFO(cursor
.type
) = (p
->conp
->vc_cursor_type
& CUR_HWMASK
)) {
1868 case CUR_LOWER_THIRD
:
1871 case CUR_LOWER_HALF
:
1874 case CUR_TWO_THIRDS
:
1883 ACCESS_FBINFO(cursor
.w
) = fontwidth(p
);
1884 ACCESS_FBINFO(cursor
.u
) = cu
;
1885 ACCESS_FBINFO(cursor
.d
) = cd
;
1888 #ifdef CONFIG_FB_MATROX_MILLENIUM
1889 #define POS3026_XCURCTRL 20
1891 static void matroxfb_ti3026_flashcursor(unsigned long ptr
) {
1892 #define minfo ((struct matrox_fb_info*)ptr)
1893 spin_lock(&ACCESS_FBINFO(lock
.DAC
));
1894 outTi3026(PMINFO TVP3026_XCURCTRL
, inTi3026(PMINFO TVP3026_XCURCTRL
) ^ TVP3026_XCURCTRL_DIS
^ TVP3026_XCURCTRL_XGA
);
1895 ACCESS_FBINFO(cursor
.timer
.expires
) = jiffies
+ HZ
/2;
1896 add_timer(&ACCESS_FBINFO(cursor
.timer
));
1897 spin_unlock(&ACCESS_FBINFO(lock
.DAC
));
1901 static void matroxfb_ti3026_createcursor(WPMINFO
struct display
* p
) {
1902 unsigned long flags
;
1907 if (ACCESS_FBINFO(currcon_display
) != p
)
1910 DBG("matroxfb_ti3026_createcursor");
1912 matroxfb_createcursorshape(PMINFO p
, p
->var
.vmode
);
1914 xline
= (~0) << (32 - ACCESS_FBINFO(cursor
.w
));
1915 spin_lock_irqsave(&ACCESS_FBINFO(lock
.DAC
), flags
);
1916 mga_outb(M_RAMDAC_BASE
+TVP3026_INDEX
, 0);
1917 to
= ACCESS_FBINFO(cursor
.u
);
1918 for (i
= 0; i
< to
; i
++) {
1919 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1920 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1921 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1922 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1923 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1924 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1925 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1926 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1928 to
= ACCESS_FBINFO(cursor
.d
);
1929 for (; i
< to
; i
++) {
1930 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, xline
>> 24);
1931 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, xline
>> 16);
1932 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, xline
>> 8);
1933 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, xline
);
1934 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1935 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1936 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1937 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1939 for (; i
< 64; i
++) {
1940 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1941 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1942 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1943 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1944 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1945 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1946 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1947 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0);
1949 for (i
= 0; i
< 512; i
++)
1950 mga_outb(M_RAMDAC_BASE
+TVP3026_CURRAMDATA
, 0xFF);
1951 spin_unlock_irqrestore(&ACCESS_FBINFO(lock
.DAC
), flags
);
1954 static void matroxfb_ti3026_cursor(struct display
* p
, int mode
, int x
, int y
) {
1955 unsigned long flags
;
1958 DBG("matroxfb_ti3026_cursor")
1960 if (ACCESS_FBINFO(currcon_display
) != p
)
1963 if (mode
== CM_ERASE
) {
1964 if (ACCESS_FBINFO(cursor
.state
) != CM_ERASE
) {
1965 spin_lock_irqsave(&ACCESS_FBINFO(lock
.DAC
), flags
);
1966 ACCESS_FBINFO(cursor
.state
) = CM_ERASE
;
1967 del_timer(&ACCESS_FBINFO(cursor
.timer
));
1968 outTi3026(PMINFO TVP3026_XCURCTRL
, ACCESS_FBINFO(currenthw
->DACreg
[POS3026_XCURCTRL
]));
1969 spin_unlock_irqrestore(&ACCESS_FBINFO(lock
.DAC
), flags
);
1973 if ((p
->conp
->vc_cursor_type
& CUR_HWMASK
) != ACCESS_FBINFO(cursor
.type
))
1974 matroxfb_ti3026_createcursor(PMINFO p
);
1977 y
-= p
->var
.yoffset
;
1978 if (p
->var
.vmode
& FB_VMODE_DOUBLE
)
1980 spin_lock_irqsave(&ACCESS_FBINFO(lock
.DAC
), flags
);
1981 if ((x
!= ACCESS_FBINFO(cursor
.x
)) || (y
!= ACCESS_FBINFO(cursor
.y
)) || ACCESS_FBINFO(cursor
.redraw
)) {
1982 ACCESS_FBINFO(cursor
.redraw
) = 0;
1983 ACCESS_FBINFO(cursor
.x
) = x
;
1984 ACCESS_FBINFO(cursor
.y
) = y
;
1987 outTi3026(PMINFO TVP3026_XCURCTRL
, ACCESS_FBINFO(currenthw
->DACreg
[POS3026_XCURCTRL
]));
1988 mga_outb(M_RAMDAC_BASE
+TVP3026_CURPOSXL
, x
);
1989 mga_outb(M_RAMDAC_BASE
+TVP3026_CURPOSXH
, x
>> 8);
1990 mga_outb(M_RAMDAC_BASE
+TVP3026_CURPOSYL
, y
);
1991 mga_outb(M_RAMDAC_BASE
+TVP3026_CURPOSYH
, y
>> 8);
1993 ACCESS_FBINFO(cursor
.state
) = CM_DRAW
;
1994 if (ACCESS_FBINFO(devflags
.blink
))
1995 mod_timer(&ACCESS_FBINFO(cursor
.timer
), jiffies
+ HZ
/2);
1996 outTi3026(PMINFO TVP3026_XCURCTRL
, ACCESS_FBINFO(currenthw
->DACreg
[POS3026_XCURCTRL
]) | TVP3026_XCURCTRL_XGA
);
1997 spin_unlock_irqrestore(&ACCESS_FBINFO(lock
.DAC
), flags
);
1999 #undef POS3026_XCURCTRL
2001 static int matroxfb_ti3026_setfont(struct display
* p
, int width
, int height
) {
2003 DBG("matrox_ti3026_setfont");
2006 matroxfb_ti3026_createcursor(PMXINFO(p
) p
);
2013 static void matroxfb_DAC1064_flashcursor(unsigned long ptr
) {
2014 #define minfo ((struct matrox_fb_info*)ptr)
2015 spin_lock(&ACCESS_FBINFO(lock
.DAC
));
2016 outDAC1064(PMINFO M1064_XCURCTRL
, inDAC1064(PMINFO M1064_XCURCTRL
) ^ M1064_XCURCTRL_DIS
^ M1064_XCURCTRL_XGA
);
2017 ACCESS_FBINFO(cursor
.timer
.expires
) = jiffies
+ HZ
/2;
2018 add_timer(&ACCESS_FBINFO(cursor
.timer
));
2019 spin_unlock(&ACCESS_FBINFO(lock
.DAC
));
2023 static void matroxfb_DAC1064_createcursor(WPMINFO
struct display
* p
) {
2029 if (ACCESS_FBINFO(currcon_display
) != p
)
2032 matroxfb_createcursorshape(PMINFO p
, p
->var
.vmode
);
2034 xline
= (~0) << (32 - ACCESS_FBINFO(cursor
.w
));
2035 cursorbase
= ACCESS_FBINFO(video
.vbase
);
2036 h
= ACCESS_FBINFO(features
.DAC1064
.cursorimage
);
2042 mga_outl(M_OPMODE
, M_OPMODE_32BPP
);
2044 to
= ACCESS_FBINFO(cursor
.u
);
2045 for (i
= 0; i
< to
; i
++) {
2046 mga_writel(cursorbase
, h
, 0);
2047 mga_writel(cursorbase
, h
+4, 0);
2048 mga_writel(cursorbase
, h
+8, ~0);
2049 mga_writel(cursorbase
, h
+12, ~0);
2052 to
= ACCESS_FBINFO(cursor
.d
);
2053 for (; i
< to
; i
++) {
2054 mga_writel(cursorbase
, h
, 0);
2055 mga_writel(cursorbase
, h
+4, xline
);
2056 mga_writel(cursorbase
, h
+8, ~0);
2057 mga_writel(cursorbase
, h
+12, ~0);
2060 for (; i
< 64; i
++) {
2061 mga_writel(cursorbase
, h
, 0);
2062 mga_writel(cursorbase
, h
+4, 0);
2063 mga_writel(cursorbase
, h
+8, ~0);
2064 mga_writel(cursorbase
, h
+12, ~0);
2068 mga_outl(M_OPMODE
, ACCESS_FBINFO(accel
.m_opmode
));
2074 static void matroxfb_DAC1064_cursor(struct display
* p
, int mode
, int x
, int y
) {
2075 unsigned long flags
;
2078 if (ACCESS_FBINFO(currcon_display
) != p
)
2081 if (mode
== CM_ERASE
) {
2082 if (ACCESS_FBINFO(cursor
.state
) != CM_ERASE
) {
2083 spin_lock_irqsave(&ACCESS_FBINFO(lock
.DAC
), flags
);
2084 ACCESS_FBINFO(cursor
.state
) = CM_ERASE
;
2085 del_timer(&ACCESS_FBINFO(cursor
.timer
));
2086 outDAC1064(PMINFO M1064_XCURCTRL
, M1064_XCURCTRL_DIS
);
2087 spin_unlock_irqrestore(&ACCESS_FBINFO(lock
.DAC
), flags
);
2091 if ((p
->conp
->vc_cursor_type
& CUR_HWMASK
) != ACCESS_FBINFO(cursor
.type
))
2092 matroxfb_DAC1064_createcursor(PMINFO p
);
2095 y
-= p
->var
.yoffset
;
2096 if (p
->var
.vmode
& FB_VMODE_DOUBLE
)
2098 spin_lock_irqsave(&ACCESS_FBINFO(lock
.DAC
), flags
);
2099 if ((x
!= ACCESS_FBINFO(cursor
.x
)) || (y
!= ACCESS_FBINFO(cursor
.y
)) || ACCESS_FBINFO(cursor
.redraw
)) {
2100 ACCESS_FBINFO(cursor
.redraw
) = 0;
2101 ACCESS_FBINFO(cursor
.x
) = x
;
2102 ACCESS_FBINFO(cursor
.y
) = y
;
2105 outDAC1064(PMINFO M1064_XCURCTRL
, M1064_XCURCTRL_DIS
);
2106 mga_outb(M_RAMDAC_BASE
+M1064_CURPOSXL
, x
);
2107 mga_outb(M_RAMDAC_BASE
+M1064_CURPOSXH
, x
>> 8);
2108 mga_outb(M_RAMDAC_BASE
+M1064_CURPOSYL
, y
);
2109 mga_outb(M_RAMDAC_BASE
+M1064_CURPOSYH
, y
>> 8);
2111 ACCESS_FBINFO(cursor
.state
) = CM_DRAW
;
2112 if (ACCESS_FBINFO(devflags
.blink
))
2113 mod_timer(&ACCESS_FBINFO(cursor
.timer
), jiffies
+ HZ
/2);
2114 outDAC1064(PMINFO M1064_XCURCTRL
, M1064_XCURCTRL_XGA
);
2115 spin_unlock_irqrestore(&ACCESS_FBINFO(lock
.DAC
), flags
);
2118 static int matroxfb_DAC1064_setfont(struct display
* p
, int width
, int height
) {
2120 matroxfb_DAC1064_createcursor(PMXINFO(p
) p
);
2126 #define FNTCHARCNT(fd) (((int *)(fd))[-3])
2129 static int matroxfb_fastfont_tryset(WPMINFO
struct display
* p
) {
2133 if (!p
|| !p
->fontdata
)
2135 width
= fontwidth(p
);
2138 fsize
= (p
->userfont
?FNTCHARCNT(p
->fontdata
):256) * fontheight(p
);
2139 if (((fsize
* width
+ 31) / 32) * 4 > ACCESS_FBINFO(fastfont
.size
))
2144 mga_outl(M_OPMODE
, M_OPMODE_8BPP
);
2147 mga_memcpy_toio(ACCESS_FBINFO(fastfont
.vbase
), 0, p
->fontdata
, fsize
);
2152 u_int32_t mask
, valid
, reg
;
2154 dst
= ACCESS_FBINFO(fastfont
.vbase
);
2155 font
= (u_int8_t
*)p
->fontdata
;
2156 mask
= ~0 << (8 - width
);
2161 reg
|= (*font
++ & mask
) << (8 - valid
);
2164 mga_writeb(dst
, i
++, reg
>> 8);
2170 mga_writeb(dst
, i
, reg
>> 8);
2172 } else if (width
<= 16) {
2174 mga_memcpy_toio(ACCESS_FBINFO(fastfont
.vbase
), 0, p
->fontdata
, fsize
*2);
2178 u_int32_t mask
, valid
, reg
;
2181 dst
= ACCESS_FBINFO(fastfont
.vbase
);
2182 font
= (u_int16_t
*)p
->fontdata
;
2183 mask
= ~0 << (16 - width
);
2188 reg
|= (ntohs(*font
++) & mask
) << (16 - valid
);
2191 mga_writew(dst
, i
, htons(reg
>> 16));
2198 mga_writew(dst
, i
, htons(reg
>> 16));
2202 mga_memcpy_toio(ACCESS_FBINFO(fastfont
.vbase
), 0, p
->fontdata
, fsize
*4);
2206 u_int32_t mask
, valid
, reg
;
2209 dst
= ACCESS_FBINFO(fastfont
.vbase
);
2210 font
= (u_int32_t
*)p
->fontdata
;
2211 mask
= ~0 << (32 - width
);
2216 reg
|= (ntohl(*font
) & mask
) >> valid
;
2219 mga_writel(dst
, i
, htonl(reg
));
2223 reg
= (ntohl(*font
) & mask
) << (width
- valid
);
2230 mga_writel(dst
, i
, htonl(reg
));
2233 mga_outl(M_OPMODE
, ACCESS_FBINFO(accel
.m_opmode
));
2240 static void matrox_text_setup(struct display
* p
) {
2243 p
->next_line
= p
->line_length
? p
->line_length
: ((p
->var
.xres_virtual
/ (fontwidth(p
)?fontwidth(p
):8)) * ACCESS_FBINFO(devflags
.textstep
));
2247 static void matrox_text_bmove(struct display
* p
, int sy
, int sx
, int dy
, int dx
,
2248 int height
, int width
) {
2249 unsigned int srcoff
;
2250 unsigned int dstoff
;
2256 step
= ACCESS_FBINFO(devflags
.textstep
);
2257 srcoff
= (sy
* p
->next_line
) + (sx
* step
);
2258 dstoff
= (dy
* p
->next_line
) + (dx
* step
);
2259 if (dstoff
< srcoff
) {
2260 while (height
> 0) {
2262 for (i
= width
; i
> 0; dstoff
+= step
, srcoff
+= step
, i
--)
2263 mga_writew(ACCESS_FBINFO(video
.vbase
), dstoff
, mga_readw(ACCESS_FBINFO(video
.vbase
), srcoff
));
2265 dstoff
+= p
->next_line
- width
* step
;
2266 srcoff
+= p
->next_line
- width
* step
;
2271 off
= (height
- 1) * p
->next_line
+ (width
- 1) * step
;
2274 while (height
> 0) {
2276 for (i
= width
; i
> 0; dstoff
-= step
, srcoff
-= step
, i
--)
2277 mga_writew(ACCESS_FBINFO(video
.vbase
), dstoff
, mga_readw(ACCESS_FBINFO(video
.vbase
), srcoff
));
2278 dstoff
-= p
->next_line
- width
* step
;
2279 srcoff
-= p
->next_line
- width
* step
;
2286 static void matrox_text_clear(struct vc_data
* conp
, struct display
* p
, int sy
, int sx
,
2287 int height
, int width
) {
2293 step
= ACCESS_FBINFO(devflags
.textstep
);
2294 offs
= sy
* p
->next_line
+ sx
* step
;
2295 val
= ntohs((attr_bgcol(p
, conp
->vc_video_erase_char
) << 4) | attr_fgcol(p
, conp
->vc_video_erase_char
) | (' ' << 8));
2299 while (height
> 0) {
2301 for (i
= width
; i
> 0; offs
+= step
, i
--)
2302 mga_writew(ACCESS_FBINFO(video
.vbase
), offs
, val
);
2303 offs
+= p
->next_line
- width
* step
;
2309 static void matrox_text_putc(struct vc_data
* conp
, struct display
* p
, int c
, int yy
, int xx
) {
2315 step
= ACCESS_FBINFO(devflags
.textstep
);
2316 offs
= yy
* p
->next_line
+ xx
* step
;
2317 chr
= attr_fgcol(p
,c
) | (attr_bgcol(p
,c
) << 4) | ((c
& p
->charmask
) << 8);
2318 if (chr
& 0x10000) chr
|= 0x08;
2322 mga_writew(ACCESS_FBINFO(video
.vbase
), offs
, ntohs(chr
));
2327 static void matrox_text_putcs(struct vc_data
* conp
, struct display
* p
, const unsigned short* s
,
2328 int count
, int yy
, int xx
) {
2334 step
= ACCESS_FBINFO(devflags
.textstep
);
2335 offs
= yy
* p
->next_line
+ xx
* step
;
2336 attr
= attr_fgcol(p
, scr_readw(s
)) | (attr_bgcol(p
, scr_readw(s
)) << 4);
2340 while (count
-- > 0) {
2341 unsigned int chr
= ((scr_readw(s
++)) & p
->charmask
) << 8;
2342 if (chr
& 0x10000) chr
^= 0x10008;
2343 mga_writew(ACCESS_FBINFO(video
.vbase
), offs
, ntohs(attr
|chr
));
2350 static void matrox_text_revc(struct display
* p
, int xx
, int yy
) {
2355 step
= ACCESS_FBINFO(devflags
.textstep
);
2356 offs
= yy
* p
->next_line
+ xx
* step
+ 1;
2360 mga_writeb(ACCESS_FBINFO(video
.vbase
), offs
, mga_readb(ACCESS_FBINFO(video
.vbase
), offs
) ^ 0x77);
2365 static int matrox_text_loadfont(WPMINFO
struct display
* p
) {
2372 if (!p
|| !p
->fontdata
)
2374 width
= fontwidth(p
);
2375 fsize
= p
->userfont
?FNTCHARCNT(p
->fontdata
):256;
2377 dst
= ACCESS_FBINFO(video
.vbase
);
2379 font
= (u_int8_t
*)p
->fontdata
;
2383 mga_setr(M_SEQ_INDEX
, 0x02, 0x04);
2387 for (l
= 0; l
< fontheight(p
); l
++) {
2388 mga_writeb(dst
, i
, *font
++);
2389 if (fontwidth(p
) > 8) font
++;
2390 i
+= ACCESS_FBINFO(devflags
.vgastep
);
2392 i
+= (32 - fontheight(p
)) * ACCESS_FBINFO(devflags
.vgastep
);
2394 mga_setr(M_SEQ_INDEX
, 0x02, 0x03);
2401 static void matrox_text_createcursor(WPMINFO
struct display
* p
) {
2403 if (ACCESS_FBINFO(currcon_display
) != p
)
2406 matroxfb_createcursorshape(PMINFO p
, 0);
2410 mga_setr(M_CRTC_INDEX
, 0x0A, ACCESS_FBINFO(cursor
.u
));
2411 mga_setr(M_CRTC_INDEX
, 0x0B, ACCESS_FBINFO(cursor
.d
) - 1);
2416 static void matrox_text_cursor(struct display
* p
, int mode
, int x
, int y
) {
2420 if (ACCESS_FBINFO(currcon_display
) != p
)
2423 if (mode
== CM_ERASE
) {
2424 if (ACCESS_FBINFO(cursor
.state
) != CM_ERASE
) {
2428 mga_setr(M_CRTC_INDEX
, 0x0A, 0x20);
2432 ACCESS_FBINFO(cursor
.state
) = CM_ERASE
;
2436 if ((p
->conp
->vc_cursor_type
& CUR_HWMASK
) != ACCESS_FBINFO(cursor
.type
))
2437 matrox_text_createcursor(PMINFO p
);
2439 /* DO NOT CHECK cursor.x != x because of vgaHWinit moves cursor to 0,0 */
2440 ACCESS_FBINFO(cursor
.x
) = x
;
2441 ACCESS_FBINFO(cursor
.y
) = y
;
2442 pos
= p
->next_line
/ ACCESS_FBINFO(devflags
.textstep
) * y
+ x
;
2446 mga_setr(M_CRTC_INDEX
, 0x0F, pos
);
2447 mga_setr(M_CRTC_INDEX
, 0x0E, pos
>> 8);
2449 mga_setr(M_CRTC_INDEX
, 0x0A, ACCESS_FBINFO(cursor
.u
));
2453 ACCESS_FBINFO(cursor
.state
) = CM_DRAW
;
2456 static void matrox_text_round(CPMINFO
struct fb_var_screeninfo
* var
, struct display
* p
) {
2464 /* do not touch xres */
2465 vxres
= (var
->xres_virtual
+ hf
- 1) / hf
;
2470 vxres
= (vxres
+ 1) & ~1; /* must be even */
2473 if (var
->yres
< var
->yres_virtual
) {
2474 ych
= ACCESS_FBINFO(devflags
.textvram
) / vxres
;
2475 var
->yres_virtual
= ych
* vf
;
2477 ych
= var
->yres_virtual
/ vf
;
2478 if (vxres
* ych
> ACCESS_FBINFO(devflags
.textvram
)) {
2479 ych
= ACCESS_FBINFO(devflags
.textvram
) / vxres
;
2480 var
->yres_virtual
= ych
* vf
;
2482 var
->xres_virtual
= vxres
* hf
;
2485 static int matrox_text_setfont(struct display
* p
, int width
, int height
) {
2486 DBG("matrox_text_setfont");
2491 matrox_text_round(PMINFO
&p
->var
, p
);
2492 p
->next_line
= p
->line_length
= ((p
->var
.xres_virtual
/ (fontwidth(p
)?fontwidth(p
):8)) * ACCESS_FBINFO(devflags
.textstep
));
2495 matrox_text_createcursor(PMINFO p
);
2500 #define matrox_cfb16_revc matrox_cfbX_revc
2501 #define matrox_cfb24_revc matrox_cfbX_revc
2502 #define matrox_cfb32_revc matrox_cfbX_revc
2504 #define matrox_cfb24_clear matrox_cfb32_clear
2505 #define matrox_cfb24_putc matrox_cfb32_putc
2506 #define matrox_cfb24_putcs matrox_cfb32_putcs
2508 #ifdef FBCON_HAS_VGATEXT
2509 static struct display_switch matroxfb_text
= {
2510 matrox_text_setup
, matrox_text_bmove
, matrox_text_clear
,
2511 matrox_text_putc
, matrox_text_putcs
, matrox_text_revc
,
2512 matrox_text_cursor
, matrox_text_setfont
, NULL
,
2513 FONTWIDTH(8)|FONTWIDTH(9)
2517 #ifdef FBCON_HAS_CFB4
2518 static struct display_switch matroxfb_cfb4
= {
2519 fbcon_cfb4_setup
, matrox_cfb4_bmove
, matrox_cfb4_clear
,
2520 fbcon_cfb4_putc
, fbcon_cfb4_putcs
, matrox_cfb4_revc
,
2522 /* cursor... */ /* set_font... */
2523 FONTWIDTH(8) /* fix, fix, fix it */
2527 #ifdef FBCON_HAS_CFB8
2528 static struct display_switch matroxfb_cfb8
= {
2529 fbcon_cfb8_setup
, matrox_cfbX_bmove
, matrox_cfb8_clear
,
2530 matrox_cfb8_putc
, matrox_cfb8_putcs
, matrox_cfb8_revc
,
2531 NULL
, NULL
, matrox_cfbX_clear_margins
,
2536 #ifdef FBCON_HAS_CFB16
2537 static struct display_switch matroxfb_cfb16
= {
2538 fbcon_cfb16_setup
, matrox_cfbX_bmove
, matrox_cfb16_clear
,
2539 matrox_cfb16_putc
, matrox_cfb16_putcs
, matrox_cfb16_revc
,
2540 NULL
, NULL
, matrox_cfbX_clear_margins
,
2545 #ifdef FBCON_HAS_CFB24
2546 static struct display_switch matroxfb_cfb24
= {
2547 fbcon_cfb24_setup
, matrox_cfbX_bmove
, matrox_cfb24_clear
,
2548 matrox_cfb24_putc
, matrox_cfb24_putcs
, matrox_cfb24_revc
,
2549 NULL
, NULL
, matrox_cfbX_clear_margins
,
2550 ~1 /* FONTWIDTHS */ /* TODO: and what about non-aligned access on BE? I think that there are no in my code */
2554 #ifdef FBCON_HAS_CFB32
2555 static struct display_switch matroxfb_cfb32
= {
2556 fbcon_cfb32_setup
, matrox_cfbX_bmove
, matrox_cfb32_clear
,
2557 matrox_cfb32_putc
, matrox_cfb32_putcs
, matrox_cfb32_revc
,
2558 NULL
, NULL
, matrox_cfbX_clear_margins
,
2563 static struct pci_dev
* pci_find(struct pci_dev
* p
) {
2567 if (p
) return p
->next
;
2571 static void initMatrox(WPMINFO
struct display
* p
) {
2572 struct display_switch
*swtmp
;
2576 if (ACCESS_FBINFO(currcon_display
) != p
)
2578 if (p
->dispsw
&& p
->conp
)
2579 fb_con
.con_cursor(p
->conp
, CM_ERASE
);
2580 p
->dispsw_data
= NULL
;
2581 if ((p
->var
.accel_flags
& FB_ACCELF_TEXT
) != FB_ACCELF_TEXT
) {
2582 if (p
->type
== FB_TYPE_TEXT
) {
2583 swtmp
= &matroxfb_text
;
2585 switch (p
->var
.bits_per_pixel
) {
2586 #ifdef FBCON_HAS_CFB4
2588 swtmp
= &fbcon_cfb4
;
2591 #ifdef FBCON_HAS_CFB8
2593 swtmp
= &fbcon_cfb8
;
2596 #ifdef FBCON_HAS_CFB16
2598 p
->dispsw_data
= &ACCESS_FBINFO(cmap
.cfb16
);
2599 swtmp
= &fbcon_cfb16
;
2602 #ifdef FBCON_HAS_CFB24
2604 p
->dispsw_data
= &ACCESS_FBINFO(cmap
.cfb24
);
2605 swtmp
= &fbcon_cfb24
;
2608 #ifdef FBCON_HAS_CFB32
2610 p
->dispsw_data
= &ACCESS_FBINFO(cmap
.cfb32
);
2611 swtmp
= &fbcon_cfb32
;
2615 p
->dispsw
= &fbcon_dummy
;
2619 dprintk(KERN_INFO
"matroxfb: acceleration disabled\n");
2620 } else if (p
->type
== FB_TYPE_TEXT
) {
2621 swtmp
= &matroxfb_text
;
2623 switch (p
->var
.bits_per_pixel
) {
2624 #ifdef FBCON_HAS_CFB4
2626 swtmp
= &matroxfb_cfb4
;
2629 #ifdef FBCON_HAS_CFB8
2631 swtmp
= &matroxfb_cfb8
;
2634 #ifdef FBCON_HAS_CFB16
2636 p
->dispsw_data
= &ACCESS_FBINFO(cmap
.cfb16
);
2637 swtmp
= &matroxfb_cfb16
;
2640 #ifdef FBCON_HAS_CFB24
2642 p
->dispsw_data
= &ACCESS_FBINFO(cmap
.cfb24
);
2643 swtmp
= &matroxfb_cfb24
;
2646 #ifdef FBCON_HAS_CFB32
2648 p
->dispsw_data
= &ACCESS_FBINFO(cmap
.cfb32
);
2649 swtmp
= &matroxfb_cfb32
;
2653 p
->dispsw
= &fbcon_dummy
;
2657 memcpy(&ACCESS_FBINFO(dispsw
), swtmp
, sizeof(ACCESS_FBINFO(dispsw
)));
2658 p
->dispsw
= &ACCESS_FBINFO(dispsw
);
2659 if ((p
->type
!= FB_TYPE_TEXT
) && ACCESS_FBINFO(devflags
.hwcursor
)) {
2660 if (isMillenium(MINFO
)) {
2661 #ifdef CONFIG_FB_MATROX_MILLENIUM
2662 ACCESS_FBINFO(dispsw
.cursor
) = matroxfb_ti3026_cursor
;
2663 ACCESS_FBINFO(dispsw
.set_font
) = matroxfb_ti3026_setfont
;
2667 ACCESS_FBINFO(dispsw
.cursor
) = matroxfb_DAC1064_cursor
;
2668 ACCESS_FBINFO(dispsw
.set_font
) = matroxfb_DAC1064_setfont
;
2674 /* --------------------------------------------------------------------- */
2680 /* --------------------------------------------------------------------- */
2682 static struct fb_var_screeninfo vesafb_defined __initdata
= {
2683 640,480,640,480,/* W,H, W, H (virtual) load xres,xres_virtual*/
2684 0,0, /* virtual -> visible no offset */
2685 8, /* depth -> load bits_per_pixel */
2686 0, /* greyscale ? */
2690 {0,0,0}, /* transparency */
2691 0, /* standard pixel format */
2694 FB_ACCELF_TEXT
, /* accel flags */
2695 39721L,48L,16L,33L,10L,
2696 96L,2L,~0, /* No sync info */
2697 FB_VMODE_NONINTERLACED
,
2703 /* --------------------------------------------------------------------- */
2705 static void matrox_pan_var(WPMINFO
struct fb_var_screeninfo
*var
) {
2707 unsigned short p0
, p1
, p2
;
2708 #ifdef CONFIG_FB_MATROX_32MB
2711 struct display
*disp
;
2713 DBG("matrox_pan_var")
2715 disp
= ACCESS_FBINFO(currcon_display
);
2716 if (disp
->type
== FB_TYPE_TEXT
) {
2717 pos
= var
->yoffset
/ fontheight(disp
) * disp
->next_line
/ ACCESS_FBINFO(devflags
.textstep
) + var
->xoffset
/ (fontwidth(disp
)?fontwidth(disp
):8);
2719 pos
= (var
->yoffset
* var
->xres_virtual
+ var
->xoffset
) * ACCESS_FBINFO(curr
.final_bppShift
) / 32;
2720 pos
+= ACCESS_FBINFO(curr
.ydstorg
.chunks
);
2722 p0
= ACCESS_FBINFO(currenthw
)->CRTC
[0x0D] = pos
& 0xFF;
2723 p1
= ACCESS_FBINFO(currenthw
)->CRTC
[0x0C] = (pos
& 0xFF00) >> 8;
2724 p2
= ACCESS_FBINFO(currenthw
)->CRTCEXT
[0] = (ACCESS_FBINFO(currenthw
)->CRTCEXT
[0] & 0xB0) | ((pos
>> 16) & 0x0F) | ((pos
>> 14) & 0x40);
2725 #ifdef CONFIG_FB_MATROX_32MB
2726 p3
= ACCESS_FBINFO(currenthw
)->CRTCEXT
[8] = pos
>> 21;
2731 mga_setr(M_CRTC_INDEX
, 0x0D, p0
);
2732 mga_setr(M_CRTC_INDEX
, 0x0C, p1
);
2733 #ifdef CONFIG_FB_MATROX_32MB
2734 if (ACCESS_FBINFO(devflags
.support32MB
))
2735 mga_setr(M_EXTVGA_INDEX
, 0x08, p3
);
2737 mga_setr(M_EXTVGA_INDEX
, 0x00, p2
);
2743 * Open/Release the frame buffer device
2746 static int matroxfb_open(struct fb_info
*info
, int user
)
2748 DBG_LOOP("matroxfb_open")
2751 * Nothing, only a usage count for the moment
2757 static int matroxfb_release(struct fb_info
*info
, int user
)
2759 DBG_LOOP("matroxfb_release")
2765 static int matroxfb_pan_display(struct fb_var_screeninfo
*var
, int con
,
2766 struct fb_info
* info
) {
2767 #define minfo ((struct matrox_fb_info*)info)
2769 DBG("matroxfb_pan_display")
2771 if (var
->vmode
& FB_VMODE_YWRAP
) {
2772 if (var
->yoffset
< 0 || var
->yoffset
>= fb_display
[con
].var
.yres_virtual
|| var
->xoffset
)
2775 if (var
->xoffset
+fb_display
[con
].var
.xres
> fb_display
[con
].var
.xres_virtual
||
2776 var
->yoffset
+fb_display
[con
].var
.yres
> fb_display
[con
].var
.yres_virtual
)
2779 if (con
== ACCESS_FBINFO(currcon
))
2780 matrox_pan_var(PMINFO var
);
2781 fb_display
[con
].var
.xoffset
= var
->xoffset
;
2782 fb_display
[con
].var
.yoffset
= var
->yoffset
;
2783 if (var
->vmode
& FB_VMODE_YWRAP
)
2784 fb_display
[con
].var
.vmode
|= FB_VMODE_YWRAP
;
2786 fb_display
[con
].var
.vmode
&= ~FB_VMODE_YWRAP
;
2791 static int matroxfb_updatevar(int con
, struct fb_info
*info
)
2793 #define minfo ((struct matrox_fb_info*)info)
2794 DBG("matroxfb_updatevar");
2796 matrox_pan_var(PMINFO
&fb_display
[con
].var
);
2801 static int matroxfb_get_final_bppShift(CPMINFO
int bpp
) {
2804 DBG("matroxfb_get_final_bppShift")
2810 if (isInterleave(MINFO
))
2812 if (ACCESS_FBINFO(devflags
.video64bits
))
2817 static int matroxfb_test_and_set_rounding(CPMINFO
int xres
, int bpp
) {
2821 DBG("matroxfb_test_and_set_rounding")
2824 case 0: return xres
;
2825 case 4: rounding
= 128;
2827 case 8: rounding
= 64; /* doc says 64; 32 is OK for G400 */
2829 case 16: rounding
= 32;
2831 case 24: rounding
= 64; /* doc says 64; 32 is OK for G400 */
2833 default: rounding
= 16;
2834 /* on G400, 16 really does not work */
2835 if (ACCESS_FBINFO(devflags
.accelerator
) == FB_ACCEL_MATROX_MGAG400
)
2839 if (isInterleave(MINFO
)) {
2842 over
= xres
% rounding
;
2844 xres
+= rounding
-over
;
2848 static int matroxfb_pitch_adjust(CPMINFO
int xres
, int bpp
) {
2852 DBG("matroxfb_pitch_adjust")
2854 if (!bpp
) return xres
;
2856 width
= ACCESS_FBINFO(capable
.vxres
);
2858 if (ACCESS_FBINFO(devflags
.precise_width
)) {
2860 if ((*width
>= xres
) && (matroxfb_test_and_set_rounding(PMINFO
*width
, bpp
) == *width
)) {
2867 xres_new
= matroxfb_test_and_set_rounding(PMINFO xres
, bpp
);
2869 if (!xres_new
) return 0;
2870 if (xres
!= xres_new
) {
2871 printk(KERN_INFO
"matroxfb: cannot set xres to %d, rounded up to %d\n", xres
, xres_new
);
2876 #ifdef CONFIG_FB_MATROX_MILLENIUM
2877 static const unsigned char DACseq
[] =
2878 { TVP3026_XLATCHCTRL
, TVP3026_XTRUECOLORCTRL
,
2879 TVP3026_XMUXCTRL
, TVP3026_XCLKCTRL
,
2880 TVP3026_XPALETTEPAGE
,
2885 TVP3026_XCOLKEYOVRMIN
, TVP3026_XCOLKEYOVRMAX
, TVP3026_XCOLKEYREDMIN
, TVP3026_XCOLKEYREDMAX
,
2886 TVP3026_XCOLKEYGREENMIN
, TVP3026_XCOLKEYGREENMAX
, TVP3026_XCOLKEYBLUEMIN
, TVP3026_XCOLKEYBLUEMAX
,
2887 TVP3026_XCOLKEYCTRL
,
2888 TVP3026_XMEMPLLCTRL
, TVP3026_XSENSETEST
, TVP3026_XCURCTRL
};
2890 #define POS3026_XLATCHCTRL 0
2891 #define POS3026_XTRUECOLORCTRL 1
2892 #define POS3026_XMUXCTRL 2
2893 #define POS3026_XCLKCTRL 3
2894 #define POS3026_XGENCTRL 5
2895 #define POS3026_XMISCCTRL 6
2896 #define POS3026_XMEMPLLCTRL 18
2897 #define POS3026_XCURCTRL 20
2899 static const unsigned char MGADACbpp32
[] =
2900 { TVP3026_XLATCHCTRL_2_1
, TVP3026_XTRUECOLORCTRL_DIRECTCOLOR
| TVP3026_XTRUECOLORCTRL_ORGB_8888
,
2901 0x00, TVP3026_XCLKCTRL_DIV1
| TVP3026_XCLKCTRL_SRC_PLL
,
2903 TVP3026_XGENCTRL_HSYNC_POS
| TVP3026_XGENCTRL_VSYNC_POS
| TVP3026_XGENCTRL_LITTLE_ENDIAN
| TVP3026_XGENCTRL_BLACK_0IRE
| TVP3026_XGENCTRL_NO_SYNC_ON_GREEN
| TVP3026_XGENCTRL_OVERSCAN_DIS
,
2904 TVP3026_XMISCCTRL_DAC_PUP
| TVP3026_XMISCCTRL_DAC_8BIT
| TVP3026_XMISCCTRL_PSEL_DIS
| TVP3026_XMISCCTRL_PSEL_HIGH
,
2907 0xFF, 0xFF, 0xFF, 0xFF,
2908 0xFF, 0xFF, 0xFF, 0xFF,
2909 TVP3026_XCOLKEYCTRL_ZOOM1
,
2910 0x00, 0x00, TVP3026_XCURCTRL_DIS
};
2911 #endif /* CONFIG_FB_MATROX_MILLENIUM */
2913 static int PLL_calcclock(CPMINFO
unsigned int freq
, unsigned int fmax
, unsigned int* in
, unsigned int* feed
, unsigned int* post
) {
2914 unsigned int bestdiff
= ~0;
2915 unsigned int bestvco
= 0;
2916 unsigned int fxtal
= ACCESS_FBINFO(features
.pll
.ref_freq
);
2920 DBG("PLL_calcclock")
2925 printk(KERN_ERR
"post_shift_max: %d\n", ACCESS_FBINFO(features
.pll
.post_shift_max
));
2926 printk(KERN_ERR
"ref_freq: %d\n", ACCESS_FBINFO(features
.pll
.ref_freq
));
2927 printk(KERN_ERR
"freq: %d\n", freq
);
2928 printk(KERN_ERR
"vco_freq_min: %d\n", ACCESS_FBINFO(features
.pll
.vco_freq_min
));
2929 printk(KERN_ERR
"in_div_min: %d\n", ACCESS_FBINFO(features
.pll
.in_div_min
));
2930 printk(KERN_ERR
"in_div_max: %d\n", ACCESS_FBINFO(features
.pll
.in_div_max
));
2931 printk(KERN_ERR
"feed_div_min: %d\n", ACCESS_FBINFO(features
.pll
.feed_div_min
));
2932 printk(KERN_ERR
"feed_div_max: %d\n", ACCESS_FBINFO(features
.pll
.feed_div_max
));
2933 printk(KERN_ERR
"fmax: %d\n", fmax
);
2935 for (p
= 1; p
<= ACCESS_FBINFO(features
.pll
.post_shift_max
); p
++) {
2936 if (fwant
* 2 > fmax
)
2940 if (fwant
< ACCESS_FBINFO(features
.pll
.vco_freq_min
)) fwant
= ACCESS_FBINFO(features
.pll
.vco_freq_min
);
2941 if (fwant
> fmax
) fwant
= fmax
;
2942 for (; p
-- > 0; fwant
>>= 1, bestdiff
>>= 1) {
2945 if (fwant
< ACCESS_FBINFO(features
.pll
.vco_freq_min
)) break;
2946 for (m
= ACCESS_FBINFO(features
.pll
.in_div_min
); m
<= ACCESS_FBINFO(features
.pll
.in_div_max
); m
++) {
2947 unsigned int diff
, fvco
;
2950 n
= (fwant
* (m
+ 1) + (fxtal
>> 1)) / fxtal
- 1;
2951 if (n
> ACCESS_FBINFO(features
.pll
.feed_div_max
))
2953 if (n
< ACCESS_FBINFO(features
.pll
.feed_div_min
))
2954 n
= ACCESS_FBINFO(features
.pll
.feed_div_min
);
2955 fvco
= (fxtal
* (n
+ 1)) / (m
+ 1);
2957 diff
= fwant
- fvco
;
2959 diff
= fvco
- fwant
;
2960 if (diff
< bestdiff
) {
2969 dprintk(KERN_ERR
"clk: %02X %02X %02X %d %d %d\n", *in
, *feed
, *post
, fxtal
, bestvco
, fwant
);
2974 static void DAC1064_calcclock(CPMINFO
unsigned int freq
, unsigned int fmax
, unsigned int* in
, unsigned int* feed
, unsigned int* post
) {
2978 DBG("DAC1064_calcclock")
2980 fvco
= PLL_calcclock(PMINFO freq
, fmax
, in
, feed
, &p
);
2984 else if (fvco
<= 140000)
2986 else if (fvco
<= 180000)
2994 #ifdef CONFIG_FB_MATROX_MILLENIUM
2995 static int Ti3026_calcclock(CPMINFO
unsigned int freq
, unsigned int fmax
, int* in
, int* feed
, int* post
) {
2997 unsigned int lin
, lfeed
, lpost
;
2999 DBG("Ti3026_calcclock")
3001 fvco
= PLL_calcclock(PMINFO freq
, fmax
, &lin
, &lfeed
, &lpost
);
3002 fvco
>>= (*post
= lpost
);
3008 static int Ti3026_setpclk(CPMINFO
struct matrox_hw_state
* hw
, int clk
, struct display
* p
) {
3010 unsigned int pixfeed
, pixin
, pixpost
;
3012 DBG("Ti3026_setpclk")
3014 f_pll
= Ti3026_calcclock(PMINFO clk
, ACCESS_FBINFO(max_pixel_clock
), &pixin
, &pixfeed
, &pixpost
);
3016 hw
->DACclk
[0] = pixin
| 0xC0;
3017 hw
->DACclk
[1] = pixfeed
;
3018 hw
->DACclk
[2] = pixpost
| 0xB0;
3020 if (p
->type
== FB_TYPE_TEXT
) {
3021 hw
->DACreg
[POS3026_XMEMPLLCTRL
] = TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL
| TVP3026_XMEMPLLCTRL_RCLK_PIXPLL
;
3022 hw
->DACclk
[3] = 0xFD;
3023 hw
->DACclk
[4] = 0x3D;
3024 hw
->DACclk
[5] = 0x70;
3026 unsigned int loopfeed
, loopin
, looppost
, loopdiv
, z
;
3029 Bpp
= ACCESS_FBINFO(curr
.final_bppShift
);
3031 if (p
->var
.bits_per_pixel
== 24) {
3032 loopfeed
= 3; /* set lm to any possible value */
3033 loopin
= 3 * 32 / Bpp
;
3036 loopin
= 4 * 32 / Bpp
;
3038 z
= (110000 * loopin
) / (f_pll
* loopfeed
);
3039 loopdiv
= 0; /* div 2 */
3050 if (p
->var
.bits_per_pixel
== 24) {
3051 hw
->DACclk
[3] = ((65 - loopin
) & 0x3F) | 0xC0;
3052 hw
->DACclk
[4] = (65 - loopfeed
) | 0x80;
3053 if (ACCESS_FBINFO(accel
.ramdac_rev
) > 0x20) {
3054 if (isInterleave(MINFO
))
3055 hw
->DACreg
[POS3026_XLATCHCTRL
] = TVP3026B_XLATCHCTRL_8_3
;
3057 hw
->DACclk
[4] &= ~0xC0;
3058 hw
->DACreg
[POS3026_XLATCHCTRL
] = TVP3026B_XLATCHCTRL_4_3
;
3061 if (isInterleave(MINFO
))
3064 hw
->DACclk
[4] ^= 0xC0; /* change from 0x80 to 0x40 */
3065 hw
->DACreg
[POS3026_XLATCHCTRL
] = TVP3026A_XLATCHCTRL_4_3
;
3068 hw
->DACclk
[5] = looppost
| 0xF8;
3069 if (ACCESS_FBINFO(devflags
.mga_24bpp_fix
))
3070 hw
->DACclk
[5] ^= 0x40;
3072 hw
->DACclk
[3] = ((65 - loopin
) & 0x3F) | 0xC0;
3073 hw
->DACclk
[4] = 65 - loopfeed
;
3074 hw
->DACclk
[5] = looppost
| 0xF0;
3076 hw
->DACreg
[POS3026_XMEMPLLCTRL
] = loopdiv
| TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL
| TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL
;
3082 static void var2my(struct fb_var_screeninfo
* var
, struct my_timming
* mt
) {
3083 unsigned int pixclock
= var
->pixclock
;
3087 if (!pixclock
) pixclock
= 10000; /* 10ns = 100MHz */
3088 mt
->pixclock
= 1000000000 / pixclock
;
3089 if (mt
->pixclock
< 1) mt
->pixclock
= 1;
3090 mt
->dblscan
= var
->vmode
& FB_VMODE_DOUBLE
;
3091 mt
->interlaced
= var
->vmode
& FB_VMODE_INTERLACED
;
3092 mt
->HDisplay
= var
->xres
;
3093 mt
->HSyncStart
= mt
->HDisplay
+ var
->right_margin
;
3094 mt
->HSyncEnd
= mt
->HSyncStart
+ var
->hsync_len
;
3095 mt
->HTotal
= mt
->HSyncEnd
+ var
->left_margin
;
3096 mt
->VDisplay
= var
->yres
;
3097 mt
->VSyncStart
= mt
->VDisplay
+ var
->lower_margin
;
3098 mt
->VSyncEnd
= mt
->VSyncStart
+ var
->vsync_len
;
3099 mt
->VTotal
= mt
->VSyncEnd
+ var
->upper_margin
;
3100 mt
->sync
= var
->sync
;
3103 static int vgaHWinit(CPMINFO
struct matrox_hw_state
* hw
, struct my_timming
* m
, struct display
* p
) {
3104 unsigned int hd
, hs
, he
, hbe
, ht
;
3105 unsigned int vd
, vs
, ve
, vt
;
3107 unsigned int divider
;
3109 int text
= p
->type
== FB_TYPE_TEXT
;
3113 fwidth
= fontwidth(p
);
3114 if (!fwidth
) fwidth
= 8;
3124 hw
->SEQ
[1] = 0x01; /* or 0x09 */
3125 hw
->SEQ
[2] = 0x0F; /* bitplanes */
3131 /* CRTC 0..7, 9, 16..19, 21, 22 are reprogrammed by Matrox Millenium code... Hope that by MGA1064 too */
3135 m
->VSyncStart
<<= 1;
3138 if (m
->interlaced
) {
3141 m
->VSyncStart
>>= 1;
3145 /* GCTL is ignored when not using 0xA0000 aperture */
3161 /* Whole ATTR is ignored in PowerGraphics mode */
3162 for (i
= 0; i
< 16; i
++)
3165 hw
->ATTR
[16] = 0x04;
3167 hw
->ATTR
[16] = 0x41;
3169 hw
->ATTR
[17] = 0xFF;
3170 hw
->ATTR
[18] = 0x0F;
3172 hw
->ATTR
[19] = 0x08;
3174 hw
->ATTR
[19] = 0x00;
3175 hw
->ATTR
[20] = 0x00;
3178 hd
= m
->HDisplay
/ fwidth
;
3179 hs
= m
->HSyncStart
/ fwidth
;
3180 he
= m
->HSyncEnd
/ fwidth
;
3181 ht
= m
->HTotal
/ fwidth
;
3184 hd
= m
->HDisplay
>> 3;
3185 hs
= m
->HSyncStart
>> 3;
3186 he
= m
->HSyncEnd
>> 3;
3187 ht
= m
->HTotal
>> 3;
3188 /* standard timmings are in 8pixels, but for interleaved we cannot */
3189 /* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */
3190 /* using 16 or more pixels per unit can save us */
3191 divider
= ACCESS_FBINFO(curr
.final_bppShift
);
3193 while (divider
& 3) {
3200 divider
= divider
/ 4;
3201 /* divider can be from 1 to 8 */
3202 while (divider
> 8) {
3213 vd
= m
->VDisplay
- 1;
3214 vs
= m
->VSyncStart
- 1;
3215 ve
= m
->VSyncEnd
- 1;
3217 /* G200 cannot work with (ht & 7) == 6 */
3218 if (((ht
& 0x07) == 0x06) || ((ht
& 0x0F) == 0x04))
3222 wd
= p
->var
.xres_virtual
/ (fwidth
* 2);
3225 wd
= p
->var
.xres_virtual
* ACCESS_FBINFO(curr
.final_bppShift
) / 64;
3230 if (m
->interlaced
) {
3231 hw
->CRTCEXT
[0] = 0x80;
3232 hw
->CRTCEXT
[5] = (hs
+ he
- ht
) >> 1;
3237 hw
->CRTCEXT
[0] |= (wd
& 0x300) >> 4;
3238 hw
->CRTCEXT
[1] = (((ht
- 4) & 0x100) >> 8) |
3239 ((hd
& 0x100) >> 7) | /* blanking */
3240 ((hs
& 0x100) >> 6) | /* sync start */
3241 (hbe
& 0x040); /* end hor. blanking */
3242 hw
->CRTCEXT
[2] = ((vt
& 0xC00) >> 10) |
3243 ((vd
& 0x400) >> 8) | /* disp end */
3244 ((vd
& 0xC00) >> 7) | /* vblanking start */
3245 ((vs
& 0xC00) >> 5);
3247 hw
->CRTCEXT
[3] = 0x00;
3249 hw
->CRTCEXT
[3] = (divider
- 1) | 0x80;
3255 hw
->CRTC
[3] = (hbe
& 0x1F) | 0x80;
3257 hw
->CRTC
[5] = ((hbe
& 0x20) << 2) | (he
& 0x1F);
3259 hw
->CRTC
[5] |= 0x60; /* delay sync for 3 clocks (to same picture position on MGA and VGA) */
3260 hw
->CRTC
[6] = vt
& 0xFF;
3261 hw
->CRTC
[7] = ((vt
& 0x100) >> 8) |
3262 ((vd
& 0x100) >> 7) |
3263 ((vs
& 0x100) >> 6) |
3264 ((vd
& 0x100) >> 5) |
3266 ((vt
& 0x200) >> 4) |
3267 ((vd
& 0x200) >> 3) |
3268 ((vs
& 0x200) >> 2);
3270 hw
->CRTC
[9] = ((vd
& 0x200) >> 4) | 0x40;
3272 hw
->CRTC
[9] |= fontheight(p
) - 1;
3273 if (m
->dblscan
&& !m
->interlaced
)
3274 hw
->CRTC
[9] |= 0x80;
3275 for (i
= 10; i
< 16; i
++)
3277 hw
->CRTC
[16] = vs
/* & 0xFF */;
3278 hw
->CRTC
[17] = (ve
& 0x0F) | 0x20;
3279 hw
->CRTC
[18] = vd
/* & 0xFF */;
3280 hw
->CRTC
[19] = wd
/* & 0xFF */;
3281 hw
->CRTC
[20] = 0x00;
3282 hw
->CRTC
[21] = vd
/* & 0xFF */;
3283 hw
->CRTC
[22] = (vt
+ 1) /* & 0xFF */;
3285 if (ACCESS_FBINFO(devflags
.textmode
) == 1)
3286 hw
->CRTC
[23] = 0xC3;
3288 hw
->CRTC
[23] = 0xA3;
3289 if (ACCESS_FBINFO(devflags
.textmode
) == 4)
3290 hw
->CRTC
[20] = 0x5F;
3292 hw
->CRTC
[20] = 0x1F;
3294 hw
->CRTC
[23] = 0xC3;
3295 hw
->CRTC
[24] = 0xFF;
3301 static const unsigned char MGA1064_DAC_regs
[] = {
3302 M1064_XCURADDL
, M1064_XCURADDH
, M1064_XCURCTRL
,
3303 M1064_XCURCOL0RED
, M1064_XCURCOL0GREEN
, M1064_XCURCOL0BLUE
,
3304 M1064_XCURCOL1RED
, M1064_XCURCOL1GREEN
, M1064_XCURCOL1BLUE
,
3305 M1064_XCURCOL2RED
, M1064_XCURCOL2GREEN
, M1064_XCURCOL2BLUE
,
3306 DAC1064_XVREFCTRL
, M1064_XMULCTRL
, M1064_XPIXCLKCTRL
, M1064_XGENCTRL
,
3308 M1064_XGENIOCTRL
, M1064_XGENIODATA
, M1064_XZOOMCTRL
, M1064_XSENSETEST
,
3310 M1064_XCOLKEYMASKL
, M1064_XCOLKEYMASKH
, M1064_XCOLKEYL
, M1064_XCOLKEYH
};
3312 #define POS1064_XCURADDL 0
3313 #define POS1064_XCURADDH 1
3314 #define POS1064_XVREFCTRL 12
3315 #define POS1064_XMULCTRL 13
3316 #define POS1064_XGENCTRL 15
3317 #define POS1064_XMISCCTRL 16
3319 static const unsigned char MGA1064_DAC
[] = {
3320 0x00, 0x00, M1064_XCURCTRL_DIS
,
3321 0x00, 0x00, 0x00, /* black */
3322 0xFF, 0xFF, 0xFF, /* white */
3323 0xFF, 0x00, 0x00, /* red */
3325 M1064_XPIXCLKCTRL_PLL_UP
| M1064_XPIXCLKCTRL_EN
| M1064_XPIXCLKCTRL_SRC_PLL
,
3326 M1064_XGENCTRL_VS_0
| M1064_XGENCTRL_ALPHA_DIS
| M1064_XGENCTRL_BLACK_0IRE
| M1064_XGENCTRL_NO_SYNC_ON_GREEN
,
3327 M1064_XMISCCTRL_DAC_EN
| M1064_XMISCCTRL_MFC_DIS
| M1064_XMISCCTRL_DAC_8BIT
| M1064_XMISCCTRL_LUT_EN
,
3328 0x10, 0x3F, M1064_XZOOMCTRL_1
, M1064_XSENSETEST_BCOMP
| M1064_XSENSETEST_GCOMP
| M1064_XSENSETEST_RCOMP
| M1064_XSENSETEST_PDOWN
,
3330 0x00, 0x00, 0xFF, 0xFF};
3332 static void DAC1064_setpclk(CPMINFO
struct matrox_hw_state
* hw
, unsigned long fout
) {
3333 unsigned int m
, n
, p
;
3335 DBG("DAC1064_setpclk")
3337 DAC1064_calcclock(PMINFO fout
, ACCESS_FBINFO(max_pixel_clock
), &m
, &n
, &p
);
3343 static void __init
DAC1064_setmclk(CPMINFO
struct matrox_hw_state
* hw
, int oscinfo
, unsigned long fmem
){
3346 DBG("DAC1064_setmclk")
3348 if (ACCESS_FBINFO(devflags
.noinit
)) {
3349 /* read MCLK and give up... */
3350 hw
->DACclk
[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM
);
3351 hw
->DACclk
[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN
);
3352 hw
->DACclk
[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP
);
3355 mx
= hw
->MXoptionReg
| 0x00000004;
3356 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, mx
);
3358 if (oscinfo
& DAC1064_OPT_GDIV1
)
3360 if (oscinfo
& DAC1064_OPT_MDIV1
)
3362 if (oscinfo
& DAC1064_OPT_RESERVED
)
3364 if ((oscinfo
& DAC1064_OPT_SCLK_MASK
) == DAC1064_OPT_SCLK_PLL
) {
3365 /* select PCI clock until we have setup oscilator... */
3367 unsigned int m
, n
, p
;
3369 /* powerup system PLL, select PCI clock */
3371 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, mx
);
3373 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, mx
);
3375 /* !!! you must not access device if MCLK is not running !!!
3376 Doing so cause immediate PCI lockup :-( Maybe they should
3377 generate ABORT or I/O (parity...) error and Linux should
3378 recover from this... (kill driver/process). But world is not
3380 /* (bit 2 of PCI_OPTION_REG must be 0... and bits 0,1 must not
3381 select PLL... because of PLL can be stopped at this time) */
3382 DAC1064_calcclock(PMINFO fmem
, ACCESS_FBINFO(max_pixel_clock
), &m
, &n
, &p
);
3383 outDAC1064(PMINFO DAC1064_XSYSPLLM
, hw
->DACclk
[3] = m
);
3384 outDAC1064(PMINFO DAC1064_XSYSPLLN
, hw
->DACclk
[4] = n
);
3385 outDAC1064(PMINFO DAC1064_XSYSPLLP
, hw
->DACclk
[5] = p
);
3386 for (clk
= 65536; clk
; --clk
) {
3387 if (inDAC1064(PMINFO DAC1064_XSYSPLLSTAT
) & 0x40)
3391 printk(KERN_ERR
"matroxfb: aiee, SYSPLL not locked\n");
3395 /* select specified system clock source */
3396 mx
|= oscinfo
& DAC1064_OPT_SCLK_MASK
;
3398 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, mx
);
3400 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, mx
);
3401 hw
->MXoptionReg
= mx
;
3404 static int DAC1064_init_1(CPMINFO
struct matrox_hw_state
* hw
, struct my_timming
* m
, struct display
*p
) {
3406 DBG("DAC1064_init_1")
3408 memcpy(hw
->DACreg
, MGA1064_DAC
, sizeof(MGA1064_DAC_regs
));
3409 if (p
->type
== FB_TYPE_TEXT
) {
3410 hw
->DACreg
[POS1064_XMISCCTRL
] = M1064_XMISCCTRL_DAC_EN
3411 | M1064_XMISCCTRL_MFC_DIS
3412 | M1064_XMISCCTRL_DAC_6BIT
3413 | M1064_XMISCCTRL_LUT_EN
;
3414 hw
->DACreg
[POS1064_XMULCTRL
] = M1064_XMULCTRL_DEPTH_8BPP
3415 | M1064_XMULCTRL_GRAPHICS_PALETIZED
;
3417 switch (p
->var
.bits_per_pixel
) {
3418 /* case 4: not supported by MGA1064 DAC */
3420 hw
->DACreg
[POS1064_XMULCTRL
] = M1064_XMULCTRL_DEPTH_8BPP
| M1064_XMULCTRL_GRAPHICS_PALETIZED
;
3423 if (p
->var
.green
.length
== 5)
3424 hw
->DACreg
[POS1064_XMULCTRL
] = M1064_XMULCTRL_DEPTH_15BPP_1BPP
| M1064_XMULCTRL_GRAPHICS_PALETIZED
;
3426 hw
->DACreg
[POS1064_XMULCTRL
] = M1064_XMULCTRL_DEPTH_16BPP
| M1064_XMULCTRL_GRAPHICS_PALETIZED
;
3429 hw
->DACreg
[POS1064_XMULCTRL
] = M1064_XMULCTRL_DEPTH_24BPP
| M1064_XMULCTRL_GRAPHICS_PALETIZED
;
3432 hw
->DACreg
[POS1064_XMULCTRL
] = M1064_XMULCTRL_DEPTH_32BPP
| M1064_XMULCTRL_GRAPHICS_PALETIZED
;
3435 return 1; /* unsupported depth */
3438 hw
->DACreg
[POS1064_XVREFCTRL
] = ACCESS_FBINFO(features
.DAC1064
.xvrefctrl
);
3439 hw
->DACreg
[POS1064_XGENCTRL
] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK
;
3440 hw
->DACreg
[POS1064_XGENCTRL
] |= (m
->sync
& FB_SYNC_ON_GREEN
)?M1064_XGENCTRL_SYNC_ON_GREEN
:M1064_XGENCTRL_NO_SYNC_ON_GREEN
;
3441 hw
->DACreg
[POS1064_XCURADDL
] = ACCESS_FBINFO(features
.DAC1064
.cursorimage
) >> 10;
3442 hw
->DACreg
[POS1064_XCURADDH
] = ACCESS_FBINFO(features
.DAC1064
.cursorimage
) >> 18;
3446 static int DAC1064_init_2(CPMINFO
struct matrox_hw_state
* hw
, struct my_timming
* m
, struct display
* p
) {
3448 DBG("DAC1064_init_2")
3450 DAC1064_setpclk(PMINFO hw
, m
->pixclock
);
3451 if (p
->var
.bits_per_pixel
> 16) { /* 256 entries */
3454 for (i
= 0; i
< 256; i
++) {
3455 hw
->DACpal
[i
* 3 + 0] = i
;
3456 hw
->DACpal
[i
* 3 + 1] = i
;
3457 hw
->DACpal
[i
* 3 + 2] = i
;
3459 } else if (p
->var
.bits_per_pixel
> 8) {
3460 if (p
->var
.green
.length
== 5) { /* 0..31, 128..159 */
3463 for (i
= 0; i
< 32; i
++) {
3465 hw
->DACpal
[i
* 3 + 0] = i
<< 3;
3466 hw
->DACpal
[i
* 3 + 1] = i
<< 3;
3467 hw
->DACpal
[i
* 3 + 2] = i
<< 3;
3469 hw
->DACpal
[(i
+ 128) * 3 + 0] = i
<< 3;
3470 hw
->DACpal
[(i
+ 128) * 3 + 1] = i
<< 3;
3471 hw
->DACpal
[(i
+ 128) * 3 + 2] = i
<< 3;
3476 for (i
= 0; i
< 64; i
++) { /* 0..63 */
3477 hw
->DACpal
[i
* 3 + 0] = i
<< 3;
3478 hw
->DACpal
[i
* 3 + 1] = i
<< 2;
3479 hw
->DACpal
[i
* 3 + 2] = i
<< 3;
3483 memset(hw
->DACpal
, 0, 768);
3488 static void DAC1064_restore_1(CPMINFO
const struct matrox_hw_state
* hw
, const struct matrox_hw_state
* oldhw
) {
3490 DBG("DAC1064_restore_1")
3494 outDAC1064(PMINFO DAC1064_XSYSPLLM
, hw
->DACclk
[3]);
3495 outDAC1064(PMINFO DAC1064_XSYSPLLN
, hw
->DACclk
[4]);
3496 outDAC1064(PMINFO DAC1064_XSYSPLLP
, hw
->DACclk
[5]);
3497 if (!oldhw
|| memcmp(hw
->DACreg
, oldhw
->DACreg
, sizeof(MGA1064_DAC_regs
))) {
3500 for (i
= 0; i
< sizeof(MGA1064_DAC_regs
); i
++)
3501 outDAC1064(PMINFO MGA1064_DAC_regs
[i
], hw
->DACreg
[i
]);
3507 static void DAC1064_restore_2(WPMINFO
const struct matrox_hw_state
* hw
, const struct matrox_hw_state
* oldhw
, struct display
* p
) {
3511 DBG("DAC1064_restore_2")
3515 for (i
= 0; i
< 3; i
++)
3516 outDAC1064(PMINFO M1064_XPIXPLLCM
+ i
, hw
->DACclk
[i
]);
3517 for (tmout
= 500000; tmout
; tmout
--) {
3518 if (inDAC1064(PMINFO M1064_XPIXPLLSTAT
) & 0x40)
3526 printk(KERN_ERR
"matroxfb: Pixel PLL not locked after 5 secs\n");
3529 if (p
->type
== FB_TYPE_TEXT
) {
3530 matrox_text_createcursor(PMINFO p
);
3531 matrox_text_loadfont(PMINFO p
);
3534 matroxfb_DAC1064_createcursor(PMINFO p
);
3535 i
= matroxfb_fastfont_tryset(PMINFO p
);
3540 ACCESS_FBINFO(curr
.putc
) = matrox_cfbX_fastputc
;
3541 ACCESS_FBINFO(curr
.putcs
) = matrox_cfbX_fastputcs
;
3543 ACCESS_FBINFO(curr
.putc
) = matrox_cfbX_putc
;
3544 ACCESS_FBINFO(curr
.putcs
) = matrox_cfbX_putcs
;
3547 dprintk(KERN_DEBUG
"DAC1064regs ");
3548 for (i
= 0; i
< sizeof(MGA1064_DAC_regs
); i
++) {
3549 dprintk("R%02X=%02X ", MGA1064_DAC_regs
[i
], hw
->DACreg
[i
]);
3550 if ((i
& 0x7) == 0x7) dprintk("\n" KERN_DEBUG
"continuing... ");
3552 dprintk("\n" KERN_DEBUG
"DAC1064clk ");
3553 for (i
= 0; i
< 6; i
++)
3554 dprintk("C%02X=%02X ", i
, hw
->DACclk
[i
]);
3558 #endif /* NEED_DAC1064 */
3560 #ifdef CONFIG_FB_MATROX_MYSTIQUE
3561 static int MGA1064_init(CPMINFO
struct matrox_hw_state
* hw
, struct my_timming
* m
, struct display
* p
) {
3565 if (DAC1064_init_1(PMINFO hw
, m
, p
)) return 1;
3566 if (vgaHWinit(PMINFO hw
, m
, p
)) return 1;
3568 hw
->MiscOutReg
= 0xCB;
3569 if (m
->sync
& FB_SYNC_HOR_HIGH_ACT
)
3570 hw
->MiscOutReg
&= ~0x40;
3571 if (m
->sync
& FB_SYNC_VERT_HIGH_ACT
)
3572 hw
->MiscOutReg
&= ~0x80;
3573 if (m
->sync
& FB_SYNC_COMP_HIGH_ACT
) /* should be only FB_SYNC_COMP */
3574 hw
->CRTCEXT
[3] |= 0x40;
3576 if (DAC1064_init_2(PMINFO hw
, m
, p
)) return 1;
3581 #ifdef CONFIG_FB_MATROX_G100
3582 static int MGAG100_init(CPMINFO
struct matrox_hw_state
* hw
, struct my_timming
* m
, struct display
* p
) {
3586 if (DAC1064_init_1(PMINFO hw
, m
, p
)) return 1;
3587 hw
->MXoptionReg
&= ~0x2000;
3588 if (vgaHWinit(PMINFO hw
, m
, p
)) return 1;
3590 hw
->MiscOutReg
= 0xEF;
3591 if (m
->sync
& FB_SYNC_HOR_HIGH_ACT
)
3592 hw
->MiscOutReg
&= ~0x40;
3593 if (m
->sync
& FB_SYNC_VERT_HIGH_ACT
)
3594 hw
->MiscOutReg
&= ~0x80;
3595 if (m
->sync
& FB_SYNC_COMP_HIGH_ACT
) /* should be only FB_SYNC_COMP */
3596 hw
->CRTCEXT
[3] |= 0x40;
3598 if (DAC1064_init_2(PMINFO hw
, m
, p
)) return 1;
3603 #ifdef CONFIG_FB_MATROX_MILLENIUM
3604 static int Ti3026_init(CPMINFO
struct matrox_hw_state
* hw
, struct my_timming
* m
, struct display
* p
) {
3605 u_int8_t muxctrl
= isInterleave(MINFO
) ? TVP3026_XMUXCTRL_MEMORY_64BIT
: TVP3026_XMUXCTRL_MEMORY_32BIT
;
3609 memcpy(hw
->DACreg
, MGADACbpp32
, sizeof(hw
->DACreg
));
3610 if (p
->type
== FB_TYPE_TEXT
) {
3611 hw
->DACreg
[POS3026_XLATCHCTRL
] = TVP3026_XLATCHCTRL_8_1
;
3612 hw
->DACreg
[POS3026_XTRUECOLORCTRL
] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR
;
3613 hw
->DACreg
[POS3026_XMUXCTRL
] = TVP3026_XMUXCTRL_VGA
;
3614 hw
->DACreg
[POS3026_XCLKCTRL
] = TVP3026_XCLKCTRL_SRC_PLL
|
3615 TVP3026_XCLKCTRL_DIV4
;
3616 hw
->DACreg
[POS3026_XMISCCTRL
] = TVP3026_XMISCCTRL_DAC_PUP
| TVP3026_XMISCCTRL_DAC_6BIT
| TVP3026_XMISCCTRL_PSEL_DIS
| TVP3026_XMISCCTRL_PSEL_LOW
;
3618 switch (p
->var
.bits_per_pixel
) {
3619 case 4: hw
->DACreg
[POS3026_XLATCHCTRL
] = TVP3026_XLATCHCTRL_16_1
; /* or _8_1, they are same */
3620 hw
->DACreg
[POS3026_XTRUECOLORCTRL
] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR
;
3621 hw
->DACreg
[POS3026_XMUXCTRL
] = muxctrl
| TVP3026_XMUXCTRL_PIXEL_4BIT
;
3622 hw
->DACreg
[POS3026_XCLKCTRL
] = TVP3026_XCLKCTRL_SRC_PLL
| TVP3026_XCLKCTRL_DIV8
;
3623 hw
->DACreg
[POS3026_XMISCCTRL
] = TVP3026_XMISCCTRL_DAC_PUP
| TVP3026_XMISCCTRL_DAC_8BIT
| TVP3026_XMISCCTRL_PSEL_DIS
| TVP3026_XMISCCTRL_PSEL_LOW
;
3625 case 8: hw
->DACreg
[POS3026_XLATCHCTRL
] = TVP3026_XLATCHCTRL_8_1
; /* or _4_1, they are same */
3626 hw
->DACreg
[POS3026_XTRUECOLORCTRL
] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR
;
3627 hw
->DACreg
[POS3026_XMUXCTRL
] = muxctrl
| TVP3026_XMUXCTRL_PIXEL_8BIT
;
3628 hw
->DACreg
[POS3026_XCLKCTRL
] = TVP3026_XCLKCTRL_SRC_PLL
| TVP3026_XCLKCTRL_DIV4
;
3629 hw
->DACreg
[POS3026_XMISCCTRL
] = TVP3026_XMISCCTRL_DAC_PUP
| TVP3026_XMISCCTRL_DAC_8BIT
| TVP3026_XMISCCTRL_PSEL_DIS
| TVP3026_XMISCCTRL_PSEL_LOW
;
3632 /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used everytime) */
3633 hw
->DACreg
[POS3026_XTRUECOLORCTRL
] = (p
->var
.green
.length
== 5)? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR
| TVP3026_XTRUECOLORCTRL_ORGB_1555
) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR
| TVP3026_XTRUECOLORCTRL_RGB_565
);
3634 hw
->DACreg
[POS3026_XMUXCTRL
] = muxctrl
| TVP3026_XMUXCTRL_PIXEL_16BIT
;
3635 hw
->DACreg
[POS3026_XCLKCTRL
] = TVP3026_XCLKCTRL_SRC_PLL
| TVP3026_XCLKCTRL_DIV2
;
3638 /* XLATCHCTRL is: for (A) use _4_3 (?_8_3 is same? TBD), for (B) it is set in setpclk */
3639 hw
->DACreg
[POS3026_XTRUECOLORCTRL
] = TVP3026_XTRUECOLORCTRL_DIRECTCOLOR
| TVP3026_XTRUECOLORCTRL_RGB_888
;
3640 hw
->DACreg
[POS3026_XMUXCTRL
] = muxctrl
| TVP3026_XMUXCTRL_PIXEL_32BIT
;
3641 hw
->DACreg
[POS3026_XCLKCTRL
] = TVP3026_XCLKCTRL_SRC_PLL
| TVP3026_XCLKCTRL_DIV4
;
3644 /* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used everytime) */
3645 hw
->DACreg
[POS3026_XMUXCTRL
] = muxctrl
| TVP3026_XMUXCTRL_PIXEL_32BIT
;
3648 return 1; /* TODO: failed */
3651 if (vgaHWinit(PMINFO hw
, m
, p
)) return 1;
3654 hw
->MiscOutReg
= 0xCB;
3655 if (m
->sync
& FB_SYNC_HOR_HIGH_ACT
)
3656 hw
->DACreg
[POS3026_XGENCTRL
] |= TVP3026_XGENCTRL_HSYNC_NEG
;
3657 if (m
->sync
& FB_SYNC_VERT_HIGH_ACT
)
3658 hw
->DACreg
[POS3026_XGENCTRL
] |= TVP3026_XGENCTRL_VSYNC_NEG
;
3659 if (m
->sync
& FB_SYNC_ON_GREEN
)
3660 hw
->DACreg
[POS3026_XGENCTRL
] |= TVP3026_XGENCTRL_SYNC_ON_GREEN
;
3663 if (ACCESS_FBINFO(video
.len
) < 0x400000)
3664 hw
->CRTCEXT
[3] |= 0x08;
3665 else if (ACCESS_FBINFO(video
.len
) > 0x400000)
3666 hw
->CRTCEXT
[3] |= 0x10;
3669 if (m
->interlaced
) {
3670 hw
->DACreg
[POS3026_XCURCTRL
] |= TVP3026_XCURCTRL_INTERLACED
;
3672 if (m
->HTotal
>= 1536)
3673 hw
->DACreg
[POS3026_XCURCTRL
] |= TVP3026_XCURCTRL_BLANK4096
;
3675 /* set interleaving */
3676 hw
->MXoptionReg
&= ~0x00001000;
3677 if ((p
->type
!= FB_TYPE_TEXT
) && isInterleave(MINFO
)) hw
->MXoptionReg
|= 0x00001000;
3680 Ti3026_setpclk(PMINFO hw
, m
->pixclock
, p
);
3683 #endif /* CONFIG_FB_MATROX_MILLENIUM */
3685 static int matroxfb_get_cmap_len(struct fb_var_screeninfo
*var
) {
3687 DBG("matroxfb_get_cmap_len")
3689 switch (var
->bits_per_pixel
) {
3690 #ifdef FBCON_HAS_VGATEXT
3692 return 16; /* pseudocolor... 16 entries HW palette */
3694 #ifdef FBCON_HAS_CFB4
3696 return 16; /* pseudocolor... 16 entries HW palette */
3698 #ifdef FBCON_HAS_CFB8
3700 return 256; /* pseudocolor... 256 entries HW palette */
3702 #ifdef FBCON_HAS_CFB16
3704 return 16; /* directcolor... 16 entries SW palette */
3705 /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
3707 #ifdef FBCON_HAS_CFB24
3709 return 16; /* directcolor... 16 entries SW palette */
3710 /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
3712 #ifdef FBCON_HAS_CFB32
3714 return 16; /* directcolor... 16 entries SW palette */
3715 /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
3718 return 16; /* return something reasonable... or panic()? */
3721 static int matroxfb_decode_var(CPMINFO
struct display
* p
, struct fb_var_screeninfo
*var
, int *visual
, int *video_cmap_len
, unsigned int* ydstorg
) {
3722 unsigned int vramlen
;
3723 unsigned int memlen
;
3725 DBG("matroxfb_decode_var")
3727 switch (var
->bits_per_pixel
) {
3728 #ifdef FBCON_HAS_VGATEXT
3729 case 0: if (!ACCESS_FBINFO(capable
.text
)) return -EINVAL
;
3732 #ifdef FBCON_HAS_CFB4
3733 case 4: if (!ACCESS_FBINFO(capable
.cfb4
)) return -EINVAL
;
3736 #ifdef FBCON_HAS_CFB8
3739 #ifdef FBCON_HAS_CFB16
3742 #ifdef FBCON_HAS_CFB24
3745 #ifdef FBCON_HAS_CFB32
3748 default: return -EINVAL
;
3751 vramlen
= ACCESS_FBINFO(video
.len_usable
);
3752 if (var
->bits_per_pixel
) {
3753 var
->xres_virtual
= matroxfb_pitch_adjust(PMINFO var
->xres_virtual
, var
->bits_per_pixel
);
3754 memlen
= var
->xres_virtual
* var
->bits_per_pixel
* var
->yres_virtual
/ 8;
3755 if (memlen
> vramlen
) {
3756 var
->yres_virtual
= vramlen
* 8 / (var
->xres_virtual
* var
->bits_per_pixel
);
3757 memlen
= var
->xres_virtual
* var
->bits_per_pixel
* var
->yres_virtual
/ 8;
3759 /* There is hardware bug that no line can cross 4MB boundary */
3760 /* give up for CFB24, it is impossible to easy workaround it */
3761 /* for other try to do something */
3762 if (!ACCESS_FBINFO(capable
.cross4MB
) && (memlen
> 0x400000)) {
3763 if (var
->bits_per_pixel
== 24) {
3766 unsigned int linelen
;
3767 unsigned int m1
= linelen
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
3768 unsigned int m2
= PAGE_SIZE
; /* or 128 if you do not need PAGE ALIGNED address */
3769 unsigned int max_yres
;
3774 while (m2
>= m1
) m2
-= m1
;
3779 m2
= linelen
* PAGE_SIZE
/ m2
;
3780 *ydstorg
= m2
= 0x400000 % m2
;
3781 max_yres
= (vramlen
- m2
) / linelen
;
3782 if (var
->yres_virtual
> max_yres
)
3783 var
->yres_virtual
= max_yres
;
3787 matrox_text_round(PMINFO var
, p
);
3789 /* we must limit pixclock by mclk...
3790 Millenium I: 66 MHz = 15000
3791 Millenium II: 61 MHz = 16300
3792 Millenium G200: 83 MHz = 12000 */
3793 if (var
->pixclock
< 15000)
3794 var
->pixclock
= 15000; /* limit for "normal" gclk & mclk */
3797 /* YDSTLEN contains only signed 16bit value */
3798 if (var
->yres_virtual
> 32767)
3799 var
->yres_virtual
= 32767;
3800 if (var
->yres_virtual
< var
->yres
)
3801 var
->yres
= var
->yres_virtual
;
3802 if (var
->xres_virtual
< var
->xres
)
3803 var
->xres
= var
->xres_virtual
;
3804 if (var
->xoffset
+ var
->xres
> var
->xres_virtual
)
3805 var
->xoffset
= var
->xres_virtual
- var
->xres
;
3806 if (var
->yoffset
+ var
->yres
> var
->yres_virtual
)
3807 var
->yoffset
= var
->yres_virtual
- var
->yres
;
3809 if (var
->bits_per_pixel
== 0) {
3810 var
->red
.offset
= 0;
3811 var
->red
.length
= 6;
3812 var
->green
.offset
= 0;
3813 var
->green
.length
= 6;
3814 var
->blue
.offset
= 0;
3815 var
->blue
.length
= 6;
3816 var
->transp
.offset
= 0;
3817 var
->transp
.length
= 0;
3818 *visual
= MX_VISUAL_PSEUDOCOLOR
;
3819 } else if (var
->bits_per_pixel
== 4) {
3820 var
->red
.offset
= 0;
3821 var
->red
.length
= 8;
3822 var
->green
.offset
= 0;
3823 var
->green
.length
= 8;
3824 var
->blue
.offset
= 0;
3825 var
->blue
.length
= 8;
3826 var
->transp
.offset
= 0;
3827 var
->transp
.length
= 0;
3828 *visual
= MX_VISUAL_PSEUDOCOLOR
;
3829 } else if (var
->bits_per_pixel
<= 8) {
3830 var
->red
.offset
= 0;
3831 var
->red
.length
= 8;
3832 var
->green
.offset
= 0;
3833 var
->green
.length
= 8;
3834 var
->blue
.offset
= 0;
3835 var
->blue
.length
= 8;
3836 var
->transp
.offset
= 0;
3837 var
->transp
.length
= 0;
3838 *visual
= MX_VISUAL_PSEUDOCOLOR
;
3840 if (var
->bits_per_pixel
<= 16) {
3841 if (var
->green
.length
== 5) {
3842 var
->red
.offset
= 10;
3843 var
->red
.length
= 5;
3844 var
->green
.offset
= 5;
3845 var
->green
.length
= 5;
3846 var
->blue
.offset
= 0;
3847 var
->blue
.length
= 5;
3848 var
->transp
.offset
= 15;
3849 var
->transp
.length
= 1;
3851 var
->red
.offset
= 11;
3852 var
->red
.length
= 5;
3853 var
->green
.offset
= 5;
3854 var
->green
.length
= 6;
3855 var
->blue
.offset
= 0;
3856 var
->blue
.length
= 5;
3857 var
->transp
.offset
= 0;
3858 var
->transp
.length
= 0;
3860 } else if (var
->bits_per_pixel
<= 24) {
3861 var
->red
.offset
= 16;
3862 var
->red
.length
= 8;
3863 var
->green
.offset
= 8;
3864 var
->green
.length
= 8;
3865 var
->blue
.offset
= 0;
3866 var
->blue
.length
= 8;
3867 var
->transp
.offset
= 0;
3868 var
->transp
.length
= 0;
3870 var
->red
.offset
= 16;
3871 var
->red
.length
= 8;
3872 var
->green
.offset
= 8;
3873 var
->green
.length
= 8;
3874 var
->blue
.offset
= 0;
3875 var
->blue
.length
= 8;
3876 var
->transp
.offset
= 24;
3877 var
->transp
.length
= 8;
3879 dprintk("matroxfb: truecolor: "
3880 "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
3889 *visual
= MX_VISUAL_DIRECTCOLOR
;
3891 *video_cmap_len
= matroxfb_get_cmap_len(var
);
3892 dprintk(KERN_INFO
"requested %d*%d/%dbpp (%d*%d)\n", var
->xres
, var
->yres
, var
->bits_per_pixel
,
3893 var
->xres_virtual
, var
->yres_virtual
);
3897 #ifdef CONFIG_FB_MATROX_MILLENIUM
3898 static void __init
ti3026_setMCLK(CPMINFO
struct matrox_hw_state
* hw
, int fout
){
3900 unsigned int pclk_m
, pclk_n
, pclk_p
;
3901 unsigned int mclk_m
, mclk_n
, mclk_p
;
3902 unsigned int rfhcnt
, mclk_ctl
;
3905 DBG("ti3026_setMCLK")
3907 f_pll
= Ti3026_calcclock(PMINFO fout
, ACCESS_FBINFO(max_pixel_clock
), &mclk_n
, &mclk_m
, &mclk_p
);
3910 outTi3026(PMINFO TVP3026_XPLLADDR
, 0xFC);
3911 pclk_n
= inTi3026(PMINFO TVP3026_XPIXPLLDATA
);
3912 outTi3026(PMINFO TVP3026_XPLLADDR
, 0xFD);
3913 pclk_m
= inTi3026(PMINFO TVP3026_XPIXPLLDATA
);
3914 outTi3026(PMINFO TVP3026_XPLLADDR
, 0xFE);
3915 pclk_p
= inTi3026(PMINFO TVP3026_XPIXPLLDATA
);
3918 outTi3026(PMINFO TVP3026_XPLLADDR
, 0xFE);
3919 outTi3026(PMINFO TVP3026_XPIXPLLDATA
, 0x00);
3921 /* set pclk to new mclk */
3922 outTi3026(PMINFO TVP3026_XPLLADDR
, 0xFC);
3923 outTi3026(PMINFO TVP3026_XPIXPLLDATA
, mclk_n
| 0xC0);
3924 outTi3026(PMINFO TVP3026_XPIXPLLDATA
, mclk_m
);
3925 outTi3026(PMINFO TVP3026_XPIXPLLDATA
, mclk_p
| 0xB0);
3927 /* wait for PLL to lock */
3928 for (tmout
= 500000; tmout
; tmout
--) {
3929 if (inTi3026(PMINFO TVP3026_XPIXPLLDATA
) & 0x40)
3934 printk(KERN_ERR
"matroxfb: Temporary pixel PLL not locked after 5 secs\n");
3936 /* output pclk on mclk pin */
3937 mclk_ctl
= inTi3026(PMINFO TVP3026_XMEMPLLCTRL
);
3938 outTi3026(PMINFO TVP3026_XMEMPLLCTRL
, mclk_ctl
& 0xE7);
3939 outTi3026(PMINFO TVP3026_XMEMPLLCTRL
, (mclk_ctl
& 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4
);
3942 outTi3026(PMINFO TVP3026_XPLLADDR
, 0xFB);
3943 outTi3026(PMINFO TVP3026_XMEMPLLDATA
, 0x00);
3945 /* set mclk to new freq */
3946 outTi3026(PMINFO TVP3026_XPLLADDR
, 0xF3);
3947 outTi3026(PMINFO TVP3026_XMEMPLLDATA
, mclk_n
| 0xC0);
3948 outTi3026(PMINFO TVP3026_XMEMPLLDATA
, mclk_m
);
3949 outTi3026(PMINFO TVP3026_XMEMPLLDATA
, mclk_p
| 0xB0);
3951 /* wait for PLL to lock */
3952 for (tmout
= 500000; tmout
; tmout
--) {
3953 if (inTi3026(PMINFO TVP3026_XMEMPLLDATA
) & 0x40)
3958 printk(KERN_ERR
"matroxfb: Memory PLL not locked after 5 secs\n");
3960 f_pll
= f_pll
* 333 / (10000 << mclk_p
);
3961 if (isMilleniumII(MINFO
)) {
3962 rfhcnt
= (f_pll
- 128) / 256;
3966 rfhcnt
= (f_pll
- 64) / 128;
3970 hw
->MXoptionReg
= (hw
->MXoptionReg
& ~0x000F0000) | (rfhcnt
<< 16);
3971 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, hw
->MXoptionReg
);
3973 /* output MCLK to MCLK pin */
3974 outTi3026(PMINFO TVP3026_XMEMPLLCTRL
, (mclk_ctl
& 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL
);
3975 outTi3026(PMINFO TVP3026_XMEMPLLCTRL
, (mclk_ctl
) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL
| TVP3026_XMEMPLLCTRL_STROBEMKC4
);
3978 outTi3026(PMINFO TVP3026_XPLLADDR
, 0xFE);
3979 outTi3026(PMINFO TVP3026_XPIXPLLDATA
, 0x00);
3982 outTi3026(PMINFO TVP3026_XPLLADDR
, 0xFC);
3983 outTi3026(PMINFO TVP3026_XPIXPLLDATA
, pclk_n
);
3984 outTi3026(PMINFO TVP3026_XPIXPLLDATA
, pclk_m
);
3985 outTi3026(PMINFO TVP3026_XPIXPLLDATA
, pclk_p
);
3987 /* wait for PLL to lock */
3988 for (tmout
= 500000; tmout
; tmout
--) {
3989 if (inTi3026(PMINFO TVP3026_XPIXPLLDATA
) & 0x40)
3994 printk(KERN_ERR
"matroxfb: Pixel PLL not locked after 5 secs\n");
3997 static void __init
ti3026_ramdac_init(WPMINFO
struct matrox_hw_state
* hw
){
3999 DBG("ti3026_ramdac_init")
4001 ACCESS_FBINFO(features
.pll
.vco_freq_min
) = 110000;
4002 ACCESS_FBINFO(features
.pll
.ref_freq
) = 114545;
4003 ACCESS_FBINFO(features
.pll
.feed_div_min
) = 2;
4004 ACCESS_FBINFO(features
.pll
.feed_div_max
) = 24;
4005 ACCESS_FBINFO(features
.pll
.in_div_min
) = 2;
4006 ACCESS_FBINFO(features
.pll
.in_div_max
) = 63;
4007 ACCESS_FBINFO(features
.pll
.post_shift_max
) = 3;
4008 if (ACCESS_FBINFO(devflags
.noinit
))
4010 ti3026_setMCLK(PMINFO hw
, 60000);
4014 static void matroxfb_fastfont_init(struct matrox_fb_info
* minfo
){
4017 size
= ACCESS_FBINFO(fastfont
.size
);
4018 ACCESS_FBINFO(fastfont
.size
) = 0;
4020 unsigned int end
= ACCESS_FBINFO(video
.len_usable
);
4025 start
= (end
- size
) & PAGE_MASK
;
4026 if (start
>= 0x00100000) {
4027 ACCESS_FBINFO(video
.len_usable
) = start
;
4028 ACCESS_FBINFO(fastfont
.mgabase
) = start
* 8;
4029 ACCESS_FBINFO(fastfont
.vbase
) = ACCESS_FBINFO(video
.vbase
);
4030 vaddr_add(&ACCESS_FBINFO(fastfont
.vbase
), start
);
4031 ACCESS_FBINFO(fastfont
.size
) = end
- start
;
4037 #ifdef CONFIG_FB_MATROX_MYSTIQUE
4038 static void __init
MGA1064_ramdac_init(WPMINFO
struct matrox_hw_state
* hw
){
4040 DBG("MGA1064_ramdac_init");
4042 /* ACCESS_FBINFO(features.DAC1064.vco_freq_min) = 120000; */
4043 ACCESS_FBINFO(features
.pll
.vco_freq_min
) = 62000;
4044 ACCESS_FBINFO(features
.pll
.ref_freq
) = 14318;
4045 ACCESS_FBINFO(features
.pll
.feed_div_min
) = 100;
4046 ACCESS_FBINFO(features
.pll
.feed_div_max
) = 127;
4047 ACCESS_FBINFO(features
.pll
.in_div_min
) = 1;
4048 ACCESS_FBINFO(features
.pll
.in_div_max
) = 31;
4049 ACCESS_FBINFO(features
.pll
.post_shift_max
) = 3;
4050 ACCESS_FBINFO(features
.DAC1064
.xvrefctrl
) = DAC1064_XVREFCTRL_EXTERNAL
;
4051 /* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */
4052 DAC1064_setmclk(PMINFO hw
, DAC1064_OPT_MDIV2
| DAC1064_OPT_GDIV3
| DAC1064_OPT_SCLK_PLL
, 133333);
4055 static int __init
MGA1064_preinit(WPMINFO
struct matrox_hw_state
* hw
){
4056 static const int vxres_mystique
[] = { 512, 640, 768, 800, 832, 960,
4057 1024, 1152, 1280, 1600, 1664, 1920,
4059 DBG("MGA1064_preinit")
4061 /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
4062 ACCESS_FBINFO(capable
.text
) = 1;
4063 ACCESS_FBINFO(capable
.vxres
) = vxres_mystique
;
4064 ACCESS_FBINFO(features
.accel
.has_cacheflush
) = 1;
4065 ACCESS_FBINFO(cursor
.timer
.function
) = matroxfb_DAC1064_flashcursor
;
4067 if (ACCESS_FBINFO(devflags
.noinit
))
4068 return 0; /* do not modify settings */
4069 hw
->MXoptionReg
&= 0xC0000100;
4070 hw
->MXoptionReg
|= 0x00094E20;
4071 if (ACCESS_FBINFO(devflags
.novga
))
4072 hw
->MXoptionReg
&= ~0x00000100;
4073 if (ACCESS_FBINFO(devflags
.nobios
))
4074 hw
->MXoptionReg
&= ~0x40000000;
4075 if (ACCESS_FBINFO(devflags
.nopciretry
))
4076 hw
->MXoptionReg
|= 0x20000000;
4077 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, hw
->MXoptionReg
);
4078 mga_setr(M_SEQ_INDEX
, 0x01, 0x20);
4079 mga_outl(M_CTLWTST
, 0x00000000);
4081 mga_outl(M_MACCESS
, 0x00008000);
4083 mga_outl(M_MACCESS
, 0x0000C000);
4087 static void __init
MGA1064_reset(WPMINFO
struct matrox_hw_state
* hw
){
4089 DBG("MGA1064_reset");
4091 ACCESS_FBINFO(features
.DAC1064
.cursorimage
) = ACCESS_FBINFO(video
.len_usable
) - 1024;
4092 if (ACCESS_FBINFO(devflags
.hwcursor
))
4093 ACCESS_FBINFO(video
.len_usable
) -= 1024;
4094 matroxfb_fastfont_init(MINFO
);
4095 MGA1064_ramdac_init(PMINFO hw
);
4099 #ifdef CONFIG_FB_MATROX_G100
4101 static int x7AF4
= 0x10; /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */
4102 /* G100 wants 0x10, G200 SGRAM does not care... */
4104 static int def50
= 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
4107 static void __init
MGAG100_progPixClock(CPMINFO
int flags
, int m
, int n
, int p
){
4112 DBG("MGAG100_progPixClock")
4114 outDAC1064(PMINFO M1064_XPIXCLKCTRL
, inDAC1064(PMINFO M1064_XPIXCLKCTRL
) | M1064_XPIXCLKCTRL_DIS
|
4115 M1064_XPIXCLKCTRL_PLL_UP
);
4116 switch (flags
& 3) {
4117 case 0: reg
= M1064_XPIXPLLAM
; break;
4118 case 1: reg
= M1064_XPIXPLLBM
; break;
4119 default: reg
= M1064_XPIXPLLCM
; break;
4121 outDAC1064(PMINFO reg
++, m
);
4122 outDAC1064(PMINFO reg
++, n
);
4123 outDAC1064(PMINFO reg
, p
);
4124 selClk
= mga_inb(M_MISC_REG_READ
) & ~0xC;
4125 /* there should be flags & 0x03 & case 0/1/else */
4126 /* and we should first select source and after that we should wait for PLL */
4127 /* and we are waiting for PLL with oscilator disabled... Is it right? */
4128 switch (flags
& 0x03) {
4130 case 0x01: selClk
|= 4; break;
4131 default: selClk
|= 0x0C; break;
4133 mga_outb(M_MISC_REG
, selClk
);
4134 for (clk
= 500000; clk
; clk
--) {
4135 if (inDAC1064(PMINFO M1064_XPIXPLLSTAT
) & 0x40)
4140 printk(KERN_ERR
"matroxfb: Pixel PLL%c not locked after usual time\n", (reg
-M1064_XPIXPLLAM
-2)/4 + 'A');
4141 selClk
= inDAC1064(PMINFO M1064_XPIXCLKCTRL
) & ~M1064_XPIXCLKCTRL_SRC_MASK
;
4142 switch (flags
& 0x0C) {
4143 case 0x00: selClk
|= M1064_XPIXCLKCTRL_SRC_PCI
; break;
4144 case 0x04: selClk
|= M1064_XPIXCLKCTRL_SRC_PLL
; break;
4145 default: selClk
|= M1064_XPIXCLKCTRL_SRC_EXT
; break;
4147 outDAC1064(PMINFO M1064_XPIXCLKCTRL
, selClk
);
4148 outDAC1064(PMINFO M1064_XPIXCLKCTRL
, inDAC1064(PMINFO M1064_XPIXCLKCTRL
) & ~M1064_XPIXCLKCTRL_DIS
);
4151 static void __init
MGAG100_setPixClock(CPMINFO
int flags
, int freq
){
4152 unsigned int m
, n
, p
;
4154 DBG("MGAG100_setPixClock")
4156 DAC1064_calcclock(PMINFO freq
, ACCESS_FBINFO(max_pixel_clock
), &m
, &n
, &p
);
4157 MGAG100_progPixClock(PMINFO flags
, m
, n
, p
);
4160 static int __init
MGAG100_preinit(WPMINFO
struct matrox_hw_state
* hw
){
4161 static const int vxres_g100
[] = { 512, 640, 768, 800, 832, 960,
4162 1024, 1152, 1280, 1600, 1664, 1920,
4169 DBG("MGAG100_preinit")
4171 /* there are some instabilities if in_div > 19 && vco < 61000 */
4172 ACCESS_FBINFO(features
.pll
.vco_freq_min
) = 62000;
4173 ACCESS_FBINFO(features
.pll
.ref_freq
) = 27000;
4174 ACCESS_FBINFO(features
.pll
.feed_div_min
) = 7;
4175 ACCESS_FBINFO(features
.pll
.feed_div_max
) = 127;
4176 ACCESS_FBINFO(features
.pll
.in_div_min
) = 1;
4177 ACCESS_FBINFO(features
.pll
.in_div_max
) = 31;
4178 ACCESS_FBINFO(features
.pll
.post_shift_max
) = 3;
4179 ACCESS_FBINFO(features
.DAC1064
.xvrefctrl
) = DAC1064_XVREFCTRL_G100_DEFAULT
;
4180 /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
4181 ACCESS_FBINFO(capable
.text
) = 1;
4182 ACCESS_FBINFO(capable
.vxres
) = vxres_g100
;
4183 ACCESS_FBINFO(features
.accel
.has_cacheflush
) = 1;
4184 ACCESS_FBINFO(cursor
.timer
.function
) = matroxfb_DAC1064_flashcursor
;
4185 ACCESS_FBINFO(capable
.plnwt
) = ACCESS_FBINFO(devflags
.accelerator
) != FB_ACCEL_MATROX_MGAG100
;
4187 if (ACCESS_FBINFO(devflags
.noinit
))
4189 hw
->MXoptionReg
&= 0xC0000100;
4190 hw
->MXoptionReg
|= 0x00078020;
4191 if (ACCESS_FBINFO(devflags
.novga
))
4192 hw
->MXoptionReg
&= ~0x00000100;
4193 if (ACCESS_FBINFO(devflags
.nobios
))
4194 hw
->MXoptionReg
&= ~0x40000000;
4195 if (ACCESS_FBINFO(devflags
.nopciretry
))
4196 hw
->MXoptionReg
|= 0x20000000;
4197 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, hw
->MXoptionReg
);
4198 pci_read_config_dword(ACCESS_FBINFO(pcidev
), 0x50, ®50
);
4200 pci_write_config_dword(ACCESS_FBINFO(pcidev
), 0x50, reg50
);
4202 DAC1064_setmclk(PMINFO hw
, DAC1064_OPT_MDIV2
| DAC1064_OPT_GDIV3
| DAC1064_OPT_SCLK_PCI
, 133333);
4204 if (ACCESS_FBINFO(devflags
.accelerator
) == FB_ACCEL_MATROX_MGAG100
) {
4205 hw
->MXoptionReg
|= 0x1080;
4206 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, hw
->MXoptionReg
);
4207 mga_outl(M_CTLWTST
, 0x00000300);
4208 /* mga_outl(M_CTLWTST, 0x03258A31); */
4210 mga_outb(0x1C05, 0x00);
4211 mga_outb(0x1C05, 0x80);
4213 mga_outb(0x1C05, 0x40);
4214 mga_outb(0x1C05, 0xC0);
4218 pci_write_config_dword(ACCESS_FBINFO(pcidev
), 0x50, reg50
);
4219 /* it should help with G100 */
4220 mga_outb(M_GRAPHICS_INDEX
, 6);
4221 mga_outb(M_GRAPHICS_DATA
, (mga_inb(M_GRAPHICS_DATA
) & 3) | 4);
4222 mga_setr(M_EXTVGA_INDEX
, 0x03, 0x81);
4223 mga_setr(M_EXTVGA_INDEX
, 0x04, 0x00);
4224 mga_writeb(ACCESS_FBINFO(video
.vbase
), 0x0000, 0xAA);
4225 mga_writeb(ACCESS_FBINFO(video
.vbase
), 0x0800, 0x55);
4226 mga_writeb(ACCESS_FBINFO(video
.vbase
), 0x4000, 0x55);
4228 if (mga_readb(ACCESS_FBINFO(video
.vbase
), 0x0000) != 0xAA) {
4229 hw
->MXoptionReg
&= ~0x1000;
4233 hw
->MXoptionReg
|= 0x00000C00;
4234 if (ACCESS_FBINFO(devflags
.sgram
))
4235 hw
->MXoptionReg
|= 0x4000;
4236 mga_outl(M_CTLWTST
, 0x042450A1);
4237 mga_outb(0x1E47, 0x00);
4238 mga_outb(0x1E46, 0x00);
4240 mga_outb(0x1C05, 0x00);
4241 mga_outb(0x1C05, 0x80);
4243 mga_outw(0x1E44, 0x0108);
4245 hw
->MXoptionReg
= (hw
->MXoptionReg
& ~0x1F8000) | 0x78000;
4246 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, hw
->MXoptionReg
);
4250 static void __init
MGAG100_reset(WPMINFO
struct matrox_hw_state
* hw
){
4253 DBG("MGAG100_reset")
4255 ACCESS_FBINFO(features
.DAC1064
.cursorimage
) = ACCESS_FBINFO(video
.len_usable
) - 1024;
4256 if (ACCESS_FBINFO(devflags
.hwcursor
))
4257 ACCESS_FBINFO(video
.len_usable
) -= 1024;
4258 matroxfb_fastfont_init(MINFO
);
4261 #ifdef G100_BROKEN_IBM_82351
4264 find
1014/22 (IBM
/82351); /* if found and bridging Matrox, do some strange stuff */
4265 pci_read_config_byte(ibm
, PCI_SECONDARY_BUS
, &b
);
4266 if (b
== ACCESS_FBINFO(pcidev
)->bus
->number
) {
4267 pci_write_config_byte(ibm
, PCI_COMMAND
+1, 0); /* disable back-to-back & SERR */
4268 pci_write_config_byte(ibm
, 0x41, 0xF4); /* ??? */
4269 pci_write_config_byte(ibm
, PCI_IO_BASE
, 0xF0); /* ??? */
4270 pci_write_config_byte(ibm
, PCI_IO_LIMIT
, 0x00); /* ??? */
4273 if (!ACCESS_FBINFO(devflags
.noinit
)) {
4275 hw
->MXoptionReg
|= 0x40;
4276 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, hw
->MXoptionReg
);
4278 mga_setr(M_EXTVGA_INDEX
, 0x06, 0x50);
4281 DAC1064_setmclk(PMINFO hw
, DAC1064_OPT_RESERVED
| DAC1064_OPT_MDIV2
| DAC1064_OPT_GDIV1
| DAC1064_OPT_SCLK_PLL
, 133333);
4282 if (ACCESS_FBINFO(devflags
.noinit
))
4284 MGAG100_setPixClock(PMINFO
4, 25175);
4285 MGAG100_setPixClock(PMINFO
5, 28322);
4287 b
= inDAC1064(PMINFO M1064_XGENIODATA
) & ~1;
4288 outDAC1064(PMINFO M1064_XGENIODATA
, b
);
4289 b
= inDAC1064(PMINFO M1064_XGENIOCTRL
) | 1;
4290 outDAC1064(PMINFO M1064_XGENIOCTRL
, b
);
4295 static void vgaHWrestore(CPMINFO
struct matrox_hw_state
* hw
, struct matrox_hw_state
* oldhw
) {
4300 dprintk(KERN_INFO
"MiscOutReg: %02X\n", hw
->MiscOutReg
);
4301 dprintk(KERN_INFO
"SEQ regs: ");
4302 for (i
= 0; i
< 5; i
++)
4303 dprintk("%02X:", hw
->SEQ
[i
]);
4305 dprintk(KERN_INFO
"GDC regs: ");
4306 for (i
= 0; i
< 9; i
++)
4307 dprintk("%02X:", hw
->GCTL
[i
]);
4309 dprintk(KERN_INFO
"CRTC regs: ");
4310 for (i
= 0; i
< 25; i
++)
4311 dprintk("%02X:", hw
->CRTC
[i
]);
4313 dprintk(KERN_INFO
"ATTR regs: ");
4314 for (i
= 0; i
< 21; i
++)
4315 dprintk("%02X:", hw
->ATTR
[i
]);
4320 mga_inb(M_ATTR_RESET
);
4321 mga_outb(M_ATTR_INDEX
, 0);
4322 mga_outb(M_MISC_REG
, hw
->MiscOutReg
);
4323 for (i
= 1; i
< 5; i
++)
4324 mga_setr(M_SEQ_INDEX
, i
, hw
->SEQ
[i
]);
4325 mga_setr(M_CRTC_INDEX
, 17, hw
->CRTC
[17] & 0x7F);
4326 for (i
= 0; i
< 25; i
++)
4327 mga_setr(M_CRTC_INDEX
, i
, hw
->CRTC
[i
]);
4328 for (i
= 0; i
< 9; i
++)
4329 mga_setr(M_GRAPHICS_INDEX
, i
, hw
->GCTL
[i
]);
4330 for (i
= 0; i
< 21; i
++) {
4331 mga_inb(M_ATTR_RESET
);
4332 mga_outb(M_ATTR_INDEX
, i
);
4333 mga_outb(M_ATTR_INDEX
, hw
->ATTR
[i
]);
4335 mga_outb(M_PALETTE_MASK
, 0xFF);
4336 mga_outb(M_DAC_REG
, 0x00);
4337 for (i
= 0; i
< 768; i
++)
4338 mga_outb(M_DAC_VAL
, hw
->DACpal
[i
]);
4339 mga_inb(M_ATTR_RESET
);
4340 mga_outb(M_ATTR_INDEX
, 0x20);
4345 static int matrox_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
4346 unsigned blue
, unsigned transp
,
4347 struct fb_info
*fb_info
)
4350 #ifdef CONFIG_FB_MATROX_MULTIHEAD
4351 struct matrox_fb_info
* minfo
= (struct matrox_fb_info
*)fb_info
;
4354 DBG("matrox_setcolreg")
4357 * Set a single color register. The values supplied are
4358 * already rounded down to the hardware's capabilities
4359 * (according to the entries in the `var' structure). Return
4360 * != 0 for invalid regno.
4363 if (regno
>= ACCESS_FBINFO(curr
.cmap_len
))
4366 ACCESS_FBINFO(palette
[regno
].red
) = red
;
4367 ACCESS_FBINFO(palette
[regno
].green
) = green
;
4368 ACCESS_FBINFO(palette
[regno
].blue
) = blue
;
4369 ACCESS_FBINFO(palette
[regno
].transp
) = transp
;
4371 p
= ACCESS_FBINFO(currcon_display
);
4372 if (p
->var
.grayscale
) {
4373 /* gray = 0.30*R + 0.59*G + 0.11*B */
4374 red
= green
= blue
= (red
* 77 + green
* 151 + blue
* 28) >> 8;
4377 red
= CNVT_TOHW(red
, p
->var
.red
.length
);
4378 green
= CNVT_TOHW(green
, p
->var
.green
.length
);
4379 blue
= CNVT_TOHW(blue
, p
->var
.blue
.length
);
4380 transp
= CNVT_TOHW(transp
, p
->var
.transp
.length
);
4382 switch (p
->var
.bits_per_pixel
) {
4383 #if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB4) || defined(FBCON_HAS_VGATEXT)
4384 #ifdef FBCON_HAS_VGATEXT
4387 #ifdef FBCON_HAS_CFB4
4390 #ifdef FBCON_HAS_CFB8
4393 mga_outb(M_DAC_REG
, regno
);
4394 mga_outb(M_DAC_VAL
, red
);
4395 mga_outb(M_DAC_VAL
, green
);
4396 mga_outb(M_DAC_VAL
, blue
);
4399 #ifdef FBCON_HAS_CFB16
4401 ACCESS_FBINFO(cmap
.cfb16
[regno
]) =
4402 (red
<< p
->var
.red
.offset
) |
4403 (green
<< p
->var
.green
.offset
) |
4404 (blue
<< p
->var
.blue
.offset
) |
4405 (transp
<< p
->var
.transp
.offset
); /* for 1:5:5:5 */
4408 #ifdef FBCON_HAS_CFB24
4410 ACCESS_FBINFO(cmap
.cfb24
[regno
]) =
4411 (red
<< p
->var
.red
.offset
) |
4412 (green
<< p
->var
.green
.offset
) |
4413 (blue
<< p
->var
.blue
.offset
);
4416 #ifdef FBCON_HAS_CFB32
4418 ACCESS_FBINFO(cmap
.cfb32
[regno
]) =
4419 (red
<< p
->var
.red
.offset
) |
4420 (green
<< p
->var
.green
.offset
) |
4421 (blue
<< p
->var
.blue
.offset
) |
4422 (transp
<< p
->var
.transp
.offset
); /* 8:8:8:8 */
4429 static void do_install_cmap(WPMINFO
struct display
* dsp
)
4431 DBG("do_install_cmap")
4434 fb_set_cmap(&dsp
->cmap
, 1, matrox_setcolreg
, &ACCESS_FBINFO(fbcon
));
4436 fb_set_cmap(fb_default_cmap(ACCESS_FBINFO(curr
.cmap_len
)),
4437 1, matrox_setcolreg
, &ACCESS_FBINFO(fbcon
));
4440 #ifdef CONFIG_FB_MATROX_MYSTIQUE
4441 static void MGA1064_restore(WPMINFO
struct matrox_hw_state
* hw
, struct matrox_hw_state
* oldhw
, struct display
* p
) {
4444 DBG("MGA1064_restore")
4448 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, hw
->MXoptionReg
);
4449 mga_outb(M_IEN
, 0x00);
4450 mga_outb(M_CACHEFLUSH
, 0x00);
4454 DAC1064_restore_1(PMINFO hw
, oldhw
);
4455 vgaHWrestore(PMINFO hw
, oldhw
);
4456 for (i
= 0; i
< 6; i
++)
4457 mga_setr(M_EXTVGA_INDEX
, i
, hw
->CRTCEXT
[i
]);
4458 DAC1064_restore_2(PMINFO hw
, oldhw
, p
);
4462 #ifdef CONFIG_FB_MATROX_G100
4463 static void MGAG100_restore(WPMINFO
struct matrox_hw_state
* hw
, struct matrox_hw_state
* oldhw
, struct display
* p
) {
4466 DBG("MGAG100_restore")
4470 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, hw
->MXoptionReg
);
4473 DAC1064_restore_1(PMINFO hw
, oldhw
);
4474 vgaHWrestore(PMINFO hw
, oldhw
);
4475 #ifdef CONFIG_FB_MATROX_32MB
4476 if (ACCESS_FBINFO(devflags
.support32MB
))
4477 mga_setr(M_EXTVGA_INDEX
, 8, hw
->CRTCEXT
[8]);
4479 for (i
= 0; i
< 6; i
++)
4480 mga_setr(M_EXTVGA_INDEX
, i
, hw
->CRTCEXT
[i
]);
4481 DAC1064_restore_2(PMINFO hw
, oldhw
, p
);
4485 #ifdef CONFIG_FB_MATROX_MILLENIUM
4486 static void Ti3026_restore(WPMINFO
struct matrox_hw_state
* hw
, struct matrox_hw_state
* oldhw
, struct display
* p
) {
4489 DBG("Ti3026_restore")
4491 dprintk(KERN_INFO
"EXTVGA regs: ");
4492 for (i
= 0; i
< 6; i
++)
4493 dprintk("%02X:", hw
->CRTCEXT
[i
]);
4498 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, hw
->MXoptionReg
);
4502 vgaHWrestore(PMINFO hw
, oldhw
);
4506 for (i
= 0; i
< 6; i
++)
4507 mga_setr(M_EXTVGA_INDEX
, i
, hw
->CRTCEXT
[i
]);
4509 for (i
= 0; i
< 21; i
++) {
4510 outTi3026(PMINFO DACseq
[i
], hw
->DACreg
[i
]);
4513 outTi3026(PMINFO TVP3026_XPLLADDR
, 0x00);
4514 oldhw
->DACclk
[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA
);
4515 oldhw
->DACclk
[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA
);
4516 outTi3026(PMINFO TVP3026_XPLLADDR
, 0x15);
4517 oldhw
->DACclk
[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA
);
4518 oldhw
->DACclk
[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA
);
4519 outTi3026(PMINFO TVP3026_XPLLADDR
, 0x2A);
4520 oldhw
->DACclk
[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA
);
4521 oldhw
->DACclk
[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA
);
4524 if (!oldhw
|| memcmp(hw
->DACclk
, oldhw
->DACclk
, 6)) {
4525 /* agrhh... setting up PLL is very slow on Millenium... */
4526 /* Mystique PLL is locked in few ms, but Millenium PLL lock takes about 0.15 s... */
4527 /* Maybe even we should call schedule() ? */
4530 outTi3026(PMINFO TVP3026_XCLKCTRL
, hw
->DACreg
[POS3026_XCLKCTRL
]);
4531 outTi3026(PMINFO TVP3026_XPLLADDR
, 0x2A);
4532 outTi3026(PMINFO TVP3026_XLOOPPLLDATA
, 0);
4533 outTi3026(PMINFO TVP3026_XPIXPLLDATA
, 0);
4535 outTi3026(PMINFO TVP3026_XPLLADDR
, 0x00);
4536 for (i
= 0; i
< 3; i
++)
4537 outTi3026(PMINFO TVP3026_XPIXPLLDATA
, hw
->DACclk
[i
]);
4538 /* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */
4539 if (hw
->MiscOutReg
& 0x08) {
4541 outTi3026(PMINFO TVP3026_XPLLADDR
, 0x3F);
4542 for (tmout
= 500000; tmout
; --tmout
) {
4543 if (inTi3026(PMINFO TVP3026_XPIXPLLDATA
) & 0x40)
4551 printk(KERN_ERR
"matroxfb: Pixel PLL not locked after 5 secs\n");
4553 dprintk(KERN_INFO
"PixelPLL: %d\n", 500000-tmout
);
4556 outTi3026(PMINFO TVP3026_XMEMPLLCTRL
, hw
->DACreg
[POS3026_XMEMPLLCTRL
]);
4557 outTi3026(PMINFO TVP3026_XPLLADDR
, 0x00);
4558 for (i
= 3; i
< 6; i
++)
4559 outTi3026(PMINFO TVP3026_XLOOPPLLDATA
, hw
->DACclk
[i
]);
4561 if ((hw
->MiscOutReg
& 0x08) && ((hw
->DACclk
[5] & 0x80) == 0x80)) {
4565 outTi3026(PMINFO TVP3026_XPLLADDR
, 0x3F);
4566 for (tmout
= 500000; tmout
; --tmout
) {
4567 if (inTi3026(PMINFO TVP3026_XLOOPPLLDATA
) & 0x40)
4573 printk(KERN_ERR
"matroxfb: Loop PLL not locked after 5 secs\n");
4575 dprintk(KERN_INFO
"LoopPLL: %d\n", 500000-tmout
);
4579 if (p
->type
== FB_TYPE_TEXT
) {
4580 matrox_text_createcursor(PMINFO p
);
4581 matrox_text_loadfont(PMINFO p
);
4584 matroxfb_ti3026_createcursor(PMINFO p
);
4585 i
= matroxfb_fastfont_tryset(PMINFO p
);
4590 ACCESS_FBINFO(curr
.putc
) = matrox_cfbX_fastputc
;
4591 ACCESS_FBINFO(curr
.putcs
) = matrox_cfbX_fastputcs
;
4593 ACCESS_FBINFO(curr
.putc
) = matrox_cfbX_putc
;
4594 ACCESS_FBINFO(curr
.putcs
) = matrox_cfbX_putcs
;
4597 dprintk(KERN_DEBUG
"3026DACregs ");
4598 for (i
= 0; i
< 21; i
++) {
4599 dprintk("R%02X=%02X ", DACseq
[i
], hw
->DACreg
[i
]);
4600 if ((i
& 0x7) == 0x7) dprintk("\n" KERN_DEBUG
"continuing... ");
4602 dprintk("\n" KERN_DEBUG
"DACclk ");
4603 for (i
= 0; i
< 6; i
++)
4604 dprintk("C%02X=%02X ", i
, hw
->DACclk
[i
]);
4609 static int matroxfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
4610 struct fb_info
*info
)
4613 DBG("matroxfb_get_fix")
4615 #define minfo ((struct matrox_fb_info*)info)
4618 p
= fb_display
+ con
;
4620 p
= ACCESS_FBINFO(fbcon
.disp
);
4622 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
4623 strcpy(fix
->id
,"MATROX");
4625 fix
->smem_start
= ACCESS_FBINFO(video
.base
) + ACCESS_FBINFO(curr
.ydstorg
.bytes
);
4626 fix
->smem_len
= ACCESS_FBINFO(video
.len_usable
) - ACCESS_FBINFO(curr
.ydstorg
.bytes
);
4627 fix
->type
= p
->type
;
4628 fix
->type_aux
= p
->type_aux
;
4629 fix
->visual
= p
->visual
;
4630 fix
->xpanstep
= 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */
4633 fix
->line_length
= p
->line_length
;
4634 fix
->mmio_start
= ACCESS_FBINFO(mmio
.base
);
4635 fix
->mmio_len
= ACCESS_FBINFO(mmio
.len
);
4636 fix
->accel
= ACCESS_FBINFO(devflags
.accelerator
);
4641 static int matroxfb_get_var(struct fb_var_screeninfo
*var
, int con
,
4642 struct fb_info
*info
)
4644 #define minfo ((struct matrox_fb_info*)info)
4645 DBG("matroxfb_get_var")
4648 *var
=ACCESS_FBINFO(fbcon
.disp
)->var
;
4650 *var
=fb_display
[con
].var
;
4655 static int matroxfb_set_var(struct fb_var_screeninfo
*var
, int con
,
4656 struct fb_info
*info
)
4658 #define minfo ((struct matrox_fb_info*)info)
4662 unsigned int ydstorg
;
4663 struct display
* display
;
4666 DBG("matroxfb_set_var")
4669 display
= fb_display
+ con
;
4671 display
= ACCESS_FBINFO(fbcon
.disp
);
4672 if ((err
= matroxfb_decode_var(PMINFO display
, var
, &visual
, &cmap_len
, &ydstorg
)) != 0)
4674 switch (var
->activate
& FB_ACTIVATE_MASK
) {
4675 case FB_ACTIVATE_TEST
: return 0;
4676 case FB_ACTIVATE_NXTOPEN
: /* ?? */
4677 case FB_ACTIVATE_NOW
: break; /* continue */
4678 default: return -EINVAL
; /* unknown */
4681 chgvar
= ((display
->var
.xres
!= var
->xres
) ||
4682 (display
->var
.yres
!= var
->yres
) ||
4683 (display
->var
.xres_virtual
!= var
->xres_virtual
) ||
4684 (display
->var
.yres_virtual
!= var
->yres_virtual
) ||
4685 (display
->var
.bits_per_pixel
!= var
->bits_per_pixel
) ||
4686 memcmp(&display
->var
.red
, &var
->red
, sizeof(var
->red
)) ||
4687 memcmp(&display
->var
.green
, &var
->green
, sizeof(var
->green
)) ||
4688 memcmp(&display
->var
.blue
, &var
->blue
, sizeof(var
->blue
)));
4692 display
->var
= *var
;
4694 display
->screen_base
= vaddr_va(ACCESS_FBINFO(video
.vbase
)) + ydstorg
;
4695 display
->visual
= visual
;
4696 display
->ypanstep
= 1;
4697 display
->ywrapstep
= 0;
4698 if (var
->bits_per_pixel
) {
4699 display
->type
= FB_TYPE_PACKED_PIXELS
;
4700 display
->type_aux
= 0;
4701 display
->next_line
= display
->line_length
= (var
->xres_virtual
* var
->bits_per_pixel
) >> 3;
4703 display
->type
= FB_TYPE_TEXT
;
4704 display
->type_aux
= ACCESS_FBINFO(devflags
.text_type_aux
);
4705 display
->next_line
= display
->line_length
= (var
->xres_virtual
/ (fontwidth(display
)?fontwidth(display
):8)) * ACCESS_FBINFO(devflags
.textstep
);
4707 display
->can_soft_blank
= 1;
4708 display
->inverse
= ACCESS_FBINFO(devflags
.inverse
);
4709 /* conp, fb_info, vrows, cursor_x, cursor_y, fgcol, bgcol */
4710 /* next_plane, fontdata, _font*, userfont */
4711 initMatrox(PMINFO display
); /* dispsw */
4712 /* dispsw, scrollmode, yscroll */
4713 /* fgshift, bgshift, charmask */
4714 if (chgvar
&& info
&& info
->changevar
)
4715 info
->changevar(con
);
4716 if (con
== ACCESS_FBINFO(currcon
)) {
4719 ACCESS_FBINFO(curr
.cmap_len
) = cmap_len
;
4720 if (display
->type
== FB_TYPE_TEXT
) {
4721 /* textmode must be in first megabyte, so no ydstorg allowed */
4722 ACCESS_FBINFO(curr
.ydstorg
.bytes
) = 0;
4723 ACCESS_FBINFO(curr
.ydstorg
.chunks
) = 0;
4724 ACCESS_FBINFO(curr
.ydstorg
.pixels
) = 0;
4726 ydstorg
+= ACCESS_FBINFO(devflags
.ydstorg
);
4727 ACCESS_FBINFO(curr
.ydstorg
.bytes
) = ydstorg
;
4728 ACCESS_FBINFO(curr
.ydstorg
.chunks
) = ydstorg
>> (isInterleave(MINFO
)?3:2);
4729 if (var
->bits_per_pixel
== 4)
4730 ACCESS_FBINFO(curr
.ydstorg
.pixels
) = ydstorg
;
4732 ACCESS_FBINFO(curr
.ydstorg
.pixels
) = (ydstorg
* 8) / var
->bits_per_pixel
;
4734 ACCESS_FBINFO(curr
.final_bppShift
) = matroxfb_get_final_bppShift(PMINFO var
->bits_per_pixel
);
4735 if (visual
== MX_VISUAL_PSEUDOCOLOR
) {
4738 for (i
= 0; i
< 16; i
++) {
4742 ACCESS_FBINFO(palette
[i
].red
) = default_red
[j
];
4743 ACCESS_FBINFO(palette
[i
].green
) = default_grn
[j
];
4744 ACCESS_FBINFO(palette
[i
].blue
) = default_blu
[j
];
4748 { struct my_timming mt
;
4749 struct matrox_hw_state
* hw
;
4750 struct matrox_hw_state
* ohw
;
4753 hw
= ACCESS_FBINFO(newhw
);
4754 ohw
= ACCESS_FBINFO(currenthw
);
4756 /* MXoptionReg is not set from scratch */
4757 hw
->MXoptionReg
= ohw
->MXoptionReg
;
4758 /* DACclk[3]..[5] are not initialized with DAC1064 */
4759 memcpy(hw
->DACclk
, ohw
->DACclk
, sizeof(hw
->DACclk
));
4760 /* others are initialized by init() */
4762 del_timer(&ACCESS_FBINFO(cursor
.timer
));
4763 ACCESS_FBINFO(cursor
.state
) = CM_ERASE
;
4765 ACCESS_FBINFO(hw_switch
->init(PMINFO hw
, &mt
, display
));
4766 if (display
->type
== FB_TYPE_TEXT
) {
4767 if (fontheight(display
))
4768 pos
= var
->yoffset
/ fontheight(display
) * display
->next_line
/ ACCESS_FBINFO(devflags
.textstep
) + var
->xoffset
/ (fontwidth(display
)?fontwidth(display
):8);
4772 pos
= (var
->yoffset
* var
->xres_virtual
+ var
->xoffset
) * ACCESS_FBINFO(curr
.final_bppShift
) / 32;
4773 pos
+= ACCESS_FBINFO(curr
.ydstorg
.chunks
);
4776 hw
->CRTC
[0x0D] = pos
& 0xFF;
4777 hw
->CRTC
[0x0C] = (pos
& 0xFF00) >> 8;
4778 hw
->CRTCEXT
[0] = (hw
->CRTCEXT
[0] & 0xF0) | ((pos
>> 16) & 0x0F) | ((pos
>> 14) & 0x40);
4779 hw
->CRTCEXT
[8] = pos
>> 21;
4780 ACCESS_FBINFO(hw_switch
->restore(PMINFO hw
, ohw
, display
));
4781 ACCESS_FBINFO(cursor
.redraw
) = 1;
4782 ACCESS_FBINFO(currenthw
) = hw
;
4783 ACCESS_FBINFO(newhw
) = ohw
;
4784 matrox_cfbX_init(PMINFO display
);
4785 do_install_cmap(PMINFO display
);
4786 #if defined(CONFIG_FB_OF) && defined(CONFIG_FB_COMPAT_XPMAC)
4787 if (console_fb_info
== &ACCESS_FBINFO(fbcon
)) {
4790 display_info
.width
= var
->xres
;
4791 display_info
.height
= var
->yres
;
4792 display_info
.depth
= var
->bits_per_pixel
;
4793 display_info
.pitch
= (var
->xres_virtual
)*(var
->bits_per_pixel
)/8;
4794 if (mac_var_to_vmode(var
, &vmode
, &cmode
))
4795 display_info
.mode
= 0;
4797 display_info
.mode
= vmode
;
4798 strcpy(display_info
.name
, ACCESS_FBINFO(matrox_name
));
4799 display_info
.fb_address
= ACCESS_FBINFO(video
.base
);
4800 display_info
.cmap_adr_address
= 0;
4801 display_info
.cmap_data_address
= 0;
4802 display_info
.disp_reg_address
= ACCESS_FBINFO(mmio
.base
);
4804 #endif /* CONFIG_FB_OF && CONFIG_FB_COMPAT_XPMAC */
4811 static int matrox_getcolreg(unsigned regno
, unsigned *red
, unsigned *green
,
4812 unsigned *blue
, unsigned *transp
,
4813 struct fb_info
*info
)
4816 DBG("matrox_getcolreg")
4818 #define minfo ((struct matrox_fb_info*)info)
4820 * Read a single color register and split it into colors/transparent.
4821 * Return != 0 for invalid regno.
4824 if (regno
>= ACCESS_FBINFO(curr
.cmap_len
))
4827 *red
= ACCESS_FBINFO(palette
[regno
].red
);
4828 *green
= ACCESS_FBINFO(palette
[regno
].green
);
4829 *blue
= ACCESS_FBINFO(palette
[regno
].blue
);
4830 *transp
= ACCESS_FBINFO(palette
[regno
].transp
);
4835 static int matroxfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
4836 struct fb_info
*info
)
4838 #define minfo ((struct matrox_fb_info*)info)
4839 struct display
* dsp
= (con
< 0) ? ACCESS_FBINFO(fbcon
.disp
)
4842 DBG("matroxfb_get_cmap")
4844 if (con
== ACCESS_FBINFO(currcon
)) /* current console? */
4845 return fb_get_cmap(cmap
, kspc
, matrox_getcolreg
, info
);
4846 else if (dsp
->cmap
.len
) /* non default colormap? */
4847 fb_copy_cmap(&dsp
->cmap
, cmap
, kspc
? 0 : 2);
4849 fb_copy_cmap(fb_default_cmap(matroxfb_get_cmap_len(&dsp
->var
)),
4850 cmap
, kspc
? 0 : 2);
4855 static int matroxfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
4856 struct fb_info
*info
)
4858 unsigned int cmap_len
;
4859 struct display
* dsp
= (con
< 0) ? info
->disp
: (fb_display
+ con
);
4860 #define minfo ((struct matrox_fb_info*)info)
4862 DBG("matroxfb_set_cmap")
4864 cmap_len
= matroxfb_get_cmap_len(&dsp
->var
);
4865 if (dsp
->cmap
.len
!= cmap_len
) {
4868 err
= fb_alloc_cmap(&dsp
->cmap
, cmap_len
, 0);
4872 if (con
== ACCESS_FBINFO(currcon
)) { /* current console? */
4873 return fb_set_cmap(cmap
, kspc
, matrox_setcolreg
, info
);
4875 fb_copy_cmap(cmap
, &dsp
->cmap
, kspc
? 0 : 1);
4880 static int matroxfb_ioctl(struct inode
*inode
, struct file
*file
,
4881 unsigned int cmd
, unsigned long arg
, int con
,
4882 struct fb_info
*info
)
4885 DBG("matroxfb_ioctl")
4890 static struct fb_ops matroxfb_ops
= {
4898 matroxfb_pan_display
,
4903 static int matroxfb_switch(int con
, struct fb_info
*info
)
4905 #define minfo ((struct matrox_fb_info*)info)
4906 struct fb_cmap
* cmap
;
4908 DBG("matroxfb_switch");
4910 if (ACCESS_FBINFO(currcon
) >= 0) {
4911 /* Do we have to save the colormap? */
4912 cmap
= &(ACCESS_FBINFO(currcon_display
)->cmap
);
4913 dprintk(KERN_DEBUG
"switch1: con = %d, cmap.len = %d\n", ACCESS_FBINFO(currcon
), cmap
->len
);
4916 dprintk(KERN_DEBUG
"switch1a: %p %p %p %p\n", cmap
->red
, cmap
->green
, cmap
->blue
, cmap
->transp
);
4917 fb_get_cmap(cmap
, 1, matrox_getcolreg
, info
);
4920 dprintk(KERN_DEBUG
"switch1r: %X\n", cmap
->red
[0]);
4925 ACCESS_FBINFO(currcon
) = con
;
4926 ACCESS_FBINFO(currcon_display
) = fb_display
+ con
;
4927 fb_display
[con
].var
.activate
= FB_ACTIVATE_NOW
;
4929 cmap
= &fb_display
[con
].cmap
;
4930 dprintk(KERN_DEBUG
"switch2: con = %d, cmap.len = %d\n", con
, cmap
->len
);
4931 dprintk(KERN_DEBUG
"switch2a: %p %p %p %p\n", cmap
->red
, cmap
->green
, cmap
->blue
, cmap
->transp
);
4932 if (fb_display
[con
].cmap
.red
) {
4933 dprintk(KERN_DEBUG
"switch2r: %X\n", cmap
->red
[0]);
4936 matroxfb_set_var(&fb_display
[con
].var
, con
, info
);
4938 dprintk(KERN_DEBUG
"switch3: con = %d, cmap.len = %d\n", con
, cmap
->len
);
4939 dprintk(KERN_DEBUG
"switch3a: %p %p %p %p\n", cmap
->red
, cmap
->green
, cmap
->blue
, cmap
->transp
);
4940 if (fb_display
[con
].cmap
.red
) {
4941 dprintk(KERN_DEBUG
"switch3r: %X\n", cmap
->red
[0]);
4948 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
4950 static void matroxfb_blank(int blank
, struct fb_info
*info
)
4952 #define minfo ((struct matrox_fb_info*)info)
4956 DBG("matroxfb_blank")
4959 case 1: seq
= 0x20; crtc
= 0x00; break; /* works ??? */
4960 case 2: seq
= 0x20; crtc
= 0x10; break;
4961 case 3: seq
= 0x20; crtc
= 0x20; break;
4962 case 4: seq
= 0x20; crtc
= 0x30; break;
4963 default: seq
= 0x00; crtc
= 0x00; break;
4968 mga_outb(M_SEQ_INDEX
, 1);
4969 mga_outb(M_SEQ_DATA
, (mga_inb(M_SEQ_DATA
) & ~0x20) | seq
);
4970 mga_outb(M_EXTVGA_INDEX
, 1);
4971 mga_outb(M_EXTVGA_DATA
, (mga_inb(M_EXTVGA_DATA
) & ~0x30) | crtc
);
4978 #define RSResolution(X) ((X) & 0x0F)
4982 #define RS1024x768 4
4983 #define RS1280x1024 5
4984 #define RS1600x1200 6
4987 #define RS1152x864 9
4988 #define RS1408x1056 10
4989 #define RS640x350 11
4990 #define RS1056x344 12 /* 132 x 43 text */
4991 #define RS1056x400 13 /* 132 x 50 text */
4992 #define RS1056x480 14 /* 132 x 60 text */
4995 static struct { int xres
, yres
, left
, right
, upper
, lower
, hslen
, vslen
, vfreq
; } timmings
[] __initdata
= {
4996 { 640, 400, 48, 16, 39, 8, 96, 2, 70 },
4997 { 640, 480, 48, 16, 33, 10, 96, 2, 60 },
4998 { 800, 600, 144, 24, 28, 8, 112, 6, 60 },
4999 { 1024, 768, 160, 32, 30, 4, 128, 4, 60 },
5000 { 1280, 1024, 224, 32, 32, 4, 136, 4, 60 },
5001 { 1600, 1200, 272, 48, 32, 5, 152, 5, 60 },
5002 { 768, 576, 144, 16, 28, 6, 112, 4, 60 },
5003 { 960, 720, 144, 24, 28, 8, 112, 4, 60 },
5004 { 1152, 864, 192, 32, 30, 4, 128, 4, 60 },
5005 { 1408, 1056, 256, 40, 32, 5, 144, 5, 60 },
5006 { 640, 350, 48, 16, 39, 8, 96, 2, 70 },
5007 { 1056, 344, 96, 24, 59, 44, 160, 2, 70 },
5008 { 1056, 400, 96, 24, 39, 8, 160, 2, 70 },
5009 { 1056, 480, 96, 24, 36, 12, 160, 3, 60 },
5010 { 0, 0, ~0, ~0, ~0, ~0, 0, 0, 0 }
5013 #define RSDepth(X) (((X) >> 8) & 0x0F)
5023 static struct { struct fb_bitfield red
, green
, blue
, transp
; int bits_per_pixel
; } colors
[] __initdata
= {
5024 { { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 8 },
5025 { { 10, 5, 0}, { 5, 5, 0}, { 0, 5, 0}, { 15, 1, 0}, 16 },
5026 { { 11, 5, 0}, { 6, 5, 0}, { 0, 5, 0}, { 0, 0, 0}, 16 },
5027 { { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 24, 8, 0}, 32 },
5028 { { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 4 },
5029 { { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 24 },
5030 { { 0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, { 0, 0, 0}, 0 }, /* textmode with (default) VGA8x16 */
5031 { { 0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, { 0, 0, 0}, 0 }, /* textmode hardwired to VGA8x8 */
5034 #define RSCreate(X,Y) ((X) | ((Y) << 8))
5035 static struct { unsigned int vesa
; unsigned int info
; } *RSptr
, vesamap
[] __initdata
= {
5036 /* default must be first */
5037 #ifdef FBCON_HAS_CFB8
5038 { ~0, RSCreate(RSNoxNo
, RS8bpp
) },
5039 { 0x101, RSCreate(RS640x480
, RS8bpp
) },
5040 { 0x100, RSCreate(RS640x400
, RS8bpp
) },
5041 { 0x180, RSCreate(RS768x576
, RS8bpp
) },
5042 { 0x103, RSCreate(RS800x600
, RS8bpp
) },
5043 { 0x188, RSCreate(RS960x720
, RS8bpp
) },
5044 { 0x105, RSCreate(RS1024x768
, RS8bpp
) },
5045 { 0x190, RSCreate(RS1152x864
, RS8bpp
) },
5046 { 0x107, RSCreate(RS1280x1024
, RS8bpp
) },
5047 { 0x198, RSCreate(RS1408x1056
, RS8bpp
) },
5048 { 0x11C, RSCreate(RS1600x1200
, RS8bpp
) },
5050 #ifdef FBCON_HAS_CFB16
5051 { ~0, RSCreate(RSNoxNo
, RS15bpp
) },
5052 { 0x110, RSCreate(RS640x480
, RS15bpp
) },
5053 { 0x181, RSCreate(RS768x576
, RS15bpp
) },
5054 { 0x113, RSCreate(RS800x600
, RS15bpp
) },
5055 { 0x189, RSCreate(RS960x720
, RS15bpp
) },
5056 { 0x116, RSCreate(RS1024x768
, RS15bpp
) },
5057 { 0x191, RSCreate(RS1152x864
, RS15bpp
) },
5058 { 0x119, RSCreate(RS1280x1024
, RS15bpp
) },
5059 { 0x199, RSCreate(RS1408x1056
, RS15bpp
) },
5060 { 0x11D, RSCreate(RS1600x1200
, RS15bpp
) },
5061 { 0x111, RSCreate(RS640x480
, RS16bpp
) },
5062 { 0x182, RSCreate(RS768x576
, RS16bpp
) },
5063 { 0x114, RSCreate(RS800x600
, RS16bpp
) },
5064 { 0x18A, RSCreate(RS960x720
, RS16bpp
) },
5065 { 0x117, RSCreate(RS1024x768
, RS16bpp
) },
5066 { 0x192, RSCreate(RS1152x864
, RS16bpp
) },
5067 { 0x11A, RSCreate(RS1280x1024
, RS16bpp
) },
5068 { 0x19A, RSCreate(RS1408x1056
, RS16bpp
) },
5069 { 0x11E, RSCreate(RS1600x1200
, RS16bpp
) },
5071 #ifdef FBCON_HAS_CFB24
5072 { ~0, RSCreate(RSNoxNo
, RS24bpp
) },
5073 { 0x1B2, RSCreate(RS640x480
, RS24bpp
) },
5074 { 0x184, RSCreate(RS768x576
, RS24bpp
) },
5075 { 0x1B5, RSCreate(RS800x600
, RS24bpp
) },
5076 { 0x18C, RSCreate(RS960x720
, RS24bpp
) },
5077 { 0x1B8, RSCreate(RS1024x768
, RS24bpp
) },
5078 { 0x194, RSCreate(RS1152x864
, RS24bpp
) },
5079 { 0x1BB, RSCreate(RS1280x1024
, RS24bpp
) },
5080 { 0x19C, RSCreate(RS1408x1056
, RS24bpp
) },
5081 { 0x1BF, RSCreate(RS1600x1200
, RS24bpp
) },
5083 #ifdef FBCON_HAS_CFB32
5084 { ~0, RSCreate(RSNoxNo
, RS32bpp
) },
5085 { 0x112, RSCreate(RS640x480
, RS32bpp
) },
5086 { 0x183, RSCreate(RS768x576
, RS32bpp
) },
5087 { 0x115, RSCreate(RS800x600
, RS32bpp
) },
5088 { 0x18B, RSCreate(RS960x720
, RS32bpp
) },
5089 { 0x118, RSCreate(RS1024x768
, RS32bpp
) },
5090 { 0x193, RSCreate(RS1152x864
, RS32bpp
) },
5091 { 0x11B, RSCreate(RS1280x1024
, RS32bpp
) },
5092 { 0x19B, RSCreate(RS1408x1056
, RS32bpp
) },
5093 { 0x11F, RSCreate(RS1600x1200
, RS32bpp
) },
5095 #ifdef FBCON_HAS_VGATEXT
5096 { ~0, RSCreate(RSNoxNo
, RSText
) },
5097 { 0x002, RSCreate(RS640x400
, RSText
) }, /* 80x25 */
5098 { 0x003, RSCreate(RS640x400
, RSText
) }, /* 80x25 */
5099 { 0x007, RSCreate(RS640x400
, RSText
) }, /* 80x25 */
5100 { 0x1C0, RSCreate(RS640x400
, RSText8
) }, /* 80x50 */
5101 { 0x108, RSCreate(RS640x480
, RSText8
) }, /* 80x60 */
5102 { 0x109, RSCreate(RS1056x400
, RSText
) }, /* 132x25 */
5103 { 0x10A, RSCreate(RS1056x344
, RSText8
) }, /* 132x43 */
5104 { 0x10B, RSCreate(RS1056x400
, RSText8
) }, /* 132x50 */
5105 { 0x10C, RSCreate(RS1056x480
, RSText8
) }, /* 132x60 */
5107 #ifdef FBCON_HAS_CFB4
5108 { ~0, RSCreate(RSNoxNo
, RS4bpp
) },
5109 { 0x010, RSCreate(RS640x350
, RS4bpp
) },
5110 { 0x012, RSCreate(RS640x480
, RS4bpp
) },
5111 { 0x102, RSCreate(RS800x600
, RS4bpp
) },
5112 { 0x104, RSCreate(RS1024x768
, RS4bpp
) },
5113 { 0x106, RSCreate(RS1280x1024
, RS4bpp
) },
5117 /* initialized by setup, see explanation at end of file (search for MODULE_PARM_DESC) */
5118 static unsigned int mem
= 0; /* "matrox:mem:xxxxxM" */
5119 static int option_precise_width
= 1; /* cannot be changed, option_precise_width==0 must imply noaccel */
5120 static int inv24
= 0; /* "matrox:inv24" */
5121 static int cross4MB
= -1; /* "matrox:cross4MB" */
5122 static int disabled
= 0; /* "matrox:disabled" */
5123 static int noaccel
= 0; /* "matrox:noaccel" */
5124 static int nopan
= 0; /* "matrox:nopan" */
5125 static int no_pci_retry
= 0; /* "matrox:nopciretry" */
5126 static int novga
= 0; /* "matrox:novga" */
5127 static int nobios
= 0; /* "matrox:nobios" */
5128 static int noinit
= 1; /* "matrox:init" */
5129 static int inverse
= 0; /* "matrox:inverse" */
5130 static int hwcursor
= 1; /* "matrox:nohwcursor" */
5131 static int blink
= 1; /* "matrox:noblink" */
5132 static int sgram
= 0; /* "matrox:sgram" */
5134 static int mtrr
= 1; /* "matrox:nomtrr" */
5136 static int grayscale
= 0; /* "matrox:grayscale" */
5137 static unsigned int fastfont
= 0; /* "matrox:fastfont:xxxxx" */
5138 static int dev
= -1; /* "matrox:dev:xxxxx" */
5139 static unsigned int vesa
= ~0; /* "matrox:vesa:xxxxx" */
5140 static int depth
= -1; /* "matrox:depth:xxxxx" */
5141 static unsigned int xres
= 0; /* "matrox:xres:xxxxx" */
5142 static unsigned int yres
= 0; /* "matrox:yres:xxxxx" */
5143 static unsigned int upper
= ~0; /* "matrox:upper:xxxxx" */
5144 static unsigned int lower
= ~0; /* "matrox:lower:xxxxx" */
5145 static unsigned int vslen
= 0; /* "matrox:vslen:xxxxx" */
5146 static unsigned int left
= ~0; /* "matrox:left:xxxxx" */
5147 static unsigned int right
= ~0; /* "matrox:right:xxxxx" */
5148 static unsigned int hslen
= 0; /* "matrox:hslen:xxxxx" */
5149 static unsigned int pixclock
= 0; /* "matrox:pixclock:xxxxx" */
5150 static int sync
= -1; /* "matrox:sync:xxxxx" */
5151 static unsigned int fv
= 0; /* "matrox:fv:xxxxx" */
5152 static unsigned int fh
= 0; /* "matrox:fh:xxxxxk" */
5153 static unsigned int maxclk
= 0; /* "matrox:maxclk:xxxxM" */
5154 static char fontname
[64]; /* "matrox:font:xxxxx" */
5157 static char videomode
[64]; /* "matrox:mode:xxxxx" or "matrox:xxxxx" */
5161 int __init
matroxfb_setup(char *options
) {
5164 DBG("matroxfb_setup")
5168 if (!options
|| !*options
)
5171 for(this_opt
=strtok(options
,","); this_opt
; this_opt
=strtok(NULL
,",")) {
5172 if (!*this_opt
) continue;
5174 dprintk("matroxfb_setup: option %s\n", this_opt
);
5176 if (!strncmp(this_opt
, "dev:", 4))
5177 dev
= simple_strtoul(this_opt
+4, NULL
, 0);
5178 else if (!strncmp(this_opt
, "depth:", 6)) {
5179 switch (simple_strtoul(this_opt
+6, NULL
, 0)) {
5180 case 0: depth
= RSText
; break;
5181 case 4: depth
= RS4bpp
; break;
5182 case 8: depth
= RS8bpp
; break;
5183 case 15:depth
= RS15bpp
; break;
5184 case 16:depth
= RS16bpp
; break;
5185 case 24:depth
= RS24bpp
; break;
5186 case 32:depth
= RS32bpp
; break;
5188 printk(KERN_ERR
"matroxfb: unsupported color depth\n");
5190 } else if (!strncmp(this_opt
, "xres:", 5))
5191 xres
= simple_strtoul(this_opt
+5, NULL
, 0);
5192 else if (!strncmp(this_opt
, "yres:", 5))
5193 yres
= simple_strtoul(this_opt
+5, NULL
, 0);
5194 else if (!strncmp(this_opt
, "vslen:", 6))
5195 vslen
= simple_strtoul(this_opt
+6, NULL
, 0);
5196 else if (!strncmp(this_opt
, "hslen:", 6))
5197 hslen
= simple_strtoul(this_opt
+6, NULL
, 0);
5198 else if (!strncmp(this_opt
, "left:", 5))
5199 left
= simple_strtoul(this_opt
+5, NULL
, 0);
5200 else if (!strncmp(this_opt
, "right:", 6))
5201 right
= simple_strtoul(this_opt
+6, NULL
, 0);
5202 else if (!strncmp(this_opt
, "upper:", 6))
5203 upper
= simple_strtoul(this_opt
+6, NULL
, 0);
5204 else if (!strncmp(this_opt
, "lower:", 6))
5205 lower
= simple_strtoul(this_opt
+6, NULL
, 0);
5206 else if (!strncmp(this_opt
, "pixclock:", 9))
5207 pixclock
= simple_strtoul(this_opt
+9, NULL
, 0);
5208 else if (!strncmp(this_opt
, "sync:", 5))
5209 sync
= simple_strtoul(this_opt
+5, NULL
, 0);
5210 else if (!strncmp(this_opt
, "vesa:", 5))
5211 vesa
= simple_strtoul(this_opt
+5, NULL
, 0);
5212 else if (!strncmp(this_opt
, "font:", 5))
5213 strncpy(fontname
, this_opt
+5, sizeof(fontname
)-1);
5214 else if (!strncmp(this_opt
, "maxclk:", 7))
5215 maxclk
= simple_strtoul(this_opt
+7, NULL
, 0);
5216 else if (!strncmp(this_opt
, "fh:", 3))
5217 fh
= simple_strtoul(this_opt
+3, NULL
, 0);
5218 else if (!strncmp(this_opt
, "fv:", 3))
5219 fv
= simple_strtoul(this_opt
+3, NULL
, 0);
5220 else if (!strncmp(this_opt
, "mem:", 4))
5221 mem
= simple_strtoul(this_opt
+4, NULL
, 0);
5222 else if (!strncmp(this_opt
, "mode:", 5))
5223 strncpy(videomode
, this_opt
+5, sizeof(videomode
)-1);
5225 else if (!strncmp(this_opt
, "vmode:", 6)) {
5226 unsigned int vmode
= simple_strtoul(this_opt
+6, NULL
, 0);
5227 if (vmode
> 0 && vmode
<= VMODE_MAX
)
5228 default_vmode
= vmode
;
5229 } else if (!strncmp(this_opt
, "cmode:", 6)) {
5230 unsigned int cmode
= simple_strtoul(this_opt
+6, NULL
, 0);
5234 default_cmode
= CMODE_8
;
5238 default_cmode
= CMODE_16
;
5242 default_cmode
= CMODE_32
;
5247 else if (!strncmp(this_opt
, "fastfont:", 9))
5248 fastfont
= simple_strtoul(this_opt
+9, NULL
, 0);
5249 else if (!strcmp(this_opt
, "nofastfont")) /* fastfont:N and nofastfont (nofastfont = fastfont:0) */
5251 else if (!strcmp(this_opt
, "disabled")) /* nodisabled does not exist */
5253 else if (!strcmp(this_opt
, "enabled")) /* noenabled does not exist */
5255 else if (!strcmp(this_opt
, "sgram")) /* nosgram == sdram */
5257 else if (!strcmp(this_opt
, "sdram"))
5262 if (!strncmp(this_opt
, "no", 2)) {
5266 if (! strcmp(this_opt
, "inverse"))
5268 else if (!strcmp(this_opt
, "accel"))
5270 else if (!strcmp(this_opt
, "pan"))
5272 else if (!strcmp(this_opt
, "pciretry"))
5273 no_pci_retry
= !value
;
5274 else if (!strcmp(this_opt
, "vga"))
5276 else if (!strcmp(this_opt
, "bios"))
5278 else if (!strcmp(this_opt
, "init"))
5281 else if (!strcmp(this_opt
, "mtrr"))
5284 else if (!strcmp(this_opt
, "inv24"))
5286 else if (!strcmp(this_opt
, "cross4MB"))
5288 else if (!strcmp(this_opt
, "hwcursor"))
5290 else if (!strcmp(this_opt
, "blink"))
5292 else if (!strcmp(this_opt
, "grayscale"))
5295 strncpy(videomode
, this_opt
, sizeof(videomode
)-1);
5301 #endif /* !MODULE */
5303 static int matroxfb_getmemory(WPMINFO
unsigned int maxSize
, unsigned int* realOffset
, unsigned int *realSize
){
5307 unsigned char store
;
5308 unsigned char bytes
[32];
5310 unsigned long cbase
;
5311 unsigned long mbase
;
5315 DBG("matroxfb_getmemory")
5317 vm
= ACCESS_FBINFO(video
.vbase
);
5318 maxSize
&= ~0x1FFFFF; /* must be X*2MB (really it must be 2 or X*4MB) */
5320 if (maxSize
< 0x0200000) return 0;
5321 if (maxSize
> 0x2000000) maxSize
= 0x2000000;
5323 mga_outb(M_EXTVGA_INDEX
, 0x03);
5324 mga_outb(M_EXTVGA_DATA
, mga_inb(M_EXTVGA_DATA
) | 0x80);
5326 store
= mga_readb(vm
, 0x1234);
5328 for (offs
= 0x100000; offs
< maxSize
; offs
+= 0x200000)
5329 *tmp
++ = mga_readb(vm
, offs
);
5330 for (offs
= 0x100000; offs
< maxSize
; offs
+= 0x200000)
5331 mga_writeb(vm
, offs
, 0x02);
5332 if (ACCESS_FBINFO(features
.accel
.has_cacheflush
))
5333 mga_outb(M_CACHEFLUSH
, 0x00);
5335 mga_writeb(vm
, 0x1234, 0x99);
5338 for (offs
= 0x100000; offs
< maxSize
; offs
+= 0x200000) {
5339 if (mga_readb(vm
, offs
) != 0x02)
5341 mga_writeb(vm
, offs
, mga_readb(vm
, offs
) - 0x02);
5342 if (mga_readb(vm
, offs
))
5344 if (offs
- 0x100000 == cbase
+ clen
) {
5347 cbase
= offs
- 0x100000;
5351 #ifndef MATROX_2MB_WITH_4MB_ADDON
5360 for (offs2
= 0x100000; offs2
< maxSize
; offs2
+= 0x200000)
5361 mga_writeb(vm
, offs2
, *tmp
++);
5362 mga_writeb(vm
, 0x1234, store
);
5364 mga_outb(M_EXTVGA_INDEX
, 0x03);
5365 mga_outb(M_EXTVGA_DATA
, mga_inb(M_EXTVGA_DATA
) & ~0x80);
5367 *realOffset
= mbase
;
5369 #ifdef CONFIG_FB_MATROX_MILLENIUM
5370 ACCESS_FBINFO(interleave
) = !(!isMillenium(MINFO
) || (mbase
& 0x3FFFFF) || (mlen
& 0x3FFFFF));
5375 #ifdef CONFIG_FB_MATROX_MILLENIUM
5376 static int __init
Ti3026_preinit(WPMINFO
struct matrox_hw_state
* hw
){
5377 static const int vxres_mill2
[] = { 512, 640, 768, 800, 832, 960,
5378 1024, 1152, 1280, 1600, 1664, 1920,
5380 static const int vxres_mill1
[] = { 640, 768, 800, 960,
5381 1024, 1152, 1280, 1600, 1920,
5384 DBG("Ti3026_preinit")
5386 ACCESS_FBINFO(millenium
) = 1;
5387 ACCESS_FBINFO(milleniumII
) = (ACCESS_FBINFO(pcidev
)->device
!= PCI_DEVICE_ID_MATROX_MIL
);
5388 ACCESS_FBINFO(capable
.cfb4
) = 1;
5389 ACCESS_FBINFO(capable
.text
) = 1; /* isMilleniumII(MINFO); */
5390 ACCESS_FBINFO(capable
.vxres
) = isMilleniumII(MINFO
)?vxres_mill2
:vxres_mill1
;
5391 ACCESS_FBINFO(cursor
.timer
.function
) = matroxfb_ti3026_flashcursor
;
5393 if (ACCESS_FBINFO(devflags
.noinit
))
5395 /* preserve VGA I/O, BIOS and PPC */
5396 hw
->MXoptionReg
&= 0xC0000100;
5397 hw
->MXoptionReg
|= 0x002C0000;
5398 if (ACCESS_FBINFO(devflags
.novga
))
5399 hw
->MXoptionReg
&= ~0x00000100;
5400 if (ACCESS_FBINFO(devflags
.nobios
))
5401 hw
->MXoptionReg
&= ~0x40000000;
5402 if (ACCESS_FBINFO(devflags
.nopciretry
))
5403 hw
->MXoptionReg
|= 0x20000000;
5404 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, hw
->MXoptionReg
);
5406 ACCESS_FBINFO(accel
.ramdac_rev
) = inTi3026(PMINFO TVP3026_XSILICONREV
);
5408 outTi3026(PMINFO TVP3026_XCLKCTRL
, TVP3026_XCLKCTRL_SRC_CLK0VGA
| TVP3026_XCLKCTRL_CLKSTOPPED
);
5409 outTi3026(PMINFO TVP3026_XTRUECOLORCTRL
, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR
);
5410 outTi3026(PMINFO TVP3026_XMUXCTRL
, TVP3026_XMUXCTRL_VGA
);
5412 outTi3026(PMINFO TVP3026_XPLLADDR
, 0x2A);
5413 outTi3026(PMINFO TVP3026_XLOOPPLLDATA
, 0x00);
5414 outTi3026(PMINFO TVP3026_XPIXPLLDATA
, 0x00);
5416 mga_outb(M_MISC_REG
, 0x67);
5418 outTi3026(PMINFO TVP3026_XMEMPLLCTRL
, TVP3026_XMEMPLLCTRL_STROBEMKC4
| TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL
);
5420 mga_outl(M_RESET
, 1);
5422 mga_outl(M_RESET
, 0);
5424 mga_outl(M_MACCESS
, 0x00008000);
5429 static void __init
Ti3026_reset(WPMINFO
struct matrox_hw_state
* hw
){
5433 matroxfb_fastfont_init(MINFO
);
5435 ti3026_ramdac_init(PMINFO hw
);
5439 #ifdef CONFIG_FB_MATROX_MILLENIUM
5440 static struct matrox_switch matrox_millenium
= {
5441 Ti3026_preinit
, Ti3026_reset
, Ti3026_init
, Ti3026_restore
5445 #ifdef CONFIG_FB_MATROX_MYSTIQUE
5446 static struct matrox_switch matrox_mystique
= {
5447 MGA1064_preinit
, MGA1064_reset
, MGA1064_init
, MGA1064_restore
5451 #ifdef CONFIG_FB_MATROX_G100
5452 static struct matrox_switch matrox_G100
= {
5453 MGAG100_preinit
, MGAG100_reset
, MGAG100_init
, MGAG100_restore
5457 struct video_board
{
5461 struct matrox_switch
* lowlevel
;
5463 #ifdef CONFIG_FB_MATROX_MILLENIUM
5464 static struct video_board vbMillenium __initdata
= {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA2064W
, &matrox_millenium
};
5465 static struct video_board vbMillenium2 __initdata
= {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W
, &matrox_millenium
};
5466 static struct video_board vbMillenium2A __initdata
= {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W_AGP
, &matrox_millenium
};
5467 #endif /* CONFIG_FB_MATROX_MILLENIUM */
5468 #ifdef CONFIG_FB_MATROX_MYSTIQUE
5469 static struct video_board vbMystique __initdata
= {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA1064SG
, &matrox_mystique
};
5470 #endif /* CONFIG_FB_MATROX_MYSTIQUE */
5471 #ifdef CONFIG_FB_MATROX_G100
5472 static struct video_board vbG100 __initdata
= {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGAG100
, &matrox_G100
};
5473 static struct video_board vbG200 __initdata
= {0x1000000, 0x1000000, FB_ACCEL_MATROX_MGAG200
, &matrox_G100
};
5474 #ifdef CONFIG_FB_MATROX_32MB
5475 /* from doc it looks like that accelerator can draw only to low 16MB :-( Direct accesses & displaying are OK for
5477 static struct video_board vbG400 __initdata
= {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400
, &matrox_G100
};
5479 static struct video_board vbG400 __initdata
= {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400
, &matrox_G100
};
5483 #define DEVF_VIDEO64BIT 0x01
5484 #define DEVF_SWAPS 0x02
5485 #define DEVF_MILLENIUM 0x04
5486 #define DEVF_MILLENIUM2 0x08
5487 #define DEVF_CROSS4MB 0x10
5488 #define DEVF_TEXT4B 0x20
5489 #define DEVF_DDC_8_2 0x40
5490 #define DEVF_DMA 0x80
5491 #define DEVF_SUPPORT32MB 0x100
5492 #define DEVF_ANY_VXRES 0x200
5494 #define DEVF_G100 (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB | DEVF_DDC_8_2) /* no doc, no vxres... */
5495 #define DEVF_G200 (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB | DEVF_DDC_8_2 | DEVF_ANY_VXRES)
5496 #define DEVF_G400 (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB | DEVF_DDC_8_2 | DEVF_ANY_VXRES | DEVF_SUPPORT32MB)
5498 static struct board
{
5499 unsigned short vendor
, device
, rev
, svid
, sid
;
5501 unsigned int maxclk
;
5502 struct video_board
* base
;
5504 } dev_list
[] __initdata
= {
5505 #ifdef CONFIG_FB_MATROX_MILLENIUM
5506 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_MIL
, 0xFF,
5508 DEVF_MILLENIUM
| DEVF_TEXT4B
,
5511 "Millennium (PCI)"},
5512 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_MIL_2
, 0xFF,
5514 DEVF_MILLENIUM
| DEVF_MILLENIUM2
| DEVF_SWAPS
,
5517 "Millennium II (PCI)"},
5518 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_MIL_2_AGP
, 0xFF,
5520 DEVF_MILLENIUM
| DEVF_MILLENIUM2
| DEVF_SWAPS
,
5523 "Millennium II (AGP)"},
5525 #ifdef CONFIG_FB_MATROX_MYSTIQUE
5526 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_MYS
, 0x02,
5532 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_MYS
, 0xFF,
5534 DEVF_VIDEO64BIT
| DEVF_SWAPS
,
5537 "Mystique 220 (PCI)"},
5539 #ifdef CONFIG_FB_MATROX_G100
5540 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G100
, 0xFF,
5541 PCI_SS_VENDOR_ID_MATROX
, PCI_SS_ID_MATROX_MGA_G100_PCI
,
5546 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G100
, 0xFF,
5551 "unknown G100 (PCI)"},
5552 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G100_AGP
, 0xFF,
5553 PCI_SS_VENDOR_ID_MATROX
, PCI_SS_ID_MATROX_GENERIC
,
5558 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G100_AGP
, 0xFF,
5559 PCI_SS_VENDOR_ID_MATROX
, PCI_SS_ID_MATROX_MGA_G100_AGP
,
5564 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G100_AGP
, 0xFF,
5565 PCI_SS_VENDOR_ID_SIEMENS_NIXDORF
, PCI_SS_ID_SIEMENS_MGA_G100_AGP
,
5570 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G100_AGP
, 0xFF,
5571 PCI_SS_VENDOR_ID_MATROX
, PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP
,
5575 "Productiva G100 (AGP)"},
5576 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G100_AGP
, 0xFF,
5581 "unknown G100 (AGP)"},
5582 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G200_PCI
, 0xFF,
5587 "unknown G200 (PCI)"},
5588 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G200_AGP
, 0xFF,
5589 PCI_SS_VENDOR_ID_MATROX
, PCI_SS_ID_MATROX_GENERIC
,
5594 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G200_AGP
, 0xFF,
5595 PCI_SS_VENDOR_ID_MATROX
, PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP
,
5599 "Mystique G200 (AGP)"},
5600 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G200_AGP
, 0xFF,
5601 PCI_SS_VENDOR_ID_MATROX
, PCI_SS_ID_MATROX_MILLENIUM_G200_AGP
,
5605 "Millennium G200 (AGP)"},
5606 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G200_AGP
, 0xFF,
5607 PCI_SS_VENDOR_ID_MATROX
, PCI_SS_ID_MATROX_MARVEL_G200_AGP
,
5611 "Marvel G200 (AGP)"},
5612 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G200_AGP
, 0xFF,
5613 PCI_SS_VENDOR_ID_SIEMENS_NIXDORF
, PCI_SS_ID_SIEMENS_MGA_G200_AGP
,
5618 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G200_AGP
, 0xFF,
5623 "unknown G200 (AGP)"},
5624 {PCI_VENDOR_ID_MATROX
, PCI_DEVICE_ID_MATROX_G400_AGP
, 0xFF,
5629 "unknown G400 (AGP)"},
5639 /* it cannot be static const struct due to __initdata
5641 static struct fb_videomode defaultmode __initdata
= {
5642 /* 640x480 @ 60Hz, 31.5 kHz */
5643 NULL
, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
5644 0, FB_VMODE_NONINTERLACED
5646 #endif /* !MODULE */
5648 static int __init
initMatrox2(WPMINFO
struct display
* d
, struct board
* b
){
5649 unsigned long ctrlptr_phys
= 0;
5650 unsigned long video_base_phys
= 0;
5651 unsigned int memsize
;
5652 struct matrox_hw_state
* hw
= ACCESS_FBINFO(currenthw
);
5656 /* set default values... */
5657 vesafb_defined
.accel_flags
= FB_ACCELF_TEXT
;
5659 ACCESS_FBINFO(hw_switch
) = b
->base
->lowlevel
;
5660 ACCESS_FBINFO(devflags
.accelerator
) = b
->base
->accelID
;
5661 ACCESS_FBINFO(max_pixel_clock
) = b
->maxclk
;
5663 printk(KERN_INFO
"matroxfb: Matrox %s detected\n", b
->name
);
5664 ACCESS_FBINFO(capable
.plnwt
) = 1;
5665 ACCESS_FBINFO(devflags
.video64bits
) = b
->flags
& DEVF_VIDEO64BIT
;
5666 if (b
->flags
& DEVF_TEXT4B
) {
5667 ACCESS_FBINFO(devflags
.vgastep
) = 4;
5668 ACCESS_FBINFO(devflags
.textmode
) = 4;
5669 ACCESS_FBINFO(devflags
.vgastepdisp
) = 16;
5670 ACCESS_FBINFO(devflags
.text_type_aux
) = FB_AUX_TEXT_MGA_STEP16
;
5672 ACCESS_FBINFO(devflags
.vgastep
) = 8;
5673 ACCESS_FBINFO(devflags
.textmode
) = 1;
5674 ACCESS_FBINFO(devflags
.vgastepdisp
) = 64;
5675 ACCESS_FBINFO(devflags
.text_type_aux
) = FB_AUX_TEXT_MGA_STEP8
;
5677 #ifdef CONFIG_FB_MATROX_32MB
5678 ACCESS_FBINFO(devflags
.support32MB
) = b
->flags
& DEVF_SUPPORT32MB
;
5680 ACCESS_FBINFO(devflags
.precise_width
) = !(b
->flags
& DEVF_ANY_VXRES
);
5681 ACCESS_FBINFO(devflags
.textstep
) = ACCESS_FBINFO(devflags
.vgastep
) * ACCESS_FBINFO(devflags
.textmode
);
5682 ACCESS_FBINFO(devflags
.textvram
) = 65536 / ACCESS_FBINFO(devflags
.textmode
);
5684 if (ACCESS_FBINFO(capable
.cross4MB
) < 0)
5685 ACCESS_FBINFO(capable
.cross4MB
) = b
->flags
& DEVF_CROSS4MB
;
5686 if (b
->flags
& DEVF_SWAPS
) {
5687 ctrlptr_phys
= ACCESS_FBINFO(pcidev
)->resource
[1].start
;
5688 video_base_phys
= ACCESS_FBINFO(pcidev
)->resource
[0].start
;
5690 ctrlptr_phys
= ACCESS_FBINFO(pcidev
)->resource
[0].start
;
5691 video_base_phys
= ACCESS_FBINFO(pcidev
)->resource
[1].start
;
5693 if (!ctrlptr_phys
) {
5694 printk(KERN_ERR
"matroxfb: control registers are not available, matroxfb disabled\n");
5697 if (!video_base_phys
) {
5698 printk(KERN_ERR
"matroxfb: video RAM is not available in PCI address space, matroxfb disabled\n");
5701 if (mga_ioremap(ctrlptr_phys
, 16384, MGA_IOREMAP_MMIO
, &ACCESS_FBINFO(mmio
.vbase
))) {
5702 printk(KERN_ERR
"matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys
);
5705 ACCESS_FBINFO(mmio
.base
) = ctrlptr_phys
;
5706 ACCESS_FBINFO(mmio
.len
) = 16384;
5707 memsize
= b
->base
->maxvram
;
5708 /* convert mem (autodetect k, M) */
5709 if (mem
< 1024) mem
*= 1024;
5710 if (mem
< 0x00100000) mem
*= 1024;
5712 if (mem
&& (mem
< memsize
))
5714 ACCESS_FBINFO(video
.base
) = video_base_phys
;
5715 if (mga_ioremap(video_base_phys
, memsize
, MGA_IOREMAP_FB
, &ACCESS_FBINFO(video
.vbase
))) {
5716 printk(KERN_ERR
"matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
5717 video_base_phys
, memsize
);
5718 mga_iounmap(ACCESS_FBINFO(mmio
.vbase
));
5723 u_int32_t mga_option
;
5725 /* Matrox MilleniumII is deactivated on bootup, but address
5726 regions are assigned to board. So we have to enable it */
5727 pci_read_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, &mga_option
);
5728 pci_read_config_dword(ACCESS_FBINFO(pcidev
), PCI_COMMAND
, &cmd
);
5729 mga_option
&= 0x7FFFFFFF; /* clear BIG_ENDIAN */
5730 if ((cmd
& PCI_COMMAND_MEMORY
) !=
5731 PCI_COMMAND_MEMORY
) {
5732 /* But if we have to enable it, we have probably to
5733 disable VGA I/O and BIOS... Sure? */
5734 dprintk(KERN_WARNING
"matroxfb: PCI BIOS did not enable device!\n");
5735 cmd
= (cmd
| PCI_COMMAND_MEMORY
) & ~PCI_COMMAND_VGA_PALETTE
;
5736 mga_option
&= 0xBFFFFEFF;
5737 /* we must not enable VGA, BIOS if PCI BIOS did not enable device itself */
5738 ACCESS_FBINFO(devflags
.novga
) = 1;
5739 ACCESS_FBINFO(devflags
.nobios
) = 1;
5740 /* we must initialize device if PCI BIOS did not enable it.
5741 It probably means that it is second head ... */
5742 ACCESS_FBINFO(devflags
.noinit
) = 0;
5744 mga_option
|= MX_OPTION_BSWAP
;
5745 if (pci_find_device(PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_82437
, NULL
)) {
5746 if (!(mga_option
& 0x20000000) && !ACCESS_FBINFO(devflags
.nopciretry
)) {
5747 printk(KERN_WARNING
"matroxfb: Disabling PCI retries due to i82437 present\n");
5749 mga_option
|= 0x20000000;
5750 ACCESS_FBINFO(devflags
.nopciretry
) = 1;
5752 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_COMMAND
, cmd
);
5753 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_OPTION_REG
, mga_option
);
5754 hw
->MXoptionReg
= mga_option
;
5756 /* select non-DMA memory for PCI_MGA_DATA, otherwise dump of PCI cfg space can lock PCI bus */
5757 /* maybe preinit() candidate, but it is same... for all devices... at this time... */
5758 pci_write_config_dword(ACCESS_FBINFO(pcidev
), PCI_MGA_INDEX
, 0x00003C00);
5761 if (ACCESS_FBINFO(hw_switch
)->preinit(PMINFO hw
)) {
5762 mga_iounmap(ACCESS_FBINFO(video
.vbase
));
5763 mga_iounmap(ACCESS_FBINFO(mmio
.vbase
));
5770 if (!matroxfb_getmemory(PMINFO memsize
, &offs
, &ACCESS_FBINFO(video
.len
)) || !ACCESS_FBINFO(video
.len
)) {
5771 printk(KERN_ERR
"matroxfb: cannot determine memory size\n");
5772 mga_iounmap(ACCESS_FBINFO(video
.vbase
));
5773 mga_iounmap(ACCESS_FBINFO(mmio
.vbase
));
5776 #ifdef MATROX_2MB_WITH_4MB_ADDON
5777 #ifdef FBCON_HAS_CFB24
5779 unsigned int end
= offs
+ ACCESS_FBINFO(video
.len
);
5782 offs
= ((offs
- 1) / (4096 * 3) + 1) * 4096 * 3;
5783 ACCESS_FBINFO(video
.len
) = end
- offs
;
5786 ACCESS_FBINFO(devflags
.ydstorg
) = offs
;
5787 video_base_phys
+= offs
;
5789 ACCESS_FBINFO(capable
.text
) = 0;
5791 ACCESS_FBINFO(devflags
.ydstorg
) = 0;
5794 ACCESS_FBINFO(currcon
) = -1;
5795 ACCESS_FBINFO(currcon_display
) = d
;
5796 mga_iounmap(ACCESS_FBINFO(video
.vbase
));
5797 ACCESS_FBINFO(video
.base
) = video_base_phys
;
5798 if (mga_ioremap(video_base_phys
, ACCESS_FBINFO(video
.len
), MGA_IOREMAP_FB
, &ACCESS_FBINFO(video
.vbase
))) {
5799 printk(KERN_ERR
"matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
5800 video_base_phys
, ACCESS_FBINFO(video
.len
));
5801 mga_iounmap(ACCESS_FBINFO(mmio
.vbase
));
5804 ACCESS_FBINFO(video
.len_usable
) = ACCESS_FBINFO(video
.len
);
5805 if (ACCESS_FBINFO(video
.len_usable
) > b
->base
->maxdisplayable
)
5806 ACCESS_FBINFO(video
.len_usable
) = b
->base
->maxdisplayable
;
5809 ACCESS_FBINFO(mtrr
.vram
) = mtrr_add(video_base_phys
, ACCESS_FBINFO(video
.len
), MTRR_TYPE_WRCOMB
, 1);
5810 ACCESS_FBINFO(mtrr
.vram_valid
) = 1;
5811 printk(KERN_INFO
"matroxfb: MTRR's turned on\n");
5813 #endif /* CONFIG_MTRR */
5815 if (!ACCESS_FBINFO(devflags
.novga
))
5816 request_region(0x3C0, 32, "matrox");
5817 ACCESS_FBINFO(hw_switch
->reset(PMINFO hw
));
5819 /* validate params, autodetect k, M */
5820 if (fh
< 1000) fh
*= 1000; /* 1kHz minimum */
5821 if (maxclk
< 1000) maxclk
*= 1000; /* kHz -> Hz, MHz -> kHz */
5822 if (maxclk
< 1000000) maxclk
*= 1000; /* kHz -> Hz, 1MHz minimum */
5824 vesa
&= 0x1DFF; /* mask out clearscreen, acceleration and so on */
5826 ACCESS_FBINFO(fbcon
.monspecs
.hfmin
) = 0;
5827 ACCESS_FBINFO(fbcon
.monspecs
.hfmax
) = fh
;
5828 ACCESS_FBINFO(fbcon
.monspecs
.vfmin
) = 0;
5829 ACCESS_FBINFO(fbcon
.monspecs
.vfmax
) = fv
;
5830 ACCESS_FBINFO(fbcon
.monspecs
.dpms
) = 0; /* TBD */
5832 /* static settings */
5833 for (RSptr
= vesamap
; RSptr
->vesa
; RSptr
++) {
5834 if (RSptr
->vesa
== vesa
) break;
5837 printk(KERN_ERR
"Invalid vesa mode 0x%04X\n", vesa
);
5841 int res
= RSResolution(RSptr
->info
)-1;
5843 left
= timmings
[res
].left
;
5845 xres
= timmings
[res
].xres
;
5847 right
= timmings
[res
].right
;
5849 hslen
= timmings
[res
].hslen
;
5851 upper
= timmings
[res
].upper
;
5853 yres
= timmings
[res
].yres
;
5855 lower
= timmings
[res
].lower
;
5857 vslen
= timmings
[res
].vslen
;
5858 if (!(fv
||fh
||maxclk
||pixclock
))
5859 fv
= timmings
[res
].vfreq
;
5861 depth
= RSDepth(RSptr
->info
);
5863 if ((depth
== RSText8
) && (!*ACCESS_FBINFO(fbcon
.fontname
))) {
5864 strcpy(ACCESS_FBINFO(fbcon
.fontname
), "VGA8x8");
5866 vesafb_defined
.red
= colors
[depth
-1].red
;
5867 vesafb_defined
.green
= colors
[depth
-1].green
;
5868 vesafb_defined
.blue
= colors
[depth
-1].blue
;
5869 vesafb_defined
.bits_per_pixel
= colors
[depth
-1].bits_per_pixel
;
5870 vesafb_defined
.grayscale
= grayscale
;
5871 vesafb_defined
.vmode
= 0;
5873 vesafb_defined
.accel_flags
&= ~FB_ACCELF_TEXT
;
5875 strcpy(ACCESS_FBINFO(fbcon
.modename
), "MATROX VGA");
5876 ACCESS_FBINFO(fbcon
.changevar
) = NULL
;
5877 ACCESS_FBINFO(fbcon
.node
) = -1;
5878 ACCESS_FBINFO(fbcon
.fbops
) = &matroxfb_ops
;
5879 ACCESS_FBINFO(fbcon
.disp
) = d
;
5880 ACCESS_FBINFO(fbcon
.switch_con
) = &matroxfb_switch
;
5881 ACCESS_FBINFO(fbcon
.updatevar
) = &matroxfb_updatevar
;
5882 ACCESS_FBINFO(fbcon
.blank
) = &matroxfb_blank
;
5883 ACCESS_FBINFO(fbcon
.flags
) = FBINFO_FLAG_DEFAULT
;
5884 ACCESS_FBINFO(video
.len_usable
) &= PAGE_MASK
;
5887 /* mode database is marked __init ... */
5889 fb_find_mode(&vesafb_defined
, &ACCESS_FBINFO(fbcon
), videomode
[0]?videomode
:NULL
,
5890 NULL
, 0, &defaultmode
, vesafb_defined
.bits_per_pixel
);
5892 #endif /* !MODULE */
5894 /* mode modifiers */
5896 vesafb_defined
.hsync_len
= hslen
;
5898 vesafb_defined
.vsync_len
= vslen
;
5900 vesafb_defined
.left_margin
= left
;
5902 vesafb_defined
.right_margin
= right
;
5904 vesafb_defined
.upper_margin
= upper
;
5906 vesafb_defined
.lower_margin
= lower
;
5908 vesafb_defined
.xres
= xres
;
5910 vesafb_defined
.yres
= yres
;
5912 vesafb_defined
.sync
= sync
;
5913 else if (vesafb_defined
.sync
== ~0) {
5914 vesafb_defined
.sync
= 0;
5916 vesafb_defined
.sync
|= FB_SYNC_HOR_HIGH_ACT
;
5917 else if (yres
< 480)
5918 vesafb_defined
.sync
|= FB_SYNC_VERT_HIGH_ACT
;
5921 /* fv, fh, maxclk limits was specified */
5926 tmp
= fv
* (vesafb_defined
.upper_margin
+ vesafb_defined
.yres
5927 + vesafb_defined
.lower_margin
+ vesafb_defined
.vsync_len
);
5928 if ((tmp
< fh
) || (fh
== 0)) fh
= tmp
;
5931 tmp
= fh
* (vesafb_defined
.left_margin
+ vesafb_defined
.xres
5932 + vesafb_defined
.right_margin
+ vesafb_defined
.hsync_len
);
5933 if ((tmp
< maxclk
) || (maxclk
== 0)) maxclk
= tmp
;
5935 maxclk
= (maxclk
+ 499) / 500;
5937 tmp
= (2000000000 + maxclk
) / maxclk
;
5938 if (tmp
> pixclock
) pixclock
= tmp
;
5942 if (pixclock
< 2000) /* > 500MHz */
5943 pixclock
= 4000; /* 250MHz */
5944 if (pixclock
> 1000000)
5945 pixclock
= 1000000; /* 1MHz */
5946 vesafb_defined
.pixclock
= pixclock
;
5949 /* FIXME: Where to move this?! */
5950 #if defined(CONFIG_FB_OF)
5951 #if defined(CONFIG_FB_COMPAT_XPMAC)
5952 strcpy(ACCESS_FBINFO(matrox_name
), "MTRX,"); /* OpenFirmware naming convension */
5953 strncat(ACCESS_FBINFO(matrox_name
), b
->name
, 26);
5954 if (!console_fb_info
)
5955 console_fb_info
= &ACCESS_FBINFO(fbcon
);
5957 if ((xres
<= 640) && (yres
<= 480)) {
5958 struct fb_var_screeninfo var
;
5959 if (default_vmode
== VMODE_NVRAM
) {
5960 default_vmode
= nvram_read_byte(NV_VMODE
);
5961 if (default_vmode
<= 0 || default_vmode
> VMODE_MAX
)
5962 default_vmode
= VMODE_CHOOSE
;
5964 if (default_vmode
<= 0 || default_vmode
> VMODE_MAX
)
5965 default_vmode
= VMODE_640_480_60
;
5966 if (default_cmode
== CMODE_NVRAM
)
5967 default_cmode
= nvram_read_byte(NV_CMODE
);
5968 if (default_cmode
< CMODE_8
|| default_cmode
> CMODE_32
)
5969 default_cmode
= CMODE_8
;
5970 if (!mac_vmode_to_var(default_vmode
, default_cmode
, &var
)) {
5971 var
.accel_flags
= vesafb_defined
.accel_flags
;
5972 var
.xoffset
= var
.yoffset
= 0;
5973 vesafb_defined
= var
; /* Note: mac_vmode_to_var() doesnot set all parameters */
5977 vesafb_defined
.xres_virtual
= vesafb_defined
.xres
;
5979 vesafb_defined
.yres_virtual
= vesafb_defined
.yres
;
5981 vesafb_defined
.yres_virtual
= 65536; /* large enough to be INF, but small enough
5982 to yres_virtual * xres_virtual < 2^32 */
5984 if (matroxfb_set_var(&vesafb_defined
, -2, &ACCESS_FBINFO(fbcon
))) {
5985 printk(KERN_ERR
"matroxfb: cannot set required parameters\n");
5989 printk(KERN_INFO
"matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n",
5990 vesafb_defined
.xres
, vesafb_defined
.yres
, vesafb_defined
.bits_per_pixel
,
5991 vesafb_defined
.xres_virtual
, vesafb_defined
.yres_virtual
);
5992 printk(KERN_INFO
"matroxfb: framebuffer at 0x%lX, mapped to 0x%p, size %d\n",
5993 ACCESS_FBINFO(video
.base
), vaddr_va(ACCESS_FBINFO(video
.vbase
)), ACCESS_FBINFO(video
.len
));
5995 /* We do not have to set currcon to 0... register_framebuffer do it for us on first console
5996 * and we do not want currcon == 0 for subsequent framebuffers */
5998 if (register_framebuffer(&ACCESS_FBINFO(fbcon
)) < 0) {
6001 printk("fb%d: %s frame buffer device\n",
6002 GET_FB_IDX(ACCESS_FBINFO(fbcon
.node
)), ACCESS_FBINFO(fbcon
.modename
));
6003 if (ACCESS_FBINFO(currcon
) < 0) {
6004 /* there is no console on this fb... but we have to initialize hardware
6005 * until someone tells me what is proper thing to do */
6006 printk(KERN_INFO
"fb%d: initializing hardware\n",
6007 GET_FB_IDX(ACCESS_FBINFO(fbcon
.node
)));
6008 matroxfb_set_var(&vesafb_defined
, -1, &ACCESS_FBINFO(fbcon
));
6013 static struct matrox_fb_info
* fb_list
= NULL
;
6015 static int __init
matrox_init(void){
6016 struct pci_dev
* pdev
= NULL
;
6022 while ((pdev
= pci_find(pdev
)) != NULL
) {
6028 pci_read_config_byte(pdev
, PCI_REVISION_ID
, &rev
);
6029 pci_read_config_word(pdev
, PCI_SUBSYSTEM_VENDOR_ID
, &svid
);
6030 pci_read_config_word(pdev
, PCI_SUBSYSTEM_ID
, &sid
);
6031 for (b
= dev_list
; b
->vendor
; b
++) {
6032 if ((b
->vendor
!= pdev
->vendor
) || (b
->device
!= pdev
->device
) || (b
->rev
< rev
)) continue;
6034 if ((b
->svid
!= svid
) || (b
->sid
!= sid
)) continue;
6036 struct matrox_fb_info
* minfo
;
6040 #ifdef CONFIG_FB_MATROX_MULTIHEAD
6041 minfo
= (struct matrox_fb_info
*)kmalloc(sizeof(*minfo
), GFP_KERNEL
);
6043 d
= (struct display
*)kmalloc(sizeof(*d
), GFP_KERNEL
);
6046 minfo
= &global_mxinfo
;
6049 memset(MINFO
, 0, sizeof(*MINFO
));
6050 memset(d
, 0, sizeof(*d
));
6052 ACCESS_FBINFO(currenthw
) = &ACCESS_FBINFO(hw1
);
6053 ACCESS_FBINFO(newhw
) = &ACCESS_FBINFO(hw2
);
6054 ACCESS_FBINFO(pcidev
) = pdev
;
6056 memcpy(ACCESS_FBINFO(fbcon
.fontname
), fontname
, sizeof(ACCESS_FBINFO(fbcon
.fontname
)));
6058 ACCESS_FBINFO(devflags
.inverse
) = inverse
;
6059 ACCESS_FBINFO(devflags
.novga
) = novga
;
6060 ACCESS_FBINFO(devflags
.nobios
) = nobios
;
6061 ACCESS_FBINFO(devflags
.noinit
) = noinit
;
6062 ACCESS_FBINFO(devflags
.nopciretry
) = no_pci_retry
;
6063 ACCESS_FBINFO(devflags
.mga_24bpp_fix
) = inv24
;
6064 ACCESS_FBINFO(devflags
.precise_width
) = option_precise_width
;
6065 ACCESS_FBINFO(devflags
.hwcursor
) = hwcursor
;
6066 ACCESS_FBINFO(devflags
.blink
) = blink
;
6067 ACCESS_FBINFO(devflags
.sgram
) = sgram
;
6068 ACCESS_FBINFO(capable
.cross4MB
) = cross4MB
;
6070 ACCESS_FBINFO(fastfont
.size
) = fastfont
;
6072 ACCESS_FBINFO(cursor
.state
) = CM_ERASE
;
6073 ACCESS_FBINFO(cursor
.timer
.prev
) = ACCESS_FBINFO(cursor
.timer
.next
) = NULL
;
6074 ACCESS_FBINFO(cursor
.timer
.data
) = (unsigned long)MINFO
;
6075 spin_lock_init(&ACCESS_FBINFO(lock
.DAC
));
6077 err
= initMatrox2(PMINFO d
, b
);
6079 ACCESS_FBINFO(next_fb
) = fb_list
;
6081 #ifdef CONFIG_FB_MATROX_MULTIHEAD
6087 #ifdef CONFIG_FB_MATROX_MULTIHEAD
6094 #ifdef CONFIG_FB_MATROX_MULTIHEAD
6097 if (dev
== 0) return 0;
6106 static int __init initialized
= 0;
6108 int __init
matroxfb_init(void)
6110 DBG("matroxfb_init")
6116 if (!fb_list
) return -ENXIO
;
6120 #if defined(CONFIG_FB_OF)
6121 int __init
matrox_of_init(struct device_node
*dp
){
6122 DBG("matrox_of_init");
6128 if (!fb_list
) return -ENXIO
;
6131 #endif /* CONFIG_FB_OF */
6135 MODULE_AUTHOR("(c) 1998,1999 Petr Vandrovec <vandrove@vc.cvut.cz>");
6136 MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400");
6137 MODULE_PARM(mem
, "i");
6138 MODULE_PARM_DESC(mem
, "Size of available memory in MB, KB or B (2,4,8,12,16MB, default=autodetect)");
6139 MODULE_PARM(disabled
, "i");
6140 MODULE_PARM_DESC(disabled
, "Disabled (0 or 1=disabled), meaningless for module (default=0)");
6141 MODULE_PARM(noaccel
, "i");
6142 MODULE_PARM_DESC(noaccel
, "Do not use accelerating engine (0 or 1=disabled) (default=0)");
6143 MODULE_PARM(nopan
, "i");
6144 MODULE_PARM_DESC(nopan
, "Disable pan on startup (0 or 1=disabled) (default=0)");
6145 MODULE_PARM(no_pci_retry
, "i");
6146 MODULE_PARM_DESC(no_pci_retry
, "PCI retries enabled (0 or 1=disabled) (default=0)");
6147 MODULE_PARM(novga
, "i");
6148 MODULE_PARM_DESC(novga
, "VGA I/O (0x3C0-0x3DF) disabled (0 or 1=disabled) (default=0)");
6149 MODULE_PARM(nobios
, "i");
6150 MODULE_PARM_DESC(nobios
, "Disables ROM BIOS (0 or 1=disabled) (default=do not change BIOS state)");
6151 MODULE_PARM(noinit
, "i");
6152 MODULE_PARM_DESC(noinit
, "Disables W/SG/SD-RAM and bus interface initialization (0 or 1=do not initialize) (default=0)");
6153 MODULE_PARM(mtrr
, "i");
6154 MODULE_PARM_DESC(mtrr
, "This speeds up video memory accesses (0=disabled or 1) (default=1)");
6155 MODULE_PARM(sgram
, "i");
6156 MODULE_PARM_DESC(sgram
, "Indicates that G200/G400 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)");
6157 MODULE_PARM(inv24
, "i");
6158 MODULE_PARM_DESC(inv24
, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
6159 MODULE_PARM(inverse
, "i");
6160 MODULE_PARM_DESC(inverse
, "Inverse (0 or 1) (default=0)");
6161 #ifdef CONFIG_FB_MATROX_MULTIHEAD
6162 MODULE_PARM(dev
, "i");
6163 MODULE_PARM_DESC(dev
, "Multihead support, attach to device ID (0..N) (default=all working)");
6165 MODULE_PARM(dev
, "i");
6166 MODULE_PARM_DESC(dev
, "Multihead support, attach to device ID (0..N) (default=first working)");
6168 MODULE_PARM(vesa
, "i");
6169 MODULE_PARM_DESC(vesa
, "Startup videomode (0x000-0x1FF) (default=0x101)");
6170 MODULE_PARM(xres
, "i");
6171 MODULE_PARM_DESC(xres
, "Horizontal resolutioni (px), overrides xres from vesa (default=vesa)");
6172 MODULE_PARM(yres
, "i");
6173 MODULE_PARM_DESC(yres
, "Vertical resolution (scans), overrides yres from vesa (default=vesa)");
6174 MODULE_PARM(upper
, "i");
6175 MODULE_PARM_DESC(upper
, "Upper blank space (scans), overrides upper from vesa (default=vesa)");
6176 MODULE_PARM(lower
, "i");
6177 MODULE_PARM_DESC(lower
, "Lower blank space (scans), overrides lower from vesa (default=vesa)");
6178 MODULE_PARM(vslen
, "i");
6179 MODULE_PARM_DESC(vslen
, "Vertical sync length (scans), overrides lower from vesa (default=vesa)");
6180 MODULE_PARM(left
, "i");
6181 MODULE_PARM_DESC(left
, "Left blank space (px), overrides left from vesa (default=vesa)");
6182 MODULE_PARM(right
, "i");
6183 MODULE_PARM_DESC(right
, "Right blank space (px), overrides right from vesa (default=vesa)");
6184 MODULE_PARM(hslen
, "i");
6185 MODULE_PARM_DESC(hslen
, "Horizontal sync length (px), overrides hslen from vesa (default=vesa)");
6186 MODULE_PARM(pixclock
, "i");
6187 MODULE_PARM_DESC(pixclock
, "Pixelclock (ns), overrides pixclock from vesa (default=vesa)");
6188 MODULE_PARM(sync
, "i");
6189 MODULE_PARM_DESC(sync
, "Sync polarity, overrides sync from vesa (default=vesa)");
6190 MODULE_PARM(depth
, "i");
6191 MODULE_PARM_DESC(depth
, "Color depth (0=text,8,15,16,24,32) (default=vesa)");
6192 MODULE_PARM(maxclk
, "i");
6193 MODULE_PARM_DESC(maxclk
, "Startup maximal clock, 0-999MHz, 1000-999999kHz, 1000000-INF Hz");
6194 MODULE_PARM(fh
, "i");
6195 MODULE_PARM_DESC(fh
, "Startup horizontal frequency, 0-999kHz, 1000-INF Hz");
6196 MODULE_PARM(fv
, "i");
6197 MODULE_PARM_DESC(fv
, "Startup vertical frequency, 0-INF Hz\n"
6198 "You should specify \"fv:max_monitor_vsync,fh:max_monitor_hsync,maxclk:max_monitor_dotclock\"\n");
6199 MODULE_PARM(hwcursor
, "i");
6200 MODULE_PARM_DESC(hwcursor
, "Enables hardware cursor (0 or 1) (default=0)");
6201 MODULE_PARM(blink
, "i");
6202 MODULE_PARM_DESC(blink
, "Enables hardware cursor blinking (0 or 1) (default=1)");
6203 MODULE_PARM(fastfont
, "i");
6204 MODULE_PARM_DESC(fastfont
, "Specifies, how much memory should be used for font data (0, 1024-65536 are reasonable) (default=0)");
6205 MODULE_PARM(grayscale
, "i");
6206 MODULE_PARM_DESC(grayscale
, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)");
6207 MODULE_PARM(cross4MB
, "i");
6208 MODULE_PARM_DESC(cross4MB
, "Specifies that 4MB boundary can be in middle of line. (default=autodetected)");
6210 MODULE_PARM(vmode
, "i");
6211 MODULE_PARM_DESC(vmode
, "Specify the vmode mode number that should be used (640x480 default)");
6212 MODULE_PARM(cmode
, "i");
6213 MODULE_PARM_DESC(cmode
, "Specify the video depth that should be used (8bit default)");
6216 int __init
init_module(void){
6227 else if (depth
== 4)
6229 else if (depth
== 8)
6231 else if (depth
== 15)
6233 else if (depth
== 16)
6235 else if (depth
== 24)
6237 else if (depth
== 32)
6239 else if (depth
!= -1) {
6240 printk(KERN_ERR
"matroxfb: depth %d is not supported, using default\n", depth
);
6244 if (!fb_list
) return -ENXIO
;
6248 void cleanup_module(void) {
6250 DBG("cleanup_module")
6258 struct matrox_fb_info
* minfo
;
6261 fb_list
= fb_list
->next_fb
;
6262 unregister_framebuffer(&ACCESS_FBINFO(fbcon
));
6263 del_timer(&ACCESS_FBINFO(cursor
.timer
));
6265 if (ACCESS_FBINFO(mtrr
.vram_valid
))
6266 mtrr_del(ACCESS_FBINFO(mtrr
.vram
), ACCESS_FBINFO(video
.base
), ACCESS_FBINFO(video
.len
));
6268 mga_iounmap(ACCESS_FBINFO(mmio
.vbase
));
6269 mga_iounmap(ACCESS_FBINFO(video
.vbase
));
6270 #ifdef CONFIG_FB_MATROX_MULTIHEAD
6271 kfree_s(ACCESS_FBINFO(fbcon
.disp
), sizeof(struct display
));
6272 kfree_s(minfo
, sizeof(struct matrox_fb_info
));
6278 * Overrides for Emacs so that we follow Linus's tabbing style.
6279 * ---------------------------------------------------------------------------