2
* Copyright 1999 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
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 copyright
7
* notice and this permission notice appear in supporting documentation, and
8
* that the name of Marc Aurele La France not be used in advertising or
9
* publicity pertaining to distribution of the software without specific,
10
* written prior permission. Marc Aurele La France makes no representations
11
* about the suitability of this software for any purpose. It is provided
12
* "as-is" without express or implied warranty.
14
* MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
16
* EVENT SHALL MARC AURELE LA FRANCE 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.
30
#include "atimach64io.h"
31
#include "atiwonderio.h"
36
* This function is entered to unlock registers and disable unwanted
37
* emulations. It saves the current state for later restoration by ATILock().
49
CARD32 saved_lcd_gen_ctrl = 0, lcd_gen_ctrl = 0;
51
#endif /* AVOID_CPIO */
55
pATI->Unlocked = TRUE;
58
/* Reset everything */
59
pATI->LockData.bus_cntl = inr(BUS_CNTL);
60
if (pATI->Chip < ATI_CHIP_264VT4)
62
pATI->LockData.bus_cntl =
63
(pATI->LockData.bus_cntl & ~BUS_HOST_ERR_INT_EN) |
65
if (pATI->Chip < ATI_CHIP_264VTB)
66
pATI->LockData.bus_cntl =
67
(pATI->LockData.bus_cntl & ~BUS_FIFO_ERR_INT_EN) |
70
tmp = pATI->LockData.bus_cntl & ~BUS_ROM_DIS;
71
if (pATI->Chip < ATI_CHIP_264VTB)
72
tmp |= SetBits(15, BUS_FIFO_WS);
74
tmp &= ~BUS_MASTER_DIS;
75
if (pATI->Chip >= ATI_CHIP_264VT)
76
tmp |= BUS_EXT_REG_EN; /* Enable Block 1 */
78
pATI->LockData.crtc_int_cntl = inr(CRTC_INT_CNTL);
79
outr(CRTC_INT_CNTL, (pATI->LockData.crtc_int_cntl & ~CRTC_INT_ENS) |
85
outr(CRTC_INT_CNTL, (inr(CRTC_INT_CNTL) & ~CRTC_INT_ACKS) |
86
CRTC_VBLANK_INT_EN); /* Enable VBLANK interrupt - handled by DRM */
88
#endif /* XF86DRI_DEVEL */
90
pATI->LockData.gen_test_cntl = inr(GEN_TEST_CNTL) &
91
(GEN_OVR_OUTPUT_EN | GEN_OVR_POLARITY | GEN_CUR_EN |
93
tmp = pATI->LockData.gen_test_cntl & ~GEN_CUR_EN;
94
outr(GEN_TEST_CNTL, tmp | GEN_GUI_EN);
95
outr(GEN_TEST_CNTL, tmp);
96
outr(GEN_TEST_CNTL, tmp | GEN_GUI_EN);
97
tmp = pATI->LockData.crtc_gen_cntl = inr(CRTC_GEN_CNTL) &
98
~(CRTC_EN | CRTC_LOCK_REGS);
99
if (pATI->Chip >= ATI_CHIP_264XL)
100
tmp = (tmp & ~CRTC_INT_ENS_X) | CRTC_INT_ACKS_X;
101
outr(CRTC_GEN_CNTL, tmp | CRTC_EN);
102
outr(CRTC_GEN_CNTL, tmp);
103
outr(CRTC_GEN_CNTL, tmp | CRTC_EN);
104
if ((pATI->LCDPanelID >= 0) && (pATI->Chip != ATI_CHIP_264LT))
106
pATI->LockData.lcd_index = inr(LCD_INDEX);
107
if (pATI->Chip >= ATI_CHIP_264XL)
108
outr(LCD_INDEX, pATI->LockData.lcd_index &
109
~(LCD_MONDET_INT_EN | LCD_MONDET_INT));
112
* Prevent BIOS initiated display switches on dual-CRT controllers.
114
if (!pATI->OptionBIOSDisplay && (pATI->Chip != ATI_CHIP_264XL))
117
pATI->LockData.scratch_reg3 = inr(SCRATCH_REG3) & ~DISPLAY_SWITCH_DISABLE;
118
outr(SCRATCH_REG3, pATI->LockData.scratch_reg3);
120
pATI->LockData.scratch_reg3 = inr(SCRATCH_REG3);
122
pATI->LockData.scratch_reg3 | DISPLAY_SWITCH_DISABLE);
127
pATI->LockData.mem_cntl = inr(MEM_CNTL);
128
if (pATI->Chip < ATI_CHIP_264CT)
129
outr(MEM_CNTL, pATI->LockData.mem_cntl &
130
~(CTL_MEM_BNDRY | CTL_MEM_BNDRY_EN));
132
/* Disable feature connector on integrated controllers */
133
tmp = pATI->LockData.dac_cntl = inr(DAC_CNTL);
134
if (pATI->Chip >= ATI_CHIP_264CT)
135
tmp &= ~DAC_FEA_CON_EN;
139
/* Ensure VGA aperture is enabled */
140
pATI->LockData.config_cntl = inr(CONFIG_CNTL);
141
tmp |= DAC_VGA_ADR_EN;
142
outr(CONFIG_CNTL, pATI->LockData.config_cntl & ~CFG_VGA_DIS);
144
#endif /* AVOID_CPIO */
148
if (pATI->Chip >= ATI_CHIP_264VTB)
150
pATI->LockData.mpp_config = inr(MPP_CONFIG);
151
pATI->LockData.mpp_strobe_seq = inr(MPP_STROBE_SEQ);
152
pATI->LockData.tvo_cntl = inr(TVO_CNTL);
154
if (pATI->Chip >= ATI_CHIP_264GT2C)
156
pATI->LockData.hw_debug = inr(HW_DEBUG);
158
if (pATI->Chip >= ATI_CHIP_264GTPRO)
160
if (!(pATI->LockData.hw_debug & CMDFIFO_SIZE_EN))
162
pATI->LockData.hw_debug | CMDFIFO_SIZE_EN);
164
pATI->LockData.i2c_cntl_0 =
165
inr(I2C_CNTL_0) | (I2C_CNTL_STAT | I2C_CNTL_HPTR_RST);
167
pATI->LockData.i2c_cntl_0 & ~I2C_CNTL_INT_EN);
168
pATI->LockData.i2c_cntl_1 = inr(I2C_CNTL_1);
172
if (pATI->LockData.hw_debug & CMDFIFO_SIZE_DIS)
174
pATI->LockData.hw_debug & ~CMDFIFO_SIZE_DIS);
182
if (pATI->VGAAdapter)
184
if (pATI->CPIO_VGAWonder)
187
* Ensure all registers are read/write and disable all non-VGA
190
pATI->LockData.b1 = ATIGetExtReg(0xB1U);
191
ATIModifyExtReg(pATI, 0xB1U, pATI->LockData.b1, 0xFCU, 0x00U);
192
pATI->LockData.b4 = ATIGetExtReg(0xB4U);
193
ATIModifyExtReg(pATI, 0xB4U, pATI->LockData.b4, 0x00U, 0x00U);
194
pATI->LockData.b5 = ATIGetExtReg(0xB5U);
195
ATIModifyExtReg(pATI, 0xB5U, pATI->LockData.b5, 0xBFU, 0x00U);
196
pATI->LockData.b6 = ATIGetExtReg(0xB6U);
197
ATIModifyExtReg(pATI, 0xB6U, pATI->LockData.b6, 0xDDU, 0x00U);
198
pATI->LockData.b8 = ATIGetExtReg(0xB8U);
199
ATIModifyExtReg(pATI, 0xB8U, pATI->LockData.b8, 0xC0U, 0x00U);
200
pATI->LockData.b9 = ATIGetExtReg(0xB9U);
201
ATIModifyExtReg(pATI, 0xB9U, pATI->LockData.b9, 0x7FU, 0x00U);
203
pATI->LockData.be = ATIGetExtReg(0xBEU);
204
ATIModifyExtReg(pATI, 0xBEU, pATI->LockData.be, 0xFAU, 0x01U);
206
pATI->LockData.a6 = ATIGetExtReg(0xA6U);
207
ATIModifyExtReg(pATI, 0xA6U, pATI->LockData.a6,
209
pATI->LockData.ab = ATIGetExtReg(0xABU);
210
ATIModifyExtReg(pATI, 0xABU, pATI->LockData.ab,
216
if (pATI->LCDPanelID >= 0)
218
if (pATI->Chip == ATI_CHIP_264LT)
220
saved_lcd_gen_ctrl = inr(LCD_GEN_CTRL);
222
/* Setup to unlock non-shadow registers */
223
lcd_gen_ctrl = saved_lcd_gen_ctrl & ~SHADOW_RW_EN;
224
outr(LCD_GEN_CTRL, lcd_gen_ctrl);
226
else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
227
(pATI->Chip == ATI_CHIP_264XL) ||
228
(pATI->Chip == ATI_CHIP_MOBILITY)) */
230
saved_lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL);
232
/* Setup to unlock non-shadow registers */
233
lcd_gen_ctrl = saved_lcd_gen_ctrl &
234
~(CRTC_RW_SELECT | SHADOW_RW_EN);
235
ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
239
ATISetVGAIOBase(pATI, inb(R_GENMO));
242
* There's a bizarre interaction here. If bit 0x80 of CRTC[17] is on,
243
* then CRTC[3] is read-only. If bit 0x80 of CRTC[3] is off, then
244
* CRTC[17] is write-only (or a read attempt actually returns bits from
245
* C/EGA's light pen position). This means that if both conditions are
246
* met, CRTC[17]'s value on server entry cannot be retrieved.
249
pATI->LockData.crt03 = tmp = GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
251
((outb(CRTD(pATI->CPIO_VGABase), tmp | 0x80U),
252
tmp = inb(CRTD(pATI->CPIO_VGABase))) & 0x80U))
254
/* CRTC[16-17] should be readable */
255
pATI->LockData.crt11 = tmp =
256
GetReg(CRTX(pATI->CPIO_VGABase), 0x11U);
257
if (tmp & 0x80U) /* Unprotect CRTC[0-7] */
258
outb(CRTD(pATI->CPIO_VGABase), tmp & 0x7FU);
263
* Could not make CRTC[17] readable, so unprotect CRTC[0-7]
264
* replacing VSyncEnd with zero. This zero will be replaced after
265
* acquiring the needed access.
267
unsigned int VSyncEnd, VBlankStart, VBlankEnd;
270
PutReg(CRTX(pATI->CPIO_VGABase), 0x11U, 0x20U);
271
/* Make CRTC[16-17] readable */
272
PutReg(CRTX(pATI->CPIO_VGABase), 0x03U, tmp | 0x80U);
273
/* Make vertical synch pulse as wide as possible */
274
crt07 = GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
275
crt09 = GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
276
VBlankStart = (((crt09 & 0x20U) << 4) | ((crt07 & 0x08U) << 5) |
277
GetReg(CRTX(pATI->CPIO_VGABase), 0x15U)) + 1;
278
VBlankEnd = (VBlankStart & 0x0300U) |
279
GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
280
if (VBlankEnd <= VBlankStart)
281
VBlankEnd += 0x0100U;
282
VSyncEnd = (((crt07 & 0x80U) << 2) | ((crt07 & 0x04U) << 6) |
283
GetReg(CRTX(pATI->CPIO_VGABase), 0x10U)) + 0x0FU;
284
if (VSyncEnd >= VBlankEnd)
285
VSyncEnd = VBlankEnd - 1;
286
pATI->LockData.crt11 = (VSyncEnd & 0x0FU) | 0x20U;
287
PutReg(CRTX(pATI->CPIO_VGABase), 0x11U, pATI->LockData.crt11);
288
pATI->LockData.crt11 |= 0x80U;
291
if (pATI->LCDPanelID >= 0)
293
/* Setup to unlock shadow registers */
294
lcd_gen_ctrl |= SHADOW_RW_EN;
296
if (pATI->Chip == ATI_CHIP_264LT)
297
outr(LCD_GEN_CTRL, lcd_gen_ctrl);
298
else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
299
(pATI->Chip == ATI_CHIP_264XL) ||
300
(pATI->Chip == ATI_CHIP_MOBILITY)) */
301
ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
303
/* Unlock shadow registers */
304
ATISetVGAIOBase(pATI, inb(R_GENMO));
306
pATI->LockData.shadow_crt03 = tmp =
307
GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
309
((outb(CRTD(pATI->CPIO_VGABase), tmp | 0x80U),
310
tmp = inb(CRTD(pATI->CPIO_VGABase))) & 0x80U))
312
/* CRTC[16-17] should be readable */
313
pATI->LockData.shadow_crt11 = tmp =
314
GetReg(CRTX(pATI->CPIO_VGABase), 0x11U);
315
if (tmp & 0x80U) /* Unprotect CRTC[0-7] */
317
outb(CRTD(pATI->CPIO_VGABase), tmp & 0x7FU);
319
else if (!tmp && pATI->LockData.crt11)
321
pATI->LockData.shadow_crt11 = tmp = pATI->LockData.crt11;
322
outb(CRTD(pATI->CPIO_VGABase), tmp & 0x7FU);
328
* Could not make CRTC[17] readable, so unprotect CRTC[0-7]
329
* replacing VSyncEnd with zero. This zero will be replaced
330
* after acquiring the needed access.
332
unsigned int VSyncEnd, VBlankStart, VBlankEnd;
335
PutReg(CRTX(pATI->CPIO_VGABase), 0x11U, 0x20U);
336
/* Make CRTC[16-17] readable */
337
PutReg(CRTX(pATI->CPIO_VGABase), 0x03U, tmp | 0x80U);
338
/* Make vertical synch pulse as wide as possible */
339
crt07 = GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
340
crt09 = GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
341
VBlankStart = (((crt09 & 0x20U) << 4) |
342
((crt07 & 0x08U) << 5) |
343
GetReg(CRTX(pATI->CPIO_VGABase), 0x15U)) + 1;
344
VBlankEnd = (VBlankStart & 0x0300U) |
345
GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
346
if (VBlankEnd <= VBlankStart)
347
VBlankEnd += 0x0100U;
348
VSyncEnd = (((crt07 & 0x80U) << 2) | ((crt07 & 0x04U) << 6) |
349
GetReg(CRTX(pATI->CPIO_VGABase), 0x10U)) + 0x0FU;
350
if (VSyncEnd >= VBlankEnd)
351
VSyncEnd = VBlankEnd - 1;
352
pATI->LockData.shadow_crt11 = (VSyncEnd & 0x0FU) | 0x20U;
353
PutReg(CRTX(pATI->CPIO_VGABase), 0x11U,
354
pATI->LockData.shadow_crt11);
355
pATI->LockData.shadow_crt11 |= 0x80U;
358
/* Restore selection */
359
if (pATI->Chip == ATI_CHIP_264LT)
361
outr(LCD_GEN_CTRL, saved_lcd_gen_ctrl);
363
else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
364
(pATI->Chip == ATI_CHIP_264XL) ||
365
(pATI->Chip == ATI_CHIP_MOBILITY)) */
367
ATIMach64PutLCDReg(LCD_GEN_CNTL, saved_lcd_gen_ctrl);
369
/* Restore LCD index */
370
out8(LCD_INDEX, GetByte(pATI->LockData.lcd_index, 0));
375
#endif /* AVOID_CPIO */
382
* This function restores the state saved by ATIUnlock() above.
393
CARD32 saved_lcd_gen_ctrl = 0, lcd_gen_ctrl = 0;
395
#endif /* AVOID_CPIO */
399
pATI->Unlocked = FALSE;
403
if (pATI->VGAAdapter)
405
if (pATI->LCDPanelID >= 0)
407
if (pATI->Chip == ATI_CHIP_264LT)
409
saved_lcd_gen_ctrl = inr(LCD_GEN_CTRL);
411
/* Setup to lock non-shadow registers */
412
lcd_gen_ctrl = saved_lcd_gen_ctrl & ~SHADOW_RW_EN;
413
outr(LCD_GEN_CTRL, lcd_gen_ctrl);
415
else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
416
(pATI->Chip == ATI_CHIP_264XL) ||
417
(pATI->Chip == ATI_CHIP_MOBILITY)) */
419
saved_lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL);
421
/* Setup to lock non-shadow registers */
422
lcd_gen_ctrl = saved_lcd_gen_ctrl &
423
~(CRTC_RW_SELECT | SHADOW_RW_EN);
424
ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
428
ATISetVGAIOBase(pATI, inb(R_GENMO));
430
/* Restore VGA locks */
431
PutReg(CRTX(pATI->CPIO_VGABase), 0x03U, pATI->LockData.crt03);
432
PutReg(CRTX(pATI->CPIO_VGABase), 0x11U, pATI->LockData.crt11);
434
if (pATI->LCDPanelID >= 0)
436
/* Setup to lock shadow registers */
437
lcd_gen_ctrl |= SHADOW_RW_EN;
439
if (pATI->Chip == ATI_CHIP_264LT)
440
outr(LCD_GEN_CTRL, lcd_gen_ctrl);
441
else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
442
(pATI->Chip == ATI_CHIP_264XL) ||
443
(pATI->Chip == ATI_CHIP_MOBILITY)) */
444
ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl);
446
/* Lock shadow registers */
447
ATISetVGAIOBase(pATI, inb(R_GENMO));
449
PutReg(CRTX(pATI->CPIO_VGABase), 0x03U,
450
pATI->LockData.shadow_crt03);
451
PutReg(CRTX(pATI->CPIO_VGABase), 0x11U,
452
pATI->LockData.shadow_crt11);
454
/* Restore selection */
455
if (pATI->Chip == ATI_CHIP_264LT)
456
outr(LCD_GEN_CTRL, saved_lcd_gen_ctrl);
457
else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
458
(pATI->Chip == ATI_CHIP_264XL) ||
459
(pATI->Chip == ATI_CHIP_MOBILITY)) */
460
ATIMach64PutLCDReg(LCD_GEN_CNTL, saved_lcd_gen_ctrl);
463
if (pATI->CPIO_VGAWonder)
466
* Restore emulation and protection bits in ATI extended VGA
469
ATIModifyExtReg(pATI, 0xB1U, -1, 0xFCU, pATI->LockData.b1);
470
ATIModifyExtReg(pATI, 0xB4U, -1, 0x00U, pATI->LockData.b4);
471
ATIModifyExtReg(pATI, 0xB5U, -1, 0xBFU, pATI->LockData.b5);
472
ATIModifyExtReg(pATI, 0xB6U, -1, 0xDDU, pATI->LockData.b6);
473
ATIModifyExtReg(pATI, 0xB8U, -1, 0xC0U, pATI->LockData.b8 & 0x03U);
474
ATIModifyExtReg(pATI, 0xB9U, -1, 0x7FU, pATI->LockData.b9);
476
ATIModifyExtReg(pATI, 0xBEU, -1, 0xFAU, pATI->LockData.be);
478
ATIModifyExtReg(pATI, 0xA6U, -1, 0x7FU, pATI->LockData.a6);
479
ATIModifyExtReg(pATI, 0xABU, -1, 0xE7U, pATI->LockData.ab);
482
ATIModifyExtReg(pATI, 0xB8U, -1, 0xC0U, pATI->LockData.b8);
486
#endif /* AVOID_CPIO */
489
/* Reset everything */
490
outr(BUS_CNTL, pATI->LockData.bus_cntl);
492
outr(CRTC_INT_CNTL, pATI->LockData.crtc_int_cntl);
494
outr(GEN_TEST_CNTL, pATI->LockData.gen_test_cntl | GEN_GUI_EN);
495
outr(GEN_TEST_CNTL, pATI->LockData.gen_test_cntl);
496
outr(GEN_TEST_CNTL, pATI->LockData.gen_test_cntl | GEN_GUI_EN);
498
outr(CRTC_GEN_CNTL, pATI->LockData.crtc_gen_cntl | CRTC_EN);
499
outr(CRTC_GEN_CNTL, pATI->LockData.crtc_gen_cntl);
500
outr(CRTC_GEN_CNTL, pATI->LockData.crtc_gen_cntl | CRTC_EN);
504
outr(CONFIG_CNTL, pATI->LockData.config_cntl);
506
#endif /* AVOID_CPIO */
508
outr(DAC_CNTL, pATI->LockData.dac_cntl);
509
if (pATI->Chip < ATI_CHIP_264CT)
510
outr(MEM_CNTL, pATI->LockData.mem_cntl);
511
if ((pATI->LCDPanelID >= 0) && (pATI->Chip != ATI_CHIP_264LT))
513
outr(LCD_INDEX, pATI->LockData.lcd_index);
515
if (!pATI->OptionBIOSDisplay && (pATI->Chip != ATI_CHIP_264XL))
516
outr(SCRATCH_REG3, pATI->LockData.scratch_reg3);
519
if (pATI->Chip >= ATI_CHIP_264VTB)
521
outr(MPP_CONFIG, pATI->LockData.mpp_config);
522
outr(MPP_STROBE_SEQ, pATI->LockData.mpp_strobe_seq);
524
outr(TVO_CNTL, pATI->LockData.tvo_cntl);
526
if (pATI->Chip >= ATI_CHIP_264GT2C)
528
outr(HW_DEBUG, pATI->LockData.hw_debug);
529
if (pATI->Chip >= ATI_CHIP_264GTPRO)
531
outr(I2C_CNTL_0, pATI->LockData.i2c_cntl_0);
532
outr(I2C_CNTL_1, pATI->LockData.i2c_cntl_1);