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