xref: /haiku/src/add-ons/accelerants/s3/virge_init.cpp (revision 508f54795f39c3e7552d87c95aae9dd8ec6f505b)
1 /*
2 	Haiku S3 Virge driver adapted from the X.org Virge driver.
3 
4 	Copyright (C) 1994-1999 The XFree86 Project, Inc.	All Rights Reserved.
5 
6 	Copyright 2007-2008 Haiku, Inc.  All rights reserved.
7 	Distributed under the terms of the MIT license.
8 
9 	Authors:
10 	Gerald Zajac 2007-2008
11 */
12 
13 
14 #include "accel.h"
15 #include "virge.h"
16 
17 
18 
19 static void
20 VirgeWaitFifoGX2(uint32 slots )
21 {
22 	while (((ReadReg32(SUBSYS_STAT_REG) >> 9) & 0x60) < slots) {}
23 }
24 
25 
26 
27 static void
28 VirgeWaitFifoMain(uint32 slots )
29 {
30 	while (((ReadReg32(SUBSYS_STAT_REG) >> 8) & 0x1f) < slots) {}
31 }
32 
33 
34 static void
35 VirgeWaitIdleEmpty()
36 {
37 	// Wait until GP is idle and queue is empty.
38 
39 	if(gInfo.sharedInfo->chipType == S3_TRIO_3D)
40 		while ((IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) != 0x20002000);
41 	else
42 		while ((IN_SUBSYS_STAT() & 0x3f00) != 0x3000);
43 }
44 
45 
46 static bool
47 Virge_GetColorSpaceParams(int colorSpace, uint32& bitsPerPixel, uint32& maxPixelClock)
48 {
49 	// Get parameters for a color space which is supported by the Virge chips.
50 	// Argument maxPixelClock is in KHz.
51 	// Return true if the color space is supported;  else return false.
52 
53 	// Note that the X.org code set the max clock to 440000 for a Virge VX chip
54 	// and 270000 for all other chips.  440000 seems rather high for a chip that
55 	// old;  thus, 270000 is used for all chips.
56 
57 	switch (colorSpace) {
58 		case B_RGB16:
59 			bitsPerPixel = 16;
60 			maxPixelClock = 270000;
61 			break;
62 		case B_CMAP8:
63 			bitsPerPixel = 8;
64 			maxPixelClock = 270000;
65 			break;
66 		default:
67 			TRACE("Unsupported color space: 0x%X\n", colorSpace);
68 			return false;
69 	}
70 
71 	return true;
72 }
73 
74 
75 
76 status_t
77 Virge_Init(void)
78 {
79 	TRACE("Virge_Init()\n");
80 
81 	SharedInfo& si = *gInfo.sharedInfo;
82 
83 	// Use PIO for following operations since MMIO may not be currently enabled.
84 
85 	WritePIO_8(VGA_ENABLE, ReadPIO_8(VGA_ENABLE) | 0x01);	// enable VGA
86 	WritePIO_8(MISC_OUT_W, ReadPIO_8(MISC_OUT_R) | 0x01);	// enable color
87 
88 	// Set linear base register to the PCI register value;
89 	// some DX chipsets don't seem to do it automatically.
90 
91 	WritePIO_8(CRTC_INDEX, 0x59);
92 	WritePIO_8(CRTC_DATA, (uint32)(si.videoMemPCI) >> 24);
93 	WritePIO_8(CRTC_INDEX, 0x5A);
94 	WritePIO_8(CRTC_DATA, (uint32)(si.videoMemPCI) >> 16);
95 
96 	// Enable MMIO.
97 
98 	WritePIO_8(CRTC_INDEX, 0x53);
99 	WritePIO_8(CRTC_DATA, ReadPIO_8(CRTC_DATA) | 0x8);
100 
101 	if (si.chipType == S3_TRIO_3D)
102 		WriteCrtcReg(0x40, 0x01, 0x01);
103 
104 	// Detect amount of installed ram.
105 
106 	uint8 config1 = ReadCrtcReg(0x36);	// get amount of vram installed
107 	uint8 config2 = ReadCrtcReg(0x37);	// get amount of off-screen ram
108 
109 	// Compute the amount of video memory and offscreen memory.
110 
111 	int   ramOffScreenMB = 0;	// off screen memory size in megabytes
112 	int   ramSizeMB = 0;		// memory size in megabytes
113 
114 	if (si.chipType == S3_VIRGE_VX) {
115 		switch ((config2 & 0x60) >> 5) {
116 			case 1:
117 				ramOffScreenMB = 4;
118 				break;
119 			case 2:
120 				ramOffScreenMB = 2;
121 				break;
122 		}
123 
124 		switch ((config1 & 0x60) >> 5) {
125 			case 0:
126 				ramSizeMB = 2;
127 				break;
128 			case 1:
129 				ramSizeMB = 4;
130 				break;
131 			case 2:
132 				ramSizeMB = 6;
133 				break;
134 			case 3:
135 				ramSizeMB = 8;
136 				break;
137 		}
138 		ramSizeMB -= ramOffScreenMB;
139 
140 	} else if (si.chipType == S3_TRIO_3D_2X) {
141 		switch ((config1 & 0xE0) >> 5) {
142 			case 0:   	// 8MB -- only 4MB usable for display/cursor
143 				ramSizeMB = 4;
144 				ramOffScreenMB = 4;
145 				break;
146 			case 1:     // 32 bit interface -- yuck
147 				TRACE("Undefined video memory size on S3 Trio 3D/2X\n");
148 			case 2:
149 				ramSizeMB = 4;
150 				break;
151 			case 6:
152 				ramSizeMB = 2;
153 				break;
154 		}
155 	} else if (si.chipType == S3_TRIO_3D) {
156 		switch ((config1 & 0xE0) >> 5) {
157 			case 0:
158 			case 2:
159 				ramSizeMB = 4;
160 				break;
161 			case 4:
162 				ramSizeMB = 2;
163 				break;
164 		}
165 	} else if (si.chipType == S3_VIRGE_GX2 || S3_VIRGE_MX_SERIES(si.chipType)) {
166 		switch ((config1 & 0xC0) >> 6) {
167 			case 1:
168 				ramSizeMB = 4;
169 				break;
170 			case 3:
171 				ramSizeMB = 2;
172 				break;
173 		}
174 	} else {
175 		switch ((config1 & 0xE0) >> 5) {
176 			case 0:
177 				ramSizeMB = 4;
178 				break;
179 			case 4:
180 				ramSizeMB = 2;
181 				break;
182 			case 6:
183 				ramSizeMB = 1;
184 				break;
185 		}
186 	}
187 
188 	TRACE("usable memory: %d MB,  off-screen memory: %d MB\n", ramSizeMB, ramOffScreenMB);
189 
190 	if (ramSizeMB <= 0)
191 		return B_ERROR;
192 
193 	si.videoMemSize = ramSizeMB * 1024 * 1024;
194 	si.cursorOffset = si.videoMemSize - CURSOR_BYTES;	// put cursor at end of video memory
195 	si.frameBufferOffset = 0;
196 	si.maxFrameBufferSize = si.videoMemSize - CURSOR_BYTES;
197 
198 	// Detect current mclk.
199 
200 	WriteSeqReg(0x08, 0x06);		// unlock extended sequencer regs
201 
202 	uint8 m = ReadSeqReg(0x11) & 0x7f;
203 	uint8 n = ReadSeqReg(0x10);
204 	uint8 n1 = n & 0x1f;
205 	uint8 n2 = (n >> 5) & 0x03;
206 	si.mclk = ((1431818 * (m + 2)) / (n1 + 2) / (1 << n2) + 50) / 100;
207 
208 	TRACE("Detected current MCLK value of %1.3f MHz\n", si.mclk / 1000.0);
209 
210 	if (S3_VIRGE_MX_SERIES(si.chipType)) {
211 		si.displayType = ((ReadSeqReg(0x31) & 0x10) ? MT_LCD : MT_CRT);
212 		si.panelX = (ReadSeqReg(0x61) + ((ReadSeqReg(0x66) & 0x02) << 7) + 1) * 8;
213 		si.panelY =  ReadSeqReg(0x69) + ((ReadSeqReg(0x6e) & 0x70) << 4) + 1;
214 
215 		TRACE("%dx%d LCD panel detected %s\n", si.panelX, si.panelY,
216 				 si.displayType == MT_LCD ? "and active" : "but not active");
217 	} else {
218 		si.displayType = MT_CRT;
219 		si.panelX = 0;
220 		si.panelY = 0;
221 	}
222 
223 	// Set up the array of color spaces supported by the Virge/Trio3D chips.
224 
225 	si.colorSpaces[0] = B_CMAP8;
226 	si.colorSpaces[1] = B_RGB16;
227 	si.colorSpaceCount = 2;
228 
229 	si.bDisableHdwCursor = false;	// allow use of hardware cursor
230 	si.bDisableAccelDraw = false;	// allow use of accelerated drawing functions
231 
232 	// Setup the mode list.
233 
234 	return CreateModeList(IsModeUsable, Virge_GetEdidInfo);
235 }
236 
237 
238 void
239 Virge_SetFunctionPointers(void)
240 {
241 	// Setting the function pointers must be done prior to first ModeInit call
242 	// or any accel activity.
243 
244 	if (S3_VIRGE_GX2_SERIES(gInfo.sharedInfo->chipType)) {
245 		gInfo.WaitQueue = VirgeWaitFifoGX2;
246 	} else {
247 		gInfo.WaitQueue = VirgeWaitFifoMain;
248 	}
249 
250 	gInfo.WaitIdleEmpty = VirgeWaitIdleEmpty;
251 
252 	gInfo.DPMSCapabilities = Virge_DPMSCapabilities;
253 	gInfo.GetDPMSMode = Virge_GetDPMSMode;
254 	gInfo.SetDPMSMode = Virge_SetDPMSMode;
255 
256 	gInfo.LoadCursorImage = Virge_LoadCursorImage;
257 	gInfo.SetCursorPosition = Virge_SetCursorPosition;
258 	gInfo.ShowCursor = Virge_ShowCursor;
259 
260 	gInfo.FillRectangle = Virge_FillRectangle;
261 	gInfo.FillSpan = Virge_FillSpan;
262 	gInfo.InvertRectangle = Virge_InvertRectangle;
263 	gInfo.ScreenToScreenBlit = Virge_ScreenToScreenBlit;
264 
265 	gInfo.AdjustFrame = Virge_AdjustFrame;
266 	gInfo.ChipInit = Virge_Init;
267 	gInfo.GetColorSpaceParams = Virge_GetColorSpaceParams;
268 	gInfo.SetDisplayMode = Virge_SetDisplayMode;
269 	gInfo.SetIndexedColors = Virge_SetIndexedColors;
270 }
271