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