r128_driver.c revision 19019ffe
1/* 2 * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, 3 * Precision Insight, Inc., Cedar Park, Texas, and 4 * VA Linux Systems Inc., Fremont, California. 5 * 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining 9 * a copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation on the rights to use, copy, modify, merge, 12 * publish, distribute, sublicense, and/or sell copies of the Software, 13 * and to permit persons to whom the Software is furnished to do so, 14 * subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the 17 * next paragraph) shall be included in all copies or substantial 18 * portions of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX 24 * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 * OTHER DEALINGS IN THE SOFTWARE. 28 */ 29 30#ifdef HAVE_CONFIG_H 31#include "config.h" 32#endif 33 34/* 35 * Authors: 36 * Rickard E. Faith <faith@valinux.com> 37 * Kevin E. Martin <martin@valinux.com> 38 * Gareth Hughes <gareth@valinux.com> 39 * 40 * Credits: 41 * 42 * Thanks to Alan Hourihane <alanh@fairlite.demon..co.uk> and SuSE for 43 * providing source code to their 3.3.x Rage 128 driver. Portions of 44 * this file are based on the initialization code for that driver. 45 * 46 * References: 47 * 48 * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical 49 * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April 50 * 1999. 51 * 52 * RAGE 128 Software Development Manual (Technical Reference Manual P/N 53 * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. 54 * 55 * This server does not yet support these XFree86 4.0 features: 56 * DDC1 & DDC2 57 * shadowfb 58 * overlay planes 59 * 60 * Modified by Marc Aurele La France <tsi@xfree86.org> for ATI driver merge. 61 * 62 * Dualhead support - Alex Deucher <agd5f@yahoo.com> 63 */ 64 65#include <string.h> 66#include <stdio.h> 67 68 /* Driver data structures */ 69#include "r128.h" 70#include "r128_probe.h" 71#include "r128_reg.h" 72#include "r128_version.h" 73 74#ifdef XF86DRI 75#define _XF86DRI_SERVER_ 76#include "r128_dri.h" 77#include "r128_common.h" 78#include "r128_sarea.h" 79#endif 80 81#include "fb.h" 82 83 /* colormap initialization */ 84#include "micmap.h" 85 86 /* X and server generic header files */ 87#include "xf86.h" 88#include "xf86_OSproc.h" 89#include "xf86PciInfo.h" 90#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 91#include "xf86RAC.h" 92#include "xf86Resources.h" 93#endif 94#include "xf86cmap.h" 95#include "xf86xv.h" 96#include "vbe.h" 97 98 /* fbdevhw & vgahw */ 99#ifdef WITH_VGAHW 100#include "vgaHW.h" 101#endif 102#include "fbdevhw.h" 103#include "dixstruct.h" 104 105 /* DPMS support. */ 106#ifdef HAVE_XEXTPROTO_71 107#include <X11/extensions/dpmsconst.h> 108#else 109#define DPMS_SERVER 110#include <X11/extensions/dpms.h> 111#endif 112 113 114#ifndef MAX 115#define MAX(a,b) ((a)>(b)?(a):(b)) 116#endif 117 118#define USE_CRT_ONLY 0 119 120 /* Forward definitions for driver functions */ 121static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen); 122static Bool R128SaveScreen(ScreenPtr pScreen, int mode); 123static void R128Save(ScrnInfoPtr pScrn); 124static void R128Restore(ScrnInfoPtr pScrn); 125static Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); 126static void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn, 127 int PowerManagementMode, int flags); 128static void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn, 129 int PowerManagementMode, int flags); 130 131typedef enum { 132 OPTION_NOACCEL, 133 OPTION_SW_CURSOR, 134 OPTION_DAC_6BIT, 135 OPTION_DAC_8BIT, 136#ifdef XF86DRI 137 OPTION_XV_DMA, 138 OPTION_IS_PCI, 139 OPTION_CCE_PIO, 140 OPTION_NO_SECURITY, 141 OPTION_USEC_TIMEOUT, 142 OPTION_AGP_MODE, 143 OPTION_AGP_SIZE, 144 OPTION_RING_SIZE, 145 OPTION_BUFFER_SIZE, 146 OPTION_PAGE_FLIP, 147#endif 148#if USE_CRT_ONLY 149 /* FIXME: Disable CRTOnly until it is tested */ 150 OPTION_CRT, 151#endif 152 OPTION_DISPLAY, 153 OPTION_PANEL_WIDTH, 154 OPTION_PANEL_HEIGHT, 155 OPTION_PROG_FP_REGS, 156 OPTION_FBDEV, 157 OPTION_VIDEO_KEY, 158 OPTION_SHOW_CACHE, 159 OPTION_VGA_ACCESS 160} R128Opts; 161 162static const OptionInfoRec R128Options[] = { 163 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 164 { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 165 { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE }, 166 { OPTION_DAC_8BIT, "Dac8Bit", OPTV_BOOLEAN, {0}, TRUE }, 167#ifdef XF86DRI 168 { OPTION_XV_DMA, "DMAForXv", OPTV_BOOLEAN, {0}, FALSE }, 169 { OPTION_IS_PCI, "ForcePCIMode", OPTV_BOOLEAN, {0}, FALSE }, 170 { OPTION_CCE_PIO, "CCEPIOMode", OPTV_BOOLEAN, {0}, FALSE }, 171 { OPTION_NO_SECURITY, "CCENoSecurity", OPTV_BOOLEAN, {0}, FALSE }, 172 { OPTION_USEC_TIMEOUT, "CCEusecTimeout", OPTV_INTEGER, {0}, FALSE }, 173 { OPTION_AGP_MODE, "AGPMode", OPTV_INTEGER, {0}, FALSE }, 174 { OPTION_AGP_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE }, 175 { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE }, 176 { OPTION_BUFFER_SIZE, "BufferSize", OPTV_INTEGER, {0}, FALSE }, 177 { OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE }, 178#endif 179 { OPTION_DISPLAY, "Display", OPTV_STRING, {0}, FALSE }, 180 { OPTION_PANEL_WIDTH, "PanelWidth", OPTV_INTEGER, {0}, FALSE }, 181 { OPTION_PANEL_HEIGHT, "PanelHeight", OPTV_INTEGER, {0}, FALSE }, 182 { OPTION_PROG_FP_REGS, "ProgramFPRegs", OPTV_BOOLEAN, {0}, FALSE }, 183 { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, 184 { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, 185 { OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, 186 { OPTION_VGA_ACCESS, "VGAAccess", OPTV_BOOLEAN, {0}, TRUE }, 187 { -1, NULL, OPTV_NONE, {0}, FALSE } 188}; 189 190const OptionInfoRec *R128OptionsWeak(void) { return R128Options; } 191 192R128RAMRec R128RAM[] = { /* Memory Specifications 193 From RAGE 128 Software Development 194 Manual (Technical Reference Manual P/N 195 SDK-G04000 Rev 0.01), page 3-21. */ 196 { 4, 4, 3, 3, 1, 3, 1, 16, 12, "128-bit SDR SGRAM 1:1" }, 197 { 4, 8, 3, 3, 1, 3, 1, 17, 13, "64-bit SDR SGRAM 1:1" }, 198 { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SGRAM 2:1" }, 199 { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SGRAM" }, 200}; 201 202extern _X_EXPORT int gR128EntityIndex; 203 204int getR128EntityIndex(void) 205{ 206 return gR128EntityIndex; 207} 208 209R128EntPtr R128EntPriv(ScrnInfoPtr pScrn) 210{ 211 DevUnion *pPriv; 212 R128InfoPtr info = R128PTR(pScrn); 213 pPriv = xf86GetEntityPrivate(info->pEnt->index, 214 getR128EntityIndex()); 215 return pPriv->ptr; 216} 217 218/* Allocate our private R128InfoRec. */ 219static Bool R128GetRec(ScrnInfoPtr pScrn) 220{ 221 if (pScrn->driverPrivate) return TRUE; 222 223 pScrn->driverPrivate = xnfcalloc(sizeof(R128InfoRec), 1); 224 return TRUE; 225} 226 227/* Free our private R128InfoRec. */ 228static void R128FreeRec(ScrnInfoPtr pScrn) 229{ 230 if (!pScrn || !pScrn->driverPrivate) return; 231 xfree(pScrn->driverPrivate); 232 pScrn->driverPrivate = NULL; 233} 234 235/* Memory map the MMIO region. Used during pre-init and by R128MapMem, 236 below. */ 237static Bool R128MapMMIO(ScrnInfoPtr pScrn) 238{ 239 R128InfoPtr info = R128PTR(pScrn); 240 241 if (info->FBDev) { 242 info->MMIO = fbdevHWMapMMIO(pScrn); 243 } else { 244 /* If the primary screen has already mapped the MMIO region, 245 use its pointer instead of mapping it a second time. */ 246 if (info->IsSecondary) { 247 DevUnion* pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 248 getR128EntityIndex()); 249 R128EntPtr pR128Ent = pPriv->ptr; 250 R128InfoPtr info0 = R128PTR(pR128Ent->pPrimaryScrn); 251 info->MMIO=info0->MMIO; 252 if (info->MMIO) return TRUE; 253 } 254#ifndef XSERVER_LIBPCIACCESS 255 info->MMIO = xf86MapPciMem(pScrn->scrnIndex, 256 VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, 257 info->PciTag, 258 info->MMIOAddr, 259 R128_MMIOSIZE); 260#else 261 int err = pci_device_map_range(info->PciInfo, 262 info->MMIOAddr, 263 R128_MMIOSIZE, 264 PCI_DEV_MAP_FLAG_WRITABLE, 265 &info->MMIO); 266 267 if (err) { 268 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 269 "Unable to map MMIO aperture. %s (%d)\n", 270 strerror (err), err); 271 return FALSE; 272 } 273#endif 274 } 275 276 if (!info->MMIO) return FALSE; 277 return TRUE; 278} 279 280/* Unmap the MMIO region. Used during pre-init and by R128UnmapMem, 281 below. */ 282static Bool R128UnmapMMIO(ScrnInfoPtr pScrn) 283{ 284 R128InfoPtr info = R128PTR(pScrn); 285 286 if (info->FBDev) 287 fbdevHWUnmapMMIO(pScrn); 288 else { 289#ifndef XSERVER_LIBPCIACCESS 290 xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, R128_MMIOSIZE); 291#else 292 pci_device_unmap_range(info->PciInfo, info->MMIO, R128_MMIOSIZE); 293#endif 294 } 295 info->MMIO = NULL; 296 return TRUE; 297} 298 299/* Memory map the frame buffer. Used by R128MapMem, below. */ 300static Bool R128MapFB(ScrnInfoPtr pScrn) 301{ 302 R128InfoPtr info = R128PTR(pScrn); 303 304 if (info->FBDev) { 305 info->FB = fbdevHWMapVidmem(pScrn); 306 } else { 307#ifndef XSERVER_LIBPCIACCESS 308 info->FB = xf86MapPciMem(pScrn->scrnIndex, 309 VIDMEM_FRAMEBUFFER, 310 info->PciTag, 311 info->LinearAddr, 312 info->FbMapSize); 313#else 314 int err = pci_device_map_range(info->PciInfo, 315 info->LinearAddr, 316 info->FbMapSize, 317 PCI_DEV_MAP_FLAG_WRITABLE | 318 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 319 &info->FB); 320 321 if (err) { 322 xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 323 "Unable to map FB aperture. %s (%d)\n", 324 strerror (err), err); 325 return FALSE; 326 } 327#endif 328 } 329 330 if (!info->FB) return FALSE; 331 return TRUE; 332} 333 334/* Unmap the frame buffer. Used by R128UnmapMem, below. */ 335static Bool R128UnmapFB(ScrnInfoPtr pScrn) 336{ 337 R128InfoPtr info = R128PTR(pScrn); 338 339 if (info->FBDev) 340 fbdevHWUnmapVidmem(pScrn); 341 else 342#ifndef XSERVER_LIBPCIACCESS 343 xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize); 344#else 345 pci_device_unmap_range(info->PciInfo, info->FB, info->FbMapSize); 346#endif 347 info->FB = NULL; 348 return TRUE; 349} 350 351/* Memory map the MMIO region and the frame buffer. */ 352static Bool R128MapMem(ScrnInfoPtr pScrn) 353{ 354 if (!R128MapMMIO(pScrn)) return FALSE; 355 if (!R128MapFB(pScrn)) { 356 R128UnmapMMIO(pScrn); 357 return FALSE; 358 } 359 return TRUE; 360} 361 362/* Unmap the MMIO region and the frame buffer. */ 363static Bool R128UnmapMem(ScrnInfoPtr pScrn) 364{ 365 if (!R128UnmapMMIO(pScrn) || !R128UnmapFB(pScrn)) return FALSE; 366 return TRUE; 367} 368 369/* Read PLL information */ 370unsigned R128INPLL(ScrnInfoPtr pScrn, int addr) 371{ 372 R128InfoPtr info = R128PTR(pScrn); 373 unsigned char *R128MMIO = info->MMIO; 374 375 OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x3f); 376 return INREG(R128_CLOCK_CNTL_DATA); 377} 378 379#if 0 380/* Read PAL information (only used for debugging). */ 381static int R128INPAL(int idx) 382{ 383 R128InfoPtr info = R128PTR(pScrn); 384 unsigned char *R128MMIO = info->MMIO; 385 386 OUTREG(R128_PALETTE_INDEX, idx << 16); 387 return INREG(R128_PALETTE_DATA); 388} 389#endif 390 391/* Wait for vertical sync. */ 392void R128WaitForVerticalSync(ScrnInfoPtr pScrn) 393{ 394 R128InfoPtr info = R128PTR(pScrn); 395 unsigned char *R128MMIO = info->MMIO; 396 int i; 397 398 OUTREG(R128_GEN_INT_STATUS, R128_VSYNC_INT_AK); 399 for (i = 0; i < R128_TIMEOUT; i++) { 400 if (INREG(R128_GEN_INT_STATUS) & R128_VSYNC_INT) break; 401 } 402} 403 404/* Blank screen. */ 405static void R128Blank(ScrnInfoPtr pScrn) 406{ 407 R128InfoPtr info = R128PTR(pScrn); 408 unsigned char *R128MMIO = info->MMIO; 409 410 if(!info->IsSecondary) 411 { 412 switch(info->DisplayType) 413 { 414 case MT_LCD: 415 OUTREGP(R128_LVDS_GEN_CNTL, R128_LVDS_DISPLAY_DIS, 416 ~R128_LVDS_DISPLAY_DIS); 417 break; 418 case MT_CRT: 419 OUTREGP(R128_CRTC_EXT_CNTL, R128_CRTC_DISPLAY_DIS, ~R128_CRTC_DISPLAY_DIS); 420 break; 421 case MT_DFP: 422 OUTREGP(R128_FP_GEN_CNTL, R128_FP_BLANK_DIS, ~R128_FP_BLANK_DIS); 423 break; 424 case MT_NONE: 425 default: 426 break; 427 } 428 } 429 else 430 { 431 OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~R128_CRTC2_DISP_DIS); 432 } 433} 434 435/* Unblank screen. */ 436static void R128Unblank(ScrnInfoPtr pScrn) 437{ 438 R128InfoPtr info = R128PTR(pScrn); 439 unsigned char *R128MMIO = info->MMIO; 440 441 if(!info->IsSecondary) 442 { 443 switch(info->DisplayType) 444 { 445 case MT_LCD: 446 OUTREGP(R128_LVDS_GEN_CNTL, 0, 447 ~R128_LVDS_DISPLAY_DIS); 448 break; 449 case MT_CRT: 450 OUTREGP(R128_CRTC_EXT_CNTL, 0, ~R128_CRTC_DISPLAY_DIS); 451 break; 452 case MT_DFP: 453 OUTREGP(R128_FP_GEN_CNTL, 0, ~R128_FP_BLANK_DIS); 454 break; 455 case MT_NONE: 456 default: 457 break; 458 } 459 } 460 else 461 { 462 switch(info->DisplayType) 463 { 464 case MT_LCD: 465 case MT_DFP: 466 case MT_CRT: 467 OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_DISP_DIS); 468 break; 469 case MT_NONE: 470 default: 471 break; 472 } 473 } 474} 475 476/* Compute log base 2 of val. */ 477int R128MinBits(int val) 478{ 479 int bits; 480 481 if (!val) return 1; 482 for (bits = 0; val; val >>= 1, ++bits); 483 return bits; 484} 485 486/* Compute n/d with rounding. */ 487static int R128Div(int n, int d) 488{ 489 return (n + (d / 2)) / d; 490} 491 492/* Read the Video BIOS block and the FP registers (if applicable). */ 493static Bool R128GetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) 494{ 495 R128InfoPtr info = R128PTR(pScrn); 496 int i; 497 int FPHeader = 0; 498 499#define R128_BIOS8(v) (info->VBIOS[v]) 500#define R128_BIOS16(v) (info->VBIOS[v] | \ 501 (info->VBIOS[(v) + 1] << 8)) 502#define R128_BIOS32(v) (info->VBIOS[v] | \ 503 (info->VBIOS[(v) + 1] << 8) | \ 504 (info->VBIOS[(v) + 2] << 16) | \ 505 (info->VBIOS[(v) + 3] << 24)) 506 507#ifdef XSERVER_LIBPCIACCESS 508 int size = info->PciInfo->rom_size > R128_VBIOS_SIZE ? info->PciInfo->rom_size : R128_VBIOS_SIZE; 509 info->VBIOS = xalloc(size); 510#else 511 info->VBIOS = xalloc(R128_VBIOS_SIZE); 512#endif 513 514 if (!info->VBIOS) { 515 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 516 "Cannot allocate space for hold Video BIOS!\n"); 517 return FALSE; 518 } 519 520 if (pInt10) { 521 info->BIOSAddr = pInt10->BIOSseg << 4; 522 (void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr), 523 R128_VBIOS_SIZE); 524 } else { 525#ifdef XSERVER_LIBPCIACCESS 526 if (pci_device_read_rom(info->PciInfo, info->VBIOS)) { 527 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 528 "Failed to read PCI ROM!\n"); 529 } 530#else 531 xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, R128_VBIOS_SIZE); 532 if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { 533 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 534 "Video BIOS not detected in PCI space!\n"); 535 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 536 "Attempting to read Video BIOS from legacy ISA space!\n"); 537 info->BIOSAddr = 0x000c0000; 538 xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, R128_VBIOS_SIZE, info->VBIOS); 539 } 540#endif 541 } 542 if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { 543 info->BIOSAddr = 0x00000000; 544 xfree(info->VBIOS); 545 info->VBIOS = NULL; 546 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 547 "Video BIOS not found!\n"); 548 } 549 550 if(info->HasCRTC2) 551 { 552 if(info->IsSecondary) 553 { 554 /* there may be a way to detect this, for now, just assume 555 second head is CRT */ 556 info->DisplayType = MT_CRT; 557 558 if(info->DisplayType > MT_NONE) 559 { 560 DevUnion* pPriv; 561 R128EntPtr pR128Ent; 562 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 563 getR128EntityIndex()); 564 pR128Ent = pPriv->ptr; 565 pR128Ent->HasSecondary = TRUE; 566 567 } 568 else return FALSE; 569 570 } 571 else 572 { 573 /* really need some sort of detection here */ 574 if (info->HasPanelRegs) { 575 info->DisplayType = MT_LCD; 576 } else if (info->isDFP) { 577 info->DisplayType = MT_DFP; 578 } else 579 { 580 /*DVI port has no monitor connected, try CRT port. 581 If something on CRT port, treat it as primary*/ 582 if(xf86IsEntityShared(pScrn->entityList[0])) 583 { 584 DevUnion* pPriv; 585 R128EntPtr pR128Ent; 586 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 587 getR128EntityIndex()); 588 pR128Ent = pPriv->ptr; 589 pR128Ent->BypassSecondary = TRUE; 590 } 591 592 info->DisplayType = MT_CRT; 593#if 0 594 { 595 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 596 "No monitor detected!!!\n"); 597 return FALSE; 598 } 599#endif 600 } 601 } 602 } 603 else 604 { 605 /*Regular Radeon ASIC, only one CRTC, but it could be 606 used for DFP with a DVI output, like AIW board*/ 607 if(info->isDFP) info->DisplayType = MT_DFP; 608 else info->DisplayType = MT_CRT; 609 } 610 611 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Display == Type %d\n", 612 (info->IsSecondary ? "Secondary" : "Primary"), 613 info->DisplayType); 614 615 616 if (info->VBIOS && info->DisplayType == MT_LCD) { 617 info->FPBIOSstart = 0; 618 619 /* FIXME: There should be direct access to the start of the FP info 620 tables, but until we find out where that offset is stored, we 621 must search for the ATI signature string: "M3 ". */ 622 for (i = 4; i < R128_VBIOS_SIZE-8; i++) { 623 if (R128_BIOS8(i) == 'M' && 624 R128_BIOS8(i+1) == '3' && 625 R128_BIOS8(i+2) == ' ' && 626 R128_BIOS8(i+3) == ' ' && 627 R128_BIOS8(i+4) == ' ' && 628 R128_BIOS8(i+5) == ' ' && 629 R128_BIOS8(i+6) == ' ' && 630 R128_BIOS8(i+7) == ' ') { 631 FPHeader = i-2; 632 break; 633 } 634 } 635 636 if (!FPHeader) return TRUE; 637 638 /* Assume that only one panel is attached and supported */ 639 for (i = FPHeader+20; i < FPHeader+84; i += 2) { 640 if (R128_BIOS16(i) != 0) { 641 info->FPBIOSstart = R128_BIOS16(i); 642 break; 643 } 644 } 645 if (!info->FPBIOSstart) return TRUE; 646 647 if (!info->PanelXRes) 648 info->PanelXRes = R128_BIOS16(info->FPBIOSstart+25); 649 if (!info->PanelYRes) 650 info->PanelYRes = R128_BIOS16(info->FPBIOSstart+27); 651 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel size: %dx%d\n", 652 info->PanelXRes, info->PanelYRes); 653 654 info->PanelPwrDly = R128_BIOS8(info->FPBIOSstart+56); 655 656 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel ID: "); 657 for (i = 1; i <= 24; i++) 658 ErrorF("%c", R128_BIOS8(info->FPBIOSstart+i)); 659 ErrorF("\n"); 660 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Type: "); 661 i = R128_BIOS16(info->FPBIOSstart+29); 662 if (i & 1) ErrorF("Color, "); 663 else ErrorF("Monochrome, "); 664 if (i & 2) ErrorF("Dual(split), "); 665 else ErrorF("Single, "); 666 switch ((i >> 2) & 0x3f) { 667 case 0: ErrorF("STN"); break; 668 case 1: ErrorF("TFT"); break; 669 case 2: ErrorF("Active STN"); break; 670 case 3: ErrorF("EL"); break; 671 case 4: ErrorF("Plasma"); break; 672 default: ErrorF("UNKNOWN"); break; 673 } 674 ErrorF("\n"); 675 if (R128_BIOS8(info->FPBIOSstart+61) & 1) { 676 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Interface: LVDS\n"); 677 } else { 678 /* FIXME: Add Non-LVDS flat pael support */ 679 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 680 "Non-LVDS panel interface detected! " 681 "This support is untested and may not " 682 "function properly\n"); 683 } 684 } 685 686 if (!info->PanelXRes || !info->PanelYRes) { 687 info->HasPanelRegs = FALSE; 688 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 689 "Can't determine panel dimensions, and none specified.\n" 690 "\tDisabling programming of FP registers.\n"); 691 } 692 693 return TRUE; 694} 695 696/* Read PLL parameters from BIOS block. Default to typical values if there 697 is no BIOS. */ 698static Bool R128GetPLLParameters(ScrnInfoPtr pScrn) 699{ 700 R128InfoPtr info = R128PTR(pScrn); 701 R128PLLPtr pll = &info->pll; 702 703#if defined(__powerpc__) || defined(__alpha__) 704 /* there is no bios under Linux PowerPC but Open Firmware 705 does set up the PLL registers properly and we can use 706 those to calculate xclk and find the reference divider */ 707 708 unsigned x_mpll_ref_fb_div; 709 unsigned xclk_cntl; 710 unsigned Nx, M; 711 unsigned PostDivSet[] = {0, 1, 2, 4, 8, 3, 6, 12}; 712 713 /* Assume REF clock is 2950 (in units of 10khz) */ 714 /* and that all pllclk must be between 125 Mhz and 250Mhz */ 715 pll->reference_freq = 2950; 716 pll->min_pll_freq = 12500; 717 pll->max_pll_freq = 25000; 718 719 /* need to memory map the io to use INPLL since it 720 has not been done yet at this point in the startup */ 721 R128MapMMIO(pScrn); 722 x_mpll_ref_fb_div = INPLL(pScrn, R128_X_MPLL_REF_FB_DIV); 723 xclk_cntl = INPLL(pScrn, R128_XCLK_CNTL) & 0x7; 724 pll->reference_div = 725 INPLL(pScrn,R128_PPLL_REF_DIV) & R128_PPLL_REF_DIV_MASK; 726 /* unmap it again */ 727 R128UnmapMMIO(pScrn); 728 729 Nx = (x_mpll_ref_fb_div & 0x00FF00) >> 8; 730 M = (x_mpll_ref_fb_div & 0x0000FF); 731 732 pll->xclk = R128Div((2 * Nx * pll->reference_freq), 733 (M * PostDivSet[xclk_cntl])); 734 735#else /* !defined(__powerpc__) */ 736 737 if (!info->VBIOS) { 738 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 739 "Video BIOS not detected, using default PLL parameters!\n"); 740 /* These probably aren't going to work for 741 the card you are using. Specifically, 742 reference freq can be 29.50MHz, 743 28.63MHz, or 14.32MHz. YMMV. */ 744 pll->reference_freq = 2950; 745 pll->reference_div = 65; 746 pll->min_pll_freq = 12500; 747 pll->max_pll_freq = 25000; 748 pll->xclk = 10300; 749 } else { 750 CARD16 bios_header = R128_BIOS16(0x48); 751 CARD16 pll_info_block = R128_BIOS16(bios_header + 0x30); 752 R128TRACE(("Header at 0x%04x; PLL Information at 0x%04x\n", 753 bios_header, pll_info_block)); 754 755 pll->reference_freq = R128_BIOS16(pll_info_block + 0x0e); 756 pll->reference_div = R128_BIOS16(pll_info_block + 0x10); 757 pll->min_pll_freq = R128_BIOS32(pll_info_block + 0x12); 758 pll->max_pll_freq = R128_BIOS32(pll_info_block + 0x16); 759 pll->xclk = R128_BIOS16(pll_info_block + 0x08); 760 } 761#endif /* __powerpc__ */ 762 763 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 764 "PLL parameters: rf=%d rd=%d min=%d max=%d; xclk=%d\n", 765 pll->reference_freq, 766 pll->reference_div, 767 pll->min_pll_freq, 768 pll->max_pll_freq, 769 pll->xclk); 770 771 return TRUE; 772} 773 774/* This is called by R128PreInit to set up the default visual. */ 775static Bool R128PreInitVisual(ScrnInfoPtr pScrn) 776{ 777 R128InfoPtr info = R128PTR(pScrn); 778 779 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, (Support24bppFb 780 | Support32bppFb 781 | SupportConvert32to24 782 ))) 783 return FALSE; 784 785 switch (pScrn->depth) { 786 case 8: 787 case 15: 788 case 16: 789 case 24: 790 break; 791 default: 792 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 793 "Given depth (%d) is not supported by %s driver\n", 794 pScrn->depth, R128_DRIVER_NAME); 795 return FALSE; 796 } 797 798 xf86PrintDepthBpp(pScrn); 799 800 info->fifo_slots = 0; 801 info->pix24bpp = xf86GetBppFromDepth(pScrn, pScrn->depth); 802 info->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; 803 info->CurrentLayout.depth = pScrn->depth; 804 info->CurrentLayout.pixel_bytes = pScrn->bitsPerPixel / 8; 805 info->CurrentLayout.pixel_code = (pScrn->bitsPerPixel != 16 806 ? pScrn->bitsPerPixel 807 : pScrn->depth); 808 809 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 810 "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n", 811 pScrn->depth, 812 info->CurrentLayout.pixel_bytes, 813 info->CurrentLayout.pixel_bytes > 1 ? "s" : "", 814 info->pix24bpp); 815 816 817 if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE; 818 819 if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 820 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 821 "Default visual (%s) is not supported at depth %d\n", 822 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 823 return FALSE; 824 } 825 return TRUE; 826 827} 828 829/* This is called by R128PreInit to handle all color weight issues. */ 830static Bool R128PreInitWeight(ScrnInfoPtr pScrn) 831{ 832 R128InfoPtr info = R128PTR(pScrn); 833 834 /* Save flag for 6 bit DAC to use for 835 setting CRTC registers. Otherwise use 836 an 8 bit DAC, even if xf86SetWeight sets 837 pScrn->rgbBits to some value other than 838 8. */ 839 info->dac6bits = FALSE; 840 if (pScrn->depth > 8) { 841 rgb defaultWeight = { 0, 0, 0 }; 842 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE; 843 } else { 844 pScrn->rgbBits = 8; 845 if (xf86ReturnOptValBool(info->Options, OPTION_DAC_6BIT, FALSE)) { 846 pScrn->rgbBits = 6; 847 info->dac6bits = TRUE; 848 } 849 } 850 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 851 "Using %d bits per RGB (%d bit DAC)\n", 852 pScrn->rgbBits, info->dac6bits ? 6 : 8); 853 854 return TRUE; 855 856} 857 858/* This is called by R128PreInit to handle config file overrides for things 859 like chipset and memory regions. Also determine memory size and type. 860 If memory type ever needs an override, put it in this routine. */ 861static Bool R128PreInitConfig(ScrnInfoPtr pScrn) 862{ 863 R128InfoPtr info = R128PTR(pScrn); 864 unsigned char *R128MMIO = info->MMIO; 865 EntityInfoPtr pEnt = info->pEnt; 866 GDevPtr dev = pEnt->device; 867 int offset = 0; /* RAM Type */ 868 MessageType from; 869 870 /* Chipset */ 871 from = X_PROBED; 872 if (dev->chipset && *dev->chipset) { 873 info->Chipset = xf86StringToToken(R128Chipsets, dev->chipset); 874 from = X_CONFIG; 875 } else if (dev->chipID >= 0) { 876 info->Chipset = dev->chipID; 877 from = X_CONFIG; 878 } else { 879 info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo); 880 } 881 pScrn->chipset = (char *)xf86TokenToString(R128Chipsets, info->Chipset); 882 883 if (!pScrn->chipset) { 884 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 885 "ChipID 0x%04x is not recognized\n", info->Chipset); 886 return FALSE; 887 } 888 889 if (info->Chipset < 0) { 890 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 891 "Chipset \"%s\" is not recognized\n", pScrn->chipset); 892 return FALSE; 893 } 894 895 xf86DrvMsg(pScrn->scrnIndex, from, 896 "Chipset: \"%s\" (ChipID = 0x%04x)\n", 897 pScrn->chipset, 898 info->Chipset); 899 900 /* Framebuffer */ 901 902 from = X_PROBED; 903 info->LinearAddr = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & 0xfc000000; 904 pScrn->memPhysBase = info->LinearAddr; 905 if (dev->MemBase) { 906 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 907 "Linear address override, using 0x%08lx instead of 0x%08lx\n", 908 dev->MemBase, 909 info->LinearAddr); 910 info->LinearAddr = dev->MemBase; 911 from = X_CONFIG; 912 } else if (!info->LinearAddr) { 913 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 914 "No valid linear framebuffer address\n"); 915 return FALSE; 916 } 917 xf86DrvMsg(pScrn->scrnIndex, from, 918 "Linear framebuffer at 0x%08lx\n", info->LinearAddr); 919 920 /* MMIO registers */ 921 from = X_PROBED; 922 info->MMIOAddr = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & 0xffffff00; 923 if (dev->IOBase) { 924 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 925 "MMIO address override, using 0x%08lx instead of 0x%08lx\n", 926 dev->IOBase, 927 info->MMIOAddr); 928 info->MMIOAddr = dev->IOBase; 929 from = X_CONFIG; 930 } else if (!info->MMIOAddr) { 931 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n"); 932 return FALSE; 933 } 934 xf86DrvMsg(pScrn->scrnIndex, from, 935 "MMIO registers at 0x%08lx\n", info->MMIOAddr); 936 937#ifndef XSERVER_LIBPCIACCESS 938 /* BIOS */ 939 from = X_PROBED; 940 info->BIOSAddr = info->PciInfo->biosBase & 0xfffe0000; 941 if (dev->BiosBase) { 942 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 943 "BIOS address override, using 0x%08lx instead of 0x%08lx\n", 944 dev->BiosBase, 945 info->BIOSAddr); 946 info->BIOSAddr = dev->BiosBase; 947 from = X_CONFIG; 948 } 949 if (info->BIOSAddr) { 950 xf86DrvMsg(pScrn->scrnIndex, from, 951 "BIOS at 0x%08lx\n", info->BIOSAddr); 952 } 953#endif 954 955 /* Flat panel (part 1) */ 956 if (xf86GetOptValBool(info->Options, OPTION_PROG_FP_REGS, 957 &info->HasPanelRegs)) { 958 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 959 "Turned flat panel register programming %s\n", 960 info->HasPanelRegs ? "on" : "off"); 961 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 962 "\n\nWARNING: Forcing the driver to use/not use the flat panel registers\nmight damage your flat panel. Use at your *OWN* *RISK*.\n\n"); 963 } else { 964 info->isDFP = FALSE; 965 info->isPro2 = FALSE; 966 info->HasCRTC2 = FALSE; 967 switch (info->Chipset) { 968 /* R128 Pro and Pro2 can have DFP, we will deal with it. 969 No support for dual-head/xinerama yet. 970 M3 can also have DFP, no support for now */ 971 case PCI_CHIP_RAGE128TF: 972 case PCI_CHIP_RAGE128TL: 973 case PCI_CHIP_RAGE128TR: 974 /* FIXME: RAGE128 TS/TT/TU are assumed to be PRO2 as all 6 chips came 975 * out at the same time, so are of the same family likely. 976 * This requires confirmation however to be fully correct. 977 * Mike A. Harris <mharris@redhat.com> 978 */ 979 case PCI_CHIP_RAGE128TS: 980 case PCI_CHIP_RAGE128TT: 981 case PCI_CHIP_RAGE128TU: info->isPro2 = TRUE; 982 /* FIXME: RAGE128 P[ABCEGHIJKLMNOQSTUVWX] are assumed to have DFP 983 * capability, as the comment at the top suggests. 984 * This requires confirmation however to be fully correct. 985 * Mike A. Harris <mharris@redhat.com> 986 */ 987 case PCI_CHIP_RAGE128PA: 988 case PCI_CHIP_RAGE128PB: 989 case PCI_CHIP_RAGE128PC: 990 case PCI_CHIP_RAGE128PE: 991 case PCI_CHIP_RAGE128PG: 992 case PCI_CHIP_RAGE128PH: 993 case PCI_CHIP_RAGE128PI: 994 case PCI_CHIP_RAGE128PJ: 995 case PCI_CHIP_RAGE128PK: 996 case PCI_CHIP_RAGE128PL: 997 case PCI_CHIP_RAGE128PM: 998 case PCI_CHIP_RAGE128PN: 999 case PCI_CHIP_RAGE128PO: 1000 case PCI_CHIP_RAGE128PQ: 1001 case PCI_CHIP_RAGE128PS: 1002 case PCI_CHIP_RAGE128PT: 1003 case PCI_CHIP_RAGE128PU: 1004 case PCI_CHIP_RAGE128PV: 1005 case PCI_CHIP_RAGE128PW: 1006 case PCI_CHIP_RAGE128PX: 1007 1008 case PCI_CHIP_RAGE128PD: 1009 case PCI_CHIP_RAGE128PF: 1010 case PCI_CHIP_RAGE128PP: 1011 case PCI_CHIP_RAGE128PR: info->isDFP = TRUE; break; 1012 1013 case PCI_CHIP_RAGE128LE: 1014 case PCI_CHIP_RAGE128LF: 1015 case PCI_CHIP_RAGE128MF: 1016 case PCI_CHIP_RAGE128ML: 1017 info->HasPanelRegs = TRUE; 1018 /* which chips support dualhead? */ 1019 info->HasCRTC2 = TRUE; 1020 break; 1021 case PCI_CHIP_RAGE128RE: 1022 case PCI_CHIP_RAGE128RF: 1023 case PCI_CHIP_RAGE128RG: 1024 case PCI_CHIP_RAGE128RK: 1025 case PCI_CHIP_RAGE128RL: 1026 case PCI_CHIP_RAGE128SM: 1027 /* FIXME: RAGE128 S[EFGHKLN] are assumed to be like the SM above as 1028 * all of them are listed as "Rage 128 4x" in ATI docs. 1029 * This requires confirmation however to be fully correct. 1030 * Mike A. Harris <mharris@redhat.com> 1031 */ 1032 case PCI_CHIP_RAGE128SE: 1033 case PCI_CHIP_RAGE128SF: 1034 case PCI_CHIP_RAGE128SG: 1035 case PCI_CHIP_RAGE128SH: 1036 case PCI_CHIP_RAGE128SK: 1037 case PCI_CHIP_RAGE128SL: 1038 case PCI_CHIP_RAGE128SN: 1039 default: info->HasPanelRegs = FALSE; break; 1040 } 1041 } 1042 1043 /* Read registers used to determine options */ 1044 from = X_PROBED; 1045 R128MapMMIO(pScrn); 1046 R128MMIO = info->MMIO; 1047 1048 if (info->FBDev) 1049 pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024; 1050 else 1051 pScrn->videoRam = INREG(R128_CONFIG_MEMSIZE) / 1024; 1052 1053 info->MemCntl = INREG(R128_MEM_CNTL); 1054 info->BusCntl = INREG(R128_BUS_CNTL); 1055 1056 /* On non-flat panel systems, the default is to display to the CRT, 1057 and on flat panel systems, the default is to display to the flat 1058 panel unless the user explicity chooses otherwise using the "Display" 1059 config file setting. BIOS_5_SCRATCH holds the display device on flat 1060 panel systems only. */ 1061 if (info->HasPanelRegs) { 1062 char *Display = xf86GetOptValString(info->Options, OPTION_DISPLAY); 1063 1064 if (info->FBDev) 1065 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1066 "Option \"Display\" ignored " 1067 "(framebuffer device determines display type)\n"); 1068 else if (info->IsPrimary || info->IsSecondary) 1069 info->BIOSDisplay = R128_DUALHEAD; 1070 else if (!Display || !xf86NameCmp(Display, "FP")) 1071 info->BIOSDisplay = R128_BIOS_DISPLAY_FP; 1072 else if (!xf86NameCmp(Display, "BIOS")) 1073 info->BIOSDisplay = INREG8(R128_BIOS_5_SCRATCH); 1074 else if (!xf86NameCmp(Display, "Mirror")) 1075 info->BIOSDisplay = R128_BIOS_DISPLAY_FP_CRT; 1076 else if (!xf86NameCmp(Display, "CRT")) 1077 info->BIOSDisplay = R128_BIOS_DISPLAY_CRT; 1078 else { 1079 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1080 "Unsupported type \"%s\" specified for Option \"Display\".\n" 1081 "\tSupported types are: " 1082 "\"BIOS\", \"Mirror\", \"CRT\" and \"FP\"\n", Display); 1083 return FALSE; 1084 } 1085 } else { 1086 info->BIOSDisplay = R128_BIOS_DISPLAY_CRT; 1087 } 1088 1089 R128MMIO = NULL; 1090 R128UnmapMMIO(pScrn); 1091 1092 /* RAM */ 1093 switch (info->MemCntl & 0x3) { 1094 case 0: /* SDR SGRAM 1:1 */ 1095 switch (info->Chipset) { 1096 case PCI_CHIP_RAGE128TF: 1097 case PCI_CHIP_RAGE128TL: 1098 case PCI_CHIP_RAGE128TR: 1099 case PCI_CHIP_RAGE128LE: 1100 case PCI_CHIP_RAGE128LF: 1101 case PCI_CHIP_RAGE128MF: 1102 case PCI_CHIP_RAGE128ML: 1103 case PCI_CHIP_RAGE128RE: 1104 case PCI_CHIP_RAGE128RF: 1105 case PCI_CHIP_RAGE128RG: offset = 0; break; /* 128-bit SDR SGRAM 1:1 */ 1106 case PCI_CHIP_RAGE128RK: 1107 case PCI_CHIP_RAGE128RL: 1108 case PCI_CHIP_RAGE128SM: 1109 default: offset = 1; break; /* 64-bit SDR SGRAM 1:1 */ 1110 } 1111 break; 1112 case 1: offset = 2; break; /* 64-bit SDR SGRAM 2:1 */ 1113 case 2: offset = 3; break; /* 64-bit DDR SGRAM */ 1114 default: offset = 1; break; /* 64-bit SDR SGRAM 1:1 */ 1115 } 1116 info->ram = &R128RAM[offset]; 1117 1118 if (dev->videoRam) { 1119 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1120 "Video RAM override, using %d kB instead of %d kB\n", 1121 dev->videoRam, 1122 pScrn->videoRam); 1123 from = X_CONFIG; 1124 pScrn->videoRam = dev->videoRam; 1125 } 1126 1127 xf86DrvMsg(pScrn->scrnIndex, from, 1128 "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name); 1129 1130 if (info->IsPrimary) { 1131 pScrn->videoRam /= 2; 1132 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1133 "Using %dk of videoram for primary head\n", 1134 pScrn->videoRam); 1135 } 1136 1137 if (info->IsSecondary) { 1138 pScrn->videoRam /= 2; 1139 info->LinearAddr += pScrn->videoRam * 1024; 1140 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1141 "Using %dk of videoram for secondary head\n", 1142 pScrn->videoRam); 1143 } 1144 1145 pScrn->videoRam &= ~1023; 1146 info->FbMapSize = pScrn->videoRam * 1024; 1147 1148 1149 /* Flat panel (part 2) */ 1150 switch (info->BIOSDisplay) { 1151 case R128_DUALHEAD: 1152 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1153 "Dual display\n"); 1154 break; 1155 case R128_BIOS_DISPLAY_FP: 1156 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1157 "Using flat panel for display\n"); 1158 break; 1159 case R128_BIOS_DISPLAY_CRT: 1160 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1161 "Using external CRT for display\n"); 1162 break; 1163 case R128_BIOS_DISPLAY_FP_CRT: 1164 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1165 "Using both flat panel and external CRT " 1166 "for display\n"); 1167 break; 1168 } 1169 1170 if (info->HasPanelRegs) { 1171 /* Panel width/height overrides */ 1172 info->PanelXRes = 0; 1173 info->PanelYRes = 0; 1174 if (xf86GetOptValInteger(info->Options, 1175 OPTION_PANEL_WIDTH, &(info->PanelXRes))) { 1176 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1177 "Flat panel width: %d\n", info->PanelXRes); 1178 } 1179 if (xf86GetOptValInteger(info->Options, 1180 OPTION_PANEL_HEIGHT, &(info->PanelYRes))) { 1181 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1182 "Flat panel height: %d\n", info->PanelYRes); 1183 } 1184 } 1185 1186#ifdef XF86DRI 1187 /* DMA for Xv */ 1188 info->DMAForXv = xf86ReturnOptValBool(info->Options, OPTION_XV_DMA, FALSE); 1189 if (info->DMAForXv) { 1190 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1191 "Will try to use DMA for Xv image transfers\n"); 1192 } 1193 1194 /* AGP/PCI */ 1195 if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) { 1196 info->IsPCI = TRUE; 1197 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI-only mode\n"); 1198 } else { 1199 switch (info->Chipset) { 1200 case PCI_CHIP_RAGE128LE: 1201 case PCI_CHIP_RAGE128RE: 1202 case PCI_CHIP_RAGE128RK: 1203 case PCI_CHIP_RAGE128PD: 1204 case PCI_CHIP_RAGE128PR: 1205 case PCI_CHIP_RAGE128PP: info->IsPCI = TRUE; break; 1206 case PCI_CHIP_RAGE128LF: 1207 case PCI_CHIP_RAGE128MF: 1208 case PCI_CHIP_RAGE128ML: 1209 case PCI_CHIP_RAGE128PF: 1210 case PCI_CHIP_RAGE128RF: 1211 case PCI_CHIP_RAGE128RG: 1212 case PCI_CHIP_RAGE128RL: 1213 case PCI_CHIP_RAGE128SM: 1214 case PCI_CHIP_RAGE128TF: 1215 case PCI_CHIP_RAGE128TL: 1216 case PCI_CHIP_RAGE128TR: 1217 /* FIXME: Rage 128 S[EFGHKLN], T[STU], P[ABCEGHIJKLMNOQSTUVWX] are 1218 * believed to be AGP, but need confirmation. <mharris@redhat.com> 1219 */ 1220 case PCI_CHIP_RAGE128PA: 1221 case PCI_CHIP_RAGE128PB: 1222 case PCI_CHIP_RAGE128PC: 1223 case PCI_CHIP_RAGE128PE: 1224 case PCI_CHIP_RAGE128PG: 1225 case PCI_CHIP_RAGE128PH: 1226 case PCI_CHIP_RAGE128PI: 1227 case PCI_CHIP_RAGE128PJ: 1228 case PCI_CHIP_RAGE128PK: 1229 case PCI_CHIP_RAGE128PL: 1230 case PCI_CHIP_RAGE128PM: 1231 case PCI_CHIP_RAGE128PN: 1232 case PCI_CHIP_RAGE128PO: 1233 case PCI_CHIP_RAGE128PQ: 1234 case PCI_CHIP_RAGE128PS: 1235 case PCI_CHIP_RAGE128PT: 1236 case PCI_CHIP_RAGE128PU: 1237 case PCI_CHIP_RAGE128PV: 1238 case PCI_CHIP_RAGE128PW: 1239 case PCI_CHIP_RAGE128PX: 1240 case PCI_CHIP_RAGE128TS: 1241 case PCI_CHIP_RAGE128TT: 1242 case PCI_CHIP_RAGE128TU: 1243 case PCI_CHIP_RAGE128SE: 1244 case PCI_CHIP_RAGE128SF: 1245 case PCI_CHIP_RAGE128SG: 1246 case PCI_CHIP_RAGE128SH: 1247 case PCI_CHIP_RAGE128SK: 1248 case PCI_CHIP_RAGE128SL: 1249 case PCI_CHIP_RAGE128SN: 1250 default: info->IsPCI = FALSE; break; 1251 } 1252 } 1253#endif 1254 1255 return TRUE; 1256} 1257 1258static Bool R128PreInitDDC(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) 1259{ 1260#if !defined(__powerpc__) && !defined(__alpha__) && !defined(__sparc__) 1261 R128InfoPtr info = R128PTR(pScrn); 1262 vbeInfoPtr pVbe; 1263#endif 1264 1265 if (!xf86LoadSubModule(pScrn, "ddc")) return FALSE; 1266 1267#if defined(__powerpc__) || defined(__alpha__) || defined(__sparc__) 1268 /* Int10 is broken on PPC and some Alphas */ 1269 return TRUE; 1270#else 1271 if (xf86LoadSubModule(pScrn, "vbe")) { 1272 pVbe = VBEInit(pInt10,info->pEnt->index); 1273 if (!pVbe) return FALSE; 1274 xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(pVbe,NULL))); 1275 vbeFree(pVbe); 1276 return TRUE; 1277 } else 1278 return FALSE; 1279#endif 1280} 1281 1282/* This is called by R128PreInit to initialize gamma correction. */ 1283static Bool R128PreInitGamma(ScrnInfoPtr pScrn) 1284{ 1285 Gamma zeros = { 0.0, 0.0, 0.0 }; 1286 1287 if (!xf86SetGamma(pScrn, zeros)) return FALSE; 1288 return TRUE; 1289} 1290 1291static void 1292R128I2CGetBits(I2CBusPtr b, int *Clock, int *data) 1293{ 1294 ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 1295 R128InfoPtr info = R128PTR(pScrn); 1296 unsigned long val; 1297 unsigned char *R128MMIO = info->MMIO; 1298 1299 /* Get the result. */ 1300 val = INREG(info->DDCReg); 1301 *Clock = (val & R128_GPIO_MONID_Y_3) != 0; 1302 *data = (val & R128_GPIO_MONID_Y_0) != 0; 1303 1304} 1305 1306static void 1307R128I2CPutBits(I2CBusPtr b, int Clock, int data) 1308{ 1309 ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 1310 R128InfoPtr info = R128PTR(pScrn); 1311 unsigned long val; 1312 unsigned char *R128MMIO = info->MMIO; 1313 1314 val = INREG(info->DDCReg) 1315 & ~(CARD32)(R128_GPIO_MONID_EN_0 | R128_GPIO_MONID_EN_3); 1316 val |= (Clock ? 0:R128_GPIO_MONID_EN_3); 1317 val |= (data ? 0:R128_GPIO_MONID_EN_0); 1318 OUTREG(info->DDCReg, val); 1319} 1320 1321 1322static Bool 1323R128I2cInit(ScrnInfoPtr pScrn) 1324{ 1325 R128InfoPtr info = R128PTR(pScrn); 1326 if ( !xf86LoadSubModule(pScrn, "i2c") ) { 1327 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1328 "Failed to load i2c module\n"); 1329 return FALSE; 1330 } 1331 1332 info->pI2CBus = xf86CreateI2CBusRec(); 1333 if(!info->pI2CBus) return FALSE; 1334 1335 info->pI2CBus->BusName = "DDC"; 1336 info->pI2CBus->scrnIndex = pScrn->scrnIndex; 1337 info->DDCReg = R128_GPIO_MONID; 1338 info->pI2CBus->I2CPutBits = R128I2CPutBits; 1339 info->pI2CBus->I2CGetBits = R128I2CGetBits; 1340 info->pI2CBus->AcknTimeout = 5; 1341 1342 if (!xf86I2CBusInit(info->pI2CBus)) { 1343 return FALSE; 1344 } 1345 return TRUE; 1346} 1347 1348/* return TRUE is a DFP is indeed connected to a DVI port */ 1349static Bool R128GetDFPInfo(ScrnInfoPtr pScrn) 1350{ 1351 R128InfoPtr info = R128PTR(pScrn); 1352 int i; 1353 xf86MonPtr MonInfo = NULL; 1354 xf86MonPtr ddc; 1355 unsigned char *R128MMIO = info->MMIO; 1356 1357 if(!R128I2cInit(pScrn)){ 1358 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1359 "I2C initialization failed!\n"); 1360 } 1361 1362 OUTREG(info->DDCReg, (INREG(info->DDCReg) 1363 | R128_GPIO_MONID_MASK_0 | R128_GPIO_MONID_MASK_3)); 1364 1365 OUTREG(info->DDCReg, INREG(info->DDCReg) 1366 & ~(CARD32)(R128_GPIO_MONID_A_0 | R128_GPIO_MONID_A_3)); 1367 1368 MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus); 1369 if(!MonInfo) { 1370 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1371 "No DFP detected\n"); 1372 return FALSE; 1373 } 1374 xf86SetDDCproperties(pScrn, MonInfo); 1375 ddc = pScrn->monitor->DDC; 1376 1377 for(i=0; i<4; i++) 1378 { 1379 if((ddc->det_mon[i].type == 0) && 1380 (ddc->det_mon[i].section.d_timings.h_active > 0) && 1381 (ddc->det_mon[i].section.d_timings.v_active > 0)) 1382 { 1383 info->PanelXRes = 1384 ddc->det_mon[i].section.d_timings.h_active; 1385 info->PanelYRes = 1386 ddc->det_mon[i].section.d_timings.v_active; 1387 1388 info->HOverPlus = 1389 ddc->det_mon[i].section.d_timings.h_sync_off; 1390 info->HSyncWidth = 1391 ddc->det_mon[i].section.d_timings.h_sync_width; 1392 info->HBlank = 1393 ddc->det_mon[i].section.d_timings.h_blanking; 1394 info->VOverPlus = 1395 ddc->det_mon[i].section.d_timings.v_sync_off; 1396 info->VSyncWidth = 1397 ddc->det_mon[i].section.d_timings.v_sync_width; 1398 info->VBlank = 1399 ddc->det_mon[i].section.d_timings.v_blanking; 1400 } 1401 } 1402 return TRUE; 1403} 1404 1405 1406static void R128SetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) 1407{ 1408 int i; 1409 xf86MonPtr ddc = pScrn->monitor->DDC; 1410 if(flag) /*HSync*/ 1411 { 1412 for(i=0; i<4; i++) 1413 { 1414 if(ddc->det_mon[i].type == DS_RANGES) 1415 { 1416 pScrn->monitor->nHsync = 1; 1417 pScrn->monitor->hsync[0].lo = 1418 ddc->det_mon[i].section.ranges.min_h; 1419 pScrn->monitor->hsync[0].hi = 1420 ddc->det_mon[i].section.ranges.max_h; 1421 return; 1422 } 1423 } 1424 /*if no sync ranges detected in detailed timing table, 1425 let's try to derive them from supported VESA modes 1426 Are we doing too much here!!!? 1427 **/ 1428 i = 0; 1429 if(ddc->timings1.t1 & 0x02) /*800x600@56*/ 1430 { 1431 pScrn->monitor->hsync[i].lo = 1432 pScrn->monitor->hsync[i].hi = 35.2; 1433 i++; 1434 } 1435 if(ddc->timings1.t1 & 0x04) /*640x480@75*/ 1436 { 1437 pScrn->monitor->hsync[i].lo = 1438 pScrn->monitor->hsync[i].hi = 37.5; 1439 i++; 1440 } 1441 if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01)) 1442 { 1443 pScrn->monitor->hsync[i].lo = 1444 pScrn->monitor->hsync[i].hi = 37.9; 1445 i++; 1446 } 1447 if(ddc->timings1.t2 & 0x40) 1448 { 1449 pScrn->monitor->hsync[i].lo = 1450 pScrn->monitor->hsync[i].hi = 46.9; 1451 i++; 1452 } 1453 if((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08)) 1454 { 1455 pScrn->monitor->hsync[i].lo = 1456 pScrn->monitor->hsync[i].hi = 48.1; 1457 i++; 1458 } 1459 if(ddc->timings1.t2 & 0x04) 1460 { 1461 pScrn->monitor->hsync[i].lo = 1462 pScrn->monitor->hsync[i].hi = 56.5; 1463 i++; 1464 } 1465 if(ddc->timings1.t2 & 0x02) 1466 { 1467 pScrn->monitor->hsync[i].lo = 1468 pScrn->monitor->hsync[i].hi = 60.0; 1469 i++; 1470 } 1471 if(ddc->timings1.t2 & 0x01) 1472 { 1473 pScrn->monitor->hsync[i].lo = 1474 pScrn->monitor->hsync[i].hi = 64.0; 1475 i++; 1476 } 1477 pScrn->monitor->nHsync = i; 1478 } 1479 else /*Vrefresh*/ 1480 { 1481 for(i=0; i<4; i++) 1482 { 1483 if(ddc->det_mon[i].type == DS_RANGES) 1484 { 1485 pScrn->monitor->nVrefresh = 1; 1486 pScrn->monitor->vrefresh[0].lo = 1487 ddc->det_mon[i].section.ranges.min_v; 1488 pScrn->monitor->vrefresh[0].hi = 1489 ddc->det_mon[i].section.ranges.max_v; 1490 return; 1491 } 1492 } 1493 i = 0; 1494 if(ddc->timings1.t1 & 0x02) /*800x600@56*/ 1495 { 1496 pScrn->monitor->vrefresh[i].lo = 1497 pScrn->monitor->vrefresh[i].hi = 56; 1498 i++; 1499 } 1500 if((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08)) 1501 { 1502 pScrn->monitor->vrefresh[i].lo = 1503 pScrn->monitor->vrefresh[i].hi = 60; 1504 i++; 1505 } 1506 if(ddc->timings1.t2 & 0x04) 1507 { 1508 pScrn->monitor->vrefresh[i].lo = 1509 pScrn->monitor->vrefresh[i].hi = 70; 1510 i++; 1511 } 1512 if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80)) 1513 { 1514 pScrn->monitor->vrefresh[i].lo = 1515 pScrn->monitor->vrefresh[i].hi = 72; 1516 i++; 1517 } 1518 if((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40) 1519 || (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01)) 1520 { 1521 pScrn->monitor->vrefresh[i].lo = 1522 pScrn->monitor->vrefresh[i].hi = 75; 1523 i++; 1524 } 1525 pScrn->monitor->nVrefresh = i; 1526 } 1527} 1528 1529/*********** 1530 xfree's xf86ValidateModes routine deosn't work well with DFPs 1531 here is our own validation routine. All modes between 1532 640<=XRes<=MaxRes and 480<=YRes<=MaxYRes will be permitted. 1533 NOTE: RageProII doesn't support rmx, can only work with the 1534 standard modes the monitor can support (scale). 1535************/ 1536 1537static int R128ValidateFPModes(ScrnInfoPtr pScrn) 1538{ 1539 int i, j, count=0, width, height; 1540 R128InfoPtr info = R128PTR(pScrn); 1541 DisplayModePtr last = NULL, new = NULL, first = NULL; 1542 xf86MonPtr ddc; 1543 1544 /* Free any allocated modes during configuration. We don't need them*/ 1545 while (pScrn->modes) 1546 { 1547 xf86DeleteMode(&pScrn->modes, pScrn->modes); 1548 } 1549 while (pScrn->modePool) 1550 { 1551 xf86DeleteMode(&pScrn->modePool, pScrn->modePool); 1552 } 1553 1554 pScrn->virtualX = pScrn->display->virtualX; 1555 pScrn->virtualY = pScrn->display->virtualY; 1556 1557 /* If no mode specified in config, we use native resolution*/ 1558 if(!pScrn->display->modes[0]) 1559 { 1560 pScrn->display->modes[0] = xnfalloc(16); 1561 sprintf(pScrn->display->modes[0], "%dx%d", 1562 info->PanelXRes, info->PanelYRes); 1563 } 1564 1565 for(i=0; pScrn->display->modes[i] != NULL; i++) 1566 { 1567 if (sscanf(pScrn->display->modes[i], "%dx%d", &width, &height) == 2) 1568 { 1569 1570 if(width < 640 || width > info->PanelXRes || 1571 height < 480 || height > info->PanelYRes) 1572 { 1573 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1574 "Mode %s is out of range.\n" 1575 "Valid mode should be between 640x480-%dx%d\n", 1576 pScrn->display->modes[i], info->PanelXRes, info->PanelYRes); 1577 continue; 1578 } 1579 1580 new = xnfcalloc(1, sizeof(DisplayModeRec)); 1581 new->prev = last; 1582 new->name = xnfalloc(strlen(pScrn->display->modes[i]) + 1); 1583 strcpy(new->name, pScrn->display->modes[i]); 1584 new->HDisplay = new->CrtcHDisplay = width; 1585 new->VDisplay = new->CrtcVDisplay = height; 1586 1587 ddc = pScrn->monitor->DDC; 1588 for(j=0; j<DET_TIMINGS; j++) 1589 { 1590 /*We use native mode clock only*/ 1591 if(ddc->det_mon[j].type == 0){ 1592 new->Clock = ddc->det_mon[j].section.d_timings.clock / 1000; 1593 break; 1594 } 1595 } 1596 1597 if(new->prev) new->prev->next = new; 1598 last = new; 1599 if(!first) first = new; 1600 pScrn->display->virtualX = 1601 pScrn->virtualX = MAX(pScrn->virtualX, width); 1602 pScrn->display->virtualY = 1603 pScrn->virtualY = MAX(pScrn->virtualY, height); 1604 count++; 1605 } 1606 else 1607 { 1608 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1609 "Mode name %s is invalid\n", pScrn->display->modes[i]); 1610 continue; 1611 } 1612 } 1613 1614 if(last) 1615 { 1616 last->next = first; 1617 first->prev = last; 1618 pScrn->modes = first; 1619 1620 /*FIXME: May need to validate line pitch here*/ 1621 { 1622 int dummy = 0; 1623 switch(pScrn->depth / 8) 1624 { 1625 case 1: 1626 dummy = 128 - pScrn->virtualX % 128; 1627 break; 1628 case 2: 1629 dummy = 32 - pScrn->virtualX % 32; 1630 break; 1631 case 3: 1632 case 4: 1633 dummy = 16 - pScrn->virtualX % 16; 1634 } 1635 pScrn->displayWidth = pScrn->virtualX + dummy; 1636 } 1637 1638 } 1639 1640 return count; 1641} 1642 1643 1644/* This is called by R128PreInit to validate modes and compute parameters 1645 for all of the valid modes. */ 1646static Bool R128PreInitModes(ScrnInfoPtr pScrn) 1647{ 1648 R128InfoPtr info = R128PTR(pScrn); 1649 ClockRangePtr clockRanges; 1650 int modesFound; 1651 1652 if(info->isDFP) { 1653 R128MapMem(pScrn); 1654 info->BIOSDisplay = R128_BIOS_DISPLAY_FP; 1655 /* validate if DFP really connected. */ 1656 if(!R128GetDFPInfo(pScrn)) { 1657 info->isDFP = FALSE; 1658 info->BIOSDisplay = R128_BIOS_DISPLAY_CRT; 1659 } else if(!info->isPro2) { 1660 /* RageProII doesn't support rmx, we can't use native-mode 1661 stretching for other non-native modes. It will rely on 1662 whatever VESA modes monitor can support. */ 1663 modesFound = R128ValidateFPModes(pScrn); 1664 if(modesFound < 1) { 1665 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1666 "No valid mode found for this DFP/LCD\n"); 1667 R128UnmapMem(pScrn); 1668 return FALSE; 1669 1670 } 1671 } 1672 R128UnmapMem(pScrn); 1673 } 1674 1675 if(!info->isDFP || info->isPro2) { 1676 /* Get mode information */ 1677 pScrn->progClock = TRUE; 1678 clockRanges = xnfcalloc(sizeof(*clockRanges), 1); 1679 clockRanges->next = NULL; 1680 clockRanges->minClock = info->pll.min_pll_freq; 1681 clockRanges->maxClock = info->pll.max_pll_freq * 10; 1682 clockRanges->clockIndex = -1; 1683 if (info->HasPanelRegs || info->isDFP) { 1684 clockRanges->interlaceAllowed = FALSE; 1685 clockRanges->doubleScanAllowed = FALSE; 1686 } else { 1687 clockRanges->interlaceAllowed = TRUE; 1688 clockRanges->doubleScanAllowed = TRUE; 1689 } 1690 1691 if(pScrn->monitor->DDC) { 1692 /*if we still don't know sync range yet, let's try EDID. 1693 Note that, since we can have dual heads, the Xconfigurator 1694 may not be able to probe both monitors correctly through 1695 vbe probe function (R128ProbeDDC). Here we provide an 1696 additional way to auto-detect sync ranges if they haven't 1697 been added to XF86Config manually. 1698 **/ 1699 if(pScrn->monitor->nHsync <= 0) 1700 R128SetSyncRangeFromEdid(pScrn, 1); 1701 if(pScrn->monitor->nVrefresh <= 0) 1702 R128SetSyncRangeFromEdid(pScrn, 0); 1703 } 1704 1705 modesFound = xf86ValidateModes(pScrn, 1706 pScrn->monitor->Modes, 1707 pScrn->display->modes, 1708 clockRanges, 1709 NULL, /* linePitches */ 1710 8 * 64, /* minPitch */ 1711 8 * 1024, /* maxPitch */ 1712/* 1713 * ATI docs say pitchInc must be 8 * 64, but this doesn't permit a pitch of 1714 * 800 bytes, which is known to work on the Rage128 LF on clamshell iBooks 1715 */ 1716 8 * 32, /* pitchInc */ 1717 128, /* minHeight */ 1718 2048, /* maxHeight */ 1719 pScrn->display->virtualX, 1720 pScrn->display->virtualY, 1721 info->FbMapSize, 1722 LOOKUP_BEST_REFRESH); 1723 1724 if (modesFound < 1 && info->FBDev) { 1725 fbdevHWUseBuildinMode(pScrn); 1726 pScrn->displayWidth = fbdevHWGetLineLength(pScrn)/(pScrn->bitsPerPixel/8); 1727 modesFound = 1; 1728 } 1729 1730 if (modesFound == -1) return FALSE; 1731 xf86PruneDriverModes(pScrn); 1732 if (!modesFound || !pScrn->modes) { 1733 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 1734 return FALSE; 1735 } 1736 xf86SetCrtcForModes(pScrn, 0); 1737 } 1738 /* Set DPI */ 1739 pScrn->currentMode = pScrn->modes; 1740 xf86PrintModes(pScrn); 1741 1742 xf86SetDpi(pScrn, 0, 0); 1743 1744 /* Get ScreenInit function */ 1745 if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; 1746 1747 info->CurrentLayout.displayWidth = pScrn->displayWidth; 1748 info->CurrentLayout.mode = pScrn->currentMode; 1749 1750 return TRUE; 1751} 1752 1753/* This is called by R128PreInit to initialize the hardware cursor. */ 1754static Bool R128PreInitCursor(ScrnInfoPtr pScrn) 1755{ 1756 R128InfoPtr info = R128PTR(pScrn); 1757 1758 if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 1759 if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE; 1760 } 1761 return TRUE; 1762} 1763 1764/* This is called by R128PreInit to initialize hardware acceleration. */ 1765static Bool R128PreInitAccel(ScrnInfoPtr pScrn) 1766{ 1767 R128InfoPtr info = R128PTR(pScrn); 1768 1769 if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { 1770 if (!xf86LoadSubModule(pScrn, "xaa")) return FALSE; 1771 } 1772 return TRUE; 1773} 1774 1775static Bool R128PreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10) 1776{ 1777 R128InfoPtr info = R128PTR(pScrn); 1778#if 1 && !defined(__alpha__) 1779 /* int10 is broken on some Alphas */ 1780 if (xf86LoadSubModule(pScrn, "int10")) { 1781 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); 1782 *ppInt10 = xf86InitInt10(info->pEnt->index); 1783 } 1784#endif 1785 return TRUE; 1786} 1787 1788#ifdef XF86DRI 1789static Bool R128PreInitDRI(ScrnInfoPtr pScrn) 1790{ 1791 R128InfoPtr info = R128PTR(pScrn); 1792 1793 if (xf86ReturnOptValBool(info->Options, OPTION_CCE_PIO, FALSE)) { 1794 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing CCE into PIO mode\n"); 1795 info->CCEMode = R128_DEFAULT_CCE_PIO_MODE; 1796 } else { 1797 info->CCEMode = R128_DEFAULT_CCE_BM_MODE; 1798 } 1799 1800 if (xf86ReturnOptValBool(info->Options, OPTION_NO_SECURITY, FALSE)) { 1801 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1802 "WARNING!!! CCE Security checks disabled!!! **********\n"); 1803 info->CCESecure = FALSE; 1804 } else { 1805 info->CCESecure = TRUE; 1806 } 1807 1808 info->agpMode = R128_DEFAULT_AGP_MODE; 1809 info->agpSize = R128_DEFAULT_AGP_SIZE; 1810 info->ringSize = R128_DEFAULT_RING_SIZE; 1811 info->bufSize = R128_DEFAULT_BUFFER_SIZE; 1812 info->agpTexSize = R128_DEFAULT_AGP_TEX_SIZE; 1813 1814 info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT; 1815 1816 if (!info->IsPCI) { 1817 if (xf86GetOptValInteger(info->Options, 1818 OPTION_AGP_MODE, &(info->agpMode))) { 1819 if (info->agpMode < 1 || info->agpMode > R128_AGP_MAX_MODE) { 1820 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1821 "Illegal AGP Mode: %d\n", info->agpMode); 1822 return FALSE; 1823 } 1824 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1825 "Using AGP %dx mode\n", info->agpMode); 1826 } 1827 1828 if (xf86GetOptValInteger(info->Options, 1829 OPTION_AGP_SIZE, (int *)&(info->agpSize))) { 1830 switch (info->agpSize) { 1831 case 4: 1832 case 8: 1833 case 16: 1834 case 32: 1835 case 64: 1836 case 128: 1837 case 256: 1838 break; 1839 default: 1840 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1841 "Illegal AGP size: %d MB\n", info->agpSize); 1842 return FALSE; 1843 } 1844 } 1845 1846 if (xf86GetOptValInteger(info->Options, 1847 OPTION_RING_SIZE, &(info->ringSize))) { 1848 if (info->ringSize < 1 || info->ringSize >= (int)info->agpSize) { 1849 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1850 "Illegal ring buffer size: %d MB\n", 1851 info->ringSize); 1852 return FALSE; 1853 } 1854 } 1855 1856 if (xf86GetOptValInteger(info->Options, 1857 OPTION_BUFFER_SIZE, &(info->bufSize))) { 1858 if (info->bufSize < 1 || info->bufSize >= (int)info->agpSize) { 1859 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1860 "Illegal vertex/indirect buffers size: %d MB\n", 1861 info->bufSize); 1862 return FALSE; 1863 } 1864 if (info->bufSize > 2) { 1865 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1866 "Illegal vertex/indirect buffers size: %d MB\n", 1867 info->bufSize); 1868 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1869 "Clamping vertex/indirect buffers size to 2 MB\n"); 1870 info->bufSize = 2; 1871 } 1872 } 1873 1874 if (info->ringSize + info->bufSize + info->agpTexSize > 1875 (int)info->agpSize) { 1876 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1877 "Buffers are too big for requested AGP space\n"); 1878 return FALSE; 1879 } 1880 1881 info->agpTexSize = info->agpSize - (info->ringSize + info->bufSize); 1882 } 1883 1884 if (xf86GetOptValInteger(info->Options, OPTION_USEC_TIMEOUT, 1885 &(info->CCEusecTimeout))) { 1886 /* This option checked by the R128 DRM kernel module */ 1887 } 1888 1889 if (!xf86LoadSubModule(pScrn, "shadowfb")) { 1890 info->allowPageFlip = 0; 1891 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1892 "Couldn't load shadowfb module:\n"); 1893 } else { 1894 info->allowPageFlip = xf86ReturnOptValBool(info->Options, 1895 OPTION_PAGE_FLIP, 1896 FALSE); 1897 } 1898 1899 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n", 1900 info->allowPageFlip ? "en" : "dis"); 1901 1902 return TRUE; 1903} 1904#endif 1905 1906static void 1907R128ProbeDDC(ScrnInfoPtr pScrn, int indx) 1908{ 1909 vbeInfoPtr pVbe; 1910 if (xf86LoadSubModule(pScrn, "vbe")) { 1911 pVbe = VBEInit(NULL,indx); 1912 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 1913 vbeFree(pVbe); 1914 } 1915} 1916 1917/* R128PreInit is called once at server startup. */ 1918Bool R128PreInit(ScrnInfoPtr pScrn, int flags) 1919{ 1920 R128InfoPtr info; 1921 xf86Int10InfoPtr pInt10 = NULL; 1922 1923 R128TRACE(("R128PreInit\n")); 1924 1925 if (pScrn->numEntities != 1) return FALSE; 1926 1927 if (!R128GetRec(pScrn)) return FALSE; 1928 1929 info = R128PTR(pScrn); 1930 1931 info->IsSecondary = FALSE; 1932 info->IsPrimary = FALSE; 1933 info->SwitchingMode = FALSE; 1934 1935 info->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 1936 if (info->pEnt->location.type != BUS_PCI) goto fail; 1937 1938 if(xf86IsEntityShared(pScrn->entityList[0])) 1939 { 1940 if(xf86IsPrimInitDone(pScrn->entityList[0])) 1941 { 1942 DevUnion* pPriv; 1943 R128EntPtr pR128Ent; 1944 info->IsSecondary = TRUE; 1945 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 1946 getR128EntityIndex()); 1947 pR128Ent = pPriv->ptr; 1948 if(pR128Ent->BypassSecondary) return FALSE; 1949 pR128Ent->pSecondaryScrn = pScrn; 1950 } 1951 else 1952 { 1953 DevUnion* pPriv; 1954 R128EntPtr pR128Ent; 1955 info->IsPrimary = TRUE; 1956 xf86SetPrimInitDone(pScrn->entityList[0]); 1957 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 1958 getR128EntityIndex()); 1959 pR128Ent = pPriv->ptr; 1960 pR128Ent->pPrimaryScrn = pScrn; 1961 pR128Ent->IsDRIEnabled = FALSE; 1962 pR128Ent->BypassSecondary = FALSE; 1963 pR128Ent->HasSecondary = FALSE; 1964 pR128Ent->RestorePrimary = FALSE; 1965 pR128Ent->IsSecondaryRestored = FALSE; 1966 } 1967 } 1968 1969 if (flags & PROBE_DETECT) { 1970 R128ProbeDDC(pScrn, info->pEnt->index); 1971 return TRUE; 1972 } 1973 1974 info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); 1975 info->PciTag = pciTag(PCI_DEV_BUS(info->PciInfo), 1976 PCI_DEV_DEV(info->PciInfo), 1977 PCI_DEV_FUNC(info->PciInfo)); 1978 1979 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1980 "PCI bus %d card %d func %d\n", 1981 PCI_DEV_BUS(info->PciInfo), 1982 PCI_DEV_DEV(info->PciInfo), 1983 PCI_DEV_FUNC(info->PciInfo)); 1984 1985#ifndef XSERVER_LIBPCIACCESS 1986 if (xf86RegisterResources(info->pEnt->index, 0, ResNone)) goto fail; 1987 if (xf86SetOperatingState(resVga, info->pEnt->index, ResUnusedOpr)) goto fail; 1988 1989 pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR; 1990#endif 1991 pScrn->monitor = pScrn->confScreen->monitor; 1992 1993 if (!R128PreInitVisual(pScrn)) goto fail; 1994 1995 /* We can't do this until we have a 1996 pScrn->display. */ 1997 xf86CollectOptions(pScrn, NULL); 1998 if (!(info->Options = xalloc(sizeof(R128Options)))) goto fail; 1999 memcpy(info->Options, R128Options, sizeof(R128Options)); 2000 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options); 2001 2002 /* By default, don't do VGA IOs on ppc */ 2003#if defined(__powerpc__) || defined(__sparc__) || !defined(WITH_VGAHW) 2004 info->VGAAccess = FALSE; 2005#else 2006 info->VGAAccess = TRUE; 2007#endif 2008 2009#ifdef WITH_VGAHW 2010 xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS, &info->VGAAccess); 2011 if (info->VGAAccess) { 2012 if (!xf86LoadSubModule(pScrn, "vgahw")) 2013 info->VGAAccess = FALSE; 2014 else { 2015 if (!vgaHWGetHWRec(pScrn)) 2016 info->VGAAccess = FALSE; 2017 } 2018 if (!info->VGAAccess) 2019 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Loading VGA module failed," 2020 " trying to run without it\n"); 2021 } else 2022 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAAccess option set to FALSE," 2023 " VGA module load skipped\n"); 2024 if (info->VGAAccess) 2025 vgaHWGetIOBase(VGAHWPTR(pScrn)); 2026#else 2027 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAHW support not compiled, VGA " 2028 "module load skipped\n"); 2029#endif 2030 2031 2032 2033 if (!R128PreInitWeight(pScrn)) goto fail; 2034 2035 if(xf86GetOptValInteger(info->Options, OPTION_VIDEO_KEY, &(info->videoKey))) { 2036 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", 2037 info->videoKey); 2038 } else { 2039 info->videoKey = 0x1E; 2040 } 2041 2042 if (xf86ReturnOptValBool(info->Options, OPTION_SHOW_CACHE, FALSE)) { 2043 info->showCache = TRUE; 2044 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n"); 2045 } 2046 2047#ifdef __powerpc__ 2048 if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, TRUE)) 2049#else 2050 if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) 2051#endif 2052 { 2053 info->FBDev = TRUE; 2054 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2055 "Using framebuffer device\n"); 2056 } 2057 2058 if (info->FBDev) { 2059 /* check for linux framebuffer device */ 2060 if (!xf86LoadSubModule(pScrn, "fbdevhw")) return FALSE; 2061 if (!fbdevHWInit(pScrn, info->PciInfo, NULL)) return FALSE; 2062 pScrn->SwitchMode = fbdevHWSwitchModeWeak(); 2063 pScrn->AdjustFrame = fbdevHWAdjustFrameWeak(); 2064 pScrn->ValidMode = fbdevHWValidModeWeak(); 2065 } 2066 2067 if (!info->FBDev) 2068 if (!R128PreInitInt10(pScrn, &pInt10)) goto fail; 2069 2070 if (!R128PreInitConfig(pScrn)) goto fail; 2071 2072 if (!R128GetBIOSParameters(pScrn, pInt10)) goto fail; 2073 2074 if (!R128GetPLLParameters(pScrn)) goto fail; 2075 2076 /* Don't fail on this one */ 2077 R128PreInitDDC(pScrn, pInt10); 2078 2079 if (!R128PreInitGamma(pScrn)) goto fail; 2080 2081 if (!R128PreInitModes(pScrn)) goto fail; 2082 2083 if (!R128PreInitCursor(pScrn)) goto fail; 2084 2085 if (!R128PreInitAccel(pScrn)) goto fail; 2086 2087#ifdef XF86DRI 2088 if (!R128PreInitDRI(pScrn)) goto fail; 2089#endif 2090 2091 /* Free the video bios (if applicable) */ 2092 if (info->VBIOS) { 2093 xfree(info->VBIOS); 2094 info->VBIOS = NULL; 2095 } 2096 2097 /* Free int10 info */ 2098 if (pInt10) 2099 xf86FreeInt10(pInt10); 2100 2101 xf86DrvMsg(pScrn->scrnIndex, X_NOTICE, 2102 "For information on using the multimedia capabilities\n\tof this" 2103 " adapter, please see http://gatos.sf.net.\n"); 2104 2105 return TRUE; 2106 2107 fail: 2108 /* Pre-init failed. */ 2109 2110 /* Free the video bios (if applicable) */ 2111 if (info->VBIOS) { 2112 xfree(info->VBIOS); 2113 info->VBIOS = NULL; 2114 } 2115 2116 /* Free int10 info */ 2117 if (pInt10) 2118 xf86FreeInt10(pInt10); 2119 2120#ifdef WITH_VGAHW 2121 if (info->VGAAccess) 2122 vgaHWFreeHWRec(pScrn); 2123#endif 2124 R128FreeRec(pScrn); 2125 return FALSE; 2126} 2127 2128/* Load a palette. */ 2129static void R128LoadPalette(ScrnInfoPtr pScrn, int numColors, 2130 int *indices, LOCO *colors, VisualPtr pVisual) 2131{ 2132 R128InfoPtr info = R128PTR(pScrn); 2133 unsigned char *R128MMIO = info->MMIO; 2134 int i, j; 2135 int idx; 2136 unsigned char r, g, b; 2137 2138 /* If the second monitor is connected, we also 2139 need to deal with the secondary palette*/ 2140 if (info->IsSecondary) j = 1; 2141 else j = 0; 2142 2143 PAL_SELECT(j); 2144 2145 2146 /* Select palette 0 (main CRTC) if using FP-enabled chip */ 2147 /*if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0);*/ 2148 2149 if (info->CurrentLayout.depth == 15) { 2150 /* 15bpp mode. This sends 32 values. */ 2151 for (i = 0; i < numColors; i++) { 2152 idx = indices[i]; 2153 r = colors[idx].red; 2154 g = colors[idx].green; 2155 b = colors[idx].blue; 2156 OUTPAL(idx * 8, r, g, b); 2157 } 2158 } 2159 else if (info->CurrentLayout.depth == 16) { 2160 /* 16bpp mode. This sends 64 values. */ 2161 /* There are twice as many green values as 2162 there are values for red and blue. So, 2163 we take each red and blue pair, and 2164 combine it with each of the two green 2165 values. */ 2166 for (i = 0; i < numColors; i++) { 2167 idx = indices[i]; 2168 r = colors[idx / 2].red; 2169 g = colors[idx].green; 2170 b = colors[idx / 2].blue; 2171 OUTPAL(idx * 4, r, g, b); 2172 } 2173 } 2174 else { 2175 /* 8bpp mode. This sends 256 values. */ 2176 for (i = 0; i < numColors; i++) { 2177 idx = indices[i]; 2178 r = colors[idx].red; 2179 b = colors[idx].blue; 2180 g = colors[idx].green; 2181 OUTPAL(idx, r, g, b); 2182 } 2183 } 2184} 2185 2186static void 2187R128BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) 2188{ 2189 ScreenPtr pScreen = screenInfo.screens[i]; 2190 ScrnInfoPtr pScrn = xf86Screens[i]; 2191 R128InfoPtr info = R128PTR(pScrn); 2192 2193#ifdef XF86DRI 2194 if (info->directRenderingEnabled) 2195 FLUSH_RING(); 2196#endif 2197 2198 pScreen->BlockHandler = info->BlockHandler; 2199 (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); 2200 pScreen->BlockHandler = R128BlockHandler; 2201 2202 if(info->VideoTimerCallback) { 2203 (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds); 2204 } 2205} 2206 2207/* Called at the start of each server generation. */ 2208Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, 2209 int argc, char **argv) 2210{ 2211 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 2212 R128InfoPtr info = R128PTR(pScrn); 2213 BoxRec MemBox; 2214 int y2; 2215 2216 R128TRACE(("R128ScreenInit %x %d\n", pScrn->memPhysBase, pScrn->fbOffset)); 2217 2218#ifdef XF86DRI 2219 /* Turn off the CCE for now. */ 2220 info->CCEInUse = FALSE; 2221 info->indirectBuffer = NULL; 2222#endif 2223 2224 if (!R128MapMem(pScrn)) return FALSE; 2225 pScrn->fbOffset = 0; 2226 if(info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024; 2227#ifdef XF86DRI 2228 info->fbX = 0; 2229 info->fbY = 0; 2230 info->frontOffset = 0; 2231 info->frontPitch = pScrn->displayWidth; 2232#endif 2233 2234 info->PaletteSavedOnVT = FALSE; 2235 2236 R128Save(pScrn); 2237 if (info->FBDev) { 2238 if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE; 2239 } else { 2240 if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE; 2241 } 2242 2243 R128SaveScreen(pScreen, SCREEN_SAVER_ON); 2244 pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 2245 2246 /* Visual setup */ 2247 miClearVisualTypes(); 2248 if (!miSetVisualTypes(pScrn->depth, 2249 miGetDefaultVisualMask(pScrn->depth), 2250 pScrn->rgbBits, 2251 pScrn->defaultVisual)) return FALSE; 2252 miSetPixmapDepths (); 2253 2254#ifdef XF86DRI 2255 /* Setup DRI after visuals have been 2256 established, but before fbScreenInit is 2257 called. fbScreenInit will eventually 2258 call the driver's InitGLXVisuals call 2259 back. */ 2260 { 2261 /* FIXME: When we move to dynamic allocation of back and depth 2262 buffers, we will want to revisit the following check for 3 2263 times the virtual size of the screen below. */ 2264 int width_bytes = (pScrn->displayWidth * 2265 info->CurrentLayout.pixel_bytes); 2266 int maxy = info->FbMapSize / width_bytes; 2267 2268 if (xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { 2269 xf86DrvMsg(scrnIndex, X_WARNING, 2270 "Acceleration disabled, not initializing the DRI\n"); 2271 info->directRenderingEnabled = FALSE; 2272 } else if (maxy <= pScrn->virtualY * 3) { 2273 xf86DrvMsg(scrnIndex, X_WARNING, 2274 "Static buffer allocation failed -- " 2275 "need at least %d kB video memory\n", 2276 (pScrn->displayWidth * pScrn->virtualY * 2277 info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024); 2278 info->directRenderingEnabled = FALSE; 2279 } else { 2280 if(info->IsSecondary) 2281 info->directRenderingEnabled = FALSE; 2282 else 2283 { 2284 /* Xinerama has sync problem with DRI, disable it for now */ 2285 if(xf86IsEntityShared(pScrn->entityList[0])) 2286 { 2287 info->directRenderingEnabled = FALSE; 2288 xf86DrvMsg(scrnIndex, X_WARNING, 2289 "Direct Rendering Disabled -- " 2290 "Dual-head configuration is not working with DRI " 2291 "at present.\nPlease use only one Device/Screen " 2292 "section in your XFConfig file.\n"); 2293 } 2294 else 2295 info->directRenderingEnabled = 2296 R128DRIScreenInit(pScreen); 2297 if(xf86IsEntityShared(pScrn->entityList[0])) 2298 { 2299 DevUnion* pPriv; 2300 R128EntPtr pR128Ent; 2301 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 2302 getR128EntityIndex()); 2303 pR128Ent = pPriv->ptr; 2304 pR128Ent->IsDRIEnabled = info->directRenderingEnabled; 2305 } 2306 } 2307 } 2308 } 2309#endif 2310 2311 if (!fbScreenInit (pScreen, info->FB, 2312 pScrn->virtualX, pScrn->virtualY, 2313 pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, 2314 pScrn->bitsPerPixel)) 2315 return FALSE; 2316 2317 xf86SetBlackWhitePixels(pScreen); 2318 2319 if (pScrn->bitsPerPixel > 8) { 2320 VisualPtr visual; 2321 2322 visual = pScreen->visuals + pScreen->numVisuals; 2323 while (--visual >= pScreen->visuals) { 2324 if ((visual->class | DynamicClass) == DirectColor) { 2325 visual->offsetRed = pScrn->offset.red; 2326 visual->offsetGreen = pScrn->offset.green; 2327 visual->offsetBlue = pScrn->offset.blue; 2328 visual->redMask = pScrn->mask.red; 2329 visual->greenMask = pScrn->mask.green; 2330 visual->blueMask = pScrn->mask.blue; 2331 } 2332 } 2333 } 2334 2335 /* must be after RGB order fixed */ 2336 fbPictureInit (pScreen, 0, 0); 2337 2338 /* Memory manager setup */ 2339#ifdef XF86DRI 2340 if (info->directRenderingEnabled) { 2341 FBAreaPtr fbarea; 2342 int width_bytes = (pScrn->displayWidth * 2343 info->CurrentLayout.pixel_bytes); 2344 int cpp = info->CurrentLayout.pixel_bytes; 2345 int bufferSize = pScrn->virtualY * width_bytes; 2346 int l, total; 2347 int scanlines; 2348 2349 switch (info->CCEMode) { 2350 case R128_DEFAULT_CCE_PIO_MODE: 2351 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in PIO mode\n"); 2352 break; 2353 case R128_DEFAULT_CCE_BM_MODE: 2354 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in BM mode\n"); 2355 break; 2356 default: 2357 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in UNKNOWN mode\n"); 2358 break; 2359 } 2360 2361 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2362 "Using %d MB AGP aperture\n", info->agpSize); 2363 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2364 "Using %d MB for the ring buffer\n", info->ringSize); 2365 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2366 "Using %d MB for vertex/indirect buffers\n", info->bufSize); 2367 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2368 "Using %d MB for AGP textures\n", info->agpTexSize); 2369 2370 /* Try for front, back, depth, and two framebuffers worth of 2371 * pixmap cache. Should be enough for a fullscreen background 2372 * image plus some leftovers. 2373 */ 2374 info->textureSize = info->FbMapSize - 5 * bufferSize; 2375 2376 /* If that gives us less than half the available memory, let's 2377 * be greedy and grab some more. Sorry, I care more about 3D 2378 * performance than playing nicely, and you'll get around a full 2379 * framebuffer's worth of pixmap cache anyway. 2380 */ 2381 if (info->textureSize < (int)info->FbMapSize / 2) { 2382 info->textureSize = info->FbMapSize - 4 * bufferSize; 2383 } 2384 2385 if (info->textureSize > 0) { 2386 l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS); 2387 if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY; 2388 2389 /* Round the texture size up to the nearest whole number of 2390 * texture regions. Again, be greedy about this, don't 2391 * round down. 2392 */ 2393 info->log2TexGran = l; 2394 info->textureSize = (info->textureSize >> l) << l; 2395 } else { 2396 info->textureSize = 0; 2397 } 2398 2399 /* Set a minimum usable local texture heap size. This will fit 2400 * two 256x256x32bpp textures. 2401 */ 2402 if (info->textureSize < 512 * 1024) { 2403 info->textureOffset = 0; 2404 info->textureSize = 0; 2405 } 2406 2407 total = info->FbMapSize - info->textureSize; 2408 scanlines = total / width_bytes; 2409 if (scanlines > 8191) scanlines = 8191; 2410 2411 /* Recalculate the texture offset and size to accomodate any 2412 * rounding to a whole number of scanlines. 2413 */ 2414 info->textureOffset = scanlines * width_bytes; 2415 2416 MemBox.x1 = 0; 2417 MemBox.y1 = 0; 2418 MemBox.x2 = pScrn->displayWidth; 2419 MemBox.y2 = scanlines; 2420 2421 if (!xf86InitFBManager(pScreen, &MemBox)) { 2422 xf86DrvMsg(scrnIndex, X_ERROR, 2423 "Memory manager initialization to (%d,%d) (%d,%d) failed\n", 2424 MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); 2425 return FALSE; 2426 } else { 2427 int width, height; 2428 2429 xf86DrvMsg(scrnIndex, X_INFO, 2430 "Memory manager initialized to (%d,%d) (%d,%d)\n", 2431 MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); 2432 if ((fbarea = xf86AllocateOffscreenArea(pScreen, 2433 pScrn->displayWidth, 2434 2, 0, NULL, NULL, NULL))) { 2435 xf86DrvMsg(scrnIndex, X_INFO, 2436 "Reserved area from (%d,%d) to (%d,%d)\n", 2437 fbarea->box.x1, fbarea->box.y1, 2438 fbarea->box.x2, fbarea->box.y2); 2439 } else { 2440 xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); 2441 } 2442 if (xf86QueryLargestOffscreenArea(pScreen, &width, 2443 &height, 0, 0, 0)) { 2444 xf86DrvMsg(scrnIndex, X_INFO, 2445 "Largest offscreen area available: %d x %d\n", 2446 width, height); 2447 } 2448 } 2449 2450 /* Allocate the shared back buffer */ 2451 if ((fbarea = xf86AllocateOffscreenArea(pScreen, 2452 pScrn->virtualX, 2453 pScrn->virtualY, 2454 32, NULL, NULL, NULL))) { 2455 xf86DrvMsg(scrnIndex, X_INFO, 2456 "Reserved back buffer from (%d,%d) to (%d,%d)\n", 2457 fbarea->box.x1, fbarea->box.y1, 2458 fbarea->box.x2, fbarea->box.y2); 2459 2460 info->backX = fbarea->box.x1; 2461 info->backY = fbarea->box.y1; 2462 info->backOffset = (fbarea->box.y1 * width_bytes + 2463 fbarea->box.x1 * cpp); 2464 info->backPitch = pScrn->displayWidth; 2465 } else { 2466 xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve back buffer\n"); 2467 info->backX = -1; 2468 info->backY = -1; 2469 info->backOffset = -1; 2470 info->backPitch = -1; 2471 } 2472 2473 /* Allocate the shared depth buffer */ 2474 if ((fbarea = xf86AllocateOffscreenArea(pScreen, 2475 pScrn->virtualX, 2476 pScrn->virtualY + 1, 2477 32, NULL, NULL, NULL))) { 2478 xf86DrvMsg(scrnIndex, X_INFO, 2479 "Reserved depth buffer from (%d,%d) to (%d,%d)\n", 2480 fbarea->box.x1, fbarea->box.y1, 2481 fbarea->box.x2, fbarea->box.y2); 2482 2483 info->depthX = fbarea->box.x1; 2484 info->depthY = fbarea->box.y1; 2485 info->depthOffset = (fbarea->box.y1 * width_bytes + 2486 fbarea->box.x1 * cpp); 2487 info->depthPitch = pScrn->displayWidth; 2488 info->spanOffset = ((fbarea->box.y2 - 1) * width_bytes + 2489 fbarea->box.x1 * cpp); 2490 xf86DrvMsg(scrnIndex, X_INFO, 2491 "Reserved depth span from (%d,%d) offset 0x%x\n", 2492 fbarea->box.x1, fbarea->box.y2 - 1, info->spanOffset); 2493 } else { 2494 xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve depth buffer\n"); 2495 info->depthX = -1; 2496 info->depthY = -1; 2497 info->depthOffset = -1; 2498 info->depthPitch = -1; 2499 info->spanOffset = -1; 2500 } 2501 2502 xf86DrvMsg(scrnIndex, X_INFO, 2503 "Reserved %d kb for textures at offset 0x%x\n", 2504 info->textureSize/1024, info->textureOffset); 2505 } 2506 else 2507#endif 2508 { 2509 MemBox.x1 = 0; 2510 MemBox.y1 = 0; 2511 MemBox.x2 = pScrn->displayWidth; 2512 y2 = (info->FbMapSize 2513 / (pScrn->displayWidth * 2514 info->CurrentLayout.pixel_bytes)); 2515 /* The acceleration engine uses 14 bit 2516 signed coordinates, so we can't have any 2517 drawable caches beyond this region. */ 2518 if (y2 > 8191) y2 = 8191; 2519 MemBox.y2 = y2; 2520 2521 if (!xf86InitFBManager(pScreen, &MemBox)) { 2522 xf86DrvMsg(scrnIndex, X_ERROR, 2523 "Memory manager initialization to (%d,%d) (%d,%d) failed\n", 2524 MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); 2525 return FALSE; 2526 } else { 2527 int width, height; 2528 FBAreaPtr fbarea; 2529 2530 xf86DrvMsg(scrnIndex, X_INFO, 2531 "Memory manager initialized to (%d,%d) (%d,%d)\n", 2532 MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); 2533 if ((fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, 2534 2, 0, NULL, NULL, NULL))) { 2535 xf86DrvMsg(scrnIndex, X_INFO, 2536 "Reserved area from (%d,%d) to (%d,%d)\n", 2537 fbarea->box.x1, fbarea->box.y1, 2538 fbarea->box.x2, fbarea->box.y2); 2539 } else { 2540 xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); 2541 } 2542 if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 2543 0, 0, 0)) { 2544 xf86DrvMsg(scrnIndex, X_INFO, 2545 "Largest offscreen area available: %d x %d\n", 2546 width, height); 2547 } 2548 } 2549 } 2550 2551 /* Acceleration setup */ 2552 if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { 2553 if (R128AccelInit(pScreen)) { 2554 xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n"); 2555 info->accelOn = TRUE; 2556 } else { 2557 xf86DrvMsg(scrnIndex, X_ERROR, 2558 "Acceleration initialization failed\n"); 2559 xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); 2560 info->accelOn = FALSE; 2561 } 2562 } else { 2563 xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); 2564 info->accelOn = FALSE; 2565 } 2566 2567 /* DGA setup */ 2568 R128DGAInit(pScreen); 2569 2570 /* Backing store setup */ 2571 miInitializeBackingStore(pScreen); 2572 xf86SetBackingStore(pScreen); 2573 2574 /* Set Silken Mouse */ 2575 xf86SetSilkenMouse(pScreen); 2576 2577 /* Cursor setup */ 2578 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 2579 2580 /* Hardware cursor setup */ 2581 if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 2582 if (R128CursorInit(pScreen)) { 2583 int width, height; 2584 2585 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2586 "Using hardware cursor (scanline %ld)\n", 2587 info->cursor_start / pScrn->displayWidth); 2588 if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 2589 0, 0, 0)) { 2590 xf86DrvMsg(scrnIndex, X_INFO, 2591 "Largest offscreen area available: %d x %d\n", 2592 width, height); 2593 } 2594 } else { 2595 xf86DrvMsg(scrnIndex, X_ERROR, 2596 "Hardware cursor initialization failed\n"); 2597 xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n"); 2598 } 2599 } else { 2600 info->cursor_start = 0; 2601 xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n"); 2602 } 2603 2604 /* Colormap setup */ 2605 if (!miCreateDefColormap(pScreen)) return FALSE; 2606 if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8, 2607 (info->FBDev ? fbdevHWLoadPaletteWeak() : 2608 R128LoadPalette), NULL, 2609 CMAP_PALETTED_TRUECOLOR 2610 | CMAP_RELOAD_ON_MODE_SWITCH 2611#if 0 /* This option messes up text mode! (eich@suse.de) */ 2612 | CMAP_LOAD_EVEN_IF_OFFSCREEN 2613#endif 2614 )) return FALSE; 2615 2616 /* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */ 2617 if (info->FBDev) 2618 xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0); 2619 2620 else { 2621 if (info->DisplayType == MT_LCD) 2622 xf86DPMSInit(pScreen, R128DisplayPowerManagementSetLCD, 0); 2623 else 2624 xf86DPMSInit(pScreen, R128DisplayPowerManagementSet, 0); 2625 } 2626 2627 if (!info->IsSecondary) 2628 R128InitVideo(pScreen); 2629 2630 /* Provide SaveScreen */ 2631 pScreen->SaveScreen = R128SaveScreen; 2632 2633 /* Wrap CloseScreen */ 2634 info->CloseScreen = pScreen->CloseScreen; 2635 pScreen->CloseScreen = R128CloseScreen; 2636 2637 /* Note unused options */ 2638 if (serverGeneration == 1) 2639 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 2640 2641#ifdef XF86DRI 2642 /* DRI finalization */ 2643 if (info->directRenderingEnabled) { 2644 /* Now that mi, fb, drm and others have 2645 done their thing, complete the DRI 2646 setup. */ 2647 info->directRenderingEnabled = R128DRIFinishScreenInit(pScreen); 2648 } 2649 if (info->directRenderingEnabled) { 2650 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); 2651 } else { 2652 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2653 "Direct rendering disabled\n"); 2654 } 2655#endif 2656 2657 info->BlockHandler = pScreen->BlockHandler; 2658 pScreen->BlockHandler = R128BlockHandler; 2659 2660 return TRUE; 2661} 2662 2663/* Write common registers (initialized to 0). */ 2664static void R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 2665{ 2666 R128InfoPtr info = R128PTR(pScrn); 2667 unsigned char *R128MMIO = info->MMIO; 2668 2669 OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl | R128_FP_BLANK_DIS); 2670 2671 OUTREG(R128_OVR_CLR, restore->ovr_clr); 2672 OUTREG(R128_OVR_WID_LEFT_RIGHT, restore->ovr_wid_left_right); 2673 OUTREG(R128_OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom); 2674 OUTREG(R128_OV0_SCALE_CNTL, restore->ov0_scale_cntl); 2675 OUTREG(R128_MPP_TB_CONFIG, restore->mpp_tb_config ); 2676 OUTREG(R128_MPP_GP_CONFIG, restore->mpp_gp_config ); 2677 OUTREG(R128_SUBPIC_CNTL, restore->subpic_cntl); 2678 OUTREG(R128_VIPH_CONTROL, restore->viph_control); 2679 OUTREG(R128_I2C_CNTL_1, restore->i2c_cntl_1); 2680 OUTREG(R128_GEN_INT_CNTL, restore->gen_int_cntl); 2681 OUTREG(R128_CAP0_TRIG_CNTL, restore->cap0_trig_cntl); 2682 OUTREG(R128_CAP1_TRIG_CNTL, restore->cap1_trig_cntl); 2683 OUTREG(R128_BUS_CNTL, restore->bus_cntl); 2684 OUTREG(R128_CONFIG_CNTL, restore->config_cntl); 2685} 2686 2687/* Write CRTC registers. */ 2688static void R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 2689{ 2690 R128InfoPtr info = R128PTR(pScrn); 2691 unsigned char *R128MMIO = info->MMIO; 2692 2693 OUTREG(R128_CRTC_GEN_CNTL, restore->crtc_gen_cntl); 2694 2695 OUTREGP(R128_CRTC_EXT_CNTL, restore->crtc_ext_cntl, 2696 R128_CRTC_VSYNC_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_DISPLAY_DIS); 2697 2698 OUTREGP(R128_DAC_CNTL, restore->dac_cntl, 2699 R128_DAC_RANGE_CNTL | R128_DAC_BLANKING); 2700 2701 OUTREG(R128_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); 2702 OUTREG(R128_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); 2703 OUTREG(R128_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); 2704 OUTREG(R128_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid); 2705 OUTREG(R128_CRTC_OFFSET, restore->crtc_offset); 2706 OUTREG(R128_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); 2707 OUTREG(R128_CRTC_PITCH, restore->crtc_pitch); 2708} 2709 2710/* Write CRTC2 registers. */ 2711static void R128RestoreCrtc2Registers(ScrnInfoPtr pScrn, 2712 R128SavePtr restore) 2713{ 2714 R128InfoPtr info = R128PTR(pScrn); 2715 unsigned char *R128MMIO = info->MMIO; 2716 2717 OUTREGP(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl, 2718 R128_CRTC2_DISP_DIS); 2719 2720 OUTREG(R128_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); 2721 OUTREG(R128_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid); 2722 OUTREG(R128_CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp); 2723 OUTREG(R128_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid); 2724 OUTREG(R128_CRTC2_OFFSET, restore->crtc2_offset); 2725 OUTREG(R128_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); 2726 OUTREG(R128_CRTC2_PITCH, restore->crtc2_pitch); 2727} 2728 2729/* Write flat panel registers */ 2730static void R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 2731{ 2732 R128InfoPtr info = R128PTR(pScrn); 2733 unsigned char *R128MMIO = info->MMIO; 2734 CARD32 tmp; 2735 2736 if (info->BIOSDisplay != R128_DUALHEAD) 2737 OUTREG(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); 2738 OUTREG(R128_FP_HORZ_STRETCH, restore->fp_horz_stretch); 2739 OUTREG(R128_FP_VERT_STRETCH, restore->fp_vert_stretch); 2740 OUTREG(R128_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp); 2741 OUTREG(R128_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp); 2742 OUTREG(R128_FP_H_SYNC_STRT_WID, restore->fp_h_sync_strt_wid); 2743 OUTREG(R128_FP_V_SYNC_STRT_WID, restore->fp_v_sync_strt_wid); 2744 OUTREG(R128_TMDS_CRC, restore->tmds_crc); 2745 OUTREG(R128_FP_PANEL_CNTL, restore->fp_panel_cntl); 2746 OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl & ~(CARD32)R128_FP_BLANK_DIS); 2747 2748 if(info->isDFP) return; 2749 2750 tmp = INREG(R128_LVDS_GEN_CNTL); 2751 if ((tmp & (R128_LVDS_ON | R128_LVDS_BLON)) == 2752 (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON))) { 2753 OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl); 2754 } else { 2755 if (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON)) { 2756 OUTREG(R128_LVDS_GEN_CNTL, 2757 restore->lvds_gen_cntl & (CARD32)~R128_LVDS_BLON); 2758 usleep(R128PTR(pScrn)->PanelPwrDly * 1000); 2759 OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl); 2760 } else { 2761 OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl | R128_LVDS_BLON); 2762 usleep(R128PTR(pScrn)->PanelPwrDly * 1000); 2763 OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl); 2764 } 2765 } 2766} 2767 2768static void R128PLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn) 2769{ 2770 while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R); 2771} 2772 2773static void R128PLLWriteUpdate(ScrnInfoPtr pScrn) 2774{ 2775 R128InfoPtr info = R128PTR(pScrn); 2776 unsigned char *R128MMIO = info->MMIO; 2777 2778 while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R); 2779 2780 OUTPLLP(pScrn, R128_PPLL_REF_DIV, R128_PPLL_ATOMIC_UPDATE_W, 2781 ~R128_PPLL_ATOMIC_UPDATE_W); 2782 2783} 2784 2785static void R128PLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn) 2786{ 2787 while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R); 2788} 2789 2790static void R128PLL2WriteUpdate(ScrnInfoPtr pScrn) 2791{ 2792 R128InfoPtr info = R128PTR(pScrn); 2793 unsigned char *R128MMIO = info->MMIO; 2794 2795 while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R); 2796 2797 OUTPLLP(pScrn, R128_P2PLL_REF_DIV, 2798 R128_P2PLL_ATOMIC_UPDATE_W, 2799 ~(R128_P2PLL_ATOMIC_UPDATE_W)); 2800} 2801 2802/* Write PLL registers. */ 2803static void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 2804{ 2805 R128InfoPtr info = R128PTR(pScrn); 2806 unsigned char *R128MMIO = info->MMIO; 2807 2808 2809 OUTPLLP(pScrn, R128_VCLK_ECP_CNTL, 2810 R128_VCLK_SRC_SEL_CPUCLK, 2811 ~(R128_VCLK_SRC_SEL_MASK)); 2812 2813 OUTPLLP(pScrn, 2814 R128_PPLL_CNTL, 2815 R128_PPLL_RESET 2816 | R128_PPLL_ATOMIC_UPDATE_EN 2817 | R128_PPLL_VGA_ATOMIC_UPDATE_EN, 2818 ~(R128_PPLL_RESET 2819 | R128_PPLL_ATOMIC_UPDATE_EN 2820 | R128_PPLL_VGA_ATOMIC_UPDATE_EN)); 2821 2822 OUTREGP(R128_CLOCK_CNTL_INDEX, R128_PLL_DIV_SEL, ~(R128_PLL_DIV_SEL)); 2823 2824/* R128PLLWaitForReadUpdateComplete(pScrn);*/ 2825 OUTPLLP(pScrn, R128_PPLL_REF_DIV, 2826 restore->ppll_ref_div, ~R128_PPLL_REF_DIV_MASK); 2827/* R128PLLWriteUpdate(pScrn); 2828 2829 R128PLLWaitForReadUpdateComplete(pScrn);*/ 2830 OUTPLLP(pScrn, R128_PPLL_DIV_3, 2831 restore->ppll_div_3, ~R128_PPLL_FB3_DIV_MASK); 2832/* R128PLLWriteUpdate(pScrn);*/ 2833 OUTPLLP(pScrn, R128_PPLL_DIV_3, 2834 restore->ppll_div_3, ~R128_PPLL_POST3_DIV_MASK); 2835 2836 R128PLLWriteUpdate(pScrn); 2837 R128PLLWaitForReadUpdateComplete(pScrn); 2838 2839 OUTPLL(R128_HTOTAL_CNTL, restore->htotal_cntl); 2840/* R128PLLWriteUpdate(pScrn);*/ 2841 2842 OUTPLLP(pScrn, R128_PPLL_CNTL, 0, ~(R128_PPLL_RESET 2843 | R128_PPLL_SLEEP 2844 | R128_PPLL_ATOMIC_UPDATE_EN 2845 | R128_PPLL_VGA_ATOMIC_UPDATE_EN)); 2846 2847 R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", 2848 restore->ppll_ref_div, 2849 restore->ppll_div_3, 2850 restore->htotal_cntl, 2851 INPLL(pScrn, R128_PPLL_CNTL))); 2852 R128TRACE(("Wrote: rd=%d, fd=%d, pd=%d\n", 2853 restore->ppll_ref_div & R128_PPLL_REF_DIV_MASK, 2854 restore->ppll_div_3 & R128_PPLL_FB3_DIV_MASK, 2855 (restore->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16)); 2856 2857 usleep(5000); /* let the clock lock */ 2858 2859 OUTPLLP(pScrn, R128_VCLK_ECP_CNTL, 2860 R128_VCLK_SRC_SEL_PPLLCLK, 2861 ~(R128_VCLK_SRC_SEL_MASK)); 2862 2863} 2864 2865/* Write PLL2 registers. */ 2866static void R128RestorePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) 2867{ 2868 R128InfoPtr info = R128PTR(pScrn); 2869 unsigned char *R128MMIO = info->MMIO; 2870 2871 OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL, 2872 R128_V2CLK_SRC_SEL_CPUCLK, 2873 ~R128_V2CLK_SRC_SEL_MASK); 2874 2875 OUTPLLP(pScrn, 2876 R128_P2PLL_CNTL, 2877 R128_P2PLL_RESET 2878 | R128_P2PLL_ATOMIC_UPDATE_EN 2879 | R128_P2PLL_VGA_ATOMIC_UPDATE_EN, 2880 ~(R128_P2PLL_RESET 2881 | R128_P2PLL_ATOMIC_UPDATE_EN 2882 | R128_P2PLL_VGA_ATOMIC_UPDATE_EN)); 2883 2884#if 1 2885 OUTREGP(R128_CLOCK_CNTL_INDEX, 0, R128_PLL2_DIV_SEL_MASK); 2886#endif 2887 2888 /*R128PLL2WaitForReadUpdateComplete(pScrn);*/ 2889 2890 OUTPLLP(pScrn, R128_P2PLL_REF_DIV, restore->p2pll_ref_div, ~R128_P2PLL_REF_DIV_MASK); 2891 2892/* R128PLL2WriteUpdate(pScrn); 2893 R128PLL2WaitForReadUpdateComplete(pScrn);*/ 2894 2895 OUTPLLP(pScrn, R128_P2PLL_DIV_0, 2896 restore->p2pll_div_0, ~R128_P2PLL_FB0_DIV_MASK); 2897 2898/* R128PLL2WriteUpdate(pScrn); 2899 R128PLL2WaitForReadUpdateComplete(pScrn);*/ 2900 2901 OUTPLLP(pScrn, R128_P2PLL_DIV_0, 2902 restore->p2pll_div_0, ~R128_P2PLL_POST0_DIV_MASK); 2903 2904 R128PLL2WriteUpdate(pScrn); 2905 R128PLL2WaitForReadUpdateComplete(pScrn); 2906 2907 OUTPLL(R128_HTOTAL2_CNTL, restore->htotal_cntl2); 2908 2909/* R128PLL2WriteUpdate(pScrn);*/ 2910 2911 OUTPLLP(pScrn, R128_P2PLL_CNTL, 0, ~(R128_P2PLL_RESET 2912 | R128_P2PLL_SLEEP 2913 | R128_P2PLL_ATOMIC_UPDATE_EN 2914 | R128_P2PLL_VGA_ATOMIC_UPDATE_EN)); 2915 2916 R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", 2917 restore->p2pll_ref_div, 2918 restore->p2pll_div_0, 2919 restore->htotal_cntl2, 2920 INPLL(pScrn, RADEON_P2PLL_CNTL))); 2921 R128TRACE(("Wrote: rd=%d, fd=%d, pd=%d\n", 2922 restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, 2923 restore->p2pll_div_0 & RADEON_P2PLL_FB3_DIV_MASK, 2924 (restore->p2pll_div_0 & RADEON_P2PLL_POST3_DIV_MASK) >>16)); 2925 2926 usleep(5000); /* Let the clock to lock */ 2927 2928 OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL, 2929 R128_V2CLK_SRC_SEL_P2PLLCLK, 2930 ~R128_V2CLK_SRC_SEL_MASK); 2931 2932} 2933 2934/* Write DDA registers. */ 2935static void R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 2936{ 2937 R128InfoPtr info = R128PTR(pScrn); 2938 unsigned char *R128MMIO = info->MMIO; 2939 2940 OUTREG(R128_DDA_CONFIG, restore->dda_config); 2941 OUTREG(R128_DDA_ON_OFF, restore->dda_on_off); 2942} 2943 2944/* Write DDA registers. */ 2945static void R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) 2946{ 2947 R128InfoPtr info = R128PTR(pScrn); 2948 unsigned char *R128MMIO = info->MMIO; 2949 2950 OUTREG(R128_DDA2_CONFIG, restore->dda2_config); 2951 OUTREG(R128_DDA2_ON_OFF, restore->dda2_on_off); 2952} 2953 2954/* Write palette data. */ 2955static void R128RestorePalette(ScrnInfoPtr pScrn, R128SavePtr restore) 2956{ 2957 R128InfoPtr info = R128PTR(pScrn); 2958 unsigned char *R128MMIO = info->MMIO; 2959 int i; 2960 2961 if (!restore->palette_valid) return; 2962 2963 PAL_SELECT(1); 2964 OUTPAL_START(0); 2965 for (i = 0; i < 256; i++) { 2966 R128WaitForFifo(pScrn, 32); /* delay */ 2967 OUTPAL_NEXT_CARD32(restore->palette2[i]); 2968 } 2969 2970 PAL_SELECT(0); 2971 OUTPAL_START(0); 2972 for (i = 0; i < 256; i++) { 2973 R128WaitForFifo(pScrn, 32); /* delay */ 2974 OUTPAL_NEXT_CARD32(restore->palette[i]); 2975 } 2976 2977} 2978 2979/* Write out state to define a new video mode. */ 2980static void R128RestoreMode(ScrnInfoPtr pScrn, R128SavePtr restore) 2981{ 2982 R128InfoPtr info = R128PTR(pScrn); 2983 DevUnion* pPriv; 2984 R128EntPtr pR128Ent; 2985 static R128SaveRec restore0; 2986 2987 R128TRACE(("R128RestoreMode(%p)\n", restore)); 2988 if(!info->HasCRTC2) 2989 { 2990 R128RestoreCommonRegisters(pScrn, restore); 2991 R128RestoreDDARegisters(pScrn, restore); 2992 R128RestoreCrtcRegisters(pScrn, restore); 2993 if((info->DisplayType == MT_DFP) || 2994 (info->DisplayType == MT_LCD)) 2995 { 2996 R128RestoreFPRegisters(pScrn, restore); 2997 } 2998 R128RestorePLLRegisters(pScrn, restore); 2999 return; 3000 } 3001 3002 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 3003 getR128EntityIndex()); 3004 pR128Ent = pPriv->ptr; 3005 3006 3007 /***** 3008 When changing mode with Dual-head card (VE/M6), care must 3009 be taken for the special order in setting registers. CRTC2 has 3010 to be set before changing CRTC_EXT register. 3011 In the dual-head setup, X server calls this routine twice with 3012 primary and secondary pScrn pointers respectively. The calls 3013 can come with different order. Regardless the order of X server issuing 3014 the calls, we have to ensure we set registers in the right order!!! 3015 Otherwise we may get a blank screen. 3016 *****/ 3017 3018 if(info->IsSecondary) 3019 { 3020 if (!pR128Ent->RestorePrimary && !info->SwitchingMode) 3021 R128RestoreCommonRegisters(pScrn, restore); 3022 R128RestoreDDA2Registers(pScrn, restore); 3023 R128RestoreCrtc2Registers(pScrn, restore); 3024 R128RestorePLL2Registers(pScrn, restore); 3025 3026 if(info->SwitchingMode) return; 3027 3028 pR128Ent->IsSecondaryRestored = TRUE; 3029 3030 if(pR128Ent->RestorePrimary) 3031 { 3032 R128InfoPtr info0 = R128PTR(pR128Ent->pPrimaryScrn); 3033 pR128Ent->RestorePrimary = FALSE; 3034 3035 R128RestoreCrtcRegisters(pScrn, &restore0); 3036 if((info0->DisplayType == MT_DFP) || 3037 (info0->DisplayType == MT_LCD)) 3038 { 3039 R128RestoreFPRegisters(pScrn, &restore0); 3040 } 3041 3042 R128RestorePLLRegisters(pScrn, &restore0); 3043 pR128Ent->IsSecondaryRestored = FALSE; 3044 3045 } 3046 } 3047 else 3048 { 3049 if (!pR128Ent->IsSecondaryRestored) 3050 R128RestoreCommonRegisters(pScrn, restore); 3051 R128RestoreDDARegisters(pScrn, restore); 3052 if(!pR128Ent->HasSecondary || pR128Ent->IsSecondaryRestored 3053 || info->SwitchingMode) 3054 { 3055 pR128Ent->IsSecondaryRestored = FALSE; 3056 R128RestoreCrtcRegisters(pScrn, restore); 3057 if((info->DisplayType == MT_DFP) || 3058 (info->DisplayType == MT_LCD)) 3059 { 3060 R128RestoreFPRegisters(pScrn, restore); 3061 } 3062 R128RestorePLLRegisters(pScrn, restore); 3063 } 3064 else 3065 { 3066 memcpy(&restore0, restore, sizeof(restore0)); 3067 pR128Ent->RestorePrimary = TRUE; 3068 } 3069 } 3070 3071 R128RestorePalette(pScrn, restore); 3072} 3073 3074/* Read common registers. */ 3075static void R128SaveCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr save) 3076{ 3077 R128InfoPtr info = R128PTR(pScrn); 3078 unsigned char *R128MMIO = info->MMIO; 3079 3080 save->ovr_clr = INREG(R128_OVR_CLR); 3081 save->ovr_wid_left_right = INREG(R128_OVR_WID_LEFT_RIGHT); 3082 save->ovr_wid_top_bottom = INREG(R128_OVR_WID_TOP_BOTTOM); 3083 save->ov0_scale_cntl = INREG(R128_OV0_SCALE_CNTL); 3084 save->mpp_tb_config = INREG(R128_MPP_TB_CONFIG); 3085 save->mpp_gp_config = INREG(R128_MPP_GP_CONFIG); 3086 save->subpic_cntl = INREG(R128_SUBPIC_CNTL); 3087 save->viph_control = INREG(R128_VIPH_CONTROL); 3088 save->i2c_cntl_1 = INREG(R128_I2C_CNTL_1); 3089 save->gen_int_cntl = INREG(R128_GEN_INT_CNTL); 3090 save->cap0_trig_cntl = INREG(R128_CAP0_TRIG_CNTL); 3091 save->cap1_trig_cntl = INREG(R128_CAP1_TRIG_CNTL); 3092 save->bus_cntl = INREG(R128_BUS_CNTL); 3093 save->config_cntl = INREG(R128_CONFIG_CNTL); 3094} 3095 3096/* Read CRTC registers. */ 3097static void R128SaveCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save) 3098{ 3099 R128InfoPtr info = R128PTR(pScrn); 3100 unsigned char *R128MMIO = info->MMIO; 3101 3102 save->crtc_gen_cntl = INREG(R128_CRTC_GEN_CNTL); 3103 save->crtc_ext_cntl = INREG(R128_CRTC_EXT_CNTL); 3104 save->dac_cntl = INREG(R128_DAC_CNTL); 3105 save->crtc_h_total_disp = INREG(R128_CRTC_H_TOTAL_DISP); 3106 save->crtc_h_sync_strt_wid = INREG(R128_CRTC_H_SYNC_STRT_WID); 3107 save->crtc_v_total_disp = INREG(R128_CRTC_V_TOTAL_DISP); 3108 save->crtc_v_sync_strt_wid = INREG(R128_CRTC_V_SYNC_STRT_WID); 3109 save->crtc_offset = INREG(R128_CRTC_OFFSET); 3110 save->crtc_offset_cntl = INREG(R128_CRTC_OFFSET_CNTL); 3111 save->crtc_pitch = INREG(R128_CRTC_PITCH); 3112} 3113 3114/* Read flat panel registers */ 3115static void R128SaveFPRegisters(ScrnInfoPtr pScrn, R128SavePtr save) 3116{ 3117 R128InfoPtr info = R128PTR(pScrn); 3118 unsigned char *R128MMIO = info->MMIO; 3119 3120 if (info->BIOSDisplay != R128_DUALHEAD) 3121 save->crtc2_gen_cntl = INREG(R128_CRTC2_GEN_CNTL); 3122 save->fp_crtc_h_total_disp = INREG(R128_FP_CRTC_H_TOTAL_DISP); 3123 save->fp_crtc_v_total_disp = INREG(R128_FP_CRTC_V_TOTAL_DISP); 3124 save->fp_gen_cntl = INREG(R128_FP_GEN_CNTL); 3125 save->fp_h_sync_strt_wid = INREG(R128_FP_H_SYNC_STRT_WID); 3126 save->fp_horz_stretch = INREG(R128_FP_HORZ_STRETCH); 3127 save->fp_panel_cntl = INREG(R128_FP_PANEL_CNTL); 3128 save->fp_v_sync_strt_wid = INREG(R128_FP_V_SYNC_STRT_WID); 3129 save->fp_vert_stretch = INREG(R128_FP_VERT_STRETCH); 3130 save->lvds_gen_cntl = INREG(R128_LVDS_GEN_CNTL); 3131 save->tmds_crc = INREG(R128_TMDS_CRC); 3132 save->tmds_transmitter_cntl = INREG(R128_TMDS_TRANSMITTER_CNTL); 3133} 3134 3135/* Read CRTC2 registers. */ 3136static void R128SaveCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save) 3137{ 3138 R128InfoPtr info = R128PTR(pScrn); 3139 unsigned char *R128MMIO = info->MMIO; 3140 3141 save->crtc2_gen_cntl = INREG(R128_CRTC2_GEN_CNTL); 3142 save->crtc2_h_total_disp = INREG(R128_CRTC2_H_TOTAL_DISP); 3143 save->crtc2_h_sync_strt_wid = INREG(R128_CRTC2_H_SYNC_STRT_WID); 3144 save->crtc2_v_total_disp = INREG(R128_CRTC2_V_TOTAL_DISP); 3145 save->crtc2_v_sync_strt_wid = INREG(R128_CRTC2_V_SYNC_STRT_WID); 3146 save->crtc2_offset = INREG(R128_CRTC2_OFFSET); 3147 save->crtc2_offset_cntl = INREG(R128_CRTC2_OFFSET_CNTL); 3148 save->crtc2_pitch = INREG(R128_CRTC2_PITCH); 3149} 3150 3151/* Read PLL registers. */ 3152static void R128SavePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save) 3153{ 3154 save->ppll_ref_div = INPLL(pScrn, R128_PPLL_REF_DIV); 3155 save->ppll_div_3 = INPLL(pScrn, R128_PPLL_DIV_3); 3156 save->htotal_cntl = INPLL(pScrn, R128_HTOTAL_CNTL); 3157 3158 R128TRACE(("Read: 0x%08x 0x%08x 0x%08x\n", 3159 save->ppll_ref_div, 3160 save->ppll_div_3, 3161 save->htotal_cntl)); 3162 R128TRACE(("Read: rd=%d, fd=%d, pd=%d\n", 3163 save->ppll_ref_div & R128_PPLL_REF_DIV_MASK, 3164 save->ppll_div_3 & R128_PPLL_FB3_DIV_MASK, 3165 (save->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16)); 3166} 3167 3168/* Read PLL2 registers. */ 3169static void R128SavePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save) 3170{ 3171 save->p2pll_ref_div = INPLL(pScrn, R128_P2PLL_REF_DIV); 3172 save->p2pll_div_0 = INPLL(pScrn, R128_P2PLL_DIV_0); 3173 save->htotal_cntl2 = INPLL(pScrn, R128_HTOTAL2_CNTL); 3174 3175 R128TRACE(("Read: 0x%08x 0x%08x 0x%08x\n", 3176 save->p2pll_ref_div, 3177 save->p2pll_div_0, 3178 save->htotal_cntl2)); 3179 R128TRACE(("Read: rd=%d, fd=%d, pd=%d\n", 3180 save->p2pll_ref_div & R128_P2PLL_REF_DIV_MASK, 3181 save->p2pll_div_0 & R128_P2PLL_FB0_DIV_MASK, 3182 (save->p2pll_div_0 & R128_P2PLL_POST0_DIV_MASK) >> 16)); 3183} 3184 3185/* Read DDA registers. */ 3186static void R128SaveDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save) 3187{ 3188 R128InfoPtr info = R128PTR(pScrn); 3189 unsigned char *R128MMIO = info->MMIO; 3190 3191 save->dda_config = INREG(R128_DDA_CONFIG); 3192 save->dda_on_off = INREG(R128_DDA_ON_OFF); 3193} 3194 3195/* Read DDA2 registers. */ 3196static void R128SaveDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save) 3197{ 3198 R128InfoPtr info = R128PTR(pScrn); 3199 unsigned char *R128MMIO = info->MMIO; 3200 3201 save->dda2_config = INREG(R128_DDA2_CONFIG); 3202 save->dda2_on_off = INREG(R128_DDA2_ON_OFF); 3203} 3204 3205/* Read palette data. */ 3206static void R128SavePalette(ScrnInfoPtr pScrn, R128SavePtr save) 3207{ 3208 R128InfoPtr info = R128PTR(pScrn); 3209 unsigned char *R128MMIO = info->MMIO; 3210 int i; 3211 3212 PAL_SELECT(1); 3213 INPAL_START(0); 3214 for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT(); 3215 PAL_SELECT(0); 3216 INPAL_START(0); 3217 for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT(); 3218 save->palette_valid = TRUE; 3219} 3220 3221/* Save state that defines current video mode. */ 3222static void R128SaveMode(ScrnInfoPtr pScrn, R128SavePtr save) 3223{ 3224 R128InfoPtr info = R128PTR(pScrn); 3225 3226 R128TRACE(("R128SaveMode(%p)\n", save)); 3227 3228 if(info->IsSecondary) 3229 { 3230 R128SaveCrtc2Registers(pScrn, save); 3231 R128SavePLL2Registers(pScrn, save); 3232 R128SaveDDA2Registers(pScrn, save); 3233 } 3234 else 3235 { 3236 R128SaveCommonRegisters(pScrn, save); 3237 R128SaveCrtcRegisters(pScrn, save); 3238 if((info->DisplayType == MT_DFP) || 3239 (info->DisplayType == MT_LCD)) 3240 { 3241 R128SaveFPRegisters(pScrn, save); 3242 } 3243 R128SavePLLRegisters(pScrn, save); 3244 R128SaveDDARegisters(pScrn, save); 3245 R128SavePalette(pScrn, save); 3246 } 3247 3248 R128TRACE(("R128SaveMode returns %p\n", save)); 3249} 3250 3251/* Save everything needed to restore the original VC state. */ 3252static void R128Save(ScrnInfoPtr pScrn) 3253{ 3254 R128InfoPtr info = R128PTR(pScrn); 3255 unsigned char *R128MMIO = info->MMIO; 3256 R128SavePtr save = &info->SavedReg; 3257 3258 R128TRACE(("R128Save\n")); 3259 if (info->FBDev) { 3260 fbdevHWSave(pScrn); 3261 return; 3262 } 3263 3264 if (!info->IsSecondary) { 3265#ifdef WITH_VGAHW 3266 if (info->VGAAccess) { 3267 vgaHWPtr hwp = VGAHWPTR(pScrn); 3268 3269 vgaHWUnlock(hwp); 3270# if defined(__powerpc__) 3271 /* temporary hack to prevent crashing on PowerMacs when trying to 3272 * read VGA fonts and colormap, will find a better solution 3273 * in the future. TODO: Check if there's actually some VGA stuff 3274 * setup in the card at all !! 3275 */ 3276 vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */ 3277# else 3278 /* Save mode * & fonts & cmap */ 3279 vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS); 3280# endif 3281 vgaHWLock(hwp); 3282 } 3283#endif 3284 3285 save->dp_datatype = INREG(R128_DP_DATATYPE); 3286 save->gen_reset_cntl = INREG(R128_GEN_RESET_CNTL); 3287 save->clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX); 3288 save->amcgpio_en_reg = INREG(R128_AMCGPIO_EN_REG); 3289 save->amcgpio_mask = INREG(R128_AMCGPIO_MASK); 3290 } 3291 3292 R128SaveMode(pScrn, save); 3293 3294} 3295 3296/* Restore the original (text) mode. */ 3297static void R128Restore(ScrnInfoPtr pScrn) 3298{ 3299 R128InfoPtr info = R128PTR(pScrn); 3300 unsigned char *R128MMIO = info->MMIO; 3301 R128SavePtr restore = &info->SavedReg; 3302 3303 R128TRACE(("R128Restore\n")); 3304 if (info->FBDev) { 3305 fbdevHWRestore(pScrn); 3306 return; 3307 } 3308 3309 R128Blank(pScrn); 3310 3311 if (!info->IsSecondary) { 3312 OUTREG(R128_AMCGPIO_MASK, restore->amcgpio_mask); 3313 OUTREG(R128_AMCGPIO_EN_REG, restore->amcgpio_en_reg); 3314 OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index); 3315 OUTREG(R128_GEN_RESET_CNTL, restore->gen_reset_cntl); 3316 OUTREG(R128_DP_DATATYPE, restore->dp_datatype); 3317 } 3318 3319 R128RestoreMode(pScrn, restore); 3320#ifdef WITH_VGAHW 3321 if (info->VGAAccess) { 3322 vgaHWPtr hwp = VGAHWPTR(pScrn); 3323 if (!info->IsSecondary) { 3324 vgaHWUnlock(hwp); 3325# if defined(__powerpc__) 3326 /* Temporary hack to prevent crashing on PowerMacs when trying to 3327 * write VGA fonts, will find a better solution in the future 3328 */ 3329 vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE ); 3330# else 3331 vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); 3332# endif 3333 vgaHWLock(hwp); 3334 } else { 3335 R128EntPtr pR128Ent = R128EntPriv(pScrn); 3336 ScrnInfoPtr pScrn0 = pR128Ent->pPrimaryScrn; 3337 R128InfoPtr info0 = R128PTR(pScrn0); 3338 vgaHWPtr hwp0; 3339 3340 if (info0->VGAAccess) { 3341 hwp0 = VGAHWPTR(pScrn0); 3342 vgaHWUnlock(hwp0); 3343#if defined(__powerpc__) 3344 vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE); 3345#else 3346 vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); 3347#endif 3348 vgaHWLock(hwp0); 3349 } 3350 } 3351 } 3352#endif 3353 3354 R128WaitForVerticalSync(pScrn); 3355 R128Unblank(pScrn); 3356} 3357 3358/* Define common registers for requested video mode. */ 3359static void R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info) 3360{ 3361 save->ovr_clr = 0; 3362 save->ovr_wid_left_right = 0; 3363 save->ovr_wid_top_bottom = 0; 3364 save->ov0_scale_cntl = 0; 3365 save->mpp_tb_config = 0; 3366 save->mpp_gp_config = 0; 3367 save->subpic_cntl = 0; 3368 save->viph_control = 0; 3369 save->i2c_cntl_1 = 0; 3370#ifdef XF86DRI 3371 save->gen_int_cntl = info->gen_int_cntl; 3372#else 3373 save->gen_int_cntl = 0; 3374#endif 3375 save->cap0_trig_cntl = 0; 3376 save->cap1_trig_cntl = 0; 3377 save->bus_cntl = info->BusCntl; 3378 /* 3379 * If bursts are enabled, turn on discards and aborts 3380 */ 3381 if (save->bus_cntl & (R128_BUS_WRT_BURST|R128_BUS_READ_BURST)) 3382 save->bus_cntl |= R128_BUS_RD_DISCARD_EN | R128_BUS_RD_ABORT_EN; 3383} 3384 3385/* Define CRTC registers for requested video mode. */ 3386static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, 3387 DisplayModePtr mode, R128InfoPtr info) 3388{ 3389 int format; 3390 int hsync_start; 3391 int hsync_wid; 3392 int hsync_fudge; 3393 int vsync_wid; 3394 int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; 3395 int hsync_fudge_fp[] = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 }; 3396// int hsync_fudge_fp_crt[] = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 }; 3397 3398 switch (info->CurrentLayout.pixel_code) { 3399 case 4: format = 1; break; 3400 case 8: format = 2; break; 3401 case 15: format = 3; break; /* 555 */ 3402 case 16: format = 4; break; /* 565 */ 3403 case 24: format = 5; break; /* RGB */ 3404 case 32: format = 6; break; /* xRGB */ 3405 default: 3406 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 3407 "Unsupported pixel depth (%d)\n", 3408 info->CurrentLayout.bitsPerPixel); 3409 return FALSE; 3410 } 3411 3412 if ((info->DisplayType == MT_DFP) || 3413 (info->DisplayType == MT_LCD)) 3414 hsync_fudge = hsync_fudge_fp[format-1]; 3415 else 3416 hsync_fudge = hsync_fudge_default[format-1]; 3417 3418 save->crtc_gen_cntl = (R128_CRTC_EXT_DISP_EN 3419 | R128_CRTC_EN 3420 | (format << 8) 3421 | ((mode->Flags & V_DBLSCAN) 3422 ? R128_CRTC_DBL_SCAN_EN 3423 : 0) 3424 | ((mode->Flags & V_INTERLACE) 3425 ? R128_CRTC_INTERLACE_EN 3426 : 0) 3427 | ((mode->Flags & V_CSYNC) 3428 ? R128_CRTC_CSYNC_EN 3429 : 0)); 3430 3431 if((info->DisplayType == MT_DFP) || 3432 (info->DisplayType == MT_LCD)) 3433 { 3434 save->crtc_ext_cntl = R128_VGA_ATI_LINEAR | 3435 R128_XCRT_CNT_EN; 3436 save->crtc_gen_cntl &= ~(R128_CRTC_DBL_SCAN_EN | 3437 R128_CRTC_INTERLACE_EN); 3438 } 3439 else 3440 save->crtc_ext_cntl = R128_VGA_ATI_LINEAR | 3441 R128_XCRT_CNT_EN | 3442 R128_CRTC_CRT_ON; 3443 3444 save->dac_cntl = (R128_DAC_MASK_ALL 3445 | R128_DAC_VGA_ADR_EN 3446 | (info->dac6bits ? 0 : R128_DAC_8BIT_EN)); 3447 3448 3449 if(info->isDFP && !info->isPro2) 3450 { 3451 if(info->PanelXRes < mode->CrtcHDisplay) 3452 mode->HDisplay = mode->CrtcHDisplay = info->PanelXRes; 3453 if(info->PanelYRes < mode->CrtcVDisplay) 3454 mode->VDisplay = mode->CrtcVDisplay = info->PanelYRes; 3455 mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank; 3456 mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus; 3457 mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth; 3458 mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank; 3459 mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus; 3460 mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth; 3461 } 3462 3463 save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff) 3464 | (((mode->CrtcHDisplay / 8) - 1) << 16)); 3465 3466 hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; 3467 if (!hsync_wid) hsync_wid = 1; 3468 if (hsync_wid > 0x3f) hsync_wid = 0x3f; 3469 3470 hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge; 3471 3472 save->crtc_h_sync_strt_wid = ((hsync_start & 0xfff) 3473 | (hsync_wid << 16) 3474 | ((mode->Flags & V_NHSYNC) 3475 ? R128_CRTC_H_SYNC_POL 3476 : 0)); 3477 3478#if 1 3479 /* This works for double scan mode. */ 3480 save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 3481 | ((mode->CrtcVDisplay - 1) << 16)); 3482#else 3483 /* This is what cce/nbmode.c example code 3484 does -- is this correct? */ 3485 save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 3486 | ((mode->CrtcVDisplay 3487 * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1) 3488 << 16)); 3489#endif 3490 3491 vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 3492 if (!vsync_wid) vsync_wid = 1; 3493 if (vsync_wid > 0x1f) vsync_wid = 0x1f; 3494 3495 save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) 3496 | (vsync_wid << 16) 3497 | ((mode->Flags & V_NVSYNC) 3498 ? R128_CRTC_V_SYNC_POL 3499 : 0)); 3500 save->crtc_offset = 0; 3501 save->crtc_offset_cntl = 0; 3502 save->crtc_pitch = info->CurrentLayout.displayWidth / 8; 3503 3504 R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", 3505 save->crtc_pitch, pScrn->virtualX, info->CurrentLayout.displayWidth)); 3506 3507#if X_BYTE_ORDER == X_BIG_ENDIAN 3508 /* Change the endianness of the aperture */ 3509 switch (info->CurrentLayout.pixel_code) { 3510 case 15: 3511 case 16: save->config_cntl |= APER_0_BIG_ENDIAN_16BPP_SWAP; break; 3512 case 32: save->config_cntl |= APER_0_BIG_ENDIAN_32BPP_SWAP; break; 3513 default: break; 3514 } 3515#endif 3516 3517 return TRUE; 3518} 3519 3520/* Define CRTC2 registers for requested video mode. */ 3521static Bool R128InitCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save, 3522 DisplayModePtr mode, R128InfoPtr info) 3523{ 3524 int format; 3525 int hsync_start; 3526 int hsync_wid; 3527 int hsync_fudge; 3528 int vsync_wid; 3529 int bytpp; 3530 int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; 3531 3532 switch (info->CurrentLayout.pixel_code) { 3533 case 4: format = 1; bytpp = 0; break; 3534 case 8: format = 2; bytpp = 1; break; 3535 case 15: format = 3; bytpp = 2; break; /* 555 */ 3536 case 16: format = 4; bytpp = 2; break; /* 565 */ 3537 case 24: format = 5; bytpp = 3; break; /* RGB */ 3538 case 32: format = 6; bytpp = 4; break; /* xRGB */ 3539 default: 3540 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 3541 "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel); 3542 return FALSE; 3543 } 3544 R128TRACE(("Format = %d (%d bytes per pixel)\n", format, bytpp)); 3545 3546 hsync_fudge = hsync_fudge_default[format-1]; 3547 3548 save->crtc2_gen_cntl = (R128_CRTC2_EN 3549 | (format << 8) 3550 | ((mode->Flags & V_DBLSCAN) 3551 ? R128_CRTC2_DBL_SCAN_EN 3552 : 0)); 3553/* 3554 save->crtc2_gen_cntl &= ~R128_CRTC_EXT_DISP_EN; 3555 save->crtc2_gen_cntl |= (1 << 21); 3556*/ 3557 save->crtc2_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff) 3558 | (((mode->CrtcHDisplay / 8) - 1) << 16)); 3559 3560 hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; 3561 if (!hsync_wid) hsync_wid = 1; 3562 if (hsync_wid > 0x3f) hsync_wid = 0x3f; 3563 3564 hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge; 3565 3566 save->crtc2_h_sync_strt_wid = ((hsync_start & 0xfff) 3567 | (hsync_wid << 16) 3568 | ((mode->Flags & V_NHSYNC) 3569 ? R128_CRTC2_H_SYNC_POL 3570 : 0)); 3571 3572#if 1 3573 /* This works for double scan mode. */ 3574 save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 3575 | ((mode->CrtcVDisplay - 1) << 16)); 3576#else 3577 /* This is what cce/nbmode.c example code 3578 does -- is this correct? */ 3579 save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 3580 | ((mode->CrtcVDisplay 3581 * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1) 3582 << 16)); 3583#endif 3584 3585 vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 3586 if (!vsync_wid) vsync_wid = 1; 3587 if (vsync_wid > 0x1f) vsync_wid = 0x1f; 3588 3589 save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) 3590 | (vsync_wid << 16) 3591 | ((mode->Flags & V_NVSYNC) 3592 ? R128_CRTC2_V_SYNC_POL 3593 : 0)); 3594 3595 save->crtc2_offset = 0; 3596 save->crtc2_offset_cntl = 0; 3597 3598 save->crtc2_pitch = info->CurrentLayout.displayWidth / 8; 3599 3600 R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", 3601 save->crtc2_pitch, pScrn->virtualX, 3602 info->CurrentLayout.displayWidth)); 3603 return TRUE; 3604} 3605 3606/* Define CRTC registers for requested video mode. */ 3607static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, 3608 DisplayModePtr mode, R128InfoPtr info) 3609{ 3610 int xres = mode->CrtcHDisplay; 3611 int yres = mode->CrtcVDisplay; 3612 float Hratio, Vratio; 3613 3614 if (info->BIOSDisplay == R128_BIOS_DISPLAY_CRT) { 3615 save->crtc_ext_cntl |= R128_CRTC_CRT_ON; 3616 save->crtc2_gen_cntl = 0; 3617 save->fp_gen_cntl = orig->fp_gen_cntl; 3618 save->fp_gen_cntl &= ~(R128_FP_FPON | 3619 R128_FP_CRTC_USE_SHADOW_VEND | 3620 R128_FP_CRTC_HORZ_DIV2_EN | 3621 R128_FP_CRTC_HOR_CRT_DIV2_DIS | 3622 R128_FP_USE_SHADOW_EN); 3623 save->fp_gen_cntl |= (R128_FP_SEL_CRTC2 | 3624 R128_FP_CRTC_DONT_SHADOW_VPAR); 3625 save->fp_panel_cntl = orig->fp_panel_cntl & (CARD32)~R128_FP_DIGON; 3626 save->lvds_gen_cntl = orig->lvds_gen_cntl & 3627 (CARD32)~(R128_LVDS_ON | R128_LVDS_BLON); 3628 return; 3629 } 3630 3631 if (xres > info->PanelXRes) xres = info->PanelXRes; 3632 if (yres > info->PanelYRes) yres = info->PanelYRes; 3633 3634 Hratio = (float)xres/(float)info->PanelXRes; 3635 Vratio = (float)yres/(float)info->PanelYRes; 3636 3637 save->fp_horz_stretch = 3638 (((((int)(Hratio * R128_HORZ_STRETCH_RATIO_MAX + 0.5)) 3639 & R128_HORZ_STRETCH_RATIO_MASK) << R128_HORZ_STRETCH_RATIO_SHIFT) | 3640 (orig->fp_horz_stretch & (R128_HORZ_PANEL_SIZE | 3641 R128_HORZ_FP_LOOP_STRETCH | 3642 R128_HORZ_STRETCH_RESERVED))); 3643 save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN; 3644 save->fp_horz_stretch &= ~R128_AUTO_HORZ_RATIO; 3645 if (xres == info->PanelXRes) 3646 save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE); 3647 else 3648 save->fp_horz_stretch |= (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE); 3649 3650 save->fp_vert_stretch = 3651 (((((int)(Vratio * R128_VERT_STRETCH_RATIO_MAX + 0.5)) 3652 & R128_VERT_STRETCH_RATIO_MASK) << R128_VERT_STRETCH_RATIO_SHIFT) | 3653 (orig->fp_vert_stretch & (R128_VERT_PANEL_SIZE | 3654 R128_VERT_STRETCH_RESERVED))); 3655 save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN; 3656 if (yres == info->PanelYRes) 3657 save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND); 3658 else 3659 save->fp_vert_stretch |= (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND); 3660 3661 save->fp_gen_cntl = (orig->fp_gen_cntl & 3662 (CARD32)~(R128_FP_SEL_CRTC2 | 3663 R128_FP_CRTC_USE_SHADOW_VEND | 3664 R128_FP_CRTC_HORZ_DIV2_EN | 3665 R128_FP_CRTC_HOR_CRT_DIV2_DIS | 3666 R128_FP_USE_SHADOW_EN)); 3667 3668 save->fp_panel_cntl = orig->fp_panel_cntl; 3669 save->lvds_gen_cntl = orig->lvds_gen_cntl; 3670 save->tmds_crc = orig->tmds_crc; 3671 3672 /* Disable CRT output by disabling CRT output and setting the CRT 3673 DAC to use CRTC2, which we set to 0's. In the future, we will 3674 want to use the dual CRTC capabilities of the R128 to allow both 3675 the flat panel and external CRT to either simultaneously display 3676 the same image or display two different images. */ 3677 3678 3679 if(!info->isDFP){ 3680 if (info->BIOSDisplay == R128_BIOS_DISPLAY_FP_CRT) { 3681 save->crtc_ext_cntl |= R128_CRTC_CRT_ON; 3682 } else if (info->BIOSDisplay == R128_DUALHEAD) { 3683 save->crtc_ext_cntl |= R128_CRTC_CRT_ON; 3684 save->dac_cntl |= R128_DAC_CRT_SEL_CRTC2; 3685 save->dac_cntl |= R128_DAC_PALETTE2_SNOOP_EN; 3686 } else { 3687 save->crtc_ext_cntl &= ~R128_CRTC_CRT_ON; 3688 save->dac_cntl |= R128_DAC_CRT_SEL_CRTC2; 3689 save->crtc2_gen_cntl = 0; 3690 } 3691 } 3692 3693 /* WARNING: Be careful about turning on the flat panel */ 3694 if(info->isDFP){ 3695 save->fp_gen_cntl = orig->fp_gen_cntl; 3696 3697 save->fp_gen_cntl &= ~(R128_FP_CRTC_USE_SHADOW_VEND | 3698 R128_FP_CRTC_USE_SHADOW_ROWCUR | 3699 R128_FP_CRTC_HORZ_DIV2_EN | 3700 R128_FP_CRTC_HOR_CRT_DIV2_DIS | 3701 R128_FP_CRT_SYNC_SEL | 3702 R128_FP_USE_SHADOW_EN); 3703 3704 save->fp_panel_cntl |= (R128_FP_DIGON | R128_FP_BLON); 3705 save->fp_gen_cntl |= (R128_FP_FPON | R128_FP_TDMS_EN | 3706 R128_FP_CRTC_DONT_SHADOW_VPAR | R128_FP_CRTC_DONT_SHADOW_HEND); 3707 save->tmds_transmitter_cntl = (orig->tmds_transmitter_cntl 3708 & ~(CARD32)R128_TMDS_PLLRST) | R128_TMDS_PLLEN; 3709 } 3710 else 3711 save->lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_BLON); 3712 3713 save->fp_crtc_h_total_disp = save->crtc_h_total_disp; 3714 save->fp_crtc_v_total_disp = save->crtc_v_total_disp; 3715 save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; 3716 save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; 3717} 3718 3719/* Define PLL registers for requested video mode. */ 3720static void R128InitPLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save, 3721 R128PLLPtr pll, double dot_clock) 3722{ 3723 unsigned long freq = dot_clock * 100; 3724 struct { 3725 int divider; 3726 int bitvalue; 3727 } *post_div, 3728 post_divs[] = { 3729 /* From RAGE 128 VR/RAGE 128 GL Register 3730 Reference Manual (Technical Reference 3731 Manual P/N RRG-G04100-C Rev. 0.04), page 3732 3-17 (PLL_DIV_[3:0]). */ 3733 { 1, 0 }, /* VCLK_SRC */ 3734 { 2, 1 }, /* VCLK_SRC/2 */ 3735 { 4, 2 }, /* VCLK_SRC/4 */ 3736 { 8, 3 }, /* VCLK_SRC/8 */ 3737 3738 { 3, 4 }, /* VCLK_SRC/3 */ 3739 /* bitvalue = 5 is reserved */ 3740 { 6, 6 }, /* VCLK_SRC/6 */ 3741 { 12, 7 }, /* VCLK_SRC/12 */ 3742 { 0, 0 } 3743 }; 3744 3745 if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; 3746 if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; 3747 3748 for (post_div = &post_divs[0]; post_div->divider; ++post_div) { 3749 save->pll_output_freq = post_div->divider * freq; 3750 if (save->pll_output_freq >= pll->min_pll_freq 3751 && save->pll_output_freq <= pll->max_pll_freq) break; 3752 } 3753 3754 save->dot_clock_freq = freq; 3755 save->feedback_div = R128Div(pll->reference_div * save->pll_output_freq, 3756 pll->reference_freq); 3757 save->post_div = post_div->divider; 3758 3759 R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n", 3760 save->dot_clock_freq, 3761 save->pll_output_freq, 3762 save->feedback_div, 3763 save->post_div)); 3764 3765 save->ppll_ref_div = pll->reference_div; 3766 save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); 3767 save->htotal_cntl = 0; 3768 3769} 3770 3771/* Define PLL2 registers for requested video mode. */ 3772static void R128InitPLL2Registers(R128SavePtr save, R128PLLPtr pll, 3773 double dot_clock) 3774{ 3775 unsigned long freq = dot_clock * 100; 3776 struct { 3777 int divider; 3778 int bitvalue; 3779 } *post_div, 3780 post_divs[] = { 3781 /* From RAGE 128 VR/RAGE 128 GL Register 3782 Reference Manual (Technical Reference 3783 Manual P/N RRG-G04100-C Rev. 0.04), page 3784 3-17 (PLL_DIV_[3:0]). */ 3785 { 1, 0 }, /* VCLK_SRC */ 3786 { 2, 1 }, /* VCLK_SRC/2 */ 3787 { 4, 2 }, /* VCLK_SRC/4 */ 3788 { 8, 3 }, /* VCLK_SRC/8 */ 3789 3790 { 3, 4 }, /* VCLK_SRC/3 */ 3791 /* bitvalue = 5 is reserved */ 3792 { 6, 6 }, /* VCLK_SRC/6 */ 3793 { 12, 7 }, /* VCLK_SRC/12 */ 3794 { 0, 0 } 3795 }; 3796 3797 if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; 3798 if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; 3799 3800 for (post_div = &post_divs[0]; post_div->divider; ++post_div) { 3801 save->pll_output_freq_2 = post_div->divider * freq; 3802 if (save->pll_output_freq_2 >= pll->min_pll_freq 3803 && save->pll_output_freq_2 <= pll->max_pll_freq) break; 3804 } 3805 3806 save->dot_clock_freq_2 = freq; 3807 save->feedback_div_2 = R128Div(pll->reference_div 3808 * save->pll_output_freq_2, 3809 pll->reference_freq); 3810 save->post_div_2 = post_div->divider; 3811 3812 R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n", 3813 save->dot_clock_freq_2, 3814 save->pll_output_freq_2, 3815 save->feedback_div_2, 3816 save->post_div_2)); 3817 3818 save->p2pll_ref_div = pll->reference_div; 3819 save->p2pll_div_0 = (save->feedback_div_2 | (post_div->bitvalue<<16)); 3820 save->htotal_cntl2 = 0; 3821} 3822 3823/* Define DDA registers for requested video mode. */ 3824static Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save, 3825 R128PLLPtr pll, R128InfoPtr info, 3826 DisplayModePtr mode) 3827{ 3828 int DisplayFifoWidth = 128; 3829 int DisplayFifoDepth = 32; 3830 int XclkFreq; 3831 int VclkFreq; 3832 int XclksPerTransfer; 3833 int XclksPerTransferPrecise; 3834 int UseablePrecision; 3835 int Roff; 3836 int Ron; 3837 3838 XclkFreq = pll->xclk; 3839 3840 VclkFreq = R128Div(pll->reference_freq * save->feedback_div, 3841 pll->reference_div * save->post_div); 3842 3843 if(info->isDFP && !info->isPro2){ 3844 if(info->PanelXRes != mode->CrtcHDisplay) 3845 VclkFreq = (VclkFreq * mode->CrtcHDisplay)/info->PanelXRes; 3846 } 3847 3848 XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth, 3849 VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); 3850 3851 UseablePrecision = R128MinBits(XclksPerTransfer) + 1; 3852 3853 XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth) 3854 << (11 - UseablePrecision), 3855 VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); 3856 3857 Roff = XclksPerTransferPrecise * (DisplayFifoDepth - 4); 3858 3859 Ron = (4 * info->ram->MB 3860 + 3 * MAX(info->ram->Trcd - 2, 0) 3861 + 2 * info->ram->Trp 3862 + info->ram->Twr 3863 + info->ram->CL 3864 + info->ram->Tr2w 3865 + XclksPerTransfer) << (11 - UseablePrecision); 3866 3867 if (Ron + info->ram->Rloop >= Roff) { 3868 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 3869 "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n", 3870 Ron, info->ram->Rloop, Roff); 3871 return FALSE; 3872 } 3873 3874 save->dda_config = (XclksPerTransferPrecise 3875 | (UseablePrecision << 16) 3876 | (info->ram->Rloop << 20)); 3877 3878 save->dda_on_off = (Ron << 16) | Roff; 3879 3880 R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n", 3881 XclkFreq, 3882 VclkFreq, 3883 XclksPerTransfer, 3884 XclksPerTransferPrecise, 3885 UseablePrecision)); 3886 R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n", 3887 Roff, Ron, info->ram->Rloop)); 3888 3889 return TRUE; 3890} 3891 3892/* Define DDA2 registers for requested video mode. */ 3893static Bool R128InitDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save, 3894 R128PLLPtr pll, R128InfoPtr info, 3895 DisplayModePtr mode) 3896{ 3897 int DisplayFifoWidth = 128; 3898 int DisplayFifoDepth = 32; 3899 int XclkFreq; 3900 int VclkFreq; 3901 int XclksPerTransfer; 3902 int XclksPerTransferPrecise; 3903 int UseablePrecision; 3904 int Roff; 3905 int Ron; 3906 3907 XclkFreq = pll->xclk; 3908 3909 VclkFreq = R128Div(pll->reference_freq * save->feedback_div_2, 3910 pll->reference_div * save->post_div_2); 3911 3912 if(info->isDFP && !info->isPro2){ 3913 if(info->PanelXRes != mode->CrtcHDisplay) 3914 VclkFreq = (VclkFreq * mode->CrtcHDisplay)/info->PanelXRes; 3915 } 3916 3917 XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth, 3918 VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); 3919 3920 UseablePrecision = R128MinBits(XclksPerTransfer) + 1; 3921 3922 XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth) 3923 << (11 - UseablePrecision), 3924 VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); 3925 3926 Roff = XclksPerTransferPrecise * (DisplayFifoDepth - 4); 3927 3928 Ron = (4 * info->ram->MB 3929 + 3 * MAX(info->ram->Trcd - 2, 0) 3930 + 2 * info->ram->Trp 3931 + info->ram->Twr 3932 + info->ram->CL 3933 + info->ram->Tr2w 3934 + XclksPerTransfer) << (11 - UseablePrecision); 3935 3936 3937 if (Ron + info->ram->Rloop >= Roff) { 3938 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 3939 "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n", 3940 Ron, info->ram->Rloop, Roff); 3941 return FALSE; 3942 } 3943 3944 save->dda2_config = (XclksPerTransferPrecise 3945 | (UseablePrecision << 16) 3946 | (info->ram->Rloop << 20)); 3947 3948 /*save->dda2_on_off = (Ron << 16) | Roff;*/ 3949 /* shift most be 18 otherwise there's corruption on crtc2 */ 3950 save->dda2_on_off = (Ron << 18) | Roff; 3951 3952 R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n", 3953 XclkFreq, 3954 VclkFreq, 3955 XclksPerTransfer, 3956 XclksPerTransferPrecise, 3957 UseablePrecision)); 3958 R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n", 3959 Roff, Ron, info->ram->Rloop)); 3960 3961 return TRUE; 3962} 3963 3964#if 0 3965/* Define initial palette for requested video mode. This doesn't do 3966 anything for XFree86 4.0. */ 3967static void R128InitPalette(R128SavePtr save) 3968{ 3969 save->palette_valid = FALSE; 3970} 3971#endif 3972 3973/* Define registers for a requested video mode. */ 3974static Bool R128Init(ScrnInfoPtr pScrn, DisplayModePtr mode, R128SavePtr save) 3975{ 3976 R128InfoPtr info = R128PTR(pScrn); 3977 double dot_clock = mode->Clock/1000.0; 3978 3979#if R128_DEBUG 3980 ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", 3981 mode->name, 3982 dot_clock, 3983 3984 mode->HDisplay, 3985 mode->HSyncStart, 3986 mode->HSyncEnd, 3987 mode->HTotal, 3988 3989 mode->VDisplay, 3990 mode->VSyncStart, 3991 mode->VSyncEnd, 3992 mode->VTotal, 3993 pScrn->depth, 3994 pScrn->bitsPerPixel); 3995 if (mode->Flags & V_DBLSCAN) ErrorF(" D"); 3996 if (mode->Flags & V_CSYNC) ErrorF(" C"); 3997 if (mode->Flags & V_INTERLACE) ErrorF(" I"); 3998 if (mode->Flags & V_PHSYNC) ErrorF(" +H"); 3999 if (mode->Flags & V_NHSYNC) ErrorF(" -H"); 4000 if (mode->Flags & V_PVSYNC) ErrorF(" +V"); 4001 if (mode->Flags & V_NVSYNC) ErrorF(" -V"); 4002 ErrorF("\n"); 4003 ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", 4004 mode->name, 4005 dot_clock, 4006 4007 mode->CrtcHDisplay, 4008 mode->CrtcHSyncStart, 4009 mode->CrtcHSyncEnd, 4010 mode->CrtcHTotal, 4011 4012 mode->CrtcVDisplay, 4013 mode->CrtcVSyncStart, 4014 mode->CrtcVSyncEnd, 4015 mode->CrtcVTotal, 4016 pScrn->depth, 4017 pScrn->bitsPerPixel); 4018 if (mode->Flags & V_DBLSCAN) ErrorF(" D"); 4019 if (mode->Flags & V_CSYNC) ErrorF(" C"); 4020 if (mode->Flags & V_INTERLACE) ErrorF(" I"); 4021 if (mode->Flags & V_PHSYNC) ErrorF(" +H"); 4022 if (mode->Flags & V_NHSYNC) ErrorF(" -H"); 4023 if (mode->Flags & V_PVSYNC) ErrorF(" +V"); 4024 if (mode->Flags & V_NVSYNC) ErrorF(" -V"); 4025 ErrorF("\n"); 4026#endif 4027 4028 info->Flags = mode->Flags; 4029 4030 if(info->IsSecondary) 4031 { 4032 if (!R128InitCrtc2Registers(pScrn, save, 4033 pScrn->currentMode,info)) 4034 return FALSE; 4035 R128InitPLL2Registers(save, &info->pll, dot_clock); 4036 if (!R128InitDDA2Registers(pScrn, save, &info->pll, info, mode)) 4037 return FALSE; 4038 } 4039 else 4040 { 4041 R128InitCommonRegisters(save, info); 4042 if(!R128InitCrtcRegisters(pScrn, save, mode, info)) 4043 return FALSE; 4044 if(dot_clock) 4045 { 4046 R128InitPLLRegisters(pScrn, save, &info->pll, dot_clock); 4047 if (!R128InitDDARegisters(pScrn, save, &info->pll, info, mode)) 4048 return FALSE; 4049 } 4050 else 4051 { 4052 save->ppll_ref_div = info->SavedReg.ppll_ref_div; 4053 save->ppll_div_3 = info->SavedReg.ppll_div_3; 4054 save->htotal_cntl = info->SavedReg.htotal_cntl; 4055 save->dda_config = info->SavedReg.dda_config; 4056 save->dda_on_off = info->SavedReg.dda_on_off; 4057 } 4058 /* not used for now */ 4059 /*if (!info->PaletteSavedOnVT) RADEONInitPalette(save);*/ 4060 } 4061 4062 if (((info->DisplayType == MT_DFP) || 4063 (info->DisplayType == MT_LCD))) 4064 { 4065 R128InitFPRegisters(&info->SavedReg, save, mode, info); 4066 } 4067 4068 R128TRACE(("R128Init returns %p\n", save)); 4069 return TRUE; 4070} 4071 4072/* Initialize a new mode. */ 4073static Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 4074{ 4075 R128InfoPtr info = R128PTR(pScrn); 4076 4077 if (!R128Init(pScrn, mode, &info->ModeReg)) return FALSE; 4078 /* FIXME? DRILock/DRIUnlock here? */ 4079 pScrn->vtSema = TRUE; 4080 R128Blank(pScrn); 4081 R128RestoreMode(pScrn, &info->ModeReg); 4082 R128Unblank(pScrn); 4083 4084 info->CurrentLayout.mode = mode; 4085 4086 return TRUE; 4087} 4088 4089static Bool R128SaveScreen(ScreenPtr pScreen, int mode) 4090{ 4091 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 4092 Bool unblank; 4093 4094 unblank = xf86IsUnblank(mode); 4095 if (unblank) 4096 SetTimeSinceLastInputEvent(); 4097 4098 if ((pScrn != NULL) && pScrn->vtSema) { 4099 if (unblank) 4100 R128Unblank(pScrn); 4101 else 4102 R128Blank(pScrn); 4103 } 4104 return TRUE; 4105} 4106 4107/* 4108 * SwitchMode() doesn't work right on crtc2 on some laptops. 4109 * The workaround is to switch the mode, then switch to another VT, then 4110 * switch back. --AGD 4111 */ 4112Bool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 4113{ 4114 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4115 R128InfoPtr info = R128PTR(pScrn); 4116 Bool ret; 4117 4118 info->SwitchingMode = TRUE; 4119 ret = R128ModeInit(xf86Screens[scrnIndex], mode); 4120 info->SwitchingMode = FALSE; 4121 return ret; 4122} 4123 4124/* Used to disallow modes that are not supported by the hardware. */ 4125ModeStatus R128ValidMode(int scrnIndex, DisplayModePtr mode, 4126 Bool verbose, int flags) 4127{ 4128 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4129 R128InfoPtr info = R128PTR(pScrn); 4130 4131 if (info->BIOSDisplay == R128_BIOS_DISPLAY_CRT) 4132 return MODE_OK; 4133 4134 if(info->isDFP) { 4135 if(info->PanelXRes < mode->CrtcHDisplay || 4136 info->PanelYRes < mode->CrtcVDisplay) 4137 return MODE_NOMODE; 4138 else 4139 return MODE_OK; 4140 } 4141 4142 if (info->DisplayType == MT_LCD) { 4143 if (mode->Flags & V_INTERLACE) return MODE_NO_INTERLACE; 4144 if (mode->Flags & V_DBLSCAN) return MODE_NO_DBLESCAN; 4145 } 4146 4147 if (info->DisplayType == MT_LCD && 4148 info->VBIOS) { 4149 int i; 4150 for (i = info->FPBIOSstart+64; R128_BIOS16(i) != 0; i += 2) { 4151 int j = R128_BIOS16(i); 4152 4153 if (mode->CrtcHDisplay == R128_BIOS16(j) && 4154 mode->CrtcVDisplay == R128_BIOS16(j+2)) { 4155 if ((flags & MODECHECK_FINAL) == MODECHECK_FINAL) { 4156 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4157 "Modifying mode according to VBIOS: %ix%i [pclk %.1f MHz] for FP to: ", 4158 mode->CrtcHDisplay,mode->CrtcVDisplay, 4159 (float)mode->Clock/1000); 4160 4161 /* Assume we are using expanded mode */ 4162 if (R128_BIOS16(j+5)) j = R128_BIOS16(j+5); 4163 else j += 9; 4164 4165 mode->Clock = (CARD32)R128_BIOS16(j) * 10; 4166 4167 mode->HDisplay = mode->CrtcHDisplay = 4168 ((R128_BIOS16(j+10) & 0x01ff)+1)*8; 4169 mode->HSyncStart = mode->CrtcHSyncStart = 4170 ((R128_BIOS16(j+12) & 0x01ff)+1)*8; 4171 mode->HSyncEnd = mode->CrtcHSyncEnd = 4172 mode->CrtcHSyncStart + (R128_BIOS8(j+14) & 0x1f); 4173 mode->HTotal = mode->CrtcHTotal = 4174 ((R128_BIOS16(j+8) & 0x01ff)+1)*8; 4175 4176 mode->VDisplay = mode->CrtcVDisplay = 4177 (R128_BIOS16(j+17) & 0x07ff)+1; 4178 mode->VSyncStart = mode->CrtcVSyncStart = 4179 (R128_BIOS16(j+19) & 0x07ff)+1; 4180 mode->VSyncEnd = mode->CrtcVSyncEnd = 4181 mode->CrtcVSyncStart + ((R128_BIOS16(j+19) >> 11) & 0x1f); 4182 mode->VTotal = mode->CrtcVTotal = 4183 (R128_BIOS16(j+15) & 0x07ff)+1; 4184 xf86ErrorF("%ix%i [pclk %.1f MHz]\n", 4185 mode->CrtcHDisplay,mode->CrtcVDisplay, 4186 (float)mode->Clock/1000); 4187 } 4188 return MODE_OK; 4189 } 4190 } 4191 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, 4192 "Mode rejected for FP %ix%i [pclk: %.1f] " 4193 "(not listed in VBIOS)\n", 4194 mode->CrtcHDisplay, mode->CrtcVDisplay, 4195 (float)mode->Clock / 1000); 4196 return MODE_NOMODE; 4197 } 4198 4199 return MODE_OK; 4200} 4201 4202/* Adjust viewport into virtual desktop such that (0,0) in viewport space 4203 is (x,y) in virtual space. */ 4204void R128AdjustFrame(int scrnIndex, int x, int y, int flags) 4205{ 4206 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4207 R128InfoPtr info = R128PTR(pScrn); 4208 unsigned char *R128MMIO = info->MMIO; 4209 int Base; 4210 4211 if(info->showCache && y && pScrn->vtSema) 4212 y += pScrn->virtualY - 1; 4213 4214 Base = y * info->CurrentLayout.displayWidth + x; 4215 4216 switch (info->CurrentLayout.pixel_code) { 4217 case 15: 4218 case 16: Base *= 2; break; 4219 case 24: Base *= 3; break; 4220 case 32: Base *= 4; break; 4221 } 4222 4223 Base &= ~7; /* 3 lower bits are always 0 */ 4224 4225 if (info->CurrentLayout.pixel_code == 24) 4226 Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */ 4227 4228 if(info->IsSecondary) 4229 { 4230 Base += pScrn->fbOffset; 4231 OUTREG(R128_CRTC2_OFFSET, Base); 4232 } 4233 else 4234 OUTREG(R128_CRTC_OFFSET, Base); 4235 4236} 4237 4238/* Called when VT switching back to the X server. Reinitialize the video 4239 mode. */ 4240Bool R128EnterVT(int scrnIndex, int flags) 4241{ 4242 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4243 R128InfoPtr info = R128PTR(pScrn); 4244 4245 R128TRACE(("R128EnterVT\n")); 4246 if (info->FBDev) { 4247 if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE; 4248 } else 4249 if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE; 4250 if (info->accelOn) 4251 R128EngineInit(pScrn); 4252 4253#ifdef XF86DRI 4254 if (info->directRenderingEnabled) { 4255 if (info->irq) { 4256 /* Need to make sure interrupts are enabled */ 4257 unsigned char *R128MMIO = info->MMIO; 4258 OUTREG(R128_GEN_INT_CNTL, info->gen_int_cntl); 4259 } 4260 R128CCE_START(pScrn, info); 4261 DRIUnlock(pScrn->pScreen); 4262 } 4263#endif 4264 4265 info->PaletteSavedOnVT = FALSE; 4266 pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 4267 4268 return TRUE; 4269} 4270 4271/* Called when VT switching away from the X server. Restore the original 4272 text mode. */ 4273void R128LeaveVT(int scrnIndex, int flags) 4274{ 4275 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4276 R128InfoPtr info = R128PTR(pScrn); 4277 R128SavePtr save = &info->ModeReg; 4278 4279 R128TRACE(("R128LeaveVT\n")); 4280#ifdef XF86DRI 4281 if (info->directRenderingEnabled) { 4282 DRILock(pScrn->pScreen, 0); 4283 R128CCE_STOP(pScrn, info); 4284 } 4285#endif 4286 R128SavePalette(pScrn, save); 4287 info->PaletteSavedOnVT = TRUE; 4288 if (info->FBDev) 4289 fbdevHWLeaveVT(scrnIndex,flags); 4290 else 4291 R128Restore(pScrn); 4292} 4293 4294 4295/* Called at the end of each server generation. Restore the original text 4296 mode, unmap video memory, and unwrap and call the saved CloseScreen 4297 function. */ 4298static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen) 4299{ 4300 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4301 R128InfoPtr info = R128PTR(pScrn); 4302 4303 R128TRACE(("R128CloseScreen\n")); 4304 4305#ifdef XF86DRI 4306 /* Disable direct rendering */ 4307 if (info->directRenderingEnabled) { 4308 R128DRICloseScreen(pScreen); 4309 info->directRenderingEnabled = FALSE; 4310 } 4311#endif 4312 4313 if (pScrn->vtSema) { 4314 R128Restore(pScrn); 4315 R128UnmapMem(pScrn); 4316 } 4317 4318 if (info->accel) XAADestroyInfoRec(info->accel); 4319 info->accel = NULL; 4320 4321 if (info->scratch_save) xfree(info->scratch_save); 4322 info->scratch_save = NULL; 4323 4324 if (info->cursor) xf86DestroyCursorInfoRec(info->cursor); 4325 info->cursor = NULL; 4326 4327 if (info->DGAModes) xfree(info->DGAModes); 4328 info->DGAModes = NULL; 4329 4330 if (info->adaptor) { 4331 xfree(info->adaptor->pPortPrivates[0].ptr); 4332 xf86XVFreeVideoAdaptorRec(info->adaptor); 4333 info->adaptor = NULL; 4334 } 4335 4336 pScrn->vtSema = FALSE; 4337 4338 pScreen->BlockHandler = info->BlockHandler; 4339 pScreen->CloseScreen = info->CloseScreen; 4340 return (*pScreen->CloseScreen)(scrnIndex, pScreen); 4341} 4342 4343void R128FreeScreen(int scrnIndex, int flags) 4344{ 4345 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4346 R128InfoPtr info = R128PTR(pScrn); 4347 4348 R128TRACE(("R128FreeScreen\n")); 4349 if (info == NULL) 4350 return; 4351#ifdef WITH_VGAHW 4352 if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 4353 vgaHWFreeHWRec(pScrn); 4354#endif 4355 R128FreeRec(pScrn); 4356} 4357 4358/* Sets VESA Display Power Management Signaling (DPMS) Mode. */ 4359static void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn, 4360 int PowerManagementMode, int flags) 4361{ 4362 R128InfoPtr info = R128PTR(pScrn); 4363 unsigned char *R128MMIO = info->MMIO; 4364 int mask = (R128_CRTC_DISPLAY_DIS 4365 | R128_CRTC_HSYNC_DIS 4366 | R128_CRTC_VSYNC_DIS); 4367 int mask2 = R128_CRTC2_DISP_DIS; 4368 4369 switch (PowerManagementMode) { 4370 case DPMSModeOn: 4371 /* Screen: On; HSync: On, VSync: On */ 4372 if (info->IsSecondary) 4373 OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~mask2); 4374 else 4375 OUTREGP(R128_CRTC_EXT_CNTL, 0, ~mask); 4376 break; 4377 case DPMSModeStandby: 4378 /* Screen: Off; HSync: Off, VSync: On */ 4379 if (info->IsSecondary) 4380 OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask2); 4381 else 4382 OUTREGP(R128_CRTC_EXT_CNTL, 4383 R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS, ~mask); 4384 break; 4385 case DPMSModeSuspend: 4386 /* Screen: Off; HSync: On, VSync: Off */ 4387 if (info->IsSecondary) 4388 OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask2); 4389 else 4390 OUTREGP(R128_CRTC_EXT_CNTL, 4391 R128_CRTC_DISPLAY_DIS | R128_CRTC_VSYNC_DIS, ~mask); 4392 break; 4393 case DPMSModeOff: 4394 /* Screen: Off; HSync: Off, VSync: Off */ 4395 if (info->IsSecondary) 4396 OUTREGP(R128_CRTC2_GEN_CNTL, mask2, ~mask2); 4397 else 4398 OUTREGP(R128_CRTC_EXT_CNTL, mask, ~mask); 4399 break; 4400 } 4401 if(info->isDFP) { 4402 switch (PowerManagementMode) { 4403 case DPMSModeOn: 4404 OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL) | (R128_FP_FPON | R128_FP_TDMS_EN)); 4405 break; 4406 case DPMSModeStandby: 4407 case DPMSModeSuspend: 4408 case DPMSModeOff: 4409 OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL) & ~(R128_FP_FPON | R128_FP_TDMS_EN)); 4410 break; 4411 } 4412 } 4413} 4414 4415static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on); 4416 4417static void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn, 4418 int PowerManagementMode, int flags) 4419{ 4420 R128InfoPtr info = R128PTR(pScrn); 4421 unsigned char *R128MMIO = info->MMIO; 4422 int mask = R128_LVDS_DISPLAY_DIS; 4423 4424 switch (PowerManagementMode) { 4425 case DPMSModeOn: 4426 /* Screen: On; HSync: On, VSync: On */ 4427 OUTREGP(R128_LVDS_GEN_CNTL, 0, ~mask); 4428 r128_set_backlight_enable(pScrn, 1); 4429 break; 4430 case DPMSModeStandby: 4431 /* Fall through */ 4432 case DPMSModeSuspend: 4433 /* Fall through */ 4434 break; 4435 case DPMSModeOff: 4436 /* Screen: Off; HSync: Off, VSync: Off */ 4437 OUTREGP(R128_LVDS_GEN_CNTL, mask, ~mask); 4438 r128_set_backlight_enable(pScrn, 0); 4439 break; 4440 } 4441} 4442 4443static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on) 4444{ 4445 R128InfoPtr info = R128PTR(pScrn); 4446 unsigned char *R128MMIO = info->MMIO; 4447 unsigned int lvds_gen_cntl = INREG(R128_LVDS_GEN_CNTL); 4448 4449 lvds_gen_cntl |= (/*R128_LVDS_BL_MOD_EN |*/ R128_LVDS_BLON); 4450 if (on) { 4451 lvds_gen_cntl |= R128_LVDS_DIGON; 4452 if (!(lvds_gen_cntl & R128_LVDS_ON)) { 4453 lvds_gen_cntl &= ~R128_LVDS_BLON; 4454 OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); 4455 (void)INREG(R128_LVDS_GEN_CNTL); 4456 usleep(10000); 4457 lvds_gen_cntl |= R128_LVDS_BLON; 4458 OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); 4459 } 4460#if 0 4461 lvds_gen_cntl &= ~R128_LVDS_BL_MOD_LEVEL_MASK; 4462 lvds_gen_cntl |= (0xFF /* backlight_conv[level] */ << 4463 R128_LVDS_BL_MOD_LEVEL_SHIFT); 4464#endif 4465 lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_EN); 4466 lvds_gen_cntl &= ~R128_LVDS_DISPLAY_DIS; 4467 } else { 4468#if 0 4469 lvds_gen_cntl &= ~R128_LVDS_BL_MOD_LEVEL_MASK; 4470 lvds_gen_cntl |= (0xFF /* backlight_conv[0] */ << 4471 R128_LVDS_BL_MOD_LEVEL_SHIFT); 4472#endif 4473 lvds_gen_cntl |= R128_LVDS_DISPLAY_DIS; 4474 OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); 4475 usleep(10); 4476 lvds_gen_cntl &= ~(R128_LVDS_ON | R128_LVDS_EN | R128_LVDS_BLON 4477 | R128_LVDS_DIGON); 4478 } 4479 4480 OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); 4481 4482 return 0; 4483} 4484