2 * linux/drivers/video/rivafb.c - nVidia RIVA 128/TNT/TNT2 fb driver
4 * Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com>
8 * ani joshi: Lots of debugging and cleanup work, really helped
11 * Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven
12 * Includes riva_hw.c from nVidia, see copyright below.
13 * KGI code provided the basis for state storage, init, and mode switching.
15 * This file is subject to the terms and conditions of the GNU General Public
16 * License. See the file COPYING in the main directory of this archive
20 /* version number of this driver */
21 #define RIVAFB_VERSION "0.6.5"
23 #include <linux/config.h>
24 #include <linux/module.h>
25 #include <linux/kernel.h>
26 #include <linux/errno.h>
27 #include <linux/string.h>
29 #include <linux/selection.h>
30 #include <linux/tty.h>
31 #include <linux/malloc.h>
32 #include <linux/delay.h>
34 #include <linux/init.h>
35 #include <linux/pci.h>
37 #include <video/fbcon.h>
43 #include <video/fbcon-cfb4.h>
44 #include <video/fbcon-cfb8.h>
45 #include <video/fbcon-cfb16.h>
46 #include <video/fbcon-cfb32.h>
48 #ifndef CONFIG_PCI /* sanity check */
49 #error This driver requires PCI support.
52 /*****************************************************************
54 * various helpful macros and constants
58 /* #define RIVAFBDEBUG */
60 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
62 #define DPRINTK(fmt, args...)
66 #define assert(expr) \
68 printk( "Assertion failed! %s,%s,%s,line=%d\n",\
69 #expr,__FILE__,__FUNCTION__,__LINE__); \
76 /* GGI compatibility macros */
79 #define FatalError panic
80 #define NUM_SEQ_REGS 0x05
81 #define NUM_CRT_REGS 0x41
82 #define NUM_GRC_REGS 0x09
83 #define NUM_ATC_REGS 0x15
85 /* max number of VGA controllers we scan for */
86 #define RIVA_MAX_VGA_CONTROLLERS 8
88 #define PFX "rivafb: "
90 #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
92 /* macro that allows you to set overflow bits */
93 #define SetBitField(value,from,to) SetBF(to,GetBF(value,from))
94 #define SetBit(n) (1<<(n))
95 #define Set8Bits(value) ((value)&0xff)
97 struct riva_chip_info
{
100 unsigned short vendor
;
101 unsigned short device
;
105 static const struct riva_chip_info riva_pci_probe_list
[] =
107 {"RIVA-128", 3, PCI_VENDOR_ID_NVIDIA_SGS
, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128
},
108 {"RIVA-TNT", 4, PCI_VENDOR_ID_NVIDIA
, PCI_DEVICE_ID_NVIDIA_TNT
},
109 {"RIVA-TNT2", 5, PCI_VENDOR_ID_NVIDIA
, PCI_DEVICE_ID_NVIDIA_TNT2
},
110 {"RIVA-TNT2", 5, PCI_VENDOR_ID_NVIDIA
, PCI_DEVICE_ID_NVIDIA_UTNT2
},
111 {"RIVA-TNT2", 5, PCI_VENDOR_ID_NVIDIA
, PCI_DEVICE_ID_NVIDIA_VTNT2
},
112 {"RIVA-TNT2", 5, PCI_VENDOR_ID_NVIDIA
, PCI_DEVICE_ID_NVIDIA_ITNT2
},
117 /* holds the state of the VGA core and extended Riva hw state from riva_hw.c.
118 * From KGI originally. */
130 * describes the state of a Riva board
133 struct riva_regs state
; /* state of hw board */
134 __u32 visual
; /* FB_VISUAL_xxx */
135 unsigned depth
; /* bpp of current mode */
139 unsigned char red
, green
, blue
, transp
;
146 struct fb_info info
; /* kernel framebuffer info */
148 RIVA_HW_INST riva
; /* interface to riva_hw.c */
150 const char *drvr_name
; /* Riva hardware board type */
152 unsigned long ctrl_base_phys
; /* physical control register base addr */
153 unsigned long fb_base_phys
; /* physical framebuffer base addr */
155 caddr_t ctrl_base
; /* virtual control register base addr */
156 caddr_t fb_base
; /* virtual framebuffer base addr */
158 unsigned ram_amount
; /* amount of RAM on card, in megabytes */
159 unsigned dclk_max
; /* max DCLK */
161 struct riva_regs initial_state
; /* initial startup video mode */
165 struct display
*currcon_display
;
167 struct rivafb_info
*next
;
169 struct pci_dev
*pd
; /* pointer to board's pci info */
170 unsigned base0_region_size
; /* size of control register region */
171 unsigned base1_region_size
; /* size of framebuffer region */
173 #ifdef FBCON_HAS_CFB8
174 riva_cfb8_cmap_t palette
[256]; /* VGA DAC palette cache */
177 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
179 #ifdef FBCON_HAS_CFB16
182 #ifdef FBCON_HAS_CFB32
186 #endif /* FBCON_HAS_CFB16 | FBCON_HAS_CFB32 */
189 /* ------------------- global variables ------------------------ */
192 static struct rivafb_info
*riva_boards
= NULL
;
194 /* command line data, set in rivafb_setup() */
195 static char fontname
[40] __initdata
= { 0 };
196 static char noaccel __initdata
= 0; /* unused */
198 static const char *mode_option __initdata
= NULL
;
202 /* ------------------- prototypes ------------------------------ */
204 int rivafb_open (struct fb_info
*info
, int user
);
205 int rivafb_release (struct fb_info
*info
, int user
);
206 int rivafb_get_fix (struct fb_fix_screeninfo
*fix
, int con
,
207 struct fb_info
*info
);
208 int rivafb_get_var (struct fb_var_screeninfo
*var
, int con
,
209 struct fb_info
*info
);
210 int rivafb_set_var (struct fb_var_screeninfo
*var
, int con
,
211 struct fb_info
*info
);
212 int rivafb_get_cmap (struct fb_cmap
*cmap
, int kspc
, int con
,
213 struct fb_info
*info
);
214 int rivafb_set_cmap (struct fb_cmap
*cmap
, int kspc
, int con
,
215 struct fb_info
*info
);
216 int rivafb_pan_display (struct fb_var_screeninfo
*var
, int con
,
217 struct fb_info
*info
);
218 int rivafb_ioctl (struct inode
*inode
, struct file
*file
, unsigned int cmd
,
219 unsigned long arg
, int con
, struct fb_info
*info
);
220 int rivafb_switch(int con
, struct fb_info
*info
);
221 void rivafb_blank (int blank
, struct fb_info
*info
);
223 static void riva_load_video_mode (struct rivafb_info
*rivainfo
,
224 struct fb_var_screeninfo
*video_mode
);
225 static int riva_getcolreg (unsigned regno
, unsigned *red
, unsigned *green
,
226 unsigned *blue
, unsigned *transp
,
227 struct fb_info
*info
);
228 static int riva_setcolreg (unsigned regno
, unsigned red
, unsigned green
,
229 unsigned blue
, unsigned transp
,
230 struct fb_info
*info
);
231 static int riva_get_cmap_len(const struct fb_var_screeninfo
*var
);
233 static u32
riva_pci_region_size (struct pci_dev
*pd
, unsigned baseaddr
);
235 static void riva_pci_iounmap (struct rivafb_info
*rinfo
);
236 static int riva_pci_register (struct pci_dev
*pd
, const struct riva_chip_info
*rci
);
237 static int riva_pci_register_devices (void);
238 static int riva_set_fbinfo (struct rivafb_info
*rinfo
);
241 void riva_save_state(struct rivafb_info
*rinfo
, struct riva_regs
*regs
);
243 void riva_load_state(struct rivafb_info
*rinfo
, struct riva_regs
*regs
);
245 struct rivafb_info
*riva_board_list_add(struct rivafb_info
*board_list
,
246 struct rivafb_info
*new_node
);
249 static void riva_pci_region_init (struct pci_dev
*pd
, struct rivafb_info
*rinfo
);
252 static void riva_wclut (unsigned char regnum
, unsigned char red
,
253 unsigned char green
, unsigned char blue
);
258 /* kernel interface */
259 static struct fb_ops riva_fb_ops
=
276 static const struct riva_regs reg_template
=
278 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ATTR */
279 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
280 0x41, 0x01, 0x0F, 0x13, 0x00 },
281 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* CRT */
282 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, /* 0x10 */
284 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */
286 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30 */
288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, /* GRA */
293 { 0x03, 0x01, 0x0F, 0x00, 0x0E}, /* SEQ */
299 /* ------------------- general utility functions -------------------------- */
303 * @rivainfo: pointer to internal driver struct for a given Riva card
306 * Sets up console Low level operations depending on the current? color depth
310 void riva_set_dispsw (struct rivafb_info
*rinfo
)
312 struct display
*disp
= &rinfo
->disp
;
316 assert (rinfo
!= NULL
);
318 disp
->dispsw_data
= NULL
;
320 switch (disp
->var
.bits_per_pixel
) {
323 disp
->dispsw
= &fbcon_mfb
;
326 #ifdef FBCON_HAS_CFB4
328 disp
->dispsw
= &fbcon_cfb4
;
331 #ifdef FBCON_HAS_CFB8
333 disp
->dispsw
= &fbcon_cfb8
;
336 #ifdef FBCON_HAS_CFB16
339 disp
->dispsw
= &fbcon_cfb16
;
340 disp
->dispsw_data
= &rinfo
->con_cmap
.cfb16
;
343 #ifdef FBCON_HAS_CFB24
345 disp
->dispsw
= &fbcon_cfb24
;
346 disp
->dispsw_data
= rinfo
->con_cmap
.cfb24
;
349 #ifdef FBCON_HAS_CFB32
351 disp
->dispsw
= &fbcon_cfb32
;
352 disp
->dispsw_data
= rinfo
->con_cmap
.cfb32
;
356 DPRINTK ("Setting fbcon_dummy renderer\n");
357 disp
->dispsw
= &fbcon_dummy
;
366 static int riva_init_disp_var (struct rivafb_info
*rinfo
)
369 fb_find_mode(&rinfo
->disp
.var
, &rinfo
->info
, mode_option
,
372 fb_find_mode(&rinfo
->disp
.var
, &rinfo
->info
,
373 "640x480-8@60", NULL
, 0, NULL
, 8);
380 static int __init
riva_init_disp (struct rivafb_info
*rinfo
)
382 struct fb_info
*info
;
383 struct display
*disp
;
387 assert (rinfo
!= NULL
);
394 #warning FIXME: assure that disp->cmap is completely filled out
396 disp
->screen_base
= rinfo
->fb_base
;
397 disp
->visual
= FB_VISUAL_PSEUDOCOLOR
;
398 disp
->type
= FB_TYPE_PACKED_PIXELS
;
402 disp
->next_line
= disp
->line_length
=
403 (disp
->var
.xres_virtual
* disp
->var
.bits_per_pixel
) >> 3;
404 disp
->can_soft_blank
= 1;
407 riva_set_dispsw(rinfo
);
409 rinfo
->currcon_display
= disp
;
411 if ((riva_init_disp_var (rinfo
)) < 0) { /* must be done last */
412 DPRINTK("EXIT, returning -1\n");
416 DPRINTK("EXIT, returning 0\n");
423 static int __init
riva_set_fbinfo (struct rivafb_info
*rinfo
)
425 struct fb_info
*info
;
427 assert (rinfo
!= NULL
);
431 strcpy (info
->modename
, rinfo
->drvr_name
);
433 info
->flags
= FBINFO_FLAG_DEFAULT
;
434 info
->fbops
= &riva_fb_ops
;
436 #warning FIXME: set monspecs to what???
438 info
->display_fg
= NULL
; /* FIXME: correct? */
439 strncpy (info
->fontname
, fontname
, sizeof (info
->fontname
));
440 info
->fontname
[sizeof (info
->fontname
) - 1] = 0;
442 info
->changevar
= NULL
; /* FIXME: needed? */
443 info
->switch_con
= rivafb_switch
;
444 info
->updatevar
= NULL
; /* FIXME? */
445 info
->blank
= rivafb_blank
;
447 if (riva_init_disp (rinfo
) < 0) /* must be done last */
456 /* ----------------------------- PCI bus ----------------------------- */
462 * riva_pci_region_size
463 * @pd: pointer to PCI device to be configured
466 * Obtains from the PCI bus the size of the address space allocated to
467 * the given card's base address zero region.
471 u32
riva_pci_region_size (struct pci_dev
*pd
, unsigned baseaddr
)
473 return pd
->resource
[baseaddr
].end
- pd
->resource
[baseaddr
].start
+ 1;
489 void riva_pci_region_init (struct pci_dev
*pd
, struct rivafb_info
*rinfo
)
493 assert (rinfo
!= NULL
);
497 rinfo
->base0_region_size
= riva_pci_region_size (pd
, PCI_BASE_ADDRESS_0
);
498 assert(rinfo
->base0_region_size
>= 0x00800000); /* from GGI */
499 rinfo
->base1_region_size
= riva_pci_region_size (pd
, PCI_BASE_ADDRESS_1
);
500 assert(rinfo
->base0_region_size
>= 0x01000000); /* from GGI */
502 /* Get the base addresses */
503 pcibios_read_config_dword(0, rinfo
->pd
->devfn
, PCI_BASE_ADDRESS_0
,
504 (unsigned int*)&addr
);
506 /* This function should return an int. */
511 rinfo
->ctrl_base_phys
= addr
& PCI_BASE_ADDRESS_MEM_MASK
;
513 pcibios_read_config_dword(0, rinfo
->pd
->devfn
, PCI_BASE_ADDRESS_1
,
514 (unsigned int*)&addr
);
516 rinfo
->fb_base_phys
= addr
& PCI_BASE_ADDRESS_MEM_MASK
;
518 rinfo
->ctrl_base
= ioremap (rinfo
->ctrl_base_phys
, rinfo
->base0_region_size
);
519 assert (rinfo
->ctrl_base
!= NULL
);
520 rinfo
->fb_base
= ioremap (rinfo
->fb_base_phys
, rinfo
->base1_region_size
);
521 assert (rinfo
->fb_base
!= NULL
);
523 rinfo
->riva
.EnableIRQ
= 0;
524 rinfo
->riva
.IO
= (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
525 rinfo
->riva
.PRAMDAC
= (unsigned *)(rinfo
->ctrl_base
+0x00680000);
526 rinfo
->riva
.PFB
= (unsigned *)(rinfo
->ctrl_base
+0x00100000);
527 rinfo
->riva
.PFIFO
= (unsigned *)(rinfo
->ctrl_base
+0x00002000);
528 rinfo
->riva
.PGRAPH
= (unsigned *)(rinfo
->ctrl_base
+0x00400000);
529 rinfo
->riva
.PEXTDEV
= (unsigned *)(rinfo
->ctrl_base
+0x00101000);
530 rinfo
->riva
.PTIMER
= (unsigned *)(rinfo
->ctrl_base
+0x00009000);
531 rinfo
->riva
.PMC
= (unsigned *)(rinfo
->ctrl_base
+0x00000000);
532 rinfo
->riva
.FIFO
= (unsigned *)(rinfo
->ctrl_base
+0x00800000);
534 switch (rinfo
->riva
.Architecture
)
537 rinfo
->riva
.PRAMIN
= (unsigned *)(rinfo
->ctrl_base
+0x00C00000);
541 rinfo
->riva
.PCRTC
= (unsigned *)(rinfo
->ctrl_base
+0x00600000);
542 rinfo
->riva
.PRAMIN
= (unsigned *)(rinfo
->ctrl_base
+0x00710000);
559 void riva_pci_iounmap (struct rivafb_info
*rinfo
)
561 assert (rinfo
!= NULL
);
562 assert (rinfo
->ctrl_base_phys
!= 0x00000000);
563 assert (rinfo
->ctrl_base
!= NULL
);
564 assert (rinfo
->fb_base_phys
!= 0x00000000);
565 assert (rinfo
->fb_base
!= NULL
);
567 iounmap (rinfo
->ctrl_base
);
568 iounmap (rinfo
->fb_base
);
575 static void __init
riva_init_clut (struct rivafb_info
*fb_info
)
579 for (j
= 0; j
< 256; j
++) {
582 fb_info
->palette
[j
].red
= default_red
[k
];
583 fb_info
->palette
[j
].green
= default_grn
[k
];
584 fb_info
->palette
[j
].blue
= default_blu
[k
];
586 fb_info
->palette
[j
].red
=
587 fb_info
->palette
[j
].green
=
588 fb_info
->palette
[j
].blue
= j
;
592 fb_info
->palette
[j
].red
,
593 fb_info
->palette
[j
].green
,
594 fb_info
->palette
[j
].blue
);
600 static int __init
riva_pci_register (struct pci_dev
*pd
,
601 const struct riva_chip_info
*rci
)
603 struct rivafb_info
*rinfo
;
606 assert (rci
!= NULL
);
608 rinfo
= kmalloc (sizeof (struct rivafb_info
), GFP_KERNEL
);
609 assert (rinfo
!= NULL
);
610 memset (rinfo
, 0, sizeof (struct rivafb_info
));
612 rinfo
->drvr_name
= rci
->name
;
613 rinfo
->riva
.Architecture
= rci
->arch_rev
;
616 rinfo
->base0_region_size
= riva_pci_region_size (pd
, 0);
617 rinfo
->base1_region_size
= riva_pci_region_size (pd
, 1);
619 assert(rinfo
->base0_region_size
>= 0x00800000); /* from GGI */
620 assert(rinfo
->base0_region_size
>= 0x01000000); /* from GGI */
622 rinfo
->ctrl_base_phys
= rinfo
->pd
->resource
[0].start
;
623 rinfo
->fb_base_phys
= rinfo
->pd
->resource
[1].start
;
625 request_region(0x3C0, 32, "rivafb");
627 if (!request_mem_region(rinfo
->ctrl_base_phys
,
628 rinfo
->base0_region_size
, "rivafb") ||
629 !request_mem_region(rinfo
->fb_base_phys
, rinfo
->base1_region_size
,
631 printk (KERN_ERR PFX
"cannot reserve MMIO region\n");
635 rinfo
->ctrl_base
= ioremap (rinfo
->ctrl_base_phys
,
636 rinfo
->base0_region_size
);
637 assert (rinfo
->ctrl_base
!= NULL
);
639 rinfo
->fb_base
= ioremap (rinfo
->fb_base_phys
,
640 rinfo
->base1_region_size
);
641 assert (rinfo
->fb_base
!= NULL
);
643 rinfo
->riva
.EnableIRQ
= 0;
644 rinfo
->riva
.IO
= (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
645 rinfo
->riva
.PRAMDAC
= (unsigned *)(rinfo
->ctrl_base
+0x00680000);
646 rinfo
->riva
.PFB
= (unsigned *)(rinfo
->ctrl_base
+0x00100000);
647 rinfo
->riva
.PFIFO
= (unsigned *)(rinfo
->ctrl_base
+0x00002000);
648 rinfo
->riva
.PGRAPH
= (unsigned *)(rinfo
->ctrl_base
+0x00400000);
649 rinfo
->riva
.PEXTDEV
= (unsigned *)(rinfo
->ctrl_base
+0x00101000);
650 rinfo
->riva
.PTIMER
= (unsigned *)(rinfo
->ctrl_base
+0x00009000);
651 rinfo
->riva
.PMC
= (unsigned *)(rinfo
->ctrl_base
+0x00000000);
652 rinfo
->riva
.FIFO
= (unsigned *)(rinfo
->ctrl_base
+0x00800000);
654 switch (rinfo
->riva
.Architecture
)
657 rinfo
->riva
.PRAMIN
= (unsigned *)(rinfo
->ctrl_base
+0x00C00000);
661 rinfo
->riva
.PCRTC
= (unsigned *)(rinfo
->ctrl_base
+0x00600000);
662 rinfo
->riva
.PRAMIN
= (unsigned *)(rinfo
->ctrl_base
+0x00710000);
666 RivaGetConfig(&rinfo
->riva
);
670 assert (rinfo
->pd
!= NULL
);
673 vga_io_wcrt (0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */
674 outb(rinfo
->riva
.LockUnlockIO
, rinfo
->riva
.LockUnlockIndex
);
675 outb(rinfo
->riva
.LockUnlockIO
+ 1, 0x57);
677 memcpy (&rinfo
->initial_state
, ®_template
, sizeof (reg_template
));
678 riva_save_state (rinfo
, &rinfo
->initial_state
);
680 rinfo
->ram_amount
= rinfo
->riva
.RamAmountKBytes
* 1024;
681 rinfo
->dclk_max
= rinfo
->riva
.MaxVClockFreqKHz
* 1000;
683 riva_set_fbinfo (rinfo
);
685 riva_init_clut (rinfo
);
687 riva_load_video_mode (rinfo
, &rinfo
->disp
.var
);
689 if (register_framebuffer ((struct fb_info
*) rinfo
) < 0) {
690 printk(KERN_ERR PFX
"error registering riva framebuffer\n");
695 riva_boards
= riva_board_list_add (riva_boards
, rinfo
);
697 printk("PCI Riva NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
698 rinfo
->riva
.Architecture
,
701 rinfo
->ram_amount
/ (1024 * 1024),
702 rinfo
->fb_base_phys
);
710 static int __init
riva_pci_register_devices (void)
713 const struct riva_chip_info
*nci
= &riva_pci_probe_list
[0];
715 assert (nci
!= NULL
);
716 while (nci
->name
!= NULL
) {
717 pd
= pci_find_device (nci
->vendor
, nci
->device
, NULL
);
719 if (riva_pci_register (pd
, nci
) < 0)
722 pd
= pci_find_device (nci
->vendor
, nci
->device
, pd
);
733 /*** riva_wclut - set CLUT entry ***/
734 static void riva_wclut (unsigned char regnum
, unsigned char red
,
735 unsigned char green
, unsigned char blue
)
737 unsigned int data
= VGA_PEL_D
;
739 /* address write mode register is not translated.. */
740 vga_io_w (VGA_PEL_IW
, regnum
);
742 vga_io_w (data
, red
);
743 vga_io_w (data
, green
);
744 vga_io_w (data
, blue
);
749 /* ------------ Hardware Independent Functions ------------ */
751 int __init
rivafb_setup(char *options
)
755 if (!options
|| !*options
)
758 for (this_opt
= strtok(options
, ","); this_opt
;
759 this_opt
= strtok(NULL
, ",")) {
760 if (!strncmp(this_opt
, "font:", 5)) {
765 for (i
= 0; i
< sizeof(fontname
) - 1; i
++)
766 if (!*p
|| *p
== ' ' || *p
== ',')
768 memcpy(fontname
, this_opt
+ 5, i
);
772 else if (!strncmp(this_opt
, "noaccel", 7)) {
777 mode_option
= this_opt
;
786 int __init
rivafb_init (void)
788 if (riva_pci_register_devices () < 0)
791 if (riva_boards
== NULL
)
798 /* ------------------------------------------------------------------------- */
803 void __exit
rivafb_cleanup (struct fb_info
*info
)
805 #warning FIXME: is this all we need to do?
807 struct rivafb_info
*tmp
, *board
= riva_boards
;
809 while (board
!= NULL
) {
810 riva_load_state (board
, &board
->initial_state
);
811 riva_pci_iounmap (board
);
813 unregister_framebuffer ((struct fb_info
*) board
);
818 kfree_s (tmp
, sizeof (struct rivafb_info
));
821 (void) info
; /* unused function arg */
828 * Frame buffer operations
831 int rivafb_open(struct fb_info
*info
, int user
)
833 /* Nothing, only a usage count for the moment */
838 int rivafb_release(struct fb_info
*info
, int user
)
854 int rivafb_get_fix (struct fb_fix_screeninfo
*fix
, int con
,
855 struct fb_info
*info
)
857 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
862 assert (fix
!= NULL
);
863 assert (info
!= NULL
);
864 assert (rivainfo
->drvr_name
&& rivainfo
->drvr_name
[0]);
865 assert (rivainfo
->fb_base_phys
> 0);
866 assert (rivainfo
->ram_amount
> 0);
868 p
= (con
< 0) ? rivainfo
->info
.disp
: &fb_display
[con
];
870 memset (fix
, 0, sizeof (struct fb_fix_screeninfo
));
871 sprintf (fix
->id
, "Riva %s", rivainfo
->drvr_name
);
873 fix
->smem_start
= rivainfo
->fb_base_phys
;
874 fix
->smem_len
= rivainfo
->ram_amount
;
877 fix
->type_aux
= p
->type_aux
;
878 fix
->visual
= p
->visual
;
882 fix
->ywrapstep
= 0; /* FIXME: no ywrap for now */
884 fix
->line_length
= p
->line_length
;
886 #warning FIXME: set up MMIO region
890 #warning FIXME: reference riva acceleration fb.h constant here
891 fix
->accel
= FB_ACCEL_NONE
;
893 DPRINTK ("EXIT, returning 0\n");
909 int rivafb_get_var (struct fb_var_screeninfo
*var
, int con
,
910 struct fb_info
*info
)
912 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
916 assert (info
!= NULL
);
917 assert (var
!= NULL
);
919 *var
= (con
< 0) ? rivainfo
->disp
.var
: fb_display
[con
].var
;
921 DPRINTK ("EXIT, returning 0\n");
937 int rivafb_set_var (struct fb_var_screeninfo
*var
, int con
,
938 struct fb_info
*info
)
940 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
942 struct fb_var_screeninfo v
;
943 int nom
, den
; /* translating from pixels->bytes */
959 assert (info
!= NULL
);
960 assert (var
!= NULL
);
962 DPRINTK ("Requested: %dx%dx%d\n", var
->xres
, var
->yres
, var
->bits_per_pixel
);
963 DPRINTK (" virtual: %dx%d\n", var
->xres_virtual
, var
->yres_virtual
);
964 DPRINTK (" offset: (%d,%d)\n", var
->xoffset
, var
->yoffset
);
965 DPRINTK ("grayscale: %d\n", var
->grayscale
);
967 dsp
= (con
< 0) ? rivainfo
->info
.disp
: &fb_display
[con
];
968 assert (dsp
!= NULL
);
970 /* if var has changed, we should call changevar() later */
972 chgvar
= ((dsp
->var
.xres
!= var
->xres
) ||
973 (dsp
->var
.yres
!= var
->yres
) ||
974 (dsp
->var
.xres_virtual
!= var
->xres_virtual
) ||
975 (dsp
->var
.yres_virtual
!= var
->yres_virtual
) ||
976 (dsp
->var
.bits_per_pixel
!= var
->bits_per_pixel
) ||
977 memcmp(&dsp
->var
.red
, &var
->red
, sizeof(var
->red
)) ||
978 memcmp(&dsp
->var
.green
, &var
->green
, sizeof(var
->green
)) ||
979 memcmp(&dsp
->var
.blue
, &var
->blue
, sizeof(var
->blue
)));
982 memcpy (&v
, var
, sizeof (v
));
984 switch (v
.bits_per_pixel
) {
987 dsp
->dispsw
= &fbcon_mfb
;
988 dsp
->line_length
= v
.xres_virtual
/ 8;
989 dsp
->visual
= FB_VISUAL_MONO10
;
995 #ifdef FBCON_HAS_CFB8
997 v
.bits_per_pixel
= 8;
998 dsp
->dispsw
= &fbcon_cfb8
;
1001 dsp
->line_length
= v
.xres_virtual
;
1002 dsp
->visual
= FB_VISUAL_PSEUDOCOLOR
;
1012 #ifdef FBCON_HAS_CFB16
1014 v
.bits_per_pixel
= 16;
1015 dsp
->dispsw
= &fbcon_cfb16
;
1016 dsp
->dispsw_data
= &rivainfo
->con_cmap
.cfb16
;
1019 dsp
->line_length
= v
.xres_virtual
* 2;
1020 dsp
->visual
= FB_VISUAL_DIRECTCOLOR
;
1023 v
.green
.offset
= -3;
1036 #ifdef FBCON_HAS_CFB32
1038 v
.bits_per_pixel
= 32;
1039 dsp
->dispsw
= &fbcon_cfb32
;
1040 dsp
->dispsw_data
= rivainfo
->con_cmap
.cfb32
;
1043 dsp
->line_length
= v
.xres_virtual
* 4;
1044 dsp
->visual
= FB_VISUAL_DIRECTCOLOR
;
1047 v
.green
.offset
= 16;
1061 printk (KERN_ERR PFX
"mode %dx%dx%d rejected...color depth not supported.\n",
1062 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1063 DPRINTK ("EXIT, returning -EINVAL\n");
1067 if (v
.xres
* nom
/ den
* v
.yres
> rivainfo
->ram_amount
) {
1068 printk (KERN_ERR PFX
"mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
1069 var
->xres
, var
->yres
, var
->bits_per_pixel
);
1070 DPRINTK ("EXIT - EINVAL error\n");
1074 /* use highest possible virtual resolution */
1075 if (v
.xres_virtual
== -1 &&
1076 v
.yres_virtual
== -1) {
1077 printk (KERN_WARNING PFX
"using maximum available virtual resolution\n");
1078 for (i
= 0; modes
[i
].xres
!= -1; i
++) {
1079 if (modes
[i
].xres
* nom
/ den
* modes
[i
].yres
< rivainfo
->ram_amount
/ 2)
1082 if (modes
[i
].xres
== -1) {
1083 printk (KERN_ERR PFX
"could not find a virtual resolution that fits into video memory!!\n");
1084 DPRINTK ("EXIT - EINVAL error\n");
1087 v
.xres_virtual
= modes
[i
].xres
;
1088 v
.yres_virtual
= modes
[i
].yres
;
1090 printk (KERN_INFO PFX
"virtual resolution set to maximum of %dx%d\n",
1091 v
.xres_virtual
, v
.yres_virtual
);
1092 } else if (v
.xres_virtual
== -1) {
1093 /* FIXME: maximize X virtual resolution only */
1094 } else if (v
.yres_virtual
== -1) {
1095 /* FIXME: maximize Y virtual resolution only */
1103 /* truncate xoffset and yoffset to maximum if too high */
1104 if (v
.xoffset
> v
.xres_virtual
- v
.xres
)
1105 v
.xoffset
= v
.xres_virtual
- v
.xres
- 1;
1107 if (v
.yoffset
> v
.yres_virtual
- v
.yres
)
1108 v
.yoffset
= v
.yres_virtual
- v
.yres
- 1;
1115 v
.transp
.msb_right
= 0;
1117 switch (v
.activate
& FB_ACTIVATE_MASK
) {
1118 case FB_ACTIVATE_TEST
:
1119 DPRINTK ("EXIT - FB_ACTIVATE_TEST\n");
1121 case FB_ACTIVATE_NXTOPEN
: /* ?? */
1122 case FB_ACTIVATE_NOW
:
1123 break; /* continue */
1125 DPRINTK ("EXIT - unknown activation type\n");
1126 return -EINVAL
; /* unknown */
1129 dsp
->type
= FB_TYPE_PACKED_PIXELS
;
1131 #warning FIXME: verify that the above code sets dsp->* fields correctly
1133 memcpy (&dsp
->var
, &v
, sizeof (v
));
1135 riva_load_video_mode (rivainfo
, &v
);
1137 if (chgvar
&& info
&& info
->changevar
)
1138 info
->changevar (con
);
1140 DPRINTK ("EXIT, returning 0\n");
1156 * Copied from matroxfb::matroxfb_get_cmap()
1159 int rivafb_get_cmap (struct fb_cmap
*cmap
, int kspc
, int con
,
1160 struct fb_info
*info
)
1162 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1163 struct display
*dsp
;
1165 DPRINTK ("ENTER\n");
1167 assert (rivainfo
!= NULL
);
1168 assert (cmap
!= NULL
);
1170 dsp
= (con
< 0) ? rivainfo
->info
.disp
: &fb_display
[con
];
1172 if (con
== rivainfo
->currcon
) { /* current console? */
1173 int rc
= fb_get_cmap (cmap
, kspc
, riva_getcolreg
, info
);
1174 DPRINTK ("EXIT - returning %d\n", rc
);
1176 } else if (dsp
->cmap
.len
) /* non default colormap? */
1177 fb_copy_cmap (&dsp
->cmap
, cmap
, kspc
? 0 : 2);
1179 fb_copy_cmap (fb_default_cmap (riva_get_cmap_len (&dsp
->var
)),
1180 cmap
, kspc
? 0 : 2);
1182 DPRINTK ("EXIT, returning 0\n");
1198 * Copied from matroxfb::matroxfb_set_cmap()
1201 int rivafb_set_cmap (struct fb_cmap
*cmap
, int kspc
, int con
,
1202 struct fb_info
*info
)
1204 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1205 struct display
*dsp
;
1206 unsigned int cmap_len
;
1208 DPRINTK ("ENTER\n");
1210 assert (rivainfo
!= NULL
);
1211 assert (cmap
!= NULL
);
1213 dsp
= (con
< 0) ? rivainfo
->info
.disp
: &fb_display
[con
];
1215 cmap_len
= riva_get_cmap_len (&dsp
->var
);
1216 if (dsp
->cmap
.len
!= cmap_len
) {
1217 int err
= fb_alloc_cmap (&dsp
->cmap
, cmap_len
, 0);
1219 DPRINTK ("EXIT - returning %d\n", err
);
1223 if (con
== rivainfo
->currcon
) { /* current console? */
1224 int rc
= fb_set_cmap (cmap
, kspc
, riva_setcolreg
, info
);
1225 DPRINTK ("EXIT - returning %d\n", rc
);
1228 fb_copy_cmap (cmap
, &dsp
->cmap
, kspc
? 0 : 1);
1230 DPRINTK ("EXIT, returning 0\n");
1238 * rivafb_pan_display
1239 * @var: standard kernel fb changeable data
1240 * @par: riva-specific hardware info about current video mode
1241 * @info: pointer to rivafb_info object containing info for current riva board
1244 * Pan (or wrap, depending on the `vmode' field) the display using the
1245 * `xoffset' and `yoffset' fields of the `var' structure.
1246 * If the values don't fit, return -EINVAL.
1248 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1251 int rivafb_pan_display (struct fb_var_screeninfo
*var
, int con
,
1252 struct fb_info
*info
)
1255 struct display
*dsp
;
1256 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1258 DPRINTK ("ENTER\n");
1260 assert (rivainfo
!= NULL
);
1262 if (var
->xoffset
> (var
->xres_virtual
- var
->xres
))
1264 if (var
->yoffset
> (var
->yres_virtual
- var
->yres
))
1267 dsp
= (con
< 0) ? rivainfo
->info
.disp
: &fb_display
[con
];
1269 if (var
->vmode
& FB_VMODE_YWRAP
) {
1270 if (var
->yoffset
< 0 || var
->yoffset
>= dsp
->var
.yres_virtual
|| var
->xoffset
)
1273 if (var
->xoffset
+dsp
->var
.xres
> dsp
->var
.xres_virtual
||
1274 var
->yoffset
+dsp
->var
.yres
> dsp
->var
.yres_virtual
)
1278 base
= var
->yoffset
* dsp
->line_length
+ var
->xoffset
;
1280 if (con
== rivainfo
->currcon
) {
1281 /* FIXME: do the dirty deed */
1284 dsp
->var
.xoffset
= var
->xoffset
;
1285 dsp
->var
.yoffset
= var
->yoffset
;
1287 if (var
->vmode
& FB_VMODE_YWRAP
)
1288 dsp
->var
.vmode
|= FB_VMODE_YWRAP
;
1290 dsp
->var
.vmode
&= ~FB_VMODE_YWRAP
;
1292 DPRINTK ("EXIT, returning 0\n");
1311 int rivafb_ioctl (struct inode
*inode
, struct file
*file
, unsigned int cmd
,
1312 unsigned long arg
, int con
, struct fb_info
*info
)
1314 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1316 DPRINTK ("ENTER\n");
1318 assert (rivainfo
!= NULL
);
1320 /* no rivafb-specific ioctls */
1322 DPRINTK ("EXIT, returning -EINVAL\n");
1338 int rivafb_switch(int con
, struct fb_info
*info
)
1340 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1341 struct fb_cmap
* cmap
;
1342 struct display
*dsp
;
1346 assert (rivainfo
!= NULL
);
1348 dsp
= (con
< 0) ? rivainfo
->info
.disp
: &fb_display
[con
];
1350 if (rivainfo
->currcon
>= 0) {
1351 /* Do we have to save the colormap? */
1352 cmap
= &(rivainfo
->currcon_display
->cmap
);
1353 DPRINTK("switch1: con = %d, cmap.len = %d\n", rivainfo
->currcon
, cmap
->len
);
1356 DPRINTK("switch1a: %p %p %p %p\n", cmap
->red
, cmap
->green
, cmap
->blue
, cmap
->transp
);
1357 fb_get_cmap(cmap
, 1, riva_getcolreg
, info
);
1360 DPRINTK("switch1r: %X\n", cmap
->red
[0]);
1365 rivainfo
->currcon
= con
;
1366 rivainfo
->currcon_display
= dsp
;
1367 dsp
->var
.activate
= FB_ACTIVATE_NOW
;
1371 DPRINTK("switch2: con = %d, cmap.len = %d\n", con
, cmap
->len
);
1372 DPRINTK("switch2a: %p %p %p %p\n", cmap
->red
, cmap
->green
, cmap
->blue
, cmap
->transp
);
1373 if (dsp
->cmap
.red
) {
1374 DPRINTK("switch2r: %X\n", cmap
->red
[0]);
1378 rivafb_set_var(&dsp
->var
, con
, info
);
1381 DPRINTK("switch3: con = %d, cmap.len = %d\n", con
, cmap
->len
);
1382 DPRINTK("switch3a: %p %p %p %p\n", cmap
->red
, cmap
->green
, cmap
->blue
, cmap
->transp
);
1383 if (dsp
->cmap
.red
) {
1384 DPRINTK("switch3r: %X\n", cmap
->red
[0]);
1388 DPRINTK("EXIT, returning 0\n");
1395 void rivafb_blank (int blank
, struct fb_info
*info
)
1398 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1400 DPRINTK ("ENTER\n");
1402 assert (rivainfo
!= NULL
);
1404 tmp
= vga_io_rseq (VGA_SEQ_CLOCK_MODE
) & ~VGA_SR01_SCREEN_OFF
;
1407 tmp
|= VGA_SR01_SCREEN_OFF
;
1409 vga_io_wseq (VGA_SEQ_CLOCK_MODE
, tmp
);
1415 /* -------------------------------------------------------------------------
1417 * internal fb_ops helper functions
1419 * -------------------------------------------------------------------------
1430 static int riva_get_cmap_len(const struct fb_var_screeninfo
*var
)
1432 int rc
= 16; /* reasonable default */
1434 assert (var
!= NULL
);
1436 switch (var
->bits_per_pixel
) {
1437 #ifdef FBCON_HAS_CFB4
1439 rc
= 16; /* pseudocolor... 16 entries HW palette */
1442 #ifdef FBCON_HAS_CFB8
1444 rc
= 256; /* pseudocolor... 256 entries HW palette */
1447 #ifdef FBCON_HAS_CFB16
1449 rc
= 16; /* directcolor... 16 entries SW palette */
1450 break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
1452 #ifdef FBCON_HAS_CFB32
1454 rc
= 16; /* directcolor... 16 entries SW palette */
1455 break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
1459 /* should not occur */
1474 * @info: pointer to rivafb_info object containing info for current riva board
1477 * Read a single color register and split it into colors/transparent.
1478 * The return values must have a 16 bit magnitude.
1479 * Return != 0 for invalid regno.
1482 * fbcmap.c:fb_get_cmap()
1483 * fbgen.c:fbgen_get_cmap()
1484 * fbgen.c:fbgen_switch()
1487 static int riva_getcolreg (unsigned regno
, unsigned *red
, unsigned *green
,
1488 unsigned *blue
, unsigned *transp
,
1489 struct fb_info
*info
)
1491 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1495 *red
= rivainfo
->palette
[regno
].red
;
1496 *green
= rivainfo
->palette
[regno
].green
;
1497 *blue
= rivainfo
->palette
[regno
].blue
;
1510 * @info: pointer to rivafb_info object containing info for current riva board
1513 * Set a single color register. The values supplied have a 16 bit
1515 * Return != 0 for invalid regno.
1518 * fbcmap.c:fb_set_cmap()
1519 * fbgen.c:fbgen_get_cmap()
1520 * fbgen.c:fbgen_install_cmap()
1521 * fbgen.c:fbgen_set_var()
1522 * fbgen.c:fbgen_switch()
1523 * fbgen.c:fbgen_blank()
1524 * fbgen.c:fbgen_blank()
1527 static int riva_setcolreg (unsigned regno
, unsigned red
, unsigned green
,
1528 unsigned blue
, unsigned transp
,
1529 struct fb_info
*info
)
1531 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1536 assert (rivainfo
!= NULL
);
1537 assert (rivainfo
->currcon_display
!= NULL
);
1542 p
= rivainfo
->currcon_display
;
1543 if (p
->var
.grayscale
) {
1544 /* gray = 0.30*R + 0.59*G + 0.11*B */
1545 red
= green
= blue
= (red
* 77 + green
* 151 + blue
* 28) >> 8;
1548 #ifdef FBCON_HAS_CFB8
1549 switch (p
->var
.bits_per_pixel
) {
1551 /* "transparent" stuff is completely ignored. */
1552 riva_wclut (regno
, red
>> 10, green
>> 10, blue
>> 10);
1558 #endif /* FBCON_HAS_CFB8 */
1560 rivainfo
->palette
[regno
].red
= red
;
1561 rivainfo
->palette
[regno
].green
= green
;
1562 rivainfo
->palette
[regno
].blue
= blue
;
1567 switch (p
->var
.bits_per_pixel
) {
1569 #ifdef FBCON_HAS_CFB16
1571 assert (regno
< 16);
1573 rivainfo
->con_cmap
.cfb16
[regno
] =
1574 ((red
& 0xf800) >> 9) |
1575 ((green
& 0xf800) >> 14) |
1576 ((green
& 0xf800) << 2) |
1577 ((blue
& 0xf800) >> 3);
1579 rivainfo
->con_cmap
.cfb16
[regno
] =
1580 ((red
& 0xf800) >> 1) |
1581 ((green
& 0xf800) >> 6) |
1582 ((blue
& 0xf800) >> 11);
1585 #endif /* FBCON_HAS_CFB16 */
1587 #ifdef FBCON_HAS_CFB32
1589 assert (regno
< 16);
1591 rivainfo
->con_cmap
.cfb32
[regno
] =
1593 ((green
& 0xff00) << 8) |
1594 ((blue
& 0xff00) << 16);
1596 rivainfo
->con_cmap
.cfb32
[regno
] =
1597 ((red
& 0xff00) << 8) |
1598 ((green
& 0xff00)) |
1599 ((blue
& 0xff00) >> 8);
1602 #endif /* FBCON_HAS_CFB32 */
1615 * riva_load_video_mode()
1617 * calculate some timings and then send em off to riva_load_state()
1620 static void riva_load_video_mode (struct rivafb_info
*rinfo
,
1621 struct fb_var_screeninfo
*video_mode
)
1623 struct riva_regs newmode
;
1624 int bpp
, width
, hDisplaySize
, hDisplay
, hStart
,
1625 hEnd
, hTotal
, height
, vDisplay
, vStart
,
1626 vEnd
, vTotal
, dotClock
;
1628 /* time to calculate */
1630 bpp
= video_mode
->bits_per_pixel
;
1631 width
= hDisplaySize
= video_mode
->xres
;
1632 hDisplay
= (hDisplaySize
/8) - 1;
1633 hStart
= (hDisplaySize
+ video_mode
->right_margin
)/8 + 2;
1634 hEnd
= (hDisplaySize
+ video_mode
->right_margin
+
1635 video_mode
->hsync_len
)/8 - 1;
1636 hTotal
= (hDisplaySize
+ video_mode
->right_margin
+
1637 video_mode
->hsync_len
+ video_mode
->left_margin
)/8 - 1;
1638 height
= video_mode
->yres
;
1639 vDisplay
= video_mode
->yres
- 1;
1640 vStart
= video_mode
->yres
+ video_mode
->lower_margin
- 1;
1641 vEnd
= video_mode
->yres
+ video_mode
->lower_margin
+
1642 video_mode
->vsync_len
- 1;
1643 vTotal
= video_mode
->yres
+ video_mode
->lower_margin
+
1644 video_mode
->vsync_len
+ video_mode
->upper_margin
+ 2;
1645 dotClock
= 1000000000 / video_mode
->pixclock
;
1647 memcpy(&newmode
, ®_template
, sizeof(struct riva_regs
));
1649 newmode
.crtc
[0x0] = Set8Bits(hTotal
- 4);
1650 newmode
.crtc
[0x1] = Set8Bits(hDisplay
);
1651 newmode
.crtc
[0x2] = Set8Bits(hDisplay
);
1652 newmode
.crtc
[0x3] = SetBitField(hTotal
,4:0,4:0) | SetBit(7);
1653 newmode
.crtc
[0x4] = Set8Bits(hStart
);
1654 newmode
.crtc
[0x5] = SetBitField(hTotal
,5:5,7:7)
1655 | SetBitField(hEnd
,4:0,4:0);
1656 newmode
.crtc
[0x6] = SetBitField(vTotal
,7:0,7:0);
1657 newmode
.crtc
[0x7] = SetBitField(vTotal
,8:8,0:0)
1658 | SetBitField(vDisplay
,8:8,1:1)
1659 | SetBitField(vStart
,8:8,2:2)
1660 | SetBitField(vDisplay
,8:8,3:3)
1662 | SetBitField(vTotal
,9:9,5:5)
1663 | SetBitField(vDisplay
,9:9,6:6)
1664 | SetBitField(vStart
,9:9,7:7);
1665 newmode
.crtc
[0x9] = SetBitField(vDisplay
,9:9,5:5)
1667 newmode
.crtc
[0x10] = Set8Bits(vStart
);
1668 newmode
.crtc
[0x11] = SetBitField(vEnd
,3:0,3:0)
1670 newmode
.crtc
[0x12] = Set8Bits(vDisplay
);
1671 newmode
.crtc
[0x13] = ((width
/8)*(bpp
/8)) & 0xFF;
1672 newmode
.crtc
[0x15] = Set8Bits(vDisplay
);
1673 newmode
.crtc
[0x16] = Set8Bits(vTotal
+ 1);
1675 newmode
.ext
.bpp
= bpp
;
1676 newmode
.ext
.width
= width
;
1677 newmode
.ext
.height
= height
;
1679 rinfo
->riva
.CalcStateExt(&rinfo
->riva
,&newmode
.ext
,bpp
,width
,
1680 hDisplaySize
,hDisplay
,hStart
,hEnd
,hTotal
,
1681 height
,vDisplay
,vStart
,vEnd
,vTotal
,dotClock
);
1683 rinfo
->initial_state
= newmode
;
1684 riva_load_state(rinfo
,&newmode
);
1691 /* ------------------------------------------------------------------------- */
1699 int __init
init_module(void)
1701 return rivafb_init();
1704 void __exit
cleanup_module(void)
1706 struct rivafb_info
*tmp
, *board
= riva_boards
;
1708 while (board
!= NULL
) {
1709 riva_load_state (board
, &board
->initial_state
);
1711 unregister_framebuffer ((struct fb_info
*) board
);
1714 iounmap (tmp
->ctrl_base
);
1715 iounmap (tmp
->fb_base
);
1716 board
= board
->next
;
1729 void riva_save_state(struct rivafb_info
*rinfo
, struct riva_regs
*regs
)
1733 io_out8(NV_CIO_SR_LOCK_INDEX
, 0x3D4);
1734 io_out8(NV_CIO_SR_UNLOCK_RW_VALUE
, 0x3D5);
1736 rinfo
->riva
.UnloadStateExt(&rinfo
->riva
, ®s
->ext
);
1738 regs
->misc_output
= io_in8(0x3CC);
1740 for (i
= 0; i
< NUM_CRT_REGS
; i
++)
1743 regs
->crtc
[i
] = io_in8(0x3D5);
1746 for (i
= 0; i
< NUM_ATC_REGS
; i
++)
1749 regs
->attr
[i
] = io_in8(0x3C1);
1752 for (i
= 0; i
< NUM_GRC_REGS
; i
++)
1755 regs
->gra
[i
] = io_in8(0x3CF);
1759 for (i
= 0; i
< NUM_SEQ_REGS
; i
++)
1762 regs
->seq
[i
] = io_in8(0x3C5);
1769 void riva_load_state(struct rivafb_info
*rinfo
, struct riva_regs
*regs
)
1772 RIVA_HW_STATE
*state
= ®s
->ext
;
1774 io_out8(0x11, 0x3D4);
1775 io_out8(0x00, 0x3D5);
1777 io_out8(NV_CIO_SR_LOCK_INDEX
, 0x3D4);
1778 io_out8(NV_CIO_SR_UNLOCK_RW_VALUE
, 0x3D5);
1780 rinfo
->riva
.LoadStateExt(&rinfo
->riva
,state
);
1782 io_out8(regs
->misc_output
, 0x3C2);
1784 for (i
= 0; i
< NUM_CRT_REGS
; i
++)
1789 io_out8(regs
->crtc
[i
], 0x3D5);
1836 io_out8(regs
->crtc
[i
], 0x3D5);
1841 for (i
= 0; i
< NUM_ATC_REGS
; i
++)
1844 io_out8(regs
->attr
[i
], 0x3C1);
1847 for (i
= 0; i
< NUM_GRC_REGS
; i
++)
1850 io_out8(regs
->gra
[i
], 0x3CF);
1853 for (i
= 0; i
< NUM_SEQ_REGS
; i
++)
1856 io_out8(regs
->seq
[i
], 0x3C5);
1864 * riva_board_list_add
1865 * @board_list: Root node of list of boards
1866 * @new_node: New node to be added
1869 * Adds @new_node to the list referenced by @board_list
1875 struct rivafb_info
*riva_board_list_add(struct rivafb_info
*board_list
,
1876 struct rivafb_info
*new_node
)
1878 struct rivafb_info
*i_p
= board_list
;
1880 new_node
->next
= NULL
;
1882 if (board_list
== NULL
)
1885 while (i_p
->next
!= NULL
)
1887 i_p
->next
= new_node
;