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