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