1 /* Author: 2 Rudolf Cornelissen 4/2003-4/2004 3 */ 4 5 #define MODULE_BIT 0x00008000 6 7 #include "nm_std.h" 8 9 static status_t test_ram(void); 10 static status_t nmxxxx_general_powerup (void); 11 static status_t nm_general_bios_to_powergraphics(void); 12 13 static void nm_dump_configuration_space (void) 14 { 15 #define DUMP_CFG(reg, type) if (si->ps.card_type >= type) do { \ 16 uint32 value = CFGR(reg); \ 17 MSG(("configuration_space 0x%02x %20s 0x%08x\n", \ 18 NMCFG_##reg, #reg, value)); \ 19 } while (0) 20 DUMP_CFG (DEVID, 0); 21 DUMP_CFG (DEVCTRL, 0); 22 DUMP_CFG (CLASS, 0); 23 DUMP_CFG (HEADER, 0); 24 DUMP_CFG (NMBASE2, 0); 25 DUMP_CFG (NMBASE1, 0); 26 DUMP_CFG (NMBASE3, 0); 27 DUMP_CFG (SUBSYSIDR, 0); 28 DUMP_CFG (ROMBASE, 0); 29 DUMP_CFG (CAP_PTR, 0); 30 DUMP_CFG (INTCTRL, 0); 31 DUMP_CFG (OPTION, 0); 32 DUMP_CFG (NM_INDEX, 0); 33 DUMP_CFG (NM_DATA, 0); 34 DUMP_CFG (SUBSYSIDW, 0); 35 DUMP_CFG (OPTION2, G100); 36 DUMP_CFG (OPTION3, 0); 37 DUMP_CFG (OPTION4, 0); 38 DUMP_CFG (PM_IDENT, G100); 39 DUMP_CFG (PM_CSR, G100); 40 DUMP_CFG (AGP_IDENT, 0); 41 DUMP_CFG (AGP_STS, 0); 42 DUMP_CFG (AGP_CMD, 0); 43 #undef DUMP_CFG 44 } 45 46 status_t nm_general_powerup() 47 { 48 status_t status; 49 50 LOG(1,("POWERUP: Neomagic (open)BeOS Accelerant 0.06-9 running.\n")); 51 52 /* detect card type and power it up */ 53 switch(CFGR(DEVID)) 54 { 55 case 0x000110c8: //NM2070 ISA 56 si->ps.card_type = NM2070; 57 LOG(4,("POWERUP: Detected MagicGraph 128 (NM2070)\n")); 58 break; 59 case 0x000210c8: //NM2090 ISA 60 si->ps.card_type = NM2090; 61 LOG(4,("POWERUP: Detected MagicGraph 128V (NM2090)\n")); 62 break; 63 case 0x000310c8: //NM2093 ISA 64 si->ps.card_type = NM2093; 65 LOG(4,("POWERUP: Detected MagicGraph 128ZV (NM2093)\n")); 66 break; 67 case 0x008310c8: //NM2097 PCI 68 si->ps.card_type = NM2097; 69 LOG(4,("POWERUP: Detected MagicGraph 128ZV+ (NM2097)\n")); 70 break; 71 case 0x000410c8: //NM2160 PCI 72 si->ps.card_type = NM2160; 73 LOG(4,("POWERUP: Detected MagicGraph 128XD (NM2160)\n")); 74 break; 75 case 0x000510c8: //NM2200 76 si->ps.card_type = NM2200; 77 LOG(4,("POWERUP: Detected MagicMedia 256AV (NM2200)\n")); 78 break; 79 case 0x002510c8: //NM2230 80 si->ps.card_type = NM2230; 81 LOG(4,("POWERUP: Detected MagicMedia 256AV+ (NM2230)\n")); 82 break; 83 case 0x000610c8: //NM2360 84 si->ps.card_type = NM2360; 85 LOG(4,("POWERUP: Detected MagicMedia 256ZX (NM2360)\n")); 86 break; 87 case 0x001610c8: //NM2380 88 si->ps.card_type = NM2380; 89 LOG(4,("POWERUP: Detected MagicMedia 256XL+ (NM2380)\n")); 90 break; 91 default: 92 LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID))); 93 return B_ERROR; 94 } 95 96 /* power up the card */ 97 status = nmxxxx_general_powerup(); 98 99 /* override memory detection if requested by user */ 100 if (si->settings.memory != 0) 101 si->ps.memory_size = si->settings.memory; 102 103 return status; 104 } 105 106 static status_t test_ram(void) 107 { 108 uint32 value, offset; 109 status_t result = B_OK; 110 111 /* make sure we don't corrupt the hardware cursor by using fbc.frame_buffer. */ 112 if (si->fbc.frame_buffer == NULL) 113 { 114 LOG(8,("INIT: test_ram detected NULL pointer.\n")); 115 return B_ERROR; 116 } 117 118 for (offset = 0, value = 0x55aa55aa; offset < 256; offset++) 119 { 120 /* write testpattern to cardRAM */ 121 ((uint32 *)si->fbc.frame_buffer)[offset] = value; 122 /* toggle testpattern */ 123 value = 0xffffffff - value; 124 } 125 126 for (offset = 0, value = 0x55aa55aa; offset < 256; offset++) 127 { 128 /* readback and verify testpattern from cardRAM */ 129 if (((uint32 *)si->fbc.frame_buffer)[offset] != value) result = B_ERROR; 130 /* toggle testpattern */ 131 value = 0xffffffff - value; 132 } 133 return result; 134 } 135 136 /* NOTE: 137 * This routine *has* to be done *after* SetDispplayMode has been executed, 138 * or test results will not be representative! 139 * (CAS latency is dependant on nm setup on some (DRAM) boards) */ 140 status_t nm_set_cas_latency() 141 { 142 /* check current RAM access to see if we need to change anything */ 143 if (test_ram() == B_OK) 144 { 145 LOG(4,("INIT: RAM access OK.\n")); 146 return B_OK; 147 } 148 149 /* check if we read PINS at starttime so we have valid registersettings at our disposal */ 150 LOG(4,("INIT: RAM access errors; not fixable: missing coldstart specs.\n")); 151 return B_ERROR; 152 } 153 154 void nm_unlock() 155 { 156 /* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */ 157 ISAGRPHW(GRPHXLOCK, 0x26); 158 } 159 160 static status_t nmxxxx_general_powerup() 161 { 162 uint8 temp; 163 // status_t result; 164 165 LOG(4, ("INIT: powerup\n")); 166 if (si->settings.logmask & 0x80000000) nm_dump_configuration_space(); 167 168 /* set ISA registermapping to VGA colormode */ 169 temp = (ISARB(MISCR) | 0x01); 170 /* we need to wait a bit or the card will mess-up it's register values.. */ 171 snooze(10); 172 ISAWB(MISCW, temp); 173 174 /* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */ 175 ISAGRPHW(GRPHXLOCK, 0x26); 176 177 /* unlock cards CRTC registers */ 178 //don't touch: most cards get into trouble on this! 179 // ISAGRPHW(GENLOCK, 0x00); 180 181 /* initialize the shared_info struct */ 182 set_specs(); 183 /* log the struct settings */ 184 dump_specs(); 185 186 /* activate PCI access: b7 = framebuffer, b6 = registers */ 187 ISAGRPHW(IFACECTRL2, 0xc0); 188 189 /* disable VGA-mode cursor (just to be sure) */ 190 ISACRTCW(VGACURCTRL, 0x00); 191 192 /* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */ 193 /*if (si->settings.usebios || (result != B_OK)) */return nm_general_bios_to_powergraphics(); 194 195 /*power up the PLLs,LUT,DAC*/ 196 LOG(2,("INIT: powerup\n")); 197 198 /* turn off both displays and the hardcursor (also disables transfers) */ 199 nm_crtc_dpms(false, false, false); 200 nm_crtc_cursor_hide(); 201 202 /* setup sequencer clocking mode */ 203 ISASEQW(CLKMODE, 0x21); 204 205 /* G100 SGRAM and SDRAM use external pix and dac refs, do *not* activate internals! 206 * (this would create electrical shortcuts, 207 * resulting in extra chip heat and distortions visible on screen */ 208 /* set voltage reference - using DAC reference block partly */ 209 // DXIW(VREFCTRL,0x03); 210 /* wait for 100ms for voltage reference to stabilize */ 211 delay(100000); 212 /* power up the SYSPLL */ 213 // CFGW(OPTION,CFGR(OPTION)|0x20); 214 /* power up the PIXPLL */ 215 // DXIW(PIXCLKCTRL,0x08); 216 217 /* disable pixelclock oscillations before switching on CLUT */ 218 // DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04)); 219 /* disable 15bit mode CLUT-overlay function */ 220 // DXIW(GENCTRL, DXIR(GENCTRL & 0xfd)); 221 /* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */ 222 // DXIW(MISCCTRL,0x1b); 223 // snooze(250); 224 /* re-enable pixelclock oscillations */ 225 // DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb)); 226 227 /*make sure card is in powergraphics mode*/ 228 // VGAW_I(CRTCEXT,3,0x80); 229 230 /*set the system clocks to powergraphics speed*/ 231 // LOG(2,("INIT: Setting system PLL to powergraphics speeds\n")); 232 // g100_dac_set_sys_pll(); 233 234 /* 'official' RAM initialisation */ 235 // LOG(2,("INIT: RAM init\n")); 236 /* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */ 237 // ACCW(PLNWT,0x00000000); 238 // ACCW(PLNWT,0xffffffff); 239 /* program memory control waitstates */ 240 // ACCW(MCTLWTST,si->ps.mctlwtst_reg); 241 /* set memory configuration including: 242 * - no split framebuffer. 243 * - Mark says b14 (G200) should be done also though not defined for G100 in spec, 244 * - b3 v3_mem_type was included by Mark for memconfig setup: but looks like not defined */ 245 // CFGW(OPTION,(CFGR(OPTION)&0xFFFF8FFF) | ((si->ps.v3_mem_type & 0x04) << 10)); 246 /* set memory buffer type: 247 * - Mark says: if((v3_mem_type & 0x03) == 0x03) then do not or-in bits in option2; 248 * but looks like v3_mem_type b1 is not defined, 249 * - Mark also says: place v3_mem_type b1 in option2 bit13 (if not 0x03) but b13 = reserved. */ 250 // CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|((si->ps.v3_mem_type & 0x01) << 12)); 251 /* set RAM read tap delay */ 252 // CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFFFF0) | ((si->ps.v3_mem_type & 0xf0) >> 4)); 253 /* wait 200uS minimum */ 254 // snooze(250); 255 256 /* reset memory (MACCESS is a write only register!) */ 257 // ACCW(MACCESS, 0x00000000); 258 /* select JEDEC reset method */ 259 // ACCW(MACCESS, 0x00004000); 260 /* perform actual RAM reset */ 261 // ACCW(MACCESS, 0x0000c000); 262 // snooze(250); 263 /* start memory refresh */ 264 // CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000)); 265 /* set memory control waitstate again AFTER the RAM reset */ 266 // ACCW(MCTLWTST,si->ps.mctlwtst_reg); 267 /* end 'official' RAM initialisation. */ 268 269 /* Bus parameters: enable retries, use advanced read */ 270 // CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29))); 271 272 /*enable writing to crtc registers*/ 273 // VGAW_I(CRTC,0x11,0); 274 275 /* turn on display */ 276 nm_crtc_dpms(true, true, true); 277 278 return B_OK; 279 } 280 281 status_t nm_general_output_select() 282 { 283 /* log currently selected output */ 284 switch (nm_general_output_read()) 285 { 286 case 0x01: 287 LOG(2, ("INIT: external CRT only mode active\n")); 288 break; 289 case 0x02: 290 LOG(2, ("INIT: internal LCD only mode active\n")); 291 break; 292 case 0x03: 293 LOG(2, ("INIT: simultaneous LCD/CRT mode active\n")); 294 break; 295 } 296 return B_OK; 297 } 298 299 uint8 nm_general_output_read() 300 { 301 uint8 output; 302 303 output = (ISAGRPHR(PANELCTRL1) & 0x03); 304 305 if (output == 0) 306 { 307 /* using 'failsafe' mode: the flatpanel needs all the protection it can get... */ 308 LOG(4, ("INIT: illegal outputmode detected, reporting internal mode!\n")); 309 output = 2; 310 } 311 312 return output; 313 } 314 315 /* basic change of card state from VGA to powergraphics -> should work from BIOS init state*/ 316 static 317 status_t nm_general_bios_to_powergraphics() 318 { 319 uint8 temp; 320 321 LOG(2, ("INIT: Skipping card coldstart!\n")); 322 323 /* turn off display */ 324 nm_crtc_dpms(false, false, false); 325 326 /* set card to 'enhanced' mode: (only VGA standard registers used for NeoMagic cards) */ 327 /* (keep) card enabled, set plain normal memory usage, no old VGA 'tricks' ... */ 328 ISACRTCW(MODECTL, 0xc3); 329 /* ... plain sequential memory use, more than 64Kb RAM installed, 330 * switch to graphics mode ... */ 331 ISASEQW(MEMMODE, 0x0e); 332 /* ... disable bitplane tweaking ... */ 333 /* note: 334 * NeoMagic cards have custom b4-b7 use in this register! */ 335 ISAGRPHW(ENSETRESET, 0x80); 336 /* ... no logical function tweaking with display data, no data rotation ... */ 337 ISAGRPHW(DATAROTATE, 0x00); 338 /* ... reset read map select to plane 0 ... */ 339 ISAGRPHW(READMAPSEL, 0x00); 340 /* ... set standard mode ... */ 341 ISAGRPHW(MODE, 0x00); 342 /* ... ISA framebuffer mapping is 64Kb window, switch to graphics mode (again), 343 * select standard adressing ... */ 344 ISAGRPHW(MISC, 0x05); 345 /* ... disable bit masking ... */ 346 ISAGRPHW(BITMASK, 0xff); 347 /* ... attributes are in color, switch to graphics mode (again) ... */ 348 ISAATBW(MODECTL, 0x01); 349 /* ... set overscan color to black ... */ 350 ISAATBW(OSCANCOLOR, 0x00); 351 /* ... enable all color planes ... */ 352 ISAATBW(COLPLANE_EN, 0x0f); 353 /* ... reset horizontal pixelpanning ... */ 354 ISAATBW(HORPIXPAN, 0x00); 355 /* ... reset colorpalette groupselect bits ... */ 356 ISAATBW(COLSEL, 0x00); 357 /* ... do unknown standard VGA register ... */ 358 /* note: 359 * NeoMagic cards have custom b6 use in this register! */ 360 ISAATBW(0x16, 0x01); 361 /* ... and enable all four byteplanes. */ 362 ISASEQW(MAPMASK, 0x0f); 363 364 /* setup sequencer clocking mode */ 365 ISASEQW(CLKMODE, 0x21); 366 367 /* enable memory above 256Kb: set b4 (disables adress wraparound at 256Kb boundary) */ 368 ISAGRPHW(FBSTADDE, 0x10); 369 370 /* this register has influence on the CRTC framebuffer offset, so reset! */ 371 //fixme: investigate further... 372 ISAGRPHW(0x15, 0x00); 373 374 /* enable fast PCI write bursts (b4-5) */ 375 temp = ((ISAGRPHR(IFACECTRL1) & 0x0f) | 0x30); 376 /* we need to wait a bit or the card will mess-up it's register values.. */ 377 snooze(10); 378 ISAGRPHW(IFACECTRL1, temp); 379 380 /* this speeds up RAM writes according to XFree driver */ 381 // fixme: don't touch until more is known: part of RAM or CORE PLL??? 382 // ISAGRPHW(SPEED, 0xc0); 383 384 /* turn on display */ 385 nm_crtc_dpms(true, true, true); 386 387 return B_OK; 388 } 389 390 /* Check if mode virtual_size adheres to the cards _maximum_ contraints, and modify 391 * virtual_size to the nearest valid maximum for the mode on the card if not so. 392 * Then: check if virtual_width adheres to the cards _multiple_ constraints, and 393 * create mode slopspace if not so. 394 * We use acc multiple constraints here if we expect we can use acceleration, because 395 * acc constraints are worse than CRTC constraints. 396 * 397 * Mode slopspace is reflected in fbc->bytes_per_row BTW. */ 398 status_t nm_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode) 399 { 400 /* Note: 401 * This routine assumes that the CRTC memory pitch granularity is 'smaller than', 402 * or 'equals' the acceleration engine memory pitch granularity! */ 403 404 uint32 video_pitch = 0; 405 uint32 crtc_mask; 406 uint8 depth = 8; 407 408 /* determine pixel multiple based on CRTC memory pitch constraints. 409 * (Note: Don't mix this up with CRTC timing contraints! Those are 410 * multiples of 8 for horizontal, 1 for vertical timing.) 411 * 412 * CRTC pitch constraints are the same for all Neomagic cards */ 413 switch (target->space) 414 { 415 case B_CMAP8: crtc_mask = 0x07; depth = 8; break; 416 case B_RGB15: crtc_mask = 0x03; depth = 16; break; 417 case B_RGB16: crtc_mask = 0x03; depth = 16; break; 418 case B_RGB24: crtc_mask = 0x07; depth = 24; break; 419 default: 420 LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space)); 421 return B_ERROR; 422 } 423 424 /* check if we can setup this mode with acceleration: 425 * constraints are same for all cards */ 426 *acc_mode = true; 427 428 switch (si->ps.card_type) 429 { 430 case NM2097: 431 case NM2160: 432 if (target->space != B_RGB24) *acc_mode = true; 433 else *acc_mode = false; 434 break; 435 default: 436 *acc_mode = false; 437 break; 438 } 439 440 /* virtual_width */ 441 if (target->virtual_width > 1600) *acc_mode = false; 442 443 /* virtual_height */ 444 if (si->ps.card_type < NM2200) 445 { 446 /* confirmed NM2097 and NM2160 */ 447 if (target->virtual_height > 1024) *acc_mode = false; 448 } 449 else 450 { 451 /* fixme: needs confirmation, assuming this height will still work.. */ 452 if (target->virtual_height > 2048) *acc_mode = false; 453 } 454 455 /* now check virtual_size based on CRTC constraints and modify if needed */ 456 //fixme: checkout cardspecs here!! (NM2160 can do 8192 _bytes_ at least (in theory)) 457 { 458 /* virtual_width */ 459 switch(target->space) 460 { 461 case B_CMAP8: 462 if (target->virtual_width > 16368) 463 target->virtual_width = 16368; 464 break; 465 case B_RGB15_LITTLE: 466 case B_RGB16_LITTLE: 467 if (target->virtual_width > 8184) 468 target->virtual_width = 8184; 469 break; 470 case B_RGB24_LITTLE: 471 if (target->virtual_width > 5456) 472 target->virtual_width = 5456; 473 break; 474 } 475 476 /* virtual_height: The only constraint here is the cards memory size which is 477 * checked later on in ProposeMode: virtual_height is adjusted then if needed. 478 * 'Limiting here' to the variable size that's at least available (uint16). */ 479 if (target->virtual_height > 65535) target->virtual_height = 65535; 480 } 481 482 /* OK, now we know that virtual_width is valid, and it's needing no slopspace if 483 * it was confined above, so we can finally calculate safely if we need slopspace 484 * for this mode... */ 485 /* note: 486 * we prefer unaccelerated modes above accelerated ones if not enough RAM exists 487 * and the mode can be closer matched to the requested one if unaccelerated. */ 488 if (*acc_mode) 489 { 490 uint32 mem_avail, bytes_X_height; 491 492 /* calculate amount of available memory */ 493 mem_avail = (si->ps.memory_size * 1024); 494 if (si->settings.hardcursor) mem_avail -= si->ps.curmem_size; 495 /* helper */ 496 bytes_X_height = (depth >> 3) * target->virtual_height; 497 498 /* Accelerated modes work with a table, there are very few fixed settings.. */ 499 if (target->virtual_width == 640) video_pitch = 640; 500 else 501 if (target->virtual_width <= 800) 502 { 503 if (((800 * bytes_X_height) > mem_avail) && 504 (target->virtual_width < (800 - crtc_mask))) 505 *acc_mode = false; 506 else 507 video_pitch = 800; 508 } 509 else 510 if (target->virtual_width <= 1024) 511 { 512 if (((1024 * bytes_X_height) > mem_avail) && 513 (target->virtual_width < (1024 - crtc_mask))) 514 *acc_mode = false; 515 else 516 video_pitch = 1024; 517 } 518 else 519 if (target->virtual_width <= 1152) 520 { 521 if (((1152 * bytes_X_height) > mem_avail) && 522 (target->virtual_width < (1152 - crtc_mask))) 523 *acc_mode = false; 524 else 525 video_pitch = 1152; 526 } 527 else 528 if (target->virtual_width <= 1280) 529 { 530 if (((1280 * bytes_X_height) > mem_avail) && 531 (target->virtual_width < (1280 - crtc_mask))) 532 *acc_mode = false; 533 else 534 video_pitch = 1280; 535 } 536 else 537 if (target->virtual_width <= 1600) 538 { 539 if (((1600 * bytes_X_height) > mem_avail) && 540 (target->virtual_width < (1600 - crtc_mask))) 541 *acc_mode = false; 542 else 543 video_pitch = 1600; 544 } 545 } 546 if (!*acc_mode) 547 video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask); 548 549 LOG(2,("INIT: memory pitch will be set to %d pixels for colorspace 0x%08x\n", 550 video_pitch, target->space)); 551 if (target->virtual_width != video_pitch) 552 LOG(2,("INIT: effective mode slopspace is %d pixels\n", 553 (video_pitch - target->virtual_width))); 554 555 /* now calculate bytes_per_row for this mode */ 556 *bytes_per_row = video_pitch * (depth >> 3); 557 558 return B_OK; 559 } 560