1 /* 2 Haiku ATI video driver adapted from the X.org ATI driver. 3 4 Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, 5 Precision Insight, Inc., Cedar Park, Texas, and 6 VA Linux Systems Inc., Fremont, California. 7 8 Copyright 2009 Haiku, Inc. All rights reserved. 9 Distributed under the terms of the MIT license. 10 11 Authors: 12 Gerald Zajac 2009 13 */ 14 15 16 #include "accelerant.h" 17 #include "rage128.h" 18 19 20 21 // Memory Specifications from RAGE 128 Software Development Manual 22 // (Technical Reference Manual P/N SDK-G04000 Rev 0.01), page 3-21. 23 static R128_RAMSpec sRAMSpecs[] = { 24 { 4, 4, 3, 3, 1, 3, 1, 16, 12, "128-bit SDR SGRAM 1:1" }, 25 { 4, 8, 3, 3, 1, 3, 1, 17, 13, "64-bit SDR SGRAM 1:1" }, 26 { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SGRAM 2:1" }, 27 { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SGRAM" }, 28 }; 29 30 31 32 static bool 33 Rage128_GetColorSpaceParams(int colorSpace, uint8& bitsPerPixel, uint32& maxPixelClock) 34 { 35 // Get parameters for a color space which is supported by the Rage128 chips. 36 // Argument maxPixelClock is in KHz. 37 // Return true if the color space is supported; else return false. 38 39 switch (colorSpace) { 40 case B_RGB32: 41 bitsPerPixel = 32; 42 break; 43 case B_RGB16: 44 bitsPerPixel = 16; 45 break; 46 case B_RGB15: 47 bitsPerPixel = 15; 48 break; 49 case B_CMAP8: 50 bitsPerPixel = 8; 51 break; 52 default: 53 TRACE("Unsupported color space: 0x%X\n", colorSpace); 54 return false; 55 } 56 57 maxPixelClock = gInfo.sharedInfo->r128PLLParams.max_pll_freq * 10; 58 return true; 59 } 60 61 62 static void 63 WaitForFifo(uint32 entries) 64 { 65 // The FIFO has 64 slots. This routines waits until at least `entries' 66 // of these slots are empty. 67 68 while (true) { 69 for (int i = 0; i < R128_TIMEOUT; i++) { 70 uint32 slots = INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK; 71 if (slots >= entries) 72 return; 73 } 74 75 TRACE("FIFO timed out: %d entries, stat=0x%08x, probe=0x%08x\n", 76 INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK, 77 INREG(R128_GUI_STAT), 78 INREG(R128_GUI_PROBE)); 79 TRACE("FIFO timed out, resetting engine...\n"); 80 81 Rage128_EngineReset(); 82 } 83 } 84 85 86 static void 87 WaitForIdle() 88 { 89 // Wait for the graphics engine to be completely idle. That is, the FIFO 90 // has drained, the Pixel Cache is flushed, and the engine is idle. This 91 // is a standard "sync" function that will make the hardware "quiescent". 92 93 WaitForFifo(64); 94 95 while (true) { 96 for (uint32 i = 0; i < R128_TIMEOUT; i++) { 97 if ( ! (INREG(R128_GUI_STAT) & R128_GUI_ACTIVE)) { 98 Rage128_EngineFlush(); 99 return ; 100 } 101 } 102 103 TRACE("Idle timed out: %d entries, stat=0x%08x, probe=0x%08x\n", 104 INREG(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK, 105 INREG(R128_GUI_STAT), 106 INREG(R128_GUI_PROBE)); 107 TRACE("Idle timed out, resetting engine...\n"); 108 109 Rage128_EngineReset(); 110 } 111 } 112 113 114 status_t 115 Rage128_Init(void) 116 { 117 TRACE("Rage128_Init()\n"); 118 119 SharedInfo& si = *gInfo.sharedInfo; 120 121 si.videoMemSize = INREG(R128_CONFIG_MEMSIZE); 122 123 si.cursorOffset = (si.videoMemSize - CURSOR_BYTES) & ~0xfff; // align to 4k boundary 124 si.frameBufferOffset = 0; 125 si.maxFrameBufferSize = si.cursorOffset - si.frameBufferOffset; 126 127 TRACE("Video Memory size: %d MB frameBufferOffset: 0x%x cursorOffset: 0x%x\n", 128 si.videoMemSize / 1024 / 1024, si.frameBufferOffset, si.cursorOffset); 129 130 // Get the specifications of the memory used by the chip. 131 132 uint32 offset; 133 134 switch (INREG(R128_MEM_CNTL) & 0x3) { 135 case 0: // SDR SGRAM 1:1 136 switch (si.deviceID) { 137 case 0x4C45: // RAGE128 LE: 138 case 0x4C46: // RAGE128 LF: 139 case 0x4D46: // RAGE128 MF: 140 case 0x4D4C: // RAGE128 ML: 141 case 0x5245: // RAGE128 RE: 142 case 0x5246: // RAGE128 RF: 143 case 0x5247: // RAGE128 RG: 144 case 0x5446: // RAGE128 TF: 145 case 0x544C: // RAGE128 TL: 146 case 0x5452: // RAGE128 TR: 147 offset = 0; // 128-bit SDR SGRAM 1:1 148 break; 149 default: 150 offset = 1; // 64-bit SDR SGRAM 1:1 151 break; 152 } 153 break; 154 case 1: 155 offset = 2; // 64-bit SDR SGRAM 2:1 156 break; 157 case 2: 158 offset = 3; // 64-bit DDR SGRAM 159 break; 160 default: 161 offset = 1; // 64-bit SDR SGRAM 1:1 162 break; 163 } 164 si.r128MemSpec = sRAMSpecs[offset]; 165 TRACE("RAM type: %s\n", si.r128MemSpec.name); 166 167 // Determine the type of display. 168 169 si.displayType = MT_VGA; 170 171 if (INREG(R128_FP_PANEL_CNTL) & R128_FP_DIGON) // don't know if this is correct 172 si.displayType = MT_DVI; 173 174 if (si.chipType == RAGE128_MOBILITY && si.panelX > 0 && si.panelY > 0) { 175 if (INREG(R128_LVDS_GEN_CNTL) & R128_LVDS_ON) 176 si.displayType = MT_LAPTOP; // laptop LCD display is on 177 } 178 179 // Set up the array of color spaces supported by the Rage128 chips. 180 181 si.colorSpaces[0] = B_CMAP8; 182 si.colorSpaces[1] = B_RGB15; 183 si.colorSpaces[2] = B_RGB16; 184 si.colorSpaces[3] = B_RGB32; 185 si.colorSpaceCount = 4; 186 187 // Setup the mode list. 188 189 return CreateModeList(IsModeUsable); 190 } 191 192 193 void 194 Rage128_SetFunctionPointers(void) 195 { 196 // Setting the function pointers must be done prior to first ModeInit call 197 // or any accel activity. 198 199 gInfo.WaitForFifo = WaitForFifo; 200 gInfo.WaitForIdle = WaitForIdle; 201 202 gInfo.DPMSCapabilities = Rage128_DPMSCapabilities; 203 gInfo.GetDPMSMode = Rage128_GetDPMSMode; 204 gInfo.SetDPMSMode = Rage128_SetDPMSMode; 205 206 gInfo.LoadCursorImage = Rage128_LoadCursorImage; 207 gInfo.SetCursorPosition = Rage128_SetCursorPosition; 208 gInfo.ShowCursor = Rage128_ShowCursor; 209 210 gInfo.FillRectangle = Rage128_FillRectangle; 211 gInfo.FillSpan = Rage128_FillSpan; 212 gInfo.InvertRectangle = Rage128_InvertRectangle; 213 gInfo.ScreenToScreenBlit = Rage128_ScreenToScreenBlit; 214 215 gInfo.AdjustFrame = Rage128_AdjustFrame; 216 gInfo.ChipInit = Rage128_Init; 217 gInfo.GetColorSpaceParams = Rage128_GetColorSpaceParams; 218 gInfo.SetDisplayMode = Rage128_SetDisplayMode; 219 gInfo.SetIndexedColors = Rage128_SetIndexedColors; 220 } 221 222