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