1 /* 2 Haiku S3 Savage driver adapted from the X.org Savage driver. 3 4 Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 5 Copyright (c) 2003-2006, X.Org Foundation 6 7 Copyright 2007-2008 Haiku, Inc. All rights reserved. 8 Distributed under the terms of the MIT license. 9 10 Authors: 11 Gerald Zajac 2006-2008 12 */ 13 14 15 #include "accel.h" 16 #include "savage.h" 17 18 19 #define BASE_FREQ 14.31818 20 21 22 struct SavageRegRec { 23 uint8 CRTC[25]; // Crtc Controller reg's 24 25 uint8 SR12, SR13, SR1B, SR29; 26 uint8 CR33, CR34, CR3A, CR3B, CR3C; 27 uint8 CR42, CR43, CR45; 28 uint8 CR50, CR51, CR53, CR58, CR5D, CR5E; 29 uint8 CR65, CR66, CR67, CR69; 30 uint8 CR86, CR88; 31 uint8 CR90, CR91, CRB0; 32 }; 33 34 35 36 static void 37 Savage_SetGBD_Twister(const DisplayModeEx& mode) 38 { 39 SharedInfo& si = *gInfo.sharedInfo; 40 int bci_enable; 41 42 if (si.chipType == S3_SAVAGE4) 43 bci_enable = BCI_ENABLE; 44 else 45 bci_enable = BCI_ENABLE_TWISTER; 46 47 // MM81C0 and 81C4 are used to control primary stream. 48 WriteReg32(PRI_STREAM_FBUF_ADDR0, 0); 49 WriteReg32(PRI_STREAM_FBUF_ADDR1, 0); 50 51 // Program Primary Stream Stride Register. 52 // 53 // Tell engine if tiling on or off, set primary stream stride, and 54 // if tiling, set tiling bits/pixel and primary stream tile offset. 55 // Note that tile offset (bits 16 - 29) must be scanline width in 56 // bytes/128bytespertile * 256 Qwords/tile. This is equivalent to 57 // lDelta * 2. Remember that if tiling, lDelta is screenwidth in 58 // bytes padded up to an even number of tilewidths. 59 60 WriteReg32(PRI_STREAM_STRIDE, 61 (((mode.bytesPerRow * 2) << 16) & 0x3FFFE000) | 62 (mode.bytesPerRow & 0x00001fff)); 63 64 // CR69, bit 7 = 1 65 // to use MM streams processor registers to control primary stream. 66 67 WriteCrtcReg(0x69, 0x80, 0x80); 68 69 WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_LITTLE_ENDIAN | S3_BD64); 70 71 // If MS1NB style linear tiling mode. 72 // bit MM850C[15] = 0 select NB linear tile mode. 73 // bit MM850C[15] = 1 select MS-1 128-bit non-linear tile mode. 74 75 uint32 ulTmp = ReadReg32(ADVANCED_FUNC_CTRL) | 0x8000; // use MS-s style tile mode 76 WriteReg32(ADVANCED_FUNC_CTRL, ulTmp); 77 78 // CR88, bit 4 - Block write enabled/disabled. 79 // 80 // Note: Block write must be disabled when writing to tiled 81 // memory. Even when writing to non-tiled memory, block 82 // write should only be enabled for certain types of SGRAM. 83 84 WriteCrtcReg(0x88, DISABLE_BLOCK_WRITE_2D, DISABLE_BLOCK_WRITE_2D); 85 } 86 87 88 static void 89 Savage_SetGBD_3D(const DisplayModeEx& mode) 90 { 91 int bci_enable = BCI_ENABLE; 92 93 // MM81C0 and 81C4 are used to control primary stream. 94 WriteReg32(PRI_STREAM_FBUF_ADDR0, 0); 95 WriteReg32(PRI_STREAM_FBUF_ADDR1, 0); 96 97 // Program Primary Stream Stride Register. 98 // 99 // Tell engine if tiling on or off, set primary stream stride, and 100 // if tiling, set tiling bits/pixel and primary stream tile offset. 101 // Note that tile offset (bits 16 - 29) must be scanline width in 102 // bytes/128bytespertile * 256 Qwords/tile. This is equivalent to 103 // lDelta * 2. Remember that if tiling, lDelta is screenwidth in 104 // bytes padded up to an even number of tilewidths. 105 106 WriteReg32(PRI_STREAM_STRIDE, 107 (((mode.bytesPerRow * 2) << 16) & 0x3FFFE000) | 108 (mode.bytesPerRow & 0x00001fff)); 109 110 // CR69, bit 7 = 1 to use MM streams processor registers to control primary 111 // stream. 112 113 WriteCrtcReg(0x69, 0x80, 0x80); 114 115 WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_LITTLE_ENDIAN | S3_BD64); 116 117 // If MS1NB style linear tiling mode. 118 // bit MM850C[15] = 0 select NB linear tile mode. 119 // bit MM850C[15] = 1 select MS-1 128-bit non-linear tile mode. 120 121 uint32 ulTmp = ReadReg32(ADVANCED_FUNC_CTRL) | 0x8000; // use MS-s style tile mode 122 WriteReg32(ADVANCED_FUNC_CTRL, ulTmp); 123 124 // CR88, bit 4 - Block write enabled/disabled. 125 // 126 // Note: Block write must be disabled when writing to tiled 127 // memory. Even when writing to non-tiled memory, block 128 // write should only be enabled for certain types of SGRAM. 129 130 WriteCrtcReg(0x88, DISABLE_BLOCK_WRITE_2D, DISABLE_BLOCK_WRITE_2D); 131 } 132 133 134 static void 135 Savage_SetGBD_MX(const DisplayModeEx& mode) 136 { 137 SharedInfo& si = *gInfo.sharedInfo; 138 int bci_enable = BCI_ENABLE; 139 140 // CR67_3: 141 // = 1 stream processor MMIO address and stride register 142 // are used to control the primary stream. 143 // = 0 standard VGA address and stride registers 144 // are used to control the primary streams. 145 146 WriteCrtcReg(0x67, 0x08, 0x08); 147 // IGA 2. 148 WriteSeqReg(0x26, 0x4f); // select IGA 2 read/writes 149 WriteCrtcReg(0x67, 0x08, 0x08); 150 WriteSeqReg(0x26, 0x40); // select IGA 1 151 152 // Set primary stream to bank 0 via reg CRCA. 153 WriteCrtcReg(MEMORY_CTRL0_REG, 0x00, MEM_PS1 + MEM_PS2); 154 155 // MM81C0 and 81C4 are used to control primary stream. 156 WriteReg32(PRI_STREAM_FBUF_ADDR0, si.frameBufferOffset & 0x7fffff); 157 WriteReg32(PRI_STREAM_FBUF_ADDR1, si.frameBufferOffset & 0x7fffff); 158 WriteReg32(PRI_STREAM2_FBUF_ADDR0, si.frameBufferOffset & 0x7fffff); 159 WriteReg32(PRI_STREAM2_FBUF_ADDR1, si.frameBufferOffset & 0x7fffff); 160 161 // Program Primary Stream Stride Register. 162 // 163 // Tell engine if tiling on or off, set primary stream stride, and 164 // if tiling, set tiling bits/pixel and primary stream tile offset. 165 // Note that tile offset (bits 16 - 29) must be scanline width in 166 // bytes/128bytespertile * 256 Qwords/tile. This is equivalent to 167 // lDelta * 2. Remember that if tiling, lDelta is screenwidth in 168 // bytes padded up to an even number of tilewidths. 169 170 WriteReg32(PRI_STREAM_STRIDE, 171 (((mode.bytesPerRow * 2) << 16) & 0x3FFF0000) | 172 (mode.bytesPerRow & 0x00003fff)); 173 WriteReg32(PRI_STREAM2_STRIDE, 174 (((mode.bytesPerRow * 2) << 16) & 0x3FFF0000) | 175 (mode.bytesPerRow & 0x00003fff)); 176 177 WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_LITTLE_ENDIAN | S3_BD64); 178 179 // CR78, bit 3 - Block write enabled(1)/disabled(0). 180 // bit 2 - Block write cycle time(0:2 cycles,1: 1 cycle) 181 // Note: Block write must be disabled when writing to tiled 182 // memory. Even when writing to non-tiled memory, block 183 // write should only be enabled for certain types of SGRAM. 184 185 WriteCrtcReg(0x78, 0xfb, 0xfb); 186 } 187 188 189 static void 190 Savage_SetGBD_Super(const DisplayModeEx& mode) 191 { 192 SharedInfo& si = *gInfo.sharedInfo; 193 int bci_enable = BCI_ENABLE_TWISTER; 194 195 // CR67_3: 196 // = 1 stream processor MMIO address and stride register 197 // are used to control the primary stream. 198 // = 0 standard VGA address and stride registers 199 // are used to control the primary streams. 200 201 WriteCrtcReg(0x67, 0x08, 0x08); 202 // IGA 2. 203 WriteSeqReg(0x26, 0x4f); // select IGA 2 read/writes 204 WriteCrtcReg(0x67, 0x08, 0x08); 205 WriteSeqReg(0x26, 0x40); // select IGA 1 206 207 // Load ps1 active registers as determined by MM81C0/81C4. 208 // Load ps2 active registers as determined by MM81B0/81B4. 209 210 WriteCrtcReg(0x65, 0x03, 0x03); 211 212 // Program Primary Stream Stride Register. 213 // 214 // Tell engine if tiling on or off, set primary stream stride, and 215 // if tiling, set tiling bits/pixel and primary stream tile offset. 216 // Note that tile offset (bits 16 - 29) must be scanline width in 217 // bytes/128bytespertile * 256 Qwords/tile. This is equivalent to 218 // lDelta * 2. Remember that if tiling, lDelta is screenwidth in 219 // bytes padded up to an even number of tilewidths. 220 221 WriteReg32(PRI_STREAM_STRIDE, 222 (((mode.bytesPerRow * 2) << 16) & 0x3FFF0000) | 223 (mode.bytesPerRow & 0x00001fff)); 224 WriteReg32(PRI_STREAM2_STRIDE, 225 (((mode.bytesPerRow * 2) << 16) & 0x3FFF0000) | 226 (mode.bytesPerRow & 0x00001fff)); 227 228 // MM81C0 and 81C4 are used to control primary stream. 229 WriteReg32(PRI_STREAM_FBUF_ADDR0, si.frameBufferOffset); 230 WriteReg32(PRI_STREAM_FBUF_ADDR1, 0x80000000); 231 WriteReg32(PRI_STREAM2_FBUF_ADDR0, (si.frameBufferOffset & 0xfffffffc) | 0x80000000); 232 WriteReg32(PRI_STREAM2_FBUF_ADDR1, si.frameBufferOffset & 0xfffffffc); 233 234 // Bit 28:block write disable. 235 WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_BD64 | 0x10000000); 236 } 237 238 239 static void 240 Savage_SetGBD_2000(const DisplayModeEx& mode) 241 { 242 SharedInfo& si = *gInfo.sharedInfo; 243 int bci_enable = BCI_ENABLE_TWISTER; 244 245 // MM81C0 and 81B0 are used to control primary stream. 246 WriteReg32(PRI_STREAM_FBUF_ADDR0, si.frameBufferOffset); 247 WriteReg32(PRI_STREAM2_FBUF_ADDR0, si.frameBufferOffset); 248 249 // Program Primary Stream Stride Register. 250 // 251 // Tell engine if tiling on or off, set primary stream stride, and 252 // if tiling, set tiling bits/pixel and primary stream tile offset. 253 // Note that tile offset (bits 16 - 29) must be scanline width in 254 // bytes/128bytespertile * 256 Qwords/tile. This is equivalent to 255 // lDelta * 2. Remember that if tiling, lDelta is screenwidth in 256 // bytes padded up to an even number of tilewidths. 257 258 WriteReg32(PRI_STREAM_STRIDE, ((mode.bytesPerRow << 4) & 0x7ff0)); 259 WriteReg32(PRI_STREAM2_STRIDE, ((mode.bytesPerRow << 4) & 0x7ff0)); 260 261 // CR67_3: 262 // = 1 stream processor MMIO address and stride register 263 // are used to control the primary stream. 264 // = 0 standard VGA address and stride registers 265 // are used to control the primary streams 266 267 WriteCrtcReg(0x67, 0x08, 0x08); 268 269 // Bit 28:block write disable. 270 WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_BD64 | 0x10000000); 271 272 WriteCrtcReg(0x73, 0x00, 0x20); // CR73 bit 5 = 0 block write disable 273 } 274 275 276 277 static void 278 Savage_SetGBD(const DisplayModeEx& mode) 279 { 280 SharedInfo& si = *gInfo.sharedInfo; 281 282 VerticalRetraceWait(); 283 284 switch (gInfo.sharedInfo->chipType) { 285 case S3_SAVAGE_3D: 286 Savage_SetGBD_3D(mode); 287 break; 288 289 case S3_SAVAGE_MX: 290 Savage_SetGBD_MX(mode); 291 break; 292 293 case S3_SAVAGE4: 294 case S3_PROSAVAGE: 295 case S3_TWISTER: 296 case S3_PROSAVAGE_DDR: 297 Savage_SetGBD_Twister(mode); 298 break; 299 300 case S3_SUPERSAVAGE: 301 Savage_SetGBD_Super(mode); 302 break; 303 304 case S3_SAVAGE2000: 305 Savage_SetGBD_2000(mode); 306 break; 307 } 308 309 WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD 310 311 // Set up the Global Bitmap Descriptor used for BCI. 312 // Do not enable block_write because we can't determine if the memory 313 // type is a certain type of SGRAM for which block write can be used. 314 // bit 24~25: tile format, 00 = linear 315 // bit 28: block write disble/enable, 0 = disable, 1 = enable 316 317 si.globalBitmapDesc = mode.timing.h_display | (mode.bpp << 16) 318 | TILE_FORMAT_LINEAR | BCI_BD_BW_DISABLE | S3_BD64; // disable block write 319 } 320 321 322 static void 323 Savage_Initialize2DEngine(const DisplayModeEx& mode) 324 { 325 SharedInfo& si = *gInfo.sharedInfo; 326 327 WriteCrtcReg(0x40, 0x01); // enable graphics engine 328 WriteCrtcReg(0x31, 0x0c); // turn on 16-bit register access 329 330 // Setup plane masks. 331 WriteReg32(0x8128, ~0); // enable all write planes 332 WriteReg32(0x812C, ~0); // enable all read planes 333 WriteReg16(0x8134, 0x27); 334 WriteReg16(0x8136, 0x07); 335 336 switch (si.chipType) { 337 case S3_SAVAGE_3D: 338 case S3_SAVAGE_MX: 339 340 WriteReg32(0x48C18, ReadReg32(0x48C18) & 0x3FF0); // Disable BCI 341 342 // Setup BCI command overflow buffer. 0x48c14 343 // Bits 0-11 = Bits 22-11 of the Command Buffer Offset. 344 // Bits 12-28 = Total number of entries in the command buffer(Read only). 345 // Bits 29-31 = COB size index, 111 = 32K entries or 128K bytes 346 WriteReg32(0x48C14, (si.cobOffset >> 11) | (si.cobSizeIndex << 29)); 347 348 // Program shadow status update. 349 WriteReg32(0x48C10, 0x78207220); 350 351 WriteReg32(0x48C0C, 0); 352 // Enable BCI and command overflow buffer. 353 WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x0C); 354 break; 355 356 case S3_SAVAGE4: 357 case S3_PROSAVAGE: 358 case S3_TWISTER: 359 case S3_PROSAVAGE_DDR: 360 case S3_SUPERSAVAGE: 361 362 // Some Savage4 and ProSavage chips have coherency problems with 363 // respect to the Command Overflow Buffer (COB); thus, do not 364 // enable the COB. 365 366 WriteReg32(0x48C18, ReadReg32(0x48C18) & 0x3FF0); // Disable BCI 367 WriteReg32(0x48C10, 0x00700040); 368 WriteReg32(0x48C0C, 0); 369 WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x08); // enable BCI without COB 370 371 break; 372 373 case S3_SAVAGE2000: 374 375 // Disable BCI. 376 WriteReg32(0x48C18, 0); 377 // Setup BCI command overflow buffer. 378 WriteReg32(0x48C18, (si.cobOffset >> 7) | (si.cobSizeIndex)); 379 // Disable shadow status update. 380 WriteReg32(0x48A30, 0); 381 // Enable BCI and command overflow buffer. 382 WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x00280000); 383 384 break; 385 } 386 387 // Use and set global bitmap descriptor. 388 389 Savage_SetGBD(mode); 390 } 391 392 393 static void 394 Savage_GEReset(const DisplayModeEx& mode) 395 { 396 gInfo.WaitIdleEmpty(); 397 snooze(10000); 398 399 for (int r = 1; r < 10; r++) { 400 bool bSuccess = false; 401 402 WriteCrtcReg(0x66, 0x02, 0x02); 403 snooze(10000); 404 WriteCrtcReg(0x66, 0x00, 0x02); 405 snooze(10000); 406 407 gInfo.WaitIdleEmpty(); 408 409 WriteReg32(DEST_SRC_STR, mode.bytesPerRow << 16 | mode.bytesPerRow); 410 411 snooze(10000); 412 switch (gInfo.sharedInfo->chipType) { 413 case S3_SAVAGE_3D: 414 case S3_SAVAGE_MX: 415 bSuccess = (STATUS_WORD0 & 0x0008ffff) == 0x00080000; 416 break; 417 418 case S3_SAVAGE4: 419 case S3_PROSAVAGE: 420 case S3_PROSAVAGE_DDR: 421 case S3_TWISTER: 422 case S3_SUPERSAVAGE: 423 bSuccess = (ALT_STATUS_WORD0 & 0x0081ffff) == 0x00800000; 424 break; 425 426 case S3_SAVAGE2000: 427 bSuccess = (ALT_STATUS_WORD0 & 0x008fffff) == 0; 428 break; 429 } 430 431 if (bSuccess) 432 break; 433 434 snooze(10000); 435 TRACE("Savage_GEReset(), restarting S3 graphics engine reset %2d ...\n", r); 436 } 437 438 // At this point, the FIFO is empty and the engine is idle. 439 440 WriteReg32(SRC_BASE, 0); 441 WriteReg32(DEST_BASE, 0); 442 WriteReg32(CLIP_L_R, ((0) << 16) | mode.timing.h_display); 443 WriteReg32(CLIP_T_B, ((0) << 16) | mode.timing.v_display); 444 WriteReg32(MONO_PAT_0, ~0); 445 WriteReg32(MONO_PAT_1, ~0); 446 447 Savage_SetGBD(mode); 448 } 449 450 451 static void 452 Savage_CalcClock(long freq, int min_m, 453 int min_n1, int max_n1, 454 int min_n2, int max_n2, 455 long freq_min, long freq_max, 456 unsigned int *mdiv, unsigned int *ndiv, unsigned int *r) 457 { 458 uint8 best_n1 = 16 + 2, best_n2 = 2, best_m = 125 + 2; 459 460 double ffreq = freq / 1000.0 / BASE_FREQ; 461 double ffreq_max = freq_max / 1000.0 / BASE_FREQ; 462 double ffreq_min = freq_min / 1000.0 / BASE_FREQ; 463 464 if (ffreq < ffreq_min / (1 << max_n2)) { 465 TRACE("Savage_CalcClock() invalid frequency %1.3f Mhz\n", ffreq * BASE_FREQ); 466 ffreq = ffreq_min / (1 << max_n2); 467 } 468 if (ffreq > ffreq_max / (1 << min_n2)) { 469 TRACE("Savage_CalcClock() invalid frequency %1.3f Mhz\n", ffreq * BASE_FREQ); 470 ffreq = ffreq_max / (1 << min_n2); 471 } 472 473 // Work out suitable timings. 474 475 double best_diff = ffreq; 476 477 for (uint8 n2 = min_n2; n2 <= max_n2; n2++) { 478 for (uint8 n1 = min_n1 + 2; n1 <= max_n1 + 2; n1++) { 479 int m = (int)(ffreq * n1 * (1 << n2) + 0.5); 480 if (m < min_m + 2 || m > 127 + 2) 481 continue; 482 483 double div = (double)(m) / (double)(n1); 484 if ((div >= ffreq_min) && (div <= ffreq_max)) { 485 double diff = ffreq - div / (1 << n2); 486 if (diff < 0.0) 487 diff = -diff; 488 if (diff < best_diff) { 489 best_diff = diff; 490 best_m = m; 491 best_n1 = n1; 492 best_n2 = n2; 493 } 494 } 495 } 496 } 497 498 *ndiv = best_n1 - 2; 499 *r = best_n2; 500 *mdiv = best_m - 2; 501 } 502 503 504 static void 505 Savage_WriteMode(const DisplayModeEx& mode, const SavageRegRec& regRec) 506 { 507 TRACE("Savage_WriteMode() begin\n"); 508 509 SharedInfo& si = *gInfo.sharedInfo; 510 511 gInfo.WaitIdleEmpty(); 512 513 WriteMiscOutReg(0x23); 514 WriteCrtcReg(0x38, 0x48); // unlock sys regs CR20~CR3F 515 WriteCrtcReg(0x39, 0xa0); // unlock sys regs CR40~CRFF 516 WriteSeqReg(0x08, 0x06); // unlock sequencer regs SR09~SRFF 517 518 if ( ! S3_SAVAGE_MOBILE_SERIES(si.chipType)) 519 Savage_Initialize2DEngine(mode); 520 521 if (ReadCrtcReg(0x66) & 0x01) { 522 Savage_GEReset(mode); // reset GE to make sure nothing is going on 523 } 524 525 WriteCrtcReg(0x67, regRec.CR67 & ~0x0e); // no STREAMS yet old and new 526 527 // Set register SR19 to zero so that the ProSavage chips will start up 528 // when booting under BeOS using the default boot screen, and set register 529 // CR5F to zero so that the ProSavage chips will start up when Haiku boot 530 // screen had a depth of 32 bits/pixel 531 532 if (si.chipType == S3_PROSAVAGE || si.chipType == S3_TWISTER) { 533 WriteSeqReg(0x19, 0); 534 WriteCrtcReg(0x5f, 0); 535 } 536 537 // Clear bit 3 in SR30 so that Savage MX chip will startup. If bit 3 is 538 // not cleared, it will startup only if booting under BeOS using the 539 // default boot screen or the boot screen resolution matches the resolution 540 // of the mode currently being set. 541 542 if (si.chipType == S3_SAVAGE_MX) 543 WriteSeqReg(0x30, 0x00, 0x08); 544 545 // Set extended regs. 546 547 WriteCrtcReg(0x66, regRec.CR66); 548 WriteCrtcReg(0x3a, regRec.CR3A); 549 WriteCrtcReg(0x58, regRec.CR58); 550 WriteCrtcReg(0x53, regRec.CR53 & 0x7f); 551 552 // If Savage IX/MX or SuperSavage, set SR54 & SR56 to 0x10 so that when 553 // resolutions are set where the width and/or height is less than the 554 // native resolution of the attached LCD display, the chip will not expand 555 // the display to fill the screen. That is, if a resolution is set to 556 // 640x480, it will use only 640x480 pixels for the display. When the chip 557 // expands the display, text is much less readable. 558 559 if (S3_SAVAGE_MOBILE_SERIES(si.chipType)) { 560 WriteSeqReg(0x54, 0x10); 561 WriteSeqReg(0x56, 0x10); 562 } 563 564 // Set the standard CRTC vga regs. 565 566 WriteCrtcReg(0x11, 0x00, 0x80); // unlock CRTC reg's 0-7 by clearing bit 7 of cr11 567 568 for (int j = 0; j < (int)B_COUNT_OF(regRec.CRTC); j++) 569 WriteCrtcReg(j, regRec.CRTC[j]); 570 571 // Setup HSYNC & VSYNC polarity. 572 573 uint8 temp = ((ReadMiscOutReg() & 0x3f) | 0x0c); 574 575 if (!(mode.timing.flags & B_POSITIVE_HSYNC)) 576 temp |= 0x40; 577 if (!(mode.timing.flags & B_POSITIVE_VSYNC)) 578 temp |= 0x80; 579 580 WriteMiscOutReg(temp); 581 582 // Extended mode timing registers. 583 WriteCrtcReg(0x53, regRec.CR53); 584 WriteCrtcReg(0x5d, regRec.CR5D); 585 WriteCrtcReg(0x5e, regRec.CR5E); 586 WriteCrtcReg(0x3b, regRec.CR3B); 587 WriteCrtcReg(0x3c, regRec.CR3C); 588 WriteCrtcReg(0x43, regRec.CR43); 589 WriteCrtcReg(0x65, regRec.CR65); 590 591 // Restore the desired video mode with cr67. 592 WriteCrtcReg(0x67, regRec.CR67 & ~0x0e); // no streams for new and old streams engines 593 594 // Other mode timing and extended regs. 595 WriteCrtcReg(0x34, regRec.CR34); 596 WriteCrtcReg(0x42, regRec.CR42); 597 WriteCrtcReg(0x45, regRec.CR45); 598 WriteCrtcReg(0x50, regRec.CR50); 599 WriteCrtcReg(0x51, regRec.CR51); 600 601 // Memory timings. 602 VerticalRetraceWait(); 603 WriteCrtcReg(0x69, regRec.CR69); 604 605 WriteCrtcReg(0x33, regRec.CR33); 606 WriteCrtcReg(0x86, regRec.CR86); 607 WriteCrtcReg(0x88, regRec.CR88); 608 WriteCrtcReg(0x90, regRec.CR90); 609 WriteCrtcReg(0x91, regRec.CR91); 610 611 if (si.chipType == S3_SAVAGE4) 612 WriteCrtcReg(0xb0, regRec.CRB0); 613 614 WriteSeqReg(0x1b, regRec.SR1B); 615 616 if ( ! (S3_SAVAGE_MOBILE_SERIES(si.chipType) && si.displayType == MT_LCD)) { 617 // Set extended seq regs for dclk. 618 WriteSeqReg(0x12, regRec.SR12); 619 WriteSeqReg(0x13, regRec.SR13); 620 WriteSeqReg(0x29, regRec.SR29); 621 622 // Load new m, n pll values for dclk & mclk. 623 temp = ReadSeqReg(0x15) & ~0x20; 624 WriteSeqReg(0x15, temp); 625 WriteSeqReg(0x15, temp | 0x20); 626 WriteSeqReg(0x15, temp); 627 snooze(100); 628 } 629 630 // Now write out cr67 in full, possibly starting STREAMS. 631 VerticalRetraceWait(); 632 WriteCrtcReg(0x67, regRec.CR67); 633 634 uint8 cr66 = ReadCrtcReg(0x66); 635 WriteCrtcReg(0x66, cr66 | 0x80); 636 uint8 cr3a = ReadCrtcReg(0x3a); 637 WriteCrtcReg(0x3a, cr3a | 0x80); 638 639 Savage_GEReset(mode); 640 641 WriteCrtcReg(0x66, cr66); 642 WriteCrtcReg(0x3a, cr3a); 643 644 Savage_Initialize2DEngine(mode); 645 646 WriteCrtcReg(0x40, 0x01); // enable graphics engine 647 648 Savage_SetGBD(mode); 649 650 TRACE("Savage_WriteMode() done\n"); 651 652 return; 653 } 654 655 656 static bool 657 Savage_ModeInit(const DisplayModeEx& mode) 658 { 659 TRACE("Savage_ModeInit(%dx%d, %d kHz)\n", 660 mode.timing.h_display, mode.timing.v_display, mode.timing.pixel_clock); 661 662 SharedInfo& si = *gInfo.sharedInfo; 663 SavageRegRec regRec; 664 665 int horizScaleFactor = 1; 666 667 if (mode.bpp == 16 && si.chipType == S3_SAVAGE_3D) 668 horizScaleFactor = 2; 669 670 InitCrtcTimingValues(mode, horizScaleFactor, regRec.CRTC, 671 regRec.CR3B, regRec.CR3C, regRec.CR5D, regRec.CR5E); 672 regRec.CRTC[0x17] = 0xEB; 673 674 int dclk = mode.timing.pixel_clock; 675 regRec.CR67 = 0x00; 676 677 switch (mode.bpp) { 678 case 8: 679 if ((si.chipType == S3_SAVAGE2000) && (dclk >= 230000)) 680 regRec.CR67 = 0x10; // 8bpp, 2 pixels/clock 681 else 682 regRec.CR67 = 0x00; // 8bpp, 1 pixel/clock 683 break; 684 685 case 15: 686 if (S3_SAVAGE_MOBILE_SERIES(si.chipType) 687 || ((si.chipType == S3_SAVAGE2000) && (dclk >= 230000))) 688 regRec.CR67 = 0x30; // 15bpp, 2 pixel/clock 689 else 690 regRec.CR67 = 0x20; // 15bpp, 1 pixels/clock 691 break; 692 693 case 16: 694 if (S3_SAVAGE_MOBILE_SERIES(si.chipType) 695 || ((si.chipType == S3_SAVAGE2000) && (dclk >= 230000))) 696 regRec.CR67 = 0x50; // 16bpp, 2 pixel/clock 697 else 698 regRec.CR67 = 0x40; // 16bpp, 1 pixels/clock 699 break; 700 701 case 32: 702 regRec.CR67 = 0xd0; 703 break; 704 } 705 706 regRec.CR3A = (ReadCrtcReg(0x3a) & 0x7f) | 0x15; 707 regRec.CR53 = 0x00; 708 regRec.CR66 = 0x89; 709 regRec.CR58 = (ReadCrtcReg(0x58) & 0x80) | 0x13; 710 711 regRec.SR1B = ReadSeqReg(0x1b) | 0x10; // enable 8-bit Color Lookup Table 712 713 regRec.CR43 = regRec.CR45 = regRec.CR65 = 0x00; 714 715 unsigned int m, n, r; 716 Savage_CalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r); 717 regRec.SR12 = (r << 6) | (n & 0x3f); 718 regRec.SR13 = m & 0xff; 719 regRec.SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2; 720 721 TRACE("CalcClock, m: %d n: %d r: %d\n", m, n, r); 722 723 regRec.CR42 = 0x00; 724 regRec.CR34 = 0x10; 725 726 int width = mode.bytesPerRow / 8; 727 regRec.CR91 = 0xff & width; 728 regRec.CR51 = (0x300 & width) >> 4; 729 regRec.CR90 = 0x80 | (width >> 8); 730 731 // Set frame buffer description. 732 733 if (mode.bpp <= 8) 734 regRec.CR50 = 0; 735 else if (mode.bpp <= 16) 736 regRec.CR50 = 0x10; 737 else 738 regRec.CR50 = 0x30; 739 740 width = mode.timing.h_display; // width of display in pixels 741 742 if (width == 640) 743 regRec.CR50 |= 0x40; 744 else if (width == 800) 745 regRec.CR50 |= 0x80; 746 else if (width == 1024) 747 regRec.CR50 |= 0x00; 748 else if (width == 1152) 749 regRec.CR50 |= 0x01; 750 else if (width == 1280) 751 regRec.CR50 |= 0xc0; 752 else if (width == 1600) 753 regRec.CR50 |= 0x81; 754 else 755 regRec.CR50 |= 0xc1; // use GBD 756 757 if (S3_SAVAGE_MOBILE_SERIES(si.chipType)) 758 regRec.CR33 = 0x00; 759 else 760 regRec.CR33 = 0x08; 761 762 regRec.CR69 = 0; 763 regRec.CR86 = ReadCrtcReg(0x86) | 0x08; 764 regRec.CR88 = ReadCrtcReg(0x88) | DISABLE_BLOCK_WRITE_2D; 765 regRec.CRB0 = ReadCrtcReg(0xb0) | 0x80; 766 767 Savage_WriteMode(mode, regRec); // write registers to set mode 768 769 return true; 770 } 771 772 773 774 bool 775 Savage_SetDisplayMode(const DisplayModeEx& mode) 776 { 777 // The code to actually configure the display. 778 // All the error checking must be done in ProposeDisplayMode(), 779 // and assume that the mode values we get here are acceptable. 780 781 WriteSeqReg(0x01, 0x20, 0x20); // blank the screen 782 783 if ( ! Savage_ModeInit(mode)) { 784 TRACE("Savage_ModeInit() failed\n"); 785 return false; 786 } 787 788 Savage_AdjustFrame(mode); 789 790 WriteSeqReg(0x01, 0x00, 0x20); // unblank the screen 791 792 return true; 793 } 794 795 796 797 void 798 Savage_AdjustFrame(const DisplayModeEx& mode) 799 { 800 // Adjust start address in frame buffer. 801 802 SharedInfo& si = *gInfo.sharedInfo; 803 804 int address = (mode.v_display_start * mode.virtual_width) 805 + ((mode.h_display_start & ~0x3F) * (mode.bpp / 8)); 806 address &= ~0x1F; 807 address += si.frameBufferOffset; 808 809 switch (si.chipType) { 810 case S3_SAVAGE_MX: 811 WriteReg32(PRI_STREAM_FBUF_ADDR0, address & 0xFFFFFFFC); 812 WriteReg32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFFC); 813 break; 814 case S3_SUPERSAVAGE: 815 WriteReg32(PRI_STREAM_FBUF_ADDR0, 0x80000000); 816 WriteReg32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFF8); 817 break; 818 case S3_SAVAGE2000: 819 // Certain Y values seems to cause havoc, not sure why 820 WriteReg32(PRI_STREAM_FBUF_ADDR0, (address & 0xFFFFFFF8)); 821 WriteReg32(PRI_STREAM2_FBUF_ADDR0, (address & 0xFFFFFFF8)); 822 break; 823 default: 824 WriteReg32(PRI_STREAM_FBUF_ADDR0, address | 0xFFFFFFFC); 825 WriteReg32(PRI_STREAM_FBUF_ADDR1, address | 0x80000000); 826 break; 827 } 828 829 return; 830 } 831 832 833 void 834 Savage_SetIndexedColors(uint count, uint8 first, uint8* colorData, uint32 flags) 835 { 836 // Set the indexed color palette for 8-bit color depth mode. 837 838 (void)flags; // avoid compiler warning for unused arg 839 840 if (gInfo.sharedInfo->displayMode.space != B_CMAP8) 841 return ; 842 843 while (count--) { 844 WriteIndexedColor(first++, // color index 845 colorData[0], // red 846 colorData[1], // green 847 colorData[2]); // blue 848 colorData += 3; 849 } 850 } 851