1/* 2 * linux/drivers/video/neofb.c -- NeoMagic Framebuffer Driver 3 * 4 * Copyright (c) 2001 Denis Oliver Kropp <dok@convergence.de> 5 * 6 * 7 * Card specific code is based on XFree86's neomagic driver. 8 * Framebuffer framework code is based on code of cyber2000fb. 9 * 10 * This file is subject to the terms and conditions of the GNU General 11 * Public License. See the file COPYING in the main directory of this 12 * archive for more details. 13 * 14 * 15 * 0.3.2 16 * - got rid of all floating point (dok) 17 * 18 * 0.3.1 19 * - added module license (dok) 20 * 21 * 0.3 22 * - hardware accelerated clear and move for 2200 and above (dok) 23 * - maximum allowed dotclock is handled now (dok) 24 * 25 * 0.2.1 26 * - correct panning after X usage (dok) 27 * - added module and kernel parameters (dok) 28 * - no stretching if external display is enabled (dok) 29 * 30 * 0.2 31 * - initial version (dok) 32 * 33 * 34 * TODO 35 * - ioctl for internal/external switching 36 * - blanking 37 * - 32bit depth support, maybe impossible 38 * - disable pan-on-sync, need specs 39 * 40 * BUGS 41 * - white margin on bootup like with tdfxfb (colormap problem?) 42 * 43 */ 44 45#include <linux/config.h> 46#include <linux/module.h> 47#include <linux/kernel.h> 48#include <linux/errno.h> 49#include <linux/string.h> 50#include <linux/mm.h> 51#include <linux/tty.h> 52#include <linux/slab.h> 53#include <linux/delay.h> 54#include <linux/fb.h> 55#include <linux/pci.h> 56#include <linux/init.h> 57 58#include <asm/io.h> 59#include <asm/irq.h> 60#include <asm/pgtable.h> 61#include <asm/system.h> 62#include <asm/uaccess.h> 63 64#ifdef CONFIG_MTRR 65#include <asm/mtrr.h> 66#endif 67 68#include <video/fbcon.h> 69#include <video/fbcon-cfb8.h> 70#include <video/fbcon-cfb16.h> 71#include <video/fbcon-cfb24.h> 72#include <video/fbcon-cfb32.h> 73 74#include "neofb.h" 75 76 77#define NEOFB_VERSION "0.3.2" 78 79/* --------------------------------------------------------------------- */ 80 81static int disabled = 0; 82static int internal = 0; 83static int external = 0; 84static int nostretch = 0; 85static int nopciburst = 0; 86 87 88#ifdef MODULE 89 90MODULE_AUTHOR("(c) 2001-2002 Denis Oliver Kropp <dok@convergence.de>"); 91MODULE_LICENSE("GPL"); 92MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips"); 93MODULE_PARM(disabled, "i"); 94MODULE_PARM_DESC(disabled, "Disable this driver's initialization."); 95MODULE_PARM(internal, "i"); 96MODULE_PARM_DESC(internal, "Enable output on internal LCD Display."); 97MODULE_PARM(external, "i"); 98MODULE_PARM_DESC(external, "Enable output on external CRT."); 99MODULE_PARM(nostretch, "i"); 100MODULE_PARM_DESC(nostretch, "Disable stretching of modes smaller than LCD."); 101MODULE_PARM(nopciburst, "i"); 102MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode."); 103 104#endif 105 106 107/* --------------------------------------------------------------------- */ 108 109static biosMode bios8[] = { 110 { 320, 240, 0x40 }, 111 { 300, 400, 0x42 }, 112 { 640, 400, 0x20 }, 113 { 640, 480, 0x21 }, 114 { 800, 600, 0x23 }, 115 { 1024, 768, 0x25 }, 116}; 117 118static biosMode bios16[] = { 119 { 320, 200, 0x2e }, 120 { 320, 240, 0x41 }, 121 { 300, 400, 0x43 }, 122 { 640, 480, 0x31 }, 123 { 800, 600, 0x34 }, 124 { 1024, 768, 0x37 }, 125}; 126 127static biosMode bios24[] = { 128 { 640, 480, 0x32 }, 129 { 800, 600, 0x35 }, 130 { 1024, 768, 0x38 } 131}; 132 133#ifdef NO_32BIT_SUPPORT_YET 134static biosMode bios32[] = { 135 { 640, 480, 0x33 }, 136 { 800, 600, 0x36 }, 137 { 1024, 768, 0x39 } 138 }; 139#endif 140 141static int neoFindMode (int xres, int yres, int depth) 142{ 143 int xres_s; 144 int i, size; 145 biosMode *mode; 146 147 switch (depth) 148 { 149 case 8: 150 size = sizeof(bios8) / sizeof(biosMode); 151 mode = bios8; 152 break; 153 case 16: 154 size = sizeof(bios16) / sizeof(biosMode); 155 mode = bios16; 156 break; 157 case 24: 158 size = sizeof(bios24) / sizeof(biosMode); 159 mode = bios24; 160 break; 161#ifdef NO_32BIT_SUPPORT_YET 162 case 32: 163 size = sizeof(bios32) / sizeof(biosMode); 164 mode = bios32; 165 break; 166#endif 167 default: 168 return 0; 169 } 170 171 for (i = 0; i < size; i++) 172 { 173 if (xres <= mode[i].x_res) 174 { 175 xres_s = mode[i].x_res; 176 for (; i < size; i++) 177 { 178 if (mode[i].x_res != xres_s) 179 return mode[i-1].mode; 180 if (yres <= mode[i].y_res) 181 return mode[i].mode; 182 } 183 } 184 } 185 return mode[size - 1].mode; 186} 187 188/* -------------------- Hardware specific routines ------------------------- */ 189 190/* 191 * Hardware Acceleration for Neo2200+ 192 */ 193static inline void neo2200_wait_idle (struct neofb_info *fb) 194{ 195 int waitcycles; 196 197 while (fb->neo2200->bltStat & 1) 198 waitcycles++; 199} 200 201static inline void neo2200_wait_fifo (struct neofb_info *fb, 202 int requested_fifo_space) 203{ 204 // ndev->neo.waitfifo_calls++; 205 // ndev->neo.waitfifo_sum += requested_fifo_space; 206 207 208 neo2200_wait_idle (fb); 209} 210 211static inline void neo2200_accel_init (struct neofb_info *fb, 212 struct fb_var_screeninfo *var) 213{ 214 Neo2200 *neo2200 = fb->neo2200; 215 u32 bltMod, pitch; 216 217 neo2200_wait_idle (fb); 218 219 switch (var->bits_per_pixel) 220 { 221 case 8: 222 bltMod = NEO_MODE1_DEPTH8; 223 pitch = var->xres_virtual; 224 break; 225 case 15: 226 case 16: 227 bltMod = NEO_MODE1_DEPTH16; 228 pitch = var->xres_virtual * 2; 229 break; 230 default: 231 printk( KERN_ERR "neofb: neo2200_accel_init: unexpected bits per pixel!\n" ); 232 return; 233 } 234 235 neo2200->bltStat = bltMod << 16; 236 neo2200->pitch = (pitch << 16) | pitch; 237} 238 239static void neo2200_accel_setup (struct display *p) 240{ 241 struct neofb_info *fb = (struct neofb_info *)p->fb_info; 242 struct fb_var_screeninfo *var = &p->fb_info->var; 243 244 fb->dispsw->setup(p); 245 246 neo2200_accel_init (fb, var); 247} 248 249static void 250neo2200_accel_bmove (struct display *p, int sy, int sx, int dy, int dx, 251 int height, int width) 252{ 253 struct neofb_info *fb = (struct neofb_info *)p->fb_info; 254 struct fb_var_screeninfo *var = &p->fb_info->var; 255 Neo2200 *neo2200 = fb->neo2200; 256 u_long src, dst; 257 int bpp, pitch, inc_y; 258 u_int fh, fw; 259 260 if (sx != dx) 261 { 262 neo2200_wait_idle (fb); 263 fb->dispsw->bmove(p, sy, sx, dy, dx, height, width); 264 return; 265 } 266 267 bpp = (var->bits_per_pixel+7) / 8; 268 pitch = var->xres_virtual * bpp; 269 270 fw = fontwidth(p); 271 sx *= fw * bpp; 272 dx *= fw * bpp; 273 width *= fw; 274 275 fh = fontheight(p); 276 sy *= fh; 277 dy *= fh; 278 279 if (sy > dy) 280 inc_y = fh; 281 else 282 { 283 inc_y = -fh; 284 sy += (height - 1) * fh; 285 dy += (height - 1) * fh; 286 } 287 288 neo2200_wait_fifo (fb, 1); 289 290 /* set blt control */ 291 neo2200->bltCntl = NEO_BC3_FIFO_EN | 292 NEO_BC3_SKIP_MAPPING | 0x0c0000; 293 294 while (height--) 295 { 296 src = sx + sy * pitch; 297 dst = dx + dy * pitch; 298 299 neo2200_wait_fifo (fb, 3); 300 301 neo2200->srcStart = src; 302 neo2200->dstStart = dst; 303 neo2200->xyExt = (fh << 16) | (width & 0xffff); 304 305 sy += inc_y; 306 dy += inc_y; 307 } 308} 309 310static void 311neo2200_accel_clear (struct vc_data *conp, struct display *p, int sy, int sx, 312 int height, int width) 313{ 314 struct neofb_info *fb = (struct neofb_info *)p->fb_info; 315 struct fb_var_screeninfo *var = &p->fb_info->var; 316 Neo2200 *neo2200 = fb->neo2200; 317 u_long dst; 318 u_int fw, fh; 319 u32 bgx = attr_bgcol_ec(p, conp); 320 321 fw = fontwidth(p); 322 fh = fontheight(p); 323 324 dst = sx * fw + sy * var->xres_virtual * fh; 325 width = width * fw; 326 height = height * fh; 327 328 neo2200_wait_fifo (fb, 4); 329 330 /* set blt control */ 331 neo2200->bltCntl = NEO_BC3_FIFO_EN | 332 NEO_BC0_SRC_IS_FG | 333 NEO_BC3_SKIP_MAPPING | 0x0c0000; 334 335 switch (var->bits_per_pixel) 336 { 337 case 8: 338 neo2200->fgColor = bgx; 339 break; 340 case 16: 341 neo2200->fgColor = ((u16 *)(p->fb_info)->pseudo_palette)[bgx]; 342 break; 343 } 344 345 neo2200->dstStart = dst * ((var->bits_per_pixel+7) / 8); 346 347 neo2200->xyExt = (height << 16) | (width & 0xffff); 348} 349 350static void 351neo2200_accel_putc (struct vc_data *conp, struct display *p, int c, 352 int yy, int xx) 353{ 354 struct neofb_info *fb = (struct neofb_info *)p->fb_info; 355 356 neo2200_wait_idle (fb); 357 fb->dispsw->putc(conp, p, c, yy, xx); 358} 359 360static void 361neo2200_accel_putcs (struct vc_data *conp, struct display *p, 362 const unsigned short *s, int count, int yy, int xx) 363{ 364 struct neofb_info *fb = (struct neofb_info *)p->fb_info; 365 366 neo2200_wait_idle (fb); 367 fb->dispsw->putcs(conp, p, s, count, yy, xx); 368} 369 370static void neo2200_accel_revc (struct display *p, int xx, int yy) 371{ 372 struct neofb_info *fb = (struct neofb_info *)p->fb_info; 373 374 neo2200_wait_idle (fb); 375 fb->dispsw->revc (p, xx, yy); 376} 377 378static void 379neo2200_accel_clear_margins (struct vc_data *conp, struct display *p, 380 int bottom_only) 381{ 382 struct neofb_info *fb = (struct neofb_info *)p->fb_info; 383 384 fb->dispsw->clear_margins (conp, p, bottom_only); 385} 386 387static struct display_switch fbcon_neo2200_accel = { 388 setup: neo2200_accel_setup, 389 bmove: neo2200_accel_bmove, 390 clear: neo2200_accel_clear, 391 putc: neo2200_accel_putc, 392 putcs: neo2200_accel_putcs, 393 revc: neo2200_accel_revc, 394 clear_margins: neo2200_accel_clear_margins, 395 fontwidthmask: FONTWIDTH(8)|FONTWIDTH(16) 396}; 397 398 399/* --------------------------------------------------------------------- */ 400 401/* 402 * Set a single color register. Return != 0 for invalid regno. 403 */ 404static int neo_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 405 u_int transp, struct fb_info *fb) 406{ 407 struct neofb_info *info = (struct neofb_info *)fb; 408 409 if (regno >= NR_PALETTE) 410 return -EINVAL; 411 412 info->palette[regno].red = red; 413 info->palette[regno].green = green; 414 info->palette[regno].blue = blue; 415 info->palette[regno].transp = transp; 416 417 switch (fb->var.bits_per_pixel) 418 { 419#ifdef FBCON_HAS_CFB8 420 case 8: 421 outb(regno, 0x3c8); 422 423 outb(red >> 10, 0x3c9); 424 outb(green >> 10, 0x3c9); 425 outb(blue >> 10, 0x3c9); 426 break; 427#endif 428 429#ifdef FBCON_HAS_CFB16 430 case 16: 431 if (regno < 16) 432 ((u16 *)fb->pseudo_palette)[regno] = ((red & 0xf800) ) | 433 ((green & 0xfc00) >> 5) | 434 ((blue & 0xf800) >> 11); 435 break; 436#endif 437 438#ifdef FBCON_HAS_CFB24 439 case 24: 440 if (regno < 16) 441 ((u32 *)fb->pseudo_palette)[regno] = ((red & 0xff00) << 8) | 442 ((green & 0xff00) ) | 443 ((blue & 0xff00) >> 8); 444 break; 445#endif 446 447#ifdef NO_32BIT_SUPPORT_YET 448#ifdef FBCON_HAS_CFB32 449 case 32: 450 if (regno < 16) 451 ((u32 *)fb->pseudo_palette)[regno] = ((transp & 0xff00) << 16) | 452 ((red & 0xff00) << 8) | 453 ((green & 0xff00) ) | 454 ((blue & 0xff00) >> 8); 455 break; 456#endif 457#endif 458 459 default: 460 return 1; 461 } 462 463 return 0; 464} 465 466static void vgaHWLock (void) 467{ 468 /* Protect CRTC[0-7] */ 469 VGAwCR (0x11, VGArCR (0x11) | 0x80); 470} 471 472static void vgaHWUnlock (void) 473{ 474 /* Unprotect CRTC[0-7] */ 475 VGAwCR (0x11, VGArCR (0x11) & ~0x80); 476} 477 478static void neoLock (void) 479{ 480 VGAwGR (0x09, 0x00); 481 vgaHWLock(); 482} 483 484static void neoUnlock (void) 485{ 486 vgaHWUnlock(); 487 VGAwGR (0x09, 0x26); 488} 489 490/* 491 * vgaHWSeqReset 492 * perform a sequencer reset. 493 */ 494void 495vgaHWSeqReset(int start) 496{ 497 if (start) 498 VGAwSEQ (0x00, 0x01); /* Synchronous Reset */ 499 else 500 VGAwSEQ (0x00, 0x03); /* End Reset */ 501} 502 503void 504vgaHWProtect(int on) 505{ 506 unsigned char tmp; 507 508 if (on) 509 { 510 /* 511 * Turn off screen and disable sequencer. 512 */ 513 tmp = VGArSEQ (0x01); 514 515 vgaHWSeqReset (1); /* start synchronous reset */ 516 VGAwSEQ (0x01, tmp | 0x20); /* disable the display */ 517 518 VGAenablePalette(); 519 } 520 else 521 { 522 /* 523 * Reenable sequencer, then turn on screen. 524 */ 525 526 tmp = VGArSEQ (0x01); 527 528 VGAwSEQ (0x01, tmp & ~0x20); /* reenable display */ 529 vgaHWSeqReset (0); /* clear synchronousreset */ 530 531 VGAdisablePalette(); 532 } 533} 534 535static void vgaHWRestore (const struct neofb_info *info, 536 const struct neofb_par *par) 537{ 538 int i; 539 540 VGAwMISC (par->MiscOutReg); 541 542 for (i = 1; i < 5; i++) 543 VGAwSEQ (i, par->Sequencer[i]); 544 545 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */ 546 VGAwCR (17, par->CRTC[17] & ~0x80); 547 548 for (i = 0; i < 25; i++) 549 VGAwCR (i, par->CRTC[i]); 550 551 for (i = 0; i < 9; i++) 552 VGAwGR (i, par->Graphics[i]); 553 554 VGAenablePalette(); 555 556 for (i = 0; i < 21; i++) 557 VGAwATTR (i, par->Attribute[i]); 558 559 VGAdisablePalette(); 560} 561 562static void neofb_set_par (struct neofb_info *info, 563 const struct neofb_par *par) 564{ 565 unsigned char temp; 566 int i; 567 int clock_hi = 0; 568 569 DBG("neofb_set_par"); 570 571 neoUnlock(); 572 573 vgaHWProtect (1); /* Blank the screen */ 574 575 /* linear colormap for non palettized modes */ 576 switch (par->depth) 577 { 578 case 8: 579 break; 580 case 16: 581 for (i=0; i<64; i++) 582 { 583 outb(i, 0x3c8); 584 585 outb(i << 1, 0x3c9); 586 outb(i, 0x3c9); 587 outb(i << 1, 0x3c9); 588 } 589 break; 590 case 24: 591#ifdef NO_32BIT_SUPPORT_YET 592 case 32: 593#endif 594 for (i=0; i<256; i++) 595 { 596 outb(i, 0x3c8); 597 598 outb(i, 0x3c9); 599 outb(i, 0x3c9); 600 outb(i, 0x3c9); 601 } 602 break; 603 } 604 605 /* alread unlocked above */ 606 /* BOGUS VGAwGR (0x09, 0x26);*/ 607 608 /* don't know what this is, but it's 0 from bootup anyway */ 609 VGAwGR (0x15, 0x00); 610 611 /* was set to 0x01 by my bios in text and vesa modes */ 612 VGAwGR (0x0A, par->GeneralLockReg); 613 614 /* 615 * The color mode needs to be set before calling vgaHWRestore 616 * to ensure the DAC is initialized properly. 617 * 618 * NOTE: Make sure we don't change bits make sure we don't change 619 * any reserved bits. 620 */ 621 temp = VGArGR(0x90); 622 switch (info->accel) 623 { 624 case FB_ACCEL_NEOMAGIC_NM2070: 625 temp &= 0xF0; /* Save bits 7:4 */ 626 temp |= (par->ExtColorModeSelect & ~0xF0); 627 break; 628 case FB_ACCEL_NEOMAGIC_NM2090: 629 case FB_ACCEL_NEOMAGIC_NM2093: 630 case FB_ACCEL_NEOMAGIC_NM2097: 631 case FB_ACCEL_NEOMAGIC_NM2160: 632 case FB_ACCEL_NEOMAGIC_NM2200: 633 case FB_ACCEL_NEOMAGIC_NM2230: 634 case FB_ACCEL_NEOMAGIC_NM2360: 635 case FB_ACCEL_NEOMAGIC_NM2380: 636 temp &= 0x70; /* Save bits 6:4 */ 637 temp |= (par->ExtColorModeSelect & ~0x70); 638 break; 639 } 640 641 VGAwGR(0x90,temp); 642 643 /* 644 * In some rare cases a lockup might occur if we don't delay 645 * here. (Reported by Miles Lane) 646 */ 647 //mdelay(200); 648 649 /* 650 * Disable horizontal and vertical graphics and text expansions so 651 * that vgaHWRestore works properly. 652 */ 653 temp = VGArGR(0x25); 654 temp &= 0x39; 655 VGAwGR (0x25, temp); 656 657 /* 658 * Sleep for 200ms to make sure that the two operations above have 659 * had time to take effect. 660 */ 661 mdelay(200); 662 663 /* 664 * This function handles restoring the generic VGA registers. */ 665 vgaHWRestore (info, par); 666 667 668 VGAwGR(0x0E, par->ExtCRTDispAddr); 669 VGAwGR(0x0F, par->ExtCRTOffset); 670 temp = VGArGR(0x10); 671 temp &= 0x0F; /* Save bits 3:0 */ 672 temp |= (par->SysIfaceCntl1 & ~0x0F); /* VESA Bios sets bit 1! */ 673 VGAwGR(0x10, temp); 674 675 VGAwGR(0x11, par->SysIfaceCntl2); 676 VGAwGR(0x15, 0 /*par->SingleAddrPage*/); 677 VGAwGR(0x16, 0 /*par->DualAddrPage*/); 678 679 temp = VGArGR(0x20); 680 switch (info->accel) 681 { 682 case FB_ACCEL_NEOMAGIC_NM2070: 683 temp &= 0xFC; /* Save bits 7:2 */ 684 temp |= (par->PanelDispCntlReg1 & ~0xFC); 685 break; 686 case FB_ACCEL_NEOMAGIC_NM2090: 687 case FB_ACCEL_NEOMAGIC_NM2093: 688 case FB_ACCEL_NEOMAGIC_NM2097: 689 case FB_ACCEL_NEOMAGIC_NM2160: 690 temp &= 0xDC; /* Save bits 7:6,4:2 */ 691 temp |= (par->PanelDispCntlReg1 & ~0xDC); 692 break; 693 case FB_ACCEL_NEOMAGIC_NM2200: 694 case FB_ACCEL_NEOMAGIC_NM2230: 695 case FB_ACCEL_NEOMAGIC_NM2360: 696 case FB_ACCEL_NEOMAGIC_NM2380: 697 temp &= 0x98; /* Save bits 7,4:3 */ 698 temp |= (par->PanelDispCntlReg1 & ~0x98); 699 break; 700 } 701 VGAwGR(0x20, temp); 702 703 temp = VGArGR(0x25); 704 temp &= 0x38; /* Save bits 5:3 */ 705 temp |= (par->PanelDispCntlReg2 & ~0x38); 706 VGAwGR(0x25, temp); 707 708 if (info->accel != FB_ACCEL_NEOMAGIC_NM2070) 709 { 710 temp = VGArGR(0x30); 711 temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */ 712 temp |= (par->PanelDispCntlReg3 & ~0xEF); 713 VGAwGR(0x30, temp); 714 } 715 716 VGAwGR(0x28, par->PanelVertCenterReg1); 717 VGAwGR(0x29, par->PanelVertCenterReg2); 718 VGAwGR(0x2a, par->PanelVertCenterReg3); 719 720 if (info->accel != FB_ACCEL_NEOMAGIC_NM2070) 721 { 722 VGAwGR(0x32, par->PanelVertCenterReg4); 723 VGAwGR(0x33, par->PanelHorizCenterReg1); 724 VGAwGR(0x34, par->PanelHorizCenterReg2); 725 VGAwGR(0x35, par->PanelHorizCenterReg3); 726 } 727 728 if (info->accel == FB_ACCEL_NEOMAGIC_NM2160) 729 VGAwGR(0x36, par->PanelHorizCenterReg4); 730 731 if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 || 732 info->accel == FB_ACCEL_NEOMAGIC_NM2230 || 733 info->accel == FB_ACCEL_NEOMAGIC_NM2360 || 734 info->accel == FB_ACCEL_NEOMAGIC_NM2380) 735 { 736 VGAwGR(0x36, par->PanelHorizCenterReg4); 737 VGAwGR(0x37, par->PanelVertCenterReg5); 738 VGAwGR(0x38, par->PanelHorizCenterReg5); 739 740 clock_hi = 1; 741 } 742 743 /* Program VCLK3 if needed. */ 744 if (par->ProgramVCLK 745 && ((VGArGR(0x9B) != par->VCLK3NumeratorLow) 746 || (VGArGR(0x9F) != par->VCLK3Denominator) 747 || (clock_hi && ((VGArGR(0x8F) & ~0x0f) 748 != (par->VCLK3NumeratorHigh & ~0x0F))))) 749 { 750 VGAwGR(0x9B, par->VCLK3NumeratorLow); 751 if (clock_hi) 752 { 753 temp = VGArGR(0x8F); 754 temp &= 0x0F; /* Save bits 3:0 */ 755 temp |= (par->VCLK3NumeratorHigh & ~0x0F); 756 VGAwGR(0x8F, temp); 757 } 758 VGAwGR(0x9F, par->VCLK3Denominator); 759 } 760 761 if (par->biosMode) 762 VGAwCR(0x23, par->biosMode); 763 764 VGAwGR (0x93, 0xc0); /* Gives 5x faster framebuffer writes !!! */ 765 766 /* Program vertical extension register */ 767 if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 || 768 info->accel == FB_ACCEL_NEOMAGIC_NM2230 || 769 info->accel == FB_ACCEL_NEOMAGIC_NM2360 || 770 info->accel == FB_ACCEL_NEOMAGIC_NM2380) 771 { 772 VGAwCR(0x70, par->VerticalExt); 773 } 774 775 776 vgaHWProtect (0); /* Turn on screen */ 777 778 /* Calling this also locks offset registers required in update_start */ 779 neoLock(); 780} 781 782static void neofb_update_start (struct neofb_info *info, struct fb_var_screeninfo *var) 783{ 784 int oldExtCRTDispAddr; 785 int Base; 786 787 DBG("neofb_update_start"); 788 789 Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2; 790 Base *= (var->bits_per_pixel + 7) / 8; 791 792 neoUnlock(); 793 794 /* 795 * These are the generic starting address registers. 796 */ 797 VGAwCR(0x0C, (Base & 0x00FF00) >> 8); 798 VGAwCR(0x0D, (Base & 0x00FF)); 799 800 /* 801 * Make sure we don't clobber some other bits that might already 802 * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't 803 * be needed. 804 */ 805 oldExtCRTDispAddr = VGArGR(0x0E); 806 VGAwGR(0x0E,(((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0))); 807 808 neoLock(); 809} 810 811/* 812 * Set the Colormap 813 */ 814static int neofb_set_cmap(struct fb_cmap *cmap, int kspc, int con, 815 struct fb_info *fb) 816{ 817 struct neofb_info *info = (struct neofb_info *)fb; 818 struct display* disp = (con < 0) ? fb->disp : (fb_display + con); 819 struct fb_cmap *dcmap = &disp->cmap; 820 int err = 0; 821 822 /* no colormap allocated? */ 823 if (!dcmap->len) 824 { 825 int size; 826 827 if (fb->var.bits_per_pixel == 8) 828 size = NR_PALETTE; 829 else 830 size = 32; 831 832 err = fb_alloc_cmap (dcmap, size, 0); 833 } 834 835 /* 836 * we should be able to remove this test once fbcon has been 837 * "improved" --rmk 838 */ 839 if (!err && con == info->currcon) 840 { 841 err = fb_set_cmap (cmap, kspc, neo_setcolreg, fb); 842 dcmap = &fb->cmap; 843 } 844 845 if (!err) 846 fb_copy_cmap (cmap, dcmap, kspc ? 0 : 1); 847 848 return err; 849} 850 851/* 852 * neoCalcVCLK -- 853 * 854 * Determine the closest clock frequency to the one requested. 855 */ 856#define REF_FREQ 0xe517 /* 14.31818 in 20.12 fixed point */ 857#define MAX_N 127 858#define MAX_D 31 859#define MAX_F 1 860 861static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, long freq) 862{ 863 int n, d, f; 864 int n_best = 0, d_best = 0, f_best = 0; 865 long f_best_diff = (0x7ffff << 12); /* 20.12 */ 866 long f_target = (freq << 12) / 1000; /* 20.12 */ 867 868 for (f = 0; f <= MAX_F; f++) 869 for (n = 0; n <= MAX_N; n++) 870 for (d = 0; d <= MAX_D; d++) 871 { 872 long f_out; /* 20.12 */ 873 long f_diff; /* 20.12 */ 874 875 f_out = ((((n+1) << 12) / ((d+1)*(1<<f))) >> 12) * REF_FREQ; 876 f_diff = abs(f_out-f_target); 877 if (f_diff < f_best_diff) 878 { 879 f_best_diff = f_diff; 880 n_best = n; 881 d_best = d; 882 f_best = f; 883 } 884 } 885 886 if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 || 887 info->accel == FB_ACCEL_NEOMAGIC_NM2230 || 888 info->accel == FB_ACCEL_NEOMAGIC_NM2360 || 889 info->accel == FB_ACCEL_NEOMAGIC_NM2380) 890 { 891 /* NOT_DONE: We are trying the full range of the 2200 clock. 892 We should be able to try n up to 2047 */ 893 par->VCLK3NumeratorLow = n_best; 894 par->VCLK3NumeratorHigh = (f_best << 7); 895 } 896 else 897 par->VCLK3NumeratorLow = n_best | (f_best << 7); 898 899 par->VCLK3Denominator = d_best; 900 901#ifdef NEOFB_DEBUG 902 printk ("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d\n", 903 f_target >> 12, 904 par->VCLK3NumeratorLow, 905 par->VCLK3NumeratorHigh, 906 par->VCLK3Denominator, 907 f_best_diff >> 12); 908#endif 909} 910 911/* 912 * vgaHWInit -- 913 * Handle the initialization, etc. of a screen. 914 * Return FALSE on failure. 915 */ 916 917static int vgaHWInit (const struct fb_var_screeninfo *var, 918 const struct neofb_info *info, 919 struct neofb_par *par, 920 struct xtimings *timings) 921{ 922 par->MiscOutReg = 0x23; 923 924 if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT)) 925 par->MiscOutReg |= 0x40; 926 927 if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT)) 928 par->MiscOutReg |= 0x80; 929 930 /* 931 * Time Sequencer 932 */ 933 par->Sequencer[0] = 0x00; 934 par->Sequencer[1] = 0x01; 935 par->Sequencer[2] = 0x0F; 936 par->Sequencer[3] = 0x00; /* Font select */ 937 par->Sequencer[4] = 0x0E; /* Misc */ 938 939 /* 940 * CRTC Controller 941 */ 942 par->CRTC[0] = (timings->HTotal >> 3) - 5; 943 par->CRTC[1] = (timings->HDisplay >> 3) - 1; 944 par->CRTC[2] = (timings->HDisplay >> 3) - 1; 945 par->CRTC[3] = (((timings->HTotal >> 3) - 1) & 0x1F) | 0x80; 946 par->CRTC[4] = (timings->HSyncStart >> 3); 947 par->CRTC[5] = ((((timings->HTotal >> 3) - 1) & 0x20) << 2) 948 | (((timings->HSyncEnd >> 3)) & 0x1F); 949 par->CRTC[6] = (timings->VTotal - 2) & 0xFF; 950 par->CRTC[7] = (((timings->VTotal - 2) & 0x100) >> 8) 951 | (((timings->VDisplay - 1) & 0x100) >> 7) 952 | ((timings->VSyncStart & 0x100) >> 6) 953 | (((timings->VDisplay - 1) & 0x100) >> 5) 954 | 0x10 955 | (((timings->VTotal - 2) & 0x200) >> 4) 956 | (((timings->VDisplay - 1) & 0x200) >> 3) 957 | ((timings->VSyncStart & 0x200) >> 2); 958 par->CRTC[8] = 0x00; 959 par->CRTC[9] = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40; 960 961 if (timings->dblscan) 962 par->CRTC[9] |= 0x80; 963 964 par->CRTC[10] = 0x00; 965 par->CRTC[11] = 0x00; 966 par->CRTC[12] = 0x00; 967 par->CRTC[13] = 0x00; 968 par->CRTC[14] = 0x00; 969 par->CRTC[15] = 0x00; 970 par->CRTC[16] = timings->VSyncStart & 0xFF; 971 par->CRTC[17] = (timings->VSyncEnd & 0x0F) | 0x20; 972 par->CRTC[18] = (timings->VDisplay - 1) & 0xFF; 973 par->CRTC[19] = var->xres_virtual >> 4; 974 par->CRTC[20] = 0x00; 975 par->CRTC[21] = (timings->VDisplay - 1) & 0xFF; 976 par->CRTC[22] = (timings->VTotal - 1) & 0xFF; 977 par->CRTC[23] = 0xC3; 978 par->CRTC[24] = 0xFF; 979 980 /* 981 * are these unnecessary? 982 * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO); 983 * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO); 984 */ 985 986 /* 987 * Graphics Display Controller 988 */ 989 par->Graphics[0] = 0x00; 990 par->Graphics[1] = 0x00; 991 par->Graphics[2] = 0x00; 992 par->Graphics[3] = 0x00; 993 par->Graphics[4] = 0x00; 994 par->Graphics[5] = 0x40; 995 par->Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */ 996 par->Graphics[7] = 0x0F; 997 par->Graphics[8] = 0xFF; 998 999 1000 par->Attribute[0] = 0x00; /* standard colormap translation */ 1001 par->Attribute[1] = 0x01; 1002 par->Attribute[2] = 0x02; 1003 par->Attribute[3] = 0x03; 1004 par->Attribute[4] = 0x04; 1005 par->Attribute[5] = 0x05; 1006 par->Attribute[6] = 0x06; 1007 par->Attribute[7] = 0x07; 1008 par->Attribute[8] = 0x08; 1009 par->Attribute[9] = 0x09; 1010 par->Attribute[10] = 0x0A; 1011 par->Attribute[11] = 0x0B; 1012 par->Attribute[12] = 0x0C; 1013 par->Attribute[13] = 0x0D; 1014 par->Attribute[14] = 0x0E; 1015 par->Attribute[15] = 0x0F; 1016 par->Attribute[16] = 0x41; 1017 par->Attribute[17] = 0xFF; 1018 par->Attribute[18] = 0x0F; 1019 par->Attribute[19] = 0x00; 1020 par->Attribute[20] = 0x00; 1021 1022 return 0; 1023} 1024 1025static int neofb_decode_var (struct fb_var_screeninfo *var, 1026 const struct neofb_info *info, 1027 struct neofb_par *par) 1028{ 1029 struct xtimings timings; 1030 int lcd_stretch; 1031 int hoffset, voffset; 1032 int memlen, vramlen; 1033 int mode_ok = 0; 1034 unsigned int pixclock = var->pixclock; 1035 1036 DBG("neofb_decode_var"); 1037 1038 if (!pixclock) pixclock = 10000; /* 10ns = 100MHz */ 1039 timings.pixclock = 1000000000 / pixclock; 1040 if (timings.pixclock < 1) timings.pixclock = 1; 1041 timings.dblscan = var->vmode & FB_VMODE_DOUBLE; 1042 timings.interlaced = var->vmode & FB_VMODE_INTERLACED; 1043 timings.HDisplay = var->xres; 1044 timings.HSyncStart = timings.HDisplay + var->right_margin; 1045 timings.HSyncEnd = timings.HSyncStart + var->hsync_len; 1046 timings.HTotal = timings.HSyncEnd + var->left_margin; 1047 timings.VDisplay = var->yres; 1048 timings.VSyncStart = timings.VDisplay + var->lower_margin; 1049 timings.VSyncEnd = timings.VSyncStart + var->vsync_len; 1050 timings.VTotal = timings.VSyncEnd + var->upper_margin; 1051 timings.sync = var->sync; 1052 1053 if (timings.pixclock > info->maxClock) 1054 return -EINVAL; 1055 1056 /* Is the mode larger than the LCD panel? */ 1057 if ((var->xres > info->NeoPanelWidth) || 1058 (var->yres > info->NeoPanelHeight)) 1059 { 1060 printk (KERN_INFO "Mode (%dx%d) larger than the LCD panel (%dx%d)\n", 1061 var->xres, 1062 var->yres, 1063 info->NeoPanelWidth, 1064 info->NeoPanelHeight); 1065 return -EINVAL; 1066 } 1067 1068 /* Is the mode one of the acceptable sizes? */ 1069 switch (var->xres) 1070 { 1071 case 1280: 1072 if (var->yres == 1024) 1073 mode_ok = 1; 1074 break; 1075 case 1024: 1076 if (var->yres == 768) 1077 mode_ok = 1; 1078 break; 1079 case 800: 1080 if (var->yres == 600) 1081 mode_ok = 1; 1082 break; 1083 case 640: 1084 if (var->yres == 480) 1085 mode_ok = 1; 1086 break; 1087 } 1088 1089 if (!mode_ok) 1090 { 1091 printk (KERN_INFO "Mode (%dx%d) won't display properly on LCD\n", 1092 var->xres, var->yres); 1093 return -EINVAL; 1094 } 1095 1096 1097 switch (var->bits_per_pixel) 1098 { 1099#ifdef FBCON_HAS_CFB8 1100 case 8: 1101 break; 1102#endif 1103 1104#ifdef FBCON_HAS_CFB16 1105 case 16: 1106 break; 1107#endif 1108 1109#ifdef FBCON_HAS_CFB24 1110 case 24: 1111 break; 1112#endif 1113 1114#ifdef NO_32BIT_SUPPORT_YET 1115# ifdef FBCON_HAS_CFB32 1116 case 32: 1117 break; 1118# endif 1119#endif 1120 1121 default: 1122 return -EINVAL; 1123 } 1124 1125 par->depth = var->bits_per_pixel; 1126 1127 vramlen = info->video.len; 1128 if (vramlen > 4*1024*1024) 1129 vramlen = 4*1024*1024; 1130 1131 if (var->yres_virtual < var->yres) 1132 var->yres_virtual = var->yres; 1133 if (var->xres_virtual < var->xres) 1134 var->xres_virtual = var->xres; 1135 1136 memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8; 1137 if (memlen > vramlen) 1138 { 1139 var->yres_virtual = vramlen * 8 / (var->xres_virtual * var->bits_per_pixel); 1140 memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8; 1141 } 1142 1143 /* we must round yres/xres down, we already rounded y/xres_virtual up 1144 if it was possible. We should return -EINVAL, but I disagree */ 1145 if (var->yres_virtual < var->yres) 1146 var->yres = var->yres_virtual; 1147 if (var->xres_virtual < var->xres) 1148 var->xres = var->xres_virtual; 1149 if (var->xoffset + var->xres > var->xres_virtual) 1150 var->xoffset = var->xres_virtual - var->xres; 1151 if (var->yoffset + var->yres > var->yres_virtual) 1152 var->yoffset = var->yres_virtual - var->yres; 1153 1154 1155 /* 1156 * This will allocate the datastructure and initialize all of the 1157 * generic VGA registers. 1158 */ 1159 1160 if (vgaHWInit (var, info, par, &timings)) 1161 return -EINVAL; 1162 1163 /* 1164 * The default value assigned by vgaHW.c is 0x41, but this does 1165 * not work for NeoMagic. 1166 */ 1167 par->Attribute[16] = 0x01; 1168 1169 switch (var->bits_per_pixel) 1170 { 1171 case 8: 1172 par->CRTC[0x13] = var->xres_virtual >> 3; 1173 par->ExtCRTOffset = var->xres_virtual >> 11; 1174 par->ExtColorModeSelect = 0x11; 1175 break; 1176 case 16: 1177 par->CRTC[0x13] = var->xres_virtual >> 2; 1178 par->ExtCRTOffset = var->xres_virtual >> 10; 1179 par->ExtColorModeSelect = 0x13; 1180 break; 1181 case 24: 1182 par->CRTC[0x13] = (var->xres_virtual * 3) >> 3; 1183 par->ExtCRTOffset = (var->xres_virtual * 3) >> 11; 1184 par->ExtColorModeSelect = 0x14; 1185 break; 1186#ifdef NO_32BIT_SUPPORT_YET 1187 case 32: 1188 par->CRTC[0x13] = var->xres_virtual >> 1; 1189 par->ExtCRTOffset = var->xres_virtual >> 9; 1190 par->ExtColorModeSelect = 0x15; 1191 break; 1192#endif 1193 default: 1194 break; 1195 } 1196 1197 par->ExtCRTDispAddr = 0x10; 1198 1199 /* Vertical Extension */ 1200 par->VerticalExt = (((timings.VTotal -2) & 0x400) >> 10 ) 1201 | (((timings.VDisplay -1) & 0x400) >> 9 ) 1202 | (((timings.VSyncStart) & 0x400) >> 8 ) 1203 | (((timings.VSyncStart) & 0x400) >> 7 ); 1204 1205 /* Fast write bursts on unless disabled. */ 1206 if (info->pci_burst) 1207 par->SysIfaceCntl1 = 0x30; 1208 else 1209 par->SysIfaceCntl1 = 0x00; 1210 1211 par->SysIfaceCntl2 = 0xc0; /* VESA Bios sets this to 0x80! */ 1212 1213 /* Enable any user specified display devices. */ 1214 par->PanelDispCntlReg1 = 0x00; 1215 if (info->internal_display) 1216 par->PanelDispCntlReg1 |= 0x02; 1217 if (info->external_display) 1218 par->PanelDispCntlReg1 |= 0x01; 1219 1220 /* If the user did not specify any display devices, then... */ 1221 if (par->PanelDispCntlReg1 == 0x00) { 1222 /* Default to internal (i.e., LCD) only. */ 1223 par->PanelDispCntlReg1 |= 0x02; 1224 } 1225 1226 /* If we are using a fixed mode, then tell the chip we are. */ 1227 switch (var->xres) 1228 { 1229 case 1280: 1230 par->PanelDispCntlReg1 |= 0x60; 1231 break; 1232 case 1024: 1233 par->PanelDispCntlReg1 |= 0x40; 1234 break; 1235 case 800: 1236 par->PanelDispCntlReg1 |= 0x20; 1237 break; 1238 case 640: 1239 default: 1240 break; 1241 } 1242 1243 /* Setup shadow register locking. */ 1244 switch (par->PanelDispCntlReg1 & 0x03) 1245 { 1246 case 0x01: /* External CRT only mode: */ 1247 par->GeneralLockReg = 0x00; 1248 /* We need to program the VCLK for external display only mode. */ 1249 par->ProgramVCLK = 1; 1250 break; 1251 case 0x02: /* Internal LCD only mode: */ 1252 case 0x03: /* Simultaneous internal/external (LCD/CRT) mode: */ 1253 par->GeneralLockReg = 0x01; 1254 /* Don't program the VCLK when using the LCD. */ 1255 par->ProgramVCLK = 0; 1256 break; 1257 } 1258 1259 /* 1260 * If the screen is to be stretched, turn on stretching for the 1261 * various modes. 1262 * 1263 * OPTION_LCD_STRETCH means stretching should be turned off! 1264 */ 1265 par->PanelDispCntlReg2 = 0x00; 1266 par->PanelDispCntlReg3 = 0x00; 1267 1268 if (info->lcd_stretch && 1269 (par->PanelDispCntlReg1 == 0x02) && /* LCD only */ 1270 (var->xres != info->NeoPanelWidth)) 1271 { 1272 switch (var->xres) 1273 { 1274 case 320: /* Needs testing. KEM -- 24 May 98 */ 1275 case 400: /* Needs testing. KEM -- 24 May 98 */ 1276 case 640: 1277 case 800: 1278 case 1024: 1279 lcd_stretch = 1; 1280 par->PanelDispCntlReg2 |= 0xC6; 1281 break; 1282 default: 1283 lcd_stretch = 0; 1284 /* No stretching in these modes. */ 1285 } 1286 } 1287 else 1288 lcd_stretch = 0; 1289 1290 /* 1291 * If the screen is to be centerd, turn on the centering for the 1292 * various modes. 1293 */ 1294 par->PanelVertCenterReg1 = 0x00; 1295 par->PanelVertCenterReg2 = 0x00; 1296 par->PanelVertCenterReg3 = 0x00; 1297 par->PanelVertCenterReg4 = 0x00; 1298 par->PanelVertCenterReg5 = 0x00; 1299 par->PanelHorizCenterReg1 = 0x00; 1300 par->PanelHorizCenterReg2 = 0x00; 1301 par->PanelHorizCenterReg3 = 0x00; 1302 par->PanelHorizCenterReg4 = 0x00; 1303 par->PanelHorizCenterReg5 = 0x00; 1304 1305 1306 if (par->PanelDispCntlReg1 & 0x02) 1307 { 1308 if (var->xres == info->NeoPanelWidth) 1309 { 1310 /* 1311 * No centering required when the requested display width 1312 * equals the panel width. 1313 */ 1314 } 1315 else 1316 { 1317 par->PanelDispCntlReg2 |= 0x01; 1318 par->PanelDispCntlReg3 |= 0x10; 1319 1320 /* Calculate the horizontal and vertical offsets. */ 1321 if (!lcd_stretch) 1322 { 1323 hoffset = ((info->NeoPanelWidth - var->xres) >> 4) - 1; 1324 voffset = ((info->NeoPanelHeight - var->yres) >> 1) - 2; 1325 } 1326 else 1327 { 1328 /* Stretched modes cannot be centered. */ 1329 hoffset = 0; 1330 voffset = 0; 1331 } 1332 1333 switch (var->xres) 1334 { 1335 case 320: /* Needs testing. KEM -- 24 May 98 */ 1336 par->PanelHorizCenterReg3 = hoffset; 1337 par->PanelVertCenterReg2 = voffset; 1338 break; 1339 case 400: /* Needs testing. KEM -- 24 May 98 */ 1340 par->PanelHorizCenterReg4 = hoffset; 1341 par->PanelVertCenterReg1 = voffset; 1342 break; 1343 case 640: 1344 par->PanelHorizCenterReg1 = hoffset; 1345 par->PanelVertCenterReg3 = voffset; 1346 break; 1347 case 800: 1348 par->PanelHorizCenterReg2 = hoffset; 1349 par->PanelVertCenterReg4 = voffset; 1350 break; 1351 case 1024: 1352 par->PanelHorizCenterReg5 = hoffset; 1353 par->PanelVertCenterReg5 = voffset; 1354 break; 1355 case 1280: 1356 default: 1357 /* No centering in these modes. */ 1358 break; 1359 } 1360 } 1361 } 1362 1363 par->biosMode = neoFindMode (var->xres, var->yres, var->bits_per_pixel); 1364 1365 /* 1366 * Calculate the VCLK that most closely matches the requested dot 1367 * clock. 1368 */ 1369 neoCalcVCLK (info, par, timings.pixclock); 1370 1371 /* Since we program the clocks ourselves, always use VCLK3. */ 1372 par->MiscOutReg |= 0x0C; 1373 1374 return 0; 1375} 1376 1377static int neofb_set_var (struct fb_var_screeninfo *var, int con, 1378 struct fb_info *fb) 1379{ 1380 struct neofb_info *info = (struct neofb_info *)fb; 1381 struct display *display; 1382 struct neofb_par par; 1383 int err, chgvar = 0; 1384 1385 DBG("neofb_set_var"); 1386 1387 err = neofb_decode_var (var, info, &par); 1388 if (err) 1389 return err; 1390 1391 if (var->activate & FB_ACTIVATE_TEST) 1392 return 0; 1393 1394 if (con < 0) 1395 { 1396 display = fb->disp; 1397 chgvar = 0; 1398 } 1399 else 1400 { 1401 display = fb_display + con; 1402 1403 if (fb->var.xres != var->xres) 1404 chgvar = 1; 1405 if (fb->var.yres != var->yres) 1406 chgvar = 1; 1407 if (fb->var.xres_virtual != var->xres_virtual) 1408 chgvar = 1; 1409 if (fb->var.yres_virtual != var->yres_virtual) 1410 chgvar = 1; 1411 if (fb->var.bits_per_pixel != var->bits_per_pixel) 1412 chgvar = 1; 1413 } 1414 1415 if (!info->neo2200) 1416 var->accel_flags &= ~FB_ACCELF_TEXT; 1417 1418 var->red.msb_right = 0; 1419 var->green.msb_right = 0; 1420 var->blue.msb_right = 0; 1421 1422 switch (var->bits_per_pixel) 1423 { 1424#ifdef FBCON_HAS_CFB8 1425 case 8: /* PSEUDOCOLOUR, 256 */ 1426 var->transp.offset = 0; 1427 var->transp.length = 0; 1428 var->red.offset = 0; 1429 var->red.length = 8; 1430 var->green.offset = 0; 1431 var->green.length = 8; 1432 var->blue.offset = 0; 1433 var->blue.length = 8; 1434 1435 fb->fix.visual = FB_VISUAL_PSEUDOCOLOR; 1436 info->dispsw = &fbcon_cfb8; 1437 display->dispsw_data = NULL; 1438 display->next_line = var->xres_virtual; 1439 break; 1440#endif 1441 1442#ifdef FBCON_HAS_CFB16 1443 case 16: /* DIRECTCOLOUR, 64k */ 1444 var->transp.offset = 0; 1445 var->transp.length = 0; 1446 var->red.offset = 11; 1447 var->red.length = 5; 1448 var->green.offset = 5; 1449 var->green.length = 6; 1450 var->blue.offset = 0; 1451 var->blue.length = 5; 1452 1453 fb->fix.visual = FB_VISUAL_DIRECTCOLOR; 1454 info->dispsw = &fbcon_cfb16; 1455 display->dispsw_data = fb->pseudo_palette; 1456 display->next_line = var->xres_virtual * 2; 1457 break; 1458#endif 1459 1460#ifdef FBCON_HAS_CFB24 1461 case 24: /* TRUECOLOUR, 16m */ 1462 var->transp.offset = 0; 1463 var->transp.length = 0; 1464 var->red.offset = 16; 1465 var->red.length = 8; 1466 var->green.offset = 8; 1467 var->green.length = 8; 1468 var->blue.offset = 0; 1469 var->blue.length = 8; 1470 1471 fb->fix.visual = FB_VISUAL_TRUECOLOR; 1472 info->dispsw = &fbcon_cfb24; 1473 display->dispsw_data = fb->pseudo_palette; 1474 display->next_line = var->xres_virtual * 3; 1475 1476 var->accel_flags &= ~FB_ACCELF_TEXT; 1477 break; 1478#endif 1479 1480#ifdef NO_32BIT_SUPPORT_YET 1481# ifdef FBCON_HAS_CFB32 1482 case 32: /* TRUECOLOUR, 16m */ 1483 var->transp.offset = 24; 1484 var->transp.length = 8; 1485 var->red.offset = 16; 1486 var->red.length = 8; 1487 var->green.offset = 8; 1488 var->green.length = 8; 1489 var->blue.offset = 0; 1490 var->blue.length = 8; 1491 1492 fb->fix.visual = FB_VISUAL_TRUECOLOR; 1493 info->dispsw = &fbcon_cfb32; 1494 display->dispsw_data = fb->pseudo_palette; 1495 display->next_line = var->xres_virtual * 4; 1496 1497 var->accel_flags &= ~FB_ACCELF_TEXT; 1498 break; 1499# endif 1500#endif 1501 1502 default: 1503 printk (KERN_WARNING "neofb: no support for %dbpp\n", var->bits_per_pixel); 1504 info->dispsw = &fbcon_dummy; 1505 var->accel_flags &= ~FB_ACCELF_TEXT; 1506 break; 1507 } 1508 1509 if (var->accel_flags & FB_ACCELF_TEXT) 1510 display->dispsw = &fbcon_neo2200_accel; 1511 else 1512 display->dispsw = info->dispsw; 1513 1514 fb->fix.line_length = display->next_line; 1515 1516 display->screen_base = fb->screen_base; 1517 display->line_length = fb->fix.line_length; 1518 display->visual = fb->fix.visual; 1519 display->type = fb->fix.type; 1520 display->type_aux = fb->fix.type_aux; 1521 display->ypanstep = fb->fix.ypanstep; 1522 display->ywrapstep = fb->fix.ywrapstep; 1523 display->can_soft_blank = 1; 1524 display->inverse = 0; 1525 1526 fb->var = *var; 1527 fb->var.activate &= ~FB_ACTIVATE_ALL; 1528 1529 /* 1530 * Update the old var. The fbcon drivers still use this. 1531 * Once they are using cfb->fb.var, this can be dropped. 1532 * --rmk 1533 */ 1534 display->var = fb->var; 1535 1536 /* 1537 * If we are setting all the virtual consoles, also set the 1538 * defaults used to create new consoles. 1539 */ 1540 if (var->activate & FB_ACTIVATE_ALL) 1541 fb->disp->var = fb->var; 1542 1543 if (chgvar && fb && fb->changevar) 1544 fb->changevar (con); 1545 1546 if (con == info->currcon) 1547 { 1548 if (chgvar || con < 0) 1549 neofb_set_par (info, &par); 1550 1551 neofb_update_start (info, var); 1552 fb_set_cmap (&fb->cmap, 1, neo_setcolreg, fb); 1553 1554 if (var->accel_flags & FB_ACCELF_TEXT) 1555 neo2200_accel_init (info, var); 1556 } 1557 1558 return 0; 1559} 1560 1561/* 1562 * Pan or Wrap the Display 1563 */ 1564static int neofb_pan_display (struct fb_var_screeninfo *var, int con, 1565 struct fb_info *fb) 1566{ 1567 struct neofb_info *info = (struct neofb_info *)fb; 1568 u_int y_bottom; 1569 1570 y_bottom = var->yoffset; 1571 1572 if (!(var->vmode & FB_VMODE_YWRAP)) 1573 y_bottom += var->yres; 1574 1575 if (var->xoffset > (var->xres_virtual - var->xres)) 1576 return -EINVAL; 1577 if (y_bottom > fb->var.yres_virtual) 1578 return -EINVAL; 1579 1580 neofb_update_start (info, var); 1581 1582 fb->var.xoffset = var->xoffset; 1583 fb->var.yoffset = var->yoffset; 1584 1585 if (var->vmode & FB_VMODE_YWRAP) 1586 fb->var.vmode |= FB_VMODE_YWRAP; 1587 else 1588 fb->var.vmode &= ~FB_VMODE_YWRAP; 1589 1590 return 0; 1591} 1592 1593 1594/* 1595 * Update the `var' structure (called by fbcon.c) 1596 * 1597 * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'. 1598 * Since it's called by a kernel driver, no range checking is done. 1599 */ 1600static int neofb_updatevar (int con, struct fb_info *fb) 1601{ 1602 struct neofb_info *info = (struct neofb_info *)fb; 1603 1604 neofb_update_start (info, &fb_display[con].var); 1605 1606 return 0; 1607} 1608 1609static int neofb_switch (int con, struct fb_info *fb) 1610{ 1611 struct neofb_info *info = (struct neofb_info *)fb; 1612 struct display *disp; 1613 struct fb_cmap *cmap; 1614 1615 if (info->currcon >= 0) 1616 { 1617 disp = fb_display + info->currcon; 1618 1619 /* 1620 * Save the old colormap and video mode. 1621 */ 1622 disp->var = fb->var; 1623 if (disp->cmap.len) 1624 fb_copy_cmap(&fb->cmap, &disp->cmap, 0); 1625 } 1626 1627 info->currcon = con; 1628 disp = fb_display + con; 1629 1630 /* 1631 * Install the new colormap and change the video mode. By default, 1632 * fbcon sets all the colormaps and video modes to the default 1633 * values at bootup. 1634 * 1635 * Really, we want to set the colourmap size depending on the 1636 * depth of the new video mode. For now, we leave it at its 1637 * default 256 entry. 1638 */ 1639 if (disp->cmap.len) 1640 cmap = &disp->cmap; 1641 else 1642 cmap = fb_default_cmap(1 << disp->var.bits_per_pixel); 1643 1644 fb_copy_cmap(cmap, &fb->cmap, 0); 1645 1646 disp->var.activate = FB_ACTIVATE_NOW; 1647 neofb_set_var(&disp->var, con, fb); 1648 1649 return 0; 1650} 1651 1652/* 1653 * (Un)Blank the display. 1654 */ 1655static void neofb_blank (int blank, struct fb_info *fb) 1656{ 1657 // struct neofb_info *info = (struct neofb_info *)fb; 1658 1659 /* 1660 * Blank the screen if blank_mode != 0, else unblank. If 1661 * blank == NULL then the caller blanks by setting the CLUT 1662 * (Color Look Up Table) to all black. Return 0 if blanking 1663 * succeeded, != 0 if un-/blanking failed due to e.g. a 1664 * video mode which doesn't support it. Implements VESA 1665 * suspend and powerdown modes on hardware that supports 1666 * disabling hsync/vsync: 1667 * blank_mode == 2: suspend vsync 1668 * blank_mode == 3: suspend hsync 1669 * blank_mode == 4: powerdown 1670 * 1671 * wms...Enable VESA DMPS compatible powerdown mode 1672 * run "setterm -powersave powerdown" to take advantage 1673 */ 1674 1675 switch (blank) 1676 { 1677 case 4: /* powerdown - both sync lines down */ 1678 break; 1679 case 3: /* hsync off */ 1680 break; 1681 case 2: /* vsync off */ 1682 break; 1683 case 1: /* just software blanking of screen */ 1684 break; 1685 default: /* case 0, or anything else: unblank */ 1686 break; 1687 } 1688} 1689 1690/* 1691 * Get the currently displayed virtual consoles colormap. 1692 */ 1693static int gen_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *fb) 1694{ 1695 fb_copy_cmap (&fb->cmap, cmap, kspc ? 0 : 2); 1696 return 0; 1697} 1698 1699/* 1700 * Get the currently displayed virtual consoles fixed part of the display. 1701 */ 1702static int gen_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *fb) 1703{ 1704 *fix = fb->fix; 1705 return 0; 1706} 1707 1708/* 1709 * Get the current user defined part of the display. 1710 */ 1711static int gen_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *fb) 1712{ 1713 *var = fb->var; 1714 return 0; 1715} 1716 1717static struct fb_ops neofb_ops = { 1718 owner: THIS_MODULE, 1719 fb_set_var: neofb_set_var, 1720 fb_set_cmap: neofb_set_cmap, 1721 fb_pan_display: neofb_pan_display, 1722 fb_get_fix: gen_get_fix, 1723 fb_get_var: gen_get_var, 1724 fb_get_cmap: gen_get_cmap, 1725}; 1726 1727/* --------------------------------------------------------------------- */ 1728 1729static struct fb_var_screeninfo __devinitdata neofb_var640x480x8 = { 1730 accel_flags: FB_ACCELF_TEXT, 1731 xres: 640, 1732 yres: 480, 1733 xres_virtual: 640, 1734 yres_virtual: 30000, 1735 bits_per_pixel: 8, 1736 pixclock: 39722, 1737 left_margin: 48, 1738 right_margin: 16, 1739 upper_margin: 33, 1740 lower_margin: 10, 1741 hsync_len: 96, 1742 vsync_len: 2, 1743 sync: 0, 1744 vmode: FB_VMODE_NONINTERLACED 1745}; 1746 1747static struct fb_var_screeninfo __devinitdata neofb_var800x600x8 = { 1748 accel_flags: FB_ACCELF_TEXT, 1749 xres: 800, 1750 yres: 600, 1751 xres_virtual: 800, 1752 yres_virtual: 30000, 1753 bits_per_pixel: 8, 1754 pixclock: 25000, 1755 left_margin: 88, 1756 right_margin: 40, 1757 upper_margin: 23, 1758 lower_margin: 1, 1759 hsync_len: 128, 1760 vsync_len: 4, 1761 sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 1762 vmode: FB_VMODE_NONINTERLACED 1763}; 1764 1765static struct fb_var_screeninfo __devinitdata neofb_var1024x768x8 = { 1766 accel_flags: FB_ACCELF_TEXT, 1767 xres: 1024, 1768 yres: 768, 1769 xres_virtual: 1024, 1770 yres_virtual: 30000, 1771 bits_per_pixel: 8, 1772 pixclock: 15385, 1773 left_margin: 160, 1774 right_margin: 24, 1775 upper_margin: 29, 1776 lower_margin: 3, 1777 hsync_len: 136, 1778 vsync_len: 6, 1779 sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 1780 vmode: FB_VMODE_NONINTERLACED 1781}; 1782 1783#ifdef NOT_DONE 1784static struct fb_var_screeninfo __devinitdata neofb_var1280x1024x8 = { 1785 accel_flags: FB_ACCELF_TEXT, 1786 xres: 1280, 1787 yres: 1024, 1788 xres_virtual: 1280, 1789 yres_virtual: 30000, 1790 bits_per_pixel: 8, 1791 pixclock: 9260, 1792 left_margin: 248, 1793 right_margin: 48, 1794 upper_margin: 38, 1795 lower_margin: 1, 1796 hsync_len: 112, 1797 vsync_len: 3, 1798 sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 1799 vmode: FB_VMODE_NONINTERLACED 1800}; 1801#endif 1802 1803static struct fb_var_screeninfo *neofb_var = NULL; 1804 1805 1806static int __devinit neo_map_mmio (struct neofb_info *info) 1807{ 1808 DBG("neo_map_mmio"); 1809 1810 info->mmio.pbase = pci_resource_start (info->pcidev, 1); 1811 info->mmio.len = MMIO_SIZE; 1812 1813 if (!request_mem_region (info->mmio.pbase, MMIO_SIZE, "memory mapped I/O")) 1814 { 1815 printk ("neofb: memory mapped IO in use\n"); 1816 return -EBUSY; 1817 } 1818 1819 info->mmio.vbase = ioremap (info->mmio.pbase, MMIO_SIZE); 1820 if (!info->mmio.vbase) 1821 { 1822 printk ("neofb: unable to map memory mapped IO\n"); 1823 release_mem_region (info->mmio.pbase, info->mmio.len); 1824 return -ENOMEM; 1825 } 1826 else 1827 printk (KERN_INFO "neofb: mapped io at %p\n", info->mmio.vbase); 1828 1829 info->fb.fix.mmio_start = info->mmio.pbase; 1830 info->fb.fix.mmio_len = info->mmio.len; 1831 1832 return 0; 1833} 1834 1835static void __devinit neo_unmap_mmio (struct neofb_info *info) 1836{ 1837 DBG("neo_unmap_mmio"); 1838 1839 if (info->mmio.vbase) 1840 { 1841 iounmap (info->mmio.vbase); 1842 info->mmio.vbase = NULL; 1843 1844 release_mem_region (info->mmio.pbase, info->mmio.len); 1845 } 1846} 1847 1848static int __devinit neo_map_video (struct neofb_info *info, int video_len) 1849{ 1850 DBG("neo_map_video"); 1851 1852 info->video.pbase = pci_resource_start (info->pcidev, 0); 1853 info->video.len = video_len; 1854 1855 if (!request_mem_region (info->video.pbase, info->video.len, "frame buffer")) 1856 { 1857 printk ("neofb: frame buffer in use\n"); 1858 return -EBUSY; 1859 } 1860 1861 info->video.vbase = ioremap (info->video.pbase, info->video.len); 1862 if (!info->video.vbase) 1863 { 1864 printk ("neofb: unable to map screen memory\n"); 1865 release_mem_region (info->video.pbase, info->video.len); 1866 return -ENOMEM; 1867 } 1868 else 1869 printk (KERN_INFO "neofb: mapped framebuffer at %p\n", info->video.vbase); 1870 1871 info->fb.fix.smem_start = info->video.pbase; 1872 info->fb.fix.smem_len = info->video.len; 1873 info->fb.screen_base = info->video.vbase; 1874 1875#ifdef CONFIG_MTRR 1876 info->video.mtrr = mtrr_add (info->video.pbase, pci_resource_len (info->pcidev, 0), MTRR_TYPE_WRCOMB, 1); 1877#endif 1878 1879 /* Clear framebuffer, it's all white in memory after boot */ 1880 memset (info->video.vbase, 0, info->video.len); 1881 1882 return 0; 1883} 1884 1885static void __devinit neo_unmap_video (struct neofb_info *info) 1886{ 1887 DBG("neo_unmap_video"); 1888 1889 if (info->video.vbase) 1890 { 1891#ifdef CONFIG_MTRR 1892 mtrr_del (info->video.mtrr, info->video.pbase, info->video.len); 1893#endif 1894 1895 iounmap (info->video.vbase); 1896 info->video.vbase = NULL; 1897 info->fb.screen_base = NULL; 1898 1899 release_mem_region (info->video.pbase, info->video.len); 1900 } 1901} 1902 1903static int __devinit neo_init_hw (struct neofb_info *info) 1904{ 1905 int videoRam = 896; 1906 int maxClock = 65000; 1907 int CursorMem = 1024; 1908 int CursorOff = 0x100; 1909 int linearSize = 1024; 1910 int maxWidth = 1024; 1911 int maxHeight = 1024; 1912 unsigned char type, display; 1913 int w; 1914 1915 DBG("neo_init_hw"); 1916 1917 neoUnlock(); 1918 1919 1920 /* Determine the panel type */ 1921 VGAwGR(0x09,0x26); 1922 type = VGArGR(0x21); 1923 display = VGArGR(0x20); 1924 1925 /* Determine panel width -- used in NeoValidMode. */ 1926 w = VGArGR(0x20); 1927 VGAwGR(0x09,0x00); 1928 switch ((w & 0x18) >> 3) 1929 { 1930 case 0x00: 1931 info->NeoPanelWidth = 640; 1932 info->NeoPanelHeight = 480; 1933 neofb_var = &neofb_var640x480x8; 1934 break; 1935 case 0x01: 1936 info->NeoPanelWidth = 800; 1937 info->NeoPanelHeight = 600; 1938 neofb_var = &neofb_var800x600x8; 1939 break; 1940 case 0x02: 1941 info->NeoPanelWidth = 1024; 1942 info->NeoPanelHeight = 768; 1943 neofb_var = &neofb_var1024x768x8; 1944 break; 1945 case 0x03: 1946 /* 1280x1024 panel support needs to be added */ 1947#ifdef NOT_DONE 1948 info->NeoPanelWidth = 1280; 1949 info->NeoPanelHeight = 1024; 1950 neofb_var = &neofb_var1280x1024x8; 1951 break; 1952#else 1953 printk (KERN_ERR "neofb: Only 640x480, 800x600 and 1024x768 panels are currently supported\n"); 1954 return -1; 1955#endif 1956 default: 1957 info->NeoPanelWidth = 640; 1958 info->NeoPanelHeight = 480; 1959 neofb_var = &neofb_var640x480x8; 1960 break; 1961 } 1962 1963 printk (KERN_INFO "Panel is a %dx%d %s %s display\n", 1964 info->NeoPanelWidth, 1965 info->NeoPanelHeight, 1966 (type & 0x02) ? "color" : "monochrome", 1967 (type & 0x10) ? "TFT" : "dual scan"); 1968 1969 switch (info->accel) 1970 { 1971 case FB_ACCEL_NEOMAGIC_NM2070: 1972 videoRam = 896; 1973 maxClock = 65000; 1974 CursorMem = 2048; 1975 CursorOff = 0x100; 1976 linearSize = 1024; 1977 maxWidth = 1024; 1978 maxHeight = 1024; 1979 break; 1980 case FB_ACCEL_NEOMAGIC_NM2090: 1981 case FB_ACCEL_NEOMAGIC_NM2093: 1982 videoRam = 1152; 1983 maxClock = 80000; 1984 CursorMem = 2048; 1985 CursorOff = 0x100; 1986 linearSize = 2048; 1987 maxWidth = 1024; 1988 maxHeight = 1024; 1989 break; 1990 case FB_ACCEL_NEOMAGIC_NM2097: 1991 videoRam = 1152; 1992 maxClock = 80000; 1993 CursorMem = 1024; 1994 CursorOff = 0x100; 1995 linearSize = 2048; 1996 maxWidth = 1024; 1997 maxHeight = 1024; 1998 break; 1999 case FB_ACCEL_NEOMAGIC_NM2160: 2000 videoRam = 2048; 2001 maxClock = 90000; 2002 CursorMem = 1024; 2003 CursorOff = 0x100; 2004 linearSize = 2048; 2005 maxWidth = 1024; 2006 maxHeight = 1024; 2007 break; 2008 case FB_ACCEL_NEOMAGIC_NM2200: 2009 videoRam = 2560; 2010 maxClock = 110000; 2011 CursorMem = 1024; 2012 CursorOff = 0x1000; 2013 linearSize = 4096; 2014 maxWidth = 1280; 2015 maxHeight = 1024; /* ???? */ 2016 2017 info->neo2200 = (Neo2200*) info->mmio.vbase; 2018 break; 2019 case FB_ACCEL_NEOMAGIC_NM2230: 2020 videoRam = 3008; 2021 maxClock = 110000; 2022 CursorMem = 1024; 2023 CursorOff = 0x1000; 2024 linearSize = 4096; 2025 maxWidth = 1280; 2026 maxHeight = 1024; /* ???? */ 2027 2028 info->neo2200 = (Neo2200*) info->mmio.vbase; 2029 break; 2030 case FB_ACCEL_NEOMAGIC_NM2360: 2031 videoRam = 4096; 2032 maxClock = 110000; 2033 CursorMem = 1024; 2034 CursorOff = 0x1000; 2035 linearSize = 4096; 2036 maxWidth = 1280; 2037 maxHeight = 1024; /* ???? */ 2038 2039 info->neo2200 = (Neo2200*) info->mmio.vbase; 2040 break; 2041 case FB_ACCEL_NEOMAGIC_NM2380: 2042 videoRam = 6144; 2043 maxClock = 110000; 2044 CursorMem = 1024; 2045 CursorOff = 0x1000; 2046 linearSize = 8192; 2047 maxWidth = 1280; 2048 maxHeight = 1024; /* ???? */ 2049 2050 info->neo2200 = (Neo2200*) info->mmio.vbase; 2051 break; 2052 } 2053 2054 info->maxClock = maxClock; 2055 2056 return videoRam * 1024; 2057} 2058 2059 2060static struct neofb_info * __devinit neo_alloc_fb_info (struct pci_dev *dev, 2061 const struct pci_device_id *id) 2062{ 2063 struct neofb_info *info; 2064 2065 info = kmalloc (sizeof(struct neofb_info) + sizeof(struct display) + 2066 sizeof(u32) * 16, GFP_KERNEL); 2067 2068 if (!info) 2069 return NULL; 2070 2071 memset (info, 0, sizeof(struct neofb_info) + sizeof(struct display)); 2072 2073 info->currcon = -1; 2074 info->pcidev = dev; 2075 info->accel = id->driver_data; 2076 2077 info->pci_burst = !nopciburst; 2078 info->lcd_stretch = !nostretch; 2079 2080 if (!internal && !external) 2081 { 2082 info->internal_display = 1; 2083 info->external_display = 0; 2084 } 2085 else 2086 { 2087 info->internal_display = internal; 2088 info->external_display = external; 2089 } 2090 2091 switch (info->accel) 2092 { 2093 case FB_ACCEL_NEOMAGIC_NM2070: 2094 sprintf (info->fb.fix.id, "MagicGraph 128"); 2095 break; 2096 case FB_ACCEL_NEOMAGIC_NM2090: 2097 sprintf (info->fb.fix.id, "MagicGraph 128V"); 2098 break; 2099 case FB_ACCEL_NEOMAGIC_NM2093: 2100 sprintf (info->fb.fix.id, "MagicGraph 128ZV"); 2101 break; 2102 case FB_ACCEL_NEOMAGIC_NM2097: 2103 sprintf (info->fb.fix.id, "MagicGraph 128ZV+"); 2104 break; 2105 case FB_ACCEL_NEOMAGIC_NM2160: 2106 sprintf (info->fb.fix.id, "MagicGraph 128XD"); 2107 break; 2108 case FB_ACCEL_NEOMAGIC_NM2200: 2109 sprintf (info->fb.fix.id, "MagicGraph 256AV"); 2110 break; 2111 case FB_ACCEL_NEOMAGIC_NM2230: 2112 sprintf (info->fb.fix.id, "MagicGraph 256AV+"); 2113 break; 2114 case FB_ACCEL_NEOMAGIC_NM2360: 2115 sprintf (info->fb.fix.id, "MagicGraph 256ZX"); 2116 break; 2117 case FB_ACCEL_NEOMAGIC_NM2380: 2118 sprintf (info->fb.fix.id, "MagicGraph 256XL+"); 2119 break; 2120 } 2121 2122 info->fb.fix.type = FB_TYPE_PACKED_PIXELS; 2123 info->fb.fix.type_aux = 0; 2124 info->fb.fix.xpanstep = 0; 2125 info->fb.fix.ypanstep = 4; 2126 info->fb.fix.ywrapstep = 0; 2127 info->fb.fix.accel = id->driver_data; 2128 2129 info->fb.var.nonstd = 0; 2130 info->fb.var.activate = FB_ACTIVATE_NOW; 2131 info->fb.var.height = -1; 2132 info->fb.var.width = -1; 2133 info->fb.var.accel_flags = 0; 2134 2135 strcpy (info->fb.modename, info->fb.fix.id); 2136 2137 info->fb.fbops = &neofb_ops; 2138 info->fb.changevar = NULL; 2139 info->fb.switch_con = neofb_switch; 2140 info->fb.updatevar = neofb_updatevar; 2141 info->fb.blank = neofb_blank; 2142 info->fb.flags = FBINFO_FLAG_DEFAULT; 2143 info->fb.disp = (struct display *)(info + 1); 2144 info->fb.pseudo_palette = (void *)(info->fb.disp + 1); 2145 2146 fb_alloc_cmap (&info->fb.cmap, NR_PALETTE, 0); 2147 2148 return info; 2149} 2150 2151static void __devinit neo_free_fb_info (struct neofb_info *info) 2152{ 2153 if (info) 2154 { 2155 /* 2156 * Free the colourmap 2157 */ 2158 fb_alloc_cmap (&info->fb.cmap, 0, 0); 2159 2160 kfree (info); 2161 } 2162} 2163 2164/* --------------------------------------------------------------------- */ 2165 2166static int __devinit neofb_probe (struct pci_dev* dev, const struct pci_device_id* id) 2167{ 2168 struct neofb_info *info; 2169 u_int h_sync, v_sync; 2170 int err; 2171 int video_len; 2172 2173 DBG("neofb_probe"); 2174 2175 err = pci_enable_device (dev); 2176 if (err) 2177 return err; 2178 2179 err = -ENOMEM; 2180 info = neo_alloc_fb_info (dev, id); 2181 if (!info) 2182 goto failed; 2183 2184 err = neo_map_mmio (info); 2185 if (err) 2186 goto failed; 2187 2188 video_len = neo_init_hw (info); 2189 if (video_len < 0) 2190 { 2191 err = video_len; 2192 goto failed; 2193 } 2194 2195 err = neo_map_video (info, video_len); 2196 if (err) 2197 goto failed; 2198 2199 neofb_set_var (neofb_var, -1, &info->fb); 2200 2201 /* 2202 * Calculate the hsync and vsync frequencies. Note that 2203 * we split the 1e12 constant up so that we can preserve 2204 * the precision and fit the results into 32-bit registers. 2205 * (1953125000 * 512 = 1e12) 2206 */ 2207 h_sync = 1953125000 / info->fb.var.pixclock; 2208 h_sync = h_sync * 512 / (info->fb.var.xres + info->fb.var.left_margin + 2209 info->fb.var.right_margin + info->fb.var.hsync_len); 2210 v_sync = h_sync / (info->fb.var.yres + info->fb.var.upper_margin + 2211 info->fb.var.lower_margin + info->fb.var.vsync_len); 2212 2213 printk(KERN_INFO "neofb v" NEOFB_VERSION ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n", 2214 info->fb.fix.smem_len >> 10, 2215 info->fb.var.xres, info->fb.var.yres, 2216 h_sync / 1000, h_sync % 1000, v_sync); 2217 2218 2219 err = register_framebuffer (&info->fb); 2220 if (err < 0) 2221 goto failed; 2222 2223 printk (KERN_INFO "fb%d: %s frame buffer device\n", 2224 GET_FB_IDX(info->fb.node), info->fb.modename); 2225 2226 /* 2227 * Our driver data 2228 */ 2229 dev->driver_data = info; 2230 2231 return 0; 2232 2233failed: 2234 neo_unmap_video (info); 2235 neo_unmap_mmio (info); 2236 neo_free_fb_info (info); 2237 2238 return err; 2239} 2240 2241static void __devexit neofb_remove (struct pci_dev *dev) 2242{ 2243 struct neofb_info *info = (struct neofb_info *)dev->driver_data; 2244 2245 DBG("neofb_remove"); 2246 2247 if (info) 2248 { 2249 /* 2250 * If unregister_framebuffer fails, then 2251 * we will be leaving hooks that could cause 2252 * oopsen laying around. 2253 */ 2254 if (unregister_framebuffer (&info->fb)) 2255 printk (KERN_WARNING "neofb: danger danger! Oopsen imminent!\n"); 2256 2257 neo_unmap_video (info); 2258 neo_unmap_mmio (info); 2259 neo_free_fb_info (info); 2260 2261 /* 2262 * Ensure that the driver data is no longer 2263 * valid. 2264 */ 2265 dev->driver_data = NULL; 2266 } 2267} 2268 2269static struct pci_device_id neofb_devices[] __devinitdata = { 2270 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2070, 2271 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2070}, 2272 2273 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2090, 2274 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2090}, 2275 2276 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2093, 2277 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2093}, 2278 2279 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2097, 2280 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2097}, 2281 2282 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2160, 2283 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2160}, 2284 2285 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2200, 2286 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2200}, 2287 2288 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2230, 2289 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2230}, 2290 2291 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2360, 2292 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2360}, 2293 2294 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2380, 2295 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2380}, 2296 2297 {0, 0, 0, 0, 0, 0, 0} 2298}; 2299 2300MODULE_DEVICE_TABLE(pci, neofb_devices); 2301 2302static struct pci_driver neofb_driver = { 2303 name: "neofb", 2304 id_table: neofb_devices, 2305 probe: neofb_probe, 2306 remove: __devexit_p(neofb_remove) 2307}; 2308 2309/* **************************** init-time only **************************** */ 2310 2311static void __init neo_init (void) 2312{ 2313 DBG("neo_init"); 2314 pci_register_driver (&neofb_driver); 2315} 2316 2317/* **************************** exit-time only **************************** */ 2318 2319static void __exit neo_done (void) 2320{ 2321 DBG("neo_done"); 2322 pci_unregister_driver (&neofb_driver); 2323} 2324 2325 2326#ifndef MODULE 2327 2328/* ************************* init in-kernel code ************************** */ 2329 2330int __init neofb_setup (char *options) 2331{ 2332 char *this_opt; 2333 2334 DBG("neofb_setup"); 2335 2336 if (!options || !*options) 2337 return 0; 2338 2339 for (this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) 2340 { 2341 if (!*this_opt) continue; 2342 2343 if (!strncmp(this_opt, "disabled", 8)) 2344 disabled = 1; 2345 if (!strncmp(this_opt, "internal", 8)) 2346 internal = 1; 2347 if (!strncmp(this_opt, "external", 8)) 2348 external = 1; 2349 if (!strncmp(this_opt, "nostretch", 9)) 2350 nostretch = 1; 2351 if (!strncmp(this_opt, "nopciburst", 10)) 2352 nopciburst = 1; 2353 } 2354 2355 return 0; 2356} 2357 2358static int __initdata initialized = 0; 2359 2360int __init neofb_init(void) 2361{ 2362 DBG("neofb_init"); 2363 2364 if (disabled) 2365 return -ENXIO; 2366 2367 if (!initialized) 2368 { 2369 initialized = 1; 2370 neo_init(); 2371 } 2372 2373 /* never return failure, user can hotplug card later... */ 2374 return 0; 2375} 2376 2377#else 2378 2379/* *************************** init module code **************************** */ 2380 2381int __init init_module(void) 2382{ 2383 DBG("init_module"); 2384 2385 if (disabled) 2386 return -ENXIO; 2387 2388 neo_init(); 2389 2390 /* never return failure; user can hotplug card later... */ 2391 return 0; 2392} 2393 2394#endif /* MODULE */ 2395 2396module_exit(neo_done); 2397