nvbios: Add some valid register ranges for nv50.
[nouveau] / src / nv_dac.c
1  /***************************************************************************\
2 |*                                                                           *|
3 |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
4 |*                                                                           *|
5 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
6 |*     international laws.  Users and possessors of this source code are     *|
7 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
8 |*     use this code in individual and commercial software.                  *|
9 |*                                                                           *|
10 |*     Any use of this source code must include,  in the user documenta-     *|
11 |*     tion and  internal comments to the code,  notices to the end user     *|
12 |*     as follows:                                                           *|
13 |*                                                                           *|
14 |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
15 |*                                                                           *|
16 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
17 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
18 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
19 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
20 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
21 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
22 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
23 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
24 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
25 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
26 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
27 |*                                                                           *|
28 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
29 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
30 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
31 |*     computer  software  documentation,"  as such  terms  are  used in     *|
32 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
33 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
34 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
35 |*     all U.S. Government End Users  acquire the source code  with only     *|
36 |*     those rights set forth herein.                                        *|
37 |*                                                                           *|
38  \***************************************************************************/
39
40 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_dac.c,v 1.45 2005/07/09 00:53:00 mvojkovi Exp $ */
41
42 #include "nv_include.h"
43
44 static int
45 NVDACPanelTweaks(NVPtr pNv, NVRegPtr state)
46 {
47    int tweak = 0;
48
49    if(pNv->usePanelTweak) {
50        tweak = pNv->PanelTweak;
51    } else {
52        /* begin flat panel hacks */
53        /* This is unfortunate, but some chips need this register
54           tweaked or else you get artifacts where adjacent pixels are
55           swapped.  There are no hard rules for what to set here so all
56           we can do is experiment and apply hacks. */
57
58        if(((pNv->Chipset & 0xffff) == 0x0328) && (state->bpp == 32)) {
59           /* At least one NV34 laptop needs this workaround. */
60           tweak = -1;
61        }
62
63        if((pNv->Chipset & 0xfff0) == CHIPSET_NV31) {
64           tweak = 1;
65        }
66        /* end flat panel hacks */
67    }
68
69    return tweak;
70 }
71
72 Bool
73 NVDACInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
74 {
75     int i;
76     int horizDisplay    = (mode->CrtcHDisplay/8)   - 1;
77     int horizStart      = (mode->CrtcHSyncStart/8) - 1;
78     int horizEnd        = (mode->CrtcHSyncEnd/8)   - 1;
79     int horizTotal      = (mode->CrtcHTotal/8)     - 5;
80     int horizBlankStart = (mode->CrtcHDisplay/8)   - 1;
81     int horizBlankEnd   = (mode->CrtcHTotal/8)     - 1;
82     int vertDisplay     =  mode->CrtcVDisplay      - 1;
83     int vertStart       =  mode->CrtcVSyncStart    - 1;
84     int vertEnd         =  mode->CrtcVSyncEnd      - 1;
85     int vertTotal       =  mode->CrtcVTotal        - 2;
86     int vertBlankStart  =  mode->CrtcVDisplay      - 1;
87     int vertBlankEnd    =  mode->CrtcVTotal        - 1;
88    
89     NVPtr pNv = NVPTR(pScrn);
90     NVRegPtr nvReg = &pNv->ModeReg;
91     vgaRegPtr   pVga;
92
93     /*
94      * Initialize all of the generic VGA registers.  Don't bother with
95      * VGA_FIX_SYNC_PULSES, given the relevant CRTC settings are overridden
96      * below.  Ditto for the KGA workaround.
97      */
98     if (!vgaHWInit(pScrn, mode))
99         return(FALSE);
100
101     pVga = &VGAHWPTR(pScrn)->ModeReg;
102
103     /*
104      * Set all CRTC values.
105      */
106
107     if(mode->Flags & V_INTERLACE) 
108         vertTotal |= 1;
109
110     if(pNv->FlatPanel == 1) {
111         vertStart = vertTotal - 3;  
112         vertEnd = vertTotal - 2;
113         vertBlankStart = vertStart;
114         horizStart = horizTotal - 5;
115         horizEnd = horizTotal - 2;   
116         horizBlankEnd = horizTotal + 4;   
117         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 )        { 
118                 /* This reportedly works around Xv some overlay bandwidth problems*/
119                 horizTotal += 2;
120                 }
121     }
122
123     pVga->CRTC[0x0]  = Set8Bits(horizTotal);
124     pVga->CRTC[0x1]  = Set8Bits(horizDisplay);
125     pVga->CRTC[0x2]  = Set8Bits(horizBlankStart);
126     pVga->CRTC[0x3]  = SetBitField(horizBlankEnd,4:0,4:0) 
127                        | SetBit(7);
128     pVga->CRTC[0x4]  = Set8Bits(horizStart);
129     pVga->CRTC[0x5]  = SetBitField(horizBlankEnd,5:5,7:7)
130                        | SetBitField(horizEnd,4:0,4:0);
131     pVga->CRTC[0x6]  = SetBitField(vertTotal,7:0,7:0);
132     pVga->CRTC[0x7]  = SetBitField(vertTotal,8:8,0:0)
133                        | SetBitField(vertDisplay,8:8,1:1)
134                        | SetBitField(vertStart,8:8,2:2)
135                        | SetBitField(vertBlankStart,8:8,3:3)
136                        | SetBit(4)
137                        | SetBitField(vertTotal,9:9,5:5)
138                        | SetBitField(vertDisplay,9:9,6:6)
139                        | SetBitField(vertStart,9:9,7:7);
140     pVga->CRTC[0x9]  = SetBitField(vertBlankStart,9:9,5:5)
141                        | SetBit(6)
142                        | ((mode->Flags & V_DBLSCAN) ? 0x80 : 0x00);
143     pVga->CRTC[0x10] = Set8Bits(vertStart);
144     pVga->CRTC[0x11] = SetBitField(vertEnd,3:0,3:0) | SetBit(5);
145     pVga->CRTC[0x12] = Set8Bits(vertDisplay);
146     pVga->CRTC[0x13] = ((pScrn->displayWidth/8)*(pScrn->bitsPerPixel/8));
147     pVga->CRTC[0x15] = Set8Bits(vertBlankStart);
148     pVga->CRTC[0x16] = Set8Bits(vertBlankEnd);
149
150     pVga->Attribute[0x10] = 0x01;
151
152     if(pNv->Television)
153        pVga->Attribute[0x11] = 0x00;
154
155     nvReg->screen = SetBitField(horizBlankEnd,6:6,4:4)
156                   | SetBitField(vertBlankStart,10:10,3:3)
157                   | SetBitField(vertStart,10:10,2:2)
158                   | SetBitField(vertDisplay,10:10,1:1)
159                   | SetBitField(vertTotal,10:10,0:0);
160
161     nvReg->horiz  = SetBitField(horizTotal,8:8,0:0) 
162                   | SetBitField(horizDisplay,8:8,1:1)
163                   | SetBitField(horizBlankStart,8:8,2:2)
164                   | SetBitField(horizStart,8:8,3:3);
165
166     nvReg->extra  = SetBitField(vertTotal,11:11,0:0)
167                     | SetBitField(vertDisplay,11:11,2:2)
168                     | SetBitField(vertStart,11:11,4:4)
169                     | SetBitField(vertBlankStart,11:11,6:6);
170
171     if(mode->Flags & V_INTERLACE) {
172        horizTotal = (horizTotal >> 1) & ~1;
173        nvReg->interlace = Set8Bits(horizTotal);
174        nvReg->horiz |= SetBitField(horizTotal,8:8,4:4);
175     } else {
176        nvReg->interlace = 0xff;  /* interlace off */
177     }
178
179
180     /*
181      * Initialize DAC palette.
182      */
183     if(pScrn->bitsPerPixel != 8 )
184     {
185         for (i = 0; i < 256; i++)
186         {
187             pVga->DAC[i*3]     = i;
188             pVga->DAC[(i*3)+1] = i;
189             pVga->DAC[(i*3)+2] = i;
190         }
191     }
192     
193     /*
194      * Calculate the extended registers.
195      */
196
197     if (pScrn->depth < 24) 
198         i = pScrn->depth;
199     else i = 32;
200
201     if(pNv->Architecture >= NV_ARCH_10)
202         pNv->CURSOR = (CARD32 *)pNv->Cursor->map;
203
204     NVCalcStateExt(pNv, 
205                     nvReg,
206                     i,
207                     pScrn->displayWidth,
208                     mode->CrtcHDisplay,
209                     pScrn->virtualY,
210                     mode->Clock,
211                     mode->Flags);
212
213     nvReg->scale = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL) & 0xfff000ff;
214     if(pNv->FlatPanel == 1) {
215        nvReg->pixel |= (1 << 7);
216        if(!pNv->fpScaler || (pNv->fpWidth <= mode->HDisplay)
217                          || (pNv->fpHeight <= mode->VDisplay))
218        {
219            nvReg->scale |= (1 << 8) ;
220        }
221        nvReg->crtcSync = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_HCRTC);
222        nvReg->crtcSync += NVDACPanelTweaks(pNv, nvReg);
223     }
224
225     nvReg->vpll = nvReg->pll;
226     nvReg->vpll2 = nvReg->pll;
227     nvReg->vpllB = nvReg->pllB;
228     nvReg->vpll2B = nvReg->pllB;
229
230     nvReg->fifo = nvReadCurVGA(pNv, 0x1c) & ~(1<<5);
231
232     if(pNv->crtc_active[1]) {
233        nvReg->head  = NVReadCRTC(pNv, 0, NV_CRTC_FSEL) & ~0x00001000;
234        nvReg->head2 = NVReadCRTC(pNv, 1, NV_CRTC_FSEL) | 0x00001000;
235        nvReg->crtcOwner = 3;
236        nvReg->pllsel |= 0x20000800;
237        nvReg->vpll = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL);
238        if(pNv->twoStagePLL) 
239           nvReg->vpllB = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL_B);
240     } else if(pNv->twoHeads) {
241        nvReg->head  =  NVReadCRTC(pNv, 0, NV_CRTC_FSEL) | 0x00001000;
242        nvReg->head2 =  NVReadCRTC(pNv, 1, NV_CRTC_FSEL) & ~0x00001000;
243        nvReg->crtcOwner = 0;
244        nvReg->vpll2 = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL2);
245        if(pNv->twoStagePLL) 
246           nvReg->vpll2B = NVReadRAMDAC(pNv, 0, NV_RAMDAC_VPLL2_B);
247     }
248
249     nvReg->cursorConfig = 0x00000100;
250     if(mode->Flags & V_DBLSCAN)
251        nvReg->cursorConfig |= (1 << 4);
252     if(pNv->alphaCursor) {
253         if((pNv->Chipset & 0x0ff0) != CHIPSET_NV11) 
254            nvReg->cursorConfig |= 0x04011000;
255         else
256            nvReg->cursorConfig |= 0x14011000;
257         nvReg->general |= (1 << 29);
258     } else
259        nvReg->cursorConfig |= 0x02000000;
260
261     if(pNv->twoHeads) {
262         if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
263            nvReg->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_DITHER_NV11) & ~0x00010000;
264            if(pNv->FPDither)
265               nvReg->dither |= 0x00010000;
266         } else {
267            nvReg->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_DITHER) & ~1;
268            if(pNv->FPDither)
269               nvReg->dither |= 1;
270         } 
271     }
272
273     nvReg->timingH = 0;
274     nvReg->timingV = 0;
275     nvReg->displayV = mode->CrtcVDisplay;
276
277     return (TRUE);
278 }
279
280 void 
281 NVDACRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, NVRegPtr nvReg,
282              Bool primary)
283 {
284     int restore = VGA_SR_MODE;
285
286     if(primary) restore |= VGA_SR_CMAP | VGA_SR_FONTS;
287     NVLoadStateExt(pScrn, nvReg);
288 #if defined(__powerpc__)
289     restore &= ~VGA_SR_FONTS;
290 #endif
291     vgaHWRestore(pScrn, vgaReg, restore);
292 }
293
294 /*
295  * NVDACSave
296  *
297  * This function saves the video state.
298  */
299 void
300 NVDACSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, NVRegPtr nvReg,
301           Bool saveFonts)
302 {
303     NVPtr pNv = NVPTR(pScrn);
304
305 #if defined(__powerpc__)
306     saveFonts = FALSE;
307 #endif
308
309     vgaHWSave(pScrn, vgaReg, VGA_SR_CMAP | VGA_SR_MODE | 
310                              (saveFonts? VGA_SR_FONTS : 0));
311     NVUnloadStateExt(pNv, nvReg);
312
313         /* can't read this reliably on NV11 */
314         if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
315                 /* 0 if inactive -> crtc0 is active, otherwise 1 */
316                 nvReg->crtcOwner = pNv->crtc_active[1];
317         }
318 }
319
320 #define DEPTH_SHIFT(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8)))
321 #define MAKE_INDEX(in, w) (DEPTH_SHIFT(in, w) * 3)
322
323 void
324 NVDACLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
325                  VisualPtr pVisual )
326 {
327     int i, index;
328     vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg;
329
330     switch(pScrn->depth) {
331     case 15:
332         for(i = 0; i < numColors; i++) {
333             index = indices[i];
334             pVga->DAC[MAKE_INDEX(index, 5) + 0] = colors[index].red;
335             pVga->DAC[MAKE_INDEX(index, 5) + 1] = colors[index].green;
336             pVga->DAC[MAKE_INDEX(index, 5) + 2] = colors[index].blue;
337         }
338         break;
339     case 16:
340         for(i = 0; i < numColors; i++) {
341             index = indices[i];
342             pVga->DAC[MAKE_INDEX(index, 6) + 1] = colors[index].green;
343             if(index < 32) {
344                 pVga->DAC[MAKE_INDEX(index, 5) + 0] = colors[index].red;
345                 pVga->DAC[MAKE_INDEX(index, 5) + 2] = colors[index].blue;
346             }
347         }
348         break;
349     default:
350         for(i = 0; i < numColors; i++) {
351             index = indices[i];
352             pVga->DAC[index*3]     = colors[index].red;
353             pVga->DAC[(index*3)+1] = colors[index].green;
354             pVga->DAC[(index*3)+2] = colors[index].blue;
355         }
356         break;
357     }
358     vgaHWRestore(pScrn, pVga, VGA_SR_CMAP);
359 }
360
361 /*
362  * DDC1 support only requires DDC_SDA_MASK,
363  * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK
364  */
365 #define DDC_SDA_READ_MASK  (1 << 3)
366 #define DDC_SCL_READ_MASK  (1 << 2)
367 #define DDC_SDA_WRITE_MASK (1 << 4)
368 #define DDC_SCL_WRITE_MASK (1 << 5)
369
370 static void
371 NV_I2CGetBits(I2CBusPtr b, int *clock, int *data)
372 {
373     NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
374     unsigned char val;
375
376     /* Get the result. */
377     val = nvReadCurVGA(pNv, pNv->DDCBase);
378
379     *clock = (val & DDC_SCL_READ_MASK) != 0;
380     *data  = (val & DDC_SDA_READ_MASK) != 0;
381 }
382
383 static void
384 NV_I2CPutBits(I2CBusPtr b, int clock, int data)
385 {
386     NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
387     unsigned char val;
388
389     val = nvReadCurVGA(pNv, pNv->DDCBase + 1) & 0xf0;
390     if (clock)
391         val |= DDC_SCL_WRITE_MASK;
392     else
393         val &= ~DDC_SCL_WRITE_MASK;
394
395     if (data)
396         val |= DDC_SDA_WRITE_MASK;
397     else
398         val &= ~DDC_SDA_WRITE_MASK;
399
400     nvWriteCurVGA(pNv, pNv->DDCBase + 1, val | 0x1);
401 }
402
403 Bool
404 NVDACi2cInit(ScrnInfoPtr pScrn)
405 {
406     NVPtr pNv = NVPTR(pScrn);
407     I2CBusPtr I2CPtr;
408
409     I2CPtr = xf86CreateI2CBusRec();
410     if(!I2CPtr) return FALSE;
411
412     pNv->I2C = I2CPtr;
413
414     I2CPtr->BusName    = "DDC";
415     I2CPtr->scrnIndex  = pScrn->scrnIndex;
416     I2CPtr->I2CPutBits = NV_I2CPutBits;
417     I2CPtr->I2CGetBits = NV_I2CGetBits;
418     I2CPtr->AcknTimeout = 5;
419
420     if (!xf86I2CBusInit(I2CPtr)) {
421         return FALSE;
422     }
423     return TRUE;
424 }
425