1/* Copyright (c) 2003-2006 Advanced Micro Devices, Inc. 2 * 3 * Portioned modeled from xf86-video-intel/src/i830_driver.c 4 * Copyright 2001 VA Linux Systems Inc., Fremont, California. 5 * Copyright \ufffd 2002 by David Dawes 6 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to 9 * deal in the Software without restriction, including without limitation the 10 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 * sell copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 * IN THE SOFTWARE. 24 * 25 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 26 * contributors may be used to endorse or promote products derived from this 27 * software without specific prior written permission. 28 */ 29 30#ifdef HAVE_CONFIG_H 31#include "config.h" 32#endif 33 34#include <stdio.h> 35#include <fcntl.h> 36#include <unistd.h> 37#include <sys/mman.h> 38 39#include "xorg-server.h" 40 41#include "xf86.h" 42#include "xf86_OSproc.h" 43#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 44#include "xf86Resources.h" 45#endif 46#include "xf86cmap.h" 47#include "compiler.h" 48#include "mipointer.h" 49#include "shadow.h" 50#include <X11/extensions/randr.h> 51#include "fb.h" 52#include "miscstruct.h" 53#include "micmap.h" 54#include "vbe.h" 55#include "fb.h" 56#include "randrstr.h" 57 58#include "geode.h" 59#include "gfx_defs.h" 60#include "gfx_regs.h" 61#include "panel.h" 62 63/* Bring in VGA functions */ 64#include "gx_vga.c" 65 66#define GX_MIN_PITCH 1024 67#define GX_MAX_PITCH 8192 68#define GX_MAX_WIDTH 1600 69#define GX_MIN_HEIGHT 400 70#define GX_MAX_HEIGHT 1200 71#define GX_CB_PITCH 544 72#define GX_CB_SIZE 544 73 74#define GX_CPU_REG_SIZE 0x4000 75#define GX_GP_REG_SIZE 0x4000 76#define GX_VID_REG_SIZE 0x4000 77 78#define DEFAULT_IMG_LINE_BUFS 20 79#define DEFAULT_CLR_LINE_BUFS 20 80 81extern OptionInfoRec GX_GeodeOptions[]; 82 83extern unsigned char *XpressROMPtr; 84 85static inline void 86gx_enable_dac_power(void) 87{ 88 gfx_write_vid32(RCDF_VID_MISC, 89 gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH); 90} 91 92static inline void 93gx_disable_dac_power(void) 94{ 95 gfx_write_vid32(RCDF_VID_MISC, 96 RCDF_DAC_POWER_DOWN | RCDF_ANALOG_POWER_DOWN | 97 (gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH)); 98} 99 100static void 101GXInitEXAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail) 102{ 103 GeodePtr pGeode = GEODEPTR(pScrni); 104 105 if (pGeode->exaBfrSz > 0 && pGeode->exaBfrSz <= *avail) { 106 pGeode->exaBfrOffset = *offset; 107 *offset += pGeode->exaBfrOffset; 108 *avail -= pGeode->exaBfrOffset; 109 } 110} 111 112static void 113GXInitXAAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail) 114{ 115 GeodePtr pGeode = GEODEPTR(pScrni); 116 unsigned int size, i, pitch; 117 118 /* XXX - FIXME - What if we are out of room? Then what? */ 119 /* For now, we NULL them all out. */ 120 121 if (pGeode->NoOfImgBuffers > 0) { 122 size = pGeode->displayPitch * pGeode->NoOfImgBuffers; 123 if (size <= *avail) { 124 for (i = 0; i < pGeode->NoOfImgBuffers; i++) { 125 pGeode->AccelImageWriteBuffers[i] = pGeode->FBBase + *offset; 126 *offset += pGeode->displayPitch; 127 *avail -= pGeode->displayPitch; 128 } 129 } 130 else { 131 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 132 "Not enough memory for image write buffers.\n"); 133 134 for (i = 0; i < pGeode->NoOfImgBuffers; i++) 135 pGeode->AccelImageWriteBuffers[i] = NULL; 136 } 137 } 138 139 if (pGeode->NoOfColorExpandLines > 0) { 140 pitch = ((pGeode->displayPitch + 31) >> 5) << 2; 141 size = pitch * pGeode->NoOfColorExpandLines; 142 143 if (size <= *avail) { 144 for (i = 0; i < pGeode->NoOfColorExpandLines; i++) { 145 pGeode->AccelColorExpandBuffers[i] = pGeode->FBBase + *offset; 146 *offset += pitch; 147 *avail -= pitch; 148 } 149 } 150 else { 151 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 152 "Not enough memory for color expansion buffers.\n"); 153 154 for (i = 0; i < pGeode->NoOfImgBuffers; i++) 155 pGeode->AccelColorExpandBuffers[i] = NULL; 156 } 157 } 158} 159 160static Bool 161GXAllocateMemory(ScreenPtr pScrn, ScrnInfoPtr pScrni, int rotate) 162{ 163 GeodePtr pGeode = GEODEPTR(pScrni); 164 165 unsigned int fboffset, fbavail; 166 unsigned int size; 167 unsigned int bytpp = (pScrni->bitsPerPixel + 7) / 8; 168 BOOL ret = TRUE; 169 170 if (pGeode->tryCompression) 171 pGeode->displayPitch = 172 GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel); 173 else 174 pGeode->displayPitch = 175 ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3); 176 177 pGeode->Pitch = pGeode->displayPitch; 178 pGeode->displayWidth = pGeode->displayPitch / bytpp; 179 pScrni->displayWidth = pGeode->displayWidth; 180 181 fbavail = pGeode->FBAvail - 0x4000; 182 183 pGeode->displayOffset = fboffset = 0; 184 pGeode->displaySize = pScrni->virtualY * pGeode->displayPitch; 185 186 fbavail -= pGeode->displaySize; 187 fboffset += pGeode->displaySize; 188 189 if (pGeode->tryCompression) { 190 size = pScrni->virtualY * GX_CB_PITCH; 191 192 if (size <= fbavail) { 193 pGeode->CBData.compression_offset = fboffset; 194 195 fboffset += size; 196 fbavail -= size; 197 198 pGeode->Compression = TRUE; 199 } 200 else { 201 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 202 "Not enough memory for compression\n"); 203 pGeode->Compression = FALSE; 204 } 205 } 206 207 if (pGeode->tryHWCursor) { 208 209 if (fbavail >= 1024) { 210 pGeode->CursorStartOffset = fboffset; 211 fboffset += 1024; 212 fbavail -= 1024; 213 pGeode->HWCursor = TRUE; 214 } 215 else { 216 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 217 "Not enough memory for the hardware cursor\n"); 218 pGeode->HWCursor = FALSE; 219 } 220 } 221 222 if (!pGeode->NoAccel) { 223 if (pGeode->useEXA) 224 GXInitEXAMemory(pScrni, &fboffset, &fbavail); 225 else 226 GXInitXAAMemory(pScrni, &fboffset, &fbavail); 227 } 228 229 pGeode->shadowSize = 0; 230 231 if (rotate != RR_Rotate_0) { 232 if (rotate & (RR_Rotate_90 | RR_Rotate_270)) 233 size = pGeode->displayPitch * pScrni->virtualX; 234 else 235 size = pGeode->displayPitch * pScrni->virtualY; 236 237 if (size <= fbavail) { 238 pGeode->shadowOffset = fboffset; 239 pGeode->shadowSize = size; 240 241 fboffset += size; 242 fbavail -= size; 243 } 244 else { 245 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 246 "Not enough memory for the shadow framebuffer\n"); 247 ret = FALSE; 248 } 249 } 250 251 /* XAA always exists - we can't remove it on demand like we can with EXA. 252 * So we assume the worse, and only give XAA enough offspace room to 253 * account for any eventuality that RandR might throw at us. */ 254 255 if (!pGeode->NoAccel) { 256 257 if (pGeode->useEXA && pGeode->pExa) { 258 ExaDriverPtr pExa = pGeode->pExa; 259 260 pExa->offScreenBase = fboffset; 261 pExa->memorySize = fboffset + fbavail; 262 } 263 264 if (!pGeode->useEXA) { 265 266#if XF86XAA 267 if (!xf86FBManagerRunning(pScrn)) { 268 269 unsigned int offset = fboffset; 270 unsigned int avail = fbavail; 271 RegionRec OffscreenRegion; 272 BoxRec AvailBox; 273 274 /* Assume the shadow FB exists even if it doesn't */ 275 276 if (pGeode->shadowSize == 0) { 277 size = (pScrn->width * bytpp) * pScrni->virtualX; 278 offset += size; 279 avail -= size; 280 } 281 282 AvailBox.x1 = 0; 283 AvailBox.y1 = 284 (offset + pGeode->displayPitch - 1) / pGeode->displayPitch; 285 286 AvailBox.x2 = pGeode->displayWidth; 287 AvailBox.y2 = (offset + avail) / pGeode->displayPitch; 288 289 if (AvailBox.y1 < AvailBox.y2) { 290 REGION_INIT(pScrn, &OffscreenRegion, &AvailBox, 2); 291 292 if (!xf86InitFBManagerRegion(pScrn, &OffscreenRegion)) 293 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 294 "Memory manager initialization failed.\n"); 295 296 REGION_UNINIT(pScrn, &OffscreenRegion); 297 } 298 else 299 xf86DrvMsg(pScrni->scrnIndex, X_INFO, 300 "Cache disabled - no offscreen memory available.\n"); 301 } 302 else 303 xf86DrvMsg(pScrni->scrnIndex, X_INFO, 304 "XAA offscreen memory has already been allocated.\n"); 305#endif 306 } 307 } 308 return ret; 309} 310 311static Bool 312GXSaveScreen(ScreenPtr pScrn, int mode) 313{ 314 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 315 GeodePtr pGeode = GEODEPTR(pScrni); 316 317 if (pGeode->useVGA && !pScrni->vtSema) 318 return vgaHWSaveScreen(pScrn, mode); 319 320 return TRUE; 321} 322 323/* Common function - used by the LX too */ 324#ifdef XSERVER_LIBPCIACCESS 325static inline void * 326map_pci_mem(ScrnInfoPtr pScrni, int vram, 327 struct pci_device *dev, int bar, int size) 328{ 329 void *ptr; 330 int map_size = size ? size : dev->regions[bar].size; 331 332 int err = pci_device_map_range(dev, 333 dev->regions[bar].base_addr, 334 map_size, 335 PCI_DEV_MAP_FLAG_WRITABLE | 336 (vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0), 337 &ptr); 338 339 if (err) 340 return NULL; 341 return ptr; 342} 343 344static inline int 345unmap_pci_mem(ScrnInfoPtr pScrni, struct pci_device *dev, void *ptr, int size) 346{ 347 return pci_device_unmap_range(dev, ptr, size); 348} 349#endif 350 351extern unsigned long gfx_gx2_scratch_base; 352 353static Bool 354GXMapMem(ScrnInfoPtr pScrni) 355{ 356 GeodeRec *pGeode = GEODEPTR(pScrni); 357 int index = pScrni->scrnIndex; 358 359 pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index); 360 361#ifndef XSERVER_LIBPCIACCESS 362 gfx_virt_regptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO, 363 pci->memBase[2], 364 pci->size[2]); 365 366 gfx_virt_gpptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO, 367 pci->memBase[1], 368 pci->size[1]); 369 370 gfx_virt_vidptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO, 371 pci->memBase[3], 372 pci->size[3]); 373 374 gfx_virt_fbptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 375 pci->memBase[0], 376 pGeode->FBAvail); 377#else 378 gfx_virt_regptr = map_pci_mem(pScrni, 0, pci, 2, 0); 379 gfx_virt_gpptr = map_pci_mem(pScrni, 0, pci, 1, 0); 380 gfx_virt_vidptr = map_pci_mem(pScrni, 0, pci, 3, 0); 381 gfx_virt_fbptr = map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail); 382#endif 383 384 gfx_gx2_scratch_base = pGeode->FBAvail - 0x4000; 385 386#ifndef XSERVER_LIBPCIACCESS 387 XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000); 388#else 389 { 390 int fd = open("/dev/mem", O_RDWR); 391 if (fd < 0) { 392 xf86DrvMsg(index, X_ERROR, "Failed to open /dev/mem: %m\n"); 393 return FALSE; 394 } 395 XpressROMPtr = mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xF0000); 396 close(fd); 397 } 398#endif 399 pGeode->FBBase = gfx_virt_fbptr; 400 401 if ((!gfx_virt_regptr) || (!gfx_virt_gpptr) || 402 (!gfx_virt_vidptr) || (!gfx_virt_fbptr)) 403 return FALSE; 404 405 if (!pGeode->NoAccel && pGeode->useEXA) 406 pGeode->pExa->memoryBase = pGeode->FBBase; 407 408 xf86DrvMsg(index, X_INFO, "Found Geode %x %p\n", 409 pGeode->FBAvail, pGeode->FBBase); 410 411 return TRUE; 412} 413 414/* Check to see if VGA exists - we map the space and look for a 415 signature - if it doesn't match exactly, then we assume no VGA. 416*/ 417 418static Bool 419GXCheckVGA(ScrnInfoPtr pScrni, EntityInfoPtr pEnt) 420{ 421#ifndef XSERVER_LIBPCIACCESS 422 unsigned char *ptr; 423 const char *vgasig = "IBM VGA Compatible"; 424 int ret; 425 426 ptr = 427 xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E, 428 strlen(vgasig)); 429 430 if (ptr == NULL) 431 return FALSE; 432 433 ret = memcmp(ptr, vgasig, strlen(vgasig)); 434 xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig)); 435 436 return ret ? FALSE : TRUE; 437#else 438 pciVideoPtr pci = xf86GetPciInfoForEntity(pEnt->index); 439 440 return pci_device_is_boot_vga(pci); 441#endif 442} 443 444static Bool 445GXPreInit(ScrnInfoPtr pScrni, int flags) 446{ 447 GeodePtr pGeode; 448 ClockRangePtr GeodeClockRange; 449 OptionInfoRec *GeodeOptions = &GX_GeodeOptions[0]; 450 int ret; 451 QQ_WORD msrValue; 452 EntityInfoPtr pEnt; 453 rgb defaultWeight = { 0, 0, 0 }; 454 int modecnt; 455 const char *s, *panelgeo; 456 Bool useVGA; 457 458 if (pScrni->numEntities != 1) 459 return FALSE; 460 461 pEnt = xf86GetEntityInfo(pScrni->entityList[0]); 462#ifndef XSERVER_LIBPCIACCESS 463 if (pEnt->resources) 464 return FALSE; 465#endif 466 467 pGeode = pScrni->driverPrivate = xnfcalloc(1, sizeof(GeodeRec)); 468 469 if (pGeode == NULL) 470 return FALSE; 471 472 useVGA = GXCheckVGA(pScrni, pEnt); 473 474 if (flags & PROBE_DETECT) { 475 GeodeProbeDDC(pScrni, pEnt->index); 476 return TRUE; 477 } 478 479 /* Probe for VGA */ 480 pGeode->useVGA = useVGA; 481 pGeode->pEnt = pEnt; 482 483 if (pGeode->useVGA) { 484 if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni)) 485 pGeode->useVGA = FALSE; 486 else 487 vgaHWSetStdFuncs(VGAHWPTR(pScrni)); 488 489#if INT10_SUPPORT 490 pGeode->vesa = calloc(1, sizeof(VESARec)); 491#endif 492 } 493 494 gfx_msr_init(); 495 496 ret = gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msrValue); 497 498 if (!ret) { 499 pGeode->Output = 500 ((msrValue.low & RCDF_CONFIG_FMT_MASK) == 501 RCDF_CONFIG_FMT_FP) ? OUTPUT_PANEL : OUTPUT_CRT; 502 } 503 504 /* Fill in the monitor information */ 505 pScrni->monitor = pScrni->confScreen->monitor; 506 507 if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb)) 508 return FALSE; 509 510 switch (pScrni->depth) { 511 case 8: 512 pScrni->rgbBits = 8; 513 case 16: 514 case 24: 515 case 32: 516 break; 517 default: 518 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 519 "The driver does not support %d as a depth.\n", 520 pScrni->depth); 521 return FALSE; 522 } 523 524 xf86PrintDepthBpp(pScrni); 525 526 if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight)) 527 return FALSE; 528 529 if (!xf86SetDefaultVisual(pScrni, -1)) 530 return FALSE; 531 532 /* 533 * If the driver can do gamma correction, it should call xf86SetGamma() 534 * here. 535 */ 536 { 537 Gamma zeros = { 0.0, 0.0, 0.0 }; 538 539 if (!xf86SetGamma(pScrni, zeros)) { 540 return FALSE; 541 } 542 } 543 544 pScrni->progClock = TRUE; 545 xf86CollectOptions(pScrni, NULL); 546 xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions); 547 548 /* Set up our various options that may get reversed as we go on */ 549 550 pGeode->FBVGAActive = FALSE; 551 pGeode->tryHWCursor = TRUE; 552 pGeode->tryCompression = TRUE; 553 554 pGeode->NoAccel = FALSE; 555 pGeode->useEXA = FALSE; 556 557 pGeode->Panel = (pGeode->Output & OUTPUT_PANEL) ? TRUE : FALSE; 558 559 pGeode->NoOfImgBuffers = DEFAULT_IMG_LINE_BUFS; 560 pGeode->NoOfColorExpandLines = DEFAULT_CLR_LINE_BUFS; 561 pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ; 562 563 xf86GetOptValBool(GeodeOptions, GX_OPTION_HW_CURSOR, &pGeode->tryHWCursor); 564 565 if (!xf86GetOptValInteger(GeodeOptions, GX_OPTION_FBSIZE, 566 (int *) &(pGeode->FBAvail))) 567 pGeode->FBAvail = 0; 568 569 /* For compatibility - allow SWCursor too */ 570 571 if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_SW_CURSOR, FALSE)) 572 pGeode->tryHWCursor = FALSE; 573 574 if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOCOMPRESSION, FALSE)) 575 pGeode->tryCompression = FALSE; 576 577 if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOACCEL, FALSE)) 578 pGeode->NoAccel = TRUE; 579 580 pGeode->rotation = RR_Rotate_0; 581 582 if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ROTATE))) { 583 584 if (!xf86NameCmp(s, "LEFT")) 585 pGeode->rotation = RR_Rotate_90; 586 else if (!xf86NameCmp(s, "INVERT")) 587 pGeode->rotation = RR_Rotate_180; 588 else if (!xf86NameCmp(s, "CCW")) 589 pGeode->rotation = RR_Rotate_270; 590 else 591 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "Invalid rotation %s.\n", s); 592 } 593 594 xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_IMG_BUFS, 595 &(pGeode->NoOfImgBuffers)); 596 597 if (pGeode->NoOfImgBuffers <= 0) 598 pGeode->NoOfImgBuffers = 0; 599 600 xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS, 601 &(pGeode->NoOfColorExpandLines)); 602 603 if (pGeode->NoOfColorExpandLines <= 0) 604 pGeode->NoOfColorExpandLines = 0; 605 606 xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS, 607 (int *) &(pGeode->exaBfrSz)); 608 609 if (pGeode->exaBfrSz <= 0) 610 pGeode->exaBfrSz = 0; 611 612 if (pGeode->Panel == TRUE) { 613 if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOPANEL, FALSE)) 614 pGeode->Panel = FALSE; 615 } 616 617 panelgeo = xf86GetOptValString(GeodeOptions, GX_OPTION_PANEL_GEOMETRY); 618 619 if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ACCEL_METHOD))) { 620#if defined(XF86XAA) && defined(XF86EXA) 621 if (!xf86NameCmp(s, "XAA")) 622 pGeode->useEXA = FALSE; 623 else if (xf86NameCmp(s, "EXA")) 624 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 625 "Unknown acceleration method %s. Defaulting to XAA.\n", 626 s); 627#elif defined(XF86EXA) 628 pGeode->useEXA = TRUE; 629#else 630 pGeode->useEXA = FALSE; 631#endif 632 } 633 634 xf86DrvMsg(pScrni->scrnIndex, X_INFO, 635 "Using %s acceleration architecture\n", 636 pGeode->useEXA ? "EXA" : "XAA"); 637 638 /* Set up the panel */ 639 640 if (pGeode->Panel) { 641 if (panelgeo != NULL) { 642 if (GeodeGetFPGeometry(panelgeo, &pGeode->PanelX, &pGeode->PanelY)) 643 pGeode->Panel = FALSE; 644 } 645#ifdef PNL_SUP 646 else { 647 int b, f; 648 649 /* The bitdepth and refresh isn't used anywhere else in the driver */ 650 651 if ((pGeode->Panel = Pnl_IsPanelEnabledInBIOS())) 652 Pnl_GetPanelInfoFromBIOS(&pGeode->PanelX, &pGeode->PanelY, &b, 653 &f); 654 } 655#endif 656 } 657 658 /* Set up the VGA */ 659 660 if (pGeode->useVGA) { 661#if INT10_SUPPORT 662 VESARec *pVesa; 663 664 if (!xf86LoadSubModule(pScrni, "int10")) 665 return FALSE; 666 667 pVesa = pGeode->vesa; 668 669 if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) { 670 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 671 "Unable to initialize 1NT10 support\n"); 672 pGeode->useVGA = FALSE; 673 } 674#endif 675 } 676 677 /* First try to get the framebuffer size from the framebuffer, 678 * and if that fails, revert all the way back to the legacy 679 * method 680 */ 681 682 if (pGeode->FBAvail == 0) { 683 if (GeodeGetSizeFromFB(&pGeode->FBAvail)) 684 pGeode->FBAvail = gfx_get_frame_buffer_size(); 685 } 686 687 if (pScrni->memPhysBase == 0) 688 pScrni->memPhysBase = gfx_get_frame_buffer_base(); 689 690 pScrni->fbOffset = 0; 691 692 if (pGeode->pEnt->device->videoRam == 0) 693 pScrni->videoRam = pGeode->FBAvail / 1024; 694 else 695 pScrni->videoRam = pGeode->pEnt->device->videoRam; 696 697 GeodeClockRange = (ClockRangePtr) xnfcalloc(1, sizeof(ClockRange)); 698 GeodeClockRange->next = NULL; 699 GeodeClockRange->minClock = 25175; 700 GeodeClockRange->maxClock = 229500; 701 GeodeClockRange->clockIndex = -1; 702 GeodeClockRange->interlaceAllowed = TRUE; 703 GeodeClockRange->doubleScanAllowed = FALSE; 704 705 pScrni->monitor->DDC = GeodeDoDDC(pScrni, pGeode->pEnt->index); 706 707 /* I'm still not 100% sure this uses the right values */ 708 709 modecnt = xf86ValidateModes(pScrni, 710 pScrni->monitor->Modes, 711 pScrni->display->modes, 712 GeodeClockRange, 713 NULL, GX_MIN_PITCH, GX_MAX_PITCH, 714 32, GX_MIN_HEIGHT, GX_MAX_HEIGHT, 715 pScrni->display->virtualX, 716 pScrni->display->virtualY, pGeode->FBAvail, 717 LOOKUP_BEST_REFRESH); 718 719 if (modecnt <= 0) { 720 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n"); 721 return FALSE; 722 } 723 724 xf86PruneDriverModes(pScrni); 725 726 if (pScrni->modes == NULL) { 727 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n"); 728 return FALSE; 729 } 730 731 xf86SetCrtcForModes(pScrni, 0); 732 pScrni->currentMode = pScrni->modes; 733 734 xf86PrintModes(pScrni); 735 xf86SetDpi(pScrni, 0, 0); 736 737 /* Load the modules we'll need */ 738 739 if (xf86LoadSubModule(pScrni, "fb") == NULL) { 740 return FALSE; 741 } 742 743 if (pGeode->NoAccel == FALSE) { 744 const char *module = (pGeode->useEXA) ? "exa" : "xaa"; 745 746 if (!xf86LoadSubModule(pScrni, module)) { 747 return FALSE; 748 } 749 } 750 751 if (pGeode->tryHWCursor == TRUE) { 752 if (!xf86LoadSubModule(pScrni, "ramdac")) { 753 return FALSE; 754 } 755 } 756 757#ifndef XSERVER_LIBPCIACCESS 758 if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) { 759 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 760 "Couldn't register the resources.\n"); 761 return FALSE; 762 } 763#endif 764 return TRUE; 765} 766 767static void 768GXRestore(ScrnInfoPtr pScrni) 769{ 770 GeodeRec *pGeode = GEODEPTR(pScrni); 771 772 if (pGeode->useVGA && pGeode->FBVGAActive) { 773 vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 774 775 vgaHWProtect(pScrni, TRUE); 776 vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL); 777 vgaHWProtect(pScrni, FALSE); 778 } 779} 780 781static Bool 782GXUnmapMem(ScrnInfoPtr pScrni) 783{ 784 GeodeRec *pGeode = GEODEPTR(pScrni); 785 786 /* unmap all the memory map's */ 787#ifndef XSERVER_LIBPCIACCESS 788 xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_regptr, GX_CPU_REG_SIZE); 789 xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_gpptr, GX_GP_REG_SIZE); 790 xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_vidptr, GX_VID_REG_SIZE); 791 xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_fbptr, pGeode->FBAvail); 792#else 793 pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index); 794 795 unmap_pci_mem(pScrni, pci, gfx_virt_regptr, GX_CPU_REG_SIZE); 796 unmap_pci_mem(pScrni, pci, gfx_virt_gpptr, GX_GP_REG_SIZE); 797 unmap_pci_mem(pScrni, pci, gfx_virt_vidptr, GX_VID_REG_SIZE); 798 unmap_pci_mem(pScrni, pci, gfx_virt_fbptr, pGeode->FBAvail); 799 800 munmap(XpressROMPtr, 0x10000); 801#endif 802 return TRUE; 803} 804 805static void 806GXSetDvLineSize(unsigned int pitch) 807{ 808 unsigned long temp, dv_size = MDC_DV_LINE_SIZE_1024; 809 810 if (pitch > 1024) { 811 dv_size = MDC_DV_LINE_SIZE_2048; 812 } 813 if (pitch > 2048) { 814 dv_size = MDC_DV_LINE_SIZE_4096; 815 } 816 if (pitch > 4096) { 817 dv_size = MDC_DV_LINE_SIZE_8192; 818 } 819 820 /* WRITE DIRTY/VALID CONTROL WITH LINE LENGTH */ 821 822 temp = READ_REG32(MDC_DV_CTL); 823 WRITE_REG32(MDC_DV_CTL, (temp & ~MDC_DV_LINE_SIZE_MASK) | dv_size); 824} 825 826/* XXX - this is nothing like the original function - not sure exactly what the purpose is for this quite yet */ 827 828static void 829GXAdjustFrame(ADJUST_FRAME_ARGS_DECL) 830{ 831 SCRN_INFO_PTR(arg); 832 GeodeRec *pGeode = GEODEPTR(pScrni); 833 unsigned long offset; 834 835 offset = y * pGeode->Pitch + x * (pScrni->bitsPerPixel >> 3); 836 837 gfx_set_display_offset(offset); 838} 839 840static Bool 841GXSetVideoMode(ScrnInfoPtr pScrni, DisplayModePtr pMode) 842{ 843 GeodeRec *pGeode = GEODEPTR(pScrni); 844 int flags = 0; 845 int custom = 0; 846 847 pScrni->vtSema = TRUE; 848 849 gx_disable_dac_power(); 850 851 if (pMode->Flags & V_NHSYNC) 852 flags |= 1; 853 if (pMode->Flags & V_NVSYNC) 854 flags |= 2; 855 856 /* Check to see if we should use custom or built-in timings */ 857 858 if (pGeode->Panel) 859 custom = (pMode->type & M_T_USERDEF); 860 else 861 custom = !(pMode->type & (M_T_BUILTIN | M_T_DEFAULT)); 862 863 /* If we're not doing a custom mode, then just set the fixed timings, 864 * otherwise, do the whole shooting match */ 865 866 if (!custom) { 867 GFX(set_fixed_timings(pGeode->PanelX, pGeode->PanelY, 868 pMode->CrtcHDisplay, pMode->CrtcVDisplay, 869 pScrni->bitsPerPixel)); 870 } 871 else { 872 if (pGeode->Panel) 873 GFX(set_panel_present(pGeode->PanelX, pGeode->PanelY, 874 pMode->CrtcHDisplay, pMode->CrtcVDisplay, 875 pScrni->bitsPerPixel)); 876 877 GFX(set_display_timings(pScrni->bitsPerPixel, flags, 878 pMode->CrtcHDisplay, pMode->CrtcHBlankStart, 879 pMode->CrtcHSyncStart, pMode->CrtcHSyncEnd, 880 pMode->CrtcHBlankEnd, pMode->CrtcHTotal, 881 pMode->CrtcVDisplay, pMode->CrtcVBlankStart, 882 pMode->CrtcVSyncStart, pMode->CrtcVSyncEnd, 883 pMode->CrtcVBlankEnd, pMode->CrtcVTotal, 884 (int) ((pMode->SynthClock / 1000.0) * 885 0x10000))); 886 } 887 888 GFX(set_crt_enable(CRT_ENABLE)); 889 GFX(set_display_pitch(pGeode->displayPitch)); 890 GFX(set_display_offset(0L)); 891 GFX(wait_vertical_blank()); 892 893 if (pGeode->Compression) { 894 GXSetDvLineSize(pGeode->Pitch); 895 896 gfx_set_compression_offset(pGeode->CBData.compression_offset); 897 gfx_set_compression_pitch(GX_CB_PITCH); 898 gfx_set_compression_size(GX_CB_SIZE); 899 900 gfx_set_compression_enable(1); 901 } 902 903 if (pGeode->HWCursor && !(pMode->Flags & V_DBLSCAN)) { 904 GXLoadCursorImage(pScrni, NULL); 905 GFX(set_cursor_position(pGeode->CursorStartOffset, 0, 0, 0, 0)); 906 GXShowCursor(pScrni); 907 } 908 else { 909 GFX(set_cursor_enable(0)); 910 pGeode->HWCursor = FALSE; 911 } 912 913 GXAdjustFrame(ADJUST_FRAME_ARGS(pScrni->frameX0, pScrni->frameY0)); 914 gx_enable_dac_power(); 915 916 return TRUE; 917} 918 919static Bool 920GXSwitchMode(SWITCH_MODE_ARGS_DECL) 921{ 922 SCRN_INFO_PTR(arg); 923 GeodeRec *pGeode = GEODEPTR(pScrni); 924 int ret = TRUE; 925 int rotate; 926 927 /* Syn the engine and shutdown the DAC momentarily */ 928 929 gfx_wait_until_idle(); 930 931 /* Set up the memory for the new mode */ 932 rotate = GXGetRotation(pScrni->pScreen); 933 ret = GXAllocateMemory(pScrni->pScreen, pScrni, rotate); 934 935 if (ret) { 936 if (pGeode->curMode != pMode) 937 ret = GXSetVideoMode(pScrni, pMode); 938 } 939 940 if (ret) 941 ret = GXRotate(pScrni, pMode); 942 943 /* Go back the way it was */ 944 945 if (ret == FALSE) { 946 if (!GXSetVideoMode(pScrni, pGeode->curMode)) 947 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 948 "Could not restore the previous mode\n"); 949 } 950 else 951 pGeode->curMode = pMode; 952 953 return ret; 954} 955 956static void 957GXLeaveGraphics(ScrnInfoPtr pScrni) 958{ 959 GeodeRec *pGeode = GEODEPTR(pScrni); 960 961 gfx_wait_until_idle(); 962 963 /* Restore VG registers */ 964 gfx_set_display_timings(pGeode->FBgfxdisplaytiming.wBpp, 965 pGeode->FBgfxdisplaytiming.wPolarity, 966 pGeode->FBgfxdisplaytiming.wHActive, 967 pGeode->FBgfxdisplaytiming.wHBlankStart, 968 pGeode->FBgfxdisplaytiming.wHSyncStart, 969 pGeode->FBgfxdisplaytiming.wHSyncEnd, 970 pGeode->FBgfxdisplaytiming.wHBlankEnd, 971 pGeode->FBgfxdisplaytiming.wHTotal, 972 pGeode->FBgfxdisplaytiming.wVActive, 973 pGeode->FBgfxdisplaytiming.wVBlankStart, 974 pGeode->FBgfxdisplaytiming.wVSyncStart, 975 pGeode->FBgfxdisplaytiming.wVSyncEnd, 976 pGeode->FBgfxdisplaytiming.wVBlankEnd, 977 pGeode->FBgfxdisplaytiming.wVTotal, 978 pGeode->FBgfxdisplaytiming.dwDotClock); 979 980 gfx_set_compression_enable(0); 981 982 /* Restore the previous Compression state */ 983 if (pGeode->FBCompressionEnable) { 984 gfx_set_compression_offset(pGeode->FBCompressionOffset); 985 gfx_set_compression_pitch(pGeode->FBCompressionPitch); 986 gfx_set_compression_size(pGeode->FBCompressionSize); 987 gfx_set_compression_enable(1); 988 } 989 990 gfx_set_display_pitch(pGeode->FBgfxdisplaytiming.wPitch); 991 992 gfx_set_display_offset(pGeode->FBDisplayOffset); 993 994 /* Restore Cursor */ 995 gfx_set_cursor_position(pGeode->FBCursorOffset, 0, 0, 0, 0); 996 997 if (pGeode->useVGA) { 998 pGeode->vesa->pInt->num = 0x10; 999 pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode; 1000 pGeode->vesa->pInt->bx = 0; 1001 xf86ExecX86int10(pGeode->vesa->pInt); 1002 gfx_delay_milliseconds(3); 1003 } 1004 1005 GXRestore(pScrni); 1006 1007 gx_enable_dac_power(); 1008} 1009 1010static Bool 1011GXCloseScreen(CLOSE_SCREEN_ARGS_DECL) 1012{ 1013 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 1014 GeodeRec *pGeode = GEODEPTR(pScrni); 1015 1016 if (pScrni->vtSema) 1017 GXLeaveGraphics(pScrni); 1018 1019#ifdef XF86XAA 1020 if (pGeode->AccelInfoRec) 1021 XAADestroyInfoRec(pGeode->AccelInfoRec); 1022#endif 1023 1024 if (pGeode->AccelImageWriteBuffers) { 1025 free(pGeode->AccelImageWriteBuffers[0]); 1026 free(pGeode->AccelImageWriteBuffers); 1027 pGeode->AccelImageWriteBuffers = NULL; 1028 } 1029 1030 if (pGeode->AccelColorExpandBuffers) { 1031 free(pGeode->AccelColorExpandBuffers); 1032 pGeode->AccelColorExpandBuffers = NULL; 1033 } 1034 1035 if (pGeode->pExa) { 1036 exaDriverFini(pScrn); 1037 free(pGeode->pExa); 1038 pGeode->pExa = NULL; 1039 } 1040 1041 pScrni->vtSema = FALSE; 1042 1043 GXUnmapMem(pScrni); 1044 1045 pScrni->PointerMoved = pGeode->PointerMoved; 1046 pScrn->CloseScreen = pGeode->CloseScreen; 1047 1048 if (pScrn->CloseScreen) 1049 return (*pScrn->CloseScreen) (CLOSE_SCREEN_ARGS); 1050 1051 return TRUE; 1052} 1053 1054static Bool 1055GXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni) 1056{ 1057 GeodeRec *pGeode = GEODEPTR(pScrni); 1058 1059 if (!GXMapMem(pScrni)) 1060 return FALSE; 1061 1062 if (pGeode->useVGA) 1063 pGeode->FBVGAActive = gu2_get_vga_active(); 1064 1065 gfx_wait_until_idle(); 1066 1067 /* Save off the current state (should this be somewhere else)? */ 1068 1069 pGeode->FBgfxdisplaytiming.dwDotClock = gfx_get_clock_frequency(); 1070 pGeode->FBgfxdisplaytiming.wPitch = gfx_get_display_pitch(); 1071 pGeode->FBgfxdisplaytiming.wBpp = gfx_get_display_bpp(); 1072 pGeode->FBgfxdisplaytiming.wHTotal = gfx_get_htotal(); 1073 pGeode->FBgfxdisplaytiming.wHActive = gfx_get_hactive(); 1074 pGeode->FBgfxdisplaytiming.wHSyncStart = gfx_get_hsync_start(); 1075 pGeode->FBgfxdisplaytiming.wHSyncEnd = gfx_get_hsync_end(); 1076 pGeode->FBgfxdisplaytiming.wHBlankStart = gfx_get_hblank_start(); 1077 pGeode->FBgfxdisplaytiming.wHBlankEnd = gfx_get_hblank_end(); 1078 pGeode->FBgfxdisplaytiming.wVTotal = gfx_get_vtotal(); 1079 pGeode->FBgfxdisplaytiming.wVActive = gfx_get_vactive(); 1080 pGeode->FBgfxdisplaytiming.wVSyncStart = gfx_get_vsync_start(); 1081 pGeode->FBgfxdisplaytiming.wVSyncEnd = gfx_get_vsync_end(); 1082 pGeode->FBgfxdisplaytiming.wVBlankStart = gfx_get_vblank_start(); 1083 pGeode->FBgfxdisplaytiming.wVBlankEnd = gfx_get_vblank_end(); 1084 pGeode->FBgfxdisplaytiming.wPolarity = gfx_get_sync_polarities(); 1085 1086 pGeode->FBDisplayOffset = gfx_get_display_offset(); 1087 1088 if (pGeode->useVGA) { 1089 vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 1090 1091 pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040); 1092 } 1093 1094 pGeode->FBCompressionEnable = gfx_get_compression_enable(); 1095 pGeode->FBCompressionOffset = gfx_get_compression_offset(); 1096 pGeode->FBCompressionPitch = gfx_get_compression_pitch(); 1097 pGeode->FBCompressionSize = gfx_get_compression_size(); 1098 1099#ifdef PNL_SUP 1100 Pnl_SavePanelState(); 1101#endif 1102 1103 /* Turn off the VGA */ 1104 1105 if (pGeode->useVGA && pGeode->FBVGAActive) { 1106 unsigned short sequencer; 1107 vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 1108 1109 /* Map VGA aperture */ 1110 if (!vgaHWMapMem(pScrni)) 1111 return FALSE; 1112 1113 /* Unlock VGA registers */ 1114 vgaHWUnlock(pvgaHW); 1115 1116 /* Save the current state and setup the current mode */ 1117 vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL); 1118 1119 /* DISABLE VGA SEQUENCER */ 1120 /* This allows the VGA state machine to terminate. We must delay */ 1121 /* such that there are no pending MBUS requests. */ 1122 1123 gfx_outb(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_CLK_MODE); 1124 sequencer = gfx_inb(MDC_SEQUENCER_DATA); 1125 sequencer |= MDC_CLK_MODE_SCREEN_OFF; 1126 gfx_outb(MDC_SEQUENCER_DATA, sequencer); 1127 1128 gfx_delay_milliseconds(1); 1129 1130 /* BLANK THE VGA DISPLAY */ 1131 gfx_outw(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_RESET); 1132 sequencer = gfx_inb(MDC_SEQUENCER_DATA); 1133 sequencer &= ~MDC_RESET_VGA_DISP_ENABLE; 1134 gfx_outb(MDC_SEQUENCER_DATA, sequencer); 1135 1136 gfx_delay_milliseconds(1); 1137 } 1138 1139 /* Set up the memory */ 1140 /* XXX - FIXME - when we allow initial rotation, it should be here */ 1141 GXAllocateMemory(pScrn, pScrni, pGeode->rotation); 1142 1143 /* Clear the framebuffer */ 1144 memset(pGeode->FBBase + pGeode->displayOffset, 0, pGeode->displaySize); 1145 1146 /* Set up the video mode */ 1147 GXSetVideoMode(pScrni, pScrni->currentMode); 1148 pGeode->curMode = pScrni->currentMode; 1149 1150 return TRUE; 1151} 1152 1153static void 1154GXLoadPalette(ScrnInfoPtr pScrni, 1155 int numColors, int *indizes, LOCO * colors, VisualPtr pVisual) 1156{ 1157 int i, index, color; 1158 1159 for (i = 0; i < numColors; i++) { 1160 index = indizes[i] & 0xFF; 1161 color = (((unsigned long) (colors[index].red & 0xFF)) << 16) | 1162 (((unsigned long) (colors[index].green & 0xFF)) << 8) | 1163 ((unsigned long) (colors[index].blue & 0xFF)); 1164 1165 GFX(set_display_palette_entry(index, color)); 1166 } 1167} 1168 1169#ifdef DPMSExtension 1170static void 1171GXPanelPower(int enable) 1172{ 1173 unsigned long power = READ_VID32(RCDF_POWER_MANAGEMENT); 1174 1175 if (enable != 0) 1176 power |= RCDF_PM_PANEL_POWER_ON; 1177 else 1178 power &= ~RCDF_PM_PANEL_POWER_ON; 1179 1180 WRITE_VID32(RCDF_POWER_MANAGEMENT, power); 1181} 1182 1183static void 1184GXDPMSSet(ScrnInfoPtr pScrni, int mode, int flags) 1185{ 1186 GeodeRec *pGeode; 1187 1188 pGeode = GEODEPTR(pScrni); 1189 1190 if (!pScrni->vtSema) 1191 return; 1192 1193 switch (mode) { 1194 case DPMSModeOn: 1195 /* Screen: On; HSync: On; VSync: On */ 1196 GFX(set_crt_enable(CRT_ENABLE)); 1197#if defined(PNL_SUP) 1198 if (pGeode->Panel) { 1199 Pnl_PowerUp(); 1200 GXPanelPower(1); 1201 } 1202#endif 1203 break; 1204 1205 case DPMSModeStandby: 1206 /* Screen: Off; HSync: Off; VSync: On */ 1207 GFX(set_crt_enable(CRT_STANDBY)); 1208#if defined(PNL_SUP) 1209 if (pGeode->Panel) { 1210 Pnl_PowerDown(); 1211 GXPanelPower(0); 1212 } 1213#endif 1214 break; 1215 1216 case DPMSModeSuspend: 1217 /* Screen: Off; HSync: On; VSync: Off */ 1218 GFX(set_crt_enable(CRT_SUSPEND)); 1219#if defined(PNL_SUP) 1220 if (pGeode->Panel) { 1221 Pnl_PowerDown(); 1222 GXPanelPower(0); 1223 } 1224#endif 1225 break; 1226 1227 case DPMSModeOff: 1228 /* Screen: Off; HSync: Off; VSync: Off */ 1229 GFX(set_crt_enable(CRT_DISABLE)); 1230#if defined(PNL_SUP) 1231 if (pGeode->Panel) { 1232 Pnl_PowerDown(); 1233 GXPanelPower(0); 1234 } 1235#endif 1236 break; 1237 } 1238} 1239#endif 1240 1241static Bool 1242GXCreateScreenResources(ScreenPtr pScreen) 1243{ 1244 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen); 1245 GeodeRec *pGeode = GEODEPTR(pScrni); 1246 1247 pScreen->CreateScreenResources = pGeode->CreateScreenResources; 1248 if (!(*pScreen->CreateScreenResources) (pScreen)) 1249 return FALSE; 1250 1251 if (xf86LoaderCheckSymbol("GXRandRSetConfig") 1252 && pGeode->rotation != RR_Rotate_0) { 1253 Rotation(*GXRandRSetConfig) (ScreenPtr pScreen, Rotation rr, int rate, 1254 RRScreenSizePtr pSize) = NULL; 1255 1256 RRScreenSize p; 1257 Rotation requestedRotation = pGeode->rotation; 1258 1259 pGeode->rotation = RR_Rotate_0; 1260 1261 /* Just setup enough for an initial rotate */ 1262 1263 p.width = pScreen->width; 1264 p.height = pScreen->height; 1265 p.mmWidth = pScreen->mmWidth; 1266 p.mmHeight = pScreen->mmHeight; 1267 1268 GXRandRSetConfig = LoaderSymbol("GXRandRSetConfig"); 1269 if (GXRandRSetConfig) { 1270 pGeode->starting = TRUE; 1271 (*GXRandRSetConfig) (pScreen, requestedRotation, 0, &p); 1272 pGeode->starting = FALSE; 1273 } 1274 } 1275 1276 return TRUE; 1277} 1278 1279static Bool 1280GXScreenInit(SCREEN_INIT_ARGS_DECL) 1281{ 1282 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 1283 GeodeRec *pGeode = GEODEPTR(pScrni); 1284 XF86ModReqInfo shadowReq; 1285 int maj, min, ret, rotate; 1286 1287 pGeode->starting = TRUE; 1288 1289 /* If we are using VGA then go ahead and map the memory */ 1290 1291 if (pGeode->useVGA) { 1292 1293 if (!vgaHWMapMem(pScrni)) 1294 return FALSE; 1295 1296 vgaHWGetIOBase(VGAHWPTR(pScrni)); 1297 } 1298 1299 if (!pGeode->NoAccel) { 1300 1301 if (pGeode->useEXA) { 1302 1303 if (!(pGeode->pExa = exaDriverAlloc())) { 1304 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 1305 "Couldn't allocate the EXA structure.\n"); 1306 pGeode->NoAccel = TRUE; 1307 } 1308 else { 1309 ExaDriverPtr pExa = pGeode->pExa; 1310 1311 /* THis is set in GXAllocMem */ 1312 pExa->memoryBase = 0; 1313 1314 /* This is set in GXAllocateMemory */ 1315 pExa->memorySize = 0; 1316 1317 pExa->pixmapOffsetAlign = 32; 1318 pExa->pixmapPitchAlign = 32; 1319 pExa->flags = EXA_OFFSCREEN_PIXMAPS; 1320 pExa->maxX = GX_MAX_WIDTH - 1; 1321 pExa->maxY = GX_MAX_HEIGHT - 1; 1322 } 1323 } 1324 else { 1325 pGeode->AccelImageWriteBuffers = 1326 calloc(pGeode->NoOfImgBuffers, 1327 sizeof(pGeode->AccelImageWriteBuffers[0])); 1328 pGeode->AccelColorExpandBuffers = 1329 calloc(pGeode->NoOfColorExpandLines, 1330 sizeof(pGeode->AccelColorExpandBuffers[0])); 1331 } 1332 } 1333 1334 /* XXX FIXME - Take down any of the structures on failure? */ 1335 1336 if (!GXEnterGraphics(pScrn, pScrni)) 1337 return FALSE; 1338 1339 miClearVisualTypes(); 1340 1341 /* XXX Again - take down anything? */ 1342 1343 if (pScrni->bitsPerPixel > 8) { 1344 if (!miSetVisualTypes(pScrni->depth, 1345 TrueColorMask, pScrni->rgbBits, 1346 pScrni->defaultVisual)) { 1347 return FALSE; 1348 } 1349 } 1350 else { 1351 if (!miSetVisualTypes(pScrni->depth, 1352 miGetDefaultVisualMask(pScrni->depth), 1353 pScrni->rgbBits, pScrni->defaultVisual)) { 1354 return FALSE; 1355 } 1356 } 1357 1358 miSetPixmapDepths(); 1359 1360 /* Point at the visible area to start */ 1361 1362 ret = fbScreenInit(pScrn, pGeode->FBBase + pGeode->displayOffset, 1363 pScrni->virtualX, pScrni->virtualY, 1364 pScrni->xDpi, pScrni->yDpi, pGeode->displayWidth, 1365 pScrni->bitsPerPixel); 1366 1367 if (!ret) 1368 return FALSE; 1369 1370 xf86SetBlackWhitePixels(pScrn); 1371 1372 /* Set up the color ordering */ 1373 1374 if (pScrni->bitsPerPixel > 8) { 1375 VisualPtr visual = pScrn->visuals + pScrn->numVisuals; 1376 1377 while (--visual >= pScrn->visuals) { 1378 if ((visual->class | DynamicClass) == DirectColor) { 1379 visual->offsetRed = pScrni->offset.red; 1380 visual->offsetGreen = pScrni->offset.green; 1381 visual->offsetBlue = pScrni->offset.blue; 1382 visual->redMask = pScrni->mask.red; 1383 visual->greenMask = pScrni->mask.green; 1384 visual->blueMask = pScrni->mask.blue; 1385 } 1386 } 1387 } 1388 1389 /* Must follow the color ordering */ 1390 fbPictureInit(pScrn, 0, 0); 1391 1392 if (!pGeode->NoAccel) 1393 GXAccelInit(pScrn); 1394 1395 xf86SetBackingStore(pScrn); 1396 1397 /* Set up the soft cursor */ 1398 miDCInitialize(pScrn, xf86GetPointerScreenFuncs()); 1399 1400 /* Set up the HW cursor - must follow the soft cursor init */ 1401 1402 if (pGeode->tryHWCursor) { 1403 if (!GXHWCursorInit(pScrn)) 1404 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 1405 "Hardware cursor initialization failed.\n"); 1406 } 1407 1408 /* Set up the color map */ 1409 1410 if (!miCreateDefColormap(pScrn)) 1411 return FALSE; 1412 1413 if (pScrni->bitsPerPixel == 8) { 1414 /* Must follow initialization of the default colormap */ 1415 1416 if (!xf86HandleColormaps(pScrn, 256, 8, 1417 GXLoadPalette, NULL, 1418 CMAP_PALETTED_TRUECOLOR | 1419 CMAP_RELOAD_ON_MODE_SWITCH)) { 1420 return FALSE; 1421 } 1422 } 1423#ifdef DPMSExtension 1424 xf86DPMSInit(pScrn, GXDPMSSet, 0); 1425#endif 1426 1427 GXInitVideo(pScrn); 1428 1429 /* Set up RandR */ 1430 1431#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 24 1432 xf86DisableRandR(); /* We provide our own RandR goodness */ 1433#endif 1434 1435 /* Try to set up the shadow FB for rotation */ 1436 1437 memset(&shadowReq, 0, sizeof(shadowReq)); 1438 shadowReq.majorversion = 1; 1439 shadowReq.minorversion = 1; 1440 1441 if (LoadSubModule(pScrni->module, "shadow", 1442 NULL, NULL, NULL, &shadowReq, &maj, &min)) { 1443 1444 rotate = RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270; 1445 shadowSetup(pScrn); 1446 } 1447 else { 1448 LoaderErrorMsg(NULL, "shadow", maj, min); 1449 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 1450 "Error loading shadow - rotation not available.\n"); 1451 1452 if (pGeode->rotation != RR_Rotate_0) 1453 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 1454 "Reverting back to normal rotation.\n"); 1455 1456 rotate = pGeode->rotation = RR_Rotate_0; 1457 } 1458 1459 GXRandRInit(pScrn, rotate); 1460 1461 pGeode->PointerMoved = pScrni->PointerMoved; 1462 pScrni->PointerMoved = GeodePointerMoved; 1463 1464 pGeode->CreateScreenResources = pScrn->CreateScreenResources; 1465 pScrn->CreateScreenResources = GXCreateScreenResources; 1466 1467 pGeode->CloseScreen = pScrn->CloseScreen; 1468 pScrn->CloseScreen = GXCloseScreen; 1469 pScrn->SaveScreen = GXSaveScreen; 1470 1471 if (serverGeneration == 1) 1472 xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options); 1473 1474 pGeode->starting = FALSE; 1475 1476 return TRUE; 1477} 1478 1479static int 1480GXValidMode(VALID_MODE_ARGS_DECL) 1481{ 1482 SCRN_INFO_PTR(arg); 1483 GeodeRec *pGeode = GEODEPTR(pScrni); 1484 int p; 1485 int custom = 0; 1486 1487 if (pGeode->Panel) 1488 custom = (pMode->type & M_T_USERDEF); 1489 else 1490 custom = (pMode->type & (M_T_BUILTIN | M_T_DEFAULT)); 1491 1492 /* Use the durango lookup for !custom modes */ 1493 1494 if (!custom && pGeode->Panel) { 1495 if (pMode->CrtcHDisplay > pGeode->PanelX || 1496 pMode->CrtcVDisplay > pGeode->PanelY || 1497 gfx_is_panel_mode_supported(pGeode->PanelX, 1498 pGeode->PanelY, 1499 pMode->CrtcHDisplay, 1500 pMode->CrtcVDisplay, 1501 pScrni->bitsPerPixel) < 0) { 1502 1503 return MODE_BAD; 1504 } 1505 } 1506 1507 if (gfx_is_display_mode_supported(pMode->CrtcHDisplay, 1508 pMode->CrtcVDisplay, 1509 pScrni->bitsPerPixel, 1510 GeodeGetRefreshRate(pMode)) < 0) { 1511 return MODE_BAD; 1512 } 1513 1514 if (pMode->Flags & V_INTERLACE) 1515 return MODE_NO_INTERLACE; 1516 1517 if (pGeode->tryCompression) 1518 p = GeodeCalculatePitchBytes(pMode->CrtcHDisplay, pScrni->bitsPerPixel); 1519 else 1520 p = ((pMode->CrtcHDisplay + 3) & ~3) * (pScrni->bitsPerPixel >> 3); 1521 1522 if (p * pMode->CrtcVDisplay > pGeode->FBAvail) 1523 return MODE_MEM; 1524 1525 return MODE_OK; 1526} 1527 1528/* XXX - Way more to do here */ 1529 1530static Bool 1531GXEnterVT(VT_FUNC_ARGS_DECL) 1532{ 1533 SCRN_INFO_PTR(arg); 1534 return GXEnterGraphics(NULL, pScrni); 1535} 1536 1537static void 1538GXLeaveVT(VT_FUNC_ARGS_DECL) 1539{ 1540 SCRN_INFO_PTR(arg); 1541 GeodeRec *pGeode = GEODEPTR(pScrni); 1542 1543 pGeode->PrevDisplayOffset = gfx_get_display_offset(); 1544 GXLeaveGraphics(pScrni); 1545} 1546 1547void 1548GXSetupChipsetFPtr(ScrnInfoPtr pScrn) 1549{ 1550 pScrn->PreInit = GXPreInit; 1551 pScrn->ScreenInit = GXScreenInit; 1552 pScrn->SwitchMode = GXSwitchMode; 1553 pScrn->AdjustFrame = GXAdjustFrame; 1554 pScrn->EnterVT = GXEnterVT; 1555 pScrn->LeaveVT = GXLeaveVT; 1556 pScrn->FreeScreen = GeodeFreeScreen; 1557 pScrn->ValidMode = GXValidMode; 1558} 1559 1560/* ====== Common functions ====== 1561 * These are all the common functions that we use for both GX and LX - They live here 1562 * because most of them came along for the GX first, and then were adapted to the LX. 1563 * We could move these to a common function, but there is no hurry 1564 * ============================== */ 1565 1566void 1567GeodePointerMoved(POINTER_MOVED_ARGS_DECL) 1568{ 1569 SCRN_INFO_PTR(arg); 1570 GeodeRec *pGeode = GEODEPTR(pScrni); 1571 1572 int newX = x, newY = y; 1573 1574 switch (pGeode->rotation) { 1575 case RR_Rotate_0: 1576 break; 1577 case RR_Rotate_90: 1578 newX = y; 1579 newY = pScrni->pScreen->width - x - 1; 1580 break; 1581 case RR_Rotate_180: 1582 newX = pScrni->pScreen->width - x - 1; 1583 newY = pScrni->pScreen->height - y - 1; 1584 break; 1585 case RR_Rotate_270: 1586 newX = pScrni->pScreen->height - y - 1; 1587 newY = x; 1588 break; 1589 } 1590 1591 (*pGeode->PointerMoved) (POINTER_MOVED_ARGS(newX, newY)); 1592} 1593 1594int 1595GeodeGetFPGeometry(const char *str, int *width, int *height) 1596{ 1597 1598 int ret = sscanf(str, "%dx%d", width, height); 1599 1600 return (ret == 2) ? 0 : 1; 1601} 1602 1603static void 1604GeodeFreeRec(ScrnInfoPtr pScrni) 1605{ 1606 if (pScrni->driverPrivate != NULL) { 1607 free(pScrni->driverPrivate); 1608 pScrni->driverPrivate = NULL; 1609 } 1610} 1611 1612void 1613GeodeFreeScreen(FREE_SCREEN_ARGS_DECL) 1614{ 1615 SCRN_INFO_PTR(arg); 1616 GeodeRec *pGeode = GEODEPTR(pScrni); 1617 1618 if (pGeode == NULL) 1619 return; 1620 1621 if (pGeode->useVGA) { 1622 if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 1623 vgaHWFreeHWRec(pScrni); 1624 } 1625 1626 GeodeFreeRec(pScrni); 1627} 1628 1629int 1630GeodeCalculatePitchBytes(unsigned int width, unsigned int bpp) 1631{ 1632 1633 int delta = width * (bpp >> 3); 1634 1635 /* Less then 640 has doubling enabled */ 1636 1637 if (width < 640) 1638 delta <<= 1; 1639 1640 /* Calculate the pitch (compression requires a power of 2) */ 1641 1642 if (delta > 4096) 1643 delta = 8192; 1644 else if (delta > 2048) 1645 delta = 4096; 1646 else if (delta > 1024) 1647 delta = 2048; 1648 else 1649 delta = 1024; 1650 1651 return delta; 1652} 1653