atidsp.c revision 32b578d3
1/* 2 * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of Marc Aurele La France not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. Marc Aurele La France makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as-is" without express or implied warranty. 13 * 14 * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 16 * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include "config.h" 25#endif 26#include "ati.h" 27#include "atichip.h" 28#include "atidsp.h" 29#include "atimach64io.h" 30#include "atividmem.h" 31 32/* 33 * ATIDSPPreInit -- 34 * 35 * This function initialises global variables used to set DSP registers on a 36 * VT-B or later. 37 */ 38Bool 39ATIDSPPreInit 40( 41 int iScreen, 42 ATIPtr pATI 43) 44{ 45 CARD32 IOValue, dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off; 46 int trp; 47 48 /* 49 * VT-B's and later have additional post-dividers that are not powers of 50 * two. 51 */ 52 pATI->ClockDescriptor.NumD = 8; 53 54 /* Retrieve XCLK settings */ 55 IOValue = ATIMach64GetPLLReg(PLL_XCLK_CNTL); 56 pATI->XCLKPostDivider = GetBits(IOValue, PLL_XCLK_SRC_SEL); 57 pATI->XCLKReferenceDivider = 1; 58 switch (pATI->XCLKPostDivider) 59 { 60 case 0: case 1: case 2: case 3: 61 break; 62 63 case 4: 64 pATI->XCLKReferenceDivider = 3; 65 pATI->XCLKPostDivider = 0; 66 break; 67 68 default: 69 xf86DrvMsg(iScreen, X_ERROR, 70 "Unsupported XCLK source: %d.\n", pATI->XCLKPostDivider); 71 return FALSE; 72 } 73 74 pATI->XCLKPostDivider -= GetBits(IOValue, PLL_MFB_TIMES_4_2B); 75 pATI->XCLKFeedbackDivider = ATIMach64GetPLLReg(PLL_MCLK_FB_DIV); 76 77 xf86DrvMsgVerb(iScreen, X_INFO, 2, 78 "Engine XCLK %.3f MHz; Refresh rate code %ld.\n", 79 ATIDivide(pATI->XCLKFeedbackDivider * pATI->ReferenceNumerator, 80 pATI->XCLKReferenceDivider * pATI->ClockDescriptor.MaxM * 81 pATI->ReferenceDenominator, 1 - pATI->XCLKPostDivider, 0) / 82 (double)1000.0, 83 GetBits(pATI->LockData.mem_cntl, CTL_MEM_REFRESH_RATE_B)); 84 85 /* Compute maximum RAS delay and friends */ 86 trp = GetBits(pATI->LockData.mem_cntl, CTL_MEM_TRP); 87 pATI->XCLKPageFaultDelay = GetBits(pATI->LockData.mem_cntl, CTL_MEM_TRCD) + 88 GetBits(pATI->LockData.mem_cntl, CTL_MEM_TCRD) + trp + 2; 89 pATI->XCLKMaxRASDelay = GetBits(pATI->LockData.mem_cntl, CTL_MEM_TRAS) + 90 trp + 2; 91 pATI->DisplayFIFODepth = 32; 92 93 if (pATI->Chip < ATI_CHIP_264VT4) 94 { 95 pATI->XCLKPageFaultDelay += 2; 96 pATI->XCLKMaxRASDelay += 3; 97 pATI->DisplayFIFODepth = 24; 98 } 99 100 switch (pATI->MemoryType) 101 { 102 case MEM_264_DRAM: 103 if (pATI->VideoRAM <= 1024) 104 { 105 pATI->DisplayLoopLatency = 10; 106 } 107 else 108 { 109 pATI->DisplayLoopLatency = 8; 110 pATI->XCLKPageFaultDelay += 2; 111 } 112 break; 113 114 case MEM_264_EDO: 115 case MEM_264_PSEUDO_EDO: 116 if (pATI->VideoRAM <= 1024) 117 { 118 pATI->DisplayLoopLatency = 9; 119 } 120 else 121 { 122 pATI->DisplayLoopLatency = 8; 123 pATI->XCLKPageFaultDelay++; 124 } 125 break; 126 127 case MEM_264_SDRAM: 128 if (pATI->VideoRAM <= 1024) 129 { 130 pATI->DisplayLoopLatency = 11; 131 } 132 else 133 { 134 pATI->DisplayLoopLatency = 10; 135 pATI->XCLKPageFaultDelay++; 136 } 137 break; 138 139 case MEM_264_SGRAM: 140 pATI->DisplayLoopLatency = 8; 141 pATI->XCLKPageFaultDelay += 3; 142 break; 143 144 default: /* Set maximums */ 145 pATI->DisplayLoopLatency = 11; 146 pATI->XCLKPageFaultDelay += 3; 147 break; 148 } 149 150 if (pATI->XCLKMaxRASDelay <= pATI->XCLKPageFaultDelay) 151 pATI->XCLKMaxRASDelay = pATI->XCLKPageFaultDelay + 1; 152 153 /* Allow BIOS to override */ 154 dsp_config = inr(DSP_CONFIG); 155 dsp_on_off = inr(DSP_ON_OFF); 156 vga_dsp_config = inr(VGA_DSP_CONFIG); 157 vga_dsp_on_off = inr(VGA_DSP_ON_OFF); 158 159 if (dsp_config) 160 pATI->DisplayLoopLatency = GetBits(dsp_config, DSP_LOOP_LATENCY); 161 162 if ((!dsp_on_off && (pATI->Chip < ATI_CHIP_264GTPRO)) || 163 ((dsp_on_off == vga_dsp_on_off) && 164 (!dsp_config || !((dsp_config ^ vga_dsp_config) & DSP_XCLKS_PER_QW)))) 165 { 166 if (ATIDivide(GetBits(vga_dsp_on_off, VGA_DSP_OFF), 167 GetBits(vga_dsp_config, VGA_DSP_XCLKS_PER_QW), 5, 1) > 24) 168 pATI->DisplayFIFODepth = 32; 169 else 170 pATI->DisplayFIFODepth = 24; 171 } 172 173 return TRUE; 174} 175 176/* 177 * ATIDSPSave -- 178 * 179 * This function is called to remember DSP register values on VT-B and later 180 * controllers. 181 */ 182void 183ATIDSPSave 184( 185 ATIPtr pATI, 186 ATIHWPtr pATIHW 187) 188{ 189 pATIHW->dsp_on_off = inr(DSP_ON_OFF); 190 pATIHW->dsp_config = inr(DSP_CONFIG); 191} 192 193 194/* 195 * ATIDSPCalculate -- 196 * 197 * This function sets up DSP register values for a VTB or later. Note that 198 * this would be slightly different if VCLK 0 or 1 were used for the mode 199 * instead. In that case, this function would set VGA_DSP_CONFIG and 200 * VGA_DSP_ON_OFF, would have to zero out DSP_CONFIG and DSP_ON_OFF, and would 201 * have to consider that VGA_DSP_CONFIG is partitioned slightly differently 202 * than DSP_CONFIG. 203 */ 204void 205ATIDSPCalculate 206( 207 ATIPtr pATI, 208 ATIHWPtr pATIHW, 209 DisplayModePtr pMode 210) 211{ 212 int Multiplier, Divider; 213 int RASMultiplier = pATI->XCLKMaxRASDelay, RASDivider = 1; 214 int dsp_precision, dsp_on, dsp_off, dsp_xclks; 215 int tmp, vshift, xshift; 216 217# define Maximum_DSP_PRECISION ((int)MaxBits(DSP_PRECISION)) 218 219 /* Compute a memory-to-screen bandwidth ratio */ 220 Multiplier = pATI->XCLKFeedbackDivider * 221 pATI->ClockDescriptor.PostDividers[pATIHW->PostDivider]; 222 Divider = pATIHW->FeedbackDivider * pATI->XCLKReferenceDivider; 223 224 { 225 Divider *= pATI->bitsPerPixel / 4; 226 } 227 228 /* Start by assuming a display FIFO width of 64 bits */ 229 vshift = (6 - 2) - pATI->XCLKPostDivider; 230 231 if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0)) 232 { 233 /* Compensate for horizontal stretching */ 234 Multiplier *= pATI->LCDHorizontal; 235 Divider *= pMode->HDisplay & ~7; 236 237 RASMultiplier *= pATI->LCDHorizontal; 238 RASDivider *= pMode->HDisplay & ~7; 239 } 240 241 /* Determine dsp_precision first */ 242 tmp = ATIDivide(Multiplier * pATI->DisplayFIFODepth, Divider, vshift, -1); 243 for (dsp_precision = -5; tmp; dsp_precision++) 244 tmp >>= 1; 245 if (dsp_precision < 0) 246 dsp_precision = 0; 247 else if (dsp_precision > Maximum_DSP_PRECISION) 248 dsp_precision = Maximum_DSP_PRECISION; 249 250 xshift = 6 - dsp_precision; 251 vshift += xshift; 252 253 /* Move on to dsp_off */ 254 dsp_off = ATIDivide(Multiplier * (pATI->DisplayFIFODepth - 1), Divider, 255 vshift, -1) - ATIDivide(1, 1, vshift - xshift, 1); 256 257 /* Next is dsp_on */ 258 { 259 dsp_on = ATIDivide(Multiplier, Divider, vshift, 1); 260 tmp = ATIDivide(RASMultiplier, RASDivider, xshift, 1); 261 if (dsp_on < tmp) 262 dsp_on = tmp; 263 dsp_on += (tmp * 2) + 264 ATIDivide(pATI->XCLKPageFaultDelay, 1, xshift, 1); 265 } 266 267 /* Calculate rounding factor and apply it to dsp_on */ 268 tmp = ((1 << (Maximum_DSP_PRECISION - dsp_precision)) - 1) >> 1; 269 dsp_on = ((dsp_on + tmp) / (tmp + 1)) * (tmp + 1); 270 271 if (dsp_on >= ((dsp_off / (tmp + 1)) * (tmp + 1))) 272 { 273 dsp_on = dsp_off - ATIDivide(Multiplier, Divider, vshift, -1); 274 dsp_on = (dsp_on / (tmp + 1)) * (tmp + 1); 275 } 276 277 /* Last but not least: dsp_xclks */ 278 dsp_xclks = ATIDivide(Multiplier, Divider, vshift + 5, 1); 279 280 /* Build DSP register contents */ 281 pATIHW->dsp_on_off = SetBits(dsp_on, DSP_ON) | 282 SetBits(dsp_off, DSP_OFF); 283 pATIHW->dsp_config = SetBits(dsp_precision, DSP_PRECISION) | 284 SetBits(dsp_xclks, DSP_XCLKS_PER_QW) | 285 SetBits(pATI->DisplayLoopLatency, DSP_LOOP_LATENCY); 286} 287 288/* 289 * ATIDSPSet -- 290 * 291 * This function is called to set DSP registers on VT-B and later controllers. 292 */ 293void 294ATIDSPSet 295( 296 ATIPtr pATI, 297 ATIHWPtr pATIHW 298) 299{ 300 outr(DSP_ON_OFF, pATIHW->dsp_on_off); 301 outr(DSP_CONFIG, pATIHW->dsp_config); 302} 303