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 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 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 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 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 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 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