2 * linux/drivers/video/rivafb.c - nVidia RIVA 128/TNT/TNT2 fb driver
4 * Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
6 * Copyright 1999-2000 Jeff Garzik
10 * Ani Joshi: Lots of debugging and cleanup work, really helped
11 * get the driver going
13 * Ferenc Bakonyi: Bug fixes, cleanup, modularization
15 * Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven
16 * Includes riva_hw.c from nVidia, see copyright below.
17 * KGI code provided the basis for state storage, init, and mode switching.
19 * This file is subject to the terms and conditions of the GNU General Public
20 * License. See the file README.legal in the main directory of this archive
24 /* version number of this driver */
25 #define RIVAFB_VERSION "0.7.2"
27 #include <linux/config.h>
28 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/errno.h>
31 #include <linux/string.h>
33 #include <linux/selection.h>
34 #include <linux/tty.h>
35 #include <linux/malloc.h>
36 #include <linux/delay.h>
38 #include <linux/init.h>
39 #include <linux/pci.h>
41 #include <video/fbcon.h>
47 #include <video/fbcon-cfb4.h>
48 #include <video/fbcon-cfb8.h>
49 #include <video/fbcon-cfb16.h>
50 #include <video/fbcon-cfb32.h>
52 #ifndef CONFIG_PCI /* sanity check */
53 #error This driver requires PCI support.
56 /*****************************************************************
58 * various helpful macros and constants
62 /* #define RIVAFBDEBUG */
64 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
66 #define DPRINTK(fmt, args...)
70 #define assert(expr) \
72 printk( "Assertion failed! %s,%s,%s,line=%d\n",\
73 #expr,__FILE__,__FUNCTION__,__LINE__); \
80 /* GGI compatibility macros */
83 #define NUM_SEQ_REGS 0x05
84 #define NUM_CRT_REGS 0x41
85 #define NUM_GRC_REGS 0x09
86 #define NUM_ATC_REGS 0x15
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)
102 CH_RIVA_UTNT2
, /* UTNT2 */
103 CH_RIVA_VTNT2
, /* VTNT2 */
104 CH_RIVA_UVTNT2
, /* VTNT2 */
105 CH_RIVA_ITNT2
, /* ITNT2 */
109 /* directly indexed by riva_chips enum, above */
110 static struct riva_chip_info
{
113 } riva_chip_info
[] __devinitdata
= {
119 { "RIVA-UVTNT2", 5 },
124 static struct pci_device_id rivafb_pci_tbl
[] __devinitdata
= {
125 { PCI_VENDOR_ID_NVIDIA_SGS
, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, CH_RIVA_128
},
126 { PCI_VENDOR_ID_NVIDIA
, PCI_DEVICE_ID_NVIDIA_TNT
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, CH_RIVA_TNT
},
127 { PCI_VENDOR_ID_NVIDIA
, PCI_DEVICE_ID_NVIDIA_TNT2
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, CH_RIVA_TNT2
},
128 { PCI_VENDOR_ID_NVIDIA
, PCI_DEVICE_ID_NVIDIA_UTNT2
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, CH_RIVA_UTNT2
},
129 { PCI_VENDOR_ID_NVIDIA
, PCI_DEVICE_ID_NVIDIA_VTNT2
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, CH_RIVA_VTNT2
},
130 { PCI_VENDOR_ID_NVIDIA
, PCI_DEVICE_ID_NVIDIA_UVTNT2
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, CH_RIVA_VTNT2
},
131 { PCI_VENDOR_ID_NVIDIA
, PCI_DEVICE_ID_NVIDIA_ITNT2
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, CH_RIVA_ITNT2
},
132 { 0, } /* terminate list */
134 MODULE_DEVICE_TABLE(pci
, rivafb_pci_tbl
);
137 /* holds the state of the VGA core and extended Riva hw state from riva_hw.c.
138 * From KGI originally. */
140 u8 attr
[NUM_ATC_REGS
];
141 u8 crtc
[NUM_CRT_REGS
];
142 u8 gra
[NUM_GRC_REGS
];
143 u8 seq
[NUM_SEQ_REGS
];
150 * describes the state of a Riva board
153 struct riva_regs state
; /* state of hw board */
154 __u32 visual
; /* FB_VISUAL_xxx */
155 unsigned depth
; /* bpp of current mode */
159 unsigned char red
, green
, blue
, transp
;
166 struct fb_info info
; /* kernel framebuffer info */
168 RIVA_HW_INST riva
; /* interface to riva_hw.c */
170 const char *drvr_name
; /* Riva hardware board type */
172 unsigned long ctrl_base_phys
; /* physical control register base addr */
173 unsigned long fb_base_phys
; /* physical framebuffer base addr */
175 caddr_t ctrl_base
; /* virtual control register base addr */
176 caddr_t fb_base
; /* virtual framebuffer base addr */
178 unsigned ram_amount
; /* amount of RAM on card, in bytes */
179 unsigned dclk_max
; /* max DCLK */
181 struct riva_regs initial_state
; /* initial startup video mode */
185 struct display
*currcon_display
;
187 struct rivafb_info
*next
;
189 struct pci_dev
*pd
; /* pointer to board's pci info */
190 unsigned base0_region_size
; /* size of control register region */
191 unsigned base1_region_size
; /* size of framebuffer region */
193 riva_cfb8_cmap_t palette
[256]; /* VGA DAC palette cache */
195 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
197 #ifdef FBCON_HAS_CFB16
200 #ifdef FBCON_HAS_CFB32
204 #endif /* FBCON_HAS_CFB16 | FBCON_HAS_CFB32 */
207 /* ------------------- global variables ------------------------ */
210 static struct rivafb_info
*riva_boards
= NULL
;
212 /* command line data, set in rivafb_setup() */
213 static char fontname
[40] __initdata
= { 0 };
215 static char noaccel __initdata
= 0; /* unused */
216 static const char *mode_option __initdata
= NULL
;
219 static struct fb_var_screeninfo rivafb_default_var
= {
220 /* 640x480-8@60, yres_virtual=2400 (fits for all Riva cards */
221 640, 480, 640, 2400, 0, 0, 8, 0,
222 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
223 0, 0, -1, -1, 0, 39721, 40, 24, 32, 11, 96, 2,
224 0, FB_VMODE_NONINTERLACED
228 /* ------------------- prototypes ------------------------------ */
230 static int rivafb_get_fix (struct fb_fix_screeninfo
*fix
, int con
,
231 struct fb_info
*info
);
232 static int rivafb_get_var (struct fb_var_screeninfo
*var
, int con
,
233 struct fb_info
*info
);
234 static int rivafb_set_var (struct fb_var_screeninfo
*var
, int con
,
235 struct fb_info
*info
);
236 static int rivafb_get_cmap (struct fb_cmap
*cmap
, int kspc
, int con
,
237 struct fb_info
*info
);
238 static int rivafb_set_cmap (struct fb_cmap
*cmap
, int kspc
, int con
,
239 struct fb_info
*info
);
240 static int rivafb_pan_display (struct fb_var_screeninfo
*var
, int con
,
241 struct fb_info
*info
);
242 static int rivafb_ioctl (struct inode
*inode
, struct file
*file
, unsigned int cmd
,
243 unsigned long arg
, int con
, struct fb_info
*info
);
244 static int rivafb_switch (int con
, struct fb_info
*info
);
245 static int rivafb_updatevar (int con
, struct fb_info
*info
);
246 static void rivafb_blank (int blank
, struct fb_info
*info
);
248 static void riva_load_video_mode (struct rivafb_info
*rivainfo
,
249 struct fb_var_screeninfo
*video_mode
);
250 static int riva_getcolreg (unsigned regno
, unsigned *red
, unsigned *green
,
251 unsigned *blue
, unsigned *transp
,
252 struct fb_info
*info
);
253 static int riva_setcolreg (unsigned regno
, unsigned red
, unsigned green
,
254 unsigned blue
, unsigned transp
,
255 struct fb_info
*info
);
256 static int riva_get_cmap_len (const struct fb_var_screeninfo
*var
);
258 static int riva_set_fbinfo (struct rivafb_info
*rinfo
);
260 static void riva_save_state (struct rivafb_info
*rinfo
, struct riva_regs
*regs
);
261 static void riva_load_state (struct rivafb_info
*rinfo
, struct riva_regs
*regs
);
262 static struct rivafb_info
*riva_board_list_add (struct rivafb_info
*board_list
,
263 struct rivafb_info
*new_node
);
264 static struct rivafb_info
*riva_board_list_del (struct rivafb_info
*board_list
,
265 struct rivafb_info
*del_node
);
266 static void riva_wclut (unsigned char regnum
, unsigned char red
,
267 unsigned char green
, unsigned char blue
);
272 /* kernel interface */
273 static struct fb_ops riva_fb_ops
= {
275 fb_get_fix
: rivafb_get_fix
,
276 fb_get_var
: rivafb_get_var
,
277 fb_set_var
: rivafb_set_var
,
278 fb_get_cmap
: rivafb_get_cmap
,
279 fb_set_cmap
: rivafb_set_cmap
,
280 fb_pan_display
: rivafb_pan_display
,
281 fb_ioctl
: rivafb_ioctl
,
288 static const struct riva_regs reg_template
= {
289 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ATTR */
290 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
291 0x41, 0x01, 0x0F, 0x00, 0x00},
292 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* CRT */
293 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, /* 0x10 */
295 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */
297 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30 */
299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, /* GRA */
304 {0x03, 0x01, 0x0F, 0x00, 0x0E}, /* SEQ */
310 /* ------------------- general utility functions -------------------------- */
314 * @rivainfo: pointer to internal driver struct for a given Riva card
317 * Sets up console Low level operations depending on the current? color depth
321 static void riva_set_dispsw (struct rivafb_info
*rinfo
)
323 struct display
*disp
= &rinfo
->disp
;
327 assert (rinfo
!= NULL
);
329 disp
->dispsw_data
= NULL
;
331 switch (disp
->var
.bits_per_pixel
) {
334 disp
->dispsw
= &fbcon_mfb
;
337 #ifdef FBCON_HAS_CFB4
339 disp
->dispsw
= &fbcon_cfb4
;
342 #ifdef FBCON_HAS_CFB8
344 disp
->dispsw
= &fbcon_cfb8
;
347 #ifdef FBCON_HAS_CFB16
350 disp
->dispsw
= &fbcon_cfb16
;
351 disp
->dispsw_data
= &rinfo
->con_cmap
.cfb16
;
354 #ifdef FBCON_HAS_CFB24
356 disp
->dispsw
= &fbcon_cfb24
;
357 disp
->dispsw_data
= rinfo
->con_cmap
.cfb24
;
360 #ifdef FBCON_HAS_CFB32
362 disp
->dispsw
= &fbcon_cfb32
;
363 disp
->dispsw_data
= rinfo
->con_cmap
.cfb32
;
367 DPRINTK ("Setting fbcon_dummy renderer\n");
368 disp
->dispsw
= &fbcon_dummy
;
377 static int riva_init_disp_var (struct rivafb_info
*rinfo
)
381 fb_find_mode (&rinfo
->disp
.var
, &rinfo
->info
, mode_option
,
390 static int __devinit
riva_init_disp (struct rivafb_info
*rinfo
)
392 struct fb_info
*info
;
393 struct display
*disp
;
397 assert (rinfo
!= NULL
);
402 disp
->var
= rivafb_default_var
;
405 #warning FIXME: assure that disp->cmap is completely filled out
407 disp
->screen_base
= rinfo
->fb_base
;
408 disp
->visual
= FB_VISUAL_PSEUDOCOLOR
;
409 disp
->type
= FB_TYPE_PACKED_PIXELS
;
413 disp
->next_line
= disp
->line_length
=
414 (disp
->var
.xres_virtual
* disp
->var
.bits_per_pixel
) >> 3;
415 disp
->can_soft_blank
= 1;
418 riva_set_dispsw (rinfo
);
420 disp
->scrollmode
= 0;
422 rinfo
->currcon_display
= disp
;
424 if ((riva_init_disp_var (rinfo
)) < 0) { /* must be done last */
425 DPRINTK ("EXIT, returning -1\n");
429 DPRINTK ("EXIT, returning 0\n");
436 static int __devinit
riva_set_fbinfo (struct rivafb_info
*rinfo
)
438 struct fb_info
*info
;
440 assert (rinfo
!= NULL
);
444 strcpy (info
->modename
, rinfo
->drvr_name
);
446 info
->flags
= FBINFO_FLAG_DEFAULT
;
447 info
->fbops
= &riva_fb_ops
;
449 /* FIXME: set monspecs to what??? */
451 info
->display_fg
= NULL
;
452 strncpy (info
->fontname
, fontname
, sizeof (info
->fontname
));
453 info
->fontname
[sizeof (info
->fontname
) - 1] = 0;
455 info
->changevar
= NULL
;
456 info
->switch_con
= rivafb_switch
;
457 info
->updatevar
= rivafb_updatevar
;
458 info
->blank
= rivafb_blank
;
460 if (riva_init_disp (rinfo
) < 0) /* must be done last */
469 /* ----------------------------- PCI bus ----------------------------- */
474 static int __devinit
rivafb_init_one (struct pci_dev
*pd
,
475 const struct pci_device_id
*ent
)
477 struct rivafb_info
*rinfo
;
478 struct riva_chip_info
*rci
= &riva_chip_info
[ent
->driver_data
];
481 assert (rci
!= NULL
);
483 rinfo
= kmalloc (sizeof (struct rivafb_info
), GFP_KERNEL
);
487 memset (rinfo
, 0, sizeof (struct rivafb_info
));
489 rinfo
->drvr_name
= rci
->name
;
490 rinfo
->riva
.Architecture
= rci
->arch_rev
;
493 rinfo
->base0_region_size
= pci_resource_len (pd
, 0);
494 rinfo
->base1_region_size
= pci_resource_len (pd
, 1);
496 assert (rinfo
->base0_region_size
>= 0x00800000); /* from GGI */
497 assert (rinfo
->base1_region_size
>= 0x01000000); /* from GGI */
499 rinfo
->ctrl_base_phys
= pci_resource_start (rinfo
->pd
, 0);
500 rinfo
->fb_base_phys
= pci_resource_start (rinfo
->pd
, 1);
502 if (!request_mem_region (rinfo
->ctrl_base_phys
,
503 rinfo
->base0_region_size
, "rivafb")) {
504 printk (KERN_ERR PFX
"cannot reserve MMIO region\n");
508 if (!request_mem_region (rinfo
->fb_base_phys
,
509 rinfo
->base1_region_size
, "rivafb")) {
510 printk (KERN_ERR PFX
"cannot reserve FB region\n");
511 goto err_out_free_base0
;
514 rinfo
->ctrl_base
= ioremap (rinfo
->ctrl_base_phys
,
515 rinfo
->base0_region_size
);
516 if (!rinfo
->ctrl_base
) {
517 printk (KERN_ERR PFX
"cannot ioremap ctrl base\n");
518 goto err_out_free_base1
;
521 rinfo
->fb_base
= ioremap (rinfo
->fb_base_phys
,
522 rinfo
->base1_region_size
);
523 if (!rinfo
->fb_base
) {
524 printk (KERN_ERR PFX
"cannot ioremap ctrl base\n");
525 goto err_out_iounmap_ctrl
;
528 rinfo
->riva
.EnableIRQ
= 0;
529 rinfo
->riva
.IO
= (inb (0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
530 rinfo
->riva
.PRAMDAC
= (unsigned *) (rinfo
->ctrl_base
+ 0x00680000);
531 rinfo
->riva
.PFB
= (unsigned *) (rinfo
->ctrl_base
+ 0x00100000);
532 rinfo
->riva
.PFIFO
= (unsigned *) (rinfo
->ctrl_base
+ 0x00002000);
533 rinfo
->riva
.PGRAPH
= (unsigned *) (rinfo
->ctrl_base
+ 0x00400000);
534 rinfo
->riva
.PEXTDEV
= (unsigned *) (rinfo
->ctrl_base
+ 0x00101000);
535 rinfo
->riva
.PTIMER
= (unsigned *) (rinfo
->ctrl_base
+ 0x00009000);
536 rinfo
->riva
.PMC
= (unsigned *) (rinfo
->ctrl_base
+ 0x00000000);
537 rinfo
->riva
.FIFO
= (unsigned *) (rinfo
->ctrl_base
+ 0x00800000);
539 switch (rinfo
->riva
.Architecture
) {
542 (unsigned *) (rinfo
->ctrl_base
+ 0x00C00000);
547 (unsigned *) (rinfo
->ctrl_base
+ 0x00600000);
549 (unsigned *) (rinfo
->ctrl_base
+ 0x00710000);
553 RivaGetConfig (&rinfo
->riva
);
557 assert (rinfo
->pd
!= NULL
);
560 vga_io_wcrt (0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */
561 outb (rinfo
->riva
.LockUnlockIndex
, rinfo
->riva
.LockUnlockIO
);
562 outb (0x57, rinfo
->riva
.LockUnlockIO
+ 1);
564 memcpy (&rinfo
->initial_state
, ®_template
,
565 sizeof (reg_template
));
566 riva_save_state (rinfo
, &rinfo
->initial_state
);
568 rinfo
->ram_amount
= rinfo
->riva
.RamAmountKBytes
* 1024;
569 rinfo
->dclk_max
= rinfo
->riva
.MaxVClockFreqKHz
* 1000;
571 riva_set_fbinfo (rinfo
);
573 fb_memset (rinfo
->fb_base
, 0, rinfo
->ram_amount
);
575 riva_load_video_mode (rinfo
, &rinfo
->disp
.var
);
577 if (register_framebuffer ((struct fb_info
*) rinfo
) < 0) {
579 "error registering riva framebuffer\n");
580 goto err_out_iounmap_fb
;
583 riva_boards
= riva_board_list_add(riva_boards
, rinfo
);
585 pd
->driver_data
= rinfo
;
587 printk ("PCI Riva NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
588 rinfo
->riva
.Architecture
,
591 rinfo
->ram_amount
/ (1024 * 1024) + 1,
592 rinfo
->fb_base_phys
);
597 iounmap (rinfo
->fb_base
);
598 err_out_iounmap_ctrl
:
599 iounmap (rinfo
->ctrl_base
);
601 release_mem_region (rinfo
->fb_base_phys
, rinfo
->base1_region_size
);
603 release_mem_region (rinfo
->ctrl_base_phys
, rinfo
->base0_region_size
);
611 static void __devexit
rivafb_remove_one (struct pci_dev
*pd
)
613 struct rivafb_info
*board
= pd
->driver_data
;
618 riva_boards
= riva_board_list_del(riva_boards
, board
);
620 riva_load_state (board
, &board
->initial_state
);
622 unregister_framebuffer ((struct fb_info
*) board
);
624 iounmap (board
->ctrl_base
);
625 iounmap (board
->fb_base
);
627 release_mem_region (board
->ctrl_base_phys
,
628 board
->base0_region_size
);
629 release_mem_region (board
->fb_base_phys
,
630 board
->base1_region_size
);
636 /*** riva_wclut - set CLUT entry ***/
637 static void riva_wclut (unsigned char regnum
, unsigned char red
,
638 unsigned char green
, unsigned char blue
)
640 unsigned int data
= VGA_PEL_D
;
642 /* address write mode register is not translated.. */
643 vga_io_w (VGA_PEL_IW
, regnum
);
645 vga_io_w (data
, red
);
646 vga_io_w (data
, green
);
647 vga_io_w (data
, blue
);
652 /* ------------ Hardware Independent Functions ------------ */
655 int __init
rivafb_setup (char *options
)
659 if (!options
|| !*options
)
662 for (this_opt
= strtok (options
, ","); this_opt
;
663 this_opt
= strtok (NULL
, ",")) {
664 if (!strncmp (this_opt
, "font:", 5)) {
669 for (i
= 0; i
< sizeof (fontname
) - 1; i
++)
670 if (!*p
|| *p
== ' ' || *p
== ',')
672 memcpy (fontname
, this_opt
+ 5, i
);
676 else if (!strncmp (this_opt
, "noaccel", 7)) {
681 mode_option
= this_opt
;
691 /* ------------------------------------------------------------------------- */
695 * Frame buffer operations
698 static int rivafb_get_fix (struct fb_fix_screeninfo
*fix
, int con
,
699 struct fb_info
*info
)
701 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
706 assert (fix
!= NULL
);
707 assert (info
!= NULL
);
708 assert (rivainfo
->drvr_name
&& rivainfo
->drvr_name
[0]);
709 assert (rivainfo
->fb_base_phys
> 0);
710 assert (rivainfo
->ram_amount
> 0);
712 p
= (con
< 0) ? rivainfo
->info
.disp
: &fb_display
[con
];
714 memset (fix
, 0, sizeof (struct fb_fix_screeninfo
));
715 sprintf (fix
->id
, "Riva %s", rivainfo
->drvr_name
);
717 fix
->smem_start
= rivainfo
->fb_base_phys
;
718 fix
->smem_len
= rivainfo
->ram_amount
;
721 fix
->type_aux
= p
->type_aux
;
722 fix
->visual
= p
->visual
;
726 fix
->ywrapstep
= 0; /* FIXME: no ywrap for now */
728 fix
->line_length
= p
->line_length
;
730 #warning FIXME: set up MMIO region, export via FB_ACCEL_xxx
733 fix
->accel
= FB_ACCEL_NONE
;
735 DPRINTK ("EXIT, returning 0\n");
741 static int rivafb_get_var (struct fb_var_screeninfo
*var
, int con
,
742 struct fb_info
*info
)
744 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
748 assert (info
!= NULL
);
749 assert (var
!= NULL
);
751 *var
= (con
< 0) ? rivainfo
->disp
.var
: fb_display
[con
].var
;
753 DPRINTK ("EXIT, returning 0\n");
760 static int rivafb_set_var (struct fb_var_screeninfo
*var
, int con
,
761 struct fb_info
*info
)
763 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
765 struct fb_var_screeninfo v
;
766 int nom
, den
; /* translating from pixels->bytes */
783 assert (info
!= NULL
);
784 assert (var
!= NULL
);
786 DPRINTK ("Requested: %dx%dx%d\n", var
->xres
, var
->yres
,
787 var
->bits_per_pixel
);
788 DPRINTK (" virtual: %dx%d\n", var
->xres_virtual
,
790 DPRINTK (" offset: (%d,%d)\n", var
->xoffset
, var
->yoffset
);
791 DPRINTK ("grayscale: %d\n", var
->grayscale
);
793 dsp
= (con
< 0) ? rivainfo
->info
.disp
: &fb_display
[con
];
794 assert (dsp
!= NULL
);
796 /* if var has changed, we should call changevar() later */
798 chgvar
= ((dsp
->var
.xres
!= var
->xres
) ||
799 (dsp
->var
.yres
!= var
->yres
) ||
800 (dsp
->var
.xres_virtual
!= var
->xres_virtual
) ||
801 (dsp
->var
.yres_virtual
!= var
->yres_virtual
) ||
802 (dsp
->var
.bits_per_pixel
!= var
->bits_per_pixel
)
803 || memcmp (&dsp
->var
.red
, &var
->red
,
805 || memcmp (&dsp
->var
.green
, &var
->green
,
807 || memcmp (&dsp
->var
.blue
, &var
->blue
,
808 sizeof (var
->blue
)));
811 memcpy (&v
, var
, sizeof (v
));
813 switch (v
.bits_per_pixel
) {
816 dsp
->dispsw
= &fbcon_mfb
;
817 dsp
->line_length
= v
.xres_virtual
/ 8;
818 dsp
->visual
= FB_VISUAL_MONO10
;
824 #ifdef FBCON_HAS_CFB8
826 v
.bits_per_pixel
= 8;
827 dsp
->dispsw
= &fbcon_cfb8
;
830 dsp
->line_length
= v
.xres_virtual
;
831 dsp
->visual
= FB_VISUAL_PSEUDOCOLOR
;
841 #ifdef FBCON_HAS_CFB16
843 v
.bits_per_pixel
= 16;
844 dsp
->dispsw
= &fbcon_cfb16
;
845 dsp
->dispsw_data
= &rivainfo
->con_cmap
.cfb16
;
848 dsp
->line_length
= v
.xres_virtual
* 2;
849 dsp
->visual
= FB_VISUAL_DIRECTCOLOR
;
865 #ifdef FBCON_HAS_CFB32
867 v
.bits_per_pixel
= 32;
868 dsp
->dispsw
= &fbcon_cfb32
;
869 dsp
->dispsw_data
= rivainfo
->con_cmap
.cfb32
;
872 dsp
->line_length
= v
.xres_virtual
* 4;
873 dsp
->visual
= FB_VISUAL_DIRECTCOLOR
;
891 "mode %dx%dx%d rejected...color depth not supported.\n",
892 var
->xres
, var
->yres
, var
->bits_per_pixel
);
893 DPRINTK ("EXIT, returning -EINVAL\n");
897 if (v
.xres
* nom
/ den
* v
.yres
> rivainfo
->ram_amount
) {
899 "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
900 var
->xres
, var
->yres
, var
->bits_per_pixel
);
901 DPRINTK ("EXIT - EINVAL error\n");
905 /* use highest possible virtual resolution */
906 if (v
.xres_virtual
== -1 && v
.yres_virtual
== -1) {
907 printk (KERN_WARNING PFX
908 "using maximum available virtual resolution\n");
909 for (i
= 0; modes
[i
].xres
!= -1; i
++) {
910 if (modes
[i
].xres
* nom
/ den
* modes
[i
].yres
<
911 rivainfo
->ram_amount
/ 2)
914 if (modes
[i
].xres
== -1) {
916 "could not find a virtual resolution that fits into video memory!!\n");
917 DPRINTK ("EXIT - EINVAL error\n");
920 v
.xres_virtual
= modes
[i
].xres
;
921 v
.yres_virtual
= modes
[i
].yres
;
923 printk (KERN_INFO PFX
924 "virtual resolution set to maximum of %dx%d\n",
925 v
.xres_virtual
, v
.yres_virtual
);
926 } else if (v
.xres_virtual
== -1) {
927 /* FIXME: maximize X virtual resolution only */
928 } else if (v
.yres_virtual
== -1) {
929 /* FIXME: maximize Y virtual resolution only */
937 /* truncate xoffset and yoffset to maximum if too high */
938 if (v
.xoffset
> v
.xres_virtual
- v
.xres
)
939 v
.xoffset
= v
.xres_virtual
- v
.xres
- 1;
941 if (v
.yoffset
> v
.yres_virtual
- v
.yres
)
942 v
.yoffset
= v
.yres_virtual
- v
.yres
- 1;
947 v
.transp
.offset
= v
.transp
.length
= v
.transp
.msb_right
= 0;
949 switch (v
.activate
& FB_ACTIVATE_MASK
) {
950 case FB_ACTIVATE_TEST
:
951 DPRINTK ("EXIT - FB_ACTIVATE_TEST\n");
953 case FB_ACTIVATE_NXTOPEN
: /* ?? */
954 case FB_ACTIVATE_NOW
:
955 break; /* continue */
957 DPRINTK ("EXIT - unknown activation type\n");
958 return -EINVAL
; /* unknown */
961 dsp
->type
= FB_TYPE_PACKED_PIXELS
;
963 #warning FIXME: verify that the above code sets dsp->* fields correctly
965 memcpy (&dsp
->var
, &v
, sizeof (v
));
967 riva_load_video_mode (rivainfo
, &v
);
969 if (chgvar
&& info
&& info
->changevar
)
970 info
->changevar (con
);
972 DPRINTK ("EXIT, returning 0\n");
978 static int rivafb_get_cmap (struct fb_cmap
*cmap
, int kspc
, int con
,
979 struct fb_info
*info
)
981 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
986 assert (rivainfo
!= NULL
);
987 assert (cmap
!= NULL
);
989 dsp
= (con
< 0) ? rivainfo
->info
.disp
: &fb_display
[con
];
991 if (con
== rivainfo
->currcon
) { /* current console? */
992 int rc
= fb_get_cmap (cmap
, kspc
, riva_getcolreg
, info
);
993 DPRINTK ("EXIT - returning %d\n", rc
);
995 } else if (dsp
->cmap
.len
) /* non default colormap? */
996 fb_copy_cmap (&dsp
->cmap
, cmap
, kspc
? 0 : 2);
998 fb_copy_cmap (fb_default_cmap
999 (riva_get_cmap_len (&dsp
->var
)), cmap
,
1002 DPRINTK ("EXIT, returning 0\n");
1008 static int rivafb_set_cmap (struct fb_cmap
*cmap
, int kspc
, int con
,
1009 struct fb_info
*info
)
1011 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1012 struct display
*dsp
;
1013 unsigned int cmap_len
;
1015 DPRINTK ("ENTER\n");
1017 assert (rivainfo
!= NULL
);
1018 assert (cmap
!= NULL
);
1020 dsp
= (con
< 0) ? rivainfo
->info
.disp
: &fb_display
[con
];
1022 cmap_len
= riva_get_cmap_len (&dsp
->var
);
1023 if (dsp
->cmap
.len
!= cmap_len
) {
1024 int err
= fb_alloc_cmap (&dsp
->cmap
, cmap_len
, 0);
1026 DPRINTK ("EXIT - returning %d\n", err
);
1030 if (con
== rivainfo
->currcon
) { /* current console? */
1031 int rc
= fb_set_cmap (cmap
, kspc
, riva_setcolreg
, info
);
1032 DPRINTK ("EXIT - returning %d\n", rc
);
1035 fb_copy_cmap (cmap
, &dsp
->cmap
, kspc
? 0 : 1);
1037 DPRINTK ("EXIT, returning 0\n");
1045 * rivafb_pan_display
1046 * @var: standard kernel fb changeable data
1047 * @par: riva-specific hardware info about current video mode
1048 * @info: pointer to rivafb_info object containing info for current riva board
1051 * Pan (or wrap, depending on the `vmode' field) the display using the
1052 * `xoffset' and `yoffset' fields of the `var' structure.
1053 * If the values don't fit, return -EINVAL.
1055 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1058 static int rivafb_pan_display (struct fb_var_screeninfo
*var
, int con
,
1059 struct fb_info
*info
)
1062 struct display
*dsp
;
1063 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1065 DPRINTK ("ENTER\n");
1067 assert (rivainfo
!= NULL
);
1069 if (var
->xoffset
> (var
->xres_virtual
- var
->xres
))
1071 if (var
->yoffset
> (var
->yres_virtual
- var
->yres
))
1074 dsp
= (con
< 0) ? rivainfo
->info
.disp
: &fb_display
[con
];
1076 if (var
->vmode
& FB_VMODE_YWRAP
) {
1077 if (var
->yoffset
< 0
1078 || var
->yoffset
>= dsp
->var
.yres_virtual
1079 || var
->xoffset
) return -EINVAL
;
1081 if (var
->xoffset
+ dsp
->var
.xres
> dsp
->var
.xres_virtual
||
1082 var
->yoffset
+ dsp
->var
.yres
> dsp
->var
.yres_virtual
)
1086 base
= var
->yoffset
* dsp
->line_length
+ var
->xoffset
;
1088 if (con
== rivainfo
->currcon
) {
1089 rivainfo
->riva
.SetStartAddress (&rivainfo
->riva
, base
);
1092 dsp
->var
.xoffset
= var
->xoffset
;
1093 dsp
->var
.yoffset
= var
->yoffset
;
1095 if (var
->vmode
& FB_VMODE_YWRAP
)
1096 dsp
->var
.vmode
|= FB_VMODE_YWRAP
;
1098 dsp
->var
.vmode
&= ~FB_VMODE_YWRAP
;
1100 DPRINTK ("EXIT, returning 0\n");
1106 static int rivafb_ioctl (struct inode
*inode
, struct file
*file
, unsigned int cmd
,
1107 unsigned long arg
, int con
, struct fb_info
*info
)
1109 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1111 DPRINTK ("ENTER\n");
1113 assert (rivainfo
!= NULL
);
1115 /* no rivafb-specific ioctls */
1117 DPRINTK ("EXIT, returning -EINVAL\n");
1123 static int rivafb_switch (int con
, struct fb_info
*info
)
1125 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1126 struct fb_cmap
*cmap
;
1127 struct display
*dsp
;
1129 DPRINTK ("ENTER\n");
1131 assert (rivainfo
!= NULL
);
1133 dsp
= (con
< 0) ? rivainfo
->info
.disp
: &fb_display
[con
];
1135 if (rivainfo
->currcon
>= 0) {
1136 /* Do we have to save the colormap? */
1137 cmap
= &(rivainfo
->currcon_display
->cmap
);
1138 DPRINTK ("switch1: con = %d, cmap.len = %d\n",
1139 rivainfo
->currcon
, cmap
->len
);
1142 DPRINTK ("switch1a: %p %p %p %p\n", cmap
->red
,
1143 cmap
->green
, cmap
->blue
, cmap
->transp
);
1144 fb_get_cmap (cmap
, 1, riva_getcolreg
, info
);
1147 DPRINTK ("switch1r: %X\n", cmap
->red
[0]);
1152 rivainfo
->currcon
= con
;
1153 rivainfo
->currcon_display
= dsp
;
1154 dsp
->var
.activate
= FB_ACTIVATE_NOW
;
1158 DPRINTK ("switch2: con = %d, cmap.len = %d\n", con
, cmap
->len
);
1159 DPRINTK ("switch2a: %p %p %p %p\n", cmap
->red
, cmap
->green
,
1160 cmap
->blue
, cmap
->transp
);
1161 if (dsp
->cmap
.red
) {
1162 DPRINTK ("switch2r: %X\n", cmap
->red
[0]);
1166 rivafb_set_var (&dsp
->var
, con
, info
);
1169 DPRINTK ("switch3: con = %d, cmap.len = %d\n", con
, cmap
->len
);
1170 DPRINTK ("switch3a: %p %p %p %p\n", cmap
->red
, cmap
->green
,
1171 cmap
->blue
, cmap
->transp
);
1172 if (dsp
->cmap
.red
) {
1173 DPRINTK ("switch3r: %X\n", cmap
->red
[0]);
1177 DPRINTK ("EXIT, returning 0\n");
1181 static int rivafb_updatevar (int con
, struct fb_info
*info
)
1185 DPRINTK ("ENTER\n");
1188 0) ? -EINVAL
: rivafb_pan_display (&fb_display
[con
].var
,
1190 DPRINTK ("EXIT, returning %d\n", rc
);
1195 static void rivafb_blank (int blank
, struct fb_info
*info
)
1198 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1200 DPRINTK ("ENTER\n");
1202 assert (rivainfo
!= NULL
);
1204 tmp
= vga_io_rseq (VGA_SEQ_CLOCK_MODE
) & ~VGA_SR01_SCREEN_OFF
;
1207 tmp
|= VGA_SR01_SCREEN_OFF
;
1209 vga_io_wseq (VGA_SEQ_CLOCK_MODE
, tmp
);
1215 /* -------------------------------------------------------------------------
1217 * internal fb_ops helper functions
1219 * -------------------------------------------------------------------------
1230 static int riva_get_cmap_len (const struct fb_var_screeninfo
*var
)
1232 int rc
= 16; /* reasonable default */
1234 assert (var
!= NULL
);
1236 switch (var
->bits_per_pixel
) {
1237 #ifdef FBCON_HAS_CFB4
1239 rc
= 16; /* pseudocolor... 16 entries HW palette */
1242 #ifdef FBCON_HAS_CFB8
1244 rc
= 256; /* pseudocolor... 256 entries HW palette */
1247 #ifdef FBCON_HAS_CFB16
1249 rc
= 16; /* directcolor... 16 entries SW palette */
1250 break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
1252 #ifdef FBCON_HAS_CFB32
1254 rc
= 16; /* directcolor... 16 entries SW palette */
1255 break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
1259 /* should not occur */
1274 * @info: pointer to rivafb_info object containing info for current riva board
1277 * Read a single color register and split it into colors/transparent.
1278 * The return values must have a 16 bit magnitude.
1279 * Return != 0 for invalid regno.
1282 * fbcmap.c:fb_get_cmap()
1283 * fbgen.c:fbgen_get_cmap()
1284 * fbgen.c:fbgen_switch()
1287 static int riva_getcolreg (unsigned regno
, unsigned *red
, unsigned *green
,
1288 unsigned *blue
, unsigned *transp
,
1289 struct fb_info
*info
)
1291 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1296 *red
= rivainfo
->palette
[regno
].red
;
1297 *green
= rivainfo
->palette
[regno
].green
;
1298 *blue
= rivainfo
->palette
[regno
].blue
;
1312 * @info: pointer to rivafb_info object containing info for current riva board
1315 * Set a single color register. The values supplied have a 16 bit
1317 * Return != 0 for invalid regno.
1320 * fbcmap.c:fb_set_cmap()
1321 * fbgen.c:fbgen_get_cmap()
1322 * fbgen.c:fbgen_install_cmap()
1323 * fbgen.c:fbgen_set_var()
1324 * fbgen.c:fbgen_switch()
1325 * fbgen.c:fbgen_blank()
1326 * fbgen.c:fbgen_blank()
1329 static int riva_setcolreg (unsigned regno
, unsigned red
, unsigned green
,
1330 unsigned blue
, unsigned transp
,
1331 struct fb_info
*info
)
1333 struct rivafb_info
*rivainfo
= (struct rivafb_info
*) info
;
1337 DPRINTK ("ENTER\n");
1339 assert (rivainfo
!= NULL
);
1340 assert (rivainfo
->currcon_display
!= NULL
);
1345 p
= rivainfo
->currcon_display
;
1346 if (p
->var
.grayscale
) {
1347 /* gray = 0.30*R + 0.59*G + 0.11*B */
1348 red
= green
= blue
=
1349 (red
* 77 + green
* 151 + blue
* 28) >> 8;
1352 switch (rivainfo
->riva
.Architecture
) {
1362 #ifdef FBCON_HAS_CFB8
1363 switch (p
->var
.bits_per_pixel
) {
1365 /* "transparent" stuff is completely ignored. */
1366 riva_wclut (regno
, red
>> shift
, green
>> shift
, blue
>> shift
);
1372 #endif /* FBCON_HAS_CFB8 */
1374 rivainfo
->palette
[regno
].red
= red
;
1375 rivainfo
->palette
[regno
].green
= green
;
1376 rivainfo
->palette
[regno
].blue
= blue
;
1381 switch (p
->var
.bits_per_pixel
) {
1383 #ifdef FBCON_HAS_CFB16
1385 assert (regno
< 16);
1387 rivainfo
->con_cmap
.cfb16
[regno
] =
1388 ((red
& 0xf800) >> 9) |
1389 ((green
& 0xf800) >> 14) |
1390 ((green
& 0xf800) << 2) | ((blue
& 0xf800) >> 3);
1392 rivainfo
->con_cmap
.cfb16
[regno
] =
1393 ((red
& 0xf800) >> 1) |
1394 ((green
& 0xf800) >> 6) | ((blue
& 0xf800) >> 11);
1397 #endif /* FBCON_HAS_CFB16 */
1399 #ifdef FBCON_HAS_CFB32
1401 assert (regno
< 16);
1403 rivainfo
->con_cmap
.cfb32
[regno
] =
1405 ((green
& 0xff00) << 8) | ((blue
& 0xff00) << 16);
1407 rivainfo
->con_cmap
.cfb32
[regno
] =
1408 ((red
& 0xff00) << 8) |
1409 ((green
& 0xff00)) | ((blue
& 0xff00) >> 8);
1412 #endif /* FBCON_HAS_CFB32 */
1425 * riva_load_video_mode()
1427 * calculate some timings and then send em off to riva_load_state()
1430 static void riva_load_video_mode (struct rivafb_info
*rinfo
,
1431 struct fb_var_screeninfo
*video_mode
)
1433 struct riva_regs newmode
;
1434 int bpp
, width
, hDisplaySize
, hDisplay
, hStart
,
1435 hEnd
, hTotal
, height
, vDisplay
, vStart
, vEnd
, vTotal
, dotClock
;
1437 /* time to calculate */
1439 bpp
= video_mode
->bits_per_pixel
;
1440 width
= hDisplaySize
= video_mode
->xres
;
1441 hDisplay
= (hDisplaySize
/ 8) - 1;
1442 hStart
= (hDisplaySize
+ video_mode
->right_margin
) / 8 + 2;
1443 hEnd
= (hDisplaySize
+ video_mode
->right_margin
+
1444 video_mode
->hsync_len
) / 8 - 1;
1445 hTotal
= (hDisplaySize
+ video_mode
->right_margin
+
1446 video_mode
->hsync_len
+ video_mode
->left_margin
) / 8 - 1;
1447 height
= video_mode
->yres
;
1448 vDisplay
= video_mode
->yres
- 1;
1449 vStart
= video_mode
->yres
+ video_mode
->lower_margin
- 1;
1450 vEnd
= video_mode
->yres
+ video_mode
->lower_margin
+
1451 video_mode
->vsync_len
- 1;
1452 vTotal
= video_mode
->yres
+ video_mode
->lower_margin
+
1453 video_mode
->vsync_len
+ video_mode
->upper_margin
+ 2;
1454 dotClock
= 1000000000 / video_mode
->pixclock
;
1456 memcpy (&newmode
, ®_template
, sizeof (struct riva_regs
));
1458 newmode
.crtc
[0x0] = Set8Bits (hTotal
- 4);
1459 newmode
.crtc
[0x1] = Set8Bits (hDisplay
);
1460 newmode
.crtc
[0x2] = Set8Bits (hDisplay
);
1461 newmode
.crtc
[0x3] = SetBitField (hTotal
, 4: 0, 4:0) | SetBit (7);
1462 newmode
.crtc
[0x4] = Set8Bits (hStart
);
1463 newmode
.crtc
[0x5] = SetBitField (hTotal
, 5: 5, 7:7)
1464 | SetBitField (hEnd
, 4: 0, 4:0);
1465 newmode
.crtc
[0x6] = SetBitField (vTotal
, 7: 0, 7:0);
1466 newmode
.crtc
[0x7] = SetBitField (vTotal
, 8: 8, 0:0)
1467 | SetBitField (vDisplay
, 8: 8, 1:1)
1468 | SetBitField (vStart
, 8: 8, 2:2)
1469 | SetBitField (vDisplay
, 8: 8, 3:3)
1471 | SetBitField (vTotal
, 9: 9, 5:5)
1472 | SetBitField (vDisplay
, 9: 9, 6:6)
1473 | SetBitField (vStart
, 9: 9, 7:7);
1474 newmode
.crtc
[0x9] = SetBitField (vDisplay
, 9: 9, 5:5)
1476 newmode
.crtc
[0x10] = Set8Bits (vStart
);
1477 newmode
.crtc
[0x11] = SetBitField (vEnd
, 3: 0, 3:0)
1479 newmode
.crtc
[0x12] = Set8Bits (vDisplay
);
1480 newmode
.crtc
[0x13] = ((width
/ 8) * (bpp
/ 8)) & 0xFF;
1481 newmode
.crtc
[0x15] = Set8Bits (vDisplay
);
1482 newmode
.crtc
[0x16] = Set8Bits (vTotal
+ 1);
1484 newmode
.ext
.bpp
= bpp
;
1485 newmode
.ext
.width
= width
;
1486 newmode
.ext
.height
= height
;
1488 rinfo
->riva
.CalcStateExt (&rinfo
->riva
, &newmode
.ext
, bpp
, width
,
1489 hDisplaySize
, hDisplay
, hStart
, hEnd
,
1490 hTotal
, height
, vDisplay
, vStart
, vEnd
,
1493 rinfo
->initial_state
= newmode
;
1494 riva_load_state (rinfo
, &newmode
);
1498 /* ------------------------------------------------------------------------- */
1505 static struct pci_driver rivafb_driver
= {
1507 id_table
: rivafb_pci_tbl
,
1508 probe
: rivafb_init_one
,
1509 remove
: rivafb_remove_one
,
1513 int __init
rivafb_init (void)
1515 return pci_module_init (&rivafb_driver
);
1519 static void __exit
rivafb_exit (void)
1521 pci_unregister_driver (&rivafb_driver
);
1526 module_init(rivafb_init
);
1528 module_exit(rivafb_exit
);
1530 MODULE_AUTHOR("Ani Joshi, maintainer");
1531 MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2");
1535 static void riva_save_state (struct rivafb_info
*rinfo
, struct riva_regs
*regs
)
1539 outb (rinfo
->riva
.LockUnlockIndex
, rinfo
->riva
.LockUnlockIO
);
1540 outb (0x57, rinfo
->riva
.LockUnlockIO
+ 1);
1542 rinfo
->riva
.UnloadStateExt (&rinfo
->riva
, ®s
->ext
);
1544 regs
->misc_output
= io_in8 (0x3CC);
1546 for (i
= 0; i
< NUM_CRT_REGS
; i
++) {
1548 regs
->crtc
[i
] = io_in8 (0x3D5);
1551 for (i
= 0; i
< NUM_ATC_REGS
; i
++) {
1553 regs
->attr
[i
] = io_in8 (0x3C1);
1556 for (i
= 0; i
< NUM_GRC_REGS
; i
++) {
1558 regs
->gra
[i
] = io_in8 (0x3CF);
1562 for (i
= 0; i
< NUM_SEQ_REGS
; i
++) {
1564 regs
->seq
[i
] = io_in8 (0x3C5);
1571 void riva_load_state (struct rivafb_info
*rinfo
, struct riva_regs
*regs
)
1574 RIVA_HW_STATE
*state
= ®s
->ext
;
1576 io_out8 (0x11, 0x3D4);
1577 io_out8 (0x00, 0x3D5);
1579 outb (rinfo
->riva
.LockUnlockIndex
, rinfo
->riva
.LockUnlockIO
);
1580 outb (0x57, rinfo
->riva
.LockUnlockIO
+ 1);
1582 rinfo
->riva
.LoadStateExt (&rinfo
->riva
, state
);
1584 io_out8 (regs
->misc_output
, 0x3C2);
1586 for (i
= 0; i
< NUM_CRT_REGS
; i
++) {
1589 io_out8 (regs
->crtc
[i
], 0x3D5);
1629 io_out8 (regs
->crtc
[i
], 0x3D5);
1634 for (i
= 0; i
< NUM_ATC_REGS
; i
++) {
1636 io_out8 (regs
->attr
[i
], 0x3C0);
1639 for (i
= 0; i
< NUM_GRC_REGS
; i
++) {
1641 io_out8 (regs
->gra
[i
], 0x3CF);
1644 for (i
= 0; i
< NUM_SEQ_REGS
; i
++) {
1646 io_out8 (regs
->seq
[i
], 0x3C5);
1654 * riva_board_list_add
1655 * @board_list: Root node of list of boards
1656 * @new_node: New node to be added
1659 * Adds @new_node to the list referenced by @board_list
1665 struct rivafb_info
*riva_board_list_add (struct rivafb_info
*board_list
,
1666 struct rivafb_info
*new_node
)
1668 struct rivafb_info
*i_p
= board_list
;
1670 new_node
->next
= NULL
;
1672 if (board_list
== NULL
)
1675 while (i_p
->next
!= NULL
)
1677 i_p
->next
= new_node
;
1685 * riva_board_list_del
1686 * @board_list: Root node of list of boards
1687 * @del_node: Node to be removed
1690 * Removes @del_node from the list referenced by @board_list
1696 struct rivafb_info
*riva_board_list_del (struct rivafb_info
*board_list
,
1697 struct rivafb_info
*del_node
)
1699 struct rivafb_info
*i_p
= board_list
;
1701 if (board_list
== del_node
)
1702 return del_node
->next
;
1704 while (i_p
->next
!= del_node
)
1706 i_p
->next
= del_node
->next
;