lx_driver.c revision 3406bd8e
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 vg_set_custom_mode(&(pGeode->FBcimdisplaytiming.vgDisplayMode), 687 pGeode->FBcimdisplaytiming.wBpp); 688 689 vg_set_compression_enable(0); 690 691 /* Restore the previous Compression state */ 692 if (pGeode->FBCompressionEnable) { 693 vg_configure_compression(&(pGeode->FBCBData)); 694 vg_set_compression_enable(1); 695 } 696 697 vg_set_display_pitch(pGeode->FBcimdisplaytiming.wPitch); 698 vg_set_display_offset(pGeode->FBDisplayOffset); 699 700 /* Restore Cursor */ 701 vg_set_cursor_position(pGeode->FBCursor.cursor_x, 702 pGeode->FBCursor.cursor_y, &panning); 703 704 LXRestore(pScrni); 705 706 if (pGeode->useVGA && pGeode->VGAActive) { 707 pGeode->vesa->pInt->num = 0x10; 708 pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode; 709 pGeode->vesa->pInt->bx = 0; 710 xf86ExecX86int10(pGeode->vesa->pInt); 711 vg_delay_milliseconds(3); 712 } 713 714 pScrni->vtSema = FALSE; 715} 716 717static Bool 718LXCloseScreen(CLOSE_SCREEN_ARGS_DECL) 719{ 720 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 721 GeodeRec *pGeode = GEODEPTR(pScrni); 722 723 if (pScrni->vtSema) 724 LXLeaveGraphics(pScrni); 725 726 if (pGeode->pExa) { 727 exaDriverFini(pScrn); 728 free(pGeode->pExa); 729 pGeode->pExa = NULL; 730 } 731 732 /* Unmap the offscreen allocations */ 733 GeodeCloseOffscreen(pScrni); 734 735 LXUnmapMem(pScrni); 736 737 if (pGeode->useVGA) 738 vgaHWUnmapMem(pScrni); 739 740 pScrni->PointerMoved = pGeode->PointerMoved; 741 pScrn->CloseScreen = pGeode->CloseScreen; 742 743 if (pScrn->CloseScreen) 744 return (*pScrn->CloseScreen) (CLOSE_SCREEN_ARGS); 745 746 return TRUE; 747} 748 749static Bool 750LXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni) 751{ 752 int bpp; 753 GeodeRec *pGeode = GEODEPTR(pScrni); 754 755 pGeode->VGAActive = gu3_get_vga_active(); 756 757 gp_wait_until_idle(); 758 759 vg_get_current_display_mode(&pGeode->FBcimdisplaytiming.vgDisplayMode, 760 &bpp); 761 762 pGeode->FBcimdisplaytiming.wBpp = bpp; 763 pGeode->FBcimdisplaytiming.wPitch = vg_get_display_pitch(); 764 765 pGeode->FBDisplayOffset = vg_get_display_offset(); 766 767 if (pGeode->useVGA && pGeode->VGAActive) { 768 vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 769 770 pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040); 771 } 772 773 pGeode->FBCompressionEnable = vg_get_compression_enable(); 774 vg_get_compression_info(&(pGeode->FBCBData)); 775 776 /* Save Cursor offset */ 777 vg_get_cursor_info(&pGeode->FBCursor); 778 779 /* Turn off the VGA */ 780 781 if (pGeode->useVGA) { 782 unsigned short sequencer; 783 vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 784 785 /* Unlock VGA registers */ 786 vgaHWUnlock(pvgaHW); 787 788 /* Save the current state and setup the current mode */ 789 vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL); 790 791 /* DISABLE VGA SEQUENCER */ 792 /* This allows the VGA state machine to terminate. We must delay */ 793 /* such that there are no pending MBUS requests. */ 794 795 cim_outb(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_CLK_MODE); 796 sequencer = cim_inb(DC3_SEQUENCER_DATA); 797 sequencer |= DC3_CLK_MODE_SCREEN_OFF; 798 cim_outb(DC3_SEQUENCER_DATA, sequencer); 799 800 vg_delay_milliseconds(1); 801 802 /* BLANK THE VGA DISPLAY */ 803 cim_outw(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_RESET); 804 sequencer = cim_inb(DC3_SEQUENCER_DATA); 805 sequencer &= ~DC3_RESET_VGA_DISP_ENABLE; 806 cim_outb(DC3_SEQUENCER_DATA, sequencer); 807 808 vg_delay_milliseconds(1); 809 } 810 811 /* Clear the framebuffer */ 812 memset(pGeode->FBBase, 0, pGeode->displaySize); 813 814 /* Set the modes */ 815 if (!xf86SetDesiredModes(pScrni)) 816 return FALSE; 817 818 pScrni->vtSema = TRUE; 819 820 return TRUE; 821} 822 823static void 824LXLoadPalette(ScrnInfoPtr pScrni, 825 int numColors, int *indizes, LOCO * colors, VisualPtr pVisual) 826{ 827 int i, index, color; 828 829 for (i = 0; i < numColors; i++) { 830 index = indizes[i] & 0xFF; 831 color = (((unsigned long) (colors[index].red & 0xFF)) << 16) | 832 (((unsigned long) (colors[index].green & 0xFF)) << 8) | 833 ((unsigned long) (colors[index].blue & 0xFF)); 834 835 vg_set_display_palette_entry(index, color); 836 } 837} 838 839static Bool 840LXScreenInit(SCREEN_INIT_ARGS_DECL) 841{ 842 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 843 GeodeRec *pGeode = GEODEPTR(pScrni); 844 int ret; 845 unsigned int dwidth; 846 847 pGeode->starting = TRUE; 848 849 /* If we are using VGA then go ahead and map the memory */ 850 851 if (pGeode->useVGA) { 852 853 if (!vgaHWMapMem(pScrni)) 854 return FALSE; 855 856 vgaHWGetIOBase(VGAHWPTR(pScrni)); 857 } 858 859 if (!pGeode->NoAccel) { 860 861 pGeode->pExa = exaDriverAlloc(); 862 863 if (pGeode->pExa) { 864 865 pGeode->pExa->memoryBase = 0; 866 pGeode->pExa->memorySize = 0; 867 868 pGeode->pExa->pixmapOffsetAlign = 32; 869 pGeode->pExa->pixmapPitchAlign = 32; 870 pGeode->pExa->flags = EXA_OFFSCREEN_PIXMAPS; 871 pGeode->pExa->maxX = LX_MAX_WIDTH - 1; 872 pGeode->pExa->maxY = LX_MAX_HEIGHT - 1; 873 } 874 else { 875 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 876 "Couldn't allocate the EXA structure.\n"); 877 pGeode->NoAccel = TRUE; 878 } 879 } 880 881 /* Map the memory here before doing anything else */ 882 883 if (!LXMapMem(pScrni)) 884 return FALSE; 885 886 LXInitOffscreen(pScrni); 887 888 /* XXX FIXME - Take down any of the structures on failure? */ 889 if (!LXEnterGraphics(pScrn, pScrni)) 890 return FALSE; 891 892 miClearVisualTypes(); 893 894 /* XXX Again - take down anything? */ 895 896 if (pScrni->bitsPerPixel > 8) { 897 if (!miSetVisualTypes(pScrni->depth, 898 TrueColorMask, pScrni->rgbBits, 899 pScrni->defaultVisual)) { 900 return FALSE; 901 } 902 } 903 else { 904 if (!miSetVisualTypes(pScrni->depth, 905 miGetDefaultVisualMask(pScrni->depth), 906 pScrni->rgbBits, pScrni->defaultVisual)) { 907 return FALSE; 908 } 909 } 910 911 miSetPixmapDepths(); 912 913 if (pScrni->virtualX > pScrni->displayWidth) 914 pScrni->displayWidth = pScrni->virtualX; 915 916 /* Point at the visible area to start */ 917 918 /* fbScreenInit assumes that the stride is display width * 919 * bytes per pixel. If compression is on, then our stride might 920 * be completely different, so we divide the pitch by the 921 * bytes per pixel to fake fbScreenInit into doing the right thing */ 922 923 dwidth = pGeode->Pitch / ((pScrni->bitsPerPixel + 7) / 8); 924 925 ret = fbScreenInit(pScrn, pGeode->FBBase, 926 pScrni->virtualX, pScrni->virtualY, 927 pScrni->xDpi, pScrni->yDpi, dwidth, 928 pScrni->bitsPerPixel); 929 930 if (!ret) 931 return FALSE; 932 933 xf86SetBlackWhitePixels(pScrn); 934 935 /* Set up the color ordering */ 936 if (pScrni->bitsPerPixel > 8) { 937 VisualPtr visual = pScrn->visuals + pScrn->numVisuals; 938 939 while (--visual >= pScrn->visuals) { 940 if ((visual->class | DynamicClass) == DirectColor) { 941 visual->offsetRed = pScrni->offset.red; 942 visual->offsetGreen = pScrni->offset.green; 943 visual->offsetBlue = pScrni->offset.blue; 944 visual->redMask = pScrni->mask.red; 945 visual->greenMask = pScrni->mask.green; 946 visual->blueMask = pScrni->mask.blue; 947 } 948 } 949 } 950 951 /* Must follow the color ordering */ 952 fbPictureInit(pScrn, 0, 0); 953 954 if (!pGeode->NoAccel) 955 pGeode->NoAccel = LXExaInit(pScrn) ? FALSE : TRUE; 956 957 xf86SetBackingStore(pScrn); 958 959 /* Set up the soft cursor */ 960 miDCInitialize(pScrn, xf86GetPointerScreenFuncs()); 961 962 /* Set up the HW cursor - must follow the soft cursor init */ 963 964 if (pGeode->tryHWCursor) { 965 if (!LXCursorInit(pScrn)) 966 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 967 "Hardware cursor initialization failed.\n"); 968 } 969 970 /* Set up the color map */ 971 972 if (!miCreateDefColormap(pScrn)) 973 return FALSE; 974 975 if (pScrni->bitsPerPixel == 8) { 976 /* Must follow initialization of the default colormap */ 977 978 if (!xf86HandleColormaps(pScrn, 256, 8, 979 LXLoadPalette, NULL, 980 CMAP_PALETTED_TRUECOLOR | 981 CMAP_RELOAD_ON_MODE_SWITCH)) { 982 return FALSE; 983 } 984 } 985 xf86DPMSInit(pScrn, xf86DPMSSet, 0); 986 987 LXInitVideo(pScrn); 988 989 pGeode->PointerMoved = pScrni->PointerMoved; 990 pScrni->PointerMoved = GeodePointerMoved; 991 992 pGeode->CloseScreen = pScrn->CloseScreen; 993 pScrn->CloseScreen = LXCloseScreen; 994 pScrn->SaveScreen = LXSaveScreen; 995 996 if (!xf86CrtcScreenInit(pScrn)) { 997 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "CRTCScreenInit failed.\n"); 998 return FALSE; 999 } 1000 1001 if (serverGeneration == 1) 1002 xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options); 1003 1004 pGeode->starting = FALSE; 1005 1006 return TRUE; 1007} 1008 1009static int 1010LXValidMode(VALID_MODE_ARGS_DECL) 1011{ 1012 return MODE_OK; 1013} 1014 1015static Bool 1016LXEnterVT(VT_FUNC_ARGS_DECL) 1017{ 1018 SCRN_INFO_PTR(arg); 1019 return LXEnterGraphics(NULL, pScrni); 1020} 1021 1022static void 1023LXLeaveVT(VT_FUNC_ARGS_DECL) 1024{ 1025 SCRN_INFO_PTR(arg); 1026 GeodeRec *pGeode = GEODEPTR(pScrni); 1027 1028 pGeode->PrevDisplayOffset = vg_get_display_offset(); 1029 LXLeaveGraphics(pScrni); 1030} 1031 1032void 1033LXSetupChipsetFPtr(ScrnInfoPtr pScrn) 1034{ 1035 pScrn->PreInit = LXPreInit; 1036 pScrn->ScreenInit = LXScreenInit; 1037 pScrn->SwitchMode = LXSwitchMode; 1038 pScrn->AdjustFrame = LXAdjustFrame; 1039 pScrn->EnterVT = LXEnterVT; 1040 pScrn->LeaveVT = LXLeaveVT; 1041 pScrn->FreeScreen = GeodeFreeScreen; 1042 pScrn->ValidMode = LXValidMode; 1043} 1044