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