1 /* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */
3 * Copyright 1996-1997 David J. McKay
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 /* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen
27 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_dac.c,v 1.31 2003/01/02 20:44:56 mvojkovi Exp $ */
29 #include "nv_include.h"
32 NVDACInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
35 int horizDisplay = (mode->CrtcHDisplay/8) - 1;
36 int horizStart = (mode->CrtcHSyncStart/8) - 1;
37 int horizEnd = (mode->CrtcHSyncEnd/8) - 1;
38 int horizTotal = (mode->CrtcHTotal/8) - 5;
39 int horizBlankStart = (mode->CrtcHDisplay/8) - 1;
40 int horizBlankEnd = (mode->CrtcHTotal/8) - 1;
41 int vertDisplay = mode->CrtcVDisplay - 1;
42 int vertStart = mode->CrtcVSyncStart - 1;
43 int vertEnd = mode->CrtcVSyncEnd - 1;
44 int vertTotal = mode->CrtcVTotal - 2;
45 int vertBlankStart = mode->CrtcVDisplay - 1;
46 int vertBlankEnd = mode->CrtcVTotal - 1;
49 NVPtr pNv = NVPTR(pScrn);
50 NVRegPtr nvReg = &pNv->ModeReg;
51 NVFBLayout *pLayout = &pNv->CurrentLayout;
54 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVDACInit\n"));
57 * This will initialize all of the generic VGA registers.
59 if (!vgaHWInit(pScrn, mode))
62 pVga = &VGAHWPTR(pScrn)->ModeReg;
65 * Set all CRTC values.
68 if(mode->Flags & V_INTERLACE)
71 if(pNv->FlatPanel == 1) {
72 vertStart = vertTotal - 3;
73 vertEnd = vertTotal - 2;
74 vertBlankStart = vertStart;
75 horizStart = horizTotal - 3;
76 horizEnd = horizTotal - 2;
77 horizBlankEnd = horizTotal + 4;
80 pVga->CRTC[0x0] = Set8Bits(horizTotal);
81 pVga->CRTC[0x1] = Set8Bits(horizDisplay);
82 pVga->CRTC[0x2] = Set8Bits(horizBlankStart);
83 pVga->CRTC[0x3] = SetBitField(horizBlankEnd,4:0,4:0)
85 pVga->CRTC[0x4] = Set8Bits(horizStart);
86 pVga->CRTC[0x5] = SetBitField(horizBlankEnd,5:5,7:7)
87 | SetBitField(horizEnd,4:0,4:0);
88 pVga->CRTC[0x6] = SetBitField(vertTotal,7:0,7:0);
89 pVga->CRTC[0x7] = SetBitField(vertTotal,8:8,0:0)
90 | SetBitField(vertDisplay,8:8,1:1)
91 | SetBitField(vertStart,8:8,2:2)
92 | SetBitField(vertBlankStart,8:8,3:3)
94 | SetBitField(vertTotal,9:9,5:5)
95 | SetBitField(vertDisplay,9:9,6:6)
96 | SetBitField(vertStart,9:9,7:7);
97 pVga->CRTC[0x9] = SetBitField(vertBlankStart,9:9,5:5)
99 | ((mode->Flags & V_DBLSCAN) ? 0x80 : 0x00);
100 pVga->CRTC[0x10] = Set8Bits(vertStart);
101 pVga->CRTC[0x11] = SetBitField(vertEnd,3:0,3:0) | SetBit(5);
102 pVga->CRTC[0x12] = Set8Bits(vertDisplay);
103 pVga->CRTC[0x13] = ((pLayout->displayWidth/8)*(pLayout->bitsPerPixel/8));
104 pVga->CRTC[0x15] = Set8Bits(vertBlankStart);
105 pVga->CRTC[0x16] = Set8Bits(vertBlankEnd);
107 pVga->Attribute[0x10] = 0x01;
109 nvReg->screen = SetBitField(horizBlankEnd,6:6,4:4)
110 | SetBitField(vertBlankStart,10:10,3:3)
111 | SetBitField(vertStart,10:10,2:2)
112 | SetBitField(vertDisplay,10:10,1:1)
113 | SetBitField(vertTotal,10:10,0:0);
115 nvReg->horiz = SetBitField(horizTotal,8:8,0:0)
116 | SetBitField(horizDisplay,8:8,1:1)
117 | SetBitField(horizBlankStart,8:8,2:2)
118 | SetBitField(horizStart,8:8,3:3);
120 nvReg->extra = SetBitField(vertTotal,11:11,0:0)
121 | SetBitField(vertDisplay,11:11,2:2)
122 | SetBitField(vertStart,11:11,4:4)
123 | SetBitField(vertBlankStart,11:11,6:6);
125 if(mode->Flags & V_INTERLACE) {
126 horizTotal = (horizTotal >> 1) & ~1;
127 nvReg->interlace = Set8Bits(horizTotal);
128 nvReg->horiz |= SetBitField(horizTotal,8:8,4:4);
130 nvReg->interlace = 0xff; /* interlace off */
135 * Initialize DAC palette.
137 if(pLayout->bitsPerPixel != 8 )
139 for (i = 0; i < 256; i++)
142 pVga->DAC[(i*3)+1] = i;
143 pVga->DAC[(i*3)+2] = i;
148 * Calculate the extended registers.
151 if(pLayout->depth < 24)
155 if(pNv->riva.Architecture >= NV_ARCH_10)
156 pNv->riva.CURSOR = (U032 *)(pNv->FbStart + pNv->riva.CursorStart);
158 pNv->riva.LockUnlock(&pNv->riva, 0);
160 pNv->riva.CalcStateExt(&pNv->riva,
163 pLayout->displayWidth,
169 nvReg->scale = pNv->riva.PRAMDAC[0x00000848/4] & 0xfff000ff;
170 if(pNv->FlatPanel == 1) {
171 nvReg->pixel |= (1 << 7);
172 nvReg->scale |= (1 << 8) ;
174 if(pNv->SecondCRTC) {
175 nvReg->head = pNv->riva.PCRTC0[0x00000860/4] & ~0x00001000;
176 nvReg->head2 = pNv->riva.PCRTC0[0x00002860/4] | 0x00001000;
177 nvReg->crtcOwner = 3;
178 nvReg->pllsel |= 0x20000800;
179 nvReg->vpll2 = nvReg->vpll;
181 if(pNv->riva.twoHeads) {
182 nvReg->head = pNv->riva.PCRTC0[0x00000860/4] | 0x00001000;
183 nvReg->head2 = pNv->riva.PCRTC0[0x00002860/4] & ~0x00001000;
184 nvReg->crtcOwner = 0;
185 nvReg->vpll2 = pNv->riva.PRAMDAC0[0x00000520/4];
188 nvReg->cursorConfig = 0x00000100;
189 if(mode->Flags & V_DBLSCAN)
190 nvReg->cursorConfig |= (1 << 4);
191 if(pNv->alphaCursor) {
192 nvReg->cursorConfig |= 0x04011000;
193 nvReg->general |= (1 << 29);
195 if((pNv->Chipset & 0x0ff0) == 0x0110) {
196 nvReg->dither = pNv->riva.PRAMDAC[0x0528/4] & ~0x00010000;
197 if(pNv->riva.flatPanel & FP_DITHER)
198 nvReg->dither |= 0x00010000;
200 nvReg->cursorConfig |= (1 << 28);
202 if((pNv->riva.Chipset & 0x0ff0) >= 0x0170) {
203 nvReg->dither = pNv->riva.PRAMDAC[0x083C/4] & ~1;
204 nvReg->cursorConfig |= (1 << 28);
205 if(pNv->riva.flatPanel & FP_DITHER)
208 nvReg->cursorConfig |= (1 << 28);
211 nvReg->cursorConfig |= 0x02000000;
220 NVDACRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, NVRegPtr nvReg,
223 NVPtr pNv = NVPTR(pScrn);
224 int restore = VGA_SR_MODE;
226 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVDACRestore\n"));
228 if(primary) restore |= VGA_SR_CMAP | VGA_SR_FONTS;
229 else if((pNv->Chipset & 0xffff) == 0x0018)
230 restore |= VGA_SR_CMAP;
231 pNv->riva.LoadStateExt(&pNv->riva, nvReg);
232 #if defined(__powerpc__)
233 restore &= ~VGA_SR_FONTS;
235 vgaHWRestore(pScrn, vgaReg, restore);
241 * This function saves the video state.
244 NVDACSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, NVRegPtr nvReg,
247 NVPtr pNv = NVPTR(pScrn);
248 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVDACSave\n"));
250 #if defined(__powerpc__)
254 vgaHWSave(pScrn, vgaReg, VGA_SR_CMAP | VGA_SR_MODE |
255 (saveFonts? VGA_SR_FONTS : 0));
256 pNv->riva.UnloadStateExt(&pNv->riva, nvReg);
258 if((pNv->Chipset & 0x0ff0) == 0x0110)
259 nvReg->crtcOwner = ((pNv->Chipset & 0x0fff) == 0x0112) ? 3 : 0;
262 #define DEPTH_SHIFT(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8)))
263 #define MAKE_INDEX(in, w) (DEPTH_SHIFT(in, w) * 3)
266 NVDACLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
270 NVPtr pNv = NVPTR(pScrn);
273 pVga = &VGAHWPTR(pScrn)->ModeReg;
275 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVDACLoadPalette\n"));
277 if((pNv->riva.Architecture == NV_ARCH_03) &&
278 (pNv->CurrentLayout.depth != 8))
281 switch(pNv->CurrentLayout.depth) {
283 for(i = 0; i < numColors; i++) {
285 pVga->DAC[MAKE_INDEX(index, 5) + 0] = colors[index].red;
286 pVga->DAC[MAKE_INDEX(index, 5) + 1] = colors[index].green;
287 pVga->DAC[MAKE_INDEX(index, 5) + 2] = colors[index].blue;
291 for(i = 0; i < numColors; i++) {
293 pVga->DAC[MAKE_INDEX(index, 6) + 1] = colors[index].green;
295 pVga->DAC[MAKE_INDEX(index, 5) + 0] = colors[index].red;
296 pVga->DAC[MAKE_INDEX(index, 5) + 2] = colors[index].blue;
301 for(i = 0; i < numColors; i++) {
303 pVga->DAC[index*3] = colors[index].red;
304 pVga->DAC[(index*3)+1] = colors[index].green;
305 pVga->DAC[(index*3)+2] = colors[index].blue;
309 vgaHWRestore(pScrn, pVga, VGA_SR_CMAP);
313 * DDC1 support only requires DDC_SDA_MASK,
314 * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK
316 #define DDC_SDA_READ_MASK (1 << 3)
317 #define DDC_SCL_READ_MASK (1 << 2)
318 #define DDC_SDA_WRITE_MASK (1 << 4)
319 #define DDC_SCL_WRITE_MASK (1 << 5)
322 NV_ddc1Read(ScrnInfoPtr pScrn)
324 NVPtr pNv = NVPTR(pScrn);
328 while(VGA_RD08(pNv->riva.PCIO, 0x3da) & 0x08);
329 while(!(VGA_RD08(pNv->riva.PCIO, 0x3da) & 0x08));
332 VGA_WR08(pNv->riva.PCIO, 0x3d4, pNv->DDCBase);
333 val = VGA_RD08(pNv->riva.PCIO, 0x3d5);
334 DEBUG(ErrorF("NV_ddc1Read(%p,...) returns %d\n",
336 return (val & DDC_SDA_READ_MASK) != 0;
340 NV_I2CGetBits(I2CBusPtr b, int *clock, int *data)
342 NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
345 /* Get the result. */
346 VGA_WR08(pNv->riva.PCIO, 0x3d4, pNv->DDCBase);
347 val = VGA_RD08(pNv->riva.PCIO, 0x3d5);
349 *clock = (val & DDC_SCL_READ_MASK) != 0;
350 *data = (val & DDC_SDA_READ_MASK) != 0;
351 DEBUG(ErrorF("NV_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n",
352 b, val, *clock, *data));
356 NV_I2CPutBits(I2CBusPtr b, int clock, int data)
358 NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
361 VGA_WR08(pNv->riva.PCIO, 0x3d4, pNv->DDCBase + 1);
362 val = VGA_RD08(pNv->riva.PCIO, 0x3d5) & 0xf0;
364 val |= DDC_SCL_WRITE_MASK;
366 val &= ~DDC_SCL_WRITE_MASK;
369 val |= DDC_SDA_WRITE_MASK;
371 val &= ~DDC_SDA_WRITE_MASK;
373 VGA_WR08(pNv->riva.PCIO, 0x3d4, pNv->DDCBase + 1);
374 VGA_WR08(pNv->riva.PCIO, 0x3d5, val | 0x1);
376 DEBUG(ErrorF("NV_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val));
380 NV_i2cInit(ScrnInfoPtr pScrn)
382 NVPtr pNv = NVPTR(pScrn);
385 I2CPtr = xf86CreateI2CBusRec();
386 if(!I2CPtr) return FALSE;
390 I2CPtr->BusName = "DDC";
391 I2CPtr->scrnIndex = pScrn->scrnIndex;
392 I2CPtr->I2CPutBits = NV_I2CPutBits;
393 I2CPtr->I2CGetBits = NV_I2CGetBits;
394 I2CPtr->AcknTimeout = 5;
396 if (!xf86I2CBusInit(I2CPtr)) {
406 NVRamdacInit(ScrnInfoPtr pScrn)
408 NVPtr pNv = NVPTR(pScrn);
409 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NVRamdacInit\n"));
410 pNv->ddc1Read = NV_ddc1Read;
411 /* vgaHWddc1SetSpeed will only work if the card is in VGA mode */
412 pNv->DDC1SetSpeed = vgaHWddc1SetSpeed;
413 pNv->i2cInit = NV_i2cInit;