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