pm_dac.c revision c35d236e
1/*
2 * Copyright 1997-2001 by Alan Hourihane <alanh@fairlite.demon.co.uk>
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 Alan Hourihane not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Alan Hourihane 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 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ALAN HOURIHANE 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:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
23 *           Dirk Hohndel,   <hohndel@suse.de>
24 *	     Stefan Dirsch,  <sndirsch@suse.de>
25 *	     Helmut Fahrion, <hf@suse.de>
26 *
27 * this work is sponsored by S.u.S.E. GmbH, Fuerth, Elsa GmbH, Aachen and
28 * Siemens Nixdorf Informationssysteme
29 */
30/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/glint/pm_dac.c,v 1.11tsi Exp $ */
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#include "xf86.h"
37#include "xf86_OSproc.h"
38
39#include "xf86PciInfo.h"
40#include "xf86Pci.h"
41
42#include "IBM.h"
43#include "TI.h"
44#include "glint_regs.h"
45#include "glint.h"
46
47Bool
48PermediaInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
49{
50    GLINTPtr pGlint = GLINTPTR(pScrn);
51    GLINTRegPtr pReg = &pGlint->ModeReg[0];
52    RamDacHWRecPtr pIBM = RAMDACHWPTR(pScrn);
53    RamDacRegRecPtr ramdacReg = &pIBM->ModeReg;
54    CARD32 temp1, temp2, temp3, temp4;
55
56    STOREREG(Aperture0, 0x00000000);
57    STOREREG(Aperture1, 0x00000000);
58
59    pReg->glintRegs[PMFramebufferWriteMask >> 3] = 0xFFFFFFFF;
60    pReg->glintRegs[PMBypassWriteMask >> 3] = 0xFFFFFFFF;
61
62    pReg->glintRegs[DFIFODis >> 3] = 1;
63    pReg->glintRegs[FIFODis >> 3] = 3;
64
65    temp1 = mode->CrtcHSyncStart - mode->CrtcHDisplay;
66    temp2 = mode->CrtcVSyncStart - mode->CrtcVDisplay;
67    temp3 = mode->CrtcHSyncEnd - mode->CrtcHSyncStart;
68    temp4 = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
69
70    pReg->glintRegs[PMHTotal >> 3] = Shiftbpp(pScrn,mode->CrtcHTotal);
71    pReg->glintRegs[PMHsEnd >> 3] = Shiftbpp(pScrn, temp1 + temp3);
72    pReg->glintRegs[PMHsStart >> 3] = Shiftbpp(pScrn, temp1);
73    pReg->glintRegs[PMHbEnd >> 3] = Shiftbpp(pScrn, mode->CrtcHTotal -
74							mode->CrtcHDisplay);
75    pReg->glintRegs[PMHgEnd >> 3] = Shiftbpp(pScrn, mode->CrtcHTotal -
76							mode->CrtcHDisplay);
77    pReg->glintRegs[PMScreenStride >> 3] =
78					Shiftbpp(pScrn,pScrn->displayWidth>>1);
79
80    pReg->glintRegs[PMVTotal >> 3] = mode->CrtcVTotal;
81    pReg->glintRegs[PMVsEnd >> 3] = temp2 + temp4;
82    pReg->glintRegs[PMVsStart >> 3] = temp2;
83    pReg->glintRegs[PMVbEnd >> 3] = mode->CrtcVTotal - mode->CrtcVDisplay;
84
85    pReg->glintRegs[PMVideoControl >> 3] =
86 	    (((mode->Flags & V_PHSYNC) ? 0x1 : 0x3) << 3) |
87 	    (((mode->Flags & V_PVSYNC) ? 0x1 : 0x3) << 5) | 1;
88
89    pReg->glintRegs[VClkCtl >> 3] = 3;
90    pReg->glintRegs[PMScreenBase >> 3] = 0;
91    pReg->glintRegs[PMHTotal >> 3] -= 1; /* PMHTotal */
92    pReg->glintRegs[PMHsStart >> 3] -= 1; /* PMHsStart */
93    pReg->glintRegs[PMVTotal >> 3] -= 1; /* PMVTotal */
94    pReg->glintRegs[ChipConfig >> 3] = GLINT_READ_REG(ChipConfig) & 0xFFFFFFFD;
95
96    switch(pGlint->RamDac->RamDacType) {
97    case IBM526_RAMDAC:
98    case IBM526DB_RAMDAC:
99    {
100	/* Get the programmable clock values */
101    	unsigned long m=0,n=0,p=0,c=0;
102
103	(void) IBMramdac526CalculateMNPCForClock(pGlint->RefClock, mode->Clock,
104			1, pGlint->MinClock, pGlint->MaxClock, &m, &n, &p, &c);
105
106	ramdacReg->DacRegs[IBMRGB_m0] = m;
107	ramdacReg->DacRegs[IBMRGB_n0] = n;
108	ramdacReg->DacRegs[IBMRGB_p0] = p;
109	ramdacReg->DacRegs[IBMRGB_c0] = c;
110
111	ramdacReg->DacRegs[IBMRGB_pll_ctrl1] = 0x05;
112	ramdacReg->DacRegs[IBMRGB_pll_ctrl2] = 0x00;
113
114	p = 1;
115	(void) IBMramdac526CalculateMNPCForClock(pGlint->RefClock, mode->Clock,
116			0, pGlint->MinClock, pGlint->MaxClock, &m, &n, &p, &c);
117
118	ramdacReg->DacRegs[IBMRGB_sysclk] = 0x05;
119	ramdacReg->DacRegs[IBMRGB_sysclk_m] = m;
120	ramdacReg->DacRegs[IBMRGB_sysclk_n] = n;
121	ramdacReg->DacRegs[IBMRGB_sysclk_p] = p;
122	ramdacReg->DacRegs[IBMRGB_sysclk_c] = c;
123    }
124    ramdacReg->DacRegs[IBMRGB_misc1] = SENS_DSAB_DISABLE | VRAM_SIZE_32;
125    ramdacReg->DacRegs[IBMRGB_misc2] = COL_RES_8BIT | PORT_SEL_VRAM;
126    if (pScrn->depth >= 24)
127	ramdacReg->DacRegs[IBMRGB_misc2] |= PCLK_SEL_LCLK;
128    else
129	ramdacReg->DacRegs[IBMRGB_misc2] |= PCLK_SEL_PLL;
130    ramdacReg->DacRegs[IBMRGB_misc3] = 0;
131    ramdacReg->DacRegs[IBMRGB_misc_clock] = 1;
132    ramdacReg->DacRegs[IBMRGB_sync] = 0;
133    ramdacReg->DacRegs[IBMRGB_hsync_pos] = 0;
134    ramdacReg->DacRegs[IBMRGB_pwr_mgmt] = 0;
135    ramdacReg->DacRegs[IBMRGB_dac_op] = 0;
136    ramdacReg->DacRegs[IBMRGB_pal_ctrl] = 0;
137    break;
138    case TI3026_RAMDAC:
139    {
140	/* Get the programmable clock values */
141	unsigned long m=0,n=0,p=0;
142	unsigned long clock;
143	unsigned long q, VCO = 0;
144
145	clock = TIramdacCalculateMNPForClock(pGlint->RefClock,
146		mode->Clock, 1, pGlint->MinClock, pGlint->MaxClock, &m, &n, &p);
147
148	STORERAMDAC(TIDAC_PIXEL_N, ((n & 0x3f) | 0xC0));
149	STORERAMDAC(TIDAC_PIXEL_M,  (m & 0x3f));
150	STORERAMDAC(TIDAC_PIXEL_P, ((p & 0x03) | 0xbc));
151	STORERAMDAC(TIDAC_PIXEL_VALID, TRUE);
152
153    	if (pGlint->RamDac->RamDacType == (TI3026_RAMDAC))
154            n = 65 - ((32 << 2) / pScrn->bitsPerPixel);
155	else
156            n = 65 - ((128 << 2) / pScrn->bitsPerPixel);
157	m = 61;
158	p = 0;
159	for (q = 0; q < 8; q++) {
160	    if (q > 0) p = 3;
161	    for ( ; p < 4; p++) {
162		VCO = ((clock * (q + 1) * (65 - m)) / (65 - n)) << (p + 1);
163		if (VCO >= 110000) { break; }
164	    }
165	    if (VCO >= 110000) { break; }
166	}
167	STORERAMDAC(TIDAC_clock_ctrl, (q | 0x38));
168
169	STORERAMDAC(TIDAC_LOOP_N, ((n & 0x3f) | 0xC0));
170	STORERAMDAC(TIDAC_LOOP_M,  (m & 0x3f));
171	STORERAMDAC(TIDAC_LOOP_P, ((p & 0x03) | 0xF0));
172	STORERAMDAC(TIDAC_LOOP_VALID, TRUE);
173	break;
174    }
175    }
176
177    (*pGlint->RamDac->SetBpp)(pScrn, ramdacReg);
178
179    /* The permedia uses a 32bit data path, the TI ramdac code
180     * defaults to 64bit. So we knock it down to 32bit here */
181    if (pGlint->RamDac->RamDacType == (TI3026_RAMDAC))
182	ramdacReg->DacRegs[TIDAC_multiplex_ctrl] -= 1;
183
184    return(TRUE);
185}
186
187void
188PermediaSave(ScrnInfoPtr pScrn, GLINTRegPtr glintReg)
189{
190    GLINTPtr pGlint = GLINTPTR(pScrn);
191
192    /* We can't rely on the vgahw layer copying the font information
193     * back properly, due to problems with MMIO access to VGA space
194     * so we memcpy the information using the slow routines */
195    xf86SlowBcopy((CARD8*)pGlint->FbBase, (CARD8*)pGlint->VGAdata, 65536);
196
197    glintReg->glintRegs[Aperture0 >> 3]  = GLINT_READ_REG(Aperture0);
198    glintReg->glintRegs[Aperture1 >> 3]  = GLINT_READ_REG(Aperture1);
199    glintReg->glintRegs[PMFramebufferWriteMask] =
200					GLINT_READ_REG(PMFramebufferWriteMask);
201    glintReg->glintRegs[PMBypassWriteMask >> 3] =
202					GLINT_READ_REG(PMBypassWriteMask);
203    glintReg->glintRegs[DFIFODis >> 3]  = GLINT_READ_REG(DFIFODis);
204    glintReg->glintRegs[FIFODis >> 3]  = GLINT_READ_REG(FIFODis);
205
206    glintReg->glintRegs[PMHTotal >> 3] = GLINT_READ_REG(PMHTotal);
207    glintReg->glintRegs[PMHbEnd >> 3] = GLINT_READ_REG(PMHbEnd);
208    glintReg->glintRegs[PMHgEnd >> 3] = GLINT_READ_REG(PMHgEnd);
209    glintReg->glintRegs[PMScreenStride >> 3] = GLINT_READ_REG(PMScreenStride);
210    glintReg->glintRegs[PMHsStart >> 3] = GLINT_READ_REG(PMHsStart);
211    glintReg->glintRegs[PMHsEnd >> 3] = GLINT_READ_REG(PMHsEnd);
212    glintReg->glintRegs[PMVTotal >> 3] = GLINT_READ_REG(PMVTotal);
213    glintReg->glintRegs[PMVbEnd >> 3] = GLINT_READ_REG(PMVbEnd);
214    glintReg->glintRegs[PMVsStart >> 3] = GLINT_READ_REG(PMVsStart);
215    glintReg->glintRegs[PMVsEnd >> 3] = GLINT_READ_REG(PMVsEnd);
216    glintReg->glintRegs[PMScreenBase >> 3] = GLINT_READ_REG(PMScreenBase);
217    glintReg->glintRegs[PMVideoControl >> 3] = GLINT_READ_REG(PMVideoControl);
218    glintReg->glintRegs[VClkCtl >> 3] = GLINT_READ_REG(VClkCtl);
219    glintReg->glintRegs[ChipConfig >> 3] = GLINT_READ_REG(ChipConfig);
220}
221
222void
223PermediaRestore(ScrnInfoPtr pScrn, GLINTRegPtr pReg)
224{
225    GLINTPtr pGlint = GLINTPTR(pScrn);
226
227    /* We can't rely on the vgahw layer copying the font information
228     * back properly, due to problems with MMIO access to VGA space
229     * so we memcpy the information using the slow routines */
230    if (pGlint->STATE)
231	xf86SlowBcopy((CARD8*)pGlint->VGAdata, (CARD8*)pGlint->FbBase, 65536);
232
233    RESTOREREG(ChipConfig);
234    RESTOREREG(DFIFODis);
235    RESTOREREG(FIFODis);
236    RESTOREREG(Aperture0);
237    RESTOREREG(Aperture1);
238    RESTOREREG(PMFramebufferWriteMask);
239    RESTOREREG(PMBypassWriteMask);
240    RESTOREREG(PMVideoControl);
241    RESTOREREG(PMHgEnd);
242    RESTOREREG(VClkCtl);
243    RESTOREREG(PMHTotal);
244    RESTOREREG(PMHbEnd);
245    RESTOREREG(PMHsStart);
246    RESTOREREG(PMHsEnd);
247    RESTOREREG(PMVTotal);
248    RESTOREREG(PMVbEnd);
249    RESTOREREG(PMVsStart);
250    RESTOREREG(PMVsEnd);
251    RESTOREREG(PMScreenBase);
252    RESTOREREG(PMScreenStride);
253}
254