pm3_dac.c revision 1fb744b4
1/*
2 * Copyright 2000,2001 by Sven Luther <luther@dpt-info.u-strasbg.fr>.
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
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Sven Luther not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Sven Luther 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 * SVEN LUTHER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL SVEN LUTHER 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 * Authors: Sven Luther, <luther@dpt-info.u-strasbg.fr>
23 *          Thomas Witzel, <twitzel@nmr.mgh.harvard.edu>
24 *          Alan Hourihane, <alanh@fairlite.demon.co.uk>
25 *
26 * this work is sponsored by Appian Graphics.
27 *
28 */
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#include "xf86.h"
35#include "xf86_OSproc.h"
36
37#include "xf86Pci.h"
38#include "xf86int10.h"
39
40#include "glint_regs.h"
41#include "pm3_regs.h"
42#include "glint.h"
43
44#define DEBUG 0
45
46#if DEBUG
47# define TRACE_ENTER(str)       ErrorF("glint: " str " %d\n",pScrn->scrnIndex)
48# define TRACE_EXIT(str)        ErrorF("glint: " str " done\n")
49# define TRACE(str)             ErrorF("glint trace: " str "\n")
50#else
51# define TRACE_ENTER(str)
52# define TRACE_EXIT(str)
53# define TRACE(str)
54#endif
55
56int
57Permedia3MemorySizeDetect(ScrnInfoPtr pScrn)
58{
59    GLINTPtr pGlint = GLINTPTR (pScrn);
60    CARD32 size = 0, temp, temp1, temp2, i;
61
62    /* We can map 64MB, as that's the size of the Permedia3 aperture
63     * regardless of memory configuration */
64    pGlint->FbMapSize = 64*1024*1024;
65
66#ifndef XSERVER_LIBPCIACCESS
67    /* Mark as VIDMEM_MMIO to avoid write-combining while detecting memory */
68    pGlint->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
69			pGlint->PciTag, pGlint->FbAddress, pGlint->FbMapSize);
70#else
71    {
72      void** result = (void**)&pGlint->FbBase;
73      int err = pci_device_map_range(pGlint->PciInfo,
74				     pGlint->FbAddress,
75				     pGlint->FbMapSize,
76				     PCI_DEV_MAP_FLAG_WRITABLE,
77				     result);
78
79      if (err)
80	return FALSE;
81    }
82
83#endif
84    if (pGlint->FbBase == NULL)
85	return 0;
86
87    temp = GLINT_READ_REG(PM3MemBypassWriteMask);
88    GLINT_SLOW_WRITE_REG(0xffffffff, PM3MemBypassWriteMask);
89
90    /* The Permedia3 splits up memory, and even replicates it. Grrr.
91     * So that each 32MB appears at offset 0, and offset 32, unless
92     * there's really 64MB attached to the chip.
93     * So, 16MB appears at offset 0, nothing between 16-32, then it re-appears
94     * at offset 32.
95     * This below is to detect the cases of memory combinations
96     */
97
98    /* Test first 32MB */
99    for(i=0;i<32;i++) {
100    	/* write test pattern */
101	MMIO_OUT32(pGlint->FbBase, i*1024*1024, i*0x00345678);
102	mem_barrier();
103	temp1 = MMIO_IN32(pGlint->FbBase, i*1024*1024);
104    	/* Let's check for wrapover, write will fail at 16MB boundary */
105	if (temp1 == (i*0x00345678))
106	    size = i;
107	else
108	    break;
109    }
110
111    /* Ok, we're satisfied we've got 32MB, let's test the second lot */
112    if ((size + 1) == i) {
113	for(i=0;i<32;i++) {
114	    /* Clear first 32MB */
115	    MMIO_OUT32(pGlint->FbBase, i*1024*1024, 0);
116	}
117	mem_barrier();
118
119        for(i=32;i<64;i++) {
120    	    /* write test pattern */
121	    MMIO_OUT32(pGlint->FbBase, i*1024*1024, i*0x00345678);
122	    mem_barrier();
123	    temp1 = MMIO_IN32(pGlint->FbBase, i*1024*1024);
124	    temp2 = MMIO_IN32(pGlint->FbBase, (i-32)*1024*1024);
125    	    /* Let's check for wrapover */
126	    if ( (temp1 == (i*0x00345678)) && (temp2 == 0) )
127	        size = i;
128	    else
129	        break;
130	}
131    }
132
133    GLINT_SLOW_WRITE_REG(temp, PM3MemBypassWriteMask);
134
135#ifndef XSERVER_LIBPCIACCESS
136    xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pGlint->FbBase,
137							pGlint->FbMapSize);
138#else
139    pci_device_unmap_range(pGlint->PciInfo, pGlint->FbBase, pGlint->FbMapSize);
140#endif
141
142    pGlint->FbBase = NULL;
143    pGlint->FbMapSize = 0;
144
145    return ( (size+1) * 1024 );
146}
147
148static unsigned long
149PM3DAC_CalculateClock
150(
151 unsigned long ReqClock,		/* In kHz units */
152 unsigned long RefClock,		/* In kHz units */
153 unsigned char *prescale,		/* ClkPreScale */
154 unsigned char *feedback,		/* ClkFeedBackScale */
155 unsigned char *postscale		/* ClkPostScale */
156 )
157{
158  unsigned long fMinVCO = 2000000; /* min fVCO is 200MHz (in 100Hz units) */
159  unsigned long fMaxVCO = 6220000; /* max fVCO is 622MHz (in 100Hz units) */
160  unsigned long fMinINTREF = 10000;/* min fINTREF is 1MHz (in 100Hz units) */
161  unsigned long fMaxINTREF = 20000;/* max fINTREF is 2MHz (in 100Hz units) */
162  unsigned long	M, N, P; /* M=feedback, N=prescale, P=postscale */
163  unsigned long	fINTREF;
164  unsigned long	fVCO;
165  unsigned long	ActualClock;
166  long		Error;
167  unsigned long LowestError = 1000000;
168  unsigned int	bFoundFreq = FALSE;
169  int		cInnerLoopIterations = 0;
170  int		LoopCount;
171  unsigned long	ClosestClock = 0;
172
173  ReqClock*=10; /* convert into 100Hz units */
174  RefClock*=10; /* convert into 100Hz units */
175
176  for(P = 0; P <= 5; ++P)
177    {
178      unsigned long fVCOLowest, fVCOHighest;
179
180      /* it is pointless going through the main loop if all values of
181         N produce an fVCO outside the acceptable range */
182      N = 1;
183      M = (N * (1UL << P) * ReqClock) / (2 * RefClock);
184      fVCOLowest = (2 * RefClock * M) / N;
185      N = 255;
186      M = (N * (1UL << P) * ReqClock) / (2 * RefClock);
187      fVCOHighest = (2 * RefClock * M) / N;
188
189      if(fVCOHighest < fMinVCO || fVCOLowest > fMaxVCO)
190	{
191	  continue;
192	}
193
194      for(N = 1; N <= 255; ++N, ++cInnerLoopIterations)
195	{
196	  fINTREF = RefClock / N;
197	  if(fINTREF < fMinINTREF || fINTREF > fMaxINTREF)
198	    {
199	      if(fINTREF > fMaxINTREF)
200		{
201		  /* hopefully we will get into range as the prescale
202		     value increases */
203		  continue;
204		}
205	      else
206		{
207		  /* already below minimum and it will only get worse:
208		     move to the next postscale value */
209		  break;
210		}
211	    }
212
213	  M = (N * (1UL << P) * ReqClock) / (2 * RefClock);
214	  if(M > 255)
215	    {
216	      /* M, N & P registers are only 8 bits wide */
217	      break;
218	    }
219
220	  /* we can expect rounding errors in calculating M, which
221	     will always be rounded down. So we will checkout our
222	     calculated value of M along with (M+1) */
223	  for(LoopCount = (M == 255) ? 1 : 2; --LoopCount >= 0; ++M)
224	    {
225	      fVCO = (2 * RefClock * M) / N;
226	      if(fVCO >= fMinVCO && fVCO <= fMaxVCO)
227		{
228		  ActualClock = fVCO / (1UL << P);
229		  Error = ActualClock - ReqClock;
230		  if(Error < 0)
231		    Error = -Error;
232		  if(Error < LowestError)
233		    {
234		      bFoundFreq = TRUE;
235		      LowestError = Error;
236		      ClosestClock = ActualClock;
237		      *prescale = N;
238		      *feedback = M;
239		      *postscale = P;
240		      if(Error == 0)
241			goto Done;
242		    }
243		}
244	    }
245	}
246    }
247
248Done:
249
250  if(bFoundFreq)
251    ActualClock = ClosestClock;
252  else
253    ActualClock = 0;
254
255#if 0
256  ErrorF("PM3DAC_CalculateClock: Got prescale=%d, feedback=%d, postscale=%d, WantedClock = %d00 ActualClock = %d00 (Error %d00)\n",
257	 *prescale, *feedback, *postscale, ReqClock, ActualClock, LowestError);
258#endif
259
260    return(ActualClock);
261}
262
263static unsigned long
264PM4DAC_CalculateClock
265(
266 unsigned long req_clock,		/* In kHz units */
267 unsigned long ref_clock,		/* In kHz units */
268 unsigned char *param_m,		/* ClkPreScale */
269 unsigned char *param_n, 		/* ClkFeedBackScale */
270 unsigned char *param_p			/* ClkPostScale */
271 )
272{
273#define INITIALFREQERR 10000
274
275  long fMinVCO = 200000;	/* min fVCO is 200MHz (in 10000Hz units) */
276  long fMaxVCO = 400000;	/* max fVCO is 400MHz (in 10000Hz units) */
277  unsigned long int	M, N, P;
278  unsigned long int	fVCO;
279  unsigned long int	ActualClock;
280  int		Error;
281  int		LowestError = INITIALFREQERR;
282  short		bFoundFreq = FALSE;
283  int		cInnerLoopIterations = 0;
284  int		LoopCount;
285
286  /*
287   * Actual Equations:
288   *		fVCO = (ref_clock * M)/(N+1)
289   *		PIXELCLOCK = fVCO/(1<<p)
290   *		200 <= fVCO <= 400
291   *		24 <= N <= 80
292   *		1 <= M <= 15
293   *		0 <= P <= 3
294   *		1Mhz < ref_clock/(N+1) <= 2Mhz - not used
295   * For refclk == 14.318 we have the tighter equations:
296   *		32 <= N <= 80
297   *		3 <= M <= 12
298   * Notes:
299   *		The spec says that the PLLs will only do 260Mhz, but I have assumed 300Mhz 'cos
300   *		260Mhz is a crap limit.
301   */
302
303#define	P4RD_PLL_MIN_P	0
304#define	P4RD_PLL_MAX_P	3
305#define	P4RD_PLL_MIN_M	1
306#define	P4RD_PLL_MAX_M	12
307#define	P4RD_PLL_MIN_N	24
308#define	P4RD_PLL_MAX_N	80
309
310  for(P = P4RD_PLL_MIN_P; P <= P4RD_PLL_MAX_P; ++P) {
311      unsigned long int fVCOLowest, fVCOHighest;
312
313      /* it's pointless going through the main loop if all values of
314       * N produce an fVCO outside the acceptable range */
315
316      M = P4RD_PLL_MIN_M;
317      N = ((M + 1) * (1 << P) * req_clock) / ref_clock;
318
319      fVCOLowest = (ref_clock * N) / (M + 1);
320
321      M = P4RD_PLL_MAX_M;
322      N = ((M + 1) * (1 << P) * req_clock) / ref_clock;
323
324      fVCOHighest = (ref_clock * N) / (M + 1);
325
326      if(fVCOHighest < fMinVCO || fVCOLowest > fMaxVCO)
327	  continue;
328
329      for(M = P4RD_PLL_MIN_M; M <= P4RD_PLL_MAX_M; ++M, ++cInnerLoopIterations)
330	{
331	  N = ((M + 1) * (1 << P) * req_clock) / ref_clock;
332
333	  if(N > P4RD_PLL_MAX_N || N < P4RD_PLL_MIN_N)
334	      continue;
335
336	  /*  we can expect rounding errors in calculating M, which will always be rounded down. */
337	  /*  So we'll checkout our calculated value of M along with (M+1) */
338
339	  for(LoopCount = (N == P4RD_PLL_MAX_N) ? 1 : 2; --LoopCount >= 0; ++N)
340	    {
341	      fVCO = (ref_clock * N) / (M + 1);
342
343	      if( (fVCO >= fMinVCO) && (fVCO <= fMaxVCO) )
344		{
345		  ActualClock = (fVCO / (1 << P));
346
347		  Error = ActualClock - req_clock;
348
349		  if(Error < 0)
350		      Error = -Error;
351
352		  /*  It is desirable that we use the lowest value of M if the*/
353		  /*  frequencies are the same.*/
354		  if(Error < LowestError || (Error == LowestError && M < *param_m))
355		    {
356		      bFoundFreq = TRUE;
357		      LowestError = Error;
358		      *param_m = M;
359		      *param_n = N;
360		      *param_p = P;
361		      if(Error == 0)
362			goto Done;
363		    }
364		}
365	    }
366	}
367    }
368
369Done:
370  if(bFoundFreq)
371    ActualClock = (ref_clock * (*param_n)) / (((*param_m) + 1) * (1 << (*param_p)));
372  else
373    ActualClock = 0;
374
375  return(ActualClock);
376}
377
378void
379Permedia3PreInit(ScrnInfoPtr pScrn)
380{
381    GLINTPtr pGlint = GLINTPTR(pScrn);
382    CARD32 LocalMemCaps;
383
384    TRACE_ENTER("Permedia3PreInit");
385
386    if (IS_J2000) {
387    	unsigned char m,n,p;
388
389	if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA)
390	    GLINT_SLOW_WRITE_REG(GCSRSecondaryGLINTMapEn, GCSRAperture);
391
392	/* Memory timings for the Appian J2000 board.
393	 * This is needed for the second head which is left un-initialized
394	 * by the bios, thus freezing the machine. */
395	GLINT_SLOW_WRITE_REG(0x02e311B8, PM3LocalMemCaps);
396	GLINT_SLOW_WRITE_REG(0x07424905, PM3LocalMemTimings);
397	GLINT_SLOW_WRITE_REG(0x0c000003, PM3LocalMemControl);
398	GLINT_SLOW_WRITE_REG(0x00000061, PM3LocalMemRefresh);
399	GLINT_SLOW_WRITE_REG(0x00000000, PM3LocalMemPowerDown);
400
401	/* Let's program the K, M and S Clocks to the same values as the bios
402	 * does for first head :
403	 *   - KClk and MClk are 105Mhz.
404	 *   - S Clock is set to PClk.
405	 * Note 1 : pGlint->RefClock is not set yet, so use 14318 instead.
406	 * Note 2 : KClk gets internally halved, so we need to double it.
407	 */
408	(void) PM3DAC_CalculateClock(2*105000, 14318, &m,&n,&p);
409        Permedia2vOutIndReg(pScrn, PM3RD_KClkPreScale, 0x00, m);
410        Permedia2vOutIndReg(pScrn, PM3RD_KClkFeedbackScale, 0x00, n);
411        Permedia2vOutIndReg(pScrn, PM3RD_KClkPostScale, 0x00, p);
412        Permedia2vOutIndReg(pScrn, PM3RD_KClkControl, 0x00,
413	    PM3RD_KClkControl_STATE_RUN |
414	    PM3RD_KClkControl_SOURCE_PLL |
415	    PM3RD_KClkControl_ENABLE);
416        Permedia2vOutIndReg(pScrn, PM3RD_MClkControl, 0x00,
417	    PM3RD_MClkControl_STATE_RUN |
418	    PM3RD_MClkControl_SOURCE_KCLK |
419	    PM3RD_MClkControl_ENABLE);
420        Permedia2vOutIndReg(pScrn, PM3RD_SClkControl, 0x00,
421	    PM3RD_SClkControl_STATE_RUN |
422	    PM3RD_SClkControl_SOURCE_PCLK |
423	    PM3RD_SClkControl_ENABLE);
424    }
425
426#if defined(__alpha__)
427    /*
428     * On Alpha, we have to "int10" secondary VX1 cards early;
429     * otherwise, some information taken from registers, like
430     * memory size, is incorrect.
431     */
432    if (!xf86IsPrimaryPci(pGlint->PciInfo)) {
433        if ( IS_QVX1 ) {
434
435	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
436		       "VX1 secondary enabling VGA before int10\n");
437
438	    /* Enable VGA on the current card. */
439	    PCI_WRITE_BYTE(pGlint->PciInfo, 0, 0xf8);
440	    PCI_WRITE_BYTE(pGlint->PciInfo, 0, 0xf4);
441	    PCI_WRITE_BYTE(pGlint->PciInfo, 0, 0xfc);
442
443	    /* The card we are on should be VGA-enabled now, so run int10. */
444	    if (xf86LoadSubModule(pScrn, "int10")) {
445	        xf86Int10InfoPtr pInt;
446
447		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n");
448		pInt = xf86InitInt10(pGlint->pEnt->index);
449		xf86FreeInt10(pInt);
450	    }
451
452	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
453		       "VX1 secondary disabling VGA after int10\n");
454
455	    /* Finally, disable VGA on the current card. */
456	    PCI_WRITE_BYTE(pGlint->PciInfo, 0x70, 0xf8);
457	    PCI_WRITE_BYTE(pGlint->PciInfo, 0x01, 0xf4);
458	    PCI_WRITE_BYTE(pGlint->PciInfo, 0x00, 0xfc);
459	}
460    }
461#endif /* __alpha__ */
462
463    /* If we have SDRAM instead of SGRAM, we have to do some things
464       differently in the FillRectSolid code. */
465    LocalMemCaps = GLINT_READ_REG(PM3LocalMemCaps);
466    pGlint->PM3_UsingSGRAM = !(LocalMemCaps & PM3LocalMemCaps_NoWriteMask);
467    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %s memory\n",
468	       pGlint->PM3_UsingSGRAM ? "SGRAM" : "SDRAM");
469
470    TRACE_EXIT("Permedia3PreInit");
471}
472
473Bool
474Permedia3Init(ScrnInfoPtr pScrn, DisplayModePtr mode, GLINTRegPtr pReg)
475{
476    GLINTPtr pGlint = GLINTPTR(pScrn);
477    CARD32 temp1, temp2, temp3, temp4;
478
479    if ((pGlint->numMultiDevices == 2) || (IS_J2000)) {
480	STOREREG(GCSRAperture, GCSRSecondaryGLINTMapEn);
481    }
482
483    if (pGlint->MultiAperture) {
484	STOREREG(GMultGLINTAperture, pGlint->realWidth);
485	STOREREG(GMultGLINT1, PCI_REGION_BASE(pGlint->MultiPciInfo[0], 2, REGION_MEM) & 0xFF800000);
486	STOREREG(GMultGLINT2, PCI_REGION_BASE(pGlint->MultiPciInfo[1], 2, REGION_MEM) & 0xFF800000);
487    }
488
489    STOREREG(PM3MemBypassWriteMask, 	0xffffffff);
490    STOREREG(Aperture0,		 	0x00000000);
491    STOREREG(Aperture1,		 	0x00000000);
492
493    if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA)
494    	STOREREG(DFIFODis,			0x00000001);
495
496    STOREREG(FIFODis,			0x00000007);
497
498    temp1 = mode->CrtcHSyncStart - mode->CrtcHDisplay;
499    temp2 = mode->CrtcVSyncStart - mode->CrtcVDisplay;
500    temp3 = mode->CrtcHSyncEnd - mode->CrtcHSyncStart;
501    temp4 = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
502
503    STOREREG(PMHTotal,	Shiftbpp(pScrn, mode->CrtcHTotal) - 1);
504    STOREREG(PMHsEnd,	Shiftbpp(pScrn, temp1 + temp3));
505    STOREREG(PMHsStart,	Shiftbpp(pScrn, temp1));
506    STOREREG(PMHbEnd,	Shiftbpp(pScrn, mode->CrtcHTotal - mode->CrtcHDisplay));
507    STOREREG(PMHgEnd,	Shiftbpp(pScrn, mode->CrtcHTotal - mode->CrtcHDisplay));
508    STOREREG(PMScreenStride, Shiftbpp(pScrn, pScrn->displayWidth));
509
510    STOREREG(PMVTotal,	mode->CrtcVTotal - 1);
511    STOREREG(PMVsEnd,	temp2 + temp4 - 1);
512    STOREREG(PMVsStart,	temp2 - 1);
513    STOREREG(PMVbEnd,	mode->CrtcVTotal - mode->CrtcVDisplay);
514
515    switch (pScrn->bitsPerPixel)
516    {
517	case 8:
518	    STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_8BIT);
519	    STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_8BIT);
520	    STOREREG(PMVideoControl,	 1 | (1 << 3) | (1 << 5) | (0 << 19));
521	    break;
522	case 16:
523#if X_BYTE_ORDER != X_BIG_ENDIAN
524	    STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_16BIT);
525	    STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_16BIT);
526#else
527	    STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_16BIT |
528					 PM3ByApertureMode_BYTESWAP_BADC);
529	    STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_16BIT |
530					 PM3ByApertureMode_BYTESWAP_BADC);
531#endif
532	    STOREREG(PMVideoControl,	 1 | (1 << 3) | (1 << 5) | (1 << 19));
533	    break;
534	case 32:
535#if X_BYTE_ORDER != X_BIG_ENDIAN
536	    STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_32BIT);
537	    STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_32BIT);
538#else
539	    STOREREG(PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_32BIT |
540					 PM3ByApertureMode_BYTESWAP_DCBA);
541	    STOREREG(PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_32BIT |
542					 PM3ByApertureMode_BYTESWAP_DCBA);
543#endif
544	    STOREREG(PMVideoControl,	 1 | (1 << 3) | (1 << 5) | (2 << 19));
545	    break;
546    }
547
548    STOREREG(VClkCtl, GLINT_READ_REG(VClkCtl) & 0xFFFFFFFC);
549    STOREREG(PMScreenBase, 0x00000000);
550    STOREREG(ChipConfig, GLINT_READ_REG(ChipConfig) & 0xFFFFFFFD);
551
552    {
553	/* Get the programmable clock values */
554    	unsigned char m,n,p;
555
556	/* Let's program the dot clock */
557	switch (pGlint->Chipset) {
558	case PCI_VENDOR_3DLABS_CHIP_PERMEDIA4:
559	case PCI_VENDOR_3DLABS_CHIP_R4:
560	  (void) PM4DAC_CalculateClock(mode->Clock, pGlint->RefClock, &m,&n,&p);
561	  break;
562	case PCI_VENDOR_3DLABS_CHIP_PERMEDIA3:
563	  (void) PM3DAC_CalculateClock(mode->Clock, pGlint->RefClock, &m,&n,&p);
564	  break;
565	case PCI_VENDOR_3DLABS_CHIP_GAMMA:
566	  switch (pGlint->MultiChip) {
567	    case PCI_CHIP_3DLABS_PERMEDIA3:
568		(void) PM3DAC_CalculateClock(mode->Clock,
569					    pGlint->RefClock, &m,&n,&p);
570		break;
571	    case PCI_CHIP_3DLABS_R4:
572		(void) PM4DAC_CalculateClock(mode->Clock,
573					    pGlint->RefClock, &m,&n,&p);
574		break;
575	  }
576	  break;
577	}
578	STOREDAC(PM3RD_DClk0PreScale, m);
579	STOREDAC(PM3RD_DClk0FeedbackScale, n);
580	STOREDAC(PM3RD_DClk0PostScale, p);
581    }
582
583    temp1 = 0;
584    temp2 = 0;
585    temp3 = 0;
586
587    if (pGlint->UseFlatPanel) {
588    	temp2 |= PM3RD_DACControl_BLANK_PEDESTAL_ENABLE;
589    	temp3 |= PM3RD_MiscControl_VSB_OUTPUT_ENABLE;
590    	STOREREG(VSConfiguration, 0x06);
591    	STOREREG(VSBBase, 1<<14);
592    }
593
594    if (mode->Flags & V_PHSYNC) temp1 |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
595    if (mode->Flags & V_PVSYNC) temp1 |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
596
597    STOREREG(PM2VDACRDIndexControl, 0x00);
598    STOREDAC(PM2VDACRDSyncControl, temp1);
599    STOREDAC(PM2VDACRDDACControl, temp2);
600
601    if (pScrn->rgbBits == 8)
602	temp3 |= 0x01; /* 8bit DAC */
603
604    switch (pScrn->bitsPerPixel)
605    {
606    case 8:
607	STOREDAC(PM2VDACRDPixelSize, 0x00);
608	STOREDAC(PM2VDACRDColorFormat, 0x2E);
609    	break;
610    case 16:
611    	temp3 |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE;
612	STOREDAC(PM2VDACRDPixelSize, 0x01);
613	if (pScrn->depth == 15) {
614	    STOREDAC(PM2VDACRDColorFormat, 0x61);
615	} else {
616	    STOREDAC(PM2VDACRDColorFormat, 0x70);
617	}
618    	break;
619    case 24:
620    	temp3 |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE;
621	STOREDAC(PM2VDACRDPixelSize, 0x04);
622	STOREDAC(PM2VDACRDColorFormat, 0x20);
623    	break;
624    case 32:
625    	temp3 |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE;
626	if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
627	    temp3 |= 0x18;
628	    STOREDAC(PM2VDACRDOverlayKey, pScrn->colorKey);
629	}
630	STOREDAC(PM2VDACRDPixelSize, 0x02);
631	STOREDAC(PM2VDACRDColorFormat, 0x20);
632    	break;
633    }
634    STOREDAC(PM2VDACRDMiscControl, temp3);
635
636    STOREREG(PM3FifoControl, 0x905); /* Lower the default fifo threshold */
637
638    return(TRUE);
639}
640
641void
642Permedia3Save(ScrnInfoPtr pScrn, GLINTRegPtr pReg)
643{
644    GLINTPtr pGlint = GLINTPTR(pScrn);
645    int i;
646
647    /* We can't rely on the vgahw layer copying the font information
648     * back properly, due to problems with MMIO access to VGA space
649     * so we memcpy the information using the slow routines */
650    xf86SlowBcopy((CARD8*)pGlint->FbBase, (CARD8*)pGlint->VGAdata, 65536);
651
652    if ((pGlint->numMultiDevices == 2) || (IS_J2000)) {
653	SAVEREG(GCSRAperture);
654    }
655
656    if (pGlint->MultiAperture) {
657	SAVEREG(GMultGLINTAperture);
658	SAVEREG(GMultGLINT1);
659	SAVEREG(GMultGLINT2);
660    }
661
662    /* Permedia 3 memory Timings */
663    SAVEREG(PM3MemBypassWriteMask);
664    SAVEREG(PM3ByAperture1Mode);
665    SAVEREG(PM3ByAperture2Mode);
666    SAVEREG(ChipConfig);
667    SAVEREG(Aperture0);
668    SAVEREG(Aperture1);
669    SAVEREG(PM3FifoControl);
670
671    if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA)
672   	SAVEREG(DFIFODis);
673    SAVEREG(FIFODis);
674    SAVEREG(PMHTotal);
675    SAVEREG(PMHbEnd);
676    SAVEREG(PMHgEnd);
677    SAVEREG(PMScreenStride);
678    SAVEREG(PMHsStart);
679    SAVEREG(PMHsEnd);
680    SAVEREG(PMVTotal);
681    SAVEREG(PMVbEnd);
682    SAVEREG(PMVsStart);
683    SAVEREG(PMVsEnd);
684    SAVEREG(PMScreenBase);
685    SAVEREG(PMVideoControl);
686    SAVEREG(VClkCtl);
687    if (pGlint->UseFlatPanel) {
688    	SAVEREG(VSConfiguration);
689    	SAVEREG(VSBBase);
690    }
691
692    for (i=0;i<768;i++) {
693    	Permedia2ReadAddress(pScrn, i);
694	pReg->cmap[i] = Permedia2ReadData(pScrn);
695    }
696
697    SAVEREG(PM2VDACRDIndexControl);
698    P2VIN(PM2VDACRDOverlayKey);
699    P2VIN(PM2VDACRDSyncControl);
700    P2VIN(PM2VDACRDMiscControl);
701    P2VIN(PM2VDACRDDACControl);
702    P2VIN(PM2VDACRDPixelSize);
703    P2VIN(PM2VDACRDColorFormat);
704    P2VIN(PM2VDACRDDClk0PreScale);
705    P2VIN(PM2VDACRDDClk0FeedbackScale);
706    P2VIN(PM2VDACRDDClk0PostScale);
707}
708
709void
710Permedia3Restore(ScrnInfoPtr pScrn, GLINTRegPtr pReg)
711{
712    GLINTPtr pGlint = GLINTPTR(pScrn);
713    CARD32 temp;
714    int i;
715
716    /* We can't rely on the vgahw layer copying the font information
717     * back properly, due to problems with MMIO access to VGA space
718     * so we memcpy the information using the slow routines */
719    if (pGlint->STATE)
720	xf86SlowBcopy((CARD8*)pGlint->VGAdata, (CARD8*)pGlint->FbBase, 65536);
721
722    if ((pGlint->numMultiDevices == 2) || (IS_J2000)) {
723	RESTOREREG(GCSRAperture);
724    }
725
726    if (pGlint->MultiAperture) {
727	RESTOREREG(GMultGLINTAperture);
728	RESTOREREG(GMultGLINT1);
729	RESTOREREG(GMultGLINT2);
730    }
731
732    /* Permedia 3 memory Timings */
733    RESTOREREG(PM3MemBypassWriteMask);
734    RESTOREREG(PM3ByAperture1Mode);
735    RESTOREREG(PM3ByAperture2Mode);
736    RESTOREREG(ChipConfig);
737    RESTOREREG(Aperture0);
738    RESTOREREG(Aperture1);
739    RESTOREREG(PM3FifoControl);
740    if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA)
741    	RESTOREREG(DFIFODis);
742    RESTOREREG(FIFODis);
743    RESTOREREG(PMVideoControl);
744    RESTOREREG(PMHbEnd);
745    RESTOREREG(PMHgEnd);
746    RESTOREREG(PMScreenBase);
747    RESTOREREG(VClkCtl);
748    RESTOREREG(PMScreenStride);
749    RESTOREREG(PMHTotal);
750    RESTOREREG(PMHsStart);
751    RESTOREREG(PMHsEnd);
752    RESTOREREG(PMVTotal);
753    RESTOREREG(PMVbEnd);
754    RESTOREREG(PMVsStart);
755    RESTOREREG(PMVsEnd);
756
757    if (pGlint->UseFlatPanel) {
758    	RESTOREREG(VSConfiguration);
759    	RESTOREREG(VSBBase);
760    }
761
762    RESTOREREG(PM2VDACRDIndexControl);
763    P2VOUT(PM2VDACRDOverlayKey);
764    P2VOUT(PM2VDACRDSyncControl);
765    P2VOUT(PM2VDACRDMiscControl);
766    P2VOUT(PM2VDACRDDACControl);
767    P2VOUT(PM2VDACRDPixelSize);
768    P2VOUT(PM2VDACRDColorFormat);
769
770    for (i=0;i<768;i++) {
771    	Permedia2WriteAddress(pScrn, i);
772	Permedia2WriteData(pScrn, pReg->cmap[i]);
773    }
774
775    temp = Permedia2vInIndReg(pScrn, PM2VDACIndexClockControl) & 0xFC;
776    P2VOUT(PM2VDACRDDClk0PreScale);
777    P2VOUT(PM2VDACRDDClk0FeedbackScale);
778    P2VOUT(PM2VDACRDDClk0PostScale);
779    Permedia2vOutIndReg(pScrn, PM2VDACIndexClockControl, 0x00, temp|0x03);
780}
781
782void Permedia3LoadPalette(
783    ScrnInfoPtr pScrn,
784    int numColors,
785    int *indices,
786    LOCO *colors,
787    VisualPtr pVisual
788){
789#if 0
790    GLINTPtr pGlint = GLINTPTR(pScrn);
791#endif
792    int i, index, shift = 0, j, repeat = 1;
793
794    if (pScrn->depth == 15) {
795	repeat = 8;
796	shift = 3;
797    }
798
799    for(i = 0; i < numColors; i++) {
800	index = indices[i];
801	for (j = 0; j < repeat; j++) {
802	    Permedia2WriteAddress(pScrn, (index << shift)+j);
803	    Permedia2WriteData(pScrn, colors[index].red);
804	    Permedia2WriteData(pScrn, colors[index].green);
805	    Permedia2WriteData(pScrn, colors[index].blue);
806	}
807#if 0
808        GLINT_SLOW_WRITE_REG(index, PM3LUTIndex);
809	GLINT_SLOW_WRITE_REG((colors[index].red & 0xFF) |
810			     ((colors[index].green & 0xFF) << 8) |
811			     ((colors[index].blue & 0xFF) << 16),
812			     PM3LUTData);
813#endif
814    }
815}
816
817/* special one for 565 mode */
818void Permedia3LoadPalette16(
819    ScrnInfoPtr pScrn,
820    int numColors,
821    int *indices,
822    LOCO *colors,
823    VisualPtr pVisual
824){
825#if 0
826    GLINTPtr pGlint = GLINTPTR(pScrn);
827#endif
828    int i, index, j;
829
830    for(i = 0; i < numColors; i++) {
831	index = indices[i];
832	for (j = 0; j < 4; j++) {
833	    Permedia2WriteAddress(pScrn, (index << 2)+j);
834	    Permedia2WriteData(pScrn, colors[index >> 1].red);
835	    Permedia2WriteData(pScrn, colors[index].green);
836	    Permedia2WriteData(pScrn, colors[index >> 1].blue);
837	}
838#if 0
839        GLINT_SLOW_WRITE_REG(index, PM3LUTIndex);
840	GLINT_SLOW_WRITE_REG((colors[index].red & 0xFF) |
841			     ((colors[index].green & 0xFF) << 8) |
842			     ((colors[index].blue & 0xFF) << 16),
843			     PM3LUTData);
844#endif
845
846	if(index <= 31) {
847	    for (j = 0; j < 4; j++) {
848	    	Permedia2WriteAddress(pScrn, (index << 3)+j);
849	    	Permedia2WriteData(pScrn, colors[index].red);
850	    	Permedia2WriteData(pScrn, colors[(index << 1) + 1].green);
851	    	Permedia2WriteData(pScrn, colors[index].blue);
852	    }
853	}
854    }
855}
856