gx_driver.c revision c744f008
141687f09Smrg/* Copyright (c) 2003-2006 Advanced Micro Devices, Inc. 241687f09Smrg * 341687f09Smrg * Portioned modeled from xf86-video-intel/src/i830_driver.c 441687f09Smrg * Copyright 2001 VA Linux Systems Inc., Fremont, California. 541687f09Smrg * Copyright \ufffd 2002 by David Dawes 641687f09Smrg 741687f09Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy 841687f09Smrg * of this software and associated documentation files (the "Software"), to 941687f09Smrg * deal in the Software without restriction, including without limitation the 1041687f09Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 1141687f09Smrg * sell copies of the Software, and to permit persons to whom the Software is 1241687f09Smrg * furnished to do so, subject to the following conditions: 1341687f09Smrg * 1441687f09Smrg * The above copyright notice and this permission notice shall be included in 1541687f09Smrg * all copies or substantial portions of the Software. 1641687f09Smrg * 1741687f09Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1841687f09Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1941687f09Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2041687f09Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2141687f09Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2241687f09Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2341687f09Smrg * IN THE SOFTWARE. 2441687f09Smrg * 2541687f09Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 2641687f09Smrg * contributors may be used to endorse or promote products derived from this 2741687f09Smrg * software without specific prior written permission. 2841687f09Smrg */ 2941687f09Smrg 3041687f09Smrg#ifdef HAVE_CONFIG_H 3141687f09Smrg#include "config.h" 3241687f09Smrg#endif 3341687f09Smrg 3441687f09Smrg#include <stdio.h> 3541687f09Smrg#include <fcntl.h> 3641687f09Smrg#include <unistd.h> 3741687f09Smrg#include <sys/mman.h> 3841687f09Smrg 3941687f09Smrg#include "xorg-server.h" 4041687f09Smrg 4141687f09Smrg#include "xf86.h" 4241687f09Smrg#include "xf86_OSproc.h" 4341687f09Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 4441687f09Smrg#include "xf86Resources.h" 4541687f09Smrg#endif 4641687f09Smrg#include "xf86cmap.h" 4741687f09Smrg#include "compiler.h" 4841687f09Smrg#include "mipointer.h" 4941687f09Smrg#include "shadow.h" 5041687f09Smrg#include <X11/extensions/randr.h> 5141687f09Smrg#include "fb.h" 5241687f09Smrg#include "miscstruct.h" 5341687f09Smrg#include "micmap.h" 5441687f09Smrg#include "vbe.h" 5541687f09Smrg#include "fb.h" 5641687f09Smrg#include "randrstr.h" 5741687f09Smrg 5841687f09Smrg#include "geode.h" 5941687f09Smrg#include "gfx_defs.h" 6041687f09Smrg#include "gfx_regs.h" 6141687f09Smrg#include "panel.h" 6241687f09Smrg 6341687f09Smrg/* Bring in VGA functions */ 6441687f09Smrg#include "gx_vga.c" 6541687f09Smrg 6641687f09Smrg#define GX_MIN_PITCH 1024 6741687f09Smrg#define GX_MAX_PITCH 8192 6841687f09Smrg#define GX_MAX_WIDTH 1600 6941687f09Smrg#define GX_MIN_HEIGHT 400 7041687f09Smrg#define GX_MAX_HEIGHT 1200 7141687f09Smrg#define GX_CB_PITCH 544 7241687f09Smrg#define GX_CB_SIZE 544 7341687f09Smrg 7441687f09Smrg#define GX_CPU_REG_SIZE 0x4000 7541687f09Smrg#define GX_GP_REG_SIZE 0x4000 7641687f09Smrg#define GX_VID_REG_SIZE 0x4000 7741687f09Smrg 7841687f09Smrg#define DEFAULT_IMG_LINE_BUFS 20 7941687f09Smrg#define DEFAULT_CLR_LINE_BUFS 20 8041687f09Smrg 8141687f09Smrgextern OptionInfoRec GX_GeodeOptions[]; 8241687f09Smrg 8341687f09Smrgextern unsigned char *XpressROMPtr; 8441687f09Smrg 8541687f09Smrgstatic inline void 8641687f09Smrggx_enable_dac_power(void) 8741687f09Smrg{ 8841687f09Smrg gfx_write_vid32(RCDF_VID_MISC, 8941687f09Smrg gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH); 9041687f09Smrg} 9141687f09Smrg 9241687f09Smrgstatic inline void 9341687f09Smrggx_disable_dac_power(void) 9441687f09Smrg{ 9541687f09Smrg gfx_write_vid32(RCDF_VID_MISC, 9641687f09Smrg RCDF_DAC_POWER_DOWN | RCDF_ANALOG_POWER_DOWN | 9741687f09Smrg (gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH)); 9841687f09Smrg} 9941687f09Smrg 10041687f09Smrgstatic void 10141687f09SmrgGXInitEXAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail) 10241687f09Smrg{ 10341687f09Smrg GeodePtr pGeode = GEODEPTR(pScrni); 10441687f09Smrg 10541687f09Smrg if (pGeode->exaBfrSz > 0 && pGeode->exaBfrSz <= *avail) { 10641687f09Smrg pGeode->exaBfrOffset = *offset; 10741687f09Smrg *offset += pGeode->exaBfrOffset; 10841687f09Smrg *avail -= pGeode->exaBfrOffset; 10941687f09Smrg } 11041687f09Smrg} 11141687f09Smrg 11241687f09Smrgstatic void 11341687f09SmrgGXInitXAAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail) 11441687f09Smrg{ 11541687f09Smrg GeodePtr pGeode = GEODEPTR(pScrni); 11641687f09Smrg unsigned int size, i, pitch; 11741687f09Smrg 11841687f09Smrg /* XXX - FIXME - What if we are out of room? Then what? */ 11941687f09Smrg /* For now, we NULL them all out. */ 12041687f09Smrg 12141687f09Smrg if (pGeode->NoOfImgBuffers > 0) { 12241687f09Smrg size = pGeode->displayPitch * pGeode->NoOfImgBuffers; 12341687f09Smrg if (size <= *avail) { 12441687f09Smrg for (i = 0; i < pGeode->NoOfImgBuffers; i++) { 12541687f09Smrg pGeode->AccelImageWriteBuffers[i] = pGeode->FBBase + *offset; 12641687f09Smrg *offset += pGeode->displayPitch; 12741687f09Smrg *avail -= pGeode->displayPitch; 12841687f09Smrg } 12941687f09Smrg } 13041687f09Smrg else { 13141687f09Smrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 13241687f09Smrg "Not enough memory for image write buffers.\n"); 13341687f09Smrg 13441687f09Smrg for (i = 0; i < pGeode->NoOfImgBuffers; i++) 13541687f09Smrg pGeode->AccelImageWriteBuffers[i] = NULL; 13641687f09Smrg } 13741687f09Smrg } 13841687f09Smrg 13941687f09Smrg if (pGeode->NoOfColorExpandLines > 0) { 14041687f09Smrg pitch = ((pGeode->displayPitch + 31) >> 5) << 2; 14141687f09Smrg size = pitch * pGeode->NoOfColorExpandLines; 14241687f09Smrg 14341687f09Smrg if (size <= *avail) { 14441687f09Smrg for (i = 0; i < pGeode->NoOfColorExpandLines; i++) { 14541687f09Smrg pGeode->AccelColorExpandBuffers[i] = pGeode->FBBase + *offset; 14641687f09Smrg *offset += pitch; 14741687f09Smrg *avail -= pitch; 14841687f09Smrg } 14941687f09Smrg } 15041687f09Smrg else { 15141687f09Smrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 15241687f09Smrg "Not enough memory for color expansion buffers.\n"); 15341687f09Smrg 15441687f09Smrg for (i = 0; i < pGeode->NoOfImgBuffers; i++) 15541687f09Smrg pGeode->AccelColorExpandBuffers[i] = NULL; 15641687f09Smrg } 15741687f09Smrg } 15841687f09Smrg} 15941687f09Smrg 16041687f09Smrgstatic Bool 16141687f09SmrgGXAllocateMemory(ScreenPtr pScrn, ScrnInfoPtr pScrni, int rotate) 16241687f09Smrg{ 16341687f09Smrg GeodePtr pGeode = GEODEPTR(pScrni); 16441687f09Smrg 16541687f09Smrg unsigned int fboffset, fbavail; 16641687f09Smrg unsigned int size; 16741687f09Smrg unsigned int bytpp = (pScrni->bitsPerPixel + 7) / 8; 16841687f09Smrg BOOL ret = TRUE; 16941687f09Smrg 17041687f09Smrg if (pGeode->tryCompression) 17141687f09Smrg pGeode->displayPitch = 17241687f09Smrg GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel); 17341687f09Smrg else 17441687f09Smrg pGeode->displayPitch = 17541687f09Smrg ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3); 17641687f09Smrg 17741687f09Smrg pGeode->Pitch = pGeode->displayPitch; 17841687f09Smrg pGeode->displayWidth = pGeode->displayPitch / bytpp; 17941687f09Smrg pScrni->displayWidth = pGeode->displayWidth; 18041687f09Smrg 18141687f09Smrg fbavail = pGeode->FBAvail - 0x4000; 18241687f09Smrg 18341687f09Smrg pGeode->displayOffset = fboffset = 0; 18441687f09Smrg pGeode->displaySize = pScrni->virtualY * pGeode->displayPitch; 18541687f09Smrg 18641687f09Smrg fbavail -= pGeode->displaySize; 18741687f09Smrg fboffset += pGeode->displaySize; 18841687f09Smrg 18941687f09Smrg if (pGeode->tryCompression) { 19041687f09Smrg size = pScrni->virtualY * GX_CB_PITCH; 19141687f09Smrg 19241687f09Smrg if (size <= fbavail) { 19341687f09Smrg pGeode->CBData.compression_offset = fboffset; 19441687f09Smrg 19541687f09Smrg fboffset += size; 19641687f09Smrg fbavail -= size; 19741687f09Smrg 19841687f09Smrg pGeode->Compression = TRUE; 19941687f09Smrg } 20041687f09Smrg else { 20141687f09Smrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 20241687f09Smrg "Not enough memory for compression\n"); 20341687f09Smrg pGeode->Compression = FALSE; 20441687f09Smrg } 20541687f09Smrg } 20641687f09Smrg 20741687f09Smrg if (pGeode->tryHWCursor) { 20841687f09Smrg 20941687f09Smrg if (fbavail >= 1024) { 21041687f09Smrg pGeode->CursorStartOffset = fboffset; 21141687f09Smrg fboffset += 1024; 21241687f09Smrg fbavail -= 1024; 21341687f09Smrg pGeode->HWCursor = TRUE; 21441687f09Smrg } 21541687f09Smrg else { 21641687f09Smrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 21741687f09Smrg "Not enough memory for the hardware cursor\n"); 21841687f09Smrg pGeode->HWCursor = FALSE; 21941687f09Smrg } 22041687f09Smrg } 22141687f09Smrg 22241687f09Smrg if (!pGeode->NoAccel) { 22341687f09Smrg if (pGeode->useEXA) 22441687f09Smrg GXInitEXAMemory(pScrni, &fboffset, &fbavail); 22541687f09Smrg else 22641687f09Smrg GXInitXAAMemory(pScrni, &fboffset, &fbavail); 22741687f09Smrg } 22841687f09Smrg 22941687f09Smrg pGeode->shadowSize = 0; 23041687f09Smrg 23141687f09Smrg if (rotate != RR_Rotate_0) { 23241687f09Smrg if (rotate & (RR_Rotate_90 | RR_Rotate_270)) 23341687f09Smrg size = pGeode->displayPitch * pScrni->virtualX; 23441687f09Smrg else 23541687f09Smrg size = pGeode->displayPitch * pScrni->virtualY; 23641687f09Smrg 23741687f09Smrg if (size <= fbavail) { 23841687f09Smrg pGeode->shadowOffset = fboffset; 23941687f09Smrg pGeode->shadowSize = size; 24041687f09Smrg 24141687f09Smrg fboffset += size; 24241687f09Smrg fbavail -= size; 24341687f09Smrg } 24441687f09Smrg else { 24541687f09Smrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 24641687f09Smrg "Not enough memory for the shadow framebuffer\n"); 24741687f09Smrg ret = FALSE; 24841687f09Smrg } 24941687f09Smrg } 25041687f09Smrg 25141687f09Smrg /* XAA always exists - we can't remove it on demand like we can with EXA. 25241687f09Smrg * So we assume the worse, and only give XAA enough offspace room to 25341687f09Smrg * account for any eventuality that RandR might throw at us. */ 25441687f09Smrg 25541687f09Smrg if (!pGeode->NoAccel) { 25641687f09Smrg 25741687f09Smrg if (pGeode->useEXA && pGeode->pExa) { 25841687f09Smrg ExaDriverPtr pExa = pGeode->pExa; 25941687f09Smrg 26041687f09Smrg pExa->offScreenBase = fboffset; 26141687f09Smrg pExa->memorySize = fboffset + fbavail; 26241687f09Smrg } 26341687f09Smrg 26441687f09Smrg if (!pGeode->useEXA) { 26541687f09Smrg 26641687f09Smrg#if XF86XAA 26741687f09Smrg if (!xf86FBManagerRunning(pScrn)) { 26841687f09Smrg 26941687f09Smrg unsigned int offset = fboffset; 27041687f09Smrg unsigned int avail = fbavail; 27141687f09Smrg RegionRec OffscreenRegion; 27241687f09Smrg BoxRec AvailBox; 27341687f09Smrg 27441687f09Smrg /* Assume the shadow FB exists even if it doesn't */ 27541687f09Smrg 27641687f09Smrg if (pGeode->shadowSize == 0) { 27741687f09Smrg size = (pScrn->width * bytpp) * pScrni->virtualX; 27841687f09Smrg offset += size; 27941687f09Smrg avail -= size; 28041687f09Smrg } 28141687f09Smrg 28241687f09Smrg AvailBox.x1 = 0; 28341687f09Smrg AvailBox.y1 = 28441687f09Smrg (offset + pGeode->displayPitch - 1) / pGeode->displayPitch; 28541687f09Smrg 28641687f09Smrg AvailBox.x2 = pGeode->displayWidth; 28741687f09Smrg AvailBox.y2 = (offset + avail) / pGeode->displayPitch; 28841687f09Smrg 28941687f09Smrg if (AvailBox.y1 < AvailBox.y2) { 29041687f09Smrg REGION_INIT(pScrn, &OffscreenRegion, &AvailBox, 2); 29141687f09Smrg 29241687f09Smrg if (!xf86InitFBManagerRegion(pScrn, &OffscreenRegion)) 29341687f09Smrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 29441687f09Smrg "Memory manager initialization failed.\n"); 29541687f09Smrg 29641687f09Smrg REGION_UNINIT(pScrn, &OffscreenRegion); 29741687f09Smrg } 29841687f09Smrg else 29941687f09Smrg xf86DrvMsg(pScrni->scrnIndex, X_INFO, 30041687f09Smrg "Cache disabled - no offscreen memory available.\n"); 30141687f09Smrg } 30241687f09Smrg else 30341687f09Smrg xf86DrvMsg(pScrni->scrnIndex, X_INFO, 30441687f09Smrg "XAA offscreen memory has already been allocated.\n"); 30541687f09Smrg#endif 30641687f09Smrg } 30741687f09Smrg } 3080ed5401bSmrg return ret; 30941687f09Smrg} 31041687f09Smrg 31141687f09Smrgstatic Bool 31241687f09SmrgGXSaveScreen(ScreenPtr pScrn, int mode) 31341687f09Smrg{ 31441687f09Smrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 31541687f09Smrg GeodePtr pGeode = GEODEPTR(pScrni); 31641687f09Smrg 31741687f09Smrg if (pGeode->useVGA && !pScrni->vtSema) 31849ef06a4Smrg return vgaHWSaveScreen(pScrn, mode); 31941687f09Smrg 32041687f09Smrg return TRUE; 32141687f09Smrg} 32241687f09Smrg 32341687f09Smrg/* Common function - used by the LX too */ 32441687f09Smrg#ifdef XSERVER_LIBPCIACCESS 32541687f09Smrgstatic inline void * 32649ef06a4Smrgmap_pci_mem(ScrnInfoPtr pScrni, int vram, 32741687f09Smrg struct pci_device *dev, int bar, int size) 32849ef06a4Smrg{ 32941687f09Smrg void *ptr; 33041687f09Smrg int map_size = size ? size : dev->regions[bar].size; 33141687f09Smrg 33241687f09Smrg int err = pci_device_map_range(dev, 33341687f09Smrg dev->regions[bar].base_addr, 33441687f09Smrg map_size, 33541687f09Smrg PCI_DEV_MAP_FLAG_WRITABLE | 33641687f09Smrg (vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0), 33741687f09Smrg &ptr); 33841687f09Smrg 33949ef06a4Smrg if (err) 34041687f09Smrg return NULL; 34149ef06a4Smrg return ptr; 34241687f09Smrg} 34341687f09Smrg 34441687f09Smrgstatic inline int 34541687f09Smrgunmap_pci_mem(ScrnInfoPtr pScrni, struct pci_device *dev, void *ptr, int size) 3460ed5401bSmrg{ 34741687f09Smrg return pci_device_unmap_range(dev, ptr, size); 34841687f09Smrg} 34941687f09Smrg#endif 35041687f09Smrg 35141687f09Smrgextern unsigned long gfx_gx2_scratch_base; 35241687f09Smrg 35341687f09Smrgstatic Bool 35441687f09SmrgGXMapMem(ScrnInfoPtr pScrni) 35541687f09Smrg{ 35641687f09Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 35741687f09Smrg int index = pScrni->scrnIndex; 35841687f09Smrg 35941687f09Smrg pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index); 36041687f09Smrg 36141687f09Smrg#ifndef XSERVER_LIBPCIACCESS 36241687f09Smrg gfx_virt_regptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO, 36341687f09Smrg pci->memBase[2], 36441687f09Smrg pci->size[2]); 36541687f09Smrg 36641687f09Smrg gfx_virt_gpptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO, 36741687f09Smrg pci->memBase[1], 36841687f09Smrg pci->size[1]); 36941687f09Smrg 37041687f09Smrg gfx_virt_vidptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO, 37141687f09Smrg pci->memBase[3], 37241687f09Smrg pci->size[3]); 37341687f09Smrg 37441687f09Smrg gfx_virt_fbptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 37541687f09Smrg pci->memBase[0], 37641687f09Smrg pGeode->FBAvail); 37741687f09Smrg#else 37841687f09Smrg gfx_virt_regptr = map_pci_mem(pScrni, 0, pci, 2, 0); 37941687f09Smrg gfx_virt_gpptr = map_pci_mem(pScrni, 0, pci, 1, 0); 38041687f09Smrg gfx_virt_vidptr = map_pci_mem(pScrni, 0, pci, 3, 0); 38141687f09Smrg gfx_virt_fbptr = map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail); 38241687f09Smrg#endif 38341687f09Smrg 38441687f09Smrg gfx_gx2_scratch_base = pGeode->FBAvail - 0x4000; 38541687f09Smrg 38641687f09Smrg#ifndef XSERVER_LIBPCIACCESS 38741687f09Smrg XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000); 38841687f09Smrg#else 38941687f09Smrg { 39041687f09Smrg int fd = open("/dev/mem", O_RDWR); 39141687f09Smrg if (fd < 0) { 39241687f09Smrg xf86DrvMsg(index, X_ERROR, "Failed to open /dev/mem: %m\n"); 39341687f09Smrg return FALSE; 39441687f09Smrg } 39541687f09Smrg XpressROMPtr = mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xF0000); 39641687f09Smrg close(fd); 39741687f09Smrg } 39841687f09Smrg#endif 39941687f09Smrg pGeode->FBBase = gfx_virt_fbptr; 40041687f09Smrg 40141687f09Smrg if ((!gfx_virt_regptr) || (!gfx_virt_gpptr) || 40241687f09Smrg (!gfx_virt_vidptr) || (!gfx_virt_fbptr)) 40341687f09Smrg return FALSE; 40441687f09Smrg 40541687f09Smrg if (!pGeode->NoAccel && pGeode->useEXA) 40641687f09Smrg pGeode->pExa->memoryBase = pGeode->FBBase; 40741687f09Smrg 40841687f09Smrg xf86DrvMsg(index, X_INFO, "Found Geode %x %p\n", 40941687f09Smrg pGeode->FBAvail, pGeode->FBBase); 41041687f09Smrg 41141687f09Smrg return TRUE; 41241687f09Smrg} 41341687f09Smrg 41441687f09Smrg/* Check to see if VGA exists - we map the space and look for a 41541687f09Smrg signature - if it doesn't match exactly, then we assume no VGA. 41641687f09Smrg*/ 41741687f09Smrg 41841687f09Smrgstatic Bool 41941687f09SmrgGXCheckVGA(ScrnInfoPtr pScrni, EntityInfoPtr pEnt) 42041687f09Smrg{ 42141687f09Smrg#ifndef XSERVER_LIBPCIACCESS 42241687f09Smrg unsigned char *ptr; 42341687f09Smrg const char *vgasig = "IBM VGA Compatible"; 42441687f09Smrg int ret; 42541687f09Smrg 42641687f09Smrg ptr = 42741687f09Smrg xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E, 42841687f09Smrg strlen(vgasig)); 42941687f09Smrg 43041687f09Smrg if (ptr == NULL) 43141687f09Smrg return FALSE; 43241687f09Smrg 43341687f09Smrg ret = memcmp(ptr, vgasig, strlen(vgasig)); 43441687f09Smrg xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig)); 4354babd585Smrg 4364babd585Smrg return ret ? FALSE : TRUE; 43741687f09Smrg#else 43841687f09Smrg pciVideoPtr pci = xf86GetPciInfoForEntity(pEnt->index); 43941687f09Smrg 44041687f09Smrg return pci_device_is_boot_vga(pci); 44141687f09Smrg#endif 44241687f09Smrg} 44341687f09Smrg 44441687f09Smrgstatic Bool 44541687f09SmrgGXPreInit(ScrnInfoPtr pScrni, int flags) 44641687f09Smrg{ 44741687f09Smrg GeodePtr pGeode; 44841687f09Smrg ClockRangePtr GeodeClockRange; 44941687f09Smrg OptionInfoRec *GeodeOptions = &GX_GeodeOptions[0]; 45041687f09Smrg int ret; 45141687f09Smrg QQ_WORD msrValue; 45241687f09Smrg EntityInfoPtr pEnt; 45341687f09Smrg rgb defaultWeight = { 0, 0, 0 }; 45441687f09Smrg int modecnt; 45541687f09Smrg const char *s, *panelgeo; 45641687f09Smrg Bool useVGA; 45741687f09Smrg 45841687f09Smrg if (pScrni->numEntities != 1) 45941687f09Smrg return FALSE; 46041687f09Smrg 46141687f09Smrg pEnt = xf86GetEntityInfo(pScrni->entityList[0]); 46241687f09Smrg#ifndef XSERVER_LIBPCIACCESS 46341687f09Smrg if (pEnt->resources) 46441687f09Smrg return FALSE; 46541687f09Smrg#endif 46641687f09Smrg 46741687f09Smrg pGeode = pScrni->driverPrivate = xnfcalloc(1, sizeof(GeodeRec)); 46841687f09Smrg 46941687f09Smrg if (pGeode == NULL) 47041687f09Smrg return FALSE; 47141687f09Smrg 47241687f09Smrg useVGA = GXCheckVGA(pScrni, pEnt); 47341687f09Smrg 47441687f09Smrg if (flags & PROBE_DETECT) { 47541687f09Smrg GeodeProbeDDC(pScrni, pEnt->index); 47641687f09Smrg return TRUE; 47741687f09Smrg } 47841687f09Smrg 47941687f09Smrg /* Probe for VGA */ 48041687f09Smrg pGeode->useVGA = useVGA; 48141687f09Smrg pGeode->pEnt = pEnt; 48241687f09Smrg 48341687f09Smrg if (pGeode->useVGA) { 48441687f09Smrg if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni)) 48541687f09Smrg pGeode->useVGA = FALSE; 48641687f09Smrg else 487 vgaHWSetStdFuncs(VGAHWPTR(pScrni)); 488 489#if INT10_SUPPORT 490 pGeode->vesa = calloc(1, sizeof(VESARec)); 491#endif 492 } 493 494 gfx_msr_init(); 495 496 ret = gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msrValue); 497 498 if (!ret) { 499 pGeode->Output = 500 ((msrValue.low & RCDF_CONFIG_FMT_MASK) == 501 RCDF_CONFIG_FMT_FP) ? OUTPUT_PANEL : OUTPUT_CRT; 502 } 503 504 /* Fill in the monitor information */ 505 pScrni->monitor = pScrni->confScreen->monitor; 506 507 if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb)) 508 return FALSE; 509 510 switch (pScrni->depth) { 511 case 8: 512 pScrni->rgbBits = 8; 513 case 16: 514 case 24: 515 case 32: 516 break; 517 default: 518 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 519 "The driver does not support %d as a depth.\n", 520 pScrni->depth); 521 return FALSE; 522 } 523 524 xf86PrintDepthBpp(pScrni); 525 526 if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight)) 527 return FALSE; 528 529 if (!xf86SetDefaultVisual(pScrni, -1)) 530 return FALSE; 531 532 /* 533 * If the driver can do gamma correction, it should call xf86SetGamma() 534 * here. 535 */ 536 { 537 Gamma zeros = { 0.0, 0.0, 0.0 }; 538 539 if (!xf86SetGamma(pScrni, zeros)) { 540 return FALSE; 541 } 542 } 543 544 pScrni->progClock = TRUE; 545 xf86CollectOptions(pScrni, NULL); 546 xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions); 547 548 /* Set up our various options that may get reversed as we go on */ 549 550 pGeode->FBVGAActive = FALSE; 551 pGeode->tryHWCursor = TRUE; 552 pGeode->tryCompression = TRUE; 553 554 pGeode->NoAccel = FALSE; 555 pGeode->useEXA = FALSE; 556 557 pGeode->Panel = (pGeode->Output & OUTPUT_PANEL) ? TRUE : FALSE; 558 559 pGeode->NoOfImgBuffers = DEFAULT_IMG_LINE_BUFS; 560 pGeode->NoOfColorExpandLines = DEFAULT_CLR_LINE_BUFS; 561 pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ; 562 563 xf86GetOptValBool(GeodeOptions, GX_OPTION_HW_CURSOR, &pGeode->tryHWCursor); 564 565 if (!xf86GetOptValInteger(GeodeOptions, GX_OPTION_FBSIZE, 566 (int *) &(pGeode->FBAvail))) 567 pGeode->FBAvail = 0; 568 569 /* For compatibility - allow SWCursor too */ 570 571 if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_SW_CURSOR, FALSE)) 572 pGeode->tryHWCursor = FALSE; 573 574 if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOCOMPRESSION, FALSE)) 575 pGeode->tryCompression = FALSE; 576 577 if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOACCEL, FALSE)) 578 pGeode->NoAccel = TRUE; 579 580 pGeode->rotation = RR_Rotate_0; 581 582 if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ROTATE))) { 583 584 if (!xf86NameCmp(s, "LEFT")) 585 pGeode->rotation = RR_Rotate_90; 586 else if (!xf86NameCmp(s, "INVERT")) 587 pGeode->rotation = RR_Rotate_180; 588 else if (!xf86NameCmp(s, "CCW")) 589 pGeode->rotation = RR_Rotate_270; 590 else 591 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "Invalid rotation %s.\n", s); 592 } 593 594 xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_IMG_BUFS, 595 &(pGeode->NoOfImgBuffers)); 596 597 if (pGeode->NoOfImgBuffers <= 0) 598 pGeode->NoOfImgBuffers = 0; 599 600 xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS, 601 &(pGeode->NoOfColorExpandLines)); 602 603 if (pGeode->NoOfColorExpandLines <= 0) 604 pGeode->NoOfColorExpandLines = 0; 605 606 xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS, 607 (int *) &(pGeode->exaBfrSz)); 608 609 if (pGeode->exaBfrSz <= 0) 610 pGeode->exaBfrSz = 0; 611 612 if (pGeode->Panel == TRUE) { 613 if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOPANEL, FALSE)) 614 pGeode->Panel = FALSE; 615 } 616 617 panelgeo = xf86GetOptValString(GeodeOptions, GX_OPTION_PANEL_GEOMETRY); 618 619 if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ACCEL_METHOD))) { 620#if defined(XF86XAA) && defined(XF86EXA) 621 if (!xf86NameCmp(s, "XAA")) 622 pGeode->useEXA = FALSE; 623 else if (xf86NameCmp(s, "EXA")) 624 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 625 "Unknown acceleration method %s. Defaulting to XAA.\n", 626 s); 627#elif defined(XF86EXA) 628 pGeode->useEXA = TRUE; 629#else 630 pGeode->useEXA = FALSE; 631#endif 632 } 633 634 xf86DrvMsg(pScrni->scrnIndex, X_INFO, 635 "Using %s acceleration architecture\n", 636 pGeode->useEXA ? "EXA" : "XAA"); 637 638 /* Set up the panel */ 639 640 if (pGeode->Panel) { 641 if (panelgeo != NULL) { 642 if (GeodeGetFPGeometry(panelgeo, &pGeode->PanelX, &pGeode->PanelY)) 643 pGeode->Panel = FALSE; 644 } 645#ifdef PNL_SUP 646 else { 647 int b, f; 648 649 /* The bitdepth and refresh isn't used anywhere else in the driver */ 650 651 if ((pGeode->Panel = Pnl_IsPanelEnabledInBIOS())) 652 Pnl_GetPanelInfoFromBIOS(&pGeode->PanelX, &pGeode->PanelY, &b, 653 &f); 654 } 655#endif 656 } 657 658 /* Set up the VGA */ 659 660 if (pGeode->useVGA) { 661#if INT10_SUPPORT 662 VESARec *pVesa; 663 664 if (!xf86LoadSubModule(pScrni, "int10")) 665 return FALSE; 666 667 pVesa = pGeode->vesa; 668 669 if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) { 670 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 671 "Unable to initialize 1NT10 support\n"); 672 pGeode->useVGA = FALSE; 673 } 674#endif 675 } 676 677 /* First try to get the framebuffer size from the framebuffer, 678 * and if that fails, revert all the way back to the legacy 679 * method 680 */ 681 682 if (pGeode->FBAvail == 0) { 683 if (GeodeGetSizeFromFB(&pGeode->FBAvail)) 684 pGeode->FBAvail = gfx_get_frame_buffer_size(); 685 } 686 687 if (pScrni->memPhysBase == 0) 688 pScrni->memPhysBase = gfx_get_frame_buffer_base(); 689 690 pScrni->fbOffset = 0; 691 692 if (pGeode->pEnt->device->videoRam == 0) 693 pScrni->videoRam = pGeode->FBAvail / 1024; 694 else 695 pScrni->videoRam = pGeode->pEnt->device->videoRam; 696 697 GeodeClockRange = (ClockRangePtr) xnfcalloc(1, sizeof(ClockRange)); 698 GeodeClockRange->next = NULL; 699 GeodeClockRange->minClock = 25175; 700 GeodeClockRange->maxClock = 229500; 701 GeodeClockRange->clockIndex = -1; 702 GeodeClockRange->interlaceAllowed = TRUE; 703 GeodeClockRange->doubleScanAllowed = FALSE; 704 705 pScrni->monitor->DDC = GeodeDoDDC(pScrni, pGeode->pEnt->index); 706 707 /* I'm still not 100% sure this uses the right values */ 708 709 modecnt = xf86ValidateModes(pScrni, 710 pScrni->monitor->Modes, 711 pScrni->display->modes, 712 GeodeClockRange, 713 NULL, GX_MIN_PITCH, GX_MAX_PITCH, 714 32, GX_MIN_HEIGHT, GX_MAX_HEIGHT, 715 pScrni->display->virtualX, 716 pScrni->display->virtualY, pGeode->FBAvail, 717 LOOKUP_BEST_REFRESH); 718 719 if (modecnt <= 0) { 720 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n"); 721 return FALSE; 722 } 723 724 xf86PruneDriverModes(pScrni); 725 726 if (pScrni->modes == NULL) { 727 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n"); 728 return FALSE; 729 } 730 731 xf86SetCrtcForModes(pScrni, 0); 732 pScrni->currentMode = pScrni->modes; 733 734 xf86PrintModes(pScrni); 735 xf86SetDpi(pScrni, 0, 0); 736 737 /* Load the modules we'll need */ 738 739 if (xf86LoadSubModule(pScrni, "fb") == NULL) { 740 return FALSE; 741 } 742 743 if (pGeode->NoAccel == FALSE) { 744 const char *module = (pGeode->useEXA) ? "exa" : "xaa"; 745 746 if (!xf86LoadSubModule(pScrni, module)) { 747 return FALSE; 748 } 749 } 750 751 if (pGeode->tryHWCursor == TRUE) { 752 if (!xf86LoadSubModule(pScrni, "ramdac")) { 753 return FALSE; 754 } 755 } 756 757#ifndef XSERVER_LIBPCIACCESS 758 if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) { 759 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 760 "Couldn't register the resources.\n"); 761 return FALSE; 762 } 763#endif 764 return TRUE; 765} 766 767static void 768GXRestore(ScrnInfoPtr pScrni) 769{ 770 GeodeRec *pGeode = GEODEPTR(pScrni); 771 772 if (pGeode->useVGA && pGeode->FBVGAActive) { 773 vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 774 775 vgaHWProtect(pScrni, TRUE); 776 vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL); 777 vgaHWProtect(pScrni, FALSE); 778 } 779} 780 781static Bool 782GXUnmapMem(ScrnInfoPtr pScrni) 783{ 784 GeodeRec *pGeode = GEODEPTR(pScrni); 785 786 /* unmap all the memory map's */ 787#ifndef XSERVER_LIBPCIACCESS 788 xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_regptr, GX_CPU_REG_SIZE); 789 xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_gpptr, GX_GP_REG_SIZE); 790 xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_vidptr, GX_VID_REG_SIZE); 791 xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_fbptr, pGeode->FBAvail); 792#else 793 pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index); 794 795 unmap_pci_mem(pScrni, pci, gfx_virt_regptr, GX_CPU_REG_SIZE); 796 unmap_pci_mem(pScrni, pci, gfx_virt_gpptr, GX_GP_REG_SIZE); 797 unmap_pci_mem(pScrni, pci, gfx_virt_vidptr, GX_VID_REG_SIZE); 798 unmap_pci_mem(pScrni, pci, gfx_virt_fbptr, pGeode->FBAvail); 799 800 munmap(XpressROMPtr, 0x10000); 801#endif 802 return TRUE; 803} 804 805static void 806GXSetDvLineSize(unsigned int pitch) 807{ 808 unsigned long temp, dv_size = MDC_DV_LINE_SIZE_1024; 809 810 if (pitch > 1024) { 811 dv_size = MDC_DV_LINE_SIZE_2048; 812 } 813 if (pitch > 2048) { 814 dv_size = MDC_DV_LINE_SIZE_4096; 815 } 816 if (pitch > 4096) { 817 dv_size = MDC_DV_LINE_SIZE_8192; 818 } 819 820 /* WRITE DIRTY/VALID CONTROL WITH LINE LENGTH */ 821 822 temp = READ_REG32(MDC_DV_CTL); 823 WRITE_REG32(MDC_DV_CTL, (temp & ~MDC_DV_LINE_SIZE_MASK) | dv_size); 824} 825 826/* XXX - this is nothing like the original function - not sure exactly what the purpose is for this quite yet */ 827 828static void 829GXAdjustFrame(ADJUST_FRAME_ARGS_DECL) 830{ 831 SCRN_INFO_PTR(arg); 832 GeodeRec *pGeode = GEODEPTR(pScrni); 833 unsigned long offset; 834 835 offset = y * pGeode->Pitch + x * (pScrni->bitsPerPixel >> 3); 836 837 gfx_set_display_offset(offset); 838} 839 840static Bool 841GXSetVideoMode(ScrnInfoPtr pScrni, DisplayModePtr pMode) 842{ 843 GeodeRec *pGeode = GEODEPTR(pScrni); 844 int flags = 0; 845 int custom = 0; 846 847 pScrni->vtSema = TRUE; 848 849 gx_disable_dac_power(); 850 851 if (pMode->Flags & V_NHSYNC) 852 flags |= 1; 853 if (pMode->Flags & V_NVSYNC) 854 flags |= 2; 855 856 /* Check to see if we should use custom or built-in timings */ 857 858 if (pGeode->Panel) 859 custom = (pMode->type & M_T_USERDEF); 860 else 861 custom = !(pMode->type & (M_T_BUILTIN | M_T_DEFAULT)); 862 863 /* If we're not doing a custom mode, then just set the fixed timings, 864 * otherwise, do the whole shooting match */ 865 866 if (!custom) { 867 GFX(set_fixed_timings(pGeode->PanelX, pGeode->PanelY, 868 pMode->CrtcHDisplay, pMode->CrtcVDisplay, 869 pScrni->bitsPerPixel)); 870 } 871 else { 872 if (pGeode->Panel) 873 GFX(set_panel_present(pGeode->PanelX, pGeode->PanelY, 874 pMode->CrtcHDisplay, pMode->CrtcVDisplay, 875 pScrni->bitsPerPixel)); 876 877 GFX(set_display_timings(pScrni->bitsPerPixel, flags, 878 pMode->CrtcHDisplay, pMode->CrtcHBlankStart, 879 pMode->CrtcHSyncStart, pMode->CrtcHSyncEnd, 880 pMode->CrtcHBlankEnd, pMode->CrtcHTotal, 881 pMode->CrtcVDisplay, pMode->CrtcVBlankStart, 882 pMode->CrtcVSyncStart, pMode->CrtcVSyncEnd, 883 pMode->CrtcVBlankEnd, pMode->CrtcVTotal, 884 (int) ((pMode->SynthClock / 1000.0) * 885 0x10000))); 886 } 887 888 GFX(set_crt_enable(CRT_ENABLE)); 889 GFX(set_display_pitch(pGeode->displayPitch)); 890 GFX(set_display_offset(0L)); 891 GFX(wait_vertical_blank()); 892 893 if (pGeode->Compression) { 894 GXSetDvLineSize(pGeode->Pitch); 895 896 gfx_set_compression_offset(pGeode->CBData.compression_offset); 897 gfx_set_compression_pitch(GX_CB_PITCH); 898 gfx_set_compression_size(GX_CB_SIZE); 899 900 gfx_set_compression_enable(1); 901 } 902 903 if (pGeode->HWCursor && !(pMode->Flags & V_DBLSCAN)) { 904 GXLoadCursorImage(pScrni, NULL); 905 GFX(set_cursor_position(pGeode->CursorStartOffset, 0, 0, 0, 0)); 906 GXShowCursor(pScrni); 907 } 908 else { 909 GFX(set_cursor_enable(0)); 910 pGeode->HWCursor = FALSE; 911 } 912 913 GXAdjustFrame(ADJUST_FRAME_ARGS(pScrni->frameX0, pScrni->frameY0)); 914 gx_enable_dac_power(); 915 916 return TRUE; 917} 918 919static Bool 920GXSwitchMode(SWITCH_MODE_ARGS_DECL) 921{ 922 SCRN_INFO_PTR(arg); 923 GeodeRec *pGeode = GEODEPTR(pScrni); 924 int ret = TRUE; 925 int rotate; 926 927 /* Syn the engine and shutdown the DAC momentarily */ 928 929 gfx_wait_until_idle(); 930 931 /* Set up the memory for the new mode */ 932 rotate = GXGetRotation(pScrni->pScreen); 933 ret = GXAllocateMemory(pScrni->pScreen, pScrni, rotate); 934 935 if (ret) { 936 if (pGeode->curMode != pMode) 937 ret = GXSetVideoMode(pScrni, pMode); 938 } 939 940 if (ret) 941 ret = GXRotate(pScrni, pMode); 942 943 /* Go back the way it was */ 944 945 if (ret == FALSE) { 946 if (!GXSetVideoMode(pScrni, pGeode->curMode)) 947 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 948 "Could not restore the previous mode\n"); 949 } 950 else 951 pGeode->curMode = pMode; 952 953 return ret; 954} 955 956static void 957GXLeaveGraphics(ScrnInfoPtr pScrni) 958{ 959 GeodeRec *pGeode = GEODEPTR(pScrni); 960 961 gfx_wait_until_idle(); 962 963 /* Restore VG registers */ 964 gfx_set_display_timings(pGeode->FBgfxdisplaytiming.wBpp, 965 pGeode->FBgfxdisplaytiming.wPolarity, 966 pGeode->FBgfxdisplaytiming.wHActive, 967 pGeode->FBgfxdisplaytiming.wHBlankStart, 968 pGeode->FBgfxdisplaytiming.wHSyncStart, 969 pGeode->FBgfxdisplaytiming.wHSyncEnd, 970 pGeode->FBgfxdisplaytiming.wHBlankEnd, 971 pGeode->FBgfxdisplaytiming.wHTotal, 972 pGeode->FBgfxdisplaytiming.wVActive, 973 pGeode->FBgfxdisplaytiming.wVBlankStart, 974 pGeode->FBgfxdisplaytiming.wVSyncStart, 975 pGeode->FBgfxdisplaytiming.wVSyncEnd, 976 pGeode->FBgfxdisplaytiming.wVBlankEnd, 977 pGeode->FBgfxdisplaytiming.wVTotal, 978 pGeode->FBgfxdisplaytiming.dwDotClock); 979 980 gfx_set_compression_enable(0); 981 982 /* Restore the previous Compression state */ 983 if (pGeode->FBCompressionEnable) { 984 gfx_set_compression_offset(pGeode->FBCompressionOffset); 985 gfx_set_compression_pitch(pGeode->FBCompressionPitch); 986 gfx_set_compression_size(pGeode->FBCompressionSize); 987 gfx_set_compression_enable(1); 988 } 989 990 gfx_set_display_pitch(pGeode->FBgfxdisplaytiming.wPitch); 991 992 gfx_set_display_offset(pGeode->FBDisplayOffset); 993 994 /* Restore Cursor */ 995 gfx_set_cursor_position(pGeode->FBCursorOffset, 0, 0, 0, 0); 996 997 if (pGeode->useVGA) { 998 pGeode->vesa->pInt->num = 0x10; 999 pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode; 1000 pGeode->vesa->pInt->bx = 0; 1001 xf86ExecX86int10(pGeode->vesa->pInt); 1002 gfx_delay_milliseconds(3); 1003 } 1004 1005 GXRestore(pScrni); 1006 1007 gx_enable_dac_power(); 1008} 1009 1010static Bool 1011GXCloseScreen(CLOSE_SCREEN_ARGS_DECL) 1012{ 1013 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 1014 GeodeRec *pGeode = GEODEPTR(pScrni); 1015 1016 if (pScrni->vtSema) 1017 GXLeaveGraphics(pScrni); 1018 1019#ifdef XF86XAA 1020 if (pGeode->AccelInfoRec) 1021 XAADestroyInfoRec(pGeode->AccelInfoRec); 1022#endif 1023 1024 if (pGeode->AccelImageWriteBuffers) { 1025 free(pGeode->AccelImageWriteBuffers[0]); 1026 free(pGeode->AccelImageWriteBuffers); 1027 pGeode->AccelImageWriteBuffers = NULL; 1028 } 1029 1030 if (pGeode->AccelColorExpandBuffers) { 1031 free(pGeode->AccelColorExpandBuffers); 1032 pGeode->AccelColorExpandBuffers = NULL; 1033 } 1034 1035 if (pGeode->pExa) { 1036 exaDriverFini(pScrn); 1037 free(pGeode->pExa); 1038 pGeode->pExa = NULL; 1039 } 1040 1041 pScrni->vtSema = FALSE; 1042 1043 GXUnmapMem(pScrni); 1044 1045 pScrni->PointerMoved = pGeode->PointerMoved; 1046 pScrn->CloseScreen = pGeode->CloseScreen; 1047 1048 if (pScrn->CloseScreen) 1049 return (*pScrn->CloseScreen) (CLOSE_SCREEN_ARGS); 1050 1051 return TRUE; 1052} 1053 1054static Bool 1055GXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni) 1056{ 1057 GeodeRec *pGeode = GEODEPTR(pScrni); 1058 1059 if (!GXMapMem(pScrni)) 1060 return FALSE; 1061 1062 if (pGeode->useVGA) 1063 pGeode->FBVGAActive = gu2_get_vga_active(); 1064 1065 gfx_wait_until_idle(); 1066 1067 /* Save off the current state (should this be somewhere else)? */ 1068 1069 pGeode->FBgfxdisplaytiming.dwDotClock = gfx_get_clock_frequency(); 1070 pGeode->FBgfxdisplaytiming.wPitch = gfx_get_display_pitch(); 1071 pGeode->FBgfxdisplaytiming.wBpp = gfx_get_display_bpp(); 1072 pGeode->FBgfxdisplaytiming.wHTotal = gfx_get_htotal(); 1073 pGeode->FBgfxdisplaytiming.wHActive = gfx_get_hactive(); 1074 pGeode->FBgfxdisplaytiming.wHSyncStart = gfx_get_hsync_start(); 1075 pGeode->FBgfxdisplaytiming.wHSyncEnd = gfx_get_hsync_end(); 1076 pGeode->FBgfxdisplaytiming.wHBlankStart = gfx_get_hblank_start(); 1077 pGeode->FBgfxdisplaytiming.wHBlankEnd = gfx_get_hblank_end(); 1078 pGeode->FBgfxdisplaytiming.wVTotal = gfx_get_vtotal(); 1079 pGeode->FBgfxdisplaytiming.wVActive = gfx_get_vactive(); 1080 pGeode->FBgfxdisplaytiming.wVSyncStart = gfx_get_vsync_start(); 1081 pGeode->FBgfxdisplaytiming.wVSyncEnd = gfx_get_vsync_end(); 1082 pGeode->FBgfxdisplaytiming.wVBlankStart = gfx_get_vblank_start(); 1083 pGeode->FBgfxdisplaytiming.wVBlankEnd = gfx_get_vblank_end(); 1084 pGeode->FBgfxdisplaytiming.wPolarity = gfx_get_sync_polarities(); 1085 1086 pGeode->FBDisplayOffset = gfx_get_display_offset(); 1087 1088 if (pGeode->useVGA) { 1089 vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 1090 1091 pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040); 1092 } 1093 1094 pGeode->FBCompressionEnable = gfx_get_compression_enable(); 1095 pGeode->FBCompressionOffset = gfx_get_compression_offset(); 1096 pGeode->FBCompressionPitch = gfx_get_compression_pitch(); 1097 pGeode->FBCompressionSize = gfx_get_compression_size(); 1098 1099#ifdef PNL_SUP 1100 Pnl_SavePanelState(); 1101#endif 1102 1103 /* Turn off the VGA */ 1104 1105 if (pGeode->useVGA && pGeode->FBVGAActive) { 1106 unsigned short sequencer; 1107 vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 1108 1109 /* Map VGA aperture */ 1110 if (!vgaHWMapMem(pScrni)) 1111 return FALSE; 1112 1113 /* Unlock VGA registers */ 1114 vgaHWUnlock(pvgaHW); 1115 1116 /* Save the current state and setup the current mode */ 1117 vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL); 1118 1119 /* DISABLE VGA SEQUENCER */ 1120 /* This allows the VGA state machine to terminate. We must delay */ 1121 /* such that there are no pending MBUS requests. */ 1122 1123 gfx_outb(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_CLK_MODE); 1124 sequencer = gfx_inb(MDC_SEQUENCER_DATA); 1125 sequencer |= MDC_CLK_MODE_SCREEN_OFF; 1126 gfx_outb(MDC_SEQUENCER_DATA, sequencer); 1127 1128 gfx_delay_milliseconds(1); 1129 1130 /* BLANK THE VGA DISPLAY */ 1131 gfx_outw(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_RESET); 1132 sequencer = gfx_inb(MDC_SEQUENCER_DATA); 1133 sequencer &= ~MDC_RESET_VGA_DISP_ENABLE; 1134 gfx_outb(MDC_SEQUENCER_DATA, sequencer); 1135 1136 gfx_delay_milliseconds(1); 1137 } 1138 1139 /* Set up the memory */ 1140 /* XXX - FIXME - when we allow initial rotation, it should be here */ 1141 GXAllocateMemory(pScrn, pScrni, pGeode->rotation); 1142 1143 /* Clear the framebuffer */ 1144 memset(pGeode->FBBase + pGeode->displayOffset, 0, pGeode->displaySize); 1145 1146 /* Set up the video mode */ 1147 GXSetVideoMode(pScrni, pScrni->currentMode); 1148 pGeode->curMode = pScrni->currentMode; 1149 1150 return TRUE; 1151} 1152 1153static void 1154GXLoadPalette(ScrnInfoPtr pScrni, 1155 int numColors, int *indizes, LOCO * colors, VisualPtr pVisual) 1156{ 1157 int i, index, color; 1158 1159 for (i = 0; i < numColors; i++) { 1160 index = indizes[i] & 0xFF; 1161 color = (((unsigned long) (colors[index].red & 0xFF)) << 16) | 1162 (((unsigned long) (colors[index].green & 0xFF)) << 8) | 1163 ((unsigned long) (colors[index].blue & 0xFF)); 1164 1165 GFX(set_display_palette_entry(index, color)); 1166 } 1167} 1168 1169#ifdef DPMSExtension 1170static void 1171GXPanelPower(int enable) 1172{ 1173 unsigned long power = READ_VID32(RCDF_POWER_MANAGEMENT); 1174 1175 if (enable != 0) 1176 power |= RCDF_PM_PANEL_POWER_ON; 1177 else 1178 power &= ~RCDF_PM_PANEL_POWER_ON; 1179 1180 WRITE_VID32(RCDF_POWER_MANAGEMENT, power); 1181} 1182 1183static void 1184GXDPMSSet(ScrnInfoPtr pScrni, int mode, int flags) 1185{ 1186 GeodeRec *pGeode; 1187 1188 pGeode = GEODEPTR(pScrni); 1189 1190 if (!pScrni->vtSema) 1191 return; 1192 1193 switch (mode) { 1194 case DPMSModeOn: 1195 /* Screen: On; HSync: On; VSync: On */ 1196 GFX(set_crt_enable(CRT_ENABLE)); 1197#if defined(PNL_SUP) 1198 if (pGeode->Panel) { 1199 Pnl_PowerUp(); 1200 GXPanelPower(1); 1201 } 1202#endif 1203 break; 1204 1205 case DPMSModeStandby: 1206 /* Screen: Off; HSync: Off; VSync: On */ 1207 GFX(set_crt_enable(CRT_STANDBY)); 1208#if defined(PNL_SUP) 1209 if (pGeode->Panel) { 1210 Pnl_PowerDown(); 1211 GXPanelPower(0); 1212 } 1213#endif 1214 break; 1215 1216 case DPMSModeSuspend: 1217 /* Screen: Off; HSync: On; VSync: Off */ 1218 GFX(set_crt_enable(CRT_SUSPEND)); 1219#if defined(PNL_SUP) 1220 if (pGeode->Panel) { 1221 Pnl_PowerDown(); 1222 GXPanelPower(0); 1223 } 1224#endif 1225 break; 1226 1227 case DPMSModeOff: 1228 /* Screen: Off; HSync: Off; VSync: Off */ 1229 GFX(set_crt_enable(CRT_DISABLE)); 1230#if defined(PNL_SUP) 1231 if (pGeode->Panel) { 1232 Pnl_PowerDown(); 1233 GXPanelPower(0); 1234 } 1235#endif 1236 break; 1237 } 1238} 1239#endif 1240 1241static Bool 1242GXCreateScreenResources(ScreenPtr pScreen) 1243{ 1244 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen); 1245 GeodeRec *pGeode = GEODEPTR(pScrni); 1246 1247 pScreen->CreateScreenResources = pGeode->CreateScreenResources; 1248 if (!(*pScreen->CreateScreenResources) (pScreen)) 1249 return FALSE; 1250 1251 if (xf86LoaderCheckSymbol("GXRandRSetConfig") 1252 && pGeode->rotation != RR_Rotate_0) { 1253 Rotation(*GXRandRSetConfig) (ScreenPtr pScreen, Rotation rr, int rate, 1254 RRScreenSizePtr pSize) = NULL; 1255 1256 RRScreenSize p; 1257 Rotation requestedRotation = pGeode->rotation; 1258 1259 pGeode->rotation = RR_Rotate_0; 1260 1261 /* Just setup enough for an initial rotate */ 1262 1263 p.width = pScreen->width; 1264 p.height = pScreen->height; 1265 p.mmWidth = pScreen->mmWidth; 1266 p.mmHeight = pScreen->mmHeight; 1267 1268 GXRandRSetConfig = LoaderSymbol("GXRandRSetConfig"); 1269 if (GXRandRSetConfig) { 1270 pGeode->starting = TRUE; 1271 (*GXRandRSetConfig) (pScreen, requestedRotation, 0, &p); 1272 pGeode->starting = FALSE; 1273 } 1274 } 1275 1276 return TRUE; 1277} 1278 1279static Bool 1280GXScreenInit(SCREEN_INIT_ARGS_DECL) 1281{ 1282 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 1283 GeodeRec *pGeode = GEODEPTR(pScrni); 1284 XF86ModReqInfo shadowReq; 1285 int maj, min, ret, rotate; 1286 1287 pGeode->starting = TRUE; 1288 1289 /* If we are using VGA then go ahead and map the memory */ 1290 1291 if (pGeode->useVGA) { 1292 1293 if (!vgaHWMapMem(pScrni)) 1294 return FALSE; 1295 1296 vgaHWGetIOBase(VGAHWPTR(pScrni)); 1297 } 1298 1299 if (!pGeode->NoAccel) { 1300 1301 if (pGeode->useEXA) { 1302 1303 if (!(pGeode->pExa = exaDriverAlloc())) { 1304 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 1305 "Couldn't allocate the EXA structure.\n"); 1306 pGeode->NoAccel = TRUE; 1307 } 1308 else { 1309 ExaDriverPtr pExa = pGeode->pExa; 1310 1311 /* THis is set in GXAllocMem */ 1312 pExa->memoryBase = 0; 1313 1314 /* This is set in GXAllocateMemory */ 1315 pExa->memorySize = 0; 1316 1317 pExa->pixmapOffsetAlign = 32; 1318 pExa->pixmapPitchAlign = 32; 1319 pExa->flags = EXA_OFFSCREEN_PIXMAPS; 1320 pExa->maxX = GX_MAX_WIDTH - 1; 1321 pExa->maxY = GX_MAX_HEIGHT - 1; 1322 } 1323 } 1324 else { 1325 pGeode->AccelImageWriteBuffers = 1326 calloc(pGeode->NoOfImgBuffers, 1327 sizeof(pGeode->AccelImageWriteBuffers[0])); 1328 pGeode->AccelColorExpandBuffers = 1329 calloc(pGeode->NoOfColorExpandLines, 1330 sizeof(pGeode->AccelColorExpandBuffers[0])); 1331 } 1332 } 1333 1334 /* XXX FIXME - Take down any of the structures on failure? */ 1335 1336 if (!GXEnterGraphics(pScrn, pScrni)) 1337 return FALSE; 1338 1339 miClearVisualTypes(); 1340 1341 /* XXX Again - take down anything? */ 1342 1343 if (pScrni->bitsPerPixel > 8) { 1344 if (!miSetVisualTypes(pScrni->depth, 1345 TrueColorMask, pScrni->rgbBits, 1346 pScrni->defaultVisual)) { 1347 return FALSE; 1348 } 1349 } 1350 else { 1351 if (!miSetVisualTypes(pScrni->depth, 1352 miGetDefaultVisualMask(pScrni->depth), 1353 pScrni->rgbBits, pScrni->defaultVisual)) { 1354 return FALSE; 1355 } 1356 } 1357 1358 miSetPixmapDepths(); 1359 1360 /* Point at the visible area to start */ 1361 1362 ret = fbScreenInit(pScrn, pGeode->FBBase + pGeode->displayOffset, 1363 pScrni->virtualX, pScrni->virtualY, 1364 pScrni->xDpi, pScrni->yDpi, pGeode->displayWidth, 1365 pScrni->bitsPerPixel); 1366 1367 if (!ret) 1368 return FALSE; 1369 1370 xf86SetBlackWhitePixels(pScrn); 1371 1372 /* Set up the color ordering */ 1373 1374 if (pScrni->bitsPerPixel > 8) { 1375 VisualPtr visual = pScrn->visuals + pScrn->numVisuals; 1376 1377 while (--visual >= pScrn->visuals) { 1378 if ((visual->class | DynamicClass) == DirectColor) { 1379 visual->offsetRed = pScrni->offset.red; 1380 visual->offsetGreen = pScrni->offset.green; 1381 visual->offsetBlue = pScrni->offset.blue; 1382 visual->redMask = pScrni->mask.red; 1383 visual->greenMask = pScrni->mask.green; 1384 visual->blueMask = pScrni->mask.blue; 1385 } 1386 } 1387 } 1388 1389 /* Must follow the color ordering */ 1390 fbPictureInit(pScrn, 0, 0); 1391 1392 if (!pGeode->NoAccel) 1393 GXAccelInit(pScrn); 1394 1395 xf86SetBackingStore(pScrn); 1396 1397 /* Set up the soft cursor */ 1398 miDCInitialize(pScrn, xf86GetPointerScreenFuncs()); 1399 1400 /* Set up the HW cursor - must follow the soft cursor init */ 1401 1402 if (pGeode->tryHWCursor) { 1403 if (!GXHWCursorInit(pScrn)) 1404 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 1405 "Hardware cursor initialization failed.\n"); 1406 } 1407 1408 /* Set up the color map */ 1409 1410 if (!miCreateDefColormap(pScrn)) 1411 return FALSE; 1412 1413 if (pScrni->bitsPerPixel == 8) { 1414 /* Must follow initialization of the default colormap */ 1415 1416 if (!xf86HandleColormaps(pScrn, 256, 8, 1417 GXLoadPalette, NULL, 1418 CMAP_PALETTED_TRUECOLOR | 1419 CMAP_RELOAD_ON_MODE_SWITCH)) { 1420 return FALSE; 1421 } 1422 } 1423#ifdef DPMSExtension 1424 xf86DPMSInit(pScrn, GXDPMSSet, 0); 1425#endif 1426 1427 GXInitVideo(pScrn); 1428 1429 /* Set up RandR */ 1430 1431#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 24 1432 xf86DisableRandR(); /* We provide our own RandR goodness */ 1433#endif 1434 1435 /* Try to set up the shadow FB for rotation */ 1436 1437 memset(&shadowReq, 0, sizeof(shadowReq)); 1438 shadowReq.majorversion = 1; 1439 shadowReq.minorversion = 1; 1440 1441 if (LoadSubModule(pScrni->module, "shadow", 1442 NULL, NULL, NULL, &shadowReq, &maj, &min)) { 1443 1444 rotate = RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270; 1445 shadowSetup(pScrn); 1446 } 1447 else { 1448 LoaderErrorMsg(NULL, "shadow", maj, min); 1449 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 1450 "Error loading shadow - rotation not available.\n"); 1451 1452 if (pGeode->rotation != RR_Rotate_0) 1453 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 1454 "Reverting back to normal rotation.\n"); 1455 1456 rotate = pGeode->rotation = RR_Rotate_0; 1457 } 1458 1459 GXRandRInit(pScrn, rotate); 1460 1461 pGeode->PointerMoved = pScrni->PointerMoved; 1462 pScrni->PointerMoved = GeodePointerMoved; 1463 1464 pGeode->CreateScreenResources = pScrn->CreateScreenResources; 1465 pScrn->CreateScreenResources = GXCreateScreenResources; 1466 1467 pGeode->CloseScreen = pScrn->CloseScreen; 1468 pScrn->CloseScreen = GXCloseScreen; 1469 pScrn->SaveScreen = GXSaveScreen; 1470 1471 if (serverGeneration == 1) 1472 xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options); 1473 1474 pGeode->starting = FALSE; 1475 1476 return TRUE; 1477} 1478 1479static int 1480GXValidMode(VALID_MODE_ARGS_DECL) 1481{ 1482 SCRN_INFO_PTR(arg); 1483 GeodeRec *pGeode = GEODEPTR(pScrni); 1484 int p; 1485 int custom = 0; 1486 1487 if (pGeode->Panel) 1488 custom = (pMode->type & M_T_USERDEF); 1489 else 1490 custom = (pMode->type & (M_T_BUILTIN | M_T_DEFAULT)); 1491 1492 /* Use the durango lookup for !custom modes */ 1493 1494 if (!custom && pGeode->Panel) { 1495 if (pMode->CrtcHDisplay > pGeode->PanelX || 1496 pMode->CrtcVDisplay > pGeode->PanelY || 1497 gfx_is_panel_mode_supported(pGeode->PanelX, 1498 pGeode->PanelY, 1499 pMode->CrtcHDisplay, 1500 pMode->CrtcVDisplay, 1501 pScrni->bitsPerPixel) < 0) { 1502 1503 return MODE_BAD; 1504 } 1505 } 1506 1507 if (gfx_is_display_mode_supported(pMode->CrtcHDisplay, 1508 pMode->CrtcVDisplay, 1509 pScrni->bitsPerPixel, 1510 GeodeGetRefreshRate(pMode)) < 0) { 1511 return MODE_BAD; 1512 } 1513 1514 if (pMode->Flags & V_INTERLACE) 1515 return MODE_NO_INTERLACE; 1516 1517 if (pGeode->tryCompression) 1518 p = GeodeCalculatePitchBytes(pMode->CrtcHDisplay, pScrni->bitsPerPixel); 1519 else 1520 p = ((pMode->CrtcHDisplay + 3) & ~3) * (pScrni->bitsPerPixel >> 3); 1521 1522 if (p * pMode->CrtcVDisplay > pGeode->FBAvail) 1523 return MODE_MEM; 1524 1525 return MODE_OK; 1526} 1527 1528/* XXX - Way more to do here */ 1529 1530static Bool 1531GXEnterVT(VT_FUNC_ARGS_DECL) 1532{ 1533 SCRN_INFO_PTR(arg); 1534 return GXEnterGraphics(NULL, pScrni); 1535} 1536 1537static void 1538GXLeaveVT(VT_FUNC_ARGS_DECL) 1539{ 1540 SCRN_INFO_PTR(arg); 1541 GeodeRec *pGeode = GEODEPTR(pScrni); 1542 1543 pGeode->PrevDisplayOffset = gfx_get_display_offset(); 1544 GXLeaveGraphics(pScrni); 1545} 1546 1547void 1548GXSetupChipsetFPtr(ScrnInfoPtr pScrn) 1549{ 1550 pScrn->PreInit = GXPreInit; 1551 pScrn->ScreenInit = GXScreenInit; 1552 pScrn->SwitchMode = GXSwitchMode; 1553 pScrn->AdjustFrame = GXAdjustFrame; 1554 pScrn->EnterVT = GXEnterVT; 1555 pScrn->LeaveVT = GXLeaveVT; 1556 pScrn->FreeScreen = GeodeFreeScreen; 1557 pScrn->ValidMode = GXValidMode; 1558} 1559 1560/* ====== Common functions ====== 1561 * These are all the common functions that we use for both GX and LX - They live here 1562 * because most of them came along for the GX first, and then were adapted to the LX. 1563 * We could move these to a common function, but there is no hurry 1564 * ============================== */ 1565 1566void 1567GeodePointerMoved(POINTER_MOVED_ARGS_DECL) 1568{ 1569 SCRN_INFO_PTR(arg); 1570 GeodeRec *pGeode = GEODEPTR(pScrni); 1571 1572 int newX = x, newY = y; 1573 1574 switch (pGeode->rotation) { 1575 case RR_Rotate_0: 1576 break; 1577 case RR_Rotate_90: 1578 newX = y; 1579 newY = pScrni->pScreen->width - x - 1; 1580 break; 1581 case RR_Rotate_180: 1582 newX = pScrni->pScreen->width - x - 1; 1583 newY = pScrni->pScreen->height - y - 1; 1584 break; 1585 case RR_Rotate_270: 1586 newX = pScrni->pScreen->height - y - 1; 1587 newY = x; 1588 break; 1589 } 1590 1591 (*pGeode->PointerMoved) (POINTER_MOVED_ARGS(newX, newY)); 1592} 1593 1594int 1595GeodeGetFPGeometry(const char *str, int *width, int *height) 1596{ 1597 1598 int ret = sscanf(str, "%dx%d", width, height); 1599 1600 return (ret == 2) ? 0 : 1; 1601} 1602 1603static void 1604GeodeFreeRec(ScrnInfoPtr pScrni) 1605{ 1606 if (pScrni->driverPrivate != NULL) { 1607 free(pScrni->driverPrivate); 1608 pScrni->driverPrivate = NULL; 1609 } 1610} 1611 1612void 1613GeodeFreeScreen(FREE_SCREEN_ARGS_DECL) 1614{ 1615 SCRN_INFO_PTR(arg); 1616 GeodeRec *pGeode = GEODEPTR(pScrni); 1617 1618 if (pGeode == NULL) 1619 return; 1620 1621 if (pGeode->useVGA) { 1622 if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 1623 vgaHWFreeHWRec(pScrni); 1624 } 1625 1626 GeodeFreeRec(pScrni); 1627} 1628 1629int 1630GeodeCalculatePitchBytes(unsigned int width, unsigned int bpp) 1631{ 1632 1633 int delta = width * (bpp >> 3); 1634 1635 /* Less then 640 has doubling enabled */ 1636 1637 if (width < 640) 1638 delta <<= 1; 1639 1640 /* Calculate the pitch (compression requires a power of 2) */ 1641 1642 if (delta > 4096) 1643 delta = 8192; 1644 else if (delta > 2048) 1645 delta = 4096; 1646 else if (delta > 1024) 1647 delta = 2048; 1648 else 1649 delta = 1024; 1650 1651 return delta; 1652} 1653