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