1/* Copyright (c) 2003-2008 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 <string.h> 36#include <fcntl.h> 37#include <unistd.h> 38#include <sys/mman.h> 39 40#include "xorg-server.h" 41 42#include "xf86.h" 43#include "xf86_OSproc.h" 44#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 45#include "xf86Resources.h" 46#endif 47#include "xf86i2c.h" 48#include "xf86Crtc.h" 49#include "xf86cmap.h" 50#include "compiler.h" 51#include "mipointer.h" 52#include "fb.h" 53#include "miscstruct.h" 54#include "micmap.h" 55#include "vbe.h" 56#include "fb.h" 57#include "cim_defs.h" 58#include "cim_regs.h" 59#include "geode.h" 60 61/* Bring in VGA functions */ 62#include "lx_vga.c" 63 64#define LX_MAX_WIDTH 1940 65#define LX_MAX_HEIGHT 1600 66 67/* Size of the register blocks */ 68 69#define LX_GP_REG_SIZE 0x4000 70#define LX_VG_REG_SIZE 0x4000 71#define LX_VID_REG_SIZE 0x4000 72#define LX_VIP_REG_SIZE 0x4000 73 74/* Size of the Cimarron command buffer */ 75#define CIM_CMD_BFR_SZ 0x200000 76 77extern OptionInfoRec LX_GeodeOptions[]; 78 79extern unsigned char *XpressROMPtr; 80 81static Bool 82LXSaveScreen(ScreenPtr pScrn, int mode) 83{ 84 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 85 GeodePtr pGeode = GEODEPTR(pScrni); 86 87 if (pGeode->useVGA && !pScrni->vtSema) 88 return vgaHWSaveScreen(pScrn, mode); 89 90 return TRUE; 91} 92 93/* This is an overly complex MSR read mechanism */ 94 95/* From Cimarron - the VSAII read/write methods - we use these as fallback */ 96 97#define LX_MSR_READ(adr,lo,hi) \ 98 __asm__ __volatile__( \ 99 " mov $0x0AC1C, %%edx\n" \ 100 " mov $0xFC530007, %%eax\n" \ 101 " out %%eax,%%dx\n" \ 102 " add $2,%%dl\n" \ 103 " in %%dx, %%ax" \ 104 : "=a" (lo), "=d" (hi) \ 105 : "c" (adr)) 106 107#define LX_MSR_WRITE(adr,low,high) \ 108 { int d0, d1, d2, d3, d4; \ 109 __asm__ __volatile__( \ 110 " push %%ebx\n" \ 111 " mov $0x0AC1C, %%edx\n" \ 112 " mov $0xFC530007, %%eax\n" \ 113 " out %%eax,%%dx\n" \ 114 " add $2,%%dl\n" \ 115 " mov %6, %%ebx\n" \ 116 " mov %7, %0\n" \ 117 " mov %5, %3\n" \ 118 " xor %2, %2\n" \ 119 " xor %1, %1\n" \ 120 " out %%ax, %%dx\n" \ 121 " pop %%ebx\n" \ 122 : "=a"(d0),"=&D"(d1),"=&S"(d2), \ 123 "=c"(d3),"=d"(d4) \ 124 : "1"(adr),"2"(high),"3"(low)); \ 125 } 126 127static void 128LXReadMSR(unsigned long addr, unsigned long *lo, unsigned long *hi) 129{ 130 if (GeodeReadMSR(addr, lo, hi) == -1) { 131 unsigned int l, h; 132 133 LX_MSR_READ(addr, l, h); 134 *lo = l; 135 *hi = h; 136 } 137} 138 139static void 140LXWriteMSR(unsigned long addr, unsigned long lo, unsigned long hi) 141{ 142 if (GeodeWriteMSR(addr, lo, hi) == -1) 143 LX_MSR_WRITE(addr, lo, hi); 144} 145 146static unsigned int 147LXCalcPitch(ScrnInfoPtr pScrni) 148{ 149 GeodeRec *pGeode = GEODEPTR(pScrni); 150 151 if (pGeode->tryCompression) 152 return GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel); 153 else 154 return ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3); 155} 156 157#ifdef XSERVER_LIBPCIACCESS 158static inline void * 159map_pci_mem(ScrnInfoPtr pScrni, int vram, 160 struct pci_device *dev, int bar, int size) 161{ 162 void *ptr; 163 int map_size = size ? size : dev->regions[bar].size; 164 165 int err = pci_device_map_range(dev, 166 dev->regions[bar].base_addr, 167 map_size, 168 PCI_DEV_MAP_FLAG_WRITABLE | 169 (vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0), 170 &ptr); 171 172 if (err) 173 return NULL; 174 return ptr; 175} 176 177static inline int 178unmap_pci_mem(ScrnInfoPtr pScrni, struct pci_device *dev, void *ptr, int size) 179{ 180 return pci_device_unmap_range(dev, ptr, size); 181} 182 183#endif 184 185static Bool 186LXMapMem(ScrnInfoPtr pScrni) 187{ 188 GeodeRec *pGeode = GEODEPTR(pScrni); 189 int index = pScrni->scrnIndex; 190 unsigned long cmd_bfr_phys; 191 192 pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index); 193 194#ifndef XSERVER_LIBPCIACCESS 195 PCITAG tag; 196 197 tag = pciTag(pci->bus, pci->device, pci->func); 198 199 cim_gp_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO, 200 tag, pci->memBase[1], 201 LX_GP_REG_SIZE); 202 203 cim_vg_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO, 204 tag, pci->memBase[2], 205 LX_VG_REG_SIZE); 206 207 cim_vid_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO, 208 tag, pci->memBase[3], 209 LX_VID_REG_SIZE); 210 211 cim_vip_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO, 212 tag, pci->memBase[4], 213 LX_VIP_REG_SIZE); 214 215 cim_fb_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_FRAMEBUFFER, 216 tag, pci->memBase[0], 217 pGeode->FBAvail + 218 CIM_CMD_BFR_SZ); 219#else 220 cim_gp_ptr = map_pci_mem(pScrni, 0, pci, 1, LX_GP_REG_SIZE); 221 cim_vg_ptr = map_pci_mem(pScrni, 0, pci, 2, LX_VG_REG_SIZE); 222 cim_vid_ptr = map_pci_mem(pScrni, 0, pci, 3, LX_VID_REG_SIZE); 223 cim_vip_ptr = map_pci_mem(pScrni, 0, pci, 4, LX_VIP_REG_SIZE); 224 cim_fb_ptr = 225 map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail + CIM_CMD_BFR_SZ); 226#endif 227 228 if (pScrni->memPhysBase == 0) 229 pScrni->memPhysBase = PCI_REGION_BASE(pci, 0, REGION_MEM); 230 231 cmd_bfr_phys = PCI_REGION_BASE(pci, 0, REGION_MEM) + pGeode->CmdBfrOffset; 232 cim_cmd_base_ptr = cim_fb_ptr + pGeode->CmdBfrOffset; 233 234 if (!cim_gp_ptr || !cim_vg_ptr || !cim_vid_ptr || !cim_fb_ptr || 235 !cim_vip_ptr) 236 return FALSE; 237 238 gp_set_frame_buffer_base(PCI_REGION_BASE(pci, 0, REGION_MEM), 239 pGeode->FBAvail); 240 gp_set_command_buffer_base(cmd_bfr_phys, 0, pGeode->CmdBfrSize); 241 242#ifndef XSERVER_LIBPCIACCESS 243 XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000); 244#else 245 { 246 int fd = open("/dev/mem", O_RDWR); 247 if (fd < 0) { 248 xf86DrvMsg(index, X_ERROR, "Failed to open /dev/mem: %m\n"); 249 return FALSE; 250 } 251 XpressROMPtr = mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xF0000); 252 close(fd); 253 } 254#endif 255 256 pGeode->FBBase = cim_fb_ptr; 257 258 if (!pGeode->NoAccel) 259 pGeode->pExa->memoryBase = pGeode->FBBase; 260 261 xf86DrvMsg(index, X_INFO, "Geode LX video memory %x bytes at %p\n", 262 pGeode->FBAvail, pGeode->FBBase); 263 264 return TRUE; 265} 266 267/* Check to see if VGA exists - we map the space and look for a 268 signature - if it doesn't match exactly, then we assume no VGA. 269*/ 270 271static Bool 272LXCheckVGA(ScrnInfoPtr pScrni, EntityInfoPtr pEnt) 273{ 274#ifndef XSERVER_LIBPCIACCESS 275 unsigned char *ptr; 276 const char *vgasig = "IBM VGA Compatible"; 277 int ret; 278 279 ptr = 280 xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E, 281 strlen(vgasig)); 282 283 if (ptr == NULL) 284 return FALSE; 285 286 ret = memcmp(ptr, vgasig, strlen(vgasig)); 287 xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig)); 288 289 return ret ? FALSE : TRUE; 290#else 291 pciVideoPtr pci = xf86GetPciInfoForEntity(pEnt->index); 292 293 return pci_device_is_boot_vga(pci); 294#endif 295} 296 297static Bool 298LXCrtcResize(ScrnInfoPtr pScrni, int width, int height) 299{ 300 return TRUE; 301} 302 303static const xf86CrtcConfigFuncsRec lx_xf86crtc_config_funcs = { 304 LXCrtcResize, 305}; 306 307static Bool 308LXPreInit(ScrnInfoPtr pScrni, int flags) 309{ 310 GeodePtr pGeode; 311 EntityInfoPtr pEnt; 312 OptionInfoRec *GeodeOptions = &LX_GeodeOptions[0]; 313 rgb defaultWeight = { 0, 0, 0 }; 314 const char *s; 315 316 if (pScrni->numEntities != 1) 317 return FALSE; 318 319 pEnt = xf86GetEntityInfo(pScrni->entityList[0]); 320#ifndef XSERVER_LIBPCIACCESS 321 if (pEnt->resources) 322 return FALSE; 323#endif 324 if (flags & PROBE_DETECT) { 325 GeodeProbeDDC(pScrni, pEnt->index); 326 return TRUE; 327 } 328 329 pGeode = pScrni->driverPrivate = xnfcalloc(1, sizeof(GeodeRec)); 330 331 if (pGeode == NULL) 332 return FALSE; 333 334 pGeode->useVGA = LXCheckVGA(pScrni, pEnt); 335 pGeode->VGAActive = FALSE; 336 pGeode->pEnt = pEnt; 337 338 if (pGeode->useVGA) { 339 if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni)) 340 pGeode->useVGA = FALSE; 341 else 342 vgaHWSetStdFuncs(VGAHWPTR(pScrni)); 343 344 pGeode->vesa = calloc(1, sizeof(VESARec)); 345 } 346 347 cim_rdmsr = LXReadMSR; 348 cim_wrmsr = LXWriteMSR; 349 350 /* Set up the Cimarron MSR tables */ 351 msr_init_table(); 352 353 /* By default, we support panel and CRT - the config file should 354 * disable the ones we don't want 355 */ 356 357 pGeode->Output = OUTPUT_PANEL | OUTPUT_CRT; 358 359 /* Fill in the monitor information */ 360 pScrni->monitor = pScrni->confScreen->monitor; 361 362 if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb)) 363 return FALSE; 364 365 switch (pScrni->depth) { 366 case 8: 367 pScrni->rgbBits = 8; 368 case 16: 369 case 24: 370 case 32: 371 break; 372 default: 373 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 374 "The driver does not support %d as a depth.\n", 375 pScrni->depth); 376 return FALSE; 377 } 378 379 xf86PrintDepthBpp(pScrni); 380 381 if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight)) 382 return FALSE; 383 384 if (!xf86SetDefaultVisual(pScrni, -1)) 385 return FALSE; 386 387 /* 388 * If the driver can do gamma correction, it should call xf86SetGamma() 389 * here. 390 */ 391 { 392 Gamma zeros = { 0.0, 0.0, 0.0 }; 393 394 if (!xf86SetGamma(pScrni, zeros)) { 395 return FALSE; 396 } 397 } 398 399 pScrni->progClock = TRUE; 400 xf86CollectOptions(pScrni, NULL); 401 xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions); 402 403 /* Set up our various options that may get reversed as we go on */ 404 405 pGeode->tryHWCursor = TRUE; 406 pGeode->tryCompression = TRUE; 407 408 /* Protect against old versions of EXA */ 409 410#if (EXA_VERSION_MAJOR < 2) 411 pGeode->NoAccel = TRUE; 412 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 413 "*** This driver was compiled with EXA version %d\n"); 414 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 415 "*** we need version 2 or greater\n"); 416 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 417 "*** All accelerations are being turned off.\n"); 418#else 419 pGeode->NoAccel = FALSE; 420#endif 421 422 pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ; 423 424 xf86GetOptValBool(GeodeOptions, LX_OPTION_HW_CURSOR, &pGeode->tryHWCursor); 425 426 if (!xf86GetOptValInteger(GeodeOptions, LX_OPTION_FBSIZE, 427 (int *) &(pGeode->FBAvail))) 428 pGeode->FBAvail = 0; 429 430 /* For compatibility - allow SWCursor too */ 431 432 if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_SW_CURSOR, FALSE)) 433 pGeode->tryHWCursor = FALSE; 434 435 if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOCOMPRESSION, FALSE)) 436 pGeode->tryCompression = FALSE; 437 438 if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOACCEL, FALSE)) 439 pGeode->NoAccel = TRUE; 440 441 pGeode->rotation = RR_Rotate_0; 442 443 if ((s = xf86GetOptValString(GeodeOptions, LX_OPTION_ROTATE))) { 444 445 if (!xf86NameCmp(s, "LEFT")) 446 pGeode->rotation = RR_Rotate_90; 447 else if (!xf86NameCmp(s, "INVERT")) 448 pGeode->rotation = RR_Rotate_180; 449 else if (!xf86NameCmp(s, "CCW")) 450 pGeode->rotation = RR_Rotate_270; 451 else 452 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "Invalid rotation %s.\n", s); 453 } 454 455 xf86GetOptValInteger(GeodeOptions, LX_OPTION_EXA_SCRATCH_BFRSZ, 456 (int *) &(pGeode->exaBfrSz)); 457 458 if (pGeode->exaBfrSz <= 0) 459 pGeode->exaBfrSz = 0; 460 461 if (pGeode->Output & OUTPUT_PANEL) { 462 if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOPANEL, FALSE)) 463 pGeode->Output &= ~OUTPUT_PANEL; 464 } 465 466 /* Panel detection code - 467 * 1. See if an OLPC DCON is attached - we can make some assumptions 468 * about the panel if so. 469 * 2. Use panel mode specified in the config 470 * 3. "Autodetect" the panel through VSA 471 */ 472 473 if (dcon_init(pScrni)) { 474 pGeode->Output = OUTPUT_PANEL | OUTPUT_DCON; 475 } 476 else if (pGeode->Output & OUTPUT_PANEL) { 477 const char *pmode = xf86GetOptValString(GeodeOptions, LX_OPTION_PANEL_MODE); 478 479 if (pmode != NULL) 480 pGeode->panelMode = LXGetManualPanelMode(pmode); 481 482 if (pGeode->panelMode == NULL) 483 pGeode->panelMode = LXGetLegacyPanelMode(pScrni); 484 485 if (pGeode->panelMode == NULL) 486 pGeode->Output &= ~OUTPUT_PANEL; 487 } 488 489 /* Default to turn scaling on for panels */ 490 491 if (pGeode->Output & OUTPUT_PANEL) 492 pGeode->Scale = TRUE; 493 494 xf86DrvMsg(pScrni->scrnIndex, X_INFO, "LX output options:\n"); 495 xf86DrvMsg(pScrni->scrnIndex, X_INFO, " CRT: %s\n", 496 pGeode->Output & OUTPUT_CRT ? "YES" : "NO"); 497 498 xf86DrvMsg(pScrni->scrnIndex, X_INFO, " PANEL: %s\n", 499 pGeode->Output & OUTPUT_PANEL ? "YES" : "NO"); 500 501 xf86DrvMsg(pScrni->scrnIndex, X_INFO, " DCON: %s\n", 502 pGeode->Output & OUTPUT_DCON ? "YES" : "NO"); 503 504 xf86DrvMsg(pScrni->scrnIndex, X_INFO, " VGA: %s\n", 505 pGeode->useVGA ? "YES" : "NO"); 506 507 /* Set up VGA */ 508 509 if (pGeode->useVGA) { 510 VESARec *pVesa; 511 512 if (!xf86LoadSubModule(pScrni, "int10")) 513 return FALSE; 514 515 pVesa = pGeode->vesa; 516 517 if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) { 518 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 519 "Unable to initialize 1NT10 support\n"); 520 pGeode->useVGA = FALSE; 521 } 522 } 523 524 /* Read the amount of framebuffer memory */ 525 /* First try to read it from the framebuffer, and if that fails, 526 * do it the legacy way 527 */ 528 529 if (pGeode->FBAvail == 0) { 530 if (GeodeGetSizeFromFB(&pGeode->FBAvail)) { 531 unsigned long value; 532 533 cim_outw(0xAC1C, 0xFC53); 534 cim_outw(0xAC1C, 0x0200); 535 536 value = (unsigned long) (cim_inw(0xAC1E)) & 0xFE; 537 pGeode->FBAvail = value << 20; 538 } 539 } 540 541 pScrni->fbOffset = 0; 542 543 if (pGeode->pEnt->device->videoRam == 0) 544 pScrni->videoRam = pGeode->FBAvail / 1024; 545 else { 546 pScrni->videoRam = pGeode->pEnt->device->videoRam; 547 pGeode->FBAvail = pScrni->videoRam << 10; 548 } 549 550 /* If we have <= 16Mb of memory then compression is going 551 to hurt - so warn and disable */ 552 553 if (pGeode->tryCompression && pGeode->FBAvail <= 0x1000000) { 554 xf86DrvMsg(pScrni->scrnIndex, X_INFO, 555 "%x bytes of video memory is less then optimal\n", 556 pGeode->FBAvail); 557 xf86DrvMsg(pScrni->scrnIndex, X_INFO, 558 "when compression is on. Disabling compression.\n"); 559 pGeode->tryCompression = FALSE; 560 } 561 562 /* Carve out some memory for the command buffer */ 563 564 pGeode->CmdBfrSize = CIM_CMD_BFR_SZ; 565 pGeode->FBAvail -= CIM_CMD_BFR_SZ; 566 567 pGeode->CmdBfrOffset = pGeode->FBAvail; 568 569 /* Allocate a a CRTC config structure */ 570 xf86CrtcConfigInit(pScrni, &lx_xf86crtc_config_funcs); 571 572 /* Set up the GPU CRTC */ 573 LXSetupCrtc(pScrni); 574 575 xf86CrtcSetSizeRange(pScrni, 320, 200, LX_MAX_WIDTH, LX_MAX_HEIGHT); 576 577 /* Setup the output */ 578 LXSetupOutput(pScrni); 579 580 if (!xf86InitialConfiguration(pScrni, FALSE)) { 581 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes.\n"); 582 return FALSE; 583 } 584 585 xf86PrintModes(pScrni); 586 587 pScrni->currentMode = pScrni->modes; 588 589 pGeode->Pitch = LXCalcPitch(pScrni); 590 591 xf86SetDpi(pScrni, 0, 0); 592 593 /* Load the modules we'll need */ 594 595 if (xf86LoadSubModule(pScrni, "fb") == NULL) { 596 return FALSE; 597 } 598 599 if (!pGeode->NoAccel) { 600 if (!xf86LoadSubModule(pScrni, "exa")) 601 return FALSE; 602 } 603#ifndef XSERVER_LIBPCIACCESS 604 if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) { 605 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 606 "Couldn't register the resources.\n"); 607 return FALSE; 608 } 609#endif 610 return TRUE; 611} 612 613static void 614LXRestore(ScrnInfoPtr pScrni) 615{ 616 GeodeRec *pGeode = GEODEPTR(pScrni); 617 618 if (pGeode->useVGA) { 619 vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 620 621 vgaHWProtect(pScrni, TRUE); 622 vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL); 623 vgaHWProtect(pScrni, FALSE); 624 } 625} 626 627static Bool 628LXUnmapMem(ScrnInfoPtr pScrni) 629{ 630#ifndef XSERVER_LIBPCIACCESS 631 xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_gp_ptr, LX_GP_REG_SIZE); 632 xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vg_ptr, LX_VG_REG_SIZE); 633 xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vid_ptr, LX_VID_REG_SIZE); 634 xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vip_ptr, LX_VIP_REG_SIZE); 635 636 xf86UnMapVidMem(pScrni->scrnIndex, XpressROMPtr, 0x10000); 637#else 638 GeodeRec *pGeode = GEODEPTR(pScrni); 639 pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index); 640 641 unmap_pci_mem(pScrni, pci, cim_gp_ptr, LX_GP_REG_SIZE); 642 unmap_pci_mem(pScrni, pci, cim_vg_ptr, LX_VG_REG_SIZE); 643 unmap_pci_mem(pScrni, pci, cim_vid_ptr, LX_VID_REG_SIZE); 644 unmap_pci_mem(pScrni, pci, cim_vip_ptr, LX_VIP_REG_SIZE); 645 unmap_pci_mem(pScrni, pci, cim_fb_ptr, pGeode->FBAvail + CIM_CMD_BFR_SZ); 646 647 munmap(XpressROMPtr, 0x10000); 648#endif 649 650 return TRUE; 651} 652 653/* These should be correctly accounted for rotation */ 654 655void 656LXAdjustFrame(ADJUST_FRAME_ARGS_DECL) 657{ 658 SCRN_INFO_PTR(arg); 659 GeodeRec *pGeode = GEODEPTR(pScrni); 660 661 unsigned long offset; 662 663 offset = (y * pGeode->Pitch); 664 offset += x * (pScrni->bitsPerPixel >> 3); 665 666 vg_set_display_offset(offset); 667} 668 669static Bool 670LXSwitchMode(SWITCH_MODE_ARGS_DECL) 671{ 672 SCRN_INFO_PTR(arg); 673 GeodeRec *pGeode = GEODEPTR(pScrni); 674 675 /* Set the new mode */ 676 return xf86SetSingleMode(pScrni, pMode, pGeode->rotation); 677} 678 679static void 680LXLeaveGraphics(ScrnInfoPtr pScrni) 681{ 682 GeodeRec *pGeode = GEODEPTR(pScrni); 683 VG_PANNING_COORDINATES panning; 684 685 gp_wait_until_idle(); 686 687 lx_disable_dac_power(pScrni, DF_CRT_DISABLE); 688 689 vg_set_custom_mode(&(pGeode->FBcimdisplaytiming.vgDisplayMode), 690 pGeode->FBcimdisplaytiming.wBpp); 691 692 vg_set_compression_enable(0); 693 694 /* Restore the previous Compression state */ 695 if (pGeode->FBCompressionEnable) { 696 vg_configure_compression(&(pGeode->FBCBData)); 697 vg_set_compression_enable(1); 698 } 699 700 vg_set_display_pitch(pGeode->FBcimdisplaytiming.wPitch); 701 vg_set_display_offset(pGeode->FBDisplayOffset); 702 703 /* Restore Cursor */ 704 vg_set_cursor_position(pGeode->FBCursor.cursor_x, 705 pGeode->FBCursor.cursor_y, &panning); 706 707 LXRestore(pScrni); 708 709 if (pGeode->useVGA && pGeode->VGAActive) { 710 pGeode->vesa->pInt->num = 0x10; 711 pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode; 712 pGeode->vesa->pInt->bx = 0; 713 xf86ExecX86int10(pGeode->vesa->pInt); 714 vg_delay_milliseconds(3); 715 } 716 717 lx_enable_dac_power(pScrni, 1); 718 pScrni->vtSema = FALSE; 719} 720 721static Bool 722LXCloseScreen(CLOSE_SCREEN_ARGS_DECL) 723{ 724 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 725 GeodeRec *pGeode = GEODEPTR(pScrni); 726 727 if (pScrni->vtSema) 728 LXLeaveGraphics(pScrni); 729 730 if (pGeode->pExa) { 731 exaDriverFini(pScrn); 732 free(pGeode->pExa); 733 pGeode->pExa = NULL; 734 } 735 736 /* Unmap the offscreen allocations */ 737 GeodeCloseOffscreen(pScrni); 738 739 LXUnmapMem(pScrni); 740 741 if (pGeode->useVGA) 742 vgaHWUnmapMem(pScrni); 743 744 pScrni->PointerMoved = pGeode->PointerMoved; 745 pScrn->CloseScreen = pGeode->CloseScreen; 746 747 if (pScrn->CloseScreen) 748 return (*pScrn->CloseScreen) (CLOSE_SCREEN_ARGS); 749 750 return TRUE; 751} 752 753static Bool 754LXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni) 755{ 756 int bpp; 757 GeodeRec *pGeode = GEODEPTR(pScrni); 758 759 pGeode->VGAActive = gu3_get_vga_active(); 760 761 gp_wait_until_idle(); 762 763 vg_get_current_display_mode(&pGeode->FBcimdisplaytiming.vgDisplayMode, 764 &bpp); 765 766 pGeode->FBcimdisplaytiming.wBpp = bpp; 767 pGeode->FBcimdisplaytiming.wPitch = vg_get_display_pitch(); 768 769 pGeode->FBDisplayOffset = vg_get_display_offset(); 770 771 if (pGeode->useVGA && pGeode->VGAActive) { 772 vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 773 774 pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040); 775 } 776 777 pGeode->FBCompressionEnable = vg_get_compression_enable(); 778 vg_get_compression_info(&(pGeode->FBCBData)); 779 780 /* Save Cursor offset */ 781 vg_get_cursor_info(&pGeode->FBCursor); 782 783 /* Turn off the VGA */ 784 785 if (pGeode->useVGA) { 786 unsigned short sequencer; 787 vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 788 789 /* Unlock VGA registers */ 790 vgaHWUnlock(pvgaHW); 791 792 /* Save the current state and setup the current mode */ 793 vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL); 794 795 /* DISABLE VGA SEQUENCER */ 796 /* This allows the VGA state machine to terminate. We must delay */ 797 /* such that there are no pending MBUS requests. */ 798 799 cim_outb(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_CLK_MODE); 800 sequencer = cim_inb(DC3_SEQUENCER_DATA); 801 sequencer |= DC3_CLK_MODE_SCREEN_OFF; 802 cim_outb(DC3_SEQUENCER_DATA, sequencer); 803 804 vg_delay_milliseconds(1); 805 806 /* BLANK THE VGA DISPLAY */ 807 cim_outw(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_RESET); 808 sequencer = cim_inb(DC3_SEQUENCER_DATA); 809 sequencer &= ~DC3_RESET_VGA_DISP_ENABLE; 810 cim_outb(DC3_SEQUENCER_DATA, sequencer); 811 812 vg_delay_milliseconds(1); 813 } 814 815 /* Clear the framebuffer */ 816 memset(pGeode->FBBase, 0, pGeode->displaySize); 817 818 /* Set the modes */ 819 if (!xf86SetDesiredModes(pScrni)) 820 return FALSE; 821 822 pScrni->vtSema = TRUE; 823 824 return TRUE; 825} 826 827static void 828LXLoadPalette(ScrnInfoPtr pScrni, 829 int numColors, int *indizes, LOCO * colors, VisualPtr pVisual) 830{ 831 int i, index, color; 832 833 for (i = 0; i < numColors; i++) { 834 index = indizes[i] & 0xFF; 835 color = (((unsigned long) (colors[index].red & 0xFF)) << 16) | 836 (((unsigned long) (colors[index].green & 0xFF)) << 8) | 837 ((unsigned long) (colors[index].blue & 0xFF)); 838 839 vg_set_display_palette_entry(index, color); 840 } 841} 842 843static Bool 844LXScreenInit(SCREEN_INIT_ARGS_DECL) 845{ 846 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 847 GeodeRec *pGeode = GEODEPTR(pScrni); 848 int ret; 849 unsigned int dwidth; 850 851 pGeode->starting = TRUE; 852 853 /* If we are using VGA then go ahead and map the memory */ 854 855 if (pGeode->useVGA) { 856 857 if (!vgaHWMapMem(pScrni)) 858 return FALSE; 859 860 vgaHWGetIOBase(VGAHWPTR(pScrni)); 861 } 862 863 if (!pGeode->NoAccel) { 864 865 pGeode->pExa = exaDriverAlloc(); 866 867 if (pGeode->pExa) { 868 869 pGeode->pExa->memoryBase = 0; 870 pGeode->pExa->memorySize = 0; 871 872 pGeode->pExa->pixmapOffsetAlign = 32; 873 pGeode->pExa->pixmapPitchAlign = 32; 874 pGeode->pExa->flags = EXA_OFFSCREEN_PIXMAPS; 875 pGeode->pExa->maxX = LX_MAX_WIDTH - 1; 876 pGeode->pExa->maxY = LX_MAX_HEIGHT - 1; 877 } 878 else { 879 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 880 "Couldn't allocate the EXA structure.\n"); 881 pGeode->NoAccel = TRUE; 882 } 883 } 884 885 /* Map the memory here before doing anything else */ 886 887 if (!LXMapMem(pScrni)) 888 return FALSE; 889 890 LXInitOffscreen(pScrni); 891 892 /* XXX FIXME - Take down any of the structures on failure? */ 893 if (!LXEnterGraphics(pScrn, pScrni)) 894 return FALSE; 895 896 miClearVisualTypes(); 897 898 /* XXX Again - take down anything? */ 899 900 if (pScrni->bitsPerPixel > 8) { 901 if (!miSetVisualTypes(pScrni->depth, 902 TrueColorMask, pScrni->rgbBits, 903 pScrni->defaultVisual)) { 904 return FALSE; 905 } 906 } 907 else { 908 if (!miSetVisualTypes(pScrni->depth, 909 miGetDefaultVisualMask(pScrni->depth), 910 pScrni->rgbBits, pScrni->defaultVisual)) { 911 return FALSE; 912 } 913 } 914 915 miSetPixmapDepths(); 916 917 if (pScrni->virtualX > pScrni->displayWidth) 918 pScrni->displayWidth = pScrni->virtualX; 919 920 /* Point at the visible area to start */ 921 922 /* fbScreenInit assumes that the stride is display width * 923 * bytes per pixel. If compression is on, then our stride might 924 * be completely different, so we divide the pitch by the 925 * bytes per pixel to fake fbScreenInit into doing the right thing */ 926 927 dwidth = pGeode->Pitch / ((pScrni->bitsPerPixel + 7) / 8); 928 929 ret = fbScreenInit(pScrn, pGeode->FBBase, 930 pScrni->virtualX, pScrni->virtualY, 931 pScrni->xDpi, pScrni->yDpi, dwidth, 932 pScrni->bitsPerPixel); 933 934 if (!ret) 935 return FALSE; 936 937 xf86SetBlackWhitePixels(pScrn); 938 939 /* Set up the color ordering */ 940 if (pScrni->bitsPerPixel > 8) { 941 VisualPtr visual = pScrn->visuals + pScrn->numVisuals; 942 943 while (--visual >= pScrn->visuals) { 944 if ((visual->class | DynamicClass) == DirectColor) { 945 visual->offsetRed = pScrni->offset.red; 946 visual->offsetGreen = pScrni->offset.green; 947 visual->offsetBlue = pScrni->offset.blue; 948 visual->redMask = pScrni->mask.red; 949 visual->greenMask = pScrni->mask.green; 950 visual->blueMask = pScrni->mask.blue; 951 } 952 } 953 } 954 955 /* Must follow the color ordering */ 956 fbPictureInit(pScrn, 0, 0); 957 958 if (!pGeode->NoAccel) 959 pGeode->NoAccel = LXExaInit(pScrn) ? FALSE : TRUE; 960 961 xf86SetBackingStore(pScrn); 962 963 /* Set up the soft cursor */ 964 miDCInitialize(pScrn, xf86GetPointerScreenFuncs()); 965 966 /* Set up the HW cursor - must follow the soft cursor init */ 967 968 if (pGeode->tryHWCursor) { 969 if (!LXCursorInit(pScrn)) 970 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 971 "Hardware cursor initialization failed.\n"); 972 } 973 974 /* Set up the color map */ 975 976 if (!miCreateDefColormap(pScrn)) 977 return FALSE; 978 979 if (pScrni->bitsPerPixel == 8) { 980 /* Must follow initialization of the default colormap */ 981 982 if (!xf86HandleColormaps(pScrn, 256, 8, 983 LXLoadPalette, NULL, 984 CMAP_PALETTED_TRUECOLOR | 985 CMAP_RELOAD_ON_MODE_SWITCH)) { 986 return FALSE; 987 } 988 } 989 xf86DPMSInit(pScrn, xf86DPMSSet, 0); 990 991 LXInitVideo(pScrn); 992 993 pGeode->PointerMoved = pScrni->PointerMoved; 994 pScrni->PointerMoved = GeodePointerMoved; 995 996 pGeode->CloseScreen = pScrn->CloseScreen; 997 pScrn->CloseScreen = LXCloseScreen; 998 pScrn->SaveScreen = LXSaveScreen; 999 1000 if (!xf86CrtcScreenInit(pScrn)) { 1001 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "CRTCScreenInit failed.\n"); 1002 return FALSE; 1003 } 1004 1005 if (serverGeneration == 1) 1006 xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options); 1007 1008 pGeode->starting = FALSE; 1009 1010 return TRUE; 1011} 1012 1013static int 1014LXValidMode(VALID_MODE_ARGS_DECL) 1015{ 1016 return MODE_OK; 1017} 1018 1019static Bool 1020LXEnterVT(VT_FUNC_ARGS_DECL) 1021{ 1022 SCRN_INFO_PTR(arg); 1023 return LXEnterGraphics(NULL, pScrni); 1024} 1025 1026static void 1027LXLeaveVT(VT_FUNC_ARGS_DECL) 1028{ 1029 SCRN_INFO_PTR(arg); 1030 GeodeRec *pGeode = GEODEPTR(pScrni); 1031 1032 pGeode->PrevDisplayOffset = vg_get_display_offset(); 1033 LXLeaveGraphics(pScrni); 1034} 1035 1036void 1037LXSetupChipsetFPtr(ScrnInfoPtr pScrn) 1038{ 1039 pScrn->PreInit = LXPreInit; 1040 pScrn->ScreenInit = LXScreenInit; 1041 pScrn->SwitchMode = LXSwitchMode; 1042 pScrn->AdjustFrame = LXAdjustFrame; 1043 pScrn->EnterVT = LXEnterVT; 1044 pScrn->LeaveVT = LXLeaveVT; 1045 pScrn->FreeScreen = GeodeFreeScreen; 1046 pScrn->ValidMode = LXValidMode; 1047} 1048