xref: /haiku/src/add-ons/accelerants/ati/rage128_init.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
1 /*
2 	Haiku ATI video driver adapted from the X.org ATI driver.
3 
4 	Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
5 						 Precision Insight, Inc., Cedar Park, Texas, and
6 						 VA Linux Systems Inc., Fremont, California.
7 
8 	Copyright 2009 Haiku, Inc.  All rights reserved.
9 	Distributed under the terms of the MIT license.
10 
11 	Authors:
12 	Gerald Zajac 2009
13 */
14 
15 
16 #include "accelerant.h"
17 #include "rage128.h"
18 
19 
20 
21 // Memory Specifications from RAGE 128 Software Development Manual
22 // (Technical Reference Manual P/N SDK-G04000 Rev 0.01), page 3-21.
23 static R128_RAMSpec sRAMSpecs[] = {
24 	{ 4, 4, 3, 3, 1, 3, 1, 16, 12, "128-bit SDR SGRAM 1:1" },
25 	{ 4, 8, 3, 3, 1, 3, 1, 17, 13, "64-bit SDR SGRAM 1:1" },
26 	{ 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SGRAM 2:1" },
27 	{ 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SGRAM" },
28 };
29 
30 
31 
32 static bool
33 Rage128_GetColorSpaceParams(int colorSpace, uint8& bitsPerPixel, uint32& maxPixelClock)
34 {
35 	// Get parameters for a color space which is supported by the Rage128 chips.
36 	// Argument maxPixelClock is in KHz.
37 	// Return true if the color space is supported;  else return false.
38 
39 	switch (colorSpace) {
40 		case B_RGB32:
41 			bitsPerPixel = 32;
42 			break;
43 		case B_RGB16:
44 			bitsPerPixel = 16;
45 			break;
46 		case B_RGB15:
47 			bitsPerPixel = 15;
48 			break;
49 		case B_CMAP8:
50 			bitsPerPixel = 8;
51 			break;
52 		default:
53 			TRACE("Unsupported color space: 0x%X\n", colorSpace);
54 			return false;
55 	}
56 
57 	maxPixelClock = gInfo.sharedInfo->r128PLLParams.max_pll_freq * 10;
58 	return true;
59 }
60 
61 
62 static void
63 WaitForFifo(uint32 entries)
64 {
65 	// The FIFO has 64 slots.  This routines waits until at least `entries'
66 	// of these slots are empty.
67 
68 	while (true) {
69 		for (int i = 0; i < R128_TIMEOUT; i++) {
70 			uint32 slots = INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
71 			if (slots >= entries)
72 				return;
73 		}
74 
75 		TRACE("FIFO timed out: %d entries, stat=0x%08x, probe=0x%08x\n",
76 			INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK,
77 			INREG(R128_GUI_STAT),
78 			INREG(R128_GUI_PROBE));
79 		TRACE("FIFO timed out, resetting engine...\n");
80 
81 		Rage128_EngineReset();
82 	}
83 }
84 
85 
86 static void
87 WaitForIdle()
88 {
89 	// Wait for the graphics engine to be completely idle.  That is, the FIFO
90 	// has drained, the Pixel Cache is flushed, and the engine is idle.  This
91 	// is a standard "sync" function that will make the hardware "quiescent".
92 
93 	WaitForFifo(64);
94 
95 	while (true) {
96 		for (uint32 i = 0; i < R128_TIMEOUT; i++) {
97 			if ( ! (INREG(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
98 				Rage128_EngineFlush();
99 				return ;
100 			}
101 		}
102 
103 		TRACE("Idle timed out: %d entries, stat=0x%08x, probe=0x%08x\n",
104 				   INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK,
105 				   INREG(R128_GUI_STAT),
106 				   INREG(R128_GUI_PROBE));
107 		TRACE("Idle timed out, resetting engine...\n");
108 
109 		Rage128_EngineReset();
110 	}
111 }
112 
113 
114 status_t
115 Rage128_Init(void)
116 {
117 	TRACE("Rage128_Init()\n");
118 
119 	SharedInfo& si = *gInfo.sharedInfo;
120 
121 	si.videoMemSize = INREG(R128_CONFIG_MEMSIZE);
122 
123 	si.cursorOffset = (si.videoMemSize - CURSOR_BYTES) & ~0xfff;	// align to 4k boundary
124 	si.frameBufferOffset = 0;
125 	si.maxFrameBufferSize = si.cursorOffset - si.frameBufferOffset;
126 
127 	TRACE("Video Memory size: %d MB  frameBufferOffset: 0x%x  cursorOffset: 0x%x\n",
128 		si.videoMemSize / 1024 / 1024, si.frameBufferOffset, si.cursorOffset);
129 
130 	// Get the specifications of the memory used by the chip.
131 
132 	uint32 offset;
133 
134 	switch (INREG(R128_MEM_CNTL) & 0x3) {
135 	case 0:					// SDR SGRAM 1:1
136 		switch (si.deviceID) {
137 		case 0x4C45:		// RAGE128 LE:
138 		case 0x4C46:		// RAGE128 LF:
139 		case 0x4D46:		// RAGE128 MF:
140 		case 0x4D4C:		// RAGE128 ML:
141 		case 0x5245:		// RAGE128 RE:
142 		case 0x5246:		// RAGE128 RF:
143 		case 0x5247:		// RAGE128 RG:
144 		case 0x5446:		// RAGE128 TF:
145 		case 0x544C:		// RAGE128 TL:
146 		case 0x5452:		// RAGE128 TR:
147 			offset = 0;		// 128-bit SDR SGRAM 1:1
148 			break;
149 		default:
150 			offset = 1;		// 64-bit SDR SGRAM 1:1
151 			break;
152 		}
153 		break;
154 	case 1:
155 		offset = 2;		// 64-bit SDR SGRAM 2:1
156 		break;
157 	case 2:
158 		offset = 3;		// 64-bit DDR SGRAM
159 		break;
160 	default:
161 		offset = 1;		// 64-bit SDR SGRAM 1:1
162 		break;
163 	}
164 	si.r128MemSpec = sRAMSpecs[offset];
165 	TRACE("RAM type: %s\n", si.r128MemSpec.name);
166 
167 	// Determine the type of display.
168 
169 	si.displayType = MT_VGA;
170 
171 	if (INREG(R128_FP_PANEL_CNTL) & R128_FP_DIGON)	// don't know if this is correct
172 		si.displayType = MT_DVI;
173 
174 	if (si.chipType == RAGE128_MOBILITY && si.panelX > 0 && si.panelY > 0) {
175 		if (INREG(R128_LVDS_GEN_CNTL) & R128_LVDS_ON)
176 			si.displayType = MT_LAPTOP;	// laptop LCD display is on
177 	}
178 
179 	// Set up the array of color spaces supported by the Rage128 chips.
180 
181 	si.colorSpaces[0] = B_CMAP8;
182 	si.colorSpaces[1] = B_RGB15;
183 	si.colorSpaces[2] = B_RGB16;
184 	si.colorSpaces[3] = B_RGB32;
185 	si.colorSpaceCount = 4;
186 
187 	// Setup the mode list.
188 
189 	return CreateModeList(IsModeUsable);
190 }
191 
192 
193 void
194 Rage128_SetFunctionPointers(void)
195 {
196 	// Setting the function pointers must be done prior to first ModeInit call
197 	// or any accel activity.
198 
199 	gInfo.WaitForFifo = WaitForFifo;
200 	gInfo.WaitForIdle = WaitForIdle;
201 
202 	gInfo.DPMSCapabilities = Rage128_DPMSCapabilities;
203 	gInfo.GetDPMSMode = Rage128_GetDPMSMode;
204 	gInfo.SetDPMSMode = Rage128_SetDPMSMode;
205 
206 	gInfo.LoadCursorImage = Rage128_LoadCursorImage;
207 	gInfo.SetCursorPosition = Rage128_SetCursorPosition;
208 	gInfo.ShowCursor = Rage128_ShowCursor;
209 
210 	gInfo.FillRectangle = Rage128_FillRectangle;
211 	gInfo.FillSpan = Rage128_FillSpan;
212 	gInfo.InvertRectangle = Rage128_InvertRectangle;
213 	gInfo.ScreenToScreenBlit = Rage128_ScreenToScreenBlit;
214 
215 	gInfo.AdjustFrame = Rage128_AdjustFrame;
216 	gInfo.ChipInit = Rage128_Init;
217 	gInfo.GetColorSpaceParams = Rage128_GetColorSpaceParams;
218 	gInfo.SetDisplayMode = Rage128_SetDisplayMode;
219 	gInfo.SetIndexedColors = Rage128_SetIndexedColors;
220 }
221 
222