2 * SiS 300/630/540 frame buffer device For Kernal 2.4.x
4 * This driver is partly based on the VBE 2.0 compliant graphic
5 * boards framebuffer driver, which is
7 * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
13 #undef CONFIG_FB_SIS_LINUXBIOS
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/errno.h>
18 #include <linux/string.h>
20 #include <linux/tty.h>
21 #include <linux/malloc.h>
22 #include <linux/delay.h>
24 #include <linux/console.h>
25 #include <linux/selection.h>
26 #include <linux/ioport.h>
27 #include <linux/init.h>
28 #include <linux/pci.h>
29 #include <linux/vt_kern.h>
30 #include <linux/capability.h>
31 #include <linux/sisfb.h>
36 #include <video/fbcon.h>
37 #include <video/fbcon-cfb8.h>
38 #include <video/fbcon-cfb16.h>
39 #include <video/fbcon-cfb24.h>
40 #include <video/fbcon-cfb32.h>
42 /* ------------------- Constant Definitions ------------------------- */
48 #define FBIOGET_GLYPH 0x4620
49 #define FBIOGET_HWCINFO 0x4621
51 #define BR(x) (0x8200 | (x) << 2)
53 #define BITBLT 0x00000000
54 #define COLOREXP 0x00000001
55 #define ENCOLOREXP 0x00000002
56 #define MULTIPLE_SCANLINE 0x00000003
57 #define LINE 0x00000004
58 #define TRAPAZOID_FILL 0x00000005
59 #define TRANSPARENT_BITBLT 0x00000006
61 #define SRCVIDEO 0x00000000
62 #define SRCSYSTEM 0x00000010
63 #define SRCAGP 0x00000020
65 #define PATFG 0x00000000
66 #define PATPATREG 0x00000040
67 #define PATMONO 0x00000080
69 #define X_INC 0x00010000
70 #define X_DEC 0x00000000
71 #define Y_INC 0x00020000
72 #define Y_DEC 0x00000000
74 #define NOCLIP 0x00000000
75 #define NOMERGECLIP 0x04000000
76 #define CLIPENABLE 0x00040000
77 #define CLIPWITHOUTMERGE 0x04040000
79 #define OPAQUE 0x00000000
80 #define TRANSPARENT 0x00100000
82 #define DSTAGP 0x02000000
83 #define DSTVIDEO 0x02000000
85 #define LINE_STYLE 0x00800000
86 #define NO_RESET_COUNTER 0x00400000
87 #define NO_LAST_PIXEL 0x00200000
90 #define TURBO_QUEUE_CAP 0x80
91 #define HW_CURSOR_CAP 0x40
93 /* VGA register Offsets */
94 #define SEQ_ADR (0x14)
95 #define SEQ_DATA (0x15)
96 #define DAC_ADR (0x18)
97 #define DAC_DATA (0x19)
98 #define CRTC_ADR (0x24)
99 #define CRTC_DATA (0x25)
101 /* SiS indexed register indexes */
102 #define IND_SIS_PASSWORD (0x05)
103 #define IND_SIS_DRAM_SIZE (0x14)
104 #define IND_SIS_MODULE_ENABLE (0x1E)
105 #define IND_SIS_PCI_ADDRESS_SET (0x20)
106 #define IND_SIS_TURBOQUEUE_ADR (0x26)
107 #define IND_SIS_TURBOQUEUE_SET (0x27)
109 /* Sis register value */
110 #define SIS_PASSWORD (0x86)
112 #define SIS_2D_ENABLE (0x40)
114 #define SIS_MEM_MAP_IO_ENABLE (0x01)
115 #define SIS_PCI_ADDR_ENABLE (0x80)
117 #define MMIO_SIZE 0x20000 /* 128K MMIO capability */
118 #define MAX_ROM_SCAN 0x10000
120 #define RESERVED_MEM_SIZE_4M 0x400000 /* 4M */
121 #define RESERVED_MEM_SIZE_8M 0x800000 /* 8M */
124 #define DEFAULT_MODE 0
126 #define ModeInfoFlag 0x07
127 #define MemoryInfoFlag 0x1E0
128 #define MemorySizeShift 0x05
132 #define DoubleScanMode 0x8000
133 #define HalfDCLK 0x1000
135 #define InterlaceMode 0x80
136 #define LineCompareOff 0x400
137 #define DACInfoFlag 0x18
139 #define VCLKStartFreq 25
141 #define SIS_Glamour 0x0300
142 #define SIS_Trojan 0x6300
143 #define SIS_Spartan 0x5300
146 #define OH_ALLOC_SIZE 4000
147 #define SENTINEL 0x7fffffff
149 #define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */
150 #define HW_CURSOR_AREA_SIZE 0x1000 /* 4K */
152 /* video connection status */
153 #define VB_COMPOSITE 0x01
154 #define VB_SVIDEO 0x02
155 #define VB_SCART 0x04
161 /* ------------------- Global Variables ----------------------------- */
163 struct video_info ivideo
;
173 /* Supported SiS Chips list */
174 static struct board
{
178 {PCI_VENDOR_ID_SI
, PCI_DEVICE_ID_SI_300
, "SIS 300"},
179 {PCI_VENDOR_ID_SI
, PCI_DEVICE_ID_SI_540_VGA
, "SIS 540"},
180 {PCI_VENDOR_ID_SI
, PCI_DEVICE_ID_SI_630_VGA
, "SIS 630"},
184 /* card parameters */
185 unsigned long rom_base
;
186 unsigned long rom_vbase
;
189 static int video_type
= FB_TYPE_PACKED_PIXELS
;
190 static int video_linelength
;
191 static int video_cmap_len
;
192 static int sisfb_off
= 0;
194 static struct fb_var_screeninfo default_var
= {
204 FB_ACTIVATE_NOW
, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0,
206 FB_VMODE_NONINTERLACED
,
210 static struct display disp
;
211 static struct fb_info fb_info
;
214 u16 blue
, green
, red
, pad
;
218 #ifdef FBCON_HAS_CFB16
221 #ifdef FBCON_HAS_CFB24
224 #ifdef FBCON_HAS_CFB32
229 static int inverse
= 0;
230 static int currcon
= 0;
232 static struct display_switch sisfb_sw
;
238 u16 P3c4
, P3d4
, P3c0
, P3ce
, P3c2
, P3ca
, P3c6
, P3c7
, P3c8
, P3c9
, P3da
;
240 u16 flag_clearbuffer
;
242 int ModeIDOffset
, StandTable
, CRT1Table
, ScreenOffset
;
243 int REFIndex
, ModeType
;
251 static const struct _sisbios_mode
{
261 {"640x480x8", 0x2E, 640, 480, 8, 1, 80, 30},
262 {"640x480x16", 0x44, 640, 480, 16, 1, 80, 30},
263 {"640x480x32", 0x62, 640, 480, 32, 1, 80, 30},
264 {"800x600x8", 0x30, 800, 600, 8, 2, 100, 37},
265 {"800x600x16", 0x47, 800, 600, 16, 2, 100, 37},
266 {"800x600x32", 0x63, 800, 600, 32, 2, 100, 37},
267 {"1024x768x8", 0x38, 1024, 768, 8, 2, 128, 48},
268 {"1024x768x16", 0x4A, 1024, 768, 16, 2, 128, 48},
269 {"1024x768x32", 0x64, 1024, 768, 32, 2, 128, 48},
270 {"1280x1024x8", 0x3A, 1280, 1024, 8, 2, 160, 64},
271 {"1280x1024x16", 0x4D, 1280, 1024, 16, 2, 160, 64},
272 {"1280x1024x32", 0x65, 1280, 1024, 32, 2, 160, 64},
273 {"1600x1200x8", 0x3C, 1600, 1200, 8, 1, 200, 75},
274 {"1600x1200x16", 0x3D, 1600, 1200, 16, 1, 200, 75},
275 {"1600x1200x32", 0x66, 1600, 1200, 32, 1, 200, 75},
276 {"1920x1440x8", 0x68, 1920, 1440, 8, 1, 240, 75},
277 {"1920x1440x16", 0x69, 1920, 1440, 16, 1, 240, 75},
278 {"1920x1440x32", 0x6B, 1920, 1440, 32, 1, 240, 75},
279 {"\0", 0x00, 0, 0, 0, 0, 0, 0}
282 static struct _vrate
{
288 {1, 640, 480, 60}, {2, 640, 480, 72}, {3, 640, 480, 75}, {4, 640, 480, 85},
289 {5, 640, 480, 100}, {6, 640, 480, 120}, {7, 640, 480, 160}, {8, 640, 480, 200},
290 {1, 800, 600, 56}, {2, 800, 600, 60}, {3, 800, 600, 72}, {4, 800, 600, 75},
291 {5, 800, 600, 85}, {6, 800, 600, 100}, {7, 800, 600, 120}, {8, 800, 600, 160},
292 {1, 1024, 768, 43}, {2, 1024, 768, 60}, {3, 1024, 768, 70}, {4, 1024, 768, 75},
293 {5, 1024, 768, 85}, {6, 1024, 768, 100}, {7, 1024, 768, 120},
294 {1, 1280, 1024, 43}, {2, 1280, 1024, 60}, {3, 1280, 1024, 75}, {4, 1280, 1024, 85},
295 {1, 1600, 1200, 60}, {2, 1600, 1200, 65}, {3, 1600, 1200, 70}, {4, 1600, 1200, 75},
301 u16 DRAMType
[17][5] = {
302 {0x0C, 0x0A, 0x02, 0x40, 0x39}, {0x0D, 0x0A, 0x01, 0x40, 0x48},
303 {0x0C, 0x09, 0x02, 0x20, 0x35}, {0x0D, 0x09, 0x01, 0x20, 0x44},
304 {0x0C, 0x08, 0x02, 0x10, 0x31}, {0x0D, 0x08, 0x01, 0x10, 0x40},
305 {0x0C, 0x0A, 0x01, 0x20, 0x34}, {0x0C, 0x09, 0x01, 0x08, 0x32},
306 {0x0B, 0x08, 0x02, 0x08, 0x21}, {0x0C, 0x08, 0x01, 0x08, 0x30},
307 {0x0A, 0x08, 0x02, 0x04, 0x11}, {0x0B, 0x0A, 0x01, 0x10, 0x28},
308 {0x09, 0x08, 0x02, 0x02, 0x01}, {0x0B, 0x09, 0x01, 0x08, 0x24},
309 {0x0B, 0x08, 0x01, 0x04, 0x20}, {0x0A, 0x08, 0x01, 0x02, 0x10},
310 {0x09, 0x08, 0x01, 0x01, 0x00}
314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
316 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
317 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
320 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
321 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F
325 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
326 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
327 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
328 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
329 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
330 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
331 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
332 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F
336 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15,
337 0x20, 0x30, 0x24, 0x34, 0x21, 0x31, 0x25, 0x35,
338 0x08, 0x18, 0x0C, 0x1C, 0x09, 0x19, 0x0D, 0x1D,
339 0x28, 0x38, 0x2C, 0x3C, 0x29, 0x39, 0x2D, 0x3D,
340 0x02, 0x12, 0x06, 0x16, 0x03, 0x13, 0x07, 0x17,
341 0x22, 0x32, 0x26, 0x36, 0x23, 0x33, 0x27, 0x37,
342 0x0A, 0x1A, 0x0E, 0x1E, 0x0B, 0x1B, 0x0F, 0x1F,
343 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F
347 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
348 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
349 0x00, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18,
350 0x1C, 0x20, 0x24, 0x28, 0x2D, 0x32, 0x38, 0x3F,
351 0x00, 0x10, 0x1F, 0x2F, 0x3F, 0x1F, 0x27, 0x2F,
352 0x37, 0x3F, 0x2D, 0x31, 0x36, 0x3A, 0x3F, 0x00,
353 0x07, 0x0E, 0x15, 0x1C, 0x0E, 0x11, 0x15, 0x18,
354 0x1C, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x04,
355 0x08, 0x0C, 0x10, 0x08, 0x0A, 0x0C, 0x0E, 0x10,
356 0x0B, 0x0C, 0x0D, 0x0F, 0x10
359 #ifdef CONFIG_FB_SIS_LINUXBIOS
361 #define Monitor1Sense 0x20
363 unsigned char SRegsInit
[] = {
364 0x03, 0x00, 0x03, 0x00, 0x02, 0xa1, 0x00, 0x13,
365 0x2f, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0x00, 0x0f, 0x00, 0x00, 0x4f, 0x01, 0x00, 0x00,
367 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
368 0xa1, 0x76, 0xb2, 0xf6, 0x0d, 0x00, 0x00, 0x00,
369 0x37, 0x61, 0x80, 0x1b, 0xe1, 0x01, 0x55, 0x43,
370 0x80, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff,
371 0x8e, 0x40, 0x00, 0x00, 0x08, 0x00, 0xff, 0xff
374 unsigned char SRegs
[] = {
375 0x03, 0x01, 0x0F, 0x00, 0x0E, 0xA1, 0x02, 0x13,
376 0x3F, 0x86, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
377 0x0B, 0x0F, 0x00, 0x00, 0x4F, 0x01, 0x00, 0x00,
378 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x40, 0x00,
379 0xA1, 0xB6, 0xB2, 0xF6, 0x0D, 0x00, 0xF8, 0xF0,
380 0x37, 0x61, 0x80, 0x1B, 0xE1, 0x80, 0x55, 0x43,
381 0x80, 0x00, 0x11, 0xFF, 0x00, 0x00, 0x00, 0xFF,
382 0x8E, 0x40, 0x00, 0x00, 0x08, 0x00, 0xFF, 0xFF
385 unsigned char CRegs
[] = {
386 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0x0b, 0x3e,
387 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388 0xe9, 0x0b, 0xdf, 0x50, 0x40, 0xe7, 0x04, 0xa3,
389 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff
392 unsigned char GRegs
[] = {
393 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, 0x00
396 unsigned char ARegs
[] = {
397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
403 unsigned char MReg
= 0x6f;
413 unsigned long ulOffset
;
414 unsigned long ulSize
;
418 struct OHALLOC
*pohaNext
;
425 struct OH
*pohFreeList
;
426 struct OHALLOC
*pohaChain
;
428 unsigned long ulMaxFreeSize
;
432 unsigned long heap_start
;
433 unsigned long heap_end
;
434 unsigned long heap_size
;
436 unsigned int tqueue_pos
;
437 unsigned long hwcursor_vbase
;
439 /* Draw Function stuff */
442 /* -------------------- Macro definitions --------------------------- */
445 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
447 #define DPRINTK(fmt, args...)
450 #define vgawb(reg,data) \
451 (outb(data, ivideo.vga_base+reg))
452 #define vgaww(reg,data) \
453 (outw(data, ivideo.vga_base+reg))
454 #define vgawl(reg,data) \
455 (outl(data, ivideo.vga_base+reg))
457 (inb(ivideo.vga_base+reg))
459 /* ---------------------- Routine Prototype ------------------------- */
461 /* Interface used by the world */
462 int sisfb_setup(char *options
);
463 static int sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
464 struct fb_info
*info
);
465 static int sisfb_get_var(struct fb_var_screeninfo
*var
, int con
,
466 struct fb_info
*info
);
467 static int sisfb_set_var(struct fb_var_screeninfo
*var
, int con
,
468 struct fb_info
*info
);
469 static int sisfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
470 struct fb_info
*info
);
471 static int sisfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
472 struct fb_info
*info
);
473 static int sisfb_ioctl(struct inode
*inode
, struct file
*file
,
474 unsigned int cmd
, unsigned long arg
, int con
,
475 struct fb_info
*info
);
477 /* Interface to the low level console driver */
478 int sisfb_init(void);
479 static int sisfb_update_var(int con
, struct fb_info
*info
);
480 static int sisfb_switch(int con
, struct fb_info
*info
);
481 static void sisfb_blank(int blank
, struct fb_info
*info
);
483 /* Internal routines */
484 static void crtc_to_var(struct fb_var_screeninfo
*var
);
485 static void sisfb_set_disp(int con
, struct fb_var_screeninfo
*var
);
486 static int sis_getcolreg(unsigned regno
, unsigned *red
, unsigned *green
,
487 unsigned *blue
, unsigned *transp
,
488 struct fb_info
*fb_info
);
489 static int sis_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
490 unsigned blue
, unsigned transp
,
491 struct fb_info
*fb_info
);
492 static void do_install_cmap(int con
, struct fb_info
*info
);
493 static int do_set_var(struct fb_var_screeninfo
*var
, int isactive
,
494 struct fb_info
*info
);
496 /* set-mode routines */
497 static void set_reg1(u16 port
, u16 index
, u16 data
);
498 static void set_reg3(u16 port
, u16 data
);
499 static void set_reg4(u16 port
, unsigned long data
);
500 static u8
get_reg1(u16 port
, u16 index
);
501 static u8
get_reg2(u16 port
);
502 //#ifndef CONFIG_FB_SIS_LINUXBIOS
503 static u32
get_reg3(u16 port
);
504 static u16
get_modeID_length(unsigned long ROMAddr
, u16 ModeNo
);
505 static int search_modeID(unsigned long ROMAddr
, u16 ModeNo
);
506 static int check_memory_size(unsigned long ROMAddr
);
507 static void get_mode_ptr(unsigned long ROMAddr
, u16 ModeNo
);
508 static void set_seq_regs(unsigned long ROMAddr
);
509 static void set_misc_regs(unsigned long ROMAddr
);
510 static void set_crtc_regs(unsigned long ROMAddr
);
511 static void set_attregs(unsigned long ROMAddr
);
512 static void set_grc_regs(unsigned long ROMAddr
);
513 static void ClearExt1Regs(void);
514 static u16
GetRefindexLength(unsigned long ROMAddr
, u16 ModeNo
);
515 static int get_rate_ptr(unsigned long ROMAddr
, u16 ModeNo
);
516 static void set_sync(unsigned long ROMAddr
);
517 static void set_crt1_crtc(unsigned long ROMAddr
);
518 static void set_crt1_offset(unsigned long ROMAddr
);
519 static u16
get_vclk_len(unsigned long ROMAddr
);
520 static void set_crt1_vclk(unsigned long ROMAddr
);
521 static void set_vclk_state(unsigned long ROMAddr
, u16 ModeNo
);
522 static u16
calc_delay2(unsigned long ROMAddr
, u16 key
);
523 static u16
calc_delay(unsigned long ROMAddr
, u16 key
);
524 static void set_crt1_FIFO(unsigned long ROMAddr
);
525 static void set_crt1_FIFO2(unsigned long ROMAddr
);
526 static void set_crt1_mode_regs(unsigned long ROMAddr
, u16 ModeNo
);
527 static void set_interlace(unsigned long ROMAddr
, u16 ModeNo
);
529 static void write_DAC(u16 dl
, u16 ah
, u16 al
, u16 dh
);
530 static void load_DAC(unsigned long ROMAddr
);
531 static void display_on(void);
533 static int SiSSetMode(u16 ModeNo
);
534 static void pre_setmode(void);
535 static void post_setmode(void);
536 static void search_mode(const char *name
);
537 static u8
search_refresh_rate(unsigned int rate
);
540 static int sisfb_heap_init(void);
541 static struct OH
*poh_new_node(void);
542 static struct OH
*poh_allocate(unsigned long size
);
543 static struct OH
*poh_free(unsigned long base
);
544 static void delete_node(struct OH
*poh
);
545 static void insert_node(struct OH
*pohList
, struct OH
*poh
);
546 static void free_node(struct OH
*poh
);
548 /* ---------------------- Internal Routines ------------------------- */
550 inline static u32
RD32(unsigned char *base
, s32 off
)
552 return readl(base
+ off
);
555 inline static void WR32(unsigned char *base
, s32 off
, u32 v
)
557 writel(v
, base
+ off
);
560 inline static void WR16(unsigned char *base
, s32 off
, u16 v
)
562 writew(v
, base
+ off
);
565 inline static void WR8(unsigned char *base
, s32 off
, u8 v
)
567 writeb(v
, base
+ off
);
570 inline static u32
regrl(s32 off
)
572 return RD32(ivideo
.mmio_vbase
, off
);
575 inline static void regwl(s32 off
, u32 v
)
577 WR32(ivideo
.mmio_vbase
, off
, v
);
580 inline static void regww(s32 off
, u16 v
)
582 WR16(ivideo
.mmio_vbase
, off
, v
);
585 inline static void regwb(s32 off
, u8 v
)
587 WR8(ivideo
.mmio_vbase
, off
, v
);
591 * Get CRTC registers to set var
593 static void crtc_to_var(struct fb_var_screeninfo
*var
)
595 u16 VRE
, VBE
, VRS
, VBS
, VDE
, VT
;
596 u16 HRE
, HBE
, HRS
, HBS
, HDE
, HT
;
597 u8 uSRdata
, uCRdata
, uCRdata2
, uCRdata3
, uMRdata
;
598 int A
, B
, C
, D
, E
, F
, temp
;
602 uSRdata
= vgarb(SEQ_DATA
);
605 var
->vmode
= FB_VMODE_INTERLACED
;
607 var
->vmode
= FB_VMODE_NONINTERLACED
;
609 switch ((uSRdata
& 0x1c) >> 2) {
611 var
->bits_per_pixel
= 8;
614 var
->bits_per_pixel
= 16;
617 var
->bits_per_pixel
= 32;
621 switch (var
->bits_per_pixel
) {
624 var
->green
.length
= 6;
625 var
->blue
.length
= 6;
626 video_cmap_len
= 256;
628 case 16: /* RGB 565 */
629 var
->red
.offset
= 11;
631 var
->green
.offset
= 5;
632 var
->green
.length
= 6;
633 var
->blue
.offset
= 0;
634 var
->blue
.length
= 5;
635 var
->transp
.offset
= 0;
636 var
->transp
.length
= 0;
640 case 24: /* RGB 888 */
641 var
->red
.offset
= 16;
643 var
->green
.offset
= 8;
644 var
->green
.length
= 8;
645 var
->blue
.offset
= 0;
646 var
->blue
.length
= 8;
647 var
->transp
.offset
= 0;
648 var
->transp
.length
= 0;
652 var
->red
.offset
= 16;
654 var
->green
.offset
= 8;
655 var
->green
.length
= 8;
656 var
->blue
.offset
= 0;
657 var
->blue
.length
= 8;
658 var
->transp
.offset
= 24;
659 var
->transp
.length
= 8;
665 uSRdata
= vgarb(SEQ_DATA
);
667 vgawb(CRTC_ADR
, 0x6);
668 uCRdata
= vgarb(CRTC_DATA
);
669 vgawb(CRTC_ADR
, 0x7);
670 uCRdata2
= vgarb(CRTC_DATA
);
672 (uCRdata
& 0xff) | ((u16
) (uCRdata2
& 0x01) << 8) |
673 ((u16
) (uCRdata2
& 0x20) << 4) | ((u16
) (uSRdata
& 0x01) <<
677 vgawb(CRTC_ADR
, 0x12);
678 uCRdata
= vgarb(CRTC_DATA
);
680 (uCRdata
& 0xff) | ((u16
) (uCRdata2
& 0x02) << 7) |
681 ((u16
) (uCRdata2
& 0x40) << 3) | ((u16
) (uSRdata
& 0x02) << 9);
684 vgawb(CRTC_ADR
, 0x10);
685 uCRdata
= vgarb(CRTC_DATA
);
687 (uCRdata
& 0xff) | ((u16
) (uCRdata2
& 0x04) << 6) |
688 ((u16
) (uCRdata2
& 0x80) << 2) | ((u16
) (uSRdata
& 0x08) << 7);
691 vgawb(CRTC_ADR
, 0x15);
692 uCRdata
= vgarb(CRTC_DATA
);
693 vgawb(CRTC_ADR
, 0x9);
694 uCRdata3
= vgarb(CRTC_DATA
);
696 (uCRdata
& 0xff) | ((u16
) (uCRdata2
& 0x08) << 5) |
697 ((u16
) (uCRdata3
& 0x20) << 4) | ((u16
) (uSRdata
& 0x04) << 8);
699 vgawb(CRTC_ADR
, 0x16);
700 uCRdata
= vgarb(CRTC_DATA
);
701 VBE
= (uCRdata
& 0xff) | ((u16
) (uSRdata
& 0x10) << 4);
702 temp
= VBE
- ((E
- 1) & 511);
703 B
= (temp
> 0) ? temp
: (temp
+ 512);
705 vgawb(CRTC_ADR
, 0x11);
706 uCRdata
= vgarb(CRTC_DATA
);
707 VRE
= (uCRdata
& 0x0f) | ((uSRdata
& 0x20) >> 1);
708 temp
= VRE
- ((E
+ F
- 1) & 31);
709 C
= (temp
> 0) ? temp
: (temp
+ 32);
713 var
->yres
= var
->yres_virtual
= E
;
714 var
->upper_margin
= D
;
715 var
->lower_margin
= F
;
719 uSRdata
= vgarb(SEQ_DATA
);
721 vgawb(CRTC_ADR
, 0x0);
722 uCRdata
= vgarb(CRTC_DATA
);
723 HT
= (uCRdata
& 0xff) | ((u16
) (uSRdata
& 0x03) << 8);
726 vgawb(CRTC_ADR
, 0x1);
727 uCRdata
= vgarb(CRTC_DATA
);
728 HDE
= (uCRdata
& 0xff) | ((u16
) (uSRdata
& 0x0C) << 6);
731 vgawb(CRTC_ADR
, 0x4);
732 uCRdata
= vgarb(CRTC_DATA
);
733 HRS
= (uCRdata
& 0xff) | ((u16
) (uSRdata
& 0xC0) << 2);
736 vgawb(CRTC_ADR
, 0x2);
737 uCRdata
= vgarb(CRTC_DATA
);
738 HBS
= (uCRdata
& 0xff) | ((u16
) (uSRdata
& 0x30) << 4);
741 uSRdata
= vgarb(SEQ_DATA
);
742 vgawb(CRTC_ADR
, 0x3);
743 uCRdata
= vgarb(CRTC_DATA
);
744 vgawb(CRTC_ADR
, 0x5);
745 uCRdata2
= vgarb(CRTC_DATA
);
747 (uCRdata
& 0x1f) | ((u16
) (uCRdata2
& 0x80) >> 2) |
748 ((u16
) (uSRdata
& 0x03) << 6);
749 HRE
= (uCRdata2
& 0x1f) | ((uSRdata
& 0x04) << 3);
751 temp
= HBE
- ((E
- 1) & 255);
752 B
= (temp
> 0) ? temp
: (temp
+ 256);
754 temp
= HRE
- ((E
+ F
+ 3) & 63);
755 C
= (temp
> 0) ? temp
: (temp
+ 64);
759 var
->xres
= var
->xres_virtual
= E
* 8;
760 var
->left_margin
= D
* 8;
761 var
->right_margin
= F
* 8;
762 var
->hsync_len
= C
* 8;
764 var
->activate
= FB_ACTIVATE_NOW
;
768 uMRdata
= vgarb(0x1C);
770 var
->sync
&= ~FB_SYNC_VERT_HIGH_ACT
;
772 var
->sync
|= FB_SYNC_VERT_HIGH_ACT
;
775 var
->sync
&= ~FB_SYNC_HOR_HIGH_ACT
;
777 var
->sync
|= FB_SYNC_HOR_HIGH_ACT
;
783 hrate
= (double) ivideo
.refresh_rate
* (double) VT
/ 2;
785 var
->pixclock
= (u32
) (1E12
/ drate
);
788 static void sisfb_set_disp(int con
, struct fb_var_screeninfo
*var
)
790 struct fb_fix_screeninfo fix
;
791 struct display
*display
;
792 struct display_switch
*sw
;
796 display
= &fb_display
[con
];
798 display
= &disp
; /* used during initialization */
800 sisfb_get_fix(&fix
, con
, 0);
802 display
->screen_base
= ivideo
.video_vbase
;
803 display
->visual
= fix
.visual
;
804 display
->type
= fix
.type
;
805 display
->type_aux
= fix
.type_aux
;
806 display
->ypanstep
= fix
.ypanstep
;
807 display
->ywrapstep
= fix
.ywrapstep
;
808 display
->line_length
= fix
.line_length
;
809 display
->next_line
= fix
.line_length
;
810 /*display->can_soft_blank = 1; */
811 display
->can_soft_blank
= 0;
812 display
->inverse
= inverse
;
816 switch (ivideo
.video_bpp
) {
817 #ifdef FBCON_HAS_CFB8
823 #ifdef FBCON_HAS_CFB16
827 display
->dispsw_data
= fbcon_cmap
.cfb16
;
831 #ifdef FBCON_HAS_CFB24
834 display
->dispsw_data
= fbcon_cmap
.cfb24
;
838 #ifdef FBCON_HAS_CFB32
841 display
->dispsw_data
= fbcon_cmap
.cfb32
;
849 memcpy(&sisfb_sw
, sw
, sizeof(*sw
));
850 display
->dispsw
= &sisfb_sw
;
851 restore_flags(flags
);
853 display
->scrollmode
= SCROLL_YREDRAW
;
854 sisfb_sw
.bmove
= fbcon_redraw_bmove
;
858 * Read a single color register and split it into colors/transparent.
859 * Return != 0 for invalid regno.
862 static int sis_getcolreg(unsigned regno
, unsigned *red
, unsigned *green
, unsigned *blue
,
863 unsigned *transp
, struct fb_info
*fb_info
)
865 if (regno
>= video_cmap_len
)
868 *red
= palette
[regno
].red
;
869 *green
= palette
[regno
].green
;
870 *blue
= palette
[regno
].blue
;
876 * Set a single color register. The values supplied are already
877 * rounded down to the hardware's capabilities (according to the
878 * entries in the var structure). Return != 0 for invalid regno.
881 static int sis_setcolreg(unsigned regno
, unsigned red
, unsigned green
, unsigned blue
,
882 unsigned transp
, struct fb_info
*fb_info
)
885 if (regno
>= video_cmap_len
)
888 palette
[regno
].red
= red
;
889 palette
[regno
].green
= green
;
890 palette
[regno
].blue
= blue
;
892 switch (ivideo
.video_bpp
) {
893 #ifdef FBCON_HAS_CFB8
895 vgawb(DAC_ADR
, regno
);
896 vgawb(DAC_DATA
, red
>> 10);
897 vgawb(DAC_DATA
, green
>> 10);
898 vgawb(DAC_DATA
, blue
>> 10);
901 #ifdef FBCON_HAS_CFB16
904 fbcon_cmap
.cfb16
[regno
] =
906 ((green
& 0xfc00) >> 5) | ((blue
& 0xf800) >> 11);
909 #ifdef FBCON_HAS_CFB24
914 fbcon_cmap
.cfb24
[regno
] =
915 (red
<< 16) | (green
<< 8) | (blue
);
918 #ifdef FBCON_HAS_CFB32
923 fbcon_cmap
.cfb32
[regno
] =
924 (red
<< 16) | (green
<< 8) | (blue
);
931 static void do_install_cmap(int con
, struct fb_info
*info
)
936 if (fb_display
[con
].cmap
.len
)
937 fb_set_cmap(&fb_display
[con
].cmap
, 1, sis_setcolreg
, info
);
939 fb_set_cmap(fb_default_cmap(video_cmap_len
), 1,
940 sis_setcolreg
, info
);
943 static int do_set_var(struct fb_var_screeninfo
*var
, int isactive
,
944 struct fb_info
*info
)
946 unsigned int htotal
=
947 var
->left_margin
+ var
->xres
+ var
->right_margin
+
949 unsigned int vtotal
=
950 var
->upper_margin
+ var
->yres
+ var
->lower_margin
+
952 double drate
= 0, hrate
= 0;
955 if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_NONINTERLACED
)
957 else if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
)
959 else if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
)
963 if (!htotal
|| !vtotal
) {
964 DPRINTK("Invalid 'var' Information!\n");
968 drate
= 1E12
/ var
->pixclock
;
969 hrate
= drate
/ htotal
;
970 ivideo
.refresh_rate
= (unsigned int) (hrate
/ vtotal
* 2 + 0.5);
973 while ((sisbios_mode
[mode_idx
].mode_no
!= 0)
974 && (sisbios_mode
[mode_idx
].xres
<= var
->xres
)) {
975 if ((sisbios_mode
[mode_idx
].xres
== var
->xres
)
976 && (sisbios_mode
[mode_idx
].yres
== var
->yres
)
977 && (sisbios_mode
[mode_idx
].bpp
== var
->bits_per_pixel
)) {
978 mode_no
= sisbios_mode
[mode_idx
].mode_no
;
986 printk("sisfb does not support mode %dx%d-%d\n", var
->xres
,
987 var
->yres
, var
->bits_per_pixel
);
991 if (search_refresh_rate(ivideo
.refresh_rate
) == 0) {
992 /* not supported rate */
993 rate_idx
= sisbios_mode
[mode_idx
].rate_idx
;
994 ivideo
.refresh_rate
= 60;
997 if (((var
->activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_NOW
) && isactive
) {
1000 if (SiSSetMode(mode_no
)) {
1001 DPRINTK("sisfb: set mode[0x%x]: failed\n",
1008 ivideo
.video_bpp
= sisbios_mode
[mode_idx
].bpp
;
1009 ivideo
.video_width
= sisbios_mode
[mode_idx
].xres
;
1010 ivideo
.video_height
= sisbios_mode
[mode_idx
].yres
;
1012 ivideo
.video_width
* (ivideo
.video_bpp
>> 3);
1014 DPRINTK("Current Mode: %dx%d-%d line_length=%d\n",
1015 ivideo
.video_width
, ivideo
.video_height
,
1016 ivideo
.video_bpp
, video_linelength
);
1022 /* ---------------------- Draw Funtions ----------------------------- */
1024 static void sis_get_glyph(struct GlyInfo
*gly
)
1026 struct display
*p
= &fb_display
[currcon
];
1030 u8
*gbuf
= gly
->gmask
;
1034 gly
->fontheight
= fontheight(p
);
1035 gly
->fontwidth
= fontwidth(p
);
1036 widthb
= (fontwidth(p
) + 7) / 8;
1038 c
= gly
->ch
& p
->charmask
;
1039 if (fontwidth(p
) <= 8)
1040 cdat
= p
->fontdata
+ c
* fontheight(p
);
1042 cdat
= p
->fontdata
+ (c
* fontheight(p
) << 1);
1044 size
= fontheight(p
) * widthb
;
1045 memcpy(gbuf
, cdat
, size
);
1050 /* ---------------------- HEAP Routines ----------------------------- */
1053 * Heap Initialization
1056 static int sisfb_heap_init(void)
1061 if (ivideo
.video_size
> 0x800000)
1062 /* video ram is large than 8M */
1063 heap_start
= (unsigned long) ivideo
.video_vbase
+ RESERVED_MEM_SIZE_8M
;
1065 heap_start
= (unsigned long) ivideo
.video_vbase
+ RESERVED_MEM_SIZE_4M
;
1067 heap_end
= (unsigned long) ivideo
.video_vbase
+ ivideo
.video_size
;
1068 heap_size
= heap_end
- heap_start
;
1071 /* Setting for Turbo Queue */
1072 if (heap_size
>= TURBO_QUEUE_AREA_SIZE
) {
1074 (ivideo
.video_size
-
1075 TURBO_QUEUE_AREA_SIZE
) / (64 * 1024);
1076 jTemp
= (u8
) (tqueue_pos
& 0xff);
1077 vgawb(SEQ_ADR
, IND_SIS_TURBOQUEUE_SET
);
1078 tq_state
= vgarb(SEQ_DATA
);
1081 tq_state
|= (u8
) (tqueue_pos
>> 8);
1082 vgawb(SEQ_DATA
, tq_state
);
1083 vgawb(SEQ_ADR
, IND_SIS_TURBOQUEUE_ADR
);
1084 vgawb(SEQ_DATA
, jTemp
);
1086 caps
|= TURBO_QUEUE_CAP
;
1088 heap_end
-= TURBO_QUEUE_AREA_SIZE
;
1089 heap_size
-= TURBO_QUEUE_AREA_SIZE
;
1092 /* Setting for HW cursor(4K) */
1093 if (heap_size
>= HW_CURSOR_AREA_SIZE
) {
1094 heap_end
-= HW_CURSOR_AREA_SIZE
;
1095 heap_size
-= HW_CURSOR_AREA_SIZE
;
1096 hwcursor_vbase
= heap_end
;
1098 caps
|= HW_CURSOR_CAP
;
1101 heap
.pohaChain
= NULL
;
1102 heap
.pohFreeList
= NULL
;
1104 poh
= poh_new_node();
1109 /* The first node describles the entire heap size */
1110 poh
->pohNext
= &heap
.ohFree
;
1111 poh
->pohPrev
= &heap
.ohFree
;
1112 poh
->ulSize
= heap_end
- heap_start
+ 1;
1113 poh
->ulOffset
= heap_start
- (unsigned long) ivideo
.video_vbase
;
1115 DPRINTK("sisfb:Heap start:0x%p, end:0x%p, len=%dk\n",
1116 (char *) heap_start
, (char *) heap_end
,
1117 (unsigned int) poh
->ulSize
/ 1024);
1119 DPRINTK("sisfb:First Node offset:0x%x, size:%dk\n",
1120 (unsigned int) poh
->ulOffset
, (unsigned int) poh
->ulSize
/ 1024);
1122 /* The second node in our free list sentinel */
1123 heap
.ohFree
.pohNext
= poh
;
1124 heap
.ohFree
.pohPrev
= poh
;
1125 heap
.ohFree
.ulSize
= 0;
1126 heap
.ulMaxFreeSize
= poh
->ulSize
;
1128 /* Initialize the discardable list */
1129 heap
.ohUsed
.pohNext
= &heap
.ohUsed
;
1130 heap
.ohUsed
.pohPrev
= &heap
.ohUsed
;
1131 heap
.ohUsed
.ulSize
= SENTINEL
;
1137 * Allocates a basic memory unit in which we'll pack our data structures.
1140 static struct OH
*poh_new_node(void)
1144 struct OHALLOC
*poha
;
1147 if (heap
.pohFreeList
== NULL
) {
1148 poha
= kmalloc(OH_ALLOC_SIZE
, GFP_KERNEL
);
1150 poha
->pohaNext
= heap
.pohaChain
;
1151 heap
.pohaChain
= poha
;
1155 sizeof(struct OHALLOC
)) / sizeof(struct OH
) + 1;
1157 poh
= &poha
->aoh
[0];
1158 for (i
= cOhs
- 1; i
!= 0; i
--) {
1159 poh
->pohNext
= poh
+ 1;
1163 poh
->pohNext
= NULL
;
1164 heap
.pohFreeList
= &poha
->aoh
[0];
1167 poh
= heap
.pohFreeList
;
1168 heap
.pohFreeList
= poh
->pohNext
;
1174 * Allocates space, return NULL when failed
1177 static struct OH
*poh_allocate(unsigned long size
)
1183 if (size
> heap
.ulMaxFreeSize
) {
1184 DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
1185 (unsigned int) size
/ 1024);
1189 pohThis
= heap
.ohFree
.pohNext
;
1191 while (pohThis
!= &heap
.ohFree
) {
1192 if (size
<= pohThis
->ulSize
) {
1196 pohThis
= pohThis
->pohNext
;
1200 DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
1201 (unsigned int) size
/ 1024);
1205 if (size
== pohThis
->ulSize
) {
1207 delete_node(pohThis
);
1209 pohRoot
= poh_new_node();
1211 if (pohRoot
== NULL
) {
1215 pohRoot
->ulOffset
= pohThis
->ulOffset
;
1216 pohRoot
->ulSize
= size
;
1218 pohThis
->ulOffset
+= size
;
1219 pohThis
->ulSize
-= size
;
1222 heap
.ulMaxFreeSize
-= size
;
1224 pohThis
= &heap
.ohUsed
;
1225 insert_node(pohThis
, pohRoot
);
1231 * To remove a node from a list.
1234 static void delete_node(struct OH
*poh
)
1240 pohPrev
= poh
->pohPrev
;
1241 pohNext
= poh
->pohNext
;
1243 pohPrev
->pohNext
= pohNext
;
1244 pohNext
->pohPrev
= pohPrev
;
1250 * To insert a node into a list.
1253 static void insert_node(struct OH
*pohList
, struct OH
*poh
)
1257 pohTemp
= pohList
->pohNext
;
1259 pohList
->pohNext
= poh
;
1260 pohTemp
->pohPrev
= poh
;
1262 poh
->pohPrev
= pohList
;
1263 poh
->pohNext
= pohTemp
;
1267 * Frees an off-screen heap allocation.
1270 static struct OH
*poh_free(unsigned long base
)
1274 struct OH
*pohFreed
;
1277 unsigned long ulUpper
;
1278 unsigned long ulLower
;
1281 pohFreed
= heap
.ohUsed
.pohNext
;
1283 while (pohFreed
!= &heap
.ohUsed
) {
1284 if (pohFreed
->ulOffset
== base
) {
1289 pohFreed
= pohFreed
->pohNext
;
1295 heap
.ulMaxFreeSize
+= pohFreed
->ulSize
;
1297 pohPrev
= pohNext
= NULL
;
1298 ulUpper
= pohFreed
->ulOffset
+ pohFreed
->ulSize
;
1299 ulLower
= pohFreed
->ulOffset
;
1301 pohThis
= heap
.ohFree
.pohNext
;
1303 while (pohThis
!= &heap
.ohFree
) {
1304 if (pohThis
->ulOffset
== ulUpper
) {
1307 else if ((pohThis
->ulOffset
+ pohThis
->ulSize
) ==
1311 pohThis
= pohThis
->pohNext
;
1314 delete_node(pohFreed
);
1316 if (pohPrev
&& pohNext
) {
1317 pohPrev
->ulSize
+= (pohFreed
->ulSize
+ pohNext
->ulSize
);
1318 delete_node(pohNext
);
1319 free_node(pohFreed
);
1325 pohPrev
->ulSize
+= pohFreed
->ulSize
;
1326 free_node(pohFreed
);
1331 pohNext
->ulSize
+= pohFreed
->ulSize
;
1332 pohNext
->ulOffset
= pohFreed
->ulOffset
;
1333 free_node(pohFreed
);
1337 insert_node(&heap
.ohFree
, pohFreed
);
1343 * Frees our basic data structure allocation unit by adding it to a free
1347 static void free_node(struct OH
*poh
)
1353 poh
->pohNext
= heap
.pohFreeList
;
1354 heap
.pohFreeList
= poh
;
1359 void sis_malloc(struct sis_memreq
*req
)
1363 poh
= poh_allocate(req
->size
);
1368 DPRINTK("sisfb: VMEM Allocation Failed\n");
1370 DPRINTK("sisfb: VMEM Allocation Successed : 0x%p\n",
1371 (char *) (poh
->ulOffset
+
1372 (unsigned long) ivideo
.video_vbase
));
1374 req
->offset
= poh
->ulOffset
;
1375 req
->size
= poh
->ulSize
;
1380 void sis_free(unsigned long base
)
1384 poh
= poh_free(base
);
1387 DPRINTK("sisfb: poh_free() failed at base 0x%x\n",
1388 (unsigned int) base
);
1395 /* ---------------------- SetMode Routines -------------------------- */
1397 static void set_reg1(u16 port
, u16 index
, u16 data
)
1399 outb((u8
) (index
& 0xff), port
);
1401 outb((u8
) (data
& 0xff), port
);
1404 static void set_reg3(u16 port
, u16 data
)
1406 outb((u8
) (data
& 0xff), port
);
1409 static void set_reg4(u16 port
, unsigned long data
)
1411 outl((u32
) (data
& 0xffffffff), port
);
1414 static u8
get_reg1(u16 port
, u16 index
)
1418 outb((u8
) (index
& 0xff), port
);
1424 static u8
get_reg2(u16 port
)
1433 static u32
get_reg3(u16 port
)
1441 static u16
get_modeID_length(unsigned long ROMAddr
, u16 ModeNo
)
1443 unsigned char ModeID
;
1446 unsigned short PreviousWord
,CurrentWord
;
1451 usModeIDOffset
=*((unsigned short *)(ROMAddr
+0x20A)); // Get EModeIDTable
1453 CurrentWord
=*((unsigned short *)(ROMAddr
+usModeIDOffset
)); // Offset 0x20A
1454 PreviousWord
=*((unsigned short *)(ROMAddr
+usModeIDOffset
-2)); // Offset 0x20A
1455 while((CurrentWord
!=0x2E07)||(PreviousWord
!=0x0801))
1458 usModeIDOffset
=usModeIDOffset
+1; // 10 <= ExtStructSize
1459 CurrentWord
=*((unsigned short *)(ROMAddr
+usModeIDOffset
));
1460 PreviousWord
=*((unsigned short *)(ROMAddr
+usModeIDOffset
-2));
1464 return(modeidlength
);
1467 static int search_modeID(unsigned long ROMAddr
, u16 ModeNo
)
1469 unsigned char ModeID
;
1471 unsigned int count
= 0;
1473 ModeIDOffset
= *((u16
*) (ROMAddr
+ 0x20A));
1474 ModeID
= *((unsigned char *) (ROMAddr
+ ModeIDOffset
));
1475 usIDLength
= get_modeID_length(ROMAddr
, ModeNo
);
1476 while (ModeID
!= 0xff && ModeID
!= ModeNo
) {
1477 ModeIDOffset
= ModeIDOffset
+ usIDLength
;
1478 ModeID
= *((unsigned char *) (ROMAddr
+ ModeIDOffset
));
1479 if (count
++ >= 0xff)
1488 static int check_memory_size(unsigned long ROMAddr
)
1494 modeflag
= *((u16
*) (ROMAddr
+ ModeIDOffset
+ 0x01));
1495 ModeType
= modeflag
& ModeInfoFlag
;
1497 memorysize
= modeflag
& MemoryInfoFlag
;
1498 memorysize
= memorysize
>> MemorySizeShift
;
1501 temp
= get_reg1(P3c4
, 0x14);
1505 if (temp
< memorysize
)
1511 static void get_mode_ptr(unsigned long ROMAddr
, u16 ModeNo
)
1513 unsigned char index
;
1515 StandTable
= *((u16
*) (ROMAddr
+ 0x202));
1518 index
= *((unsigned char *) (ROMAddr
+ ModeIDOffset
+ 0x03));
1520 if (ModeType
<= 0x02)
1526 StandTable
= StandTable
+ 64 * index
;
1530 static void set_seq_regs(unsigned long ROMAddr
)
1532 unsigned char SRdata
;
1535 #ifdef CONFIG_FB_SIS_LINUXBIOS
1536 SRdata
= SRegs
[0x01];
1538 set_reg1(P3c4
, 0x00, 0x03);
1539 StandTable
= StandTable
+ 0x05;
1540 SRdata
= *((unsigned char *) (ROMAddr
+ StandTable
));
1543 SRdata
= SRdata
| 0x20;
1544 set_reg1(P3c4
, 0x01, SRdata
);
1547 for (i
= 02; i
<= 04; i
++) {
1548 #ifdef CONFIG_FB_SIS_LINUXBIOS
1552 SRdata
= *((unsigned char *) (ROMAddr
+ StandTable
));
1554 set_reg1(P3c4
, i
, SRdata
);
1558 static void set_misc_regs(unsigned long ROMAddr
)
1560 #ifdef CONFIG_FB_SIS_LINUXBIOS
1561 set_reg3(P3c2
, 0x23);
1563 unsigned char Miscdata
;
1566 Miscdata
= *((unsigned char *) (ROMAddr
+ StandTable
));
1567 set_reg3(P3c2
, Miscdata
);
1571 static void set_crtc_regs(unsigned long ROMAddr
)
1573 unsigned char CRTCdata
;
1576 CRTCdata
= (unsigned char) get_reg1(P3d4
, 0x11);
1577 #ifndef CONFIG_FB_SIS_LINUXBIOS
1578 CRTCdata
= CRTCdata
& 0x7f;
1580 set_reg1(P3d4
, 0x11, CRTCdata
);
1582 for (i
= 0; i
<= 0x18; i
++) {
1583 #ifdef CONFIG_FB_SIS_LINUXBIOS
1584 set_reg1(P3d4
, i
, CRegs
[i
]);
1587 CRTCdata
= *((unsigned char *) (ROMAddr
+ StandTable
));
1588 set_reg1(P3d4
, i
, CRTCdata
);
1593 static void set_attregs(unsigned long ROMAddr
)
1595 unsigned char ARdata
;
1598 for (i
= 0; i
<= 0x13; i
++) {
1599 #ifdef CONFIG_FB_SIS_LINUXBIOS
1602 set_reg3(P3c0
, ARegs
[i
]);
1605 ARdata
= *((unsigned char *) (ROMAddr
+ StandTable
));
1609 set_reg3(P3c0
, ARdata
);
1614 set_reg3(P3c0
, 0x14);
1615 set_reg3(P3c0
, 0x00);
1617 set_reg3(P3c0
, 0x20);
1620 static void set_grc_regs(unsigned long ROMAddr
)
1622 unsigned char GRdata
;
1625 for (i
= 0; i
<= 0x08; i
++) {
1626 #ifdef CONFIG_FB_SIS_LINUXBIOS
1627 set_reg1(P3ce
, i
, GRegs
[i
]);
1630 GRdata
= *((unsigned char *) (ROMAddr
+ StandTable
));
1631 set_reg1(P3ce
, i
, GRdata
);
1635 #ifndef CONFIG_FB_SIS_LINUXBIOS
1636 if (ModeType
> ModeVGA
) {
1637 GRdata
= (unsigned char) get_reg1(P3ce
, 0x05);
1638 GRdata
= GRdata
& 0xBF;
1639 set_reg1(P3ce
, 0x05, GRdata
);
1644 static void ClearExt1Regs(void)
1648 for (i
= 0x0A; i
<= 0x0E; i
++)
1649 set_reg1(P3c4
, i
, 0x00);
1652 static u16
GetRefindexLength(unsigned long ROMAddr
, u16 ModeNo
)
1654 unsigned char ModeID
;
1661 usModeIDOffset
= *((u16
*) (ROMAddr
+ 0x20A));
1662 ModeID
= *((unsigned char *) (ROMAddr
+ usModeIDOffset
));
1663 usIDLength
= get_modeID_length(ROMAddr
, ModeNo
);
1664 while (ModeID
!= 0x40) {
1665 usModeIDOffset
= usModeIDOffset
+ usIDLength
;
1666 ModeID
= *((unsigned char *) (ROMAddr
+ usModeIDOffset
));
1670 usREFIndex
= *((u16
*) (ROMAddr
+ usModeIDOffset
+ 0x04));
1672 temp
= *((unsigned char *) (ROMAddr
+ usREFIndex
));
1673 while (temp
!= 0xFF) {
1676 temp
= *((unsigned char *) (ROMAddr
+ usREFIndex
));
1678 return (refindexlength
);
1681 static int get_rate_ptr(unsigned long ROMAddr
, u16 ModeNo
)
1685 u16 ulRefIndexLength
;
1690 index
= get_reg1(P3d4
, 0x33);
1691 index
= index
& 0x0F;
1695 REFIndex
= *((u16
*) (ROMAddr
+ ModeIDOffset
+ 0x04));
1697 ulRefIndexLength
= GetRefindexLength(ROMAddr
, ModeNo
);
1700 temp
= *((u16
*) (ROMAddr
+ REFIndex
));
1703 temp
= temp
& ModeInfoFlag
;
1704 if (temp
< ModeType
)
1707 REFIndex
= REFIndex
+ ulRefIndexLength
;
1709 } while (index
>= 0);
1711 REFIndex
= REFIndex
- ulRefIndexLength
;
1715 static void set_sync(unsigned long ROMAddr
)
1717 #ifdef CONFIG_FB_SIS_LINUXBIOS
1718 set_reg3(P3c2
, MReg
);
1723 sync
= *((u16
*) (ROMAddr
+ REFIndex
));
1727 set_reg3(P3c2
, temp
);
1731 static void set_crt1_crtc(unsigned long ROMAddr
)
1733 #ifdef CONFIG_FB_SIS_LINUXBIOS
1737 data
= (unsigned char) get_reg1(P3d4
, 0x11);
1739 set_reg1(P3d4
, 0x11, data
);
1741 for (i
= 0; i
<= 0x07; i
++)
1742 set_reg1(P3d4
, i
, CRegs
[i
]);
1743 for (i
= 0x10; i
<= 0x12; i
++)
1744 set_reg1(P3d4
, i
, CRegs
[i
]);
1745 for (i
= 0x15; i
<= 0x16; i
++)
1746 set_reg1(P3d4
, i
, CRegs
[i
]);
1747 for (i
= 0x0A; i
<= 0x0C; i
++)
1748 set_reg1(P3c4
, i
, SRegs
[i
]);
1750 data
= SRegs
[0x0E] & 0xE0;
1751 set_reg1(P3c4
, 0x0E, data
);
1753 set_reg1(P3d4
, 0x09, CRegs
[0x09]);
1755 unsigned char index
;
1759 index
= *((unsigned char *) (ROMAddr
+ REFIndex
+ 0x02));
1760 CRT1Table
= *((u16
*) (ROMAddr
+ 0x204));
1761 CRT1Table
= CRT1Table
+ index
* CRT1Len
;
1763 data
= (unsigned char) get_reg1(P3d4
, 0x11);
1765 set_reg1(P3d4
, 0x11, data
);
1768 for (i
= 0; i
<= 0x05; i
++) {
1770 data
= *((unsigned char *) (ROMAddr
+ CRT1Table
));
1771 set_reg1(P3d4
, i
, data
);
1773 for (i
= 0x06; i
<= 0x07; i
++) {
1775 data
= *((unsigned char *) (ROMAddr
+ CRT1Table
));
1776 set_reg1(P3d4
, i
, data
);
1778 for (i
= 0x10; i
<= 0x12; i
++) {
1780 data
= *((unsigned char *) (ROMAddr
+ CRT1Table
));
1781 set_reg1(P3d4
, i
, data
);
1783 for (i
= 0x15; i
<= 0x16; i
++) {
1785 data
= *((unsigned char *) (ROMAddr
+ CRT1Table
));
1786 set_reg1(P3d4
, i
, data
);
1788 for (i
= 0x0A; i
<= 0x0C; i
++) {
1790 data
= *((unsigned char *) (ROMAddr
+ CRT1Table
));
1791 set_reg1(P3c4
, i
, data
);
1795 data
= *((unsigned char *) (ROMAddr
+ CRT1Table
));
1797 set_reg1(P3c4
, 0x0E, data
);
1799 data
= (unsigned char) get_reg1(P3d4
, 0x09);
1801 i
= *((unsigned char *) (ROMAddr
+ CRT1Table
));
1805 i
= *((u16
*) (ROMAddr
+ ModeIDOffset
+ 0x01));
1806 i
= i
& DoubleScanMode
;
1809 set_reg1(P3d4
, 0x09, data
);
1811 if (ModeType
> 0x03)
1812 set_reg1(P3d4
, 0x14, 0x4F);
1817 static void set_crt1_offset(unsigned long ROMAddr
)
1819 #ifdef CONFIG_FB_SIS_LINUXBIOS
1820 set_reg1(P3c4
, 0x0E, SRegs
[0x0E]);
1821 set_reg1(P3c4
, 0x10, SRegs
[0x10]);
1827 temp
= *((unsigned char *) (ROMAddr
+ ModeIDOffset
+ 0x03));
1829 ScreenOffset
= *((u16
*) (ROMAddr
+ 0x206));
1830 temp
= *((unsigned char *) (ROMAddr
+ ScreenOffset
+ temp
));
1832 temp2
= *((u16
*) (ROMAddr
+ REFIndex
+ 0x00));
1833 temp2
= temp2
& InterlaceMode
;
1836 temp2
= ModeType
- ModeEGA
;
1857 temp
= temp
* temp2
;
1863 i
= get_reg1(P3c4
, 0x0E);
1866 set_reg1(P3c4
, 0x0E, i
);
1868 temp
= (unsigned char) temp2
;
1870 set_reg1(P3d4
, 0x13, temp
);
1872 temp2
= *((u16
*) (ROMAddr
+ REFIndex
+ 0x00));
1873 temp2
= temp2
& InterlaceMode
;
1877 DisplayUnit
= DisplayUnit
<< 5;
1878 ah
= (DisplayUnit
& 0xff00) >> 8;
1879 al
= DisplayUnit
& 0x00ff;
1884 set_reg1(P3c4
, 0x10, ah
);
1888 static u16
get_vclk_len(unsigned long ROMAddr
)
1890 u16 VCLKDataStart
, vclklabel
, temp
;
1891 VCLKDataStart
= *((u16
*) (ROMAddr
+ 0x208));
1892 for (temp
= 0;; temp
++) {
1893 vclklabel
= *((u16
*) (ROMAddr
+ VCLKDataStart
+ temp
));
1894 if (vclklabel
== VCLKStartFreq
) {
1902 static void set_crt1_vclk(unsigned long ROMAddr
)
1906 #ifndef CONFIG_FB_SIS_LINUXBIOS
1907 unsigned char index
, data
;
1909 index
= *((unsigned char *) (ROMAddr
+ REFIndex
+ 0x03));
1911 CRT1VCLKLen
= get_vclk_len(ROMAddr
);
1912 data
= index
* CRT1VCLKLen
;
1913 VCLKData
= *((u16
*) (ROMAddr
+ 0x208));
1914 VCLKData
= VCLKData
+ data
;
1917 set_reg1(P3c4
, 0x31, 0);
1919 for (i
= 0x2B; i
<= 0x2C; i
++) {
1920 #ifdef CONFIG_FB_SIS_LINUXBIOS
1921 set_reg1(P3c4
, i
, SRegs
[i
]);
1923 data
= *((unsigned char *) (ROMAddr
+ VCLKData
));
1924 set_reg1(P3c4
, i
, data
);
1928 set_reg1(P3c4
, 0x2D, 0x80);
1930 static void set_vclk_state(unsigned long ROMAddr
, u16 ModeNo
)
1932 #ifdef CONFIG_FB_SIS_LINUXBIOS
1933 set_reg1(P3c4
, 0x32, SRegs
[0x32]);
1934 set_reg1(P3c4
, 0x07, SRegs
[0x07]);
1939 unsigned char index
;
1941 index
= *((unsigned char *) (ROMAddr
+ REFIndex
+ 0x03));
1943 CRT1VCLKLen
= get_vclk_len(ROMAddr
);
1944 data
= index
* CRT1VCLKLen
;
1945 VCLKData
= *((u16
*) (ROMAddr
+ 0x208));
1946 VCLKData
= VCLKData
+ data
+ (CRT1VCLKLen
- 2);
1948 VCLK
= *((u16
*) (ROMAddr
+ VCLKData
));
1952 data
= get_reg1(P3c4
, 0x07);
1956 set_reg1(P3c4
, 0x07, data
);
1958 data
= get_reg1(P3c4
, 0x32);
1962 set_reg1(P3c4
, 0x32, data
);
1971 data
= get_reg1(P3c4
, 0x07);
1973 data
= data
| data2
;
1974 set_reg1(P3c4
, 0x07, data
);
1978 static u16
calc_delay2(unsigned long ROMAddr
, u16 key
)
1981 unsigned char LatencyFactor
[] = {
1982 88, 80, 78, 72, 70, 00,
1983 00, 79, 77, 71, 69, 49,
1984 88, 80, 78, 72, 70, 00,
1985 00, 72, 70, 64, 62, 44
1988 data
= get_reg1(P3c4
, 0x14);
1992 data
= get_reg1(P3c4
, 0x15);
1993 data
= (data
& 0xf0) >> 4;
1998 index
= index
+ data
;
1999 data
= LatencyFactor
[index
];
2004 static u16
calc_delay(unsigned long ROMAddr
, u16 key
)
2006 u16 data
, data2
, temp0
, temp1
;
2007 unsigned char ThLowA
[] = {
2008 61, 3, 52, 5, 68, 7, 100, 11,
2009 43, 3, 42, 5, 54, 7, 78, 11,
2010 34, 3, 37, 5, 47, 7, 67, 11
2012 unsigned char ThLowB
[] = {
2013 81, 4, 72, 6, 88, 8, 120, 12,
2014 55, 4, 54, 6, 66, 8, 90, 12,
2015 42, 4, 45, 6, 55, 8, 75, 12
2017 unsigned char ThTiming
[] = { 1, 2, 2, 3, 0, 1, 1, 2 };
2019 data
= get_reg1(P3c4
, 0x16);
2021 data2
= get_reg1(P3c4
, 0x14);
2022 data2
= (data2
>> 4) & 0x0C;
2023 data
= data
| data2
;
2026 temp0
= (u16
) ThLowA
[data
];
2027 temp1
= (u16
) ThLowA
[data
+ 1];
2029 temp0
= (u16
) ThLowB
[data
];
2030 temp1
= (u16
) ThLowB
[data
+ 1];
2034 data
= get_reg1(P3c4
, 0x18);
2036 data2
= data2
| 0x01;
2038 data2
= data2
| 0x02;
2040 data2
= data2
| 0x04;
2042 data
= temp1
* ThTiming
[data2
] + temp0
;
2047 static void set_crt1_FIFO(unsigned long ROMAddr
)
2049 u16 index
, data
, VCLK
, data2
, MCLKOffset
, MCLK
, colorth
= 1;
2052 index
= *((unsigned char *) (ROMAddr
+ REFIndex
+ 0x03));
2054 CRT1VCLKLen
= get_vclk_len(ROMAddr
);
2055 data
= index
* CRT1VCLKLen
;
2056 VCLKData
= *((u16
*) (ROMAddr
+ 0x208));
2057 VCLKData
= VCLKData
+ data
+ (CRT1VCLKLen
- 2);
2058 VCLK
= *((u16
*) (ROMAddr
+ VCLKData
));
2060 MCLKOffset
= *((u16
*) (ROMAddr
+ 0x20C));
2061 index
= get_reg1(P3c4
, 0x3A);
2063 MCLKOffset
= MCLKOffset
+ index
* 5;
2064 MCLK
= *((unsigned char *) (ROMAddr
+ MCLKOffset
+ 0x03));
2066 data2
= ModeType
- 0x02;
2089 B
= (calc_delay(ROMAddr
, 0) * VCLK
* colorth
);
2090 B
= B
/ (16 * MCLK
);
2093 A
= (calc_delay(ROMAddr
, 1) * VCLK
* colorth
);
2094 A
= A
/ (16 * MCLK
);
2109 data
= get_reg1(P3c4
, 0x16);
2114 data2
= get_reg1(P3c4
, 0x16);
2115 data2
= (data2
& 0x3f) | data
;
2116 set_reg1(P3c4
, 0x16, data2
);
2120 } while (bl
> 0x13);
2125 set_reg1(P3c4
, 0x08, ah
);
2130 data2
= get_reg1(P3c4
, 0x0F);
2131 data2
= data2
& 0x9f;
2132 data2
= data2
| data
;
2133 set_reg1(P3c4
, 0x0F, data2
);
2138 set_reg1(P3c4
, 0x3b, 0x00);
2139 data2
= get_reg1(P3c4
, 0x09);
2140 data2
= data2
& 0xF0;
2141 data2
= data2
| data
;
2142 set_reg1(P3c4
, 0x09, data2
);
2145 static void set_crt1_FIFO2(unsigned long ROMAddr
)
2147 #ifdef CONFIG_FB_SIS_LINUXBIOS
2148 set_reg1(P3c4
, 0x15, SRegs
[0x15]);
2150 set_reg4(0xcf8, 0x80000050);
2151 set_reg4(0xcfc, 0xc5041e04);
2153 set_reg1(P3c4
, 0x08, SRegs
[0x08]);
2154 set_reg1(P3c4
, 0x0F, SRegs
[0x0F]);
2155 set_reg1(P3c4
, 0x3b, 0x00);
2156 set_reg1(P3c4
, 0x09, SRegs
[0x09]);
2159 u16 index
, data
, VCLK
, data2
, MCLKOffset
, MCLK
, colorth
= 1;
2163 index
= *((unsigned char *) (ROMAddr
+ REFIndex
+ 0x03));
2165 CRT1VCLKLen
= get_vclk_len(ROMAddr
);
2166 data
= index
* CRT1VCLKLen
;
2167 VCLKData
= *((u16
*) (ROMAddr
+ 0x208));
2168 VCLKData
= VCLKData
+ data
+ (CRT1VCLKLen
- 2);
2169 VCLK
= *((u16
*) (ROMAddr
+ VCLKData
));
2171 MCLKOffset
= *((u16
*) (ROMAddr
+ 0x20C));
2172 index
= get_reg1(P3c4
, 0x1A);
2174 MCLKOffset
= MCLKOffset
+ index
* 5;
2175 MCLK
= *((u16
*) (ROMAddr
+ MCLKOffset
+ 0x03));
2177 data2
= ModeType
- 0x02;
2200 B
= (calc_delay2(ROMAddr
, 0) * VCLK
* colorth
);
2201 if (B
% (16 * MCLK
) == 0) {
2202 B
= B
/ (16 * MCLK
);
2205 B
= B
/ (16 * MCLK
);
2210 data
= get_reg1(P3c4
, 0x15);
2216 data2
= get_reg1(P3c4
, 0x15);
2217 data2
= (data2
& 0x0f) | data
;
2218 set_reg1(P3c4
, 0x15, data2
);
2222 } while (bl
> 0x13);
2224 data2
= get_reg1(P3c4
, 0x15);
2225 data2
= (data2
& 0xf0) >> 4;
2226 data2
= data2
<< 24;
2228 set_reg4(0xcf8, 0x80000050);
2229 eax
= get_reg3(0xcfc);
2230 eax
= eax
& 0x0f0ffffff;
2232 set_reg4(0xcfc, eax
);
2237 set_reg1(P3c4
, 0x08, ah
);
2242 data2
= get_reg1(P3c4
, 0x0F);
2243 data2
= data2
& 0x9f;
2244 data2
= data2
| data
;
2245 set_reg1(P3c4
, 0x0F, data2
);
2250 set_reg1(P3c4
, 0x3b, 0x00);
2251 data2
= get_reg1(P3c4
, 0x09);
2252 data2
= data2
& 0xF0;
2253 data2
= data2
| data
;
2254 set_reg1(P3c4
, 0x09, data2
);
2258 static void set_crt1_mode_regs(unsigned long ROMAddr
, u16 ModeNo
)
2260 #ifdef CONFIG_FB_SIS_LINUXBIOS
2261 set_reg1(P3c4
, 0x06, SRegs
[0x06]);
2262 set_reg1(P3c4
, 0x01, SRegs
[0x01]);
2263 set_reg1(P3c4
, 0x0F, SRegs
[0x0F]);
2264 set_reg1(P3c4
, 0x21, SRegs
[0x21]);
2267 u16 data
, data2
, data3
;
2270 data
= *((u16
*) (ROMAddr
+ REFIndex
+ 0x00));
2276 if (ModeType
> 0x02) {
2277 data2
= data2
| 0x02;
2278 data3
= ModeType
- ModeVGA
;
2280 data2
= data2
| data3
;
2283 data
= data
& InterlaceMode
;
2285 data2
= data2
| 0x20;
2286 set_reg1(P3c4
, 0x06, data2
);
2288 data
= get_reg1(P3c4
, 0x01);
2290 data2
= *((u16
*) (ROMAddr
+ ModeIDOffset
+ 0x01));
2291 data2
= data2
& HalfDCLK
;
2294 set_reg1(P3c4
, 0x01, data
);
2296 data
= get_reg1(P3c4
, 0x0F);
2298 data2
= *((u16
*) (ROMAddr
+ ModeIDOffset
+ 0x01));
2299 data2
= data2
& LineCompareOff
;
2302 set_reg1(P3c4
, 0x0F, data
);
2304 data
= get_reg1(P3c4
, 0x21);
2306 if (ModeType
== 0x00)
2308 else if (ModeType
<= 0x02)
2312 set_reg1(P3c4
, 0x21, data
);
2316 static void set_interlace(unsigned long ROMAddr
, u16 ModeNo
)
2318 #ifdef CONFIG_FB_SIS_LINUXBIOS
2319 set_reg1(P3d4
, 0x19, CRegs
[0x19]);
2320 set_reg1(P3d4
, 0x1A, CRegs
[0x1A]);
2326 Temp
= (unsigned long) get_reg1(P3d4
, 0x01);
2332 else if (Temp
== 1280)
2337 Temp2
= *((u16
*) (ROMAddr
+ REFIndex
+ 0x00));
2338 Temp2
&= InterlaceMode
;
2342 set_reg1(P3d4
, 0x19, data
);
2344 Temp
= (unsigned long) get_reg1(P3d4
, 0x1A);
2345 Temp2
= (u16
) (Temp
& 0xFC);
2346 set_reg1(P3d4
, 0x1A, (u16
) Temp
);
2348 Temp
= (unsigned long) get_reg1(P3c4
, 0x0f);
2349 Temp2
= (u16
) Temp
& 0xBF;
2351 Temp2
= Temp2
| 0x40;
2352 set_reg1(P3d4
, 0x1A, (u16
) Temp2
);
2356 static void write_DAC(u16 dl
, u16 ah
, u16 al
, u16 dh
)
2377 set_reg3(P3c9
, (u16
) dh
);
2378 set_reg3(P3c9
, (u16
) bh
);
2379 set_reg3(P3c9
, (u16
) bl
);
2383 static void load_DAC(unsigned long ROMAddr
)
2390 u16
*table
= VGA_DAC
;
2392 #ifndef CONFIG_FB_SIS_LINUXBIOS
2393 data
= *((u16
*) (ROMAddr
+ ModeIDOffset
+ 0x01));
2394 data
= data
& DACInfoFlag
;
2416 set_reg3(P3c6
, 0xFF);
2417 set_reg3(P3c8
, 0x00);
2419 for (i
= 0; i
< j
; i
++) {
2421 for (k
= 0; k
< 3; k
++) {
2426 data2
= data2
+ 0x15;
2427 set_reg3(P3c9
, data2
);
2433 for (i
= 16; i
< 32; i
++) {
2435 for (k
= 0; k
< 3; k
++)
2436 set_reg3(P3c9
, data
);
2439 for (m
= 0; m
< 9; m
++) {
2443 for (n
= 0; n
< 3; n
++) {
2444 for (o
= 0; o
< 5; o
++) {
2449 write_DAC(dl
, ah
, al
, dh
);
2452 for (o
= 0; o
< 3; o
++) {
2457 write_DAC(dl
, ah
, al
, dh
);
2466 static void display_on(void)
2470 data
= get_reg1(P3c4
, 0x01);
2472 set_reg1(P3c4
, 0x01, data
);
2475 void SetMemoryClock(void)
2481 0x5A, 0x64, 0x80, 0x66, 0x00, // SDRAM
2482 0xB3, 0x45, 0x80, 0x83, 0x00, // SGRAM
2483 0x37, 0x61, 0x80, 0x00, 0x01, // ESDRAM
2484 0x37, 0x22, 0x80, 0x33, 0x01,
2485 0x37, 0x61, 0x80, 0x00, 0x01,
2486 0x37, 0x61, 0x80, 0x00, 0x01,
2487 0x37, 0x61, 0x80, 0x00, 0x01,
2488 0x37, 0x61, 0x80, 0x00, 0x01
2492 0x54, 0x43, 0x80, 0x00, 0x01,
2493 0x53, 0x43, 0x80, 0x00, 0x01,
2494 0x55, 0x43, 0x80, 0x00, 0x01,
2495 0x52, 0x43, 0x80, 0x00, 0x01,
2496 0x3f, 0x42, 0x80, 0x00, 0x01,
2497 0x54, 0x43, 0x80, 0x00, 0x01,
2498 0x54, 0x43, 0x80, 0x00, 0x01,
2499 0x54, 0x43, 0x80, 0x00, 0x01
2504 for (i
= 0x28; i
<= 0x2A; i
++) { // Set MCLK
2505 set_reg1(P3c4
, i
, MCLK
[idx
]);
2510 for (i
= 0x2E; i
<= 0x30; i
++) { // Set ECLK
2511 set_reg1(P3c4
, i
, ECLK
[idx
]);
2516 void ClearDAC(u16 port
)
2520 set_reg3(P3c8
, 0x00);
2521 for (i
= 0; i
< (256 * 3); i
++)
2522 set_reg3(P3c9
, 0x00);
2525 void ClearALLBuffer(void)
2527 unsigned long AdapterMemorySize
;
2529 AdapterMemorySize
= get_reg1(P3c4
, 0x14);
2530 AdapterMemorySize
= AdapterMemorySize
& 0x3F;
2531 AdapterMemorySize
++;
2533 memset((char *) ivideo
.video_vbase
, 0, AdapterMemorySize
);
2540 for (temp
= 1; temp
> 0;) {
2541 temp
= get_reg2(P3da
);
2544 for (; temp
== 0;) {
2545 temp
= get_reg2(P3da
);
2550 void WaitDisplay(void)
2552 unsigned short temp
;
2554 for (temp
= 0; temp
== 0;) {
2555 temp
= get_reg2(P3da
);
2558 for (; temp
== 1;) {
2559 temp
= get_reg2(P3da
);
2564 int TestMonitorType(unsigned short d1
, unsigned short d2
, unsigned short d3
)
2566 unsigned short temp
;
2567 set_reg3(P3c6
, 0xFF);
2568 set_reg3(P3c8
, 0x00);
2572 WaitDisplay(); //wait horizontal retrace
2573 temp
= get_reg2(P3c2
);
2580 void SetRegANDOR(unsigned short Port
, unsigned short Index
,
2581 unsigned short DataAND
, unsigned short DataOR
)
2583 unsigned short temp1
;
2584 temp1
= get_reg1(Port
, Index
); //part1port index 02
2585 temp1
= (temp1
& (DataAND
)) | DataOR
;
2586 set_reg1(Port
, Index
, temp1
);
2590 int DetectMonitor(void)
2592 unsigned short flag1
;
2593 unsigned short DAC_TEST_PARMS
[3] = { 0x0F, 0x0F, 0x0F };
2594 unsigned short DAC_CLR_PARMS
[3] = { 0x00, 0x00, 0x00 };
2596 flag1
= get_reg1(P3c4
, 0x38); //call BridgeisOn
2597 if ((flag1
& 0x20)) {
2598 set_reg1(P3d4
, 0x30, 0x41);
2601 SiSSetMode(0x2E); //set mode to 0x2E instead of 0x3
2609 flag1
= TestMonitorType(DAC_TEST_PARMS
[0], DAC_TEST_PARMS
[1],
2612 flag1
= TestMonitorType(DAC_TEST_PARMS
[0], DAC_TEST_PARMS
[1],
2617 SetRegANDOR(P3d4
, 0x32, ~Monitor1Sense
, Monitor1Sense
);
2619 SetRegANDOR(P3d4
, 0x32, ~Monitor1Sense
, 0x0);
2622 TestMonitorType(DAC_CLR_PARMS
[0], DAC_CLR_PARMS
[1],
2625 set_reg1(P3d4
, 0x34, 0x4A);
2630 int SiSInit300(void)
2632 //unsigned long ROMAddr = rom_vbase;
2633 u16 BaseAddr
= (u16
) ivideo
.vga_base
;
2634 unsigned char i
, temp
, AGP
;
2635 unsigned long j
, k
, ulTemp
;
2636 unsigned char SR11
, SR19
, SR1A
, SR21
, SR22
;
2640 P3c4
= BaseAddr
+ 0x14;
2641 P3d4
= BaseAddr
+ 0x24;
2642 P3c0
= BaseAddr
+ 0x10;
2643 P3ce
= BaseAddr
+ 0x1e;
2644 P3c2
= BaseAddr
+ 0x12;
2645 P3ca
= BaseAddr
+ 0x1a;
2646 P3c6
= BaseAddr
+ 0x16;
2647 P3c7
= BaseAddr
+ 0x17;
2648 P3c8
= BaseAddr
+ 0x18;
2649 P3c9
= BaseAddr
+ 0x19;
2650 P3da
= BaseAddr
+ 0x2A;
2652 set_reg1(P3c4
, 0x05, 0x86); // 1.Openkey
2654 SR14
= (unsigned char) get_reg1(P3c4
, 0x14);
2655 SR19
= (unsigned char) get_reg1(P3c4
, 0x19);
2656 SR1A
= (unsigned char) get_reg1(P3c4
, 0x1A);
2658 for (i
= 0x06; i
< 0x20; i
++)
2659 set_reg1(P3c4
, i
, 0); // 2.Reset Extended register
2660 for (i
= 0x21; i
<= 0x27; i
++)
2661 set_reg1(P3c4
, i
, 0); // Reset Extended register
2662 for (i
= 0x31; i
<= 0x3D; i
++)
2663 set_reg1(P3c4
, i
, 0);
2664 for (i
= 0x30; i
<= 0x37; i
++)
2665 set_reg1(P3d4
, i
, 0);
2668 if ((ivideo
.chip_id
== SIS_Trojan
) || (ivideo
.chip_id
== SIS_Spartan
))
2669 // 3.Set Define Extended register
2670 temp
= (unsigned char) SR1A
;
2672 temp
= *((unsigned char *) (ROMAddr
+ SoftSettingAddr
));
2673 if ((temp
& SoftDRAMType
) == 0) {
2674 // 3.Set Define Extended register
2675 temp
= (unsigned char) get_reg1(P3c4
, 0x3A);
2680 // 3.Set Define Extended register
2681 temp
= (unsigned char) SR1A
;
2683 RAMType
= temp
& 0x07;
2685 for (k
= 0; k
< 5; k
++)
2686 for (j
= 0; j
< 0xffff; j
++)
2687 ulTemp
= (unsigned long) get_reg1(P3c4
, 0x05);
2689 Temp
= (unsigned long) get_reg1(P3c4
, 0x3C);
2691 set_reg1(P3c4
, 0x3C, (unsigned short) Temp
);
2692 for (k
= 0; k
< 5; k
++)
2693 for (j
= 0; j
< 0xffff; j
++)
2694 Temp
= (unsigned long) get_reg1(P3c4
, 0x05);
2696 Temp
= (unsigned long) get_reg1(P3c4
, 0x3C);
2698 set_reg1(P3c4
, 0x3C, (unsigned short) Temp
);
2699 for (k
= 0; k
< 5; k
++)
2700 for (j
= 0; j
< 0xffff; j
++)
2701 Temp
= (unsigned long) get_reg1(P3c4
, 0x05);
2703 //SR07=*((unsigned char *)(ROMAddr+0xA4)); // todo
2704 set_reg1(P3c4
, 0x07, SRegsInit
[0x07]);
2706 if (HwDeviceExtension
->jChipID
== SIS_Glamour
)
2707 for (i
= 0x15; i
<= 0x1C; i
++) {
2708 temp
= *((unsigned char *) (ROMAddr
+ 0xA5 + ((i
- 0x15) * 8) + RAMType
));
2709 set_reg1(P3c4
, i
, temp
);
2713 //SR1F=*((unsigned char *)(ROMAddr+0xE5));
2714 set_reg1(P3c4
, 0x1F, SRegsInit
[0x1F]);
2718 temp
= (unsigned char) get_reg1(P3c4
, 0x3A);
2724 //SR21=*((unsigned char *)(ROMAddr+0xE6));
2725 SR21
= SRegsInit
[0x21];
2727 SR21
= SR21
& 0xEF; // PCI
2728 set_reg1(P3c4
, 0x21, SR21
);
2730 //SR22=*((unsigned char *)(ROMAddr+0xE7));
2731 SR22
= SRegsInit
[0x22];
2733 SR22
= SR22
& 0x20; // AGP
2734 set_reg1(P3c4
, 0x22, SR22
);
2736 //SR23=*((unsigned char *)(ROMAddr+0xE8));
2737 set_reg1(P3c4
, 0x23, SRegsInit
[0x23]);
2739 //SR24=*((unsigned char *)(ROMAddr+0xE9));
2740 set_reg1(P3c4
, 0x24, SRegsInit
[0x24]);
2742 //SR25=*((unsigned char *)(ROMAddr+0xEA));
2743 set_reg1(P3c4
, 0x25, SRegsInit
[0x25]);
2745 //SR32=*((unsigned char *)(ROMAddr+0xEB));
2746 set_reg1(P3c4
, 0x32, SRegsInit
[0x32]);
2749 set_reg1(P3c4
, 0x11, SR11
);
2752 if (IF_DEF_LVDS
== 1) {
2755 } else if (IF_DEF_TRUMPION
== 1) {
2757 temp
= ExtChipTrumpion
;
2766 set_reg1(P3d4
, 0x37, temp
);
2769 //09/07/99 modify by domao for 630/540 MM
2770 if (HwDeviceExtension
->jChipID
== SIS_Glamour
) {
2772 SetDRAMSize(HwDeviceExtension
);
2773 SetDRAMSize(HwDeviceExtension
);
2775 //For SiS 630/540 Chip
2776 //Restore SR14, SR19 and SR1A
2777 set_reg1(P3c4
, 0x14, SR14
);
2778 set_reg1(P3c4
, 0x19, SR19
);
2779 set_reg1(P3c4
, 0x1A, SR1A
);
2783 set_reg1(P3c4
, 0x14, SR14
);
2784 set_reg1(P3c4
, 0x19, SR19
);
2785 set_reg1(P3c4
, 0x1A, SR1A
);
2786 set_reg3(P3c6
, 0xff);
2792 GetSenseStatus(HwDeviceExtension
, BaseAddr
, ROMAddr
);
2798 static int SiSSetMode(u16 ModeNo
)
2800 //#ifndef CONFIG_FB_SIS_LINUXBIOS
2804 u16 cr30flag
, cr31flag
;
2805 unsigned long ROMAddr
= rom_vbase
;
2806 u16 BaseAddr
= (u16
) ivideo
.vga_base
;
2809 P3c4
= BaseAddr
+ 0x14;
2810 P3d4
= BaseAddr
+ 0x24;
2811 P3c0
= BaseAddr
+ 0x10;
2812 P3ce
= BaseAddr
+ 0x1e;
2813 P3c2
= BaseAddr
+ 0x12;
2814 P3ca
= BaseAddr
+ 0x1a;
2815 P3c6
= BaseAddr
+ 0x16;
2816 P3c7
= BaseAddr
+ 0x17;
2817 P3c8
= BaseAddr
+ 0x18;
2818 P3c9
= BaseAddr
+ 0x19;
2819 P3da
= BaseAddr
+ 0x2A;
2821 #ifndef CONFIG_FB_SIS_LINUXBIOS
2822 temp
= search_modeID(ROMAddr
, ModeNo
);
2827 temp
= check_memory_size(ROMAddr
);
2833 cr30flag
= (unsigned char) get_reg1(P3d4
, 0x30);
2834 if (((cr30flag
& 0x01) == 1) || ((cr30flag
& 0x02) == 0)) {
2835 #ifndef CONFIG_FB_SIS_LINUXBIOS
2836 get_mode_ptr(ROMAddr
, ModeNo
);
2838 set_seq_regs(ROMAddr
);
2839 set_misc_regs(ROMAddr
);
2840 set_crtc_regs(ROMAddr
);
2841 set_attregs(ROMAddr
);
2842 set_grc_regs(ROMAddr
);
2845 #ifndef CONFIG_FB_SIS_LINUXBIOS
2846 temp
= get_rate_ptr(ROMAddr
, ModeNo
);
2850 set_crt1_crtc(ROMAddr
);
2851 set_crt1_offset(ROMAddr
);
2852 set_crt1_vclk(ROMAddr
);
2853 set_vclk_state(ROMAddr
, ModeNo
);
2855 if ((ivideo
.chip_id
== SIS_Trojan
) || (ivideo
.chip_id
== SIS_Spartan
))
2856 set_crt1_FIFO2(ROMAddr
);
2858 set_crt1_FIFO(ROMAddr
);
2859 #ifndef CONFIG_FB_SIS_LINUXBIOS
2862 set_crt1_mode_regs(ROMAddr
, ModeNo
);
2863 if ((ivideo
.chip_id
== SIS_Trojan
) || (ivideo
.chip_id
== SIS_Spartan
))
2864 set_interlace(ROMAddr
, ModeNo
);
2867 /* clear OnScreen */
2868 memset((char *) ivideo
.video_vbase
, 0,
2869 video_linelength
* ivideo
.video_height
);
2872 cr30flag
= (unsigned char) get_reg1(P3d4
, 0x30);
2873 if (((cr30flag
& 0x01) == 1) || ((cr30flag
& 0x02) == 0)) {
2874 //set_seq_regs(ROMAddr);
2876 unsigned char SRdata
;
2877 SRdata
= SRegs
[0x01] | 0x20;
2878 set_reg1(P3c4
, 0x01, SRdata
);
2880 for (i
= 02; i
<= 04; i
++)
2881 set_reg1(P3c4
, i
, SRegs
[i
]);
2884 //set_misc_regs(ROMAddr);
2886 set_reg3(P3c2
, 0x23);
2889 //set_crtc_regs(ROMAddr);
2891 unsigned char CRTCdata
;
2893 CRTCdata
= (unsigned char) get_reg1(P3d4
, 0x11);
2894 set_reg1(P3d4
, 0x11, CRTCdata
);
2896 for (i
= 0; i
<= 0x18; i
++)
2897 set_reg1(P3d4
, i
, CRegs
[i
]);
2900 //set_attregs(ROMAddr);
2902 for (i
= 0; i
<= 0x13; i
++) {
2905 set_reg3(P3c0
, ARegs
[i
]);
2908 set_reg3(P3c0
, 0x14);
2909 set_reg3(P3c0
, 0x00);
2911 set_reg3(P3c0
, 0x20);
2914 //set_grc_regs(ROMAddr);
2916 for (i
= 0; i
<= 0x08; i
++)
2917 set_reg1(P3ce
, i
, GRegs
[i
]);
2922 for (i
= 0x0A; i
<= 0x0E; i
++)
2923 set_reg1(P3c4
, i
, 0x00);
2926 //set_sync(ROMAddr);
2928 set_reg3(P3c2
, MReg
);
2931 //set_crt1_crtc(ROMAddr);
2935 data
= (unsigned char) get_reg1(P3d4
, 0x11);
2937 set_reg1(P3d4
, 0x11, data
);
2939 for (i
= 0; i
<= 0x07; i
++)
2940 set_reg1(P3d4
, i
, CRegs
[i
]);
2941 for (i
= 0x10; i
<= 0x12; i
++)
2942 set_reg1(P3d4
, i
, CRegs
[i
]);
2943 for (i
= 0x15; i
<= 0x16; i
++)
2944 set_reg1(P3d4
, i
, CRegs
[i
]);
2945 for (i
= 0x0A; i
<= 0x0C; i
++)
2946 set_reg1(P3c4
, i
, SRegs
[i
]);
2948 data
= SRegs
[0x0E] & 0xE0;
2949 set_reg1(P3c4
, 0x0E, data
);
2951 set_reg1(P3d4
, 0x09, CRegs
[0x09]);
2955 //set_crt1_offset(ROMAddr);
2957 set_reg1(P3c4
, 0x0E, SRegs
[0x0E]);
2958 set_reg1(P3c4
, 0x10, SRegs
[0x10]);
2961 //set_crt1_vclk(ROMAddr);
2963 set_reg1(P3c4
, 0x31, 0);
2965 for (i
= 0x2B; i
<= 0x2C; i
++)
2966 set_reg1(P3c4
, i
, SRegs
[i
]);
2967 set_reg1(P3c4
, 0x2D, 0x80);
2970 //set_vclk_state(ROMAddr, ModeNo);
2972 set_reg1(P3c4
, 0x32, SRegs
[0x32]);
2973 set_reg1(P3c4
, 0x07, SRegs
[0x07]);
2976 if ((ivideo
.chip_id
== SIS_Trojan
)
2977 || (ivideo
.chip_id
== SIS_Spartan
)) {
2978 //set_crt1_FIFO2(ROMAddr);
2979 set_reg1(P3c4
, 0x15, SRegs
[0x15]);
2981 set_reg4(0xcf8, 0x80000050);
2982 set_reg4(0xcfc, 0xc5041e04);
2984 set_reg1(P3c4
, 0x08, SRegs
[0x08]);
2985 set_reg1(P3c4
, 0x0F, SRegs
[0x0F]);
2986 set_reg1(P3c4
, 0x3b, 0x00);
2987 set_reg1(P3c4
, 0x09, SRegs
[0x09]);
2990 //set_crt1_mode_regs(ROMAddr, ModeNo);
2992 set_reg1(P3c4
, 0x06, SRegs
[0x06]);
2993 set_reg1(P3c4
, 0x01, SRegs
[0x01]);
2994 set_reg1(P3c4
, 0x0F, SRegs
[0x0F]);
2995 set_reg1(P3c4
, 0x21, SRegs
[0x21]);
2998 if ((ivideo
.chip_id
== SIS_Trojan
) || (ivideo
.chip_id
== SIS_Spartan
)) {
2999 //set_interlace(ROMAddr, ModeNo);
3000 set_reg1(P3d4
, 0x19, CRegs
[0x19]);
3001 set_reg1(P3d4
, 0x1A, CRegs
[0x1A]);
3005 /* clear OnScreen */
3006 memset((char *) ivideo
.video_vbase
, 0,
3007 video_linelength
* ivideo
.video_height
);
3010 cr31flag
= (unsigned char) get_reg1(P3d4
, 0x31);
3017 static void pre_setmode(void)
3019 vgawb(CRTC_ADR
, 0x30);
3020 vgawb(CRTC_DATA
, 0x00);
3022 vgawb(CRTC_ADR
, 0x31);
3023 vgawb(CRTC_DATA
, 0x60);
3025 DPRINTK("Setting CR33 = 0x%x\n", rate_idx
& 0x0f);
3027 /* set CRT1 refresh rate */
3028 vgawb(CRTC_ADR
, 0x33);
3029 vgawb(CRTC_DATA
, rate_idx
& 0x0f);
3032 static void post_setmode(void)
3037 vgawb(CRTC_ADR
, 0x17);
3038 uTemp
= vgarb(CRTC_DATA
);
3040 vgawb(CRTC_DATA
, uTemp
);
3042 /* disable 24-bit palette RAM and Gamma correction */
3043 vgawb(SEQ_ADR
, 0x07);
3044 uTemp
= vgarb(SEQ_DATA
);
3046 vgawb(SEQ_DATA
, uTemp
);
3049 static void search_mode(const char *name
)
3056 while (sisbios_mode
[i
].mode_no
!= 0) {
3057 if (!strcmp(name
, sisbios_mode
[i
].name
)) {
3064 DPRINTK("Invalid user mode : %s\n", name
);
3067 static u8
search_refresh_rate(unsigned int rate
)
3072 xres
= sisbios_mode
[mode_idx
].xres
;
3073 yres
= sisbios_mode
[mode_idx
].yres
;
3075 while ((vrate
[i
].idx
!= 0) && (vrate
[i
].xres
<= xres
)) {
3076 if ((vrate
[i
].xres
== xres
) && (vrate
[i
].yres
== yres
)
3077 && (vrate
[i
].refresh
== rate
)) {
3078 rate_idx
= vrate
[i
].idx
;
3084 DPRINTK("sisfb: Unsupported rate %d in %dx%d mode\n", rate
, xres
,
3092 /* ------------------ Public Routines ------------------------------- */
3095 * Get the Fixed Part of the Display
3098 static int sisfb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
3099 struct fb_info
*info
)
3101 DPRINTK("sisfb: sisfb_get_fix:[%d]\n", con
);
3103 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
3104 strcpy(fix
->id
, fb_info
.modename
);
3106 fix
->smem_start
= ivideo
.video_base
;
3107 if(ivideo
.video_size
> 0x800000)
3108 fix
->smem_len
= RESERVED_MEM_SIZE_8M
; /* reserved for Xserver */
3110 fix
->smem_len
= RESERVED_MEM_SIZE_4M
; /* reserved for Xserver */
3112 fix
->type
= video_type
;
3114 if (ivideo
.video_bpp
== 8)
3115 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
3117 fix
->visual
= FB_VISUAL_TRUECOLOR
;
3121 fix
->line_length
= video_linelength
;
3122 fix
->mmio_start
= ivideo
.mmio_base
;
3123 fix
->mmio_len
= MMIO_SIZE
;
3124 fix
->accel
= FB_ACCEL_SIS_GLAMOUR
;
3125 fix
->reserved
[0] = ivideo
.video_size
& 0xFFFF;
3126 fix
->reserved
[1] = (ivideo
.video_size
>> 16) & 0xFFFF;
3127 fix
->reserved
[2] = caps
; /* capabilities */
3133 * Get the User Defined Part of the Display
3136 static int sisfb_get_var(struct fb_var_screeninfo
*var
, int con
,
3137 struct fb_info
*info
)
3139 DPRINTK("sisfb: sisfb_get_var:[%d]\n", con
);
3142 memcpy(var
, &default_var
, sizeof(struct fb_var_screeninfo
));
3144 *var
= fb_display
[con
].var
;
3149 * Set the User Defined Part of the Display
3152 static int sisfb_set_var(struct fb_var_screeninfo
*var
, int con
,
3153 struct fb_info
*info
)
3156 unsigned int cols
, rows
;
3158 fb_display
[con
].var
.activate
= FB_ACTIVATE_NOW
;
3161 if (do_set_var(var
, con
== currcon
, info
)) {
3162 crtc_to_var(var
); /* return current mode to user */
3166 /* get actual setting value */
3169 /* update display of current console */
3170 sisfb_set_disp(con
, var
);
3172 if (info
->changevar
)
3173 (*info
->changevar
) (con
);
3175 if ((err
= fb_alloc_cmap(&fb_display
[con
].cmap
, 0, 0)))
3178 do_install_cmap(con
, info
);
3180 /* inform console to update struct display */
3181 cols
= sisbios_mode
[mode_idx
].cols
;
3182 rows
= sisbios_mode
[mode_idx
].rows
;
3183 vc_resize_con(rows
, cols
, fb_display
[con
].conp
->vc_num
);
3193 static int sisfb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
3194 struct fb_info
*info
)
3196 DPRINTK("sisfb: sisfb_get_cmap:[%d]\n", con
);
3199 return fb_get_cmap(cmap
, kspc
, sis_getcolreg
, info
);
3200 else if (fb_display
[con
].cmap
.len
) /* non default colormap? */
3201 fb_copy_cmap(&fb_display
[con
].cmap
, cmap
, kspc
? 0 : 2);
3203 fb_copy_cmap(fb_default_cmap(video_cmap_len
), cmap
, kspc
? 0 : 2);
3212 static int sisfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
3213 struct fb_info
*info
)
3217 if (!fb_display
[con
].cmap
.len
) { /* no colormap allocated */
3218 err
= fb_alloc_cmap(&fb_display
[con
].cmap
, video_cmap_len
, 0);
3222 if (con
== currcon
) /* current console */
3223 return fb_set_cmap(cmap
, kspc
, sis_setcolreg
, info
);
3225 fb_copy_cmap(cmap
, &fb_display
[con
].cmap
, kspc
? 0 : 1);
3229 static int sisfb_ioctl(struct inode
*inode
, struct file
*file
,
3230 unsigned int cmd
, unsigned long arg
, int con
,
3231 struct fb_info
*info
)
3235 if (!capable(CAP_SYS_RAWIO
))
3237 sis_malloc((struct sis_memreq
*) arg
);
3240 if (!capable(CAP_SYS_RAWIO
))
3242 sis_free(*(unsigned long *) arg
);
3245 sis_get_glyph((struct GlyInfo
*) arg
);
3247 case FBIOGET_HWCINFO
:
3249 unsigned long *hwc_offset
= (unsigned long *) arg
;
3251 if (caps
| HW_CURSOR_CAP
)
3252 *hwc_offset
= hwcursor_vbase
-
3253 (unsigned long) ivideo
.video_vbase
;
3265 static int sisfb_mmap(struct fb_info
*info
, struct file
*file
,
3266 struct vm_area_struct
*vma
)
3268 struct fb_var_screeninfo var
;
3269 unsigned long start
;
3273 if (vma
->vm_pgoff
> (~0UL >> PAGE_SHIFT
))
3275 off
= vma
->vm_pgoff
<< PAGE_SHIFT
;
3277 /* frame buffer memory */
3278 start
= (unsigned long) ivideo
.video_base
;
3279 len
= PAGE_ALIGN((start
& ~PAGE_MASK
) + ivideo
.video_size
);
3282 /* memory mapped io */
3284 sisfb_get_var(&var
, currcon
, info
);
3285 if (var
.accel_flags
)
3287 start
= (unsigned long) ivideo
.mmio_base
;
3288 len
= PAGE_ALIGN((start
& ~PAGE_MASK
) + MMIO_SIZE
);
3292 if ((vma
->vm_end
- vma
->vm_start
+ off
) > len
)
3295 vma
->vm_pgoff
= off
>> PAGE_SHIFT
;
3297 #if defined(__i386__)
3298 if (boot_cpu_data
.x86
> 3)
3299 pgprot_val(vma
->vm_page_prot
) |= _PAGE_PCD
;
3301 if (io_remap_page_range(vma
->vm_start
, off
, vma
->vm_end
- vma
->vm_start
,
3307 static struct fb_ops sisfb_ops
= {
3309 fb_get_fix
: sisfb_get_fix
,
3310 fb_get_var
: sisfb_get_var
,
3311 fb_set_var
: sisfb_set_var
,
3312 fb_get_cmap
: sisfb_get_cmap
,
3313 fb_set_cmap
: sisfb_set_cmap
,
3314 fb_ioctl
: sisfb_ioctl
,
3315 fb_mmap
: sisfb_mmap
,
3318 int sisfb_setup(char *options
)
3322 fb_info
.fontname
[0] = '\0';
3323 ivideo
.refresh_rate
= 0;
3325 if (!options
|| !*options
)
3328 for (this_opt
= strtok(options
, ","); this_opt
;
3329 this_opt
= strtok(NULL
, ",")) {
3333 if (!strcmp(this_opt
, "inverse")) {
3336 } else if (!strncmp(this_opt
, "font:", 5)) {
3337 strcpy(fb_info
.fontname
, this_opt
+ 5);
3338 } else if (!strncmp(this_opt
, "mode:", 5)) {
3339 search_mode(this_opt
+ 5);
3340 } else if (!strncmp(this_opt
, "vrate:", 6)) {
3341 ivideo
.refresh_rate
=
3342 simple_strtoul(this_opt
+ 6, NULL
, 0);
3343 } else if (!strncmp(this_opt
, "off", 3)) {
3346 DPRINTK("invalid parameter %s\n", this_opt
);
3351 static int sisfb_update_var(int con
, struct fb_info
*info
)
3357 * Switch Console (called by fbcon.c)
3360 static int sisfb_switch(int con
, struct fb_info
*info
)
3364 DPRINTK("sisfb: switch console from [%d] to [%d]\n", currcon
, con
);
3366 /* update colormap of current console */
3367 if (fb_display
[currcon
].cmap
.len
)
3368 fb_get_cmap(&fb_display
[currcon
].cmap
, 1, sis_getcolreg
, info
);
3370 fb_display
[con
].var
.activate
= FB_ACTIVATE_NOW
;
3372 /* same mode, needn't change mode actually */
3374 if (!memcmp(&fb_display
[con
].var
, &fb_display
[currcon
].var
, sizeof(struct fb_var_screeninfo
)))
3382 do_set_var(&fb_display
[con
].var
, 1, info
);
3384 sisfb_set_disp(con
, &fb_display
[con
].var
);
3386 /* Install new colormap */
3387 do_install_cmap(con
, info
);
3389 cols
= sisbios_mode
[mode_idx
].cols
;
3390 rows
= sisbios_mode
[mode_idx
].rows
;
3391 vc_resize_con(rows
, cols
, fb_display
[con
].conp
->vc_num
);
3393 sisfb_update_var(con
, info
);
3399 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
3401 static void sisfb_blank(int blank
, struct fb_info
*info
)
3405 vgawb(CRTC_ADR
, 0x17);
3406 CRData
= vgarb(CRTC_DATA
);
3408 if (blank
> 0) /* turn off CRT1 */
3410 else /* turn on CRT1 */
3413 vgawb(CRTC_ADR
, 0x17);
3414 vgawb(CRTC_DATA
, CRData
);
3417 int __init
sisfb_init(void)
3419 struct pci_dev
*pdev
= NULL
;
3422 unsigned char jTemp
;
3430 pci_for_each_dev(pdev
) {
3431 for (b
= dev_list
; b
->vendor
; b
++)
3433 if ((b
->vendor
== pdev
->vendor
)
3434 && (b
->device
== pdev
->device
))
3437 strcpy(fb_info
.modename
, b
->name
);
3438 ivideo
.chip_id
= pdev
->device
;
3450 #ifdef CONFIG_FB_SIS_LINUXBIOS
3451 pci_read_config_dword(pdev
, PCI_COMMAND
, &cmd
);
3452 cmd
|= PCI_COMMAND_IO
;
3453 cmd
|= PCI_COMMAND_MEMORY
;
3454 pci_write_config_dword(pdev
, PCI_COMMAND
, cmd
);
3457 ivideo
.video_base
= pci_resource_start(pdev
, 0);
3458 if (!request_mem_region(ivideo
.video_base
, pci_resource_len(pdev
, 0),
3460 printk(KERN_ERR
"sisfb: cannot reserve frame buffer memory\n");
3463 ivideo
.mmio_base
= pci_resource_start(pdev
, 1);
3464 if (!request_mem_region(ivideo
.mmio_base
, pci_resource_len(pdev
, 1),
3466 printk(KERN_ERR
"sisfb: cannot reserve MMIO region\n");
3467 release_mem_region(pci_resource_start(pdev
, 1),
3468 pci_resource_len(pdev
, 1));
3471 ivideo
.vga_base
= pci_resource_start(pdev
, 2);
3472 if (!request_region(ivideo
.vga_base
, pci_resource_len(pdev
, 2),
3474 printk(KERN_ERR
"sisfb: cannot reserve I/O ports\n");
3475 release_mem_region(pci_resource_start(pdev
, 1),
3476 pci_resource_len(pdev
, 1));
3477 release_mem_region(pci_resource_start(pdev
, 0),
3478 pci_resource_len(pdev
, 0));
3481 ivideo
.vga_base
+= 0x30;
3483 #ifndef CONFIG_FB_SIS_LINUXBIOS
3484 rom_base
= 0x000C0000;
3485 request_region(rom_base
, 32, "sisfb");
3491 vgawb(SEQ_ADR
, IND_SIS_PASSWORD
);
3492 vgawb(SEQ_DATA
, SIS_PASSWORD
);
3494 /* Enable MMIO & PCI linear address */
3495 vgawb(SEQ_ADR
, IND_SIS_PCI_ADDRESS_SET
);
3496 jTemp
= vgarb(SEQ_DATA
);
3497 jTemp
|= SIS_PCI_ADDR_ENABLE
;
3498 jTemp
|= SIS_MEM_MAP_IO_ENABLE
;
3499 vgawb(SEQ_DATA
, jTemp
);
3501 /* get video ram size by SR14 */
3502 vgawb(SEQ_ADR
, IND_SIS_DRAM_SIZE
);
3503 ivideo
.video_size
= ((int) ((vgarb(SEQ_DATA
) & 0x3f) + 1) << 20);
3506 mode_idx
= DEFAULT_MODE
; /* 0:640x480x8 */
3508 #ifdef CONFIG_FB_SIS_LINUXBIOS
3509 mode_idx
= DEFAULT_MODE
;
3510 rate_idx
= sisbios_mode
[mode_idx
].rate_idx
;
3511 /* set to default refresh rate 60MHz */
3512 ivideo
.refresh_rate
= 60;
3515 mode_no
= sisbios_mode
[mode_idx
].mode_no
;
3517 if (ivideo
.refresh_rate
!= 0)
3518 search_refresh_rate(ivideo
.refresh_rate
);
3520 if (rate_idx
== 0) {
3521 rate_idx
= sisbios_mode
[mode_idx
].rate_idx
;
3522 /* set to default refresh rate 60MHz */
3523 ivideo
.refresh_rate
= 60;
3526 ivideo
.video_bpp
= sisbios_mode
[mode_idx
].bpp
;
3527 ivideo
.video_width
= sisbios_mode
[mode_idx
].xres
;
3528 ivideo
.video_height
= sisbios_mode
[mode_idx
].yres
;
3529 video_linelength
= ivideo
.video_width
* (ivideo
.video_bpp
>> 3);
3531 ivideo
.video_vbase
= ioremap(ivideo
.video_base
, ivideo
.video_size
);
3532 ivideo
.mmio_vbase
= ioremap(ivideo
.mmio_base
, MMIO_SIZE
);
3534 #ifndef CONFIG_FB_SIS_LINUXBIOS
3535 rom_vbase
= (unsigned long) ioremap(rom_base
, MAX_ROM_SCAN
);
3541 "sisfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3542 ivideo
.video_base
, ivideo
.video_vbase
,
3543 ivideo
.video_size
/ 1024);
3544 printk(KERN_INFO
"sisfb: mode is %dx%dx%d, linelength=%d\n",
3545 ivideo
.video_width
, ivideo
.video_height
, ivideo
.video_bpp
,
3548 /* enable 2D engine */
3549 vgawb(SEQ_ADR
, IND_SIS_MODULE_ENABLE
);
3550 jTemp
= vgarb(SEQ_DATA
);
3551 jTemp
|= SIS_2D_ENABLE
;
3552 vgawb(SEQ_DATA
, jTemp
);
3556 if (SiSSetMode(mode_no
)) {
3557 DPRINTK("sisfb: set mode[0x%x]: failed\n", 0x30);
3563 crtc_to_var(&default_var
);
3565 fb_info
.changevar
= NULL
;
3567 fb_info
.fbops
= &sisfb_ops
;
3568 fb_info
.disp
= &disp
;
3569 fb_info
.switch_con
= &sisfb_switch
;
3570 fb_info
.updatevar
= &sisfb_update_var
;
3571 fb_info
.blank
= &sisfb_blank
;
3572 fb_info
.flags
= FBINFO_FLAG_DEFAULT
;
3574 sisfb_set_disp(-1, &default_var
);
3576 if (sisfb_heap_init()) {
3577 DPRINTK("sisfb: Failed to enable offscreen heap\n");
3580 /* to avoid the inversed bgcolor bug of the initial state */
3581 vc_resize_con(1, 1, 0);
3583 if (register_framebuffer(&fb_info
) < 0)
3586 ivideo
.status
= CRT1
;
3588 printk(KERN_INFO
"fb%d: %s frame buffer device\n",
3589 GET_FB_IDX(fb_info
.node
), fb_info
.modename
);
3596 static char *mode
= NULL
;
3597 static unsigned int rate
= 0;
3599 MODULE_PARM(mode
, "s");
3600 MODULE_PARM(rate
, "i");
3602 int init_module(void)
3607 ivideo
.refresh_rate
= rate
;
3614 void cleanup_module(void)
3616 unregister_framebuffer(&fb_info
);
3621 EXPORT_SYMBOL(sis_malloc
);
3622 EXPORT_SYMBOL(sis_free
);
3624 EXPORT_SYMBOL(ivideo
);