xref: /haiku/src/add-ons/accelerants/s3/savage_init.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
1 /*
2 	Haiku S3 Savage driver adapted from the X.org Savage driver.
3 
4 	Copyright (C) 1994-2000 The XFree86 Project, Inc.	All Rights Reserved.
5 	Copyright (c) 2003-2006, X.Org Foundation
6 
7 	Copyright 2007-2008 Haiku, Inc.  All rights reserved.
8 	Distributed under the terms of the MIT license.
9 
10 	Authors:
11 	Gerald Zajac 2006-2008
12 */
13 
14 
15 #include "accel.h"
16 #include "savage.h"
17 
18 
19 
20 static bool
21 Savage_GetColorSpaceParams(int colorSpace, uint32& bitsPerPixel, uint32& maxPixelClock)
22 {
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.
26 
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;
43 	}
44 
45 	return true;
46 }
47 
48 
49 // Wait until "v" queue entries are free.
50 
51 static void
52 WaitQueue3D(uint32 v)
53 {
54 	uint32 slots = MAXFIFO - v;
55 	while ((STATUS_WORD0 & 0x0000ffff) > slots);
56 }
57 
58 
59 static void
60 WaitQueue4(uint32 v)
61 {
62 	uint32 slots = MAXFIFO - v;
63 	while ((ALT_STATUS_WORD0 & 0x001fffff) > slots);
64 }
65 
66 
67 static void
68 WaitQueue2K(uint32 v)
69 {
70 	uint32 slots = MAXFIFO - v;
71 	while ((ALT_STATUS_WORD0 & 0x000fffff) > slots);
72 }
73 
74 
75 // Wait until GP is idle and queue is empty.
76 
77 static void
78 WaitIdleEmpty3D()
79 {
80 	while ((STATUS_WORD0 & 0x0008ffff) != 0x80000);
81 }
82 
83 
84 static void
85 WaitIdleEmpty4()
86 {
87 	while ((ALT_STATUS_WORD0 & 0x00e1ffff) != 0x00e00000) ;
88 }
89 
90 
91 static void
92 WaitIdleEmpty2K()
93 {
94 	while ((ALT_STATUS_WORD0 & 0x009fffff) != 0);
95 }
96 
97 
98 static void
99 Savage_GetPanelInfo()
100 {
101 	SharedInfo& si = *gInfo.sharedInfo;
102 
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
109 	};
110 
111 	// Check LCD panel information.
112 
113 	uint8 cr6b = ReadCrtcReg(0x6b);
114 
115 	int panelX = (ReadSeqReg(0x61) + ((ReadSeqReg(0x66) & 0x02) << 7) + 1) * 8;
116 	int panelY =  ReadSeqReg(0x69) + ((ReadSeqReg(0x6e) & 0x70) << 4) + 1;
117 
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.
121 
122 	if (panelX == 1408)
123 		panelX = 1400;
124 
125 	char* sTechnology;
126 
127 	if ((ReadSeqReg(0x39) & 0x03) == 0)
128 		sTechnology = "TFT";
129 	else if ((ReadSeqReg(0x30) & 0x01) == 0)
130 		sTechnology = "DSTN";
131 	else
132 		sTechnology = "STN";
133 
134 	TRACE("%dx%d %s LCD panel detected %s\n", panelX, panelY, sTechnology,
135 			 cr6b & ActiveLCD ? "and active" : "but not active");
136 
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;
143 	}
144 }
145 
146 
147 status_t
148 Savage_Init(void)
149 {
150 	TRACE("Savage_Init()\n");
151 
152 	SharedInfo& si = *gInfo.sharedInfo;
153 
154 	// MMIO should be automatically enabled for Savage chips;  thus, use MMIO
155 	// to enable VGA and turn color on.
156 
157 	WriteReg8(VGA_ENABLE + 0x8000, ReadReg8(VGA_ENABLE + 0x8000) | 0x01);
158 	WriteMiscOutReg(ReadMiscOutReg() | 0x01);		// turn color on
159 
160 	if (si.chipType >= S3_SAVAGE4)
161 		WriteCrtcReg(0x40, 0x01, 0x01);
162 
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
167 
168 	WriteCrtcReg(0x40, 0x00, 0x01);
169 	WriteCrtcReg(0x38, 0x48);		// unlock sys regs CR20~CR3F
170 
171 	// Compute the amount of video memory and offscreen memory.
172 
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
178 
179 	uint8 cr36 = ReadCrtcReg(0x36);		// get amount of video ram
180 
181 	switch (si.chipType) {
182 		case S3_SAVAGE_3D:
183 			ramSizeMB = RamSavage3D[ (cr36 & 0xC0) >> 6 ];
184 			break;
185 
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;
193 
194 			// FALL THROUGH
195 
196 		case S3_SAVAGE2000:
197 			ramSizeMB = RamSavage4[ (cr36 & 0xE0) >> 5 ];
198 			break;
199 
200 		case S3_SAVAGE_MX:
201 		case S3_SUPERSAVAGE:
202 			ramSizeMB = RamSavageMX[ (cr36 & 0x0E) >> 1 ];
203 			break;
204 
205 		case S3_PROSAVAGE:
206 		case S3_PROSAVAGE_DDR:
207 		case S3_TWISTER:
208 			ramSizeMB = RamSavageNB[ (cr36 & 0xE0) >> 5 ];
209 			break;
210 
211 		default:
212 			// How did we get here?
213 			ramSizeMB = 0;
214 			break;
215 	}
216 
217 	uint32 usableMB = ramSizeMB;
218 
219 
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.
222 
223 	if (si.chipType == S3_SAVAGE_MX && ramSizeMB > 8)
224 		usableMB = 8;
225 
226 	TRACE("Savage_Init() memory size: %d MB, usable memory: %d MB\n", ramSizeMB, usableMB);
227 
228 	if (usableMB <= 0)
229 		return B_ERROR;
230 
231 	si.videoMemSize = usableMB * 1024 * 1024;
232 
233 	// Compute the Command Overflow Buffer (COB) location.
234 
235 	uint32 cobSize = 0x20000;	// use 128kB for the COB
236 	si.cobSizeIndex = 7;
237 
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.
241 
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;
246 
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);
249 
250 	// Reset graphics engine to avoid memory corruption.
251 
252 	WriteCrtcReg(0x66, 0x02, 0x02);		// set reset flag
253 	snooze(10000);
254 	WriteCrtcReg(0x66, 0x00, 0x02);		// clear reset flag
255 	snooze(10000);
256 
257 	// Check for DVI/flat panel.
258 
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");
265 		}
266 	}
267 
268 	if (S3_SAVAGE_MOBILE_SERIES(si.chipType) || S3_MOBILE_TWISTER_SERIES(si.chipType)) {
269 		si.displayType = MT_LCD;
270 		Savage_GetPanelInfo();
271 	}
272 	else if (bDvi)
273 		si.displayType = MT_DFP;
274 	else
275 		si.displayType = MT_CRT;
276 
277 	TRACE("Display Type: %d\n", si.displayType);
278 
279 	// Detect current mclk.
280 
281 	WriteSeqReg(0x08, 0x06);		// unlock extended sequencer regs
282 
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;
288 
289 	TRACE("Detected current MCLK value of %1.3f MHz\n", si.mclk / 1000.0);
290 
291 	// Set up the array of color spaces supported by the Savage chips.
292 
293 	si.colorSpaces[0] = B_CMAP8;
294 	si.colorSpaces[1] = B_RGB16;
295 	si.colorSpaces[2] = B_RGB32;
296 	si.colorSpaceCount = 3;
297 
298 	si.bDisableHdwCursor = false;	// allow use of hardware cursor
299 	si.bDisableAccelDraw = false;	// allow use of accelerated drawing functions
300 
301 	// Setup the mode list.
302 
303 	return CreateModeList(IsModeUsable, Savage_GetEdidInfo);
304 }
305 
306 
307 void
308 Savage_SetFunctionPointers(void)
309 {
310 	// Setting the function pointers must be done prior to first ModeInit call
311 	// or any accel activity.
312 
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;
319 
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;
328 
329 		case S3_SAVAGE2000:
330 			 gInfo.WaitQueue		= WaitQueue2K;
331 			 gInfo.WaitIdleEmpty	= WaitIdleEmpty2K;
332 			 break;
333 	}
334 
335 	gInfo.DPMSCapabilities = Savage_DPMSCapabilities;
336 	gInfo.GetDPMSMode = Savage_GetDPMSMode;
337 	gInfo.SetDPMSMode = Savage_SetDPMSMode;
338 
339 	gInfo.LoadCursorImage = Savage_LoadCursorImage;
340 	gInfo.SetCursorPosition = Savage_SetCursorPosition;
341 	gInfo.ShowCursor = Savage_ShowCursor;
342 
343 	gInfo.FillRectangle = Savage_FillRectangle;
344 	gInfo.FillSpan = Savage_FillSpan;
345 	gInfo.InvertRectangle = Savage_InvertRectangle;
346 	gInfo.ScreenToScreenBlit = Savage_ScreenToScreenBlit;
347 
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;
353 }
354 
355