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