BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / add-ons / accelerants / s3 / savage_mode.cpp
blob85fde3ba0f6f2d207818d608888ed1b0a78788d6
1 /*
2 Haiku S3 Savage driver adapted from the X.org Savage driver.
4 Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
5 Copyright (c) 2003-2006, X.Org Foundation
7 Copyright 2007-2008 Haiku, Inc. All rights reserved.
8 Distributed under the terms of the MIT license.
10 Authors:
11 Gerald Zajac 2006-2008
15 #include "accel.h"
16 #include "savage.h"
19 #define BASE_FREQ 14.31818
22 struct SavageRegRec {
23 uint8 CRTC[25]; // Crtc Controller reg's
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;
36 static void
37 Savage_SetGBD_Twister(const DisplayModeEx& mode)
39 SharedInfo& si = *gInfo.sharedInfo;
40 int bci_enable;
42 if (si.chipType == S3_SAVAGE4)
43 bci_enable = BCI_ENABLE;
44 else
45 bci_enable = BCI_ENABLE_TWISTER;
47 // MM81C0 and 81C4 are used to control primary stream.
48 WriteReg32(PRI_STREAM_FBUF_ADDR0, 0);
49 WriteReg32(PRI_STREAM_FBUF_ADDR1, 0);
51 // Program Primary Stream Stride Register.
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.
60 WriteReg32(PRI_STREAM_STRIDE,
61 (((mode.bytesPerRow * 2) << 16) & 0x3FFFE000) |
62 (mode.bytesPerRow & 0x00001fff));
64 // CR69, bit 7 = 1
65 // to use MM streams processor registers to control primary stream.
67 WriteCrtcReg(0x69, 0x80, 0x80);
69 WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
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.
75 uint32 ulTmp = ReadReg32(ADVANCED_FUNC_CTRL) | 0x8000; // use MS-s style tile mode
76 WriteReg32(ADVANCED_FUNC_CTRL, ulTmp);
78 // CR88, bit 4 - Block write enabled/disabled.
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.
84 WriteCrtcReg(0x88, DISABLE_BLOCK_WRITE_2D, DISABLE_BLOCK_WRITE_2D);
88 static void
89 Savage_SetGBD_3D(const DisplayModeEx& mode)
91 int bci_enable = BCI_ENABLE;
93 // MM81C0 and 81C4 are used to control primary stream.
94 WriteReg32(PRI_STREAM_FBUF_ADDR0, 0);
95 WriteReg32(PRI_STREAM_FBUF_ADDR1, 0);
97 // Program Primary Stream Stride Register.
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.
106 WriteReg32(PRI_STREAM_STRIDE,
107 (((mode.bytesPerRow * 2) << 16) & 0x3FFFE000) |
108 (mode.bytesPerRow & 0x00001fff));
110 // CR69, bit 7 = 1 to use MM streams processor registers to control primary
111 // stream.
113 WriteCrtcReg(0x69, 0x80, 0x80);
115 WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
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.
121 uint32 ulTmp = ReadReg32(ADVANCED_FUNC_CTRL) | 0x8000; // use MS-s style tile mode
122 WriteReg32(ADVANCED_FUNC_CTRL, ulTmp);
124 // CR88, bit 4 - Block write enabled/disabled.
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.
130 WriteCrtcReg(0x88, DISABLE_BLOCK_WRITE_2D, DISABLE_BLOCK_WRITE_2D);
134 static void
135 Savage_SetGBD_MX(const DisplayModeEx& mode)
137 SharedInfo& si = *gInfo.sharedInfo;
138 int bci_enable = BCI_ENABLE;
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.
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
152 // Set primary stream to bank 0 via reg CRCA.
153 WriteCrtcReg(MEMORY_CTRL0_REG, 0x00, MEM_PS1 + MEM_PS2);
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);
161 // Program Primary Stream Stride Register.
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.
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));
177 WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
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.
185 WriteCrtcReg(0x78, 0xfb, 0xfb);
189 static void
190 Savage_SetGBD_Super(const DisplayModeEx& mode)
192 SharedInfo& si = *gInfo.sharedInfo;
193 int bci_enable = BCI_ENABLE_TWISTER;
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.
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
207 // Load ps1 active registers as determined by MM81C0/81C4.
208 // Load ps2 active registers as determined by MM81B0/81B4.
210 WriteCrtcReg(0x65, 0x03, 0x03);
212 // Program Primary Stream Stride Register.
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.
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));
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);
234 // Bit 28:block write disable.
235 WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_BD64 | 0x10000000);
239 static void
240 Savage_SetGBD_2000(const DisplayModeEx& mode)
242 SharedInfo& si = *gInfo.sharedInfo;
243 int bci_enable = BCI_ENABLE_TWISTER;
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);
249 // Program Primary Stream Stride Register.
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.
258 WriteReg32(PRI_STREAM_STRIDE, ((mode.bytesPerRow << 4) & 0x7ff0));
259 WriteReg32(PRI_STREAM2_STRIDE, ((mode.bytesPerRow << 4) & 0x7ff0));
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
267 WriteCrtcReg(0x67, 0x08, 0x08);
269 // Bit 28:block write disable.
270 WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_BD64 | 0x10000000);
272 WriteCrtcReg(0x73, 0x00, 0x20); // CR73 bit 5 = 0 block write disable
277 static void
278 Savage_SetGBD(const DisplayModeEx& mode)
280 SharedInfo& si = *gInfo.sharedInfo;
282 VerticalRetraceWait();
284 switch (gInfo.sharedInfo->chipType) {
285 case S3_SAVAGE_3D:
286 Savage_SetGBD_3D(mode);
287 break;
289 case S3_SAVAGE_MX:
290 Savage_SetGBD_MX(mode);
291 break;
293 case S3_SAVAGE4:
294 case S3_PROSAVAGE:
295 case S3_TWISTER:
296 case S3_PROSAVAGE_DDR:
297 Savage_SetGBD_Twister(mode);
298 break;
300 case S3_SUPERSAVAGE:
301 Savage_SetGBD_Super(mode);
302 break;
304 case S3_SAVAGE2000:
305 Savage_SetGBD_2000(mode);
306 break;
309 WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD
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
317 si.globalBitmapDesc = mode.timing.h_display | (mode.bpp << 16)
318 | TILE_FORMAT_LINEAR | BCI_BD_BW_DISABLE | S3_BD64; // disable block write
322 static void
323 Savage_Initialize2DEngine(const DisplayModeEx& mode)
325 SharedInfo& si = *gInfo.sharedInfo;
327 WriteCrtcReg(0x40, 0x01); // enable graphics engine
328 WriteCrtcReg(0x31, 0x0c); // turn on 16-bit register access
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);
336 switch (si.chipType) {
337 case S3_SAVAGE_3D:
338 case S3_SAVAGE_MX:
340 WriteReg32(0x48C18, ReadReg32(0x48C18) & 0x3FF0); // Disable BCI
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));
348 // Program shadow status update.
349 WriteReg32(0x48C10, 0x78207220);
351 WriteReg32(0x48C0C, 0);
352 // Enable BCI and command overflow buffer.
353 WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x0C);
354 break;
356 case S3_SAVAGE4:
357 case S3_PROSAVAGE:
358 case S3_TWISTER:
359 case S3_PROSAVAGE_DDR:
360 case S3_SUPERSAVAGE:
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.
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
371 break;
373 case S3_SAVAGE2000:
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);
384 break;
387 // Use and set global bitmap descriptor.
389 Savage_SetGBD(mode);
393 static void
394 Savage_GEReset(const DisplayModeEx& mode)
396 gInfo.WaitIdleEmpty();
397 snooze(10000);
399 for (int r = 1; r < 10; r++) {
400 bool bSuccess = false;
402 WriteCrtcReg(0x66, 0x02, 0x02);
403 snooze(10000);
404 WriteCrtcReg(0x66, 0x00, 0x02);
405 snooze(10000);
407 gInfo.WaitIdleEmpty();
409 WriteReg32(DEST_SRC_STR, mode.bytesPerRow << 16 | mode.bytesPerRow);
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;
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;
426 case S3_SAVAGE2000:
427 bSuccess = (ALT_STATUS_WORD0 & 0x008fffff) == 0;
428 break;
431 if (bSuccess)
432 break;
434 snooze(10000);
435 TRACE("Savage_GEReset(), restarting S3 graphics engine reset %2d ...\n", r);
438 // At this point, the FIFO is empty and the engine is idle.
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);
447 Savage_SetGBD(mode);
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)
458 uint8 best_n1 = 16 + 2, best_n2 = 2, best_m = 125 + 2;
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;
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);
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);
473 // Work out suitable timings.
475 double best_diff = ffreq;
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;
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;
498 *ndiv = best_n1 - 2;
499 *r = best_n2;
500 *mdiv = best_m - 2;
504 static void
505 Savage_WriteMode(const DisplayModeEx& mode, const SavageRegRec& regRec)
507 TRACE("Savage_WriteMode() begin\n");
509 SharedInfo& si = *gInfo.sharedInfo;
511 gInfo.WaitIdleEmpty();
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
518 if ( ! S3_SAVAGE_MOBILE_SERIES(si.chipType))
519 Savage_Initialize2DEngine(mode);
521 if (ReadCrtcReg(0x66) & 0x01) {
522 Savage_GEReset(mode); // reset GE to make sure nothing is going on
525 WriteCrtcReg(0x67, regRec.CR67 & ~0x0e); // no STREAMS yet old and new
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
532 if (si.chipType == S3_PROSAVAGE || si.chipType == S3_TWISTER) {
533 WriteSeqReg(0x19, 0);
534 WriteCrtcReg(0x5f, 0);
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.
542 if (si.chipType == S3_SAVAGE_MX)
543 WriteSeqReg(0x30, 0x00, 0x08);
545 // Set extended regs.
547 WriteCrtcReg(0x66, regRec.CR66);
548 WriteCrtcReg(0x3a, regRec.CR3A);
549 WriteCrtcReg(0x58, regRec.CR58);
550 WriteCrtcReg(0x53, regRec.CR53 & 0x7f);
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.
559 if (S3_SAVAGE_MOBILE_SERIES(si.chipType)) {
560 WriteSeqReg(0x54, 0x10);
561 WriteSeqReg(0x56, 0x10);
564 // Set the standard CRTC vga regs.
566 WriteCrtcReg(0x11, 0x00, 0x80); // unlock CRTC reg's 0-7 by clearing bit 7 of cr11
568 for (int j = 0; j < (int)B_COUNT_OF(regRec.CRTC); j++)
569 WriteCrtcReg(j, regRec.CRTC[j]);
571 // Setup HSYNC & VSYNC polarity.
573 uint8 temp = ((ReadMiscOutReg() & 0x3f) | 0x0c);
575 if (!(mode.timing.flags & B_POSITIVE_HSYNC))
576 temp |= 0x40;
577 if (!(mode.timing.flags & B_POSITIVE_VSYNC))
578 temp |= 0x80;
580 WriteMiscOutReg(temp);
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);
591 // Restore the desired video mode with cr67.
592 WriteCrtcReg(0x67, regRec.CR67 & ~0x0e); // no streams for new and old streams engines
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);
601 // Memory timings.
602 VerticalRetraceWait();
603 WriteCrtcReg(0x69, regRec.CR69);
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);
611 if (si.chipType == S3_SAVAGE4)
612 WriteCrtcReg(0xb0, regRec.CRB0);
614 WriteSeqReg(0x1b, regRec.SR1B);
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);
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);
630 // Now write out cr67 in full, possibly starting STREAMS.
631 VerticalRetraceWait();
632 WriteCrtcReg(0x67, regRec.CR67);
634 uint8 cr66 = ReadCrtcReg(0x66);
635 WriteCrtcReg(0x66, cr66 | 0x80);
636 uint8 cr3a = ReadCrtcReg(0x3a);
637 WriteCrtcReg(0x3a, cr3a | 0x80);
639 Savage_GEReset(mode);
641 WriteCrtcReg(0x66, cr66);
642 WriteCrtcReg(0x3a, cr3a);
644 Savage_Initialize2DEngine(mode);
646 WriteCrtcReg(0x40, 0x01); // enable graphics engine
648 Savage_SetGBD(mode);
650 TRACE("Savage_WriteMode() done\n");
652 return;
656 static bool
657 Savage_ModeInit(const DisplayModeEx& mode)
659 TRACE("Savage_ModeInit(%dx%d, %d kHz)\n",
660 mode.timing.h_display, mode.timing.v_display, mode.timing.pixel_clock);
662 SharedInfo& si = *gInfo.sharedInfo;
663 SavageRegRec regRec;
665 int horizScaleFactor = 1;
667 if (mode.bpp == 16 && si.chipType == S3_SAVAGE_3D)
668 horizScaleFactor = 2;
670 InitCrtcTimingValues(mode, horizScaleFactor, regRec.CRTC,
671 regRec.CR3B, regRec.CR3C, regRec.CR5D, regRec.CR5E);
672 regRec.CRTC[0x17] = 0xEB;
674 int dclk = mode.timing.pixel_clock;
675 regRec.CR67 = 0x00;
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;
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;
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;
701 case 32:
702 regRec.CR67 = 0xd0;
703 break;
706 regRec.CR3A = (ReadCrtcReg(0x3a) & 0x7f) | 0x15;
707 regRec.CR53 = 0x00;
708 regRec.CR66 = 0x89;
709 regRec.CR58 = (ReadCrtcReg(0x58) & 0x80) | 0x13;
711 regRec.SR1B = ReadSeqReg(0x1b) | 0x10; // enable 8-bit Color Lookup Table
713 regRec.CR43 = regRec.CR45 = regRec.CR65 = 0x00;
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;
721 TRACE("CalcClock, m: %d n: %d r: %d\n", m, n, r);
723 regRec.CR42 = 0x00;
724 regRec.CR34 = 0x10;
726 int width = mode.bytesPerRow / 8;
727 regRec.CR91 = 0xff & width;
728 regRec.CR51 = (0x300 & width) >> 4;
729 regRec.CR90 = 0x80 | (width >> 8);
731 // Set frame buffer description.
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;
740 width = mode.timing.h_display; // width of display in pixels
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
757 if (S3_SAVAGE_MOBILE_SERIES(si.chipType))
758 regRec.CR33 = 0x00;
759 else
760 regRec.CR33 = 0x08;
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;
767 Savage_WriteMode(mode, regRec); // write registers to set mode
769 return true;
774 bool
775 Savage_SetDisplayMode(const DisplayModeEx& mode)
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.
781 WriteSeqReg(0x01, 0x20, 0x20); // blank the screen
783 if ( ! Savage_ModeInit(mode)) {
784 TRACE("Savage_ModeInit() failed\n");
785 return false;
788 Savage_AdjustFrame(mode);
790 WriteSeqReg(0x01, 0x00, 0x20); // unblank the screen
792 return true;
797 void
798 Savage_AdjustFrame(const DisplayModeEx& mode)
800 // Adjust start address in frame buffer.
802 SharedInfo& si = *gInfo.sharedInfo;
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;
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;
829 return;
833 void
834 Savage_SetIndexedColors(uint count, uint8 first, uint8* colorData, uint32 flags)
836 // Set the indexed color palette for 8-bit color depth mode.
838 (void)flags; // avoid compiler warning for unused arg
840 if (gInfo.sharedInfo->displayMode.space != B_CMAP8)
841 return ;
843 while (count--) {
844 WriteIndexedColor(first++, // color index
845 colorData[0], // red
846 colorData[1], // green
847 colorData[2]); // blue
848 colorData += 3;