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)) {