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.
11 Gerald Zajac 2006-2008
19 #define BASE_FREQ 14.31818
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
;
31 uint8 CR90
, CR91
, CRB0
;
37 Savage_SetGBD_Twister(const DisplayModeEx
& mode
)
39 SharedInfo
& si
= *gInfo
.sharedInfo
;
42 if (si
.chipType
== S3_SAVAGE4
)
43 bci_enable
= BCI_ENABLE
;
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));
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
);
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
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
);
135 Savage_SetGBD_MX(const DisplayModeEx
& mode
)
137 SharedInfo
& si
= *gInfo
.sharedInfo
;
138 int bci_enable
= BCI_ENABLE
;
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);
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);
190 Savage_SetGBD_Super(const DisplayModeEx
& mode
)
192 SharedInfo
& si
= *gInfo
.sharedInfo
;
193 int bci_enable
= BCI_ENABLE_TWISTER
;
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);
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);
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));
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
278 Savage_SetGBD(const DisplayModeEx
& mode
)
280 SharedInfo
& si
= *gInfo
.sharedInfo
;
282 VerticalRetraceWait();
284 switch (gInfo
.sharedInfo
->chipType
) {
286 Savage_SetGBD_3D(mode
);
290 Savage_SetGBD_MX(mode
);
296 case S3_PROSAVAGE_DDR
:
297 Savage_SetGBD_Twister(mode
);
301 Savage_SetGBD_Super(mode
);
305 Savage_SetGBD_2000(mode
);
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
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
) {
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);
359 case S3_PROSAVAGE_DDR
:
362 // Some Savage4 and ProSavage chips have coherency problems with
363 // respect to the Command Overflow Buffer (COB); thus, do not
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
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);
387 // Use and set global bitmap descriptor.
394 Savage_GEReset(const DisplayModeEx
& mode
)
396 gInfo
.WaitIdleEmpty();
399 for (int r
= 1; r
< 10; r
++) {
400 bool bSuccess
= false;
402 WriteCrtcReg(0x66, 0x02, 0x02);
404 WriteCrtcReg(0x66, 0x00, 0x02);
407 gInfo
.WaitIdleEmpty();
409 WriteReg32(DEST_SRC_STR
, mode
.bytesPerRow
<< 16 | mode
.bytesPerRow
);
412 switch (gInfo
.sharedInfo
->chipType
) {
415 bSuccess
= (STATUS_WORD0
& 0x0008ffff) == 0x00080000;
420 case S3_PROSAVAGE_DDR
:
423 bSuccess
= (ALT_STATUS_WORD0
& 0x0081ffff) == 0x00800000;
427 bSuccess
= (ALT_STATUS_WORD0
& 0x008fffff) == 0;
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);
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)
483 double div
= (double)(m
) / (double)(n1
);
484 if ((div
>= ffreq_min
) && (div
<= ffreq_max
)) {
485 double diff
= ffreq
- div
/ (1 << n2
);
488 if (diff
< best_diff
) {
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
))
577 if (!(mode
.timing
.flags
& B_POSITIVE_VSYNC
))
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
);
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
);
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
650 TRACE("Savage_WriteMode() done\n");
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
;
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
;
679 if ((si
.chipType
== S3_SAVAGE2000
) && (dclk
>= 230000))
680 regRec
.CR67
= 0x10; // 8bpp, 2 pixels/clock
682 regRec
.CR67
= 0x00; // 8bpp, 1 pixel/clock
686 if (S3_SAVAGE_MOBILE_SERIES(si
.chipType
)
687 || ((si
.chipType
== S3_SAVAGE2000
) && (dclk
>= 230000)))
688 regRec
.CR67
= 0x30; // 15bpp, 2 pixel/clock
690 regRec
.CR67
= 0x20; // 15bpp, 1 pixels/clock
694 if (S3_SAVAGE_MOBILE_SERIES(si
.chipType
)
695 || ((si
.chipType
== S3_SAVAGE2000
) && (dclk
>= 230000)))
696 regRec
.CR67
= 0x50; // 16bpp, 2 pixel/clock
698 regRec
.CR67
= 0x40; // 16bpp, 1 pixels/clock
706 regRec
.CR3A
= (ReadCrtcReg(0x3a) & 0x7f) | 0x15;
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
);
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.
735 else if (mode
.bpp
<= 16)
740 width
= mode
.timing
.h_display
; // width of display in pixels
744 else if (width
== 800)
746 else if (width
== 1024)
748 else if (width
== 1152)
750 else if (width
== 1280)
752 else if (width
== 1600)
755 regRec
.CR50
|= 0xc1; // use GBD
757 if (S3_SAVAGE_MOBILE_SERIES(si
.chipType
))
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
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");
788 Savage_AdjustFrame(mode
);
790 WriteSeqReg(0x01, 0x00, 0x20); // unblank the screen
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));
807 address
+= si
.frameBufferOffset
;
809 switch (si
.chipType
) {
811 WriteReg32(PRI_STREAM_FBUF_ADDR0
, address
& 0xFFFFFFFC);
812 WriteReg32(PRI_STREAM_FBUF_ADDR1
, address
& 0xFFFFFFFC);
815 WriteReg32(PRI_STREAM_FBUF_ADDR0
, 0x80000000);
816 WriteReg32(PRI_STREAM_FBUF_ADDR1
, address
& 0xFFFFFFF8);
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));
824 WriteReg32(PRI_STREAM_FBUF_ADDR0
, address
| 0xFFFFFFFC);
825 WriteReg32(PRI_STREAM_FBUF_ADDR1
, address
| 0x80000000);
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
)
844 WriteIndexedColor(first
++, // color index
846 colorData
[1], // green
847 colorData
[2]); // blue