smilynx_hw.c revision eb3dced6
1/*
2Copyright (C) 1994-1999 The XFree86 Project, Inc.  All Rights Reserved.
3Copyright (C) 2000 Silicon Motion, Inc.  All Rights Reserved.
4Copyright (C) 2008 Francisco Jerez. All Rights Reserved.
5
6Permission is hereby granted, free of charge, to any person obtaining a copy of
7this software and associated documentation files (the "Software"), to deal in
8the Software without restriction, including without limitation the rights to
9use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10of the Software, and to permit persons to whom the Software is furnished to do
11so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
18NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the names of The XFree86 Project and
24Silicon Motion shall not be used in advertising or otherwise to promote the
25sale, use or other dealings in this Software without prior written
26authorization from The XFree86 Project or Silicon Motion.
27*/
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include "smi.h"
34#include "smi_crtc.h"
35#include "smilynx.h"
36
37static unsigned int SMILynx_ddc1Read(ScrnInfoPtr pScrn);
38
39Bool
40SMILynx_HWInit(ScrnInfoPtr pScrn)
41{
42    SMIPtr pSmi = SMIPTR(pScrn);
43    SMIRegPtr mode = pSmi->mode;
44    vgaHWPtr	hwp = VGAHWPTR(pScrn);
45    int		vgaIOBase  = hwp->IOBase;
46    int		vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET;
47    int		vgaCRData  = vgaIOBase + VGA_CRTC_DATA_OFFSET;
48
49    ENTER();
50
51    if (pSmi->PCIBurst) {
52	mode->SR17 |= 0x20;
53    } else {
54	mode->SR17 &= ~0x20;
55    }
56
57    /* Gamma correction */
58    if (pSmi->Chipset == SMI_LYNX3DM || pSmi->Chipset == SMI_COUGAR3DR) {
59	if(pScrn->bitsPerPixel == 8)
60	    mode->SR66 = (mode->SR66 & 0x33) | 0x00; /* Both RAMLUT on, 6 bits-RAM */
61	else
62	    mode->SR66 = (mode->SR66 & 0x33) | 0x04; /* Both RAMLUT on, Gamma correct ON */
63    }
64
65    /* Program MCLK */
66    if (pSmi->MCLK > 0)
67	SMI_CommonCalcClock(pScrn->scrnIndex, pSmi->MCLK,
68			    1, 1, 63, 0, 0,
69			    pSmi->clockRange.minClock,
70			    pSmi->clockRange.maxClock,
71			    &mode->SR6A, &mode->SR6B);
72
73    if(!pSmi->useBIOS) {
74	/* Disable DAC and LCD framebuffer r/w operation */
75	mode->SR21 |= 0xB0;
76
77	/* Power down mode is standby mode, VCLK and MCLK divided by 4 in standby mode */
78	mode->SR20  = (mode->SR20 & ~0xB0) | 0x10;
79
80	/* Set DPMS state to Off */
81	mode->SR22 |= 0x30;
82
83	if (pSmi->Chipset != SMI_COUGAR3DR) {
84	    /* Select no displays */
85	    mode->SR31 &= ~0x07;
86
87	    /* Disable virtual refresh */
88	    mode->SR31 &= ~0x80;
89
90	    /* Disable expansion */
91	    mode->SR32 &= ~0x03;
92	    /* Enable autocentering */
93	    if (SMI_LYNXM_SERIES(pSmi->Chipset))
94		mode->SR32 |= 0x04;
95	    else
96		mode->SR32 &= ~0x04;
97
98	    if (pSmi->lcd == 2) /* Panel is DSTN */
99		mode->SR21 = 0x00;
100
101	    /* Enable HW LCD power sequencing */
102	    mode->SR34 |= 0x80;
103	}
104
105	/* Disable Vertical Expansion/Vertical Centering/Horizontal Centering */
106	mode->CR90[0xE] &= ~0x7;
107
108	/* use vclk1 */
109	mode->SR68 = 0x54;
110
111	if(pSmi->Dualhead){
112	    /* set LCD to vclk2 */
113	    mode->SR69 = 0x04;
114	}
115
116	/* Disable panel video */
117	mode->SRA0 = 0;
118
119	mode->CR33 = 0;
120	mode->CR3A = 0;
121    }
122
123    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17, mode->SR17);
124    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20, mode->SR20);
125    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, mode->SR21);
126    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22, mode->SR22);
127    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, mode->SR31);
128    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32, mode->SR32);
129    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x34, mode->SR34);
130    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66, mode->SR66);
131    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x68, mode->SR68);
132    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x69, mode->SR69);
133    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A, mode->SR6A);
134    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B, mode->SR6B);
135    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0, mode->SRA0);
136
137    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, mode->CR33);
138    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A, mode->CR3A);
139    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, mode->CR90[0xE]);
140
141    LEAVE(TRUE);
142}
143
144/*
145 * This function performs the inverse of the restore function: It saves all the
146 * standard and extended registers that we are going to modify to set up a video
147 * mode.
148 */
149
150void
151SMILynx_Save(ScrnInfoPtr pScrn)
152{
153    SMIPtr	pSmi = SMIPTR(pScrn);
154    int		i;
155    CARD32	offset;
156    SMIRegPtr	save = pSmi->save;
157    vgaHWPtr	hwp = VGAHWPTR(pScrn);
158    vgaRegPtr	vgaSavePtr = &hwp->SavedReg;
159    int		vgaIOBase  = hwp->IOBase;
160    int		vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET;
161    int		vgaCRData  = vgaIOBase + VGA_CRTC_DATA_OFFSET;
162
163    ENTER();
164
165    /* Save the standard VGA registers */
166    vgaHWSave(pScrn, vgaSavePtr, VGA_SR_ALL);
167    save->smiDACMask = VGAIN8(pSmi, VGA_DAC_MASK);
168    VGAOUT8(pSmi, VGA_DAC_READ_ADDR, 0);
169    for (i = 0; i < 256; i++) {
170	save->smiDacRegs[i][0] = VGAIN8(pSmi, VGA_DAC_DATA);
171	save->smiDacRegs[i][1] = VGAIN8(pSmi, VGA_DAC_DATA);
172	save->smiDacRegs[i][2] = VGAIN8(pSmi, VGA_DAC_DATA);
173    }
174    for (i = 0, offset = 2; i < 8192; i++, offset += 8)
175	save->smiFont[i] = *(pSmi->FBBase + offset);
176
177    /* Now we save all the extended registers we need. */
178    save->SR17 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17);
179    save->SR18 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18);
180
181    save->SR20 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20);
182    save->SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
183    save->SR22 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22);
184    save->SR23 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23);
185    save->SR24 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x24);
186
187    save->SR31 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31);
188    save->SR32 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32);
189
190    save->SR66 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66);
191    save->SR68 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x68);
192    save->SR69 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x69);
193    save->SR6A = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A);
194    save->SR6B = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B);
195    save->SR6C = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C);
196    save->SR6D = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D);
197
198    save->SR81 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81);
199    save->SRA0 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0);
200
201    if (pSmi->Dualhead) {
202	/* dualhead stuff */
203	save->SR40 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x40);
204	save->SR41 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x41);
205	save->SR42 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x42);
206	save->SR43 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x43);
207	save->SR44 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x44);
208	save->SR45 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x45);
209	save->SR48 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x48);
210	save->SR49 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x49);
211	save->SR4A = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4A);
212	save->SR4B = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4B);
213	save->SR4C = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4C);
214
215	save->SR50 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x50);
216	save->SR51 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x51);
217	save->SR52 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x52);
218	save->SR53 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x53);
219	save->SR54 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x54);
220	save->SR55 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x55);
221	save->SR56 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x56);
222	save->SR57 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x57);
223	save->SR5A = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x5A);
224
225	/* PLL2 stuff */
226	save->SR6E = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6E);
227	save->SR6F = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6F);
228    }
229
230    if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
231	/* Save common registers */
232	save->CR30 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x30);
233	save->CR3A = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A);
234	for (i = 0; i < 15; i++) {
235	    save->CR90[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x90 + i);
236	}
237	for (i = 0; i < 14; i++) {
238	    save->CRA0[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0xA0 + i);
239	}
240
241	/* Save primary registers */
242	VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14] & ~0x20);
243
244	save->CR33 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33);
245	for (i = 0; i < 14; i++) {
246	    save->CR40[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i);
247	}
248	save->CR9F = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9F);
249
250	/* Save secondary registers */
251	VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14] | 0x20);
252	save->CR33_2 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33);
253	for (i = 0; i < 14; i++) {
254	    save->CR40_2[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i);
255	}
256	save->CR9F_2 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9F);
257
258	/* PDR#1069 */
259	VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14]);
260
261    }
262    else {
263	save->CR30 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x30);
264	save->CR33 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33);
265	save->CR3A = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A);
266	for (i = 0; i < 14; i++) {
267	    save->CR40[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i);
268	}
269    }
270
271    save->DPR10 = READ_DPR(pSmi, 0x10);
272    save->DPR1C = READ_DPR(pSmi, 0x1C);
273    save->DPR20 = READ_DPR(pSmi, 0x20);
274    save->DPR24 = READ_DPR(pSmi, 0x24);
275    save->DPR28 = READ_DPR(pSmi, 0x28);
276    save->DPR2C = READ_DPR(pSmi, 0x2C);
277    save->DPR30 = READ_DPR(pSmi, 0x30);
278    save->DPR3C = READ_DPR(pSmi, 0x3C);
279    save->DPR40 = READ_DPR(pSmi, 0x40);
280    save->DPR44 = READ_DPR(pSmi, 0x44);
281
282    save->VPR00 = READ_VPR(pSmi, 0x00);
283    save->VPR0C = READ_VPR(pSmi, 0x0C);
284    save->VPR10 = READ_VPR(pSmi, 0x10);
285
286    if (pSmi->Chipset == SMI_COUGAR3DR) {
287	save->FPR00_ = READ_FPR(pSmi, FPR00);
288	save->FPR0C_ = READ_FPR(pSmi, FPR0C);
289	save->FPR10_ = READ_FPR(pSmi, FPR10);
290    }
291
292    save->CPR00 = READ_CPR(pSmi, 0x00);
293
294    if (!pSmi->ModeStructInit) {
295	vgaHWCopyReg(&hwp->ModeReg, vgaSavePtr);
296	memcpy(pSmi->mode, save, sizeof(SMIRegRec));
297	pSmi->ModeStructInit = TRUE;
298    }
299
300#ifdef USE_INT10
301    if (pSmi->useBIOS && pSmi->pInt10 != NULL) {
302	pSmi->pInt10->num = 0x10;
303	pSmi->pInt10->ax = 0x0F00;
304	xf86ExecX86int10(pSmi->pInt10);
305	save->mode = pSmi->pInt10->ax & 0x007F;
306	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Current mode 0x%02X.\n",
307		   save->mode);
308    }
309#endif
310    if (xf86GetVerbosity() > 1) {
311	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
312		       "Saved current video mode.  Register dump:\n");
313	SMI_PrintRegs(pScrn);
314    }
315
316    LEAVE();
317}
318
319/*
320 * This function is used to restore a video mode. It writes out all of the
321 * standard VGA and extended registers needed to setup a video mode.
322 */
323
324void
325SMILynx_WriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, SMIRegPtr restore)
326{
327    SMIPtr	pSmi = SMIPTR(pScrn);
328    int		i;
329    CARD8	tmp;
330    CARD32	offset;
331    vgaHWPtr	hwp = VGAHWPTR(pScrn);
332    int		vgaIOBase  = hwp->IOBase;
333    int		vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET;
334    int		vgaCRData  = vgaIOBase + VGA_CRTC_DATA_OFFSET;
335
336    ENTER();
337
338    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17, restore->SR17);
339    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18, restore->SR18);
340
341    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20, restore->SR20);
342    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, restore->SR21);
343    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22, restore->SR22);
344    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23, restore->SR23);
345    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x24, restore->SR24);
346
347    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, restore->SR31);
348    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32, restore->SR32);
349
350    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66, restore->SR66);
351    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x68, restore->SR68);
352    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x69, restore->SR69);
353    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A, restore->SR6A);
354    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B, restore->SR6B);
355    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C, restore->SR6C);
356    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D, restore->SR6D);
357
358    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, restore->SR81);
359    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0, restore->SRA0);
360
361    if (pSmi->useBIOS && restore->mode != 0){
362#ifdef USE_INT10
363	pSmi->pInt10->num = 0x10;
364	pSmi->pInt10->ax = restore->mode | 0x80;
365	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode 0x%02X\n",
366		   restore->mode);
367	xf86ExecX86int10(pSmi->pInt10);
368
369	/* Enable linear mode. */
370	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
371	tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
372	outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x01);
373
374	/* Enable DPR/VPR registers. */
375	tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
376	VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03);
377#endif
378    } else {
379	/* Restore the standard VGA registers */
380	vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL);
381	if (restore->smiDACMask) {
382	    VGAOUT8(pSmi, VGA_DAC_MASK, restore->smiDACMask);
383	} else {
384	    VGAOUT8(pSmi, VGA_DAC_MASK, 0xFF);
385	}
386	VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, 0);
387	for (i = 0; i < 256; i++) {
388	    VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][0]);
389	    VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][1]);
390	    VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][2]);
391	}
392	for (i = 0, offset = 2; i < 8192; i++, offset += 8) {
393	    *(pSmi->FBBase + offset) = restore->smiFont[i];
394	}
395
396	if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
397	    /* Restore secondary registers */
398	    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E,
399			  restore->CR90[14] | 0x20);
400
401	    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33_2);
402	    for (i = 0; i < 14; i++) {
403		VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i,
404			      restore->CR40_2[i]);
405	    }
406	    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9F, restore->CR9F_2);
407
408	    /* Restore primary registers */
409	    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E,
410			  restore->CR90[14] & ~0x20);
411
412	    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33);
413	    for (i = 0; i < 14; i++) {
414		VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i,
415			      restore->CR40[i]);
416	    }
417	    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9F, restore->CR9F);
418
419	    /* Restore common registers */
420	    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x30, restore->CR30);
421	    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A, restore->CR3A);
422
423	    for (i = 0; i < 15; i++)
424		VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x90 + i,
425			      restore->CR90[i]);
426
427	    for (i = 0; i < 14; i++)
428		VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0xA0 + i,
429			      restore->CRA0[i]);
430
431	}else{
432	    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x30, restore->CR30);
433	    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33);
434	    VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A, restore->CR3A);
435	    for (i = 0; i < 14; i++) {
436		VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i,
437			      restore->CR40[i]);
438	    }
439	}
440
441	if (pSmi->Dualhead) {
442	    /* dualhead stuff */
443	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x40, restore->SR40);
444	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x41, restore->SR41);
445	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x42, restore->SR42);
446	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x43, restore->SR43);
447	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x44, restore->SR44);
448	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x45, restore->SR45);
449	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x48, restore->SR48);
450	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x49, restore->SR49);
451	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4A, restore->SR4A);
452	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4B, restore->SR4B);
453	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4C, restore->SR4C);
454
455	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x50, restore->SR50);
456	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x51, restore->SR51);
457	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x52, restore->SR52);
458	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x53, restore->SR53);
459	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x54, restore->SR54);
460	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x55, restore->SR55);
461	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x56, restore->SR56);
462	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x57, restore->SR57);
463	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x5A, restore->SR5A);
464
465	    /* PLL2 stuff */
466	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6E, restore->SR6E);
467	    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6F, restore->SR6F);
468	}
469    }
470
471    /* Reset the graphics engine */
472    WRITE_DPR(pSmi, 0x10, restore->DPR10);
473    WRITE_DPR(pSmi, 0x1C, restore->DPR1C);
474    WRITE_DPR(pSmi, 0x20, restore->DPR20);
475    WRITE_DPR(pSmi, 0x24, restore->DPR24);
476    WRITE_DPR(pSmi, 0x28, restore->DPR28);
477    WRITE_DPR(pSmi, 0x2C, restore->DPR2C);
478    WRITE_DPR(pSmi, 0x30, restore->DPR30);
479    WRITE_DPR(pSmi, 0x3C, restore->DPR3C);
480    WRITE_DPR(pSmi, 0x40, restore->DPR40);
481    WRITE_DPR(pSmi, 0x44, restore->DPR44);
482
483    /* write video controller regs */
484    WRITE_VPR(pSmi, 0x00, restore->VPR00);
485    WRITE_VPR(pSmi, 0x0C, restore->VPR0C);
486    WRITE_VPR(pSmi, 0x10, restore->VPR10);
487
488    if(pSmi->Chipset == SMI_COUGAR3DR) {
489	WRITE_FPR(pSmi, FPR00, restore->FPR00_);
490	WRITE_FPR(pSmi, FPR0C, restore->FPR0C_);
491	WRITE_FPR(pSmi, FPR10, restore->FPR10_);
492    }
493
494    WRITE_CPR(pSmi, 0x00, restore->CPR00);
495
496    if (xf86GetVerbosity() > 1) {
497	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
498		       "Done restoring mode.  Register dump:\n");
499	SMI_PrintRegs(pScrn);
500    }
501
502    vgaHWProtect(pScrn, FALSE);
503
504    LEAVE();
505}
506
507
508/*
509 * SMI_DisplayPowerManagementSet -- Sets VESA Display Power Management
510 * Signaling (DPMS) Mode.
511 */
512void
513SMILynx_DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
514							  int flags)
515{
516    SMIPtr	pSmi = SMIPTR(pScrn);
517    SMIRegPtr	mode = pSmi->mode;
518    vgaHWPtr	hwp = VGAHWPTR(pScrn);
519
520    ENTER();
521
522    /* If we already are in the requested DPMS mode, just return */
523    if (pSmi->CurrentDPMS != PowerManagementMode) {
524	/* Read the required SR registers for the DPMS handler */
525	CARD8 SR01 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01);
526
527	switch (PowerManagementMode) {
528	    case DPMSModeOn:
529		SR01 &= ~0x20; /* Screen on */
530		mode->SR23 &= ~0xC0; /* Disable chip activity detection */
531		break;
532	    case DPMSModeStandby:
533	    case DPMSModeSuspend:
534	    case DPMSModeOff:
535		SR01 |= 0x20; /* Screen off */
536		mode->SR23 = (mode->SR23 & ~0x07) | 0xD8; /* Enable chip activity detection
537							     Enable internal auto-standby mode
538							     Enable both IO Write and Host Memory write detect
539							     0 minutes timeout */
540		break;
541	}
542
543	/* Wait for vertical retrace */
544	while (hwp->readST01(hwp) & 0x8) ;
545	while (!(hwp->readST01(hwp) & 0x8)) ;
546
547	/* Write the registers */
548	VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01, SR01);
549	VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23, mode->SR23);
550
551	/* Set the DPMS mode to every output and CRTC */
552	xf86DPMSSet(pScrn, PowerManagementMode, flags);
553
554	/* Save the current power state */
555	pSmi->CurrentDPMS = PowerManagementMode;
556    }
557
558    LEAVE();
559}
560
561static unsigned int
562SMILynx_ddc1Read(ScrnInfoPtr pScrn)
563{
564    register vgaHWPtr hwp = VGAHWPTR(pScrn);
565    SMIPtr pSmi = SMIPTR(pScrn);
566    unsigned int ret;
567
568    ENTER();
569
570    while (hwp->readST01(hwp) & 0x8) ;
571    while (!(hwp->readST01(hwp) & 0x8)) ;
572
573    ret = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72) & 0x08;
574
575    LEAVE(ret);
576}
577
578xf86MonPtr
579SMILynx_ddc1(ScrnInfoPtr pScrn)
580{
581    SMIPtr pSmi = SMIPTR(pScrn);
582    xf86MonPtr pMon;
583    unsigned char tmp;
584
585    ENTER();
586
587    tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72);
588    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72, tmp | 0x20);
589
590    pMon = xf86PrintEDID(xf86DoEDID_DDC1(pScrn->scrnIndex,
591					 vgaHWddc1SetSpeedWeak(),
592					 SMILynx_ddc1Read));
593    VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72, tmp);
594
595    LEAVE(pMon);
596}
597
598
599/* This function is used to debug, it prints out the contents of Lynx regs */
600void
601SMILynx_PrintRegs(ScrnInfoPtr pScrn)
602{
603    unsigned char i;
604    SMIPtr pSmi = SMIPTR(pScrn);
605    vgaHWPtr hwp = VGAHWPTR(pScrn);
606    int vgaCRIndex = hwp->IOBase + VGA_CRTC_INDEX_OFFSET;
607    int vgaCRReg   = hwp->IOBase + VGA_CRTC_DATA_OFFSET;
608    int vgaStatus  = hwp->IOBase + VGA_IN_STAT_1_OFFSET;
609
610    xf86ErrorFVerb(VERBLEV, "MISCELLANEOUS OUTPUT\n    %02X\n",
611		   VGAIN8(pSmi, VGA_MISC_OUT_R));
612
613    xf86ErrorFVerb(VERBLEV, "\nSEQUENCER\n"
614		   "    x0 x1 x2 x3  x4 x5 x6 x7  x8 x9 xA xB  xC xD xE xF");
615    for (i = 0x00; i <= 0xAF; i++) {
616	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
617	if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
618	xf86ErrorFVerb(VERBLEV, "%02X ",
619		       VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, i));
620    }
621
622    xf86ErrorFVerb(VERBLEV, "\n\nCRT CONTROLLER\n"
623		   "    x0 x1 x2 x3  x4 x5 x6 x7  x8 x9 xA xB  xC xD xE xF");
624    for (i = 0x00; i <= 0xAD; i++) {
625	if (i == 0x20) i = 0x30;
626	if (i == 0x50) i = 0x90;
627	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
628	if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
629	xf86ErrorFVerb(VERBLEV, "%02X ",
630		       VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRReg, i));
631    }
632
633    xf86ErrorFVerb(VERBLEV, "\n\nGRAPHICS CONTROLLER\n"
634		   "    x0 x1 x2 x3  x4 x5 x6 x7  x8 x9 xA xB  xC xD xE xF");
635    for (i = 0x00; i <= 0x08; i++) {
636	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
637	if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
638	xf86ErrorFVerb(VERBLEV, "%02X ",
639		       VGAIN8_INDEX(pSmi, VGA_GRAPH_INDEX, VGA_GRAPH_DATA, i));
640    }
641
642    xf86ErrorFVerb(VERBLEV, "\n\nATTRIBUTE 0CONTROLLER\n"
643		   "    x0 x1 x2 x3  x4 x5 x6 x7  x8 x9 xA xB  xC xD xE xF");
644    for (i = 0x00; i <= 0x14; i++) {
645	(void) VGAIN8(pSmi, vgaStatus);
646	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
647	if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
648	xf86ErrorFVerb(VERBLEV, "%02X ",
649		       VGAIN8_INDEX(pSmi, VGA_ATTR_INDEX, VGA_ATTR_DATA_R, i));
650    }
651    (void) VGAIN8(pSmi, vgaStatus);
652    VGAOUT8(pSmi, VGA_ATTR_INDEX, 0x20);
653}
654