1f29dbc25Smrg/* Copyright (c) 2003-2006 Advanced Micro Devices, Inc. 2f29dbc25Smrg * 3f29dbc25Smrg * Portioned modeled from xf86-video-intel/src/i830_driver.c 4f29dbc25Smrg * Copyright 2001 VA Linux Systems Inc., Fremont, California. 5f29dbc25Smrg * Copyright \ufffd 2002 by David Dawes 6f29dbc25Smrg 7f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy 8f29dbc25Smrg * of this software and associated documentation files (the "Software"), to 9f29dbc25Smrg * deal in the Software without restriction, including without limitation the 10f29dbc25Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11f29dbc25Smrg * sell copies of the Software, and to permit persons to whom the Software is 12f29dbc25Smrg * furnished to do so, subject to the following conditions: 13f29dbc25Smrg * 14f29dbc25Smrg * The above copyright notice and this permission notice shall be included in 15f29dbc25Smrg * all copies or substantial portions of the Software. 16f29dbc25Smrg * 17f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23f29dbc25Smrg * IN THE SOFTWARE. 24f29dbc25Smrg * 25f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 26f29dbc25Smrg * contributors may be used to endorse or promote products derived from this 27f29dbc25Smrg * software without specific prior written permission. 28f29dbc25Smrg */ 29f29dbc25Smrg 30f29dbc25Smrg#ifdef HAVE_CONFIG_H 31f29dbc25Smrg#include "config.h" 32f29dbc25Smrg#endif 33f29dbc25Smrg 34f29dbc25Smrg#include <stdio.h> 357f419768Smrg#include <fcntl.h> 367f419768Smrg#include <unistd.h> 377f419768Smrg#include <sys/mman.h> 38f29dbc25Smrg 3900be8644Schristos#include "xorg-server.h" 4000be8644Schristos 41f29dbc25Smrg#include "xf86.h" 42f29dbc25Smrg#include "xf86_OSproc.h" 43f29dbc25Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 44f29dbc25Smrg#include "xf86Resources.h" 45f29dbc25Smrg#endif 46f29dbc25Smrg#include "xf86cmap.h" 47f29dbc25Smrg#include "compiler.h" 48f29dbc25Smrg#include "mipointer.h" 49f29dbc25Smrg#include "shadow.h" 50f29dbc25Smrg#include <X11/extensions/randr.h> 51f29dbc25Smrg#include "fb.h" 52f29dbc25Smrg#include "miscstruct.h" 53f29dbc25Smrg#include "micmap.h" 54f29dbc25Smrg#include "vbe.h" 55f29dbc25Smrg#include "fb.h" 56f29dbc25Smrg#include "randrstr.h" 57f29dbc25Smrg 58f29dbc25Smrg#include "geode.h" 59f29dbc25Smrg#include "gfx_defs.h" 60f29dbc25Smrg#include "gfx_regs.h" 61f29dbc25Smrg#include "panel.h" 62f29dbc25Smrg 63f29dbc25Smrg/* Bring in VGA functions */ 64f29dbc25Smrg#include "gx_vga.c" 65f29dbc25Smrg 66f29dbc25Smrg#define GX_MIN_PITCH 1024 67f29dbc25Smrg#define GX_MAX_PITCH 8192 68f29dbc25Smrg#define GX_MAX_WIDTH 1600 69f29dbc25Smrg#define GX_MIN_HEIGHT 400 70f29dbc25Smrg#define GX_MAX_HEIGHT 1200 71f29dbc25Smrg#define GX_CB_PITCH 544 72f29dbc25Smrg#define GX_CB_SIZE 544 73f29dbc25Smrg 74f29dbc25Smrg#define GX_CPU_REG_SIZE 0x4000 75f29dbc25Smrg#define GX_GP_REG_SIZE 0x4000 76f29dbc25Smrg#define GX_VID_REG_SIZE 0x4000 77f29dbc25Smrg 78f29dbc25Smrg#define DEFAULT_IMG_LINE_BUFS 20 79f29dbc25Smrg#define DEFAULT_CLR_LINE_BUFS 20 80f29dbc25Smrg 81f29dbc25Smrgextern OptionInfoRec GX_GeodeOptions[]; 82f29dbc25Smrg 83c744f008Smrgextern unsigned char *XpressROMPtr; 84f29dbc25Smrg 85f29dbc25Smrgstatic inline void 86f29dbc25Smrggx_enable_dac_power(void) 87f29dbc25Smrg{ 88f29dbc25Smrg gfx_write_vid32(RCDF_VID_MISC, 8904007ebaSmrg gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH); 90f29dbc25Smrg} 91f29dbc25Smrg 92f29dbc25Smrgstatic inline void 93f29dbc25Smrggx_disable_dac_power(void) 94f29dbc25Smrg{ 95f29dbc25Smrg gfx_write_vid32(RCDF_VID_MISC, 9604007ebaSmrg RCDF_DAC_POWER_DOWN | RCDF_ANALOG_POWER_DOWN | 9704007ebaSmrg (gfx_read_vid32(RCDF_VID_MISC) & RCDF_GAMMA_BYPASS_BOTH)); 98f29dbc25Smrg} 99f29dbc25Smrg 100f29dbc25Smrgstatic void 101f29dbc25SmrgGXInitEXAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail) 102f29dbc25Smrg{ 103f29dbc25Smrg GeodePtr pGeode = GEODEPTR(pScrni); 104f29dbc25Smrg 105f29dbc25Smrg if (pGeode->exaBfrSz > 0 && pGeode->exaBfrSz <= *avail) { 10604007ebaSmrg pGeode->exaBfrOffset = *offset; 10704007ebaSmrg *offset += pGeode->exaBfrOffset; 10804007ebaSmrg *avail -= pGeode->exaBfrOffset; 109f29dbc25Smrg } 110f29dbc25Smrg} 111f29dbc25Smrg 112f29dbc25Smrgstatic void 113f29dbc25SmrgGXInitXAAMemory(ScrnInfoPtr pScrni, unsigned int *offset, unsigned int *avail) 114f29dbc25Smrg{ 115f29dbc25Smrg GeodePtr pGeode = GEODEPTR(pScrni); 116f29dbc25Smrg unsigned int size, i, pitch; 117f29dbc25Smrg 118f29dbc25Smrg /* XXX - FIXME - What if we are out of room? Then what? */ 119f29dbc25Smrg /* For now, we NULL them all out. */ 120f29dbc25Smrg 121f29dbc25Smrg if (pGeode->NoOfImgBuffers > 0) { 12204007ebaSmrg size = pGeode->displayPitch * pGeode->NoOfImgBuffers; 12304007ebaSmrg if (size <= *avail) { 12404007ebaSmrg for (i = 0; i < pGeode->NoOfImgBuffers; i++) { 12504007ebaSmrg pGeode->AccelImageWriteBuffers[i] = pGeode->FBBase + *offset; 12604007ebaSmrg *offset += pGeode->displayPitch; 12704007ebaSmrg *avail -= pGeode->displayPitch; 12804007ebaSmrg } 12904007ebaSmrg } 13004007ebaSmrg else { 13104007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 13204007ebaSmrg "Not enough memory for image write buffers.\n"); 13304007ebaSmrg 13404007ebaSmrg for (i = 0; i < pGeode->NoOfImgBuffers; i++) 13504007ebaSmrg pGeode->AccelImageWriteBuffers[i] = NULL; 13604007ebaSmrg } 137f29dbc25Smrg } 138f29dbc25Smrg 139f29dbc25Smrg if (pGeode->NoOfColorExpandLines > 0) { 14004007ebaSmrg pitch = ((pGeode->displayPitch + 31) >> 5) << 2; 14104007ebaSmrg size = pitch * pGeode->NoOfColorExpandLines; 14204007ebaSmrg 14304007ebaSmrg if (size <= *avail) { 14404007ebaSmrg for (i = 0; i < pGeode->NoOfColorExpandLines; i++) { 14504007ebaSmrg pGeode->AccelColorExpandBuffers[i] = pGeode->FBBase + *offset; 14604007ebaSmrg *offset += pitch; 14704007ebaSmrg *avail -= pitch; 14804007ebaSmrg } 14904007ebaSmrg } 15004007ebaSmrg else { 15104007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 15204007ebaSmrg "Not enough memory for color expansion buffers.\n"); 15304007ebaSmrg 15404007ebaSmrg for (i = 0; i < pGeode->NoOfImgBuffers; i++) 15504007ebaSmrg pGeode->AccelColorExpandBuffers[i] = NULL; 15604007ebaSmrg } 157f29dbc25Smrg } 158f29dbc25Smrg} 159f29dbc25Smrg 160f29dbc25Smrgstatic Bool 161f29dbc25SmrgGXAllocateMemory(ScreenPtr pScrn, ScrnInfoPtr pScrni, int rotate) 162f29dbc25Smrg{ 163f29dbc25Smrg GeodePtr pGeode = GEODEPTR(pScrni); 164f29dbc25Smrg 165f29dbc25Smrg unsigned int fboffset, fbavail; 166f29dbc25Smrg unsigned int size; 167f29dbc25Smrg unsigned int bytpp = (pScrni->bitsPerPixel + 7) / 8; 168f29dbc25Smrg BOOL ret = TRUE; 169f29dbc25Smrg 170f29dbc25Smrg if (pGeode->tryCompression) 17104007ebaSmrg pGeode->displayPitch = 17204007ebaSmrg GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel); 173f29dbc25Smrg else 17404007ebaSmrg pGeode->displayPitch = 17504007ebaSmrg ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3); 176f29dbc25Smrg 177f29dbc25Smrg pGeode->Pitch = pGeode->displayPitch; 178f29dbc25Smrg pGeode->displayWidth = pGeode->displayPitch / bytpp; 179f29dbc25Smrg pScrni->displayWidth = pGeode->displayWidth; 180f29dbc25Smrg 181f29dbc25Smrg fbavail = pGeode->FBAvail - 0x4000; 182f29dbc25Smrg 183f29dbc25Smrg pGeode->displayOffset = fboffset = 0; 184f29dbc25Smrg pGeode->displaySize = pScrni->virtualY * pGeode->displayPitch; 185f29dbc25Smrg 186f29dbc25Smrg fbavail -= pGeode->displaySize; 187f29dbc25Smrg fboffset += pGeode->displaySize; 188f29dbc25Smrg 189f29dbc25Smrg if (pGeode->tryCompression) { 19004007ebaSmrg size = pScrni->virtualY * GX_CB_PITCH; 191f29dbc25Smrg 19204007ebaSmrg if (size <= fbavail) { 19304007ebaSmrg pGeode->CBData.compression_offset = fboffset; 194f29dbc25Smrg 19504007ebaSmrg fboffset += size; 19604007ebaSmrg fbavail -= size; 197f29dbc25Smrg 19804007ebaSmrg pGeode->Compression = TRUE; 19904007ebaSmrg } 20004007ebaSmrg else { 20104007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 20204007ebaSmrg "Not enough memory for compression\n"); 20304007ebaSmrg pGeode->Compression = FALSE; 20404007ebaSmrg } 205f29dbc25Smrg } 206f29dbc25Smrg 207f29dbc25Smrg if (pGeode->tryHWCursor) { 208f29dbc25Smrg 20904007ebaSmrg if (fbavail >= 1024) { 21004007ebaSmrg pGeode->CursorStartOffset = fboffset; 21104007ebaSmrg fboffset += 1024; 21204007ebaSmrg fbavail -= 1024; 21304007ebaSmrg pGeode->HWCursor = TRUE; 21404007ebaSmrg } 21504007ebaSmrg else { 21604007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 21704007ebaSmrg "Not enough memory for the hardware cursor\n"); 21804007ebaSmrg pGeode->HWCursor = FALSE; 21904007ebaSmrg } 220f29dbc25Smrg } 221f29dbc25Smrg 222f29dbc25Smrg if (!pGeode->NoAccel) { 22304007ebaSmrg if (pGeode->useEXA) 22404007ebaSmrg GXInitEXAMemory(pScrni, &fboffset, &fbavail); 22504007ebaSmrg else 22604007ebaSmrg GXInitXAAMemory(pScrni, &fboffset, &fbavail); 227f29dbc25Smrg } 228f29dbc25Smrg 229f29dbc25Smrg pGeode->shadowSize = 0; 230f29dbc25Smrg 231f29dbc25Smrg if (rotate != RR_Rotate_0) { 23204007ebaSmrg if (rotate & (RR_Rotate_90 | RR_Rotate_270)) 23304007ebaSmrg size = pGeode->displayPitch * pScrni->virtualX; 23404007ebaSmrg else 23504007ebaSmrg size = pGeode->displayPitch * pScrni->virtualY; 23604007ebaSmrg 23704007ebaSmrg if (size <= fbavail) { 23804007ebaSmrg pGeode->shadowOffset = fboffset; 23904007ebaSmrg pGeode->shadowSize = size; 24004007ebaSmrg 24104007ebaSmrg fboffset += size; 24204007ebaSmrg fbavail -= size; 24304007ebaSmrg } 24404007ebaSmrg else { 24504007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 24604007ebaSmrg "Not enough memory for the shadow framebuffer\n"); 24704007ebaSmrg ret = FALSE; 24804007ebaSmrg } 249f29dbc25Smrg } 250f29dbc25Smrg 251f29dbc25Smrg /* XAA always exists - we can't remove it on demand like we can with EXA. 252f29dbc25Smrg * So we assume the worse, and only give XAA enough offspace room to 253f29dbc25Smrg * account for any eventuality that RandR might throw at us. */ 254f29dbc25Smrg 255f29dbc25Smrg if (!pGeode->NoAccel) { 256f29dbc25Smrg 25704007ebaSmrg if (pGeode->useEXA && pGeode->pExa) { 25804007ebaSmrg ExaDriverPtr pExa = pGeode->pExa; 259f29dbc25Smrg 26004007ebaSmrg pExa->offScreenBase = fboffset; 26104007ebaSmrg pExa->memorySize = fboffset + fbavail; 26204007ebaSmrg } 263f29dbc25Smrg 26404007ebaSmrg if (!pGeode->useEXA) { 265f29dbc25Smrg 26604007ebaSmrg#if XF86XAA 26704007ebaSmrg if (!xf86FBManagerRunning(pScrn)) { 268f29dbc25Smrg 26904007ebaSmrg unsigned int offset = fboffset; 27004007ebaSmrg unsigned int avail = fbavail; 27104007ebaSmrg RegionRec OffscreenRegion; 27204007ebaSmrg BoxRec AvailBox; 273f29dbc25Smrg 274c744f008Smrg /* Assume the shadow FB exists even if it doesn't */ 275f29dbc25Smrg 27604007ebaSmrg if (pGeode->shadowSize == 0) { 27704007ebaSmrg size = (pScrn->width * bytpp) * pScrni->virtualX; 27804007ebaSmrg offset += size; 27904007ebaSmrg avail -= size; 28004007ebaSmrg } 281f29dbc25Smrg 28204007ebaSmrg AvailBox.x1 = 0; 28304007ebaSmrg AvailBox.y1 = 28404007ebaSmrg (offset + pGeode->displayPitch - 1) / pGeode->displayPitch; 285f29dbc25Smrg 28604007ebaSmrg AvailBox.x2 = pGeode->displayWidth; 28704007ebaSmrg AvailBox.y2 = (offset + avail) / pGeode->displayPitch; 288f29dbc25Smrg 28904007ebaSmrg if (AvailBox.y1 < AvailBox.y2) { 29004007ebaSmrg REGION_INIT(pScrn, &OffscreenRegion, &AvailBox, 2); 291f29dbc25Smrg 29204007ebaSmrg if (!xf86InitFBManagerRegion(pScrn, &OffscreenRegion)) 29304007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 29404007ebaSmrg "Memory manager initialization failed.\n"); 295f29dbc25Smrg 29604007ebaSmrg REGION_UNINIT(pScrn, &OffscreenRegion); 29704007ebaSmrg } 29804007ebaSmrg else 29904007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_INFO, 30004007ebaSmrg "Cache disabled - no offscreen memory available.\n"); 30104007ebaSmrg } 30204007ebaSmrg else 30304007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_INFO, 30404007ebaSmrg "XAA offscreen memory has already been allocated.\n"); 30504007ebaSmrg#endif 30604007ebaSmrg } 307f29dbc25Smrg } 308f29dbc25Smrg return ret; 309f29dbc25Smrg} 310f29dbc25Smrg 311f29dbc25Smrgstatic Bool 312f29dbc25SmrgGXSaveScreen(ScreenPtr pScrn, int mode) 313f29dbc25Smrg{ 31404007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 315f29dbc25Smrg GeodePtr pGeode = GEODEPTR(pScrni); 316f29dbc25Smrg 317f29dbc25Smrg if (pGeode->useVGA && !pScrni->vtSema) 31804007ebaSmrg return vgaHWSaveScreen(pScrn, mode); 319f29dbc25Smrg 320f29dbc25Smrg return TRUE; 321f29dbc25Smrg} 322f29dbc25Smrg 323f29dbc25Smrg/* Common function - used by the LX too */ 324f29dbc25Smrg#ifdef XSERVER_LIBPCIACCESS 325f29dbc25Smrgstatic inline void * 326f29dbc25Smrgmap_pci_mem(ScrnInfoPtr pScrni, int vram, 32704007ebaSmrg struct pci_device *dev, int bar, int size) 328f29dbc25Smrg{ 329f29dbc25Smrg void *ptr; 330f29dbc25Smrg int map_size = size ? size : dev->regions[bar].size; 331f29dbc25Smrg 332f29dbc25Smrg int err = pci_device_map_range(dev, 33304007ebaSmrg dev->regions[bar].base_addr, 33404007ebaSmrg map_size, 33504007ebaSmrg PCI_DEV_MAP_FLAG_WRITABLE | 33604007ebaSmrg (vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0), 3377f419768Smrg &ptr); 338f29dbc25Smrg 339f29dbc25Smrg if (err) 34004007ebaSmrg return NULL; 341f29dbc25Smrg return ptr; 342f29dbc25Smrg} 3437f419768Smrg 3447f419768Smrgstatic inline int 3457f419768Smrgunmap_pci_mem(ScrnInfoPtr pScrni, struct pci_device *dev, void *ptr, int size) 3467f419768Smrg{ 3477f419768Smrg return pci_device_unmap_range(dev, ptr, size); 3487f419768Smrg} 349f29dbc25Smrg#endif 350f29dbc25Smrg 351f29dbc25Smrgextern unsigned long gfx_gx2_scratch_base; 352f29dbc25Smrg 353f29dbc25Smrgstatic Bool 354f29dbc25SmrgGXMapMem(ScrnInfoPtr pScrni) 355f29dbc25Smrg{ 356f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 357f29dbc25Smrg int index = pScrni->scrnIndex; 358f29dbc25Smrg 359f29dbc25Smrg pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index); 360f29dbc25Smrg 361f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS 36204007ebaSmrg gfx_virt_regptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO, 36304007ebaSmrg pci->memBase[2], 36404007ebaSmrg pci->size[2]); 365f29dbc25Smrg 36604007ebaSmrg gfx_virt_gpptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO, 36704007ebaSmrg pci->memBase[1], 36804007ebaSmrg pci->size[1]); 369f29dbc25Smrg 37004007ebaSmrg gfx_virt_vidptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_MMIO, 37104007ebaSmrg pci->memBase[3], 37204007ebaSmrg pci->size[3]); 373f29dbc25Smrg 37404007ebaSmrg gfx_virt_fbptr = (unsigned char *) xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 37504007ebaSmrg pci->memBase[0], 37604007ebaSmrg pGeode->FBAvail); 377f29dbc25Smrg#else 378f29dbc25Smrg gfx_virt_regptr = map_pci_mem(pScrni, 0, pci, 2, 0); 379f29dbc25Smrg gfx_virt_gpptr = map_pci_mem(pScrni, 0, pci, 1, 0); 380f29dbc25Smrg gfx_virt_vidptr = map_pci_mem(pScrni, 0, pci, 3, 0); 381f29dbc25Smrg gfx_virt_fbptr = map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail); 382f29dbc25Smrg#endif 383f29dbc25Smrg 384f29dbc25Smrg gfx_gx2_scratch_base = pGeode->FBAvail - 0x4000; 385f29dbc25Smrg 3867f419768Smrg#ifndef XSERVER_LIBPCIACCESS 387f29dbc25Smrg XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000); 3887f419768Smrg#else 3897f419768Smrg { 3907f419768Smrg int fd = open("/dev/mem", O_RDWR); 3917f419768Smrg if (fd < 0) { 3927f419768Smrg xf86DrvMsg(index, X_ERROR, "Failed to open /dev/mem: %m\n"); 3937f419768Smrg return FALSE; 3947f419768Smrg } 3957f419768Smrg XpressROMPtr = mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xF0000); 3967f419768Smrg close(fd); 3977f419768Smrg } 3987f419768Smrg#endif 399f29dbc25Smrg pGeode->FBBase = gfx_virt_fbptr; 400f29dbc25Smrg 401f29dbc25Smrg if ((!gfx_virt_regptr) || (!gfx_virt_gpptr) || 40204007ebaSmrg (!gfx_virt_vidptr) || (!gfx_virt_fbptr)) 40304007ebaSmrg return FALSE; 404f29dbc25Smrg 405f29dbc25Smrg if (!pGeode->NoAccel && pGeode->useEXA) 40604007ebaSmrg pGeode->pExa->memoryBase = pGeode->FBBase; 407f29dbc25Smrg 408f29dbc25Smrg xf86DrvMsg(index, X_INFO, "Found Geode %x %p\n", 40904007ebaSmrg pGeode->FBAvail, pGeode->FBBase); 410f29dbc25Smrg 411f29dbc25Smrg return TRUE; 412f29dbc25Smrg} 413f29dbc25Smrg 414f29dbc25Smrg/* Check to see if VGA exists - we map the space and look for a 415f29dbc25Smrg signature - if it doesn't match exactly, then we assume no VGA. 416f29dbc25Smrg*/ 417f29dbc25Smrg 418f29dbc25Smrgstatic Bool 4197f419768SmrgGXCheckVGA(ScrnInfoPtr pScrni, EntityInfoPtr pEnt) 420f29dbc25Smrg{ 4217f419768Smrg#ifndef XSERVER_LIBPCIACCESS 422f29dbc25Smrg unsigned char *ptr; 423f29dbc25Smrg const char *vgasig = "IBM VGA Compatible"; 424f29dbc25Smrg int ret; 425f29dbc25Smrg 426f29dbc25Smrg ptr = 42704007ebaSmrg xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E, 42804007ebaSmrg strlen(vgasig)); 429f29dbc25Smrg 430f29dbc25Smrg if (ptr == NULL) 43104007ebaSmrg return FALSE; 432f29dbc25Smrg 433f29dbc25Smrg ret = memcmp(ptr, vgasig, strlen(vgasig)); 434f29dbc25Smrg xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig)); 435f29dbc25Smrg 436f29dbc25Smrg return ret ? FALSE : TRUE; 4377f419768Smrg#else 4387f419768Smrg pciVideoPtr pci = xf86GetPciInfoForEntity(pEnt->index); 4397f419768Smrg 4407f419768Smrg return pci_device_is_boot_vga(pci); 4417f419768Smrg#endif 442f29dbc25Smrg} 443f29dbc25Smrg 444f29dbc25Smrgstatic Bool 445f29dbc25SmrgGXPreInit(ScrnInfoPtr pScrni, int flags) 446f29dbc25Smrg{ 447f29dbc25Smrg GeodePtr pGeode; 448f29dbc25Smrg ClockRangePtr GeodeClockRange; 449f29dbc25Smrg OptionInfoRec *GeodeOptions = &GX_GeodeOptions[0]; 450f29dbc25Smrg int ret; 451f29dbc25Smrg QQ_WORD msrValue; 452f29dbc25Smrg EntityInfoPtr pEnt; 453f29dbc25Smrg rgb defaultWeight = { 0, 0, 0 }; 454f29dbc25Smrg int modecnt; 4553406bd8eSmrg const char *s, *panelgeo; 456f29dbc25Smrg Bool useVGA; 457f29dbc25Smrg 458f29dbc25Smrg if (pScrni->numEntities != 1) 45904007ebaSmrg return FALSE; 460f29dbc25Smrg 461f29dbc25Smrg pEnt = xf86GetEntityInfo(pScrni->entityList[0]); 462f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS 463f29dbc25Smrg if (pEnt->resources) 46404007ebaSmrg return FALSE; 465f29dbc25Smrg#endif 466f29dbc25Smrg 46704007ebaSmrg pGeode = pScrni->driverPrivate = xnfcalloc(1, sizeof(GeodeRec)); 468f29dbc25Smrg 469f29dbc25Smrg if (pGeode == NULL) 47004007ebaSmrg return FALSE; 471f29dbc25Smrg 4727f419768Smrg useVGA = GXCheckVGA(pScrni, pEnt); 473f29dbc25Smrg 474f29dbc25Smrg if (flags & PROBE_DETECT) { 47504007ebaSmrg GeodeProbeDDC(pScrni, pEnt->index); 47604007ebaSmrg return TRUE; 477f29dbc25Smrg } 478f29dbc25Smrg 479f29dbc25Smrg /* Probe for VGA */ 480f29dbc25Smrg pGeode->useVGA = useVGA; 481f29dbc25Smrg pGeode->pEnt = pEnt; 482f29dbc25Smrg 483f29dbc25Smrg if (pGeode->useVGA) { 48404007ebaSmrg if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni)) 48504007ebaSmrg pGeode->useVGA = FALSE; 48604007ebaSmrg else 48704007ebaSmrg vgaHWSetStdFuncs(VGAHWPTR(pScrni)); 488f29dbc25Smrg 489f29dbc25Smrg#if INT10_SUPPORT 49004007ebaSmrg pGeode->vesa = calloc(1, sizeof(VESARec)); 491f29dbc25Smrg#endif 492f29dbc25Smrg } 493f29dbc25Smrg 494f29dbc25Smrg gfx_msr_init(); 495f29dbc25Smrg 496f29dbc25Smrg ret = gfx_msr_read(RC_ID_DF, MBD_MSR_CONFIG, &msrValue); 497f29dbc25Smrg 498f29dbc25Smrg if (!ret) { 49904007ebaSmrg pGeode->Output = 50004007ebaSmrg ((msrValue.low & RCDF_CONFIG_FMT_MASK) == 50104007ebaSmrg RCDF_CONFIG_FMT_FP) ? OUTPUT_PANEL : OUTPUT_CRT; 502f29dbc25Smrg } 503f29dbc25Smrg 504f29dbc25Smrg /* Fill in the monitor information */ 505f29dbc25Smrg pScrni->monitor = pScrni->confScreen->monitor; 506f29dbc25Smrg 507f29dbc25Smrg if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb)) 50804007ebaSmrg return FALSE; 509f29dbc25Smrg 510f29dbc25Smrg switch (pScrni->depth) { 511f29dbc25Smrg case 8: 51204007ebaSmrg pScrni->rgbBits = 8; 513f29dbc25Smrg case 16: 514f29dbc25Smrg case 24: 515f29dbc25Smrg case 32: 51604007ebaSmrg break; 517f29dbc25Smrg default: 51804007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 51904007ebaSmrg "The driver does not support %d as a depth.\n", 52004007ebaSmrg pScrni->depth); 52104007ebaSmrg return FALSE; 522f29dbc25Smrg } 523f29dbc25Smrg 524f29dbc25Smrg xf86PrintDepthBpp(pScrni); 525f29dbc25Smrg 526f29dbc25Smrg if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight)) 52704007ebaSmrg return FALSE; 528f29dbc25Smrg 529f29dbc25Smrg if (!xf86SetDefaultVisual(pScrni, -1)) 53004007ebaSmrg return FALSE; 531f29dbc25Smrg 532f29dbc25Smrg /* 533f29dbc25Smrg * If the driver can do gamma correction, it should call xf86SetGamma() 534f29dbc25Smrg * here. 535f29dbc25Smrg */ 536f29dbc25Smrg { 53704007ebaSmrg Gamma zeros = { 0.0, 0.0, 0.0 }; 538f29dbc25Smrg 53904007ebaSmrg if (!xf86SetGamma(pScrni, zeros)) { 54004007ebaSmrg return FALSE; 54104007ebaSmrg } 542f29dbc25Smrg } 543f29dbc25Smrg 544f29dbc25Smrg pScrni->progClock = TRUE; 545f29dbc25Smrg xf86CollectOptions(pScrni, NULL); 546f29dbc25Smrg xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions); 547f29dbc25Smrg 548f29dbc25Smrg /* Set up our various options that may get reversed as we go on */ 549f29dbc25Smrg 550f29dbc25Smrg pGeode->FBVGAActive = FALSE; 551f29dbc25Smrg pGeode->tryHWCursor = TRUE; 552f29dbc25Smrg pGeode->tryCompression = TRUE; 553f29dbc25Smrg 554f29dbc25Smrg pGeode->NoAccel = FALSE; 555f29dbc25Smrg pGeode->useEXA = FALSE; 556f29dbc25Smrg 557f29dbc25Smrg pGeode->Panel = (pGeode->Output & OUTPUT_PANEL) ? TRUE : FALSE; 558f29dbc25Smrg 559f29dbc25Smrg pGeode->NoOfImgBuffers = DEFAULT_IMG_LINE_BUFS; 560f29dbc25Smrg pGeode->NoOfColorExpandLines = DEFAULT_CLR_LINE_BUFS; 561f29dbc25Smrg pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ; 562f29dbc25Smrg 56304007ebaSmrg xf86GetOptValBool(GeodeOptions, GX_OPTION_HW_CURSOR, &pGeode->tryHWCursor); 564f29dbc25Smrg 565f29dbc25Smrg if (!xf86GetOptValInteger(GeodeOptions, GX_OPTION_FBSIZE, 56604007ebaSmrg (int *) &(pGeode->FBAvail))) 56704007ebaSmrg pGeode->FBAvail = 0; 568f29dbc25Smrg 569c744f008Smrg /* For compatibility - allow SWCursor too */ 570f29dbc25Smrg 571f29dbc25Smrg if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_SW_CURSOR, FALSE)) 57204007ebaSmrg pGeode->tryHWCursor = FALSE; 573f29dbc25Smrg 574f29dbc25Smrg if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOCOMPRESSION, FALSE)) 57504007ebaSmrg pGeode->tryCompression = FALSE; 576f29dbc25Smrg 577f29dbc25Smrg if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOACCEL, FALSE)) 57804007ebaSmrg pGeode->NoAccel = TRUE; 579f29dbc25Smrg 580f29dbc25Smrg pGeode->rotation = RR_Rotate_0; 581f29dbc25Smrg 582f29dbc25Smrg if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ROTATE))) { 583f29dbc25Smrg 58404007ebaSmrg if (!xf86NameCmp(s, "LEFT")) 58504007ebaSmrg pGeode->rotation = RR_Rotate_90; 58604007ebaSmrg else if (!xf86NameCmp(s, "INVERT")) 58704007ebaSmrg pGeode->rotation = RR_Rotate_180; 58804007ebaSmrg else if (!xf86NameCmp(s, "CCW")) 58904007ebaSmrg pGeode->rotation = RR_Rotate_270; 59004007ebaSmrg else 59104007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "Invalid rotation %s.\n", s); 592f29dbc25Smrg } 593f29dbc25Smrg 594f29dbc25Smrg xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_IMG_BUFS, 59504007ebaSmrg &(pGeode->NoOfImgBuffers)); 596f29dbc25Smrg 597f29dbc25Smrg if (pGeode->NoOfImgBuffers <= 0) 59804007ebaSmrg pGeode->NoOfImgBuffers = 0; 599f29dbc25Smrg 600f29dbc25Smrg xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS, 60104007ebaSmrg &(pGeode->NoOfColorExpandLines)); 602f29dbc25Smrg 603f29dbc25Smrg if (pGeode->NoOfColorExpandLines <= 0) 60404007ebaSmrg pGeode->NoOfColorExpandLines = 0; 605f29dbc25Smrg 606f29dbc25Smrg xf86GetOptValInteger(GeodeOptions, GX_OPTION_OSM_CLR_BUFS, 60704007ebaSmrg (int *) &(pGeode->exaBfrSz)); 608f29dbc25Smrg 609f29dbc25Smrg if (pGeode->exaBfrSz <= 0) 61004007ebaSmrg pGeode->exaBfrSz = 0; 611f29dbc25Smrg 612f29dbc25Smrg if (pGeode->Panel == TRUE) { 61304007ebaSmrg if (xf86ReturnOptValBool(GeodeOptions, GX_OPTION_NOPANEL, FALSE)) 61404007ebaSmrg pGeode->Panel = FALSE; 615f29dbc25Smrg } 616f29dbc25Smrg 617f29dbc25Smrg panelgeo = xf86GetOptValString(GeodeOptions, GX_OPTION_PANEL_GEOMETRY); 618f29dbc25Smrg 619f29dbc25Smrg if ((s = xf86GetOptValString(GeodeOptions, GX_OPTION_ACCEL_METHOD))) { 6207f419768Smrg#if defined(XF86XAA) && defined(XF86EXA) 62104007ebaSmrg if (!xf86NameCmp(s, "XAA")) 62204007ebaSmrg pGeode->useEXA = FALSE; 62304007ebaSmrg else if (xf86NameCmp(s, "EXA")) 62404007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 625c744f008Smrg "Unknown acceleration method %s. Defaulting to XAA.\n", 62604007ebaSmrg s); 6277f419768Smrg#elif defined(XF86EXA) 6287f419768Smrg pGeode->useEXA = TRUE; 6297f419768Smrg#else 6307f419768Smrg pGeode->useEXA = FALSE; 6317f419768Smrg#endif 632f29dbc25Smrg } 633f29dbc25Smrg 634f29dbc25Smrg xf86DrvMsg(pScrni->scrnIndex, X_INFO, 63504007ebaSmrg "Using %s acceleration architecture\n", 63604007ebaSmrg pGeode->useEXA ? "EXA" : "XAA"); 637f29dbc25Smrg 638f29dbc25Smrg /* Set up the panel */ 639f29dbc25Smrg 640f29dbc25Smrg if (pGeode->Panel) { 64104007ebaSmrg if (panelgeo != NULL) { 64204007ebaSmrg if (GeodeGetFPGeometry(panelgeo, &pGeode->PanelX, &pGeode->PanelY)) 64304007ebaSmrg pGeode->Panel = FALSE; 64404007ebaSmrg } 645f29dbc25Smrg#ifdef PNL_SUP 64604007ebaSmrg else { 64704007ebaSmrg int b, f; 648f29dbc25Smrg 64904007ebaSmrg /* The bitdepth and refresh isn't used anywhere else in the driver */ 650f29dbc25Smrg 65104007ebaSmrg if ((pGeode->Panel = Pnl_IsPanelEnabledInBIOS())) 65204007ebaSmrg Pnl_GetPanelInfoFromBIOS(&pGeode->PanelX, &pGeode->PanelY, &b, 65304007ebaSmrg &f); 65404007ebaSmrg } 655f29dbc25Smrg#endif 656f29dbc25Smrg } 657f29dbc25Smrg 658f29dbc25Smrg /* Set up the VGA */ 659f29dbc25Smrg 660f29dbc25Smrg if (pGeode->useVGA) { 661f29dbc25Smrg#if INT10_SUPPORT 66204007ebaSmrg VESARec *pVesa; 663f29dbc25Smrg 66404007ebaSmrg if (!xf86LoadSubModule(pScrni, "int10")) 66504007ebaSmrg return FALSE; 666f29dbc25Smrg 66704007ebaSmrg pVesa = pGeode->vesa; 668f29dbc25Smrg 66904007ebaSmrg if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) { 67004007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 67104007ebaSmrg "Unable to initialize 1NT10 support\n"); 67204007ebaSmrg pGeode->useVGA = FALSE; 67304007ebaSmrg } 674f29dbc25Smrg#endif 675f29dbc25Smrg } 676f29dbc25Smrg 677f29dbc25Smrg /* First try to get the framebuffer size from the framebuffer, 678f29dbc25Smrg * and if that fails, revert all the way back to the legacy 679f29dbc25Smrg * method 680f29dbc25Smrg */ 681f29dbc25Smrg 682f29dbc25Smrg if (pGeode->FBAvail == 0) { 68304007ebaSmrg if (GeodeGetSizeFromFB(&pGeode->FBAvail)) 68404007ebaSmrg pGeode->FBAvail = gfx_get_frame_buffer_size(); 685f29dbc25Smrg } 686f29dbc25Smrg 687f29dbc25Smrg if (pScrni->memPhysBase == 0) 68804007ebaSmrg pScrni->memPhysBase = gfx_get_frame_buffer_base(); 689f29dbc25Smrg 690f29dbc25Smrg pScrni->fbOffset = 0; 691f29dbc25Smrg 692f29dbc25Smrg if (pGeode->pEnt->device->videoRam == 0) 69304007ebaSmrg pScrni->videoRam = pGeode->FBAvail / 1024; 694f29dbc25Smrg else 69504007ebaSmrg pScrni->videoRam = pGeode->pEnt->device->videoRam; 696f29dbc25Smrg 69704007ebaSmrg GeodeClockRange = (ClockRangePtr) xnfcalloc(1, sizeof(ClockRange)); 698f29dbc25Smrg GeodeClockRange->next = NULL; 699f29dbc25Smrg GeodeClockRange->minClock = 25175; 700f29dbc25Smrg GeodeClockRange->maxClock = 229500; 701f29dbc25Smrg GeodeClockRange->clockIndex = -1; 702f29dbc25Smrg GeodeClockRange->interlaceAllowed = TRUE; 703f29dbc25Smrg GeodeClockRange->doubleScanAllowed = FALSE; 704f29dbc25Smrg 705f29dbc25Smrg pScrni->monitor->DDC = GeodeDoDDC(pScrni, pGeode->pEnt->index); 706f29dbc25Smrg 707f29dbc25Smrg /* I'm still not 100% sure this uses the right values */ 708f29dbc25Smrg 709f29dbc25Smrg modecnt = xf86ValidateModes(pScrni, 71004007ebaSmrg pScrni->monitor->Modes, 71104007ebaSmrg pScrni->display->modes, 71204007ebaSmrg GeodeClockRange, 71304007ebaSmrg NULL, GX_MIN_PITCH, GX_MAX_PITCH, 71404007ebaSmrg 32, GX_MIN_HEIGHT, GX_MAX_HEIGHT, 71504007ebaSmrg pScrni->display->virtualX, 71604007ebaSmrg pScrni->display->virtualY, pGeode->FBAvail, 71704007ebaSmrg LOOKUP_BEST_REFRESH); 718f29dbc25Smrg 719f29dbc25Smrg if (modecnt <= 0) { 72004007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n"); 72104007ebaSmrg return FALSE; 722f29dbc25Smrg } 723f29dbc25Smrg 724f29dbc25Smrg xf86PruneDriverModes(pScrni); 725f29dbc25Smrg 726f29dbc25Smrg if (pScrni->modes == NULL) { 72704007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes were found\n"); 72804007ebaSmrg return FALSE; 729f29dbc25Smrg } 730f29dbc25Smrg 731f29dbc25Smrg xf86SetCrtcForModes(pScrni, 0); 732f29dbc25Smrg pScrni->currentMode = pScrni->modes; 733f29dbc25Smrg 734f29dbc25Smrg xf86PrintModes(pScrni); 735f29dbc25Smrg xf86SetDpi(pScrni, 0, 0); 736f29dbc25Smrg 737f29dbc25Smrg /* Load the modules we'll need */ 738f29dbc25Smrg 739f29dbc25Smrg if (xf86LoadSubModule(pScrni, "fb") == NULL) { 74004007ebaSmrg return FALSE; 741f29dbc25Smrg } 742f29dbc25Smrg 743f29dbc25Smrg if (pGeode->NoAccel == FALSE) { 74404007ebaSmrg const char *module = (pGeode->useEXA) ? "exa" : "xaa"; 745f29dbc25Smrg 74604007ebaSmrg if (!xf86LoadSubModule(pScrni, module)) { 74704007ebaSmrg return FALSE; 74804007ebaSmrg } 749f29dbc25Smrg } 750f29dbc25Smrg 751f29dbc25Smrg if (pGeode->tryHWCursor == TRUE) { 75204007ebaSmrg if (!xf86LoadSubModule(pScrni, "ramdac")) { 75304007ebaSmrg return FALSE; 75404007ebaSmrg } 755f29dbc25Smrg } 756f29dbc25Smrg 757f29dbc25Smrg#ifndef XSERVER_LIBPCIACCESS 758f29dbc25Smrg if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) { 75904007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 76004007ebaSmrg "Couldn't register the resources.\n"); 76104007ebaSmrg return FALSE; 762f29dbc25Smrg } 763f29dbc25Smrg#endif 764f29dbc25Smrg return TRUE; 765f29dbc25Smrg} 766f29dbc25Smrg 767f29dbc25Smrgstatic void 768f29dbc25SmrgGXRestore(ScrnInfoPtr pScrni) 769f29dbc25Smrg{ 770f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 771f29dbc25Smrg 772f29dbc25Smrg if (pGeode->useVGA && pGeode->FBVGAActive) { 77304007ebaSmrg vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 774f29dbc25Smrg 77504007ebaSmrg vgaHWProtect(pScrni, TRUE); 77604007ebaSmrg vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL); 77704007ebaSmrg vgaHWProtect(pScrni, FALSE); 778f29dbc25Smrg } 779f29dbc25Smrg} 780f29dbc25Smrg 781f29dbc25Smrgstatic Bool 782f29dbc25SmrgGXUnmapMem(ScrnInfoPtr pScrni) 783f29dbc25Smrg{ 784f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 785f29dbc25Smrg 786f29dbc25Smrg /* unmap all the memory map's */ 7877f419768Smrg#ifndef XSERVER_LIBPCIACCESS 788f29dbc25Smrg xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_regptr, GX_CPU_REG_SIZE); 789f29dbc25Smrg xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_gpptr, GX_GP_REG_SIZE); 790f29dbc25Smrg xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_vidptr, GX_VID_REG_SIZE); 791f29dbc25Smrg xf86UnMapVidMem(pScrni->scrnIndex, gfx_virt_fbptr, pGeode->FBAvail); 7927f419768Smrg#else 7937f419768Smrg pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index); 7947f419768Smrg 7957f419768Smrg unmap_pci_mem(pScrni, pci, gfx_virt_regptr, GX_CPU_REG_SIZE); 7967f419768Smrg unmap_pci_mem(pScrni, pci, gfx_virt_gpptr, GX_GP_REG_SIZE); 7977f419768Smrg unmap_pci_mem(pScrni, pci, gfx_virt_vidptr, GX_VID_REG_SIZE); 7987f419768Smrg unmap_pci_mem(pScrni, pci, gfx_virt_fbptr, pGeode->FBAvail); 7997f419768Smrg 8007f419768Smrg munmap(XpressROMPtr, 0x10000); 8017f419768Smrg#endif 802f29dbc25Smrg return TRUE; 803f29dbc25Smrg} 804f29dbc25Smrg 805f29dbc25Smrgstatic void 806f29dbc25SmrgGXSetDvLineSize(unsigned int pitch) 807f29dbc25Smrg{ 808f29dbc25Smrg unsigned long temp, dv_size = MDC_DV_LINE_SIZE_1024; 809f29dbc25Smrg 810f29dbc25Smrg if (pitch > 1024) { 81104007ebaSmrg dv_size = MDC_DV_LINE_SIZE_2048; 812f29dbc25Smrg } 813f29dbc25Smrg if (pitch > 2048) { 81404007ebaSmrg dv_size = MDC_DV_LINE_SIZE_4096; 815f29dbc25Smrg } 816f29dbc25Smrg if (pitch > 4096) { 81704007ebaSmrg dv_size = MDC_DV_LINE_SIZE_8192; 818f29dbc25Smrg } 819f29dbc25Smrg 820f29dbc25Smrg /* WRITE DIRTY/VALID CONTROL WITH LINE LENGTH */ 821f29dbc25Smrg 822f29dbc25Smrg temp = READ_REG32(MDC_DV_CTL); 823f29dbc25Smrg WRITE_REG32(MDC_DV_CTL, (temp & ~MDC_DV_LINE_SIZE_MASK) | dv_size); 824f29dbc25Smrg} 825f29dbc25Smrg 826f29dbc25Smrg/* XXX - this is nothing like the original function - not sure exactly what the purpose is for this quite yet */ 827f29dbc25Smrg 828f29dbc25Smrgstatic void 82904007ebaSmrgGXAdjustFrame(ADJUST_FRAME_ARGS_DECL) 830f29dbc25Smrg{ 83104007ebaSmrg SCRN_INFO_PTR(arg); 832f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 833f29dbc25Smrg unsigned long offset; 834f29dbc25Smrg 835f29dbc25Smrg offset = y * pGeode->Pitch + x * (pScrni->bitsPerPixel >> 3); 836f29dbc25Smrg 837f29dbc25Smrg gfx_set_display_offset(offset); 838f29dbc25Smrg} 839f29dbc25Smrg 840f29dbc25Smrgstatic Bool 841f29dbc25SmrgGXSetVideoMode(ScrnInfoPtr pScrni, DisplayModePtr pMode) 842f29dbc25Smrg{ 843f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 844f29dbc25Smrg int flags = 0; 845f29dbc25Smrg int custom = 0; 846f29dbc25Smrg 847f29dbc25Smrg pScrni->vtSema = TRUE; 848f29dbc25Smrg 849f29dbc25Smrg gx_disable_dac_power(); 850f29dbc25Smrg 851f29dbc25Smrg if (pMode->Flags & V_NHSYNC) 85204007ebaSmrg flags |= 1; 853f29dbc25Smrg if (pMode->Flags & V_NVSYNC) 85404007ebaSmrg flags |= 2; 855f29dbc25Smrg 856f29dbc25Smrg /* Check to see if we should use custom or built-in timings */ 857f29dbc25Smrg 858f29dbc25Smrg if (pGeode->Panel) 85904007ebaSmrg custom = (pMode->type & M_T_USERDEF); 860f29dbc25Smrg else 86104007ebaSmrg custom = !(pMode->type & (M_T_BUILTIN | M_T_DEFAULT)); 862f29dbc25Smrg 863f29dbc25Smrg /* If we're not doing a custom mode, then just set the fixed timings, 864f29dbc25Smrg * otherwise, do the whole shooting match */ 865f29dbc25Smrg 866f29dbc25Smrg if (!custom) { 86704007ebaSmrg GFX(set_fixed_timings(pGeode->PanelX, pGeode->PanelY, 86804007ebaSmrg pMode->CrtcHDisplay, pMode->CrtcVDisplay, 86904007ebaSmrg pScrni->bitsPerPixel)); 87004007ebaSmrg } 87104007ebaSmrg else { 87204007ebaSmrg if (pGeode->Panel) 87304007ebaSmrg GFX(set_panel_present(pGeode->PanelX, pGeode->PanelY, 87404007ebaSmrg pMode->CrtcHDisplay, pMode->CrtcVDisplay, 87504007ebaSmrg pScrni->bitsPerPixel)); 87604007ebaSmrg 87704007ebaSmrg GFX(set_display_timings(pScrni->bitsPerPixel, flags, 87804007ebaSmrg pMode->CrtcHDisplay, pMode->CrtcHBlankStart, 87904007ebaSmrg pMode->CrtcHSyncStart, pMode->CrtcHSyncEnd, 88004007ebaSmrg pMode->CrtcHBlankEnd, pMode->CrtcHTotal, 88104007ebaSmrg pMode->CrtcVDisplay, pMode->CrtcVBlankStart, 88204007ebaSmrg pMode->CrtcVSyncStart, pMode->CrtcVSyncEnd, 88304007ebaSmrg pMode->CrtcVBlankEnd, pMode->CrtcVTotal, 88404007ebaSmrg (int) ((pMode->SynthClock / 1000.0) * 88504007ebaSmrg 0x10000))); 886f29dbc25Smrg } 887f29dbc25Smrg 888f29dbc25Smrg GFX(set_crt_enable(CRT_ENABLE)); 889f29dbc25Smrg GFX(set_display_pitch(pGeode->displayPitch)); 890f29dbc25Smrg GFX(set_display_offset(0L)); 891f29dbc25Smrg GFX(wait_vertical_blank()); 892f29dbc25Smrg 893f29dbc25Smrg if (pGeode->Compression) { 89404007ebaSmrg GXSetDvLineSize(pGeode->Pitch); 895f29dbc25Smrg 89604007ebaSmrg gfx_set_compression_offset(pGeode->CBData.compression_offset); 89704007ebaSmrg gfx_set_compression_pitch(GX_CB_PITCH); 89804007ebaSmrg gfx_set_compression_size(GX_CB_SIZE); 899f29dbc25Smrg 90004007ebaSmrg gfx_set_compression_enable(1); 901f29dbc25Smrg } 902f29dbc25Smrg 903f29dbc25Smrg if (pGeode->HWCursor && !(pMode->Flags & V_DBLSCAN)) { 90404007ebaSmrg GXLoadCursorImage(pScrni, NULL); 90504007ebaSmrg GFX(set_cursor_position(pGeode->CursorStartOffset, 0, 0, 0, 0)); 90604007ebaSmrg GXShowCursor(pScrni); 90704007ebaSmrg } 90804007ebaSmrg else { 90904007ebaSmrg GFX(set_cursor_enable(0)); 91004007ebaSmrg pGeode->HWCursor = FALSE; 911f29dbc25Smrg } 912f29dbc25Smrg 91304007ebaSmrg GXAdjustFrame(ADJUST_FRAME_ARGS(pScrni->frameX0, pScrni->frameY0)); 914f29dbc25Smrg gx_enable_dac_power(); 915f29dbc25Smrg 916f29dbc25Smrg return TRUE; 917f29dbc25Smrg} 918f29dbc25Smrg 919f29dbc25Smrgstatic Bool 92004007ebaSmrgGXSwitchMode(SWITCH_MODE_ARGS_DECL) 921f29dbc25Smrg{ 92204007ebaSmrg SCRN_INFO_PTR(arg); 923f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 924f29dbc25Smrg int ret = TRUE; 925f29dbc25Smrg int rotate; 926f29dbc25Smrg 927f29dbc25Smrg /* Syn the engine and shutdown the DAC momentarily */ 928f29dbc25Smrg 929f29dbc25Smrg gfx_wait_until_idle(); 930f29dbc25Smrg 931f29dbc25Smrg /* Set up the memory for the new mode */ 932f29dbc25Smrg rotate = GXGetRotation(pScrni->pScreen); 933f29dbc25Smrg ret = GXAllocateMemory(pScrni->pScreen, pScrni, rotate); 934f29dbc25Smrg 935f29dbc25Smrg if (ret) { 93604007ebaSmrg if (pGeode->curMode != pMode) 93704007ebaSmrg ret = GXSetVideoMode(pScrni, pMode); 938f29dbc25Smrg } 939f29dbc25Smrg 940f29dbc25Smrg if (ret) 94104007ebaSmrg ret = GXRotate(pScrni, pMode); 942f29dbc25Smrg 943f29dbc25Smrg /* Go back the way it was */ 944f29dbc25Smrg 945f29dbc25Smrg if (ret == FALSE) { 94604007ebaSmrg if (!GXSetVideoMode(pScrni, pGeode->curMode)) 94704007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 94804007ebaSmrg "Could not restore the previous mode\n"); 94904007ebaSmrg } 95004007ebaSmrg else 95104007ebaSmrg pGeode->curMode = pMode; 952f29dbc25Smrg 953f29dbc25Smrg return ret; 954f29dbc25Smrg} 955f29dbc25Smrg 956f29dbc25Smrgstatic void 957f29dbc25SmrgGXLeaveGraphics(ScrnInfoPtr pScrni) 958f29dbc25Smrg{ 959f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 960f29dbc25Smrg 961f29dbc25Smrg gfx_wait_until_idle(); 962f29dbc25Smrg 963f29dbc25Smrg /* Restore VG registers */ 964f29dbc25Smrg gfx_set_display_timings(pGeode->FBgfxdisplaytiming.wBpp, 96504007ebaSmrg pGeode->FBgfxdisplaytiming.wPolarity, 96604007ebaSmrg pGeode->FBgfxdisplaytiming.wHActive, 96704007ebaSmrg pGeode->FBgfxdisplaytiming.wHBlankStart, 96804007ebaSmrg pGeode->FBgfxdisplaytiming.wHSyncStart, 96904007ebaSmrg pGeode->FBgfxdisplaytiming.wHSyncEnd, 97004007ebaSmrg pGeode->FBgfxdisplaytiming.wHBlankEnd, 97104007ebaSmrg pGeode->FBgfxdisplaytiming.wHTotal, 97204007ebaSmrg pGeode->FBgfxdisplaytiming.wVActive, 97304007ebaSmrg pGeode->FBgfxdisplaytiming.wVBlankStart, 97404007ebaSmrg pGeode->FBgfxdisplaytiming.wVSyncStart, 97504007ebaSmrg pGeode->FBgfxdisplaytiming.wVSyncEnd, 97604007ebaSmrg pGeode->FBgfxdisplaytiming.wVBlankEnd, 97704007ebaSmrg pGeode->FBgfxdisplaytiming.wVTotal, 97804007ebaSmrg pGeode->FBgfxdisplaytiming.dwDotClock); 979f29dbc25Smrg 980f29dbc25Smrg gfx_set_compression_enable(0); 981f29dbc25Smrg 982f29dbc25Smrg /* Restore the previous Compression state */ 983f29dbc25Smrg if (pGeode->FBCompressionEnable) { 98404007ebaSmrg gfx_set_compression_offset(pGeode->FBCompressionOffset); 98504007ebaSmrg gfx_set_compression_pitch(pGeode->FBCompressionPitch); 98604007ebaSmrg gfx_set_compression_size(pGeode->FBCompressionSize); 98704007ebaSmrg gfx_set_compression_enable(1); 988f29dbc25Smrg } 989f29dbc25Smrg 990f29dbc25Smrg gfx_set_display_pitch(pGeode->FBgfxdisplaytiming.wPitch); 991f29dbc25Smrg 992f29dbc25Smrg gfx_set_display_offset(pGeode->FBDisplayOffset); 993f29dbc25Smrg 994f29dbc25Smrg /* Restore Cursor */ 995f29dbc25Smrg gfx_set_cursor_position(pGeode->FBCursorOffset, 0, 0, 0, 0); 996f29dbc25Smrg 997f29dbc25Smrg if (pGeode->useVGA) { 99804007ebaSmrg pGeode->vesa->pInt->num = 0x10; 99904007ebaSmrg pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode; 100004007ebaSmrg pGeode->vesa->pInt->bx = 0; 100104007ebaSmrg xf86ExecX86int10(pGeode->vesa->pInt); 100204007ebaSmrg gfx_delay_milliseconds(3); 1003f29dbc25Smrg } 1004f29dbc25Smrg 1005f29dbc25Smrg GXRestore(pScrni); 1006f29dbc25Smrg 1007f29dbc25Smrg gx_enable_dac_power(); 1008f29dbc25Smrg} 1009f29dbc25Smrg 1010f29dbc25Smrgstatic Bool 101104007ebaSmrgGXCloseScreen(CLOSE_SCREEN_ARGS_DECL) 1012f29dbc25Smrg{ 101304007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 1014f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 1015f29dbc25Smrg 1016f29dbc25Smrg if (pScrni->vtSema) 101704007ebaSmrg GXLeaveGraphics(pScrni); 1018f29dbc25Smrg 101904007ebaSmrg#ifdef XF86XAA 1020f29dbc25Smrg if (pGeode->AccelInfoRec) 102104007ebaSmrg XAADestroyInfoRec(pGeode->AccelInfoRec); 102204007ebaSmrg#endif 1023f29dbc25Smrg 1024f29dbc25Smrg if (pGeode->AccelImageWriteBuffers) { 102504007ebaSmrg free(pGeode->AccelImageWriteBuffers[0]); 102604007ebaSmrg free(pGeode->AccelImageWriteBuffers); 102704007ebaSmrg pGeode->AccelImageWriteBuffers = NULL; 1028f29dbc25Smrg } 1029f29dbc25Smrg 1030f29dbc25Smrg if (pGeode->AccelColorExpandBuffers) { 103104007ebaSmrg free(pGeode->AccelColorExpandBuffers); 103204007ebaSmrg pGeode->AccelColorExpandBuffers = NULL; 1033f29dbc25Smrg } 1034f29dbc25Smrg 1035f29dbc25Smrg if (pGeode->pExa) { 103604007ebaSmrg exaDriverFini(pScrn); 103704007ebaSmrg free(pGeode->pExa); 103804007ebaSmrg pGeode->pExa = NULL; 1039f29dbc25Smrg } 1040f29dbc25Smrg 1041f29dbc25Smrg pScrni->vtSema = FALSE; 1042f29dbc25Smrg 1043f29dbc25Smrg GXUnmapMem(pScrni); 1044f29dbc25Smrg 1045f29dbc25Smrg pScrni->PointerMoved = pGeode->PointerMoved; 1046f29dbc25Smrg pScrn->CloseScreen = pGeode->CloseScreen; 1047f29dbc25Smrg 1048f29dbc25Smrg if (pScrn->CloseScreen) 104904007ebaSmrg return (*pScrn->CloseScreen) (CLOSE_SCREEN_ARGS); 1050f29dbc25Smrg 1051f29dbc25Smrg return TRUE; 1052f29dbc25Smrg} 1053f29dbc25Smrg 1054f29dbc25Smrgstatic Bool 1055f29dbc25SmrgGXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni) 1056f29dbc25Smrg{ 1057f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 1058f29dbc25Smrg 1059f29dbc25Smrg if (!GXMapMem(pScrni)) 106004007ebaSmrg return FALSE; 1061f29dbc25Smrg 1062f29dbc25Smrg if (pGeode->useVGA) 106304007ebaSmrg pGeode->FBVGAActive = gu2_get_vga_active(); 1064f29dbc25Smrg 1065f29dbc25Smrg gfx_wait_until_idle(); 1066f29dbc25Smrg 1067f29dbc25Smrg /* Save off the current state (should this be somewhere else)? */ 1068f29dbc25Smrg 1069f29dbc25Smrg pGeode->FBgfxdisplaytiming.dwDotClock = gfx_get_clock_frequency(); 1070f29dbc25Smrg pGeode->FBgfxdisplaytiming.wPitch = gfx_get_display_pitch(); 1071f29dbc25Smrg pGeode->FBgfxdisplaytiming.wBpp = gfx_get_display_bpp(); 1072f29dbc25Smrg pGeode->FBgfxdisplaytiming.wHTotal = gfx_get_htotal(); 1073f29dbc25Smrg pGeode->FBgfxdisplaytiming.wHActive = gfx_get_hactive(); 1074f29dbc25Smrg pGeode->FBgfxdisplaytiming.wHSyncStart = gfx_get_hsync_start(); 1075f29dbc25Smrg pGeode->FBgfxdisplaytiming.wHSyncEnd = gfx_get_hsync_end(); 1076f29dbc25Smrg pGeode->FBgfxdisplaytiming.wHBlankStart = gfx_get_hblank_start(); 1077f29dbc25Smrg pGeode->FBgfxdisplaytiming.wHBlankEnd = gfx_get_hblank_end(); 1078f29dbc25Smrg pGeode->FBgfxdisplaytiming.wVTotal = gfx_get_vtotal(); 1079f29dbc25Smrg pGeode->FBgfxdisplaytiming.wVActive = gfx_get_vactive(); 1080f29dbc25Smrg pGeode->FBgfxdisplaytiming.wVSyncStart = gfx_get_vsync_start(); 1081f29dbc25Smrg pGeode->FBgfxdisplaytiming.wVSyncEnd = gfx_get_vsync_end(); 1082f29dbc25Smrg pGeode->FBgfxdisplaytiming.wVBlankStart = gfx_get_vblank_start(); 1083f29dbc25Smrg pGeode->FBgfxdisplaytiming.wVBlankEnd = gfx_get_vblank_end(); 1084f29dbc25Smrg pGeode->FBgfxdisplaytiming.wPolarity = gfx_get_sync_polarities(); 1085f29dbc25Smrg 1086f29dbc25Smrg pGeode->FBDisplayOffset = gfx_get_display_offset(); 1087f29dbc25Smrg 1088f29dbc25Smrg if (pGeode->useVGA) { 108904007ebaSmrg vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 1090f29dbc25Smrg 109104007ebaSmrg pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040); 1092f29dbc25Smrg } 1093f29dbc25Smrg 1094f29dbc25Smrg pGeode->FBCompressionEnable = gfx_get_compression_enable(); 1095f29dbc25Smrg pGeode->FBCompressionOffset = gfx_get_compression_offset(); 1096f29dbc25Smrg pGeode->FBCompressionPitch = gfx_get_compression_pitch(); 1097f29dbc25Smrg pGeode->FBCompressionSize = gfx_get_compression_size(); 1098f29dbc25Smrg 1099f29dbc25Smrg#ifdef PNL_SUP 1100f29dbc25Smrg Pnl_SavePanelState(); 1101f29dbc25Smrg#endif 1102f29dbc25Smrg 1103f29dbc25Smrg /* Turn off the VGA */ 1104f29dbc25Smrg 1105f29dbc25Smrg if (pGeode->useVGA && pGeode->FBVGAActive) { 110604007ebaSmrg unsigned short sequencer; 110704007ebaSmrg vgaHWPtr pvgaHW = VGAHWPTR(pScrni); 1108f29dbc25Smrg 110904007ebaSmrg /* Map VGA aperture */ 111004007ebaSmrg if (!vgaHWMapMem(pScrni)) 111104007ebaSmrg return FALSE; 1112f29dbc25Smrg 111304007ebaSmrg /* Unlock VGA registers */ 111404007ebaSmrg vgaHWUnlock(pvgaHW); 1115f29dbc25Smrg 111604007ebaSmrg /* Save the current state and setup the current mode */ 111704007ebaSmrg vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL); 1118f29dbc25Smrg 111904007ebaSmrg /* DISABLE VGA SEQUENCER */ 112004007ebaSmrg /* This allows the VGA state machine to terminate. We must delay */ 112104007ebaSmrg /* such that there are no pending MBUS requests. */ 1122f29dbc25Smrg 112304007ebaSmrg gfx_outb(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_CLK_MODE); 112404007ebaSmrg sequencer = gfx_inb(MDC_SEQUENCER_DATA); 112504007ebaSmrg sequencer |= MDC_CLK_MODE_SCREEN_OFF; 112604007ebaSmrg gfx_outb(MDC_SEQUENCER_DATA, sequencer); 1127f29dbc25Smrg 112804007ebaSmrg gfx_delay_milliseconds(1); 1129f29dbc25Smrg 113004007ebaSmrg /* BLANK THE VGA DISPLAY */ 113104007ebaSmrg gfx_outw(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_RESET); 113204007ebaSmrg sequencer = gfx_inb(MDC_SEQUENCER_DATA); 113304007ebaSmrg sequencer &= ~MDC_RESET_VGA_DISP_ENABLE; 113404007ebaSmrg gfx_outb(MDC_SEQUENCER_DATA, sequencer); 1135f29dbc25Smrg 113604007ebaSmrg gfx_delay_milliseconds(1); 1137f29dbc25Smrg } 1138f29dbc25Smrg 1139f29dbc25Smrg /* Set up the memory */ 1140c744f008Smrg /* XXX - FIXME - when we allow initial rotation, it should be here */ 1141f29dbc25Smrg GXAllocateMemory(pScrn, pScrni, pGeode->rotation); 1142f29dbc25Smrg 1143f29dbc25Smrg /* Clear the framebuffer */ 1144f29dbc25Smrg memset(pGeode->FBBase + pGeode->displayOffset, 0, pGeode->displaySize); 1145f29dbc25Smrg 1146f29dbc25Smrg /* Set up the video mode */ 1147f29dbc25Smrg GXSetVideoMode(pScrni, pScrni->currentMode); 1148f29dbc25Smrg pGeode->curMode = pScrni->currentMode; 1149f29dbc25Smrg 1150f29dbc25Smrg return TRUE; 1151f29dbc25Smrg} 1152f29dbc25Smrg 1153f29dbc25Smrgstatic void 1154f29dbc25SmrgGXLoadPalette(ScrnInfoPtr pScrni, 115504007ebaSmrg int numColors, int *indizes, LOCO * colors, VisualPtr pVisual) 1156f29dbc25Smrg{ 1157f29dbc25Smrg int i, index, color; 1158f29dbc25Smrg 1159f29dbc25Smrg for (i = 0; i < numColors; i++) { 116004007ebaSmrg index = indizes[i] & 0xFF; 116104007ebaSmrg color = (((unsigned long) (colors[index].red & 0xFF)) << 16) | 116204007ebaSmrg (((unsigned long) (colors[index].green & 0xFF)) << 8) | 116304007ebaSmrg ((unsigned long) (colors[index].blue & 0xFF)); 1164f29dbc25Smrg 116504007ebaSmrg GFX(set_display_palette_entry(index, color)); 1166f29dbc25Smrg } 1167f29dbc25Smrg} 1168f29dbc25Smrg 1169f29dbc25Smrg#ifdef DPMSExtension 1170f29dbc25Smrgstatic void 1171f29dbc25SmrgGXPanelPower(int enable) 1172f29dbc25Smrg{ 1173f29dbc25Smrg unsigned long power = READ_VID32(RCDF_POWER_MANAGEMENT); 1174f29dbc25Smrg 1175f29dbc25Smrg if (enable != 0) 117604007ebaSmrg power |= RCDF_PM_PANEL_POWER_ON; 1177f29dbc25Smrg else 117804007ebaSmrg power &= ~RCDF_PM_PANEL_POWER_ON; 1179f29dbc25Smrg 1180f29dbc25Smrg WRITE_VID32(RCDF_POWER_MANAGEMENT, power); 1181f29dbc25Smrg} 1182f29dbc25Smrg 1183f29dbc25Smrgstatic void 1184f29dbc25SmrgGXDPMSSet(ScrnInfoPtr pScrni, int mode, int flags) 1185f29dbc25Smrg{ 1186f29dbc25Smrg GeodeRec *pGeode; 1187f29dbc25Smrg 1188f29dbc25Smrg pGeode = GEODEPTR(pScrni); 1189f29dbc25Smrg 1190f29dbc25Smrg if (!pScrni->vtSema) 119104007ebaSmrg return; 1192f29dbc25Smrg 1193f29dbc25Smrg switch (mode) { 1194f29dbc25Smrg case DPMSModeOn: 119504007ebaSmrg /* Screen: On; HSync: On; VSync: On */ 119604007ebaSmrg GFX(set_crt_enable(CRT_ENABLE)); 1197f29dbc25Smrg#if defined(PNL_SUP) 119804007ebaSmrg if (pGeode->Panel) { 119904007ebaSmrg Pnl_PowerUp(); 120004007ebaSmrg GXPanelPower(1); 120104007ebaSmrg } 1202f29dbc25Smrg#endif 120304007ebaSmrg break; 1204f29dbc25Smrg 1205f29dbc25Smrg case DPMSModeStandby: 120604007ebaSmrg /* Screen: Off; HSync: Off; VSync: On */ 120704007ebaSmrg GFX(set_crt_enable(CRT_STANDBY)); 1208f29dbc25Smrg#if defined(PNL_SUP) 120904007ebaSmrg if (pGeode->Panel) { 121004007ebaSmrg Pnl_PowerDown(); 121104007ebaSmrg GXPanelPower(0); 121204007ebaSmrg } 1213f29dbc25Smrg#endif 121404007ebaSmrg break; 1215f29dbc25Smrg 1216f29dbc25Smrg case DPMSModeSuspend: 121704007ebaSmrg /* Screen: Off; HSync: On; VSync: Off */ 121804007ebaSmrg GFX(set_crt_enable(CRT_SUSPEND)); 1219f29dbc25Smrg#if defined(PNL_SUP) 122004007ebaSmrg if (pGeode->Panel) { 122104007ebaSmrg Pnl_PowerDown(); 122204007ebaSmrg GXPanelPower(0); 122304007ebaSmrg } 1224f29dbc25Smrg#endif 122504007ebaSmrg break; 1226f29dbc25Smrg 1227f29dbc25Smrg case DPMSModeOff: 122804007ebaSmrg /* Screen: Off; HSync: Off; VSync: Off */ 122904007ebaSmrg GFX(set_crt_enable(CRT_DISABLE)); 1230f29dbc25Smrg#if defined(PNL_SUP) 123104007ebaSmrg if (pGeode->Panel) { 123204007ebaSmrg Pnl_PowerDown(); 123304007ebaSmrg GXPanelPower(0); 123404007ebaSmrg } 1235f29dbc25Smrg#endif 123604007ebaSmrg break; 1237f29dbc25Smrg } 1238f29dbc25Smrg} 1239f29dbc25Smrg#endif 1240f29dbc25Smrg 1241f29dbc25Smrgstatic Bool 1242f29dbc25SmrgGXCreateScreenResources(ScreenPtr pScreen) 1243f29dbc25Smrg{ 124404007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen); 1245f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 1246f29dbc25Smrg 1247f29dbc25Smrg pScreen->CreateScreenResources = pGeode->CreateScreenResources; 1248f29dbc25Smrg if (!(*pScreen->CreateScreenResources) (pScreen)) 124904007ebaSmrg return FALSE; 1250f29dbc25Smrg 1251f29dbc25Smrg if (xf86LoaderCheckSymbol("GXRandRSetConfig") 125204007ebaSmrg && pGeode->rotation != RR_Rotate_0) { 125304007ebaSmrg Rotation(*GXRandRSetConfig) (ScreenPtr pScreen, Rotation rr, int rate, 125404007ebaSmrg RRScreenSizePtr pSize) = NULL; 1255f29dbc25Smrg 125604007ebaSmrg RRScreenSize p; 125704007ebaSmrg Rotation requestedRotation = pGeode->rotation; 1258f29dbc25Smrg 125904007ebaSmrg pGeode->rotation = RR_Rotate_0; 1260f29dbc25Smrg 126104007ebaSmrg /* Just setup enough for an initial rotate */ 1262f29dbc25Smrg 126304007ebaSmrg p.width = pScreen->width; 126404007ebaSmrg p.height = pScreen->height; 126504007ebaSmrg p.mmWidth = pScreen->mmWidth; 126604007ebaSmrg p.mmHeight = pScreen->mmHeight; 1267f29dbc25Smrg 126804007ebaSmrg GXRandRSetConfig = LoaderSymbol("GXRandRSetConfig"); 126904007ebaSmrg if (GXRandRSetConfig) { 127004007ebaSmrg pGeode->starting = TRUE; 127104007ebaSmrg (*GXRandRSetConfig) (pScreen, requestedRotation, 0, &p); 127204007ebaSmrg pGeode->starting = FALSE; 127304007ebaSmrg } 1274f29dbc25Smrg } 1275f29dbc25Smrg 1276f29dbc25Smrg return TRUE; 1277f29dbc25Smrg} 1278f29dbc25Smrg 1279f29dbc25Smrgstatic Bool 128004007ebaSmrgGXScreenInit(SCREEN_INIT_ARGS_DECL) 1281f29dbc25Smrg{ 128204007ebaSmrg ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 1283f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 1284f29dbc25Smrg XF86ModReqInfo shadowReq; 1285f29dbc25Smrg int maj, min, ret, rotate; 1286f29dbc25Smrg 1287f29dbc25Smrg pGeode->starting = TRUE; 1288f29dbc25Smrg 1289f29dbc25Smrg /* If we are using VGA then go ahead and map the memory */ 1290f29dbc25Smrg 1291f29dbc25Smrg if (pGeode->useVGA) { 1292f29dbc25Smrg 129304007ebaSmrg if (!vgaHWMapMem(pScrni)) 129404007ebaSmrg return FALSE; 1295f29dbc25Smrg 129604007ebaSmrg vgaHWGetIOBase(VGAHWPTR(pScrni)); 1297f29dbc25Smrg } 1298f29dbc25Smrg 1299f29dbc25Smrg if (!pGeode->NoAccel) { 1300f29dbc25Smrg 130104007ebaSmrg if (pGeode->useEXA) { 130204007ebaSmrg 130304007ebaSmrg if (!(pGeode->pExa = exaDriverAlloc())) { 130404007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 130504007ebaSmrg "Couldn't allocate the EXA structure.\n"); 130604007ebaSmrg pGeode->NoAccel = TRUE; 130704007ebaSmrg } 130804007ebaSmrg else { 130904007ebaSmrg ExaDriverPtr pExa = pGeode->pExa; 131004007ebaSmrg 131104007ebaSmrg /* THis is set in GXAllocMem */ 131204007ebaSmrg pExa->memoryBase = 0; 131304007ebaSmrg 131404007ebaSmrg /* This is set in GXAllocateMemory */ 131504007ebaSmrg pExa->memorySize = 0; 131604007ebaSmrg 131704007ebaSmrg pExa->pixmapOffsetAlign = 32; 131804007ebaSmrg pExa->pixmapPitchAlign = 32; 131904007ebaSmrg pExa->flags = EXA_OFFSCREEN_PIXMAPS; 132004007ebaSmrg pExa->maxX = GX_MAX_WIDTH - 1; 132104007ebaSmrg pExa->maxY = GX_MAX_HEIGHT - 1; 132204007ebaSmrg } 132304007ebaSmrg } 132404007ebaSmrg else { 132504007ebaSmrg pGeode->AccelImageWriteBuffers = 132604007ebaSmrg calloc(pGeode->NoOfImgBuffers, 132704007ebaSmrg sizeof(pGeode->AccelImageWriteBuffers[0])); 132804007ebaSmrg pGeode->AccelColorExpandBuffers = 132904007ebaSmrg calloc(pGeode->NoOfColorExpandLines, 133004007ebaSmrg sizeof(pGeode->AccelColorExpandBuffers[0])); 133104007ebaSmrg } 1332f29dbc25Smrg } 1333f29dbc25Smrg 1334f29dbc25Smrg /* XXX FIXME - Take down any of the structures on failure? */ 1335f29dbc25Smrg 1336f29dbc25Smrg if (!GXEnterGraphics(pScrn, pScrni)) 133704007ebaSmrg return FALSE; 1338f29dbc25Smrg 1339f29dbc25Smrg miClearVisualTypes(); 1340f29dbc25Smrg 1341f29dbc25Smrg /* XXX Again - take down anything? */ 1342f29dbc25Smrg 1343f29dbc25Smrg if (pScrni->bitsPerPixel > 8) { 134404007ebaSmrg if (!miSetVisualTypes(pScrni->depth, 134504007ebaSmrg TrueColorMask, pScrni->rgbBits, 134604007ebaSmrg pScrni->defaultVisual)) { 134704007ebaSmrg return FALSE; 134804007ebaSmrg } 134904007ebaSmrg } 135004007ebaSmrg else { 135104007ebaSmrg if (!miSetVisualTypes(pScrni->depth, 135204007ebaSmrg miGetDefaultVisualMask(pScrni->depth), 135304007ebaSmrg pScrni->rgbBits, pScrni->defaultVisual)) { 135404007ebaSmrg return FALSE; 135504007ebaSmrg } 1356f29dbc25Smrg } 1357f29dbc25Smrg 1358f29dbc25Smrg miSetPixmapDepths(); 1359f29dbc25Smrg 1360f29dbc25Smrg /* Point at the visible area to start */ 1361f29dbc25Smrg 1362f29dbc25Smrg ret = fbScreenInit(pScrn, pGeode->FBBase + pGeode->displayOffset, 136304007ebaSmrg pScrni->virtualX, pScrni->virtualY, 136404007ebaSmrg pScrni->xDpi, pScrni->yDpi, pGeode->displayWidth, 136504007ebaSmrg pScrni->bitsPerPixel); 1366f29dbc25Smrg 1367f29dbc25Smrg if (!ret) 136804007ebaSmrg return FALSE; 1369f29dbc25Smrg 1370f29dbc25Smrg xf86SetBlackWhitePixels(pScrn); 1371f29dbc25Smrg 1372f29dbc25Smrg /* Set up the color ordering */ 1373f29dbc25Smrg 1374f29dbc25Smrg if (pScrni->bitsPerPixel > 8) { 137504007ebaSmrg VisualPtr visual = pScrn->visuals + pScrn->numVisuals; 137604007ebaSmrg 137704007ebaSmrg while (--visual >= pScrn->visuals) { 137804007ebaSmrg if ((visual->class | DynamicClass) == DirectColor) { 137904007ebaSmrg visual->offsetRed = pScrni->offset.red; 138004007ebaSmrg visual->offsetGreen = pScrni->offset.green; 138104007ebaSmrg visual->offsetBlue = pScrni->offset.blue; 138204007ebaSmrg visual->redMask = pScrni->mask.red; 138304007ebaSmrg visual->greenMask = pScrni->mask.green; 138404007ebaSmrg visual->blueMask = pScrni->mask.blue; 138504007ebaSmrg } 138604007ebaSmrg } 1387f29dbc25Smrg } 1388f29dbc25Smrg 1389f29dbc25Smrg /* Must follow the color ordering */ 1390f29dbc25Smrg fbPictureInit(pScrn, 0, 0); 1391f29dbc25Smrg 1392f29dbc25Smrg if (!pGeode->NoAccel) 139304007ebaSmrg GXAccelInit(pScrn); 1394f29dbc25Smrg 1395f29dbc25Smrg xf86SetBackingStore(pScrn); 1396f29dbc25Smrg 1397f29dbc25Smrg /* Set up the soft cursor */ 1398f29dbc25Smrg miDCInitialize(pScrn, xf86GetPointerScreenFuncs()); 1399f29dbc25Smrg 1400f29dbc25Smrg /* Set up the HW cursor - must follow the soft cursor init */ 1401f29dbc25Smrg 1402f29dbc25Smrg if (pGeode->tryHWCursor) { 140304007ebaSmrg if (!GXHWCursorInit(pScrn)) 140404007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 140504007ebaSmrg "Hardware cursor initialization failed.\n"); 1406f29dbc25Smrg } 1407f29dbc25Smrg 1408f29dbc25Smrg /* Set up the color map */ 1409f29dbc25Smrg 1410f29dbc25Smrg if (!miCreateDefColormap(pScrn)) 141104007ebaSmrg return FALSE; 1412f29dbc25Smrg 1413f29dbc25Smrg if (pScrni->bitsPerPixel == 8) { 141404007ebaSmrg /* Must follow initialization of the default colormap */ 1415f29dbc25Smrg 141604007ebaSmrg if (!xf86HandleColormaps(pScrn, 256, 8, 141704007ebaSmrg GXLoadPalette, NULL, 141804007ebaSmrg CMAP_PALETTED_TRUECOLOR | 141904007ebaSmrg CMAP_RELOAD_ON_MODE_SWITCH)) { 142004007ebaSmrg return FALSE; 142104007ebaSmrg } 1422f29dbc25Smrg } 1423f29dbc25Smrg#ifdef DPMSExtension 1424f29dbc25Smrg xf86DPMSInit(pScrn, GXDPMSSet, 0); 1425f29dbc25Smrg#endif 1426f29dbc25Smrg 1427f29dbc25Smrg GXInitVideo(pScrn); 1428f29dbc25Smrg 1429f29dbc25Smrg /* Set up RandR */ 1430f29dbc25Smrg 14315748e6ecSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 24 143204007ebaSmrg xf86DisableRandR(); /* We provide our own RandR goodness */ 143346edf8f1Smrg#endif 1434f29dbc25Smrg 1435f29dbc25Smrg /* Try to set up the shadow FB for rotation */ 1436f29dbc25Smrg 1437f29dbc25Smrg memset(&shadowReq, 0, sizeof(shadowReq)); 1438f29dbc25Smrg shadowReq.majorversion = 1; 1439f29dbc25Smrg shadowReq.minorversion = 1; 1440f29dbc25Smrg 1441f29dbc25Smrg if (LoadSubModule(pScrni->module, "shadow", 144204007ebaSmrg NULL, NULL, NULL, &shadowReq, &maj, &min)) { 1443f29dbc25Smrg 144404007ebaSmrg rotate = RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270; 144504007ebaSmrg shadowSetup(pScrn); 144604007ebaSmrg } 144704007ebaSmrg else { 144804007ebaSmrg LoaderErrorMsg(NULL, "shadow", maj, min); 144904007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 145004007ebaSmrg "Error loading shadow - rotation not available.\n"); 1451f29dbc25Smrg 145204007ebaSmrg if (pGeode->rotation != RR_Rotate_0) 145304007ebaSmrg xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 145404007ebaSmrg "Reverting back to normal rotation.\n"); 1455f29dbc25Smrg 145604007ebaSmrg rotate = pGeode->rotation = RR_Rotate_0; 1457f29dbc25Smrg } 1458f29dbc25Smrg 1459f29dbc25Smrg GXRandRInit(pScrn, rotate); 1460f29dbc25Smrg 1461f29dbc25Smrg pGeode->PointerMoved = pScrni->PointerMoved; 1462f29dbc25Smrg pScrni->PointerMoved = GeodePointerMoved; 1463f29dbc25Smrg 1464f29dbc25Smrg pGeode->CreateScreenResources = pScrn->CreateScreenResources; 1465f29dbc25Smrg pScrn->CreateScreenResources = GXCreateScreenResources; 1466f29dbc25Smrg 1467f29dbc25Smrg pGeode->CloseScreen = pScrn->CloseScreen; 1468f29dbc25Smrg pScrn->CloseScreen = GXCloseScreen; 1469f29dbc25Smrg pScrn->SaveScreen = GXSaveScreen; 1470f29dbc25Smrg 1471f29dbc25Smrg if (serverGeneration == 1) 147204007ebaSmrg xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options); 1473f29dbc25Smrg 1474f29dbc25Smrg pGeode->starting = FALSE; 1475f29dbc25Smrg 1476f29dbc25Smrg return TRUE; 1477f29dbc25Smrg} 1478f29dbc25Smrg 1479f29dbc25Smrgstatic int 148004007ebaSmrgGXValidMode(VALID_MODE_ARGS_DECL) 1481f29dbc25Smrg{ 148204007ebaSmrg SCRN_INFO_PTR(arg); 1483f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 1484f29dbc25Smrg int p; 1485f29dbc25Smrg int custom = 0; 1486f29dbc25Smrg 1487f29dbc25Smrg if (pGeode->Panel) 148804007ebaSmrg custom = (pMode->type & M_T_USERDEF); 1489f29dbc25Smrg else 149004007ebaSmrg custom = (pMode->type & (M_T_BUILTIN | M_T_DEFAULT)); 1491f29dbc25Smrg 1492f29dbc25Smrg /* Use the durango lookup for !custom modes */ 1493f29dbc25Smrg 1494f29dbc25Smrg if (!custom && pGeode->Panel) { 1495f29dbc25Smrg if (pMode->CrtcHDisplay > pGeode->PanelX || 1496f29dbc25Smrg pMode->CrtcVDisplay > pGeode->PanelY || 1497f29dbc25Smrg gfx_is_panel_mode_supported(pGeode->PanelX, 1498f29dbc25Smrg pGeode->PanelY, 1499f29dbc25Smrg pMode->CrtcHDisplay, 1500f29dbc25Smrg pMode->CrtcVDisplay, 1501f29dbc25Smrg pScrni->bitsPerPixel) < 0) { 1502f29dbc25Smrg 1503f29dbc25Smrg return MODE_BAD; 1504f29dbc25Smrg } 1505f29dbc25Smrg } 1506f29dbc25Smrg 1507f29dbc25Smrg if (gfx_is_display_mode_supported(pMode->CrtcHDisplay, 1508f29dbc25Smrg pMode->CrtcVDisplay, 1509f29dbc25Smrg pScrni->bitsPerPixel, 1510f29dbc25Smrg GeodeGetRefreshRate(pMode)) < 0) { 1511f29dbc25Smrg return MODE_BAD; 1512f29dbc25Smrg } 1513f29dbc25Smrg 1514f29dbc25Smrg if (pMode->Flags & V_INTERLACE) 151504007ebaSmrg return MODE_NO_INTERLACE; 1516f29dbc25Smrg 1517f29dbc25Smrg if (pGeode->tryCompression) 151804007ebaSmrg p = GeodeCalculatePitchBytes(pMode->CrtcHDisplay, pScrni->bitsPerPixel); 1519f29dbc25Smrg else 152004007ebaSmrg p = ((pMode->CrtcHDisplay + 3) & ~3) * (pScrni->bitsPerPixel >> 3); 1521f29dbc25Smrg 1522f29dbc25Smrg if (p * pMode->CrtcVDisplay > pGeode->FBAvail) 152304007ebaSmrg return MODE_MEM; 1524f29dbc25Smrg 1525f29dbc25Smrg return MODE_OK; 1526f29dbc25Smrg} 1527f29dbc25Smrg 1528f29dbc25Smrg/* XXX - Way more to do here */ 1529f29dbc25Smrg 1530f29dbc25Smrgstatic Bool 153104007ebaSmrgGXEnterVT(VT_FUNC_ARGS_DECL) 1532f29dbc25Smrg{ 153304007ebaSmrg SCRN_INFO_PTR(arg); 153404007ebaSmrg return GXEnterGraphics(NULL, pScrni); 1535f29dbc25Smrg} 1536f29dbc25Smrg 1537f29dbc25Smrgstatic void 153804007ebaSmrgGXLeaveVT(VT_FUNC_ARGS_DECL) 1539f29dbc25Smrg{ 154004007ebaSmrg SCRN_INFO_PTR(arg); 1541f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 1542f29dbc25Smrg 1543f29dbc25Smrg pGeode->PrevDisplayOffset = gfx_get_display_offset(); 154404007ebaSmrg GXLeaveGraphics(pScrni); 1545f29dbc25Smrg} 1546f29dbc25Smrg 1547f29dbc25Smrgvoid 1548f29dbc25SmrgGXSetupChipsetFPtr(ScrnInfoPtr pScrn) 1549f29dbc25Smrg{ 1550f29dbc25Smrg pScrn->PreInit = GXPreInit; 1551f29dbc25Smrg pScrn->ScreenInit = GXScreenInit; 1552f29dbc25Smrg pScrn->SwitchMode = GXSwitchMode; 1553f29dbc25Smrg pScrn->AdjustFrame = GXAdjustFrame; 1554f29dbc25Smrg pScrn->EnterVT = GXEnterVT; 1555f29dbc25Smrg pScrn->LeaveVT = GXLeaveVT; 1556f29dbc25Smrg pScrn->FreeScreen = GeodeFreeScreen; 1557f29dbc25Smrg pScrn->ValidMode = GXValidMode; 1558f29dbc25Smrg} 1559f29dbc25Smrg 1560f29dbc25Smrg/* ====== Common functions ====== 1561f29dbc25Smrg * These are all the common functions that we use for both GX and LX - They live here 1562f29dbc25Smrg * because most of them came along for the GX first, and then were adapted to the LX. 1563f29dbc25Smrg * We could move these to a common function, but there is no hurry 1564f29dbc25Smrg * ============================== */ 1565f29dbc25Smrg 1566f29dbc25Smrgvoid 156704007ebaSmrgGeodePointerMoved(POINTER_MOVED_ARGS_DECL) 1568f29dbc25Smrg{ 156904007ebaSmrg SCRN_INFO_PTR(arg); 1570f29dbc25Smrg GeodeRec *pGeode = GEODEPTR(pScrni); 1571f29dbc25Smrg 1572f29dbc25Smrg int newX = x, newY = y; 1573f29dbc25Smrg 1574f29dbc25Smrg switch (pGeode->rotation) { 1575f29dbc25Smrg case RR_Rotate_0: 157604007ebaSmrg break; 1577f29dbc25Smrg case RR_Rotate_90: 157804007ebaSmrg newX = y; 157904007ebaSmrg newY = pScrni->pScreen->width - x - 1; 158004007ebaSmrg break; 1581f29dbc25Smrg case RR_Rotate_180: 158204007ebaSmrg newX = pScrni->pScreen->width - x - 1; 158304007ebaSmrg newY = pScrni->pScreen->height - y - 1; 158404007ebaSmrg break; 1585f29dbc25Smrg case RR_Rotate_270: 158604007ebaSmrg newX = pScrni->pScreen->height - y - 1; 158704007ebaSmrg newY = x; 158804007ebaSmrg break; 1589f29dbc25Smrg } 1590f29dbc25Smrg 159104007ebaSmrg (*pGeode->PointerMoved) (POINTER_MOVED_ARGS(newX, newY)); 1592f29dbc25Smrg} 1593f29dbc25Smrg 1594f29dbc25Smrgint 1595f29dbc25SmrgGeodeGetFPGeometry(const char *str, int *width, int *height) 1596f29dbc25Smrg{ 1597f29dbc25Smrg 1598f29dbc25Smrg int ret = sscanf(str, "%dx%d", width, height); 1599f29dbc25Smrg 1600f29dbc25Smrg return (ret == 2) ? 0 : 1; 1601f29dbc25Smrg} 1602f29dbc25Smrg 1603f29dbc25Smrgstatic void 1604f29dbc25SmrgGeodeFreeRec(ScrnInfoPtr pScrni) 1605f29dbc25Smrg{ 1606f29dbc25Smrg if (pScrni->driverPrivate != NULL) { 160704007ebaSmrg free(pScrni->driverPrivate); 160804007ebaSmrg pScrni->driverPrivate = NULL; 1609f29dbc25Smrg } 1610f29dbc25Smrg} 1611f29dbc25Smrg 1612f29dbc25Smrgvoid 161304007ebaSmrgGeodeFreeScreen(FREE_SCREEN_ARGS_DECL) 1614f29dbc25Smrg{ 161504007ebaSmrg SCRN_INFO_PTR(arg); 161604007ebaSmrg GeodeRec *pGeode = GEODEPTR(pScrni); 1617f29dbc25Smrg 1618f29dbc25Smrg if (pGeode == NULL) 161904007ebaSmrg return; 1620f29dbc25Smrg 1621f29dbc25Smrg if (pGeode->useVGA) { 162204007ebaSmrg if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 162304007ebaSmrg vgaHWFreeHWRec(pScrni); 1624f29dbc25Smrg } 1625f29dbc25Smrg 162604007ebaSmrg GeodeFreeRec(pScrni); 1627f29dbc25Smrg} 1628f29dbc25Smrg 1629f29dbc25Smrgint 1630f29dbc25SmrgGeodeCalculatePitchBytes(unsigned int width, unsigned int bpp) 1631f29dbc25Smrg{ 1632f29dbc25Smrg 1633f29dbc25Smrg int delta = width * (bpp >> 3); 1634f29dbc25Smrg 1635f29dbc25Smrg /* Less then 640 has doubling enabled */ 1636f29dbc25Smrg 1637f29dbc25Smrg if (width < 640) 163804007ebaSmrg delta <<= 1; 1639f29dbc25Smrg 1640c744f008Smrg /* Calculate the pitch (compression requires a power of 2) */ 1641f29dbc25Smrg 1642f29dbc25Smrg if (delta > 4096) 164304007ebaSmrg delta = 8192; 1644f29dbc25Smrg else if (delta > 2048) 164504007ebaSmrg delta = 4096; 1646f29dbc25Smrg else if (delta > 1024) 164704007ebaSmrg delta = 2048; 1648f29dbc25Smrg else 164904007ebaSmrg delta = 1024; 1650f29dbc25Smrg 1651f29dbc25Smrg return delta; 1652f29dbc25Smrg} 1653