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