1dfe64dd3Smacallan/* 2dfe64dd3Smacallan * DAC helper functions (Save/Restore, MemClk, etc) 3dfe64dd3Smacallan * 4dfe64dd3Smacallan * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria. 5dfe64dd3Smacallan * 6dfe64dd3Smacallan * Redistribution and use in source and binary forms, with or without 7dfe64dd3Smacallan * modification, are permitted provided that the following conditions 8dfe64dd3Smacallan * are met: 9dfe64dd3Smacallan * 1) Redistributions of source code must retain the above copyright 10dfe64dd3Smacallan * notice, this list of conditions and the following disclaimer. 11dfe64dd3Smacallan * 2) Redistributions in binary form must reproduce the above copyright 12dfe64dd3Smacallan * notice, this list of conditions and the following disclaimer in the 13dfe64dd3Smacallan * documentation and/or other materials provided with the distribution. 14dfe64dd3Smacallan * 3) The name of the author may not be used to endorse or promote products 15dfe64dd3Smacallan * derived from this software without specific prior written permission. 16dfe64dd3Smacallan * 17dfe64dd3Smacallan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR 18dfe64dd3Smacallan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19dfe64dd3Smacallan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20dfe64dd3Smacallan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21dfe64dd3Smacallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22dfe64dd3Smacallan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23dfe64dd3Smacallan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24dfe64dd3Smacallan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25dfe64dd3Smacallan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26dfe64dd3Smacallan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27dfe64dd3Smacallan * 28dfe64dd3Smacallan * Author: Thomas Winischhofer <thomas@winischhofer.net> 29dfe64dd3Smacallan * 30dfe64dd3Smacallan * XGI_compute_vclk(), XGICalcClock() and parts of XGIMclk(): 31dfe64dd3Smacallan * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England 32dfe64dd3Smacallan * Written by: 33dfe64dd3Smacallan * Alan Hourihane <alanh@fairlite.demon.co.uk>, 34dfe64dd3Smacallan * Mike Chapman <mike@paranoia.com>, 35dfe64dd3Smacallan * Juanjo Santamarta <santamarta@ctv.es>, 36dfe64dd3Smacallan * Mitani Hiroshi <hmitani@drl.mei.co.jp>, 37dfe64dd3Smacallan * David Thomas <davtom@dream.org.uk>, 38dfe64dd3Smacallan * Thomas Winischhofer <thomas@winischhofer.net>. 39dfe64dd3Smacallan * Licensed under the terms of the XFree86 license 40dfe64dd3Smacallan * (http://www.xfree86.org/current/LICENSE1.html) 41dfe64dd3Smacallan * 42dfe64dd3Smacallan */ 43dfe64dd3Smacallan 44dfe64dd3Smacallan#ifdef HAVE_CONFIG_H 45dfe64dd3Smacallan#include "config.h" 46dfe64dd3Smacallan#endif 47dfe64dd3Smacallan 48dfe64dd3Smacallan#include "xf86.h" 49dfe64dd3Smacallan#include "xf86_OSproc.h" 50dfe64dd3Smacallan#include "xorgVersion.h" 51dfe64dd3Smacallan#include "xf86PciInfo.h" 52dfe64dd3Smacallan#include "xf86Pci.h" 53dfe64dd3Smacallan#include "xf86DDC.h" 54dfe64dd3Smacallan 55dfe64dd3Smacallan#include "xgi.h" 56dfe64dd3Smacallan#include "xgi_dac.h" 57dfe64dd3Smacallan#include "xgi_regs.h" 58dfe64dd3Smacallan#include "xgi_vb.h" 59dfe64dd3Smacallan 60dfe64dd3Smacallanstatic void Volari_Save(ScrnInfoPtr pScrn, XGIRegPtr xgiReg) ; 61dfe64dd3Smacallanstatic void Volari_Restore(ScrnInfoPtr pScrn, XGIRegPtr xgiReg) ; 62dfe64dd3Smacallanstatic void Volari_Threshold(ScrnInfoPtr pScrn, DisplayModePtr mode, 63dfe64dd3Smacallan unsigned short *Low, unsigned short *High); 64dfe64dd3Smacallanint 65dfe64dd3Smacallancompute_vclk( 66dfe64dd3Smacallan int Clock, 67dfe64dd3Smacallan int *out_n, 68dfe64dd3Smacallan int *out_dn, 69dfe64dd3Smacallan int *out_div, 70dfe64dd3Smacallan int *out_sbit, 71dfe64dd3Smacallan int *out_scale) 72dfe64dd3Smacallan{ 73dfe64dd3Smacallan float f,x,y,t, error, min_error; 74dfe64dd3Smacallan int n, dn, best_n=0, best_dn=0; 75dfe64dd3Smacallan 76dfe64dd3Smacallan /* 77dfe64dd3Smacallan * Rules 78dfe64dd3Smacallan * 79dfe64dd3Smacallan * VCLK = 14.318 * (Divider/Post Scalar) * (Numerator/DeNumerator) 80dfe64dd3Smacallan * Factor = (Divider/Post Scalar) 81dfe64dd3Smacallan * Divider is 1 or 2 82dfe64dd3Smacallan * Post Scalar is 1, 2, 3, 4, 6 or 8 83dfe64dd3Smacallan * Numberator ranged from 1 to 128 84dfe64dd3Smacallan * DeNumerator ranged from 1 to 32 85dfe64dd3Smacallan * a. VCO = VCLK/Factor, suggest range is 150 to 250 Mhz 86dfe64dd3Smacallan * b. Post Scalar selected from 1, 2, 4 or 8 first. 87dfe64dd3Smacallan * c. DeNumerator selected from 2. 88dfe64dd3Smacallan * 89dfe64dd3Smacallan * According to rule a and b, the VCO ranges that can be scaled by 90dfe64dd3Smacallan * rule b are: 91dfe64dd3Smacallan * 150 - 250 (Factor = 1) 92dfe64dd3Smacallan * 75 - 125 (Factor = 2) 93dfe64dd3Smacallan * 37.5 - 62.5 (Factor = 4) 94dfe64dd3Smacallan * 18.75 - 31.25 (Factor = 8) 95dfe64dd3Smacallan * 96dfe64dd3Smacallan * The following ranges use Post Scalar 3 or 6: 97dfe64dd3Smacallan * 125 - 150 (Factor = 1.5) 98dfe64dd3Smacallan * 62.5 - 75 (Factor = 3) 99dfe64dd3Smacallan * 31.25 - 37.5 (Factor = 6) 100dfe64dd3Smacallan * 101dfe64dd3Smacallan * Steps: 102dfe64dd3Smacallan * 1. divide the Clock by 2 until the Clock is less or equal to 31.25. 103dfe64dd3Smacallan * 2. if the divided Clock is range from 18.25 to 31.25, than 104dfe64dd3Smacallan * the Factor is 1, 2, 4 or 8. 105dfe64dd3Smacallan * 3. if the divided Clock is range from 15.625 to 18.25, than 106dfe64dd3Smacallan * the Factor is 1.5, 3 or 6. 107dfe64dd3Smacallan * 4. select the Numberator and DeNumberator with minimum deviation. 108dfe64dd3Smacallan * 109dfe64dd3Smacallan * ** this function can select VCLK ranged from 18.75 to 250 Mhz 110dfe64dd3Smacallan */ 111dfe64dd3Smacallan f = (float) Clock; 112dfe64dd3Smacallan f /= 1000.0; 113dfe64dd3Smacallan if ((f > 250.0) || (f < 18.75)) 114dfe64dd3Smacallan return 0; 115dfe64dd3Smacallan 116dfe64dd3Smacallan min_error = f; 117dfe64dd3Smacallan y = 1.0; 118dfe64dd3Smacallan x = f; 119dfe64dd3Smacallan while (x > 31.25) { 120dfe64dd3Smacallan y *= 2.0; 121dfe64dd3Smacallan x /= 2.0; 122dfe64dd3Smacallan } 123dfe64dd3Smacallan if (x >= 18.25) { 124dfe64dd3Smacallan x *= 8.0; 125dfe64dd3Smacallan y = 8.0 / y; 126dfe64dd3Smacallan } else if (x >= 15.625) { 127dfe64dd3Smacallan x *= 12.0; 128dfe64dd3Smacallan y = 12.0 / y; 129dfe64dd3Smacallan } 130dfe64dd3Smacallan 131dfe64dd3Smacallan t = y; 132dfe64dd3Smacallan if (t == (float) 1.5) { 133dfe64dd3Smacallan *out_div = 2; 134dfe64dd3Smacallan t *= 2.0; 135dfe64dd3Smacallan } else { 136dfe64dd3Smacallan *out_div = 1; 137dfe64dd3Smacallan } 138dfe64dd3Smacallan if (t > (float) 4.0) { 139dfe64dd3Smacallan *out_sbit = 1; 140dfe64dd3Smacallan t /= 2.0; 141dfe64dd3Smacallan } else { 142dfe64dd3Smacallan *out_sbit = 0; 143dfe64dd3Smacallan } 144dfe64dd3Smacallan 145dfe64dd3Smacallan *out_scale = (int) t; 146dfe64dd3Smacallan 147dfe64dd3Smacallan for (dn=2;dn<=32;dn++) { 148dfe64dd3Smacallan for (n=1;n<=128;n++) { 149dfe64dd3Smacallan error = x; 150dfe64dd3Smacallan error -= ((float) 14.318 * (float) n / (float) dn); 151dfe64dd3Smacallan if (error < (float) 0) 152dfe64dd3Smacallan error = -error; 153dfe64dd3Smacallan if (error < min_error) { 154dfe64dd3Smacallan min_error = error; 155dfe64dd3Smacallan best_n = n; 156dfe64dd3Smacallan best_dn = dn; 157dfe64dd3Smacallan } 158dfe64dd3Smacallan } 159dfe64dd3Smacallan } 160dfe64dd3Smacallan *out_n = best_n; 161dfe64dd3Smacallan *out_dn = best_dn; 162dfe64dd3Smacallan PDEBUG(ErrorF("compute_vclk: Clock=%d, n=%d, dn=%d, div=%d, sbit=%d," 163dfe64dd3Smacallan " scale=%d\n", Clock, best_n, best_dn, *out_div, 164dfe64dd3Smacallan *out_sbit, *out_scale)); 165dfe64dd3Smacallan return 1; 166dfe64dd3Smacallan} 167dfe64dd3Smacallan 168dfe64dd3Smacallanvoid 169dfe64dd3SmacallanXGICalcClock(ScrnInfoPtr pScrn, int clock, int max_VLD, unsigned int *vclk) 170dfe64dd3Smacallan{ 171dfe64dd3Smacallan/* XGIPtr pXGI = XGIPTR(pScrn); */ 172dfe64dd3Smacallan int M, N, P , PSN, VLD , PSNx ; 173dfe64dd3Smacallan int bestM=0, bestN=0, bestP=0, bestPSN=0, bestVLD=0; 174dfe64dd3Smacallan double abest = 42.0; 175dfe64dd3Smacallan double target; 176dfe64dd3Smacallan double Fvco, Fout; 177dfe64dd3Smacallan double error, aerror; 178dfe64dd3Smacallan#ifdef DEBUG 179dfe64dd3Smacallan double bestFout; 180dfe64dd3Smacallan#endif 181dfe64dd3Smacallan 182dfe64dd3Smacallan /* 183dfe64dd3Smacallan * fd = fref*(Numerator/Denumerator)*(Divider/PostScaler) 184dfe64dd3Smacallan * 185dfe64dd3Smacallan * M = Numerator [1:128] 186dfe64dd3Smacallan * N = DeNumerator [1:32] 187dfe64dd3Smacallan * VLD = Divider (Vco Loop Divider) : divide by 1, 2 188dfe64dd3Smacallan * P = Post Scaler : divide by 1, 2, 3, 4 189dfe64dd3Smacallan * PSN = Pre Scaler (Reference Divisor Select) 190dfe64dd3Smacallan * 191dfe64dd3Smacallan * result in vclk[] 192dfe64dd3Smacallan */ 193dfe64dd3Smacallan#define Midx 0 194dfe64dd3Smacallan#define Nidx 1 195dfe64dd3Smacallan#define VLDidx 2 196dfe64dd3Smacallan#define Pidx 3 197dfe64dd3Smacallan#define PSNidx 4 198dfe64dd3Smacallan#define Fref 14318180 199dfe64dd3Smacallan/* stability constraints for internal VCO -- MAX_VCO also determines 200dfe64dd3Smacallan * the maximum Video pixel clock */ 201dfe64dd3Smacallan#define MIN_VCO Fref 202dfe64dd3Smacallan#define MAX_VCO 135000000 203dfe64dd3Smacallan#define MAX_VCO_5597 353000000 204dfe64dd3Smacallan#define MAX_PSN 0 /* no pre scaler for this chip */ 205dfe64dd3Smacallan#define TOLERANCE 0.01 /* search smallest M and N in this tolerance */ 206dfe64dd3Smacallan 207dfe64dd3Smacallan int M_min = 2; 208dfe64dd3Smacallan int M_max = 128; 209dfe64dd3Smacallan 210dfe64dd3Smacallan target = clock * 1000; 211dfe64dd3Smacallan 212dfe64dd3Smacallan for(PSNx = 0; PSNx <= MAX_PSN ; PSNx++) { 213dfe64dd3Smacallan 214dfe64dd3Smacallan int low_N, high_N; 215dfe64dd3Smacallan double FrefVLDPSN; 216dfe64dd3Smacallan 217dfe64dd3Smacallan PSN = !PSNx ? 1 : 4; 218dfe64dd3Smacallan 219dfe64dd3Smacallan low_N = 2; 220dfe64dd3Smacallan high_N = 32; 221dfe64dd3Smacallan 222dfe64dd3Smacallan for(VLD = 1 ; VLD <= max_VLD ; VLD++) { 223dfe64dd3Smacallan 224dfe64dd3Smacallan FrefVLDPSN = (double)Fref * VLD / PSN; 225dfe64dd3Smacallan 226dfe64dd3Smacallan for(N = low_N; N <= high_N; N++) { 227dfe64dd3Smacallan double tmp = FrefVLDPSN / N; 228dfe64dd3Smacallan 229dfe64dd3Smacallan for(P = 1; P <= 4; P++) { 230dfe64dd3Smacallan double Fvco_desired = target * ( P ); 231dfe64dd3Smacallan double M_desired = Fvco_desired / tmp; 232dfe64dd3Smacallan 233dfe64dd3Smacallan /* Which way will M_desired be rounded? 234dfe64dd3Smacallan * Do all three just to be safe. 235dfe64dd3Smacallan */ 236dfe64dd3Smacallan int M_low = M_desired - 1; 237dfe64dd3Smacallan int M_hi = M_desired + 1; 238dfe64dd3Smacallan 239dfe64dd3Smacallan if(M_hi < M_min || M_low > M_max) continue; 240dfe64dd3Smacallan 241dfe64dd3Smacallan if(M_low < M_min) M_low = M_min; 242dfe64dd3Smacallan 243dfe64dd3Smacallan if(M_hi > M_max) M_hi = M_max; 244dfe64dd3Smacallan 245dfe64dd3Smacallan for(M = M_low; M <= M_hi; M++) { 246dfe64dd3Smacallan Fvco = tmp * M; 247dfe64dd3Smacallan if(Fvco <= MIN_VCO) continue; 248dfe64dd3Smacallan if(Fvco > MAX_VCO) break; 249dfe64dd3Smacallan 250dfe64dd3Smacallan Fout = Fvco / ( P ); 251dfe64dd3Smacallan 252dfe64dd3Smacallan error = (target - Fout) / target; 253dfe64dd3Smacallan aerror = (error < 0) ? -error : error; 254dfe64dd3Smacallan if(aerror < abest) { 255dfe64dd3Smacallan abest = aerror; 256dfe64dd3Smacallan bestM = M; 257dfe64dd3Smacallan bestN = N; 258dfe64dd3Smacallan bestP = P; 259dfe64dd3Smacallan bestPSN = PSN; 260dfe64dd3Smacallan bestVLD = VLD; 261dfe64dd3Smacallan#ifdef DEBUG 262dfe64dd3Smacallan bestFout = Fout; 263dfe64dd3Smacallan#endif 264dfe64dd3Smacallan } 265dfe64dd3Smacallan#ifdef TWDEBUG 266dfe64dd3Smacallan xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,3, 267dfe64dd3Smacallan "Freq. selected: %.2f MHz, M=%d, N=%d, VLD=%d, P=%d, PSN=%d\n", 268dfe64dd3Smacallan (float)(clock / 1000.), M, N, P, VLD, PSN); 269dfe64dd3Smacallan xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,3, 270dfe64dd3Smacallan "Freq. set: %.2f MHz\n", Fout / 1.0e6); 271dfe64dd3Smacallan#endif 272dfe64dd3Smacallan } 273dfe64dd3Smacallan } 274dfe64dd3Smacallan } 275dfe64dd3Smacallan } 276dfe64dd3Smacallan } 277dfe64dd3Smacallan 278dfe64dd3Smacallan vclk[Midx] = bestM; 279dfe64dd3Smacallan vclk[Nidx] = bestN; 280dfe64dd3Smacallan vclk[VLDidx] = bestVLD; 281dfe64dd3Smacallan vclk[Pidx] = bestP; 282dfe64dd3Smacallan vclk[PSNidx] = bestPSN; 283dfe64dd3Smacallan/* 284dfe64dd3Smacallan PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 285dfe64dd3Smacallan "Freq. selected: %.2f MHz, M=%d, N=%d, VLD=%d, P=%d, PSN=%d\n", 286dfe64dd3Smacallan (float)(clock / 1000.), vclk[Midx], vclk[Nidx], vclk[VLDidx], 287dfe64dd3Smacallan vclk[Pidx], vclk[PSNidx])); 288dfe64dd3Smacallan PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 289dfe64dd3Smacallan "Freq. set: %.2f MHz\n", bestFout / 1.0e6)); 290dfe64dd3Smacallan PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 291dfe64dd3Smacallan "VCO Freq.: %.2f MHz\n", bestFout*bestP / 1.0e6)); 292dfe64dd3Smacallan*/ 293dfe64dd3Smacallan 294dfe64dd3Smacallan} 295dfe64dd3Smacallan 296dfe64dd3Smacallanstatic void 297dfe64dd3SmacallanVolari_Save(ScrnInfoPtr pScrn, XGIRegPtr xgiReg) 298dfe64dd3Smacallan{ 299dfe64dd3Smacallan XGIPtr pXGI = XGIPTR(pScrn); 300dfe64dd3Smacallan int vgaIOBase; 301dfe64dd3Smacallan int i; 302dfe64dd3Smacallan 303dfe64dd3Smacallan PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 304dfe64dd3Smacallan "Volari_Save(ScrnInfoPtr pScrn, XGIRegPtr xgiReg)\n")); 305dfe64dd3Smacallan 306dfe64dd3Smacallan vgaHWGetIOBase(VGAHWPTR(pScrn)); 307dfe64dd3Smacallan vgaIOBase = VGAHWPTR(pScrn)->IOBase; 308dfe64dd3Smacallan 309dfe64dd3Smacallan#if !defined(__arm__) 310dfe64dd3Smacallan outw(VGA_SEQ_INDEX, 0x8605); 311dfe64dd3Smacallan#else 312dfe64dd3Smacallan moutl(XGISR, 0x8605); 313dfe64dd3Smacallan#endif 314dfe64dd3Smacallan 315dfe64dd3Smacallan for (i = 0x06; i <= 0x3F; i++) { 316dfe64dd3Smacallan /* outb(VGA_SEQ_INDEX, i); */ 317dfe64dd3Smacallan outb(XGISR, i); 318dfe64dd3Smacallan 319dfe64dd3Smacallan /* xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 320dfe64dd3Smacallan "XR%02X Contents - %02X \n", i, inb(VGA_SEQ_DATA)); 321dfe64dd3Smacallan xgiReg->xgiRegs3C4[i] = inb(VGA_SEQ_DATA); */ 322dfe64dd3Smacallan xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 323dfe64dd3Smacallan "XR%02X Contents - %02X \n", i, inb(XGISR+1)); 324dfe64dd3Smacallan xgiReg->xgiRegs3C4[i] = inb(XGISR+1); 325dfe64dd3Smacallan } 326dfe64dd3Smacallan 327dfe64dd3Smacallan for (i=0x19; i<0x5C; i++) { 328dfe64dd3Smacallan inXGIIDXREG(XGICR, i, xgiReg->xgiRegs3D4[i]); 329dfe64dd3Smacallan } 330dfe64dd3Smacallan 331dfe64dd3Smacallan /*xgiReg->xgiRegs3C2 = inb(0x3CC);*/ 332dfe64dd3Smacallan 333dfe64dd3Smacallan xgiReg->xgiRegs3C2 = inb(pXGI->RelIO+0x4c); 334dfe64dd3Smacallan 335dfe64dd3Smacallan for (i=0x19; i<0x5C; i++) { 336dfe64dd3Smacallan inXGIIDXREG(XGICR, i, xgiReg->xgiRegs3D4[i]); 337dfe64dd3Smacallan } 338dfe64dd3Smacallan 339dfe64dd3Smacallan// yilin save the VB register 340dfe64dd3Smacallan outXGIIDXREG(XGIPART1, 0x2f, 0x01); 341dfe64dd3Smacallan 342dfe64dd3Smacallan for (i=0; i<0x50; i++) 343dfe64dd3Smacallan { 344dfe64dd3Smacallan inXGIIDXREG(XGIPART1, i, xgiReg->VBPart1[i]); 345dfe64dd3Smacallan } 346dfe64dd3Smacallan for (i=0; i<0x50; i++) 347dfe64dd3Smacallan { 348dfe64dd3Smacallan inXGIIDXREG(XGIPART2, i, xgiReg->VBPart2[i]); 349dfe64dd3Smacallan } 350dfe64dd3Smacallan for (i=0; i<0x50; i++) 351dfe64dd3Smacallan { 352dfe64dd3Smacallan inXGIIDXREG(XGIPART3, i, xgiReg->VBPart3[i]); 353dfe64dd3Smacallan } 354dfe64dd3Smacallan for (i=0; i<0x50; i++) 355dfe64dd3Smacallan { 356dfe64dd3Smacallan inXGIIDXREG(XGIPART4, i, xgiReg->VBPart4[i]); 357dfe64dd3Smacallan } 358dfe64dd3Smacallan 359dfe64dd3Smacallan PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 360dfe64dd3Smacallan "Volari_Save(ScrnInfoPtr pScrn, XGIRegPtr xgiReg) Done\n")); 361dfe64dd3Smacallan 362dfe64dd3Smacallan} 363dfe64dd3Smacallan 364dfe64dd3Smacallanstatic void 365dfe64dd3SmacallanVolari_Restore(ScrnInfoPtr pScrn, XGIRegPtr xgiReg) 366dfe64dd3Smacallan{ 367dfe64dd3Smacallan XGIPtr pXGI = XGIPTR(pScrn); 368dfe64dd3Smacallan int vgaIOBase; 369dfe64dd3Smacallan int i; 370dfe64dd3Smacallan 371dfe64dd3Smacallan PDEBUG(ErrorF("--- Volari_Restore(). \n")) ; 372dfe64dd3Smacallan xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 373dfe64dd3Smacallan "Volari_Restore(ScrnInfoPtr pScrn, XGIRegPtr xgiReg)\n"); 374dfe64dd3Smacallan 375dfe64dd3Smacallan vgaHWGetIOBase(VGAHWPTR(pScrn)); 376dfe64dd3Smacallan vgaIOBase = VGAHWPTR(pScrn)->IOBase; 377dfe64dd3Smacallan 378dfe64dd3Smacallan outXGIIDXREG(XGISR, 0x05, 0x86); 379dfe64dd3Smacallan 380dfe64dd3Smacallan 381dfe64dd3Smacallan#if 1 382dfe64dd3Smacallan /* Jong@08112009; recover this line */ 383dfe64dd3Smacallan /* Volari_DisableAccelerator(pScrn) ; */ 384dfe64dd3Smacallan#else 385dfe64dd3Smacallan inXGIIDXREG(XGISR, 0x1E, temp); 386dfe64dd3Smacallan 387dfe64dd3Smacallan if (temp & (SR1E_ENABLE_2D | SR1E_ENABLE_3D)) { 388dfe64dd3Smacallan Volari_Idle(pXGI); 389dfe64dd3Smacallan } 390dfe64dd3Smacallan 391dfe64dd3Smacallan PDEBUG(XGIDumpRegs(pScrn)); 392dfe64dd3Smacallan 393dfe64dd3Smacallan outXGIIDXREG(XGICR, 0x55, 0); 394dfe64dd3Smacallan andXGIIDXREG(XGISR, 0x1E, 395dfe64dd3Smacallan ~(SR1E_ENABLE_3D_TRANSFORM_ENGINE 396dfe64dd3Smacallan | SR1E_ENABLE_2D 397dfe64dd3Smacallan | SR1E_ENABLE_3D)); 398dfe64dd3Smacallan PDEBUG(XGIDumpRegs(pScrn)); 399dfe64dd3Smacallan#endif 400dfe64dd3Smacallan 401dfe64dd3Smacallan PDEBUG(XGIDumpRegs(pScrn)) ; //yilin 402dfe64dd3Smacallan 403dfe64dd3Smacallan for (i = 0x19; i < 0x5C; i++) { 404dfe64dd3Smacallan /* Jong 09/19/2007; added for ??? */ 405dfe64dd3Smacallan if((i!=0x48 && i!=0x4a)|| ((pXGI->Chipset != PCI_CHIP_XGIXG20)&&(pXGI->Chipset != PCI_CHIP_XGIXG21)&&(pXGI->Chipset != PCI_CHIP_XGIXG27))) 406dfe64dd3Smacallan outXGIIDXREG(XGICR, i, xgiReg->xgiRegs3D4[i]); 407dfe64dd3Smacallan } 408dfe64dd3Smacallan 409dfe64dd3Smacallan for (i = 0x06; i <= 0x3F; i++) { 410dfe64dd3Smacallan /* if( !(i==0x16 || i==0x18 || i==0x19 || i==0x28 || i==0x29 || i==0x2E || i==0x2F) ) { */ 411dfe64dd3Smacallan if( !(i==0x16 ) ) { 412dfe64dd3Smacallan /* outb(VGA_SEQ_INDEX,i); */ 413dfe64dd3Smacallan outb(XGISR,i); 414dfe64dd3Smacallan 415dfe64dd3Smacallan /* xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,4, 416dfe64dd3Smacallan "XR%X Contents - %02X ", i, inb(VGA_SEQ_DATA)); 417dfe64dd3Smacallan 418dfe64dd3Smacallan outb(VGA_SEQ_DATA,xgiReg->xgiRegs3C4[i]); 419dfe64dd3Smacallan 420dfe64dd3Smacallan xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,4, 421dfe64dd3Smacallan "Restore to - %02X Read after - %02X\n", 422dfe64dd3Smacallan xgiReg->xgiRegs3C4[i], inb(VGA_SEQ_DATA)); */ 423dfe64dd3Smacallan 424dfe64dd3Smacallan xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,4, 425dfe64dd3Smacallan "XR%X Contents - %02X ", i, inb(XGISR+1)); 426dfe64dd3Smacallan 427dfe64dd3Smacallan outb(XGISR+1,xgiReg->xgiRegs3C4[i]); 428dfe64dd3Smacallan 429dfe64dd3Smacallan xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,4, 430dfe64dd3Smacallan "Restore to - %02X Read after - %02X\n", 431dfe64dd3Smacallan xgiReg->xgiRegs3C4[i], inb(XGISR+1)); 432dfe64dd3Smacallan } 433dfe64dd3Smacallan } 434dfe64dd3Smacallan 435dfe64dd3Smacallan 436dfe64dd3Smacallan#if 0 437dfe64dd3Smacallan // yilin restore the VB register 438dfe64dd3Smacallan outXGIIDXREG(XGIPART1, 0x2f, 0x01); 439dfe64dd3Smacallan for (i=0; i<0x50; i++) 440dfe64dd3Smacallan { 441dfe64dd3Smacallan outXGIIDXREG(XGIPART1, i, xgiReg->VBPart1[i]); 442dfe64dd3Smacallan } 443dfe64dd3Smacallan for (i=0; i<0x50; i++) 444dfe64dd3Smacallan { 445dfe64dd3Smacallan outXGIIDXREG(XGIPART2, i, xgiReg->VBPart2[i]); 446dfe64dd3Smacallan } 447dfe64dd3Smacallan for (i=0; i<0x50; i++) 448dfe64dd3Smacallan { 449dfe64dd3Smacallan outXGIIDXREG(XGIPART3, i, xgiReg->VBPart3[i]); 450dfe64dd3Smacallan } 451dfe64dd3Smacallan for (i=0; i<0x50; i++) 452dfe64dd3Smacallan { 453dfe64dd3Smacallan outXGIIDXREG(XGIPART4, i, xgiReg->VBPart4[i]); 454dfe64dd3Smacallan } 455dfe64dd3Smacallan#endif 456dfe64dd3Smacallan 457dfe64dd3Smacallan outb(pXGI->RelIO+0x42, xgiReg->xgiRegs3C2); 458dfe64dd3Smacallan 459dfe64dd3Smacallan /* MemClock needs this to take effect */ 460dfe64dd3Smacallan 461dfe64dd3Smacallan#if !defined(__arm__) 462dfe64dd3Smacallan outw(VGA_SEQ_INDEX, 0x0100); /* Synchronous Reset */ 463dfe64dd3Smacallan#else 464dfe64dd3Smacallan moutl(XGISR, 0x0100); /* Synchronous Reset */ 465dfe64dd3Smacallan#endif 466dfe64dd3Smacallan 467dfe64dd3Smacallan PDEBUG(XGIDumpRegs(pScrn)) ; //yilin 468dfe64dd3Smacallan xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 469dfe64dd3Smacallan "Volari_Restore(ScrnInfoPtr pScrn, XGIRegPtr xgiReg) Done\n"); 470dfe64dd3Smacallan 471dfe64dd3Smacallan 472dfe64dd3Smacallan} 473dfe64dd3Smacallan 474dfe64dd3Smacallanstatic void 475dfe64dd3SmacallanVolari_Threshold(ScrnInfoPtr pScrn, DisplayModePtr mode, 476dfe64dd3Smacallan unsigned short *Low, unsigned short *High) 477dfe64dd3Smacallan{ 478dfe64dd3Smacallan XGIPtr pXGI = XGIPTR(pScrn); 479dfe64dd3Smacallan 480dfe64dd3Smacallan orXGIIDXREG(XGISR, 0x3D, 0x01); 481dfe64dd3Smacallan} 482dfe64dd3Smacallan 483dfe64dd3Smacallan 484dfe64dd3Smacallan/** 485dfe64dd3Smacallan * Calculate available memory bandwidth for an XG40 series chip. 486dfe64dd3Smacallan * 487dfe64dd3Smacallan * \sa XG40_MemBandWidth 488dfe64dd3Smacallan */ 489dfe64dd3Smacallanstatic int XG40_MemBandWidth(ScrnInfoPtr pScrn) 490dfe64dd3Smacallan{ 491dfe64dd3Smacallan static const float magic315[4] = { 1.2, 1.368421, 2.263158, 1.2 }; 492dfe64dd3Smacallan XGIPtr pXGI = XGIPTR(pScrn); 493dfe64dd3Smacallan const int bus = (pXGI->BusWidth > 128) ? 128 : pXGI->BusWidth; 494dfe64dd3Smacallan const int mclk = pXGI->MemClock; 495dfe64dd3Smacallan const int bpp = pScrn->bitsPerPixel; 496dfe64dd3Smacallan const float magic = magic315[bus / 64]; 497dfe64dd3Smacallan float total = (mclk * bus) / bpp; 498dfe64dd3Smacallan 499dfe64dd3Smacallan PDEBUG5(ErrorF("mclk: %d, bus: %d, magic: %f, bpp: %d\n", 500dfe64dd3Smacallan mclk, bus, magic, bpp)); 501dfe64dd3Smacallan PDEBUG5(ErrorF("Total Adapter Bandwidth is %fM\n", total/1000)); 502dfe64dd3Smacallan 503dfe64dd3Smacallan if (pXGI->VBFlags & CRT2_ENABLE) { 504dfe64dd3Smacallan total = ((total / 2) > 540000) 505dfe64dd3Smacallan ? (total - 540000) : (total / 2); 506dfe64dd3Smacallan } 507dfe64dd3Smacallan 508dfe64dd3Smacallan return (int)(total / magic); 509dfe64dd3Smacallan} 510dfe64dd3Smacallan 511dfe64dd3Smacallan 512dfe64dd3Smacallan/** 513dfe64dd3Smacallan * Calculate available memory bandwidth for an XG20 series chip. 514dfe64dd3Smacallan * 515dfe64dd3Smacallan * \sa XG20_MemBandWidth 516dfe64dd3Smacallan */ 517dfe64dd3Smacallanstatic int XG20_MemBandWidth(ScrnInfoPtr pScrn) 518dfe64dd3Smacallan{ 519dfe64dd3Smacallan XGIPtr pXGI = XGIPTR(pScrn); 520dfe64dd3Smacallan const int bus = (pXGI->BusWidth > 128) ? 128 : pXGI->BusWidth; 521dfe64dd3Smacallan const int mclk = pXGI->MemClock; 522dfe64dd3Smacallan const int bpp = pScrn->bitsPerPixel; 523dfe64dd3Smacallan const float magic = 1.44; 524dfe64dd3Smacallan float total = (mclk * bus) / bpp; 525dfe64dd3Smacallan 526dfe64dd3Smacallan /* Jong 09/19/2007; support DDRII and double pixel clock */ 527dfe64dd3Smacallan unsigned long SR39, CR97 ; 528dfe64dd3Smacallan 529dfe64dd3Smacallan PDEBUG5(ErrorF("mclk: %d, bus: %d, magic: %f, bpp: %d\n", 530dfe64dd3Smacallan mclk, bus, magic, bpp)); 531dfe64dd3Smacallan 532dfe64dd3Smacallan total = mclk*bus/bpp; 533dfe64dd3Smacallan 534dfe64dd3Smacallan /* Jong 04/26/2007; support DDRII and double pixel clock */ 535dfe64dd3Smacallan /*-------------------------------------------------------*/ 536dfe64dd3Smacallan inXGIIDXREG(XGISR, 0x39, SR39); 537dfe64dd3Smacallan inXGIIDXREG(XGICR, 0x97, CR97); 538dfe64dd3Smacallan 539dfe64dd3Smacallan /* Jong@09082009; modify for XG27 */ 540dfe64dd3Smacallan if(pXGI->Chipset == PCI_CHIP_XGIXG27) 541dfe64dd3Smacallan { 542dfe64dd3Smacallan if (CR97 & 0xC1) 543dfe64dd3Smacallan total *= 2; 544dfe64dd3Smacallan } 545dfe64dd3Smacallan else /* XG20/21 */ 546dfe64dd3Smacallan { 547dfe64dd3Smacallan if (CR97 & 0x10) 548dfe64dd3Smacallan { 549dfe64dd3Smacallan if (CR97 & 0x01) 550dfe64dd3Smacallan { 551dfe64dd3Smacallan total *= 2; 552dfe64dd3Smacallan } 553dfe64dd3Smacallan } 554dfe64dd3Smacallan else 555dfe64dd3Smacallan { 556dfe64dd3Smacallan if (SR39 & 0x2) 557dfe64dd3Smacallan { 558dfe64dd3Smacallan total *= 2; 559dfe64dd3Smacallan } 560dfe64dd3Smacallan } 561dfe64dd3Smacallan } 562dfe64dd3Smacallan /*-------------------------------------------------------*/ 563dfe64dd3Smacallan 564dfe64dd3Smacallan PDEBUG5(ErrorF("Total Adapter Bandwidth is %fM\n", total/1000)); 565dfe64dd3Smacallan 566dfe64dd3Smacallan return (int)(total / magic); 567dfe64dd3Smacallan} 568dfe64dd3Smacallan 569dfe64dd3Smacallanextern unsigned int g_GammaRed; 570dfe64dd3Smacallanextern unsigned int g_GammaGreen; 571dfe64dd3Smacallanextern unsigned int g_GammaBlue; 572dfe64dd3Smacallan 573dfe64dd3Smacallanvoid XGIAdjustGamma(ScrnInfoPtr pScrn, unsigned int gammaRed, unsigned int gammaGreen, unsigned int gammaBlue) 574dfe64dd3Smacallan{ 575dfe64dd3Smacallan XGIPtr pXGI = XGIPTR(pScrn); 576dfe64dd3Smacallan int num = 255, i; 577dfe64dd3Smacallan double red = 1.0 / (double)((double)gammaRed / 1000); 578dfe64dd3Smacallan double green = 1.0 / (double)((double)gammaGreen / 1000); 579dfe64dd3Smacallan double blue = 1.0 / (double)((double)gammaBlue / 1000); 580dfe64dd3Smacallan CARD8 GammaRampRed[256], GammaRampGreen[256], GammaRampBlue[256]; 581dfe64dd3Smacallan 582dfe64dd3Smacallan for(i = 0; i <= num; i++) { 583dfe64dd3Smacallan GammaRampRed[i] = 584dfe64dd3Smacallan (red == 1.0) ? i : (CARD8)(pow((double)i / (double)num, red) * (double)num + 0.5); 585dfe64dd3Smacallan 586dfe64dd3Smacallan GammaRampGreen[i] = 587dfe64dd3Smacallan (green == 1.0) ? i : (CARD8)(pow((double)i / (double)num, green) * (double)num + 0.5); 588dfe64dd3Smacallan 589dfe64dd3Smacallan GammaRampBlue[i] = 590dfe64dd3Smacallan (blue == 1.0) ? i : (CARD8)(pow((double)i / (double)num, blue) * (double)num + 0.5); 591dfe64dd3Smacallan } 592dfe64dd3Smacallan 593dfe64dd3Smacallan /* set gamma ramp to HW */ 594dfe64dd3Smacallan for(i = 0; i <= 255; i++) { 595dfe64dd3Smacallan MMIO_OUT32(pXGI->IOBase, 0x8570, 596dfe64dd3Smacallan (i << 24) | 597dfe64dd3Smacallan (GammaRampBlue[i] << 16) | 598dfe64dd3Smacallan (GammaRampGreen[i] << 8) | 599dfe64dd3Smacallan GammaRampRed[i]); 600dfe64dd3Smacallan } 601dfe64dd3Smacallan} 602dfe64dd3Smacallan 603dfe64dd3Smacallanvoid 604dfe64dd3SmacallanXGILoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, 605dfe64dd3Smacallan VisualPtr pVisual) 606dfe64dd3Smacallan{ 607dfe64dd3Smacallan XGIPtr pXGI = XGIPTR(pScrn); 608dfe64dd3Smacallan int i, j, index; 609dfe64dd3Smacallan/* unsigned char backup = 0; */ 610dfe64dd3Smacallan unsigned char SR7; 611dfe64dd3Smacallan Bool dogamma1 = pXGI->CRT1gamma; 612dfe64dd3Smacallan/* Bool resetxvgamma = FALSE; */ 613dfe64dd3Smacallan 614dfe64dd3Smacallan if (IS_DUAL_HEAD(pXGI)) { 615dfe64dd3Smacallan XGIEntPtr pXGIEnt = ENTITY_PRIVATE(pXGI); 616dfe64dd3Smacallan dogamma1 = pXGIEnt->CRT1gamma; 617dfe64dd3Smacallan } 618dfe64dd3Smacallan 619dfe64dd3Smacallan PDEBUG(ErrorF("xgiLoadPalette(%d)\n", numColors)); 620dfe64dd3Smacallan 621dfe64dd3Smacallan if (!IS_DUAL_HEAD(pXGI) || IS_SECOND_HEAD(pXGI)) { 622dfe64dd3Smacallan switch(pXGI->CurrentLayout.depth) { 623dfe64dd3Smacallan#ifdef XGIGAMMA 624dfe64dd3Smacallan case 15: 625dfe64dd3Smacallan if(dogamma1) { 626dfe64dd3Smacallan orXGIIDXREG(XGISR, 0x07, 0x04); 627dfe64dd3Smacallan for(i=0; i<numColors; i++) { 628dfe64dd3Smacallan index = indices[i]; 629dfe64dd3Smacallan if(index < 32) { /* Paranoia */ 630dfe64dd3Smacallan for(j=0; j<8; j++) { 631dfe64dd3Smacallan outXGIREG(XGICOLIDX, (index * 8) + j); 632dfe64dd3Smacallan outXGIREG(XGICOLDATA, colors[index].red << (8- pScrn->rgbBits)); 633dfe64dd3Smacallan outXGIREG(XGICOLDATA, colors[index].green << (8 - pScrn->rgbBits)); 634dfe64dd3Smacallan outXGIREG(XGICOLDATA, colors[index].blue << (8 - pScrn->rgbBits)); 635dfe64dd3Smacallan } 636dfe64dd3Smacallan } 637dfe64dd3Smacallan } 638dfe64dd3Smacallan } else { 639dfe64dd3Smacallan andXGIIDXREG(XGISR, 0x07, ~0x04); 640dfe64dd3Smacallan } 641dfe64dd3Smacallan break; 642dfe64dd3Smacallan case 16: 643dfe64dd3Smacallan if(dogamma1) { 644dfe64dd3Smacallan orXGIIDXREG(XGISR, 0x07, 0x04); 645dfe64dd3Smacallan inXGIIDXREG(XGISR, 0x07, SR7); 646dfe64dd3SmacallanPDEBUG(ErrorF("\ndogamma1 SR7=%x ", SR7)); 647dfe64dd3Smacallan for(i=0; i<numColors; i++) { 648dfe64dd3Smacallan index = indices[i]; 649dfe64dd3Smacallan if(index < 64) { /* Paranoia */ 650dfe64dd3Smacallan for(j=0; j<4; j++) { 651dfe64dd3Smacallan outXGIREG(XGICOLIDX, (index * 4) + j); 652dfe64dd3Smacallan outXGIREG(XGICOLDATA, colors[index/2].red << (8 - pScrn->rgbBits)); 653dfe64dd3Smacallan outXGIREG(XGICOLDATA, colors[index].green << (8 - pScrn->rgbBits)); 654dfe64dd3Smacallan outXGIREG(XGICOLDATA, colors[index/2].blue << (8 - pScrn->rgbBits)); 655dfe64dd3Smacallan } 656dfe64dd3Smacallan } 657dfe64dd3Smacallan } 658dfe64dd3Smacallan } else { 659dfe64dd3Smacallan andXGIIDXREG(XGISR, 0x07, ~0x04); 660dfe64dd3Smacallan } 661dfe64dd3Smacallan break; 662dfe64dd3Smacallan case 24: 663dfe64dd3Smacallan if(dogamma1) { 664dfe64dd3Smacallan orXGIIDXREG(XGISR, 0x07, 0x04); 665dfe64dd3Smacallan for(i=0; i<numColors; i++) { 666dfe64dd3Smacallan index = indices[i]; 667dfe64dd3Smacallan if(index < 256) { /* Paranoia */ 668dfe64dd3Smacallan outXGIREG(XGICOLIDX, index); 669dfe64dd3Smacallan outXGIREG(XGICOLDATA, colors[index].red); 670dfe64dd3Smacallan outXGIREG(XGICOLDATA, colors[index].green); 671dfe64dd3Smacallan outXGIREG(XGICOLDATA, colors[index].blue); 672dfe64dd3Smacallan } 673dfe64dd3Smacallan } 674dfe64dd3Smacallan } else { 675dfe64dd3Smacallan andXGIIDXREG(XGISR, 0x07, ~0x04); 676dfe64dd3Smacallan } 677dfe64dd3Smacallan break; 678dfe64dd3Smacallan#endif 679dfe64dd3Smacallan default: 680dfe64dd3Smacallan if((pScrn->rgbBits == 8) && (dogamma1)) 681dfe64dd3Smacallan orXGIIDXREG(XGISR, 0x07, 0x04); 682dfe64dd3Smacallan else 683dfe64dd3Smacallan andXGIIDXREG(XGISR, 0x07, ~0x04); 684dfe64dd3Smacallan for(i=0; i<numColors; i++) { 685dfe64dd3Smacallan index = indices[i]; 686dfe64dd3Smacallan outXGIREG(XGICOLIDX, index); 687dfe64dd3Smacallan outXGIREG(XGICOLDATA, colors[index].red >> (8 - pScrn->rgbBits)); 688dfe64dd3Smacallan outXGIREG(XGICOLDATA, colors[index].green >> (8 - pScrn->rgbBits)); 689dfe64dd3Smacallan outXGIREG(XGICOLDATA, colors[index].blue >> (8 - pScrn->rgbBits)); 690dfe64dd3Smacallan } 691dfe64dd3Smacallan } 692dfe64dd3Smacallan 693dfe64dd3Smacallan } 694dfe64dd3Smacallan 695dfe64dd3Smacallan if (!IS_DUAL_HEAD(pXGI) || !IS_SECOND_HEAD(pXGI)) { 696dfe64dd3Smacallan 697dfe64dd3Smacallan } 698dfe64dd3Smacallan 699dfe64dd3Smacallan if(pXGI->CurrentLayout.depth != 8) 700dfe64dd3Smacallan XGIAdjustGamma(pScrn, g_GammaRed, g_GammaGreen, g_GammaBlue); 701dfe64dd3Smacallan} 702dfe64dd3Smacallan 703dfe64dd3Smacallanvoid 704dfe64dd3SmacallanXGIDACPreInit(ScrnInfoPtr pScrn) 705dfe64dd3Smacallan{ 706dfe64dd3Smacallan XGIPtr pXGI = XGIPTR(pScrn); 707dfe64dd3Smacallan 708dfe64dd3SmacallanPDEBUG(ErrorF("XGIDACPreInit()\n")); 709dfe64dd3Smacallan 710dfe64dd3Smacallan pXGI->XGISave = Volari_Save; 711dfe64dd3Smacallan pXGI->XGIRestore = Volari_Restore; 712dfe64dd3Smacallan pXGI->SetThreshold = Volari_Threshold; 713dfe64dd3Smacallan 714dfe64dd3Smacallan pXGI->MaxClock = ((pXGI->Chipset == PCI_CHIP_XGIXG20) || (pXGI->Chipset == PCI_CHIP_XGIXG21) || (pXGI->Chipset == PCI_CHIP_XGIXG27)) 715dfe64dd3Smacallan ? XG20_MemBandWidth(pScrn) : XG40_MemBandWidth(pScrn); 716dfe64dd3Smacallan} 717dfe64dd3Smacallan 718dfe64dd3Smacallan 719dfe64dd3Smacallanint 720dfe64dd3SmacallanXG40Mclk(XGIPtr pXGI) 721dfe64dd3Smacallan{ 722dfe64dd3Smacallan int mclk; 723dfe64dd3Smacallan unsigned char Num, Denum; 724dfe64dd3Smacallan 725dfe64dd3Smacallan /* Numerator */ 726dfe64dd3Smacallan /* inXGIIDXREG(0x3c4, 0x28, Num); */ 727dfe64dd3Smacallan inXGIIDXREG(XGISR, 0x28, Num); 728dfe64dd3Smacallan mclk = 14318 * ((Num & 0x7f) + 1); 729dfe64dd3Smacallan 730dfe64dd3Smacallan /* Denumerator */ 731dfe64dd3Smacallan /* inXGIIDXREG(0x3c4, 0x29, Denum); */ 732dfe64dd3Smacallan inXGIIDXREG(XGISR, 0x29, Denum); 733dfe64dd3Smacallan mclk = mclk / ((Denum & 0x1f) + 1); 734dfe64dd3Smacallan 735dfe64dd3Smacallan /* Divider */ 736dfe64dd3Smacallan if ((Num & 0x80)!=0) { 737dfe64dd3Smacallan mclk = mclk * 2; 738dfe64dd3Smacallan } 739dfe64dd3Smacallan 740dfe64dd3Smacallan /* Post-Scaler */ 741dfe64dd3Smacallan mclk /= ((Denum & 0x80) == 0) 742dfe64dd3Smacallan ? (((Denum & 0x60) >> 5) + 1) 743dfe64dd3Smacallan : ((((Denum & 0x60) >> 5) + 1) * 2); 744dfe64dd3Smacallan 745dfe64dd3Smacallan return mclk; 746dfe64dd3Smacallan} 747dfe64dd3Smacallan 748dfe64dd3Smacallan 749dfe64dd3Smacallanstatic int 750dfe64dd3Smacallanretrace_signals_active(XGIIOADDRESS RelIO) 751dfe64dd3Smacallan{ 752dfe64dd3Smacallan unsigned char temp; 753dfe64dd3Smacallan 754dfe64dd3Smacallan /* Make sure the vertical retrace signal is enabled. 755dfe64dd3Smacallan */ 756dfe64dd3Smacallan inXGIIDXREG(RelIO + CROFFSET, 0x17, temp); 757dfe64dd3Smacallan if (!(temp & 0x80)) 758dfe64dd3Smacallan return 0; 759dfe64dd3Smacallan 760dfe64dd3Smacallan /* FIXME: Magic offset, what are you? 761dfe64dd3Smacallan */ 762dfe64dd3Smacallan inXGIIDXREG(RelIO + SROFFSET, 0x1f, temp); 763dfe64dd3Smacallan if(temp & 0xc0) 764dfe64dd3Smacallan return 0; 765dfe64dd3Smacallan 766dfe64dd3Smacallan return 1; 767dfe64dd3Smacallan} 768dfe64dd3Smacallan 769dfe64dd3Smacallan 770dfe64dd3Smacallan/** 771dfe64dd3Smacallan * Wait for beginning of next vertical retrace. 772dfe64dd3Smacallan * 773dfe64dd3Smacallan * \bugs 774dfe64dd3Smacallan * The functions \c XGI_WaitBeginRetrace and \c XGI_WaitEndRetrace are 775dfe64dd3Smacallan * nearly identical. Are both \b really necessary? 776dfe64dd3Smacallan */ 777dfe64dd3Smacallanvoid 778dfe64dd3SmacallanXGI_WaitBeginRetrace(XGIIOADDRESS RelIO) 779dfe64dd3Smacallan{ 780dfe64dd3Smacallan int watchdog; 781dfe64dd3Smacallan 782dfe64dd3Smacallan if (retrace_signals_active(RelIO)) { 783dfe64dd3Smacallan /* Wait for the CRTC to leave then re-enter the vertical retrace 784dfe64dd3Smacallan * period. 785dfe64dd3Smacallan */ 786dfe64dd3Smacallan watchdog = 65536; 787dfe64dd3Smacallan while ((inXGIREG(RelIO + INPUTSTATOFFSET) & IS_BIT_VERT_ACTIVE) && --watchdog) 788dfe64dd3Smacallan /* empty */ ; 789dfe64dd3Smacallan 790dfe64dd3Smacallan watchdog = 65536; 791dfe64dd3Smacallan while ((!(inXGIREG(RelIO + INPUTSTATOFFSET) & IS_BIT_VERT_ACTIVE)) && --watchdog) 792dfe64dd3Smacallan /* empty */ ; 793dfe64dd3Smacallan } 794dfe64dd3Smacallan} 795dfe64dd3Smacallan 796dfe64dd3Smacallan 797dfe64dd3Smacallan/** 798dfe64dd3Smacallan * Wait for end of next vertical retrace. 799dfe64dd3Smacallan * 800dfe64dd3Smacallan * \bugs 801dfe64dd3Smacallan * The functions \c XGI_WaitBeginRetrace and \c XGI_WaitEndRetrace are 802dfe64dd3Smacallan * nearly identical. Are both \b really necessary? 803dfe64dd3Smacallan */ 804dfe64dd3Smacallanvoid 805dfe64dd3SmacallanXGI_WaitEndRetrace(XGIIOADDRESS RelIO) 806dfe64dd3Smacallan{ 807dfe64dd3Smacallan int watchdog; 808dfe64dd3Smacallan 809dfe64dd3Smacallan if (retrace_signals_active(RelIO)) { 810dfe64dd3Smacallan /* Wait for the CRTC to enter then leave the vertical retrace 811dfe64dd3Smacallan * period. 812dfe64dd3Smacallan */ 813dfe64dd3Smacallan watchdog = 65536; 814dfe64dd3Smacallan while ((!(inXGIREG(RelIO + INPUTSTATOFFSET) & IS_BIT_VERT_ACTIVE)) && --watchdog) 815dfe64dd3Smacallan /* empty */ ; 816dfe64dd3Smacallan 817dfe64dd3Smacallan watchdog = 65536; 818dfe64dd3Smacallan while ((inXGIREG(RelIO + INPUTSTATOFFSET) & IS_BIT_VERT_ACTIVE) && --watchdog) 819dfe64dd3Smacallan /* empty */ ; 820dfe64dd3Smacallan } 821dfe64dd3Smacallan} 822