xref: /haiku/src/add-ons/accelerants/ati/mach64_init.cpp (revision 80829ec813241c9a702a45e39929286f13c55093)
1 /*
2 	Haiku ATI video driver adapted from the X.org ATI driver.
3 
4 	Copyright 1992,1993,1994,1995,1996,1997 by Kevin E. Martin, Chapel Hill, North Carolina.
5 	Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
6 
7 	Copyright 2009 Haiku, Inc.  All rights reserved.
8 	Distributed under the terms of the MIT license.
9 
10 	Authors:
11 	Gerald Zajac 2009
12 */
13 
14 
15 #include "accelerant.h"
16 #include "mach64.h"
17 
18 
19 
20 static bool
Mach64_InitDSPParams()21 Mach64_InitDSPParams()
22 {
23 	// Initialize global variables used to set DSP registers on a VT-B or later.
24 
25 	SharedInfo& si = *gInfo.sharedInfo;
26 	M64_Params& params = si.m64Params;
27 
28 	// Retrieve XCLK settings.
29 
30 	uint8 ioValue = Mach64_GetPLLReg(PLL_XCLK_CNTL);
31 	params.xClkPostDivider = ioValue & 0x7;
32 
33 	switch (params.xClkPostDivider) {
34 	case 0:
35 	case 1:
36 	case 2:
37 	case 3:
38 		params.xClkRefDivider = 1;
39 		break;
40 
41 	case 4:
42 		params.xClkRefDivider = 3;
43 		params.xClkPostDivider = 0;
44 		break;
45 
46 	default:
47 		TRACE("Unsupported XCLK source:  %d.\n", params.xClkPostDivider);
48 		return false;
49 	}
50 
51 	if (ioValue & PLL_MFB_TIMES_4_2B)
52 		params.xClkPostDivider--;
53 
54 	// Compute maximum RAS delay and related params.
55 
56 	uint32 memCntl = INREG(MEM_CNTL);
57 	int trp = GetBits(memCntl, CTL_MEM_TRP);
58 	params.xClkPageFaultDelay = GetBits(memCntl, CTL_MEM_TRCD) +
59 							   GetBits(memCntl, CTL_MEM_TCRD) + trp + 2;
60 	params.xClkMaxRASDelay = GetBits(memCntl, CTL_MEM_TRAS) + trp + 2;
61 
62 	params.displayFIFODepth = 32;
63 
64 	if (si.chipType < MACH64_264VT4) {
65 		params.xClkPageFaultDelay += 2;
66 		params.xClkMaxRASDelay += 3;
67 		params.displayFIFODepth = 24;
68 	}
69 
70 	// Determine type of memory used with the chip.
71 
72 	int memType = INREG(CONFIG_STAT0) & 0x7;
73 	TRACE("Memory type: %d\n", memType);
74 
75 	switch (memType) {
76 	case MEM_DRAM:
77 		if (si.videoMemSize <= 1024 * 1024) {
78 			params.displayLoopLatency = 10;
79 		} else {
80 			params.displayLoopLatency = 8;
81 			params.xClkPageFaultDelay += 2;
82 		}
83 		break;
84 
85 	case MEM_EDO:
86 	case MEM_PSEUDO_EDO:
87 		if (si.videoMemSize <= 1024 * 1024) {
88 			params.displayLoopLatency = 9;
89 		} else {
90 			params.displayLoopLatency = 8;
91 			params.xClkPageFaultDelay++;
92 		}
93 		break;
94 
95 	case MEM_SDRAM:
96 		if (si.videoMemSize <= 1024 * 1024) {
97 			params.displayLoopLatency = 11;
98 		} else {
99 			params.displayLoopLatency = 10;
100 			params.xClkPageFaultDelay++;
101 		}
102 		break;
103 
104 	case MEM_SGRAM:
105 		params.displayLoopLatency = 8;
106 		params.xClkPageFaultDelay += 3;
107 		break;
108 
109 	default:                 /* Set maximums */
110 		params.displayLoopLatency = 11;
111 		params.xClkPageFaultDelay += 3;
112 		break;
113 	}
114 
115 	if (params.xClkMaxRASDelay <= params.xClkPageFaultDelay)
116 		params.xClkMaxRASDelay = params.xClkPageFaultDelay + 1;
117 
118 	uint32 dspConfig = INREG(DSP_CONFIG);
119 	if (dspConfig)
120 		params.displayLoopLatency = GetBits(dspConfig, DSP_LOOP_LATENCY);
121 
122 	return true;
123 }
124 
125 
126 static bool
Mach64_GetColorSpaceParams(int colorSpace,uint8 & bitsPerPixel,uint32 & maxPixelClock)127 Mach64_GetColorSpaceParams(int colorSpace, uint8& bitsPerPixel, uint32& maxPixelClock)
128 {
129 	// Get parameters for a color space which is supported by the Mach64 chips.
130 	// Argument maxPixelClock is in KHz.
131 	// Return true if the color space is supported;  else return false.
132 
133 	SharedInfo& si = *gInfo.sharedInfo;
134 
135 	switch (colorSpace) {
136 		case B_RGB32:
137 			bitsPerPixel = 32;
138 			break;
139 		case B_RGB16:
140 			bitsPerPixel = 16;
141 			break;
142 		case B_RGB15:
143 			bitsPerPixel = 15;
144 			break;
145 		case B_CMAP8:
146 			bitsPerPixel = 8;
147 			break;
148 		default:
149 			TRACE("Unsupported color space: 0x%X\n", colorSpace);
150 			return false;
151 	}
152 
153 	if (si.chipType >= MACH64_264VTB) {
154 		if ((si.chipType >= MACH64_264VT4) && (si.chipType != MACH64_264LTPRO))
155 			maxPixelClock = 230000;
156 		else if (si.chipType >= MACH64_264VT3)
157 			maxPixelClock = 200000;
158 		else
159 			maxPixelClock = 170000;
160 	} else {
161 		if (bitsPerPixel == 8)
162 			maxPixelClock = 135000;
163 		else
164 			maxPixelClock = 80000;
165 	}
166 
167 	return true;
168 }
169 
170 
171 
172 status_t
Mach64_Init(void)173 Mach64_Init(void)
174 {
175 	TRACE("Mach64_Init()\n");
176 
177 	SharedInfo& si = *gInfo.sharedInfo;
178 
179 	static const int videoRamSizes[] =
180 		{ 512, 1024, 2*1024, 4*1024, 6*1024, 8*1024, 12*1024, 16*1024 };
181 
182 	uint32 memCntl = INREG(MEM_CNTL);
183 	if (si.chipType < MACH64_264VTB) {
184 		si.videoMemSize = videoRamSizes[memCntl & 0x7] * 1024;
185 	} else {
186 		uint32 ioValue = (memCntl & 0xf);
187 		if (ioValue < 8)
188 			si.videoMemSize = (ioValue + 1) * 512 * 1024;
189 		else if (ioValue < 12)
190 			si.videoMemSize = (ioValue - 3) * 1024 * 1024;
191 		else
192 			si.videoMemSize = (ioValue - 7) * 2048 * 1024;
193 	}
194 
195 	si.cursorOffset = (si.videoMemSize - CURSOR_BYTES) & ~0xfff;	// align to 4k boundary
196 	si.frameBufferOffset = 0;
197 	si.maxFrameBufferSize = si.cursorOffset - si.frameBufferOffset;
198 
199 	TRACE("Video Memory size: %d MB  frameBufferOffset: 0x%x  cursorOffset: 0x%x\n",
200 		si.videoMemSize / 1024 / 1024, si.frameBufferOffset, si.cursorOffset);
201 
202 	// 264VT-B's and later have DSP registers.
203 
204 	if ((si.chipType >= MACH64_264VTB) && !Mach64_InitDSPParams())
205 		return B_ERROR;
206 
207 	// Determine if the LCD display of a laptop computer is active.
208 
209 	si.displayType = MT_VGA;
210 
211 	if (si.chipType == MACH64_MOBILITY && si.panelX > 0 && si.panelY > 0) {
212 		if (Mach64_GetLCDReg(LCD_GEN_CNTL) & LCD_ON)
213 			si.displayType = MT_LAPTOP;
214 	}
215 
216 	// Set up the array of color spaces supported by the Mach64 chips.
217 
218 	si.colorSpaces[0] = B_CMAP8;
219 	si.colorSpaces[1] = B_RGB15;
220 	si.colorSpaces[2] = B_RGB16;
221 	si.colorSpaces[3] = B_RGB32;
222 	si.colorSpaceCount = 4;
223 
224 	// Setup the mode list.
225 
226 	return CreateModeList(IsModeUsable);
227 }
228 
229 
230 static void
Mach64_WaitForFifo(uint32 entries)231 Mach64_WaitForFifo(uint32 entries)
232 {
233 	// The FIFO has 16 slots.  This routines waits until at least `entries'
234 	// of these slots are empty.
235 
236 	while ((INREG(FIFO_STAT) & 0xffff) > (0x8000ul >> entries)) ;
237 }
238 
239 
240 static void
Mach64_WaitForIdle()241 Mach64_WaitForIdle()
242 {
243 	// Wait for the graphics engine to be completely idle.  That is, the FIFO
244 	// has drained, the Pixel Cache is flushed, and the engine is idle.  This
245 	// is a standard "sync" function that will make the hardware "quiescent".
246 
247 	Mach64_WaitForFifo(16);
248 
249 	while (INREG(GUI_STAT) & ENGINE_BUSY) ;
250 }
251 
252 
253 void
Mach64_SetFunctionPointers(void)254 Mach64_SetFunctionPointers(void)
255 {
256 	// Setting the function pointers must be done prior to first ModeInit call
257 	// or any accel activity.
258 
259 	gInfo.WaitForFifo = Mach64_WaitForFifo;
260 	gInfo.WaitForIdle = Mach64_WaitForIdle;
261 
262 	gInfo.DPMSCapabilities = Mach64_DPMSCapabilities;
263 	gInfo.GetDPMSMode = Mach64_GetDPMSMode;
264 	gInfo.SetDPMSMode = Mach64_SetDPMSMode;
265 
266 	gInfo.LoadCursorImage = Mach64_LoadCursorImage;
267 	gInfo.SetCursorPosition = Mach64_SetCursorPosition;
268 	gInfo.ShowCursor = Mach64_ShowCursor;
269 
270 	gInfo.FillRectangle = Mach64_FillRectangle;
271 	gInfo.FillSpan = Mach64_FillSpan;
272 	gInfo.InvertRectangle = Mach64_InvertRectangle;
273 	gInfo.ScreenToScreenBlit = Mach64_ScreenToScreenBlit;
274 
275 	gInfo.AdjustFrame = Mach64_AdjustFrame;
276 	gInfo.ChipInit = Mach64_Init;
277 	gInfo.GetColorSpaceParams = Mach64_GetColorSpaceParams;
278 	gInfo.SetDisplayMode = Mach64_SetDisplayMode;
279 	gInfo.SetIndexedColors = Mach64_SetIndexedColors;
280 }
281 
282