r128_driver.c revision e86a9069
1c582b7e3Smrg/* 2c582b7e3Smrg * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, 3c582b7e3Smrg * Precision Insight, Inc., Cedar Park, Texas, and 4c582b7e3Smrg * VA Linux Systems Inc., Fremont, California. 5c582b7e3Smrg * 6c582b7e3Smrg * All Rights Reserved. 7c582b7e3Smrg * 8c582b7e3Smrg * Permission is hereby granted, free of charge, to any person obtaining 9c582b7e3Smrg * a copy of this software and associated documentation files (the 10c582b7e3Smrg * "Software"), to deal in the Software without restriction, including 11c582b7e3Smrg * without limitation on the rights to use, copy, modify, merge, 12c582b7e3Smrg * publish, distribute, sublicense, and/or sell copies of the Software, 13c582b7e3Smrg * and to permit persons to whom the Software is furnished to do so, 14c582b7e3Smrg * subject to the following conditions: 15c582b7e3Smrg * 16c582b7e3Smrg * The above copyright notice and this permission notice (including the 17c582b7e3Smrg * next paragraph) shall be included in all copies or substantial 18c582b7e3Smrg * portions of the Software. 19c582b7e3Smrg * 20c582b7e3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21c582b7e3Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22c582b7e3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23c582b7e3Smrg * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX 24c582b7e3Smrg * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25c582b7e3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26c582b7e3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27c582b7e3Smrg * OTHER DEALINGS IN THE SOFTWARE. 28c582b7e3Smrg */ 29c582b7e3Smrg 30c582b7e3Smrg#ifdef HAVE_CONFIG_H 31c582b7e3Smrg#include "config.h" 32c582b7e3Smrg#endif 33c582b7e3Smrg 34c582b7e3Smrg/* 35c582b7e3Smrg * Authors: 36c582b7e3Smrg * Rickard E. Faith <faith@valinux.com> 37c582b7e3Smrg * Kevin E. Martin <martin@valinux.com> 38c582b7e3Smrg * Gareth Hughes <gareth@valinux.com> 39c582b7e3Smrg * 40c582b7e3Smrg * Credits: 41c582b7e3Smrg * 42c582b7e3Smrg * Thanks to Alan Hourihane <alanh@fairlite.demon..co.uk> and SuSE for 43c582b7e3Smrg * providing source code to their 3.3.x Rage 128 driver. Portions of 44c582b7e3Smrg * this file are based on the initialization code for that driver. 45c582b7e3Smrg * 46c582b7e3Smrg * References: 47c582b7e3Smrg * 48c582b7e3Smrg * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical 49c582b7e3Smrg * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April 50c582b7e3Smrg * 1999. 51c582b7e3Smrg * 52c582b7e3Smrg * RAGE 128 Software Development Manual (Technical Reference Manual P/N 53c582b7e3Smrg * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. 54c582b7e3Smrg * 55c582b7e3Smrg * This server does not yet support these XFree86 4.0 features: 56c582b7e3Smrg * DDC1 & DDC2 57c582b7e3Smrg * shadowfb 58c582b7e3Smrg * overlay planes 59c582b7e3Smrg * 60c582b7e3Smrg * Modified by Marc Aurele La France <tsi@xfree86.org> for ATI driver merge. 61c582b7e3Smrg * 62c582b7e3Smrg * Dualhead support - Alex Deucher <agd5f@yahoo.com> 63c582b7e3Smrg */ 64c582b7e3Smrg 65c582b7e3Smrg#include <string.h> 66c582b7e3Smrg#include <stdio.h> 67c582b7e3Smrg 68c582b7e3Smrg /* Driver data structures */ 69c582b7e3Smrg#include "r128.h" 70c582b7e3Smrg#include "r128_probe.h" 71c582b7e3Smrg#include "r128_reg.h" 72c582b7e3Smrg#include "r128_version.h" 73c582b7e3Smrg 74c582b7e3Smrg#ifdef XF86DRI 75c582b7e3Smrg#define _XF86DRI_SERVER_ 76c582b7e3Smrg#include "r128_dri.h" 77c582b7e3Smrg#include "r128_common.h" 78c582b7e3Smrg#include "r128_sarea.h" 79c582b7e3Smrg#endif 80c582b7e3Smrg 81c582b7e3Smrg#include "fb.h" 82c582b7e3Smrg 83c582b7e3Smrg /* colormap initialization */ 84c582b7e3Smrg#include "micmap.h" 85c582b7e3Smrg 86c582b7e3Smrg /* X and server generic header files */ 87c582b7e3Smrg#include "xf86.h" 88c582b7e3Smrg#include "xf86_OSproc.h" 89c582b7e3Smrg#include "xf86PciInfo.h" 9019019ffeSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 91c582b7e3Smrg#include "xf86RAC.h" 92c582b7e3Smrg#include "xf86Resources.h" 9319019ffeSmrg#endif 94a9060c92Schristos#include "xf86_OSlib.h" 95c582b7e3Smrg#include "xf86cmap.h" 96c582b7e3Smrg#include "xf86xv.h" 97c582b7e3Smrg#include "vbe.h" 9899d7194aSmacallan#include "xf86Priv.h" 99c582b7e3Smrg 100c582b7e3Smrg /* fbdevhw & vgahw */ 101c582b7e3Smrg#ifdef WITH_VGAHW 102c582b7e3Smrg#include "vgaHW.h" 103c582b7e3Smrg#endif 10479e5230eSmacallan 10579e5230eSmacallan#ifndef AVOID_FBDEV 106c582b7e3Smrg#include "fbdevhw.h" 10779e5230eSmacallan#endif 10879e5230eSmacallan 109c582b7e3Smrg#include "dixstruct.h" 110c582b7e3Smrg 111c582b7e3Smrg /* DPMS support. */ 11219019ffeSmrg#ifdef HAVE_XEXTPROTO_71 11319019ffeSmrg#include <X11/extensions/dpmsconst.h> 11419019ffeSmrg#else 115c582b7e3Smrg#define DPMS_SERVER 116c582b7e3Smrg#include <X11/extensions/dpms.h> 11719019ffeSmrg#endif 11819019ffeSmrg 11999d7194aSmacallan#ifdef __NetBSD__ 12099d7194aSmacallan#include <sys/time.h> 12199d7194aSmacallan#include <dev/wscons/wsconsio.h> 12299d7194aSmacallan#endif 123c582b7e3Smrg 124c582b7e3Smrg#ifndef MAX 125c582b7e3Smrg#define MAX(a,b) ((a)>(b)?(a):(b)) 126c582b7e3Smrg#endif 127c582b7e3Smrg 128c582b7e3Smrg#define USE_CRT_ONLY 0 129c582b7e3Smrg 130c582b7e3Smrg /* Forward definitions for driver functions */ 131c582b7e3Smrgstatic Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen); 132c582b7e3Smrgstatic Bool R128SaveScreen(ScreenPtr pScreen, int mode); 133c582b7e3Smrgstatic void R128Save(ScrnInfoPtr pScrn); 134c582b7e3Smrgstatic void R128Restore(ScrnInfoPtr pScrn); 135c582b7e3Smrgstatic Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); 136c582b7e3Smrgstatic void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn, 137c582b7e3Smrg int PowerManagementMode, int flags); 138c582b7e3Smrgstatic void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn, 139c582b7e3Smrg int PowerManagementMode, int flags); 140c582b7e3Smrg 141c582b7e3Smrgtypedef enum { 142c582b7e3Smrg OPTION_NOACCEL, 143c582b7e3Smrg OPTION_SW_CURSOR, 144c582b7e3Smrg OPTION_DAC_6BIT, 145c582b7e3Smrg OPTION_DAC_8BIT, 146c582b7e3Smrg#ifdef XF86DRI 147c582b7e3Smrg OPTION_XV_DMA, 148c582b7e3Smrg OPTION_IS_PCI, 149c582b7e3Smrg OPTION_CCE_PIO, 150c582b7e3Smrg OPTION_NO_SECURITY, 151c582b7e3Smrg OPTION_USEC_TIMEOUT, 152c582b7e3Smrg OPTION_AGP_MODE, 153c582b7e3Smrg OPTION_AGP_SIZE, 154c582b7e3Smrg OPTION_RING_SIZE, 155c582b7e3Smrg OPTION_BUFFER_SIZE, 156c582b7e3Smrg OPTION_PAGE_FLIP, 157c582b7e3Smrg#endif 158c582b7e3Smrg#if USE_CRT_ONLY 159c582b7e3Smrg /* FIXME: Disable CRTOnly until it is tested */ 160c582b7e3Smrg OPTION_CRT, 161c582b7e3Smrg#endif 162c582b7e3Smrg OPTION_DISPLAY, 163c582b7e3Smrg OPTION_PANEL_WIDTH, 164c582b7e3Smrg OPTION_PANEL_HEIGHT, 165c582b7e3Smrg OPTION_PROG_FP_REGS, 16679e5230eSmacallan#ifndef AVOID_FBDEV 167c582b7e3Smrg OPTION_FBDEV, 16879e5230eSmacallan#endif 169c582b7e3Smrg OPTION_VIDEO_KEY, 170c582b7e3Smrg OPTION_SHOW_CACHE, 171c582b7e3Smrg OPTION_VGA_ACCESS 172c582b7e3Smrg} R128Opts; 173c582b7e3Smrg 174c582b7e3Smrgstatic const OptionInfoRec R128Options[] = { 175c582b7e3Smrg { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 176c582b7e3Smrg { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 177c582b7e3Smrg { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE }, 178c582b7e3Smrg { OPTION_DAC_8BIT, "Dac8Bit", OPTV_BOOLEAN, {0}, TRUE }, 179c582b7e3Smrg#ifdef XF86DRI 180c582b7e3Smrg { OPTION_XV_DMA, "DMAForXv", OPTV_BOOLEAN, {0}, FALSE }, 181c582b7e3Smrg { OPTION_IS_PCI, "ForcePCIMode", OPTV_BOOLEAN, {0}, FALSE }, 182c582b7e3Smrg { OPTION_CCE_PIO, "CCEPIOMode", OPTV_BOOLEAN, {0}, FALSE }, 183c582b7e3Smrg { OPTION_NO_SECURITY, "CCENoSecurity", OPTV_BOOLEAN, {0}, FALSE }, 184c582b7e3Smrg { OPTION_USEC_TIMEOUT, "CCEusecTimeout", OPTV_INTEGER, {0}, FALSE }, 185c582b7e3Smrg { OPTION_AGP_MODE, "AGPMode", OPTV_INTEGER, {0}, FALSE }, 186c582b7e3Smrg { OPTION_AGP_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE }, 187c582b7e3Smrg { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE }, 188c582b7e3Smrg { OPTION_BUFFER_SIZE, "BufferSize", OPTV_INTEGER, {0}, FALSE }, 189c582b7e3Smrg { OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE }, 190c582b7e3Smrg#endif 191c582b7e3Smrg { OPTION_DISPLAY, "Display", OPTV_STRING, {0}, FALSE }, 192c582b7e3Smrg { OPTION_PANEL_WIDTH, "PanelWidth", OPTV_INTEGER, {0}, FALSE }, 193c582b7e3Smrg { OPTION_PANEL_HEIGHT, "PanelHeight", OPTV_INTEGER, {0}, FALSE }, 194c582b7e3Smrg { OPTION_PROG_FP_REGS, "ProgramFPRegs", OPTV_BOOLEAN, {0}, FALSE }, 19579e5230eSmacallan#ifndef AVOID_FBDEV 196c582b7e3Smrg { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, 19779e5230eSmacallan#endif 198c582b7e3Smrg { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, 199c582b7e3Smrg { OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, 200c582b7e3Smrg { OPTION_VGA_ACCESS, "VGAAccess", OPTV_BOOLEAN, {0}, TRUE }, 201c582b7e3Smrg { -1, NULL, OPTV_NONE, {0}, FALSE } 202c582b7e3Smrg}; 203c582b7e3Smrg 204c582b7e3Smrgconst OptionInfoRec *R128OptionsWeak(void) { return R128Options; } 205c582b7e3Smrg 206c582b7e3SmrgR128RAMRec R128RAM[] = { /* Memory Specifications 207c582b7e3Smrg From RAGE 128 Software Development 208c582b7e3Smrg Manual (Technical Reference Manual P/N 209c582b7e3Smrg SDK-G04000 Rev 0.01), page 3-21. */ 210c582b7e3Smrg { 4, 4, 3, 3, 1, 3, 1, 16, 12, "128-bit SDR SGRAM 1:1" }, 211c582b7e3Smrg { 4, 8, 3, 3, 1, 3, 1, 17, 13, "64-bit SDR SGRAM 1:1" }, 212c582b7e3Smrg { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SGRAM 2:1" }, 213c582b7e3Smrg { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SGRAM" }, 214c582b7e3Smrg}; 215c582b7e3Smrg 216c582b7e3Smrgextern _X_EXPORT int gR128EntityIndex; 217c582b7e3Smrg 218c582b7e3Smrgint getR128EntityIndex(void) 219c582b7e3Smrg{ 220c582b7e3Smrg return gR128EntityIndex; 221c582b7e3Smrg} 222c582b7e3Smrg 223c582b7e3SmrgR128EntPtr R128EntPriv(ScrnInfoPtr pScrn) 224c582b7e3Smrg{ 225c582b7e3Smrg DevUnion *pPriv; 226c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 227c582b7e3Smrg pPriv = xf86GetEntityPrivate(info->pEnt->index, 228c582b7e3Smrg getR128EntityIndex()); 229c582b7e3Smrg return pPriv->ptr; 230c582b7e3Smrg} 231c582b7e3Smrg 232c582b7e3Smrg/* Allocate our private R128InfoRec. */ 233c582b7e3Smrgstatic Bool R128GetRec(ScrnInfoPtr pScrn) 234c582b7e3Smrg{ 235c582b7e3Smrg if (pScrn->driverPrivate) return TRUE; 236c582b7e3Smrg 237c582b7e3Smrg pScrn->driverPrivate = xnfcalloc(sizeof(R128InfoRec), 1); 238c582b7e3Smrg return TRUE; 239c582b7e3Smrg} 240c582b7e3Smrg 241c582b7e3Smrg/* Free our private R128InfoRec. */ 242c582b7e3Smrgstatic void R128FreeRec(ScrnInfoPtr pScrn) 243c582b7e3Smrg{ 244c582b7e3Smrg if (!pScrn || !pScrn->driverPrivate) return; 245c582b7e3Smrg xfree(pScrn->driverPrivate); 246c582b7e3Smrg pScrn->driverPrivate = NULL; 247c582b7e3Smrg} 248c582b7e3Smrg 249c582b7e3Smrg/* Memory map the MMIO region. Used during pre-init and by R128MapMem, 250c582b7e3Smrg below. */ 251c582b7e3Smrgstatic Bool R128MapMMIO(ScrnInfoPtr pScrn) 252c582b7e3Smrg{ 253c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 254c582b7e3Smrg 25579e5230eSmacallan#ifndef AVOID_FBDEV 256c582b7e3Smrg if (info->FBDev) { 257c582b7e3Smrg info->MMIO = fbdevHWMapMMIO(pScrn); 25879e5230eSmacallan } else 25979e5230eSmacallan#endif 26079e5230eSmacallan { 26119019ffeSmrg /* If the primary screen has already mapped the MMIO region, 26219019ffeSmrg use its pointer instead of mapping it a second time. */ 26319019ffeSmrg if (info->IsSecondary) { 26419019ffeSmrg DevUnion* pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 26519019ffeSmrg getR128EntityIndex()); 26619019ffeSmrg R128EntPtr pR128Ent = pPriv->ptr; 26719019ffeSmrg R128InfoPtr info0 = R128PTR(pR128Ent->pPrimaryScrn); 26819019ffeSmrg info->MMIO=info0->MMIO; 26919019ffeSmrg if (info->MMIO) return TRUE; 27019019ffeSmrg } 271c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS 272c582b7e3Smrg info->MMIO = xf86MapPciMem(pScrn->scrnIndex, 273c582b7e3Smrg VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, 274c582b7e3Smrg info->PciTag, 275c582b7e3Smrg info->MMIOAddr, 276c582b7e3Smrg R128_MMIOSIZE); 277c582b7e3Smrg#else 278c582b7e3Smrg int err = pci_device_map_range(info->PciInfo, 279c582b7e3Smrg info->MMIOAddr, 280c582b7e3Smrg R128_MMIOSIZE, 281c582b7e3Smrg PCI_DEV_MAP_FLAG_WRITABLE, 282c582b7e3Smrg &info->MMIO); 283c582b7e3Smrg 284c582b7e3Smrg if (err) { 285c582b7e3Smrg xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 286c582b7e3Smrg "Unable to map MMIO aperture. %s (%d)\n", 287c582b7e3Smrg strerror (err), err); 288c582b7e3Smrg return FALSE; 289c582b7e3Smrg } 290c582b7e3Smrg#endif 291c582b7e3Smrg } 292c582b7e3Smrg 293c582b7e3Smrg if (!info->MMIO) return FALSE; 294c582b7e3Smrg return TRUE; 295c582b7e3Smrg} 296c582b7e3Smrg 297c582b7e3Smrg/* Unmap the MMIO region. Used during pre-init and by R128UnmapMem, 298c582b7e3Smrg below. */ 299c582b7e3Smrgstatic Bool R128UnmapMMIO(ScrnInfoPtr pScrn) 300c582b7e3Smrg{ 301c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 302c582b7e3Smrg 30379e5230eSmacallan#ifndef AVOID_FBDEV 304c582b7e3Smrg if (info->FBDev) 305c582b7e3Smrg fbdevHWUnmapMMIO(pScrn); 30679e5230eSmacallan else 30779e5230eSmacallan#endif 30879e5230eSmacallan { 309c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS 310c582b7e3Smrg xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, R128_MMIOSIZE); 311c582b7e3Smrg#else 312c582b7e3Smrg pci_device_unmap_range(info->PciInfo, info->MMIO, R128_MMIOSIZE); 313c582b7e3Smrg#endif 314c582b7e3Smrg } 315c582b7e3Smrg info->MMIO = NULL; 316c582b7e3Smrg return TRUE; 317c582b7e3Smrg} 318c582b7e3Smrg 319c582b7e3Smrg/* Memory map the frame buffer. Used by R128MapMem, below. */ 320c582b7e3Smrgstatic Bool R128MapFB(ScrnInfoPtr pScrn) 321c582b7e3Smrg{ 322c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 323c582b7e3Smrg 32479e5230eSmacallan#ifndef AVOID_FBDEV 325c582b7e3Smrg if (info->FBDev) { 326c582b7e3Smrg info->FB = fbdevHWMapVidmem(pScrn); 32779e5230eSmacallan } else 32879e5230eSmacallan#endif 32979e5230eSmacallan { 330c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS 331c582b7e3Smrg info->FB = xf86MapPciMem(pScrn->scrnIndex, 332c582b7e3Smrg VIDMEM_FRAMEBUFFER, 333c582b7e3Smrg info->PciTag, 334c582b7e3Smrg info->LinearAddr, 335c582b7e3Smrg info->FbMapSize); 336c582b7e3Smrg#else 337c582b7e3Smrg int err = pci_device_map_range(info->PciInfo, 338c582b7e3Smrg info->LinearAddr, 339c582b7e3Smrg info->FbMapSize, 340c582b7e3Smrg PCI_DEV_MAP_FLAG_WRITABLE | 341c582b7e3Smrg PCI_DEV_MAP_FLAG_WRITE_COMBINE, 342c582b7e3Smrg &info->FB); 343c582b7e3Smrg 344c582b7e3Smrg if (err) { 345c582b7e3Smrg xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 346c582b7e3Smrg "Unable to map FB aperture. %s (%d)\n", 347c582b7e3Smrg strerror (err), err); 348c582b7e3Smrg return FALSE; 349c582b7e3Smrg } 350c582b7e3Smrg#endif 351c582b7e3Smrg } 352c582b7e3Smrg 353c582b7e3Smrg if (!info->FB) return FALSE; 354c582b7e3Smrg return TRUE; 355c582b7e3Smrg} 356c582b7e3Smrg 357c582b7e3Smrg/* Unmap the frame buffer. Used by R128UnmapMem, below. */ 358c582b7e3Smrgstatic Bool R128UnmapFB(ScrnInfoPtr pScrn) 359c582b7e3Smrg{ 360c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 361c582b7e3Smrg 36279e5230eSmacallan#ifndef AVOID_FBDEV 363c582b7e3Smrg if (info->FBDev) 364c582b7e3Smrg fbdevHWUnmapVidmem(pScrn); 365c582b7e3Smrg else 36679e5230eSmacallan#endif 367c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS 368c582b7e3Smrg xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize); 369c582b7e3Smrg#else 370c582b7e3Smrg pci_device_unmap_range(info->PciInfo, info->FB, info->FbMapSize); 371c582b7e3Smrg#endif 372c582b7e3Smrg info->FB = NULL; 373c582b7e3Smrg return TRUE; 374c582b7e3Smrg} 375c582b7e3Smrg 376c582b7e3Smrg/* Memory map the MMIO region and the frame buffer. */ 377c582b7e3Smrgstatic Bool R128MapMem(ScrnInfoPtr pScrn) 378c582b7e3Smrg{ 379c582b7e3Smrg if (!R128MapMMIO(pScrn)) return FALSE; 380c582b7e3Smrg if (!R128MapFB(pScrn)) { 381c582b7e3Smrg R128UnmapMMIO(pScrn); 382c582b7e3Smrg return FALSE; 383c582b7e3Smrg } 384c582b7e3Smrg return TRUE; 385c582b7e3Smrg} 386c582b7e3Smrg 387c582b7e3Smrg/* Unmap the MMIO region and the frame buffer. */ 388c582b7e3Smrgstatic Bool R128UnmapMem(ScrnInfoPtr pScrn) 389c582b7e3Smrg{ 390c582b7e3Smrg if (!R128UnmapMMIO(pScrn) || !R128UnmapFB(pScrn)) return FALSE; 391c582b7e3Smrg return TRUE; 392c582b7e3Smrg} 393c582b7e3Smrg 394c582b7e3Smrg/* Read PLL information */ 395c582b7e3Smrgunsigned R128INPLL(ScrnInfoPtr pScrn, int addr) 396c582b7e3Smrg{ 397c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 398c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 399c582b7e3Smrg 400c582b7e3Smrg OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x3f); 401c582b7e3Smrg return INREG(R128_CLOCK_CNTL_DATA); 402c582b7e3Smrg} 403c582b7e3Smrg 404c582b7e3Smrg#if 0 405c582b7e3Smrg/* Read PAL information (only used for debugging). */ 406c582b7e3Smrgstatic int R128INPAL(int idx) 407c582b7e3Smrg{ 408c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 409c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 410c582b7e3Smrg 411c582b7e3Smrg OUTREG(R128_PALETTE_INDEX, idx << 16); 412c582b7e3Smrg return INREG(R128_PALETTE_DATA); 413c582b7e3Smrg} 414c582b7e3Smrg#endif 415c582b7e3Smrg 416c582b7e3Smrg/* Wait for vertical sync. */ 417c582b7e3Smrgvoid R128WaitForVerticalSync(ScrnInfoPtr pScrn) 418c582b7e3Smrg{ 419c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 420c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 421c582b7e3Smrg int i; 422c582b7e3Smrg 423c582b7e3Smrg OUTREG(R128_GEN_INT_STATUS, R128_VSYNC_INT_AK); 424c582b7e3Smrg for (i = 0; i < R128_TIMEOUT; i++) { 425c582b7e3Smrg if (INREG(R128_GEN_INT_STATUS) & R128_VSYNC_INT) break; 426c582b7e3Smrg } 427c582b7e3Smrg} 428c582b7e3Smrg 429c582b7e3Smrg/* Blank screen. */ 430c582b7e3Smrgstatic void R128Blank(ScrnInfoPtr pScrn) 431c582b7e3Smrg{ 432c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 433c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 434c582b7e3Smrg 435c582b7e3Smrg if(!info->IsSecondary) 436c582b7e3Smrg { 437c582b7e3Smrg switch(info->DisplayType) 438c582b7e3Smrg { 439c582b7e3Smrg case MT_LCD: 440c582b7e3Smrg OUTREGP(R128_LVDS_GEN_CNTL, R128_LVDS_DISPLAY_DIS, 441c582b7e3Smrg ~R128_LVDS_DISPLAY_DIS); 442c582b7e3Smrg break; 443c582b7e3Smrg case MT_CRT: 444c582b7e3Smrg OUTREGP(R128_CRTC_EXT_CNTL, R128_CRTC_DISPLAY_DIS, ~R128_CRTC_DISPLAY_DIS); 445c582b7e3Smrg break; 446c582b7e3Smrg case MT_DFP: 447c582b7e3Smrg OUTREGP(R128_FP_GEN_CNTL, R128_FP_BLANK_DIS, ~R128_FP_BLANK_DIS); 448c582b7e3Smrg break; 449c582b7e3Smrg case MT_NONE: 450c582b7e3Smrg default: 451c582b7e3Smrg break; 452c582b7e3Smrg } 453c582b7e3Smrg } 454c582b7e3Smrg else 455c582b7e3Smrg { 456c582b7e3Smrg OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~R128_CRTC2_DISP_DIS); 457c582b7e3Smrg } 458c582b7e3Smrg} 459c582b7e3Smrg 460c582b7e3Smrg/* Unblank screen. */ 461c582b7e3Smrgstatic void R128Unblank(ScrnInfoPtr pScrn) 462c582b7e3Smrg{ 463c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 464c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 465c582b7e3Smrg 466c582b7e3Smrg if(!info->IsSecondary) 467c582b7e3Smrg { 468c582b7e3Smrg switch(info->DisplayType) 469c582b7e3Smrg { 470c582b7e3Smrg case MT_LCD: 471c582b7e3Smrg OUTREGP(R128_LVDS_GEN_CNTL, 0, 472c582b7e3Smrg ~R128_LVDS_DISPLAY_DIS); 473c582b7e3Smrg break; 474c582b7e3Smrg case MT_CRT: 475c582b7e3Smrg OUTREGP(R128_CRTC_EXT_CNTL, 0, ~R128_CRTC_DISPLAY_DIS); 476c582b7e3Smrg break; 477c582b7e3Smrg case MT_DFP: 478c582b7e3Smrg OUTREGP(R128_FP_GEN_CNTL, 0, ~R128_FP_BLANK_DIS); 479c582b7e3Smrg break; 480c582b7e3Smrg case MT_NONE: 481c582b7e3Smrg default: 482c582b7e3Smrg break; 483c582b7e3Smrg } 484c582b7e3Smrg } 485c582b7e3Smrg else 486c582b7e3Smrg { 487c582b7e3Smrg switch(info->DisplayType) 488c582b7e3Smrg { 489c582b7e3Smrg case MT_LCD: 490c582b7e3Smrg case MT_DFP: 491c582b7e3Smrg case MT_CRT: 492c582b7e3Smrg OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_DISP_DIS); 493c582b7e3Smrg break; 494c582b7e3Smrg case MT_NONE: 495c582b7e3Smrg default: 496c582b7e3Smrg break; 497c582b7e3Smrg } 498c582b7e3Smrg } 499c582b7e3Smrg} 500c582b7e3Smrg 501c582b7e3Smrg/* Compute log base 2 of val. */ 502c582b7e3Smrgint R128MinBits(int val) 503c582b7e3Smrg{ 504c582b7e3Smrg int bits; 505c582b7e3Smrg 506c582b7e3Smrg if (!val) return 1; 507c582b7e3Smrg for (bits = 0; val; val >>= 1, ++bits); 508c582b7e3Smrg return bits; 509c582b7e3Smrg} 510c582b7e3Smrg 511c582b7e3Smrg/* Compute n/d with rounding. */ 512c582b7e3Smrgstatic int R128Div(int n, int d) 513c582b7e3Smrg{ 514c582b7e3Smrg return (n + (d / 2)) / d; 515c582b7e3Smrg} 516c582b7e3Smrg 517c582b7e3Smrg/* Read the Video BIOS block and the FP registers (if applicable). */ 518c582b7e3Smrgstatic Bool R128GetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) 519c582b7e3Smrg{ 520c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 521c582b7e3Smrg int i; 522c582b7e3Smrg int FPHeader = 0; 523c582b7e3Smrg 524c582b7e3Smrg#define R128_BIOS8(v) (info->VBIOS[v]) 525c582b7e3Smrg#define R128_BIOS16(v) (info->VBIOS[v] | \ 526c582b7e3Smrg (info->VBIOS[(v) + 1] << 8)) 527c582b7e3Smrg#define R128_BIOS32(v) (info->VBIOS[v] | \ 528c582b7e3Smrg (info->VBIOS[(v) + 1] << 8) | \ 529c582b7e3Smrg (info->VBIOS[(v) + 2] << 16) | \ 530c582b7e3Smrg (info->VBIOS[(v) + 3] << 24)) 531c582b7e3Smrg 532c582b7e3Smrg#ifdef XSERVER_LIBPCIACCESS 533c582b7e3Smrg int size = info->PciInfo->rom_size > R128_VBIOS_SIZE ? info->PciInfo->rom_size : R128_VBIOS_SIZE; 534c582b7e3Smrg info->VBIOS = xalloc(size); 535c582b7e3Smrg#else 536c582b7e3Smrg info->VBIOS = xalloc(R128_VBIOS_SIZE); 537c582b7e3Smrg#endif 538c582b7e3Smrg 539c582b7e3Smrg if (!info->VBIOS) { 540c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 541c582b7e3Smrg "Cannot allocate space for hold Video BIOS!\n"); 542c582b7e3Smrg return FALSE; 543c582b7e3Smrg } 544c582b7e3Smrg 545c582b7e3Smrg if (pInt10) { 546c582b7e3Smrg info->BIOSAddr = pInt10->BIOSseg << 4; 547c582b7e3Smrg (void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr), 548c582b7e3Smrg R128_VBIOS_SIZE); 549c582b7e3Smrg } else { 550c582b7e3Smrg#ifdef XSERVER_LIBPCIACCESS 551c582b7e3Smrg if (pci_device_read_rom(info->PciInfo, info->VBIOS)) { 552c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 553c582b7e3Smrg "Failed to read PCI ROM!\n"); 554c582b7e3Smrg } 555c582b7e3Smrg#else 556c582b7e3Smrg xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, R128_VBIOS_SIZE); 557c582b7e3Smrg if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { 558c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 559c582b7e3Smrg "Video BIOS not detected in PCI space!\n"); 560c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 561c582b7e3Smrg "Attempting to read Video BIOS from legacy ISA space!\n"); 562c582b7e3Smrg info->BIOSAddr = 0x000c0000; 563c582b7e3Smrg xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, R128_VBIOS_SIZE, info->VBIOS); 564c582b7e3Smrg } 565c582b7e3Smrg#endif 566c582b7e3Smrg } 567c582b7e3Smrg if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { 568c582b7e3Smrg info->BIOSAddr = 0x00000000; 569c582b7e3Smrg xfree(info->VBIOS); 570c582b7e3Smrg info->VBIOS = NULL; 571c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 572c582b7e3Smrg "Video BIOS not found!\n"); 573c582b7e3Smrg } 574c582b7e3Smrg 575c582b7e3Smrg if(info->HasCRTC2) 576c582b7e3Smrg { 577c582b7e3Smrg if(info->IsSecondary) 578c582b7e3Smrg { 579c582b7e3Smrg /* there may be a way to detect this, for now, just assume 580c582b7e3Smrg second head is CRT */ 581c582b7e3Smrg info->DisplayType = MT_CRT; 582c582b7e3Smrg 583c582b7e3Smrg if(info->DisplayType > MT_NONE) 584c582b7e3Smrg { 585c582b7e3Smrg DevUnion* pPriv; 586c582b7e3Smrg R128EntPtr pR128Ent; 587c582b7e3Smrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 588c582b7e3Smrg getR128EntityIndex()); 589c582b7e3Smrg pR128Ent = pPriv->ptr; 590c582b7e3Smrg pR128Ent->HasSecondary = TRUE; 591c582b7e3Smrg 592c582b7e3Smrg } 593c582b7e3Smrg else return FALSE; 594c582b7e3Smrg 595c582b7e3Smrg } 596c582b7e3Smrg else 597c582b7e3Smrg { 598c582b7e3Smrg /* really need some sort of detection here */ 599c582b7e3Smrg if (info->HasPanelRegs) { 600c582b7e3Smrg info->DisplayType = MT_LCD; 601c582b7e3Smrg } else if (info->isDFP) { 602c582b7e3Smrg info->DisplayType = MT_DFP; 603c582b7e3Smrg } else 604c582b7e3Smrg { 605c582b7e3Smrg /*DVI port has no monitor connected, try CRT port. 606c582b7e3Smrg If something on CRT port, treat it as primary*/ 607c582b7e3Smrg if(xf86IsEntityShared(pScrn->entityList[0])) 608c582b7e3Smrg { 609c582b7e3Smrg DevUnion* pPriv; 610c582b7e3Smrg R128EntPtr pR128Ent; 611c582b7e3Smrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 612c582b7e3Smrg getR128EntityIndex()); 613c582b7e3Smrg pR128Ent = pPriv->ptr; 614c582b7e3Smrg pR128Ent->BypassSecondary = TRUE; 615c582b7e3Smrg } 616c582b7e3Smrg 617c582b7e3Smrg info->DisplayType = MT_CRT; 618c582b7e3Smrg#if 0 619c582b7e3Smrg { 620c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 621c582b7e3Smrg "No monitor detected!!!\n"); 622c582b7e3Smrg return FALSE; 623c582b7e3Smrg } 624c582b7e3Smrg#endif 625c582b7e3Smrg } 626c582b7e3Smrg } 627c582b7e3Smrg } 628c582b7e3Smrg else 629c582b7e3Smrg { 630c582b7e3Smrg /*Regular Radeon ASIC, only one CRTC, but it could be 631c582b7e3Smrg used for DFP with a DVI output, like AIW board*/ 632c582b7e3Smrg if(info->isDFP) info->DisplayType = MT_DFP; 633c582b7e3Smrg else info->DisplayType = MT_CRT; 634c582b7e3Smrg } 635c582b7e3Smrg 636c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Display == Type %d\n", 637c582b7e3Smrg (info->IsSecondary ? "Secondary" : "Primary"), 638c582b7e3Smrg info->DisplayType); 639c582b7e3Smrg 640c582b7e3Smrg 641c582b7e3Smrg if (info->VBIOS && info->DisplayType == MT_LCD) { 642c582b7e3Smrg info->FPBIOSstart = 0; 643c582b7e3Smrg 644c582b7e3Smrg /* FIXME: There should be direct access to the start of the FP info 645c582b7e3Smrg tables, but until we find out where that offset is stored, we 646c582b7e3Smrg must search for the ATI signature string: "M3 ". */ 647c582b7e3Smrg for (i = 4; i < R128_VBIOS_SIZE-8; i++) { 648c582b7e3Smrg if (R128_BIOS8(i) == 'M' && 649c582b7e3Smrg R128_BIOS8(i+1) == '3' && 650c582b7e3Smrg R128_BIOS8(i+2) == ' ' && 651c582b7e3Smrg R128_BIOS8(i+3) == ' ' && 652c582b7e3Smrg R128_BIOS8(i+4) == ' ' && 653c582b7e3Smrg R128_BIOS8(i+5) == ' ' && 654c582b7e3Smrg R128_BIOS8(i+6) == ' ' && 655c582b7e3Smrg R128_BIOS8(i+7) == ' ') { 656c582b7e3Smrg FPHeader = i-2; 657c582b7e3Smrg break; 658c582b7e3Smrg } 659c582b7e3Smrg } 660c582b7e3Smrg 661c582b7e3Smrg if (!FPHeader) return TRUE; 662c582b7e3Smrg 663c582b7e3Smrg /* Assume that only one panel is attached and supported */ 664c582b7e3Smrg for (i = FPHeader+20; i < FPHeader+84; i += 2) { 665c582b7e3Smrg if (R128_BIOS16(i) != 0) { 666c582b7e3Smrg info->FPBIOSstart = R128_BIOS16(i); 667c582b7e3Smrg break; 668c582b7e3Smrg } 669c582b7e3Smrg } 670c582b7e3Smrg if (!info->FPBIOSstart) return TRUE; 671c582b7e3Smrg 672c582b7e3Smrg if (!info->PanelXRes) 673c582b7e3Smrg info->PanelXRes = R128_BIOS16(info->FPBIOSstart+25); 674c582b7e3Smrg if (!info->PanelYRes) 675c582b7e3Smrg info->PanelYRes = R128_BIOS16(info->FPBIOSstart+27); 676c582b7e3Smrg 677c582b7e3Smrg info->PanelPwrDly = R128_BIOS8(info->FPBIOSstart+56); 678c582b7e3Smrg 679c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel ID: "); 680c582b7e3Smrg for (i = 1; i <= 24; i++) 681c582b7e3Smrg ErrorF("%c", R128_BIOS8(info->FPBIOSstart+i)); 682c582b7e3Smrg ErrorF("\n"); 683c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Type: "); 684c582b7e3Smrg i = R128_BIOS16(info->FPBIOSstart+29); 685c582b7e3Smrg if (i & 1) ErrorF("Color, "); 686c582b7e3Smrg else ErrorF("Monochrome, "); 687c582b7e3Smrg if (i & 2) ErrorF("Dual(split), "); 688c582b7e3Smrg else ErrorF("Single, "); 689c582b7e3Smrg switch ((i >> 2) & 0x3f) { 690c582b7e3Smrg case 0: ErrorF("STN"); break; 691c582b7e3Smrg case 1: ErrorF("TFT"); break; 692c582b7e3Smrg case 2: ErrorF("Active STN"); break; 693c582b7e3Smrg case 3: ErrorF("EL"); break; 694c582b7e3Smrg case 4: ErrorF("Plasma"); break; 695c582b7e3Smrg default: ErrorF("UNKNOWN"); break; 696c582b7e3Smrg } 697c582b7e3Smrg ErrorF("\n"); 698c582b7e3Smrg if (R128_BIOS8(info->FPBIOSstart+61) & 1) { 699c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Interface: LVDS\n"); 700c582b7e3Smrg } else { 701c582b7e3Smrg /* FIXME: Add Non-LVDS flat pael support */ 702c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 703c582b7e3Smrg "Non-LVDS panel interface detected! " 704c582b7e3Smrg "This support is untested and may not " 705c582b7e3Smrg "function properly\n"); 706c582b7e3Smrg } 707c582b7e3Smrg } 708c582b7e3Smrg 70999d7194aSmacallan#ifdef __NetBSD__ 71099d7194aSmacallan if (!info->PanelXRes || !info->PanelYRes) { 71199d7194aSmacallan /* 71299d7194aSmacallan * we may not be on x86 so check wsdisplay for panel dimensions 71399d7194aSmacallan * XXX this assumes that the r128 is the console, although that should 71499d7194aSmacallan * be the case in the vast majority of cases where an LCD is hooked up 71599d7194aSmacallan * directly 71699d7194aSmacallan * We should probably just check the relevant registers but I'm not 71799d7194aSmacallan * sure they're available at this point. 71899d7194aSmacallan */ 71999d7194aSmacallan struct wsdisplay_fbinfo fbinfo; 72099d7194aSmacallan 72199d7194aSmacallan if (ioctl(xf86Info.screenFd, WSDISPLAYIO_GINFO, &fbinfo) == 0) { 72299d7194aSmacallan info->PanelXRes = fbinfo.width; 72399d7194aSmacallan info->PanelYRes = fbinfo.height; 72499d7194aSmacallan } 72599d7194aSmacallan } 72699d7194aSmacallan#endif 72799d7194aSmacallan 728c582b7e3Smrg if (!info->PanelXRes || !info->PanelYRes) { 729c582b7e3Smrg info->HasPanelRegs = FALSE; 730c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 731c582b7e3Smrg "Can't determine panel dimensions, and none specified.\n" 732c582b7e3Smrg "\tDisabling programming of FP registers.\n"); 73399d7194aSmacallan } else { 73499d7194aSmacallan xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel size: %dx%d\n", 73599d7194aSmacallan info->PanelXRes, info->PanelYRes); 736c582b7e3Smrg } 737c582b7e3Smrg 738c582b7e3Smrg return TRUE; 739c582b7e3Smrg} 740c582b7e3Smrg 741c582b7e3Smrg/* Read PLL parameters from BIOS block. Default to typical values if there 742c582b7e3Smrg is no BIOS. */ 743c582b7e3Smrgstatic Bool R128GetPLLParameters(ScrnInfoPtr pScrn) 744c582b7e3Smrg{ 745c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 746c582b7e3Smrg R128PLLPtr pll = &info->pll; 747c582b7e3Smrg 748c582b7e3Smrg#if defined(__powerpc__) || defined(__alpha__) 749c582b7e3Smrg /* there is no bios under Linux PowerPC but Open Firmware 750c582b7e3Smrg does set up the PLL registers properly and we can use 751c582b7e3Smrg those to calculate xclk and find the reference divider */ 752c582b7e3Smrg 753c582b7e3Smrg unsigned x_mpll_ref_fb_div; 754c582b7e3Smrg unsigned xclk_cntl; 755c582b7e3Smrg unsigned Nx, M; 756c582b7e3Smrg unsigned PostDivSet[] = {0, 1, 2, 4, 8, 3, 6, 12}; 757c582b7e3Smrg 758c582b7e3Smrg /* Assume REF clock is 2950 (in units of 10khz) */ 759c582b7e3Smrg /* and that all pllclk must be between 125 Mhz and 250Mhz */ 760c582b7e3Smrg pll->reference_freq = 2950; 761c582b7e3Smrg pll->min_pll_freq = 12500; 762c582b7e3Smrg pll->max_pll_freq = 25000; 763c582b7e3Smrg 764c582b7e3Smrg /* need to memory map the io to use INPLL since it 765c582b7e3Smrg has not been done yet at this point in the startup */ 766c582b7e3Smrg R128MapMMIO(pScrn); 767c582b7e3Smrg x_mpll_ref_fb_div = INPLL(pScrn, R128_X_MPLL_REF_FB_DIV); 768c582b7e3Smrg xclk_cntl = INPLL(pScrn, R128_XCLK_CNTL) & 0x7; 769c582b7e3Smrg pll->reference_div = 770c582b7e3Smrg INPLL(pScrn,R128_PPLL_REF_DIV) & R128_PPLL_REF_DIV_MASK; 771c582b7e3Smrg /* unmap it again */ 772c582b7e3Smrg R128UnmapMMIO(pScrn); 773c582b7e3Smrg 774c582b7e3Smrg Nx = (x_mpll_ref_fb_div & 0x00FF00) >> 8; 775c582b7e3Smrg M = (x_mpll_ref_fb_div & 0x0000FF); 776c582b7e3Smrg 777c582b7e3Smrg pll->xclk = R128Div((2 * Nx * pll->reference_freq), 778c582b7e3Smrg (M * PostDivSet[xclk_cntl])); 779c582b7e3Smrg 780c582b7e3Smrg#else /* !defined(__powerpc__) */ 781c582b7e3Smrg 782c582b7e3Smrg if (!info->VBIOS) { 783c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 784c582b7e3Smrg "Video BIOS not detected, using default PLL parameters!\n"); 785c582b7e3Smrg /* These probably aren't going to work for 786c582b7e3Smrg the card you are using. Specifically, 787c582b7e3Smrg reference freq can be 29.50MHz, 788c582b7e3Smrg 28.63MHz, or 14.32MHz. YMMV. */ 789c582b7e3Smrg pll->reference_freq = 2950; 790c582b7e3Smrg pll->reference_div = 65; 791c582b7e3Smrg pll->min_pll_freq = 12500; 792c582b7e3Smrg pll->max_pll_freq = 25000; 793c582b7e3Smrg pll->xclk = 10300; 794c582b7e3Smrg } else { 795c582b7e3Smrg CARD16 bios_header = R128_BIOS16(0x48); 796c582b7e3Smrg CARD16 pll_info_block = R128_BIOS16(bios_header + 0x30); 797c582b7e3Smrg R128TRACE(("Header at 0x%04x; PLL Information at 0x%04x\n", 798c582b7e3Smrg bios_header, pll_info_block)); 799c582b7e3Smrg 800c582b7e3Smrg pll->reference_freq = R128_BIOS16(pll_info_block + 0x0e); 801c582b7e3Smrg pll->reference_div = R128_BIOS16(pll_info_block + 0x10); 802c582b7e3Smrg pll->min_pll_freq = R128_BIOS32(pll_info_block + 0x12); 803c582b7e3Smrg pll->max_pll_freq = R128_BIOS32(pll_info_block + 0x16); 804c582b7e3Smrg pll->xclk = R128_BIOS16(pll_info_block + 0x08); 805c582b7e3Smrg } 806c582b7e3Smrg#endif /* __powerpc__ */ 807c582b7e3Smrg 808c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 809c582b7e3Smrg "PLL parameters: rf=%d rd=%d min=%d max=%d; xclk=%d\n", 810c582b7e3Smrg pll->reference_freq, 811c582b7e3Smrg pll->reference_div, 812c582b7e3Smrg pll->min_pll_freq, 813c582b7e3Smrg pll->max_pll_freq, 814c582b7e3Smrg pll->xclk); 815c582b7e3Smrg 816c582b7e3Smrg return TRUE; 817c582b7e3Smrg} 818c582b7e3Smrg 819c582b7e3Smrg/* This is called by R128PreInit to set up the default visual. */ 820c582b7e3Smrgstatic Bool R128PreInitVisual(ScrnInfoPtr pScrn) 821c582b7e3Smrg{ 822c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 823c582b7e3Smrg 824c582b7e3Smrg if (!xf86SetDepthBpp(pScrn, 0, 0, 0, (Support24bppFb 825c582b7e3Smrg | Support32bppFb 826c582b7e3Smrg | SupportConvert32to24 827c582b7e3Smrg ))) 828c582b7e3Smrg return FALSE; 829c582b7e3Smrg 830c582b7e3Smrg switch (pScrn->depth) { 831c582b7e3Smrg case 8: 832c582b7e3Smrg case 15: 833c582b7e3Smrg case 16: 834c582b7e3Smrg case 24: 835c582b7e3Smrg break; 836c582b7e3Smrg default: 837c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 838c582b7e3Smrg "Given depth (%d) is not supported by %s driver\n", 839c582b7e3Smrg pScrn->depth, R128_DRIVER_NAME); 840c582b7e3Smrg return FALSE; 841c582b7e3Smrg } 842c582b7e3Smrg 843c582b7e3Smrg xf86PrintDepthBpp(pScrn); 844c582b7e3Smrg 845c582b7e3Smrg info->fifo_slots = 0; 846c582b7e3Smrg info->pix24bpp = xf86GetBppFromDepth(pScrn, pScrn->depth); 847c582b7e3Smrg info->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; 848c582b7e3Smrg info->CurrentLayout.depth = pScrn->depth; 849c582b7e3Smrg info->CurrentLayout.pixel_bytes = pScrn->bitsPerPixel / 8; 850c582b7e3Smrg info->CurrentLayout.pixel_code = (pScrn->bitsPerPixel != 16 851c582b7e3Smrg ? pScrn->bitsPerPixel 852c582b7e3Smrg : pScrn->depth); 853c582b7e3Smrg 854c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 855c582b7e3Smrg "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n", 856c582b7e3Smrg pScrn->depth, 857c582b7e3Smrg info->CurrentLayout.pixel_bytes, 858c582b7e3Smrg info->CurrentLayout.pixel_bytes > 1 ? "s" : "", 859c582b7e3Smrg info->pix24bpp); 860c582b7e3Smrg 861c582b7e3Smrg 862c582b7e3Smrg if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE; 863c582b7e3Smrg 864c582b7e3Smrg if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 865c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 866c582b7e3Smrg "Default visual (%s) is not supported at depth %d\n", 867c582b7e3Smrg xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 868c582b7e3Smrg return FALSE; 869c582b7e3Smrg } 870c582b7e3Smrg return TRUE; 871c582b7e3Smrg 872c582b7e3Smrg} 873c582b7e3Smrg 874c582b7e3Smrg/* This is called by R128PreInit to handle all color weight issues. */ 875c582b7e3Smrgstatic Bool R128PreInitWeight(ScrnInfoPtr pScrn) 876c582b7e3Smrg{ 877c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 878c582b7e3Smrg 879c582b7e3Smrg /* Save flag for 6 bit DAC to use for 880c582b7e3Smrg setting CRTC registers. Otherwise use 881c582b7e3Smrg an 8 bit DAC, even if xf86SetWeight sets 882c582b7e3Smrg pScrn->rgbBits to some value other than 883c582b7e3Smrg 8. */ 884c582b7e3Smrg info->dac6bits = FALSE; 885c582b7e3Smrg if (pScrn->depth > 8) { 886c582b7e3Smrg rgb defaultWeight = { 0, 0, 0 }; 887c582b7e3Smrg if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE; 888c582b7e3Smrg } else { 889c582b7e3Smrg pScrn->rgbBits = 8; 890c582b7e3Smrg if (xf86ReturnOptValBool(info->Options, OPTION_DAC_6BIT, FALSE)) { 891c582b7e3Smrg pScrn->rgbBits = 6; 892c582b7e3Smrg info->dac6bits = TRUE; 893c582b7e3Smrg } 894c582b7e3Smrg } 895c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 896c582b7e3Smrg "Using %d bits per RGB (%d bit DAC)\n", 897c582b7e3Smrg pScrn->rgbBits, info->dac6bits ? 6 : 8); 898c582b7e3Smrg 899c582b7e3Smrg return TRUE; 900c582b7e3Smrg 901c582b7e3Smrg} 902c582b7e3Smrg 903c582b7e3Smrg/* This is called by R128PreInit to handle config file overrides for things 904c582b7e3Smrg like chipset and memory regions. Also determine memory size and type. 905c582b7e3Smrg If memory type ever needs an override, put it in this routine. */ 906c582b7e3Smrgstatic Bool R128PreInitConfig(ScrnInfoPtr pScrn) 907c582b7e3Smrg{ 908c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 909c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 910c582b7e3Smrg EntityInfoPtr pEnt = info->pEnt; 911c582b7e3Smrg GDevPtr dev = pEnt->device; 912c582b7e3Smrg int offset = 0; /* RAM Type */ 913c582b7e3Smrg MessageType from; 914c582b7e3Smrg 915c582b7e3Smrg /* Chipset */ 916c582b7e3Smrg from = X_PROBED; 917c582b7e3Smrg if (dev->chipset && *dev->chipset) { 918c582b7e3Smrg info->Chipset = xf86StringToToken(R128Chipsets, dev->chipset); 919c582b7e3Smrg from = X_CONFIG; 920c582b7e3Smrg } else if (dev->chipID >= 0) { 921c582b7e3Smrg info->Chipset = dev->chipID; 922c582b7e3Smrg from = X_CONFIG; 923c582b7e3Smrg } else { 924c582b7e3Smrg info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo); 925c582b7e3Smrg } 926c582b7e3Smrg pScrn->chipset = (char *)xf86TokenToString(R128Chipsets, info->Chipset); 927c582b7e3Smrg 928c582b7e3Smrg if (!pScrn->chipset) { 929c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 930c582b7e3Smrg "ChipID 0x%04x is not recognized\n", info->Chipset); 931c582b7e3Smrg return FALSE; 932c582b7e3Smrg } 933c582b7e3Smrg 934c582b7e3Smrg if (info->Chipset < 0) { 935c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 936c582b7e3Smrg "Chipset \"%s\" is not recognized\n", pScrn->chipset); 937c582b7e3Smrg return FALSE; 938c582b7e3Smrg } 939c582b7e3Smrg 940c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, from, 941c582b7e3Smrg "Chipset: \"%s\" (ChipID = 0x%04x)\n", 942c582b7e3Smrg pScrn->chipset, 943c582b7e3Smrg info->Chipset); 944c582b7e3Smrg 945c582b7e3Smrg /* Framebuffer */ 946c582b7e3Smrg 947c582b7e3Smrg from = X_PROBED; 948c582b7e3Smrg info->LinearAddr = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & 0xfc000000; 949c582b7e3Smrg pScrn->memPhysBase = info->LinearAddr; 950c582b7e3Smrg if (dev->MemBase) { 951c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 952c582b7e3Smrg "Linear address override, using 0x%08lx instead of 0x%08lx\n", 953c582b7e3Smrg dev->MemBase, 954c582b7e3Smrg info->LinearAddr); 955c582b7e3Smrg info->LinearAddr = dev->MemBase; 956c582b7e3Smrg from = X_CONFIG; 957c582b7e3Smrg } else if (!info->LinearAddr) { 958c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 959c582b7e3Smrg "No valid linear framebuffer address\n"); 960c582b7e3Smrg return FALSE; 961c582b7e3Smrg } 962c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, from, 963c582b7e3Smrg "Linear framebuffer at 0x%08lx\n", info->LinearAddr); 964c582b7e3Smrg 965c582b7e3Smrg /* MMIO registers */ 966c582b7e3Smrg from = X_PROBED; 967c582b7e3Smrg info->MMIOAddr = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & 0xffffff00; 968c582b7e3Smrg if (dev->IOBase) { 969c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 970c582b7e3Smrg "MMIO address override, using 0x%08lx instead of 0x%08lx\n", 971c582b7e3Smrg dev->IOBase, 972c582b7e3Smrg info->MMIOAddr); 973c582b7e3Smrg info->MMIOAddr = dev->IOBase; 974c582b7e3Smrg from = X_CONFIG; 975c582b7e3Smrg } else if (!info->MMIOAddr) { 976c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n"); 977c582b7e3Smrg return FALSE; 978c582b7e3Smrg } 979c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, from, 980c582b7e3Smrg "MMIO registers at 0x%08lx\n", info->MMIOAddr); 981c582b7e3Smrg 982c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS 983c582b7e3Smrg /* BIOS */ 984c582b7e3Smrg from = X_PROBED; 985c582b7e3Smrg info->BIOSAddr = info->PciInfo->biosBase & 0xfffe0000; 986c582b7e3Smrg if (dev->BiosBase) { 987c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 988c582b7e3Smrg "BIOS address override, using 0x%08lx instead of 0x%08lx\n", 989c582b7e3Smrg dev->BiosBase, 990c582b7e3Smrg info->BIOSAddr); 991c582b7e3Smrg info->BIOSAddr = dev->BiosBase; 992c582b7e3Smrg from = X_CONFIG; 993c582b7e3Smrg } 994c582b7e3Smrg if (info->BIOSAddr) { 995c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, from, 996c582b7e3Smrg "BIOS at 0x%08lx\n", info->BIOSAddr); 997c582b7e3Smrg } 998c582b7e3Smrg#endif 999c582b7e3Smrg 1000c582b7e3Smrg /* Flat panel (part 1) */ 1001c582b7e3Smrg if (xf86GetOptValBool(info->Options, OPTION_PROG_FP_REGS, 1002c582b7e3Smrg &info->HasPanelRegs)) { 1003c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1004c582b7e3Smrg "Turned flat panel register programming %s\n", 1005c582b7e3Smrg info->HasPanelRegs ? "on" : "off"); 1006c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1007c582b7e3Smrg "\n\nWARNING: Forcing the driver to use/not use the flat panel registers\nmight damage your flat panel. Use at your *OWN* *RISK*.\n\n"); 1008c582b7e3Smrg } else { 1009c582b7e3Smrg info->isDFP = FALSE; 1010c582b7e3Smrg info->isPro2 = FALSE; 1011c582b7e3Smrg info->HasCRTC2 = FALSE; 1012c582b7e3Smrg switch (info->Chipset) { 1013c582b7e3Smrg /* R128 Pro and Pro2 can have DFP, we will deal with it. 1014c582b7e3Smrg No support for dual-head/xinerama yet. 1015c582b7e3Smrg M3 can also have DFP, no support for now */ 1016c582b7e3Smrg case PCI_CHIP_RAGE128TF: 1017c582b7e3Smrg case PCI_CHIP_RAGE128TL: 1018c582b7e3Smrg case PCI_CHIP_RAGE128TR: 1019c582b7e3Smrg /* FIXME: RAGE128 TS/TT/TU are assumed to be PRO2 as all 6 chips came 1020c582b7e3Smrg * out at the same time, so are of the same family likely. 1021c582b7e3Smrg * This requires confirmation however to be fully correct. 1022c582b7e3Smrg * Mike A. Harris <mharris@redhat.com> 1023c582b7e3Smrg */ 1024c582b7e3Smrg case PCI_CHIP_RAGE128TS: 1025c582b7e3Smrg case PCI_CHIP_RAGE128TT: 1026c582b7e3Smrg case PCI_CHIP_RAGE128TU: info->isPro2 = TRUE; 1027c582b7e3Smrg /* FIXME: RAGE128 P[ABCEGHIJKLMNOQSTUVWX] are assumed to have DFP 1028c582b7e3Smrg * capability, as the comment at the top suggests. 1029c582b7e3Smrg * This requires confirmation however to be fully correct. 1030c582b7e3Smrg * Mike A. Harris <mharris@redhat.com> 1031c582b7e3Smrg */ 1032c582b7e3Smrg case PCI_CHIP_RAGE128PA: 1033c582b7e3Smrg case PCI_CHIP_RAGE128PB: 1034c582b7e3Smrg case PCI_CHIP_RAGE128PC: 1035c582b7e3Smrg case PCI_CHIP_RAGE128PE: 1036c582b7e3Smrg case PCI_CHIP_RAGE128PG: 1037c582b7e3Smrg case PCI_CHIP_RAGE128PH: 1038c582b7e3Smrg case PCI_CHIP_RAGE128PI: 1039c582b7e3Smrg case PCI_CHIP_RAGE128PJ: 1040c582b7e3Smrg case PCI_CHIP_RAGE128PK: 1041c582b7e3Smrg case PCI_CHIP_RAGE128PL: 1042c582b7e3Smrg case PCI_CHIP_RAGE128PM: 1043c582b7e3Smrg case PCI_CHIP_RAGE128PN: 1044c582b7e3Smrg case PCI_CHIP_RAGE128PO: 1045c582b7e3Smrg case PCI_CHIP_RAGE128PQ: 1046c582b7e3Smrg case PCI_CHIP_RAGE128PS: 1047c582b7e3Smrg case PCI_CHIP_RAGE128PT: 1048c582b7e3Smrg case PCI_CHIP_RAGE128PU: 1049c582b7e3Smrg case PCI_CHIP_RAGE128PV: 1050c582b7e3Smrg case PCI_CHIP_RAGE128PW: 1051c582b7e3Smrg case PCI_CHIP_RAGE128PX: 1052c582b7e3Smrg 1053c582b7e3Smrg case PCI_CHIP_RAGE128PD: 1054c582b7e3Smrg case PCI_CHIP_RAGE128PF: 1055c582b7e3Smrg case PCI_CHIP_RAGE128PP: 1056c582b7e3Smrg case PCI_CHIP_RAGE128PR: info->isDFP = TRUE; break; 1057c582b7e3Smrg 1058c582b7e3Smrg case PCI_CHIP_RAGE128LE: 1059c582b7e3Smrg case PCI_CHIP_RAGE128LF: 1060c582b7e3Smrg case PCI_CHIP_RAGE128MF: 1061c582b7e3Smrg case PCI_CHIP_RAGE128ML: 1062c582b7e3Smrg info->HasPanelRegs = TRUE; 1063c582b7e3Smrg /* which chips support dualhead? */ 1064c582b7e3Smrg info->HasCRTC2 = TRUE; 1065c582b7e3Smrg break; 1066c582b7e3Smrg case PCI_CHIP_RAGE128RE: 1067c582b7e3Smrg case PCI_CHIP_RAGE128RF: 1068c582b7e3Smrg case PCI_CHIP_RAGE128RG: 1069c582b7e3Smrg case PCI_CHIP_RAGE128RK: 1070c582b7e3Smrg case PCI_CHIP_RAGE128RL: 1071c582b7e3Smrg case PCI_CHIP_RAGE128SM: 1072c582b7e3Smrg /* FIXME: RAGE128 S[EFGHKLN] are assumed to be like the SM above as 1073c582b7e3Smrg * all of them are listed as "Rage 128 4x" in ATI docs. 1074c582b7e3Smrg * This requires confirmation however to be fully correct. 1075c582b7e3Smrg * Mike A. Harris <mharris@redhat.com> 1076c582b7e3Smrg */ 1077c582b7e3Smrg case PCI_CHIP_RAGE128SE: 1078c582b7e3Smrg case PCI_CHIP_RAGE128SF: 1079c582b7e3Smrg case PCI_CHIP_RAGE128SG: 1080c582b7e3Smrg case PCI_CHIP_RAGE128SH: 1081c582b7e3Smrg case PCI_CHIP_RAGE128SK: 1082c582b7e3Smrg case PCI_CHIP_RAGE128SL: 1083c582b7e3Smrg case PCI_CHIP_RAGE128SN: 1084c582b7e3Smrg default: info->HasPanelRegs = FALSE; break; 1085c582b7e3Smrg } 1086c582b7e3Smrg } 1087c582b7e3Smrg 1088c582b7e3Smrg /* Read registers used to determine options */ 1089c582b7e3Smrg from = X_PROBED; 1090c582b7e3Smrg R128MapMMIO(pScrn); 1091c582b7e3Smrg R128MMIO = info->MMIO; 1092c582b7e3Smrg 109379e5230eSmacallan#ifndef AVOID_FBDEV 1094c582b7e3Smrg if (info->FBDev) 1095c582b7e3Smrg pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024; 1096c582b7e3Smrg else 109779e5230eSmacallan#endif 1098c582b7e3Smrg pScrn->videoRam = INREG(R128_CONFIG_MEMSIZE) / 1024; 1099c582b7e3Smrg 1100c582b7e3Smrg info->MemCntl = INREG(R128_MEM_CNTL); 1101c582b7e3Smrg info->BusCntl = INREG(R128_BUS_CNTL); 1102c582b7e3Smrg 1103c582b7e3Smrg /* On non-flat panel systems, the default is to display to the CRT, 1104c582b7e3Smrg and on flat panel systems, the default is to display to the flat 1105c582b7e3Smrg panel unless the user explicity chooses otherwise using the "Display" 1106c582b7e3Smrg config file setting. BIOS_5_SCRATCH holds the display device on flat 1107c582b7e3Smrg panel systems only. */ 1108c582b7e3Smrg if (info->HasPanelRegs) { 1109c582b7e3Smrg char *Display = xf86GetOptValString(info->Options, OPTION_DISPLAY); 1110c582b7e3Smrg 111179e5230eSmacallan#ifndef AVOID_FBDEV 1112c582b7e3Smrg if (info->FBDev) 1113c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1114c582b7e3Smrg "Option \"Display\" ignored " 1115c582b7e3Smrg "(framebuffer device determines display type)\n"); 111679e5230eSmacallan else 111779e5230eSmacallan#endif 111879e5230eSmacallan if (info->IsPrimary || info->IsSecondary) 1119c582b7e3Smrg info->BIOSDisplay = R128_DUALHEAD; 1120c582b7e3Smrg else if (!Display || !xf86NameCmp(Display, "FP")) 1121c582b7e3Smrg info->BIOSDisplay = R128_BIOS_DISPLAY_FP; 1122c582b7e3Smrg else if (!xf86NameCmp(Display, "BIOS")) 1123c582b7e3Smrg info->BIOSDisplay = INREG8(R128_BIOS_5_SCRATCH); 1124c582b7e3Smrg else if (!xf86NameCmp(Display, "Mirror")) 1125c582b7e3Smrg info->BIOSDisplay = R128_BIOS_DISPLAY_FP_CRT; 1126c582b7e3Smrg else if (!xf86NameCmp(Display, "CRT")) 1127c582b7e3Smrg info->BIOSDisplay = R128_BIOS_DISPLAY_CRT; 1128c582b7e3Smrg else { 1129c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1130c582b7e3Smrg "Unsupported type \"%s\" specified for Option \"Display\".\n" 1131c582b7e3Smrg "\tSupported types are: " 1132c582b7e3Smrg "\"BIOS\", \"Mirror\", \"CRT\" and \"FP\"\n", Display); 1133c582b7e3Smrg return FALSE; 1134c582b7e3Smrg } 1135c582b7e3Smrg } else { 1136c582b7e3Smrg info->BIOSDisplay = R128_BIOS_DISPLAY_CRT; 1137c582b7e3Smrg } 1138c582b7e3Smrg 1139c582b7e3Smrg R128MMIO = NULL; 1140c582b7e3Smrg R128UnmapMMIO(pScrn); 1141c582b7e3Smrg 1142c582b7e3Smrg /* RAM */ 1143c582b7e3Smrg switch (info->MemCntl & 0x3) { 1144c582b7e3Smrg case 0: /* SDR SGRAM 1:1 */ 1145c582b7e3Smrg switch (info->Chipset) { 1146c582b7e3Smrg case PCI_CHIP_RAGE128TF: 1147c582b7e3Smrg case PCI_CHIP_RAGE128TL: 1148c582b7e3Smrg case PCI_CHIP_RAGE128TR: 1149c582b7e3Smrg case PCI_CHIP_RAGE128LE: 1150c582b7e3Smrg case PCI_CHIP_RAGE128LF: 1151c582b7e3Smrg case PCI_CHIP_RAGE128MF: 1152c582b7e3Smrg case PCI_CHIP_RAGE128ML: 1153c582b7e3Smrg case PCI_CHIP_RAGE128RE: 1154c582b7e3Smrg case PCI_CHIP_RAGE128RF: 1155c582b7e3Smrg case PCI_CHIP_RAGE128RG: offset = 0; break; /* 128-bit SDR SGRAM 1:1 */ 1156c582b7e3Smrg case PCI_CHIP_RAGE128RK: 1157c582b7e3Smrg case PCI_CHIP_RAGE128RL: 1158c582b7e3Smrg case PCI_CHIP_RAGE128SM: 1159c582b7e3Smrg default: offset = 1; break; /* 64-bit SDR SGRAM 1:1 */ 1160c582b7e3Smrg } 1161c582b7e3Smrg break; 1162c582b7e3Smrg case 1: offset = 2; break; /* 64-bit SDR SGRAM 2:1 */ 1163c582b7e3Smrg case 2: offset = 3; break; /* 64-bit DDR SGRAM */ 1164c582b7e3Smrg default: offset = 1; break; /* 64-bit SDR SGRAM 1:1 */ 1165c582b7e3Smrg } 1166c582b7e3Smrg info->ram = &R128RAM[offset]; 1167c582b7e3Smrg 1168c582b7e3Smrg if (dev->videoRam) { 1169c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1170c582b7e3Smrg "Video RAM override, using %d kB instead of %d kB\n", 1171c582b7e3Smrg dev->videoRam, 1172c582b7e3Smrg pScrn->videoRam); 1173c582b7e3Smrg from = X_CONFIG; 1174c582b7e3Smrg pScrn->videoRam = dev->videoRam; 1175c582b7e3Smrg } 1176c582b7e3Smrg 1177c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, from, 1178c582b7e3Smrg "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name); 1179c582b7e3Smrg 1180c582b7e3Smrg if (info->IsPrimary) { 1181c582b7e3Smrg pScrn->videoRam /= 2; 1182c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1183c582b7e3Smrg "Using %dk of videoram for primary head\n", 1184c582b7e3Smrg pScrn->videoRam); 1185c582b7e3Smrg } 1186c582b7e3Smrg 1187c582b7e3Smrg if (info->IsSecondary) { 1188c582b7e3Smrg pScrn->videoRam /= 2; 1189c582b7e3Smrg info->LinearAddr += pScrn->videoRam * 1024; 1190c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1191c582b7e3Smrg "Using %dk of videoram for secondary head\n", 1192c582b7e3Smrg pScrn->videoRam); 1193c582b7e3Smrg } 1194c582b7e3Smrg 1195c582b7e3Smrg pScrn->videoRam &= ~1023; 1196c582b7e3Smrg info->FbMapSize = pScrn->videoRam * 1024; 1197c582b7e3Smrg 1198c582b7e3Smrg 1199c582b7e3Smrg /* Flat panel (part 2) */ 1200c582b7e3Smrg switch (info->BIOSDisplay) { 1201c582b7e3Smrg case R128_DUALHEAD: 1202c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1203c582b7e3Smrg "Dual display\n"); 1204c582b7e3Smrg break; 1205c582b7e3Smrg case R128_BIOS_DISPLAY_FP: 1206c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1207c582b7e3Smrg "Using flat panel for display\n"); 1208c582b7e3Smrg break; 1209c582b7e3Smrg case R128_BIOS_DISPLAY_CRT: 1210c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1211c582b7e3Smrg "Using external CRT for display\n"); 1212c582b7e3Smrg break; 1213c582b7e3Smrg case R128_BIOS_DISPLAY_FP_CRT: 1214c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1215c582b7e3Smrg "Using both flat panel and external CRT " 1216c582b7e3Smrg "for display\n"); 1217c582b7e3Smrg break; 1218c582b7e3Smrg } 1219c582b7e3Smrg 1220c582b7e3Smrg if (info->HasPanelRegs) { 1221c582b7e3Smrg /* Panel width/height overrides */ 1222c582b7e3Smrg info->PanelXRes = 0; 1223c582b7e3Smrg info->PanelYRes = 0; 1224c582b7e3Smrg if (xf86GetOptValInteger(info->Options, 1225c582b7e3Smrg OPTION_PANEL_WIDTH, &(info->PanelXRes))) { 1226c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1227c582b7e3Smrg "Flat panel width: %d\n", info->PanelXRes); 1228c582b7e3Smrg } 1229c582b7e3Smrg if (xf86GetOptValInteger(info->Options, 1230c582b7e3Smrg OPTION_PANEL_HEIGHT, &(info->PanelYRes))) { 1231c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1232c582b7e3Smrg "Flat panel height: %d\n", info->PanelYRes); 1233c582b7e3Smrg } 1234c582b7e3Smrg } 1235c582b7e3Smrg 1236c582b7e3Smrg#ifdef XF86DRI 1237c582b7e3Smrg /* DMA for Xv */ 1238c582b7e3Smrg info->DMAForXv = xf86ReturnOptValBool(info->Options, OPTION_XV_DMA, FALSE); 1239c582b7e3Smrg if (info->DMAForXv) { 1240c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1241c582b7e3Smrg "Will try to use DMA for Xv image transfers\n"); 1242c582b7e3Smrg } 1243c582b7e3Smrg 1244c582b7e3Smrg /* AGP/PCI */ 1245c582b7e3Smrg if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) { 1246c582b7e3Smrg info->IsPCI = TRUE; 1247c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI-only mode\n"); 1248c582b7e3Smrg } else { 1249c582b7e3Smrg switch (info->Chipset) { 1250c582b7e3Smrg case PCI_CHIP_RAGE128LE: 1251c582b7e3Smrg case PCI_CHIP_RAGE128RE: 1252c582b7e3Smrg case PCI_CHIP_RAGE128RK: 1253c582b7e3Smrg case PCI_CHIP_RAGE128PD: 1254c582b7e3Smrg case PCI_CHIP_RAGE128PR: 1255c582b7e3Smrg case PCI_CHIP_RAGE128PP: info->IsPCI = TRUE; break; 1256c582b7e3Smrg case PCI_CHIP_RAGE128LF: 1257c582b7e3Smrg case PCI_CHIP_RAGE128MF: 1258c582b7e3Smrg case PCI_CHIP_RAGE128ML: 1259c582b7e3Smrg case PCI_CHIP_RAGE128PF: 1260c582b7e3Smrg case PCI_CHIP_RAGE128RF: 1261c582b7e3Smrg case PCI_CHIP_RAGE128RG: 1262c582b7e3Smrg case PCI_CHIP_RAGE128RL: 1263c582b7e3Smrg case PCI_CHIP_RAGE128SM: 1264c582b7e3Smrg case PCI_CHIP_RAGE128TF: 1265c582b7e3Smrg case PCI_CHIP_RAGE128TL: 1266c582b7e3Smrg case PCI_CHIP_RAGE128TR: 1267c582b7e3Smrg /* FIXME: Rage 128 S[EFGHKLN], T[STU], P[ABCEGHIJKLMNOQSTUVWX] are 1268c582b7e3Smrg * believed to be AGP, but need confirmation. <mharris@redhat.com> 1269c582b7e3Smrg */ 1270c582b7e3Smrg case PCI_CHIP_RAGE128PA: 1271c582b7e3Smrg case PCI_CHIP_RAGE128PB: 1272c582b7e3Smrg case PCI_CHIP_RAGE128PC: 1273c582b7e3Smrg case PCI_CHIP_RAGE128PE: 1274c582b7e3Smrg case PCI_CHIP_RAGE128PG: 1275c582b7e3Smrg case PCI_CHIP_RAGE128PH: 1276c582b7e3Smrg case PCI_CHIP_RAGE128PI: 1277c582b7e3Smrg case PCI_CHIP_RAGE128PJ: 1278c582b7e3Smrg case PCI_CHIP_RAGE128PK: 1279c582b7e3Smrg case PCI_CHIP_RAGE128PL: 1280c582b7e3Smrg case PCI_CHIP_RAGE128PM: 1281c582b7e3Smrg case PCI_CHIP_RAGE128PN: 1282c582b7e3Smrg case PCI_CHIP_RAGE128PO: 1283c582b7e3Smrg case PCI_CHIP_RAGE128PQ: 1284c582b7e3Smrg case PCI_CHIP_RAGE128PS: 1285c582b7e3Smrg case PCI_CHIP_RAGE128PT: 1286c582b7e3Smrg case PCI_CHIP_RAGE128PU: 1287c582b7e3Smrg case PCI_CHIP_RAGE128PV: 1288c582b7e3Smrg case PCI_CHIP_RAGE128PW: 1289c582b7e3Smrg case PCI_CHIP_RAGE128PX: 1290c582b7e3Smrg case PCI_CHIP_RAGE128TS: 1291c582b7e3Smrg case PCI_CHIP_RAGE128TT: 1292c582b7e3Smrg case PCI_CHIP_RAGE128TU: 1293c582b7e3Smrg case PCI_CHIP_RAGE128SE: 1294c582b7e3Smrg case PCI_CHIP_RAGE128SF: 1295c582b7e3Smrg case PCI_CHIP_RAGE128SG: 1296c582b7e3Smrg case PCI_CHIP_RAGE128SH: 1297c582b7e3Smrg case PCI_CHIP_RAGE128SK: 1298c582b7e3Smrg case PCI_CHIP_RAGE128SL: 1299c582b7e3Smrg case PCI_CHIP_RAGE128SN: 1300c582b7e3Smrg default: info->IsPCI = FALSE; break; 1301c582b7e3Smrg } 1302c582b7e3Smrg } 1303c582b7e3Smrg#endif 1304c582b7e3Smrg 1305c582b7e3Smrg return TRUE; 1306c582b7e3Smrg} 1307c582b7e3Smrg 1308c582b7e3Smrgstatic Bool R128PreInitDDC(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) 1309c582b7e3Smrg{ 1310c582b7e3Smrg#if !defined(__powerpc__) && !defined(__alpha__) && !defined(__sparc__) 1311c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1312c582b7e3Smrg vbeInfoPtr pVbe; 1313c582b7e3Smrg#endif 1314c582b7e3Smrg 1315c582b7e3Smrg if (!xf86LoadSubModule(pScrn, "ddc")) return FALSE; 1316c582b7e3Smrg 1317c582b7e3Smrg#if defined(__powerpc__) || defined(__alpha__) || defined(__sparc__) 1318c582b7e3Smrg /* Int10 is broken on PPC and some Alphas */ 1319c582b7e3Smrg return TRUE; 1320c582b7e3Smrg#else 1321c582b7e3Smrg if (xf86LoadSubModule(pScrn, "vbe")) { 1322c582b7e3Smrg pVbe = VBEInit(pInt10,info->pEnt->index); 1323c582b7e3Smrg if (!pVbe) return FALSE; 1324c582b7e3Smrg xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(pVbe,NULL))); 1325c582b7e3Smrg vbeFree(pVbe); 1326c582b7e3Smrg return TRUE; 1327c582b7e3Smrg } else 1328c582b7e3Smrg return FALSE; 1329c582b7e3Smrg#endif 1330c582b7e3Smrg} 1331c582b7e3Smrg 1332c582b7e3Smrg/* This is called by R128PreInit to initialize gamma correction. */ 1333c582b7e3Smrgstatic Bool R128PreInitGamma(ScrnInfoPtr pScrn) 1334c582b7e3Smrg{ 1335c582b7e3Smrg Gamma zeros = { 0.0, 0.0, 0.0 }; 1336c582b7e3Smrg 1337c582b7e3Smrg if (!xf86SetGamma(pScrn, zeros)) return FALSE; 1338c582b7e3Smrg return TRUE; 1339c582b7e3Smrg} 1340c582b7e3Smrg 1341c582b7e3Smrgstatic void 1342c582b7e3SmrgR128I2CGetBits(I2CBusPtr b, int *Clock, int *data) 1343c582b7e3Smrg{ 1344c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 1345c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1346c582b7e3Smrg unsigned long val; 1347c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 1348c582b7e3Smrg 1349c582b7e3Smrg /* Get the result. */ 1350c582b7e3Smrg val = INREG(info->DDCReg); 1351c582b7e3Smrg *Clock = (val & R128_GPIO_MONID_Y_3) != 0; 1352c582b7e3Smrg *data = (val & R128_GPIO_MONID_Y_0) != 0; 1353c582b7e3Smrg 1354c582b7e3Smrg} 1355c582b7e3Smrg 1356c582b7e3Smrgstatic void 1357c582b7e3SmrgR128I2CPutBits(I2CBusPtr b, int Clock, int data) 1358c582b7e3Smrg{ 1359c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 1360c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1361c582b7e3Smrg unsigned long val; 1362c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 1363c582b7e3Smrg 1364c582b7e3Smrg val = INREG(info->DDCReg) 1365c582b7e3Smrg & ~(CARD32)(R128_GPIO_MONID_EN_0 | R128_GPIO_MONID_EN_3); 1366c582b7e3Smrg val |= (Clock ? 0:R128_GPIO_MONID_EN_3); 1367c582b7e3Smrg val |= (data ? 0:R128_GPIO_MONID_EN_0); 1368c582b7e3Smrg OUTREG(info->DDCReg, val); 1369c582b7e3Smrg} 1370c582b7e3Smrg 1371c582b7e3Smrg 1372c582b7e3Smrgstatic Bool 1373c582b7e3SmrgR128I2cInit(ScrnInfoPtr pScrn) 1374c582b7e3Smrg{ 1375c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1376c582b7e3Smrg if ( !xf86LoadSubModule(pScrn, "i2c") ) { 1377c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1378c582b7e3Smrg "Failed to load i2c module\n"); 1379c582b7e3Smrg return FALSE; 1380c582b7e3Smrg } 1381c582b7e3Smrg 1382c582b7e3Smrg info->pI2CBus = xf86CreateI2CBusRec(); 1383c582b7e3Smrg if(!info->pI2CBus) return FALSE; 1384c582b7e3Smrg 1385c582b7e3Smrg info->pI2CBus->BusName = "DDC"; 1386c582b7e3Smrg info->pI2CBus->scrnIndex = pScrn->scrnIndex; 1387c582b7e3Smrg info->DDCReg = R128_GPIO_MONID; 1388c582b7e3Smrg info->pI2CBus->I2CPutBits = R128I2CPutBits; 1389c582b7e3Smrg info->pI2CBus->I2CGetBits = R128I2CGetBits; 1390c582b7e3Smrg info->pI2CBus->AcknTimeout = 5; 1391c582b7e3Smrg 1392c582b7e3Smrg if (!xf86I2CBusInit(info->pI2CBus)) { 1393c582b7e3Smrg return FALSE; 1394c582b7e3Smrg } 1395c582b7e3Smrg return TRUE; 1396c582b7e3Smrg} 1397c582b7e3Smrg 1398e86a9069Smacallan/* XXX 1399e86a9069Smacallan * the following comment is bogus - the code scans the main monitor port, 1400e86a9069Smacallan * not R128_GPIO_MONIDB 1401e86a9069Smacallan */ 1402c582b7e3Smrg/* return TRUE is a DFP is indeed connected to a DVI port */ 1403c582b7e3Smrgstatic Bool R128GetDFPInfo(ScrnInfoPtr pScrn) 1404c582b7e3Smrg{ 1405c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1406c582b7e3Smrg int i; 1407c582b7e3Smrg xf86MonPtr MonInfo = NULL; 1408c582b7e3Smrg xf86MonPtr ddc; 1409c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 1410c582b7e3Smrg 1411c582b7e3Smrg if(!R128I2cInit(pScrn)){ 1412c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1413c582b7e3Smrg "I2C initialization failed!\n"); 1414c582b7e3Smrg } 1415c582b7e3Smrg 1416c582b7e3Smrg OUTREG(info->DDCReg, (INREG(info->DDCReg) 1417c582b7e3Smrg | R128_GPIO_MONID_MASK_0 | R128_GPIO_MONID_MASK_3)); 1418c582b7e3Smrg 1419c582b7e3Smrg OUTREG(info->DDCReg, INREG(info->DDCReg) 1420c582b7e3Smrg & ~(CARD32)(R128_GPIO_MONID_A_0 | R128_GPIO_MONID_A_3)); 1421c582b7e3Smrg 1422c582b7e3Smrg MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus); 1423e86a9069Smacallan#ifdef __NetBSD__ 1424e86a9069Smacallan { 1425e86a9069Smacallan struct wsdisplayio_edid_info ei; 1426e86a9069Smacallan char buffer[1024]; 1427e86a9069Smacallan int i, j; 1428e86a9069Smacallan 1429e86a9069Smacallan ei.edid_data = buffer; 1430e86a9069Smacallan ei.buffer_size = 1024; 1431e86a9069Smacallan if (ioctl(xf86Info.screenFd, WSDISPLAYIO_GET_EDID, &ei) != -1) { 1432e86a9069Smacallan xf86Msg(X_INFO, "got %d bytes worth of EDID from wsdisplay\n", ei.data_size); 1433e86a9069Smacallan MonInfo = xf86InterpretEDID(pScrn->scrnIndex, buffer); 1434e86a9069Smacallan } else 1435e86a9069Smacallan xf86Msg(X_INFO, "ioctl failed %d\n", errno); 1436e86a9069Smacallan } 1437e86a9069Smacallan#endif 1438e86a9069Smacallan 1439c582b7e3Smrg if(!MonInfo) { 1440c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1441c582b7e3Smrg "No DFP detected\n"); 1442c582b7e3Smrg return FALSE; 1443c582b7e3Smrg } 1444c582b7e3Smrg xf86SetDDCproperties(pScrn, MonInfo); 1445c582b7e3Smrg ddc = pScrn->monitor->DDC; 1446c582b7e3Smrg 1447c582b7e3Smrg for(i=0; i<4; i++) 1448c582b7e3Smrg { 1449c582b7e3Smrg if((ddc->det_mon[i].type == 0) && 1450c582b7e3Smrg (ddc->det_mon[i].section.d_timings.h_active > 0) && 1451c582b7e3Smrg (ddc->det_mon[i].section.d_timings.v_active > 0)) 1452c582b7e3Smrg { 1453c582b7e3Smrg info->PanelXRes = 1454c582b7e3Smrg ddc->det_mon[i].section.d_timings.h_active; 1455c582b7e3Smrg info->PanelYRes = 1456c582b7e3Smrg ddc->det_mon[i].section.d_timings.v_active; 1457c582b7e3Smrg 1458c582b7e3Smrg info->HOverPlus = 1459c582b7e3Smrg ddc->det_mon[i].section.d_timings.h_sync_off; 1460c582b7e3Smrg info->HSyncWidth = 1461c582b7e3Smrg ddc->det_mon[i].section.d_timings.h_sync_width; 1462c582b7e3Smrg info->HBlank = 1463c582b7e3Smrg ddc->det_mon[i].section.d_timings.h_blanking; 1464c582b7e3Smrg info->VOverPlus = 1465c582b7e3Smrg ddc->det_mon[i].section.d_timings.v_sync_off; 1466c582b7e3Smrg info->VSyncWidth = 1467c582b7e3Smrg ddc->det_mon[i].section.d_timings.v_sync_width; 1468c582b7e3Smrg info->VBlank = 1469c582b7e3Smrg ddc->det_mon[i].section.d_timings.v_blanking; 1470c582b7e3Smrg } 1471c582b7e3Smrg } 1472c582b7e3Smrg return TRUE; 1473c582b7e3Smrg} 1474c582b7e3Smrg 1475c582b7e3Smrg 1476c582b7e3Smrgstatic void R128SetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) 1477c582b7e3Smrg{ 1478c582b7e3Smrg int i; 1479c582b7e3Smrg xf86MonPtr ddc = pScrn->monitor->DDC; 1480c582b7e3Smrg if(flag) /*HSync*/ 1481c582b7e3Smrg { 1482c582b7e3Smrg for(i=0; i<4; i++) 1483c582b7e3Smrg { 1484c582b7e3Smrg if(ddc->det_mon[i].type == DS_RANGES) 1485c582b7e3Smrg { 1486c582b7e3Smrg pScrn->monitor->nHsync = 1; 1487c582b7e3Smrg pScrn->monitor->hsync[0].lo = 1488c582b7e3Smrg ddc->det_mon[i].section.ranges.min_h; 1489c582b7e3Smrg pScrn->monitor->hsync[0].hi = 1490c582b7e3Smrg ddc->det_mon[i].section.ranges.max_h; 1491c582b7e3Smrg return; 1492c582b7e3Smrg } 1493c582b7e3Smrg } 1494c582b7e3Smrg /*if no sync ranges detected in detailed timing table, 1495c582b7e3Smrg let's try to derive them from supported VESA modes 1496c582b7e3Smrg Are we doing too much here!!!? 1497c582b7e3Smrg **/ 1498c582b7e3Smrg i = 0; 1499c582b7e3Smrg if(ddc->timings1.t1 & 0x02) /*800x600@56*/ 1500c582b7e3Smrg { 1501c582b7e3Smrg pScrn->monitor->hsync[i].lo = 1502c582b7e3Smrg pScrn->monitor->hsync[i].hi = 35.2; 1503c582b7e3Smrg i++; 1504c582b7e3Smrg } 1505c582b7e3Smrg if(ddc->timings1.t1 & 0x04) /*640x480@75*/ 1506c582b7e3Smrg { 1507c582b7e3Smrg pScrn->monitor->hsync[i].lo = 1508c582b7e3Smrg pScrn->monitor->hsync[i].hi = 37.5; 1509c582b7e3Smrg i++; 1510c582b7e3Smrg } 1511c582b7e3Smrg if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01)) 1512c582b7e3Smrg { 1513c582b7e3Smrg pScrn->monitor->hsync[i].lo = 1514c582b7e3Smrg pScrn->monitor->hsync[i].hi = 37.9; 1515c582b7e3Smrg i++; 1516c582b7e3Smrg } 1517c582b7e3Smrg if(ddc->timings1.t2 & 0x40) 1518c582b7e3Smrg { 1519c582b7e3Smrg pScrn->monitor->hsync[i].lo = 1520c582b7e3Smrg pScrn->monitor->hsync[i].hi = 46.9; 1521c582b7e3Smrg i++; 1522c582b7e3Smrg } 1523c582b7e3Smrg if((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08)) 1524c582b7e3Smrg { 1525c582b7e3Smrg pScrn->monitor->hsync[i].lo = 1526c582b7e3Smrg pScrn->monitor->hsync[i].hi = 48.1; 1527c582b7e3Smrg i++; 1528c582b7e3Smrg } 1529c582b7e3Smrg if(ddc->timings1.t2 & 0x04) 1530c582b7e3Smrg { 1531c582b7e3Smrg pScrn->monitor->hsync[i].lo = 1532c582b7e3Smrg pScrn->monitor->hsync[i].hi = 56.5; 1533c582b7e3Smrg i++; 1534c582b7e3Smrg } 1535c582b7e3Smrg if(ddc->timings1.t2 & 0x02) 1536c582b7e3Smrg { 1537c582b7e3Smrg pScrn->monitor->hsync[i].lo = 1538c582b7e3Smrg pScrn->monitor->hsync[i].hi = 60.0; 1539c582b7e3Smrg i++; 1540c582b7e3Smrg } 1541c582b7e3Smrg if(ddc->timings1.t2 & 0x01) 1542c582b7e3Smrg { 1543c582b7e3Smrg pScrn->monitor->hsync[i].lo = 1544c582b7e3Smrg pScrn->monitor->hsync[i].hi = 64.0; 1545c582b7e3Smrg i++; 1546c582b7e3Smrg } 1547c582b7e3Smrg pScrn->monitor->nHsync = i; 1548c582b7e3Smrg } 1549c582b7e3Smrg else /*Vrefresh*/ 1550c582b7e3Smrg { 1551c582b7e3Smrg for(i=0; i<4; i++) 1552c582b7e3Smrg { 1553c582b7e3Smrg if(ddc->det_mon[i].type == DS_RANGES) 1554c582b7e3Smrg { 1555c582b7e3Smrg pScrn->monitor->nVrefresh = 1; 1556c582b7e3Smrg pScrn->monitor->vrefresh[0].lo = 1557c582b7e3Smrg ddc->det_mon[i].section.ranges.min_v; 1558c582b7e3Smrg pScrn->monitor->vrefresh[0].hi = 1559c582b7e3Smrg ddc->det_mon[i].section.ranges.max_v; 1560c582b7e3Smrg return; 1561c582b7e3Smrg } 1562c582b7e3Smrg } 1563c582b7e3Smrg i = 0; 1564c582b7e3Smrg if(ddc->timings1.t1 & 0x02) /*800x600@56*/ 1565c582b7e3Smrg { 1566c582b7e3Smrg pScrn->monitor->vrefresh[i].lo = 1567c582b7e3Smrg pScrn->monitor->vrefresh[i].hi = 56; 1568c582b7e3Smrg i++; 1569c582b7e3Smrg } 1570c582b7e3Smrg if((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08)) 1571c582b7e3Smrg { 1572c582b7e3Smrg pScrn->monitor->vrefresh[i].lo = 1573c582b7e3Smrg pScrn->monitor->vrefresh[i].hi = 60; 1574c582b7e3Smrg i++; 1575c582b7e3Smrg } 1576c582b7e3Smrg if(ddc->timings1.t2 & 0x04) 1577c582b7e3Smrg { 1578c582b7e3Smrg pScrn->monitor->vrefresh[i].lo = 1579c582b7e3Smrg pScrn->monitor->vrefresh[i].hi = 70; 1580c582b7e3Smrg i++; 1581c582b7e3Smrg } 1582c582b7e3Smrg if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80)) 1583c582b7e3Smrg { 1584c582b7e3Smrg pScrn->monitor->vrefresh[i].lo = 1585c582b7e3Smrg pScrn->monitor->vrefresh[i].hi = 72; 1586c582b7e3Smrg i++; 1587c582b7e3Smrg } 1588c582b7e3Smrg if((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40) 1589c582b7e3Smrg || (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01)) 1590c582b7e3Smrg { 1591c582b7e3Smrg pScrn->monitor->vrefresh[i].lo = 1592c582b7e3Smrg pScrn->monitor->vrefresh[i].hi = 75; 1593c582b7e3Smrg i++; 1594c582b7e3Smrg } 1595c582b7e3Smrg pScrn->monitor->nVrefresh = i; 1596c582b7e3Smrg } 1597c582b7e3Smrg} 1598c582b7e3Smrg 1599c582b7e3Smrg/*********** 1600c582b7e3Smrg xfree's xf86ValidateModes routine deosn't work well with DFPs 1601c582b7e3Smrg here is our own validation routine. All modes between 1602c582b7e3Smrg 640<=XRes<=MaxRes and 480<=YRes<=MaxYRes will be permitted. 1603c582b7e3Smrg NOTE: RageProII doesn't support rmx, can only work with the 1604c582b7e3Smrg standard modes the monitor can support (scale). 1605c582b7e3Smrg************/ 1606c582b7e3Smrg 1607c582b7e3Smrgstatic int R128ValidateFPModes(ScrnInfoPtr pScrn) 1608c582b7e3Smrg{ 1609c582b7e3Smrg int i, j, count=0, width, height; 1610c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1611c582b7e3Smrg DisplayModePtr last = NULL, new = NULL, first = NULL; 1612c582b7e3Smrg xf86MonPtr ddc; 1613c582b7e3Smrg 1614c582b7e3Smrg /* Free any allocated modes during configuration. We don't need them*/ 1615c582b7e3Smrg while (pScrn->modes) 1616c582b7e3Smrg { 1617c582b7e3Smrg xf86DeleteMode(&pScrn->modes, pScrn->modes); 1618c582b7e3Smrg } 1619c582b7e3Smrg while (pScrn->modePool) 1620c582b7e3Smrg { 1621c582b7e3Smrg xf86DeleteMode(&pScrn->modePool, pScrn->modePool); 1622c582b7e3Smrg } 1623c582b7e3Smrg 1624c582b7e3Smrg pScrn->virtualX = pScrn->display->virtualX; 1625c582b7e3Smrg pScrn->virtualY = pScrn->display->virtualY; 1626c582b7e3Smrg 1627c582b7e3Smrg /* If no mode specified in config, we use native resolution*/ 1628c582b7e3Smrg if(!pScrn->display->modes[0]) 1629c582b7e3Smrg { 1630c582b7e3Smrg pScrn->display->modes[0] = xnfalloc(16); 1631c582b7e3Smrg sprintf(pScrn->display->modes[0], "%dx%d", 1632c582b7e3Smrg info->PanelXRes, info->PanelYRes); 1633c582b7e3Smrg } 1634c582b7e3Smrg 1635c582b7e3Smrg for(i=0; pScrn->display->modes[i] != NULL; i++) 1636c582b7e3Smrg { 1637c582b7e3Smrg if (sscanf(pScrn->display->modes[i], "%dx%d", &width, &height) == 2) 1638c582b7e3Smrg { 1639c582b7e3Smrg 1640c582b7e3Smrg if(width < 640 || width > info->PanelXRes || 1641c582b7e3Smrg height < 480 || height > info->PanelYRes) 1642c582b7e3Smrg { 1643c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1644c582b7e3Smrg "Mode %s is out of range.\n" 1645c582b7e3Smrg "Valid mode should be between 640x480-%dx%d\n", 1646c582b7e3Smrg pScrn->display->modes[i], info->PanelXRes, info->PanelYRes); 1647c582b7e3Smrg continue; 1648c582b7e3Smrg } 1649c582b7e3Smrg 1650c582b7e3Smrg new = xnfcalloc(1, sizeof(DisplayModeRec)); 1651c582b7e3Smrg new->prev = last; 1652c582b7e3Smrg new->name = xnfalloc(strlen(pScrn->display->modes[i]) + 1); 1653c582b7e3Smrg strcpy(new->name, pScrn->display->modes[i]); 1654c582b7e3Smrg new->HDisplay = new->CrtcHDisplay = width; 1655c582b7e3Smrg new->VDisplay = new->CrtcVDisplay = height; 1656c582b7e3Smrg 1657c582b7e3Smrg ddc = pScrn->monitor->DDC; 1658c582b7e3Smrg for(j=0; j<DET_TIMINGS; j++) 1659c582b7e3Smrg { 1660c582b7e3Smrg /*We use native mode clock only*/ 1661c582b7e3Smrg if(ddc->det_mon[j].type == 0){ 1662c582b7e3Smrg new->Clock = ddc->det_mon[j].section.d_timings.clock / 1000; 1663c582b7e3Smrg break; 1664c582b7e3Smrg } 1665c582b7e3Smrg } 1666c582b7e3Smrg 1667c582b7e3Smrg if(new->prev) new->prev->next = new; 1668c582b7e3Smrg last = new; 1669c582b7e3Smrg if(!first) first = new; 1670c582b7e3Smrg pScrn->display->virtualX = 1671c582b7e3Smrg pScrn->virtualX = MAX(pScrn->virtualX, width); 1672c582b7e3Smrg pScrn->display->virtualY = 1673c582b7e3Smrg pScrn->virtualY = MAX(pScrn->virtualY, height); 1674c582b7e3Smrg count++; 1675c582b7e3Smrg } 1676c582b7e3Smrg else 1677c582b7e3Smrg { 1678c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1679c582b7e3Smrg "Mode name %s is invalid\n", pScrn->display->modes[i]); 1680c582b7e3Smrg continue; 1681c582b7e3Smrg } 1682c582b7e3Smrg } 1683c582b7e3Smrg 1684c582b7e3Smrg if(last) 1685c582b7e3Smrg { 1686c582b7e3Smrg last->next = first; 1687c582b7e3Smrg first->prev = last; 1688c582b7e3Smrg pScrn->modes = first; 1689c582b7e3Smrg 1690c582b7e3Smrg /*FIXME: May need to validate line pitch here*/ 1691c582b7e3Smrg { 1692c582b7e3Smrg int dummy = 0; 1693c582b7e3Smrg switch(pScrn->depth / 8) 1694c582b7e3Smrg { 1695c582b7e3Smrg case 1: 1696c582b7e3Smrg dummy = 128 - pScrn->virtualX % 128; 1697c582b7e3Smrg break; 1698c582b7e3Smrg case 2: 1699c582b7e3Smrg dummy = 32 - pScrn->virtualX % 32; 1700c582b7e3Smrg break; 1701c582b7e3Smrg case 3: 1702c582b7e3Smrg case 4: 1703c582b7e3Smrg dummy = 16 - pScrn->virtualX % 16; 1704c582b7e3Smrg } 1705c582b7e3Smrg pScrn->displayWidth = pScrn->virtualX + dummy; 1706c582b7e3Smrg } 1707c582b7e3Smrg 1708c582b7e3Smrg } 1709c582b7e3Smrg 1710c582b7e3Smrg return count; 1711c582b7e3Smrg} 1712c582b7e3Smrg 1713c582b7e3Smrg 1714c582b7e3Smrg/* This is called by R128PreInit to validate modes and compute parameters 1715c582b7e3Smrg for all of the valid modes. */ 1716c582b7e3Smrgstatic Bool R128PreInitModes(ScrnInfoPtr pScrn) 1717c582b7e3Smrg{ 1718c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1719c582b7e3Smrg ClockRangePtr clockRanges; 1720c582b7e3Smrg int modesFound; 1721c582b7e3Smrg 1722c582b7e3Smrg if(info->isDFP) { 1723c582b7e3Smrg R128MapMem(pScrn); 1724c582b7e3Smrg info->BIOSDisplay = R128_BIOS_DISPLAY_FP; 1725c582b7e3Smrg /* validate if DFP really connected. */ 1726c582b7e3Smrg if(!R128GetDFPInfo(pScrn)) { 1727c582b7e3Smrg info->isDFP = FALSE; 1728c582b7e3Smrg info->BIOSDisplay = R128_BIOS_DISPLAY_CRT; 1729c582b7e3Smrg } else if(!info->isPro2) { 1730c582b7e3Smrg /* RageProII doesn't support rmx, we can't use native-mode 1731c582b7e3Smrg stretching for other non-native modes. It will rely on 1732c582b7e3Smrg whatever VESA modes monitor can support. */ 1733c582b7e3Smrg modesFound = R128ValidateFPModes(pScrn); 1734c582b7e3Smrg if(modesFound < 1) { 1735c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1736c582b7e3Smrg "No valid mode found for this DFP/LCD\n"); 1737c582b7e3Smrg R128UnmapMem(pScrn); 1738c582b7e3Smrg return FALSE; 1739c582b7e3Smrg 1740c582b7e3Smrg } 1741c582b7e3Smrg } 1742c582b7e3Smrg R128UnmapMem(pScrn); 1743c582b7e3Smrg } 1744c582b7e3Smrg 1745c582b7e3Smrg if(!info->isDFP || info->isPro2) { 1746c582b7e3Smrg /* Get mode information */ 1747c582b7e3Smrg pScrn->progClock = TRUE; 1748c582b7e3Smrg clockRanges = xnfcalloc(sizeof(*clockRanges), 1); 1749c582b7e3Smrg clockRanges->next = NULL; 1750c582b7e3Smrg clockRanges->minClock = info->pll.min_pll_freq; 1751c582b7e3Smrg clockRanges->maxClock = info->pll.max_pll_freq * 10; 1752c582b7e3Smrg clockRanges->clockIndex = -1; 1753c582b7e3Smrg if (info->HasPanelRegs || info->isDFP) { 1754c582b7e3Smrg clockRanges->interlaceAllowed = FALSE; 1755c582b7e3Smrg clockRanges->doubleScanAllowed = FALSE; 1756c582b7e3Smrg } else { 1757c582b7e3Smrg clockRanges->interlaceAllowed = TRUE; 1758c582b7e3Smrg clockRanges->doubleScanAllowed = TRUE; 1759c582b7e3Smrg } 1760c582b7e3Smrg 1761c582b7e3Smrg if(pScrn->monitor->DDC) { 1762c582b7e3Smrg /*if we still don't know sync range yet, let's try EDID. 1763c582b7e3Smrg Note that, since we can have dual heads, the Xconfigurator 1764c582b7e3Smrg may not be able to probe both monitors correctly through 1765c582b7e3Smrg vbe probe function (R128ProbeDDC). Here we provide an 1766c582b7e3Smrg additional way to auto-detect sync ranges if they haven't 1767c582b7e3Smrg been added to XF86Config manually. 1768c582b7e3Smrg **/ 1769c582b7e3Smrg if(pScrn->monitor->nHsync <= 0) 1770c582b7e3Smrg R128SetSyncRangeFromEdid(pScrn, 1); 1771c582b7e3Smrg if(pScrn->monitor->nVrefresh <= 0) 1772c582b7e3Smrg R128SetSyncRangeFromEdid(pScrn, 0); 1773c582b7e3Smrg } 1774c582b7e3Smrg 1775c582b7e3Smrg modesFound = xf86ValidateModes(pScrn, 1776c582b7e3Smrg pScrn->monitor->Modes, 1777c582b7e3Smrg pScrn->display->modes, 1778c582b7e3Smrg clockRanges, 1779c582b7e3Smrg NULL, /* linePitches */ 1780c582b7e3Smrg 8 * 64, /* minPitch */ 1781c582b7e3Smrg 8 * 1024, /* maxPitch */ 1782c582b7e3Smrg/* 1783c582b7e3Smrg * ATI docs say pitchInc must be 8 * 64, but this doesn't permit a pitch of 1784c582b7e3Smrg * 800 bytes, which is known to work on the Rage128 LF on clamshell iBooks 1785c582b7e3Smrg */ 1786c582b7e3Smrg 8 * 32, /* pitchInc */ 1787c582b7e3Smrg 128, /* minHeight */ 1788c582b7e3Smrg 2048, /* maxHeight */ 1789c582b7e3Smrg pScrn->display->virtualX, 1790c582b7e3Smrg pScrn->display->virtualY, 1791c582b7e3Smrg info->FbMapSize, 1792c582b7e3Smrg LOOKUP_BEST_REFRESH); 179379e5230eSmacallan#ifndef AVOID_FBDEV 1794c582b7e3Smrg if (modesFound < 1 && info->FBDev) { 1795c582b7e3Smrg fbdevHWUseBuildinMode(pScrn); 179679e5230eSmacallan pScrn->displayWidth = fbdevHWGetLineLength(pScrn) / 179779e5230eSmacallan (pScrn->bitsPerPixel / 8); 1798c582b7e3Smrg modesFound = 1; 1799c582b7e3Smrg } 180079e5230eSmacallan#endif 1801c582b7e3Smrg 1802c582b7e3Smrg if (modesFound == -1) return FALSE; 1803c582b7e3Smrg xf86PruneDriverModes(pScrn); 1804c582b7e3Smrg if (!modesFound || !pScrn->modes) { 1805c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 1806c582b7e3Smrg return FALSE; 1807c582b7e3Smrg } 1808c582b7e3Smrg xf86SetCrtcForModes(pScrn, 0); 1809c582b7e3Smrg } 1810c582b7e3Smrg /* Set DPI */ 1811c582b7e3Smrg pScrn->currentMode = pScrn->modes; 1812c582b7e3Smrg xf86PrintModes(pScrn); 1813c582b7e3Smrg 1814c582b7e3Smrg xf86SetDpi(pScrn, 0, 0); 1815c582b7e3Smrg 1816c582b7e3Smrg /* Get ScreenInit function */ 1817c582b7e3Smrg if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; 1818c582b7e3Smrg 1819c582b7e3Smrg info->CurrentLayout.displayWidth = pScrn->displayWidth; 1820c582b7e3Smrg info->CurrentLayout.mode = pScrn->currentMode; 1821c582b7e3Smrg 1822c582b7e3Smrg return TRUE; 1823c582b7e3Smrg} 1824c582b7e3Smrg 1825c582b7e3Smrg/* This is called by R128PreInit to initialize the hardware cursor. */ 1826c582b7e3Smrgstatic Bool R128PreInitCursor(ScrnInfoPtr pScrn) 1827c582b7e3Smrg{ 1828c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1829c582b7e3Smrg 1830c582b7e3Smrg if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 1831c582b7e3Smrg if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE; 1832c582b7e3Smrg } 1833c582b7e3Smrg return TRUE; 1834c582b7e3Smrg} 1835c582b7e3Smrg 1836c582b7e3Smrg/* This is called by R128PreInit to initialize hardware acceleration. */ 1837c582b7e3Smrgstatic Bool R128PreInitAccel(ScrnInfoPtr pScrn) 1838c582b7e3Smrg{ 1839c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1840c582b7e3Smrg 1841c582b7e3Smrg if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { 1842c582b7e3Smrg if (!xf86LoadSubModule(pScrn, "xaa")) return FALSE; 1843c582b7e3Smrg } 1844c582b7e3Smrg return TRUE; 1845c582b7e3Smrg} 1846c582b7e3Smrg 1847c582b7e3Smrgstatic Bool R128PreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10) 1848c582b7e3Smrg{ 1849c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1850c582b7e3Smrg#if 1 && !defined(__alpha__) 1851c582b7e3Smrg /* int10 is broken on some Alphas */ 1852c582b7e3Smrg if (xf86LoadSubModule(pScrn, "int10")) { 1853c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); 1854c582b7e3Smrg *ppInt10 = xf86InitInt10(info->pEnt->index); 1855c582b7e3Smrg } 1856c582b7e3Smrg#endif 1857c582b7e3Smrg return TRUE; 1858c582b7e3Smrg} 1859c582b7e3Smrg 1860c582b7e3Smrg#ifdef XF86DRI 1861c582b7e3Smrgstatic Bool R128PreInitDRI(ScrnInfoPtr pScrn) 1862c582b7e3Smrg{ 1863c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1864c582b7e3Smrg 1865c582b7e3Smrg if (xf86ReturnOptValBool(info->Options, OPTION_CCE_PIO, FALSE)) { 1866c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing CCE into PIO mode\n"); 1867c582b7e3Smrg info->CCEMode = R128_DEFAULT_CCE_PIO_MODE; 1868c582b7e3Smrg } else { 1869c582b7e3Smrg info->CCEMode = R128_DEFAULT_CCE_BM_MODE; 1870c582b7e3Smrg } 1871c582b7e3Smrg 1872c582b7e3Smrg if (xf86ReturnOptValBool(info->Options, OPTION_NO_SECURITY, FALSE)) { 1873c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1874c582b7e3Smrg "WARNING!!! CCE Security checks disabled!!! **********\n"); 1875c582b7e3Smrg info->CCESecure = FALSE; 1876c582b7e3Smrg } else { 1877c582b7e3Smrg info->CCESecure = TRUE; 1878c582b7e3Smrg } 1879c582b7e3Smrg 1880c582b7e3Smrg info->agpMode = R128_DEFAULT_AGP_MODE; 1881c582b7e3Smrg info->agpSize = R128_DEFAULT_AGP_SIZE; 1882c582b7e3Smrg info->ringSize = R128_DEFAULT_RING_SIZE; 1883c582b7e3Smrg info->bufSize = R128_DEFAULT_BUFFER_SIZE; 1884c582b7e3Smrg info->agpTexSize = R128_DEFAULT_AGP_TEX_SIZE; 1885c582b7e3Smrg 1886c582b7e3Smrg info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT; 1887c582b7e3Smrg 1888c582b7e3Smrg if (!info->IsPCI) { 1889c582b7e3Smrg if (xf86GetOptValInteger(info->Options, 1890c582b7e3Smrg OPTION_AGP_MODE, &(info->agpMode))) { 1891c582b7e3Smrg if (info->agpMode < 1 || info->agpMode > R128_AGP_MAX_MODE) { 1892c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1893c582b7e3Smrg "Illegal AGP Mode: %d\n", info->agpMode); 1894c582b7e3Smrg return FALSE; 1895c582b7e3Smrg } 1896c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1897c582b7e3Smrg "Using AGP %dx mode\n", info->agpMode); 1898c582b7e3Smrg } 1899c582b7e3Smrg 1900c582b7e3Smrg if (xf86GetOptValInteger(info->Options, 1901c582b7e3Smrg OPTION_AGP_SIZE, (int *)&(info->agpSize))) { 1902c582b7e3Smrg switch (info->agpSize) { 1903c582b7e3Smrg case 4: 1904c582b7e3Smrg case 8: 1905c582b7e3Smrg case 16: 1906c582b7e3Smrg case 32: 1907c582b7e3Smrg case 64: 1908c582b7e3Smrg case 128: 1909c582b7e3Smrg case 256: 1910c582b7e3Smrg break; 1911c582b7e3Smrg default: 1912c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1913c582b7e3Smrg "Illegal AGP size: %d MB\n", info->agpSize); 1914c582b7e3Smrg return FALSE; 1915c582b7e3Smrg } 1916c582b7e3Smrg } 1917c582b7e3Smrg 1918c582b7e3Smrg if (xf86GetOptValInteger(info->Options, 1919c582b7e3Smrg OPTION_RING_SIZE, &(info->ringSize))) { 1920c582b7e3Smrg if (info->ringSize < 1 || info->ringSize >= (int)info->agpSize) { 1921c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1922c582b7e3Smrg "Illegal ring buffer size: %d MB\n", 1923c582b7e3Smrg info->ringSize); 1924c582b7e3Smrg return FALSE; 1925c582b7e3Smrg } 1926c582b7e3Smrg } 1927c582b7e3Smrg 1928c582b7e3Smrg if (xf86GetOptValInteger(info->Options, 1929c582b7e3Smrg OPTION_BUFFER_SIZE, &(info->bufSize))) { 1930c582b7e3Smrg if (info->bufSize < 1 || info->bufSize >= (int)info->agpSize) { 1931c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1932c582b7e3Smrg "Illegal vertex/indirect buffers size: %d MB\n", 1933c582b7e3Smrg info->bufSize); 1934c582b7e3Smrg return FALSE; 1935c582b7e3Smrg } 1936c582b7e3Smrg if (info->bufSize > 2) { 1937c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1938c582b7e3Smrg "Illegal vertex/indirect buffers size: %d MB\n", 1939c582b7e3Smrg info->bufSize); 1940c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1941c582b7e3Smrg "Clamping vertex/indirect buffers size to 2 MB\n"); 1942c582b7e3Smrg info->bufSize = 2; 1943c582b7e3Smrg } 1944c582b7e3Smrg } 1945c582b7e3Smrg 1946c582b7e3Smrg if (info->ringSize + info->bufSize + info->agpTexSize > 1947c582b7e3Smrg (int)info->agpSize) { 1948c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1949c582b7e3Smrg "Buffers are too big for requested AGP space\n"); 1950c582b7e3Smrg return FALSE; 1951c582b7e3Smrg } 1952c582b7e3Smrg 1953c582b7e3Smrg info->agpTexSize = info->agpSize - (info->ringSize + info->bufSize); 1954c582b7e3Smrg } 1955c582b7e3Smrg 1956c582b7e3Smrg if (xf86GetOptValInteger(info->Options, OPTION_USEC_TIMEOUT, 1957c582b7e3Smrg &(info->CCEusecTimeout))) { 1958c582b7e3Smrg /* This option checked by the R128 DRM kernel module */ 1959c582b7e3Smrg } 1960c582b7e3Smrg 1961c582b7e3Smrg if (!xf86LoadSubModule(pScrn, "shadowfb")) { 1962c582b7e3Smrg info->allowPageFlip = 0; 1963c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1964c582b7e3Smrg "Couldn't load shadowfb module:\n"); 1965c582b7e3Smrg } else { 1966c582b7e3Smrg info->allowPageFlip = xf86ReturnOptValBool(info->Options, 1967c582b7e3Smrg OPTION_PAGE_FLIP, 1968c582b7e3Smrg FALSE); 1969c582b7e3Smrg } 1970c582b7e3Smrg 1971c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n", 1972c582b7e3Smrg info->allowPageFlip ? "en" : "dis"); 1973c582b7e3Smrg 1974c582b7e3Smrg return TRUE; 1975c582b7e3Smrg} 1976c582b7e3Smrg#endif 1977c582b7e3Smrg 1978c582b7e3Smrgstatic void 1979c582b7e3SmrgR128ProbeDDC(ScrnInfoPtr pScrn, int indx) 1980c582b7e3Smrg{ 1981c582b7e3Smrg vbeInfoPtr pVbe; 1982c582b7e3Smrg if (xf86LoadSubModule(pScrn, "vbe")) { 1983c582b7e3Smrg pVbe = VBEInit(NULL,indx); 1984c582b7e3Smrg ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 1985c582b7e3Smrg vbeFree(pVbe); 1986c582b7e3Smrg } 1987c582b7e3Smrg} 1988c582b7e3Smrg 1989c582b7e3Smrg/* R128PreInit is called once at server startup. */ 1990c582b7e3SmrgBool R128PreInit(ScrnInfoPtr pScrn, int flags) 1991c582b7e3Smrg{ 1992c582b7e3Smrg R128InfoPtr info; 1993c582b7e3Smrg xf86Int10InfoPtr pInt10 = NULL; 1994c582b7e3Smrg 1995c582b7e3Smrg R128TRACE(("R128PreInit\n")); 1996c582b7e3Smrg 1997c582b7e3Smrg if (pScrn->numEntities != 1) return FALSE; 1998c582b7e3Smrg 1999c582b7e3Smrg if (!R128GetRec(pScrn)) return FALSE; 2000c582b7e3Smrg 2001c582b7e3Smrg info = R128PTR(pScrn); 2002c582b7e3Smrg 2003c582b7e3Smrg info->IsSecondary = FALSE; 2004c582b7e3Smrg info->IsPrimary = FALSE; 2005c582b7e3Smrg info->SwitchingMode = FALSE; 2006c582b7e3Smrg 2007c582b7e3Smrg info->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 2008c582b7e3Smrg if (info->pEnt->location.type != BUS_PCI) goto fail; 2009c582b7e3Smrg 2010c582b7e3Smrg if(xf86IsEntityShared(pScrn->entityList[0])) 2011c582b7e3Smrg { 2012c582b7e3Smrg if(xf86IsPrimInitDone(pScrn->entityList[0])) 2013c582b7e3Smrg { 2014c582b7e3Smrg DevUnion* pPriv; 2015c582b7e3Smrg R128EntPtr pR128Ent; 2016c582b7e3Smrg info->IsSecondary = TRUE; 2017c582b7e3Smrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 2018c582b7e3Smrg getR128EntityIndex()); 2019c582b7e3Smrg pR128Ent = pPriv->ptr; 2020c582b7e3Smrg if(pR128Ent->BypassSecondary) return FALSE; 2021c582b7e3Smrg pR128Ent->pSecondaryScrn = pScrn; 2022c582b7e3Smrg } 2023c582b7e3Smrg else 2024c582b7e3Smrg { 2025c582b7e3Smrg DevUnion* pPriv; 2026c582b7e3Smrg R128EntPtr pR128Ent; 2027c582b7e3Smrg info->IsPrimary = TRUE; 2028c582b7e3Smrg xf86SetPrimInitDone(pScrn->entityList[0]); 2029c582b7e3Smrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 2030c582b7e3Smrg getR128EntityIndex()); 2031c582b7e3Smrg pR128Ent = pPriv->ptr; 2032c582b7e3Smrg pR128Ent->pPrimaryScrn = pScrn; 2033c582b7e3Smrg pR128Ent->IsDRIEnabled = FALSE; 2034c582b7e3Smrg pR128Ent->BypassSecondary = FALSE; 2035c582b7e3Smrg pR128Ent->HasSecondary = FALSE; 2036c582b7e3Smrg pR128Ent->RestorePrimary = FALSE; 2037c582b7e3Smrg pR128Ent->IsSecondaryRestored = FALSE; 2038c582b7e3Smrg } 2039c582b7e3Smrg } 2040c582b7e3Smrg 2041c582b7e3Smrg if (flags & PROBE_DETECT) { 2042c582b7e3Smrg R128ProbeDDC(pScrn, info->pEnt->index); 2043c582b7e3Smrg return TRUE; 2044c582b7e3Smrg } 2045c582b7e3Smrg 2046c582b7e3Smrg info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); 2047c582b7e3Smrg info->PciTag = pciTag(PCI_DEV_BUS(info->PciInfo), 2048c582b7e3Smrg PCI_DEV_DEV(info->PciInfo), 2049c582b7e3Smrg PCI_DEV_FUNC(info->PciInfo)); 2050c582b7e3Smrg 2051c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2052c582b7e3Smrg "PCI bus %d card %d func %d\n", 2053c582b7e3Smrg PCI_DEV_BUS(info->PciInfo), 2054c582b7e3Smrg PCI_DEV_DEV(info->PciInfo), 2055c582b7e3Smrg PCI_DEV_FUNC(info->PciInfo)); 2056c582b7e3Smrg 205719019ffeSmrg#ifndef XSERVER_LIBPCIACCESS 2058c582b7e3Smrg if (xf86RegisterResources(info->pEnt->index, 0, ResNone)) goto fail; 2059c582b7e3Smrg if (xf86SetOperatingState(resVga, info->pEnt->index, ResUnusedOpr)) goto fail; 2060c582b7e3Smrg 2061c582b7e3Smrg pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR; 206219019ffeSmrg#endif 2063c582b7e3Smrg pScrn->monitor = pScrn->confScreen->monitor; 2064c582b7e3Smrg 2065c582b7e3Smrg if (!R128PreInitVisual(pScrn)) goto fail; 2066c582b7e3Smrg 2067c582b7e3Smrg /* We can't do this until we have a 2068c582b7e3Smrg pScrn->display. */ 2069c582b7e3Smrg xf86CollectOptions(pScrn, NULL); 2070c582b7e3Smrg if (!(info->Options = xalloc(sizeof(R128Options)))) goto fail; 2071c582b7e3Smrg memcpy(info->Options, R128Options, sizeof(R128Options)); 2072c582b7e3Smrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options); 2073c582b7e3Smrg 2074c582b7e3Smrg /* By default, don't do VGA IOs on ppc */ 2075c582b7e3Smrg#if defined(__powerpc__) || defined(__sparc__) || !defined(WITH_VGAHW) 2076c582b7e3Smrg info->VGAAccess = FALSE; 2077c582b7e3Smrg#else 2078c582b7e3Smrg info->VGAAccess = TRUE; 2079c582b7e3Smrg#endif 2080c582b7e3Smrg 2081c582b7e3Smrg#ifdef WITH_VGAHW 2082c582b7e3Smrg xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS, &info->VGAAccess); 2083c582b7e3Smrg if (info->VGAAccess) { 2084c582b7e3Smrg if (!xf86LoadSubModule(pScrn, "vgahw")) 2085c582b7e3Smrg info->VGAAccess = FALSE; 2086c582b7e3Smrg else { 2087c582b7e3Smrg if (!vgaHWGetHWRec(pScrn)) 2088c582b7e3Smrg info->VGAAccess = FALSE; 2089c582b7e3Smrg } 2090c582b7e3Smrg if (!info->VGAAccess) 2091c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Loading VGA module failed," 2092c582b7e3Smrg " trying to run without it\n"); 2093c582b7e3Smrg } else 2094c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAAccess option set to FALSE," 2095c582b7e3Smrg " VGA module load skipped\n"); 2096c582b7e3Smrg if (info->VGAAccess) 2097c582b7e3Smrg vgaHWGetIOBase(VGAHWPTR(pScrn)); 2098c582b7e3Smrg#else 2099c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAHW support not compiled, VGA " 2100c582b7e3Smrg "module load skipped\n"); 2101c582b7e3Smrg#endif 2102c582b7e3Smrg 2103c582b7e3Smrg 2104c582b7e3Smrg 2105c582b7e3Smrg if (!R128PreInitWeight(pScrn)) goto fail; 2106c582b7e3Smrg 2107c582b7e3Smrg if(xf86GetOptValInteger(info->Options, OPTION_VIDEO_KEY, &(info->videoKey))) { 2108c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", 2109c582b7e3Smrg info->videoKey); 2110c582b7e3Smrg } else { 2111c582b7e3Smrg info->videoKey = 0x1E; 2112c582b7e3Smrg } 2113c582b7e3Smrg 2114c582b7e3Smrg if (xf86ReturnOptValBool(info->Options, OPTION_SHOW_CACHE, FALSE)) { 2115c582b7e3Smrg info->showCache = TRUE; 2116c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n"); 2117c582b7e3Smrg } 2118c582b7e3Smrg 211979e5230eSmacallan#ifndef AVOID_FBDEV 2120c582b7e3Smrg#ifdef __powerpc__ 2121c582b7e3Smrg if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, TRUE)) 2122c582b7e3Smrg#else 2123c582b7e3Smrg if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) 2124c582b7e3Smrg#endif 2125c582b7e3Smrg { 2126c582b7e3Smrg info->FBDev = TRUE; 2127c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2128c582b7e3Smrg "Using framebuffer device\n"); 2129c582b7e3Smrg } 2130c582b7e3Smrg 2131c582b7e3Smrg if (info->FBDev) { 2132c582b7e3Smrg /* check for linux framebuffer device */ 2133c582b7e3Smrg if (!xf86LoadSubModule(pScrn, "fbdevhw")) return FALSE; 2134c582b7e3Smrg if (!fbdevHWInit(pScrn, info->PciInfo, NULL)) return FALSE; 2135c582b7e3Smrg pScrn->SwitchMode = fbdevHWSwitchModeWeak(); 2136c582b7e3Smrg pScrn->AdjustFrame = fbdevHWAdjustFrameWeak(); 2137c582b7e3Smrg pScrn->ValidMode = fbdevHWValidModeWeak(); 2138c582b7e3Smrg } 2139c582b7e3Smrg 2140c582b7e3Smrg if (!info->FBDev) 214179e5230eSmacallan#endif /* !AVOID_FBDEV */ 2142c582b7e3Smrg if (!R128PreInitInt10(pScrn, &pInt10)) goto fail; 2143c582b7e3Smrg 2144c582b7e3Smrg if (!R128PreInitConfig(pScrn)) goto fail; 2145c582b7e3Smrg 2146c582b7e3Smrg if (!R128GetBIOSParameters(pScrn, pInt10)) goto fail; 2147c582b7e3Smrg 2148c582b7e3Smrg if (!R128GetPLLParameters(pScrn)) goto fail; 2149c582b7e3Smrg 2150c582b7e3Smrg /* Don't fail on this one */ 2151c582b7e3Smrg R128PreInitDDC(pScrn, pInt10); 2152c582b7e3Smrg 2153c582b7e3Smrg if (!R128PreInitGamma(pScrn)) goto fail; 2154c582b7e3Smrg 2155c582b7e3Smrg if (!R128PreInitModes(pScrn)) goto fail; 2156c582b7e3Smrg 2157c582b7e3Smrg if (!R128PreInitCursor(pScrn)) goto fail; 2158c582b7e3Smrg 2159c582b7e3Smrg if (!R128PreInitAccel(pScrn)) goto fail; 2160c582b7e3Smrg 2161c582b7e3Smrg#ifdef XF86DRI 2162c582b7e3Smrg if (!R128PreInitDRI(pScrn)) goto fail; 2163c582b7e3Smrg#endif 2164c582b7e3Smrg 2165c582b7e3Smrg /* Free the video bios (if applicable) */ 2166c582b7e3Smrg if (info->VBIOS) { 2167c582b7e3Smrg xfree(info->VBIOS); 2168c582b7e3Smrg info->VBIOS = NULL; 2169c582b7e3Smrg } 2170c582b7e3Smrg 2171c582b7e3Smrg /* Free int10 info */ 2172c582b7e3Smrg if (pInt10) 2173c582b7e3Smrg xf86FreeInt10(pInt10); 2174c582b7e3Smrg 2175c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_NOTICE, 2176c582b7e3Smrg "For information on using the multimedia capabilities\n\tof this" 2177c582b7e3Smrg " adapter, please see http://gatos.sf.net.\n"); 2178c582b7e3Smrg 2179c582b7e3Smrg return TRUE; 2180c582b7e3Smrg 2181c582b7e3Smrg fail: 2182c582b7e3Smrg /* Pre-init failed. */ 2183c582b7e3Smrg 2184c582b7e3Smrg /* Free the video bios (if applicable) */ 2185c582b7e3Smrg if (info->VBIOS) { 2186c582b7e3Smrg xfree(info->VBIOS); 2187c582b7e3Smrg info->VBIOS = NULL; 2188c582b7e3Smrg } 2189c582b7e3Smrg 2190c582b7e3Smrg /* Free int10 info */ 2191c582b7e3Smrg if (pInt10) 2192c582b7e3Smrg xf86FreeInt10(pInt10); 2193c582b7e3Smrg 2194c582b7e3Smrg#ifdef WITH_VGAHW 2195c582b7e3Smrg if (info->VGAAccess) 2196c582b7e3Smrg vgaHWFreeHWRec(pScrn); 2197c582b7e3Smrg#endif 2198c582b7e3Smrg R128FreeRec(pScrn); 2199c582b7e3Smrg return FALSE; 2200c582b7e3Smrg} 2201c582b7e3Smrg 2202c582b7e3Smrg/* Load a palette. */ 2203c582b7e3Smrgstatic void R128LoadPalette(ScrnInfoPtr pScrn, int numColors, 2204c582b7e3Smrg int *indices, LOCO *colors, VisualPtr pVisual) 2205c582b7e3Smrg{ 2206c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 2207c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 2208c582b7e3Smrg int i, j; 2209c582b7e3Smrg int idx; 2210c582b7e3Smrg unsigned char r, g, b; 2211c582b7e3Smrg 2212c582b7e3Smrg /* If the second monitor is connected, we also 2213c582b7e3Smrg need to deal with the secondary palette*/ 2214c582b7e3Smrg if (info->IsSecondary) j = 1; 2215c582b7e3Smrg else j = 0; 2216c582b7e3Smrg 2217c582b7e3Smrg PAL_SELECT(j); 2218c582b7e3Smrg 2219c582b7e3Smrg 2220c582b7e3Smrg /* Select palette 0 (main CRTC) if using FP-enabled chip */ 2221c582b7e3Smrg /*if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0);*/ 2222c582b7e3Smrg 2223c582b7e3Smrg if (info->CurrentLayout.depth == 15) { 2224c582b7e3Smrg /* 15bpp mode. This sends 32 values. */ 2225c582b7e3Smrg for (i = 0; i < numColors; i++) { 2226c582b7e3Smrg idx = indices[i]; 2227c582b7e3Smrg r = colors[idx].red; 2228c582b7e3Smrg g = colors[idx].green; 2229c582b7e3Smrg b = colors[idx].blue; 2230c582b7e3Smrg OUTPAL(idx * 8, r, g, b); 2231c582b7e3Smrg } 2232c582b7e3Smrg } 2233c582b7e3Smrg else if (info->CurrentLayout.depth == 16) { 2234c582b7e3Smrg /* 16bpp mode. This sends 64 values. */ 2235c582b7e3Smrg /* There are twice as many green values as 2236c582b7e3Smrg there are values for red and blue. So, 2237c582b7e3Smrg we take each red and blue pair, and 2238c582b7e3Smrg combine it with each of the two green 2239c582b7e3Smrg values. */ 2240c582b7e3Smrg for (i = 0; i < numColors; i++) { 2241c582b7e3Smrg idx = indices[i]; 2242c582b7e3Smrg r = colors[idx / 2].red; 2243c582b7e3Smrg g = colors[idx].green; 2244c582b7e3Smrg b = colors[idx / 2].blue; 2245c582b7e3Smrg OUTPAL(idx * 4, r, g, b); 2246c582b7e3Smrg } 2247c582b7e3Smrg } 2248c582b7e3Smrg else { 2249c582b7e3Smrg /* 8bpp mode. This sends 256 values. */ 2250c582b7e3Smrg for (i = 0; i < numColors; i++) { 2251c582b7e3Smrg idx = indices[i]; 2252c582b7e3Smrg r = colors[idx].red; 2253c582b7e3Smrg b = colors[idx].blue; 2254c582b7e3Smrg g = colors[idx].green; 2255c582b7e3Smrg OUTPAL(idx, r, g, b); 2256c582b7e3Smrg } 2257c582b7e3Smrg } 2258c582b7e3Smrg} 2259c582b7e3Smrg 2260c582b7e3Smrgstatic void 2261c582b7e3SmrgR128BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) 2262c582b7e3Smrg{ 2263c582b7e3Smrg ScreenPtr pScreen = screenInfo.screens[i]; 2264c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[i]; 2265c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 2266c582b7e3Smrg 2267c582b7e3Smrg#ifdef XF86DRI 2268c582b7e3Smrg if (info->directRenderingEnabled) 2269c582b7e3Smrg FLUSH_RING(); 2270c582b7e3Smrg#endif 2271c582b7e3Smrg 2272c582b7e3Smrg pScreen->BlockHandler = info->BlockHandler; 2273c582b7e3Smrg (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); 2274c582b7e3Smrg pScreen->BlockHandler = R128BlockHandler; 2275c582b7e3Smrg 2276c582b7e3Smrg if(info->VideoTimerCallback) { 2277c582b7e3Smrg (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds); 2278c582b7e3Smrg } 2279c582b7e3Smrg} 2280c582b7e3Smrg 2281c582b7e3Smrg/* Called at the start of each server generation. */ 2282c582b7e3SmrgBool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, 2283c582b7e3Smrg int argc, char **argv) 2284c582b7e3Smrg{ 2285c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 2286c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 2287c582b7e3Smrg BoxRec MemBox; 2288c582b7e3Smrg int y2; 2289c582b7e3Smrg 2290c582b7e3Smrg R128TRACE(("R128ScreenInit %x %d\n", pScrn->memPhysBase, pScrn->fbOffset)); 2291c582b7e3Smrg 2292c582b7e3Smrg#ifdef XF86DRI 2293c582b7e3Smrg /* Turn off the CCE for now. */ 2294c582b7e3Smrg info->CCEInUse = FALSE; 2295c582b7e3Smrg info->indirectBuffer = NULL; 2296c582b7e3Smrg#endif 2297c582b7e3Smrg 2298c582b7e3Smrg if (!R128MapMem(pScrn)) return FALSE; 2299c582b7e3Smrg pScrn->fbOffset = 0; 2300c582b7e3Smrg if(info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024; 2301c582b7e3Smrg#ifdef XF86DRI 2302c582b7e3Smrg info->fbX = 0; 2303c582b7e3Smrg info->fbY = 0; 2304c582b7e3Smrg info->frontOffset = 0; 2305c582b7e3Smrg info->frontPitch = pScrn->displayWidth; 2306c582b7e3Smrg#endif 2307c582b7e3Smrg 2308c582b7e3Smrg info->PaletteSavedOnVT = FALSE; 2309c582b7e3Smrg 2310c582b7e3Smrg R128Save(pScrn); 231179e5230eSmacallan#ifndef AVOID_FBDEV 2312c582b7e3Smrg if (info->FBDev) { 2313c582b7e3Smrg if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE; 231479e5230eSmacallan } else 231579e5230eSmacallan#endif 2316c582b7e3Smrg if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE; 2317c582b7e3Smrg 2318c582b7e3Smrg R128SaveScreen(pScreen, SCREEN_SAVER_ON); 2319c582b7e3Smrg pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 2320c582b7e3Smrg 2321c582b7e3Smrg /* Visual setup */ 2322c582b7e3Smrg miClearVisualTypes(); 2323c582b7e3Smrg if (!miSetVisualTypes(pScrn->depth, 2324c582b7e3Smrg miGetDefaultVisualMask(pScrn->depth), 2325c582b7e3Smrg pScrn->rgbBits, 2326c582b7e3Smrg pScrn->defaultVisual)) return FALSE; 2327c582b7e3Smrg miSetPixmapDepths (); 2328c582b7e3Smrg 2329c582b7e3Smrg#ifdef XF86DRI 2330c582b7e3Smrg /* Setup DRI after visuals have been 2331c582b7e3Smrg established, but before fbScreenInit is 2332c582b7e3Smrg called. fbScreenInit will eventually 2333c582b7e3Smrg call the driver's InitGLXVisuals call 2334c582b7e3Smrg back. */ 2335c582b7e3Smrg { 2336c582b7e3Smrg /* FIXME: When we move to dynamic allocation of back and depth 2337c582b7e3Smrg buffers, we will want to revisit the following check for 3 2338c582b7e3Smrg times the virtual size of the screen below. */ 2339c582b7e3Smrg int width_bytes = (pScrn->displayWidth * 2340c582b7e3Smrg info->CurrentLayout.pixel_bytes); 2341c582b7e3Smrg int maxy = info->FbMapSize / width_bytes; 2342c582b7e3Smrg 2343c582b7e3Smrg if (xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { 2344c582b7e3Smrg xf86DrvMsg(scrnIndex, X_WARNING, 2345c582b7e3Smrg "Acceleration disabled, not initializing the DRI\n"); 2346c582b7e3Smrg info->directRenderingEnabled = FALSE; 2347c582b7e3Smrg } else if (maxy <= pScrn->virtualY * 3) { 2348c582b7e3Smrg xf86DrvMsg(scrnIndex, X_WARNING, 2349c582b7e3Smrg "Static buffer allocation failed -- " 2350c582b7e3Smrg "need at least %d kB video memory\n", 2351c582b7e3Smrg (pScrn->displayWidth * pScrn->virtualY * 2352c582b7e3Smrg info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024); 2353c582b7e3Smrg info->directRenderingEnabled = FALSE; 2354c582b7e3Smrg } else { 2355c582b7e3Smrg if(info->IsSecondary) 2356c582b7e3Smrg info->directRenderingEnabled = FALSE; 2357c582b7e3Smrg else 2358c582b7e3Smrg { 2359c582b7e3Smrg /* Xinerama has sync problem with DRI, disable it for now */ 2360c582b7e3Smrg if(xf86IsEntityShared(pScrn->entityList[0])) 2361c582b7e3Smrg { 2362c582b7e3Smrg info->directRenderingEnabled = FALSE; 2363c582b7e3Smrg xf86DrvMsg(scrnIndex, X_WARNING, 2364c582b7e3Smrg "Direct Rendering Disabled -- " 2365c582b7e3Smrg "Dual-head configuration is not working with DRI " 2366c582b7e3Smrg "at present.\nPlease use only one Device/Screen " 2367c582b7e3Smrg "section in your XFConfig file.\n"); 2368c582b7e3Smrg } 2369c582b7e3Smrg else 2370c582b7e3Smrg info->directRenderingEnabled = 2371c582b7e3Smrg R128DRIScreenInit(pScreen); 2372c582b7e3Smrg if(xf86IsEntityShared(pScrn->entityList[0])) 2373c582b7e3Smrg { 2374c582b7e3Smrg DevUnion* pPriv; 2375c582b7e3Smrg R128EntPtr pR128Ent; 2376c582b7e3Smrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 2377c582b7e3Smrg getR128EntityIndex()); 2378c582b7e3Smrg pR128Ent = pPriv->ptr; 2379c582b7e3Smrg pR128Ent->IsDRIEnabled = info->directRenderingEnabled; 2380c582b7e3Smrg } 2381c582b7e3Smrg } 2382c582b7e3Smrg } 2383c582b7e3Smrg } 2384c582b7e3Smrg#endif 2385c582b7e3Smrg 2386c582b7e3Smrg if (!fbScreenInit (pScreen, info->FB, 2387c582b7e3Smrg pScrn->virtualX, pScrn->virtualY, 2388c582b7e3Smrg pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, 2389c582b7e3Smrg pScrn->bitsPerPixel)) 2390c582b7e3Smrg return FALSE; 2391c582b7e3Smrg 2392c582b7e3Smrg xf86SetBlackWhitePixels(pScreen); 2393c582b7e3Smrg 2394c582b7e3Smrg if (pScrn->bitsPerPixel > 8) { 2395c582b7e3Smrg VisualPtr visual; 2396c582b7e3Smrg 2397c582b7e3Smrg visual = pScreen->visuals + pScreen->numVisuals; 2398c582b7e3Smrg while (--visual >= pScreen->visuals) { 2399c582b7e3Smrg if ((visual->class | DynamicClass) == DirectColor) { 2400c582b7e3Smrg visual->offsetRed = pScrn->offset.red; 2401c582b7e3Smrg visual->offsetGreen = pScrn->offset.green; 2402c582b7e3Smrg visual->offsetBlue = pScrn->offset.blue; 2403c582b7e3Smrg visual->redMask = pScrn->mask.red; 2404c582b7e3Smrg visual->greenMask = pScrn->mask.green; 2405c582b7e3Smrg visual->blueMask = pScrn->mask.blue; 2406c582b7e3Smrg } 2407c582b7e3Smrg } 2408c582b7e3Smrg } 2409c582b7e3Smrg 2410c582b7e3Smrg /* must be after RGB order fixed */ 2411c582b7e3Smrg fbPictureInit (pScreen, 0, 0); 2412c582b7e3Smrg 2413c582b7e3Smrg /* Memory manager setup */ 2414c582b7e3Smrg#ifdef XF86DRI 2415c582b7e3Smrg if (info->directRenderingEnabled) { 2416c582b7e3Smrg FBAreaPtr fbarea; 2417c582b7e3Smrg int width_bytes = (pScrn->displayWidth * 2418c582b7e3Smrg info->CurrentLayout.pixel_bytes); 2419c582b7e3Smrg int cpp = info->CurrentLayout.pixel_bytes; 2420c582b7e3Smrg int bufferSize = pScrn->virtualY * width_bytes; 2421c582b7e3Smrg int l, total; 2422c582b7e3Smrg int scanlines; 2423c582b7e3Smrg 2424c582b7e3Smrg switch (info->CCEMode) { 2425c582b7e3Smrg case R128_DEFAULT_CCE_PIO_MODE: 2426c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in PIO mode\n"); 2427c582b7e3Smrg break; 2428c582b7e3Smrg case R128_DEFAULT_CCE_BM_MODE: 2429c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in BM mode\n"); 2430c582b7e3Smrg break; 2431c582b7e3Smrg default: 2432c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in UNKNOWN mode\n"); 2433c582b7e3Smrg break; 2434c582b7e3Smrg } 2435c582b7e3Smrg 2436c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2437c582b7e3Smrg "Using %d MB AGP aperture\n", info->agpSize); 2438c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2439c582b7e3Smrg "Using %d MB for the ring buffer\n", info->ringSize); 2440c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2441c582b7e3Smrg "Using %d MB for vertex/indirect buffers\n", info->bufSize); 2442c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2443c582b7e3Smrg "Using %d MB for AGP textures\n", info->agpTexSize); 2444c582b7e3Smrg 2445c582b7e3Smrg /* Try for front, back, depth, and two framebuffers worth of 2446c582b7e3Smrg * pixmap cache. Should be enough for a fullscreen background 2447c582b7e3Smrg * image plus some leftovers. 2448c582b7e3Smrg */ 2449c582b7e3Smrg info->textureSize = info->FbMapSize - 5 * bufferSize; 2450c582b7e3Smrg 2451c582b7e3Smrg /* If that gives us less than half the available memory, let's 2452c582b7e3Smrg * be greedy and grab some more. Sorry, I care more about 3D 2453c582b7e3Smrg * performance than playing nicely, and you'll get around a full 2454c582b7e3Smrg * framebuffer's worth of pixmap cache anyway. 2455c582b7e3Smrg */ 2456c582b7e3Smrg if (info->textureSize < (int)info->FbMapSize / 2) { 2457c582b7e3Smrg info->textureSize = info->FbMapSize - 4 * bufferSize; 2458c582b7e3Smrg } 2459c582b7e3Smrg 2460c582b7e3Smrg if (info->textureSize > 0) { 2461c582b7e3Smrg l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS); 2462c582b7e3Smrg if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY; 2463c582b7e3Smrg 2464c582b7e3Smrg /* Round the texture size up to the nearest whole number of 2465c582b7e3Smrg * texture regions. Again, be greedy about this, don't 2466c582b7e3Smrg * round down. 2467c582b7e3Smrg */ 2468c582b7e3Smrg info->log2TexGran = l; 2469c582b7e3Smrg info->textureSize = (info->textureSize >> l) << l; 2470c582b7e3Smrg } else { 2471c582b7e3Smrg info->textureSize = 0; 2472c582b7e3Smrg } 2473c582b7e3Smrg 2474c582b7e3Smrg /* Set a minimum usable local texture heap size. This will fit 2475c582b7e3Smrg * two 256x256x32bpp textures. 2476c582b7e3Smrg */ 2477c582b7e3Smrg if (info->textureSize < 512 * 1024) { 2478c582b7e3Smrg info->textureOffset = 0; 2479c582b7e3Smrg info->textureSize = 0; 2480c582b7e3Smrg } 2481c582b7e3Smrg 2482c582b7e3Smrg total = info->FbMapSize - info->textureSize; 2483c582b7e3Smrg scanlines = total / width_bytes; 2484c582b7e3Smrg if (scanlines > 8191) scanlines = 8191; 2485c582b7e3Smrg 2486c582b7e3Smrg /* Recalculate the texture offset and size to accomodate any 2487c582b7e3Smrg * rounding to a whole number of scanlines. 2488c582b7e3Smrg */ 2489c582b7e3Smrg info->textureOffset = scanlines * width_bytes; 2490c582b7e3Smrg 2491c582b7e3Smrg MemBox.x1 = 0; 2492c582b7e3Smrg MemBox.y1 = 0; 2493c582b7e3Smrg MemBox.x2 = pScrn->displayWidth; 2494c582b7e3Smrg MemBox.y2 = scanlines; 2495c582b7e3Smrg 2496c582b7e3Smrg if (!xf86InitFBManager(pScreen, &MemBox)) { 2497c582b7e3Smrg xf86DrvMsg(scrnIndex, X_ERROR, 2498c582b7e3Smrg "Memory manager initialization to (%d,%d) (%d,%d) failed\n", 2499c582b7e3Smrg MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); 2500c582b7e3Smrg return FALSE; 2501c582b7e3Smrg } else { 2502c582b7e3Smrg int width, height; 2503c582b7e3Smrg 2504c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, 2505c582b7e3Smrg "Memory manager initialized to (%d,%d) (%d,%d)\n", 2506c582b7e3Smrg MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); 2507c582b7e3Smrg if ((fbarea = xf86AllocateOffscreenArea(pScreen, 2508c582b7e3Smrg pScrn->displayWidth, 2509c582b7e3Smrg 2, 0, NULL, NULL, NULL))) { 2510c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, 2511c582b7e3Smrg "Reserved area from (%d,%d) to (%d,%d)\n", 2512c582b7e3Smrg fbarea->box.x1, fbarea->box.y1, 2513c582b7e3Smrg fbarea->box.x2, fbarea->box.y2); 2514c582b7e3Smrg } else { 2515c582b7e3Smrg xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); 2516c582b7e3Smrg } 2517c582b7e3Smrg if (xf86QueryLargestOffscreenArea(pScreen, &width, 2518c582b7e3Smrg &height, 0, 0, 0)) { 2519c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, 2520c582b7e3Smrg "Largest offscreen area available: %d x %d\n", 2521c582b7e3Smrg width, height); 2522c582b7e3Smrg } 2523c582b7e3Smrg } 2524c582b7e3Smrg 2525c582b7e3Smrg /* Allocate the shared back buffer */ 2526c582b7e3Smrg if ((fbarea = xf86AllocateOffscreenArea(pScreen, 2527c582b7e3Smrg pScrn->virtualX, 2528c582b7e3Smrg pScrn->virtualY, 2529c582b7e3Smrg 32, NULL, NULL, NULL))) { 2530c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, 2531c582b7e3Smrg "Reserved back buffer from (%d,%d) to (%d,%d)\n", 2532c582b7e3Smrg fbarea->box.x1, fbarea->box.y1, 2533c582b7e3Smrg fbarea->box.x2, fbarea->box.y2); 2534c582b7e3Smrg 2535c582b7e3Smrg info->backX = fbarea->box.x1; 2536c582b7e3Smrg info->backY = fbarea->box.y1; 2537c582b7e3Smrg info->backOffset = (fbarea->box.y1 * width_bytes + 2538c582b7e3Smrg fbarea->box.x1 * cpp); 2539c582b7e3Smrg info->backPitch = pScrn->displayWidth; 2540c582b7e3Smrg } else { 2541c582b7e3Smrg xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve back buffer\n"); 2542c582b7e3Smrg info->backX = -1; 2543c582b7e3Smrg info->backY = -1; 2544c582b7e3Smrg info->backOffset = -1; 2545c582b7e3Smrg info->backPitch = -1; 2546c582b7e3Smrg } 2547c582b7e3Smrg 2548c582b7e3Smrg /* Allocate the shared depth buffer */ 2549c582b7e3Smrg if ((fbarea = xf86AllocateOffscreenArea(pScreen, 2550c582b7e3Smrg pScrn->virtualX, 2551c582b7e3Smrg pScrn->virtualY + 1, 2552c582b7e3Smrg 32, NULL, NULL, NULL))) { 2553c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, 2554c582b7e3Smrg "Reserved depth buffer from (%d,%d) to (%d,%d)\n", 2555c582b7e3Smrg fbarea->box.x1, fbarea->box.y1, 2556c582b7e3Smrg fbarea->box.x2, fbarea->box.y2); 2557c582b7e3Smrg 2558c582b7e3Smrg info->depthX = fbarea->box.x1; 2559c582b7e3Smrg info->depthY = fbarea->box.y1; 2560c582b7e3Smrg info->depthOffset = (fbarea->box.y1 * width_bytes + 2561c582b7e3Smrg fbarea->box.x1 * cpp); 2562c582b7e3Smrg info->depthPitch = pScrn->displayWidth; 2563c582b7e3Smrg info->spanOffset = ((fbarea->box.y2 - 1) * width_bytes + 2564c582b7e3Smrg fbarea->box.x1 * cpp); 2565c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, 2566c582b7e3Smrg "Reserved depth span from (%d,%d) offset 0x%x\n", 2567c582b7e3Smrg fbarea->box.x1, fbarea->box.y2 - 1, info->spanOffset); 2568c582b7e3Smrg } else { 2569c582b7e3Smrg xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve depth buffer\n"); 2570c582b7e3Smrg info->depthX = -1; 2571c582b7e3Smrg info->depthY = -1; 2572c582b7e3Smrg info->depthOffset = -1; 2573c582b7e3Smrg info->depthPitch = -1; 2574c582b7e3Smrg info->spanOffset = -1; 2575c582b7e3Smrg } 2576c582b7e3Smrg 2577c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, 2578c582b7e3Smrg "Reserved %d kb for textures at offset 0x%x\n", 2579c582b7e3Smrg info->textureSize/1024, info->textureOffset); 2580c582b7e3Smrg } 2581c582b7e3Smrg else 2582c582b7e3Smrg#endif 2583c582b7e3Smrg { 2584c582b7e3Smrg MemBox.x1 = 0; 2585c582b7e3Smrg MemBox.y1 = 0; 2586c582b7e3Smrg MemBox.x2 = pScrn->displayWidth; 2587c582b7e3Smrg y2 = (info->FbMapSize 2588c582b7e3Smrg / (pScrn->displayWidth * 2589c582b7e3Smrg info->CurrentLayout.pixel_bytes)); 2590c582b7e3Smrg /* The acceleration engine uses 14 bit 2591c582b7e3Smrg signed coordinates, so we can't have any 2592c582b7e3Smrg drawable caches beyond this region. */ 2593c582b7e3Smrg if (y2 > 8191) y2 = 8191; 2594c582b7e3Smrg MemBox.y2 = y2; 2595c582b7e3Smrg 2596c582b7e3Smrg if (!xf86InitFBManager(pScreen, &MemBox)) { 2597c582b7e3Smrg xf86DrvMsg(scrnIndex, X_ERROR, 2598c582b7e3Smrg "Memory manager initialization to (%d,%d) (%d,%d) failed\n", 2599c582b7e3Smrg MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); 2600c582b7e3Smrg return FALSE; 2601c582b7e3Smrg } else { 2602c582b7e3Smrg int width, height; 2603c582b7e3Smrg FBAreaPtr fbarea; 2604c582b7e3Smrg 2605c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, 2606c582b7e3Smrg "Memory manager initialized to (%d,%d) (%d,%d)\n", 2607c582b7e3Smrg MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); 2608c582b7e3Smrg if ((fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, 2609c582b7e3Smrg 2, 0, NULL, NULL, NULL))) { 2610c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, 2611c582b7e3Smrg "Reserved area from (%d,%d) to (%d,%d)\n", 2612c582b7e3Smrg fbarea->box.x1, fbarea->box.y1, 2613c582b7e3Smrg fbarea->box.x2, fbarea->box.y2); 2614c582b7e3Smrg } else { 2615c582b7e3Smrg xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); 2616c582b7e3Smrg } 2617c582b7e3Smrg if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 2618c582b7e3Smrg 0, 0, 0)) { 2619c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, 2620c582b7e3Smrg "Largest offscreen area available: %d x %d\n", 2621c582b7e3Smrg width, height); 2622c582b7e3Smrg } 2623c582b7e3Smrg } 2624c582b7e3Smrg } 2625c582b7e3Smrg 2626c582b7e3Smrg /* Acceleration setup */ 2627c582b7e3Smrg if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { 2628c582b7e3Smrg if (R128AccelInit(pScreen)) { 2629c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n"); 2630c582b7e3Smrg info->accelOn = TRUE; 2631c582b7e3Smrg } else { 2632c582b7e3Smrg xf86DrvMsg(scrnIndex, X_ERROR, 2633c582b7e3Smrg "Acceleration initialization failed\n"); 2634c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); 2635c582b7e3Smrg info->accelOn = FALSE; 2636c582b7e3Smrg } 2637c582b7e3Smrg } else { 2638c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n"); 2639c582b7e3Smrg info->accelOn = FALSE; 2640c582b7e3Smrg } 2641c582b7e3Smrg 2642c582b7e3Smrg /* DGA setup */ 2643c582b7e3Smrg R128DGAInit(pScreen); 2644c582b7e3Smrg 2645c582b7e3Smrg /* Backing store setup */ 2646c582b7e3Smrg miInitializeBackingStore(pScreen); 2647c582b7e3Smrg xf86SetBackingStore(pScreen); 2648c582b7e3Smrg 2649c582b7e3Smrg /* Set Silken Mouse */ 2650c582b7e3Smrg xf86SetSilkenMouse(pScreen); 2651c582b7e3Smrg 2652c582b7e3Smrg /* Cursor setup */ 2653c582b7e3Smrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 2654c582b7e3Smrg 2655c582b7e3Smrg /* Hardware cursor setup */ 2656c582b7e3Smrg if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 2657c582b7e3Smrg if (R128CursorInit(pScreen)) { 2658c582b7e3Smrg int width, height; 2659c582b7e3Smrg 2660c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2661c582b7e3Smrg "Using hardware cursor (scanline %ld)\n", 2662c582b7e3Smrg info->cursor_start / pScrn->displayWidth); 2663c582b7e3Smrg if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 2664c582b7e3Smrg 0, 0, 0)) { 2665c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, 2666c582b7e3Smrg "Largest offscreen area available: %d x %d\n", 2667c582b7e3Smrg width, height); 2668c582b7e3Smrg } 2669c582b7e3Smrg } else { 2670c582b7e3Smrg xf86DrvMsg(scrnIndex, X_ERROR, 2671c582b7e3Smrg "Hardware cursor initialization failed\n"); 2672c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n"); 2673c582b7e3Smrg } 2674c582b7e3Smrg } else { 2675c582b7e3Smrg info->cursor_start = 0; 2676c582b7e3Smrg xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n"); 2677c582b7e3Smrg } 2678c582b7e3Smrg 2679c582b7e3Smrg /* Colormap setup */ 2680c582b7e3Smrg if (!miCreateDefColormap(pScreen)) return FALSE; 2681c582b7e3Smrg if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8, 268279e5230eSmacallan ( 268379e5230eSmacallan#ifndef AVOID_FBDEV 268479e5230eSmacallan info->FBDev ? fbdevHWLoadPaletteWeak() : 268579e5230eSmacallan#endif 2686c582b7e3Smrg R128LoadPalette), NULL, 2687c582b7e3Smrg CMAP_PALETTED_TRUECOLOR 2688c582b7e3Smrg | CMAP_RELOAD_ON_MODE_SWITCH 2689c582b7e3Smrg#if 0 /* This option messes up text mode! (eich@suse.de) */ 2690c582b7e3Smrg | CMAP_LOAD_EVEN_IF_OFFSCREEN 2691c582b7e3Smrg#endif 2692c582b7e3Smrg )) return FALSE; 2693c582b7e3Smrg 2694c582b7e3Smrg /* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */ 269579e5230eSmacallan#ifndef AVOID_FBDEV 2696c582b7e3Smrg if (info->FBDev) 2697c582b7e3Smrg xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0); 2698c582b7e3Smrg 269979e5230eSmacallan else 270079e5230eSmacallan#endif 270179e5230eSmacallan { 2702c582b7e3Smrg if (info->DisplayType == MT_LCD) 2703c582b7e3Smrg xf86DPMSInit(pScreen, R128DisplayPowerManagementSetLCD, 0); 2704c582b7e3Smrg else 2705c582b7e3Smrg xf86DPMSInit(pScreen, R128DisplayPowerManagementSet, 0); 2706c582b7e3Smrg } 2707c582b7e3Smrg 2708c582b7e3Smrg if (!info->IsSecondary) 2709c582b7e3Smrg R128InitVideo(pScreen); 2710c582b7e3Smrg 2711c582b7e3Smrg /* Provide SaveScreen */ 2712c582b7e3Smrg pScreen->SaveScreen = R128SaveScreen; 2713c582b7e3Smrg 2714c582b7e3Smrg /* Wrap CloseScreen */ 2715c582b7e3Smrg info->CloseScreen = pScreen->CloseScreen; 2716c582b7e3Smrg pScreen->CloseScreen = R128CloseScreen; 2717c582b7e3Smrg 2718c582b7e3Smrg /* Note unused options */ 2719c582b7e3Smrg if (serverGeneration == 1) 2720c582b7e3Smrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 2721c582b7e3Smrg 2722c582b7e3Smrg#ifdef XF86DRI 2723c582b7e3Smrg /* DRI finalization */ 2724c582b7e3Smrg if (info->directRenderingEnabled) { 2725c582b7e3Smrg /* Now that mi, fb, drm and others have 2726c582b7e3Smrg done their thing, complete the DRI 2727c582b7e3Smrg setup. */ 2728c582b7e3Smrg info->directRenderingEnabled = R128DRIFinishScreenInit(pScreen); 2729c582b7e3Smrg } 2730c582b7e3Smrg if (info->directRenderingEnabled) { 2731c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); 2732c582b7e3Smrg } else { 2733c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2734c582b7e3Smrg "Direct rendering disabled\n"); 2735c582b7e3Smrg } 2736c582b7e3Smrg#endif 2737c582b7e3Smrg 2738c582b7e3Smrg info->BlockHandler = pScreen->BlockHandler; 2739c582b7e3Smrg pScreen->BlockHandler = R128BlockHandler; 2740c582b7e3Smrg 2741c582b7e3Smrg return TRUE; 2742c582b7e3Smrg} 2743c582b7e3Smrg 2744c582b7e3Smrg/* Write common registers (initialized to 0). */ 2745c582b7e3Smrgstatic void R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 2746c582b7e3Smrg{ 2747c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 2748c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 2749c582b7e3Smrg 2750c582b7e3Smrg OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl | R128_FP_BLANK_DIS); 2751c582b7e3Smrg 2752c582b7e3Smrg OUTREG(R128_OVR_CLR, restore->ovr_clr); 2753c582b7e3Smrg OUTREG(R128_OVR_WID_LEFT_RIGHT, restore->ovr_wid_left_right); 2754c582b7e3Smrg OUTREG(R128_OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom); 2755c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, restore->ov0_scale_cntl); 2756c582b7e3Smrg OUTREG(R128_MPP_TB_CONFIG, restore->mpp_tb_config ); 2757c582b7e3Smrg OUTREG(R128_MPP_GP_CONFIG, restore->mpp_gp_config ); 2758c582b7e3Smrg OUTREG(R128_SUBPIC_CNTL, restore->subpic_cntl); 2759c582b7e3Smrg OUTREG(R128_VIPH_CONTROL, restore->viph_control); 2760c582b7e3Smrg OUTREG(R128_I2C_CNTL_1, restore->i2c_cntl_1); 2761c582b7e3Smrg OUTREG(R128_GEN_INT_CNTL, restore->gen_int_cntl); 2762c582b7e3Smrg OUTREG(R128_CAP0_TRIG_CNTL, restore->cap0_trig_cntl); 2763c582b7e3Smrg OUTREG(R128_CAP1_TRIG_CNTL, restore->cap1_trig_cntl); 2764c582b7e3Smrg OUTREG(R128_BUS_CNTL, restore->bus_cntl); 2765c582b7e3Smrg OUTREG(R128_CONFIG_CNTL, restore->config_cntl); 2766c582b7e3Smrg} 2767c582b7e3Smrg 2768c582b7e3Smrg/* Write CRTC registers. */ 2769c582b7e3Smrgstatic void R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 2770c582b7e3Smrg{ 2771c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 2772c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 2773c582b7e3Smrg 2774c582b7e3Smrg OUTREG(R128_CRTC_GEN_CNTL, restore->crtc_gen_cntl); 2775c582b7e3Smrg 2776c582b7e3Smrg OUTREGP(R128_CRTC_EXT_CNTL, restore->crtc_ext_cntl, 2777c582b7e3Smrg R128_CRTC_VSYNC_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_DISPLAY_DIS); 2778c582b7e3Smrg 2779c582b7e3Smrg OUTREGP(R128_DAC_CNTL, restore->dac_cntl, 2780c582b7e3Smrg R128_DAC_RANGE_CNTL | R128_DAC_BLANKING); 2781c582b7e3Smrg 2782c582b7e3Smrg OUTREG(R128_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); 2783c582b7e3Smrg OUTREG(R128_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); 2784c582b7e3Smrg OUTREG(R128_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); 2785c582b7e3Smrg OUTREG(R128_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid); 2786c582b7e3Smrg OUTREG(R128_CRTC_OFFSET, restore->crtc_offset); 2787c582b7e3Smrg OUTREG(R128_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); 2788c582b7e3Smrg OUTREG(R128_CRTC_PITCH, restore->crtc_pitch); 2789c582b7e3Smrg} 2790c582b7e3Smrg 2791c582b7e3Smrg/* Write CRTC2 registers. */ 2792c582b7e3Smrgstatic void R128RestoreCrtc2Registers(ScrnInfoPtr pScrn, 2793c582b7e3Smrg R128SavePtr restore) 2794c582b7e3Smrg{ 2795c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 2796c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 2797c582b7e3Smrg 2798c582b7e3Smrg OUTREGP(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl, 2799c582b7e3Smrg R128_CRTC2_DISP_DIS); 2800c582b7e3Smrg 2801c582b7e3Smrg OUTREG(R128_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); 2802c582b7e3Smrg OUTREG(R128_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid); 2803c582b7e3Smrg OUTREG(R128_CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp); 2804c582b7e3Smrg OUTREG(R128_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid); 2805c582b7e3Smrg OUTREG(R128_CRTC2_OFFSET, restore->crtc2_offset); 2806c582b7e3Smrg OUTREG(R128_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); 2807c582b7e3Smrg OUTREG(R128_CRTC2_PITCH, restore->crtc2_pitch); 2808c582b7e3Smrg} 2809c582b7e3Smrg 2810c582b7e3Smrg/* Write flat panel registers */ 2811c582b7e3Smrgstatic void R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 2812c582b7e3Smrg{ 2813c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 2814c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 2815c582b7e3Smrg CARD32 tmp; 2816c582b7e3Smrg 2817c582b7e3Smrg if (info->BIOSDisplay != R128_DUALHEAD) 2818c582b7e3Smrg OUTREG(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); 2819c582b7e3Smrg OUTREG(R128_FP_HORZ_STRETCH, restore->fp_horz_stretch); 2820c582b7e3Smrg OUTREG(R128_FP_VERT_STRETCH, restore->fp_vert_stretch); 2821c582b7e3Smrg OUTREG(R128_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp); 2822c582b7e3Smrg OUTREG(R128_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp); 2823c582b7e3Smrg OUTREG(R128_FP_H_SYNC_STRT_WID, restore->fp_h_sync_strt_wid); 2824c582b7e3Smrg OUTREG(R128_FP_V_SYNC_STRT_WID, restore->fp_v_sync_strt_wid); 2825c582b7e3Smrg OUTREG(R128_TMDS_CRC, restore->tmds_crc); 2826c582b7e3Smrg OUTREG(R128_FP_PANEL_CNTL, restore->fp_panel_cntl); 2827c582b7e3Smrg OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl & ~(CARD32)R128_FP_BLANK_DIS); 2828c582b7e3Smrg 2829c582b7e3Smrg if(info->isDFP) return; 2830c582b7e3Smrg 2831c582b7e3Smrg tmp = INREG(R128_LVDS_GEN_CNTL); 2832c582b7e3Smrg if ((tmp & (R128_LVDS_ON | R128_LVDS_BLON)) == 2833c582b7e3Smrg (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON))) { 2834c582b7e3Smrg OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl); 2835c582b7e3Smrg } else { 2836c582b7e3Smrg if (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON)) { 2837c582b7e3Smrg OUTREG(R128_LVDS_GEN_CNTL, 2838c582b7e3Smrg restore->lvds_gen_cntl & (CARD32)~R128_LVDS_BLON); 2839c582b7e3Smrg usleep(R128PTR(pScrn)->PanelPwrDly * 1000); 2840c582b7e3Smrg OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl); 2841c582b7e3Smrg } else { 2842c582b7e3Smrg OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl | R128_LVDS_BLON); 2843c582b7e3Smrg usleep(R128PTR(pScrn)->PanelPwrDly * 1000); 2844c582b7e3Smrg OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl); 2845c582b7e3Smrg } 2846c582b7e3Smrg } 2847c582b7e3Smrg} 2848c582b7e3Smrg 2849c582b7e3Smrgstatic void R128PLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn) 2850c582b7e3Smrg{ 2851c582b7e3Smrg while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R); 2852c582b7e3Smrg} 2853c582b7e3Smrg 2854c582b7e3Smrgstatic void R128PLLWriteUpdate(ScrnInfoPtr pScrn) 2855c582b7e3Smrg{ 2856c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 2857c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 2858c582b7e3Smrg 2859c582b7e3Smrg while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R); 2860c582b7e3Smrg 2861c582b7e3Smrg OUTPLLP(pScrn, R128_PPLL_REF_DIV, R128_PPLL_ATOMIC_UPDATE_W, 2862c582b7e3Smrg ~R128_PPLL_ATOMIC_UPDATE_W); 2863c582b7e3Smrg 2864c582b7e3Smrg} 2865c582b7e3Smrg 2866c582b7e3Smrgstatic void R128PLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn) 2867c582b7e3Smrg{ 2868c582b7e3Smrg while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R); 2869c582b7e3Smrg} 2870c582b7e3Smrg 2871c582b7e3Smrgstatic void R128PLL2WriteUpdate(ScrnInfoPtr pScrn) 2872c582b7e3Smrg{ 2873c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 2874c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 2875c582b7e3Smrg 2876c582b7e3Smrg while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R); 2877c582b7e3Smrg 2878c582b7e3Smrg OUTPLLP(pScrn, R128_P2PLL_REF_DIV, 2879c582b7e3Smrg R128_P2PLL_ATOMIC_UPDATE_W, 2880c582b7e3Smrg ~(R128_P2PLL_ATOMIC_UPDATE_W)); 2881c582b7e3Smrg} 2882c582b7e3Smrg 2883c582b7e3Smrg/* Write PLL registers. */ 2884c582b7e3Smrgstatic void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 2885c582b7e3Smrg{ 2886c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 2887c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 2888c582b7e3Smrg 2889c582b7e3Smrg 2890c582b7e3Smrg OUTPLLP(pScrn, R128_VCLK_ECP_CNTL, 2891c582b7e3Smrg R128_VCLK_SRC_SEL_CPUCLK, 2892c582b7e3Smrg ~(R128_VCLK_SRC_SEL_MASK)); 2893c582b7e3Smrg 2894c582b7e3Smrg OUTPLLP(pScrn, 2895c582b7e3Smrg R128_PPLL_CNTL, 2896c582b7e3Smrg R128_PPLL_RESET 2897c582b7e3Smrg | R128_PPLL_ATOMIC_UPDATE_EN 2898c582b7e3Smrg | R128_PPLL_VGA_ATOMIC_UPDATE_EN, 2899c582b7e3Smrg ~(R128_PPLL_RESET 2900c582b7e3Smrg | R128_PPLL_ATOMIC_UPDATE_EN 2901c582b7e3Smrg | R128_PPLL_VGA_ATOMIC_UPDATE_EN)); 2902c582b7e3Smrg 2903c582b7e3Smrg OUTREGP(R128_CLOCK_CNTL_INDEX, R128_PLL_DIV_SEL, ~(R128_PLL_DIV_SEL)); 2904c582b7e3Smrg 2905c582b7e3Smrg/* R128PLLWaitForReadUpdateComplete(pScrn);*/ 2906c582b7e3Smrg OUTPLLP(pScrn, R128_PPLL_REF_DIV, 2907c582b7e3Smrg restore->ppll_ref_div, ~R128_PPLL_REF_DIV_MASK); 2908c582b7e3Smrg/* R128PLLWriteUpdate(pScrn); 2909c582b7e3Smrg 2910c582b7e3Smrg R128PLLWaitForReadUpdateComplete(pScrn);*/ 2911c582b7e3Smrg OUTPLLP(pScrn, R128_PPLL_DIV_3, 2912c582b7e3Smrg restore->ppll_div_3, ~R128_PPLL_FB3_DIV_MASK); 2913c582b7e3Smrg/* R128PLLWriteUpdate(pScrn);*/ 2914c582b7e3Smrg OUTPLLP(pScrn, R128_PPLL_DIV_3, 2915c582b7e3Smrg restore->ppll_div_3, ~R128_PPLL_POST3_DIV_MASK); 2916c582b7e3Smrg 2917c582b7e3Smrg R128PLLWriteUpdate(pScrn); 2918c582b7e3Smrg R128PLLWaitForReadUpdateComplete(pScrn); 2919c582b7e3Smrg 29209e881af1Smacallan OUTPLLP(pScrn, R128_PPLL_DIV_0, 29219e881af1Smacallan restore->ppll_div_0, ~R128_PPLL_FB0_DIV_MASK); 29229e881af1Smacallan/* R128PLLWriteUpdate(pScrn);*/ 29239e881af1Smacallan OUTPLLP(pScrn, R128_PPLL_DIV_0, 29249e881af1Smacallan restore->ppll_div_0, ~R128_PPLL_POST0_DIV_MASK); 29259e881af1Smacallan 29269e881af1Smacallan R128PLLWriteUpdate(pScrn); 29279e881af1Smacallan R128PLLWaitForReadUpdateComplete(pScrn); 29289e881af1Smacallan 2929c582b7e3Smrg OUTPLL(R128_HTOTAL_CNTL, restore->htotal_cntl); 2930c582b7e3Smrg/* R128PLLWriteUpdate(pScrn);*/ 2931c582b7e3Smrg 2932c582b7e3Smrg OUTPLLP(pScrn, R128_PPLL_CNTL, 0, ~(R128_PPLL_RESET 2933c582b7e3Smrg | R128_PPLL_SLEEP 2934c582b7e3Smrg | R128_PPLL_ATOMIC_UPDATE_EN 2935c582b7e3Smrg | R128_PPLL_VGA_ATOMIC_UPDATE_EN)); 2936c582b7e3Smrg 2937c582b7e3Smrg R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", 2938c582b7e3Smrg restore->ppll_ref_div, 2939c582b7e3Smrg restore->ppll_div_3, 2940c582b7e3Smrg restore->htotal_cntl, 2941c582b7e3Smrg INPLL(pScrn, R128_PPLL_CNTL))); 2942c582b7e3Smrg R128TRACE(("Wrote: rd=%d, fd=%d, pd=%d\n", 2943c582b7e3Smrg restore->ppll_ref_div & R128_PPLL_REF_DIV_MASK, 2944c582b7e3Smrg restore->ppll_div_3 & R128_PPLL_FB3_DIV_MASK, 2945c582b7e3Smrg (restore->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16)); 2946c582b7e3Smrg 2947c582b7e3Smrg usleep(5000); /* let the clock lock */ 2948c582b7e3Smrg 2949c582b7e3Smrg OUTPLLP(pScrn, R128_VCLK_ECP_CNTL, 2950c582b7e3Smrg R128_VCLK_SRC_SEL_PPLLCLK, 2951c582b7e3Smrg ~(R128_VCLK_SRC_SEL_MASK)); 2952c582b7e3Smrg 2953c582b7e3Smrg} 2954c582b7e3Smrg 2955c582b7e3Smrg/* Write PLL2 registers. */ 2956c582b7e3Smrgstatic void R128RestorePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) 2957c582b7e3Smrg{ 2958c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 2959c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 2960c582b7e3Smrg 2961c582b7e3Smrg OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL, 2962c582b7e3Smrg R128_V2CLK_SRC_SEL_CPUCLK, 2963c582b7e3Smrg ~R128_V2CLK_SRC_SEL_MASK); 2964c582b7e3Smrg 2965c582b7e3Smrg OUTPLLP(pScrn, 2966c582b7e3Smrg R128_P2PLL_CNTL, 2967c582b7e3Smrg R128_P2PLL_RESET 2968c582b7e3Smrg | R128_P2PLL_ATOMIC_UPDATE_EN 2969c582b7e3Smrg | R128_P2PLL_VGA_ATOMIC_UPDATE_EN, 2970c582b7e3Smrg ~(R128_P2PLL_RESET 2971c582b7e3Smrg | R128_P2PLL_ATOMIC_UPDATE_EN 2972c582b7e3Smrg | R128_P2PLL_VGA_ATOMIC_UPDATE_EN)); 2973c582b7e3Smrg 2974c582b7e3Smrg#if 1 2975c582b7e3Smrg OUTREGP(R128_CLOCK_CNTL_INDEX, 0, R128_PLL2_DIV_SEL_MASK); 2976c582b7e3Smrg#endif 2977c582b7e3Smrg 2978c582b7e3Smrg /*R128PLL2WaitForReadUpdateComplete(pScrn);*/ 2979c582b7e3Smrg 2980c582b7e3Smrg OUTPLLP(pScrn, R128_P2PLL_REF_DIV, restore->p2pll_ref_div, ~R128_P2PLL_REF_DIV_MASK); 2981c582b7e3Smrg 2982c582b7e3Smrg/* R128PLL2WriteUpdate(pScrn); 2983c582b7e3Smrg R128PLL2WaitForReadUpdateComplete(pScrn);*/ 2984c582b7e3Smrg 2985c582b7e3Smrg OUTPLLP(pScrn, R128_P2PLL_DIV_0, 2986c582b7e3Smrg restore->p2pll_div_0, ~R128_P2PLL_FB0_DIV_MASK); 2987c582b7e3Smrg 2988c582b7e3Smrg/* R128PLL2WriteUpdate(pScrn); 2989c582b7e3Smrg R128PLL2WaitForReadUpdateComplete(pScrn);*/ 2990c582b7e3Smrg 2991c582b7e3Smrg OUTPLLP(pScrn, R128_P2PLL_DIV_0, 2992c582b7e3Smrg restore->p2pll_div_0, ~R128_P2PLL_POST0_DIV_MASK); 2993c582b7e3Smrg 2994c582b7e3Smrg R128PLL2WriteUpdate(pScrn); 2995c582b7e3Smrg R128PLL2WaitForReadUpdateComplete(pScrn); 2996c582b7e3Smrg 2997c582b7e3Smrg OUTPLL(R128_HTOTAL2_CNTL, restore->htotal_cntl2); 2998c582b7e3Smrg 2999c582b7e3Smrg/* R128PLL2WriteUpdate(pScrn);*/ 3000c582b7e3Smrg 3001c582b7e3Smrg OUTPLLP(pScrn, R128_P2PLL_CNTL, 0, ~(R128_P2PLL_RESET 3002c582b7e3Smrg | R128_P2PLL_SLEEP 3003c582b7e3Smrg | R128_P2PLL_ATOMIC_UPDATE_EN 3004c582b7e3Smrg | R128_P2PLL_VGA_ATOMIC_UPDATE_EN)); 3005c582b7e3Smrg 3006c582b7e3Smrg R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", 3007c582b7e3Smrg restore->p2pll_ref_div, 3008c582b7e3Smrg restore->p2pll_div_0, 3009c582b7e3Smrg restore->htotal_cntl2, 30109e881af1Smacallan INPLL(pScrn, R128_P2PLL_CNTL))); 3011c582b7e3Smrg 3012c582b7e3Smrg usleep(5000); /* Let the clock to lock */ 3013c582b7e3Smrg 3014c582b7e3Smrg OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL, 3015c582b7e3Smrg R128_V2CLK_SRC_SEL_P2PLLCLK, 3016c582b7e3Smrg ~R128_V2CLK_SRC_SEL_MASK); 3017c582b7e3Smrg 3018c582b7e3Smrg} 3019c582b7e3Smrg 3020c582b7e3Smrg/* Write DDA registers. */ 3021c582b7e3Smrgstatic void R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 3022c582b7e3Smrg{ 3023c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3024c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 3025c582b7e3Smrg 3026c582b7e3Smrg OUTREG(R128_DDA_CONFIG, restore->dda_config); 3027c582b7e3Smrg OUTREG(R128_DDA_ON_OFF, restore->dda_on_off); 3028c582b7e3Smrg} 3029c582b7e3Smrg 3030c582b7e3Smrg/* Write DDA registers. */ 3031c582b7e3Smrgstatic void R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) 3032c582b7e3Smrg{ 3033c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3034c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 3035c582b7e3Smrg 3036c582b7e3Smrg OUTREG(R128_DDA2_CONFIG, restore->dda2_config); 3037c582b7e3Smrg OUTREG(R128_DDA2_ON_OFF, restore->dda2_on_off); 3038c582b7e3Smrg} 3039c582b7e3Smrg 3040c582b7e3Smrg/* Write palette data. */ 3041c582b7e3Smrgstatic void R128RestorePalette(ScrnInfoPtr pScrn, R128SavePtr restore) 3042c582b7e3Smrg{ 3043c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3044c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 3045c582b7e3Smrg int i; 3046c582b7e3Smrg 3047c582b7e3Smrg if (!restore->palette_valid) return; 3048c582b7e3Smrg 3049c582b7e3Smrg PAL_SELECT(1); 3050c582b7e3Smrg OUTPAL_START(0); 3051c582b7e3Smrg for (i = 0; i < 256; i++) { 3052c582b7e3Smrg R128WaitForFifo(pScrn, 32); /* delay */ 3053c582b7e3Smrg OUTPAL_NEXT_CARD32(restore->palette2[i]); 3054c582b7e3Smrg } 3055c582b7e3Smrg 3056c582b7e3Smrg PAL_SELECT(0); 3057c582b7e3Smrg OUTPAL_START(0); 3058c582b7e3Smrg for (i = 0; i < 256; i++) { 3059c582b7e3Smrg R128WaitForFifo(pScrn, 32); /* delay */ 3060c582b7e3Smrg OUTPAL_NEXT_CARD32(restore->palette[i]); 3061c582b7e3Smrg } 3062c582b7e3Smrg 3063c582b7e3Smrg} 3064c582b7e3Smrg 3065c582b7e3Smrg/* Write out state to define a new video mode. */ 3066c582b7e3Smrgstatic void R128RestoreMode(ScrnInfoPtr pScrn, R128SavePtr restore) 3067c582b7e3Smrg{ 3068c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3069c582b7e3Smrg DevUnion* pPriv; 3070c582b7e3Smrg R128EntPtr pR128Ent; 3071c582b7e3Smrg static R128SaveRec restore0; 3072c582b7e3Smrg 3073c582b7e3Smrg R128TRACE(("R128RestoreMode(%p)\n", restore)); 3074c582b7e3Smrg if(!info->HasCRTC2) 3075c582b7e3Smrg { 3076c582b7e3Smrg R128RestoreCommonRegisters(pScrn, restore); 3077c582b7e3Smrg R128RestoreDDARegisters(pScrn, restore); 3078c582b7e3Smrg R128RestoreCrtcRegisters(pScrn, restore); 3079c582b7e3Smrg if((info->DisplayType == MT_DFP) || 3080c582b7e3Smrg (info->DisplayType == MT_LCD)) 3081c582b7e3Smrg { 3082c582b7e3Smrg R128RestoreFPRegisters(pScrn, restore); 3083c582b7e3Smrg } 3084c582b7e3Smrg R128RestorePLLRegisters(pScrn, restore); 3085c582b7e3Smrg return; 3086c582b7e3Smrg } 3087c582b7e3Smrg 3088c582b7e3Smrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 3089c582b7e3Smrg getR128EntityIndex()); 3090c582b7e3Smrg pR128Ent = pPriv->ptr; 3091c582b7e3Smrg 3092c582b7e3Smrg 3093c582b7e3Smrg /***** 3094c582b7e3Smrg When changing mode with Dual-head card (VE/M6), care must 3095c582b7e3Smrg be taken for the special order in setting registers. CRTC2 has 3096c582b7e3Smrg to be set before changing CRTC_EXT register. 3097c582b7e3Smrg In the dual-head setup, X server calls this routine twice with 3098c582b7e3Smrg primary and secondary pScrn pointers respectively. The calls 3099c582b7e3Smrg can come with different order. Regardless the order of X server issuing 3100c582b7e3Smrg the calls, we have to ensure we set registers in the right order!!! 3101c582b7e3Smrg Otherwise we may get a blank screen. 3102c582b7e3Smrg *****/ 3103c582b7e3Smrg 3104c582b7e3Smrg if(info->IsSecondary) 3105c582b7e3Smrg { 3106c582b7e3Smrg if (!pR128Ent->RestorePrimary && !info->SwitchingMode) 3107c582b7e3Smrg R128RestoreCommonRegisters(pScrn, restore); 3108c582b7e3Smrg R128RestoreDDA2Registers(pScrn, restore); 3109c582b7e3Smrg R128RestoreCrtc2Registers(pScrn, restore); 3110c582b7e3Smrg R128RestorePLL2Registers(pScrn, restore); 3111c582b7e3Smrg 3112c582b7e3Smrg if(info->SwitchingMode) return; 3113c582b7e3Smrg 3114c582b7e3Smrg pR128Ent->IsSecondaryRestored = TRUE; 3115c582b7e3Smrg 3116c582b7e3Smrg if(pR128Ent->RestorePrimary) 3117c582b7e3Smrg { 3118c582b7e3Smrg R128InfoPtr info0 = R128PTR(pR128Ent->pPrimaryScrn); 3119c582b7e3Smrg pR128Ent->RestorePrimary = FALSE; 3120c582b7e3Smrg 3121c582b7e3Smrg R128RestoreCrtcRegisters(pScrn, &restore0); 3122c582b7e3Smrg if((info0->DisplayType == MT_DFP) || 3123c582b7e3Smrg (info0->DisplayType == MT_LCD)) 3124c582b7e3Smrg { 3125c582b7e3Smrg R128RestoreFPRegisters(pScrn, &restore0); 3126c582b7e3Smrg } 3127c582b7e3Smrg 3128c582b7e3Smrg R128RestorePLLRegisters(pScrn, &restore0); 3129c582b7e3Smrg pR128Ent->IsSecondaryRestored = FALSE; 3130c582b7e3Smrg 3131c582b7e3Smrg } 3132c582b7e3Smrg } 3133c582b7e3Smrg else 3134c582b7e3Smrg { 3135c582b7e3Smrg if (!pR128Ent->IsSecondaryRestored) 3136c582b7e3Smrg R128RestoreCommonRegisters(pScrn, restore); 3137c582b7e3Smrg R128RestoreDDARegisters(pScrn, restore); 3138c582b7e3Smrg if(!pR128Ent->HasSecondary || pR128Ent->IsSecondaryRestored 3139c582b7e3Smrg || info->SwitchingMode) 3140c582b7e3Smrg { 3141c582b7e3Smrg pR128Ent->IsSecondaryRestored = FALSE; 3142c582b7e3Smrg R128RestoreCrtcRegisters(pScrn, restore); 3143c582b7e3Smrg if((info->DisplayType == MT_DFP) || 3144c582b7e3Smrg (info->DisplayType == MT_LCD)) 3145c582b7e3Smrg { 3146c582b7e3Smrg R128RestoreFPRegisters(pScrn, restore); 3147c582b7e3Smrg } 3148c582b7e3Smrg R128RestorePLLRegisters(pScrn, restore); 3149c582b7e3Smrg } 3150c582b7e3Smrg else 3151c582b7e3Smrg { 3152c582b7e3Smrg memcpy(&restore0, restore, sizeof(restore0)); 3153c582b7e3Smrg pR128Ent->RestorePrimary = TRUE; 3154c582b7e3Smrg } 3155c582b7e3Smrg } 3156c582b7e3Smrg 3157c582b7e3Smrg R128RestorePalette(pScrn, restore); 3158c582b7e3Smrg} 3159c582b7e3Smrg 3160c582b7e3Smrg/* Read common registers. */ 3161c582b7e3Smrgstatic void R128SaveCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr save) 3162c582b7e3Smrg{ 3163c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3164c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 3165c582b7e3Smrg 3166c582b7e3Smrg save->ovr_clr = INREG(R128_OVR_CLR); 3167c582b7e3Smrg save->ovr_wid_left_right = INREG(R128_OVR_WID_LEFT_RIGHT); 3168c582b7e3Smrg save->ovr_wid_top_bottom = INREG(R128_OVR_WID_TOP_BOTTOM); 3169c582b7e3Smrg save->ov0_scale_cntl = INREG(R128_OV0_SCALE_CNTL); 3170c582b7e3Smrg save->mpp_tb_config = INREG(R128_MPP_TB_CONFIG); 3171c582b7e3Smrg save->mpp_gp_config = INREG(R128_MPP_GP_CONFIG); 3172c582b7e3Smrg save->subpic_cntl = INREG(R128_SUBPIC_CNTL); 3173c582b7e3Smrg save->viph_control = INREG(R128_VIPH_CONTROL); 3174c582b7e3Smrg save->i2c_cntl_1 = INREG(R128_I2C_CNTL_1); 3175c582b7e3Smrg save->gen_int_cntl = INREG(R128_GEN_INT_CNTL); 3176c582b7e3Smrg save->cap0_trig_cntl = INREG(R128_CAP0_TRIG_CNTL); 3177c582b7e3Smrg save->cap1_trig_cntl = INREG(R128_CAP1_TRIG_CNTL); 3178c582b7e3Smrg save->bus_cntl = INREG(R128_BUS_CNTL); 3179c582b7e3Smrg save->config_cntl = INREG(R128_CONFIG_CNTL); 3180c582b7e3Smrg} 3181c582b7e3Smrg 3182c582b7e3Smrg/* Read CRTC registers. */ 3183c582b7e3Smrgstatic void R128SaveCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save) 3184c582b7e3Smrg{ 3185c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3186c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 3187c582b7e3Smrg 3188c582b7e3Smrg save->crtc_gen_cntl = INREG(R128_CRTC_GEN_CNTL); 3189c582b7e3Smrg save->crtc_ext_cntl = INREG(R128_CRTC_EXT_CNTL); 3190c582b7e3Smrg save->dac_cntl = INREG(R128_DAC_CNTL); 3191c582b7e3Smrg save->crtc_h_total_disp = INREG(R128_CRTC_H_TOTAL_DISP); 3192c582b7e3Smrg save->crtc_h_sync_strt_wid = INREG(R128_CRTC_H_SYNC_STRT_WID); 3193c582b7e3Smrg save->crtc_v_total_disp = INREG(R128_CRTC_V_TOTAL_DISP); 3194c582b7e3Smrg save->crtc_v_sync_strt_wid = INREG(R128_CRTC_V_SYNC_STRT_WID); 3195c582b7e3Smrg save->crtc_offset = INREG(R128_CRTC_OFFSET); 3196c582b7e3Smrg save->crtc_offset_cntl = INREG(R128_CRTC_OFFSET_CNTL); 3197c582b7e3Smrg save->crtc_pitch = INREG(R128_CRTC_PITCH); 3198c582b7e3Smrg} 3199c582b7e3Smrg 3200c582b7e3Smrg/* Read flat panel registers */ 3201c582b7e3Smrgstatic void R128SaveFPRegisters(ScrnInfoPtr pScrn, R128SavePtr save) 3202c582b7e3Smrg{ 3203c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3204c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 3205c582b7e3Smrg 3206c582b7e3Smrg if (info->BIOSDisplay != R128_DUALHEAD) 3207c582b7e3Smrg save->crtc2_gen_cntl = INREG(R128_CRTC2_GEN_CNTL); 3208c582b7e3Smrg save->fp_crtc_h_total_disp = INREG(R128_FP_CRTC_H_TOTAL_DISP); 3209c582b7e3Smrg save->fp_crtc_v_total_disp = INREG(R128_FP_CRTC_V_TOTAL_DISP); 3210c582b7e3Smrg save->fp_gen_cntl = INREG(R128_FP_GEN_CNTL); 3211c582b7e3Smrg save->fp_h_sync_strt_wid = INREG(R128_FP_H_SYNC_STRT_WID); 3212c582b7e3Smrg save->fp_horz_stretch = INREG(R128_FP_HORZ_STRETCH); 3213c582b7e3Smrg save->fp_panel_cntl = INREG(R128_FP_PANEL_CNTL); 3214c582b7e3Smrg save->fp_v_sync_strt_wid = INREG(R128_FP_V_SYNC_STRT_WID); 3215c582b7e3Smrg save->fp_vert_stretch = INREG(R128_FP_VERT_STRETCH); 3216c582b7e3Smrg save->lvds_gen_cntl = INREG(R128_LVDS_GEN_CNTL); 3217c582b7e3Smrg save->tmds_crc = INREG(R128_TMDS_CRC); 3218c582b7e3Smrg save->tmds_transmitter_cntl = INREG(R128_TMDS_TRANSMITTER_CNTL); 3219c582b7e3Smrg} 3220c582b7e3Smrg 3221c582b7e3Smrg/* Read CRTC2 registers. */ 3222c582b7e3Smrgstatic void R128SaveCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save) 3223c582b7e3Smrg{ 3224c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3225c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 3226c582b7e3Smrg 3227c582b7e3Smrg save->crtc2_gen_cntl = INREG(R128_CRTC2_GEN_CNTL); 3228c582b7e3Smrg save->crtc2_h_total_disp = INREG(R128_CRTC2_H_TOTAL_DISP); 3229c582b7e3Smrg save->crtc2_h_sync_strt_wid = INREG(R128_CRTC2_H_SYNC_STRT_WID); 3230c582b7e3Smrg save->crtc2_v_total_disp = INREG(R128_CRTC2_V_TOTAL_DISP); 3231c582b7e3Smrg save->crtc2_v_sync_strt_wid = INREG(R128_CRTC2_V_SYNC_STRT_WID); 3232c582b7e3Smrg save->crtc2_offset = INREG(R128_CRTC2_OFFSET); 3233c582b7e3Smrg save->crtc2_offset_cntl = INREG(R128_CRTC2_OFFSET_CNTL); 3234c582b7e3Smrg save->crtc2_pitch = INREG(R128_CRTC2_PITCH); 3235c582b7e3Smrg} 3236c582b7e3Smrg 3237c582b7e3Smrg/* Read PLL registers. */ 3238c582b7e3Smrgstatic void R128SavePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save) 3239c582b7e3Smrg{ 3240c582b7e3Smrg save->ppll_ref_div = INPLL(pScrn, R128_PPLL_REF_DIV); 3241c582b7e3Smrg save->ppll_div_3 = INPLL(pScrn, R128_PPLL_DIV_3); 32429e881af1Smacallan save->ppll_div_0 = INPLL(pScrn, R128_PPLL_DIV_0); 3243c582b7e3Smrg save->htotal_cntl = INPLL(pScrn, R128_HTOTAL_CNTL); 3244c582b7e3Smrg 3245c582b7e3Smrg R128TRACE(("Read: 0x%08x 0x%08x 0x%08x\n", 3246c582b7e3Smrg save->ppll_ref_div, 3247c582b7e3Smrg save->ppll_div_3, 3248c582b7e3Smrg save->htotal_cntl)); 3249c582b7e3Smrg R128TRACE(("Read: rd=%d, fd=%d, pd=%d\n", 3250c582b7e3Smrg save->ppll_ref_div & R128_PPLL_REF_DIV_MASK, 3251c582b7e3Smrg save->ppll_div_3 & R128_PPLL_FB3_DIV_MASK, 3252c582b7e3Smrg (save->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16)); 3253c582b7e3Smrg} 3254c582b7e3Smrg 3255c582b7e3Smrg/* Read PLL2 registers. */ 3256c582b7e3Smrgstatic void R128SavePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save) 3257c582b7e3Smrg{ 3258c582b7e3Smrg save->p2pll_ref_div = INPLL(pScrn, R128_P2PLL_REF_DIV); 3259c582b7e3Smrg save->p2pll_div_0 = INPLL(pScrn, R128_P2PLL_DIV_0); 3260c582b7e3Smrg save->htotal_cntl2 = INPLL(pScrn, R128_HTOTAL2_CNTL); 3261c582b7e3Smrg 3262c582b7e3Smrg R128TRACE(("Read: 0x%08x 0x%08x 0x%08x\n", 3263c582b7e3Smrg save->p2pll_ref_div, 3264c582b7e3Smrg save->p2pll_div_0, 3265c582b7e3Smrg save->htotal_cntl2)); 3266c582b7e3Smrg R128TRACE(("Read: rd=%d, fd=%d, pd=%d\n", 3267c582b7e3Smrg save->p2pll_ref_div & R128_P2PLL_REF_DIV_MASK, 3268c582b7e3Smrg save->p2pll_div_0 & R128_P2PLL_FB0_DIV_MASK, 3269c582b7e3Smrg (save->p2pll_div_0 & R128_P2PLL_POST0_DIV_MASK) >> 16)); 3270c582b7e3Smrg} 3271c582b7e3Smrg 3272c582b7e3Smrg/* Read DDA registers. */ 3273c582b7e3Smrgstatic void R128SaveDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save) 3274c582b7e3Smrg{ 3275c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3276c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 3277c582b7e3Smrg 3278c582b7e3Smrg save->dda_config = INREG(R128_DDA_CONFIG); 3279c582b7e3Smrg save->dda_on_off = INREG(R128_DDA_ON_OFF); 3280c582b7e3Smrg} 3281c582b7e3Smrg 3282c582b7e3Smrg/* Read DDA2 registers. */ 3283c582b7e3Smrgstatic void R128SaveDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save) 3284c582b7e3Smrg{ 3285c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3286c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 3287c582b7e3Smrg 3288c582b7e3Smrg save->dda2_config = INREG(R128_DDA2_CONFIG); 3289c582b7e3Smrg save->dda2_on_off = INREG(R128_DDA2_ON_OFF); 3290c582b7e3Smrg} 3291c582b7e3Smrg 3292c582b7e3Smrg/* Read palette data. */ 3293c582b7e3Smrgstatic void R128SavePalette(ScrnInfoPtr pScrn, R128SavePtr save) 3294c582b7e3Smrg{ 3295c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3296c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 3297c582b7e3Smrg int i; 3298c582b7e3Smrg 3299c582b7e3Smrg PAL_SELECT(1); 3300c582b7e3Smrg INPAL_START(0); 3301c582b7e3Smrg for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT(); 3302c582b7e3Smrg PAL_SELECT(0); 3303c582b7e3Smrg INPAL_START(0); 3304c582b7e3Smrg for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT(); 3305c582b7e3Smrg save->palette_valid = TRUE; 3306c582b7e3Smrg} 3307c582b7e3Smrg 3308c582b7e3Smrg/* Save state that defines current video mode. */ 3309c582b7e3Smrgstatic void R128SaveMode(ScrnInfoPtr pScrn, R128SavePtr save) 3310c582b7e3Smrg{ 3311c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3312c582b7e3Smrg 3313c582b7e3Smrg R128TRACE(("R128SaveMode(%p)\n", save)); 3314c582b7e3Smrg 3315c582b7e3Smrg if(info->IsSecondary) 3316c582b7e3Smrg { 3317c582b7e3Smrg R128SaveCrtc2Registers(pScrn, save); 3318c582b7e3Smrg R128SavePLL2Registers(pScrn, save); 3319c582b7e3Smrg R128SaveDDA2Registers(pScrn, save); 3320c582b7e3Smrg } 3321c582b7e3Smrg else 3322c582b7e3Smrg { 3323c582b7e3Smrg R128SaveCommonRegisters(pScrn, save); 3324c582b7e3Smrg R128SaveCrtcRegisters(pScrn, save); 3325c582b7e3Smrg if((info->DisplayType == MT_DFP) || 3326c582b7e3Smrg (info->DisplayType == MT_LCD)) 3327c582b7e3Smrg { 3328c582b7e3Smrg R128SaveFPRegisters(pScrn, save); 3329c582b7e3Smrg } 3330c582b7e3Smrg R128SavePLLRegisters(pScrn, save); 3331c582b7e3Smrg R128SaveDDARegisters(pScrn, save); 3332c582b7e3Smrg R128SavePalette(pScrn, save); 3333c582b7e3Smrg } 3334c582b7e3Smrg 3335c582b7e3Smrg R128TRACE(("R128SaveMode returns %p\n", save)); 3336c582b7e3Smrg} 3337c582b7e3Smrg 3338c582b7e3Smrg/* Save everything needed to restore the original VC state. */ 3339c582b7e3Smrgstatic void R128Save(ScrnInfoPtr pScrn) 3340c582b7e3Smrg{ 3341c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3342c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 3343c582b7e3Smrg R128SavePtr save = &info->SavedReg; 3344c582b7e3Smrg 3345c582b7e3Smrg R128TRACE(("R128Save\n")); 334679e5230eSmacallan#ifndef AVOID_FBDEV 3347c582b7e3Smrg if (info->FBDev) { 3348c582b7e3Smrg fbdevHWSave(pScrn); 3349c582b7e3Smrg return; 3350c582b7e3Smrg } 335179e5230eSmacallan#endif 3352c582b7e3Smrg 3353c582b7e3Smrg if (!info->IsSecondary) { 3354c582b7e3Smrg#ifdef WITH_VGAHW 3355c582b7e3Smrg if (info->VGAAccess) { 3356c582b7e3Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 3357c582b7e3Smrg 3358c582b7e3Smrg vgaHWUnlock(hwp); 3359c582b7e3Smrg# if defined(__powerpc__) 3360c582b7e3Smrg /* temporary hack to prevent crashing on PowerMacs when trying to 3361c582b7e3Smrg * read VGA fonts and colormap, will find a better solution 3362c582b7e3Smrg * in the future. TODO: Check if there's actually some VGA stuff 3363c582b7e3Smrg * setup in the card at all !! 3364c582b7e3Smrg */ 3365c582b7e3Smrg vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */ 3366c582b7e3Smrg# else 3367c582b7e3Smrg /* Save mode * & fonts & cmap */ 3368c582b7e3Smrg vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS); 3369c582b7e3Smrg# endif 3370c582b7e3Smrg vgaHWLock(hwp); 3371c582b7e3Smrg } 3372c582b7e3Smrg#endif 3373c582b7e3Smrg save->dp_datatype = INREG(R128_DP_DATATYPE); 3374c582b7e3Smrg save->gen_reset_cntl = INREG(R128_GEN_RESET_CNTL); 3375c582b7e3Smrg save->clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX); 3376c582b7e3Smrg save->amcgpio_en_reg = INREG(R128_AMCGPIO_EN_REG); 3377c582b7e3Smrg save->amcgpio_mask = INREG(R128_AMCGPIO_MASK); 3378c582b7e3Smrg } 3379c582b7e3Smrg 3380c582b7e3Smrg R128SaveMode(pScrn, save); 3381c582b7e3Smrg 3382c582b7e3Smrg} 3383c582b7e3Smrg 3384c582b7e3Smrg/* Restore the original (text) mode. */ 3385c582b7e3Smrgstatic void R128Restore(ScrnInfoPtr pScrn) 3386c582b7e3Smrg{ 3387c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 3388c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 3389c582b7e3Smrg R128SavePtr restore = &info->SavedReg; 3390c582b7e3Smrg 3391c582b7e3Smrg R128TRACE(("R128Restore\n")); 339279e5230eSmacallan#ifndef AVOID_FBDEV 3393c582b7e3Smrg if (info->FBDev) { 3394c582b7e3Smrg fbdevHWRestore(pScrn); 3395c582b7e3Smrg return; 3396c582b7e3Smrg } 339779e5230eSmacallan#endif 3398c582b7e3Smrg R128Blank(pScrn); 3399c582b7e3Smrg 3400c582b7e3Smrg if (!info->IsSecondary) { 3401c582b7e3Smrg OUTREG(R128_AMCGPIO_MASK, restore->amcgpio_mask); 3402c582b7e3Smrg OUTREG(R128_AMCGPIO_EN_REG, restore->amcgpio_en_reg); 3403c582b7e3Smrg OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index); 3404c582b7e3Smrg OUTREG(R128_GEN_RESET_CNTL, restore->gen_reset_cntl); 3405c582b7e3Smrg OUTREG(R128_DP_DATATYPE, restore->dp_datatype); 3406c582b7e3Smrg } 3407c582b7e3Smrg 3408c582b7e3Smrg R128RestoreMode(pScrn, restore); 34099e881af1Smacallan 34109e881af1Smacallan if (!info->IsSecondary) { 34119e881af1Smacallan OUTREG(R128_AMCGPIO_MASK, restore->amcgpio_mask); 34129e881af1Smacallan OUTREG(R128_AMCGPIO_EN_REG, restore->amcgpio_en_reg); 34139e881af1Smacallan OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index); 34149e881af1Smacallan OUTREG(R128_GEN_RESET_CNTL, restore->gen_reset_cntl); 34159e881af1Smacallan OUTREG(R128_DP_DATATYPE, restore->dp_datatype); 34169e881af1Smacallan } 34179e881af1Smacallan 3418c582b7e3Smrg#ifdef WITH_VGAHW 3419c582b7e3Smrg if (info->VGAAccess) { 3420c582b7e3Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 3421c582b7e3Smrg if (!info->IsSecondary) { 3422c582b7e3Smrg vgaHWUnlock(hwp); 3423c582b7e3Smrg# if defined(__powerpc__) 3424c582b7e3Smrg /* Temporary hack to prevent crashing on PowerMacs when trying to 3425c582b7e3Smrg * write VGA fonts, will find a better solution in the future 3426c582b7e3Smrg */ 3427c582b7e3Smrg vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE ); 3428c582b7e3Smrg# else 3429c582b7e3Smrg vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); 3430c582b7e3Smrg# endif 3431c582b7e3Smrg vgaHWLock(hwp); 3432c582b7e3Smrg } else { 3433c582b7e3Smrg R128EntPtr pR128Ent = R128EntPriv(pScrn); 3434c582b7e3Smrg ScrnInfoPtr pScrn0 = pR128Ent->pPrimaryScrn; 3435c582b7e3Smrg R128InfoPtr info0 = R128PTR(pScrn0); 3436c582b7e3Smrg vgaHWPtr hwp0; 3437c582b7e3Smrg 3438c582b7e3Smrg if (info0->VGAAccess) { 3439c582b7e3Smrg hwp0 = VGAHWPTR(pScrn0); 3440c582b7e3Smrg vgaHWUnlock(hwp0); 3441c582b7e3Smrg#if defined(__powerpc__) 3442c582b7e3Smrg vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE); 3443c582b7e3Smrg#else 3444c582b7e3Smrg vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); 3445c582b7e3Smrg#endif 3446c582b7e3Smrg vgaHWLock(hwp0); 3447c582b7e3Smrg } 3448c582b7e3Smrg } 3449c582b7e3Smrg } 3450c582b7e3Smrg#endif 3451c582b7e3Smrg 3452c582b7e3Smrg R128WaitForVerticalSync(pScrn); 3453c582b7e3Smrg R128Unblank(pScrn); 3454c582b7e3Smrg} 3455c582b7e3Smrg 3456c582b7e3Smrg/* Define common registers for requested video mode. */ 3457c582b7e3Smrgstatic void R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info) 3458c582b7e3Smrg{ 3459c582b7e3Smrg save->ovr_clr = 0; 3460c582b7e3Smrg save->ovr_wid_left_right = 0; 3461c582b7e3Smrg save->ovr_wid_top_bottom = 0; 3462c582b7e3Smrg save->ov0_scale_cntl = 0; 3463c582b7e3Smrg save->mpp_tb_config = 0; 3464c582b7e3Smrg save->mpp_gp_config = 0; 3465c582b7e3Smrg save->subpic_cntl = 0; 3466c582b7e3Smrg save->viph_control = 0; 3467c582b7e3Smrg save->i2c_cntl_1 = 0; 3468c582b7e3Smrg#ifdef XF86DRI 3469c582b7e3Smrg save->gen_int_cntl = info->gen_int_cntl; 3470c582b7e3Smrg#else 3471c582b7e3Smrg save->gen_int_cntl = 0; 3472c582b7e3Smrg#endif 3473c582b7e3Smrg save->cap0_trig_cntl = 0; 3474c582b7e3Smrg save->cap1_trig_cntl = 0; 3475c582b7e3Smrg save->bus_cntl = info->BusCntl; 3476c582b7e3Smrg /* 3477c582b7e3Smrg * If bursts are enabled, turn on discards and aborts 3478c582b7e3Smrg */ 3479c582b7e3Smrg if (save->bus_cntl & (R128_BUS_WRT_BURST|R128_BUS_READ_BURST)) 3480c582b7e3Smrg save->bus_cntl |= R128_BUS_RD_DISCARD_EN | R128_BUS_RD_ABORT_EN; 3481c582b7e3Smrg} 3482c582b7e3Smrg 3483c582b7e3Smrg/* Define CRTC registers for requested video mode. */ 3484c582b7e3Smrgstatic Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, 3485c582b7e3Smrg DisplayModePtr mode, R128InfoPtr info) 3486c582b7e3Smrg{ 3487c582b7e3Smrg int format; 3488c582b7e3Smrg int hsync_start; 3489c582b7e3Smrg int hsync_wid; 3490c582b7e3Smrg int hsync_fudge; 3491c582b7e3Smrg int vsync_wid; 3492c582b7e3Smrg int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; 3493c582b7e3Smrg int hsync_fudge_fp[] = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 }; 3494c582b7e3Smrg// int hsync_fudge_fp_crt[] = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 }; 3495c582b7e3Smrg 3496c582b7e3Smrg switch (info->CurrentLayout.pixel_code) { 3497c582b7e3Smrg case 4: format = 1; break; 3498c582b7e3Smrg case 8: format = 2; break; 3499c582b7e3Smrg case 15: format = 3; break; /* 555 */ 3500c582b7e3Smrg case 16: format = 4; break; /* 565 */ 3501c582b7e3Smrg case 24: format = 5; break; /* RGB */ 3502c582b7e3Smrg case 32: format = 6; break; /* xRGB */ 3503c582b7e3Smrg default: 3504c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 3505c582b7e3Smrg "Unsupported pixel depth (%d)\n", 3506c582b7e3Smrg info->CurrentLayout.bitsPerPixel); 3507c582b7e3Smrg return FALSE; 3508c582b7e3Smrg } 3509c582b7e3Smrg 3510c582b7e3Smrg if ((info->DisplayType == MT_DFP) || 3511c582b7e3Smrg (info->DisplayType == MT_LCD)) 3512c582b7e3Smrg hsync_fudge = hsync_fudge_fp[format-1]; 3513c582b7e3Smrg else 3514c582b7e3Smrg hsync_fudge = hsync_fudge_default[format-1]; 3515c582b7e3Smrg 3516c582b7e3Smrg save->crtc_gen_cntl = (R128_CRTC_EXT_DISP_EN 3517c582b7e3Smrg | R128_CRTC_EN 3518c582b7e3Smrg | (format << 8) 3519c582b7e3Smrg | ((mode->Flags & V_DBLSCAN) 3520c582b7e3Smrg ? R128_CRTC_DBL_SCAN_EN 3521c582b7e3Smrg : 0) 3522c582b7e3Smrg | ((mode->Flags & V_INTERLACE) 3523c582b7e3Smrg ? R128_CRTC_INTERLACE_EN 3524c582b7e3Smrg : 0) 3525c582b7e3Smrg | ((mode->Flags & V_CSYNC) 3526c582b7e3Smrg ? R128_CRTC_CSYNC_EN 3527c582b7e3Smrg : 0)); 3528c582b7e3Smrg 3529c582b7e3Smrg if((info->DisplayType == MT_DFP) || 3530c582b7e3Smrg (info->DisplayType == MT_LCD)) 3531c582b7e3Smrg { 3532c582b7e3Smrg save->crtc_ext_cntl = R128_VGA_ATI_LINEAR | 3533c582b7e3Smrg R128_XCRT_CNT_EN; 3534c582b7e3Smrg save->crtc_gen_cntl &= ~(R128_CRTC_DBL_SCAN_EN | 3535c582b7e3Smrg R128_CRTC_INTERLACE_EN); 3536c582b7e3Smrg } 3537c582b7e3Smrg else 3538c582b7e3Smrg save->crtc_ext_cntl = R128_VGA_ATI_LINEAR | 3539c582b7e3Smrg R128_XCRT_CNT_EN | 3540c582b7e3Smrg R128_CRTC_CRT_ON; 3541c582b7e3Smrg 3542c582b7e3Smrg save->dac_cntl = (R128_DAC_MASK_ALL 3543c582b7e3Smrg | R128_DAC_VGA_ADR_EN 3544c582b7e3Smrg | (info->dac6bits ? 0 : R128_DAC_8BIT_EN)); 3545c582b7e3Smrg 3546c582b7e3Smrg 3547c582b7e3Smrg if(info->isDFP && !info->isPro2) 3548c582b7e3Smrg { 3549c582b7e3Smrg if(info->PanelXRes < mode->CrtcHDisplay) 3550c582b7e3Smrg mode->HDisplay = mode->CrtcHDisplay = info->PanelXRes; 3551c582b7e3Smrg if(info->PanelYRes < mode->CrtcVDisplay) 3552c582b7e3Smrg mode->VDisplay = mode->CrtcVDisplay = info->PanelYRes; 3553c582b7e3Smrg mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank; 3554c582b7e3Smrg mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus; 3555c582b7e3Smrg mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth; 3556c582b7e3Smrg mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank; 3557c582b7e3Smrg mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus; 3558c582b7e3Smrg mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth; 3559c582b7e3Smrg } 3560c582b7e3Smrg 3561c582b7e3Smrg save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff) 3562c582b7e3Smrg | (((mode->CrtcHDisplay / 8) - 1) << 16)); 3563c582b7e3Smrg 3564c582b7e3Smrg hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; 3565c582b7e3Smrg if (!hsync_wid) hsync_wid = 1; 3566c582b7e3Smrg if (hsync_wid > 0x3f) hsync_wid = 0x3f; 3567c582b7e3Smrg 3568c582b7e3Smrg hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge; 3569c582b7e3Smrg 3570c582b7e3Smrg save->crtc_h_sync_strt_wid = ((hsync_start & 0xfff) 3571c582b7e3Smrg | (hsync_wid << 16) 3572c582b7e3Smrg | ((mode->Flags & V_NHSYNC) 3573c582b7e3Smrg ? R128_CRTC_H_SYNC_POL 3574c582b7e3Smrg : 0)); 3575c582b7e3Smrg 3576c582b7e3Smrg#if 1 3577c582b7e3Smrg /* This works for double scan mode. */ 3578c582b7e3Smrg save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 3579c582b7e3Smrg | ((mode->CrtcVDisplay - 1) << 16)); 3580c582b7e3Smrg#else 3581c582b7e3Smrg /* This is what cce/nbmode.c example code 3582c582b7e3Smrg does -- is this correct? */ 3583c582b7e3Smrg save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 3584c582b7e3Smrg | ((mode->CrtcVDisplay 3585c582b7e3Smrg * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1) 3586c582b7e3Smrg << 16)); 3587c582b7e3Smrg#endif 3588c582b7e3Smrg 3589c582b7e3Smrg vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 3590c582b7e3Smrg if (!vsync_wid) vsync_wid = 1; 3591c582b7e3Smrg if (vsync_wid > 0x1f) vsync_wid = 0x1f; 3592c582b7e3Smrg 3593c582b7e3Smrg save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) 3594c582b7e3Smrg | (vsync_wid << 16) 3595c582b7e3Smrg | ((mode->Flags & V_NVSYNC) 3596c582b7e3Smrg ? R128_CRTC_V_SYNC_POL 3597c582b7e3Smrg : 0)); 3598c582b7e3Smrg save->crtc_offset = 0; 3599c582b7e3Smrg save->crtc_offset_cntl = 0; 3600c582b7e3Smrg save->crtc_pitch = info->CurrentLayout.displayWidth / 8; 3601c582b7e3Smrg 3602c582b7e3Smrg R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", 3603c582b7e3Smrg save->crtc_pitch, pScrn->virtualX, info->CurrentLayout.displayWidth)); 3604c582b7e3Smrg 3605c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 3606c582b7e3Smrg /* Change the endianness of the aperture */ 3607c582b7e3Smrg switch (info->CurrentLayout.pixel_code) { 3608c582b7e3Smrg case 15: 3609c582b7e3Smrg case 16: save->config_cntl |= APER_0_BIG_ENDIAN_16BPP_SWAP; break; 3610c582b7e3Smrg case 32: save->config_cntl |= APER_0_BIG_ENDIAN_32BPP_SWAP; break; 3611c582b7e3Smrg default: break; 3612c582b7e3Smrg } 3613c582b7e3Smrg#endif 3614c582b7e3Smrg 3615c582b7e3Smrg return TRUE; 3616c582b7e3Smrg} 3617c582b7e3Smrg 3618c582b7e3Smrg/* Define CRTC2 registers for requested video mode. */ 3619c582b7e3Smrgstatic Bool R128InitCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save, 3620c582b7e3Smrg DisplayModePtr mode, R128InfoPtr info) 3621c582b7e3Smrg{ 3622c582b7e3Smrg int format; 3623c582b7e3Smrg int hsync_start; 3624c582b7e3Smrg int hsync_wid; 3625c582b7e3Smrg int hsync_fudge; 3626c582b7e3Smrg int vsync_wid; 3627c582b7e3Smrg int bytpp; 3628c582b7e3Smrg int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; 3629c582b7e3Smrg 3630c582b7e3Smrg switch (info->CurrentLayout.pixel_code) { 3631c582b7e3Smrg case 4: format = 1; bytpp = 0; break; 3632c582b7e3Smrg case 8: format = 2; bytpp = 1; break; 3633c582b7e3Smrg case 15: format = 3; bytpp = 2; break; /* 555 */ 3634c582b7e3Smrg case 16: format = 4; bytpp = 2; break; /* 565 */ 3635c582b7e3Smrg case 24: format = 5; bytpp = 3; break; /* RGB */ 3636c582b7e3Smrg case 32: format = 6; bytpp = 4; break; /* xRGB */ 3637c582b7e3Smrg default: 3638c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 3639c582b7e3Smrg "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel); 3640c582b7e3Smrg return FALSE; 3641c582b7e3Smrg } 3642c582b7e3Smrg R128TRACE(("Format = %d (%d bytes per pixel)\n", format, bytpp)); 3643c582b7e3Smrg 3644c582b7e3Smrg hsync_fudge = hsync_fudge_default[format-1]; 3645c582b7e3Smrg 3646c582b7e3Smrg save->crtc2_gen_cntl = (R128_CRTC2_EN 3647c582b7e3Smrg | (format << 8) 3648c582b7e3Smrg | ((mode->Flags & V_DBLSCAN) 3649c582b7e3Smrg ? R128_CRTC2_DBL_SCAN_EN 3650c582b7e3Smrg : 0)); 3651c582b7e3Smrg/* 3652c582b7e3Smrg save->crtc2_gen_cntl &= ~R128_CRTC_EXT_DISP_EN; 3653c582b7e3Smrg save->crtc2_gen_cntl |= (1 << 21); 3654c582b7e3Smrg*/ 3655c582b7e3Smrg save->crtc2_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff) 3656c582b7e3Smrg | (((mode->CrtcHDisplay / 8) - 1) << 16)); 3657c582b7e3Smrg 3658c582b7e3Smrg hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; 3659c582b7e3Smrg if (!hsync_wid) hsync_wid = 1; 3660c582b7e3Smrg if (hsync_wid > 0x3f) hsync_wid = 0x3f; 3661c582b7e3Smrg 3662c582b7e3Smrg hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge; 3663c582b7e3Smrg 3664c582b7e3Smrg save->crtc2_h_sync_strt_wid = ((hsync_start & 0xfff) 3665c582b7e3Smrg | (hsync_wid << 16) 3666c582b7e3Smrg | ((mode->Flags & V_NHSYNC) 3667c582b7e3Smrg ? R128_CRTC2_H_SYNC_POL 3668c582b7e3Smrg : 0)); 3669c582b7e3Smrg 3670c582b7e3Smrg#if 1 3671c582b7e3Smrg /* This works for double scan mode. */ 3672c582b7e3Smrg save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 3673c582b7e3Smrg | ((mode->CrtcVDisplay - 1) << 16)); 3674c582b7e3Smrg#else 3675c582b7e3Smrg /* This is what cce/nbmode.c example code 3676c582b7e3Smrg does -- is this correct? */ 3677c582b7e3Smrg save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) 3678c582b7e3Smrg | ((mode->CrtcVDisplay 3679c582b7e3Smrg * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1) 3680c582b7e3Smrg << 16)); 3681c582b7e3Smrg#endif 3682c582b7e3Smrg 3683c582b7e3Smrg vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; 3684c582b7e3Smrg if (!vsync_wid) vsync_wid = 1; 3685c582b7e3Smrg if (vsync_wid > 0x1f) vsync_wid = 0x1f; 3686c582b7e3Smrg 3687c582b7e3Smrg save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) 3688c582b7e3Smrg | (vsync_wid << 16) 3689c582b7e3Smrg | ((mode->Flags & V_NVSYNC) 3690c582b7e3Smrg ? R128_CRTC2_V_SYNC_POL 3691c582b7e3Smrg : 0)); 3692c582b7e3Smrg 3693c582b7e3Smrg save->crtc2_offset = 0; 3694c582b7e3Smrg save->crtc2_offset_cntl = 0; 3695c582b7e3Smrg 3696c582b7e3Smrg save->crtc2_pitch = info->CurrentLayout.displayWidth / 8; 3697c582b7e3Smrg 3698c582b7e3Smrg R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", 3699c582b7e3Smrg save->crtc2_pitch, pScrn->virtualX, 3700c582b7e3Smrg info->CurrentLayout.displayWidth)); 3701c582b7e3Smrg return TRUE; 3702c582b7e3Smrg} 3703c582b7e3Smrg 3704c582b7e3Smrg/* Define CRTC registers for requested video mode. */ 3705c582b7e3Smrgstatic void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, 3706c582b7e3Smrg DisplayModePtr mode, R128InfoPtr info) 3707c582b7e3Smrg{ 3708c582b7e3Smrg int xres = mode->CrtcHDisplay; 3709c582b7e3Smrg int yres = mode->CrtcVDisplay; 3710c582b7e3Smrg float Hratio, Vratio; 3711c582b7e3Smrg 3712c582b7e3Smrg if (info->BIOSDisplay == R128_BIOS_DISPLAY_CRT) { 3713c582b7e3Smrg save->crtc_ext_cntl |= R128_CRTC_CRT_ON; 3714c582b7e3Smrg save->crtc2_gen_cntl = 0; 3715c582b7e3Smrg save->fp_gen_cntl = orig->fp_gen_cntl; 3716c582b7e3Smrg save->fp_gen_cntl &= ~(R128_FP_FPON | 3717c582b7e3Smrg R128_FP_CRTC_USE_SHADOW_VEND | 3718c582b7e3Smrg R128_FP_CRTC_HORZ_DIV2_EN | 3719c582b7e3Smrg R128_FP_CRTC_HOR_CRT_DIV2_DIS | 3720c582b7e3Smrg R128_FP_USE_SHADOW_EN); 3721c582b7e3Smrg save->fp_gen_cntl |= (R128_FP_SEL_CRTC2 | 3722c582b7e3Smrg R128_FP_CRTC_DONT_SHADOW_VPAR); 3723c582b7e3Smrg save->fp_panel_cntl = orig->fp_panel_cntl & (CARD32)~R128_FP_DIGON; 3724c582b7e3Smrg save->lvds_gen_cntl = orig->lvds_gen_cntl & 3725c582b7e3Smrg (CARD32)~(R128_LVDS_ON | R128_LVDS_BLON); 3726c582b7e3Smrg return; 3727c582b7e3Smrg } 3728c582b7e3Smrg 3729c582b7e3Smrg if (xres > info->PanelXRes) xres = info->PanelXRes; 3730c582b7e3Smrg if (yres > info->PanelYRes) yres = info->PanelYRes; 3731c582b7e3Smrg 3732c582b7e3Smrg Hratio = (float)xres/(float)info->PanelXRes; 3733c582b7e3Smrg Vratio = (float)yres/(float)info->PanelYRes; 3734c582b7e3Smrg 3735c582b7e3Smrg save->fp_horz_stretch = 3736c582b7e3Smrg (((((int)(Hratio * R128_HORZ_STRETCH_RATIO_MAX + 0.5)) 3737c582b7e3Smrg & R128_HORZ_STRETCH_RATIO_MASK) << R128_HORZ_STRETCH_RATIO_SHIFT) | 3738c582b7e3Smrg (orig->fp_horz_stretch & (R128_HORZ_PANEL_SIZE | 3739c582b7e3Smrg R128_HORZ_FP_LOOP_STRETCH | 3740c582b7e3Smrg R128_HORZ_STRETCH_RESERVED))); 3741c582b7e3Smrg save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN; 3742c582b7e3Smrg save->fp_horz_stretch &= ~R128_AUTO_HORZ_RATIO; 3743c582b7e3Smrg if (xres == info->PanelXRes) 3744c582b7e3Smrg save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE); 3745c582b7e3Smrg else 3746c582b7e3Smrg save->fp_horz_stretch |= (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE); 3747c582b7e3Smrg 3748c582b7e3Smrg save->fp_vert_stretch = 3749c582b7e3Smrg (((((int)(Vratio * R128_VERT_STRETCH_RATIO_MAX + 0.5)) 3750c582b7e3Smrg & R128_VERT_STRETCH_RATIO_MASK) << R128_VERT_STRETCH_RATIO_SHIFT) | 3751c582b7e3Smrg (orig->fp_vert_stretch & (R128_VERT_PANEL_SIZE | 3752c582b7e3Smrg R128_VERT_STRETCH_RESERVED))); 3753c582b7e3Smrg save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN; 3754c582b7e3Smrg if (yres == info->PanelYRes) 3755c582b7e3Smrg save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND); 3756c582b7e3Smrg else 3757c582b7e3Smrg save->fp_vert_stretch |= (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND); 3758c582b7e3Smrg 3759c582b7e3Smrg save->fp_gen_cntl = (orig->fp_gen_cntl & 3760c582b7e3Smrg (CARD32)~(R128_FP_SEL_CRTC2 | 3761c582b7e3Smrg R128_FP_CRTC_USE_SHADOW_VEND | 3762c582b7e3Smrg R128_FP_CRTC_HORZ_DIV2_EN | 3763c582b7e3Smrg R128_FP_CRTC_HOR_CRT_DIV2_DIS | 3764c582b7e3Smrg R128_FP_USE_SHADOW_EN)); 3765c582b7e3Smrg 3766c582b7e3Smrg save->fp_panel_cntl = orig->fp_panel_cntl; 3767c582b7e3Smrg save->lvds_gen_cntl = orig->lvds_gen_cntl; 3768c582b7e3Smrg save->tmds_crc = orig->tmds_crc; 3769c582b7e3Smrg 3770c582b7e3Smrg /* Disable CRT output by disabling CRT output and setting the CRT 3771c582b7e3Smrg DAC to use CRTC2, which we set to 0's. In the future, we will 3772c582b7e3Smrg want to use the dual CRTC capabilities of the R128 to allow both 3773c582b7e3Smrg the flat panel and external CRT to either simultaneously display 3774c582b7e3Smrg the same image or display two different images. */ 3775c582b7e3Smrg 3776c582b7e3Smrg 3777c582b7e3Smrg if(!info->isDFP){ 3778c582b7e3Smrg if (info->BIOSDisplay == R128_BIOS_DISPLAY_FP_CRT) { 3779c582b7e3Smrg save->crtc_ext_cntl |= R128_CRTC_CRT_ON; 3780c582b7e3Smrg } else if (info->BIOSDisplay == R128_DUALHEAD) { 3781c582b7e3Smrg save->crtc_ext_cntl |= R128_CRTC_CRT_ON; 3782c582b7e3Smrg save->dac_cntl |= R128_DAC_CRT_SEL_CRTC2; 3783c582b7e3Smrg save->dac_cntl |= R128_DAC_PALETTE2_SNOOP_EN; 3784c582b7e3Smrg } else { 3785c582b7e3Smrg save->crtc_ext_cntl &= ~R128_CRTC_CRT_ON; 3786c582b7e3Smrg save->dac_cntl |= R128_DAC_CRT_SEL_CRTC2; 3787c582b7e3Smrg save->crtc2_gen_cntl = 0; 3788c582b7e3Smrg } 3789c582b7e3Smrg } 3790c582b7e3Smrg 3791c582b7e3Smrg /* WARNING: Be careful about turning on the flat panel */ 3792c582b7e3Smrg if(info->isDFP){ 3793c582b7e3Smrg save->fp_gen_cntl = orig->fp_gen_cntl; 3794c582b7e3Smrg 3795c582b7e3Smrg save->fp_gen_cntl &= ~(R128_FP_CRTC_USE_SHADOW_VEND | 3796c582b7e3Smrg R128_FP_CRTC_USE_SHADOW_ROWCUR | 3797c582b7e3Smrg R128_FP_CRTC_HORZ_DIV2_EN | 3798c582b7e3Smrg R128_FP_CRTC_HOR_CRT_DIV2_DIS | 3799c582b7e3Smrg R128_FP_CRT_SYNC_SEL | 3800c582b7e3Smrg R128_FP_USE_SHADOW_EN); 3801c582b7e3Smrg 3802c582b7e3Smrg save->fp_panel_cntl |= (R128_FP_DIGON | R128_FP_BLON); 3803c582b7e3Smrg save->fp_gen_cntl |= (R128_FP_FPON | R128_FP_TDMS_EN | 3804c582b7e3Smrg R128_FP_CRTC_DONT_SHADOW_VPAR | R128_FP_CRTC_DONT_SHADOW_HEND); 3805c582b7e3Smrg save->tmds_transmitter_cntl = (orig->tmds_transmitter_cntl 3806c582b7e3Smrg & ~(CARD32)R128_TMDS_PLLRST) | R128_TMDS_PLLEN; 3807c582b7e3Smrg } 3808c582b7e3Smrg else 3809c582b7e3Smrg save->lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_BLON); 3810c582b7e3Smrg 3811c582b7e3Smrg save->fp_crtc_h_total_disp = save->crtc_h_total_disp; 3812c582b7e3Smrg save->fp_crtc_v_total_disp = save->crtc_v_total_disp; 3813c582b7e3Smrg save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; 3814c582b7e3Smrg save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; 3815c582b7e3Smrg} 3816c582b7e3Smrg 3817c582b7e3Smrg/* Define PLL registers for requested video mode. */ 3818c582b7e3Smrgstatic void R128InitPLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save, 3819c582b7e3Smrg R128PLLPtr pll, double dot_clock) 3820c582b7e3Smrg{ 3821c582b7e3Smrg unsigned long freq = dot_clock * 100; 3822c582b7e3Smrg struct { 3823c582b7e3Smrg int divider; 3824c582b7e3Smrg int bitvalue; 3825c582b7e3Smrg } *post_div, 3826c582b7e3Smrg post_divs[] = { 3827c582b7e3Smrg /* From RAGE 128 VR/RAGE 128 GL Register 3828c582b7e3Smrg Reference Manual (Technical Reference 3829c582b7e3Smrg Manual P/N RRG-G04100-C Rev. 0.04), page 3830c582b7e3Smrg 3-17 (PLL_DIV_[3:0]). */ 3831c582b7e3Smrg { 1, 0 }, /* VCLK_SRC */ 3832c582b7e3Smrg { 2, 1 }, /* VCLK_SRC/2 */ 3833c582b7e3Smrg { 4, 2 }, /* VCLK_SRC/4 */ 3834c582b7e3Smrg { 8, 3 }, /* VCLK_SRC/8 */ 3835c582b7e3Smrg 3836c582b7e3Smrg { 3, 4 }, /* VCLK_SRC/3 */ 3837c582b7e3Smrg /* bitvalue = 5 is reserved */ 3838c582b7e3Smrg { 6, 6 }, /* VCLK_SRC/6 */ 3839c582b7e3Smrg { 12, 7 }, /* VCLK_SRC/12 */ 3840c582b7e3Smrg { 0, 0 } 3841c582b7e3Smrg }; 3842c582b7e3Smrg 3843c582b7e3Smrg if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; 3844c582b7e3Smrg if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; 3845c582b7e3Smrg 3846c582b7e3Smrg for (post_div = &post_divs[0]; post_div->divider; ++post_div) { 3847c582b7e3Smrg save->pll_output_freq = post_div->divider * freq; 3848c582b7e3Smrg if (save->pll_output_freq >= pll->min_pll_freq 3849c582b7e3Smrg && save->pll_output_freq <= pll->max_pll_freq) break; 3850c582b7e3Smrg } 3851c582b7e3Smrg 3852c582b7e3Smrg save->dot_clock_freq = freq; 3853c582b7e3Smrg save->feedback_div = R128Div(pll->reference_div * save->pll_output_freq, 3854c582b7e3Smrg pll->reference_freq); 3855c582b7e3Smrg save->post_div = post_div->divider; 3856c582b7e3Smrg 3857c582b7e3Smrg R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n", 3858c582b7e3Smrg save->dot_clock_freq, 3859c582b7e3Smrg save->pll_output_freq, 3860c582b7e3Smrg save->feedback_div, 3861c582b7e3Smrg save->post_div)); 3862c582b7e3Smrg 3863c582b7e3Smrg save->ppll_ref_div = pll->reference_div; 3864c582b7e3Smrg save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); 3865c582b7e3Smrg save->htotal_cntl = 0; 3866c582b7e3Smrg 3867c582b7e3Smrg} 3868c582b7e3Smrg 3869c582b7e3Smrg/* Define PLL2 registers for requested video mode. */ 3870c582b7e3Smrgstatic void R128InitPLL2Registers(R128SavePtr save, R128PLLPtr pll, 3871c582b7e3Smrg double dot_clock) 3872c582b7e3Smrg{ 3873c582b7e3Smrg unsigned long freq = dot_clock * 100; 3874c582b7e3Smrg struct { 3875c582b7e3Smrg int divider; 3876c582b7e3Smrg int bitvalue; 3877c582b7e3Smrg } *post_div, 3878c582b7e3Smrg post_divs[] = { 3879c582b7e3Smrg /* From RAGE 128 VR/RAGE 128 GL Register 3880c582b7e3Smrg Reference Manual (Technical Reference 3881c582b7e3Smrg Manual P/N RRG-G04100-C Rev. 0.04), page 3882c582b7e3Smrg 3-17 (PLL_DIV_[3:0]). */ 3883c582b7e3Smrg { 1, 0 }, /* VCLK_SRC */ 3884c582b7e3Smrg { 2, 1 }, /* VCLK_SRC/2 */ 3885c582b7e3Smrg { 4, 2 }, /* VCLK_SRC/4 */ 3886c582b7e3Smrg { 8, 3 }, /* VCLK_SRC/8 */ 3887c582b7e3Smrg 3888c582b7e3Smrg { 3, 4 }, /* VCLK_SRC/3 */ 3889c582b7e3Smrg /* bitvalue = 5 is reserved */ 3890c582b7e3Smrg { 6, 6 }, /* VCLK_SRC/6 */ 3891c582b7e3Smrg { 12, 7 }, /* VCLK_SRC/12 */ 3892c582b7e3Smrg { 0, 0 } 3893c582b7e3Smrg }; 3894c582b7e3Smrg 3895c582b7e3Smrg if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; 3896c582b7e3Smrg if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; 3897c582b7e3Smrg 3898c582b7e3Smrg for (post_div = &post_divs[0]; post_div->divider; ++post_div) { 3899c582b7e3Smrg save->pll_output_freq_2 = post_div->divider * freq; 3900c582b7e3Smrg if (save->pll_output_freq_2 >= pll->min_pll_freq 3901c582b7e3Smrg && save->pll_output_freq_2 <= pll->max_pll_freq) break; 3902c582b7e3Smrg } 3903c582b7e3Smrg 3904c582b7e3Smrg save->dot_clock_freq_2 = freq; 3905c582b7e3Smrg save->feedback_div_2 = R128Div(pll->reference_div 3906c582b7e3Smrg * save->pll_output_freq_2, 3907c582b7e3Smrg pll->reference_freq); 3908c582b7e3Smrg save->post_div_2 = post_div->divider; 3909c582b7e3Smrg 3910c582b7e3Smrg R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n", 3911c582b7e3Smrg save->dot_clock_freq_2, 3912c582b7e3Smrg save->pll_output_freq_2, 3913c582b7e3Smrg save->feedback_div_2, 3914c582b7e3Smrg save->post_div_2)); 3915c582b7e3Smrg 3916c582b7e3Smrg save->p2pll_ref_div = pll->reference_div; 3917c582b7e3Smrg save->p2pll_div_0 = (save->feedback_div_2 | (post_div->bitvalue<<16)); 3918c582b7e3Smrg save->htotal_cntl2 = 0; 3919c582b7e3Smrg} 3920c582b7e3Smrg 3921c582b7e3Smrg/* Define DDA registers for requested video mode. */ 3922c582b7e3Smrgstatic Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save, 3923c582b7e3Smrg R128PLLPtr pll, R128InfoPtr info, 3924c582b7e3Smrg DisplayModePtr mode) 3925c582b7e3Smrg{ 3926c582b7e3Smrg int DisplayFifoWidth = 128; 3927c582b7e3Smrg int DisplayFifoDepth = 32; 3928c582b7e3Smrg int XclkFreq; 3929c582b7e3Smrg int VclkFreq; 3930c582b7e3Smrg int XclksPerTransfer; 3931c582b7e3Smrg int XclksPerTransferPrecise; 3932c582b7e3Smrg int UseablePrecision; 3933c582b7e3Smrg int Roff; 3934c582b7e3Smrg int Ron; 3935c582b7e3Smrg 3936c582b7e3Smrg XclkFreq = pll->xclk; 3937c582b7e3Smrg 3938c582b7e3Smrg VclkFreq = R128Div(pll->reference_freq * save->feedback_div, 3939c582b7e3Smrg pll->reference_div * save->post_div); 3940c582b7e3Smrg 3941c582b7e3Smrg if(info->isDFP && !info->isPro2){ 3942c582b7e3Smrg if(info->PanelXRes != mode->CrtcHDisplay) 3943c582b7e3Smrg VclkFreq = (VclkFreq * mode->CrtcHDisplay)/info->PanelXRes; 3944c582b7e3Smrg } 3945c582b7e3Smrg 3946c582b7e3Smrg XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth, 3947c582b7e3Smrg VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); 3948c582b7e3Smrg 3949c582b7e3Smrg UseablePrecision = R128MinBits(XclksPerTransfer) + 1; 3950c582b7e3Smrg 3951c582b7e3Smrg XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth) 3952c582b7e3Smrg << (11 - UseablePrecision), 3953c582b7e3Smrg VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); 3954c582b7e3Smrg 3955c582b7e3Smrg Roff = XclksPerTransferPrecise * (DisplayFifoDepth - 4); 3956c582b7e3Smrg 3957c582b7e3Smrg Ron = (4 * info->ram->MB 3958c582b7e3Smrg + 3 * MAX(info->ram->Trcd - 2, 0) 3959c582b7e3Smrg + 2 * info->ram->Trp 3960c582b7e3Smrg + info->ram->Twr 3961c582b7e3Smrg + info->ram->CL 3962c582b7e3Smrg + info->ram->Tr2w 3963c582b7e3Smrg + XclksPerTransfer) << (11 - UseablePrecision); 3964c582b7e3Smrg 3965c582b7e3Smrg if (Ron + info->ram->Rloop >= Roff) { 3966c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 3967c582b7e3Smrg "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n", 3968c582b7e3Smrg Ron, info->ram->Rloop, Roff); 3969c582b7e3Smrg return FALSE; 3970c582b7e3Smrg } 3971c582b7e3Smrg 3972c582b7e3Smrg save->dda_config = (XclksPerTransferPrecise 3973c582b7e3Smrg | (UseablePrecision << 16) 3974c582b7e3Smrg | (info->ram->Rloop << 20)); 3975c582b7e3Smrg 3976c582b7e3Smrg save->dda_on_off = (Ron << 16) | Roff; 3977c582b7e3Smrg 3978c582b7e3Smrg R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n", 3979c582b7e3Smrg XclkFreq, 3980c582b7e3Smrg VclkFreq, 3981c582b7e3Smrg XclksPerTransfer, 3982c582b7e3Smrg XclksPerTransferPrecise, 3983c582b7e3Smrg UseablePrecision)); 3984c582b7e3Smrg R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n", 3985c582b7e3Smrg Roff, Ron, info->ram->Rloop)); 3986c582b7e3Smrg 3987c582b7e3Smrg return TRUE; 3988c582b7e3Smrg} 3989c582b7e3Smrg 3990c582b7e3Smrg/* Define DDA2 registers for requested video mode. */ 3991c582b7e3Smrgstatic Bool R128InitDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save, 3992c582b7e3Smrg R128PLLPtr pll, R128InfoPtr info, 3993c582b7e3Smrg DisplayModePtr mode) 3994c582b7e3Smrg{ 3995c582b7e3Smrg int DisplayFifoWidth = 128; 3996c582b7e3Smrg int DisplayFifoDepth = 32; 3997c582b7e3Smrg int XclkFreq; 3998c582b7e3Smrg int VclkFreq; 3999c582b7e3Smrg int XclksPerTransfer; 4000c582b7e3Smrg int XclksPerTransferPrecise; 4001c582b7e3Smrg int UseablePrecision; 4002c582b7e3Smrg int Roff; 4003c582b7e3Smrg int Ron; 4004c582b7e3Smrg 4005c582b7e3Smrg XclkFreq = pll->xclk; 4006c582b7e3Smrg 4007c582b7e3Smrg VclkFreq = R128Div(pll->reference_freq * save->feedback_div_2, 4008c582b7e3Smrg pll->reference_div * save->post_div_2); 4009c582b7e3Smrg 4010c582b7e3Smrg if(info->isDFP && !info->isPro2){ 4011c582b7e3Smrg if(info->PanelXRes != mode->CrtcHDisplay) 4012c582b7e3Smrg VclkFreq = (VclkFreq * mode->CrtcHDisplay)/info->PanelXRes; 4013c582b7e3Smrg } 4014c582b7e3Smrg 4015c582b7e3Smrg XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth, 4016c582b7e3Smrg VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); 4017c582b7e3Smrg 4018c582b7e3Smrg UseablePrecision = R128MinBits(XclksPerTransfer) + 1; 4019c582b7e3Smrg 4020c582b7e3Smrg XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth) 4021c582b7e3Smrg << (11 - UseablePrecision), 4022c582b7e3Smrg VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); 4023c582b7e3Smrg 4024c582b7e3Smrg Roff = XclksPerTransferPrecise * (DisplayFifoDepth - 4); 4025c582b7e3Smrg 4026c582b7e3Smrg Ron = (4 * info->ram->MB 4027c582b7e3Smrg + 3 * MAX(info->ram->Trcd - 2, 0) 4028c582b7e3Smrg + 2 * info->ram->Trp 4029c582b7e3Smrg + info->ram->Twr 4030c582b7e3Smrg + info->ram->CL 4031c582b7e3Smrg + info->ram->Tr2w 4032c582b7e3Smrg + XclksPerTransfer) << (11 - UseablePrecision); 4033c582b7e3Smrg 4034c582b7e3Smrg 4035c582b7e3Smrg if (Ron + info->ram->Rloop >= Roff) { 4036c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4037c582b7e3Smrg "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n", 4038c582b7e3Smrg Ron, info->ram->Rloop, Roff); 4039c582b7e3Smrg return FALSE; 4040c582b7e3Smrg } 4041c582b7e3Smrg 4042c582b7e3Smrg save->dda2_config = (XclksPerTransferPrecise 4043c582b7e3Smrg | (UseablePrecision << 16) 4044c582b7e3Smrg | (info->ram->Rloop << 20)); 4045c582b7e3Smrg 4046c582b7e3Smrg /*save->dda2_on_off = (Ron << 16) | Roff;*/ 4047c582b7e3Smrg /* shift most be 18 otherwise there's corruption on crtc2 */ 4048c582b7e3Smrg save->dda2_on_off = (Ron << 18) | Roff; 4049c582b7e3Smrg 4050c582b7e3Smrg R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n", 4051c582b7e3Smrg XclkFreq, 4052c582b7e3Smrg VclkFreq, 4053c582b7e3Smrg XclksPerTransfer, 4054c582b7e3Smrg XclksPerTransferPrecise, 4055c582b7e3Smrg UseablePrecision)); 4056c582b7e3Smrg R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n", 4057c582b7e3Smrg Roff, Ron, info->ram->Rloop)); 4058c582b7e3Smrg 4059c582b7e3Smrg return TRUE; 4060c582b7e3Smrg} 4061c582b7e3Smrg 4062c582b7e3Smrg#if 0 4063c582b7e3Smrg/* Define initial palette for requested video mode. This doesn't do 4064c582b7e3Smrg anything for XFree86 4.0. */ 4065c582b7e3Smrgstatic void R128InitPalette(R128SavePtr save) 4066c582b7e3Smrg{ 4067c582b7e3Smrg save->palette_valid = FALSE; 4068c582b7e3Smrg} 4069c582b7e3Smrg#endif 4070c582b7e3Smrg 4071c582b7e3Smrg/* Define registers for a requested video mode. */ 4072c582b7e3Smrgstatic Bool R128Init(ScrnInfoPtr pScrn, DisplayModePtr mode, R128SavePtr save) 4073c582b7e3Smrg{ 4074c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 4075c582b7e3Smrg double dot_clock = mode->Clock/1000.0; 4076c582b7e3Smrg 4077c582b7e3Smrg#if R128_DEBUG 4078c582b7e3Smrg ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", 4079c582b7e3Smrg mode->name, 4080c582b7e3Smrg dot_clock, 4081c582b7e3Smrg 4082c582b7e3Smrg mode->HDisplay, 4083c582b7e3Smrg mode->HSyncStart, 4084c582b7e3Smrg mode->HSyncEnd, 4085c582b7e3Smrg mode->HTotal, 4086c582b7e3Smrg 4087c582b7e3Smrg mode->VDisplay, 4088c582b7e3Smrg mode->VSyncStart, 4089c582b7e3Smrg mode->VSyncEnd, 4090c582b7e3Smrg mode->VTotal, 4091c582b7e3Smrg pScrn->depth, 4092c582b7e3Smrg pScrn->bitsPerPixel); 4093c582b7e3Smrg if (mode->Flags & V_DBLSCAN) ErrorF(" D"); 4094c582b7e3Smrg if (mode->Flags & V_CSYNC) ErrorF(" C"); 4095c582b7e3Smrg if (mode->Flags & V_INTERLACE) ErrorF(" I"); 4096c582b7e3Smrg if (mode->Flags & V_PHSYNC) ErrorF(" +H"); 4097c582b7e3Smrg if (mode->Flags & V_NHSYNC) ErrorF(" -H"); 4098c582b7e3Smrg if (mode->Flags & V_PVSYNC) ErrorF(" +V"); 4099c582b7e3Smrg if (mode->Flags & V_NVSYNC) ErrorF(" -V"); 4100c582b7e3Smrg ErrorF("\n"); 4101c582b7e3Smrg ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", 4102c582b7e3Smrg mode->name, 4103c582b7e3Smrg dot_clock, 4104c582b7e3Smrg 4105c582b7e3Smrg mode->CrtcHDisplay, 4106c582b7e3Smrg mode->CrtcHSyncStart, 4107c582b7e3Smrg mode->CrtcHSyncEnd, 4108c582b7e3Smrg mode->CrtcHTotal, 4109c582b7e3Smrg 4110c582b7e3Smrg mode->CrtcVDisplay, 4111c582b7e3Smrg mode->CrtcVSyncStart, 4112c582b7e3Smrg mode->CrtcVSyncEnd, 4113c582b7e3Smrg mode->CrtcVTotal, 4114c582b7e3Smrg pScrn->depth, 4115c582b7e3Smrg pScrn->bitsPerPixel); 4116c582b7e3Smrg if (mode->Flags & V_DBLSCAN) ErrorF(" D"); 4117c582b7e3Smrg if (mode->Flags & V_CSYNC) ErrorF(" C"); 4118c582b7e3Smrg if (mode->Flags & V_INTERLACE) ErrorF(" I"); 4119c582b7e3Smrg if (mode->Flags & V_PHSYNC) ErrorF(" +H"); 4120c582b7e3Smrg if (mode->Flags & V_NHSYNC) ErrorF(" -H"); 4121c582b7e3Smrg if (mode->Flags & V_PVSYNC) ErrorF(" +V"); 4122c582b7e3Smrg if (mode->Flags & V_NVSYNC) ErrorF(" -V"); 4123c582b7e3Smrg ErrorF("\n"); 4124c582b7e3Smrg#endif 4125c582b7e3Smrg 4126c582b7e3Smrg info->Flags = mode->Flags; 4127c582b7e3Smrg 4128c582b7e3Smrg if(info->IsSecondary) 4129c582b7e3Smrg { 4130c582b7e3Smrg if (!R128InitCrtc2Registers(pScrn, save, 4131c582b7e3Smrg pScrn->currentMode,info)) 4132c582b7e3Smrg return FALSE; 4133c582b7e3Smrg R128InitPLL2Registers(save, &info->pll, dot_clock); 4134c582b7e3Smrg if (!R128InitDDA2Registers(pScrn, save, &info->pll, info, mode)) 4135c582b7e3Smrg return FALSE; 4136c582b7e3Smrg } 4137c582b7e3Smrg else 4138c582b7e3Smrg { 4139c582b7e3Smrg R128InitCommonRegisters(save, info); 4140c582b7e3Smrg if(!R128InitCrtcRegisters(pScrn, save, mode, info)) 4141c582b7e3Smrg return FALSE; 4142c582b7e3Smrg if(dot_clock) 4143c582b7e3Smrg { 4144c582b7e3Smrg R128InitPLLRegisters(pScrn, save, &info->pll, dot_clock); 4145c582b7e3Smrg if (!R128InitDDARegisters(pScrn, save, &info->pll, info, mode)) 4146c582b7e3Smrg return FALSE; 4147c582b7e3Smrg } 4148c582b7e3Smrg else 4149c582b7e3Smrg { 4150c582b7e3Smrg save->ppll_ref_div = info->SavedReg.ppll_ref_div; 4151c582b7e3Smrg save->ppll_div_3 = info->SavedReg.ppll_div_3; 4152c582b7e3Smrg save->htotal_cntl = info->SavedReg.htotal_cntl; 4153c582b7e3Smrg save->dda_config = info->SavedReg.dda_config; 4154c582b7e3Smrg save->dda_on_off = info->SavedReg.dda_on_off; 4155c582b7e3Smrg } 4156c582b7e3Smrg /* not used for now */ 4157c582b7e3Smrg /*if (!info->PaletteSavedOnVT) RADEONInitPalette(save);*/ 4158c582b7e3Smrg } 4159c582b7e3Smrg 4160c582b7e3Smrg if (((info->DisplayType == MT_DFP) || 4161c582b7e3Smrg (info->DisplayType == MT_LCD))) 4162c582b7e3Smrg { 4163c582b7e3Smrg R128InitFPRegisters(&info->SavedReg, save, mode, info); 4164c582b7e3Smrg } 4165c582b7e3Smrg 4166c582b7e3Smrg R128TRACE(("R128Init returns %p\n", save)); 4167c582b7e3Smrg return TRUE; 4168c582b7e3Smrg} 4169c582b7e3Smrg 4170c582b7e3Smrg/* Initialize a new mode. */ 4171c582b7e3Smrgstatic Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 4172c582b7e3Smrg{ 4173c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 4174c582b7e3Smrg 4175c582b7e3Smrg if (!R128Init(pScrn, mode, &info->ModeReg)) return FALSE; 4176c582b7e3Smrg /* FIXME? DRILock/DRIUnlock here? */ 4177c582b7e3Smrg pScrn->vtSema = TRUE; 4178c582b7e3Smrg R128Blank(pScrn); 4179c582b7e3Smrg R128RestoreMode(pScrn, &info->ModeReg); 4180c582b7e3Smrg R128Unblank(pScrn); 4181c582b7e3Smrg 4182c582b7e3Smrg info->CurrentLayout.mode = mode; 4183c582b7e3Smrg 4184c582b7e3Smrg return TRUE; 4185c582b7e3Smrg} 4186c582b7e3Smrg 4187c582b7e3Smrgstatic Bool R128SaveScreen(ScreenPtr pScreen, int mode) 4188c582b7e3Smrg{ 4189c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 4190c582b7e3Smrg Bool unblank; 4191c582b7e3Smrg 4192c582b7e3Smrg unblank = xf86IsUnblank(mode); 4193c582b7e3Smrg if (unblank) 4194c582b7e3Smrg SetTimeSinceLastInputEvent(); 4195c582b7e3Smrg 4196c582b7e3Smrg if ((pScrn != NULL) && pScrn->vtSema) { 4197c582b7e3Smrg if (unblank) 4198c582b7e3Smrg R128Unblank(pScrn); 4199c582b7e3Smrg else 4200c582b7e3Smrg R128Blank(pScrn); 4201c582b7e3Smrg } 4202c582b7e3Smrg return TRUE; 4203c582b7e3Smrg} 4204c582b7e3Smrg 4205c582b7e3Smrg/* 4206c582b7e3Smrg * SwitchMode() doesn't work right on crtc2 on some laptops. 4207c582b7e3Smrg * The workaround is to switch the mode, then switch to another VT, then 4208c582b7e3Smrg * switch back. --AGD 4209c582b7e3Smrg */ 4210c582b7e3SmrgBool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 4211c582b7e3Smrg{ 4212c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4213c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 4214c582b7e3Smrg Bool ret; 4215c582b7e3Smrg 4216c582b7e3Smrg info->SwitchingMode = TRUE; 4217c582b7e3Smrg ret = R128ModeInit(xf86Screens[scrnIndex], mode); 4218c582b7e3Smrg info->SwitchingMode = FALSE; 4219c582b7e3Smrg return ret; 4220c582b7e3Smrg} 4221c582b7e3Smrg 4222c582b7e3Smrg/* Used to disallow modes that are not supported by the hardware. */ 4223c582b7e3SmrgModeStatus R128ValidMode(int scrnIndex, DisplayModePtr mode, 4224c582b7e3Smrg Bool verbose, int flags) 4225c582b7e3Smrg{ 4226c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4227c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 4228c582b7e3Smrg 4229c582b7e3Smrg if (info->BIOSDisplay == R128_BIOS_DISPLAY_CRT) 4230c582b7e3Smrg return MODE_OK; 4231c582b7e3Smrg 4232c582b7e3Smrg if(info->isDFP) { 4233c582b7e3Smrg if(info->PanelXRes < mode->CrtcHDisplay || 4234c582b7e3Smrg info->PanelYRes < mode->CrtcVDisplay) 4235c582b7e3Smrg return MODE_NOMODE; 4236c582b7e3Smrg else 4237c582b7e3Smrg return MODE_OK; 4238c582b7e3Smrg } 4239c582b7e3Smrg 4240c582b7e3Smrg if (info->DisplayType == MT_LCD) { 4241c582b7e3Smrg if (mode->Flags & V_INTERLACE) return MODE_NO_INTERLACE; 4242c582b7e3Smrg if (mode->Flags & V_DBLSCAN) return MODE_NO_DBLESCAN; 4243c582b7e3Smrg } 4244c582b7e3Smrg 4245c582b7e3Smrg if (info->DisplayType == MT_LCD && 4246c582b7e3Smrg info->VBIOS) { 4247c582b7e3Smrg int i; 4248c582b7e3Smrg for (i = info->FPBIOSstart+64; R128_BIOS16(i) != 0; i += 2) { 4249c582b7e3Smrg int j = R128_BIOS16(i); 4250c582b7e3Smrg 4251c582b7e3Smrg if (mode->CrtcHDisplay == R128_BIOS16(j) && 4252c582b7e3Smrg mode->CrtcVDisplay == R128_BIOS16(j+2)) { 4253c582b7e3Smrg if ((flags & MODECHECK_FINAL) == MODECHECK_FINAL) { 4254c582b7e3Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4255c582b7e3Smrg "Modifying mode according to VBIOS: %ix%i [pclk %.1f MHz] for FP to: ", 4256c582b7e3Smrg mode->CrtcHDisplay,mode->CrtcVDisplay, 4257c582b7e3Smrg (float)mode->Clock/1000); 4258c582b7e3Smrg 4259c582b7e3Smrg /* Assume we are using expanded mode */ 4260c582b7e3Smrg if (R128_BIOS16(j+5)) j = R128_BIOS16(j+5); 4261c582b7e3Smrg else j += 9; 4262c582b7e3Smrg 4263c582b7e3Smrg mode->Clock = (CARD32)R128_BIOS16(j) * 10; 4264c582b7e3Smrg 4265c582b7e3Smrg mode->HDisplay = mode->CrtcHDisplay = 4266c582b7e3Smrg ((R128_BIOS16(j+10) & 0x01ff)+1)*8; 4267c582b7e3Smrg mode->HSyncStart = mode->CrtcHSyncStart = 4268c582b7e3Smrg ((R128_BIOS16(j+12) & 0x01ff)+1)*8; 4269c582b7e3Smrg mode->HSyncEnd = mode->CrtcHSyncEnd = 4270c582b7e3Smrg mode->CrtcHSyncStart + (R128_BIOS8(j+14) & 0x1f); 4271c582b7e3Smrg mode->HTotal = mode->CrtcHTotal = 4272c582b7e3Smrg ((R128_BIOS16(j+8) & 0x01ff)+1)*8; 4273c582b7e3Smrg 4274c582b7e3Smrg mode->VDisplay = mode->CrtcVDisplay = 4275c582b7e3Smrg (R128_BIOS16(j+17) & 0x07ff)+1; 4276c582b7e3Smrg mode->VSyncStart = mode->CrtcVSyncStart = 4277c582b7e3Smrg (R128_BIOS16(j+19) & 0x07ff)+1; 4278c582b7e3Smrg mode->VSyncEnd = mode->CrtcVSyncEnd = 4279c582b7e3Smrg mode->CrtcVSyncStart + ((R128_BIOS16(j+19) >> 11) & 0x1f); 4280c582b7e3Smrg mode->VTotal = mode->CrtcVTotal = 4281c582b7e3Smrg (R128_BIOS16(j+15) & 0x07ff)+1; 4282c582b7e3Smrg xf86ErrorF("%ix%i [pclk %.1f MHz]\n", 4283c582b7e3Smrg mode->CrtcHDisplay,mode->CrtcVDisplay, 4284c582b7e3Smrg (float)mode->Clock/1000); 4285c582b7e3Smrg } 4286c582b7e3Smrg return MODE_OK; 4287c582b7e3Smrg } 4288c582b7e3Smrg } 4289c582b7e3Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, 4290c582b7e3Smrg "Mode rejected for FP %ix%i [pclk: %.1f] " 4291c582b7e3Smrg "(not listed in VBIOS)\n", 4292c582b7e3Smrg mode->CrtcHDisplay, mode->CrtcVDisplay, 4293c582b7e3Smrg (float)mode->Clock / 1000); 4294c582b7e3Smrg return MODE_NOMODE; 4295c582b7e3Smrg } 4296c582b7e3Smrg 4297c582b7e3Smrg return MODE_OK; 4298c582b7e3Smrg} 4299c582b7e3Smrg 4300c582b7e3Smrg/* Adjust viewport into virtual desktop such that (0,0) in viewport space 4301c582b7e3Smrg is (x,y) in virtual space. */ 4302c582b7e3Smrgvoid R128AdjustFrame(int scrnIndex, int x, int y, int flags) 4303c582b7e3Smrg{ 4304c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4305c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 4306c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 4307c582b7e3Smrg int Base; 4308c582b7e3Smrg 4309c582b7e3Smrg if(info->showCache && y && pScrn->vtSema) 4310c582b7e3Smrg y += pScrn->virtualY - 1; 4311c582b7e3Smrg 4312c582b7e3Smrg Base = y * info->CurrentLayout.displayWidth + x; 4313c582b7e3Smrg 4314c582b7e3Smrg switch (info->CurrentLayout.pixel_code) { 4315c582b7e3Smrg case 15: 4316c582b7e3Smrg case 16: Base *= 2; break; 4317c582b7e3Smrg case 24: Base *= 3; break; 4318c582b7e3Smrg case 32: Base *= 4; break; 4319c582b7e3Smrg } 4320c582b7e3Smrg 4321c582b7e3Smrg Base &= ~7; /* 3 lower bits are always 0 */ 4322c582b7e3Smrg 4323c582b7e3Smrg if (info->CurrentLayout.pixel_code == 24) 4324c582b7e3Smrg Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */ 4325c582b7e3Smrg 4326c582b7e3Smrg if(info->IsSecondary) 4327c582b7e3Smrg { 4328c582b7e3Smrg Base += pScrn->fbOffset; 4329c582b7e3Smrg OUTREG(R128_CRTC2_OFFSET, Base); 4330c582b7e3Smrg } 4331c582b7e3Smrg else 4332c582b7e3Smrg OUTREG(R128_CRTC_OFFSET, Base); 4333c582b7e3Smrg 4334c582b7e3Smrg} 4335c582b7e3Smrg 4336c582b7e3Smrg/* Called when VT switching back to the X server. Reinitialize the video 4337c582b7e3Smrg mode. */ 4338c582b7e3SmrgBool R128EnterVT(int scrnIndex, int flags) 4339c582b7e3Smrg{ 4340c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4341c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 4342c582b7e3Smrg 4343c582b7e3Smrg R128TRACE(("R128EnterVT\n")); 434479e5230eSmacallan#ifndef AVOID_FBDEV 4345c582b7e3Smrg if (info->FBDev) { 4346c582b7e3Smrg if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE; 4347c582b7e3Smrg } else 434879e5230eSmacallan#endif 4349c582b7e3Smrg if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE; 4350c582b7e3Smrg if (info->accelOn) 4351c582b7e3Smrg R128EngineInit(pScrn); 4352c582b7e3Smrg 4353c582b7e3Smrg#ifdef XF86DRI 4354c582b7e3Smrg if (info->directRenderingEnabled) { 4355c582b7e3Smrg if (info->irq) { 4356c582b7e3Smrg /* Need to make sure interrupts are enabled */ 4357c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 4358c582b7e3Smrg OUTREG(R128_GEN_INT_CNTL, info->gen_int_cntl); 4359c582b7e3Smrg } 4360c582b7e3Smrg R128CCE_START(pScrn, info); 4361c582b7e3Smrg DRIUnlock(pScrn->pScreen); 4362c582b7e3Smrg } 4363c582b7e3Smrg#endif 4364c582b7e3Smrg 4365c582b7e3Smrg info->PaletteSavedOnVT = FALSE; 4366c582b7e3Smrg pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 4367c582b7e3Smrg 4368c582b7e3Smrg return TRUE; 4369c582b7e3Smrg} 4370c582b7e3Smrg 4371c582b7e3Smrg/* Called when VT switching away from the X server. Restore the original 4372c582b7e3Smrg text mode. */ 4373c582b7e3Smrgvoid R128LeaveVT(int scrnIndex, int flags) 4374c582b7e3Smrg{ 4375c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4376c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 4377c582b7e3Smrg R128SavePtr save = &info->ModeReg; 4378c582b7e3Smrg 4379c582b7e3Smrg R128TRACE(("R128LeaveVT\n")); 4380c582b7e3Smrg#ifdef XF86DRI 4381c582b7e3Smrg if (info->directRenderingEnabled) { 4382c582b7e3Smrg DRILock(pScrn->pScreen, 0); 4383c582b7e3Smrg R128CCE_STOP(pScrn, info); 4384c582b7e3Smrg } 4385c582b7e3Smrg#endif 4386c582b7e3Smrg R128SavePalette(pScrn, save); 4387c582b7e3Smrg info->PaletteSavedOnVT = TRUE; 438879e5230eSmacallan#ifndef AVOID_FBDEV 4389c582b7e3Smrg if (info->FBDev) 4390c582b7e3Smrg fbdevHWLeaveVT(scrnIndex,flags); 4391c582b7e3Smrg else 439279e5230eSmacallan#endif 4393c582b7e3Smrg R128Restore(pScrn); 4394c582b7e3Smrg} 4395c582b7e3Smrg 4396c582b7e3Smrg 4397c582b7e3Smrg/* Called at the end of each server generation. Restore the original text 4398c582b7e3Smrg mode, unmap video memory, and unwrap and call the saved CloseScreen 4399c582b7e3Smrg function. */ 4400c582b7e3Smrgstatic Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen) 4401c582b7e3Smrg{ 4402c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4403c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 4404c582b7e3Smrg 4405c582b7e3Smrg R128TRACE(("R128CloseScreen\n")); 4406c582b7e3Smrg 4407c582b7e3Smrg#ifdef XF86DRI 4408c582b7e3Smrg /* Disable direct rendering */ 4409c582b7e3Smrg if (info->directRenderingEnabled) { 4410c582b7e3Smrg R128DRICloseScreen(pScreen); 4411c582b7e3Smrg info->directRenderingEnabled = FALSE; 4412c582b7e3Smrg } 4413c582b7e3Smrg#endif 4414c582b7e3Smrg 4415c582b7e3Smrg if (pScrn->vtSema) { 4416c582b7e3Smrg R128Restore(pScrn); 4417c582b7e3Smrg R128UnmapMem(pScrn); 4418c582b7e3Smrg } 4419c582b7e3Smrg 4420c582b7e3Smrg if (info->accel) XAADestroyInfoRec(info->accel); 4421c582b7e3Smrg info->accel = NULL; 4422c582b7e3Smrg 4423c582b7e3Smrg if (info->scratch_save) xfree(info->scratch_save); 4424c582b7e3Smrg info->scratch_save = NULL; 4425c582b7e3Smrg 4426c582b7e3Smrg if (info->cursor) xf86DestroyCursorInfoRec(info->cursor); 4427c582b7e3Smrg info->cursor = NULL; 4428c582b7e3Smrg 4429c582b7e3Smrg if (info->DGAModes) xfree(info->DGAModes); 4430c582b7e3Smrg info->DGAModes = NULL; 4431c582b7e3Smrg 4432c582b7e3Smrg if (info->adaptor) { 4433c582b7e3Smrg xfree(info->adaptor->pPortPrivates[0].ptr); 4434c582b7e3Smrg xf86XVFreeVideoAdaptorRec(info->adaptor); 4435c582b7e3Smrg info->adaptor = NULL; 4436c582b7e3Smrg } 4437c582b7e3Smrg 4438c582b7e3Smrg pScrn->vtSema = FALSE; 4439c582b7e3Smrg 4440c582b7e3Smrg pScreen->BlockHandler = info->BlockHandler; 4441c582b7e3Smrg pScreen->CloseScreen = info->CloseScreen; 4442c582b7e3Smrg return (*pScreen->CloseScreen)(scrnIndex, pScreen); 4443c582b7e3Smrg} 4444c582b7e3Smrg 4445c582b7e3Smrgvoid R128FreeScreen(int scrnIndex, int flags) 4446c582b7e3Smrg{ 4447c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4448c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 4449c582b7e3Smrg 4450c582b7e3Smrg R128TRACE(("R128FreeScreen\n")); 445119019ffeSmrg if (info == NULL) 445219019ffeSmrg return; 4453c582b7e3Smrg#ifdef WITH_VGAHW 4454c582b7e3Smrg if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 4455c582b7e3Smrg vgaHWFreeHWRec(pScrn); 4456c582b7e3Smrg#endif 4457c582b7e3Smrg R128FreeRec(pScrn); 4458c582b7e3Smrg} 4459c582b7e3Smrg 4460c582b7e3Smrg/* Sets VESA Display Power Management Signaling (DPMS) Mode. */ 4461c582b7e3Smrgstatic void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn, 4462c582b7e3Smrg int PowerManagementMode, int flags) 4463c582b7e3Smrg{ 4464c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 4465c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 4466c582b7e3Smrg int mask = (R128_CRTC_DISPLAY_DIS 4467c582b7e3Smrg | R128_CRTC_HSYNC_DIS 4468c582b7e3Smrg | R128_CRTC_VSYNC_DIS); 4469c582b7e3Smrg int mask2 = R128_CRTC2_DISP_DIS; 4470c582b7e3Smrg 4471c582b7e3Smrg switch (PowerManagementMode) { 4472c582b7e3Smrg case DPMSModeOn: 4473c582b7e3Smrg /* Screen: On; HSync: On, VSync: On */ 4474c582b7e3Smrg if (info->IsSecondary) 4475c582b7e3Smrg OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~mask2); 4476c582b7e3Smrg else 4477c582b7e3Smrg OUTREGP(R128_CRTC_EXT_CNTL, 0, ~mask); 4478c582b7e3Smrg break; 4479c582b7e3Smrg case DPMSModeStandby: 4480c582b7e3Smrg /* Screen: Off; HSync: Off, VSync: On */ 4481c582b7e3Smrg if (info->IsSecondary) 4482c582b7e3Smrg OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask2); 4483c582b7e3Smrg else 4484c582b7e3Smrg OUTREGP(R128_CRTC_EXT_CNTL, 4485c582b7e3Smrg R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS, ~mask); 4486c582b7e3Smrg break; 4487c582b7e3Smrg case DPMSModeSuspend: 4488c582b7e3Smrg /* Screen: Off; HSync: On, VSync: Off */ 4489c582b7e3Smrg if (info->IsSecondary) 4490c582b7e3Smrg OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask2); 4491c582b7e3Smrg else 4492c582b7e3Smrg OUTREGP(R128_CRTC_EXT_CNTL, 4493c582b7e3Smrg R128_CRTC_DISPLAY_DIS | R128_CRTC_VSYNC_DIS, ~mask); 4494c582b7e3Smrg break; 4495c582b7e3Smrg case DPMSModeOff: 4496c582b7e3Smrg /* Screen: Off; HSync: Off, VSync: Off */ 4497c582b7e3Smrg if (info->IsSecondary) 4498c582b7e3Smrg OUTREGP(R128_CRTC2_GEN_CNTL, mask2, ~mask2); 4499c582b7e3Smrg else 4500c582b7e3Smrg OUTREGP(R128_CRTC_EXT_CNTL, mask, ~mask); 4501c582b7e3Smrg break; 4502c582b7e3Smrg } 4503c582b7e3Smrg if(info->isDFP) { 4504c582b7e3Smrg switch (PowerManagementMode) { 4505c582b7e3Smrg case DPMSModeOn: 4506c582b7e3Smrg OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL) | (R128_FP_FPON | R128_FP_TDMS_EN)); 4507c582b7e3Smrg break; 4508c582b7e3Smrg case DPMSModeStandby: 4509c582b7e3Smrg case DPMSModeSuspend: 4510c582b7e3Smrg case DPMSModeOff: 4511c582b7e3Smrg OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL) & ~(R128_FP_FPON | R128_FP_TDMS_EN)); 4512c582b7e3Smrg break; 4513c582b7e3Smrg } 4514c582b7e3Smrg } 4515c582b7e3Smrg} 4516c582b7e3Smrg 4517c582b7e3Smrgstatic int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on); 4518c582b7e3Smrg 4519c582b7e3Smrgstatic void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn, 4520c582b7e3Smrg int PowerManagementMode, int flags) 4521c582b7e3Smrg{ 4522c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 4523c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 4524c582b7e3Smrg int mask = R128_LVDS_DISPLAY_DIS; 4525c582b7e3Smrg 4526c582b7e3Smrg switch (PowerManagementMode) { 4527c582b7e3Smrg case DPMSModeOn: 4528c582b7e3Smrg /* Screen: On; HSync: On, VSync: On */ 4529c582b7e3Smrg OUTREGP(R128_LVDS_GEN_CNTL, 0, ~mask); 4530c582b7e3Smrg r128_set_backlight_enable(pScrn, 1); 4531c582b7e3Smrg break; 4532c582b7e3Smrg case DPMSModeStandby: 4533c582b7e3Smrg /* Fall through */ 4534c582b7e3Smrg case DPMSModeSuspend: 4535c582b7e3Smrg /* Fall through */ 4536c582b7e3Smrg case DPMSModeOff: 4537c582b7e3Smrg /* Screen: Off; HSync: Off, VSync: Off */ 4538c582b7e3Smrg OUTREGP(R128_LVDS_GEN_CNTL, mask, ~mask); 4539c582b7e3Smrg r128_set_backlight_enable(pScrn, 0); 4540c582b7e3Smrg break; 4541c582b7e3Smrg } 4542c582b7e3Smrg} 4543c582b7e3Smrg 4544c582b7e3Smrgstatic int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on) 4545c582b7e3Smrg{ 4546c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 4547c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 4548c582b7e3Smrg unsigned int lvds_gen_cntl = INREG(R128_LVDS_GEN_CNTL); 4549c582b7e3Smrg 4550c582b7e3Smrg lvds_gen_cntl |= (/*R128_LVDS_BL_MOD_EN |*/ R128_LVDS_BLON); 4551c582b7e3Smrg if (on) { 4552c582b7e3Smrg lvds_gen_cntl |= R128_LVDS_DIGON; 4553c582b7e3Smrg if (!(lvds_gen_cntl & R128_LVDS_ON)) { 4554c582b7e3Smrg lvds_gen_cntl &= ~R128_LVDS_BLON; 4555c582b7e3Smrg OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); 4556c582b7e3Smrg (void)INREG(R128_LVDS_GEN_CNTL); 4557c582b7e3Smrg usleep(10000); 4558c582b7e3Smrg lvds_gen_cntl |= R128_LVDS_BLON; 4559c582b7e3Smrg OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); 4560c582b7e3Smrg } 4561c582b7e3Smrg#if 0 4562c582b7e3Smrg lvds_gen_cntl &= ~R128_LVDS_BL_MOD_LEVEL_MASK; 4563c582b7e3Smrg lvds_gen_cntl |= (0xFF /* backlight_conv[level] */ << 4564c582b7e3Smrg R128_LVDS_BL_MOD_LEVEL_SHIFT); 4565c582b7e3Smrg#endif 4566c582b7e3Smrg lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_EN); 4567c582b7e3Smrg lvds_gen_cntl &= ~R128_LVDS_DISPLAY_DIS; 4568c582b7e3Smrg } else { 4569c582b7e3Smrg#if 0 4570c582b7e3Smrg lvds_gen_cntl &= ~R128_LVDS_BL_MOD_LEVEL_MASK; 4571c582b7e3Smrg lvds_gen_cntl |= (0xFF /* backlight_conv[0] */ << 4572c582b7e3Smrg R128_LVDS_BL_MOD_LEVEL_SHIFT); 4573c582b7e3Smrg#endif 4574c582b7e3Smrg lvds_gen_cntl |= R128_LVDS_DISPLAY_DIS; 4575c582b7e3Smrg OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); 4576c582b7e3Smrg usleep(10); 4577c582b7e3Smrg lvds_gen_cntl &= ~(R128_LVDS_ON | R128_LVDS_EN | R128_LVDS_BLON 4578c582b7e3Smrg | R128_LVDS_DIGON); 4579c582b7e3Smrg } 4580c582b7e3Smrg 4581c582b7e3Smrg OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); 4582c582b7e3Smrg 4583c582b7e3Smrg return 0; 4584c582b7e3Smrg} 4585