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
VirgeWaitFifoGX2(uint32 slots)20 VirgeWaitFifoGX2(uint32 slots )
21 {
22 while (((ReadReg32(SUBSYS_STAT_REG) >> 9) & 0x60) < slots) {}
23 }
24
25
26
27 static void
VirgeWaitFifoMain(uint32 slots)28 VirgeWaitFifoMain(uint32 slots )
29 {
30 while (((ReadReg32(SUBSYS_STAT_REG) >> 8) & 0x1f) < slots) {}
31 }
32
33
34 static void
VirgeWaitIdleEmpty()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
Virge_GetColorSpaceParams(int colorSpace,uint32 & bitsPerPixel,uint32 & maxPixelClock)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
Virge_Init(void)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, (uint8)((uint32)(si.videoMemPCI) >> 24));
93 WritePIO_8(CRTC_INDEX, 0x5A);
94 WritePIO_8(CRTC_DATA, (uint8)((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
Virge_SetFunctionPointers(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