Merge with Linux 2.4.0-test3-pre2.
[linux-2.6/linux-mips.git] / drivers / video / riva / fbdev.c
blob4c2a137910ccd494b1f0ce8dcac6f862c43ecef6
1 /*
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
8 * Contributors:
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
21 * for more details.
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>
32 #include <linux/mm.h>
33 #include <linux/selection.h>
34 #include <linux/tty.h>
35 #include <linux/malloc.h>
36 #include <linux/delay.h>
37 #include <linux/fb.h>
38 #include <linux/init.h>
39 #include <linux/pci.h>
41 #include <video/fbcon.h>
43 #include "riva_hw.h"
44 #include "nv4ref.h"
45 #include "nvreg.h"
46 #include "../vga.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.
54 #endif
56 /*****************************************************************
58 * various helpful macros and constants
62 /* #define RIVAFBDEBUG */
63 #ifdef RIVAFBDEBUG
64 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
65 #else
66 #define DPRINTK(fmt, args...)
67 #endif
69 #ifndef RIVA_NDEBUG
70 #define assert(expr) \
71 if(!(expr)) { \
72 printk( "Assertion failed! %s,%s,%s,line=%d\n",\
73 #expr,__FILE__,__FUNCTION__,__LINE__); \
74 BUG(); \
76 #else
77 #define assert(expr)
78 #endif
80 /* GGI compatibility macros */
81 #define io_out8 outb
82 #define io_in8 inb
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)
98 enum riva_chips {
99 CH_RIVA_128 = 0,
100 CH_RIVA_TNT,
101 CH_RIVA_TNT2,
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 {
111 const char *name;
112 unsigned arch_rev;
113 } riva_chip_info[] __devinitdata = {
114 { "RIVA-128", 3 },
115 { "RIVA-TNT", 4 },
116 { "RIVA-TNT2", 5 },
117 { "RIVA-UTNT2", 5 },
118 { "RIVA-VTNT2", 5 },
119 { "RIVA-UVTNT2", 5 },
120 { "RIVA-ITNT2", 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. */
139 struct riva_regs {
140 u8 attr[NUM_ATC_REGS];
141 u8 crtc[NUM_CRT_REGS];
142 u8 gra[NUM_GRC_REGS];
143 u8 seq[NUM_SEQ_REGS];
144 u8 misc_output;
145 RIVA_HW_STATE ext;
150 * describes the state of a Riva board
152 struct rivafb_par {
153 struct riva_regs state; /* state of hw board */
154 __u32 visual; /* FB_VISUAL_xxx */
155 unsigned depth; /* bpp of current mode */
158 typedef struct {
159 unsigned char red, green, blue, transp;
160 } riva_cfb8_cmap_t;
164 struct rivafb_info;
165 struct rivafb_info {
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 */
183 struct display disp;
184 int currcon;
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)
196 union {
197 #ifdef FBCON_HAS_CFB16
198 u_int16_t cfb16[16];
199 #endif
200 #ifdef FBCON_HAS_CFB32
201 u_int32_t cfb32[16];
202 #endif
203 } con_cmap;
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 };
214 #ifndef MODULE
215 static char noaccel __initdata = 0; /* unused */
216 static const char *mode_option __initdata = NULL;
217 #endif
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 = {
274 owner: THIS_MODULE,
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,
287 /* from GGI */
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,
300 0x00, /* 0x40 */
302 {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, /* GRA */
303 0xFF},
304 {0x03, 0x01, 0x0F, 0x00, 0x0E}, /* SEQ */
305 0xEB /* MISC */
310 /* ------------------- general utility functions -------------------------- */
313 * riva_set_dispsw
314 * @rivainfo: pointer to internal driver struct for a given Riva card
316 * DESCRIPTION:
317 * Sets up console Low level operations depending on the current? color depth
318 * of the display
321 static void riva_set_dispsw (struct rivafb_info *rinfo)
323 struct display *disp = &rinfo->disp;
325 DPRINTK ("ENTER\n");
327 assert (rinfo != NULL);
329 disp->dispsw_data = NULL;
331 switch (disp->var.bits_per_pixel) {
332 #ifdef FBCON_HAS_MFB
333 case 1:
334 disp->dispsw = &fbcon_mfb;
335 break;
336 #endif
337 #ifdef FBCON_HAS_CFB4
338 case 4:
339 disp->dispsw = &fbcon_cfb4;
340 break;
341 #endif
342 #ifdef FBCON_HAS_CFB8
343 case 8:
344 disp->dispsw = &fbcon_cfb8;
345 break;
346 #endif
347 #ifdef FBCON_HAS_CFB16
348 case 15:
349 case 16:
350 disp->dispsw = &fbcon_cfb16;
351 disp->dispsw_data = &rinfo->con_cmap.cfb16;
352 break;
353 #endif
354 #ifdef FBCON_HAS_CFB24
355 case 24:
356 disp->dispsw = &fbcon_cfb24;
357 disp->dispsw_data = rinfo->con_cmap.cfb24;
358 break;
359 #endif
360 #ifdef FBCON_HAS_CFB32
361 case 32:
362 disp->dispsw = &fbcon_cfb32;
363 disp->dispsw_data = rinfo->con_cmap.cfb32;
364 break;
365 #endif
366 default:
367 DPRINTK ("Setting fbcon_dummy renderer\n");
368 disp->dispsw = &fbcon_dummy;
371 DPRINTK ("EXIT\n");
377 static int riva_init_disp_var (struct rivafb_info *rinfo)
379 #ifndef MODULE
380 if (mode_option)
381 fb_find_mode (&rinfo->disp.var, &rinfo->info, mode_option,
382 NULL, 0, NULL, 8);
383 #endif /* !MODULE */
384 return 0;
390 static int __devinit riva_init_disp (struct rivafb_info *rinfo)
392 struct fb_info *info;
393 struct display *disp;
395 DPRINTK ("ENTER\n");
397 assert (rinfo != NULL);
399 info = &rinfo->info;
400 disp = &rinfo->disp;
402 disp->var = rivafb_default_var;
403 info->disp = disp;
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;
410 disp->type_aux = 0;
411 disp->ypanstep = 1;
412 disp->ywrapstep = 0;
413 disp->next_line = disp->line_length =
414 (disp->var.xres_virtual * disp->var.bits_per_pixel) >> 3;
415 disp->can_soft_blank = 1;
416 disp->inverse = 0;
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");
426 return -1;
429 DPRINTK ("EXIT, returning 0\n");
430 return 0;
436 static int __devinit riva_set_fbinfo (struct rivafb_info *rinfo)
438 struct fb_info *info;
440 assert (rinfo != NULL);
442 info = &rinfo->info;
444 strcpy (info->modename, rinfo->drvr_name);
445 info->node = -1;
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 */
461 return -1;
463 return 0;
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];
480 assert (pd != NULL);
481 assert (rci != NULL);
483 rinfo = kmalloc (sizeof (struct rivafb_info), GFP_KERNEL);
484 if (!rinfo)
485 goto err_out;
487 memset (rinfo, 0, sizeof (struct rivafb_info));
489 rinfo->drvr_name = rci->name;
490 rinfo->riva.Architecture = rci->arch_rev;
492 rinfo->pd = pd;
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");
505 goto err_out_kfree;
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) {
540 case 3:
541 rinfo->riva.PRAMIN =
542 (unsigned *) (rinfo->ctrl_base + 0x00C00000);
543 break;
544 case 4:
545 case 5:
546 rinfo->riva.PCRTC =
547 (unsigned *) (rinfo->ctrl_base + 0x00600000);
548 rinfo->riva.PRAMIN =
549 (unsigned *) (rinfo->ctrl_base + 0x00710000);
550 break;
553 RivaGetConfig (&rinfo->riva);
555 /* back to normal */
557 assert (rinfo->pd != NULL);
559 /* unlock io */
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, &reg_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) {
578 printk (KERN_ERR PFX
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,
589 RIVAFB_VERSION,
590 rinfo->drvr_name,
591 rinfo->ram_amount / (1024 * 1024) + 1,
592 rinfo->fb_base_phys);
594 return 0;
596 err_out_iounmap_fb:
597 iounmap (rinfo->fb_base);
598 err_out_iounmap_ctrl:
599 iounmap (rinfo->ctrl_base);
600 err_out_free_base1:
601 release_mem_region (rinfo->fb_base_phys, rinfo->base1_region_size);
602 err_out_free_base0:
603 release_mem_region (rinfo->ctrl_base_phys, rinfo->base0_region_size);
604 err_out_kfree:
605 kfree (rinfo);
606 err_out:
607 return -ENODEV;
611 static void __devexit rivafb_remove_one (struct pci_dev *pd)
613 struct rivafb_info *board = pd->driver_data;
615 if (!board)
616 return;
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);
632 kfree (board);
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 ------------ */
654 #ifndef MODULE
655 int __init rivafb_setup (char *options)
657 char *this_opt;
659 if (!options || !*options)
660 return 0;
662 for (this_opt = strtok (options, ","); this_opt;
663 this_opt = strtok (NULL, ",")) {
664 if (!strncmp (this_opt, "font:", 5)) {
665 char *p;
666 int i;
668 p = this_opt + 5;
669 for (i = 0; i < sizeof (fontname) - 1; i++)
670 if (!*p || *p == ' ' || *p == ',')
671 break;
672 memcpy (fontname, this_opt + 5, i);
673 fontname[i] = 0;
676 else if (!strncmp (this_opt, "noaccel", 7)) {
677 noaccel = 1;
680 else
681 mode_option = this_opt;
683 return 0;
685 #endif /* !MODULE */
688 * Initialization
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;
702 struct display *p;
704 DPRINTK ("ENTER\n");
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;
720 fix->type = p->type;
721 fix->type_aux = p->type_aux;
722 fix->visual = p->visual;
724 fix->xpanstep = 1;
725 fix->ypanstep = 1;
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
731 fix->mmio_start = 0;
732 fix->mmio_len = 0;
733 fix->accel = FB_ACCEL_NONE;
735 DPRINTK ("EXIT, returning 0\n");
737 return 0;
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;
746 DPRINTK ("ENTER\n");
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");
755 return 0;
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;
764 struct display *dsp;
765 struct fb_var_screeninfo v;
766 int nom, den; /* translating from pixels->bytes */
767 int i;
768 unsigned chgvar = 0;
769 static struct {
770 int xres, yres;
771 } modes[] = {
773 1600, 1280}, {
774 1280, 1024}, {
775 1024, 768}, {
776 800, 600}, {
777 640, 480}, {
778 -1, -1}
781 DPRINTK ("ENTER\n");
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,
789 var->yres_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 */
797 if (con >= 0) {
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,
804 sizeof (var->red))
805 || memcmp (&dsp->var.green, &var->green,
806 sizeof (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) {
814 #ifdef FBCON_HAS_MFB
815 case 1:
816 dsp->dispsw = &fbcon_mfb;
817 dsp->line_length = v.xres_virtual / 8;
818 dsp->visual = FB_VISUAL_MONO10;
819 nom = 4;
820 den = 8;
821 break;
822 #endif
824 #ifdef FBCON_HAS_CFB8
825 case 2 ... 8:
826 v.bits_per_pixel = 8;
827 dsp->dispsw = &fbcon_cfb8;
828 nom = 1;
829 den = 1;
830 dsp->line_length = v.xres_virtual;
831 dsp->visual = FB_VISUAL_PSEUDOCOLOR;
832 v.red.offset = 0;
833 v.red.length = 6;
834 v.green.offset = 0;
835 v.green.length = 6;
836 v.blue.offset = 0;
837 v.blue.length = 6;
838 break;
839 #endif
841 #ifdef FBCON_HAS_CFB16
842 case 9 ... 16:
843 v.bits_per_pixel = 16;
844 dsp->dispsw = &fbcon_cfb16;
845 dsp->dispsw_data = &rivainfo->con_cmap.cfb16;
846 nom = 2;
847 den = 1;
848 dsp->line_length = v.xres_virtual * 2;
849 dsp->visual = FB_VISUAL_DIRECTCOLOR;
850 #ifdef CONFIG_PREP
851 v.red.offset = 2;
852 v.green.offset = -3;
853 v.blue.offset = 8;
854 #else
855 v.red.offset = 10;
856 v.green.offset = 5;
857 v.blue.offset = 0;
858 #endif
859 v.red.length = 5;
860 v.green.length = 5;
861 v.blue.length = 5;
862 break;
863 #endif
865 #ifdef FBCON_HAS_CFB32
866 case 17 ... 32:
867 v.bits_per_pixel = 32;
868 dsp->dispsw = &fbcon_cfb32;
869 dsp->dispsw_data = rivainfo->con_cmap.cfb32;
870 nom = 4;
871 den = 1;
872 dsp->line_length = v.xres_virtual * 4;
873 dsp->visual = FB_VISUAL_DIRECTCOLOR;
874 #ifdef CONFIG_PREP
875 v.red.offset = 8;
876 v.green.offset = 16;
877 v.blue.offset = 24;
878 #else
879 v.red.offset = 16;
880 v.green.offset = 8;
881 v.blue.offset = 0;
882 #endif
883 v.red.length = 8;
884 v.green.length = 8;
885 v.blue.length = 8;
886 break;
887 #endif
889 default:
890 printk (KERN_ERR PFX
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");
894 return -EINVAL;
897 if (v.xres * nom / den * v.yres > rivainfo->ram_amount) {
898 printk (KERN_ERR PFX
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");
902 return -EINVAL;
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)
912 break;
914 if (modes[i].xres == -1) {
915 printk (KERN_ERR PFX
916 "could not find a virtual resolution that fits into video memory!!\n");
917 DPRINTK ("EXIT - EINVAL error\n");
918 return -EINVAL;
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 */
932 if (v.xoffset < 0)
933 v.xoffset = 0;
934 if (v.yoffset < 0)
935 v.yoffset = 0;
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;
944 v.red.msb_right =
945 v.green.msb_right =
946 v.blue.msb_right =
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");
952 return 0;
953 case FB_ACTIVATE_NXTOPEN: /* ?? */
954 case FB_ACTIVATE_NOW:
955 break; /* continue */
956 default:
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");
973 return 0;
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;
982 struct display *dsp;
984 DPRINTK ("ENTER\n");
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);
994 return rc;
995 } else if (dsp->cmap.len) /* non default colormap? */
996 fb_copy_cmap (&dsp->cmap, cmap, kspc ? 0 : 2);
997 else
998 fb_copy_cmap (fb_default_cmap
999 (riva_get_cmap_len (&dsp->var)), cmap,
1000 kspc ? 0 : 2);
1002 DPRINTK ("EXIT, returning 0\n");
1004 return 0;
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);
1025 if (err) {
1026 DPRINTK ("EXIT - returning %d\n", err);
1027 return 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);
1033 return rc;
1034 } else
1035 fb_copy_cmap (cmap, &dsp->cmap, kspc ? 0 : 1);
1037 DPRINTK ("EXIT, returning 0\n");
1039 return 0;
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
1050 * DESCRIPTION:
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)
1061 unsigned int base;
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))
1070 return -EINVAL;
1071 if (var->yoffset > (var->yres_virtual - var->yres))
1072 return -EINVAL;
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;
1080 } else {
1081 if (var->xoffset + dsp->var.xres > dsp->var.xres_virtual ||
1082 var->yoffset + dsp->var.yres > dsp->var.yres_virtual)
1083 return -EINVAL;
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;
1097 else
1098 dsp->var.vmode &= ~FB_VMODE_YWRAP;
1100 DPRINTK ("EXIT, returning 0\n");
1102 return 0;
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");
1119 return -EINVAL;
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);
1141 if (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);
1145 #ifdef DEBUG
1146 if (cmap->red) {
1147 DPRINTK ("switch1r: %X\n", cmap->red[0]);
1149 #endif
1152 rivainfo->currcon = con;
1153 rivainfo->currcon_display = dsp;
1154 dsp->var.activate = FB_ACTIVATE_NOW;
1156 #ifdef riva_DEBUG
1157 cmap = &dsp->cmap;
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]);
1164 #endif
1166 rivafb_set_var (&dsp->var, con, info);
1168 #ifdef riva_DEBUG
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]);
1175 #endif
1177 DPRINTK ("EXIT, returning 0\n");
1178 return 0;
1181 static int rivafb_updatevar (int con, struct fb_info *info)
1183 int rc;
1185 DPRINTK ("ENTER\n");
1187 rc = (con <
1188 0) ? -EINVAL : rivafb_pan_display (&fb_display[con].var,
1189 con, info);
1190 DPRINTK ("EXIT, returning %d\n", rc);
1191 return rc;
1195 static void rivafb_blank (int blank, struct fb_info *info)
1197 unsigned char tmp;
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;
1206 if (blank)
1207 tmp |= VGA_SR01_SCREEN_OFF;
1209 vga_io_wseq (VGA_SEQ_CLOCK_MODE, tmp);
1211 DPRINTK ("EXIT\n");
1215 /* -------------------------------------------------------------------------
1217 * internal fb_ops helper functions
1219 * -------------------------------------------------------------------------
1224 * riva_get_cmap_len
1225 * @var:
1227 * DESCRIPTION:
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
1238 case 4:
1239 rc = 16; /* pseudocolor... 16 entries HW palette */
1240 break;
1241 #endif
1242 #ifdef FBCON_HAS_CFB8
1243 case 8:
1244 rc = 256; /* pseudocolor... 256 entries HW palette */
1245 break;
1246 #endif
1247 #ifdef FBCON_HAS_CFB16
1248 case 16:
1249 rc = 16; /* directcolor... 16 entries SW palette */
1250 break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
1251 #endif
1252 #ifdef FBCON_HAS_CFB32
1253 case 32:
1254 rc = 16; /* directcolor... 16 entries SW palette */
1255 break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
1256 #endif
1257 default:
1258 assert (0);
1259 /* should not occur */
1260 break;
1263 return rc;
1268 * riva_getcolreg
1269 * @regno:
1270 * @red:
1271 * @green:
1272 * @blue:
1273 * @transp:
1274 * @info: pointer to rivafb_info object containing info for current riva board
1276 * DESCRIPTION:
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.
1281 * CALLED FROM:
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;
1293 if (regno > 255)
1294 return 1;
1296 *red = rivainfo->palette[regno].red;
1297 *green = rivainfo->palette[regno].green;
1298 *blue = rivainfo->palette[regno].blue;
1299 *transp = 0;
1301 return 0;
1306 * riva_setcolreg
1307 * @regno:
1308 * @red:
1309 * @green:
1310 * @blue:
1311 * @transp:
1312 * @info: pointer to rivafb_info object containing info for current riva board
1314 * DESCRIPTION:
1315 * Set a single color register. The values supplied have a 16 bit
1316 * magnitude.
1317 * Return != 0 for invalid regno.
1319 * CALLED FROM:
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;
1334 struct display *p;
1335 unsigned shift = 8;
1337 DPRINTK ("ENTER\n");
1339 assert (rivainfo != NULL);
1340 assert (rivainfo->currcon_display != NULL);
1342 if (regno > 255)
1343 return -EINVAL;
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) {
1353 case 3:
1354 shift = 10;
1355 break;
1356 case 4:
1357 case 5:
1358 shift = 8;
1359 break;
1362 #ifdef FBCON_HAS_CFB8
1363 switch (p->var.bits_per_pixel) {
1364 case 8:
1365 /* "transparent" stuff is completely ignored. */
1366 riva_wclut (regno, red >> shift, green >> shift, blue >> shift);
1367 break;
1368 default:
1369 /* do nothing */
1370 break;
1372 #endif /* FBCON_HAS_CFB8 */
1374 rivainfo->palette[regno].red = red;
1375 rivainfo->palette[regno].green = green;
1376 rivainfo->palette[regno].blue = blue;
1378 if (regno >= 16)
1379 return 0;
1381 switch (p->var.bits_per_pixel) {
1383 #ifdef FBCON_HAS_CFB16
1384 case 16:
1385 assert (regno < 16);
1386 #ifdef CONFIG_PREP
1387 rivainfo->con_cmap.cfb16[regno] =
1388 ((red & 0xf800) >> 9) |
1389 ((green & 0xf800) >> 14) |
1390 ((green & 0xf800) << 2) | ((blue & 0xf800) >> 3);
1391 #else
1392 rivainfo->con_cmap.cfb16[regno] =
1393 ((red & 0xf800) >> 1) |
1394 ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
1395 #endif
1396 break;
1397 #endif /* FBCON_HAS_CFB16 */
1399 #ifdef FBCON_HAS_CFB32
1400 case 32:
1401 assert (regno < 16);
1402 #ifdef CONFIG_PREP
1403 rivainfo->con_cmap.cfb32[regno] =
1404 ((red & 0xff00)) |
1405 ((green & 0xff00) << 8) | ((blue & 0xff00) << 16);
1406 #else
1407 rivainfo->con_cmap.cfb32[regno] =
1408 ((red & 0xff00) << 8) |
1409 ((green & 0xff00)) | ((blue & 0xff00) >> 8);
1410 #endif
1411 break;
1412 #endif /* FBCON_HAS_CFB32 */
1414 default:
1415 /* do nothing */
1416 break;
1419 return 0;
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, &reg_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)
1470 | SetBit (4)
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)
1475 | SetBit (6);
1476 newmode.crtc[0x10] = Set8Bits (vStart);
1477 newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0)
1478 | SetBit (5);
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,
1491 vTotal, dotClock);
1493 rinfo->initial_state = newmode;
1494 riva_load_state (rinfo, &newmode);
1498 /* ------------------------------------------------------------------------- */
1502 * Modularization
1505 static struct pci_driver rivafb_driver = {
1506 name: "rivafb",
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);
1525 #ifdef MODULE
1526 module_init(rivafb_init);
1527 #endif /* MODULE */
1528 module_exit(rivafb_exit);
1530 MODULE_AUTHOR("Ani Joshi, maintainer");
1531 MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2");
1534 /* from GGI */
1535 static void riva_save_state (struct rivafb_info *rinfo, struct riva_regs *regs)
1537 int i;
1539 outb (rinfo->riva.LockUnlockIndex, rinfo->riva.LockUnlockIO);
1540 outb (0x57, rinfo->riva.LockUnlockIO + 1);
1542 rinfo->riva.UnloadStateExt (&rinfo->riva, &regs->ext);
1544 regs->misc_output = io_in8 (0x3CC);
1546 for (i = 0; i < NUM_CRT_REGS; i++) {
1547 io_out8 (i, 0x3D4);
1548 regs->crtc[i] = io_in8 (0x3D5);
1551 for (i = 0; i < NUM_ATC_REGS; i++) {
1552 io_out8 (i, 0x3C0);
1553 regs->attr[i] = io_in8 (0x3C1);
1556 for (i = 0; i < NUM_GRC_REGS; i++) {
1557 io_out8 (i, 0x3CE);
1558 regs->gra[i] = io_in8 (0x3CF);
1562 for (i = 0; i < NUM_SEQ_REGS; i++) {
1563 io_out8 (i, 0x3C4);
1564 regs->seq[i] = io_in8 (0x3C5);
1569 /* from GGI */
1570 static
1571 void riva_load_state (struct rivafb_info *rinfo, struct riva_regs *regs)
1573 int i;
1574 RIVA_HW_STATE *state = &regs->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++) {
1587 if (i < 0x19) {
1588 io_out8 (i, 0x3D4);
1589 io_out8 (regs->crtc[i], 0x3D5);
1590 } else {
1591 switch (i) {
1592 case 0x19:
1593 case 0x20:
1594 case 0x21:
1595 case 0x22:
1596 case 0x23:
1597 case 0x24:
1598 case 0x25:
1599 case 0x26:
1600 case 0x27:
1601 case 0x28:
1602 case 0x29:
1603 case 0x2a:
1604 case 0x2b:
1605 case 0x2c:
1606 case 0x2d:
1607 case 0x2e:
1608 case 0x2f:
1609 case 0x30:
1610 case 0x31:
1611 case 0x32:
1612 case 0x33:
1613 case 0x34:
1614 case 0x35:
1615 case 0x36:
1616 case 0x37:
1617 case 0x38:
1618 case 0x39:
1619 case 0x3a:
1620 case 0x3b:
1621 case 0x3c:
1622 case 0x3d:
1623 case 0x3e:
1624 case 0x3f:
1625 case 0x40:
1626 break;
1627 default:
1628 io_out8 (i, 0x3D4);
1629 io_out8 (regs->crtc[i], 0x3D5);
1634 for (i = 0; i < NUM_ATC_REGS; i++) {
1635 io_out8 (i, 0x3C0);
1636 io_out8 (regs->attr[i], 0x3C0);
1639 for (i = 0; i < NUM_GRC_REGS; i++) {
1640 io_out8 (i, 0x3CE);
1641 io_out8 (regs->gra[i], 0x3CF);
1644 for (i = 0; i < NUM_SEQ_REGS; i++) {
1645 io_out8 (i, 0x3C4);
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
1658 * DESCRIPTION:
1659 * Adds @new_node to the list referenced by @board_list
1661 * RETURNS:
1662 * New root node
1664 static
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)
1673 return new_node;
1675 while (i_p->next != NULL)
1676 i_p = i_p->next;
1677 i_p->next = new_node;
1679 return board_list;
1685 * riva_board_list_del
1686 * @board_list: Root node of list of boards
1687 * @del_node: Node to be removed
1689 * DESCRIPTION:
1690 * Removes @del_node from the list referenced by @board_list
1692 * RETURNS:
1693 * New root node
1695 static
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)
1705 i_p = i_p->next;
1706 i_p->next = del_node->next;
1708 return board_list;