atidsp.c revision 32b578d3
132b578d3Smrg/* 232b578d3Smrg * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org 332b578d3Smrg * 432b578d3Smrg * Permission to use, copy, modify, distribute, and sell this software and its 532b578d3Smrg * documentation for any purpose is hereby granted without fee, provided that 632b578d3Smrg * the above copyright notice appear in all copies and that both that copyright 732b578d3Smrg * notice and this permission notice appear in supporting documentation, and 832b578d3Smrg * that the name of Marc Aurele La France not be used in advertising or 932b578d3Smrg * publicity pertaining to distribution of the software without specific, 1032b578d3Smrg * written prior permission. Marc Aurele La France makes no representations 1132b578d3Smrg * about the suitability of this software for any purpose. It is provided 1232b578d3Smrg * "as-is" without express or implied warranty. 1332b578d3Smrg * 1432b578d3Smrg * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1532b578d3Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 1632b578d3Smrg * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1732b578d3Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1832b578d3Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1932b578d3Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2032b578d3Smrg * PERFORMANCE OF THIS SOFTWARE. 2132b578d3Smrg */ 2232b578d3Smrg 2332b578d3Smrg#ifdef HAVE_CONFIG_H 2432b578d3Smrg#include "config.h" 2532b578d3Smrg#endif 2632b578d3Smrg#include "ati.h" 2732b578d3Smrg#include "atichip.h" 2832b578d3Smrg#include "atidsp.h" 2932b578d3Smrg#include "atimach64io.h" 3032b578d3Smrg#include "atividmem.h" 3132b578d3Smrg 3232b578d3Smrg/* 3332b578d3Smrg * ATIDSPPreInit -- 3432b578d3Smrg * 3532b578d3Smrg * This function initialises global variables used to set DSP registers on a 3632b578d3Smrg * VT-B or later. 3732b578d3Smrg */ 3832b578d3SmrgBool 3932b578d3SmrgATIDSPPreInit 4032b578d3Smrg( 4132b578d3Smrg int iScreen, 4232b578d3Smrg ATIPtr pATI 4332b578d3Smrg) 4432b578d3Smrg{ 4532b578d3Smrg CARD32 IOValue, dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off; 4632b578d3Smrg int trp; 4732b578d3Smrg 4832b578d3Smrg /* 4932b578d3Smrg * VT-B's and later have additional post-dividers that are not powers of 5032b578d3Smrg * two. 5132b578d3Smrg */ 5232b578d3Smrg pATI->ClockDescriptor.NumD = 8; 5332b578d3Smrg 5432b578d3Smrg /* Retrieve XCLK settings */ 5532b578d3Smrg IOValue = ATIMach64GetPLLReg(PLL_XCLK_CNTL); 5632b578d3Smrg pATI->XCLKPostDivider = GetBits(IOValue, PLL_XCLK_SRC_SEL); 5732b578d3Smrg pATI->XCLKReferenceDivider = 1; 5832b578d3Smrg switch (pATI->XCLKPostDivider) 5932b578d3Smrg { 6032b578d3Smrg case 0: case 1: case 2: case 3: 6132b578d3Smrg break; 6232b578d3Smrg 6332b578d3Smrg case 4: 6432b578d3Smrg pATI->XCLKReferenceDivider = 3; 6532b578d3Smrg pATI->XCLKPostDivider = 0; 6632b578d3Smrg break; 6732b578d3Smrg 6832b578d3Smrg default: 6932b578d3Smrg xf86DrvMsg(iScreen, X_ERROR, 7032b578d3Smrg "Unsupported XCLK source: %d.\n", pATI->XCLKPostDivider); 7132b578d3Smrg return FALSE; 7232b578d3Smrg } 7332b578d3Smrg 7432b578d3Smrg pATI->XCLKPostDivider -= GetBits(IOValue, PLL_MFB_TIMES_4_2B); 7532b578d3Smrg pATI->XCLKFeedbackDivider = ATIMach64GetPLLReg(PLL_MCLK_FB_DIV); 7632b578d3Smrg 7732b578d3Smrg xf86DrvMsgVerb(iScreen, X_INFO, 2, 7832b578d3Smrg "Engine XCLK %.3f MHz; Refresh rate code %ld.\n", 7932b578d3Smrg ATIDivide(pATI->XCLKFeedbackDivider * pATI->ReferenceNumerator, 8032b578d3Smrg pATI->XCLKReferenceDivider * pATI->ClockDescriptor.MaxM * 8132b578d3Smrg pATI->ReferenceDenominator, 1 - pATI->XCLKPostDivider, 0) / 8232b578d3Smrg (double)1000.0, 8332b578d3Smrg GetBits(pATI->LockData.mem_cntl, CTL_MEM_REFRESH_RATE_B)); 8432b578d3Smrg 8532b578d3Smrg /* Compute maximum RAS delay and friends */ 8632b578d3Smrg trp = GetBits(pATI->LockData.mem_cntl, CTL_MEM_TRP); 8732b578d3Smrg pATI->XCLKPageFaultDelay = GetBits(pATI->LockData.mem_cntl, CTL_MEM_TRCD) + 8832b578d3Smrg GetBits(pATI->LockData.mem_cntl, CTL_MEM_TCRD) + trp + 2; 8932b578d3Smrg pATI->XCLKMaxRASDelay = GetBits(pATI->LockData.mem_cntl, CTL_MEM_TRAS) + 9032b578d3Smrg trp + 2; 9132b578d3Smrg pATI->DisplayFIFODepth = 32; 9232b578d3Smrg 9332b578d3Smrg if (pATI->Chip < ATI_CHIP_264VT4) 9432b578d3Smrg { 9532b578d3Smrg pATI->XCLKPageFaultDelay += 2; 9632b578d3Smrg pATI->XCLKMaxRASDelay += 3; 9732b578d3Smrg pATI->DisplayFIFODepth = 24; 9832b578d3Smrg } 9932b578d3Smrg 10032b578d3Smrg switch (pATI->MemoryType) 10132b578d3Smrg { 10232b578d3Smrg case MEM_264_DRAM: 10332b578d3Smrg if (pATI->VideoRAM <= 1024) 10432b578d3Smrg { 10532b578d3Smrg pATI->DisplayLoopLatency = 10; 10632b578d3Smrg } 10732b578d3Smrg else 10832b578d3Smrg { 10932b578d3Smrg pATI->DisplayLoopLatency = 8; 11032b578d3Smrg pATI->XCLKPageFaultDelay += 2; 11132b578d3Smrg } 11232b578d3Smrg break; 11332b578d3Smrg 11432b578d3Smrg case MEM_264_EDO: 11532b578d3Smrg case MEM_264_PSEUDO_EDO: 11632b578d3Smrg if (pATI->VideoRAM <= 1024) 11732b578d3Smrg { 11832b578d3Smrg pATI->DisplayLoopLatency = 9; 11932b578d3Smrg } 12032b578d3Smrg else 12132b578d3Smrg { 12232b578d3Smrg pATI->DisplayLoopLatency = 8; 12332b578d3Smrg pATI->XCLKPageFaultDelay++; 12432b578d3Smrg } 12532b578d3Smrg break; 12632b578d3Smrg 12732b578d3Smrg case MEM_264_SDRAM: 12832b578d3Smrg if (pATI->VideoRAM <= 1024) 12932b578d3Smrg { 13032b578d3Smrg pATI->DisplayLoopLatency = 11; 13132b578d3Smrg } 13232b578d3Smrg else 13332b578d3Smrg { 13432b578d3Smrg pATI->DisplayLoopLatency = 10; 13532b578d3Smrg pATI->XCLKPageFaultDelay++; 13632b578d3Smrg } 13732b578d3Smrg break; 13832b578d3Smrg 13932b578d3Smrg case MEM_264_SGRAM: 14032b578d3Smrg pATI->DisplayLoopLatency = 8; 14132b578d3Smrg pATI->XCLKPageFaultDelay += 3; 14232b578d3Smrg break; 14332b578d3Smrg 14432b578d3Smrg default: /* Set maximums */ 14532b578d3Smrg pATI->DisplayLoopLatency = 11; 14632b578d3Smrg pATI->XCLKPageFaultDelay += 3; 14732b578d3Smrg break; 14832b578d3Smrg } 14932b578d3Smrg 15032b578d3Smrg if (pATI->XCLKMaxRASDelay <= pATI->XCLKPageFaultDelay) 15132b578d3Smrg pATI->XCLKMaxRASDelay = pATI->XCLKPageFaultDelay + 1; 15232b578d3Smrg 15332b578d3Smrg /* Allow BIOS to override */ 15432b578d3Smrg dsp_config = inr(DSP_CONFIG); 15532b578d3Smrg dsp_on_off = inr(DSP_ON_OFF); 15632b578d3Smrg vga_dsp_config = inr(VGA_DSP_CONFIG); 15732b578d3Smrg vga_dsp_on_off = inr(VGA_DSP_ON_OFF); 15832b578d3Smrg 15932b578d3Smrg if (dsp_config) 16032b578d3Smrg pATI->DisplayLoopLatency = GetBits(dsp_config, DSP_LOOP_LATENCY); 16132b578d3Smrg 16232b578d3Smrg if ((!dsp_on_off && (pATI->Chip < ATI_CHIP_264GTPRO)) || 16332b578d3Smrg ((dsp_on_off == vga_dsp_on_off) && 16432b578d3Smrg (!dsp_config || !((dsp_config ^ vga_dsp_config) & DSP_XCLKS_PER_QW)))) 16532b578d3Smrg { 16632b578d3Smrg if (ATIDivide(GetBits(vga_dsp_on_off, VGA_DSP_OFF), 16732b578d3Smrg GetBits(vga_dsp_config, VGA_DSP_XCLKS_PER_QW), 5, 1) > 24) 16832b578d3Smrg pATI->DisplayFIFODepth = 32; 16932b578d3Smrg else 17032b578d3Smrg pATI->DisplayFIFODepth = 24; 17132b578d3Smrg } 17232b578d3Smrg 17332b578d3Smrg return TRUE; 17432b578d3Smrg} 17532b578d3Smrg 17632b578d3Smrg/* 17732b578d3Smrg * ATIDSPSave -- 17832b578d3Smrg * 17932b578d3Smrg * This function is called to remember DSP register values on VT-B and later 18032b578d3Smrg * controllers. 18132b578d3Smrg */ 18232b578d3Smrgvoid 18332b578d3SmrgATIDSPSave 18432b578d3Smrg( 18532b578d3Smrg ATIPtr pATI, 18632b578d3Smrg ATIHWPtr pATIHW 18732b578d3Smrg) 18832b578d3Smrg{ 18932b578d3Smrg pATIHW->dsp_on_off = inr(DSP_ON_OFF); 19032b578d3Smrg pATIHW->dsp_config = inr(DSP_CONFIG); 19132b578d3Smrg} 19232b578d3Smrg 19332b578d3Smrg 19432b578d3Smrg/* 19532b578d3Smrg * ATIDSPCalculate -- 19632b578d3Smrg * 19732b578d3Smrg * This function sets up DSP register values for a VTB or later. Note that 19832b578d3Smrg * this would be slightly different if VCLK 0 or 1 were used for the mode 19932b578d3Smrg * instead. In that case, this function would set VGA_DSP_CONFIG and 20032b578d3Smrg * VGA_DSP_ON_OFF, would have to zero out DSP_CONFIG and DSP_ON_OFF, and would 20132b578d3Smrg * have to consider that VGA_DSP_CONFIG is partitioned slightly differently 20232b578d3Smrg * than DSP_CONFIG. 20332b578d3Smrg */ 20432b578d3Smrgvoid 20532b578d3SmrgATIDSPCalculate 20632b578d3Smrg( 20732b578d3Smrg ATIPtr pATI, 20832b578d3Smrg ATIHWPtr pATIHW, 20932b578d3Smrg DisplayModePtr pMode 21032b578d3Smrg) 21132b578d3Smrg{ 21232b578d3Smrg int Multiplier, Divider; 21332b578d3Smrg int RASMultiplier = pATI->XCLKMaxRASDelay, RASDivider = 1; 21432b578d3Smrg int dsp_precision, dsp_on, dsp_off, dsp_xclks; 21532b578d3Smrg int tmp, vshift, xshift; 21632b578d3Smrg 21732b578d3Smrg# define Maximum_DSP_PRECISION ((int)MaxBits(DSP_PRECISION)) 21832b578d3Smrg 21932b578d3Smrg /* Compute a memory-to-screen bandwidth ratio */ 22032b578d3Smrg Multiplier = pATI->XCLKFeedbackDivider * 22132b578d3Smrg pATI->ClockDescriptor.PostDividers[pATIHW->PostDivider]; 22232b578d3Smrg Divider = pATIHW->FeedbackDivider * pATI->XCLKReferenceDivider; 22332b578d3Smrg 22432b578d3Smrg { 22532b578d3Smrg Divider *= pATI->bitsPerPixel / 4; 22632b578d3Smrg } 22732b578d3Smrg 22832b578d3Smrg /* Start by assuming a display FIFO width of 64 bits */ 22932b578d3Smrg vshift = (6 - 2) - pATI->XCLKPostDivider; 23032b578d3Smrg 23132b578d3Smrg if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0)) 23232b578d3Smrg { 23332b578d3Smrg /* Compensate for horizontal stretching */ 23432b578d3Smrg Multiplier *= pATI->LCDHorizontal; 23532b578d3Smrg Divider *= pMode->HDisplay & ~7; 23632b578d3Smrg 23732b578d3Smrg RASMultiplier *= pATI->LCDHorizontal; 23832b578d3Smrg RASDivider *= pMode->HDisplay & ~7; 23932b578d3Smrg } 24032b578d3Smrg 24132b578d3Smrg /* Determine dsp_precision first */ 24232b578d3Smrg tmp = ATIDivide(Multiplier * pATI->DisplayFIFODepth, Divider, vshift, -1); 24332b578d3Smrg for (dsp_precision = -5; tmp; dsp_precision++) 24432b578d3Smrg tmp >>= 1; 24532b578d3Smrg if (dsp_precision < 0) 24632b578d3Smrg dsp_precision = 0; 24732b578d3Smrg else if (dsp_precision > Maximum_DSP_PRECISION) 24832b578d3Smrg dsp_precision = Maximum_DSP_PRECISION; 24932b578d3Smrg 25032b578d3Smrg xshift = 6 - dsp_precision; 25132b578d3Smrg vshift += xshift; 25232b578d3Smrg 25332b578d3Smrg /* Move on to dsp_off */ 25432b578d3Smrg dsp_off = ATIDivide(Multiplier * (pATI->DisplayFIFODepth - 1), Divider, 25532b578d3Smrg vshift, -1) - ATIDivide(1, 1, vshift - xshift, 1); 25632b578d3Smrg 25732b578d3Smrg /* Next is dsp_on */ 25832b578d3Smrg { 25932b578d3Smrg dsp_on = ATIDivide(Multiplier, Divider, vshift, 1); 26032b578d3Smrg tmp = ATIDivide(RASMultiplier, RASDivider, xshift, 1); 26132b578d3Smrg if (dsp_on < tmp) 26232b578d3Smrg dsp_on = tmp; 26332b578d3Smrg dsp_on += (tmp * 2) + 26432b578d3Smrg ATIDivide(pATI->XCLKPageFaultDelay, 1, xshift, 1); 26532b578d3Smrg } 26632b578d3Smrg 26732b578d3Smrg /* Calculate rounding factor and apply it to dsp_on */ 26832b578d3Smrg tmp = ((1 << (Maximum_DSP_PRECISION - dsp_precision)) - 1) >> 1; 26932b578d3Smrg dsp_on = ((dsp_on + tmp) / (tmp + 1)) * (tmp + 1); 27032b578d3Smrg 27132b578d3Smrg if (dsp_on >= ((dsp_off / (tmp + 1)) * (tmp + 1))) 27232b578d3Smrg { 27332b578d3Smrg dsp_on = dsp_off - ATIDivide(Multiplier, Divider, vshift, -1); 27432b578d3Smrg dsp_on = (dsp_on / (tmp + 1)) * (tmp + 1); 27532b578d3Smrg } 27632b578d3Smrg 27732b578d3Smrg /* Last but not least: dsp_xclks */ 27832b578d3Smrg dsp_xclks = ATIDivide(Multiplier, Divider, vshift + 5, 1); 27932b578d3Smrg 28032b578d3Smrg /* Build DSP register contents */ 28132b578d3Smrg pATIHW->dsp_on_off = SetBits(dsp_on, DSP_ON) | 28232b578d3Smrg SetBits(dsp_off, DSP_OFF); 28332b578d3Smrg pATIHW->dsp_config = SetBits(dsp_precision, DSP_PRECISION) | 28432b578d3Smrg SetBits(dsp_xclks, DSP_XCLKS_PER_QW) | 28532b578d3Smrg SetBits(pATI->DisplayLoopLatency, DSP_LOOP_LATENCY); 28632b578d3Smrg} 28732b578d3Smrg 28832b578d3Smrg/* 28932b578d3Smrg * ATIDSPSet -- 29032b578d3Smrg * 29132b578d3Smrg * This function is called to set DSP registers on VT-B and later controllers. 29232b578d3Smrg */ 29332b578d3Smrgvoid 29432b578d3SmrgATIDSPSet 29532b578d3Smrg( 29632b578d3Smrg ATIPtr pATI, 29732b578d3Smrg ATIHWPtr pATIHW 29832b578d3Smrg) 29932b578d3Smrg{ 30032b578d3Smrg outr(DSP_ON_OFF, pATIHW->dsp_on_off); 30132b578d3Smrg outr(DSP_CONFIG, pATIHW->dsp_config); 30232b578d3Smrg} 303