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