1130803Smarcel/* 2130803Smarcel Haiku ATI video driver adapted from the X.org ATI driver. 3130803Smarcel 4130803Smarcel Copyright 1992,1993,1994,1995,1996,1997 by Kevin E. Martin, Chapel Hill, North Carolina. 5130803Smarcel Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org 6130803Smarcel 7130803Smarcel Copyright 2009 Haiku, Inc. All rights reserved. 8130803Smarcel Distributed under the terms of the MIT license. 9130803Smarcel 10130803Smarcel Authors: 11130803Smarcel Gerald Zajac 2009 12130803Smarcel*/ 13130803Smarcel 14130803Smarcel 15130803Smarcel#include "accelerant.h" 16130803Smarcel#include "mach64.h" 17130803Smarcel 18130803Smarcel 19130803Smarcel 20130803Smarcelstatic bool 21130803SmarcelMach64_InitDSPParams() 22130803Smarcel{ 23130803Smarcel // Initialize global variables used to set DSP registers on a VT-B or later. 24130803Smarcel 25130803Smarcel SharedInfo& si = *gInfo.sharedInfo; 26130803Smarcel M64_Params& params = si.m64Params; 27130803Smarcel 28130803Smarcel // Retrieve XCLK settings. 29130803Smarcel 30130803Smarcel uint8 ioValue = Mach64_GetPLLReg(PLL_XCLK_CNTL); 31130803Smarcel params.xClkPostDivider = ioValue & 0x7; 32130803Smarcel 33130803Smarcel switch (params.xClkPostDivider) { 34130803Smarcel case 0: 35130803Smarcel case 1: 36130803Smarcel case 2: 37130803Smarcel case 3: 38130803Smarcel params.xClkRefDivider = 1; 39130803Smarcel break; 40130803Smarcel 41130803Smarcel case 4: 42130803Smarcel params.xClkRefDivider = 3; 43130803Smarcel params.xClkPostDivider = 0; 44130803Smarcel break; 45130803Smarcel 46130803Smarcel default: 47130803Smarcel TRACE("Unsupported XCLK source: %d.\n", params.xClkPostDivider); 48130803Smarcel return false; 49130803Smarcel } 50130803Smarcel 51130803Smarcel if (ioValue & PLL_MFB_TIMES_4_2B) 52130803Smarcel params.xClkPostDivider--; 53130803Smarcel 54130803Smarcel // Compute maximum RAS delay and related params. 55130803Smarcel 56130803Smarcel uint32 memCntl = INREG(MEM_CNTL); 57130803Smarcel int trp = GetBits(memCntl, CTL_MEM_TRP); 58130803Smarcel params.xClkPageFaultDelay = GetBits(memCntl, CTL_MEM_TRCD) + 59130803Smarcel GetBits(memCntl, CTL_MEM_TCRD) + trp + 2; 60130803Smarcel params.xClkMaxRASDelay = GetBits(memCntl, CTL_MEM_TRAS) + trp + 2; 61130803Smarcel 62130803Smarcel params.displayFIFODepth = 32; 63130803Smarcel 64130803Smarcel if (si.chipType < MACH64_264VT4) { 65130803Smarcel params.xClkPageFaultDelay += 2; 66130803Smarcel params.xClkMaxRASDelay += 3; 67130803Smarcel params.displayFIFODepth = 24; 68130803Smarcel } 69130803Smarcel 70130803Smarcel // Determine type of memory used with the chip. 71130803Smarcel 72130803Smarcel int memType = INREG(CONFIG_STAT0) & 0x7; 73130803Smarcel TRACE("Memory type: %d\n", memType); 74130803Smarcel 75130803Smarcel switch (memType) { 76130803Smarcel case MEM_DRAM: 77130803Smarcel if (si.videoMemSize <= 1024 * 1024) { 78130803Smarcel params.displayLoopLatency = 10; 79130803Smarcel } else { 80130803Smarcel params.displayLoopLatency = 8; 81130803Smarcel params.xClkPageFaultDelay += 2; 82130803Smarcel } 83130803Smarcel break; 84130803Smarcel 85130803Smarcel case MEM_EDO: 86130803Smarcel case MEM_PSEUDO_EDO: 87130803Smarcel if (si.videoMemSize <= 1024 * 1024) { 88130803Smarcel params.displayLoopLatency = 9; 89130803Smarcel } else { 90130803Smarcel params.displayLoopLatency = 8; 91130803Smarcel params.xClkPageFaultDelay++; 92130803Smarcel } 93130803Smarcel break; 94130803Smarcel 95130803Smarcel case MEM_SDRAM: 96130803Smarcel if (si.videoMemSize <= 1024 * 1024) { 97130803Smarcel params.displayLoopLatency = 11; 98130803Smarcel } else { 99130803Smarcel params.displayLoopLatency = 10; 100130803Smarcel params.xClkPageFaultDelay++; 101130803Smarcel } 102130803Smarcel break; 103130803Smarcel 104130803Smarcel case MEM_SGRAM: 105130803Smarcel params.displayLoopLatency = 8; 106130803Smarcel params.xClkPageFaultDelay += 3; 107130803Smarcel break; 108130803Smarcel 109130803Smarcel default: /* Set maximums */ 110130803Smarcel params.displayLoopLatency = 11; 111130803Smarcel params.xClkPageFaultDelay += 3; 112130803Smarcel break; 113130803Smarcel } 114130803Smarcel 115130803Smarcel if (params.xClkMaxRASDelay <= params.xClkPageFaultDelay) 116130803Smarcel params.xClkMaxRASDelay = params.xClkPageFaultDelay + 1; 117130803Smarcel 118130803Smarcel uint32 dspConfig = INREG(DSP_CONFIG); 119130803Smarcel if (dspConfig) 120130803Smarcel params.displayLoopLatency = GetBits(dspConfig, DSP_LOOP_LATENCY); 121130803Smarcel 122130803Smarcel return true; 123130803Smarcel} 124130803Smarcel 125130803Smarcel 126130803Smarcelstatic bool 127130803SmarcelMach64_GetColorSpaceParams(int colorSpace, uint8& bitsPerPixel, uint32& maxPixelClock) 128130803Smarcel{ 129130803Smarcel // Get parameters for a color space which is supported by the Mach64 chips. 130130803Smarcel // Argument maxPixelClock is in KHz. 131130803Smarcel // Return true if the color space is supported; else return false. 132130803Smarcel 133130803Smarcel SharedInfo& si = *gInfo.sharedInfo; 134130803Smarcel 135130803Smarcel switch (colorSpace) { 136130803Smarcel case B_RGB32: 137130803Smarcel bitsPerPixel = 32; 138130803Smarcel break; 139130803Smarcel case B_RGB16: 140130803Smarcel bitsPerPixel = 16; 141130803Smarcel break; 142130803Smarcel case B_RGB15: 143130803Smarcel bitsPerPixel = 15; 144130803Smarcel break; 145130803Smarcel case B_CMAP8: 146130803Smarcel bitsPerPixel = 8; 147130803Smarcel break; 148130803Smarcel default: 149130803Smarcel TRACE("Unsupported color space: 0x%X\n", colorSpace); 150130803Smarcel return false; 151130803Smarcel } 152130803Smarcel 153130803Smarcel if (si.chipType >= MACH64_264VTB) { 154130803Smarcel if ((si.chipType >= MACH64_264VT4) && (si.chipType != MACH64_264LTPRO)) 155130803Smarcel maxPixelClock = 230000; 156130803Smarcel else if (si.chipType >= MACH64_264VT3) 157130803Smarcel maxPixelClock = 200000; 158130803Smarcel else 159130803Smarcel maxPixelClock = 170000; 160130803Smarcel } else { 161130803Smarcel if (bitsPerPixel == 8) 162130803Smarcel maxPixelClock = 135000; 163130803Smarcel else 164 maxPixelClock = 80000; 165 } 166 167 return true; 168} 169 170 171 172status_t 173Mach64_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 230static void 231Mach64_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 240static void 241Mach64_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 253void 254Mach64_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