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
21 Savage_GetColorSpaceParams(int colorSpace
, uint32
& bitsPerPixel
, uint32
& maxPixelClock
)
23 // Get parameters for a color space which is supported by the Savage chips.
24 // Argument maxPixelClock is in KHz.
25 // Return true if the color space is supported; else return false.
30 maxPixelClock
= 220000;
34 maxPixelClock
= 250000;
38 maxPixelClock
= 250000;
41 TRACE("Unsupported color space: 0x%X\n", colorSpace
);
49 // Wait until "v" queue entries are free.
54 uint32 slots
= MAXFIFO
- v
;
55 while ((STATUS_WORD0
& 0x0000ffff) > slots
);
62 uint32 slots
= MAXFIFO
- v
;
63 while ((ALT_STATUS_WORD0
& 0x001fffff) > slots
);
70 uint32 slots
= MAXFIFO
- v
;
71 while ((ALT_STATUS_WORD0
& 0x000fffff) > slots
);
75 // Wait until GP is idle and queue is empty.
80 while ((STATUS_WORD0
& 0x0008ffff) != 0x80000);
87 while ((ALT_STATUS_WORD0
& 0x00e1ffff) != 0x00e00000) ;
94 while ((ALT_STATUS_WORD0
& 0x009fffff) != 0);
101 SharedInfo
& si
= *gInfo
.sharedInfo
;
103 enum ACTIVE_DISPLAYS
{ // these are the bits in CR6B
111 // Check LCD panel information.
113 uint8 cr6b
= ReadCrtcReg(0x6b);
115 int panelX
= (ReadSeqReg(0x61) + ((ReadSeqReg(0x66) & 0x02) << 7) + 1) * 8;
116 int panelY
= ReadSeqReg(0x69) + ((ReadSeqReg(0x6e) & 0x70) << 4) + 1;
118 // A Savage IX/MV in a Thinkpad T22 or SuperSavage in a Thinkpad T23 with
119 // a 1400x1050 display will return a width of 1408; thus, in this case,
120 // set the width to the correct value of 1400.
125 const char* sTechnology
;
127 if ((ReadSeqReg(0x39) & 0x03) == 0)
129 else if ((ReadSeqReg(0x30) & 0x01) == 0)
130 sTechnology
= "DSTN";
134 TRACE("%dx%d %s LCD panel detected %s\n", panelX
, panelY
, sTechnology
,
135 cr6b
& ActiveLCD
? "and active" : "but not active");
137 if (cr6b
& ActiveLCD
) {
138 TRACE("Limiting max video mode to %dx%d\n", panelX
, panelY
);
142 si
.displayType
= MT_CRT
;
150 TRACE("Savage_Init()\n");
152 SharedInfo
& si
= *gInfo
.sharedInfo
;
154 // MMIO should be automatically enabled for Savage chips; thus, use MMIO
155 // to enable VGA and turn color on.
157 WriteReg8(VGA_ENABLE
+ 0x8000, ReadReg8(VGA_ENABLE
+ 0x8000) | 0x01);
158 WriteMiscOutReg(ReadMiscOutReg() | 0x01); // turn color on
160 if (si
.chipType
>= S3_SAVAGE4
)
161 WriteCrtcReg(0x40, 0x01, 0x01);
163 WriteCrtcReg(0x11, 0x00, 0x80); // unlock CRTC reg's 0-7 by clearing bit 7 of cr11
164 WriteCrtcReg(0x38, 0x48); // unlock sys regs CR20~CR3F
165 WriteCrtcReg(0x39, 0xa0); // unlock sys regs CR40~CRFF
166 WriteSeqReg(0x08, 0x06); // unlock sequencer regs SR09~SRFF
168 WriteCrtcReg(0x40, 0x00, 0x01);
169 WriteCrtcReg(0x38, 0x48); // unlock sys regs CR20~CR3F
171 // Compute the amount of video memory and offscreen memory.
173 static const uint8 RamSavage3D
[] = { 8, 4, 4, 2 };
174 static uint8 RamSavage4
[] = { 2, 4, 8, 12, 16, 32, 64, 32 };
175 static const uint8 RamSavageMX
[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
176 static const uint8 RamSavageNB
[] = { 0, 2, 4, 8, 16, 32, 16, 2 };
177 uint32 ramSizeMB
= 0; // memory size in megabytes
179 uint8 cr36
= ReadCrtcReg(0x36); // get amount of video ram
181 switch (si
.chipType
) {
183 ramSizeMB
= RamSavage3D
[ (cr36
& 0xC0) >> 6 ];
187 // The Savage4 has one ugly special case to consider. On
188 // systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB
189 // when it really means 8MB. Why do it the same when you
190 // can do it different...
191 if ((ReadCrtcReg(0x68) & 0xC0) == (0x01 << 6))
197 ramSizeMB
= RamSavage4
[ (cr36
& 0xE0) >> 5 ];
202 ramSizeMB
= RamSavageMX
[ (cr36
& 0x0E) >> 1 ];
206 case S3_PROSAVAGE_DDR
:
208 ramSizeMB
= RamSavageNB
[ (cr36
& 0xE0) >> 5 ];
212 // How did we get here?
217 uint32 usableMB
= ramSizeMB
;
220 // If a Savage MX chip has > 8 MB, clamp it at 8 MB since memory for the
221 // hardware cursor above 8 MB is unusable.
223 if (si
.chipType
== S3_SAVAGE_MX
&& ramSizeMB
> 8)
226 TRACE("Savage_Init() memory size: %d MB, usable memory: %d MB\n", ramSizeMB
, usableMB
);
231 si
.videoMemSize
= usableMB
* 1024 * 1024;
233 // Compute the Command Overflow Buffer (COB) location.
235 uint32 cobSize
= 0x20000; // use 128kB for the COB
238 // Note that the X.org developers stated that the command overflow buffer
239 // (COB) must END at a 4MB boundary which for all practical purposes means
240 // the very end of the video memory.
242 si
.cobOffset
= (si
.videoMemSize
- cobSize
) & ~0x1ffff; // align cob to 128k
243 si
.cursorOffset
= (si
.cobOffset
- CURSOR_BYTES
) & ~0xfff; // align to 4k boundary
244 si
.frameBufferOffset
= 0;
245 si
.maxFrameBufferSize
= si
.cursorOffset
- si
.frameBufferOffset
;
247 TRACE("cobSizeIndex: %d cobSize: %d cobOffset: 0x%x\n", si
.cobSizeIndex
, cobSize
, si
.cobOffset
);
248 TRACE("cursorOffset: 0x%x frameBufferOffset: 0x%x\n", si
.cursorOffset
, si
.frameBufferOffset
);
250 // Reset graphics engine to avoid memory corruption.
252 WriteCrtcReg(0x66, 0x02, 0x02); // set reset flag
254 WriteCrtcReg(0x66, 0x00, 0x02); // clear reset flag
257 // Check for DVI/flat panel.
260 if (si
.chipType
== S3_SAVAGE4
) {
261 WriteSeqReg(0x30, 0x00, 0x02); // clear bit 1
262 if (ReadSeqReg(0x30) & 0x02 /* 0x04 */) {
264 TRACE("Digital Flat Panel Detected\n");
268 if (S3_SAVAGE_MOBILE_SERIES(si
.chipType
) || S3_MOBILE_TWISTER_SERIES(si
.chipType
)) {
269 si
.displayType
= MT_LCD
;
270 Savage_GetPanelInfo();
273 si
.displayType
= MT_DFP
;
275 si
.displayType
= MT_CRT
;
277 TRACE("Display Type: %d\n", si
.displayType
);
279 // Detect current mclk.
281 WriteSeqReg(0x08, 0x06); // unlock extended sequencer regs
283 uint8 m
= ReadSeqReg(0x11) & 0x7f;
284 uint8 n
= ReadSeqReg(0x10);
286 uint8 n2
= (n
>> 5) & 0x03;
287 si
.mclk
= ((1431818 * (m
+ 2)) / (n1
+ 2) / (1 << n2
) + 50) / 100;
289 TRACE("Detected current MCLK value of %1.3f MHz\n", si
.mclk
/ 1000.0);
291 // Set up the array of color spaces supported by the Savage chips.
293 si
.colorSpaces
[0] = B_CMAP8
;
294 si
.colorSpaces
[1] = B_RGB16
;
295 si
.colorSpaces
[2] = B_RGB32
;
296 si
.colorSpaceCount
= 3;
298 si
.bDisableHdwCursor
= false; // allow use of hardware cursor
299 si
.bDisableAccelDraw
= false; // allow use of accelerated drawing functions
301 // Setup the mode list.
303 return CreateModeList(IsModeUsable
, Savage_GetEdidInfo
);
308 Savage_SetFunctionPointers(void)
310 // Setting the function pointers must be done prior to first ModeInit call
311 // or any accel activity.
313 switch (gInfo
.sharedInfo
->chipType
) {
316 gInfo
.WaitQueue
= WaitQueue3D
;
317 gInfo
.WaitIdleEmpty
= WaitIdleEmpty3D
;
323 case S3_PROSAVAGE_DDR
:
325 gInfo
.WaitQueue
= WaitQueue4
;
326 gInfo
.WaitIdleEmpty
= WaitIdleEmpty4
;
330 gInfo
.WaitQueue
= WaitQueue2K
;
331 gInfo
.WaitIdleEmpty
= WaitIdleEmpty2K
;
335 gInfo
.DPMSCapabilities
= Savage_DPMSCapabilities
;
336 gInfo
.GetDPMSMode
= Savage_GetDPMSMode
;
337 gInfo
.SetDPMSMode
= Savage_SetDPMSMode
;
339 gInfo
.LoadCursorImage
= Savage_LoadCursorImage
;
340 gInfo
.SetCursorPosition
= Savage_SetCursorPosition
;
341 gInfo
.ShowCursor
= Savage_ShowCursor
;
343 gInfo
.FillRectangle
= Savage_FillRectangle
;
344 gInfo
.FillSpan
= Savage_FillSpan
;
345 gInfo
.InvertRectangle
= Savage_InvertRectangle
;
346 gInfo
.ScreenToScreenBlit
= Savage_ScreenToScreenBlit
;
348 gInfo
.AdjustFrame
= Savage_AdjustFrame
;
349 gInfo
.ChipInit
= Savage_Init
;
350 gInfo
.GetColorSpaceParams
= Savage_GetColorSpaceParams
;
351 gInfo
.SetDisplayMode
= Savage_SetDisplayMode
;
352 gInfo
.SetIndexedColors
= Savage_SetIndexedColors
;