1 /* 2 Haiku S3 Savage driver adapted from the X.org Savage driver. 3 4 Copyright 1995-1997 The XFree86 Project, Inc. 5 6 Copyright 2007-2008 Haiku, Inc. All rights reserved. 7 Distributed under the terms of the MIT license. 8 9 Authors: 10 Gerald Zajac 2006-2008 11 */ 12 13 14 #include "accel.h" 15 #include "savage.h" 16 17 18 #define BASE_FREQ 14.31818 19 20 21 struct SavageRegRec { 22 uint8 CRTC[25]; // Crtc Controller reg's 23 24 uint8 SR12, SR13, SR15, SR18, SR1B, SR29; 25 uint8 CR31, CR33, CR34, CR3A, CR3B, CR3C; 26 uint8 CR40, CR42, CR43, CR45; 27 uint8 CR50, CR51, CR53, CR58, CR5D, CR5E; 28 uint8 CR65, CR66, CR67, CR69; 29 uint8 CR86, CR88; 30 uint8 CR90, CR91, CRB0; 31 }; 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 TRACE("Savage_SetGBD_Twister()\n"); 43 44 if (si.chipType == S3_SAVAGE4) 45 bci_enable = BCI_ENABLE; 46 else 47 bci_enable = BCI_ENABLE_TWISTER; 48 49 // MM81C0 and 81C4 are used to control primary stream. 50 WriteReg32(PRI_STREAM_FBUF_ADDR0, 0); 51 WriteReg32(PRI_STREAM_FBUF_ADDR1, 0); 52 53 // Program Primary Stream Stride Register. 54 // 55 // Tell engine if tiling on or off, set primary stream stride, and 56 // if tiling, set tiling bits/pixel and primary stream tile offset. 57 // Note that tile offset (bits 16 - 29) must be scanline width in 58 // bytes/128bytespertile * 256 Qwords/tile. This is equivalent to 59 // lDelta * 2. Remember that if tiling, lDelta is screenwidth in 60 // bytes padded up to an even number of tilewidths. 61 62 WriteReg32(PRI_STREAM_STRIDE, 63 (((mode.bytesPerRow * 2) << 16) & 0x3FFFE000) | 64 (mode.bytesPerRow & 0x00001fff)); 65 66 // CR69, bit 7 = 1 67 // to use MM streams processor registers to control primary stream. 68 69 WriteCrtcReg(0x69, 0x80, 0x80); 70 71 WriteReg32(0x8128, 0xFFFFFFFFL); 72 WriteReg32(0x812C, 0xFFFFFFFFL); 73 74 WriteReg32(S3_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64); 75 76 WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD 77 78 // If MS1NB style linear tiling mode. 79 // bit MM850C[15] = 0 select NB linear tile mode. 80 // bit MM850C[15] = 1 select MS-1 128-bit non-linear tile mode. 81 82 uint32 ulTmp = ReadReg32(ADVANCED_FUNC_CTRL) | 0x8000; // use MS-s style tile mode 83 WriteReg32(ADVANCED_FUNC_CTRL, ulTmp); 84 85 // Set up Tiled Surface Registers 86 // Bit 25:20 - Surface width in tiles. 87 // Bit 29 - Y Range Flag. 88 // Bit 31:30 = 00, 4 bpp. 89 // = 01, 8 bpp. 90 // = 10, 16 bpp. 91 // = 11, 32 bpp. 92 93 // Global Bitmap Descriptor Register MM816C - twister/prosavage 94 // bit 24~25: tile format 95 // 00: linear 96 // 01: destination tiling format 97 // 10: texture tiling format 98 // 11: reserved 99 // bit 28: block write disble/enable 100 // 0: disable 101 // 1: enable 102 103 // Global Bitmap Descriptor Register MM816C - savage4 104 // bit 24~25: tile format 105 // 00: linear 106 // 01: reserved 107 // 10: 16 bpp tiles 108 // 11: 32 bpp tiles 109 // bit 28: block write disable/enable 110 // 0: enable 111 // 1: disable 112 113 // Do not enable block_write even for non-tiling modes, because 114 // the driver cannot determine if the memory type is the certain 115 // type of SGRAM for which block_write can be used. 116 117 si.GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; // linear 118 si.GlobalBD.bd1.HighPart.ResBWTile |= 0x10; // disable block write 119 // HW uses width. 120 si.GlobalBD.bd1.HighPart.Stride = (uint16)(mode.timing.h_display); // number of pixels per line 121 si.GlobalBD.bd1.HighPart.Bpp = (uint8)(mode.bpp); 122 si.GlobalBD.bd1.Offset = si.frameBufferOffset; 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 // CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0). 133 // bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window 134 // at A000:0. 135 136 WriteCrtcReg(MEMORY_CONFIG_REG, 0x00, 0x01); 137 138 // Program the GBD and SBD's. 139 140 WriteReg32(S3_GLB_BD_LOW, si.GlobalBD.bd2.LoPart); 141 WriteReg32(S3_GLB_BD_HIGH, si.GlobalBD.bd2.HiPart | bci_enable | S3_LITTLE_ENDIAN | S3_BD64); 142 WriteReg32(S3_PRI_BD_LOW, si.GlobalBD.bd2.LoPart); 143 WriteReg32(S3_PRI_BD_HIGH, si.GlobalBD.bd2.HiPart); 144 } 145 146 147 static void 148 Savage_SetGBD_3D(const DisplayModeEx& mode) 149 { 150 TRACE("Savage_SetGBD_3D()\n"); 151 152 SharedInfo& si = *gInfo.sharedInfo; 153 int bci_enable = BCI_ENABLE; 154 155 // MM81C0 and 81C4 are used to control primary stream. 156 WriteReg32(PRI_STREAM_FBUF_ADDR0, 0); 157 WriteReg32(PRI_STREAM_FBUF_ADDR1, 0); 158 159 // Program Primary Stream Stride Register. 160 // 161 // Tell engine if tiling on or off, set primary stream stride, and 162 // if tiling, set tiling bits/pixel and primary stream tile offset. 163 // Note that tile offset (bits 16 - 29) must be scanline width in 164 // bytes/128bytespertile * 256 Qwords/tile. This is equivalent to 165 // lDelta * 2. Remember that if tiling, lDelta is screenwidth in 166 // bytes padded up to an even number of tilewidths. 167 168 WriteReg32(PRI_STREAM_STRIDE, 169 (((mode.bytesPerRow * 2) << 16) & 0x3FFFE000) | 170 (mode.bytesPerRow & 0x00001fff)); 171 172 // CR69, bit 7 = 1 to use MM streams processor registers to control primary 173 // stream. 174 175 WriteCrtcReg(0x69, 0x80, 0x80); 176 177 WriteReg32(0x8128, 0xFFFFFFFFL); 178 WriteReg32(0x812C, 0xFFFFFFFFL); 179 180 WriteReg32(S3_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64); 181 182 WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD 183 184 // If MS1NB style linear tiling mode. 185 // bit MM850C[15] = 0 select NB linear tile mode. 186 // bit MM850C[15] = 1 select MS-1 128-bit non-linear tile mode. 187 188 uint32 ulTmp = ReadReg32(ADVANCED_FUNC_CTRL) | 0x8000; // use MS-s style tile mode 189 WriteReg32(ADVANCED_FUNC_CTRL, ulTmp); 190 191 // Tiled Surface 0 Registers MM48C40: 192 // bit 0~23: tile surface 0 frame buffer offset 193 // bit 24~29:tile surface 0 width 194 // bit 30~31:tile surface 0 bits/pixel 195 // 00: reserved 196 // 01, 8 bits 197 // 10, 16 Bits. 198 // 11, 32 Bits. 199 200 // Global Bitmap Descriptor Register MM816C 201 // bit 24~25: tile format 202 // 00: linear 203 // 01: reserved 204 // 10: 16 bpp tiles 205 // 11: 32 bpp tiles 206 // bit 28: block write disable/enable 207 // 0: enable 208 // 1: disable 209 210 // Do not enable block_write even for non-tiling modes, because 211 // the driver cannot determine if the memory type is the certain 212 // type of SGRAM for which block_write can be used. 213 214 si.GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; // linear 215 si.GlobalBD.bd1.HighPart.ResBWTile |= 0x10; // disable block write 216 // HW uses width. 217 si.GlobalBD.bd1.HighPart.Stride = (uint16)(mode.timing.h_display); // number of pixels per line 218 si.GlobalBD.bd1.HighPart.Bpp = (uint8)(mode.bpp); 219 si.GlobalBD.bd1.Offset = si.frameBufferOffset; 220 221 // CR88, bit 4 - Block write enabled/disabled. 222 // 223 // Note: Block write must be disabled when writing to tiled 224 // memory. Even when writing to non-tiled memory, block 225 // write should only be enabled for certain types of SGRAM. 226 227 WriteCrtcReg(0x88, DISABLE_BLOCK_WRITE_2D, DISABLE_BLOCK_WRITE_2D); 228 229 // CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0). 230 // bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window 231 // at A000:0. 232 233 WriteCrtcReg(MEMORY_CONFIG_REG, 0x00, 0x01); 234 235 // Program the GBD and SBD's. 236 WriteReg32(S3_GLB_BD_LOW, si.GlobalBD.bd2.LoPart); 237 WriteReg32(S3_GLB_BD_HIGH, si.GlobalBD.bd2.HiPart | bci_enable | S3_LITTLE_ENDIAN | S3_BD64); 238 WriteReg32(S3_PRI_BD_LOW, si.GlobalBD.bd2.LoPart); 239 WriteReg32(S3_PRI_BD_HIGH, si.GlobalBD.bd2.HiPart); 240 } 241 242 243 static void 244 Savage_SetGBD_MX(const DisplayModeEx& mode) 245 { 246 TRACE("Savage_SetGBD_MX()\n"); 247 248 SharedInfo& si = *gInfo.sharedInfo; 249 int bci_enable = BCI_ENABLE; 250 251 // CR67_3: 252 // = 1 stream processor MMIO address and stride register 253 // are used to control the primary stream. 254 // = 0 standard VGA address and stride registers 255 // are used to control the primary streams. 256 257 WriteCrtcReg(0x67, 0x08, 0x08); 258 // IGA 2. 259 WriteSeqReg(0x26, 0x4f); // select IGA 2 read/writes 260 WriteCrtcReg(0x67, 0x08, 0x08); 261 WriteSeqReg(0x26, 0x40); // select IGA 1 262 263 // Set primary stream to bank 0 via reg CRCA. 264 WriteCrtcReg(MEMORY_CTRL0_REG, 0x00, MEM_PS1 + MEM_PS2); 265 266 // MM81C0 and 81C4 are used to control primary stream. 267 WriteReg32(PRI_STREAM_FBUF_ADDR0, si.frameBufferOffset & 0x7fffff); 268 WriteReg32(PRI_STREAM_FBUF_ADDR1, si.frameBufferOffset & 0x7fffff); 269 WriteReg32(PRI_STREAM2_FBUF_ADDR0, si.frameBufferOffset & 0x7fffff); 270 WriteReg32(PRI_STREAM2_FBUF_ADDR1, si.frameBufferOffset & 0x7fffff); 271 272 // Program Primary Stream Stride Register. 273 // 274 // Tell engine if tiling on or off, set primary stream stride, and 275 // if tiling, set tiling bits/pixel and primary stream tile offset. 276 // Note that tile offset (bits 16 - 29) must be scanline width in 277 // bytes/128bytespertile * 256 Qwords/tile. This is equivalent to 278 // lDelta * 2. Remember that if tiling, lDelta is screenwidth in 279 // bytes padded up to an even number of tilewidths. 280 281 WriteReg32(PRI_STREAM_STRIDE, 282 (((mode.bytesPerRow * 2) << 16) & 0x3FFF0000) | 283 (mode.bytesPerRow & 0x00003fff)); 284 WriteReg32(PRI_STREAM2_STRIDE, 285 (((mode.bytesPerRow * 2) << 16) & 0x3FFF0000) | 286 (mode.bytesPerRow & 0x00003fff)); 287 288 WriteReg32(0x8128, 0xFFFFFFFFL); 289 WriteReg32(0x812C, 0xFFFFFFFFL); 290 291 WriteReg32(S3_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64); 292 293 WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD 294 295 // CR78, bit 3 - Block write enabled(1)/disabled(0). 296 // bit 2 - Block write cycle time(0:2 cycles,1: 1 cycle) 297 // Note: Block write must be disabled when writing to tiled 298 // memory. Even when writing to non-tiled memory, block 299 // write should only be enabled for certain types of SGRAM. 300 301 WriteCrtcReg(0x78, 0xfb, 0xfb); 302 303 // Tiled Surface 0 Registers MM48C40: 304 // bit 0~23: tile surface 0 frame buffer offset 305 // bit 24~29:tile surface 0 width 306 // bit 30~31:tile surface 0 bits/pixel 307 // 00: reserved 308 // 01, 8 bits 309 // 10, 16 Bits. 310 // 11, 32 Bits. 311 312 // Global Bitmap Descriptor Register MM816C 313 // bit 24~25: tile format 314 // 00: linear 315 // 01: reserved 316 // 10: 16 bit 317 // 11: 32 bit 318 // bit 28: block write disble/enable 319 // 0: enable 320 // 1: disable 321 322 // Do not enable block_write even for non-tiling modes, because 323 // the driver cannot determine if the memory type is the certain 324 // type of SGRAM for which block_write can be used. 325 326 si.GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; // linear 327 si.GlobalBD.bd1.HighPart.ResBWTile |= 0x10; // disable block write 328 // HW uses width. 329 si.GlobalBD.bd1.HighPart.Stride = (uint16)(mode.timing.h_display); // number of pixels per line 330 si.GlobalBD.bd1.HighPart.Bpp = (uint8)(mode.bpp); 331 si.GlobalBD.bd1.Offset = si.frameBufferOffset; 332 333 // CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0). 334 // bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window 335 // at A000:0. 336 337 WriteCrtcReg(MEMORY_CONFIG_REG, 0x04, 0x05); // CR31 338 339 // Program the GBD and SBD's. 340 WriteReg32(S3_GLB_BD_LOW, si.GlobalBD.bd2.LoPart ); 341 // 8: bci enable. 342 WriteReg32(S3_GLB_BD_HIGH, (si.GlobalBD.bd2.HiPart 343 | bci_enable | S3_LITTLE_ENDIAN | S3_BD64)); 344 WriteReg32(S3_PRI_BD_LOW, si.GlobalBD.bd2.LoPart); 345 WriteReg32(S3_PRI_BD_HIGH, si.GlobalBD.bd2.HiPart); 346 WriteReg32(S3_SEC_BD_LOW, si.GlobalBD.bd2.LoPart); 347 WriteReg32(S3_SEC_BD_HIGH, si.GlobalBD.bd2.HiPart); 348 } 349 350 351 static void 352 Savage_SetGBD_Super(const DisplayModeEx& mode) 353 { 354 TRACE("Savage_SetGBD_Super()\n"); 355 356 SharedInfo& si = *gInfo.sharedInfo; 357 int bci_enable = BCI_ENABLE_TWISTER; 358 359 // CR67_3: 360 // = 1 stream processor MMIO address and stride register 361 // are used to control the primary stream. 362 // = 0 standard VGA address and stride registers 363 // are used to control the primary streams. 364 365 WriteCrtcReg(0x67, 0x08, 0x08); 366 // IGA 2. 367 WriteSeqReg(0x26, 0x4f); // select IGA 2 read/writes 368 WriteCrtcReg(0x67, 0x08, 0x08); 369 WriteSeqReg(0x26, 0x40); // select IGA 1 370 371 // Load ps1 active registers as determined by MM81C0/81C4. 372 // Load ps2 active registers as determined by MM81B0/81B4. 373 374 WriteCrtcReg(0x65, 0x03, 0x03); 375 376 // Program Primary Stream Stride Register. 377 // 378 // Tell engine if tiling on or off, set primary stream stride, and 379 // if tiling, set tiling bits/pixel and primary stream tile offset. 380 // Note that tile offset (bits 16 - 29) must be scanline width in 381 // bytes/128bytespertile * 256 Qwords/tile. This is equivalent to 382 // lDelta * 2. Remember that if tiling, lDelta is screenwidth in 383 // bytes padded up to an even number of tilewidths. 384 385 WriteReg32(PRI_STREAM_STRIDE, 386 (((mode.bytesPerRow * 2) << 16) & 0x3FFF0000) | 387 (mode.bytesPerRow & 0x00001fff)); 388 WriteReg32(PRI_STREAM2_STRIDE, 389 (((mode.bytesPerRow * 2) << 16) & 0x3FFF0000) | 390 (mode.bytesPerRow & 0x00001fff)); 391 392 // MM81C0 and 81C4 are used to control primary stream. 393 WriteReg32(PRI_STREAM_FBUF_ADDR0, si.frameBufferOffset); 394 WriteReg32(PRI_STREAM_FBUF_ADDR1, 0x80000000); 395 WriteReg32(PRI_STREAM2_FBUF_ADDR0, (si.frameBufferOffset & 0xfffffffc) | 0x80000000); 396 WriteReg32(PRI_STREAM2_FBUF_ADDR1, si.frameBufferOffset & 0xfffffffc); 397 398 WriteReg32(0x8128, 0xFFFFFFFFL); 399 WriteReg32(0x812C, 0xFFFFFFFFL); 400 401 // Bit 28:block write disable. 402 WriteReg32(S3_GLB_BD_HIGH, bci_enable | S3_BD64 | 0x10000000); 403 404 WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD 405 406 // Do not enable block_write even for non-tiling modes, because 407 // the driver cannot determine if the memory type is the certain 408 // type of SGRAM for which block_write can be used. 409 410 si.GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; // linear 411 si.GlobalBD.bd1.HighPart.ResBWTile |= 0x10; // disable block write 412 // HW uses width. 413 si.GlobalBD.bd1.HighPart.Stride = (uint16)(mode.timing.h_display); // number of pixels per line 414 si.GlobalBD.bd1.HighPart.Bpp = (uint8)(mode.bpp); 415 si.GlobalBD.bd1.Offset = si.frameBufferOffset; 416 417 // CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0). 418 // bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window 419 // at A000:0. 420 421 WriteCrtcReg(MEMORY_CONFIG_REG, 0x00, 0x01); 422 423 // Program the GBD and SBDs. 424 WriteReg32(S3_GLB_BD_LOW, si.GlobalBD.bd2.LoPart ); 425 WriteReg32(S3_GLB_BD_HIGH, (si.GlobalBD.bd2.HiPart 426 | bci_enable | S3_LITTLE_ENDIAN | S3_BD64)); 427 WriteReg32(S3_PRI_BD_LOW, si.GlobalBD.bd2.LoPart); 428 WriteReg32(S3_PRI_BD_HIGH, si.GlobalBD.bd2.HiPart); 429 WriteReg32(S3_SEC_BD_LOW, si.GlobalBD.bd2.LoPart); 430 WriteReg32(S3_SEC_BD_HIGH, si.GlobalBD.bd2.HiPart); 431 } 432 433 434 static void 435 Savage_SetGBD_2000(const DisplayModeEx& mode) 436 { 437 TRACE("Savage_SetGBD_2000()\n"); 438 439 SharedInfo& si = *gInfo.sharedInfo; 440 int bci_enable = BCI_ENABLE_TWISTER; 441 442 // MM81C0 and 81B0 are used to control primary stream. 443 WriteReg32(PRI_STREAM_FBUF_ADDR0, si.frameBufferOffset); 444 WriteReg32(PRI_STREAM2_FBUF_ADDR0, si.frameBufferOffset); 445 446 // Program Primary Stream Stride Register. 447 // 448 // Tell engine if tiling on or off, set primary stream stride, and 449 // if tiling, set tiling bits/pixel and primary stream tile offset. 450 // Note that tile offset (bits 16 - 29) must be scanline width in 451 // bytes/128bytespertile * 256 Qwords/tile. This is equivalent to 452 // lDelta * 2. Remember that if tiling, lDelta is screenwidth in 453 // bytes padded up to an even number of tilewidths. 454 455 WriteReg32(PRI_STREAM_STRIDE, ((mode.bytesPerRow << 4) & 0x7ff0)); 456 WriteReg32(PRI_STREAM2_STRIDE, ((mode.bytesPerRow << 4) & 0x7ff0)); 457 458 // CR67_3: 459 // = 1 stream processor MMIO address and stride register 460 // are used to control the primary stream. 461 // = 0 standard VGA address and stride registers 462 // are used to control the primary streams 463 464 WriteCrtcReg(0x67, 0x08, 0x08); 465 466 WriteReg32(0x8128, 0xFFFFFFFFL); 467 WriteReg32(0x812C, 0xFFFFFFFFL); 468 469 // Bit 28:block write disable. 470 WriteReg32(S3_GLB_BD_HIGH, bci_enable | S3_BD64 | 0x10000000); 471 472 WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD 473 WriteCrtcReg(0x73, 0x00, 0x20); // CR73 bit 5 = 0 block write disable 474 475 // Do not enable block_write even for non-tiling modes, because 476 // the driver cannot determine if the memory type is the certain 477 // type of SGRAM for which block_write can be used. 478 479 si.GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; // linear 480 si.GlobalBD.bd1.HighPart.ResBWTile |= 0x10; // disable block write 481 // HW uses width. 482 si.GlobalBD.bd1.HighPart.Stride = (uint16)(mode.timing.h_display); // number of pixels per line 483 si.GlobalBD.bd1.HighPart.Bpp = (uint8)(mode.bpp); 484 si.GlobalBD.bd1.Offset = si.frameBufferOffset; 485 486 // CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0). 487 // bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window 488 // at A000:0. 489 490 WriteCrtcReg(MEMORY_CONFIG_REG, 0x00, 0x01); 491 492 // Program the GBD and SBDs. 493 WriteReg32(S3_GLB_BD_LOW, si.GlobalBD.bd2.LoPart ); 494 WriteReg32(S3_GLB_BD_HIGH, (si.GlobalBD.bd2.HiPart 495 | bci_enable | S3_LITTLE_ENDIAN | S3_BD64)); 496 WriteReg32(S3_PRI_BD_LOW, si.GlobalBD.bd2.LoPart); 497 WriteReg32(S3_PRI_BD_HIGH, si.GlobalBD.bd2.HiPart); 498 WriteReg32(S3_SEC_BD_LOW, si.GlobalBD.bd2.LoPart); 499 WriteReg32(S3_SEC_BD_HIGH, si.GlobalBD.bd2.HiPart); 500 } 501 502 503 static void 504 Savage_SetGBD(const DisplayModeEx& mode) 505 { 506 TRACE("Savage_SetGBD()\n"); 507 508 VerticalRetraceWait(); 509 510 switch (gInfo.sharedInfo->chipType) { 511 case S3_SAVAGE_3D: 512 Savage_SetGBD_3D(mode); 513 break; 514 515 case S3_SAVAGE_MX: 516 Savage_SetGBD_MX(mode); 517 break; 518 519 case S3_SAVAGE4: 520 case S3_PROSAVAGE: 521 case S3_TWISTER: 522 case S3_PROSAVAGE_DDR: 523 Savage_SetGBD_Twister(mode); 524 break; 525 526 case S3_SUPERSAVAGE: 527 Savage_SetGBD_Super(mode); 528 break; 529 530 case S3_SAVAGE2000: 531 Savage_SetGBD_2000(mode); 532 break; 533 } 534 } 535 536 537 static void 538 Savage_Initialize2DEngine(const DisplayModeEx& mode) 539 { 540 TRACE("Savage_Initialize2DEngine()\n"); 541 542 SharedInfo& si = *gInfo.sharedInfo; 543 uint32 thresholds; 544 545 WriteCrtcReg(0x40, 0x01); 546 WriteCrtcReg(0x31, 0x0c); 547 548 // Setup plane masks. 549 WriteReg32(0x8128, ~0); // enable all write planes 550 WriteReg32(0x812C, ~0); // enable all read planes 551 WriteReg16(0x8134, 0x27); 552 WriteReg16(0x8136, 0x07); 553 554 switch (si.chipType) { 555 case S3_SAVAGE_3D: 556 case S3_SAVAGE_MX: 557 558 // Disable BCI. 559 WriteReg32(0x48C18, ReadReg32(0x48C18) & 0x3FF0); 560 // Setup BCI command overflow buffer. 561 WriteReg32(0x48C14, (si.cobOffset >> 11) | (si.cobIndex << 29)); // tim 562 // Program shadow status update. 563 thresholds = ((si.bciThresholdLo & 0xffff) << 16) | 564 (si.bciThresholdHi & 0xffff); 565 WriteReg32(0x48C10, thresholds); 566 567 WriteReg32(0x48C0C, 0); 568 // Enable BCI and command overflow buffer. 569 WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x0C); 570 break; 571 572 case S3_SAVAGE4: 573 case S3_PROSAVAGE: 574 case S3_TWISTER: 575 case S3_PROSAVAGE_DDR: 576 case S3_SUPERSAVAGE: 577 578 // Disable BCI. 579 WriteReg32(0x48C18, ReadReg32(0x48C18) & 0x3FF0); 580 581 if ( ! si.bDisableCOB) { 582 // Setup BCI command overflow buffer. 583 WriteReg32(0x48C14, (si.cobOffset >> 11) | (si.cobIndex << 29)); 584 } 585 // Program shadow status update; AGD: what should this be? 586 thresholds = ((si.bciThresholdLo & 0x1fffe0) << 11) 587 | ((si.bciThresholdHi & 0x1fffe0) >> 5); 588 WriteReg32(0x48C10, thresholds); 589 590 WriteReg32(0x48C0C, 0); 591 if (si.bDisableCOB) 592 WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x08); // enable BCI without COB 593 else 594 WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x0C); // enable BCI with COB 595 596 break; 597 598 case S3_SAVAGE2000: 599 600 // Disable BCI. 601 WriteReg32(0x48C18, 0); 602 // Setup BCI command overflow buffer. 603 WriteReg32(0x48C18, (si.cobOffset >> 7) | (si.cobIndex)); 604 // Disable shadow status update. 605 WriteReg32(0x48A30, 0); 606 // Enable BCI and command overflow buffer. 607 WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x00280000 ); 608 609 break; 610 } 611 612 // Use and set global bitmap descriptor. 613 614 // For reasons I do not fully understand yet, on the Savage4, the 615 // write to the GBD register, MM816C, does not "take" at this time. 616 // Only the low-order byte is acknowledged, resulting in an incorrect 617 // stride. Writing the register later, after the mode switch, works 618 // correctly. This needs to get resolved. 619 620 Savage_SetGBD(mode); 621 } 622 623 624 static void 625 Savage_GEReset(const DisplayModeEx& mode) 626 { 627 TRACE("Savage_GEReset() begin\n"); 628 629 gInfo.WaitIdleEmpty(); 630 snooze(10000); 631 632 for (int r = 1; r < 10; r++) { 633 bool bSuccess = false; 634 635 WriteCrtcReg(0x66, 0x02, 0x02); 636 snooze(10000); 637 WriteCrtcReg(0x66, 0x00, 0x02); 638 snooze(10000); 639 640 gInfo.WaitIdleEmpty(); 641 642 WriteReg32(DEST_SRC_STR, mode.bytesPerRow << 16 | mode.bytesPerRow); 643 644 snooze(10000); 645 switch (gInfo.sharedInfo->chipType) { 646 case S3_SAVAGE_3D: 647 case S3_SAVAGE_MX: 648 bSuccess = (STATUS_WORD0 & 0x0008ffff) == 0x00080000; 649 break; 650 651 case S3_SAVAGE4: 652 case S3_PROSAVAGE: 653 case S3_PROSAVAGE_DDR: 654 case S3_TWISTER: 655 case S3_SUPERSAVAGE: 656 bSuccess = (ALT_STATUS_WORD0 & 0x0081ffff) == 0x00800000; 657 break; 658 659 case S3_SAVAGE2000: 660 bSuccess = (ALT_STATUS_WORD0 & 0x008fffff) == 0; 661 break; 662 } 663 664 if (bSuccess) 665 break; 666 667 snooze(10000); 668 TRACE("Restarting S3 graphics engine reset %2d ...\n", r); 669 } 670 671 // At this point, the FIFO is empty and the engine is idle. 672 673 WriteReg32(SRC_BASE, 0); 674 WriteReg32(DEST_BASE, 0); 675 WriteReg32(CLIP_L_R, ((0) << 16) | mode.timing.h_display); 676 WriteReg32(CLIP_T_B, ((0) << 16) | mode.timing.v_display); 677 WriteReg32(MONO_PAT_0, ~0); 678 WriteReg32(MONO_PAT_1, ~0); 679 680 Savage_SetGBD(mode); 681 682 TRACE("Savage_GEReset() end\n"); 683 } 684 685 686 static void 687 Savage_CalcClock(long freq, int min_m, 688 int min_n1, int max_n1, 689 int min_n2, int max_n2, 690 long freq_min, long freq_max, 691 unsigned int *mdiv, unsigned int *ndiv, unsigned int *r) 692 { 693 uint8 best_n1 = 16 + 2, best_n2 = 2, best_m = 125 + 2; 694 695 double ffreq = freq / 1000.0 / BASE_FREQ; 696 double ffreq_max = freq_max / 1000.0 / BASE_FREQ; 697 double ffreq_min = freq_min / 1000.0 / BASE_FREQ; 698 699 if (ffreq < ffreq_min / (1 << max_n2)) { 700 TRACE("Savage_CalcClock() invalid frequency %1.3f Mhz\n", ffreq * BASE_FREQ); 701 ffreq = ffreq_min / (1 << max_n2); 702 } 703 if (ffreq > ffreq_max / (1 << min_n2)) { 704 TRACE("Savage_CalcClock() invalid frequency %1.3f Mhz\n", ffreq * BASE_FREQ); 705 ffreq = ffreq_max / (1 << min_n2); 706 } 707 708 // Work out suitable timings. 709 710 double best_diff = ffreq; 711 712 for (uint8 n2 = min_n2; n2 <= max_n2; n2++) { 713 for (uint8 n1 = min_n1 + 2; n1 <= max_n1 + 2; n1++) { 714 int m = (int)(ffreq * n1 * (1 << n2) + 0.5); 715 if (m < min_m + 2 || m > 127 + 2) 716 continue; 717 718 double div = (double)(m) / (double)(n1); 719 if ((div >= ffreq_min) && (div <= ffreq_max)) { 720 double diff = ffreq - div / (1 << n2); 721 if (diff < 0.0) 722 diff = -diff; 723 if (diff < best_diff) { 724 best_diff = diff; 725 best_m = m; 726 best_n1 = n1; 727 best_n2 = n2; 728 } 729 } 730 } 731 } 732 733 *ndiv = best_n1 - 2; 734 *r = best_n2; 735 *mdiv = best_m - 2; 736 } 737 738 739 static void 740 Savage_WriteMode(const DisplayModeEx& mode, const SavageRegRec& regRec) 741 { 742 TRACE("Savage_WriteMode() enter\n"); 743 744 SharedInfo& si = *gInfo.sharedInfo; 745 746 gInfo.WaitIdleEmpty(); 747 748 WriteMiscOutReg(0x23); 749 WriteCrtcReg(0x38, 0x48); // unlock sys regs CR20~CR3F 750 WriteCrtcReg(0x39, 0xa0); // unlock sys regs CR40~CRFF 751 WriteSeqReg(0x08, 0x06); // unlock sequencer regs SR09~SRFF 752 753 if ( ! S3_SAVAGE_MOBILE_SERIES(si.chipType)) 754 Savage_Initialize2DEngine(mode); 755 756 if (ReadCrtcReg(0x66) & 0x01) { 757 Savage_GEReset(mode); // reset GE to make sure nothing is going on 758 } 759 760 WriteCrtcReg(0x67, regRec.CR67 & ~0x0e); // no STREAMS yet old and new 761 762 // Set register SR19 to zero so that the ProSavage chips will start up 763 // when booting under BeOS using the default boot screen. 764 765 if (si.chipType == S3_PROSAVAGE || si.chipType == S3_TWISTER) 766 WriteSeqReg(0x19, 0); 767 768 // Clear bit 3 in SR30 so that Savage MX chip will startup. If bit 3 is 769 // not cleared, it will startup only if booting under BeOS using the 770 // default boot screen or the boot screen resolution matches the resolution 771 // of the mode currently being set. 772 773 if (si.chipType == S3_SAVAGE_MX) 774 WriteSeqReg(0x30, 0x00, 0x08); 775 776 // Set extended regs. 777 778 WriteCrtcReg(0x66, regRec.CR66); 779 WriteCrtcReg(0x3a, regRec.CR3A); 780 WriteCrtcReg(0x31, regRec.CR31); 781 WriteCrtcReg(0x58, regRec.CR58); 782 WriteCrtcReg(0x53, regRec.CR53 & 0x7f); 783 784 // Set DCLK registers. 785 786 WriteSeqReg(0x29, regRec.SR29); 787 WriteSeqReg(0x15, regRec.SR15); 788 789 // Set the standard CRTC vga regs. 790 791 WriteCrtcReg(0x11, 0x00, 0x80); // unlock CRTC reg's 0-7 by clearing bit 7 of cr11 792 793 for (int j = 0; j < NUM_ELEMENTS(regRec.CRTC); j++) 794 WriteCrtcReg(j, regRec.CRTC[j]); 795 796 // Setup HSYNC & VSYNC polarity. 797 798 uint8 temp = ((ReadMiscOutReg() & 0x3f) | 0x0c); 799 800 if (!(mode.timing.flags & B_POSITIVE_HSYNC)) 801 temp |= 0x40; 802 if (!(mode.timing.flags & B_POSITIVE_VSYNC)) 803 temp |= 0x80; 804 805 WriteMiscOutReg(temp); 806 807 // Extended mode timing registers. 808 WriteCrtcReg(0x53, regRec.CR53); 809 WriteCrtcReg(0x5d, regRec.CR5D); 810 WriteCrtcReg(0x5e, regRec.CR5E); 811 WriteCrtcReg(0x3b, regRec.CR3B); 812 WriteCrtcReg(0x3c, regRec.CR3C); 813 WriteCrtcReg(0x43, regRec.CR43); 814 WriteCrtcReg(0x65, regRec.CR65); 815 816 // Restore the desired video mode with cr67. 817 WriteCrtcReg(0x67, regRec.CR67 & ~0x0e); // no streams for new and old streams engines 818 819 // Other mode timing and extended regs. 820 WriteCrtcReg(0x34, regRec.CR34); 821 WriteCrtcReg(0x40, regRec.CR40); 822 WriteCrtcReg(0x42, regRec.CR42); 823 WriteCrtcReg(0x45, regRec.CR45); 824 WriteCrtcReg(0x50, regRec.CR50); 825 WriteCrtcReg(0x51, regRec.CR51); 826 827 // Memory timings. 828 VerticalRetraceWait(); 829 WriteCrtcReg(0x69, regRec.CR69); 830 831 WriteCrtcReg(0x33, regRec.CR33); 832 WriteCrtcReg(0x86, regRec.CR86); 833 WriteCrtcReg(0x88, regRec.CR88); 834 WriteCrtcReg(0x90, regRec.CR90); 835 WriteCrtcReg(0x91, regRec.CR91); 836 837 if (si.chipType == S3_SAVAGE4) 838 WriteCrtcReg(0xb0, regRec.CRB0); 839 840 // Set extended seq regs for dclk. 841 WriteSeqReg(0x12, regRec.SR12); 842 WriteSeqReg(0x13, regRec.SR13); 843 WriteSeqReg(0x29, regRec.SR29); 844 845 WriteSeqReg(0x18, regRec.SR18); 846 WriteSeqReg(0x1b, regRec.SR1B); 847 848 // Load new m, n pll values for dclk & mclk. 849 temp = ReadSeqReg(0x15) & ~0x21; 850 851 WriteSeqReg(0x15, temp | 0x03); 852 WriteSeqReg(0x15, temp | 0x23); 853 WriteSeqReg(0x15, temp | 0x03); 854 WriteSeqReg(0x15, regRec.SR15); 855 snooze( 100 ); 856 857 // Now write out cr67 in full, possibly starting STREAMS. 858 VerticalRetraceWait(); 859 WriteCrtcReg(0x67, regRec.CR67); 860 861 uint8 cr66 = ReadCrtcReg(0x66); 862 WriteCrtcReg(0x66, cr66 | 0x80); 863 uint8 cr3a = ReadCrtcReg(0x3a); 864 WriteCrtcReg(0x3a, cr3a | 0x80); 865 866 Savage_GEReset(mode); 867 868 WriteCrtcReg(0x66, cr66); 869 WriteCrtcReg(0x3a, cr3a); 870 871 Savage_Initialize2DEngine(mode); 872 873 WriteCrtcReg(0x40, 0x01); // enable graphics engine 874 875 Savage_SetGBD(mode); 876 877 TRACE("Savage_WriteMode() end\n"); 878 879 return; 880 } 881 882 883 static bool 884 Savage_ModeInit(const DisplayModeEx& mode) 885 { 886 TRACE("Savage_ModeInit(%dx%d, %dHz)\n", 887 mode.timing.h_display, mode.timing.v_display, mode.timing.pixel_clock); 888 889 SharedInfo& si = *gInfo.sharedInfo; 890 SavageRegRec regRec; 891 892 int horizScaleFactor = 1; 893 894 if (mode.bpp == 16 && si.chipType == S3_SAVAGE_3D) 895 horizScaleFactor = 2; 896 897 InitCrtcTimingValues(mode, horizScaleFactor, regRec.CRTC, 898 regRec.CR3B, regRec.CR3C, regRec.CR5D, regRec.CR5E); 899 regRec.CRTC[23] = 0xEB; 900 901 int dclk = mode.timing.pixel_clock; 902 regRec.CR67 = 0x00; 903 904 switch (mode.bpp) { 905 case 8: 906 if ((si.chipType == S3_SAVAGE2000) && (dclk >= 230000)) 907 regRec.CR67 = 0x10; // 8bpp, 2 pixels/clock 908 else 909 regRec.CR67 = 0x00; // 8bpp, 1 pixel/clock 910 break; 911 912 case 15: 913 if (S3_SAVAGE_MOBILE_SERIES(si.chipType) 914 || ((si.chipType == S3_SAVAGE2000) && (dclk >= 230000))) 915 regRec.CR67 = 0x30; // 15bpp, 2 pixel/clock 916 else 917 regRec.CR67 = 0x20; // 15bpp, 1 pixels/clock 918 break; 919 920 case 16: 921 if (S3_SAVAGE_MOBILE_SERIES(si.chipType) 922 || ((si.chipType == S3_SAVAGE2000) && (dclk >= 230000))) 923 regRec.CR67 = 0x50; // 16bpp, 2 pixel/clock 924 else 925 regRec.CR67 = 0x40; // 16bpp, 1 pixels/clock 926 break; 927 928 case 32: 929 regRec.CR67 = 0xd0; 930 break; 931 } 932 933 934 // Use traditional register-crunching to set mode. 935 936 regRec.CR3A = (ReadCrtcReg(0x3a) & 0x7f) | 0x15; 937 regRec.CR53 = 0x00; 938 regRec.CR31 = 0x8c; 939 regRec.CR66 = 0x89; 940 regRec.CR58 = (ReadCrtcReg(0x58) & 0x80) | 0x13; 941 942 if (si.chipType == S3_SAVAGE2000) 943 regRec.SR15 = 0x02; 944 else 945 regRec.SR15 = 0x83; 946 947 regRec.SR18 = 0x00; 948 regRec.SR1B = ReadSeqReg(0x1b) | 0x10; // enable 8-bit Color Lookup Table 949 950 regRec.CR43 = regRec.CR45 = regRec.CR65 = 0x00; 951 regRec.CR40 = ReadCrtcReg(0x40) & ~0x01; 952 953 unsigned int m, n, r; 954 Savage_CalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r); 955 regRec.SR12 = (r << 6) | (n & 0x3f); 956 regRec.SR13 = m & 0xff; 957 regRec.SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2; 958 959 TRACE("CalcClock, m: %d n: %d r: %d\n", m, n, r); 960 961 regRec.CR42 = 0x00; 962 regRec.CR34 = 0x10; 963 964 int width = mode.bytesPerRow / 8; 965 regRec.CR91 = 0xff & width; 966 regRec.CR51 = (0x300 & width) >> 4; 967 regRec.CR90 = 0x80 | (width >> 8); 968 969 // Set frame buffer description. 970 971 if (mode.bpp <= 8) 972 regRec.CR50 = 0; 973 else if (mode.bpp <= 16) 974 regRec.CR50 = 0x10; 975 else 976 regRec.CR50 = 0x30; 977 978 width = mode.timing.h_display; // width of display in pixels 979 980 if (width == 640) 981 regRec.CR50 |= 0x40; 982 else if (width == 800) 983 regRec.CR50 |= 0x80; 984 else if (width == 1024) 985 regRec.CR50 |= 0x00; 986 else if (width == 1152) 987 regRec.CR50 |= 0x01; 988 else if (width == 1280) 989 regRec.CR50 |= 0xc0; 990 else if (width == 1600) 991 regRec.CR50 |= 0x81; 992 else 993 regRec.CR50 |= 0xc1; // use GBD 994 995 if (S3_SAVAGE_MOBILE_SERIES(si.chipType)) 996 regRec.CR33 = 0x00; 997 else 998 regRec.CR33 = 0x08; 999 1000 regRec.CR67 |= 1; 1001 regRec.CR69 = 0; 1002 regRec.CR86 = ReadCrtcReg(0x86) | 0x08; 1003 regRec.CR88 = ReadCrtcReg(0x88) | DISABLE_BLOCK_WRITE_2D; 1004 regRec.CRB0 = ReadCrtcReg(0xb0) | 0x80; 1005 1006 Savage_WriteMode(mode, regRec); // write registers to set mode 1007 1008 return true; 1009 } 1010 1011 1012 1013 bool 1014 Savage_SetDisplayMode(const DisplayModeEx& mode) 1015 { 1016 // The code to actually configure the display. 1017 // All the error checking must be done in ProposeDisplayMode(), 1018 // and assume that the mode values we get here are acceptable. 1019 1020 WriteSeqReg(0x01, 0x20, 0x20); // blank the screen 1021 1022 if ( ! Savage_ModeInit(mode)) { 1023 TRACE("Savage_ModeInit() failed\n"); 1024 return false; 1025 } 1026 1027 Savage_AdjustFrame(mode); 1028 1029 WriteSeqReg(0x01, 0x00, 0x20); // unblank the screen 1030 return true; 1031 } 1032 1033 1034 1035 void 1036 Savage_AdjustFrame(const DisplayModeEx& mode) 1037 { 1038 // Adjust start address in frame buffer. 1039 1040 SharedInfo& si = *gInfo.sharedInfo; 1041 1042 int address = (mode.v_display_start * mode.virtual_width) 1043 + ((mode.h_display_start & ~0x3F) * (mode.bpp / 8)); 1044 address &= ~0x1F; 1045 address += si.frameBufferOffset; 1046 1047 switch (si.chipType) { 1048 case S3_SAVAGE_MX: 1049 WriteReg32(PRI_STREAM_FBUF_ADDR0, address & 0xFFFFFFFC); 1050 WriteReg32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFFC); 1051 break; 1052 case S3_SUPERSAVAGE: 1053 WriteReg32(PRI_STREAM_FBUF_ADDR0, 0x80000000); 1054 WriteReg32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFF8); 1055 break; 1056 case S3_SAVAGE2000: 1057 // Certain Y values seems to cause havoc, not sure why 1058 WriteReg32(PRI_STREAM_FBUF_ADDR0, (address & 0xFFFFFFF8)); 1059 WriteReg32(PRI_STREAM2_FBUF_ADDR0, (address & 0xFFFFFFF8)); 1060 break; 1061 default: 1062 WriteReg32(PRI_STREAM_FBUF_ADDR0, address | 0xFFFFFFFC); 1063 WriteReg32(PRI_STREAM_FBUF_ADDR1, address | 0x80000000); 1064 break; 1065 } 1066 1067 return; 1068 } 1069 1070 1071 void 1072 Savage_SetIndexedColors(uint count, uint8 first, uint8* colorData, uint32 flags) 1073 { 1074 // Set the indexed color palette for 8-bit color depth mode. 1075 1076 (void)flags; // avoid compiler warning for unused arg 1077 1078 if (gInfo.sharedInfo->displayMode.space != B_CMAP8) 1079 return ; 1080 1081 while (count--) { 1082 WriteIndexedColor(first++, // color index 1083 colorData[0], // red 1084 colorData[1], // green 1085 colorData[2]); // blue 1086 colorData += 3; 1087 } 1088 } 1089