randr12: hardcode more stuff + actually use a few previous regs
[nouveau] / src / nv_crtc.c
1 /*
2  * Copyright 2006 Dave Airlie
3  *
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:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
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  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECT
21  */
22 /*
23  * this code uses ideas taken from the NVIDIA nv driver - the nvidia license
24  * decleration is at the bottom of this file as it is rather ugly 
25  */
26
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #ifdef ENABLE_RANDR12
33
34 #include <assert.h>
35 #include "xf86.h"
36 #include "os.h"
37 #include "mibank.h"
38 #include "globals.h"
39 #include "xf86.h"
40 #include "xf86Priv.h"
41 #include "xf86DDC.h"
42 #include "mipointer.h"
43 #include "windowstr.h"
44 #include <randrstr.h>
45 #include <X11/extensions/render.h>
46
47 #include "xf86Crtc.h"
48 #include "nv_include.h"
49
50 #include "vgaHW.h"
51
52 #define CRTC_INDEX 0x3d4
53 #define CRTC_DATA 0x3d5
54 #define CRTC_IN_STAT_1 0x3da
55
56 #define WHITE_VALUE 0x3F
57 #define BLACK_VALUE 0x00
58 #define OVERSCAN_VALUE 0x01
59
60 static void nv_crtc_load_state_vga(xf86CrtcPtr crtc, RIVA_HW_STATE *state);
61 static void nv_crtc_load_state_ext(xf86CrtcPtr crtc, RIVA_HW_STATE *state);
62 static void nv_crtc_save_state_ext(xf86CrtcPtr crtc, RIVA_HW_STATE *state);
63 static void nv_crtc_save_state_vga(xf86CrtcPtr crtc, RIVA_HW_STATE *state);
64
65 static void NVWriteMiscOut(xf86CrtcPtr crtc, CARD8 value)
66 {
67   ScrnInfoPtr pScrn = crtc->scrn;
68   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
69   NVPtr pNv = NVPTR(pScrn);
70
71   NV_WR08(pNv->PVIO, VGA_MISC_OUT_W, value);
72 }
73
74 static CARD8 NVReadMiscOut(xf86CrtcPtr crtc)
75 {
76   ScrnInfoPtr pScrn = crtc->scrn;
77   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
78   NVPtr pNv = NVPTR(pScrn);
79
80   return NV_RD08(pNv->PVIO, VGA_MISC_OUT_R);
81 }
82
83
84 static void NVWriteVgaCrtc(xf86CrtcPtr crtc, CARD8 index, CARD8 value)
85 {
86   ScrnInfoPtr pScrn = crtc->scrn;
87   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
88   NVPtr pNv = NVPTR(pScrn);
89   volatile CARD8 *pCRTCReg = nv_crtc->crtc ? pNv->PCIO1 : pNv->PCIO0;
90
91   NV_WR08(pCRTCReg, CRTC_INDEX, index);
92   NV_WR08(pCRTCReg, CRTC_DATA, value);
93 }
94
95 static CARD8 NVReadVgaCrtc(xf86CrtcPtr crtc, CARD8 index)
96 {
97   ScrnInfoPtr pScrn = crtc->scrn;
98   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
99   NVPtr pNv = NVPTR(pScrn);
100   volatile CARD8 *pCRTCReg = nv_crtc->crtc ? pNv->PCIO1 : pNv->PCIO0;
101
102   NV_WR08(pCRTCReg, CRTC_INDEX, index);
103   return NV_RD08(pCRTCReg, CRTC_DATA);
104 }
105
106 static void NVWriteVgaSeq(xf86CrtcPtr crtc, CARD8 index, CARD8 value)
107 {
108   ScrnInfoPtr pScrn = crtc->scrn;
109   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
110   NVPtr pNv = NVPTR(pScrn);
111
112   NV_WR08(pNv->PVIO, VGA_SEQ_INDEX, index);
113   NV_WR08(pNv->PVIO, VGA_SEQ_DATA, value);
114 }
115
116 static CARD8 NVReadVgaSeq(xf86CrtcPtr crtc, CARD8 index)
117 {
118   ScrnInfoPtr pScrn = crtc->scrn;
119   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
120   NVPtr pNv = NVPTR(pScrn);
121   volatile CARD8 *pVGAReg = pNv->PVIO;
122
123   NV_WR08(pNv->PVIO, VGA_SEQ_INDEX, index);
124   return NV_RD08(pNv->PVIO, VGA_SEQ_DATA);
125 }
126
127 static void NVWriteVgaGr(xf86CrtcPtr crtc, CARD8 index, CARD8 value)
128 {
129   ScrnInfoPtr pScrn = crtc->scrn;
130   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
131   NVPtr pNv = NVPTR(pScrn);
132
133   NV_WR08(pNv->PVIO, VGA_GRAPH_INDEX, index);
134   NV_WR08(pNv->PVIO, VGA_GRAPH_DATA, value);
135 }
136
137 static CARD8 NVReadVgaGr(xf86CrtcPtr crtc, CARD8 index)
138 {
139   ScrnInfoPtr pScrn = crtc->scrn;
140   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
141   NVPtr pNv = NVPTR(pScrn);
142   volatile CARD8 *pVGAReg = pNv->PVIO;
143
144   NV_WR08(pVGAReg, VGA_GRAPH_INDEX, index);
145   return NV_RD08(pVGAReg, VGA_GRAPH_DATA);
146
147
148
149 static void NVWriteVgaAttr(xf86CrtcPtr crtc, CARD8 index, CARD8 value)
150 {
151   ScrnInfoPtr pScrn = crtc->scrn;
152   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
153   NVPtr pNv = NVPTR(pScrn);
154   volatile CARD8 *pCRTCReg = nv_crtc->crtc ? pNv->PCIO1 : pNv->PCIO0;
155
156   NV_RD08(pCRTCReg, CRTC_IN_STAT_1);
157   if (nv_crtc->paletteEnabled)
158     index &= ~0x20;
159   else
160     index |= 0x20;
161   NV_WR08(pCRTCReg, VGA_ATTR_INDEX, index);
162   NV_WR08(pCRTCReg, VGA_ATTR_DATA_W, value);
163 }
164
165 static CARD8 NVReadVgaAttr(xf86CrtcPtr crtc, CARD8 index)
166 {
167   ScrnInfoPtr pScrn = crtc->scrn;
168   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
169   NVPtr pNv = NVPTR(pScrn);
170   volatile CARD8 *pCRTCReg = nv_crtc->crtc ? pNv->PCIO1 : pNv->PCIO0;
171
172   NV_RD08(pCRTCReg, CRTC_IN_STAT_1);
173   if (nv_crtc->paletteEnabled)
174     index &= ~0x20;
175   else
176     index |= 0x20;
177   NV_WR08(pCRTCReg, VGA_ATTR_INDEX, index);
178   return NV_RD08(pCRTCReg, VGA_ATTR_DATA_R);
179 }
180
181 void NVCrtcSetOwner(xf86CrtcPtr crtc)
182 {
183   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
184   /*TODO beos double writes this on nv11 */
185   NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_OWNER, nv_crtc->crtc * 0x3);
186 }
187
188 static void
189 NVEnablePalette(xf86CrtcPtr crtc)
190 {
191   ScrnInfoPtr pScrn = crtc->scrn;
192   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
193   NVPtr pNv = NVPTR(pScrn);
194   volatile CARD8 *pCRTCReg = nv_crtc->crtc ? pNv->PCIO1 : pNv->PCIO0;
195
196   NV_RD08(pCRTCReg, CRTC_IN_STAT_1);
197   NV_WR08(pCRTCReg, VGA_ATTR_INDEX, 0);
198   nv_crtc->paletteEnabled = TRUE;
199 }
200
201 static void
202 NVDisablePalette(xf86CrtcPtr crtc)
203 {
204   ScrnInfoPtr pScrn = crtc->scrn;
205   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
206   NVPtr pNv = NVPTR(pScrn);
207   volatile CARD8 *pCRTCReg = nv_crtc->crtc ? pNv->PCIO1 : pNv->PCIO0;
208
209   NV_RD08(pCRTCReg, CRTC_IN_STAT_1);
210   NV_WR08(pCRTCReg, VGA_ATTR_INDEX, 0x20);
211   nv_crtc->paletteEnabled = FALSE;
212 }
213
214 static void NVWriteVgaReg(xf86CrtcPtr crtc, CARD32 reg, CARD8 value)
215 {
216  ScrnInfoPtr pScrn = crtc->scrn;
217   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
218   NVPtr pNv = NVPTR(pScrn);
219   volatile CARD8 *pCRTCReg = nv_crtc->crtc ? pNv->PCIO1 : pNv->PCIO0;
220
221   NV_WR08(pCRTCReg, reg, value);
222 }
223
224 /* perform a sequencer reset */
225 static void NVVgaSeqReset(xf86CrtcPtr crtc, Bool start)
226 {
227   if (start)
228     NVWriteVgaSeq(crtc, 0x00, 0x1);
229   else
230     NVWriteVgaSeq(crtc, 0x00, 0x3);
231
232 }
233 static void NVVgaProtect(xf86CrtcPtr crtc, Bool on)
234 {
235   CARD8 tmp;
236
237   if (on) {
238     tmp = NVReadVgaSeq(crtc, 0x1);
239     NVVgaSeqReset(crtc, TRUE);
240     NVWriteVgaSeq(crtc, 0x01, tmp | 0x20);
241
242     NVEnablePalette(crtc);
243   } else {
244     /*
245      * Reenable sequencer, then turn on screen.
246      */
247     tmp = NVReadVgaSeq(crtc, 0x1);
248     NVWriteVgaSeq(crtc, 0x01, tmp & ~0x20);     /* reenable display */
249     NVVgaSeqReset(crtc, FALSE);
250
251     NVDisablePalette(crtc);
252   }
253 }
254
255 void NVCrtcLockUnlock(xf86CrtcPtr crtc, Bool Lock)
256 {
257   CARD8 cr11;
258
259   NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_LOCK, Lock ? 0x99 : 0x57);
260   cr11 = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_VSYNCE);
261   if (Lock) cr11 |= 0x80;
262   else cr11 &= ~0x80;
263   NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_VSYNCE, cr11);
264 }
265 /*
266  * Calculate the Video Clock parameters for the PLL.
267  */
268 static void CalcVClock (
269         int             clockIn,
270         int             *clockOut,
271         CARD32          *pllOut,
272         NVPtr           pNv
273 )
274 {
275         unsigned lowM, highM, highP;
276         unsigned DeltaNew, DeltaOld;
277         unsigned VClk, Freq;
278         unsigned M, N, P;
279
280         /* M: PLL reference frequency postscaler divider */
281         /* P: PLL VCO output postscaler divider */
282         /* N: PLL VCO postscaler setting */
283
284         DeltaOld = 0xFFFFFFFF;
285
286         VClk = (unsigned)clockIn;
287
288         /* Taken from Haiku, after someone with an NV28 had an issue */
289         switch(pNv->NVArch) {
290                 case 0x28:
291                         lowM = 1;
292                         highP = 32;
293                         if (VClk > 340000) {
294                                 highM = 2;
295                         } else if (VClk > 200000) {
296                                 highM = 4;
297                         } else if (VClk > 150000) {
298                                 highM = 6;
299                         } else {
300                                 highM = 14;
301                         }
302                         break;
303                 default:
304                         lowM = 1;
305                         highP = 16;
306                         if (VClk > 340000) {
307                                 highM = 2;
308                         } else if (VClk > 250000) {
309                                 highM = 6;
310                         } else {
311                                 highM = 14;
312                         }
313                         break;
314         }
315
316         for (P = 0; P <= highP; P++) {
317                 Freq = VClk << P;
318                 if ((Freq >= 128000) && (Freq <= 350000)) {
319                         for (M = lowM; M <= highM; M++) {
320                                 N = ((VClk << P) * M) / pNv->CrystalFreqKHz;
321                                 if (N <= 255) {
322                                         Freq = ((pNv->CrystalFreqKHz * N) / M) >> P;
323                                         if (Freq > VClk) {
324                                                 DeltaNew = Freq - VClk;
325                                         } else {
326                                                 DeltaNew = VClk - Freq;
327                                         }
328                                         if (DeltaNew < DeltaOld) {
329                                                 *pllOut   = (P << 16) | (N << 8) | M;
330                                                 *clockOut = Freq;
331                                                 DeltaOld  = DeltaNew;
332                                         }
333                                 }
334                         }
335                 }
336         }
337 }
338
339 static void CalcVClock2Stage (
340         int             clockIn,
341         int             *clockOut,
342         CARD32          *pllOut,
343         CARD32          *pllBOut,
344         NVPtr           pNv
345 )
346 {
347         unsigned DeltaNew, DeltaOld;
348         unsigned VClk, Freq;
349         unsigned M, N, P;
350         unsigned lowM, highM, highP;
351
352         DeltaOld = 0xFFFFFFFF;
353
354         *pllBOut = 0x80000401;  /* fixed at x4 for now */
355
356         VClk = (unsigned)clockIn;
357
358         /* Taken from Haiku, after someone with an NV28 had an issue */
359         switch(pNv->NVArch) {
360                 case 0x28:
361                         lowM = 1;
362                         highP = 32;
363                         if (VClk > 340000) {
364                                 highM = 2;
365                         } else if (VClk > 200000) {
366                                 highM = 4;
367                         } else if (VClk > 150000) {
368                                 highM = 6;
369                         } else {
370                                 highM = 14;
371                         }
372                         break;
373                 default:
374                         lowM = 1;
375                         highP = 16;
376                         if (VClk > 340000) {
377                                 highM = 2;
378                         } else if (VClk > 250000) {
379                                 highM = 6;
380                         } else {
381                                 highM = 14;
382                         }
383                         break;
384         }
385
386         for (P = 0; P <= highP; P++) {
387                 Freq = VClk << P;
388                 if ((Freq >= 400000) && (Freq <= 1000000)) {
389                         for (M = lowM; M <= highM; M++) {
390                                 N = ((VClk << P) * M) / (pNv->CrystalFreqKHz << 2);
391                                 if ((N >= 5) && (N <= 255)) {
392                                         Freq = (((pNv->CrystalFreqKHz << 2) * N) / M) >> P;
393                                         if (Freq > VClk) {
394                                                 DeltaNew = Freq - VClk;
395                                         } else {
396                                                 DeltaNew = VClk - Freq;
397                                         }
398                                         if (DeltaNew < DeltaOld) {
399                                                 *pllOut   = (P << 16) | (N << 8) | M;
400                                                 *clockOut = Freq;
401                                                 DeltaOld  = DeltaNew;
402                                         }
403                                 }
404                         }
405                 }
406         }
407 }
408
409 static void nv_crtc_save_state_pll(NVPtr pNv, RIVA_HW_STATE *state)
410 {
411         state->vpll = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL);
412         if(pNv->twoHeads) {
413                 state->vpll2 = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL2);
414         }
415         if(pNv->twoStagePLL) {
416                 state->vpllB = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL_B);
417                 state->vpll2B = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL2_B);
418         }
419         state->pllsel = nvReadRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT);
420 }
421
422
423 static void nv_crtc_load_state_pll(NVPtr pNv, RIVA_HW_STATE *state)
424 {
425         nvWriteRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT, state->pllsel);
426
427         ErrorF("writting vpll %08X\n", state->vpll);
428         ErrorF("writting vpll2 %08X\n", state->vpll2);
429         nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL, state->vpll);
430         if(pNv->twoHeads) {
431                 nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2, state->vpll2);
432         }
433         if(pNv->twoStagePLL) {
434                 nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL_B, state->vpllB);
435                 nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2_B, state->vpll2B);
436         }  
437 }
438
439 /*
440  * Calculate extended mode parameters (SVGA) and save in a 
441  * mode state structure.
442  */
443 void nv_crtc_calc_state_ext(
444     xf86CrtcPtr crtc,
445     int            bpp,
446     int            width,
447     int            hDisplaySize,
448     int            height,
449     int            dotClock,
450     int            flags 
451 )
452 {
453     ScrnInfoPtr pScrn = crtc->scrn;
454     int pixelDepth, VClk;
455     CARD32 CursorStart;
456     NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
457     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
458     NVCrtcRegPtr regp;
459     NVPtr pNv = NVPTR(pScrn);    
460     RIVA_HW_STATE *state;
461     int num_crtc_enabled, i;
462
463     state = &pNv->ModeReg;
464
465     regp = &pNv->ModeReg.crtc_reg[nv_crtc->crtc];
466
467     /*
468      * Extended RIVA registers.
469      */
470     pixelDepth = (bpp + 1)/8;
471     if(pNv->twoStagePLL)
472         CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, pNv);
473     else
474         CalcVClock(dotClock, &VClk, &state->pll, pNv);
475
476     switch (pNv->Architecture)
477     {
478         case NV_ARCH_04:
479             nv4UpdateArbitrationSettings(VClk, 
480                                          pixelDepth * 8, 
481                                         &(state->arbitration0),
482                                         &(state->arbitration1),
483                                          pNv);
484             regp->CRTC[NV_VGA_CRTCX_CURCTL0] = 0x00;
485             regp->CRTC[NV_VGA_CRTCX_CURCTL1] = 0xbC;
486             if (flags & V_DBLSCAN)
487                 regp->CRTC[NV_VGA_CRTCX_CURCTL1] |= 2;
488             regp->CRTC[NV_VGA_CRTCX_CURCTL2] = 0x00000000;
489             state->pllsel   |= NV_RAMDAC_PLL_SELECT_VCLK_RATIO_DB2 | NV_RAMDAC_PLL_SELECT_PLL_SOURCE_ALL; 
490             state->config   = 0x00001114;
491             regp->CRTC[NV_VGA_CRTCX_REPAINT1] = hDisplaySize < 1280 ? 0x04 : 0x00;
492             break;
493         case NV_ARCH_10:
494         case NV_ARCH_20:
495         case NV_ARCH_30:
496         default:
497             if(((pNv->Chipset & 0xfff0) == CHIPSET_C51) ||
498                ((pNv->Chipset & 0xfff0) == CHIPSET_C512))
499             {
500                 state->arbitration0 = 128; 
501                 state->arbitration1 = 0x0480; 
502             } else
503             if(((pNv->Chipset & 0xffff) == CHIPSET_NFORCE) ||
504                ((pNv->Chipset & 0xffff) == CHIPSET_NFORCE2))
505             {
506                 nForceUpdateArbitrationSettings(VClk,
507                                           pixelDepth * 8,
508                                          &(state->arbitration0),
509                                          &(state->arbitration1),
510                                           pNv);
511             } else if(pNv->Architecture < NV_ARCH_30) {
512                 nv10UpdateArbitrationSettings(VClk, 
513                                           pixelDepth * 8, 
514                                          &(state->arbitration0),
515                                          &(state->arbitration1),
516                                           pNv);
517             } else {
518                 nv30UpdateArbitrationSettings(pNv,
519                                          &(state->arbitration0),
520                                          &(state->arbitration1));
521             }
522
523
524             CursorStart = pNv->Cursor->offset;
525
526             regp->CRTC[NV_VGA_CRTCX_CURCTL0] = 0x80 | (CursorStart >> 17);
527             regp->CRTC[NV_VGA_CRTCX_CURCTL1] = (CursorStart >> 11) << 2;
528             regp->CRTC[NV_VGA_CRTCX_CURCTL2] = CursorStart >> 24;
529
530             if (flags & V_DBLSCAN) 
531                 regp->CRTC[NV_VGA_CRTCX_CURCTL1]|= 2;
532
533
534             state->config   = nvReadFB(pNv, NV_PFB_CFG0);
535             regp->CRTC[NV_VGA_CRTCX_REPAINT1] = hDisplaySize < 1280 ? 0x04 : 0x00;
536             break;
537     }
538
539         /* okay do we have 2 CRTCs running ? */
540         num_crtc_enabled = 0;
541         for (i = 0; i < xf86_config->num_crtc; i++) {
542                 if (xf86_config->crtc[i]->enabled) {
543                         num_crtc_enabled++;
544                 }
545         }
546
547         if (nv_crtc->crtc == 1) {
548                 state->vpll2 = state->pll;
549                 state->vpll2B = state->pllB;
550                 state->pllsel |= NV_RAMDAC_PLL_SELECT_VCLK2_RATIO_DB2;
551                 state->pllsel |= NV_RAMDAC_PLL_SELECT_PLL_SOURCE_CRTC1;
552         } else {
553                 state->vpll = state->pll;
554                 state->vpllB = state->pllB;
555                 state->pllsel |= NV_RAMDAC_PLL_SELECT_PLL_SOURCE_ALL;
556                 state->pllsel &= ~NV_RAMDAC_PLL_SELECT_VCLK_RATIO_DB2;
557         }
558
559     regp->CRTC[NV_VGA_CRTCX_FIFO0] = state->arbitration0;
560     regp->CRTC[NV_VGA_CRTCX_FIFO_LWM] = state->arbitration1 & 0xff;
561     if (pNv->Architecture >= NV_ARCH_30) {
562       regp->CRTC[NV_VGA_CRTCX_FIFO_LWM_NV30] = state->arbitration1 >> 8;
563     }
564     
565     
566     regp->CRTC[NV_VGA_CRTCX_REPAINT0] = (((width / 8) * pixelDepth) & 0x700) >> 3;
567     regp->CRTC[NV_VGA_CRTCX_PIXEL] = (pixelDepth > 2) ? 3 : pixelDepth;
568 }
569
570
571 static void
572 nv_crtc_dpms(xf86CrtcPtr crtc, int mode)
573 {
574      NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
575      unsigned char seq1 = 0, crtc17 = 0;
576      unsigned char crtc1A;
577      int ret;
578      Bool crtc_is_on = FALSE;
579
580      NVCrtcSetOwner(crtc);
581
582      crtc1A = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_REPAINT1) & ~0xC0;
583      switch(mode) {
584      case DPMSModeStandby:
585        /* Screen: Off; HSync: Off, VSync: On -- Not Supported */
586        seq1 = 0x20;
587        crtc17 = 0x80;
588        crtc1A |= 0x80;
589        break;
590      case DPMSModeSuspend:
591        /* Screen: Off; HSync: On, VSync: Off -- Not Supported */
592        seq1 = 0x20;
593        crtc17 = 0x80;
594        crtc1A |= 0x40;
595        break;
596      case DPMSModeOff:
597        /* Screen: Off; HSync: Off, VSync: Off */
598        seq1 = 0x20;
599        crtc17 = 0x00;
600        crtc1A |= 0xC0;
601        break;
602      case DPMSModeOn:
603      default:
604        /* Screen: On; HSync: On, VSync: On */
605        seq1 = 0x00;
606        crtc17 = 0x80;
607        crtc_is_on = TRUE;
608        break;
609      }
610
611      NVWriteVgaSeq(crtc, 0x00, 0x1);
612      seq1 = NVReadVgaSeq(crtc, 0x01) & ~0x20;
613      NVWriteVgaSeq(crtc, 0x1, seq1);
614      crtc17 |= NVReadVgaCrtc(crtc, NV_VGA_CRTCX_MODECTL) & ~0x80;
615      usleep(10000);
616      NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_MODECTL, crtc17);
617      NVWriteVgaSeq(crtc, 0x0, 0x3);
618
619      NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_REPAINT1, crtc1A);
620
621         /* This is usefull for Xv NVWaitVSync() */
622         nv_crtc->pNv->crtc_active[nv_crtc->crtc] = crtc_is_on;
623 }
624
625 static Bool
626 nv_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
627                      DisplayModePtr adjusted_mode)
628 {
629     return TRUE;
630 }
631
632 static void
633 nv_crtc_mode_set_vga(xf86CrtcPtr crtc, DisplayModePtr mode)
634 {
635         ScrnInfoPtr pScrn = crtc->scrn;
636         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
637         NVCrtcRegPtr regp;
638         NVPtr pNv = NVPTR(pScrn);
639         int depth = pScrn->depth;
640         unsigned int i;
641         uint32_t drain;
642
643         regp = &pNv->ModeReg.crtc_reg[nv_crtc->crtc];
644
645         /* Initializing some default bios settings */
646
647         /* This is crude, but if it works for Haiku ;-) */
648         drain = mode->HDisplay * mode->VDisplay * pScrn->bitsPerPixel;
649
650         if ( drain <= 1024*768*4 ) {
651                 /* CRTC fifo burst size */
652                 regp->CRTC[NV_VGA_CRTCX_FIFO0] = 0x03;
653                 /* CRTC fifo fetch interval */
654                 regp->CRTC[NV_VGA_CRTCX_FIFO_LWM] = 0x20;
655         } else if (drain <= 1280*1024*4) {
656                 regp->CRTC[NV_VGA_CRTCX_FIFO0] = 0x02;
657                 regp->CRTC[NV_VGA_CRTCX_FIFO_LWM] = 0x40;
658         } else {
659                 regp->CRTC[NV_VGA_CRTCX_FIFO0] = 0x01;
660                 regp->CRTC[NV_VGA_CRTCX_FIFO_LWM] = 0x40;
661         }
662
663         /*
664         * compute correct Hsync & Vsync polarity 
665         */
666         if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
667                 && (mode->Flags & (V_PVSYNC | V_NVSYNC))) {
668
669                 regp->MiscOutReg = 0x23;
670                 if (mode->Flags & V_NHSYNC) regp->MiscOutReg |= 0x40;
671                 if (mode->Flags & V_NVSYNC) regp->MiscOutReg |= 0x80;
672         } else {
673                 int VDisplay = mode->VDisplay;
674                 if (mode->Flags & V_DBLSCAN)
675                         VDisplay *= 2;
676                 if (mode->VScan > 1)
677                         VDisplay *= mode->VScan;
678                 if (VDisplay < 400) {
679                         regp->MiscOutReg = 0xA3;                /* +hsync -vsync */
680                 } else if (VDisplay < 480) {
681                         regp->MiscOutReg = 0x63;                /* -hsync +vsync */
682                 } else if (VDisplay < 768) {
683                         regp->MiscOutReg = 0xE3;                /* -hsync -vsync */
684                 } else {
685                         regp->MiscOutReg = 0x23;                /* +hsync +vsync */
686                 }
687         }
688
689         regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2;
690
691         /*
692         * Time Sequencer
693         */
694         if (depth == 4) {
695                 regp->Sequencer[0] = 0x02;
696         } else {
697                 regp->Sequencer[0] = 0x00;
698         }
699         if (mode->Flags & V_CLKDIV2) {
700                 regp->Sequencer[1] = 0x09;
701         } else {
702                 regp->Sequencer[1] = 0x01;
703         }
704         if (depth == 1) {
705                 regp->Sequencer[2] = 1 << BIT_PLANE;
706         } else {
707                 regp->Sequencer[2] = 0x0F;
708                 regp->Sequencer[3] = 0x00;                     /* Font select */
709         }
710         if (depth < 8) {
711                 regp->Sequencer[4] = 0x06;                             /* Misc */
712         } else {
713                 regp->Sequencer[4] = 0x0E;                             /* Misc */
714         }
715
716         /*
717         * CRTC Controller
718         */
719         regp->CRTC[0]  = (mode->CrtcHTotal >> 3) - 5;
720         regp->CRTC[1]  = (mode->CrtcHDisplay >> 3) - 1;
721         regp->CRTC[2]  = (mode->CrtcHBlankStart >> 3) - 1;
722         regp->CRTC[3]  = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
723         i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F);
724         if (i < 0x80) {
725                 regp->CRTC[3] |= i;
726         }
727         regp->CRTC[4]  = (mode->CrtcHSyncStart >> 3);
728         regp->CRTC[5]  = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
729         | (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
730         regp->CRTC[6]  = (mode->CrtcVTotal - 2) & 0xFF;
731         regp->CRTC[7]  = (((mode->CrtcVTotal - 2) & 0x100) >> 8)
732                         | (((mode->CrtcVDisplay - 1) & 0x100) >> 7)
733                         | ((mode->CrtcVSyncStart & 0x100) >> 6)
734                         | (((mode->CrtcVBlankStart - 1) & 0x100) >> 5)
735                         | 0x10
736                         | (((mode->CrtcVTotal - 2) & 0x200)   >> 4)
737                         | (((mode->CrtcVDisplay - 1) & 0x200) >> 3)
738                         | ((mode->CrtcVSyncStart & 0x200) >> 2);
739         regp->CRTC[8]  = 0x00;
740         regp->CRTC[9]  = (((mode->CrtcVBlankStart - 1) & 0x200) >> 4) | 0x40;
741         if (mode->Flags & V_DBLSCAN) {
742                 regp->CRTC[9] |= 0x80;
743         }
744         if (mode->VScan >= 32) {
745                 regp->CRTC[9] |= 0x1F;
746         } else if (mode->VScan > 1) {
747                 regp->CRTC[9] |= mode->VScan - 1;
748         }
749         regp->CRTC[10] = 0x00;
750         regp->CRTC[11] = 0x00;
751         regp->CRTC[12] = 0x00;
752         regp->CRTC[13] = 0x00;
753         regp->CRTC[14] = 0x00;
754         regp->CRTC[15] = 0x00;
755         regp->CRTC[16] = mode->CrtcVSyncStart & 0xFF;
756         regp->CRTC[17] = (mode->CrtcVSyncEnd & 0x0F) | 0x20;
757         regp->CRTC[18] = (mode->CrtcVDisplay - 1) & 0xFF;
758         regp->CRTC[19] = mode->CrtcHDisplay >> 4;  /* just a guess */
759         regp->CRTC[20] = 0x00;
760         regp->CRTC[21] = (mode->CrtcVBlankStart - 1) & 0xFF; 
761         regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
762         if (depth < 8) {
763                 regp->CRTC[23] = 0xE3;
764         } else {
765                 regp->CRTC[23] = 0xC3;
766         }
767         regp->CRTC[24] = 0xFF;
768
769         /*
770         * Theory resumes here....
771         */
772
773         /*
774         * Graphics Display Controller
775         */
776         regp->Graphics[0] = 0x00;
777         regp->Graphics[1] = 0x00;
778         regp->Graphics[2] = 0x00;
779         regp->Graphics[3] = 0x00;
780         if (depth == 1) {
781                 regp->Graphics[4] = BIT_PLANE;
782                 regp->Graphics[5] = 0x00;
783         } else {
784                 regp->Graphics[4] = 0x00;
785                 if (depth == 4) {
786                         regp->Graphics[5] = 0x02;
787                 } else {
788                         regp->Graphics[5] = 0x40;
789                 }
790         }
791         regp->Graphics[6] = 0x05;   /* only map 64k VGA memory !!!! */
792         regp->Graphics[7] = 0x0F;
793         regp->Graphics[8] = 0xFF;
794   
795         if (depth == 1) {
796                 /* Initialise the Mono map according to which bit-plane gets used */
797
798                 Bool flipPixels = xf86GetFlipPixels();
799
800                 for (i=0; i<16; i++) {
801                         if (((i & (1 << BIT_PLANE)) != 0) != flipPixels) {
802                                 regp->Attribute[i] = WHITE_VALUE;
803                         } else {
804                                 regp->Attribute[i] = BLACK_VALUE;
805                         }
806                 }
807
808         } else {
809                 regp->Attribute[0]  = 0x00; /* standard colormap translation */
810                 regp->Attribute[1]  = 0x01;
811                 regp->Attribute[2]  = 0x02;
812                 regp->Attribute[3]  = 0x03;
813                 regp->Attribute[4]  = 0x04;
814                 regp->Attribute[5]  = 0x05;
815                 regp->Attribute[6]  = 0x06;
816                 regp->Attribute[7]  = 0x07;
817                 regp->Attribute[8]  = 0x08;
818                 regp->Attribute[9]  = 0x09;
819                 regp->Attribute[10] = 0x0A;
820                 regp->Attribute[11] = 0x0B;
821                 regp->Attribute[12] = 0x0C;
822                 regp->Attribute[13] = 0x0D;
823                 regp->Attribute[14] = 0x0E;
824                 regp->Attribute[15] = 0x0F;
825                 if (depth == 4) {
826                         regp->Attribute[16] = 0x81; /* wrong for the ET4000 */
827                 } else {
828                         regp->Attribute[16] = 0x41; /* wrong for the ET4000 */
829                 }
830                 if (depth > 4) {
831                         regp->Attribute[17] = 0xff;
832                 }
833                 /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */
834         }
835         regp->Attribute[18] = 0x0F;
836         regp->Attribute[19] = 0x00;
837         regp->Attribute[20] = 0x00;
838 }
839
840 /**
841  * Sets up registers for the given mode/adjusted_mode pair.
842  *
843  * The clocks, CRTCs and outputs attached to this CRTC must be off.
844  *
845  * This shouldn't enable any clocks, CRTCs, or outputs, but they should
846  * be easily turned on/off after this.
847  */
848 static void
849 nv_crtc_mode_set_regs(xf86CrtcPtr crtc, DisplayModePtr mode)
850 {
851         ScrnInfoPtr pScrn = crtc->scrn;
852         NVPtr pNv = NVPTR(pScrn);
853         NVRegPtr state = &pNv->ModeReg;
854         xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
855         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
856         NVFBLayout *pLayout = &pNv->CurrentLayout;
857         NVCrtcRegPtr regp, savep;
858         unsigned int i;
859         int horizDisplay    = (mode->CrtcHDisplay/8)   - 1;
860         int horizStart      = (mode->CrtcHSyncStart/8) - 1;
861         int horizEnd        = (mode->CrtcHSyncEnd/8)   - 1;
862         int horizTotal      = (mode->CrtcHTotal/8)     - 5;
863         int horizBlankStart = (mode->CrtcHDisplay/8)   - 1;
864         int horizBlankEnd   = (mode->CrtcHTotal/8)     - 1;
865         int vertDisplay     =  mode->CrtcVDisplay      - 1;
866         int vertStart       =  mode->CrtcVSyncStart    - 1;
867         int vertEnd         =  mode->CrtcVSyncEnd      - 1;
868         int vertTotal       =  mode->CrtcVTotal        - 2;
869         int vertBlankStart  =  mode->CrtcVDisplay      - 1;
870         int vertBlankEnd    =  mode->CrtcVTotal        - 1;
871         /* What about vsync and hsync? */
872
873         Bool is_fp = FALSE;
874
875         for (i = 0; i < xf86_config->num_output; i++) {
876                 xf86OutputPtr  output = xf86_config->output[i];
877                 NVOutputPrivatePtr nv_output = output->driver_private;
878
879                 if (output->crtc == crtc) {
880                         if ((nv_output->type == OUTPUT_PANEL) || 
881                                 (nv_output->type == OUTPUT_DIGITAL)) {
882
883                                 is_fp = TRUE;
884                         }
885                 }
886         }
887
888         ErrorF("crtc: Pre-sync workaround\n");
889         /* The CRTC needs a little time to stay in sync at panel resultion */
890         /* I don't know at this state if this is the case, but elsewere is just a hack as well */
891         /* Any better ideas were to put this? */
892         if (is_fp) {
893                 if (pNv->Architecture >= NV_ARCH_40) {
894                         horizTotal -= 56/8;
895                         /* This is my observation, screen becomes fuzzy otherwise */
896                         /* Maybe this is because the crtc timing needs to end before the dfp's? */
897                         /* Check this on older hardware please */
898                         vertTotal -= 1;
899                 } else if (pNv->NVArch == 0x11) {
900                         horizTotal -= 56/8;
901                 } else {
902                         horizTotal -= 32/8;
903                 }
904         }
905         ErrorF("crtc: Post-sync workaround\n");
906
907         regp = &pNv->ModeReg.crtc_reg[nv_crtc->crtc];    
908         savep = &pNv->SavedReg.crtc_reg[nv_crtc->crtc];
909
910         if(mode->Flags & V_INTERLACE) 
911                 vertTotal |= 1;
912
913         regp->CRTC[NV_VGA_CRTCX_HTOTAL]  = Set8Bits(horizTotal);
914         regp->CRTC[NV_VGA_CRTCX_HDISPE]  = Set8Bits(horizDisplay);
915         regp->CRTC[NV_VGA_CRTCX_HBLANKS]  = Set8Bits(horizBlankStart);
916         regp->CRTC[NV_VGA_CRTCX_HBLANKE]  = SetBitField(horizBlankEnd,4:0,4:0) 
917                                 | SetBit(7);
918         regp->CRTC[NV_VGA_CRTCX_HSYNCS]  = Set8Bits(horizStart);
919         regp->CRTC[NV_VGA_CRTCX_HSYNCE]  = SetBitField(horizBlankEnd,5:5,7:7)
920                                 | SetBitField(horizEnd,4:0,4:0);
921         regp->CRTC[NV_VGA_CRTCX_VTOTAL]  = SetBitField(vertTotal,7:0,7:0);
922         regp->CRTC[NV_VGA_CRTCX_OVERFLOW]  = SetBitField(vertTotal,8:8,0:0)
923                                 | SetBitField(vertDisplay,8:8,1:1)
924                                 | SetBitField(vertStart,8:8,2:2)
925                                 | SetBitField(vertBlankStart,8:8,3:3)
926                                 | SetBit(4)
927                                 | SetBitField(vertTotal,9:9,5:5)
928                                 | SetBitField(vertDisplay,9:9,6:6)
929                                 | SetBitField(vertStart,9:9,7:7);
930         regp->CRTC[NV_VGA_CRTCX_MAXSCLIN]  = SetBitField(vertBlankStart,9:9,5:5)
931                                 | SetBit(6)
932                                 | ((mode->Flags & V_DBLSCAN) ? 0x80 : 0x00);
933         regp->CRTC[NV_VGA_CRTCX_VSYNCS] = Set8Bits(vertStart);
934         regp->CRTC[NV_VGA_CRTCX_VSYNCE] = SetBitField(vertEnd,3:0,3:0) | SetBit(5);
935         regp->CRTC[NV_VGA_CRTCX_VDISPE] = Set8Bits(vertDisplay);
936         regp->CRTC[NV_VGA_CRTCX_PITCHL] = ((pLayout->displayWidth/8)*(pLayout->bitsPerPixel/8));
937         regp->CRTC[NV_VGA_CRTCX_VBLANKS] = Set8Bits(vertBlankStart);
938         regp->CRTC[NV_VGA_CRTCX_VBLANKE] = Set8Bits(vertBlankEnd);
939
940         regp->Attribute[0x10] = 0x01;
941
942         if(pNv->Television)
943                 regp->Attribute[0x11] = 0x00;
944
945         regp->CRTC[NV_VGA_CRTCX_LSR] = SetBitField(horizBlankEnd,6:6,4:4)
946                                 | SetBitField(vertBlankStart,10:10,3:3)
947                                 | SetBitField(vertStart,10:10,2:2)
948                                 | SetBitField(vertDisplay,10:10,1:1)
949                                 | SetBitField(vertTotal,10:10,0:0);
950
951         regp->CRTC[NV_VGA_CRTCX_HEB] = SetBitField(horizTotal,8:8,0:0) 
952                                 | SetBitField(horizDisplay,8:8,1:1)
953                                 | SetBitField(horizBlankStart,8:8,2:2)
954                                 | SetBitField(horizStart,8:8,3:3);
955
956         regp->CRTC[NV_VGA_CRTCX_EXTRA] = SetBitField(vertTotal,11:11,0:0)
957                                 | SetBitField(vertDisplay,11:11,2:2)
958                                 | SetBitField(vertStart,11:11,4:4)
959                                 | SetBitField(vertBlankStart,11:11,6:6);
960
961         if(mode->Flags & V_INTERLACE) {
962                 horizTotal = (horizTotal >> 1) & ~1;
963                 regp->CRTC[NV_VGA_CRTCX_INTERLACE] = Set8Bits(horizTotal);
964                 regp->CRTC[NV_VGA_CRTCX_HEB] |= SetBitField(horizTotal,8:8,4:4);
965         } else {
966                 regp->CRTC[NV_VGA_CRTCX_INTERLACE] = 0xff;  /* interlace off */
967         }
968
969         regp->CRTC[NV_VGA_CRTCX_BUFFER] = 0xfa;
970
971         if (is_fp) {
972                 /* Maybe we need more to enable DFP screens, haiku has some info on this register */
973                 regp->CRTC[NV_VGA_CRTCX_LCD] = (1 << 3) | (1 << 0);
974         } else {
975                 regp->CRTC[NV_VGA_CRTCX_LCD] = 0;
976         }
977
978         /* I'm trusting haiku driver on this one, they say it enables an external TDMS clock */
979         if (is_fp) {
980                 regp->CRTC[NV_VGA_CRTCX_59] = 0x1;
981         } else {
982                 regp->CRTC[NV_VGA_CRTCX_59] = 0x0;
983         }
984
985         /*
986         * Initialize DAC palette.
987         */
988         if(pLayout->bitsPerPixel != 8 ) {
989                 for (i = 0; i < 256; i++) {
990                         regp->DAC[i*3]     = i;
991                         regp->DAC[(i*3)+1] = i;
992                         regp->DAC[(i*3)+2] = i;
993                 }
994         }
995
996         /*
997         * Calculate the extended registers.
998         */
999
1000         if(pLayout->depth < 24) {
1001                 i = pLayout->depth;
1002         } else {
1003                 i = 32;
1004         }
1005
1006         if(pNv->Architecture >= NV_ARCH_10) {
1007                 pNv->CURSOR = (CARD32 *)pNv->Cursor->map;
1008         }
1009
1010         ErrorF("crtc %d %d %d\n", nv_crtc->crtc, mode->CrtcHDisplay, pLayout->displayWidth);
1011         nv_crtc_calc_state_ext(crtc,
1012                                 i,
1013                                 pLayout->displayWidth,
1014                                 mode->CrtcHDisplay,
1015                                 mode->CrtcVDisplay,
1016                                 mode->Clock,
1017                                 mode->Flags);
1018
1019         if (is_fp) {
1020                 regp->CRTC[NV_VGA_CRTCX_PIXEL] |= (1 << 7);
1021         }
1022
1023         /* This is the value i have, blob seems to use others as well */
1024         regp->CRTC[NV_VGA_CRTCX_FIFO1] = 0x1c;
1025
1026         if(nv_crtc->crtc) {
1027                 if (is_fp) {
1028                         regp->head &= ~NV_CRTC_FSEL_FPP2;
1029                         regp->head |= NV_CRTC_FSEL_FPP1;
1030                 } else {
1031                         regp->head &= ~NV_CRTC_FSEL_FPP1;
1032                         regp->head |= NV_CRTC_FSEL_FPP2;
1033                 }
1034
1035                 regp->crtcOwner = 3;
1036         /* only enable secondary pllsel if CRTC 1 is selected on */
1037         } else {
1038                 /* Maybe use pNv->crtc_active[1], or is it too early for that? */
1039                 if(pNv->twoHeads) {
1040                         regp->head  =  savep->head | 0x00001000;
1041                         if (is_fp) {
1042                                 regp->head &= ~NV_CRTC_FSEL_FPP2;
1043                                 regp->head |= NV_CRTC_FSEL_FPP1;
1044                         } else {
1045                                 regp->head &= ~NV_CRTC_FSEL_FPP1;
1046                                 regp->head |= NV_CRTC_FSEL_FPP2;
1047                         }
1048
1049                         regp->crtcOwner = 0;
1050                 }
1051         }
1052
1053         regp->cursorConfig = 0x00000100;
1054         if(mode->Flags & V_DBLSCAN)
1055                 regp->cursorConfig |= (1 << 4);
1056         if(pNv->alphaCursor) {
1057                 if((pNv->Chipset & 0x0ff0) != CHIPSET_NV11) {
1058                         regp->cursorConfig |= 0x04011000;
1059                 } else {
1060                         regp->cursorConfig |= 0x14011000;
1061                 }
1062         } else {
1063                 regp->cursorConfig |= 0x02000000;
1064         }
1065
1066         regp->CRTC[NV_VGA_CRTCX_FP_HTIMING] = 0;
1067         regp->CRTC[NV_VGA_CRTCX_FP_VTIMING] = 0;
1068
1069         /* blob sets this value */
1070         regp->CRTC[NV_VGA_CRTCX_3C] = 0x70;
1071         regp->CRTC[NV_VGA_CRTCX_45] = 0x80;
1072         regp->CRTC[NV_VGA_CRTCX_47] = 0x01;
1073
1074         /* more blob imitating */
1075         if (nv_crtc->crtc == 1) {
1076                 regp->CRTC[NV_VGA_CRTCX_56] = 0x04;
1077         } else {
1078                 regp->CRTC[NV_VGA_CRTCX_56] = 0x0;
1079         }
1080
1081         regp->unk830 = mode->CrtcVDisplay - 3;
1082         regp->unk834 = mode->CrtcVDisplay - 1;
1083 }
1084
1085 /**
1086  * Sets up registers for the given mode/adjusted_mode pair.
1087  *
1088  * The clocks, CRTCs and outputs attached to this CRTC must be off.
1089  *
1090  * This shouldn't enable any clocks, CRTCs, or outputs, but they should
1091  * be easily turned on/off after this.
1092  */
1093 static void
1094 nv_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
1095                  DisplayModePtr adjusted_mode,
1096                  int x, int y)
1097 {
1098     ScrnInfoPtr pScrn = crtc->scrn;
1099     NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1100     NVPtr pNv = NVPTR(pScrn);
1101
1102     xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode on CRTC %d\n", nv_crtc->crtc);
1103     xf86PrintModeline(pScrn->scrnIndex, mode);
1104     NVCrtcSetOwner(crtc);
1105
1106     nv_crtc_mode_set_vga(crtc, mode);
1107     nv_crtc_mode_set_regs(crtc, mode);
1108
1109
1110     NVVgaProtect(crtc, TRUE);
1111     nv_crtc_load_state_ext(crtc, &pNv->ModeReg);
1112     nv_crtc_load_state_vga(crtc, &pNv->ModeReg);
1113     nv_crtc_load_state_pll(pNv, &pNv->ModeReg);
1114
1115     NVVgaProtect(crtc, FALSE);
1116     //    NVCrtcLockUnlock(crtc, 1);
1117
1118     NVCrtcSetBase(crtc, x, y);
1119 #if X_BYTE_ORDER == X_BIG_ENDIAN
1120     /* turn on LFB swapping */
1121     {
1122         unsigned char tmp;
1123
1124         tmp = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_SWAPPING);
1125         tmp |= (1 << 7);
1126         NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_SWAPPING, tmp);
1127     }
1128 #endif
1129
1130 }
1131
1132 void nv_crtc_save(xf86CrtcPtr crtc)
1133 {
1134     ScrnInfoPtr pScrn = crtc->scrn;
1135     NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1136     NVPtr pNv = NVPTR(pScrn);
1137
1138     NVCrtcSetOwner(crtc);
1139     nv_crtc_save_state_pll(pNv, &pNv->SavedReg);
1140     nv_crtc_save_state_vga(crtc, &pNv->SavedReg);
1141     nv_crtc_save_state_ext(crtc, &pNv->SavedReg);
1142
1143 }
1144
1145 void nv_crtc_restore(xf86CrtcPtr crtc)
1146 {
1147     ScrnInfoPtr pScrn = crtc->scrn;
1148     NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1149     NVPtr pNv = NVPTR(pScrn);
1150
1151     NVCrtcSetOwner(crtc);    
1152     nv_crtc_load_state_ext(crtc, &pNv->SavedReg);
1153     nv_crtc_load_state_vga(crtc, &pNv->SavedReg);
1154     nv_crtc_load_state_pll(pNv, &pNv->SavedReg);
1155     nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, pNv->vtOWNER);
1156
1157 }
1158
1159 void nv_crtc_prepare(xf86CrtcPtr crtc)
1160 {
1161     ScrnInfoPtr pScrn = crtc->scrn;
1162     NVPtr pNv = NVPTR(pScrn);
1163
1164     /* Sync the engine before adjust mode */
1165     if (pNv->EXADriverPtr) {
1166         exaMarkSync(pScrn->pScreen);
1167         exaWaitSync(pScrn->pScreen);
1168     }
1169 }
1170
1171 void nv_crtc_commit(xf86CrtcPtr crtc)
1172 {
1173
1174
1175 }
1176
1177 static Bool nv_crtc_lock(xf86CrtcPtr crtc)
1178 {
1179         return FALSE;
1180 }
1181
1182 static void nv_crtc_unlock(xf86CrtcPtr crtc)
1183 {
1184
1185 }
1186
1187 static const xf86CrtcFuncsRec nv_crtc_funcs = {
1188     .dpms = nv_crtc_dpms,
1189     .save = nv_crtc_save, /* XXX */
1190     .restore = nv_crtc_restore, /* XXX */
1191     .mode_fixup = nv_crtc_mode_fixup,
1192     .mode_set = nv_crtc_mode_set,
1193     .prepare = nv_crtc_prepare,
1194     .commit = nv_crtc_commit,
1195     .destroy = NULL, /* XXX */
1196     .lock = nv_crtc_lock,
1197     .unlock = nv_crtc_unlock,
1198 };
1199
1200 void
1201 nv_crtc_init(ScrnInfoPtr pScrn, int crtc_num)
1202 {
1203     NVPtr pNv = NVPTR(pScrn);
1204     xf86CrtcPtr crtc;
1205     NVCrtcPrivatePtr nv_crtc;
1206
1207     crtc = xf86CrtcCreate (pScrn, &nv_crtc_funcs);
1208     if (crtc == NULL)
1209         return;
1210
1211     nv_crtc = xnfcalloc (sizeof (NVCrtcPrivateRec), 1);
1212     nv_crtc->crtc = crtc_num;
1213     /* This is usefull to do stuff from crtc functions */
1214     nv_crtc->pNv = pNv;
1215
1216     crtc->driver_private = nv_crtc;
1217
1218     NVCrtcLockUnlock(crtc, 0);
1219
1220 }
1221
1222 static void nv_crtc_load_state_vga(xf86CrtcPtr crtc, RIVA_HW_STATE *state)
1223 {
1224     ScrnInfoPtr pScrn = crtc->scrn;
1225     NVPtr pNv = NVPTR(pScrn);    
1226     NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1227     int i, j;
1228     CARD32 temp;
1229     NVCrtcRegPtr regp;
1230
1231     regp = &state->crtc_reg[nv_crtc->crtc];
1232
1233     NVWriteMiscOut(crtc, regp->MiscOutReg);
1234
1235     for (i = 1; i < 5; i++)
1236       NVWriteVgaSeq(crtc, i, regp->Sequencer[i]);
1237   
1238     /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
1239     NVWriteVgaCrtc(crtc, 17, regp->CRTC[17] & ~0x80);
1240
1241     for (i = 0; i < 25; i++)
1242       NVWriteVgaCrtc(crtc, i, regp->CRTC[i]);
1243
1244     for (i = 0; i < 9; i++)
1245       NVWriteVgaGr(crtc, i, regp->Graphics[i]);
1246     
1247     NVEnablePalette(crtc);
1248     for (i = 0; i < 21; i++)
1249       NVWriteVgaAttr(crtc, i, regp->Attribute[i]);
1250     NVDisablePalette(crtc);
1251
1252 }
1253
1254 static void nv_crtc_fix_nv40_hw_cursor(xf86CrtcPtr crtc)
1255 {
1256   /* TODO - implement this properly */
1257   ScrnInfoPtr pScrn = crtc->scrn;
1258   NVPtr pNv = NVPTR(pScrn);
1259    
1260   if(pNv->Architecture == NV_ARCH_40) {  /* HW bug */
1261     volatile CARD32 curpos = nvReadCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS);
1262     nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, curpos);
1263   }
1264
1265 }
1266 static void nv_crtc_load_state_ext(xf86CrtcPtr crtc, RIVA_HW_STATE *state)
1267 {
1268     ScrnInfoPtr pScrn = crtc->scrn;
1269     NVPtr pNv = NVPTR(pScrn);    
1270     NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1271     int i, j;
1272     CARD32 temp;
1273     NVCrtcRegPtr regp;
1274     
1275     regp = &state->crtc_reg[nv_crtc->crtc];
1276
1277     if(pNv->Architecture >= NV_ARCH_10) {
1278         if(pNv->twoHeads) {
1279            nvWriteCRTC(pNv, nv_crtc->crtc, NV_CRTC_FSEL, regp->head);
1280         }
1281         nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
1282         nvWriteVIDEO(pNv, NV_PVIDEO_INTR_EN, 0);
1283         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(0), 0);
1284         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(1), 0);
1285         nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(0), pNv->VRAMPhysicalSize - 1);
1286         nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(1), pNv->VRAMPhysicalSize - 1);
1287         nvWriteMC(pNv, 0x1588, 0);
1288
1289         NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_BUFFER, 0xff);
1290         NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_BUFFER, regp->CRTC[NV_VGA_CRTCX_BUFFER]);
1291         nvWriteCRTC(pNv, nv_crtc->crtc, NV_CRTC_CURSOR_CONFIG, regp->cursorConfig);
1292         nvWriteCRTC(pNv, nv_crtc->crtc, NV_CRTC_0830, regp->unk830);
1293         nvWriteCRTC(pNv, nv_crtc->crtc, NV_CRTC_0834, regp->unk834);
1294         
1295         NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_FP_HTIMING, regp->CRTC[NV_VGA_CRTCX_FP_HTIMING]);
1296         NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_FP_VTIMING, regp->CRTC[NV_VGA_CRTCX_FP_VTIMING]);
1297
1298         NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_3C, regp->CRTC[NV_VGA_CRTCX_3C]);
1299         NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_45, regp->CRTC[NV_VGA_CRTCX_45]);
1300         NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_47, regp->CRTC[NV_VGA_CRTCX_47]);
1301         NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_56, regp->CRTC[NV_VGA_CRTCX_56]);
1302         NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_59, regp->CRTC[NV_VGA_CRTCX_59]);
1303         NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_EXTRA, regp->CRTC[NV_VGA_CRTCX_EXTRA]);
1304     }
1305
1306     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_REPAINT0, regp->CRTC[NV_VGA_CRTCX_REPAINT0]);
1307     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_REPAINT1, regp->CRTC[NV_VGA_CRTCX_REPAINT1]);
1308     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_LSR, regp->CRTC[NV_VGA_CRTCX_LSR]);
1309     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_PIXEL, regp->CRTC[NV_VGA_CRTCX_PIXEL]);
1310     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_LCD, regp->CRTC[NV_VGA_CRTCX_LCD]);
1311     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_HEB, regp->CRTC[NV_VGA_CRTCX_HEB]);
1312     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_FIFO1, regp->CRTC[NV_VGA_CRTCX_FIFO1]);
1313     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_FIFO0, regp->CRTC[NV_VGA_CRTCX_FIFO0]);
1314     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_FIFO_LWM, regp->CRTC[NV_VGA_CRTCX_FIFO_LWM]);
1315     if(pNv->Architecture >= NV_ARCH_30) {
1316       NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_FIFO_LWM_NV30, regp->CRTC[NV_VGA_CRTCX_FIFO_LWM_NV30]);
1317     }
1318
1319     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_CURCTL0, regp->CRTC[NV_VGA_CRTCX_CURCTL0]);
1320     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_CURCTL1, regp->CRTC[NV_VGA_CRTCX_CURCTL1]);
1321     nv_crtc_fix_nv40_hw_cursor(crtc);
1322     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_CURCTL2, regp->CRTC[NV_VGA_CRTCX_CURCTL2]);
1323     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_INTERLACE, regp->CRTC[NV_VGA_CRTCX_INTERLACE]);
1324
1325     nvWriteCRTC(pNv, nv_crtc->crtc, NV_CRTC_INTR_EN_0, 0);
1326     nvWriteCRTC(pNv, nv_crtc->crtc, NV_CRTC_INTR_0, NV_CRTC_INTR_VBLANK);
1327
1328     pNv->CurrentState = state;
1329 }
1330
1331 static void nv_crtc_save_state_vga(xf86CrtcPtr crtc, RIVA_HW_STATE *state)
1332 {
1333     ScrnInfoPtr pScrn = crtc->scrn;
1334     NVPtr pNv = NVPTR(pScrn);    
1335     NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1336     int i;
1337     NVCrtcRegPtr regp;
1338
1339     regp = &state->crtc_reg[nv_crtc->crtc];
1340
1341     regp->MiscOutReg = NVReadMiscOut(crtc);
1342
1343     for (i = 0; i < 25; i++)
1344         regp->CRTC[i] = NVReadVgaCrtc(crtc, i);
1345
1346     NVEnablePalette(crtc);
1347     for (i = 0; i < 21; i++)
1348         regp->Attribute[i] = NVReadVgaAttr(crtc, i);
1349     NVDisablePalette(crtc);
1350
1351     for (i = 0; i < 9; i++)
1352         regp->Graphics[i] = NVReadVgaGr(crtc, i);
1353
1354     for (i = 1; i < 5; i++)
1355         regp->Sequencer[i] = NVReadVgaSeq(crtc, i);
1356   
1357 }
1358
1359 static void nv_crtc_save_state_ext(xf86CrtcPtr crtc, RIVA_HW_STATE *state)
1360 {
1361     ScrnInfoPtr pScrn = crtc->scrn;
1362     NVPtr pNv = NVPTR(pScrn);    
1363     NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1364     NVCrtcRegPtr regp;
1365     int i;
1366
1367     regp = &state->crtc_reg[nv_crtc->crtc];
1368  
1369     regp->CRTC[NV_VGA_CRTCX_LCD] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_LCD);
1370     regp->CRTC[NV_VGA_CRTCX_REPAINT0] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_REPAINT0);
1371     regp->CRTC[NV_VGA_CRTCX_REPAINT1] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_REPAINT1);
1372     regp->CRTC[NV_VGA_CRTCX_LSR] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_LSR);
1373     regp->CRTC[NV_VGA_CRTCX_PIXEL] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_PIXEL);
1374     regp->CRTC[NV_VGA_CRTCX_HEB] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_HEB);
1375     regp->CRTC[NV_VGA_CRTCX_FIFO1] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_FIFO1);
1376
1377     regp->CRTC[NV_VGA_CRTCX_FIFO0] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_FIFO0);
1378     regp->CRTC[NV_VGA_CRTCX_FIFO_LWM] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_FIFO_LWM);
1379     if(pNv->Architecture >= NV_ARCH_30) {
1380          regp->CRTC[NV_VGA_CRTCX_FIFO_LWM_NV30] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_FIFO_LWM_NV30);
1381     }
1382     regp->CRTC[NV_VGA_CRTCX_CURCTL0] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_CURCTL0);
1383     regp->CRTC[NV_VGA_CRTCX_CURCTL1] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_CURCTL1);
1384     regp->CRTC[NV_VGA_CRTCX_CURCTL2] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_CURCTL2);
1385     regp->CRTC[NV_VGA_CRTCX_INTERLACE] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_INTERLACE);
1386  
1387     regp->unk830 = nvReadCRTC(pNv, nv_crtc->crtc, NV_CRTC_0830);
1388     regp->unk834 = nvReadCRTC(pNv, nv_crtc->crtc, NV_CRTC_0834);
1389
1390     if(pNv->Architecture >= NV_ARCH_10) {
1391         if(pNv->twoHeads) {
1392            regp->head     = nvReadCRTC(pNv, nv_crtc->crtc, NV_CRTC_FSEL);
1393            regp->crtcOwner = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_OWNER);
1394         }
1395         regp->CRTC[NV_VGA_CRTCX_EXTRA] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_EXTRA);
1396
1397         regp->cursorConfig = nvReadCRTC(pNv, nv_crtc->crtc, NV_CRTC_CURSOR_CONFIG);
1398
1399         regp->CRTC[NV_VGA_CRTCX_3C] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_3C);
1400         regp->CRTC[NV_VGA_CRTCX_45] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_45);
1401         regp->CRTC[NV_VGA_CRTCX_47] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_47);
1402         regp->CRTC[NV_VGA_CRTCX_56] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_56);
1403         regp->CRTC[NV_VGA_CRTCX_59] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_59);
1404         regp->CRTC[NV_VGA_CRTCX_BUFFER] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_BUFFER);
1405         regp->CRTC[NV_VGA_CRTCX_FP_HTIMING] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_FP_HTIMING);
1406         regp->CRTC[NV_VGA_CRTCX_FP_VTIMING] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_FP_VTIMING);
1407     }
1408 }
1409
1410 void
1411 NVCrtcSetBase (xf86CrtcPtr crtc, int x, int y)
1412 {
1413     ScrnInfoPtr pScrn = crtc->scrn;
1414     NVPtr pNv = NVPTR(pScrn);    
1415     NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1416     NVFBLayout *pLayout = &pNv->CurrentLayout;
1417     CARD32 start = 0;
1418     
1419     start += ((y * pScrn->displayWidth + x) * (pLayout->bitsPerPixel/8));
1420     start += pNv->FB->offset;
1421
1422     nvWriteCRTC(pNv, nv_crtc->crtc, NV_CRTC_START, start);
1423
1424     crtc->x = x;
1425     crtc->y = y;
1426 }
1427
1428 void NVCrtcSetCursor(xf86CrtcPtr crtc, Bool state)
1429 {
1430   int current = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_CURCTL1);
1431
1432   if(state) 
1433     current |= 1;
1434   else
1435     current &= ~1;
1436
1437   NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_CURCTL1, current);
1438 }
1439
1440 void NVSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
1441 {
1442         xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1443         int i;
1444         for (i = 0; i < xf86_config->num_crtc; i++) {
1445                 if (xf86_config->crtc[i]->enabled) {
1446                         nv_crtc_mode_set(xf86_config->crtc[i], mode, NULL, 0,0);
1447                 }
1448         }
1449 }
1450
1451 static void NVCrtcWriteDacMask(xf86CrtcPtr crtc, CARD8 value)
1452 {
1453   ScrnInfoPtr pScrn = crtc->scrn;
1454   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1455   NVPtr pNv = NVPTR(pScrn);
1456   volatile CARD8 *pDACReg = nv_crtc->crtc ? pNv->PDIO1 : pNv->PDIO0;
1457
1458   NV_WR08(pDACReg, VGA_DAC_MASK, value);
1459 }
1460
1461 static CARD8 NVCrtcReadDacMask(xf86CrtcPtr crtc)
1462 {
1463   ScrnInfoPtr pScrn = crtc->scrn;
1464   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1465   NVPtr pNv = NVPTR(pScrn);
1466   volatile CARD8 *pDACReg = nv_crtc->crtc ? pNv->PDIO1 : pNv->PDIO0;
1467   
1468   return NV_RD08(pDACReg, VGA_DAC_MASK);
1469 }
1470
1471 static void NVCrtcWriteDacReadAddr(xf86CrtcPtr crtc, CARD8 value)
1472 {
1473   ScrnInfoPtr pScrn = crtc->scrn;
1474   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1475   NVPtr pNv = NVPTR(pScrn);
1476   volatile CARD8 *pDACReg = nv_crtc->crtc ? pNv->PDIO1 : pNv->PDIO0;
1477
1478   NV_WR08(pDACReg, VGA_DAC_READ_ADDR, value);
1479 }
1480
1481 static void NVCrtcWriteDacWriteAddr(xf86CrtcPtr crtc, CARD8 value)
1482 {
1483   ScrnInfoPtr pScrn = crtc->scrn;
1484   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1485   NVPtr pNv = NVPTR(pScrn);
1486   volatile CARD8 *pDACReg = nv_crtc->crtc ? pNv->PDIO1 : pNv->PDIO0;
1487
1488   NV_WR08(pDACReg, VGA_DAC_WRITE_ADDR, value);
1489 }
1490
1491 static void NVCrtcWriteDacData(xf86CrtcPtr crtc, CARD8 value)
1492 {
1493   ScrnInfoPtr pScrn = crtc->scrn;
1494   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1495   NVPtr pNv = NVPTR(pScrn);
1496   volatile CARD8 *pDACReg = nv_crtc->crtc ? pNv->PDIO1 : pNv->PDIO0;
1497
1498   NV_WR08(pDACReg, VGA_DAC_DATA, value);
1499 }
1500
1501 static CARD8 NVCrtcReadDacData(xf86CrtcPtr crtc, CARD8 value)
1502 {
1503   ScrnInfoPtr pScrn = crtc->scrn;
1504   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1505   NVPtr pNv = NVPTR(pScrn);
1506   volatile CARD8 *pDACReg = nv_crtc->crtc ? pNv->PDIO1 : pNv->PDIO0;
1507
1508   return NV_RD08(pDACReg, VGA_DAC_DATA);
1509 }
1510
1511 void NVCrtcLoadPalette(xf86CrtcPtr crtc)
1512 {
1513   int i;
1514   NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1515   NVCrtcRegPtr regp;
1516   ScrnInfoPtr pScrn = crtc->scrn;
1517   NVPtr pNv = NVPTR(pScrn);
1518     
1519   regp = &pNv->ModeReg.crtc_reg[nv_crtc->crtc];
1520
1521   NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_OWNER, nv_crtc->crtc * 0x3);
1522   NVCrtcWriteDacMask(crtc, 0xff);
1523   NVCrtcWriteDacWriteAddr(crtc, 0x00);
1524
1525   for (i = 0; i<768; i++) {
1526     NVCrtcWriteDacData(crtc, regp->DAC[i]);
1527   }
1528   NVDisablePalette(crtc);
1529 }
1530
1531 void NVCrtcBlankScreen(xf86CrtcPtr crtc, Bool on)
1532 {
1533     NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1534     unsigned char scrn;
1535
1536     NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_OWNER, nv_crtc->crtc * 0x3);
1537
1538     scrn = NVReadVgaSeq(crtc, 0x01);
1539     if (on) {
1540         scrn &= ~0x20;
1541     } else {
1542         scrn |= 0x20;
1543     }
1544
1545     NVVgaSeqReset(crtc, TRUE);
1546     NVWriteVgaSeq(crtc, 0x01, scrn);
1547     NVVgaSeqReset(crtc, FALSE);
1548 }
1549
1550 #endif /* ENABLE_RANDR12 */
1551
1552 /*************************************************************************** \
1553 |*                                                                           *|
1554 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
1555 |*                                                                           *|
1556 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
1557 |*     international laws.  Users and possessors of this source code are     *|
1558 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
1559 |*     use this code in individual and commercial software.                  *|
1560 |*                                                                           *|
1561 |*     Any use of this source code must include,  in the user documenta-     *|
1562 |*     tion and  internal comments to the code,  notices to the end user     *|
1563 |*     as follows:                                                           *|
1564 |*                                                                           *|
1565 |*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
1566 |*                                                                           *|
1567 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
1568 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
1569 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
1570 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
1571 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
1572 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
1573 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
1574 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
1575 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
1576 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
1577 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
1578 |*                                                                           *|
1579 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
1580 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
1581 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
1582 |*     computer  software  documentation,"  as such  terms  are  used in     *|
1583 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
1584 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
1585 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
1586 |*     all U.S. Government End Users  acquire the source code  with only     *|
1587 |*     those rights set forth herein.                                        *|
1588 |*                                                                           *|
1589  \***************************************************************************/