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