2 * Copyright (c) 2007 NVIDIA, Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #include "nv_include.h"
30 #include "nv50_type.h"
31 #include "nv50_cursor.h"
32 #include "nv50_display.h"
33 #include "nv50_output.h"
35 static void NV50CrtcShowHideCursor(xf86CrtcPtr crtc, Bool show, Bool update);
38 * PLL calculation. pclk is in kHz.
41 NV50CalcPLL(float pclk, int *pNA, int *pMA, int *pNB, int *pMB, int *pP)
43 const float refclk = 27000.0f;
44 const float minVcoA = 100000;
45 const float maxVcoA = 400000;
46 const float minVcoB = 600000;
47 float maxVcoB = 1400000;
48 const float minUA = 2000;
49 const float maxUA = 400000;
50 const float minUB = 50000;
51 const float maxUB = 200000;
52 const int minNA = 1, maxNA = 255;
53 const int minNB = 1, maxNB = 31;
54 const int minMA = 1, maxMA = 255;
55 const int minMB = 1, maxMB = 31;
56 const int minP = 0, maxP = 6;
60 int na, ma, nb, mb, p;
61 float bestError = FLT_MAX;
63 *pNA = *pMA = *pNB = *pMB = *pP = 0;
65 if(maxVcoB < pclk + pclk / 200)
66 maxVcoB = pclk + pclk / 200;
67 if(minVcoB / (1 << maxP) > pclk)
68 pclk = minVcoB / (1 << maxP);
70 vcoB = maxVcoB - maxVcoB / 200;
72 vcoB /= 1 << (lowP + 1);
74 while(pclk <= vcoB && lowP < maxP)
80 vcoB = maxVcoB + maxVcoB / 200;
82 vcoB /= 1 << (highP + 1);
84 while(pclk <= vcoB && highP < maxP)
90 for(p = lowP; p <= highP; p++)
92 for(ma = minMA; ma <= maxMA; ma++)
94 if(refclk / ma < minUA)
96 else if(refclk / ma > maxUA)
99 for(na = minNA; na <= maxNA; na++)
101 if(refclk * na / ma < minVcoA || refclk * na / ma > maxVcoA)
104 for(mb = minMB; mb <= maxMB; mb++)
106 if(refclk * na / ma / mb < minUB)
108 else if(refclk * na / ma / mb > maxUB)
111 nb = rint(pclk * (1 << p) * (ma / (float)na) * mb / refclk);
119 float freq = refclk * (na / (float)ma) * (nb / (float)mb) / (1 << p);
120 float error = fabsf(pclk - freq);
121 if(error < bestError) {
136 void NV50CrtcSetPClk(xf86CrtcPtr crtc)
138 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
139 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
140 ScrnInfoPtr pScrn = crtc->scrn;
141 NVPtr pNv = NVPTR(pScrn);
142 int lo_n, lo_m, hi_n, hi_m, p, i;
143 /* These clocks are probably rerouted from the 0x4000 range to the 0x610000 range */
144 CARD32 lo = NVRead(pNv, nv_crtc->head ? NV50_CRTC_VPLL2_A : NV50_CRTC_VPLL1_A);
145 CARD32 hi = NVRead(pNv, nv_crtc->head ? NV50_CRTC_VPLL2_B : NV50_CRTC_VPLL1_B);
147 NVWrite(pNv, 0x00614100 + nv_crtc->head * 0x800, 0x10000610);
151 NV50CalcPLL(nv_crtc->pclk, &lo_n, &lo_m, &hi_n, &hi_m, &p);
153 lo |= (lo_m << 16) | lo_n;
154 hi |= (p << 28) | (hi_m << 16) | hi_n;
155 NVWrite(pNv, nv_crtc->head ? NV50_CRTC_VPLL2_A : NV50_CRTC_VPLL1_A, lo);
156 NVWrite(pNv, nv_crtc->head ? NV50_CRTC_VPLL2_B : NV50_CRTC_VPLL1_B, hi);
157 NVWrite(pNv, 0x00614200 + nv_crtc->head * 0x800, 0);
159 for(i = 0; i < xf86_config->num_output; i++) {
160 xf86OutputPtr output = xf86_config->output[i];
162 if(output->crtc != crtc)
164 NV50OutputSetPClk(output, nv_crtc->pclk);
169 NV50CrtcGetHead(xf86CrtcPtr crtc)
171 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
172 return nv_crtc->head;
176 NV50DispPreInit(ScrnInfoPtr pScrn)
178 NVPtr pNv = NVPTR(pScrn);
179 /* These labels are guesswork based on symmetry (2 SOR's and 3 DAC's exist)*/
180 NVWrite(pNv, 0x00610184, NVRead(pNv, 0x00614004));
181 NVWrite(pNv, 0x00610190 + SOR0 * 0x10, NVRead(pNv, 0x00616100 + SOR0 * 0x800));
182 NVWrite(pNv, 0x00610190 + SOR1 * 0x10, NVRead(pNv, 0x00616100 + SOR1 * 0x800));
183 NVWrite(pNv, 0x00610194 + SOR0 * 0x10, NVRead(pNv, 0x00616104 + SOR0 * 0x800));
184 NVWrite(pNv, 0x00610194 + SOR1 * 0x10, NVRead(pNv, 0x00616104 + SOR1 * 0x800));
185 NVWrite(pNv, 0x00610198 + SOR0 * 0x10, NVRead(pNv, 0x00616108 + SOR0 * 0x800));
186 NVWrite(pNv, 0x00610198 + SOR1 * 0x10, NVRead(pNv, 0x00616108 + SOR1 * 0x800));
187 NVWrite(pNv, 0x0061019c + SOR0 * 0x10, NVRead(pNv, 0x0061610c + SOR0 * 0x800));
188 NVWrite(pNv, 0x0061019c + SOR1 * 0x10, NVRead(pNv, 0x0061610c + SOR1 * 0x800));
189 NVWrite(pNv, 0x006101d0 + DAC0 * 0x4, NVRead(pNv, 0x0061a000 + DAC0 * 0x800));
190 NVWrite(pNv, 0x006101d0 + DAC1 * 0x4, NVRead(pNv, 0x0061a000 + DAC1 * 0x800));
191 NVWrite(pNv, 0x006101d0 + DAC2 * 0x4, NVRead(pNv, 0x0061a000 + DAC2 * 0x800));
192 NVWrite(pNv, 0x006101e0 + SOR0 * 0x4, NVRead(pNv, 0x0061c000 + SOR0 * 0x800));
193 NVWrite(pNv, 0x006101e0 + SOR1 * 0x4, NVRead(pNv, 0x0061c000 + SOR1 * 0x800));
194 NVWrite(pNv, NV50_DAC0_DPMS_CTRL, 0x00550000 | NV50_DAC_DPMS_CTRL_PENDING);
195 NVWrite(pNv, 0x0061a010 + DAC0 * 0x800, 0x00000001);
196 NVWrite(pNv, NV50_DAC1_DPMS_CTRL, 0x00550000 | NV50_DAC_DPMS_CTRL_PENDING);
197 NVWrite(pNv, 0x0061a010 + DAC1 * 0x800, 0x00000001);
198 NVWrite(pNv, NV50_DAC2_DPMS_CTRL, 0x00550000 | NV50_DAC_DPMS_CTRL_PENDING);
199 NVWrite(pNv, 0x0061a010 + DAC2 * 0x800, 0x00000001);
205 NV50DispInit(ScrnInfoPtr pScrn)
207 NVPtr pNv = NVPTR(pScrn);
209 if (NVRead(pNv, NV50_DISPLAY_SUPERVISOR) & 0x100) {
210 NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, 0x100);
211 NVWrite(pNv, 0x006194e8, NVRead(pNv, 0x006194e8) & ~1);
212 while (NVRead(pNv, 0x006194e8) & 2);
215 NVWrite(pNv, 0x00610200, 0x2b00);
216 /* A bugfix (#12637) from the nv driver, to unlock the driver if it's left in a poor state */
218 val = NVRead(pNv, 0x00610200);
219 if ((val & 0x9f0000) == 0x20000)
220 NVWrite(pNv, 0x00610200, val | 0x800000);
222 if ((val & 0x3f0000) == 0x30000)
223 NVWrite(pNv, 0x00610200, val | 0x200000);
224 } while ((val & 0x1e0000) != 0);
225 NVWrite(pNv, NV50_DISPLAY_CTRL_STATE, NV50_DISPLAY_CTRL_STATE_ENABLE);
226 NVWrite(pNv, 0x00610200, 0x1000b03);
227 while (!(NVRead(pNv, 0x00610200) & 0x40000000));
229 NV50DisplayCommand(pScrn, 0x84, 0);
230 NV50DisplayCommand(pScrn, 0x88, 0);
231 /* Does the bios always use crtc0? */
232 NV50DisplayCommand(pScrn, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_BLANK);
233 NV50DisplayCommand(pScrn, 0x800, 0);
234 NV50DisplayCommand(pScrn, 0x810, 0);
235 NV50DisplayCommand(pScrn, 0x82c, 0);
241 NV50DispShutdown(ScrnInfoPtr pScrn)
243 NVPtr pNv = NVPTR(pScrn);
244 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
247 for(i = 0; i < xf86_config->num_crtc; i++) {
248 xf86CrtcPtr crtc = xf86_config->crtc[i];
250 NV50CrtcBlankScreen(crtc, TRUE);
253 NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
255 for(i = 0; i < xf86_config->num_crtc; i++) {
256 xf86CrtcPtr crtc = xf86_config->crtc[i];
257 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
261 if (nv_crtc->head == 1)
262 mask = NV50_DISPLAY_SUPERVISOR_DISABLE_CRTC1;
264 mask = NV50_DISPLAY_SUPERVISOR_DISABLE_CRTC0;
266 NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, mask);
267 while(!(NVRead(pNv, NV50_DISPLAY_SUPERVISOR) & mask));
271 NVWrite(pNv, 0x00610200, 0x0);
272 NVWrite(pNv, NV50_DISPLAY_CTRL_STATE, NV50_DISPLAY_CTRL_STATE_DISABLE);
273 while ((NVRead(pNv, 0x00610200) & 0x1e0000) != 0);
274 while ((NVRead(pNv, 0x0061c030 + SOR0 * 0x800) & 0x10000000));
275 while ((NVRead(pNv, 0x0061c030 + SOR1 * 0x800) & 0x10000000));
279 NV50CrtcDoModeFixup(DisplayModePtr dst, const DisplayModePtr src)
281 /* Magic mode timing fudge factor */
282 const int fudge = ((src->Flags & V_INTERLACE) && (src->Flags & V_DBLSCAN)) ? 2 : 1;
283 const int interlaceDiv = (src->Flags & V_INTERLACE) ? 2 : 1;
285 /* Stash the src timings in the Crtc fields in dst */
286 dst->CrtcHBlankStart = src->CrtcVTotal << 16 | src->CrtcHTotal;
287 dst->CrtcHSyncEnd = ((src->CrtcVSyncEnd - src->CrtcVSyncStart) / interlaceDiv - 1) << 16 |
288 (src->CrtcHSyncEnd - src->CrtcHSyncStart - 1);
289 dst->CrtcHBlankEnd = ((src->CrtcVBlankEnd - src->CrtcVSyncStart) / interlaceDiv - fudge) << 16 |
290 (src->CrtcHBlankEnd - src->CrtcHSyncStart - 1);
291 dst->CrtcHTotal = ((src->CrtcVTotal - src->CrtcVSyncStart + src->CrtcVBlankStart) / interlaceDiv - fudge) << 16 |
292 (src->CrtcHTotal - src->CrtcHSyncStart + src->CrtcHBlankStart - 1);
293 dst->CrtcHSkew = ((src->CrtcVTotal + src->CrtcVBlankEnd - src->CrtcVSyncStart) / 2 - 2) << 16 |
294 ((2*src->CrtcVTotal - src->CrtcVSyncStart + src->CrtcVBlankStart) / 2 - 2);
298 NV50CrtcModeFixup(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode)
300 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
302 if (nv_crtc->skipModeFixup)
305 NV50CrtcDoModeFixup(adjusted_mode, mode);
310 NV50CrtcModeSet(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode, int x, int y)
312 ScrnInfoPtr pScrn = crtc->scrn;
313 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
314 const int HDisplay = adjusted_mode->HDisplay;
315 const int VDisplay = adjusted_mode->VDisplay;
317 nv_crtc->pclk = adjusted_mode->Clock;
319 /* NV50CrtcCommand includes head offset */
320 NV50CrtcCommand(crtc, NV50_CRTC0_CLOCK, adjusted_mode->Clock | 0x800000);
321 NV50CrtcCommand(crtc, NV50_CRTC0_INTERLACE, (adjusted_mode->Flags & V_INTERLACE) ? 2 : 0);
322 NV50CrtcCommand(crtc, 0x810, 0);
323 NV50CrtcCommand(crtc, 0x82c, 0);
324 /* This confirms my suspicion that recent nvidia hardware does no vertical programming */
325 /* NV40 still has it as a legacy mode, and i don't know how to do the "new" way, but it definately exists */
326 NV50CrtcCommand(crtc, NV50_CRTC0_HBLANK_START, adjusted_mode->CrtcHBlankStart);
327 NV50CrtcCommand(crtc, NV50_CRTC0_HSYNC_END, adjusted_mode->CrtcHSyncEnd);
328 NV50CrtcCommand(crtc, NV50_CRTC0_HBLANK_END, adjusted_mode->CrtcHBlankEnd);
329 NV50CrtcCommand(crtc, NV50_CRTC0_HTOTAL, adjusted_mode->CrtcHTotal);
330 if(adjusted_mode->Flags & V_INTERLACE) {
331 NV50CrtcCommand(crtc, 0x824, adjusted_mode->CrtcHSkew);
333 NV50CrtcCommand(crtc, NV50_CRTC0_FB_SIZE, pScrn->virtualY << 16 | pScrn->virtualX);
334 NV50CrtcCommand(crtc, NV50_CRTC0_PITCH, pScrn->displayWidth * (pScrn->bitsPerPixel / 8) | 0x100000);
335 switch(pScrn->depth) {
337 NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_8BPP);
340 NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_15BPP);
343 NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_16BPP);
346 NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_24BPP);
349 NV50CrtcSetDither(crtc, FALSE);
350 NV50CrtcCommand(crtc, 0x8a8, 0x40000);
351 NV50CrtcCommand(crtc, NV50_CRTC0_FB_POS, y << 16 | x);
352 NV50CrtcCommand(crtc, NV50_CRTC0_SCRN_SIZE, VDisplay << 16 | HDisplay);
353 NV50CrtcCommand(crtc, 0x8d4, 0);
355 NV50CrtcBlankScreen(crtc, FALSE);
359 NV50CrtcBlankScreen(xf86CrtcPtr crtc, Bool blank)
361 ScrnInfoPtr pScrn = crtc->scrn;
362 NVPtr pNv = NVPTR(pScrn);
363 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
366 NV50CrtcShowHideCursor(crtc, FALSE, FALSE);
368 NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_MODE, NV50_CRTC0_CLUT_MODE_BLANK);
369 NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_OFFSET, 0);
370 if(pNv->NVArch != 0x50)
371 NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK1, NV84_CRTC0_BLANK_UNK1_BLANK);
372 NV50CrtcCommand(crtc, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_BLANK);
373 if(pNv->NVArch != 0x50)
374 NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK2, NV84_CRTC0_BLANK_UNK2_BLANK);
376 NV50CrtcCommand(crtc, NV50_CRTC0_FB_OFFSET, pNv->FB->offset >> 8);
377 NV50CrtcCommand(crtc, 0x864, 0);
378 NVWrite(pNv, 0x00610380, 0);
379 /* RAM is clamped to 256 MiB. */
380 NVWrite(pNv, NV50_CRTC0_RAM_AMOUNT, pNv->RamAmountKBytes * 1024 - 1);
381 NVWrite(pNv, 0x00610388, 0x150000);
382 NVWrite(pNv, 0x0061038C, 0);
383 NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR_OFFSET, pNv->Cursor->offset >> 8);
384 if(pNv->NVArch != 0x50)
385 NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK2, NV84_CRTC0_BLANK_UNK2_UNBLANK);
386 if(nv_crtc->cursorVisible)
387 NV50CrtcShowHideCursor(crtc, TRUE, FALSE);
388 NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_MODE,
389 pScrn->depth == 8 ? NV50_CRTC0_CLUT_MODE_OFF : NV50_CRTC0_CLUT_MODE_ON);
390 /* Each CRTC has it's own CLUT. */
391 if (nv_crtc->head == 1)
392 NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_OFFSET, pNv->CLUT1->offset >> 8);
394 NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_OFFSET, pNv->CLUT0->offset >> 8);
395 if(pNv->NVArch != 0x50)
396 NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK1, NV84_CRTC0_BLANK_UNK1_UNBLANK);
397 NV50CrtcCommand(crtc, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_UNBLANK);
401 /******************************** Cursor stuff ********************************/
402 static void NV50CrtcShowHideCursor(xf86CrtcPtr crtc, Bool show, Bool update)
404 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
405 ScrnInfoPtr pScrn = crtc->scrn;
407 NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR,
408 show ? NV50_CRTC0_CURSOR_SHOW : NV50_CRTC0_CURSOR_HIDE);
410 nv_crtc->cursorVisible = show;
411 NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
415 void NV50CrtcShowCursor(xf86CrtcPtr crtc)
417 NV50CrtcShowHideCursor(crtc, TRUE, TRUE);
420 void NV50CrtcHideCursor(xf86CrtcPtr crtc)
422 NV50CrtcShowHideCursor(crtc, FALSE, TRUE);
425 /******************************** CRTC stuff ********************************/
428 NV50CrtcPrepare(xf86CrtcPtr crtc)
430 ScrnInfoPtr pScrn = crtc->scrn;
431 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
432 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
435 for(i = 0; i < xf86_config->num_output; i++) {
436 xf86OutputPtr output = xf86_config->output[i];
439 output->funcs->mode_set(output, NULL, NULL);
442 nv_crtc->skipModeFixup = FALSE;
446 NV50CrtcSkipModeFixup(xf86CrtcPtr crtc)
448 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
449 nv_crtc->skipModeFixup = TRUE;
453 NV50CrtcSetDither(xf86CrtcPtr crtc, Bool update)
455 xf86OutputPtr output = NULL;
456 ScrnInfoPtr pScrn = crtc->scrn;
457 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
460 for (i = 0; i < xf86_config->num_output; i++) {
461 if (xf86_config->output[i]->crtc == crtc) {
462 output = xf86_config->output[i];
470 NVOutputPrivatePtr nv_output = output->driver_private;
472 NV50CrtcCommand(crtc, NV50_CRTC0_DITHERING_CTRL, nv_output->dithering ?
473 NV50_CRTC0_DITHERING_CTRL_ON : NV50_CRTC0_DITHERING_CTRL_OFF);
475 NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
478 static void ComputeAspectScale(DisplayModePtr mode, int *outX, int *outY)
480 float scaleX, scaleY, scale;
482 scaleX = mode->CrtcHDisplay / (float)mode->HDisplay;
483 scaleY = mode->CrtcVDisplay / (float)mode->VDisplay;
490 *outX = mode->HDisplay * scale;
491 *outY = mode->VDisplay * scale;
494 void NV50CrtcSetScale(xf86CrtcPtr crtc, DisplayModePtr mode, enum scaling_modes scale)
496 int outX = 0, outY = 0;
500 ComputeAspectScale(mode, &outX, &outY);
503 case SCALE_FULLSCREEN:
504 outX = mode->CrtcHDisplay;
505 outY = mode->CrtcVDisplay;
509 outX = mode->HDisplay;
510 outY = mode->VDisplay;
514 if ((mode->Flags & V_DBLSCAN) || (mode->Flags & V_INTERLACE) ||
515 mode->HDisplay != outX || mode->VDisplay != outY) {
516 NV50CrtcCommand(crtc, 0x8a4, 9);
518 NV50CrtcCommand(crtc, 0x8a4, 0);
520 NV50CrtcCommand(crtc, 0x8d8, outY << 16 | outX);
521 NV50CrtcCommand(crtc, 0x8dc, outY << 16 | outX);
525 NV50CrtcCommit(xf86CrtcPtr crtc)
527 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
528 ScrnInfoPtr pScrn = crtc->scrn;
529 int i, crtc_mask = 0;
531 /* If any heads are unused, blank them */
532 for(i = 0; i < xf86_config->num_output; i++) {
533 xf86OutputPtr output = xf86_config->output[i];
536 /* XXXagp: This assumes that xf86_config->crtc[i] is HEADi */
537 crtc_mask |= 1 << NV50CrtcGetHead(output->crtc);
541 for(i = 0; i < xf86_config->num_crtc; i++) {
542 if(!((1 << i) & crtc_mask)) {
543 NV50CrtcBlankScreen(xf86_config->crtc[i], TRUE);
547 NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);