tcp: Add APICall trace entry and move TRACEs into locked parts.
[haiku.git] / src / add-ons / accelerants / s3 / savage_init.cpp
blob56c002f78d46587b56ca10782cc14db158eae629
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"
20 static bool
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.
27 switch (colorSpace) {
28 case B_RGB32:
29 bitsPerPixel = 32;
30 maxPixelClock = 220000;
31 break;
32 case B_RGB16:
33 bitsPerPixel = 16;
34 maxPixelClock = 250000;
35 break;
36 case B_CMAP8:
37 bitsPerPixel = 8;
38 maxPixelClock = 250000;
39 break;
40 default:
41 TRACE("Unsupported color space: 0x%X\n", colorSpace);
42 return false;
45 return true;
49 // Wait until "v" queue entries are free.
51 static void
52 WaitQueue3D(uint32 v)
54 uint32 slots = MAXFIFO - v;
55 while ((STATUS_WORD0 & 0x0000ffff) > slots);
59 static void
60 WaitQueue4(uint32 v)
62 uint32 slots = MAXFIFO - v;
63 while ((ALT_STATUS_WORD0 & 0x001fffff) > slots);
67 static void
68 WaitQueue2K(uint32 v)
70 uint32 slots = MAXFIFO - v;
71 while ((ALT_STATUS_WORD0 & 0x000fffff) > slots);
75 // Wait until GP is idle and queue is empty.
77 static void
78 WaitIdleEmpty3D()
80 while ((STATUS_WORD0 & 0x0008ffff) != 0x80000);
84 static void
85 WaitIdleEmpty4()
87 while ((ALT_STATUS_WORD0 & 0x00e1ffff) != 0x00e00000) ;
91 static void
92 WaitIdleEmpty2K()
94 while ((ALT_STATUS_WORD0 & 0x009fffff) != 0);
98 static void
99 Savage_GetPanelInfo()
101 SharedInfo& si = *gInfo.sharedInfo;
103 enum ACTIVE_DISPLAYS { // these are the bits in CR6B
104 ActiveCRT = 0x01,
105 ActiveLCD = 0x02,
106 ActiveTV = 0x04,
107 ActiveCRT2 = 0x20,
108 ActiveDUO = 0x80
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.
122 if (panelX == 1408)
123 panelX = 1400;
125 const char* sTechnology;
127 if ((ReadSeqReg(0x39) & 0x03) == 0)
128 sTechnology = "TFT";
129 else if ((ReadSeqReg(0x30) & 0x01) == 0)
130 sTechnology = "DSTN";
131 else
132 sTechnology = "STN";
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);
139 si.panelX = panelX;
140 si.panelY = panelY;
141 } else {
142 si.displayType = MT_CRT;
147 status_t
148 Savage_Init(void)
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) {
182 case S3_SAVAGE_3D:
183 ramSizeMB = RamSavage3D[ (cr36 & 0xC0) >> 6 ];
184 break;
186 case S3_SAVAGE4:
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))
192 RamSavage4[1] = 8;
194 // FALL THROUGH
196 case S3_SAVAGE2000:
197 ramSizeMB = RamSavage4[ (cr36 & 0xE0) >> 5 ];
198 break;
200 case S3_SAVAGE_MX:
201 case S3_SUPERSAVAGE:
202 ramSizeMB = RamSavageMX[ (cr36 & 0x0E) >> 1 ];
203 break;
205 case S3_PROSAVAGE:
206 case S3_PROSAVAGE_DDR:
207 case S3_TWISTER:
208 ramSizeMB = RamSavageNB[ (cr36 & 0xE0) >> 5 ];
209 break;
211 default:
212 // How did we get here?
213 ramSizeMB = 0;
214 break;
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)
224 usableMB = 8;
226 TRACE("Savage_Init() memory size: %d MB, usable memory: %d MB\n", ramSizeMB, usableMB);
228 if (usableMB <= 0)
229 return B_ERROR;
231 si.videoMemSize = usableMB * 1024 * 1024;
233 // Compute the Command Overflow Buffer (COB) location.
235 uint32 cobSize = 0x20000; // use 128kB for the COB
236 si.cobSizeIndex = 7;
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
253 snooze(10000);
254 WriteCrtcReg(0x66, 0x00, 0x02); // clear reset flag
255 snooze(10000);
257 // Check for DVI/flat panel.
259 bool bDvi = false;
260 if (si.chipType == S3_SAVAGE4) {
261 WriteSeqReg(0x30, 0x00, 0x02); // clear bit 1
262 if (ReadSeqReg(0x30) & 0x02 /* 0x04 */) {
263 bDvi = true;
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();
272 else if (bDvi)
273 si.displayType = MT_DFP;
274 else
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);
285 uint8 n1 = n & 0x1f;
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);
307 void
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) {
314 case S3_SAVAGE_3D:
315 case S3_SAVAGE_MX:
316 gInfo.WaitQueue = WaitQueue3D;
317 gInfo.WaitIdleEmpty = WaitIdleEmpty3D;
318 break;
320 case S3_SAVAGE4:
321 case S3_PROSAVAGE:
322 case S3_SUPERSAVAGE:
323 case S3_PROSAVAGE_DDR:
324 case S3_TWISTER:
325 gInfo.WaitQueue = WaitQueue4;
326 gInfo.WaitIdleEmpty = WaitIdleEmpty4;
327 break;
329 case S3_SAVAGE2000:
330 gInfo.WaitQueue = WaitQueue2K;
331 gInfo.WaitIdleEmpty = WaitIdleEmpty2K;
332 break;
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;