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