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