2
* Copyright 2007 NVIDIA, Corporation
3
* Copyright 2008 Maarten Maathuis
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Software"),
7
* to deal in the Software without restriction, including without limitation
8
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, subject to the following conditions:
12
* The above copyright notice and this permission notice shall be included in
13
* all copies or substantial portions of the Software.
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
#include "nouveau_modeset.h"
25
#include "nouveau_crtc.h"
26
#include "nouveau_output.h"
27
#include "nouveau_connector.h"
29
/* Don't call the directly, only load state should do this on the long run*/
31
NV50CheckWriteVClk(ScrnInfoPtr pScrn)
33
NVPtr pNv = NVPTR(pScrn);
34
int t_start = GetTimeInMillis();
36
while (NVRead(pNv, NV50_DISPLAY_CTRL_STATE) & NV50_DISPLAY_CTRL_STATE_PENDING) {
37
/* An educated guess. */
38
const uint32_t supervisor = NVRead(pNv, NV50_DISPLAY_SUPERVISOR);
40
/* Just in case something goes bad, at least you can blindly restart your machine. */
41
if ((GetTimeInMillis() - t_start) > 5000) {
42
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "NV50CheckWriteVClk() timed out.\n");
43
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "A reboot is probably required now.\n");
47
/* Simply acknowledge it, maybe we should do more? */
48
if (supervisor & NV50_DISPLAY_SUPERVISOR_CRTCn) {
49
NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, supervisor & NV50_DISPLAY_SUPERVISOR_CRTCn);
52
if (supervisor & NV50_DISPLAY_SUPERVISOR_CLK_MASK) {
53
if (supervisor & NV50_DISPLAY_SUPERVISOR_CLK_UPDATE) {
54
const uint32_t clockvar = NVRead(pNv, NV50_DISPLAY_UNK30_CTRL);
57
for(i = 0; i < 2; i++) {
58
nouveauCrtcPtr crtc = pNv->crtc[i];
62
mask = NV50_DISPLAY_UNK30_CTRL_UPDATE_VCLK1;
64
mask = NV50_DISPLAY_UNK30_CTRL_UPDATE_VCLK0;
67
crtc->SetPixelClock(crtc, crtc->pixel_clock);
68
/* Always do something if the supervisor wants a clock change. */
69
/* This is needed because you get a deadlock if you don't kick the NV50_CRTC0_CLK_CTRL2 register. */
70
if (crtc->modeset_lock) {
71
crtc->SetClockMode(crtc, crtc->pixel_clock);
73
nouveauOutputPtr output;
74
for (output = pNv->output; output != NULL; output = output->next) {
75
if (output->crtc == crtc)
76
output->SetClockMode(output, crtc->pixel_clock);
82
NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, 1 << (ffs(supervisor & NV50_DISPLAY_SUPERVISOR_CLK_MASK) - 1));
83
NVWrite(pNv, NV50_DISPLAY_UNK30_CTRL, NV50_DISPLAY_UNK30_CTRL_PENDING);
88
void NV50DisplayCommand(ScrnInfoPtr pScrn, uint32_t addr, uint32_t value)
90
DDXMMIOH("NV50DisplayCommand: head %d addr 0x%X value 0x%X\n", 0, addr, value);
91
NVPtr pNv = NVPTR(pScrn);
92
NVWrite(pNv, NV50_DISPLAY_CTRL_VAL, value);
93
NVWrite(pNv, NV50_DISPLAY_CTRL_STATE, addr | 0x10000 | NV50_DISPLAY_CTRL_STATE_ENABLE | NV50_DISPLAY_CTRL_STATE_PENDING);
94
NV50CheckWriteVClk(pScrn);
97
void NV50CrtcCommand(nouveauCrtcPtr crtc, uint32_t addr, uint32_t value)
99
ScrnInfoPtr pScrn = crtc->scrn;
101
/* This head dependent offset is only for crtc commands. */
102
NV50DisplayCommand(pScrn, addr + 0x400 * crtc->index, value);
106
NV50CrtcModeValid(nouveauCrtcPtr crtc, DisplayModePtr mode)
112
NV50CrtcModeSet(nouveauCrtcPtr crtc, DisplayModePtr mode)
114
ScrnInfoPtr pScrn = crtc->scrn;
115
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcModeSet is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0");
117
/* Anyone know a more appropriate name? */
118
DisplayModePtr desired_mode = crtc->use_native_mode ? crtc->native_mode : mode;
120
/* Save the pixel clock for posterity. */
121
crtc->pixel_clock = desired_mode->Clock;
122
crtc->cur_mode = mode;
124
uint32_t hsync_dur = desired_mode->CrtcHSyncEnd - desired_mode->CrtcHSyncStart;
125
uint32_t vsync_dur = desired_mode->CrtcVSyncEnd - desired_mode->CrtcVSyncStart;
126
uint32_t hsync_start_to_end = desired_mode->CrtcHBlankEnd - desired_mode->CrtcHSyncStart;
127
uint32_t vsync_start_to_end = desired_mode->CrtcVBlankEnd - desired_mode->CrtcVSyncStart;
128
/* I can't give this a proper name, anyone else can? */
129
uint32_t hunk1 = desired_mode->CrtcHTotal - desired_mode->CrtcHSyncStart + desired_mode->CrtcHBlankStart;
130
uint32_t vunk1 = desired_mode->CrtcVTotal - desired_mode->CrtcVSyncStart + desired_mode->CrtcVBlankStart;
131
/* Another strange value, this time only for interlaced modes. */
132
uint32_t vunk2a = 2*desired_mode->CrtcVTotal - desired_mode->CrtcVSyncStart + desired_mode->CrtcVBlankStart;
133
uint32_t vunk2b = desired_mode->CrtcVTotal - desired_mode->CrtcVSyncStart + desired_mode->CrtcVBlankEnd;
135
if (desired_mode->Flags & V_INTERLACE) {
137
vsync_start_to_end /= 2;
142
if (desired_mode->Flags & V_DBLSCAN) {
143
vsync_start_to_end -= 1;
150
/* NV50CrtcCommand includes head offset */
151
/* This is the native mode when DFP && !SCALE_PANEL */
152
NV50CrtcCommand(crtc, NV50_CRTC0_CLOCK, desired_mode->Clock | 0x800000);
153
NV50CrtcCommand(crtc, NV50_CRTC0_INTERLACE, (desired_mode->Flags & V_INTERLACE) ? 2 : 0);
154
NV50CrtcCommand(crtc, NV50_CRTC0_DISPLAY_START, 0);
155
NV50CrtcCommand(crtc, NV50_CRTC0_UNK82C, 0);
156
NV50CrtcCommand(crtc, NV50_CRTC0_DISPLAY_TOTAL, desired_mode->CrtcVTotal << 16 | desired_mode->CrtcHTotal);
157
NV50CrtcCommand(crtc, NV50_CRTC0_SYNC_DURATION, (vsync_dur - 1) << 16 | (hsync_dur - 1));
158
NV50CrtcCommand(crtc, NV50_CRTC0_SYNC_START_TO_BLANK_END, (vsync_start_to_end - 1) << 16 | (hsync_start_to_end - 1));
159
NV50CrtcCommand(crtc, NV50_CRTC0_MODE_UNK1, (vunk1 - 1) << 16 | (hunk1 - 1));
160
if (desired_mode->Flags & V_INTERLACE) {
161
NV50CrtcCommand(crtc, NV50_CRTC0_MODE_UNK2, (vunk2b - 1) << 16 | (vunk2a - 1));
163
NV50CrtcCommand(crtc, NV50_CRTC0_FB_SIZE, pScrn->virtualY << 16 | pScrn->virtualX);
165
/* Maybe move this calculation elsewhere? */
166
crtc->fb_pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
167
NV50CrtcCommand(crtc, NV50_CRTC0_FB_PITCH, crtc->fb_pitch | 0x100000);
169
switch (pScrn->depth) {
171
NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_8BPP);
174
NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_15BPP);
177
NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_16BPP);
180
NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_24BPP);
183
crtc->SetDither(crtc);
184
NV50CrtcCommand(crtc, NV50_CRTC0_COLOR_CTRL, NV50_CRTC_COLOR_CTRL_MODE_COLOR);
185
NV50CrtcCommand(crtc, NV50_CRTC0_FB_POS, (crtc->y << 16) | (crtc->x));
186
/* This is the actual resolution of the mode. */
187
NV50CrtcCommand(crtc, NV50_CRTC0_REAL_RES, (mode->VDisplay << 16) | mode->HDisplay);
188
NV50CrtcCommand(crtc, NV50_CRTC0_SCALE_CENTER_OFFSET, NV50_CRTC_SCALE_CENTER_OFFSET_VAL(0,0));
190
/* Maybe move this as well? */
191
crtc->Blank(crtc, FALSE);
195
NV50CrtcSetPixelClock(nouveauCrtcPtr crtc, int clock)
197
ScrnInfoPtr pScrn = crtc->scrn;
198
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcSetPixelClock is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0");
200
NVPtr pNv = NVPTR(pScrn);
202
/* I don't know why exactly, but these were in my table. */
203
uint32_t pll_reg = crtc->index ? NV50_CRTC1_CLK_CTRL1 : NV50_CRTC0_CLK_CTRL1;
205
int NM1 = 0xbeef, NM2 = 0xdead, log2P;
206
struct pll_lims pll_lim;
207
get_pll_limits(pScrn, pll_reg, &pll_lim);
208
/* NV5x hardware doesn't seem to support a single vco mode, otherwise the blob is hiding it well. */
209
getMNP_double(pScrn, &pll_lim, clock, &NM1, &NM2, &log2P);
211
uint32_t reg1 = NVRead(pNv, pll_reg + 4);
212
uint32_t reg2 = NVRead(pNv, pll_reg + 8);
214
/* bit0: The blob (and bios) seem to have this on (almost) always.
215
* I'm hoping this (experiment) will fix my image stability issues.
217
NVWrite(pNv, NV50_CRTC0_CLK_CTRL1 + crtc->index * 0x800, NV50_CRTC_CLK_CTRL1_CONNECTED | 0x10000011);
219
/* Eventually we should learn ourselves what all the bits should be. */
223
uint8_t N1 = (NM1 >> 8) & 0xFF;
224
uint8_t M1 = NM1 & 0xFF;
225
uint8_t N2 = (NM2 >> 8) & 0xFF;
226
uint8_t M2 = NM2 & 0xFF;
228
reg1 |= (M1 << 16) | N1;
229
reg2 |= (log2P << 28) | (M2 << 16) | N2;
231
NVWrite(pNv, pll_reg + 4, reg1);
232
NVWrite(pNv, pll_reg + 8, reg2);
236
NV50CrtcSetClockMode(nouveauCrtcPtr crtc, int clock)
238
ScrnInfoPtr pScrn = crtc->scrn;
239
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcSetClockMode is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0");
241
NVPtr pNv = NVPTR(pScrn);
243
/* There seem to be a few indicator bits, which are similar to the SOR_CTRL bits. */
244
NVWrite(pNv, NV50_CRTC0_CLK_CTRL2 + crtc->index * 0x800, 0);
248
NV50CrtcSetFB(nouveauCrtcPtr crtc, struct nouveau_bo * buffer)
250
/* For the moment the actual hardware settings stays in ModeSet(). */
251
crtc->front_buffer = buffer;
255
NV50CrtcSetFBOffset(nouveauCrtcPtr crtc, uint32_t x, uint32_t y)
257
/* For the moment the actual hardware settings stays in ModeSet(). */
263
NV50CrtcBlank(nouveauCrtcPtr crtc, Bool blanked)
265
ScrnInfoPtr pScrn = crtc->scrn;
266
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcBlank is called (%s) for %s.\n", blanked ? "blanked" : "unblanked", crtc->index ? "CRTC1" : "CRTC0");
268
NVPtr pNv = NVPTR(pScrn);
271
crtc->HideCursor(crtc, TRUE);
273
NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_MODE, NV50_CRTC0_CLUT_MODE_BLANK);
274
NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_OFFSET, 0);
275
if (pNv->NVArch != 0x50)
276
NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK1, NV84_CRTC0_BLANK_UNK1_BLANK);
277
NV50CrtcCommand(crtc, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_BLANK);
278
if (pNv->NVArch != 0x50)
279
NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK2, NV84_CRTC0_BLANK_UNK2_BLANK);
281
NV50CrtcCommand(crtc, NV50_CRTC0_FB_OFFSET, crtc->front_buffer->offset >> 8);
282
NV50CrtcCommand(crtc, 0x864, 0);
283
NVWrite(pNv, NV50_DISPLAY_UNK_380, 0);
284
/* RAM is clamped to 256 MiB. */
285
NVWrite(pNv, NV50_DISPLAY_RAM_AMOUNT, pNv->RamAmountKBytes * 1024 - 1);
286
NVWrite(pNv, NV50_DISPLAY_UNK_388, 0x150000);
287
NVWrite(pNv, NV50_DISPLAY_UNK_38C, 0);
288
if (crtc->index == 1)
289
NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR_OFFSET, pNv->Cursor2->offset >> 8);
291
NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR_OFFSET, pNv->Cursor->offset >> 8);
292
if(pNv->NVArch != 0x50)
293
NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK2, NV84_CRTC0_BLANK_UNK2_UNBLANK);
295
if (crtc->cursor_visible)
296
crtc->ShowCursor(crtc, TRUE);
298
NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_MODE,
299
pScrn->depth == 8 ? NV50_CRTC0_CLUT_MODE_OFF : NV50_CRTC0_CLUT_MODE_ON);
300
/* Each CRTC has it's own CLUT. */
301
if (crtc->index == 1)
302
NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_OFFSET, pNv->CLUT1->offset >> 8);
304
NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_OFFSET, pNv->CLUT0->offset >> 8);
305
if (pNv->NVArch != 0x50)
306
NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK1, NV84_CRTC0_BLANK_UNK1_UNBLANK);
307
NV50CrtcCommand(crtc, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_UNBLANK);
312
NV50CrtcSetDither(nouveauCrtcPtr crtc)
314
ScrnInfoPtr pScrn = crtc->scrn;
315
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcSetDither is called (%s).\n", !crtc->modeset_lock ? "update" : "no update");
317
NV50CrtcCommand(crtc, NV50_CRTC0_DITHERING_CTRL, crtc->dithering ?
318
NV50_CRTC0_DITHERING_CTRL_ON : NV50_CRTC0_DITHERING_CTRL_OFF);
320
if (!crtc->modeset_lock)
321
NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
325
ComputeAspectScale(DisplayModePtr mode, DisplayModePtr adjusted_mode, int *outX, int *outY)
327
float scaleX, scaleY, scale;
329
scaleX = adjusted_mode->HDisplay / (float)mode->HDisplay;
330
scaleY = adjusted_mode->VDisplay / (float)mode->VDisplay;
337
*outX = mode->HDisplay * scale;
338
*outY = mode->VDisplay * scale;
342
NV50CrtcSetScaleMode(nouveauCrtcPtr crtc, int scale)
344
ScrnInfoPtr pScrn = crtc->scrn;
345
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcSetScale is called with mode %d for %s.\n", scale, crtc->index ? "CRTC1" : "CRTC0");
347
uint32_t scale_val = 0;
348
int outX = 0, outY = 0;
352
ComputeAspectScale(crtc->cur_mode, crtc->native_mode, &outX, &outY);
354
case SCALE_FULLSCREEN:
355
outX = crtc->native_mode->HDisplay;
356
outY = crtc->native_mode->VDisplay;
361
outX = crtc->cur_mode->HDisplay;
362
outY = crtc->cur_mode->VDisplay;
366
/* Got a better name for SCALER_ACTIVE? */
367
if ((crtc->cur_mode->Flags & V_DBLSCAN) || (crtc->cur_mode->Flags & V_INTERLACE) ||
368
crtc->cur_mode->HDisplay != outX || crtc->cur_mode->VDisplay != outY) {
369
scale_val = NV50_CRTC0_SCALE_CTRL_SCALER_ACTIVE;
371
scale_val = NV50_CRTC0_SCALE_CTRL_SCALER_INACTIVE;
374
NV50CrtcCommand(crtc, NV50_CRTC0_SCALE_CTRL, scale_val);
375
NV50CrtcCommand(crtc, NV50_CRTC0_SCALE_RES1, outY << 16 | outX);
376
NV50CrtcCommand(crtc, NV50_CRTC0_SCALE_RES2, outY << 16 | outX);
384
NV50CrtcShowCursor(nouveauCrtcPtr crtc, Bool forced_lock)
386
ScrnInfoPtr pScrn = crtc->scrn;
387
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcShowCursor is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0");
389
if (!crtc->modeset_lock)
390
crtc->cursor_visible = TRUE;
392
NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR_CTRL, NV50_CRTC0_CURSOR_CTRL_SHOW);
394
/* Calling this during modeset will lock things up. */
395
if (!crtc->modeset_lock && !forced_lock)
396
NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
400
NV50CrtcHideCursor(nouveauCrtcPtr crtc, Bool forced_lock)
402
ScrnInfoPtr pScrn = crtc->scrn;
403
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcHideCursor is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0");
405
if (!crtc->modeset_lock)
406
crtc->cursor_visible = FALSE;
408
NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR_CTRL, NV50_CRTC0_CURSOR_CTRL_HIDE);
410
/* Calling this during modeset will lock things up. */
411
if (!crtc->modeset_lock && !forced_lock)
412
NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
416
NV50CrtcSetCursorPosition(nouveauCrtcPtr crtc, int x, int y)
418
ScrnInfoPtr pScrn = crtc->scrn;
419
NVPtr pNv = NVPTR(pScrn);
420
NVWrite(pNv, NV50_CRTC0_CURSOR_POS + crtc->index * 0x1000, (y & 0xFFFF) << 16 | (x & 0xFFFF));
422
/* This is needed to allow the cursor to move. */
423
NVWrite(pNv, NV50_CRTC0_CURSOR_POS_CTRL + crtc->index * 0x1000, 0);
427
NV50CrtcLoadCursor(nouveauCrtcPtr crtc, Bool argb, uint32_t *src)
429
if (!argb) /* FIXME */
432
NVPtr pNv = NVPTR(crtc->scrn);
433
uint32_t *dst = NULL;
435
if (crtc->index == 1)
436
dst = (uint32_t *) pNv->Cursor2->map;
438
dst = (uint32_t *) pNv->Cursor->map;
440
/* Assume cursor is 64x64 */
441
memcpy(dst, src, 64 * 64 * 4);
449
* The indices are a bit strange, but i'll assume it's correct (taken from nv).
450
* The LUT resolution seems to be 14 bits on NV50 as opposed to the 8 bits of previous hardware.
452
#define NV50_LUT_INDEX(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8)))
454
NV50CrtcGammaSet(nouveauCrtcPtr crtc, uint16_t *red, uint16_t *green, uint16_t *blue, int size)
456
ScrnInfoPtr pScrn = crtc->scrn;
457
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcGammaSet is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0");
459
NVPtr pNv = NVPTR(pScrn);
463
/* Each CRTC has it's own CLUT. */
464
if (crtc->index == 1)
465
CLUT = pNv->CLUT1->map;
467
CLUT = pNv->CLUT0->map;
470
unsigned short red, green, blue, unused;
471
} *lut = (void *) CLUT;
473
switch (pScrn->depth) {
476
for (i = 0; i < 32; i++) {
477
index = NV50_LUT_INDEX(i, 5);
478
lut[index].red = red[i] >> 2;
479
lut[index].green = green[i] >> 2;
480
lut[index].blue = blue[i] >> 2;
485
for (i = 0; i < 32; i++) {
486
index = NV50_LUT_INDEX(i, 5);
487
lut[index].red = red[i] >> 2;
488
lut[index].blue = blue[i] >> 2;
491
/* Green has an extra bit. */
492
for (i = 0; i < 64; i++) {
493
index = NV50_LUT_INDEX(i, 6);
494
lut[index].green = green[i] >> 2;
499
for (i = 0; i < 256; i++) {
500
lut[i].red = red[i] >> 2;
501
lut[i].green = green[i] >> 2;
502
lut[i].blue = blue[i] >> 2;
509
NV50CrtcInit(ScrnInfoPtr pScrn)
512
NVPtr pNv = NVPTR(pScrn);
514
for (i=0; i < 2; i++) {
515
nouveauCrtcPtr crtc = xnfcalloc(sizeof(nouveauCrtcRec), 1);
519
/* Function pointers. */
520
crtc->ModeValid = NV50CrtcModeValid;
521
crtc->ModeSet = NV50CrtcModeSet;
522
crtc->SetPixelClock = NV50CrtcSetPixelClock;
523
crtc->SetClockMode = NV50CrtcSetClockMode;
525
crtc->SetFB = NV50CrtcSetFB;
526
crtc->SetFBOffset = NV50CrtcSetFBOffset;
528
crtc->Blank = NV50CrtcBlank;
529
crtc->SetDither = NV50CrtcSetDither;
531
crtc->SetScaleMode = NV50CrtcSetScaleMode;
533
crtc->ShowCursor = NV50CrtcShowCursor;
534
crtc->HideCursor = NV50CrtcHideCursor;
535
crtc->SetCursorPosition = NV50CrtcSetCursorPosition;
536
crtc->LoadCursor = NV50CrtcLoadCursor;
538
crtc->GammaSet = NV50CrtcGammaSet;
545
NV50CrtcDestroy(ScrnInfoPtr pScrn)
548
NVPtr pNv = NVPTR(pScrn);
550
for (i=0; i < 2; i++) {
551
nouveauCrtcPtr crtc = pNv->crtc[i];