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