1 /* 2 * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and 3 * VA Linux Systems Inc., Fremont, California. 4 * 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining 8 * a copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation on the rights to use, copy, modify, merge, 11 * publish, distribute, sublicense, and/or sell copies of the Software, 12 * and to permit persons to whom the Software is furnished to do so, 13 * subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial 17 * portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR 23 * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 */ 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #include <string.h> 34 #include <stdio.h> 35 36 #include "xf86.h" 37 #include "xf86Modes.h" 38 39 #ifdef HAVE_XEXTPROTO_71 40 #include "X11/extensions/dpmsconst.h" 41 #else 42 #define DPMS_SERVER 43 #include "X11/extensions/dpms.h" 44 #endif 45 46 #include "r128.h" 47 #include "r128_probe.h" 48 #include "r128_reg.h" 49 50 51 #ifndef MAX 52 #define MAX(a,b) ((a)>(b)?(a):(b)) 53 #endif 54 55 56 /* Define CRTC registers for requested video mode. */ 57 static Bool 58 R128InitCrtcRegisters(xf86CrtcPtr crtc, R128SavePtr save, DisplayModePtr mode) 59 { 60 ScrnInfoPtr pScrn = crtc->scrn; 61 R128InfoPtr info = R128PTR(pScrn); 62 xf86OutputPtr output = R128FirstOutput(crtc); 63 R128OutputPrivatePtr r128_output = output->driver_private; 64 65 int format; 66 int hsync_start; 67 int hsync_wid; 68 int hsync_fudge; 69 int vsync_wid; 70 int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; 71 int hsync_fudge_fp[] = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 }; 72 // int hsync_fudge_fp_crt[] = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 }; 73 74 switch (info->CurrentLayout.pixel_code) { 75 case 4: format = 1; break; 76 case 8: format = 2; break; 77 case 15: format = 3; break; /* 555 */ 78 case 16: format = 4; break; /* 565 */ 79 case 24: format = 5; break; /* RGB */ 80 case 32: format = 6; break; /* xRGB */ 81 default: 82 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 83 "Unsupported pixel depth (%d)\n", 84 info->CurrentLayout.bitsPerPixel); 85 return FALSE; 86 } 87 88 if (r128_output->MonType == MT_LCD || r128_output->MonType == MT_DFP) 89 hsync_fudge = hsync_fudge_fp[format-1]; 90 else 91 hsync_fudge = hsync_fudge_default[format-1]; 92 93 save->crtc_gen_cntl = (R128_CRTC_EXT_DISP_EN 94 | R128_CRTC_EN 95 | (format << 8) 96 | ((mode->Flags & V_DBLSCAN) 97 ? R128_CRTC_DBL_SCAN_EN 98 : 0) 99 | ((mode->Flags & V_INTERLACE) 100 ? R128_CRTC_INTERLACE_EN 101 : 0) 102 | ((mode->Flags & V_CSYNC) 103 ? R128_CRTC_CSYNC_EN 104 : 0)); 105 106 if (r128_output->MonType == MT_LCD || r128_output->MonType == MT_DFP) 107 save->crtc_gen_cntl &= ~(R128_CRTC_DBL_SCAN_EN | R128_CRTC_INTERLACE_EN); 108 109 save->crtc_ext_cntl |= R128_VGA_ATI_LINEAR | R128_XCRT_CNT_EN; 110 111 save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff) 112 | (((mode->CrtcHDisplay / 8) - 1) << 16)); 113 114 hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; 115 if (!hsync_wid) hsync_wid = 1; 116 if (hsync_wid > 0x3f) hsync_wid = 0x3f; 117 118 hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge; 119 120 save->crtc_h_sync_strt_wid = ((hsync_start & 0xfff) 121 | (hsync_wid << 16) 122 | ((mode->Flags & V_NHSYNC) 123 ? R128_CRTC_H_SYNC_POL 124 : 0)); 125 126 #if 1 127 /* This works for double scan mode. */ 128 save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 129 | ((mode->CrtcVDisplay - 1) << 16)); 130 #else 131 /* This is what cce/nbmode.c example code 132 does -- is this correct? */ 133 save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 134 | ((mode->CrtcVDisplay 135 * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1) 136 << 16)); 137 #endif 138 139 vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 140 if (!vsync_wid) vsync_wid = 1; 141 if (vsync_wid > 0x1f) vsync_wid = 0x1f; 142 143 save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) 144 | (vsync_wid << 16) 145 | ((mode->Flags & V_NVSYNC) 146 ? R128_CRTC_V_SYNC_POL 147 : 0)); 148 save->crtc_pitch = info->CurrentLayout.displayWidth / 8; 149 150 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 151 "Pitch = %d bytes (virtualX = %d, " 152 "displayWidth = %d)\n", 153 save->crtc_pitch, pScrn->virtualX, 154 info->CurrentLayout.displayWidth)); 155 156 #if X_BYTE_ORDER == X_BIG_ENDIAN 157 /* Change the endianness of the aperture */ 158 switch (info->CurrentLayout.pixel_code) { 159 case 15: 160 case 16: save->config_cntl |= APER_0_BIG_ENDIAN_16BPP_SWAP; break; 161 case 32: save->config_cntl |= APER_0_BIG_ENDIAN_32BPP_SWAP; break; 162 default: break; 163 } 164 #endif 165 166 return TRUE; 167 } 168 169 /* Define CRTC2 registers for requested video mode. */ 170 static Bool 171 R128InitCrtc2Registers(xf86CrtcPtr crtc, R128SavePtr save, DisplayModePtr mode) 172 { 173 ScrnInfoPtr pScrn = crtc->scrn; 174 R128InfoPtr info = R128PTR(pScrn); 175 176 int format; 177 int hsync_start; 178 int hsync_wid; 179 int hsync_fudge; 180 int vsync_wid; 181 int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; 182 183 switch (info->CurrentLayout.pixel_code) { 184 case 4: format = 1; break; 185 case 8: format = 2; break; 186 case 15: format = 3; break; /* 555 */ 187 case 16: format = 4; break; /* 565 */ 188 case 24: format = 5; break; /* RGB */ 189 case 32: format = 6; break; /* xRGB */ 190 default: 191 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 192 "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel); 193 return FALSE; 194 } 195 196 hsync_fudge = hsync_fudge_default[format-1]; 197 198 save->crtc2_gen_cntl = (R128_CRTC2_EN 199 | (format << 8) 200 | ((mode->Flags & V_DBLSCAN) 201 ? R128_CRTC2_DBL_SCAN_EN 202 : 0)); 203 /* 204 save->crtc2_gen_cntl &= ~R128_CRTC_EXT_DISP_EN; 205 save->crtc2_gen_cntl |= (1 << 21); 206 */ 207 save->crtc2_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff) 208 | (((mode->CrtcHDisplay / 8) - 1) << 16)); 209 210 hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; 211 if (!hsync_wid) hsync_wid = 1; 212 if (hsync_wid > 0x3f) hsync_wid = 0x3f; 213 214 hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge; 215 216 save->crtc2_h_sync_strt_wid = ((hsync_start & 0xfff) 217 | (hsync_wid << 16) 218 | ((mode->Flags & V_NHSYNC) 219 ? R128_CRTC2_H_SYNC_POL 220 : 0)); 221 222 #if 1 223 /* This works for double scan mode. */ 224 save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 225 | ((mode->CrtcVDisplay - 1) << 16)); 226 #else 227 /* This is what cce/nbmode.c example code 228 does -- is this correct? */ 229 save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 230 | ((mode->CrtcVDisplay 231 * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1) 232 << 16)); 233 #endif 234 235 vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 236 if (!vsync_wid) vsync_wid = 1; 237 if (vsync_wid > 0x1f) vsync_wid = 0x1f; 238 239 save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) 240 | (vsync_wid << 16) 241 | ((mode->Flags & V_NVSYNC) 242 ? R128_CRTC2_V_SYNC_POL 243 : 0)); 244 save->crtc2_pitch = info->CurrentLayout.displayWidth / 8; 245 246 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 247 "Pitch = %d bytes (virtualX = %d, " 248 "displayWidth = %d)\n", 249 save->crtc2_pitch, pScrn->virtualX, 250 info->CurrentLayout.displayWidth)); 251 return TRUE; 252 } 253 254 /* Write CRTC registers. */ 255 void R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 256 { 257 R128InfoPtr info = R128PTR(pScrn); 258 unsigned char *R128MMIO = info->MMIO; 259 260 OUTREG(R128_CRTC_GEN_CNTL, restore->crtc_gen_cntl); 261 262 OUTREGP(R128_CRTC_EXT_CNTL, restore->crtc_ext_cntl, 263 R128_CRTC_VSYNC_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_DISPLAY_DIS); 264 265 OUTREG(R128_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); 266 OUTREG(R128_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); 267 OUTREG(R128_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); 268 OUTREG(R128_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid); 269 OUTREG(R128_CRTC_OFFSET, restore->crtc_offset); 270 OUTREG(R128_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); 271 OUTREG(R128_CRTC_PITCH, restore->crtc_pitch); 272 } 273 274 /* Write CRTC2 registers. */ 275 void R128RestoreCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) 276 { 277 R128InfoPtr info = R128PTR(pScrn); 278 unsigned char *R128MMIO = info->MMIO; 279 280 OUTREGP(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl, 281 R128_CRTC2_DISP_DIS); 282 283 OUTREG(R128_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); 284 OUTREG(R128_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid); 285 OUTREG(R128_CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp); 286 OUTREG(R128_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid); 287 OUTREG(R128_CRTC2_OFFSET, restore->crtc2_offset); 288 OUTREG(R128_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); 289 OUTREG(R128_CRTC2_PITCH, restore->crtc2_pitch); 290 } 291 292 static Bool R128InitCrtcBase(xf86CrtcPtr crtc, R128SavePtr save, int x, int y) 293 { 294 ScrnInfoPtr pScrn = crtc->scrn; 295 R128InfoPtr info = R128PTR(pScrn); 296 int offset = y * info->CurrentLayout.displayWidth + x; 297 int Base = pScrn->fbOffset; 298 299 switch (info->CurrentLayout.pixel_code) { 300 case 15: 301 case 16: offset *= 2; break; 302 case 24: offset *= 3; break; 303 case 32: offset *= 4; break; 304 } 305 Base += offset; 306 307 if (crtc->rotatedData != NULL) 308 Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; 309 310 Base &= ~7; /* 3 lower bits are always 0 */ 311 if (info->CurrentLayout.pixel_code == 24) 312 Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */ 313 314 save->crtc_offset = Base; 315 save->crtc_offset_cntl = 0; 316 317 return TRUE; 318 } 319 320 static Bool R128InitCrtc2Base(xf86CrtcPtr crtc, R128SavePtr save, int x, int y) 321 { 322 ScrnInfoPtr pScrn = crtc->scrn; 323 R128InfoPtr info = R128PTR(pScrn); 324 int offset = y * info->CurrentLayout.displayWidth + x; 325 int Base = pScrn->fbOffset; 326 327 switch (info->CurrentLayout.pixel_code) { 328 case 15: 329 case 16: offset *= 2; break; 330 case 24: offset *= 3; break; 331 case 32: offset *= 4; break; 332 } 333 Base += offset; 334 335 if (crtc->rotatedData != NULL) 336 Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; 337 338 Base &= ~7; /* 3 lower bits are always 0 */ 339 if (info->CurrentLayout.pixel_code == 24) 340 Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */ 341 342 save->crtc2_offset = Base; 343 save->crtc2_offset_cntl = 0; 344 345 return TRUE; 346 } 347 348 /* Define PLL registers for requested video mode. */ 349 static void R128InitPLLRegisters(xf86CrtcPtr crtc, R128SavePtr save, 350 R128PLLPtr pll, double dot_clock) 351 { 352 #if R128_DEBUG 353 ScrnInfoPtr pScrn = crtc->scrn; 354 #endif 355 unsigned long freq = dot_clock * 100; 356 struct { 357 int divider; 358 int bitvalue; 359 } *post_div, 360 post_divs[] = { 361 /* From RAGE 128 VR/RAGE 128 GL Register 362 Reference Manual (Technical Reference 363 Manual P/N RRG-G04100-C Rev. 0.04), page 364 3-17 (PLL_DIV_[3:0]). */ 365 { 1, 0 }, /* VCLK_SRC */ 366 { 2, 1 }, /* VCLK_SRC/2 */ 367 { 4, 2 }, /* VCLK_SRC/4 */ 368 { 8, 3 }, /* VCLK_SRC/8 */ 369 370 { 3, 4 }, /* VCLK_SRC/3 */ 371 /* bitvalue = 5 is reserved */ 372 { 6, 6 }, /* VCLK_SRC/6 */ 373 { 12, 7 }, /* VCLK_SRC/12 */ 374 { 0, 0 } 375 }; 376 377 if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; 378 if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; 379 380 for (post_div = &post_divs[0]; post_div->divider; ++post_div) { 381 save->pll_output_freq = post_div->divider * freq; 382 if (save->pll_output_freq >= pll->min_pll_freq 383 && save->pll_output_freq <= pll->max_pll_freq) break; 384 } 385 386 save->dot_clock_freq = freq; 387 save->feedback_div = R128Div(pll->reference_div * save->pll_output_freq, 388 pll->reference_freq); 389 save->post_div = post_div->divider; 390 391 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 392 "dc=%d, of=%d, fd=%d, pd=%d\n", 393 save->dot_clock_freq, 394 save->pll_output_freq, 395 save->feedback_div, 396 save->post_div)); 397 398 save->ppll_ref_div = pll->reference_div; 399 save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); 400 save->htotal_cntl = 0; 401 402 } 403 404 /* Define PLL2 registers for requested video mode. */ 405 static void 406 R128InitPLL2Registers(xf86CrtcPtr crtc, R128SavePtr save, 407 R128PLLPtr pll, double dot_clock) 408 { 409 #if R128_DEBUG 410 ScrnInfoPtr pScrn = crtc->scrn; 411 #endif 412 unsigned long freq = dot_clock * 100; 413 struct { 414 int divider; 415 int bitvalue; 416 } *post_div, 417 post_divs[] = { 418 /* From RAGE 128 VR/RAGE 128 GL Register 419 Reference Manual (Technical Reference 420 Manual P/N RRG-G04100-C Rev. 0.04), page 421 3-17 (PLL_DIV_[3:0]). */ 422 { 1, 0 }, /* VCLK_SRC */ 423 { 2, 1 }, /* VCLK_SRC/2 */ 424 { 4, 2 }, /* VCLK_SRC/4 */ 425 { 8, 3 }, /* VCLK_SRC/8 */ 426 427 { 3, 4 }, /* VCLK_SRC/3 */ 428 /* bitvalue = 5 is reserved */ 429 { 6, 6 }, /* VCLK_SRC/6 */ 430 { 12, 7 }, /* VCLK_SRC/12 */ 431 { 0, 0 } 432 }; 433 434 if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; 435 if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; 436 437 for (post_div = &post_divs[0]; post_div->divider; ++post_div) { 438 save->pll_output_freq_2 = post_div->divider * freq; 439 if (save->pll_output_freq_2 >= pll->min_pll_freq 440 && save->pll_output_freq_2 <= pll->max_pll_freq) break; 441 } 442 443 save->dot_clock_freq_2 = freq; 444 save->feedback_div_2 = R128Div(pll->reference_div 445 * save->pll_output_freq_2, 446 pll->reference_freq); 447 save->post_div_2 = post_div->divider; 448 449 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 450 "dc=%d, of=%d, fd=%d, pd=%d\n", 451 save->dot_clock_freq_2, 452 save->pll_output_freq_2, 453 save->feedback_div_2, 454 save->post_div_2)); 455 456 save->p2pll_ref_div = pll->reference_div; 457 save->p2pll_div_0 = (save->feedback_div_2 | (post_div->bitvalue<<16)); 458 save->htotal_cntl2 = 0; 459 } 460 461 static void R128PLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn) 462 { 463 while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R); 464 } 465 466 static void R128PLLWriteUpdate(ScrnInfoPtr pScrn) 467 { 468 R128InfoPtr info = R128PTR(pScrn); 469 unsigned char *R128MMIO = info->MMIO; 470 471 while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R); 472 473 OUTPLLP(pScrn, R128_PPLL_REF_DIV, R128_PPLL_ATOMIC_UPDATE_W, 474 ~R128_PPLL_ATOMIC_UPDATE_W); 475 476 } 477 478 static void R128PLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn) 479 { 480 while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R); 481 } 482 483 static void R128PLL2WriteUpdate(ScrnInfoPtr pScrn) 484 { 485 R128InfoPtr info = R128PTR(pScrn); 486 unsigned char *R128MMIO = info->MMIO; 487 488 while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R); 489 490 OUTPLLP(pScrn, R128_P2PLL_REF_DIV, 491 R128_P2PLL_ATOMIC_UPDATE_W, 492 ~(R128_P2PLL_ATOMIC_UPDATE_W)); 493 } 494 495 /* Write PLL registers. */ 496 void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 497 { 498 R128InfoPtr info = R128PTR(pScrn); 499 unsigned char *R128MMIO = info->MMIO; 500 501 502 OUTPLLP(pScrn, R128_VCLK_ECP_CNTL, 503 R128_VCLK_SRC_SEL_CPUCLK, 504 ~(R128_VCLK_SRC_SEL_MASK)); 505 506 OUTPLLP(pScrn, 507 R128_PPLL_CNTL, 508 R128_PPLL_RESET 509 | R128_PPLL_ATOMIC_UPDATE_EN 510 | R128_PPLL_VGA_ATOMIC_UPDATE_EN, 511 ~(R128_PPLL_RESET 512 | R128_PPLL_ATOMIC_UPDATE_EN 513 | R128_PPLL_VGA_ATOMIC_UPDATE_EN)); 514 515 OUTREGP(R128_CLOCK_CNTL_INDEX, R128_PLL_DIV_SEL, ~(R128_PLL_DIV_SEL)); 516 517 /* R128PLLWaitForReadUpdateComplete(pScrn);*/ 518 OUTPLLP(pScrn, R128_PPLL_REF_DIV, 519 restore->ppll_ref_div, ~R128_PPLL_REF_DIV_MASK); 520 /* R128PLLWriteUpdate(pScrn); 521 522 R128PLLWaitForReadUpdateComplete(pScrn);*/ 523 OUTPLLP(pScrn, R128_PPLL_DIV_3, 524 restore->ppll_div_3, ~R128_PPLL_FB3_DIV_MASK); 525 /* R128PLLWriteUpdate(pScrn);*/ 526 OUTPLLP(pScrn, R128_PPLL_DIV_3, 527 restore->ppll_div_3, ~R128_PPLL_POST3_DIV_MASK); 528 529 R128PLLWriteUpdate(pScrn); 530 R128PLLWaitForReadUpdateComplete(pScrn); 531 532 OUTPLLP(pScrn, R128_PPLL_DIV_0, 533 restore->ppll_div_0, ~R128_PPLL_FB0_DIV_MASK); 534 /* R128PLLWriteUpdate(pScrn);*/ 535 OUTPLLP(pScrn, R128_PPLL_DIV_0, 536 restore->ppll_div_0, ~R128_PPLL_POST0_DIV_MASK); 537 538 R128PLLWriteUpdate(pScrn); 539 R128PLLWaitForReadUpdateComplete(pScrn); 540 541 OUTPLL(R128_HTOTAL_CNTL, restore->htotal_cntl); 542 /* R128PLLWriteUpdate(pScrn);*/ 543 544 OUTPLLP(pScrn, R128_PPLL_CNTL, 0, ~(R128_PPLL_RESET 545 | R128_PPLL_SLEEP 546 | R128_PPLL_ATOMIC_UPDATE_EN 547 | R128_PPLL_VGA_ATOMIC_UPDATE_EN)); 548 549 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 550 "Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", 551 restore->ppll_ref_div, 552 restore->ppll_div_3, 553 restore->htotal_cntl, 554 INPLL(pScrn, R128_PPLL_CNTL))); 555 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 556 "Wrote: rd=%d, fd=%d, pd=%d\n", 557 restore->ppll_ref_div & R128_PPLL_REF_DIV_MASK, 558 restore->ppll_div_3 & R128_PPLL_FB3_DIV_MASK, 559 (restore->ppll_div_3 & 560 R128_PPLL_POST3_DIV_MASK) >> 16)); 561 562 usleep(5000); /* let the clock lock */ 563 564 OUTPLLP(pScrn, R128_VCLK_ECP_CNTL, 565 R128_VCLK_SRC_SEL_PPLLCLK, 566 ~(R128_VCLK_SRC_SEL_MASK)); 567 568 } 569 570 /* Write PLL2 registers. */ 571 void R128RestorePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) 572 { 573 R128InfoPtr info = R128PTR(pScrn); 574 unsigned char *R128MMIO = info->MMIO; 575 576 OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL, 577 R128_V2CLK_SRC_SEL_CPUCLK, 578 ~R128_V2CLK_SRC_SEL_MASK); 579 580 OUTPLLP(pScrn, 581 R128_P2PLL_CNTL, 582 R128_P2PLL_RESET 583 | R128_P2PLL_ATOMIC_UPDATE_EN 584 | R128_P2PLL_VGA_ATOMIC_UPDATE_EN, 585 ~(R128_P2PLL_RESET 586 | R128_P2PLL_ATOMIC_UPDATE_EN 587 | R128_P2PLL_VGA_ATOMIC_UPDATE_EN)); 588 589 #if 1 590 OUTREGP(R128_CLOCK_CNTL_INDEX, 0, R128_PLL2_DIV_SEL_MASK); 591 #endif 592 593 /*R128PLL2WaitForReadUpdateComplete(pScrn);*/ 594 595 OUTPLLP(pScrn, R128_P2PLL_REF_DIV, restore->p2pll_ref_div, ~R128_P2PLL_REF_DIV_MASK); 596 597 /* R128PLL2WriteUpdate(pScrn); 598 R128PLL2WaitForReadUpdateComplete(pScrn);*/ 599 600 OUTPLLP(pScrn, R128_P2PLL_DIV_0, 601 restore->p2pll_div_0, ~R128_P2PLL_FB0_DIV_MASK); 602 603 /* R128PLL2WriteUpdate(pScrn); 604 R128PLL2WaitForReadUpdateComplete(pScrn);*/ 605 606 OUTPLLP(pScrn, R128_P2PLL_DIV_0, 607 restore->p2pll_div_0, ~R128_P2PLL_POST0_DIV_MASK); 608 609 R128PLL2WriteUpdate(pScrn); 610 R128PLL2WaitForReadUpdateComplete(pScrn); 611 612 OUTPLL(R128_HTOTAL2_CNTL, restore->htotal_cntl2); 613 614 /* R128PLL2WriteUpdate(pScrn);*/ 615 616 OUTPLLP(pScrn, R128_P2PLL_CNTL, 0, ~(R128_P2PLL_RESET 617 | R128_P2PLL_SLEEP 618 | R128_P2PLL_ATOMIC_UPDATE_EN 619 | R128_P2PLL_VGA_ATOMIC_UPDATE_EN)); 620 621 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 622 "Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", 623 restore->p2pll_ref_div, 624 restore->p2pll_div_0, 625 restore->htotal_cntl2, 626 INPLL(pScrn, R128_P2PLL_CNTL))); 627 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 628 "Wrote: rd=%d, fd=%d, pd=%d\n", 629 restore->p2pll_ref_div & R128_P2PLL_REF_DIV_MASK, 630 restore->p2pll_div_0 & R128_P2PLL_FB0_DIV_MASK, 631 (restore->p2pll_div_0 & 632 R128_P2PLL_POST0_DIV_MASK) >>16)); 633 634 usleep(5000); /* Let the clock to lock */ 635 636 OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL, 637 R128_V2CLK_SRC_SEL_P2PLLCLK, 638 ~R128_V2CLK_SRC_SEL_MASK); 639 640 } 641 642 /* Define DDA registers for requested video mode. */ 643 static Bool 644 R128InitDDARegisters(xf86CrtcPtr crtc, R128SavePtr save, 645 R128PLLPtr pll, DisplayModePtr mode) 646 { 647 ScrnInfoPtr pScrn = crtc->scrn; 648 R128InfoPtr info = R128PTR(pScrn); 649 xf86OutputPtr output = R128FirstOutput(crtc); 650 R128OutputPrivatePtr r128_output = output->driver_private; 651 652 int DisplayFifoWidth = 128; 653 int DisplayFifoDepth = 32; 654 int XclkFreq; 655 int VclkFreq; 656 int XclksPerTransfer; 657 int XclksPerTransferPrecise; 658 int UseablePrecision; 659 int Roff; 660 int Ron; 661 662 XclkFreq = pll->xclk; 663 664 VclkFreq = R128Div(pll->reference_freq * save->feedback_div, 665 pll->reference_div * save->post_div); 666 667 if (info->isDFP && !info->isPro2 && r128_output->PanelXRes > 0) { 668 if (r128_output->PanelXRes != mode->CrtcHDisplay) 669 VclkFreq = (VclkFreq * mode->CrtcHDisplay) / r128_output->PanelXRes; 670 } 671 672 XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth, 673 VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); 674 675 UseablePrecision = R128MinBits(XclksPerTransfer) + 1; 676 677 XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth) 678 << (11 - UseablePrecision), 679 VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); 680 681 Roff = XclksPerTransferPrecise * (DisplayFifoDepth - 4); 682 683 Ron = (4 * info->ram->MB 684 + 3 * MAX(info->ram->Trcd - 2, 0) 685 + 2 * info->ram->Trp 686 + info->ram->Twr 687 + info->ram->CL 688 + info->ram->Tr2w 689 + XclksPerTransfer) << (11 - UseablePrecision); 690 691 if (Ron + info->ram->Rloop >= Roff) { 692 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 693 "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n", 694 Ron, info->ram->Rloop, Roff); 695 return FALSE; 696 } 697 698 save->dda_config = (XclksPerTransferPrecise 699 | (UseablePrecision << 16) 700 | (info->ram->Rloop << 20)); 701 702 save->dda_on_off = (Ron << 16) | Roff; 703 704 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 705 "XclkFreq = %d; VclkFreq = %d; " 706 "per = %d, %d (usable = %d)\n", 707 XclkFreq, 708 VclkFreq, 709 XclksPerTransfer, 710 XclksPerTransferPrecise, 711 UseablePrecision)); 712 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 713 "Roff = %d, Ron = %d, Rloop = %d\n", 714 Roff, Ron, info->ram->Rloop)); 715 716 return TRUE; 717 } 718 719 /* Define DDA2 registers for requested video mode. */ 720 static Bool 721 R128InitDDA2Registers(xf86CrtcPtr crtc, R128SavePtr save, 722 R128PLLPtr pll, DisplayModePtr mode) 723 { 724 ScrnInfoPtr pScrn = crtc->scrn; 725 R128InfoPtr info = R128PTR(pScrn); 726 xf86OutputPtr output = R128FirstOutput(crtc); 727 R128OutputPrivatePtr r128_output = output->driver_private; 728 729 int DisplayFifoWidth = 128; 730 int DisplayFifoDepth = 32; 731 int XclkFreq; 732 int VclkFreq; 733 int XclksPerTransfer; 734 int XclksPerTransferPrecise; 735 int UseablePrecision; 736 int Roff; 737 int Ron; 738 739 XclkFreq = pll->xclk; 740 741 VclkFreq = R128Div(pll->reference_freq * save->feedback_div_2, 742 pll->reference_div * save->post_div_2); 743 744 if (info->isDFP && !info->isPro2 && r128_output->PanelXRes > 0) { 745 if (r128_output->PanelXRes != mode->CrtcHDisplay) 746 VclkFreq = (VclkFreq * mode->CrtcHDisplay) / r128_output->PanelXRes; 747 } 748 749 XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth, 750 VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); 751 752 UseablePrecision = R128MinBits(XclksPerTransfer) + 1; 753 754 XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth) 755 << (11 - UseablePrecision), 756 VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); 757 758 Roff = XclksPerTransferPrecise * (DisplayFifoDepth - 4); 759 760 Ron = (4 * info->ram->MB 761 + 3 * MAX(info->ram->Trcd - 2, 0) 762 + 2 * info->ram->Trp 763 + info->ram->Twr 764 + info->ram->CL 765 + info->ram->Tr2w 766 + XclksPerTransfer) << (11 - UseablePrecision); 767 768 769 if (Ron + info->ram->Rloop >= Roff) { 770 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 771 "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n", 772 Ron, info->ram->Rloop, Roff); 773 return FALSE; 774 } 775 776 save->dda2_config = (XclksPerTransferPrecise 777 | (UseablePrecision << 16) 778 | (info->ram->Rloop << 20)); 779 780 /*save->dda2_on_off = (Ron << 16) | Roff;*/ 781 /* shift most be 18 otherwise there's corruption on crtc2 */ 782 save->dda2_on_off = (Ron << 18) | Roff; 783 784 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 785 "XclkFreq = %d; VclkFreq = %d; " 786 "per = %d, %d (usable = %d)\n", 787 XclkFreq, 788 VclkFreq, 789 XclksPerTransfer, 790 XclksPerTransferPrecise, 791 UseablePrecision)); 792 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 793 "Roff = %d, Ron = %d, Rloop = %d\n", 794 Roff, Ron, info->ram->Rloop)); 795 796 return TRUE; 797 } 798 799 static void r128_crtc_load_lut(xf86CrtcPtr crtc); 800 801 static void r128_crtc_dpms(xf86CrtcPtr crtc, int mode) 802 { 803 int mask; 804 ScrnInfoPtr pScrn = crtc->scrn; 805 R128InfoPtr info = R128PTR(pScrn); 806 unsigned char *R128MMIO = info->MMIO; 807 R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 808 809 /* XXX: The HSYNC and VSYNC bits for CRTC2 don't exist on the r128? */ 810 mask = r128_crtc->crtc_id ? R128_CRTC2_DISP_DIS : (R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_VSYNC_DIS); 811 812 switch (mode) { 813 case DPMSModeOn: 814 if (r128_crtc->crtc_id) { 815 OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~mask); 816 } else { 817 OUTREGP(R128_CRTC_EXT_CNTL, 0, ~mask); 818 } 819 break; 820 case DPMSModeStandby: 821 if (r128_crtc->crtc_id) { 822 OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask); 823 } else { 824 OUTREGP(R128_CRTC_EXT_CNTL, (R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS), ~mask); 825 } 826 break; 827 case DPMSModeSuspend: 828 if (r128_crtc->crtc_id) { 829 OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask); 830 } else { 831 OUTREGP(R128_CRTC_EXT_CNTL, (R128_CRTC_DISPLAY_DIS | R128_CRTC_VSYNC_DIS), ~mask); 832 } 833 break; 834 case DPMSModeOff: 835 if (r128_crtc->crtc_id) { 836 OUTREGP(R128_CRTC2_GEN_CNTL, mask, ~mask); 837 } else { 838 OUTREGP(R128_CRTC_EXT_CNTL, mask, ~mask); 839 } 840 break; 841 } 842 843 if (mode != DPMSModeOn) { 844 if (r128_crtc->crtc_id) { 845 OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_EN); 846 } else { 847 OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_EN); 848 } 849 } else { 850 if (r128_crtc->crtc_id) { 851 OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_EN, ~R128_CRTC2_EN); 852 } else { 853 OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_EN, ~R128_CRTC_EN); 854 } 855 } 856 857 if (mode != DPMSModeOff) 858 r128_crtc_load_lut(crtc); 859 } 860 861 void r128_crtc_load_lut(xf86CrtcPtr crtc) 862 { 863 ScrnInfoPtr pScrn = crtc->scrn; 864 R128InfoPtr info = R128PTR(pScrn); 865 unsigned char *R128MMIO = info->MMIO; 866 R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 867 int i; 868 869 if (!crtc->enabled) 870 return; 871 872 PAL_SELECT(r128_crtc->crtc_id); 873 874 for (i = 0; i < 256; i++) { 875 OUTPAL(i, r128_crtc->lut_r[i], r128_crtc->lut_g[i], r128_crtc->lut_b[i]); 876 } 877 } 878 879 static Bool r128_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode) 880 { 881 return TRUE; 882 } 883 884 static void r128_crtc_mode_prepare(xf86CrtcPtr crtc) 885 { 886 r128_crtc_dpms(crtc, DPMSModeOff); 887 } 888 889 static void r128_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode, int x, int y) 890 { 891 ScrnInfoPtr pScrn = crtc->scrn; 892 R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 893 R128InfoPtr info = R128PTR(pScrn); 894 double dot_clock = adjusted_mode->Clock / 1000.0; 895 896 if (r128_crtc->cursor_offset) r128_crtc_hide_cursor(crtc); 897 xf86PrintModeline(pScrn->scrnIndex, adjusted_mode); 898 R128InitCommonRegisters(&info->ModeReg, info); 899 900 switch (r128_crtc->crtc_id) { 901 case 0: 902 R128InitCrtcRegisters(crtc, &info->ModeReg, adjusted_mode); 903 R128InitCrtcBase(crtc, &info->ModeReg, x, y); 904 if (dot_clock) { 905 R128InitPLLRegisters(crtc, &info->ModeReg, &info->pll, dot_clock); 906 R128InitDDARegisters(crtc, &info->ModeReg, &info->pll, adjusted_mode); 907 } else { 908 info->ModeReg.ppll_ref_div = info->SavedReg.ppll_ref_div; 909 info->ModeReg.ppll_div_3 = info->SavedReg.ppll_div_3; 910 info->ModeReg.htotal_cntl = info->SavedReg.htotal_cntl; 911 info->ModeReg.dda_config = info->SavedReg.dda_config; 912 info->ModeReg.dda_on_off = info->SavedReg.dda_on_off; 913 } 914 break; 915 case 1: 916 R128InitCrtc2Registers(crtc, &info->ModeReg, adjusted_mode); 917 R128InitCrtc2Base(crtc, &info->ModeReg, x, y); 918 if (dot_clock) { 919 R128InitPLL2Registers(crtc, &info->ModeReg, &info->pll, dot_clock); 920 R128InitDDA2Registers(crtc, &info->ModeReg, &info->pll, adjusted_mode); 921 } 922 break; 923 } 924 925 R128RestoreCommonRegisters(pScrn, &info->ModeReg); 926 927 switch (r128_crtc->crtc_id) { 928 case 0: 929 R128RestoreDDARegisters(pScrn, &info->ModeReg); 930 R128RestoreCrtcRegisters(pScrn, &info->ModeReg); 931 R128RestorePLLRegisters(pScrn, &info->ModeReg); 932 break; 933 case 1: 934 R128RestoreDDA2Registers(pScrn, &info->ModeReg); 935 R128RestoreCrtc2Registers(pScrn, &info->ModeReg); 936 R128RestorePLL2Registers(pScrn, &info->ModeReg); 937 break; 938 } 939 940 if (r128_crtc->cursor_offset) r128_crtc_show_cursor(crtc); 941 } 942 943 static void r128_crtc_mode_commit(xf86CrtcPtr crtc) 944 { 945 r128_crtc_dpms(crtc, DPMSModeOn); 946 } 947 948 static void r128_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, uint16_t *blue, int size) 949 { 950 R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 951 int i; 952 953 for (i = 0; i < 256; i++) { 954 r128_crtc->lut_r[i] = red[i] >> 8; 955 r128_crtc->lut_g[i] = green[i] >> 8; 956 r128_crtc->lut_b[i] = blue[i] >> 8; 957 } 958 959 r128_crtc_load_lut(crtc); 960 } 961 962 static Bool r128_crtc_lock(xf86CrtcPtr crtc) 963 { 964 ScrnInfoPtr pScrn = crtc->scrn; 965 ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 966 R128InfoPtr info = R128PTR(pScrn); 967 968 #ifdef USE_EXA 969 if (info->ExaDriver) exaWaitSync(pScreen); 970 #endif 971 972 return FALSE; 973 } 974 975 static void r128_crtc_unlock(xf86CrtcPtr crtc) 976 { 977 ScrnInfoPtr pScrn = crtc->scrn; 978 ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 979 R128InfoPtr info = R128PTR(pScrn); 980 981 #ifdef USE_EXA 982 if (info->ExaDriver) exaWaitSync(pScreen); 983 #endif 984 } 985 986 static void *r128_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) 987 { 988 ScrnInfoPtr pScrn = crtc->scrn; 989 R128InfoPtr info = R128PTR(pScrn); 990 991 R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 992 unsigned long rotate_offset = 0; 993 unsigned long rotate_pitch; 994 int cpp = pScrn->bitsPerPixel / 8; 995 int align = 4096; 996 int size; 997 998 rotate_pitch = pScrn->displayWidth * cpp; 999 size = rotate_pitch * height; 1000 rotate_offset = R128AllocateMemory(pScrn, &(r128_crtc->rotate_mem), size, align, TRUE); 1001 1002 /* If allocations failed or if there was no accel. */ 1003 if (rotate_offset == 0) 1004 return NULL; 1005 1006 return info->FB + rotate_offset; 1007 } 1008 1009 static PixmapPtr r128_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) 1010 { 1011 ScrnInfoPtr pScrn = crtc->scrn; 1012 PixmapPtr rotate_pixmap; 1013 unsigned long rotate_pitch; 1014 int cpp = pScrn->bitsPerPixel / 8; 1015 1016 if (!data) data = r128_crtc_shadow_allocate(crtc, width, height); 1017 1018 rotate_pitch = pScrn->displayWidth * cpp; 1019 rotate_pixmap = GetScratchPixmapHeader(xf86ScrnToScreen(pScrn), 1020 width, height, 1021 pScrn->depth, 1022 pScrn->bitsPerPixel, 1023 rotate_pitch, 1024 data); 1025 1026 if (rotate_pixmap == NULL) { 1027 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1028 "Couldn't allocate shadow memory for rotated CRTC\n"); 1029 return NULL; 1030 } 1031 1032 return rotate_pixmap; 1033 } 1034 1035 static void r128_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) 1036 { 1037 ScrnInfoPtr pScrn = crtc->scrn; 1038 ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 1039 R128InfoPtr info = R128PTR(pScrn); 1040 1041 R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 1042 1043 if (rotate_pixmap) FreeScratchPixmapHeader(rotate_pixmap); 1044 1045 if (data && r128_crtc->rotate_mem != NULL) { 1046 #ifdef USE_EXA 1047 if (info->ExaDriver) 1048 exaOffscreenFree(pScreen, (ExaOffscreenArea *) r128_crtc->rotate_mem); 1049 #endif 1050 r128_crtc->rotate_mem = NULL; 1051 } 1052 } 1053 1054 static const xf86CrtcFuncsRec r128_crtc_funcs = { 1055 .dpms = r128_crtc_dpms, 1056 .save = NULL, 1057 .restore = NULL, 1058 .mode_fixup = r128_crtc_mode_fixup, 1059 .prepare = r128_crtc_mode_prepare, 1060 .mode_set = r128_crtc_mode_set, 1061 .commit = r128_crtc_mode_commit, 1062 .gamma_set = r128_crtc_gamma_set, 1063 .lock = r128_crtc_lock, 1064 .unlock = r128_crtc_unlock, 1065 .shadow_create = r128_crtc_shadow_create, 1066 .shadow_allocate = r128_crtc_shadow_allocate, 1067 .shadow_destroy = r128_crtc_shadow_destroy, 1068 .set_cursor_colors = r128_crtc_set_cursor_colors, 1069 .set_cursor_position = r128_crtc_set_cursor_position, 1070 .show_cursor = r128_crtc_show_cursor, 1071 .hide_cursor = r128_crtc_hide_cursor, 1072 .load_cursor_image = r128_crtc_load_cursor_image, 1073 .destroy = NULL, 1074 }; 1075 1076 Bool R128AllocateControllers(ScrnInfoPtr pScrn) 1077 { 1078 R128EntPtr pR128Ent = R128EntPriv(pScrn); 1079 1080 if (pR128Ent->Controller[0]) 1081 return TRUE; 1082 1083 pR128Ent->pCrtc[0] = xf86CrtcCreate(pScrn, &r128_crtc_funcs); 1084 if (!pR128Ent->pCrtc[0]) 1085 return FALSE; 1086 1087 pR128Ent->Controller[0] = XNFcallocarray(1, sizeof(R128CrtcPrivateRec)); 1088 if (!pR128Ent->Controller[0]) 1089 return FALSE; 1090 1091 pR128Ent->pCrtc[0]->driver_private = pR128Ent->Controller[0]; 1092 pR128Ent->Controller[0]->crtc_id = 0; 1093 1094 if (!pR128Ent->HasCRTC2) 1095 return TRUE; 1096 1097 pR128Ent->pCrtc[1] = xf86CrtcCreate(pScrn, &r128_crtc_funcs); 1098 if (!pR128Ent->pCrtc[1]) 1099 return FALSE; 1100 1101 pR128Ent->Controller[1] = XNFcallocarray(1, sizeof(R128CrtcPrivateRec)); 1102 if (!pR128Ent->Controller[1]) { 1103 free(pR128Ent->Controller[0]); 1104 return FALSE; 1105 } 1106 1107 pR128Ent->pCrtc[1]->driver_private = pR128Ent->Controller[1]; 1108 pR128Ent->Controller[1]->crtc_id = 1; 1109 1110 return TRUE; 1111 } 1112 1113 void R128Blank(ScrnInfoPtr pScrn) 1114 { 1115 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1116 xf86OutputPtr output; 1117 xf86CrtcPtr crtc; 1118 int o, c; 1119 1120 for (c = 0; c < xf86_config->num_crtc; c++) { 1121 crtc = xf86_config->crtc[c]; 1122 for (o = 0; o < xf86_config->num_output; o++) { 1123 output = xf86_config->output[o]; 1124 if (output->crtc != crtc) 1125 continue; 1126 1127 output->funcs->dpms(output, DPMSModeOff); 1128 } 1129 crtc->funcs->dpms(crtc, DPMSModeOff); 1130 } 1131 } 1132 1133 void R128Unblank(ScrnInfoPtr pScrn) 1134 { 1135 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1136 xf86OutputPtr output; 1137 xf86CrtcPtr crtc; 1138 int o, c; 1139 1140 for (c = 0; c < xf86_config->num_crtc; c++) { 1141 crtc = xf86_config->crtc[c]; 1142 if (!crtc->enabled) 1143 continue; 1144 crtc->funcs->dpms(crtc, DPMSModeOn); 1145 for (o = 0; o < xf86_config->num_output; o++) { 1146 output = xf86_config->output[o]; 1147 if (output->crtc != crtc) 1148 continue; 1149 1150 output->funcs->dpms(output, DPMSModeOn); 1151 } 1152 } 1153 } 1154