2
* Copyright 2003 NVIDIA, Corporation
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
#include "nv_include.h"
26
NVDACPanelTweaks(NVPtr pNv, NVRegPtr state)
30
if(pNv->usePanelTweak) {
31
tweak = pNv->PanelTweak;
33
/* begin flat panel hacks */
34
/* This is unfortunate, but some chips need this register
35
tweaked or else you get artifacts where adjacent pixels are
36
swapped. There are no hard rules for what to set here so all
37
we can do is experiment and apply hacks. */
39
if(((pNv->Chipset & 0xffff) == 0x0328) && (state->bpp == 32)) {
40
/* At least one NV34 laptop needs this workaround. */
44
if((pNv->Chipset & 0xfff0) == CHIPSET_NV31) {
47
/* end flat panel hacks */
54
NVDACInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
57
int horizDisplay = (mode->CrtcHDisplay/8) - 1;
58
int horizStart = (mode->CrtcHSyncStart/8) - 1;
59
int horizEnd = (mode->CrtcHSyncEnd/8) - 1;
60
int horizTotal = (mode->CrtcHTotal/8) - 5;
61
int horizBlankStart = (mode->CrtcHDisplay/8) - 1;
62
int horizBlankEnd = (mode->CrtcHTotal/8) - 1;
63
int vertDisplay = mode->CrtcVDisplay - 1;
64
int vertStart = mode->CrtcVSyncStart - 1;
65
int vertEnd = mode->CrtcVSyncEnd - 1;
66
int vertTotal = mode->CrtcVTotal - 2;
67
int vertBlankStart = mode->CrtcVDisplay - 1;
68
int vertBlankEnd = mode->CrtcVTotal - 1;
70
NVPtr pNv = NVPTR(pScrn);
71
NVRegPtr nvReg = &pNv->ModeReg;
75
* Initialize all of the generic VGA registers. Don't bother with
76
* VGA_FIX_SYNC_PULSES, given the relevant CRTC settings are overridden
77
* below. Ditto for the KGA workaround.
79
if (!vgaHWInit(pScrn, mode))
82
pVga = &VGAHWPTR(pScrn)->ModeReg;
85
* Set all CRTC values.
88
if(mode->Flags & V_INTERLACE)
91
if(pNv->FlatPanel == 1) {
92
vertStart = vertTotal - 3;
93
vertEnd = vertTotal - 2;
94
vertBlankStart = vertStart;
95
horizStart = horizTotal - 5;
96
horizEnd = horizTotal - 2;
97
horizBlankEnd = horizTotal + 4;
98
if ( ( pNv->Architecture == NV_ARCH_40 && ((pNv->Chipset & 0xfff0) == CHIPSET_NV40) ) || pNv->Architecture == NV_ARCH_30 || pNv->Architecture == NV_ARCH_20 || pNv->Architecture == NV_ARCH_10 ) {
99
/* This reportedly works around Xv some overlay bandwidth problems*/
104
pVga->CRTC[0x0] = Set8Bits(horizTotal);
105
pVga->CRTC[0x1] = Set8Bits(horizDisplay);
106
pVga->CRTC[0x2] = Set8Bits(horizBlankStart);
107
pVga->CRTC[0x3] = SetBitField(horizBlankEnd,4:0,4:0)
109
pVga->CRTC[0x4] = Set8Bits(horizStart);
110
pVga->CRTC[0x5] = SetBitField(horizBlankEnd,5:5,7:7)
111
| SetBitField(horizEnd,4:0,4:0);
112
pVga->CRTC[0x6] = SetBitField(vertTotal,7:0,7:0);
113
pVga->CRTC[0x7] = SetBitField(vertTotal,8:8,0:0)
114
| SetBitField(vertDisplay,8:8,1:1)
115
| SetBitField(vertStart,8:8,2:2)
116
| SetBitField(vertBlankStart,8:8,3:3)
118
| SetBitField(vertTotal,9:9,5:5)
119
| SetBitField(vertDisplay,9:9,6:6)
120
| SetBitField(vertStart,9:9,7:7);
121
pVga->CRTC[0x9] = SetBitField(vertBlankStart,9:9,5:5)
123
| ((mode->Flags & V_DBLSCAN) ? 0x80 : 0x00);
124
pVga->CRTC[0x10] = Set8Bits(vertStart);
125
pVga->CRTC[0x11] = SetBitField(vertEnd,3:0,3:0) | SetBit(5);
126
pVga->CRTC[0x12] = Set8Bits(vertDisplay);
127
pVga->CRTC[0x13] = ((pScrn->displayWidth/8)*(pScrn->bitsPerPixel/8));
128
pVga->CRTC[0x15] = Set8Bits(vertBlankStart);
129
pVga->CRTC[0x16] = Set8Bits(vertBlankEnd);
131
pVga->Attribute[0x10] = 0x01;
134
pVga->Attribute[0x11] = 0x00;
136
nvReg->screen = SetBitField(horizBlankEnd,6:6,4:4)
137
| SetBitField(vertBlankStart,10:10,3:3)
138
| SetBitField(vertStart,10:10,2:2)
139
| SetBitField(vertDisplay,10:10,1:1)
140
| SetBitField(vertTotal,10:10,0:0);
142
nvReg->horiz = SetBitField(horizTotal,8:8,0:0)
143
| SetBitField(horizDisplay,8:8,1:1)
144
| SetBitField(horizBlankStart,8:8,2:2)
145
| SetBitField(horizStart,8:8,3:3);
147
nvReg->extra = SetBitField(vertTotal,11:11,0:0)
148
| SetBitField(vertDisplay,11:11,2:2)
149
| SetBitField(vertStart,11:11,4:4)
150
| SetBitField(vertBlankStart,11:11,6:6);
152
if(mode->Flags & V_INTERLACE) {
153
horizTotal = (horizTotal >> 1) & ~1;
154
nvReg->interlace = Set8Bits(horizTotal);
155
nvReg->horiz |= SetBitField(horizTotal,8:8,4:4);
157
nvReg->interlace = 0xff; /* interlace off */
162
* Initialize DAC palette.
164
if(pScrn->bitsPerPixel != 8 )
166
for (i = 0; i < 256; i++)
169
pVga->DAC[(i*3)+1] = i;
170
pVga->DAC[(i*3)+2] = i;
175
* Calculate the extended registers.
178
if (pScrn->depth < 24)
182
if(pNv->Architecture >= NV_ARCH_10)
183
pNv->CURSOR = (CARD32 *)pNv->Cursor->map;
194
nvReg->scale = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL) & 0xfff000ff;
195
if(pNv->FlatPanel == 1) {
196
nvReg->pixel |= (1 << 7);
197
if(!pNv->fpScaler || (pNv->fpWidth <= mode->HDisplay)
198
|| (pNv->fpHeight <= mode->VDisplay))
200
nvReg->scale |= (1 << 8) ;
202
nvReg->crtcSync = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_HCRTC);
203
nvReg->crtcSync += NVDACPanelTweaks(pNv, nvReg);
206
nvReg->vpll = nvReg->pll;
207
nvReg->vpll2 = nvReg->pll;
208
nvReg->vpllB = nvReg->pllB;
209
nvReg->vpll2B = nvReg->pllB;
211
nvReg->fifo = nvReadCurVGA(pNv, 0x1c) & ~(1<<5);
213
if(pNv->crtc_active[1]) {
214
nvReg->head = NVReadCRTC(pNv, 0, NV_CRTC_FSEL) & ~0x00001000;
215
nvReg->head2 = NVReadCRTC(pNv, 1, NV_CRTC_FSEL) | 0x00001000;
216
nvReg->crtcOwner = 3;
217
nvReg->pllsel |= 0x20000800;
218
nvReg->vpll = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL);
220
nvReg->vpllB = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL_B);
221
} else if(pNv->twoHeads) {
222
nvReg->head = NVReadCRTC(pNv, 0, NV_CRTC_FSEL) | 0x00001000;
223
nvReg->head2 = NVReadCRTC(pNv, 1, NV_CRTC_FSEL) & ~0x00001000;
224
nvReg->crtcOwner = 0;
225
nvReg->vpll2 = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL2);
227
nvReg->vpll2B = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL2_B);
230
nvReg->cursorConfig = 0x00000100;
231
if(mode->Flags & V_DBLSCAN)
232
nvReg->cursorConfig |= (1 << 4);
233
if(pNv->alphaCursor) {
234
if((pNv->Chipset & 0x0ff0) != CHIPSET_NV11)
235
nvReg->cursorConfig |= 0x04011000;
237
nvReg->cursorConfig |= 0x14011000;
238
nvReg->general |= (1 << 29);
240
nvReg->cursorConfig |= 0x02000000;
243
if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
244
nvReg->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_DITHER_NV11) & ~0x00010000;
246
nvReg->dither |= 0x00010000;
248
nvReg->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_DITHER) & ~1;
256
nvReg->displayV = mode->CrtcVDisplay;
262
NVDACRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, NVRegPtr nvReg,
265
int restore = VGA_SR_MODE;
267
if(primary) restore |= VGA_SR_CMAP | VGA_SR_FONTS;
268
NVLoadStateExt(pScrn, nvReg);
269
#if defined(__powerpc__)
270
restore &= ~VGA_SR_FONTS;
272
vgaHWRestore(pScrn, vgaReg, restore);
278
* This function saves the video state.
281
NVDACSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, NVRegPtr nvReg,
284
NVPtr pNv = NVPTR(pScrn);
286
#if defined(__powerpc__)
290
vgaHWSave(pScrn, vgaReg, VGA_SR_CMAP | VGA_SR_MODE |
291
(saveFonts? VGA_SR_FONTS : 0));
292
NVUnloadStateExt(pNv, nvReg);
294
/* can't read this reliably on NV11 */
295
if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
296
/* 0 if inactive -> crtc0 is active, otherwise 1 */
297
nvReg->crtcOwner = pNv->crtc_active[1];
301
#define DEPTH_SHIFT(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8)))
302
#define MAKE_INDEX(in, w) (DEPTH_SHIFT(in, w) * 3)
305
NVDACLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
309
vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg;
311
switch(pScrn->depth) {
313
for(i = 0; i < numColors; i++) {
315
pVga->DAC[MAKE_INDEX(index, 5) + 0] = colors[index].red;
316
pVga->DAC[MAKE_INDEX(index, 5) + 1] = colors[index].green;
317
pVga->DAC[MAKE_INDEX(index, 5) + 2] = colors[index].blue;
321
for(i = 0; i < numColors; i++) {
323
pVga->DAC[MAKE_INDEX(index, 6) + 1] = colors[index].green;
325
pVga->DAC[MAKE_INDEX(index, 5) + 0] = colors[index].red;
326
pVga->DAC[MAKE_INDEX(index, 5) + 2] = colors[index].blue;
331
for(i = 0; i < numColors; i++) {
333
pVga->DAC[index*3] = colors[index].red;
334
pVga->DAC[(index*3)+1] = colors[index].green;
335
pVga->DAC[(index*3)+2] = colors[index].blue;
339
vgaHWRestore(pScrn, pVga, VGA_SR_CMAP);
343
* DDC1 support only requires DDC_SDA_MASK,
344
* DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK
346
#define DDC_SDA_READ_MASK (1 << 3)
347
#define DDC_SCL_READ_MASK (1 << 2)
348
#define DDC_SDA_WRITE_MASK (1 << 4)
349
#define DDC_SCL_WRITE_MASK (1 << 5)
352
NV_I2CGetBits(I2CBusPtr b, int *clock, int *data)
354
NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
357
/* Get the result. */
358
val = nvReadCurVGA(pNv, pNv->DDCBase);
360
*clock = (val & DDC_SCL_READ_MASK) != 0;
361
*data = (val & DDC_SDA_READ_MASK) != 0;
365
NV_I2CPutBits(I2CBusPtr b, int clock, int data)
367
NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
370
val = nvReadCurVGA(pNv, pNv->DDCBase + 1) & 0xf0;
372
val |= DDC_SCL_WRITE_MASK;
374
val &= ~DDC_SCL_WRITE_MASK;
377
val |= DDC_SDA_WRITE_MASK;
379
val &= ~DDC_SDA_WRITE_MASK;
381
nvWriteCurVGA(pNv, pNv->DDCBase + 1, val | 0x1);
385
NVDACi2cInit(ScrnInfoPtr pScrn)
387
NVPtr pNv = NVPTR(pScrn);
390
I2CPtr = xf86CreateI2CBusRec();
391
if(!I2CPtr) return FALSE;
395
I2CPtr->BusName = "DDC";
396
I2CPtr->scrnIndex = pScrn->scrnIndex;
397
I2CPtr->I2CPutBits = NV_I2CPutBits;
398
I2CPtr->I2CGetBits = NV_I2CGetBits;
399
I2CPtr->AcknTimeout = 5;
401
if (!xf86I2CBusInit(I2CPtr)) {