2 * Copyright 2006 Dave Airlie
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 (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
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
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
42 #include "mipointer.h"
43 #include "windowstr.h"
45 #include <X11/extensions/render.h>
48 #include "nv_include.h"
52 #define CRTC_INDEX 0x3d4
53 #define CRTC_DATA 0x3d5
54 #define CRTC_IN_STAT_1 0x3da
56 #define WHITE_VALUE 0x3F
57 #define BLACK_VALUE 0x00
58 #define OVERSCAN_VALUE 0x01
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);
65 static void NVWriteMiscOut(xf86CrtcPtr crtc, CARD8 value)
67 ScrnInfoPtr pScrn = crtc->scrn;
68 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
69 NVPtr pNv = NVPTR(pScrn);
71 NV_WR08(pNv->PVIO, VGA_MISC_OUT_W, value);
74 static CARD8 NVReadMiscOut(xf86CrtcPtr crtc)
76 ScrnInfoPtr pScrn = crtc->scrn;
77 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
78 NVPtr pNv = NVPTR(pScrn);
80 return NV_RD08(pNv->PVIO, VGA_MISC_OUT_R);
84 static void NVWriteVgaCrtc(xf86CrtcPtr crtc, CARD8 index, CARD8 value)
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;
91 NV_WR08(pCRTCReg, CRTC_INDEX, index);
92 NV_WR08(pCRTCReg, CRTC_DATA, value);
95 static CARD8 NVReadVgaCrtc(xf86CrtcPtr crtc, CARD8 index)
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;
102 NV_WR08(pCRTCReg, CRTC_INDEX, index);
103 return NV_RD08(pCRTCReg, CRTC_DATA);
106 static void NVWriteVgaSeq(xf86CrtcPtr crtc, CARD8 index, CARD8 value)
108 ScrnInfoPtr pScrn = crtc->scrn;
109 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
110 NVPtr pNv = NVPTR(pScrn);
112 NV_WR08(pNv->PVIO, VGA_SEQ_INDEX, index);
113 NV_WR08(pNv->PVIO, VGA_SEQ_DATA, value);
116 static CARD8 NVReadVgaSeq(xf86CrtcPtr crtc, CARD8 index)
118 ScrnInfoPtr pScrn = crtc->scrn;
119 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
120 NVPtr pNv = NVPTR(pScrn);
121 volatile CARD8 *pVGAReg = pNv->PVIO;
123 NV_WR08(pNv->PVIO, VGA_SEQ_INDEX, index);
124 return NV_RD08(pNv->PVIO, VGA_SEQ_DATA);
127 static void NVWriteVgaGr(xf86CrtcPtr crtc, CARD8 index, CARD8 value)
129 ScrnInfoPtr pScrn = crtc->scrn;
130 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
131 NVPtr pNv = NVPTR(pScrn);
133 NV_WR08(pNv->PVIO, VGA_GRAPH_INDEX, index);
134 NV_WR08(pNv->PVIO, VGA_GRAPH_DATA, value);
137 static CARD8 NVReadVgaGr(xf86CrtcPtr crtc, CARD8 index)
139 ScrnInfoPtr pScrn = crtc->scrn;
140 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
141 NVPtr pNv = NVPTR(pScrn);
142 volatile CARD8 *pVGAReg = pNv->PVIO;
144 NV_WR08(pVGAReg, VGA_GRAPH_INDEX, index);
145 return NV_RD08(pVGAReg, VGA_GRAPH_DATA);
149 static void NVWriteVgaAttr(xf86CrtcPtr crtc, CARD8 index, CARD8 value)
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;
156 NV_RD08(pCRTCReg, CRTC_IN_STAT_1);
157 if (nv_crtc->paletteEnabled)
161 NV_WR08(pCRTCReg, VGA_ATTR_INDEX, index);
162 NV_WR08(pCRTCReg, VGA_ATTR_DATA_W, value);
165 static CARD8 NVReadVgaAttr(xf86CrtcPtr crtc, CARD8 index)
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;
172 NV_RD08(pCRTCReg, CRTC_IN_STAT_1);
173 if (nv_crtc->paletteEnabled)
177 NV_WR08(pCRTCReg, VGA_ATTR_INDEX, index);
178 return NV_RD08(pCRTCReg, VGA_ATTR_DATA_R);
181 void NVCrtcSetOwner(xf86CrtcPtr crtc)
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);
189 NVEnablePalette(xf86CrtcPtr crtc)
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;
196 NV_RD08(pCRTCReg, CRTC_IN_STAT_1);
197 NV_WR08(pCRTCReg, VGA_ATTR_INDEX, 0);
198 nv_crtc->paletteEnabled = TRUE;
202 NVDisablePalette(xf86CrtcPtr crtc)
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;
209 NV_RD08(pCRTCReg, CRTC_IN_STAT_1);
210 NV_WR08(pCRTCReg, VGA_ATTR_INDEX, 0x20);
211 nv_crtc->paletteEnabled = FALSE;
214 static void NVWriteVgaReg(xf86CrtcPtr crtc, CARD32 reg, CARD8 value)
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;
221 NV_WR08(pCRTCReg, reg, value);
224 /* perform a sequencer reset */
225 static void NVVgaSeqReset(xf86CrtcPtr crtc, Bool start)
228 NVWriteVgaSeq(crtc, 0x00, 0x1);
230 NVWriteVgaSeq(crtc, 0x00, 0x3);
233 static void NVVgaProtect(xf86CrtcPtr crtc, Bool on)
238 tmp = NVReadVgaSeq(crtc, 0x1);
239 NVVgaSeqReset(crtc, TRUE);
240 NVWriteVgaSeq(crtc, 0x01, tmp | 0x20);
242 NVEnablePalette(crtc);
245 * Reenable sequencer, then turn on screen.
247 tmp = NVReadVgaSeq(crtc, 0x1);
248 NVWriteVgaSeq(crtc, 0x01, tmp & ~0x20); /* reenable display */
249 NVVgaSeqReset(crtc, FALSE);
251 NVDisablePalette(crtc);
255 void NVCrtcLockUnlock(xf86CrtcPtr crtc, Bool Lock)
259 NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_LOCK, Lock ? 0x99 : 0x57);
260 cr11 = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_VSYNCE);
261 if (Lock) cr11 |= 0x80;
263 NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_VSYNCE, cr11);
266 * Calculate the Video Clock parameters for the PLL.
268 static void CalcVClock (
275 unsigned lowM, highM, highP;
276 unsigned DeltaNew, DeltaOld;
280 /* M: PLL reference frequency postscaler divider */
281 /* P: PLL VCO output postscaler divider */
282 /* N: PLL VCO postscaler setting */
284 DeltaOld = 0xFFFFFFFF;
286 VClk = (unsigned)clockIn;
288 /* Taken from Haiku, after someone with an NV28 had an issue */
289 switch(pNv->NVArch) {
295 } else if (VClk > 200000) {
297 } else if (VClk > 150000) {
308 } else if (VClk > 250000) {
316 for (P = 0; P <= highP; P++) {
318 if ((Freq >= 128000) && (Freq <= 350000)) {
319 for (M = lowM; M <= highM; M++) {
320 N = ((VClk << P) * M) / pNv->CrystalFreqKHz;
322 Freq = ((pNv->CrystalFreqKHz * N) / M) >> P;
324 DeltaNew = Freq - VClk;
326 DeltaNew = VClk - Freq;
328 if (DeltaNew < DeltaOld) {
329 *pllOut = (P << 16) | (N << 8) | M;
339 static void CalcVClock2Stage (
347 unsigned DeltaNew, DeltaOld;
350 unsigned lowM, highM, highP;
352 DeltaOld = 0xFFFFFFFF;
354 *pllBOut = 0x80000401; /* fixed at x4 for now */
356 VClk = (unsigned)clockIn;
358 /* Taken from Haiku, after someone with an NV28 had an issue */
359 switch(pNv->NVArch) {
365 } else if (VClk > 200000) {
367 } else if (VClk > 150000) {
378 } else if (VClk > 250000) {
386 for (P = 0; P <= highP; 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;
394 DeltaNew = Freq - VClk;
396 DeltaNew = VClk - Freq;
398 if (DeltaNew < DeltaOld) {
399 *pllOut = (P << 16) | (N << 8) | M;
409 static void nv_crtc_save_state_pll(NVPtr pNv, RIVA_HW_STATE *state)
411 state->vpll = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL);
413 state->vpll2 = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL2);
415 if(pNv->twoStagePLL) {
416 state->vpllB = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL_B);
417 state->vpll2B = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL2_B);
419 state->pllsel = nvReadRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT);
423 static void nv_crtc_load_state_pll(NVPtr pNv, RIVA_HW_STATE *state)
425 nvWriteRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT, state->pllsel);
427 ErrorF("writting vpll %08X\n", state->vpll);
428 ErrorF("writting vpll2 %08X\n", state->vpll2);
429 nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL, state->vpll);
431 nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2, state->vpll2);
433 if(pNv->twoStagePLL) {
434 nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL_B, state->vpllB);
435 nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2_B, state->vpll2B);
440 * Calculate extended mode parameters (SVGA) and save in a
441 * mode state structure.
443 void nv_crtc_calc_state_ext(
453 ScrnInfoPtr pScrn = crtc->scrn;
454 int pixelDepth, VClk;
456 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
457 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
459 NVPtr pNv = NVPTR(pScrn);
460 RIVA_HW_STATE *state;
461 int num_crtc_enabled, i;
463 state = &pNv->ModeReg;
465 regp = &pNv->ModeReg.crtc_reg[nv_crtc->crtc];
468 * Extended RIVA registers.
470 pixelDepth = (bpp + 1)/8;
472 CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, pNv);
474 CalcVClock(dotClock, &VClk, &state->pll, pNv);
476 switch (pNv->Architecture)
479 nv4UpdateArbitrationSettings(VClk,
481 &(state->arbitration0),
482 &(state->arbitration1),
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;
497 if(((pNv->Chipset & 0xfff0) == CHIPSET_C51) ||
498 ((pNv->Chipset & 0xfff0) == CHIPSET_C512))
500 state->arbitration0 = 128;
501 state->arbitration1 = 0x0480;
503 if(((pNv->Chipset & 0xffff) == CHIPSET_NFORCE) ||
504 ((pNv->Chipset & 0xffff) == CHIPSET_NFORCE2))
506 nForceUpdateArbitrationSettings(VClk,
508 &(state->arbitration0),
509 &(state->arbitration1),
511 } else if(pNv->Architecture < NV_ARCH_30) {
512 nv10UpdateArbitrationSettings(VClk,
514 &(state->arbitration0),
515 &(state->arbitration1),
518 nv30UpdateArbitrationSettings(pNv,
519 &(state->arbitration0),
520 &(state->arbitration1));
524 CursorStart = pNv->Cursor->offset;
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;
530 if (flags & V_DBLSCAN)
531 regp->CRTC[NV_VGA_CRTCX_CURCTL1]|= 2;
534 state->config = nvReadFB(pNv, NV_PFB_CFG0);
535 regp->CRTC[NV_VGA_CRTCX_REPAINT1] = hDisplaySize < 1280 ? 0x04 : 0x00;
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) {
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;
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;
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;
566 regp->CRTC[NV_VGA_CRTCX_REPAINT0] = (((width / 8) * pixelDepth) & 0x700) >> 3;
567 regp->CRTC[NV_VGA_CRTCX_PIXEL] = (pixelDepth > 2) ? 3 : pixelDepth;
572 nv_crtc_dpms(xf86CrtcPtr crtc, int mode)
574 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
575 unsigned char seq1 = 0, crtc17 = 0;
576 unsigned char crtc1A;
578 Bool crtc_is_on = FALSE;
580 NVCrtcSetOwner(crtc);
582 crtc1A = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_REPAINT1) & ~0xC0;
584 case DPMSModeStandby:
585 /* Screen: Off; HSync: Off, VSync: On -- Not Supported */
590 case DPMSModeSuspend:
591 /* Screen: Off; HSync: On, VSync: Off -- Not Supported */
597 /* Screen: Off; HSync: Off, VSync: Off */
604 /* Screen: On; HSync: On, VSync: On */
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;
616 NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_MODECTL, crtc17);
617 NVWriteVgaSeq(crtc, 0x0, 0x3);
619 NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_REPAINT1, crtc1A);
621 /* This is usefull for Xv NVWaitVSync() */
622 nv_crtc->pNv->crtc_active[nv_crtc->crtc] = crtc_is_on;
626 nv_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
627 DisplayModePtr adjusted_mode)
633 nv_crtc_mode_set_vga(xf86CrtcPtr crtc, DisplayModePtr mode)
635 ScrnInfoPtr pScrn = crtc->scrn;
636 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
638 NVPtr pNv = NVPTR(pScrn);
639 int depth = pScrn->depth;
643 regp = &pNv->ModeReg.crtc_reg[nv_crtc->crtc];
645 /* Initializing some default bios settings */
647 /* This is crude, but if it works for Haiku ;-) */
648 drain = mode->HDisplay * mode->VDisplay * pScrn->bitsPerPixel;
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;
659 regp->CRTC[NV_VGA_CRTCX_FIFO0] = 0x01;
660 regp->CRTC[NV_VGA_CRTCX_FIFO_LWM] = 0x40;
664 * compute correct Hsync & Vsync polarity
666 if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
667 && (mode->Flags & (V_PVSYNC | V_NVSYNC))) {
669 regp->MiscOutReg = 0x23;
670 if (mode->Flags & V_NHSYNC) regp->MiscOutReg |= 0x40;
671 if (mode->Flags & V_NVSYNC) regp->MiscOutReg |= 0x80;
673 int VDisplay = mode->VDisplay;
674 if (mode->Flags & V_DBLSCAN)
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 */
685 regp->MiscOutReg = 0x23; /* +hsync +vsync */
689 regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2;
695 regp->Sequencer[0] = 0x02;
697 regp->Sequencer[0] = 0x00;
699 if (mode->Flags & V_CLKDIV2) {
700 regp->Sequencer[1] = 0x09;
702 regp->Sequencer[1] = 0x01;
705 regp->Sequencer[2] = 1 << BIT_PLANE;
707 regp->Sequencer[2] = 0x0F;
708 regp->Sequencer[3] = 0x00; /* Font select */
711 regp->Sequencer[4] = 0x06; /* Misc */
713 regp->Sequencer[4] = 0x0E; /* Misc */
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);
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)
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;
744 if (mode->VScan >= 32) {
745 regp->CRTC[9] |= 0x1F;
746 } else if (mode->VScan > 1) {
747 regp->CRTC[9] |= mode->VScan - 1;
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;
763 regp->CRTC[23] = 0xE3;
765 regp->CRTC[23] = 0xC3;
767 regp->CRTC[24] = 0xFF;
770 * Theory resumes here....
774 * Graphics Display Controller
776 regp->Graphics[0] = 0x00;
777 regp->Graphics[1] = 0x00;
778 regp->Graphics[2] = 0x00;
779 regp->Graphics[3] = 0x00;
781 regp->Graphics[4] = BIT_PLANE;
782 regp->Graphics[5] = 0x00;
784 regp->Graphics[4] = 0x00;
786 regp->Graphics[5] = 0x02;
788 regp->Graphics[5] = 0x40;
791 regp->Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */
792 regp->Graphics[7] = 0x0F;
793 regp->Graphics[8] = 0xFF;
796 /* Initialise the Mono map according to which bit-plane gets used */
798 Bool flipPixels = xf86GetFlipPixels();
800 for (i=0; i<16; i++) {
801 if (((i & (1 << BIT_PLANE)) != 0) != flipPixels) {
802 regp->Attribute[i] = WHITE_VALUE;
804 regp->Attribute[i] = BLACK_VALUE;
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;
826 regp->Attribute[16] = 0x81; /* wrong for the ET4000 */
828 regp->Attribute[16] = 0x41; /* wrong for the ET4000 */
831 regp->Attribute[17] = 0xff;
833 /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */
835 regp->Attribute[18] = 0x0F;
836 regp->Attribute[19] = 0x00;
837 regp->Attribute[20] = 0x00;
841 * Sets up registers for the given mode/adjusted_mode pair.
843 * The clocks, CRTCs and outputs attached to this CRTC must be off.
845 * This shouldn't enable any clocks, CRTCs, or outputs, but they should
846 * be easily turned on/off after this.
849 nv_crtc_mode_set_regs(xf86CrtcPtr crtc, DisplayModePtr mode)
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;
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? */
875 for (i = 0; i < xf86_config->num_output; i++) {
876 xf86OutputPtr output = xf86_config->output[i];
877 NVOutputPrivatePtr nv_output = output->driver_private;
879 if (output->crtc == crtc) {
880 if ((nv_output->type == OUTPUT_PANEL) ||
881 (nv_output->type == OUTPUT_DIGITAL)) {
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? */
893 if (pNv->Architecture >= NV_ARCH_40) {
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 */
899 } else if (pNv->NVArch == 0x11) {
905 ErrorF("crtc: Post-sync workaround\n");
907 regp = &pNv->ModeReg.crtc_reg[nv_crtc->crtc];
908 savep = &pNv->SavedReg.crtc_reg[nv_crtc->crtc];
910 if(mode->Flags & V_INTERLACE)
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)
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)
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)
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);
940 regp->Attribute[0x10] = 0x01;
943 regp->Attribute[0x11] = 0x00;
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);
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);
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);
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);
966 regp->CRTC[NV_VGA_CRTCX_INTERLACE] = 0xff; /* interlace off */
969 regp->CRTC[NV_VGA_CRTCX_BUFFER] = 0xfa;
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);
975 regp->CRTC[NV_VGA_CRTCX_LCD] = 0;
978 /* I'm trusting haiku driver on this one, they say it enables an external TDMS clock */
980 regp->CRTC[NV_VGA_CRTCX_59] = 0x1;
982 regp->CRTC[NV_VGA_CRTCX_59] = 0x0;
986 * Initialize DAC palette.
988 if(pLayout->bitsPerPixel != 8 ) {
989 for (i = 0; i < 256; i++) {
991 regp->DAC[(i*3)+1] = i;
992 regp->DAC[(i*3)+2] = i;
997 * Calculate the extended registers.
1000 if(pLayout->depth < 24) {
1006 if(pNv->Architecture >= NV_ARCH_10) {
1007 pNv->CURSOR = (CARD32 *)pNv->Cursor->map;
1010 ErrorF("crtc %d %d %d\n", nv_crtc->crtc, mode->CrtcHDisplay, pLayout->displayWidth);
1011 nv_crtc_calc_state_ext(crtc,
1013 pLayout->displayWidth,
1020 regp->CRTC[NV_VGA_CRTCX_PIXEL] |= (1 << 7);
1023 /* This is the value i have, blob seems to use others as well */
1024 regp->CRTC[NV_VGA_CRTCX_FIFO1] = 0x1c;
1028 regp->head &= ~NV_CRTC_FSEL_FPP2;
1029 regp->head |= NV_CRTC_FSEL_FPP1;
1031 regp->head &= ~NV_CRTC_FSEL_FPP1;
1032 regp->head |= NV_CRTC_FSEL_FPP2;
1035 regp->crtcOwner = 3;
1036 /* only enable secondary pllsel if CRTC 1 is selected on */
1038 /* Maybe use pNv->crtc_active[1], or is it too early for that? */
1040 regp->head = savep->head | 0x00001000;
1042 regp->head &= ~NV_CRTC_FSEL_FPP2;
1043 regp->head |= NV_CRTC_FSEL_FPP1;
1045 regp->head &= ~NV_CRTC_FSEL_FPP1;
1046 regp->head |= NV_CRTC_FSEL_FPP2;
1049 regp->crtcOwner = 0;
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;
1060 regp->cursorConfig |= 0x14011000;
1063 regp->cursorConfig |= 0x02000000;
1066 regp->CRTC[NV_VGA_CRTCX_FP_HTIMING] = 0;
1067 regp->CRTC[NV_VGA_CRTCX_FP_VTIMING] = 0;
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;
1074 /* more blob imitating */
1075 if (nv_crtc->crtc == 1) {
1076 regp->CRTC[NV_VGA_CRTCX_56] = 0x04;
1078 regp->CRTC[NV_VGA_CRTCX_56] = 0x0;
1081 regp->unk830 = mode->CrtcVDisplay - 3;
1082 regp->unk834 = mode->CrtcVDisplay - 1;
1086 * Sets up registers for the given mode/adjusted_mode pair.
1088 * The clocks, CRTCs and outputs attached to this CRTC must be off.
1090 * This shouldn't enable any clocks, CRTCs, or outputs, but they should
1091 * be easily turned on/off after this.
1094 nv_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
1095 DisplayModePtr adjusted_mode,
1098 ScrnInfoPtr pScrn = crtc->scrn;
1099 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1100 NVPtr pNv = NVPTR(pScrn);
1102 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode on CRTC %d\n", nv_crtc->crtc);
1103 xf86PrintModeline(pScrn->scrnIndex, mode);
1104 NVCrtcSetOwner(crtc);
1106 nv_crtc_mode_set_vga(crtc, mode);
1107 nv_crtc_mode_set_regs(crtc, mode);
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);
1115 NVVgaProtect(crtc, FALSE);
1116 // NVCrtcLockUnlock(crtc, 1);
1118 NVCrtcSetBase(crtc, x, y);
1119 #if X_BYTE_ORDER == X_BIG_ENDIAN
1120 /* turn on LFB swapping */
1124 tmp = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_SWAPPING);
1126 NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_SWAPPING, tmp);
1132 void nv_crtc_save(xf86CrtcPtr crtc)
1134 ScrnInfoPtr pScrn = crtc->scrn;
1135 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1136 NVPtr pNv = NVPTR(pScrn);
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);
1145 void nv_crtc_restore(xf86CrtcPtr crtc)
1147 ScrnInfoPtr pScrn = crtc->scrn;
1148 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1149 NVPtr pNv = NVPTR(pScrn);
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);
1159 void nv_crtc_prepare(xf86CrtcPtr crtc)
1161 ScrnInfoPtr pScrn = crtc->scrn;
1162 NVPtr pNv = NVPTR(pScrn);
1164 /* Sync the engine before adjust mode */
1165 if (pNv->EXADriverPtr) {
1166 exaMarkSync(pScrn->pScreen);
1167 exaWaitSync(pScrn->pScreen);
1171 void nv_crtc_commit(xf86CrtcPtr crtc)
1177 static Bool nv_crtc_lock(xf86CrtcPtr crtc)
1182 static void nv_crtc_unlock(xf86CrtcPtr crtc)
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,
1201 nv_crtc_init(ScrnInfoPtr pScrn, int crtc_num)
1203 NVPtr pNv = NVPTR(pScrn);
1205 NVCrtcPrivatePtr nv_crtc;
1207 crtc = xf86CrtcCreate (pScrn, &nv_crtc_funcs);
1211 nv_crtc = xnfcalloc (sizeof (NVCrtcPrivateRec), 1);
1212 nv_crtc->crtc = crtc_num;
1213 /* This is usefull to do stuff from crtc functions */
1216 crtc->driver_private = nv_crtc;
1218 NVCrtcLockUnlock(crtc, 0);
1222 static void nv_crtc_load_state_vga(xf86CrtcPtr crtc, RIVA_HW_STATE *state)
1224 ScrnInfoPtr pScrn = crtc->scrn;
1225 NVPtr pNv = NVPTR(pScrn);
1226 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1231 regp = &state->crtc_reg[nv_crtc->crtc];
1233 NVWriteMiscOut(crtc, regp->MiscOutReg);
1235 for (i = 1; i < 5; i++)
1236 NVWriteVgaSeq(crtc, i, regp->Sequencer[i]);
1238 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
1239 NVWriteVgaCrtc(crtc, 17, regp->CRTC[17] & ~0x80);
1241 for (i = 0; i < 25; i++)
1242 NVWriteVgaCrtc(crtc, i, regp->CRTC[i]);
1244 for (i = 0; i < 9; i++)
1245 NVWriteVgaGr(crtc, i, regp->Graphics[i]);
1247 NVEnablePalette(crtc);
1248 for (i = 0; i < 21; i++)
1249 NVWriteVgaAttr(crtc, i, regp->Attribute[i]);
1250 NVDisablePalette(crtc);
1254 static void nv_crtc_fix_nv40_hw_cursor(xf86CrtcPtr crtc)
1256 /* TODO - implement this properly */
1257 ScrnInfoPtr pScrn = crtc->scrn;
1258 NVPtr pNv = NVPTR(pScrn);
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);
1266 static void nv_crtc_load_state_ext(xf86CrtcPtr crtc, RIVA_HW_STATE *state)
1268 ScrnInfoPtr pScrn = crtc->scrn;
1269 NVPtr pNv = NVPTR(pScrn);
1270 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1275 regp = &state->crtc_reg[nv_crtc->crtc];
1277 if(pNv->Architecture >= NV_ARCH_10) {
1279 nvWriteCRTC(pNv, nv_crtc->crtc, NV_CRTC_FSEL, regp->head);
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);
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);
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]);
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]);
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]);
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]);
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);
1328 pNv->CurrentState = state;
1331 static void nv_crtc_save_state_vga(xf86CrtcPtr crtc, RIVA_HW_STATE *state)
1333 ScrnInfoPtr pScrn = crtc->scrn;
1334 NVPtr pNv = NVPTR(pScrn);
1335 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1339 regp = &state->crtc_reg[nv_crtc->crtc];
1341 regp->MiscOutReg = NVReadMiscOut(crtc);
1343 for (i = 0; i < 25; i++)
1344 regp->CRTC[i] = NVReadVgaCrtc(crtc, i);
1346 NVEnablePalette(crtc);
1347 for (i = 0; i < 21; i++)
1348 regp->Attribute[i] = NVReadVgaAttr(crtc, i);
1349 NVDisablePalette(crtc);
1351 for (i = 0; i < 9; i++)
1352 regp->Graphics[i] = NVReadVgaGr(crtc, i);
1354 for (i = 1; i < 5; i++)
1355 regp->Sequencer[i] = NVReadVgaSeq(crtc, i);
1359 static void nv_crtc_save_state_ext(xf86CrtcPtr crtc, RIVA_HW_STATE *state)
1361 ScrnInfoPtr pScrn = crtc->scrn;
1362 NVPtr pNv = NVPTR(pScrn);
1363 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1367 regp = &state->crtc_reg[nv_crtc->crtc];
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);
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);
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);
1387 regp->unk830 = nvReadCRTC(pNv, nv_crtc->crtc, NV_CRTC_0830);
1388 regp->unk834 = nvReadCRTC(pNv, nv_crtc->crtc, NV_CRTC_0834);
1390 if(pNv->Architecture >= NV_ARCH_10) {
1392 regp->head = nvReadCRTC(pNv, nv_crtc->crtc, NV_CRTC_FSEL);
1393 regp->crtcOwner = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_OWNER);
1395 regp->CRTC[NV_VGA_CRTCX_EXTRA] = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_EXTRA);
1397 regp->cursorConfig = nvReadCRTC(pNv, nv_crtc->crtc, NV_CRTC_CURSOR_CONFIG);
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);
1411 NVCrtcSetBase (xf86CrtcPtr crtc, int x, int y)
1413 ScrnInfoPtr pScrn = crtc->scrn;
1414 NVPtr pNv = NVPTR(pScrn);
1415 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1416 NVFBLayout *pLayout = &pNv->CurrentLayout;
1419 start += ((y * pScrn->displayWidth + x) * (pLayout->bitsPerPixel/8));
1420 start += pNv->FB->offset;
1422 nvWriteCRTC(pNv, nv_crtc->crtc, NV_CRTC_START, start);
1428 void NVCrtcSetCursor(xf86CrtcPtr crtc, Bool state)
1430 int current = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_CURCTL1);
1437 NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_CURCTL1, current);
1440 void NVSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
1442 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
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);
1451 static void NVCrtcWriteDacMask(xf86CrtcPtr crtc, CARD8 value)
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;
1458 NV_WR08(pDACReg, VGA_DAC_MASK, value);
1461 static CARD8 NVCrtcReadDacMask(xf86CrtcPtr crtc)
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;
1468 return NV_RD08(pDACReg, VGA_DAC_MASK);
1471 static void NVCrtcWriteDacReadAddr(xf86CrtcPtr crtc, CARD8 value)
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;
1478 NV_WR08(pDACReg, VGA_DAC_READ_ADDR, value);
1481 static void NVCrtcWriteDacWriteAddr(xf86CrtcPtr crtc, CARD8 value)
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;
1488 NV_WR08(pDACReg, VGA_DAC_WRITE_ADDR, value);
1491 static void NVCrtcWriteDacData(xf86CrtcPtr crtc, CARD8 value)
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;
1498 NV_WR08(pDACReg, VGA_DAC_DATA, value);
1501 static CARD8 NVCrtcReadDacData(xf86CrtcPtr crtc, CARD8 value)
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;
1508 return NV_RD08(pDACReg, VGA_DAC_DATA);
1511 void NVCrtcLoadPalette(xf86CrtcPtr crtc)
1514 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1516 ScrnInfoPtr pScrn = crtc->scrn;
1517 NVPtr pNv = NVPTR(pScrn);
1519 regp = &pNv->ModeReg.crtc_reg[nv_crtc->crtc];
1521 NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_OWNER, nv_crtc->crtc * 0x3);
1522 NVCrtcWriteDacMask(crtc, 0xff);
1523 NVCrtcWriteDacWriteAddr(crtc, 0x00);
1525 for (i = 0; i<768; i++) {
1526 NVCrtcWriteDacData(crtc, regp->DAC[i]);
1528 NVDisablePalette(crtc);
1531 void NVCrtcBlankScreen(xf86CrtcPtr crtc, Bool on)
1533 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1536 NVWriteVgaCrtc(crtc, NV_VGA_CRTCX_OWNER, nv_crtc->crtc * 0x3);
1538 scrn = NVReadVgaSeq(crtc, 0x01);
1545 NVVgaSeqReset(crtc, TRUE);
1546 NVWriteVgaSeq(crtc, 0x01, scrn);
1547 NVVgaSeqReset(crtc, FALSE);
1550 #endif /* ENABLE_RANDR12 */
1552 /*************************************************************************** \
1554 |* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
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. *|
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 *|
1565 |* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *|
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. *|
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. *|
1589 \***************************************************************************/