i830_driver.c revision fa225cbc
1fa225cbcSrjs/************************************************************************** 2fa225cbcSrjs 3fa225cbcSrjsCopyright 2001 VA Linux Systems Inc., Fremont, California. 4fa225cbcSrjsCopyright © 2002 by David Dawes 5fa225cbcSrjs 6fa225cbcSrjsAll Rights Reserved. 7fa225cbcSrjs 8fa225cbcSrjsPermission is hereby granted, free of charge, to any person obtaining a 9fa225cbcSrjscopy of this software and associated documentation files (the "Software"), 10fa225cbcSrjsto deal in the Software without restriction, including without limitation 11fa225cbcSrjson the rights to use, copy, modify, merge, publish, distribute, sub 12fa225cbcSrjslicense, and/or sell copies of the Software, and to permit persons to whom 13fa225cbcSrjsthe Software is furnished to do so, subject to the following conditions: 14fa225cbcSrjs 15fa225cbcSrjsThe above copyright notice and this permission notice (including the next 16fa225cbcSrjsparagraph) shall be included in all copies or substantial portions of the 17fa225cbcSrjsSoftware. 18fa225cbcSrjs 19fa225cbcSrjsTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20fa225cbcSrjsIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21fa225cbcSrjsFITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 22fa225cbcSrjsTHE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 23fa225cbcSrjsDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24fa225cbcSrjsOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 25fa225cbcSrjsUSE OR OTHER DEALINGS IN THE SOFTWARE. 26fa225cbcSrjs 27fa225cbcSrjs**************************************************************************/ 28fa225cbcSrjs 29fa225cbcSrjs/* 30fa225cbcSrjs * Authors: Jeff Hartmann <jhartmann@valinux.com> 31fa225cbcSrjs * Abraham van der Merwe <abraham@2d3d.co.za> 32fa225cbcSrjs * David Dawes <dawes@xfree86.org> 33fa225cbcSrjs * Alan Hourihane <alanh@tungstengraphics.com> 34fa225cbcSrjs */ 35fa225cbcSrjs 36fa225cbcSrjs#ifdef HAVE_CONFIG_H 37fa225cbcSrjs#include "config.h" 38fa225cbcSrjs#endif 39fa225cbcSrjs 40fa225cbcSrjs#ifndef PRINT_MODE_INFO 41fa225cbcSrjs#define PRINT_MODE_INFO 0 42fa225cbcSrjs#endif 43fa225cbcSrjs 44fa225cbcSrjs#include <assert.h> 45fa225cbcSrjs#include <string.h> 46fa225cbcSrjs#include <stdio.h> 47fa225cbcSrjs#include <unistd.h> 48fa225cbcSrjs#include <stdlib.h> 49fa225cbcSrjs#include <stdio.h> 50fa225cbcSrjs#include <errno.h> 51fa225cbcSrjs 52fa225cbcSrjs#include "xf86.h" 53fa225cbcSrjs#include "xf86_OSproc.h" 54fa225cbcSrjs#include "xf86Priv.h" 55fa225cbcSrjs#include "xf86cmap.h" 56fa225cbcSrjs#include "compiler.h" 57fa225cbcSrjs#include "mibstore.h" 58fa225cbcSrjs#include "vgaHW.h" 59fa225cbcSrjs#include "mipointer.h" 60fa225cbcSrjs#include "micmap.h" 61fa225cbcSrjs#include "shadowfb.h" 62fa225cbcSrjs#include <X11/extensions/randr.h> 63fa225cbcSrjs#include "fb.h" 64fa225cbcSrjs#include "miscstruct.h" 65fa225cbcSrjs#include "dixstruct.h" 66fa225cbcSrjs#include "xf86xv.h" 67fa225cbcSrjs#include <X11/extensions/Xv.h> 68fa225cbcSrjs#include "shadow.h" 69fa225cbcSrjs#include "i830.h" 70fa225cbcSrjs#include "i830_display.h" 71fa225cbcSrjs#include "i830_debug.h" 72fa225cbcSrjs#include "i830_bios.h" 73fa225cbcSrjs#include "i830_video.h" 74fa225cbcSrjs#if HAVE_SYS_MMAN_H && HAVE_MPROTECT 75fa225cbcSrjs#include <sys/mman.h> 76fa225cbcSrjs#endif 77fa225cbcSrjs 78fa225cbcSrjs#ifdef INTEL_XVMC 79fa225cbcSrjs#define _INTEL_XVMC_SERVER_ 80fa225cbcSrjs#include "i830_hwmc.h" 81fa225cbcSrjs#endif 82fa225cbcSrjs 83fa225cbcSrjs#include <sys/ioctl.h> 84fa225cbcSrjs#include "i915_drm.h" 85fa225cbcSrjs#include <xf86drmMode.h> 86fa225cbcSrjs 87fa225cbcSrjs#define BIT(x) (1 << (x)) 88fa225cbcSrjs#define MAX(a,b) ((a) > (b) ? (a) : (b)) 89fa225cbcSrjs#define NB_OF(x) (sizeof (x) / sizeof (*x)) 90fa225cbcSrjs 91fa225cbcSrjs/* *INDENT-OFF* */ 92fa225cbcSrjsstatic SymTabRec I830Chipsets[] = { 93fa225cbcSrjs {PCI_CHIP_I830_M, "i830"}, 94fa225cbcSrjs {PCI_CHIP_845_G, "845G"}, 95fa225cbcSrjs {PCI_CHIP_I855_GM, "852GM/855GM"}, 96fa225cbcSrjs {PCI_CHIP_I865_G, "865G"}, 97fa225cbcSrjs {PCI_CHIP_I915_G, "915G"}, 98fa225cbcSrjs {PCI_CHIP_E7221_G, "E7221 (i915)"}, 99fa225cbcSrjs {PCI_CHIP_I915_GM, "915GM"}, 100fa225cbcSrjs {PCI_CHIP_I945_G, "945G"}, 101fa225cbcSrjs {PCI_CHIP_I945_GM, "945GM"}, 102fa225cbcSrjs {PCI_CHIP_I945_GME, "945GME"}, 103fa225cbcSrjs {PCI_CHIP_IGD_GM, "Pineview GM"}, 104fa225cbcSrjs {PCI_CHIP_IGD_G, "Pineview G"}, 105fa225cbcSrjs {PCI_CHIP_I965_G, "965G"}, 106fa225cbcSrjs {PCI_CHIP_G35_G, "G35"}, 107fa225cbcSrjs {PCI_CHIP_I965_Q, "965Q"}, 108fa225cbcSrjs {PCI_CHIP_I946_GZ, "946GZ"}, 109fa225cbcSrjs {PCI_CHIP_I965_GM, "965GM"}, 110fa225cbcSrjs {PCI_CHIP_I965_GME, "965GME/GLE"}, 111fa225cbcSrjs {PCI_CHIP_G33_G, "G33"}, 112fa225cbcSrjs {PCI_CHIP_Q35_G, "Q35"}, 113fa225cbcSrjs {PCI_CHIP_Q33_G, "Q33"}, 114fa225cbcSrjs {PCI_CHIP_GM45_GM, "GM45"}, 115fa225cbcSrjs {PCI_CHIP_IGD_E_G, "4 Series"}, 116fa225cbcSrjs {PCI_CHIP_G45_G, "G45/G43"}, 117fa225cbcSrjs {PCI_CHIP_Q45_G, "Q45/Q43"}, 118fa225cbcSrjs {PCI_CHIP_G41_G, "G41"}, 119fa225cbcSrjs {PCI_CHIP_B43_G, "B43"}, 120fa225cbcSrjs {PCI_CHIP_IGDNG_D_G, "Clarkdale"}, 121fa225cbcSrjs {PCI_CHIP_IGDNG_M_G, "Arrandale"}, 122fa225cbcSrjs {-1, NULL} 123fa225cbcSrjs}; 124fa225cbcSrjs 125fa225cbcSrjsstatic PciChipsets I830PciChipsets[] = { 126fa225cbcSrjs {PCI_CHIP_I830_M, PCI_CHIP_I830_M, NULL}, 127fa225cbcSrjs {PCI_CHIP_845_G, PCI_CHIP_845_G, NULL}, 128fa225cbcSrjs {PCI_CHIP_I855_GM, PCI_CHIP_I855_GM, NULL}, 129fa225cbcSrjs {PCI_CHIP_I865_G, PCI_CHIP_I865_G, NULL}, 130fa225cbcSrjs {PCI_CHIP_I915_G, PCI_CHIP_I915_G, NULL}, 131fa225cbcSrjs {PCI_CHIP_E7221_G, PCI_CHIP_E7221_G, NULL}, 132fa225cbcSrjs {PCI_CHIP_I915_GM, PCI_CHIP_I915_GM, NULL}, 133fa225cbcSrjs {PCI_CHIP_I945_G, PCI_CHIP_I945_G, NULL}, 134fa225cbcSrjs {PCI_CHIP_I945_GM, PCI_CHIP_I945_GM, NULL}, 135fa225cbcSrjs {PCI_CHIP_I945_GME, PCI_CHIP_I945_GME, NULL}, 136fa225cbcSrjs {PCI_CHIP_IGD_GM, PCI_CHIP_IGD_GM, NULL}, 137fa225cbcSrjs {PCI_CHIP_IGD_G, PCI_CHIP_IGD_G, NULL}, 138fa225cbcSrjs {PCI_CHIP_I965_G, PCI_CHIP_I965_G, NULL}, 139fa225cbcSrjs {PCI_CHIP_G35_G, PCI_CHIP_G35_G, NULL}, 140fa225cbcSrjs {PCI_CHIP_I965_Q, PCI_CHIP_I965_Q, NULL}, 141fa225cbcSrjs {PCI_CHIP_I946_GZ, PCI_CHIP_I946_GZ, NULL}, 142fa225cbcSrjs {PCI_CHIP_I965_GM, PCI_CHIP_I965_GM, NULL}, 143fa225cbcSrjs {PCI_CHIP_I965_GME, PCI_CHIP_I965_GME, NULL}, 144fa225cbcSrjs {PCI_CHIP_G33_G, PCI_CHIP_G33_G, NULL}, 145fa225cbcSrjs {PCI_CHIP_Q35_G, PCI_CHIP_Q35_G, NULL}, 146fa225cbcSrjs {PCI_CHIP_Q33_G, PCI_CHIP_Q33_G, NULL}, 147fa225cbcSrjs {PCI_CHIP_GM45_GM, PCI_CHIP_GM45_GM, NULL}, 148fa225cbcSrjs {PCI_CHIP_IGD_E_G, PCI_CHIP_IGD_E_G, NULL}, 149fa225cbcSrjs {PCI_CHIP_G45_G, PCI_CHIP_G45_G, NULL}, 150fa225cbcSrjs {PCI_CHIP_Q45_G, PCI_CHIP_Q45_G, NULL}, 151fa225cbcSrjs {PCI_CHIP_G41_G, PCI_CHIP_G41_G, NULL}, 152fa225cbcSrjs {PCI_CHIP_B43_G, PCI_CHIP_B43_G, NULL}, 153fa225cbcSrjs {PCI_CHIP_IGDNG_D_G, PCI_CHIP_IGDNG_D_G, NULL}, 154fa225cbcSrjs {PCI_CHIP_IGDNG_M_G, PCI_CHIP_IGDNG_M_G, NULL}, 155fa225cbcSrjs {-1, -1, NULL} 156fa225cbcSrjs}; 157fa225cbcSrjs 158fa225cbcSrjs/* 159fa225cbcSrjs * Note: "ColorKey" is provided for compatibility with the i810 driver. 160fa225cbcSrjs * However, the correct option name is "VideoKey". "ColorKey" usually 161fa225cbcSrjs * refers to the tranparency key for 8+24 overlays, not for video overlays. 162fa225cbcSrjs */ 163fa225cbcSrjs 164fa225cbcSrjstypedef enum { 165fa225cbcSrjs OPTION_DRI, 166fa225cbcSrjs OPTION_VIDEO_KEY, 167fa225cbcSrjs OPTION_COLOR_KEY, 168fa225cbcSrjs OPTION_MODEDEBUG, 169fa225cbcSrjs OPTION_FALLBACKDEBUG, 170fa225cbcSrjs OPTION_LVDS24BITMODE, 171fa225cbcSrjs OPTION_FBC, 172fa225cbcSrjs OPTION_TILING, 173fa225cbcSrjs OPTION_SWAPBUFFERS_WAIT, 174fa225cbcSrjs OPTION_LVDSFIXEDMODE, 175fa225cbcSrjs OPTION_FORCEENABLEPIPEA, 176fa225cbcSrjs#ifdef INTEL_XVMC 177fa225cbcSrjs OPTION_XVMC, 178fa225cbcSrjs#endif 179fa225cbcSrjs OPTION_PREFER_OVERLAY, 180fa225cbcSrjs} I830Opts; 181fa225cbcSrjs 182fa225cbcSrjsstatic OptionInfoRec I830Options[] = { 183fa225cbcSrjs {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, TRUE}, 184fa225cbcSrjs {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, 185fa225cbcSrjs {OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE}, 186fa225cbcSrjs {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE}, 187fa225cbcSrjs {OPTION_FALLBACKDEBUG, "FallbackDebug", OPTV_BOOLEAN, {0}, FALSE}, 188fa225cbcSrjs {OPTION_LVDS24BITMODE, "LVDS24Bit", OPTV_BOOLEAN, {0}, FALSE}, 189fa225cbcSrjs {OPTION_FBC, "FramebufferCompression", OPTV_BOOLEAN, {0}, TRUE}, 190fa225cbcSrjs {OPTION_TILING, "Tiling", OPTV_BOOLEAN, {0}, TRUE}, 191fa225cbcSrjs {OPTION_SWAPBUFFERS_WAIT, "SwapbuffersWait", OPTV_BOOLEAN, {0}, TRUE}, 192fa225cbcSrjs {OPTION_LVDSFIXEDMODE, "LVDSFixedMode", OPTV_BOOLEAN, {0}, FALSE}, 193fa225cbcSrjs {OPTION_FORCEENABLEPIPEA, "ForceEnablePipeA", OPTV_BOOLEAN, {0}, FALSE}, 194fa225cbcSrjs#ifdef INTEL_XVMC 195fa225cbcSrjs {OPTION_XVMC, "XvMC", OPTV_BOOLEAN, {0}, TRUE}, 196fa225cbcSrjs#endif 197fa225cbcSrjs {OPTION_PREFER_OVERLAY, "XvPreferOverlay", OPTV_BOOLEAN, {0}, FALSE}, 198fa225cbcSrjs {-1, NULL, OPTV_NONE, {0}, FALSE} 199fa225cbcSrjs}; 200fa225cbcSrjs/* *INDENT-ON* */ 201fa225cbcSrjs 202fa225cbcSrjsstatic void i830AdjustFrame(int scrnIndex, int x, int y, int flags); 203fa225cbcSrjsstatic Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen); 204fa225cbcSrjsstatic Bool I830EnterVT(int scrnIndex, int flags); 205fa225cbcSrjsstatic Bool SaveHWState(ScrnInfoPtr pScrn); 206fa225cbcSrjsstatic Bool RestoreHWState(ScrnInfoPtr pScrn); 207fa225cbcSrjs 208fa225cbcSrjs/* temporary */ 209fa225cbcSrjsextern void xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y); 210fa225cbcSrjs 211fa225cbcSrjs#ifdef I830DEBUG 212fa225cbcSrjsvoid 213fa225cbcSrjsI830DPRINTF(const char *filename, int line, const char *function, 214fa225cbcSrjs const char *fmt, ...) 215fa225cbcSrjs{ 216fa225cbcSrjs va_list ap; 217fa225cbcSrjs 218fa225cbcSrjs ErrorF("\n##############################################\n" 219fa225cbcSrjs "*** In function %s, on line %d, in file %s ***\n", 220fa225cbcSrjs function, line, filename); 221fa225cbcSrjs va_start(ap, fmt); 222fa225cbcSrjs VErrorF(fmt, ap); 223fa225cbcSrjs va_end(ap); 224fa225cbcSrjs ErrorF("##############################################\n\n"); 225fa225cbcSrjs} 226fa225cbcSrjs#endif /* #ifdef I830DEBUG */ 227fa225cbcSrjs 228fa225cbcSrjs/* Export I830 options to i830 driver where necessary */ 229fa225cbcSrjsconst OptionInfoRec * 230fa225cbcSrjsI830AvailableOptions(int chipid, int busid) 231fa225cbcSrjs{ 232fa225cbcSrjs int i; 233fa225cbcSrjs 234fa225cbcSrjs for (i = 0; I830PciChipsets[i].PCIid > 0; i++) { 235fa225cbcSrjs if (chipid == I830PciChipsets[i].PCIid) 236fa225cbcSrjs return I830Options; 237fa225cbcSrjs } 238fa225cbcSrjs return NULL; 239fa225cbcSrjs} 240fa225cbcSrjs 241fa225cbcSrjsstatic Bool 242fa225cbcSrjsI830GetRec(ScrnInfoPtr pScrn) 243fa225cbcSrjs{ 244fa225cbcSrjs I830Ptr pI830; 245fa225cbcSrjs 246fa225cbcSrjs if (pScrn->driverPrivate) 247fa225cbcSrjs return TRUE; 248fa225cbcSrjs pI830 = pScrn->driverPrivate = xnfcalloc(sizeof(I830Rec), 1); 249fa225cbcSrjs return TRUE; 250fa225cbcSrjs} 251fa225cbcSrjs 252fa225cbcSrjsstatic void 253fa225cbcSrjsI830FreeRec(ScrnInfoPtr pScrn) 254fa225cbcSrjs{ 255fa225cbcSrjs I830Ptr pI830; 256fa225cbcSrjs 257fa225cbcSrjs if (!pScrn) 258fa225cbcSrjs return; 259fa225cbcSrjs if (!pScrn->driverPrivate) 260fa225cbcSrjs return; 261fa225cbcSrjs 262fa225cbcSrjs pI830 = I830PTR(pScrn); 263fa225cbcSrjs 264fa225cbcSrjs xfree(pScrn->driverPrivate); 265fa225cbcSrjs pScrn->driverPrivate = NULL; 266fa225cbcSrjs} 267fa225cbcSrjs 268fa225cbcSrjsstatic int 269fa225cbcSrjsI830DetectMemory(ScrnInfoPtr pScrn) 270fa225cbcSrjs{ 271fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 272fa225cbcSrjs uint16_t gmch_ctrl; 273fa225cbcSrjs int memsize = 0, gtt_size; 274fa225cbcSrjs int range; 275fa225cbcSrjs struct pci_device *bridge = intel_host_bridge (); 276fa225cbcSrjs pci_device_cfg_read_u16(bridge, & gmch_ctrl, I830_GMCH_CTRL); 277fa225cbcSrjs 278fa225cbcSrjs if (IS_I965G(pI830)) { 279fa225cbcSrjs /* The 965 may have a GTT that is actually larger than is necessary 280fa225cbcSrjs * to cover the aperture, so check the hardware's reporting of the 281fa225cbcSrjs * GTT size. 282fa225cbcSrjs */ 283fa225cbcSrjs switch (INREG(PGETBL_CTL) & PGETBL_SIZE_MASK) { 284fa225cbcSrjs case PGETBL_SIZE_512KB: 285fa225cbcSrjs gtt_size = 512; 286fa225cbcSrjs break; 287fa225cbcSrjs case PGETBL_SIZE_256KB: 288fa225cbcSrjs gtt_size = 256; 289fa225cbcSrjs break; 290fa225cbcSrjs case PGETBL_SIZE_128KB: 291fa225cbcSrjs gtt_size = 128; 292fa225cbcSrjs break; 293fa225cbcSrjs case PGETBL_SIZE_1MB: 294fa225cbcSrjs gtt_size = 1024; 295fa225cbcSrjs break; 296fa225cbcSrjs case PGETBL_SIZE_2MB: 297fa225cbcSrjs gtt_size = 2048; 298fa225cbcSrjs break; 299fa225cbcSrjs case PGETBL_SIZE_1_5MB: 300fa225cbcSrjs gtt_size = 1024 + 512; 301fa225cbcSrjs break; 302fa225cbcSrjs default: 303fa225cbcSrjs FatalError("Unknown GTT size value: %08x\n", (int)INREG(PGETBL_CTL)); 304fa225cbcSrjs } 305fa225cbcSrjs } else if (IS_G33CLASS(pI830)) { 306fa225cbcSrjs /* G33's GTT size is detect in GMCH_CTRL */ 307fa225cbcSrjs switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { 308fa225cbcSrjs case G33_PGETBL_SIZE_1M: 309fa225cbcSrjs gtt_size = 1024; 310fa225cbcSrjs break; 311fa225cbcSrjs case G33_PGETBL_SIZE_2M: 312fa225cbcSrjs gtt_size = 2048; 313fa225cbcSrjs break; 314fa225cbcSrjs default: 315fa225cbcSrjs FatalError("Unknown GTT size value: %08x\n", 316fa225cbcSrjs (int)(gmch_ctrl & G33_PGETBL_SIZE_MASK)); 317fa225cbcSrjs } 318fa225cbcSrjs } else { 319fa225cbcSrjs /* Older chipsets only had GTT appropriately sized for the aperture. */ 320fa225cbcSrjs gtt_size = pI830->FbMapSize / (1024*1024); 321fa225cbcSrjs } 322fa225cbcSrjs 323fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "detected %d kB GTT.\n", gtt_size); 324fa225cbcSrjs 325fa225cbcSrjs /* The stolen memory has the GTT at the top, and the 4KB popup below that. 326fa225cbcSrjs * Everything else can be freely used by the graphics driver. 327fa225cbcSrjs */ 328fa225cbcSrjs range = gtt_size + 4; 329fa225cbcSrjs 330fa225cbcSrjs /* new 4 series hardware has seperate GTT stolen with GFX stolen */ 331fa225cbcSrjs if (IS_G4X(pI830) || IS_IGD(pI830) || IS_IGDNG(pI830)) 332fa225cbcSrjs range = 4; 333fa225cbcSrjs 334fa225cbcSrjs if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) { 335fa225cbcSrjs switch (gmch_ctrl & I855_GMCH_GMS_MASK) { 336fa225cbcSrjs case I855_GMCH_GMS_STOLEN_1M: 337fa225cbcSrjs memsize = MB(1) - KB(range); 338fa225cbcSrjs break; 339fa225cbcSrjs case I855_GMCH_GMS_STOLEN_4M: 340fa225cbcSrjs memsize = MB(4) - KB(range); 341fa225cbcSrjs break; 342fa225cbcSrjs case I855_GMCH_GMS_STOLEN_8M: 343fa225cbcSrjs memsize = MB(8) - KB(range); 344fa225cbcSrjs break; 345fa225cbcSrjs case I855_GMCH_GMS_STOLEN_16M: 346fa225cbcSrjs memsize = MB(16) - KB(range); 347fa225cbcSrjs break; 348fa225cbcSrjs case I855_GMCH_GMS_STOLEN_32M: 349fa225cbcSrjs memsize = MB(32) - KB(range); 350fa225cbcSrjs break; 351fa225cbcSrjs case I915G_GMCH_GMS_STOLEN_48M: 352fa225cbcSrjs if (IS_I9XX(pI830)) 353fa225cbcSrjs memsize = MB(48) - KB(range); 354fa225cbcSrjs break; 355fa225cbcSrjs case I915G_GMCH_GMS_STOLEN_64M: 356fa225cbcSrjs if (IS_I9XX(pI830)) 357fa225cbcSrjs memsize = MB(64) - KB(range); 358fa225cbcSrjs break; 359fa225cbcSrjs case G33_GMCH_GMS_STOLEN_128M: 360fa225cbcSrjs if (IS_I9XX(pI830)) 361fa225cbcSrjs memsize = MB(128) - KB(range); 362fa225cbcSrjs break; 363fa225cbcSrjs case G33_GMCH_GMS_STOLEN_256M: 364fa225cbcSrjs if (IS_I9XX(pI830)) 365fa225cbcSrjs memsize = MB(256) - KB(range); 366fa225cbcSrjs break; 367fa225cbcSrjs case INTEL_GMCH_GMS_STOLEN_96M: 368fa225cbcSrjs if (IS_I9XX(pI830)) 369fa225cbcSrjs memsize = MB(96) - KB(range); 370fa225cbcSrjs break; 371fa225cbcSrjs case INTEL_GMCH_GMS_STOLEN_160M: 372fa225cbcSrjs if (IS_I9XX(pI830)) 373fa225cbcSrjs memsize = MB(160) - KB(range); 374fa225cbcSrjs break; 375fa225cbcSrjs case INTEL_GMCH_GMS_STOLEN_224M: 376fa225cbcSrjs if (IS_I9XX(pI830)) 377fa225cbcSrjs memsize = MB(224) - KB(range); 378fa225cbcSrjs break; 379fa225cbcSrjs case INTEL_GMCH_GMS_STOLEN_352M: 380fa225cbcSrjs if (IS_I9XX(pI830)) 381fa225cbcSrjs memsize = MB(352) - KB(range); 382fa225cbcSrjs break; 383fa225cbcSrjs } 384fa225cbcSrjs } else { 385fa225cbcSrjs switch (gmch_ctrl & I830_GMCH_GMS_MASK) { 386fa225cbcSrjs case I830_GMCH_GMS_STOLEN_512: 387fa225cbcSrjs memsize = KB(512) - KB(range); 388fa225cbcSrjs break; 389fa225cbcSrjs case I830_GMCH_GMS_STOLEN_1024: 390fa225cbcSrjs memsize = MB(1) - KB(range); 391fa225cbcSrjs break; 392fa225cbcSrjs case I830_GMCH_GMS_STOLEN_8192: 393fa225cbcSrjs memsize = MB(8) - KB(range); 394fa225cbcSrjs break; 395fa225cbcSrjs case I830_GMCH_GMS_LOCAL: 396fa225cbcSrjs memsize = 0; 397fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 398fa225cbcSrjs "Local memory found, but won't be used.\n"); 399fa225cbcSrjs break; 400fa225cbcSrjs } 401fa225cbcSrjs } 402fa225cbcSrjs 403fa225cbcSrjs#if 0 404fa225cbcSrjs /* And 64KB page aligned */ 405fa225cbcSrjs memsize &= ~0xFFFF; 406fa225cbcSrjs#endif 407fa225cbcSrjs 408fa225cbcSrjs if (memsize > 0) { 409fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, 410fa225cbcSrjs "detected %d kB stolen memory.\n", memsize / 1024); 411fa225cbcSrjs } else { 412fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n"); 413fa225cbcSrjs } 414fa225cbcSrjs 415fa225cbcSrjs return memsize; 416fa225cbcSrjs} 417fa225cbcSrjs 418fa225cbcSrjsstatic Bool 419fa225cbcSrjsI830MapMMIO(ScrnInfoPtr pScrn) 420fa225cbcSrjs{ 421fa225cbcSrjs int err; 422fa225cbcSrjs struct pci_device *device; 423fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 424fa225cbcSrjs 425fa225cbcSrjs device = pI830->PciInfo; 426fa225cbcSrjs err = pci_device_map_range (device, 427fa225cbcSrjs pI830->MMIOAddr, 428fa225cbcSrjs pI830->MMIOSize, 429fa225cbcSrjs PCI_DEV_MAP_FLAG_WRITABLE, 430fa225cbcSrjs (void **) &pI830->MMIOBase); 431fa225cbcSrjs if (err) 432fa225cbcSrjs { 433fa225cbcSrjs xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 434fa225cbcSrjs "Unable to map mmio range. %s (%d)\n", 435fa225cbcSrjs strerror (err), err); 436fa225cbcSrjs return FALSE; 437fa225cbcSrjs } 438fa225cbcSrjs 439fa225cbcSrjs /* Set up the GTT mapping for the various places it has been moved over 440fa225cbcSrjs * time. 441fa225cbcSrjs */ 442fa225cbcSrjs if (IS_I9XX(pI830)) { 443fa225cbcSrjs uint32_t gttaddr; 444fa225cbcSrjs 445fa225cbcSrjs if (IS_I965G(pI830)) 446fa225cbcSrjs { 447fa225cbcSrjs if (IS_G4X(pI830) || IS_IGDNG(pI830)) { 448fa225cbcSrjs gttaddr = pI830->MMIOAddr + MB(2); 449fa225cbcSrjs pI830->GTTMapSize = MB(2); 450fa225cbcSrjs } else { 451fa225cbcSrjs gttaddr = pI830->MMIOAddr + KB(512); 452fa225cbcSrjs pI830->GTTMapSize = KB(512); 453fa225cbcSrjs } 454fa225cbcSrjs } 455fa225cbcSrjs else 456fa225cbcSrjs { 457fa225cbcSrjs gttaddr = I810_MEMBASE(pI830->PciInfo, 3) & 0xFFFFFF00; 458fa225cbcSrjs pI830->GTTMapSize = pI830->FbMapSize / 1024; 459fa225cbcSrjs } 460fa225cbcSrjs err = pci_device_map_range (device, 461fa225cbcSrjs gttaddr, pI830->GTTMapSize, 462fa225cbcSrjs PCI_DEV_MAP_FLAG_WRITABLE, 463fa225cbcSrjs (void **) &pI830->GTTBase); 464fa225cbcSrjs if (err) 465fa225cbcSrjs { 466fa225cbcSrjs xf86DrvMsg (pScrn->scrnIndex, X_ERROR, 467fa225cbcSrjs "Unable to map GTT range. %s (%d)\n", 468fa225cbcSrjs strerror (err), err); 469fa225cbcSrjs return FALSE; 470fa225cbcSrjs } 471fa225cbcSrjs } else { 472fa225cbcSrjs /* The GTT aperture on i830 is write-only. We could probably map the 473fa225cbcSrjs * actual physical pages that back it, but leave it alone for now. 474fa225cbcSrjs */ 475fa225cbcSrjs pI830->GTTBase = NULL; 476fa225cbcSrjs pI830->GTTMapSize = 0; 477fa225cbcSrjs } 478fa225cbcSrjs 479fa225cbcSrjs return TRUE; 480fa225cbcSrjs} 481fa225cbcSrjs 482fa225cbcSrjsstatic Bool 483fa225cbcSrjsI830MapMem(ScrnInfoPtr pScrn) 484fa225cbcSrjs{ 485fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 486fa225cbcSrjs long i; 487fa225cbcSrjs struct pci_device *const device = pI830->PciInfo; 488fa225cbcSrjs int err; 489fa225cbcSrjs 490fa225cbcSrjs for (i = 2; i < pI830->FbMapSize; i <<= 1) ; 491fa225cbcSrjs pI830->FbMapSize = i; 492fa225cbcSrjs 493fa225cbcSrjs err = pci_device_map_range (device, pI830->LinearAddr, pI830->FbMapSize, 494fa225cbcSrjs PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE, 495fa225cbcSrjs (void **) &pI830->FbBase); 496fa225cbcSrjs if (err) 497fa225cbcSrjs return FALSE; 498fa225cbcSrjs 499fa225cbcSrjs if (pI830->ring.mem != NULL) { 500fa225cbcSrjs pI830->ring.virtual_start = pI830->FbBase + pI830->ring.mem->offset; 501fa225cbcSrjs } 502fa225cbcSrjs 503fa225cbcSrjs return TRUE; 504fa225cbcSrjs} 505fa225cbcSrjs 506fa225cbcSrjsstatic void 507fa225cbcSrjsI830UnmapMMIO(ScrnInfoPtr pScrn) 508fa225cbcSrjs{ 509fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 510fa225cbcSrjs 511fa225cbcSrjs pci_device_unmap_range (pI830->PciInfo, pI830->MMIOBase, pI830->MMIOSize); 512fa225cbcSrjs pI830->MMIOBase = NULL; 513fa225cbcSrjs 514fa225cbcSrjs if (IS_I9XX(pI830)) { 515fa225cbcSrjs pci_device_unmap_range (pI830->PciInfo, pI830->GTTBase, pI830->GTTMapSize); 516fa225cbcSrjs pI830->GTTBase = NULL; 517fa225cbcSrjs } 518fa225cbcSrjs} 519fa225cbcSrjs 520fa225cbcSrjsstatic Bool 521fa225cbcSrjsI830UnmapMem(ScrnInfoPtr pScrn) 522fa225cbcSrjs{ 523fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 524fa225cbcSrjs 525fa225cbcSrjs pci_device_unmap_range (pI830->PciInfo, pI830->FbBase, pI830->FbMapSize); 526fa225cbcSrjs pI830->FbBase = NULL; 527fa225cbcSrjs I830UnmapMMIO(pScrn); 528fa225cbcSrjs return TRUE; 529fa225cbcSrjs} 530fa225cbcSrjs 531fa225cbcSrjsstatic void 532fa225cbcSrjsI830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 533fa225cbcSrjs LOCO * colors, VisualPtr pVisual) 534fa225cbcSrjs{ 535fa225cbcSrjs xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 536fa225cbcSrjs int i,j, index; 537fa225cbcSrjs int p; 538fa225cbcSrjs uint16_t lut_r[256], lut_g[256], lut_b[256]; 539fa225cbcSrjs 540fa225cbcSrjs DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors); 541fa225cbcSrjs 542fa225cbcSrjs for(p = 0; p < xf86_config->num_crtc; p++) { 543fa225cbcSrjs xf86CrtcPtr crtc = xf86_config->crtc[p]; 544fa225cbcSrjs I830CrtcPrivatePtr intel_crtc = crtc->driver_private; 545fa225cbcSrjs 546fa225cbcSrjs /* Initialize to the old lookup table values. */ 547fa225cbcSrjs for (i = 0; i < 256; i++) { 548fa225cbcSrjs lut_r[i] = intel_crtc->lut_r[i] << 8; 549fa225cbcSrjs lut_g[i] = intel_crtc->lut_g[i] << 8; 550fa225cbcSrjs lut_b[i] = intel_crtc->lut_b[i] << 8; 551fa225cbcSrjs } 552fa225cbcSrjs 553fa225cbcSrjs switch(pScrn->depth) { 554fa225cbcSrjs case 15: 555fa225cbcSrjs for (i = 0; i < numColors; i++) { 556fa225cbcSrjs index = indices[i]; 557fa225cbcSrjs for (j = 0; j < 8; j++) { 558fa225cbcSrjs lut_r[index * 8 + j] = colors[index].red << 8; 559fa225cbcSrjs lut_g[index * 8 + j] = colors[index].green << 8; 560fa225cbcSrjs lut_b[index * 8 + j] = colors[index].blue << 8; 561fa225cbcSrjs } 562fa225cbcSrjs } 563fa225cbcSrjs break; 564fa225cbcSrjs case 16: 565fa225cbcSrjs for (i = 0; i < numColors; i++) { 566fa225cbcSrjs index = indices[i]; 567fa225cbcSrjs 568fa225cbcSrjs if (index <= 31) { 569fa225cbcSrjs for (j = 0; j < 8; j++) { 570fa225cbcSrjs lut_r[index * 8 + j] = colors[index].red << 8; 571fa225cbcSrjs lut_b[index * 8 + j] = colors[index].blue << 8; 572fa225cbcSrjs } 573fa225cbcSrjs } 574fa225cbcSrjs 575fa225cbcSrjs for (j = 0; j < 4; j++) { 576fa225cbcSrjs lut_g[index * 4 + j] = colors[index].green << 8; 577fa225cbcSrjs } 578fa225cbcSrjs } 579fa225cbcSrjs break; 580fa225cbcSrjs default: 581fa225cbcSrjs for (i = 0; i < numColors; i++) { 582fa225cbcSrjs index = indices[i]; 583fa225cbcSrjs lut_r[index] = colors[index].red << 8; 584fa225cbcSrjs lut_g[index] = colors[index].green << 8; 585fa225cbcSrjs lut_b[index] = colors[index].blue << 8; 586fa225cbcSrjs } 587fa225cbcSrjs break; 588fa225cbcSrjs } 589fa225cbcSrjs 590fa225cbcSrjs /* Make the change through RandR */ 591fa225cbcSrjs#ifdef RANDR_12_INTERFACE 592fa225cbcSrjs RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); 593fa225cbcSrjs#else 594fa225cbcSrjs crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); 595fa225cbcSrjs#endif 596fa225cbcSrjs } 597fa225cbcSrjs} 598fa225cbcSrjs 599fa225cbcSrjs/** 600fa225cbcSrjs * Adjust the screen pixmap for the current location of the front buffer. 601fa225cbcSrjs * This is done at EnterVT when buffers are bound as long as the resources 602fa225cbcSrjs * have already been created, but the first EnterVT happens before 603fa225cbcSrjs * CreateScreenResources. 604fa225cbcSrjs */ 605fa225cbcSrjsstatic Bool 606fa225cbcSrjsi830CreateScreenResources(ScreenPtr pScreen) 607fa225cbcSrjs{ 608fa225cbcSrjs ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 609fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 610fa225cbcSrjs 611fa225cbcSrjs pScreen->CreateScreenResources = pI830->CreateScreenResources; 612fa225cbcSrjs if (!(*pScreen->CreateScreenResources)(pScreen)) 613fa225cbcSrjs return FALSE; 614fa225cbcSrjs 615fa225cbcSrjs i830_uxa_create_screen_resources(pScreen); 616fa225cbcSrjs 617fa225cbcSrjs return TRUE; 618fa225cbcSrjs} 619fa225cbcSrjs 620fa225cbcSrjsstatic int 621fa225cbcSrjsi830_output_clones (ScrnInfoPtr pScrn, int type_mask) 622fa225cbcSrjs{ 623fa225cbcSrjs xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); 624fa225cbcSrjs int o; 625fa225cbcSrjs int index_mask = 0; 626fa225cbcSrjs 627fa225cbcSrjs for (o = 0; o < config->num_output; o++) 628fa225cbcSrjs { 629fa225cbcSrjs xf86OutputPtr output = config->output[o]; 630fa225cbcSrjs I830OutputPrivatePtr intel_output = output->driver_private; 631fa225cbcSrjs if (type_mask & (1 << intel_output->type)) 632fa225cbcSrjs index_mask |= (1 << o); 633fa225cbcSrjs } 634fa225cbcSrjs return index_mask; 635fa225cbcSrjs} 636fa225cbcSrjs 637fa225cbcSrjs/** 638fa225cbcSrjs * Set up the outputs according to what type of chip we are. 639fa225cbcSrjs * 640fa225cbcSrjs * Some outputs may not initialize, due to allocation failure or because a 641fa225cbcSrjs * controller chip isn't found. 642fa225cbcSrjs */ 643fa225cbcSrjsstatic void 644fa225cbcSrjsI830SetupOutputs(ScrnInfoPtr pScrn) 645fa225cbcSrjs{ 646fa225cbcSrjs xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); 647fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 648fa225cbcSrjs int o, c; 649fa225cbcSrjs Bool lvds_detected = FALSE; 650fa225cbcSrjs 651fa225cbcSrjs /* everyone has at least a single analog output */ 652fa225cbcSrjs i830_crt_init(pScrn); 653fa225cbcSrjs 654fa225cbcSrjs /* Set up integrated LVDS */ 655fa225cbcSrjs if (IS_MOBILE(pI830) && !IS_I830(pI830)) 656fa225cbcSrjs i830_lvds_init(pScrn); 657fa225cbcSrjs 658fa225cbcSrjs if (IS_I9XX(pI830)) { 659fa225cbcSrjs Bool found = FALSE; 660fa225cbcSrjs if ((INREG(SDVOB) & SDVO_DETECTED)) { 661fa225cbcSrjs found = i830_sdvo_init(pScrn, SDVOB); 662fa225cbcSrjs 663fa225cbcSrjs if (!found && SUPPORTS_INTEGRATED_HDMI(pI830)) 664fa225cbcSrjs i830_hdmi_init(pScrn, SDVOB); 665fa225cbcSrjs } 666fa225cbcSrjs 667fa225cbcSrjs if ((INREG(SDVOB) & SDVO_DETECTED)) 668fa225cbcSrjs found = i830_sdvo_init(pScrn, SDVOC); 669fa225cbcSrjs 670fa225cbcSrjs if ((INREG(SDVOC) & SDVO_DETECTED) && 671fa225cbcSrjs !found && SUPPORTS_INTEGRATED_HDMI(pI830)) 672fa225cbcSrjs i830_hdmi_init(pScrn, SDVOC); 673fa225cbcSrjs 674fa225cbcSrjs } else { 675fa225cbcSrjs i830_dvo_init(pScrn); 676fa225cbcSrjs } 677fa225cbcSrjs if (IS_I9XX(pI830) && IS_MOBILE(pI830)) 678fa225cbcSrjs i830_tv_init(pScrn); 679fa225cbcSrjs 680fa225cbcSrjs for (o = 0; o < config->num_output; o++) 681fa225cbcSrjs { 682fa225cbcSrjs xf86OutputPtr output = config->output[o]; 683fa225cbcSrjs I830OutputPrivatePtr intel_output = output->driver_private; 684fa225cbcSrjs int crtc_mask; 685fa225cbcSrjs 686fa225cbcSrjs if (intel_output->type == I830_OUTPUT_LVDS) 687fa225cbcSrjs lvds_detected = TRUE; 688fa225cbcSrjs 689fa225cbcSrjs crtc_mask = 0; 690fa225cbcSrjs for (c = 0; c < config->num_crtc; c++) 691fa225cbcSrjs { 692fa225cbcSrjs xf86CrtcPtr crtc = config->crtc[c]; 693fa225cbcSrjs I830CrtcPrivatePtr intel_crtc = crtc->driver_private; 694fa225cbcSrjs 695fa225cbcSrjs if (intel_output->pipe_mask & (1 << intel_crtc->pipe)) 696fa225cbcSrjs crtc_mask |= (1 << c); 697fa225cbcSrjs } 698fa225cbcSrjs output->possible_crtcs = crtc_mask; 699fa225cbcSrjs output->possible_clones = i830_output_clones (pScrn, intel_output->clone_mask); 700fa225cbcSrjs } 701fa225cbcSrjs} 702fa225cbcSrjs 703fa225cbcSrjsstatic void 704fa225cbcSrjsi830_init_clock_gating(ScrnInfoPtr pScrn) 705fa225cbcSrjs{ 706fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 707fa225cbcSrjs 708fa225cbcSrjs /* Disable clock gating reported to work incorrectly according to the specs. 709fa225cbcSrjs */ 710fa225cbcSrjs if (IS_G4X(pI830)) { 711fa225cbcSrjs uint32_t dspclk_gate; 712fa225cbcSrjs OUTREG(RENCLK_GATE_D1, 0); 713fa225cbcSrjs OUTREG(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE | 714fa225cbcSrjs GS_UNIT_CLOCK_GATE_DISABLE | 715fa225cbcSrjs CL_UNIT_CLOCK_GATE_DISABLE); 716fa225cbcSrjs OUTREG(RAMCLK_GATE_D, 0); 717fa225cbcSrjs dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | 718fa225cbcSrjs OVRUNIT_CLOCK_GATE_DISABLE | 719fa225cbcSrjs OVCUNIT_CLOCK_GATE_DISABLE; 720fa225cbcSrjs if (IS_GM45(pI830)) 721fa225cbcSrjs dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; 722fa225cbcSrjs OUTREG(DSPCLK_GATE_D, dspclk_gate); 723fa225cbcSrjs } else if (IS_I965GM(pI830)) { 724fa225cbcSrjs OUTREG(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); 725fa225cbcSrjs OUTREG(RENCLK_GATE_D2, 0); 726fa225cbcSrjs OUTREG(DSPCLK_GATE_D, 0); 727fa225cbcSrjs OUTREG(RAMCLK_GATE_D, 0); 728fa225cbcSrjs OUTREG16(DEUC, 0); 729fa225cbcSrjs } else if (IS_I965G(pI830)) { 730fa225cbcSrjs OUTREG(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | 731fa225cbcSrjs I965_RCC_CLOCK_GATE_DISABLE | 732fa225cbcSrjs I965_RCPB_CLOCK_GATE_DISABLE | 733fa225cbcSrjs I965_ISC_CLOCK_GATE_DISABLE | 734fa225cbcSrjs I965_FBC_CLOCK_GATE_DISABLE); 735fa225cbcSrjs OUTREG(RENCLK_GATE_D2, 0); 736fa225cbcSrjs } else if (IS_I855(pI830) || IS_I865G(pI830)) { 737fa225cbcSrjs OUTREG(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE); 738fa225cbcSrjs } else if (IS_I830(pI830)) { 739fa225cbcSrjs OUTREG(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); 740fa225cbcSrjs } 741fa225cbcSrjs} 742fa225cbcSrjs 743fa225cbcSrjsstatic void 744fa225cbcSrjsi830_init_bios_control(ScrnInfoPtr pScrn) 745fa225cbcSrjs{ 746fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 747fa225cbcSrjs 748fa225cbcSrjs /* Set "extended desktop" */ 749fa225cbcSrjs OUTREG(SWF0, INREG(SWF0) | (1 << 21)); 750fa225cbcSrjs 751fa225cbcSrjs /* Set "driver loaded", "OS unknown", "APM 1.2" */ 752fa225cbcSrjs OUTREG(SWF4, (INREG(SWF4) & ~((3 << 19) | (7 << 16))) | 753fa225cbcSrjs (1 << 23) | (2 << 16)); 754fa225cbcSrjs} 755fa225cbcSrjs 756fa225cbcSrjsstatic int 757fa225cbcSrjsI830LVDSPresent(ScrnInfoPtr pScrn) 758fa225cbcSrjs{ 759fa225cbcSrjs xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); 760fa225cbcSrjs int o, lvds_detected = FALSE; 761fa225cbcSrjs 762fa225cbcSrjs for (o = 0; o < config->num_output; o++) { 763fa225cbcSrjs xf86OutputPtr output = config->output[o]; 764fa225cbcSrjs I830OutputPrivatePtr intel_output = output->driver_private; 765fa225cbcSrjs 766fa225cbcSrjs if (intel_output->type == I830_OUTPUT_LVDS) 767fa225cbcSrjs lvds_detected = TRUE; 768fa225cbcSrjs } 769fa225cbcSrjs 770fa225cbcSrjs return lvds_detected; 771fa225cbcSrjs} 772fa225cbcSrjs/** 773fa225cbcSrjs * Setup the CRTCs 774fa225cbcSrjs */ 775fa225cbcSrjs 776fa225cbcSrjs 777fa225cbcSrjsstatic void 778fa225cbcSrjsI830PreInitDDC(ScrnInfoPtr pScrn) 779fa225cbcSrjs{ 780fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 781fa225cbcSrjs 782fa225cbcSrjs if (!xf86LoadSubModule(pScrn, "ddc")) { 783fa225cbcSrjs pI830->ddc2 = FALSE; 784fa225cbcSrjs } else { 785fa225cbcSrjs pI830->ddc2 = TRUE; 786fa225cbcSrjs } 787fa225cbcSrjs 788fa225cbcSrjs /* DDC can use I2C bus */ 789fa225cbcSrjs /* Load I2C if we have the code to use it */ 790fa225cbcSrjs if (pI830->ddc2) { 791fa225cbcSrjs if (xf86LoadSubModule(pScrn, "i2c")) { 792fa225cbcSrjs pI830->ddc2 = TRUE; 793fa225cbcSrjs } else { 794fa225cbcSrjs pI830->ddc2 = FALSE; 795fa225cbcSrjs } 796fa225cbcSrjs } 797fa225cbcSrjs} 798fa225cbcSrjs 799fa225cbcSrjsstatic void 800fa225cbcSrjsPreInitCleanup(ScrnInfoPtr pScrn) 801fa225cbcSrjs{ 802fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 803fa225cbcSrjs 804fa225cbcSrjs if (pI830->MMIOBase) 805fa225cbcSrjs I830UnmapMMIO(pScrn); 806fa225cbcSrjs I830FreeRec(pScrn); 807fa225cbcSrjs} 808fa225cbcSrjs 809fa225cbcSrjs/* 810fa225cbcSrjs * Adjust *width to allow for tiling if possible 811fa225cbcSrjs */ 812fa225cbcSrjsBool 813fa225cbcSrjsi830_tiled_width(I830Ptr i830, int *width, int cpp) 814fa225cbcSrjs{ 815fa225cbcSrjs Bool tiled = FALSE; 816fa225cbcSrjs 817fa225cbcSrjs /* 818fa225cbcSrjs * Adjust the display width to allow for front buffer tiling if possible 819fa225cbcSrjs */ 820fa225cbcSrjs if (i830->tiling) { 821fa225cbcSrjs if (IS_I965G(i830)) { 822fa225cbcSrjs int tile_pixels = 512 / cpp; 823fa225cbcSrjs *width = (*width + tile_pixels - 1) & 824fa225cbcSrjs ~(tile_pixels - 1); 825fa225cbcSrjs tiled = TRUE; 826fa225cbcSrjs } else { 827fa225cbcSrjs /* Good pitches to allow tiling. Don't care about pitches < 1024 828fa225cbcSrjs * pixels. 829fa225cbcSrjs */ 830fa225cbcSrjs static const int pitches[] = { 831fa225cbcSrjs 1024, 832fa225cbcSrjs 2048, 833fa225cbcSrjs 4096, 834fa225cbcSrjs 8192, 835fa225cbcSrjs 0 836fa225cbcSrjs }; 837fa225cbcSrjs int i; 838fa225cbcSrjs 839fa225cbcSrjs for (i = 0; pitches[i] != 0; i++) { 840fa225cbcSrjs if (pitches[i] >= *width) { 841fa225cbcSrjs *width = pitches[i]; 842fa225cbcSrjs tiled = TRUE; 843fa225cbcSrjs break; 844fa225cbcSrjs } 845fa225cbcSrjs } 846fa225cbcSrjs } 847fa225cbcSrjs } 848fa225cbcSrjs return tiled; 849fa225cbcSrjs} 850fa225cbcSrjs 851fa225cbcSrjs/* 852fa225cbcSrjs * Pad to accelerator requirement 853fa225cbcSrjs */ 854fa225cbcSrjsint 855fa225cbcSrjsi830_pad_drawable_width(int width, int cpp) 856fa225cbcSrjs{ 857fa225cbcSrjs return (width + 63) & ~63; 858fa225cbcSrjs} 859fa225cbcSrjs 860fa225cbcSrjsstatic Bool 861fa225cbcSrjsi830_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) 862fa225cbcSrjs{ 863fa225cbcSrjs#ifdef DRI2 864fa225cbcSrjs I830Ptr i830 = I830PTR(scrn); 865fa225cbcSrjs int old_width = scrn->displayWidth; 866fa225cbcSrjs#endif 867fa225cbcSrjs int old_x = scrn->virtualX; 868fa225cbcSrjs int old_y = scrn->virtualY; 869fa225cbcSrjs 870fa225cbcSrjs if (old_x == width && old_y == height) 871fa225cbcSrjs return TRUE; 872fa225cbcSrjs 873fa225cbcSrjs scrn->virtualX = width; 874fa225cbcSrjs scrn->virtualY = height; 875fa225cbcSrjs#ifdef DRI2 876fa225cbcSrjs if (i830->front_buffer) 877fa225cbcSrjs { 878fa225cbcSrjs i830_memory *new_front, *old_front; 879fa225cbcSrjs Bool tiled; 880fa225cbcSrjs ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; 881fa225cbcSrjs 882fa225cbcSrjs scrn->displayWidth = i830_pad_drawable_width(width, i830->cpp); 883fa225cbcSrjs tiled = i830_tiled_width(i830, &scrn->displayWidth, i830->cpp); 884fa225cbcSrjs xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocate new frame buffer %dx%d stride %d\n", 885fa225cbcSrjs width, height, scrn->displayWidth); 886fa225cbcSrjs I830Sync(scrn); 887fa225cbcSrjs i830WaitForVblank(scrn); 888fa225cbcSrjs new_front = i830_allocate_framebuffer(scrn); 889fa225cbcSrjs if (!new_front) { 890fa225cbcSrjs scrn->virtualX = old_x; 891fa225cbcSrjs scrn->virtualY = old_y; 892fa225cbcSrjs scrn->displayWidth = old_width; 893fa225cbcSrjs return FALSE; 894fa225cbcSrjs } 895fa225cbcSrjs old_front = i830->front_buffer; 896fa225cbcSrjs i830->front_buffer = new_front; 897fa225cbcSrjs i830_set_pixmap_bo(screen->GetScreenPixmap(screen), 898fa225cbcSrjs new_front->bo); 899fa225cbcSrjs scrn->fbOffset = i830->front_buffer->offset; 900fa225cbcSrjs 901fa225cbcSrjs screen->ModifyPixmapHeader(screen->GetScreenPixmap(screen), 902fa225cbcSrjs width, height, -1, -1, scrn->displayWidth * i830->cpp, 903fa225cbcSrjs i830->FbBase + scrn->fbOffset); 904fa225cbcSrjs 905fa225cbcSrjs /* ick. xf86EnableDisableFBAccess smashes the screen pixmap devPrivate, 906fa225cbcSrjs * so update the value it uses 907fa225cbcSrjs */ 908fa225cbcSrjs scrn->pixmapPrivate.ptr = i830->FbBase + scrn->fbOffset; 909fa225cbcSrjs xf86DrvMsg(scrn->scrnIndex, X_INFO, "New front buffer at 0x%lx\n", 910fa225cbcSrjs i830->front_buffer->offset); 911fa225cbcSrjs i830_set_new_crtc_bo(scrn); 912fa225cbcSrjs I830Sync(scrn); 913fa225cbcSrjs i830WaitForVblank(scrn); 914fa225cbcSrjs i830_free_memory(scrn, old_front); 915fa225cbcSrjs } 916fa225cbcSrjs#endif 917fa225cbcSrjs return TRUE; 918fa225cbcSrjs} 919fa225cbcSrjs 920fa225cbcSrjsstatic const xf86CrtcConfigFuncsRec i830_xf86crtc_config_funcs = { 921fa225cbcSrjs i830_xf86crtc_resize 922fa225cbcSrjs}; 923fa225cbcSrjs 924fa225cbcSrjs#define HOTKEY_BIOS_SWITCH 0 925fa225cbcSrjs#define HOTKEY_DRIVER_NOTIFY 1 926fa225cbcSrjs 927fa225cbcSrjs/** 928fa225cbcSrjs * Controls the BIOS's behavior on hotkey switch. 929fa225cbcSrjs * 930fa225cbcSrjs * If the mode is HOTKEY_BIOS_SWITCH, the BIOS will be set to do a mode switch 931fa225cbcSrjs * on its own and update the state in the scratch register. 932fa225cbcSrjs * If the mode is HOTKEY_DRIVER_NOTIFY, the BIOS won't do a mode switch and 933fa225cbcSrjs * will just update the state to represent what it would have been switched to. 934fa225cbcSrjs */ 935fa225cbcSrjsstatic void 936fa225cbcSrjsi830SetHotkeyControl(ScrnInfoPtr pScrn, int mode) 937fa225cbcSrjs{ 938fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 939fa225cbcSrjs uint8_t gr18; 940fa225cbcSrjs 941fa225cbcSrjs /* Don't mess with kernel settings... */ 942fa225cbcSrjs if (pI830->use_drm_mode) 943fa225cbcSrjs return; 944fa225cbcSrjs 945fa225cbcSrjs gr18 = pI830->readControl(pI830, GRX, 0x18); 946fa225cbcSrjs if (mode == HOTKEY_BIOS_SWITCH) 947fa225cbcSrjs gr18 &= ~HOTKEY_VBIOS_SWITCH_BLOCK; 948fa225cbcSrjs else 949fa225cbcSrjs gr18 |= HOTKEY_VBIOS_SWITCH_BLOCK; 950fa225cbcSrjs pI830->writeControl(pI830, GRX, 0x18, gr18); 951fa225cbcSrjs} 952fa225cbcSrjs 953fa225cbcSrjs/* 954fa225cbcSrjs * DRM mode setting Linux only at this point... later on we could 955fa225cbcSrjs * add a wrapper here. 956fa225cbcSrjs */ 957fa225cbcSrjsstatic Bool i830_kernel_mode_enabled(ScrnInfoPtr pScrn) 958fa225cbcSrjs{ 959fa225cbcSrjs struct pci_device *PciInfo; 960fa225cbcSrjs EntityInfoPtr pEnt; 961fa225cbcSrjs char *busIdString; 962fa225cbcSrjs int ret; 963fa225cbcSrjs 964fa225cbcSrjs pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 965fa225cbcSrjs PciInfo = xf86GetPciInfoForEntity(pEnt->index); 966fa225cbcSrjs 967fa225cbcSrjs if (!xf86LoaderCheckSymbol("DRICreatePCIBusID")) 968fa225cbcSrjs return FALSE; 969fa225cbcSrjs 970fa225cbcSrjs busIdString = DRICreatePCIBusID(PciInfo); 971fa225cbcSrjs 972fa225cbcSrjs ret = drmCheckModesettingSupported(busIdString); 973fa225cbcSrjs if (ret) { 974fa225cbcSrjs if (xf86LoadKernelModule("i915")) 975fa225cbcSrjs ret = drmCheckModesettingSupported(busIdString); 976fa225cbcSrjs } 977fa225cbcSrjs /* Be nice to the user and load fbcon too */ 978fa225cbcSrjs if (!ret) 979fa225cbcSrjs (void) xf86LoadKernelModule("fbcon"); 980fa225cbcSrjs xfree(busIdString); 981fa225cbcSrjs if (ret) 982fa225cbcSrjs return FALSE; 983fa225cbcSrjs 984fa225cbcSrjs return TRUE; 985fa225cbcSrjs} 986fa225cbcSrjs 987fa225cbcSrjsstatic Bool 988fa225cbcSrjsi830_detect_chipset(ScrnInfoPtr pScrn) 989fa225cbcSrjs{ 990fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 991fa225cbcSrjs MessageType from = X_PROBED; 992fa225cbcSrjs const char *chipname; 993fa225cbcSrjs uint32_t capid; 994fa225cbcSrjs int fb_bar, mmio_bar; 995fa225cbcSrjs 996fa225cbcSrjs 997fa225cbcSrjs /* We have to use PIO to probe, because we haven't mapped yet. */ 998fa225cbcSrjs if (!pI830->use_drm_mode) 999fa225cbcSrjs I830SetPIOAccess(pI830); 1000fa225cbcSrjs 1001fa225cbcSrjs switch (DEVICE_ID(pI830->PciInfo)) { 1002fa225cbcSrjs case PCI_CHIP_I830_M: 1003fa225cbcSrjs chipname = "830M"; 1004fa225cbcSrjs break; 1005fa225cbcSrjs case PCI_CHIP_845_G: 1006fa225cbcSrjs chipname = "845G"; 1007fa225cbcSrjs break; 1008fa225cbcSrjs case PCI_CHIP_I855_GM: 1009fa225cbcSrjs /* Check capid register to find the chipset variant */ 1010fa225cbcSrjs pci_device_cfg_read_u32 (pI830->PciInfo, &capid, I85X_CAPID); 1011fa225cbcSrjs pI830->variant = (capid >> I85X_VARIANT_SHIFT) & I85X_VARIANT_MASK; 1012fa225cbcSrjs switch (pI830->variant) { 1013fa225cbcSrjs case I855_GM: 1014fa225cbcSrjs chipname = "855GM"; 1015fa225cbcSrjs break; 1016fa225cbcSrjs case I855_GME: 1017fa225cbcSrjs chipname = "855GME"; 1018fa225cbcSrjs break; 1019fa225cbcSrjs case I852_GM: 1020fa225cbcSrjs chipname = "852GM"; 1021fa225cbcSrjs break; 1022fa225cbcSrjs case I852_GME: 1023fa225cbcSrjs chipname = "852GME"; 1024fa225cbcSrjs break; 1025fa225cbcSrjs default: 1026fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1027fa225cbcSrjs "Unknown 852GM/855GM variant: 0x%x)\n", pI830->variant); 1028fa225cbcSrjs chipname = "852GM/855GM (unknown variant)"; 1029fa225cbcSrjs break; 1030fa225cbcSrjs } 1031fa225cbcSrjs break; 1032fa225cbcSrjs case PCI_CHIP_I865_G: 1033fa225cbcSrjs chipname = "865G"; 1034fa225cbcSrjs break; 1035fa225cbcSrjs case PCI_CHIP_I915_G: 1036fa225cbcSrjs chipname = "915G"; 1037fa225cbcSrjs break; 1038fa225cbcSrjs case PCI_CHIP_E7221_G: 1039fa225cbcSrjs chipname = "E7221 (i915)"; 1040fa225cbcSrjs break; 1041fa225cbcSrjs case PCI_CHIP_I915_GM: 1042fa225cbcSrjs chipname = "915GM"; 1043fa225cbcSrjs break; 1044fa225cbcSrjs case PCI_CHIP_I945_G: 1045fa225cbcSrjs chipname = "945G"; 1046fa225cbcSrjs break; 1047fa225cbcSrjs case PCI_CHIP_I945_GM: 1048fa225cbcSrjs chipname = "945GM"; 1049fa225cbcSrjs break; 1050fa225cbcSrjs case PCI_CHIP_I945_GME: 1051fa225cbcSrjs chipname = "945GME"; 1052fa225cbcSrjs break; 1053fa225cbcSrjs case PCI_CHIP_IGD_GM: 1054fa225cbcSrjs chipname = "Pineview GM"; 1055fa225cbcSrjs break; 1056fa225cbcSrjs case PCI_CHIP_IGD_G: 1057fa225cbcSrjs chipname = "Pineview G"; 1058fa225cbcSrjs break; 1059fa225cbcSrjs case PCI_CHIP_I965_G: 1060fa225cbcSrjs chipname = "965G"; 1061fa225cbcSrjs break; 1062fa225cbcSrjs case PCI_CHIP_G35_G: 1063fa225cbcSrjs chipname = "G35"; 1064fa225cbcSrjs break; 1065fa225cbcSrjs case PCI_CHIP_I965_Q: 1066fa225cbcSrjs chipname = "965Q"; 1067fa225cbcSrjs break; 1068fa225cbcSrjs case PCI_CHIP_I946_GZ: 1069fa225cbcSrjs chipname = "946GZ"; 1070fa225cbcSrjs break; 1071fa225cbcSrjs case PCI_CHIP_I965_GM: 1072fa225cbcSrjs chipname = "965GM"; 1073fa225cbcSrjs break; 1074fa225cbcSrjs case PCI_CHIP_I965_GME: 1075fa225cbcSrjs chipname = "965GME/GLE"; 1076fa225cbcSrjs break; 1077fa225cbcSrjs case PCI_CHIP_G33_G: 1078fa225cbcSrjs chipname = "G33"; 1079fa225cbcSrjs break; 1080fa225cbcSrjs case PCI_CHIP_Q35_G: 1081fa225cbcSrjs chipname = "Q35"; 1082fa225cbcSrjs break; 1083fa225cbcSrjs case PCI_CHIP_Q33_G: 1084fa225cbcSrjs chipname = "Q33"; 1085fa225cbcSrjs break; 1086fa225cbcSrjs case PCI_CHIP_GM45_GM: 1087fa225cbcSrjs chipname = "GM45"; 1088fa225cbcSrjs break; 1089fa225cbcSrjs case PCI_CHIP_IGD_E_G: 1090fa225cbcSrjs chipname = "4 Series"; 1091fa225cbcSrjs break; 1092fa225cbcSrjs case PCI_CHIP_G45_G: 1093fa225cbcSrjs chipname = "G45/G43"; 1094fa225cbcSrjs break; 1095fa225cbcSrjs case PCI_CHIP_Q45_G: 1096fa225cbcSrjs chipname = "Q45/Q43"; 1097fa225cbcSrjs break; 1098fa225cbcSrjs case PCI_CHIP_G41_G: 1099fa225cbcSrjs chipname = "G41"; 1100fa225cbcSrjs break; 1101fa225cbcSrjs case PCI_CHIP_B43_G: 1102fa225cbcSrjs chipname = "B43"; 1103fa225cbcSrjs break; 1104fa225cbcSrjs case PCI_CHIP_IGDNG_D_G: 1105fa225cbcSrjs chipname = "Clarkdale"; 1106fa225cbcSrjs break; 1107fa225cbcSrjs case PCI_CHIP_IGDNG_M_G: 1108fa225cbcSrjs chipname = "Arrandale"; 1109fa225cbcSrjs break; 1110fa225cbcSrjs default: 1111fa225cbcSrjs chipname = "unknown chipset"; 1112fa225cbcSrjs break; 1113fa225cbcSrjs } 1114fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1115fa225cbcSrjs "Integrated Graphics Chipset: Intel(R) %s\n", chipname); 1116fa225cbcSrjs 1117fa225cbcSrjs /* Set the Chipset and ChipRev, allowing config file entries to override. */ 1118fa225cbcSrjs if (pI830->pEnt->device->chipset && *pI830->pEnt->device->chipset) { 1119fa225cbcSrjs pScrn->chipset = pI830->pEnt->device->chipset; 1120fa225cbcSrjs from = X_CONFIG; 1121fa225cbcSrjs } else if (pI830->pEnt->device->chipID >= 0) { 1122fa225cbcSrjs pScrn->chipset = (char *)xf86TokenToString(I830Chipsets, 1123fa225cbcSrjs pI830->pEnt->device->chipID); 1124fa225cbcSrjs from = X_CONFIG; 1125fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 1126fa225cbcSrjs pI830->pEnt->device->chipID); 1127fa225cbcSrjs DEVICE_ID(pI830->PciInfo) = pI830->pEnt->device->chipID; 1128fa225cbcSrjs } else { 1129fa225cbcSrjs from = X_PROBED; 1130fa225cbcSrjs pScrn->chipset = (char *)xf86TokenToString(I830Chipsets, 1131fa225cbcSrjs DEVICE_ID(pI830->PciInfo)); 1132fa225cbcSrjs } 1133fa225cbcSrjs 1134fa225cbcSrjs if (pI830->pEnt->device->chipRev >= 0) { 1135fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 1136fa225cbcSrjs pI830->pEnt->device->chipRev); 1137fa225cbcSrjs } 1138fa225cbcSrjs 1139fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", 1140fa225cbcSrjs (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i8xx"); 1141fa225cbcSrjs 1142fa225cbcSrjs /* Check if the HW cursor needs physical address. */ 1143fa225cbcSrjs if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 1144fa225cbcSrjs pI830->CursorNeedsPhysical = TRUE; 1145fa225cbcSrjs else 1146fa225cbcSrjs pI830->CursorNeedsPhysical = FALSE; 1147fa225cbcSrjs 1148fa225cbcSrjs if (IS_I965G(pI830) || IS_G33CLASS(pI830)) 1149fa225cbcSrjs pI830->CursorNeedsPhysical = FALSE; 1150fa225cbcSrjs 1151fa225cbcSrjs /* Skip the rest if the kernel is taking care of things */ 1152fa225cbcSrjs if (pI830->use_drm_mode) 1153fa225cbcSrjs return TRUE; 1154fa225cbcSrjs 1155fa225cbcSrjs /* Now that we know the chipset, figure out the resource base addrs */ 1156fa225cbcSrjs if (IS_I9XX(pI830)) { 1157fa225cbcSrjs fb_bar = 2; 1158fa225cbcSrjs mmio_bar = 0; 1159fa225cbcSrjs } else { 1160fa225cbcSrjs fb_bar = 0; 1161fa225cbcSrjs mmio_bar = 1; 1162fa225cbcSrjs } 1163fa225cbcSrjs 1164fa225cbcSrjs if (pI830->pEnt->device->MemBase != 0) { 1165fa225cbcSrjs pI830->LinearAddr = pI830->pEnt->device->MemBase; 1166fa225cbcSrjs from = X_CONFIG; 1167fa225cbcSrjs } else { 1168fa225cbcSrjs pI830->LinearAddr = I810_MEMBASE (pI830->PciInfo, fb_bar); 1169fa225cbcSrjs if (pI830->LinearAddr == 0) { 1170fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1171fa225cbcSrjs "No valid FB address in PCI config space\n"); 1172fa225cbcSrjs PreInitCleanup(pScrn); 1173fa225cbcSrjs return FALSE; 1174fa225cbcSrjs } 1175fa225cbcSrjs } 1176fa225cbcSrjs 1177fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 1178fa225cbcSrjs (unsigned long)pI830->LinearAddr); 1179fa225cbcSrjs 1180fa225cbcSrjs if (pI830->pEnt->device->IOBase != 0) { 1181fa225cbcSrjs pI830->MMIOAddr = pI830->pEnt->device->IOBase; 1182fa225cbcSrjs from = X_CONFIG; 1183fa225cbcSrjs pI830->MMIOSize = I810_REG_SIZE; 1184fa225cbcSrjs } else { 1185fa225cbcSrjs pI830->MMIOAddr = I810_MEMBASE (pI830->PciInfo, mmio_bar); 1186fa225cbcSrjs if (pI830->MMIOAddr == 0) { 1187fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1188fa225cbcSrjs "No valid MMIO address in PCI config space\n"); 1189fa225cbcSrjs PreInitCleanup(pScrn); 1190fa225cbcSrjs return FALSE; 1191fa225cbcSrjs } 1192fa225cbcSrjs pI830->MMIOSize = pI830->PciInfo->regions[mmio_bar].size; 1193fa225cbcSrjs } 1194fa225cbcSrjs 1195fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX size %u\n", 1196fa225cbcSrjs (unsigned long)pI830->MMIOAddr, pI830->MMIOSize); 1197fa225cbcSrjs 1198fa225cbcSrjs /* Now figure out mapsize on 8xx chips */ 1199fa225cbcSrjs if (IS_I830(pI830) || IS_845G(pI830)) { 1200fa225cbcSrjs uint16_t gmch_ctrl; 1201fa225cbcSrjs struct pci_device *bridge; 1202fa225cbcSrjs 1203fa225cbcSrjs bridge = intel_host_bridge (); 1204fa225cbcSrjs pci_device_cfg_read_u16 (bridge, &gmch_ctrl, I830_GMCH_CTRL); 1205fa225cbcSrjs if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { 1206fa225cbcSrjs pI830->FbMapSize = 0x8000000; 1207fa225cbcSrjs } else { 1208fa225cbcSrjs pI830->FbMapSize = 0x4000000; /* 64MB - has this been tested ?? */ 1209fa225cbcSrjs } 1210fa225cbcSrjs } else { 1211fa225cbcSrjs if (IS_I9XX(pI830)) { 1212fa225cbcSrjs pI830->FbMapSize = pI830->PciInfo->regions[fb_bar].size; 1213fa225cbcSrjs } else { 1214fa225cbcSrjs /* 128MB aperture for later i8xx series. */ 1215fa225cbcSrjs pI830->FbMapSize = 0x8000000; 1216fa225cbcSrjs } 1217fa225cbcSrjs } 1218fa225cbcSrjs 1219fa225cbcSrjs return TRUE; 1220fa225cbcSrjs} 1221fa225cbcSrjs 1222fa225cbcSrjsstatic Bool 1223fa225cbcSrjsI830LoadSyms(ScrnInfoPtr pScrn) 1224fa225cbcSrjs{ 1225fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 1226fa225cbcSrjs 1227fa225cbcSrjs if (pI830->use_drm_mode) 1228fa225cbcSrjs return TRUE; 1229fa225cbcSrjs 1230fa225cbcSrjs /* The vgahw module should be loaded here when needed */ 1231fa225cbcSrjs if (!xf86LoadSubModule(pScrn, "vgahw")) 1232fa225cbcSrjs return FALSE; 1233fa225cbcSrjs 1234fa225cbcSrjs if (!xf86LoadSubModule(pScrn, "ramdac")) 1235fa225cbcSrjs return FALSE; 1236fa225cbcSrjs 1237fa225cbcSrjs return TRUE; 1238fa225cbcSrjs} 1239fa225cbcSrjs 1240fa225cbcSrjsstatic Bool 1241fa225cbcSrjsI830GetEarlyOptions(ScrnInfoPtr pScrn) 1242fa225cbcSrjs{ 1243fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 1244fa225cbcSrjs 1245fa225cbcSrjs /* Process the options */ 1246fa225cbcSrjs xf86CollectOptions(pScrn, NULL); 1247fa225cbcSrjs if (!(pI830->Options = xalloc(sizeof(I830Options)))) 1248fa225cbcSrjs return FALSE; 1249fa225cbcSrjs memcpy(pI830->Options, I830Options, sizeof(I830Options)); 1250fa225cbcSrjs xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI830->Options); 1251fa225cbcSrjs 1252fa225cbcSrjs pI830->fallback_debug = xf86ReturnOptValBool(pI830->Options, 1253fa225cbcSrjs OPTION_FALLBACKDEBUG, FALSE); 1254fa225cbcSrjs 1255fa225cbcSrjs if (xf86ReturnOptValBool(pI830->Options, OPTION_MODEDEBUG, FALSE)) { 1256fa225cbcSrjs pI830->debug_modes = TRUE; 1257fa225cbcSrjs } else { 1258fa225cbcSrjs pI830->debug_modes = FALSE; 1259fa225cbcSrjs } 1260fa225cbcSrjs 1261fa225cbcSrjs if (xf86ReturnOptValBool(pI830->Options, OPTION_LVDS24BITMODE, FALSE)) { 1262fa225cbcSrjs pI830->lvds_24_bit_mode = TRUE; 1263fa225cbcSrjs } else { 1264fa225cbcSrjs pI830->lvds_24_bit_mode = FALSE; 1265fa225cbcSrjs } 1266fa225cbcSrjs 1267fa225cbcSrjs if (xf86ReturnOptValBool(pI830->Options, OPTION_LVDSFIXEDMODE, TRUE)) { 1268fa225cbcSrjs pI830->skip_panel_detect = FALSE; 1269fa225cbcSrjs } else { 1270fa225cbcSrjs pI830->skip_panel_detect = TRUE; 1271fa225cbcSrjs } 1272fa225cbcSrjs 1273fa225cbcSrjs if (xf86ReturnOptValBool(pI830->Options, OPTION_FORCEENABLEPIPEA, FALSE)) 1274fa225cbcSrjs pI830->quirk_flag |= QUIRK_PIPEA_FORCE; 1275fa225cbcSrjs 1276fa225cbcSrjs return TRUE; 1277fa225cbcSrjs} 1278fa225cbcSrjs 1279fa225cbcSrjsstatic void 1280fa225cbcSrjsI830PreInitCrtcConfig(ScrnInfoPtr pScrn) 1281fa225cbcSrjs{ 1282fa225cbcSrjs xf86CrtcConfigPtr xf86_config; 1283fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 1284fa225cbcSrjs int max_width, max_height; 1285fa225cbcSrjs 1286fa225cbcSrjs /* check quirks */ 1287fa225cbcSrjs i830_fixup_devices(pScrn); 1288fa225cbcSrjs 1289fa225cbcSrjs /* Allocate an xf86CrtcConfig */ 1290fa225cbcSrjs xf86CrtcConfigInit (pScrn, &i830_xf86crtc_config_funcs); 1291fa225cbcSrjs xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1292fa225cbcSrjs 1293fa225cbcSrjs /* See i830_exa.c comments for why we limit the framebuffer size like this. 1294fa225cbcSrjs */ 1295fa225cbcSrjs if (IS_I965G(pI830)) { 1296fa225cbcSrjs max_height = max_width = min(16384 / pI830->cpp, 8192); 1297fa225cbcSrjs } else { 1298fa225cbcSrjs max_width = 2048; 1299fa225cbcSrjs max_height = 2048; 1300fa225cbcSrjs } 1301fa225cbcSrjs xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, max_height); 1302fa225cbcSrjs} 1303fa225cbcSrjs 1304fa225cbcSrjsstatic void 1305fa225cbcSrjsi830_check_dri_option(ScrnInfoPtr pScrn) 1306fa225cbcSrjs{ 1307fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 1308fa225cbcSrjs pI830->directRenderingType = DRI_NONE; 1309fa225cbcSrjs if (!xf86ReturnOptValBool(pI830->Options, OPTION_DRI, TRUE)) 1310fa225cbcSrjs pI830->directRenderingType = DRI_DISABLED; 1311fa225cbcSrjs 1312fa225cbcSrjs if (pScrn->depth != 16 && pScrn->depth != 24) { 1313fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it " 1314fa225cbcSrjs "runs only at depths 16 and 24.\n"); 1315fa225cbcSrjs pI830->directRenderingType = DRI_DISABLED; 1316fa225cbcSrjs } 1317fa225cbcSrjs} 1318fa225cbcSrjs 1319fa225cbcSrjsstatic Bool 1320fa225cbcSrjsi830_user_modesetting_init(ScrnInfoPtr pScrn) 1321fa225cbcSrjs{ 1322fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 1323fa225cbcSrjs int i, num_pipe; 1324fa225cbcSrjs 1325fa225cbcSrjs I830MapMMIO(pScrn); 1326fa225cbcSrjs 1327fa225cbcSrjs if (pI830->debug_modes) { 1328fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1329fa225cbcSrjs "Hardware state on X startup:\n"); 1330fa225cbcSrjs i830DumpRegs (pScrn); 1331fa225cbcSrjs } 1332fa225cbcSrjs 1333fa225cbcSrjs i830TakeRegSnapshot(pScrn); 1334fa225cbcSrjs 1335fa225cbcSrjs if (DEVICE_ID(pI830->PciInfo) == PCI_CHIP_E7221_G) 1336fa225cbcSrjs num_pipe = 1; 1337fa225cbcSrjs else 1338fa225cbcSrjs if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 1339fa225cbcSrjs num_pipe = 2; 1340fa225cbcSrjs else 1341fa225cbcSrjs num_pipe = 1; 1342fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n", 1343fa225cbcSrjs num_pipe, num_pipe > 1 ? "s" : ""); 1344fa225cbcSrjs 1345fa225cbcSrjs I830PreInitDDC(pScrn); 1346fa225cbcSrjs for (i = 0; i < num_pipe; i++) { 1347fa225cbcSrjs i830_crtc_init(pScrn, i); 1348fa225cbcSrjs } 1349fa225cbcSrjs I830SetupOutputs(pScrn); 1350fa225cbcSrjs 1351fa225cbcSrjs SaveHWState(pScrn); 1352fa225cbcSrjs 1353fa225cbcSrjs if (!xf86InitialConfiguration (pScrn, TRUE)) 1354fa225cbcSrjs { 1355fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); 1356fa225cbcSrjs RestoreHWState(pScrn); 1357fa225cbcSrjs PreInitCleanup(pScrn); 1358fa225cbcSrjs return FALSE; 1359fa225cbcSrjs } 1360fa225cbcSrjs RestoreHWState(pScrn); 1361fa225cbcSrjs 1362fa225cbcSrjs pI830->stolen_size = I830DetectMemory(pScrn); 1363fa225cbcSrjs 1364fa225cbcSrjs return TRUE; 1365fa225cbcSrjs} 1366fa225cbcSrjs 1367fa225cbcSrjsstatic Bool 1368fa225cbcSrjsi830_open_drm_master(ScrnInfoPtr scrn) 1369fa225cbcSrjs{ 1370fa225cbcSrjs I830Ptr i830 = I830PTR(scrn); 1371fa225cbcSrjs struct pci_device *dev = i830->PciInfo; 1372fa225cbcSrjs char *busid; 1373fa225cbcSrjs drmSetVersion sv; 1374fa225cbcSrjs struct drm_i915_getparam gp; 1375fa225cbcSrjs int err, has_gem; 1376fa225cbcSrjs 1377fa225cbcSrjs /* We wish we had asprintf, but all we get is XNFprintf. */ 1378fa225cbcSrjs busid = XNFprintf("pci:%04x:%02x:%02x.%d", 1379fa225cbcSrjs dev->domain, dev->bus, dev->dev, dev->func); 1380fa225cbcSrjs 1381fa225cbcSrjs i830->drmSubFD = drmOpen("i915", busid); 1382fa225cbcSrjs if (i830->drmSubFD == -1) { 1383fa225cbcSrjs xfree(busid); 1384fa225cbcSrjs xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1385fa225cbcSrjs "[drm] Failed to open DRM device for %s: %s\n", busid, 1386fa225cbcSrjs strerror(errno)); 1387fa225cbcSrjs return FALSE; 1388fa225cbcSrjs } 1389fa225cbcSrjs 1390fa225cbcSrjs xfree(busid); 1391fa225cbcSrjs 1392fa225cbcSrjs /* Check that what we opened was a master or a master-capable FD, 1393fa225cbcSrjs * by setting the version of the interface we'll use to talk to it. 1394fa225cbcSrjs * (see DRIOpenDRMMaster() in DRI1) 1395fa225cbcSrjs */ 1396fa225cbcSrjs sv.drm_di_major = 1; 1397fa225cbcSrjs sv.drm_di_minor = 1; 1398fa225cbcSrjs sv.drm_dd_major = -1; 1399fa225cbcSrjs sv.drm_dd_minor = -1; 1400fa225cbcSrjs err = drmSetInterfaceVersion(i830->drmSubFD, &sv); 1401fa225cbcSrjs if (err != 0) { 1402fa225cbcSrjs xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1403fa225cbcSrjs "[drm] failed to set drm interface version.\n"); 1404fa225cbcSrjs drmClose(i830->drmSubFD); 1405fa225cbcSrjs i830->drmSubFD = -1; 1406fa225cbcSrjs return FALSE; 1407fa225cbcSrjs } 1408fa225cbcSrjs 1409fa225cbcSrjs has_gem = FALSE; 1410fa225cbcSrjs gp.param = I915_PARAM_HAS_GEM; 1411fa225cbcSrjs gp.value = &has_gem; 1412fa225cbcSrjs (void)drmCommandWriteRead(i830->drmSubFD, DRM_I915_GETPARAM, 1413fa225cbcSrjs &gp, sizeof(gp)); 1414fa225cbcSrjs if (!has_gem) { 1415fa225cbcSrjs xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1416fa225cbcSrjs "[drm] Failed to detect GEM. Kernel 2.6.28 required.\n"); 1417fa225cbcSrjs drmClose(i830->drmSubFD); 1418fa225cbcSrjs i830->drmSubFD = -1; 1419fa225cbcSrjs return FALSE; 1420fa225cbcSrjs } 1421fa225cbcSrjs 1422fa225cbcSrjs return TRUE; 1423fa225cbcSrjs} 1424fa225cbcSrjs 1425fa225cbcSrjsstatic void 1426fa225cbcSrjsi830_close_drm_master(ScrnInfoPtr scrn) 1427fa225cbcSrjs{ 1428fa225cbcSrjs I830Ptr i830 = I830PTR(scrn); 1429fa225cbcSrjs if (i830 && i830->drmSubFD > 0) { 1430fa225cbcSrjs drmClose(i830->drmSubFD); 1431fa225cbcSrjs i830->drmSubFD = -1; 1432fa225cbcSrjs } 1433fa225cbcSrjs} 1434fa225cbcSrjs 1435fa225cbcSrjsstatic Bool 1436fa225cbcSrjsI830DrmModeInit(ScrnInfoPtr pScrn) 1437fa225cbcSrjs{ 1438fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 1439fa225cbcSrjs 1440fa225cbcSrjs if (drmmode_pre_init(pScrn, pI830->drmSubFD, pI830->cpp) == FALSE) { 1441fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1442fa225cbcSrjs "Kernel modesetting setup failed\n"); 1443fa225cbcSrjs PreInitCleanup(pScrn); 1444fa225cbcSrjs return FALSE; 1445fa225cbcSrjs } 1446fa225cbcSrjs 1447fa225cbcSrjs pI830->have_gem = TRUE; 1448fa225cbcSrjs 1449fa225cbcSrjs i830_init_bufmgr(pScrn); 1450fa225cbcSrjs 1451fa225cbcSrjs return TRUE; 1452fa225cbcSrjs} 1453fa225cbcSrjs 1454fa225cbcSrjsstatic void 1455fa225cbcSrjsI830XvInit(ScrnInfoPtr pScrn) 1456fa225cbcSrjs{ 1457fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 1458fa225cbcSrjs MessageType from = X_PROBED; 1459fa225cbcSrjs 1460fa225cbcSrjs pI830->XvPreferOverlay = xf86ReturnOptValBool(pI830->Options, OPTION_PREFER_OVERLAY, FALSE); 1461fa225cbcSrjs 1462fa225cbcSrjs if (xf86GetOptValInteger(pI830->Options, OPTION_VIDEO_KEY, 1463fa225cbcSrjs &(pI830->colorKey))) { 1464fa225cbcSrjs from = X_CONFIG; 1465fa225cbcSrjs } else if (xf86GetOptValInteger(pI830->Options, OPTION_COLOR_KEY, 1466fa225cbcSrjs &(pI830->colorKey))) { 1467fa225cbcSrjs from = X_CONFIG; 1468fa225cbcSrjs } else { 1469fa225cbcSrjs pI830->colorKey = 1470fa225cbcSrjs (1 << pScrn->offset.red) | (1 << pScrn->offset.green) | 1471fa225cbcSrjs (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << 1472fa225cbcSrjs pScrn->offset.blue); 1473fa225cbcSrjs from = X_DEFAULT; 1474fa225cbcSrjs } 1475fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, from, "video overlay key set to 0x%x\n", 1476fa225cbcSrjs pI830->colorKey); 1477fa225cbcSrjs} 1478fa225cbcSrjs 1479fa225cbcSrjs/** 1480fa225cbcSrjs * This is called before ScreenInit to do any require probing of screen 1481fa225cbcSrjs * configuration. 1482fa225cbcSrjs * 1483fa225cbcSrjs * This code generally covers probing, module loading, option handling 1484fa225cbcSrjs * card mapping, and RandR setup. 1485fa225cbcSrjs * 1486fa225cbcSrjs * Since xf86InitialConfiguration ends up requiring that we set video modes 1487fa225cbcSrjs * in order to detect configuration, we end up having to do a lot of driver 1488fa225cbcSrjs * setup (talking to the DRM, mapping the device, etc.) in this function. 1489fa225cbcSrjs * As a result, we want to set up that server initialization once rather 1490fa225cbcSrjs * that doing it per generation. 1491fa225cbcSrjs */ 1492fa225cbcSrjsstatic Bool 1493fa225cbcSrjsI830PreInit(ScrnInfoPtr pScrn, int flags) 1494fa225cbcSrjs{ 1495fa225cbcSrjs vgaHWPtr hwp; 1496fa225cbcSrjs I830Ptr pI830; 1497fa225cbcSrjs rgb defaultWeight = { 0, 0, 0 }; 1498fa225cbcSrjs EntityInfoPtr pEnt; 1499fa225cbcSrjs int flags24; 1500fa225cbcSrjs Gamma zeros = { 0.0, 0.0, 0.0 }; 1501fa225cbcSrjs int drm_mode_setting; 1502fa225cbcSrjs 1503fa225cbcSrjs if (pScrn->numEntities != 1) 1504fa225cbcSrjs return FALSE; 1505fa225cbcSrjs 1506fa225cbcSrjs drm_mode_setting = i830_kernel_mode_enabled(pScrn); 1507fa225cbcSrjs 1508fa225cbcSrjs pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 1509fa225cbcSrjs 1510fa225cbcSrjs if (flags & PROBE_DETECT) 1511fa225cbcSrjs return TRUE; 1512fa225cbcSrjs 1513fa225cbcSrjs /* Allocate driverPrivate */ 1514fa225cbcSrjs if (!I830GetRec(pScrn)) 1515fa225cbcSrjs return FALSE; 1516fa225cbcSrjs 1517fa225cbcSrjs pI830 = I830PTR(pScrn); 1518fa225cbcSrjs pI830->SaveGeneration = -1; 1519fa225cbcSrjs pI830->pEnt = pEnt; 1520fa225cbcSrjs pI830->use_drm_mode = drm_mode_setting; 1521fa225cbcSrjs pI830->kernel_exec_fencing = pI830->use_drm_mode; 1522fa225cbcSrjs 1523fa225cbcSrjs if (!I830LoadSyms(pScrn)) 1524fa225cbcSrjs return FALSE; 1525fa225cbcSrjs 1526fa225cbcSrjs if (!drm_mode_setting) { 1527fa225cbcSrjs /* Allocate a vgaHWRec */ 1528fa225cbcSrjs if (!vgaHWGetHWRec(pScrn)) 1529fa225cbcSrjs return FALSE; 1530fa225cbcSrjs hwp = VGAHWPTR(pScrn); 1531fa225cbcSrjs } 1532fa225cbcSrjs 1533fa225cbcSrjs pScrn->displayWidth = 640; /* default it */ 1534fa225cbcSrjs 1535fa225cbcSrjs if (pI830->pEnt->location.type != BUS_PCI) 1536fa225cbcSrjs return FALSE; 1537fa225cbcSrjs 1538fa225cbcSrjs pI830->PciInfo = xf86GetPciInfoForEntity(pI830->pEnt->index); 1539fa225cbcSrjs 1540fa225cbcSrjs if (!i830_open_drm_master(pScrn)) 1541fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to become DRM master.\n"); 1542fa225cbcSrjs 1543fa225cbcSrjs pScrn->monitor = pScrn->confScreen->monitor; 1544fa225cbcSrjs pScrn->progClock = TRUE; 1545fa225cbcSrjs pScrn->rgbBits = 8; 1546fa225cbcSrjs 1547fa225cbcSrjs flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32; 1548fa225cbcSrjs 1549fa225cbcSrjs if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) 1550fa225cbcSrjs return FALSE; 1551fa225cbcSrjs 1552fa225cbcSrjs switch (pScrn->depth) { 1553fa225cbcSrjs case 8: 1554fa225cbcSrjs case 15: 1555fa225cbcSrjs case 16: 1556fa225cbcSrjs case 24: 1557fa225cbcSrjs break; 1558fa225cbcSrjs default: 1559fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1560fa225cbcSrjs "Given depth (%d) is not supported by I830 driver\n", 1561fa225cbcSrjs pScrn->depth); 1562fa225cbcSrjs return FALSE; 1563fa225cbcSrjs } 1564fa225cbcSrjs xf86PrintDepthBpp(pScrn); 1565fa225cbcSrjs 1566fa225cbcSrjs if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 1567fa225cbcSrjs return FALSE; 1568fa225cbcSrjs if (!xf86SetDefaultVisual(pScrn, -1)) 1569fa225cbcSrjs return FALSE; 1570fa225cbcSrjs 1571fa225cbcSrjs if (!pI830->use_drm_mode) 1572fa225cbcSrjs hwp = VGAHWPTR(pScrn); 1573fa225cbcSrjs 1574fa225cbcSrjs pI830->cpp = pScrn->bitsPerPixel / 8; 1575fa225cbcSrjs 1576fa225cbcSrjs pI830->preinit = TRUE; 1577fa225cbcSrjs 1578fa225cbcSrjs if (!I830GetEarlyOptions(pScrn)) 1579fa225cbcSrjs return FALSE; 1580fa225cbcSrjs 1581fa225cbcSrjs if (!i830_detect_chipset(pScrn)) 1582fa225cbcSrjs return FALSE; 1583fa225cbcSrjs 1584fa225cbcSrjs i830_check_dri_option(pScrn); 1585fa225cbcSrjs 1586fa225cbcSrjs if (pI830->use_drm_mode) { 1587fa225cbcSrjs if (!I830DrmModeInit(pScrn)) 1588fa225cbcSrjs return FALSE; 1589fa225cbcSrjs } else { 1590fa225cbcSrjs if (i830_bios_init(pScrn)) 1591fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1592fa225cbcSrjs "VBIOS initialization failed.\n"); 1593fa225cbcSrjs I830PreInitCrtcConfig(pScrn); 1594fa225cbcSrjs if (!i830_user_modesetting_init(pScrn)) 1595fa225cbcSrjs return FALSE; 1596fa225cbcSrjs } 1597fa225cbcSrjs 1598fa225cbcSrjs I830XvInit(pScrn); 1599fa225cbcSrjs 1600fa225cbcSrjs if (!xf86SetGamma(pScrn, zeros)) { 1601fa225cbcSrjs PreInitCleanup(pScrn); 1602fa225cbcSrjs return FALSE; 1603fa225cbcSrjs } 1604fa225cbcSrjs 1605fa225cbcSrjs if (pScrn->modes == NULL) { 1606fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); 1607fa225cbcSrjs PreInitCleanup(pScrn); 1608fa225cbcSrjs return FALSE; 1609fa225cbcSrjs } 1610fa225cbcSrjs pScrn->currentMode = pScrn->modes; 1611fa225cbcSrjs 1612fa225cbcSrjs /* Set display resolution */ 1613fa225cbcSrjs xf86SetDpi(pScrn, 0, 0); 1614fa225cbcSrjs 1615fa225cbcSrjs /* Load the required sub modules */ 1616fa225cbcSrjs if (!xf86LoadSubModule(pScrn, "fb")) { 1617fa225cbcSrjs PreInitCleanup(pScrn); 1618fa225cbcSrjs return FALSE; 1619fa225cbcSrjs } 1620fa225cbcSrjs 1621fa225cbcSrjs if (!pI830->use_drm_mode) { 1622fa225cbcSrjs i830CompareRegsToSnapshot(pScrn, "After PreInit"); 1623fa225cbcSrjs 1624fa225cbcSrjs I830UnmapMMIO(pScrn); 1625fa225cbcSrjs 1626fa225cbcSrjs /* We won't be using the VGA access after the probe. */ 1627fa225cbcSrjs I830SetMMIOAccess(pI830); 1628fa225cbcSrjs } 1629fa225cbcSrjs 1630fa225cbcSrjs /* Load the dri2 module if requested. */ 1631fa225cbcSrjs if (xf86ReturnOptValBool(pI830->Options, OPTION_DRI, FALSE) && 1632fa225cbcSrjs pI830->directRenderingType != DRI_DISABLED) { 1633fa225cbcSrjs xf86LoadSubModule(pScrn, "dri2"); 1634fa225cbcSrjs } 1635fa225cbcSrjs 1636fa225cbcSrjs pI830->preinit = FALSE; 1637fa225cbcSrjs 1638fa225cbcSrjs return TRUE; 1639fa225cbcSrjs} 1640fa225cbcSrjs 1641fa225cbcSrjs/* 1642fa225cbcSrjs * Reset registers that it doesn't make sense to save/restore to a sane state. 1643fa225cbcSrjs * This is basically the ring buffer and fence registers. Restoring these 1644fa225cbcSrjs * doesn't make sense without restoring GTT mappings. This is something that 1645fa225cbcSrjs * whoever gets control next should do. 1646fa225cbcSrjs */ 1647fa225cbcSrjsstatic void 1648fa225cbcSrjsi830_stop_ring(ScrnInfoPtr pScrn, Bool flush) 1649fa225cbcSrjs{ 1650fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 1651fa225cbcSrjs unsigned long temp; 1652fa225cbcSrjs 1653fa225cbcSrjs DPRINTF(PFX, "ResetState: flush is %s\n", BOOLTOSTRING(flush)); 1654fa225cbcSrjs 1655fa225cbcSrjs /* Flush the ring buffer, then disable it. */ 1656fa225cbcSrjs temp = INREG(LP_RING + RING_LEN); 1657fa225cbcSrjs if (temp & RING_VALID) { 1658fa225cbcSrjs i830_refresh_ring(pScrn); 1659fa225cbcSrjs i830_wait_ring_idle(pScrn); 1660fa225cbcSrjs } 1661fa225cbcSrjs 1662fa225cbcSrjs OUTREG(LP_RING + RING_LEN, 0); 1663fa225cbcSrjs OUTREG(LP_RING + RING_HEAD, 0); 1664fa225cbcSrjs OUTREG(LP_RING + RING_TAIL, 0); 1665fa225cbcSrjs OUTREG(LP_RING + RING_START, 0); 1666fa225cbcSrjs} 1667fa225cbcSrjs 1668fa225cbcSrjsstatic void 1669fa225cbcSrjsi830_start_ring(ScrnInfoPtr pScrn) 1670fa225cbcSrjs{ 1671fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 1672fa225cbcSrjs unsigned int itemp; 1673fa225cbcSrjs 1674fa225cbcSrjs DPRINTF(PFX, "SetRingRegs\n"); 1675fa225cbcSrjs 1676fa225cbcSrjs OUTREG(LP_RING + RING_LEN, 0); 1677fa225cbcSrjs OUTREG(LP_RING + RING_TAIL, 0); 1678fa225cbcSrjs OUTREG(LP_RING + RING_HEAD, 0); 1679fa225cbcSrjs 1680fa225cbcSrjs assert((pI830->ring.mem->offset & I830_RING_START_MASK) == 1681fa225cbcSrjs pI830->ring.mem->offset); 1682fa225cbcSrjs 1683fa225cbcSrjs /* Don't care about the old value. Reserved bits must be zero anyway. */ 1684fa225cbcSrjs itemp = pI830->ring.mem->offset; 1685fa225cbcSrjs OUTREG(LP_RING + RING_START, itemp); 1686fa225cbcSrjs 1687fa225cbcSrjs if (((pI830->ring.mem->size - 4096) & I830_RING_NR_PAGES) != 1688fa225cbcSrjs pI830->ring.mem->size - 4096) { 1689fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1690fa225cbcSrjs "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its " 1691fa225cbcSrjs "mask (%x)\n", pI830->ring.mem->size - 4096, 1692fa225cbcSrjs I830_RING_NR_PAGES); 1693fa225cbcSrjs } 1694fa225cbcSrjs /* Don't care about the old value. Reserved bits must be zero anyway. */ 1695fa225cbcSrjs itemp = (pI830->ring.mem->size - 4096) & I830_RING_NR_PAGES; 1696fa225cbcSrjs itemp |= (RING_NO_REPORT | RING_VALID); 1697fa225cbcSrjs OUTREG(LP_RING + RING_LEN, itemp); 1698fa225cbcSrjs i830_refresh_ring(pScrn); 1699fa225cbcSrjs} 1700fa225cbcSrjs 1701fa225cbcSrjsvoid 1702fa225cbcSrjsi830_refresh_ring(ScrnInfoPtr pScrn) 1703fa225cbcSrjs{ 1704fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 1705fa225cbcSrjs 1706fa225cbcSrjs /* If we're reaching RefreshRing as a result of grabbing the DRI lock 1707fa225cbcSrjs * before we've set up the ringbuffer, don't bother. 1708fa225cbcSrjs */ 1709fa225cbcSrjs if (pI830->ring.mem == NULL) 1710fa225cbcSrjs return; 1711fa225cbcSrjs 1712fa225cbcSrjs pI830->ring.head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; 1713fa225cbcSrjs pI830->ring.tail = INREG(LP_RING + RING_TAIL); 1714fa225cbcSrjs pI830->ring.space = pI830->ring.head - (pI830->ring.tail + 8); 1715fa225cbcSrjs if (pI830->ring.space < 0) 1716fa225cbcSrjs pI830->ring.space += pI830->ring.mem->size; 1717fa225cbcSrjs} 1718fa225cbcSrjs 1719fa225cbcSrjsenum pipe { 1720fa225cbcSrjs PIPE_A = 0, 1721fa225cbcSrjs PIPE_B, 1722fa225cbcSrjs}; 1723fa225cbcSrjs 1724fa225cbcSrjsstatic Bool 1725fa225cbcSrjsi830_pipe_enabled(I830Ptr pI830, enum pipe pipe) 1726fa225cbcSrjs{ 1727fa225cbcSrjs if (pipe == PIPE_A) 1728fa225cbcSrjs return (INREG(PIPEACONF) & PIPEACONF_ENABLE); 1729fa225cbcSrjs else 1730fa225cbcSrjs return (INREG(PIPEBCONF) & PIPEBCONF_ENABLE); 1731fa225cbcSrjs} 1732fa225cbcSrjs 1733fa225cbcSrjsstatic void 1734fa225cbcSrjsi830_save_palette(I830Ptr pI830, enum pipe pipe) 1735fa225cbcSrjs{ 1736fa225cbcSrjs int i; 1737fa225cbcSrjs 1738fa225cbcSrjs if (!i830_pipe_enabled(pI830, pipe)) 1739fa225cbcSrjs return; 1740fa225cbcSrjs 1741fa225cbcSrjs for(i= 0; i < 256; i++) { 1742fa225cbcSrjs if (pipe == PIPE_A) 1743fa225cbcSrjs pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2)); 1744fa225cbcSrjs else 1745fa225cbcSrjs pI830->savePaletteB[i] = INREG(PALETTE_B + (i << 2)); 1746fa225cbcSrjs } 1747fa225cbcSrjs} 1748fa225cbcSrjs 1749fa225cbcSrjsstatic void 1750fa225cbcSrjsi830_restore_palette(I830Ptr pI830, enum pipe pipe) 1751fa225cbcSrjs{ 1752fa225cbcSrjs int i; 1753fa225cbcSrjs 1754fa225cbcSrjs if (!i830_pipe_enabled(pI830, pipe)) 1755fa225cbcSrjs return; 1756fa225cbcSrjs 1757fa225cbcSrjs for(i= 0; i < 256; i++) { 1758fa225cbcSrjs if (pipe == PIPE_A) 1759fa225cbcSrjs OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]); 1760fa225cbcSrjs else 1761fa225cbcSrjs OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]); 1762fa225cbcSrjs } 1763fa225cbcSrjs} 1764fa225cbcSrjs 1765fa225cbcSrjsstatic Bool 1766fa225cbcSrjsSaveHWState(ScrnInfoPtr pScrn) 1767fa225cbcSrjs{ 1768fa225cbcSrjs xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1769fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 1770fa225cbcSrjs vgaHWPtr hwp = VGAHWPTR(pScrn); 1771fa225cbcSrjs vgaRegPtr vgaReg = &hwp->SavedReg; 1772fa225cbcSrjs int i; 1773fa225cbcSrjs 1774fa225cbcSrjs if (pI830->fb_compression) { 1775fa225cbcSrjs pI830->saveFBC_CFB_BASE = INREG(FBC_CFB_BASE); 1776fa225cbcSrjs pI830->saveFBC_LL_BASE = INREG(FBC_LL_BASE); 1777fa225cbcSrjs pI830->saveFBC_CONTROL2 = INREG(FBC_CONTROL2); 1778fa225cbcSrjs pI830->saveFBC_CONTROL = INREG(FBC_CONTROL); 1779fa225cbcSrjs pI830->saveFBC_FENCE_OFF = INREG(FBC_FENCE_OFF); 1780fa225cbcSrjs } 1781fa225cbcSrjs 1782fa225cbcSrjs /* Save video mode information for native mode-setting. */ 1783fa225cbcSrjs if (!DSPARB_HWCONTROL(pI830)) 1784fa225cbcSrjs pI830->saveDSPARB = INREG(DSPARB); 1785fa225cbcSrjs 1786fa225cbcSrjs pI830->saveDSPACNTR = INREG(DSPACNTR); 1787fa225cbcSrjs pI830->savePIPEACONF = INREG(PIPEACONF); 1788fa225cbcSrjs pI830->savePIPEASRC = INREG(PIPEASRC); 1789fa225cbcSrjs pI830->saveFPA0 = INREG(FPA0); 1790fa225cbcSrjs pI830->saveFPA1 = INREG(FPA1); 1791fa225cbcSrjs pI830->saveDPLL_A = INREG(DPLL_A); 1792fa225cbcSrjs if (IS_I965G(pI830)) 1793fa225cbcSrjs pI830->saveDPLL_A_MD = INREG(DPLL_A_MD); 1794fa225cbcSrjs pI830->saveHTOTAL_A = INREG(HTOTAL_A); 1795fa225cbcSrjs pI830->saveHBLANK_A = INREG(HBLANK_A); 1796fa225cbcSrjs pI830->saveHSYNC_A = INREG(HSYNC_A); 1797fa225cbcSrjs pI830->saveVTOTAL_A = INREG(VTOTAL_A); 1798fa225cbcSrjs pI830->saveVBLANK_A = INREG(VBLANK_A); 1799fa225cbcSrjs pI830->saveVSYNC_A = INREG(VSYNC_A); 1800fa225cbcSrjs pI830->saveBCLRPAT_A = INREG(BCLRPAT_A); 1801fa225cbcSrjs pI830->saveDSPASTRIDE = INREG(DSPASTRIDE); 1802fa225cbcSrjs pI830->saveDSPASIZE = INREG(DSPASIZE); 1803fa225cbcSrjs pI830->saveDSPAPOS = INREG(DSPAPOS); 1804fa225cbcSrjs pI830->saveDSPABASE = INREG(DSPABASE); 1805fa225cbcSrjs 1806fa225cbcSrjs i830_save_palette(pI830, PIPE_A); 1807fa225cbcSrjs 1808fa225cbcSrjs if(xf86_config->num_crtc == 2) { 1809fa225cbcSrjs pI830->savePIPEBCONF = INREG(PIPEBCONF); 1810fa225cbcSrjs pI830->savePIPEBSRC = INREG(PIPEBSRC); 1811fa225cbcSrjs pI830->saveDSPBCNTR = INREG(DSPBCNTR); 1812fa225cbcSrjs pI830->saveFPB0 = INREG(FPB0); 1813fa225cbcSrjs pI830->saveFPB1 = INREG(FPB1); 1814fa225cbcSrjs pI830->saveDPLL_B = INREG(DPLL_B); 1815fa225cbcSrjs if (IS_I965G(pI830)) 1816fa225cbcSrjs pI830->saveDPLL_B_MD = INREG(DPLL_B_MD); 1817fa225cbcSrjs pI830->saveHTOTAL_B = INREG(HTOTAL_B); 1818fa225cbcSrjs pI830->saveHBLANK_B = INREG(HBLANK_B); 1819fa225cbcSrjs pI830->saveHSYNC_B = INREG(HSYNC_B); 1820fa225cbcSrjs pI830->saveVTOTAL_B = INREG(VTOTAL_B); 1821fa225cbcSrjs pI830->saveVBLANK_B = INREG(VBLANK_B); 1822fa225cbcSrjs pI830->saveVSYNC_B = INREG(VSYNC_B); 1823fa225cbcSrjs pI830->saveBCLRPAT_B = INREG(BCLRPAT_B); 1824fa225cbcSrjs pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE); 1825fa225cbcSrjs pI830->saveDSPBSIZE = INREG(DSPBSIZE); 1826fa225cbcSrjs pI830->saveDSPBPOS = INREG(DSPBPOS); 1827fa225cbcSrjs pI830->saveDSPBBASE = INREG(DSPBBASE); 1828fa225cbcSrjs 1829fa225cbcSrjs i830_save_palette(pI830, PIPE_B); 1830fa225cbcSrjs } 1831fa225cbcSrjs 1832fa225cbcSrjs if (IS_I965G(pI830)) { 1833fa225cbcSrjs pI830->saveDSPASURF = INREG(DSPASURF); 1834fa225cbcSrjs pI830->saveDSPBSURF = INREG(DSPBSURF); 1835fa225cbcSrjs pI830->saveDSPATILEOFF = INREG(DSPATILEOFF); 1836fa225cbcSrjs pI830->saveDSPBTILEOFF = INREG(DSPBTILEOFF); 1837fa225cbcSrjs } 1838fa225cbcSrjs 1839fa225cbcSrjs pI830->saveVCLK_DIVISOR_VGA0 = INREG(VCLK_DIVISOR_VGA0); 1840fa225cbcSrjs pI830->saveVCLK_DIVISOR_VGA1 = INREG(VCLK_DIVISOR_VGA1); 1841fa225cbcSrjs pI830->saveVCLK_POST_DIV = INREG(VCLK_POST_DIV); 1842fa225cbcSrjs pI830->saveVGACNTRL = INREG(VGACNTRL); 1843fa225cbcSrjs 1844fa225cbcSrjs pI830->saveCURSOR_A_CONTROL = INREG(CURSOR_A_CONTROL); 1845fa225cbcSrjs pI830->saveCURSOR_A_POSITION = INREG(CURSOR_A_POSITION); 1846fa225cbcSrjs pI830->saveCURSOR_A_BASE = INREG(CURSOR_A_BASE); 1847fa225cbcSrjs pI830->saveCURSOR_B_CONTROL = INREG(CURSOR_B_CONTROL); 1848fa225cbcSrjs pI830->saveCURSOR_B_POSITION = INREG(CURSOR_B_POSITION); 1849fa225cbcSrjs pI830->saveCURSOR_B_BASE = INREG(CURSOR_B_BASE); 1850fa225cbcSrjs 1851fa225cbcSrjs for(i = 0; i < 7; i++) { 1852fa225cbcSrjs pI830->saveSWF[i] = INREG(SWF0 + (i << 2)); 1853fa225cbcSrjs pI830->saveSWF[i+7] = INREG(SWF00 + (i << 2)); 1854fa225cbcSrjs } 1855fa225cbcSrjs pI830->saveSWF[14] = INREG(SWF30); 1856fa225cbcSrjs pI830->saveSWF[15] = INREG(SWF31); 1857fa225cbcSrjs pI830->saveSWF[16] = INREG(SWF32); 1858fa225cbcSrjs 1859fa225cbcSrjs pI830->saveDSPCLK_GATE_D = INREG(DSPCLK_GATE_D); 1860fa225cbcSrjs pI830->saveRENCLK_GATE_D1 = INREG(RENCLK_GATE_D1); 1861fa225cbcSrjs 1862fa225cbcSrjs if (IS_I965G(pI830)) { 1863fa225cbcSrjs pI830->saveRENCLK_GATE_D2 = INREG(RENCLK_GATE_D2); 1864fa225cbcSrjs pI830->saveRAMCLK_GATE_D = INREG(RAMCLK_GATE_D); 1865fa225cbcSrjs } 1866fa225cbcSrjs 1867fa225cbcSrjs if (IS_I965GM(pI830) || IS_GM45(pI830)) 1868fa225cbcSrjs pI830->savePWRCTXA = INREG(PWRCTXA); 1869fa225cbcSrjs 1870fa225cbcSrjs if (IS_MOBILE(pI830) && !IS_I830(pI830)) 1871fa225cbcSrjs pI830->saveLVDS = INREG(LVDS); 1872fa225cbcSrjs pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL); 1873fa225cbcSrjs 1874fa225cbcSrjs for (i = 0; i < xf86_config->num_output; i++) { 1875fa225cbcSrjs xf86OutputPtr output = xf86_config->output[i]; 1876fa225cbcSrjs if (output->funcs->save) 1877fa225cbcSrjs (*output->funcs->save) (output); 1878fa225cbcSrjs } 1879fa225cbcSrjs 1880fa225cbcSrjs vgaHWUnlock(hwp); 1881fa225cbcSrjs vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS); 1882fa225cbcSrjs 1883fa225cbcSrjs return TRUE; 1884fa225cbcSrjs} 1885fa225cbcSrjs 1886fa225cbcSrjs/* Wait for the PLL to settle down after programming */ 1887fa225cbcSrjsstatic void 1888fa225cbcSrjsi830_dpll_settle(void) 1889fa225cbcSrjs{ 1890fa225cbcSrjs usleep(10000); /* 10 ms *should* be plenty */ 1891fa225cbcSrjs} 1892fa225cbcSrjs 1893fa225cbcSrjsstatic Bool 1894fa225cbcSrjsRestoreHWState(ScrnInfoPtr pScrn) 1895fa225cbcSrjs{ 1896fa225cbcSrjs xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1897fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 1898fa225cbcSrjs vgaHWPtr hwp = VGAHWPTR(pScrn); 1899fa225cbcSrjs vgaRegPtr vgaReg = &hwp->SavedReg; 1900fa225cbcSrjs int i; 1901fa225cbcSrjs 1902fa225cbcSrjs DPRINTF(PFX, "RestoreHWState\n"); 1903fa225cbcSrjs 1904fa225cbcSrjs /* Disable outputs */ 1905fa225cbcSrjs for (i = 0; i < xf86_config->num_output; i++) { 1906fa225cbcSrjs xf86OutputPtr output = xf86_config->output[i]; 1907fa225cbcSrjs output->funcs->dpms(output, DPMSModeOff); 1908fa225cbcSrjs } 1909fa225cbcSrjs i830WaitForVblank(pScrn); 1910fa225cbcSrjs 1911fa225cbcSrjs /* Disable pipes */ 1912fa225cbcSrjs for (i = 0; i < xf86_config->num_crtc; i++) { 1913fa225cbcSrjs xf86CrtcPtr crtc = xf86_config->crtc[i]; 1914fa225cbcSrjs i830_crtc_disable(crtc, TRUE); 1915fa225cbcSrjs } 1916fa225cbcSrjs i830WaitForVblank(pScrn); 1917fa225cbcSrjs 1918fa225cbcSrjs if (IS_MOBILE(pI830) && !IS_I830(pI830)) 1919fa225cbcSrjs OUTREG(LVDS, pI830->saveLVDS); 1920fa225cbcSrjs 1921fa225cbcSrjs if (!IS_I830(pI830) && !IS_845G(pI830)) 1922fa225cbcSrjs OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); 1923fa225cbcSrjs 1924fa225cbcSrjs if (!DSPARB_HWCONTROL(pI830)) 1925fa225cbcSrjs OUTREG(DSPARB, pI830->saveDSPARB); 1926fa225cbcSrjs 1927fa225cbcSrjs OUTREG(DSPCLK_GATE_D, pI830->saveDSPCLK_GATE_D); 1928fa225cbcSrjs OUTREG(RENCLK_GATE_D1, pI830->saveRENCLK_GATE_D1); 1929fa225cbcSrjs 1930fa225cbcSrjs if (IS_I965G(pI830)) { 1931fa225cbcSrjs OUTREG(RENCLK_GATE_D2, pI830->saveRENCLK_GATE_D2); 1932fa225cbcSrjs OUTREG(RAMCLK_GATE_D, pI830->saveRAMCLK_GATE_D); 1933fa225cbcSrjs } 1934fa225cbcSrjs 1935fa225cbcSrjs if (IS_I965GM(pI830) || IS_GM45(pI830)) 1936fa225cbcSrjs OUTREG(PWRCTXA, pI830->savePWRCTXA); 1937fa225cbcSrjs 1938fa225cbcSrjs /* 1939fa225cbcSrjs * Pipe regs 1940fa225cbcSrjs * To restore the saved state, we first need to program the PLL regs, 1941fa225cbcSrjs * followed by the pipe configuration and finally the display plane 1942fa225cbcSrjs * configuration. The VGA registers can program one, both or neither 1943fa225cbcSrjs * of the PLL regs, depending on their VGA_MOD_DIS bit value. 1944fa225cbcSrjs */ 1945fa225cbcSrjs 1946fa225cbcSrjs /* 1947fa225cbcSrjs * Since either or both pipes may use the VGA clocks, make sure the 1948fa225cbcSrjs * regs are valid. 1949fa225cbcSrjs */ 1950fa225cbcSrjs OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0); 1951fa225cbcSrjs OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1); 1952fa225cbcSrjs OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV); 1953fa225cbcSrjs 1954fa225cbcSrjs /* If the pipe A PLL is active, we can restore the pipe & plane config */ 1955fa225cbcSrjs if (pI830->saveDPLL_A & DPLL_VCO_ENABLE) 1956fa225cbcSrjs { 1957fa225cbcSrjs OUTREG(FPA0, pI830->saveFPA0); 1958fa225cbcSrjs OUTREG(DPLL_A, pI830->saveDPLL_A & ~DPLL_VCO_ENABLE); 1959fa225cbcSrjs POSTING_READ(DPLL_A); 1960fa225cbcSrjs usleep(150); 1961fa225cbcSrjs } 1962fa225cbcSrjs OUTREG(FPA0, pI830->saveFPA0); 1963fa225cbcSrjs OUTREG(FPA1, pI830->saveFPA1); 1964fa225cbcSrjs OUTREG(DPLL_A, pI830->saveDPLL_A); 1965fa225cbcSrjs POSTING_READ(DPLL_A); 1966fa225cbcSrjs i830_dpll_settle(); 1967fa225cbcSrjs if (IS_I965G(pI830)) 1968fa225cbcSrjs OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD); 1969fa225cbcSrjs else 1970fa225cbcSrjs OUTREG(DPLL_A, pI830->saveDPLL_A); 1971fa225cbcSrjs POSTING_READ(DPLL_A); 1972fa225cbcSrjs i830_dpll_settle(); 1973fa225cbcSrjs 1974fa225cbcSrjs /* Restore mode config */ 1975fa225cbcSrjs OUTREG(HTOTAL_A, pI830->saveHTOTAL_A); 1976fa225cbcSrjs OUTREG(HBLANK_A, pI830->saveHBLANK_A); 1977fa225cbcSrjs OUTREG(HSYNC_A, pI830->saveHSYNC_A); 1978fa225cbcSrjs OUTREG(VTOTAL_A, pI830->saveVTOTAL_A); 1979fa225cbcSrjs OUTREG(VBLANK_A, pI830->saveVBLANK_A); 1980fa225cbcSrjs OUTREG(VSYNC_A, pI830->saveVSYNC_A); 1981fa225cbcSrjs OUTREG(BCLRPAT_A, pI830->saveBCLRPAT_A); 1982fa225cbcSrjs 1983fa225cbcSrjs OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE); 1984fa225cbcSrjs OUTREG(DSPASIZE, pI830->saveDSPASIZE); 1985fa225cbcSrjs OUTREG(DSPAPOS, pI830->saveDSPAPOS); 1986fa225cbcSrjs OUTREG(PIPEASRC, pI830->savePIPEASRC); 1987fa225cbcSrjs OUTREG(DSPABASE, pI830->saveDSPABASE); 1988fa225cbcSrjs if (IS_I965G(pI830)) 1989fa225cbcSrjs { 1990fa225cbcSrjs OUTREG(DSPASURF, pI830->saveDSPASURF); 1991fa225cbcSrjs OUTREG(DSPATILEOFF, pI830->saveDSPATILEOFF); 1992fa225cbcSrjs } 1993fa225cbcSrjs 1994fa225cbcSrjs OUTREG(PIPEACONF, pI830->savePIPEACONF); 1995fa225cbcSrjs POSTING_READ(PIPEACONF); 1996fa225cbcSrjs i830WaitForVblank(pScrn); 1997fa225cbcSrjs 1998fa225cbcSrjs /* 1999fa225cbcSrjs * Program Pipe A's plane 2000fa225cbcSrjs * The corresponding display plane may be disabled, and should only be 2001fa225cbcSrjs * enabled if pipe A is actually on (otherwise we have a bug in the initial 2002fa225cbcSrjs * state). 2003fa225cbcSrjs */ 2004fa225cbcSrjs if ((pI830->saveDSPACNTR & DISPPLANE_SEL_PIPE_MASK) == 2005fa225cbcSrjs DISPPLANE_SEL_PIPE_A) { 2006fa225cbcSrjs OUTREG(DSPACNTR, pI830->saveDSPACNTR); 2007fa225cbcSrjs OUTREG(DSPABASE, INREG(DSPABASE)); 2008fa225cbcSrjs POSTING_READ(DSPABASE); 2009fa225cbcSrjs i830WaitForVblank(pScrn); 2010fa225cbcSrjs } 2011fa225cbcSrjs if ((pI830->saveDSPBCNTR & DISPPLANE_SEL_PIPE_MASK) == 2012fa225cbcSrjs DISPPLANE_SEL_PIPE_A) { 2013fa225cbcSrjs OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); 2014fa225cbcSrjs OUTREG(DSPBBASE, INREG(DSPBBASE)); 2015fa225cbcSrjs POSTING_READ(DSPBBASE); 2016fa225cbcSrjs i830WaitForVblank(pScrn); 2017fa225cbcSrjs } 2018fa225cbcSrjs 2019fa225cbcSrjs /* See note about pipe programming above */ 2020fa225cbcSrjs if(xf86_config->num_crtc == 2) 2021fa225cbcSrjs { 2022fa225cbcSrjs /* If the pipe B PLL is active, we can restore the pipe & plane config */ 2023fa225cbcSrjs if (pI830->saveDPLL_B & DPLL_VCO_ENABLE) 2024fa225cbcSrjs { 2025fa225cbcSrjs OUTREG(FPB0, pI830->saveFPB0); 2026fa225cbcSrjs OUTREG(DPLL_B, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE); 2027fa225cbcSrjs POSTING_READ(DPLL_B); 2028fa225cbcSrjs usleep(150); 2029fa225cbcSrjs } 2030fa225cbcSrjs OUTREG(FPB0, pI830->saveFPB0); 2031fa225cbcSrjs OUTREG(FPB1, pI830->saveFPB1); 2032fa225cbcSrjs OUTREG(DPLL_B, pI830->saveDPLL_B); 2033fa225cbcSrjs POSTING_READ(DPLL_B); 2034fa225cbcSrjs i830_dpll_settle(); 2035fa225cbcSrjs if (IS_I965G(pI830)) 2036fa225cbcSrjs OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD); 2037fa225cbcSrjs else 2038fa225cbcSrjs OUTREG(DPLL_B, pI830->saveDPLL_B); 2039fa225cbcSrjs POSTING_READ(DPLL_B); 2040fa225cbcSrjs i830_dpll_settle(); 2041fa225cbcSrjs 2042fa225cbcSrjs /* Restore mode config */ 2043fa225cbcSrjs OUTREG(HTOTAL_B, pI830->saveHTOTAL_B); 2044fa225cbcSrjs OUTREG(HBLANK_B, pI830->saveHBLANK_B); 2045fa225cbcSrjs OUTREG(HSYNC_B, pI830->saveHSYNC_B); 2046fa225cbcSrjs OUTREG(VTOTAL_B, pI830->saveVTOTAL_B); 2047fa225cbcSrjs OUTREG(VBLANK_B, pI830->saveVBLANK_B); 2048fa225cbcSrjs OUTREG(VSYNC_B, pI830->saveVSYNC_B); 2049fa225cbcSrjs OUTREG(BCLRPAT_B, pI830->saveBCLRPAT_B); 2050fa225cbcSrjs OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE); 2051fa225cbcSrjs OUTREG(DSPBSIZE, pI830->saveDSPBSIZE); 2052fa225cbcSrjs OUTREG(DSPBPOS, pI830->saveDSPBPOS); 2053fa225cbcSrjs OUTREG(PIPEBSRC, pI830->savePIPEBSRC); 2054fa225cbcSrjs OUTREG(DSPBBASE, pI830->saveDSPBBASE); 2055fa225cbcSrjs if (IS_I965G(pI830)) 2056fa225cbcSrjs { 2057fa225cbcSrjs OUTREG(DSPBSURF, pI830->saveDSPBSURF); 2058fa225cbcSrjs OUTREG(DSPBTILEOFF, pI830->saveDSPBTILEOFF); 2059fa225cbcSrjs } 2060fa225cbcSrjs 2061fa225cbcSrjs OUTREG(PIPEBCONF, pI830->savePIPEBCONF); 2062fa225cbcSrjs POSTING_READ(PIPEBCONF); 2063fa225cbcSrjs i830WaitForVblank(pScrn); 2064fa225cbcSrjs 2065fa225cbcSrjs /* 2066fa225cbcSrjs * Program Pipe B's plane 2067fa225cbcSrjs * Note that pipe B may be disabled, and in that case, the plane 2068fa225cbcSrjs * should also be disabled or we must have had a bad initial state. 2069fa225cbcSrjs */ 2070fa225cbcSrjs if ((pI830->saveDSPACNTR & DISPPLANE_SEL_PIPE_MASK) == 2071fa225cbcSrjs DISPPLANE_SEL_PIPE_B) { 2072fa225cbcSrjs OUTREG(DSPACNTR, pI830->saveDSPACNTR); 2073fa225cbcSrjs OUTREG(DSPABASE, INREG(DSPABASE)); 2074fa225cbcSrjs i830WaitForVblank(pScrn); 2075fa225cbcSrjs } 2076fa225cbcSrjs if ((pI830->saveDSPBCNTR & DISPPLANE_SEL_PIPE_MASK) == 2077fa225cbcSrjs DISPPLANE_SEL_PIPE_B) { 2078fa225cbcSrjs OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); 2079fa225cbcSrjs OUTREG(DSPBBASE, INREG(DSPBBASE)); 2080fa225cbcSrjs i830WaitForVblank(pScrn); 2081fa225cbcSrjs } 2082fa225cbcSrjs } 2083fa225cbcSrjs 2084fa225cbcSrjs OUTREG(VGACNTRL, pI830->saveVGACNTRL); 2085fa225cbcSrjs 2086fa225cbcSrjs /* 2087fa225cbcSrjs * Restore cursors 2088fa225cbcSrjs * Even though the X cursor is hidden before we restore the hw state, 2089fa225cbcSrjs * we probably only disabled one cursor plane. If we're going from 2090fa225cbcSrjs * e.g. plane b to plane a here in RestoreHWState, we need to restore 2091fa225cbcSrjs * both cursor plane settings. 2092fa225cbcSrjs */ 2093fa225cbcSrjs OUTREG(CURSOR_A_POSITION, pI830->saveCURSOR_A_POSITION); 2094fa225cbcSrjs OUTREG(CURSOR_A_BASE, pI830->saveCURSOR_A_BASE); 2095fa225cbcSrjs OUTREG(CURSOR_A_CONTROL, pI830->saveCURSOR_A_CONTROL); 2096fa225cbcSrjs OUTREG(CURSOR_B_POSITION, pI830->saveCURSOR_B_POSITION); 2097fa225cbcSrjs OUTREG(CURSOR_B_BASE, pI830->saveCURSOR_B_BASE); 2098fa225cbcSrjs OUTREG(CURSOR_B_CONTROL, pI830->saveCURSOR_B_CONTROL); 2099fa225cbcSrjs 2100fa225cbcSrjs /* Restore outputs */ 2101fa225cbcSrjs for (i = 0; i < xf86_config->num_output; i++) { 2102fa225cbcSrjs xf86OutputPtr output = xf86_config->output[i]; 2103fa225cbcSrjs if (output->funcs->restore) 2104fa225cbcSrjs output->funcs->restore(output); 2105fa225cbcSrjs } 2106fa225cbcSrjs 2107fa225cbcSrjs i830_restore_palette(pI830, PIPE_A); 2108fa225cbcSrjs i830_restore_palette(pI830, PIPE_B); 2109fa225cbcSrjs 2110fa225cbcSrjs for(i = 0; i < 7; i++) { 2111fa225cbcSrjs OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]); 2112fa225cbcSrjs OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]); 2113fa225cbcSrjs } 2114fa225cbcSrjs 2115fa225cbcSrjs OUTREG(SWF30, pI830->saveSWF[14]); 2116fa225cbcSrjs OUTREG(SWF31, pI830->saveSWF[15]); 2117fa225cbcSrjs OUTREG(SWF32, pI830->saveSWF[16]); 2118fa225cbcSrjs 2119fa225cbcSrjs if (pI830->fb_compression) { 2120fa225cbcSrjs OUTREG(FBC_CFB_BASE, pI830->saveFBC_CFB_BASE); 2121fa225cbcSrjs OUTREG(FBC_LL_BASE, pI830->saveFBC_LL_BASE); 2122fa225cbcSrjs OUTREG(FBC_FENCE_OFF, pI830->saveFBC_FENCE_OFF); 2123fa225cbcSrjs OUTREG(FBC_CONTROL2, pI830->saveFBC_CONTROL2); 2124fa225cbcSrjs OUTREG(FBC_CONTROL, pI830->saveFBC_CONTROL); 2125fa225cbcSrjs } 2126fa225cbcSrjs 2127fa225cbcSrjs vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); 2128fa225cbcSrjs vgaHWLock(hwp); 2129fa225cbcSrjs 2130fa225cbcSrjs return TRUE; 2131fa225cbcSrjs} 2132fa225cbcSrjs 2133fa225cbcSrjs/** 2134fa225cbcSrjs * Intialiazes the hardware for the 3D pipeline use in the 2D driver. 2135fa225cbcSrjs * 2136fa225cbcSrjs * Some state caching is performed to avoid redundant state emits. This 2137fa225cbcSrjs * function is also responsible for marking the state as clobbered for DRI 2138fa225cbcSrjs * clients. 2139fa225cbcSrjs */ 2140fa225cbcSrjsvoid 2141fa225cbcSrjsIntelEmitInvarientState(ScrnInfoPtr pScrn) 2142fa225cbcSrjs{ 2143fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2144fa225cbcSrjs 2145fa225cbcSrjs /* If we've emitted our state since the last clobber by another client, 2146fa225cbcSrjs * skip it. 2147fa225cbcSrjs */ 2148fa225cbcSrjs if (pI830->last_3d != LAST_3D_OTHER) 2149fa225cbcSrjs return; 2150fa225cbcSrjs 2151fa225cbcSrjs if (!IS_I965G(pI830)) 2152fa225cbcSrjs { 2153fa225cbcSrjs if (IS_I9XX(pI830)) 2154fa225cbcSrjs I915EmitInvarientState(pScrn); 2155fa225cbcSrjs else 2156fa225cbcSrjs I830EmitInvarientState(pScrn); 2157fa225cbcSrjs } 2158fa225cbcSrjs} 2159fa225cbcSrjs 2160fa225cbcSrjsstatic void 2161fa225cbcSrjsI830BlockHandler(int i, 2162fa225cbcSrjs pointer blockData, pointer pTimeout, pointer pReadmask) 2163fa225cbcSrjs{ 2164fa225cbcSrjs ScreenPtr pScreen = screenInfo.screens[i]; 2165fa225cbcSrjs ScrnInfoPtr pScrn = xf86Screens[i]; 2166fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2167fa225cbcSrjs 2168fa225cbcSrjs pScreen->BlockHandler = pI830->BlockHandler; 2169fa225cbcSrjs 2170fa225cbcSrjs (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); 2171fa225cbcSrjs 2172fa225cbcSrjs pI830->BlockHandler = pScreen->BlockHandler; 2173fa225cbcSrjs pScreen->BlockHandler = I830BlockHandler; 2174fa225cbcSrjs 2175fa225cbcSrjs if (pScrn->vtSema) { 2176fa225cbcSrjs Bool flushed = FALSE; 2177fa225cbcSrjs /* Emit a flush of the rendering cache, or on the 965 and beyond 2178fa225cbcSrjs * rendering results may not hit the framebuffer until significantly 2179fa225cbcSrjs * later. 2180fa225cbcSrjs */ 2181fa225cbcSrjs if (pI830->need_mi_flush || pI830->batch_used) 2182fa225cbcSrjs { 2183fa225cbcSrjs flushed = TRUE; 2184fa225cbcSrjs I830EmitFlush(pScrn); 2185fa225cbcSrjs } 2186fa225cbcSrjs 2187fa225cbcSrjs /* Flush the batch, so that any rendering is executed in a timely 2188fa225cbcSrjs * fashion. 2189fa225cbcSrjs */ 2190fa225cbcSrjs intel_batch_flush(pScrn, flushed); 2191fa225cbcSrjs if (pI830->have_gem) 2192fa225cbcSrjs drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_THROTTLE); 2193fa225cbcSrjs 2194fa225cbcSrjs pI830->need_mi_flush = FALSE; 2195fa225cbcSrjs } 2196fa225cbcSrjs 2197fa225cbcSrjs i830_uxa_block_handler (pScreen); 2198fa225cbcSrjs 2199fa225cbcSrjs I830VideoBlockHandler(i, blockData, pTimeout, pReadmask); 2200fa225cbcSrjs} 2201fa225cbcSrjs 2202fa225cbcSrjsstatic void 2203fa225cbcSrjsi830_fixup_mtrrs(ScrnInfoPtr pScrn) 2204fa225cbcSrjs{ 2205fa225cbcSrjs#ifdef HAS_MTRR_SUPPORT 2206fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2207fa225cbcSrjs int fd; 2208fa225cbcSrjs struct mtrr_gentry gentry; 2209fa225cbcSrjs struct mtrr_sentry sentry; 2210fa225cbcSrjs 2211fa225cbcSrjs if ( ( fd = open ("/proc/mtrr", O_RDONLY, 0) ) != -1 ) { 2212fa225cbcSrjs for (gentry.regnum = 0; ioctl (fd, MTRRIOC_GET_ENTRY, &gentry) == 0; 2213fa225cbcSrjs ++gentry.regnum) { 2214fa225cbcSrjs 2215fa225cbcSrjs if (gentry.size < 1) { 2216fa225cbcSrjs /* DISABLED */ 2217fa225cbcSrjs continue; 2218fa225cbcSrjs } 2219fa225cbcSrjs 2220fa225cbcSrjs /* Check the MTRR range is one we like and if not - remove it. 2221fa225cbcSrjs * The Xserver common layer will then setup the right range 2222fa225cbcSrjs * for us. 2223fa225cbcSrjs */ 2224fa225cbcSrjs if (gentry.base == pI830->LinearAddr && 2225fa225cbcSrjs gentry.size < pI830->FbMapSize) { 2226fa225cbcSrjs 2227fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2228fa225cbcSrjs "Removing bad MTRR range (base 0x%lx, size 0x%x)\n", 2229fa225cbcSrjs gentry.base, gentry.size); 2230fa225cbcSrjs 2231fa225cbcSrjs sentry.base = gentry.base; 2232fa225cbcSrjs sentry.size = gentry.size; 2233fa225cbcSrjs sentry.type = gentry.type; 2234fa225cbcSrjs 2235fa225cbcSrjs if (ioctl (fd, MTRRIOC_DEL_ENTRY, &sentry) == -1) { 2236fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2237fa225cbcSrjs "Failed to remove bad MTRR range\n"); 2238fa225cbcSrjs } 2239fa225cbcSrjs } 2240fa225cbcSrjs } 2241fa225cbcSrjs close(fd); 2242fa225cbcSrjs } 2243fa225cbcSrjs#endif 2244fa225cbcSrjs} 2245fa225cbcSrjs 2246fa225cbcSrjsstatic Bool 2247fa225cbcSrjsi830_try_memory_allocation(ScrnInfoPtr pScrn) 2248fa225cbcSrjs{ 2249fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2250fa225cbcSrjs Bool tiled = pI830->tiling; 2251fa225cbcSrjs 2252fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2253fa225cbcSrjs "Attempting memory allocation with %stiled buffers.\n", 2254fa225cbcSrjs tiled ? "" : "un"); 2255fa225cbcSrjs 2256fa225cbcSrjs if (!i830_allocate_2d_memory(pScrn)) 2257fa225cbcSrjs goto failed; 2258fa225cbcSrjs 2259fa225cbcSrjs if (IS_I965GM(pI830) || IS_GM45(pI830)) 2260fa225cbcSrjs if (!i830_allocate_pwrctx(pScrn)) 2261fa225cbcSrjs goto failed; 2262fa225cbcSrjs 2263fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%siled allocation successful.\n", 2264fa225cbcSrjs tiled ? "T" : "Unt"); 2265fa225cbcSrjs return TRUE; 2266fa225cbcSrjs 2267fa225cbcSrjsfailed: 2268fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%siled allocation failed.\n", 2269fa225cbcSrjs tiled ? "T" : "Unt"); 2270fa225cbcSrjs return FALSE; 2271fa225cbcSrjs} 2272fa225cbcSrjs/* 2273fa225cbcSrjs * Try to allocate memory in several ways: 2274fa225cbcSrjs * 1) If direct rendering is enabled, try to allocate enough memory for tiled 2275fa225cbcSrjs * surfaces by rounding up the display width to a tileable one. 2276fa225cbcSrjs * 2) If that fails or the allocations themselves fail, try again with untiled 2277fa225cbcSrjs * allocations (if this works DRI will stay enabled). 2278fa225cbcSrjs * 3) And if all else fails, disable DRI and try just 2D allocations. 2279fa225cbcSrjs * 4) Give up and fail ScreenInit. 2280fa225cbcSrjs */ 2281fa225cbcSrjsstatic Bool 2282fa225cbcSrjsi830_memory_init(ScrnInfoPtr pScrn) 2283fa225cbcSrjs{ 2284fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2285fa225cbcSrjs int savedDisplayWidth = pScrn->displayWidth; 2286fa225cbcSrjs Bool tiled = FALSE; 2287fa225cbcSrjs 2288fa225cbcSrjs tiled = i830_tiled_width(pI830, &pScrn->displayWidth, pI830->cpp); 2289fa225cbcSrjs /* Set up our video memory allocator for the chosen videoRam */ 2290fa225cbcSrjs if (!i830_allocator_init(pScrn, pScrn->videoRam * KB(1))) { 2291fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2292fa225cbcSrjs "Couldn't initialize video memory allocator\n"); 2293fa225cbcSrjs PreInitCleanup(pScrn); 2294fa225cbcSrjs return FALSE; 2295fa225cbcSrjs } 2296fa225cbcSrjs 2297fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, 2298fa225cbcSrjs pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT, 2299fa225cbcSrjs "VideoRam: %d KB\n", pScrn->videoRam); 2300fa225cbcSrjs 2301fa225cbcSrjs /* Tiled first if we got a good displayWidth */ 2302fa225cbcSrjs if (tiled) { 2303fa225cbcSrjs if (i830_try_memory_allocation(pScrn)) 2304fa225cbcSrjs return TRUE; 2305fa225cbcSrjs else { 2306fa225cbcSrjs i830_reset_allocations(pScrn); 2307fa225cbcSrjs pI830->tiling = FALSE; 2308fa225cbcSrjs } 2309fa225cbcSrjs } 2310fa225cbcSrjs 2311fa225cbcSrjs /* If tiling fails we have to disable FBC */ 2312fa225cbcSrjs pScrn->displayWidth = savedDisplayWidth; 2313fa225cbcSrjs if (pI830->fb_compression) 2314fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2315fa225cbcSrjs "Couldn't allocate tiled memory, fb compression " 2316fa225cbcSrjs "disabled\n"); 2317fa225cbcSrjs pI830->fb_compression = FALSE; 2318fa225cbcSrjs 2319fa225cbcSrjs if (i830_try_memory_allocation(pScrn)) 2320fa225cbcSrjs return TRUE; 2321fa225cbcSrjs 2322fa225cbcSrjs return FALSE; 2323fa225cbcSrjs} 2324fa225cbcSrjs 2325fa225cbcSrjsvoid 2326fa225cbcSrjsi830_init_bufmgr(ScrnInfoPtr pScrn) 2327fa225cbcSrjs{ 2328fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2329fa225cbcSrjs 2330fa225cbcSrjs if (pI830->bufmgr) 2331fa225cbcSrjs return; 2332fa225cbcSrjs 2333fa225cbcSrjs if (pI830->have_gem) { 2334fa225cbcSrjs int batch_size; 2335fa225cbcSrjs 2336fa225cbcSrjs batch_size = 4096 * 4; 2337fa225cbcSrjs 2338fa225cbcSrjs /* The 865 has issues with larger-than-page-sized batch buffers. */ 2339fa225cbcSrjs if (IS_I865G(pI830)) 2340fa225cbcSrjs batch_size = 4096; 2341fa225cbcSrjs 2342fa225cbcSrjs pI830->bufmgr = intel_bufmgr_gem_init(pI830->drmSubFD, batch_size); 2343fa225cbcSrjs intel_bufmgr_gem_enable_reuse(pI830->bufmgr); 2344fa225cbcSrjs } else { 2345fa225cbcSrjs assert(pI830->FbBase != NULL); 2346fa225cbcSrjs pI830->bufmgr = intel_bufmgr_fake_init(pI830->drmSubFD, 2347fa225cbcSrjs pI830->fake_bufmgr_mem->offset, 2348fa225cbcSrjs pI830->FbBase + 2349fa225cbcSrjs pI830->fake_bufmgr_mem->offset, 2350fa225cbcSrjs pI830->fake_bufmgr_mem->size, 2351fa225cbcSrjs NULL); 2352fa225cbcSrjs } 2353fa225cbcSrjs} 2354fa225cbcSrjs 2355fa225cbcSrjsBool i830_crtc_on(xf86CrtcPtr crtc) 2356fa225cbcSrjs{ 2357fa225cbcSrjs ScrnInfoPtr pScrn = crtc->scrn; 2358fa225cbcSrjs xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 2359fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2360fa225cbcSrjs 2361fa225cbcSrjs if (pI830->use_drm_mode) { 2362fa225cbcSrjs int i, active_outputs = 0; 2363fa225cbcSrjs 2364fa225cbcSrjs /* Kernel manages CRTC status based out output config */ 2365fa225cbcSrjs for (i = 0; i < xf86_config->num_output; i++) { 2366fa225cbcSrjs xf86OutputPtr output = xf86_config->output[i]; 2367fa225cbcSrjs if (output->crtc == crtc && 2368fa225cbcSrjs drmmode_output_dpms_status(output) == DPMSModeOn) 2369fa225cbcSrjs active_outputs++; 2370fa225cbcSrjs } 2371fa225cbcSrjs 2372fa225cbcSrjs if (active_outputs) 2373fa225cbcSrjs return TRUE; 2374fa225cbcSrjs return FALSE; 2375fa225cbcSrjs } else { 2376fa225cbcSrjs I830CrtcPrivatePtr intel_crtc = crtc->driver_private; 2377fa225cbcSrjs 2378fa225cbcSrjs if (intel_crtc->dpms_mode == DPMSModeOn) 2379fa225cbcSrjs return TRUE; 2380fa225cbcSrjs return FALSE; 2381fa225cbcSrjs } 2382fa225cbcSrjs} 2383fa225cbcSrjs 2384fa225cbcSrjsint i830_crtc_to_pipe(xf86CrtcPtr crtc) 2385fa225cbcSrjs{ 2386fa225cbcSrjs ScrnInfoPtr pScrn = crtc->scrn; 2387fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2388fa225cbcSrjs int pipe; 2389fa225cbcSrjs 2390fa225cbcSrjs if (pI830->use_drm_mode) { 2391fa225cbcSrjs pipe = drmmode_get_pipe_from_crtc_id(pI830->bufmgr, crtc); 2392fa225cbcSrjs } else { 2393fa225cbcSrjs I830CrtcPrivatePtr intel_crtc = crtc->driver_private; 2394fa225cbcSrjs pipe = intel_crtc->pipe; 2395fa225cbcSrjs } 2396fa225cbcSrjs 2397fa225cbcSrjs return pipe; 2398fa225cbcSrjs} 2399fa225cbcSrjs 2400fa225cbcSrjsstatic void 2401fa225cbcSrjsI830AdjustMemory(ScreenPtr pScreen) 2402fa225cbcSrjs{ 2403fa225cbcSrjs ScrnInfoPtr pScrn; 2404fa225cbcSrjs I830Ptr pI830; 2405fa225cbcSrjs unsigned long sys_mem; 2406fa225cbcSrjs MessageType from; 2407fa225cbcSrjs 2408fa225cbcSrjs pScrn = xf86Screens[pScreen->myNum]; 2409fa225cbcSrjs pI830 = I830PTR(pScrn); 2410fa225cbcSrjs 2411fa225cbcSrjs /* Limit videoRam to how much we might be able to allocate from AGP */ 2412fa225cbcSrjs sys_mem = I830CheckAvailableMemory(pScrn); 2413fa225cbcSrjs if (sys_mem == -1) { 2414fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2415fa225cbcSrjs "/dev/agpgart is either not available, or no memory " 2416fa225cbcSrjs "is available\nfor allocation. Please enable agpgart\n."); 2417fa225cbcSrjs pScrn->videoRam = pI830->stolen_size / KB(1); 2418fa225cbcSrjs } 2419fa225cbcSrjs if (sys_mem + (pI830->stolen_size / 1024) < pScrn->videoRam) { 2420fa225cbcSrjs pScrn->videoRam = sys_mem + (pI830->stolen_size / 1024); 2421fa225cbcSrjs from = X_PROBED; 2422fa225cbcSrjs if (sys_mem + (pI830->stolen_size / 1024) < 2423fa225cbcSrjs pI830->pEnt->device->videoRam) { 2424fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2425fa225cbcSrjs "VideoRAM reduced to %d kByte " 2426fa225cbcSrjs "(limited to available sysmem)\n", pScrn->videoRam); 2427fa225cbcSrjs } 2428fa225cbcSrjs } 2429fa225cbcSrjs 2430fa225cbcSrjs /* Limit video RAM to the actual aperture size */ 2431fa225cbcSrjs if (pScrn->videoRam > pI830->FbMapSize / 1024) { 2432fa225cbcSrjs pScrn->videoRam = pI830->FbMapSize / 1024; 2433fa225cbcSrjs if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam) { 2434fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2435fa225cbcSrjs "VideoRam reduced to %d kByte (limited to aperture " 2436fa225cbcSrjs "size)\n", 2437fa225cbcSrjs pScrn->videoRam); 2438fa225cbcSrjs } 2439fa225cbcSrjs } 2440fa225cbcSrjs 2441fa225cbcSrjs /* Make sure it's on a page boundary */ 2442fa225cbcSrjs if (pScrn->videoRam & 3) { 2443fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB " 2444fa225cbcSrjs "(page aligned - was %d KB)\n", 2445fa225cbcSrjs pScrn->videoRam & ~3, pScrn->videoRam); 2446fa225cbcSrjs pScrn->videoRam &= ~3; 2447fa225cbcSrjs } 2448fa225cbcSrjs 2449fa225cbcSrjs if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) { 2450fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2451fa225cbcSrjs "Cannot support DRI with frame buffer width > 2048.\n"); 2452fa225cbcSrjs pI830->directRenderingType = DRI_DISABLED; 2453fa225cbcSrjs } 2454fa225cbcSrjs} 2455fa225cbcSrjs 2456fa225cbcSrjsstatic void 2457fa225cbcSrjsI830SwapPipes(ScrnInfoPtr pScrn) 2458fa225cbcSrjs{ 2459fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2460fa225cbcSrjs xf86CrtcConfigPtr config; 2461fa225cbcSrjs int c; 2462fa225cbcSrjs 2463fa225cbcSrjs config = XF86_CRTC_CONFIG_PTR(pScrn); 2464fa225cbcSrjs 2465fa225cbcSrjs /* 2466fa225cbcSrjs * If an LVDS display is present, swap the plane/pipe mappings so we can 2467fa225cbcSrjs * use FBC on the builtin display. 2468fa225cbcSrjs * Note: 965+ chips can compress either plane, so we leave the mapping 2469fa225cbcSrjs * alone in that case. 2470fa225cbcSrjs * Also make sure the DRM can handle the swap. 2471fa225cbcSrjs */ 2472fa225cbcSrjs if (I830LVDSPresent(pScrn) && !IS_I965GM(pI830) && !IS_GM45(pI830)) { 2473fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "adjusting plane->pipe mappings " 2474fa225cbcSrjs "to allow for framebuffer compression\n"); 2475fa225cbcSrjs for (c = 0; c < config->num_crtc; c++) { 2476fa225cbcSrjs xf86CrtcPtr crtc = config->crtc[c]; 2477fa225cbcSrjs I830CrtcPrivatePtr intel_crtc = crtc->driver_private; 2478fa225cbcSrjs 2479fa225cbcSrjs if (intel_crtc->pipe == 0) 2480fa225cbcSrjs intel_crtc->plane = 1; 2481fa225cbcSrjs else if (intel_crtc->pipe == 1) 2482fa225cbcSrjs intel_crtc->plane = 0; 2483fa225cbcSrjs } 2484fa225cbcSrjs } 2485fa225cbcSrjs} 2486fa225cbcSrjs 2487fa225cbcSrjsstatic void 2488fa225cbcSrjsi830_disable_render_standby(ScrnInfoPtr pScrn) 2489fa225cbcSrjs{ 2490fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2491fa225cbcSrjs uint32_t render_standby; 2492fa225cbcSrjs 2493fa225cbcSrjs /* Render Standby might cause hang issue, try always disable it.*/ 2494fa225cbcSrjs if (IS_I965GM(pI830) || IS_GM45(pI830)) { 2495fa225cbcSrjs render_standby = INREG(MCHBAR_RENDER_STANDBY); 2496fa225cbcSrjs if (render_standby & RENDER_STANDBY_ENABLE) { 2497fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disable render standby.\n"); 2498fa225cbcSrjs OUTREG(MCHBAR_RENDER_STANDBY, 2499fa225cbcSrjs (render_standby & (~RENDER_STANDBY_ENABLE))); 2500fa225cbcSrjs } 2501fa225cbcSrjs } 2502fa225cbcSrjs} 2503fa225cbcSrjs 2504fa225cbcSrjsstatic Bool 2505fa225cbcSrjsI830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 2506fa225cbcSrjs{ 2507fa225cbcSrjs ScrnInfoPtr pScrn; 2508fa225cbcSrjs vgaHWPtr hwp = NULL; 2509fa225cbcSrjs I830Ptr pI830; 2510fa225cbcSrjs VisualPtr visual; 2511fa225cbcSrjs MessageType from; 2512fa225cbcSrjs 2513fa225cbcSrjs pScrn = xf86Screens[pScreen->myNum]; 2514fa225cbcSrjs pI830 = I830PTR(pScrn); 2515fa225cbcSrjs 2516fa225cbcSrjs if (!pI830->use_drm_mode) 2517fa225cbcSrjs hwp = VGAHWPTR(pScrn); 2518fa225cbcSrjs 2519fa225cbcSrjs pScrn->displayWidth = i830_pad_drawable_width(pScrn->virtualX, pI830->cpp); 2520fa225cbcSrjs 2521fa225cbcSrjs /* 2522fa225cbcSrjs * The "VideoRam" config file parameter specifies the maximum amount of 2523fa225cbcSrjs * memory that will be used/allocated. When not present, we allow the 2524fa225cbcSrjs * driver to allocate as much memory as it wishes to satisfy its 2525fa225cbcSrjs * allocations, but if agpgart support isn't available, it gets limited 2526fa225cbcSrjs * to the amount of pre-allocated ("stolen") memory. 2527fa225cbcSrjs * 2528fa225cbcSrjs * Note that in using this value for allocator initialization, we're 2529fa225cbcSrjs * limiting aperture allocation to the VideoRam option, rather than limiting 2530fa225cbcSrjs * actual memory allocation, so alignment and things will cause less than 2531fa225cbcSrjs * VideoRam to be actually used. 2532fa225cbcSrjs */ 2533fa225cbcSrjs if (pI830->pEnt->device->videoRam == 0) { 2534fa225cbcSrjs from = X_DEFAULT; 2535fa225cbcSrjs pScrn->videoRam = pI830->FbMapSize / KB(1); 2536fa225cbcSrjs } else { 2537fa225cbcSrjs#if 0 2538fa225cbcSrjs from = X_CONFIG; 2539fa225cbcSrjs pScrn->videoRam = pI830->pEnt->device->videoRam; 2540fa225cbcSrjs#else 2541fa225cbcSrjs /* Disable VideoRam configuration, at least for now. Previously, 2542fa225cbcSrjs * VideoRam was necessary to avoid overly low limits on allocated 2543fa225cbcSrjs * memory, so users created larger, yet still small, fixed allocation 2544fa225cbcSrjs * limits in their config files. Now, the driver wants to allocate more, 2545fa225cbcSrjs * and the old intention of the VideoRam lines that had been entered is 2546fa225cbcSrjs * obsolete. 2547fa225cbcSrjs */ 2548fa225cbcSrjs from = X_DEFAULT; 2549fa225cbcSrjs pScrn->videoRam = pI830->FbMapSize / KB(1); 2550fa225cbcSrjs 2551fa225cbcSrjs if (pScrn->videoRam != pI830->pEnt->device->videoRam) { 2552fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2553fa225cbcSrjs "VideoRam configuration found, which is no longer " 2554fa225cbcSrjs "recommended.\n"); 2555fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2556fa225cbcSrjs "Continuing with default %dkB VideoRam instead of %d " 2557fa225cbcSrjs "kB.\n", 2558fa225cbcSrjs pScrn->videoRam, pI830->pEnt->device->videoRam); 2559fa225cbcSrjs } 2560fa225cbcSrjs#endif 2561fa225cbcSrjs } 2562fa225cbcSrjs 2563fa225cbcSrjs if (pI830->use_drm_mode) { 2564fa225cbcSrjs struct pci_device *const device = pI830->PciInfo; 2565fa225cbcSrjs int fb_bar = IS_I9XX(pI830) ? 2 : 0; 2566fa225cbcSrjs 2567fa225cbcSrjs pScrn->videoRam = device->regions[fb_bar].size / 1024; 2568fa225cbcSrjs } else { 2569fa225cbcSrjs I830AdjustMemory(pScreen); 2570fa225cbcSrjs } 2571fa225cbcSrjs 2572fa225cbcSrjs#ifdef DRI2 2573fa225cbcSrjs if (pI830->directRenderingType == DRI_NONE && I830DRI2ScreenInit(pScreen)) 2574fa225cbcSrjs pI830->directRenderingType = DRI_DRI2; 2575fa225cbcSrjs#endif 2576fa225cbcSrjs 2577fa225cbcSrjs /* Enable tiling by default */ 2578fa225cbcSrjs pI830->tiling = TRUE; 2579fa225cbcSrjs 2580fa225cbcSrjs /* Allow user override if they set a value */ 2581fa225cbcSrjs if (xf86IsOptionSet(pI830->Options, OPTION_TILING)) { 2582fa225cbcSrjs if (xf86ReturnOptValBool(pI830->Options, OPTION_TILING, FALSE)) 2583fa225cbcSrjs pI830->tiling = TRUE; 2584fa225cbcSrjs else 2585fa225cbcSrjs pI830->tiling = FALSE; 2586fa225cbcSrjs } 2587fa225cbcSrjs 2588fa225cbcSrjs /* Enable FB compression if possible */ 2589fa225cbcSrjs if (i830_fb_compression_supported(pI830)) 2590fa225cbcSrjs pI830->fb_compression = TRUE; 2591fa225cbcSrjs else 2592fa225cbcSrjs pI830->fb_compression = FALSE; 2593fa225cbcSrjs 2594fa225cbcSrjs /* Again, allow user override if set */ 2595fa225cbcSrjs if (xf86IsOptionSet(pI830->Options, OPTION_FBC)) { 2596fa225cbcSrjs if (xf86ReturnOptValBool(pI830->Options, OPTION_FBC, FALSE)) 2597fa225cbcSrjs pI830->fb_compression = TRUE; 2598fa225cbcSrjs else 2599fa225cbcSrjs pI830->fb_compression = FALSE; 2600fa225cbcSrjs } 2601fa225cbcSrjs 2602fa225cbcSrjs if (pI830->use_drm_mode && pI830->fb_compression == TRUE) { 2603fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2604fa225cbcSrjs "Kernel mode setting active, disabling FBC.\n"); 2605fa225cbcSrjs pI830->fb_compression = FALSE; 2606fa225cbcSrjs } 2607fa225cbcSrjs 2608fa225cbcSrjs /* SwapBuffers delays to avoid tearing */ 2609fa225cbcSrjs pI830->swapbuffers_wait = TRUE; 2610fa225cbcSrjs 2611fa225cbcSrjs /* Allow user override if they set a value */ 2612fa225cbcSrjs if (xf86IsOptionSet(pI830->Options, OPTION_SWAPBUFFERS_WAIT)) { 2613fa225cbcSrjs if (xf86ReturnOptValBool(pI830->Options, OPTION_SWAPBUFFERS_WAIT, FALSE)) 2614fa225cbcSrjs pI830->swapbuffers_wait = TRUE; 2615fa225cbcSrjs else 2616fa225cbcSrjs pI830->swapbuffers_wait = FALSE; 2617fa225cbcSrjs } 2618fa225cbcSrjs 2619fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Framebuffer compression %sabled\n", 2620fa225cbcSrjs pI830->fb_compression ? "en" : "dis"); 2621fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Tiling %sabled\n", pI830->tiling ? 2622fa225cbcSrjs "en" : "dis"); 2623fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "SwapBuffers wait %sabled\n", 2624fa225cbcSrjs pI830->swapbuffers_wait ? "en" : "dis"); 2625fa225cbcSrjs 2626fa225cbcSrjs pI830->last_3d = LAST_3D_OTHER; 2627fa225cbcSrjs pI830->overlayOn = FALSE; 2628fa225cbcSrjs 2629fa225cbcSrjs /* 2630fa225cbcSrjs * Set this so that the overlay allocation is factored in when 2631fa225cbcSrjs * appropriate. 2632fa225cbcSrjs */ 2633fa225cbcSrjs pI830->XvEnabled = TRUE; 2634fa225cbcSrjs 2635fa225cbcSrjs /* Need MMIO mapped to do GTT lookups during memory allocation. */ 2636fa225cbcSrjs if (!pI830->use_drm_mode) 2637fa225cbcSrjs I830MapMMIO(pScrn); 2638fa225cbcSrjs 2639fa225cbcSrjs /* Need FB mapped to access non-GEM objects like 2640fa225cbcSrjs * a UMS frame buffer, or the fake bufmgr. 2641fa225cbcSrjs */ 2642fa225cbcSrjs if (!pI830->use_drm_mode) { 2643fa225cbcSrjs if (!I830MapMem(pScrn)) 2644fa225cbcSrjs return FALSE; 2645fa225cbcSrjs pScrn->memPhysBase = (unsigned long)pI830->FbBase; 2646fa225cbcSrjs } 2647fa225cbcSrjs 2648fa225cbcSrjs if (!i830_memory_init(pScrn)) { 2649fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2650fa225cbcSrjs "Couldn't allocate video memory\n"); 2651fa225cbcSrjs return FALSE; 2652fa225cbcSrjs } 2653fa225cbcSrjs 2654fa225cbcSrjs i830_fixup_mtrrs(pScrn); 2655fa225cbcSrjs 2656fa225cbcSrjs pI830->starting = TRUE; 2657fa225cbcSrjs 2658fa225cbcSrjs miClearVisualTypes(); 2659fa225cbcSrjs if (!miSetVisualTypes(pScrn->depth, 2660fa225cbcSrjs miGetDefaultVisualMask(pScrn->depth), 2661fa225cbcSrjs pScrn->rgbBits, pScrn->defaultVisual)) 2662fa225cbcSrjs return FALSE; 2663fa225cbcSrjs if (!miSetPixmapDepths()) 2664fa225cbcSrjs return FALSE; 2665fa225cbcSrjs 2666fa225cbcSrjs if (!pI830->use_drm_mode) { 2667fa225cbcSrjs vgaHWSetMmioFuncs(hwp, pI830->MMIOBase, 0); 2668fa225cbcSrjs vgaHWGetIOBase(hwp); 2669fa225cbcSrjs DPRINTF(PFX, "assert( if(!vgaHWMapMem(pScrn)) )\n"); 2670fa225cbcSrjs if (!vgaHWMapMem(pScrn)) 2671fa225cbcSrjs return FALSE; 2672fa225cbcSrjs } 2673fa225cbcSrjs 2674fa225cbcSrjs DPRINTF(PFX, "assert( if(!I830EnterVT(scrnIndex, 0)) )\n"); 2675fa225cbcSrjs 2676fa225cbcSrjs if (pScrn->virtualX > pScrn->displayWidth) 2677fa225cbcSrjs pScrn->displayWidth = pScrn->virtualX; 2678fa225cbcSrjs 2679fa225cbcSrjs /* If the front buffer is not a BO, we need to 2680fa225cbcSrjs * set the initial framebuffer pixmap to point at 2681fa225cbcSrjs * it 2682fa225cbcSrjs */ 2683fa225cbcSrjs pScrn->fbOffset = pI830->front_buffer->offset; 2684fa225cbcSrjs 2685fa225cbcSrjs DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n"); 2686fa225cbcSrjs if (!fbScreenInit(pScreen, pI830->FbBase + pScrn->fbOffset, 2687fa225cbcSrjs pScrn->virtualX, pScrn->virtualY, 2688fa225cbcSrjs pScrn->xDpi, pScrn->yDpi, 2689fa225cbcSrjs pScrn->displayWidth, pScrn->bitsPerPixel)) 2690fa225cbcSrjs return FALSE; 2691fa225cbcSrjs 2692fa225cbcSrjs if (pScrn->bitsPerPixel > 8) { 2693fa225cbcSrjs /* Fixup RGB ordering */ 2694fa225cbcSrjs visual = pScreen->visuals + pScreen->numVisuals; 2695fa225cbcSrjs while (--visual >= pScreen->visuals) { 2696fa225cbcSrjs if ((visual->class | DynamicClass) == DirectColor) { 2697fa225cbcSrjs visual->offsetRed = pScrn->offset.red; 2698fa225cbcSrjs visual->offsetGreen = pScrn->offset.green; 2699fa225cbcSrjs visual->offsetBlue = pScrn->offset.blue; 2700fa225cbcSrjs visual->redMask = pScrn->mask.red; 2701fa225cbcSrjs visual->greenMask = pScrn->mask.green; 2702fa225cbcSrjs visual->blueMask = pScrn->mask.blue; 2703fa225cbcSrjs } 2704fa225cbcSrjs } 2705fa225cbcSrjs } 2706fa225cbcSrjs 2707fa225cbcSrjs fbPictureInit(pScreen, NULL, 0); 2708fa225cbcSrjs 2709fa225cbcSrjs xf86SetBlackWhitePixels(pScreen); 2710fa225cbcSrjs 2711fa225cbcSrjs if (!I830AccelInit(pScreen)) { 2712fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2713fa225cbcSrjs "Hardware acceleration initialization failed\n"); 2714fa225cbcSrjs return FALSE; 2715fa225cbcSrjs } 2716fa225cbcSrjs 2717fa225cbcSrjs if (IS_I965G(pI830)) 2718fa225cbcSrjs pI830->batch_flush_notify = i965_batch_flush_notify; 2719fa225cbcSrjs else if (IS_I9XX(pI830)) 2720fa225cbcSrjs pI830->batch_flush_notify = i915_batch_flush_notify; 2721fa225cbcSrjs else 2722fa225cbcSrjs pI830->batch_flush_notify = i830_batch_flush_notify; 2723fa225cbcSrjs 2724fa225cbcSrjs miInitializeBackingStore(pScreen); 2725fa225cbcSrjs xf86SetBackingStore(pScreen); 2726fa225cbcSrjs xf86SetSilkenMouse(pScreen); 2727fa225cbcSrjs miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 2728fa225cbcSrjs 2729fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing HW Cursor\n"); 2730fa225cbcSrjs if (!I830CursorInit(pScreen)) 2731fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2732fa225cbcSrjs "Hardware cursor initialization failed\n"); 2733fa225cbcSrjs 2734fa225cbcSrjs /* Must force it before EnterVT, so we are in control of VT and 2735fa225cbcSrjs * later memory should be bound when allocating, e.g rotate_mem */ 2736fa225cbcSrjs pScrn->vtSema = TRUE; 2737fa225cbcSrjs 2738fa225cbcSrjs if (!I830EnterVT(scrnIndex, 0)) 2739fa225cbcSrjs return FALSE; 2740fa225cbcSrjs 2741fa225cbcSrjs pI830->BlockHandler = pScreen->BlockHandler; 2742fa225cbcSrjs pScreen->BlockHandler = I830BlockHandler; 2743fa225cbcSrjs 2744fa225cbcSrjs pScreen->SaveScreen = xf86SaveScreen; 2745fa225cbcSrjs pI830->CloseScreen = pScreen->CloseScreen; 2746fa225cbcSrjs pScreen->CloseScreen = I830CloseScreen; 2747fa225cbcSrjs pI830->CreateScreenResources = pScreen->CreateScreenResources; 2748fa225cbcSrjs pScreen->CreateScreenResources = i830CreateScreenResources; 2749fa225cbcSrjs 2750fa225cbcSrjs if (!xf86CrtcScreenInit (pScreen)) 2751fa225cbcSrjs return FALSE; 2752fa225cbcSrjs 2753fa225cbcSrjs DPRINTF(PFX, "assert( if(!miCreateDefColormap(pScreen)) )\n"); 2754fa225cbcSrjs if (!miCreateDefColormap(pScreen)) 2755fa225cbcSrjs return FALSE; 2756fa225cbcSrjs 2757fa225cbcSrjs DPRINTF(PFX, "assert( if(!xf86HandleColormaps(pScreen, ...)) )\n"); 2758fa225cbcSrjs if (!xf86HandleColormaps(pScreen, 256, 8, I830LoadPalette, NULL, 2759fa225cbcSrjs CMAP_RELOAD_ON_MODE_SWITCH | 2760fa225cbcSrjs CMAP_PALETTED_TRUECOLOR)) { 2761fa225cbcSrjs return FALSE; 2762fa225cbcSrjs } 2763fa225cbcSrjs 2764fa225cbcSrjs xf86DPMSInit(pScreen, xf86DPMSSet, 0); 2765fa225cbcSrjs 2766fa225cbcSrjs#ifdef INTEL_XVMC 2767fa225cbcSrjs pI830->XvMCEnabled = FALSE; 2768fa225cbcSrjs from = ((pI830->directRenderingType == DRI_DRI2) && 2769fa225cbcSrjs xf86GetOptValBool(pI830->Options, OPTION_XVMC, 2770fa225cbcSrjs &pI830->XvMCEnabled) ? X_CONFIG : X_DEFAULT); 2771fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, from, "Intel XvMC decoder %sabled\n", 2772fa225cbcSrjs pI830->XvMCEnabled ? "en" : "dis"); 2773fa225cbcSrjs#endif 2774fa225cbcSrjs /* Init video */ 2775fa225cbcSrjs if (pI830->XvEnabled) 2776fa225cbcSrjs I830InitVideo(pScreen); 2777fa225cbcSrjs 2778fa225cbcSrjs /* Setup 3D engine, needed for rotation too */ 2779fa225cbcSrjs IntelEmitInvarientState(pScrn); 2780fa225cbcSrjs 2781fa225cbcSrjs#if defined(DRI2) 2782fa225cbcSrjs switch (pI830->directRenderingType) { 2783fa225cbcSrjs case DRI_DRI2: 2784fa225cbcSrjs pI830->directRenderingOpen = TRUE; 2785fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: DRI2 Enabled\n"); 2786fa225cbcSrjs break; 2787fa225cbcSrjs case DRI_DISABLED: 2788fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Disabled\n"); 2789fa225cbcSrjs break; 2790fa225cbcSrjs case DRI_NONE: 2791fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Failed\n"); 2792fa225cbcSrjs break; 2793fa225cbcSrjs } 2794fa225cbcSrjs#else 2795fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Not available\n"); 2796fa225cbcSrjs#endif 2797fa225cbcSrjs 2798fa225cbcSrjs if (serverGeneration == 1) 2799fa225cbcSrjs xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 2800fa225cbcSrjs 2801fa225cbcSrjs pI830->starting = FALSE; 2802fa225cbcSrjs pI830->closing = FALSE; 2803fa225cbcSrjs pI830->suspended = FALSE; 2804fa225cbcSrjs 2805fa225cbcSrjs return TRUE; 2806fa225cbcSrjs} 2807fa225cbcSrjs 2808fa225cbcSrjsstatic void 2809fa225cbcSrjsi830AdjustFrame(int scrnIndex, int x, int y, int flags) 2810fa225cbcSrjs{ 2811fa225cbcSrjs ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2812fa225cbcSrjs xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 2813fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2814fa225cbcSrjs xf86OutputPtr output = config->output[config->compat_output]; 2815fa225cbcSrjs xf86CrtcPtr crtc = output->crtc; 2816fa225cbcSrjs 2817fa225cbcSrjs DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", 2818fa225cbcSrjs x, crtc->desiredX, y, crtc->desiredY); 2819fa225cbcSrjs 2820fa225cbcSrjs if (pI830->use_drm_mode) 2821fa225cbcSrjs return; 2822fa225cbcSrjs 2823fa225cbcSrjs if (crtc && crtc->enabled) 2824fa225cbcSrjs { 2825fa225cbcSrjs /* Sync the engine before adjust frame */ 2826fa225cbcSrjs I830Sync(pScrn); 2827fa225cbcSrjs i830PipeSetBase(crtc, crtc->desiredX + x, crtc->desiredY + y); 2828fa225cbcSrjs crtc->x = output->initial_x + x; 2829fa225cbcSrjs crtc->y = output->initial_y + y; 2830fa225cbcSrjs } 2831fa225cbcSrjs} 2832fa225cbcSrjs 2833fa225cbcSrjsstatic void 2834fa225cbcSrjsI830FreeScreen(int scrnIndex, int flags) 2835fa225cbcSrjs{ 2836fa225cbcSrjs ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2837fa225cbcSrjs#ifdef INTEL_XVMC 2838fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2839fa225cbcSrjs if (pI830 && pI830->XvMCEnabled) 2840fa225cbcSrjs intel_xvmc_finish(xf86Screens[scrnIndex]); 2841fa225cbcSrjs#endif 2842fa225cbcSrjs 2843fa225cbcSrjs i830_close_drm_master(pScrn); 2844fa225cbcSrjs 2845fa225cbcSrjs I830FreeRec(xf86Screens[scrnIndex]); 2846fa225cbcSrjs if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 2847fa225cbcSrjs vgaHWFreeHWRec(xf86Screens[scrnIndex]); 2848fa225cbcSrjs} 2849fa225cbcSrjs 2850fa225cbcSrjsstatic void 2851fa225cbcSrjsI830LeaveVT(int scrnIndex, int flags) 2852fa225cbcSrjs{ 2853fa225cbcSrjs ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2854fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2855fa225cbcSrjs int ret; 2856fa225cbcSrjs 2857fa225cbcSrjs DPRINTF(PFX, "Leave VT\n"); 2858fa225cbcSrjs 2859fa225cbcSrjs pI830->leaving = TRUE; 2860fa225cbcSrjs 2861fa225cbcSrjs if (pI830->devicesTimer) 2862fa225cbcSrjs TimerFree(pI830->devicesTimer); 2863fa225cbcSrjs pI830->devicesTimer = NULL; 2864fa225cbcSrjs 2865fa225cbcSrjs i830SetHotkeyControl(pScrn, HOTKEY_BIOS_SWITCH); 2866fa225cbcSrjs 2867fa225cbcSrjs xf86RotateFreeShadow(pScrn); 2868fa225cbcSrjs 2869fa225cbcSrjs xf86_hide_cursors (pScrn); 2870fa225cbcSrjs 2871fa225cbcSrjs I830Sync(pScrn); 2872fa225cbcSrjs 2873fa225cbcSrjs if (!pI830->use_drm_mode) { 2874fa225cbcSrjs RestoreHWState(pScrn); 2875fa225cbcSrjs /* Evict everything from the bufmgr, as we're about to lose ownership of 2876fa225cbcSrjs * the graphics memory. 2877fa225cbcSrjs */ 2878fa225cbcSrjs if (!pI830->have_gem) { 2879fa225cbcSrjs intel_bufmgr_fake_evict_all(pI830->bufmgr); 2880fa225cbcSrjs i830_stop_ring(pScrn, TRUE); 2881fa225cbcSrjs } 2882fa225cbcSrjs 2883fa225cbcSrjs if (pI830->debug_modes) { 2884fa225cbcSrjs i830CompareRegsToSnapshot(pScrn, "After LeaveVT"); 2885fa225cbcSrjs i830DumpRegs (pScrn); 2886fa225cbcSrjs } 2887fa225cbcSrjs } 2888fa225cbcSrjs 2889fa225cbcSrjs intel_batch_teardown(pScrn); 2890fa225cbcSrjs 2891fa225cbcSrjs i830_unbind_all_memory(pScrn); 2892fa225cbcSrjs 2893fa225cbcSrjs if (pI830->have_gem && !pI830->use_drm_mode) { 2894fa225cbcSrjs int ret; 2895fa225cbcSrjs 2896fa225cbcSrjs /* Tell the kernel to evict all buffer objects and block GTT usage while 2897fa225cbcSrjs * we're no longer in control of the chip. 2898fa225cbcSrjs */ 2899fa225cbcSrjs ret = drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_LEAVEVT); 2900fa225cbcSrjs if (ret != 0) 2901fa225cbcSrjs FatalError("DRM_I915_LEAVEVT failed: %s\n", strerror(ret)); 2902fa225cbcSrjs } 2903fa225cbcSrjs 2904fa225cbcSrjs if (IS_I965G(pI830)) 2905fa225cbcSrjs gen4_render_state_cleanup(pScrn); 2906fa225cbcSrjs 2907fa225cbcSrjs ret = drmDropMaster(pI830->drmSubFD); 2908fa225cbcSrjs if (ret) 2909fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2910fa225cbcSrjs "drmDropMaster failed: %s\n", strerror(errno)); 2911fa225cbcSrjs} 2912fa225cbcSrjs 2913fa225cbcSrjs/* 2914fa225cbcSrjs * This gets called when gaining control of the VT, and from ScreenInit(). 2915fa225cbcSrjs */ 2916fa225cbcSrjsstatic Bool 2917fa225cbcSrjsI830EnterVT(int scrnIndex, int flags) 2918fa225cbcSrjs{ 2919fa225cbcSrjs ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2920fa225cbcSrjs xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 2921fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 2922fa225cbcSrjs int i, ret; 2923fa225cbcSrjs 2924fa225cbcSrjs DPRINTF(PFX, "Enter VT\n"); 2925fa225cbcSrjs 2926fa225cbcSrjs ret = drmSetMaster(pI830->drmSubFD); 2927fa225cbcSrjs if (ret) { 2928fa225cbcSrjs if (errno == EINVAL) { 2929fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2930fa225cbcSrjs "drmSetMaster failed: 2.6.29 or newer kernel required for " 2931fa225cbcSrjs "multi-server DRI\n"); 2932fa225cbcSrjs } else { 2933fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2934fa225cbcSrjs "drmSetMaster failed: %s\n", strerror(errno)); 2935fa225cbcSrjs } 2936fa225cbcSrjs } 2937fa225cbcSrjs 2938fa225cbcSrjs /* 2939fa225cbcSrjs * Only save state once per server generation since that's what most 2940fa225cbcSrjs * drivers do. Could change this to save state at each VT enter. 2941fa225cbcSrjs */ 2942fa225cbcSrjs if (pI830->SaveGeneration != serverGeneration) { 2943fa225cbcSrjs pI830->SaveGeneration = serverGeneration; 2944fa225cbcSrjs if (!pI830->use_drm_mode) 2945fa225cbcSrjs SaveHWState(pScrn); 2946fa225cbcSrjs } 2947fa225cbcSrjs 2948fa225cbcSrjs /* Get the hardware into a known state if needed */ 2949fa225cbcSrjs if (!pI830->use_drm_mode) { 2950fa225cbcSrjs 2951fa225cbcSrjs I830SwapPipes(pScrn); 2952fa225cbcSrjs 2953fa225cbcSrjs /* Disable outputs */ 2954fa225cbcSrjs for (i = 0; i < xf86_config->num_output; i++) { 2955fa225cbcSrjs xf86OutputPtr output = xf86_config->output[i]; 2956fa225cbcSrjs output->funcs->dpms(output, DPMSModeOff); 2957fa225cbcSrjs } 2958fa225cbcSrjs i830WaitForVblank(pScrn); 2959fa225cbcSrjs 2960fa225cbcSrjs /* Disable pipes */ 2961fa225cbcSrjs for (i = 0; i < xf86_config->num_crtc; i++) { 2962fa225cbcSrjs xf86CrtcPtr crtc = xf86_config->crtc[i]; 2963fa225cbcSrjs i830_crtc_disable(crtc, TRUE); 2964fa225cbcSrjs } 2965fa225cbcSrjs i830WaitForVblank(pScrn); 2966fa225cbcSrjs } 2967fa225cbcSrjs 2968fa225cbcSrjs pI830->leaving = FALSE; 2969fa225cbcSrjs 2970fa225cbcSrjs if (!pI830->use_drm_mode) 2971fa225cbcSrjs i830_disable_render_standby(pScrn); 2972fa225cbcSrjs 2973fa225cbcSrjs if (pI830->have_gem && !pI830->use_drm_mode) { 2974fa225cbcSrjs int ret; 2975fa225cbcSrjs 2976fa225cbcSrjs /* Tell the kernel that we're back in control and ready for GTT 2977fa225cbcSrjs * usage. 2978fa225cbcSrjs */ 2979fa225cbcSrjs ret = drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_ENTERVT); 2980fa225cbcSrjs if (ret != 0) 2981fa225cbcSrjs FatalError("DRM_I915_ENTERVT failed: %s\n", strerror(ret)); 2982fa225cbcSrjs } 2983fa225cbcSrjs 2984fa225cbcSrjs if (!i830_bind_all_memory(pScrn)) 2985fa225cbcSrjs return FALSE; 2986fa225cbcSrjs 2987fa225cbcSrjs i830_describe_allocations(pScrn, 1, ""); 2988fa225cbcSrjs 2989fa225cbcSrjs intel_batch_init(pScrn); 2990fa225cbcSrjs 2991fa225cbcSrjs if (IS_I965G(pI830)) 2992fa225cbcSrjs gen4_render_state_init(pScrn); 2993fa225cbcSrjs 2994fa225cbcSrjs if (!pI830->use_drm_mode) { 2995fa225cbcSrjs if (i830_check_error_state(pScrn)) { 2996fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2997fa225cbcSrjs "Existing errors found in hardware state.\n"); 2998fa225cbcSrjs } 2999fa225cbcSrjs 3000fa225cbcSrjs /* Re-set up the ring. */ 3001fa225cbcSrjs if (!pI830->have_gem) { 3002fa225cbcSrjs i830_stop_ring(pScrn, FALSE); 3003fa225cbcSrjs i830_start_ring(pScrn); 3004fa225cbcSrjs } 3005fa225cbcSrjs I830InitHWCursor(pScrn); 3006fa225cbcSrjs 3007fa225cbcSrjs /* Tell the BIOS that we're in control of mode setting now. */ 3008fa225cbcSrjs i830_init_bios_control(pScrn); 3009fa225cbcSrjs 3010fa225cbcSrjs i830_init_clock_gating(pScrn); 3011fa225cbcSrjs 3012fa225cbcSrjs if (pI830->power_context) 3013fa225cbcSrjs OUTREG(PWRCTXA, pI830->power_context->offset | PWRCTX_EN); 3014fa225cbcSrjs /* Clear the framebuffer */ 3015fa225cbcSrjs memset(pI830->FbBase + pScrn->fbOffset, 0, 3016fa225cbcSrjs pScrn->virtualY * pScrn->displayWidth * pI830->cpp); 3017fa225cbcSrjs } 3018fa225cbcSrjs 3019fa225cbcSrjs if (!xf86SetDesiredModes (pScrn)) 3020fa225cbcSrjs return FALSE; 3021fa225cbcSrjs 3022fa225cbcSrjs if (!pI830->use_drm_mode) { 3023fa225cbcSrjs if (pI830->debug_modes) { 3024fa225cbcSrjs xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardware state at EnterVT:\n"); 3025fa225cbcSrjs i830DumpRegs (pScrn); 3026fa225cbcSrjs } 3027fa225cbcSrjs i830DescribeOutputConfiguration(pScrn); 3028fa225cbcSrjs } 3029fa225cbcSrjs 3030fa225cbcSrjs /* Set the hotkey to just notify us. We could check its results 3031fa225cbcSrjs * periodically and attempt to do something, but it seems like we basically 3032fa225cbcSrjs * never get results when we should, and this should all be better handled 3033fa225cbcSrjs * through ACPI putting the key events out through evdev and your desktop 3034fa225cbcSrjs * environment picking it up. 3035fa225cbcSrjs */ 3036fa225cbcSrjs i830SetHotkeyControl(pScrn, HOTKEY_DRIVER_NOTIFY); 3037fa225cbcSrjs 3038fa225cbcSrjs /* Mark 3D state as being clobbered and setup the basics */ 3039fa225cbcSrjs pI830->last_3d = LAST_3D_OTHER; 3040fa225cbcSrjs IntelEmitInvarientState(pScrn); 3041fa225cbcSrjs 3042fa225cbcSrjs return TRUE; 3043fa225cbcSrjs} 3044fa225cbcSrjs 3045fa225cbcSrjsstatic Bool 3046fa225cbcSrjsI830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 3047fa225cbcSrjs{ 3048fa225cbcSrjs ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3049fa225cbcSrjs 3050fa225cbcSrjs return xf86SetSingleMode (pScrn, mode, RR_Rotate_0); 3051fa225cbcSrjs} 3052fa225cbcSrjs 3053fa225cbcSrjsstatic Bool 3054fa225cbcSrjsI830CloseScreen(int scrnIndex, ScreenPtr pScreen) 3055fa225cbcSrjs{ 3056fa225cbcSrjs ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3057fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 3058fa225cbcSrjs 3059fa225cbcSrjs pI830->closing = TRUE; 3060fa225cbcSrjs 3061fa225cbcSrjs if (pScrn->vtSema == TRUE) { 3062fa225cbcSrjs I830LeaveVT(scrnIndex, 0); 3063fa225cbcSrjs } 3064fa225cbcSrjs 3065fa225cbcSrjs if (pI830->devicesTimer) 3066fa225cbcSrjs TimerFree(pI830->devicesTimer); 3067fa225cbcSrjs pI830->devicesTimer = NULL; 3068fa225cbcSrjs 3069fa225cbcSrjs if (!pI830->use_drm_mode) { 3070fa225cbcSrjs DPRINTF(PFX, "\nUnmapping memory\n"); 3071fa225cbcSrjs I830UnmapMem(pScrn); 3072fa225cbcSrjs vgaHWUnmapMem(pScrn); 3073fa225cbcSrjs } 3074fa225cbcSrjs 3075fa225cbcSrjs if (pI830->uxa_driver) { 3076fa225cbcSrjs uxa_driver_fini (pScreen); 3077fa225cbcSrjs xfree (pI830->uxa_driver); 3078fa225cbcSrjs pI830->uxa_driver = NULL; 3079fa225cbcSrjs } 3080fa225cbcSrjs if (pI830->front_buffer) { 3081fa225cbcSrjs i830_set_pixmap_bo(pScreen->GetScreenPixmap(pScreen), NULL); 3082fa225cbcSrjs if (pI830->use_drm_mode) 3083fa225cbcSrjs drmmode_closefb(pScrn); 3084fa225cbcSrjs i830_free_memory(pScrn, pI830->front_buffer); 3085fa225cbcSrjs pI830->front_buffer = NULL; 3086fa225cbcSrjs } 3087fa225cbcSrjs 3088fa225cbcSrjs xf86_cursors_fini (pScreen); 3089fa225cbcSrjs 3090fa225cbcSrjs i830_allocator_fini(pScrn); 3091fa225cbcSrjs 3092fa225cbcSrjs i965_free_video(pScrn); 3093fa225cbcSrjs free(pI830->offscreenImages); 3094fa225cbcSrjs pI830->offscreenImages = NULL; 3095fa225cbcSrjs 3096fa225cbcSrjs pScreen->CloseScreen = pI830->CloseScreen; 3097fa225cbcSrjs (*pScreen->CloseScreen) (scrnIndex, pScreen); 3098fa225cbcSrjs 3099fa225cbcSrjs if (pI830->directRenderingOpen && pI830->directRenderingType == DRI_DRI2) { 3100fa225cbcSrjs pI830->directRenderingOpen = FALSE; 3101fa225cbcSrjs I830DRI2CloseScreen(pScreen); 3102fa225cbcSrjs } 3103fa225cbcSrjs 3104fa225cbcSrjs xf86GARTCloseScreen(scrnIndex); 3105fa225cbcSrjs 3106fa225cbcSrjs pScrn->vtSema = FALSE; 3107fa225cbcSrjs pI830->closing = FALSE; 3108fa225cbcSrjs return TRUE; 3109fa225cbcSrjs} 3110fa225cbcSrjs 3111fa225cbcSrjsstatic ModeStatus 3112fa225cbcSrjsI830ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) 3113fa225cbcSrjs{ 3114fa225cbcSrjs if (mode->Flags & V_INTERLACE) { 3115fa225cbcSrjs if (verbose) { 3116fa225cbcSrjs xf86DrvMsg(scrnIndex, X_PROBED, 3117fa225cbcSrjs "Removing interlaced mode \"%s\"\n", mode->name); 3118fa225cbcSrjs } 3119fa225cbcSrjs return MODE_BAD; 3120fa225cbcSrjs } 3121fa225cbcSrjs return MODE_OK; 3122fa225cbcSrjs} 3123fa225cbcSrjs 3124fa225cbcSrjs#ifndef SUSPEND_SLEEP 3125fa225cbcSrjs#define SUSPEND_SLEEP 0 3126fa225cbcSrjs#endif 3127fa225cbcSrjs#ifndef RESUME_SLEEP 3128fa225cbcSrjs#define RESUME_SLEEP 0 3129fa225cbcSrjs#endif 3130fa225cbcSrjs 3131fa225cbcSrjs/* 3132fa225cbcSrjs * This function is only required if we need to do anything differently from 3133fa225cbcSrjs * DoApmEvent() in common/xf86PM.c, including if we want to see events other 3134fa225cbcSrjs * than suspend/resume. 3135fa225cbcSrjs */ 3136fa225cbcSrjsstatic Bool 3137fa225cbcSrjsI830PMEvent(int scrnIndex, pmEvent event, Bool undo) 3138fa225cbcSrjs{ 3139fa225cbcSrjs ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3140fa225cbcSrjs I830Ptr pI830 = I830PTR(pScrn); 3141fa225cbcSrjs 3142fa225cbcSrjs DPRINTF(PFX, "Enter VT, event %d, undo: %s\n", event, BOOLTOSTRING(undo)); 3143fa225cbcSrjs 3144fa225cbcSrjs switch(event) { 3145fa225cbcSrjs case XF86_APM_SYS_SUSPEND: 3146fa225cbcSrjs case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend?*/ 3147fa225cbcSrjs case XF86_APM_USER_SUSPEND: 3148fa225cbcSrjs case XF86_APM_SYS_STANDBY: 3149fa225cbcSrjs case XF86_APM_USER_STANDBY: 3150fa225cbcSrjs if (!undo && !pI830->suspended) { 3151fa225cbcSrjs pScrn->LeaveVT(scrnIndex, 0); 3152fa225cbcSrjs pI830->suspended = TRUE; 3153fa225cbcSrjs sleep(SUSPEND_SLEEP); 3154fa225cbcSrjs } else if (undo && pI830->suspended) { 3155fa225cbcSrjs sleep(RESUME_SLEEP); 3156fa225cbcSrjs pScrn->EnterVT(scrnIndex, 0); 3157fa225cbcSrjs pI830->suspended = FALSE; 3158fa225cbcSrjs } 3159fa225cbcSrjs break; 3160fa225cbcSrjs case XF86_APM_STANDBY_RESUME: 3161fa225cbcSrjs case XF86_APM_NORMAL_RESUME: 3162fa225cbcSrjs case XF86_APM_CRITICAL_RESUME: 3163fa225cbcSrjs if (pI830->suspended) { 3164fa225cbcSrjs sleep(RESUME_SLEEP); 3165fa225cbcSrjs pScrn->EnterVT(scrnIndex, 0); 3166fa225cbcSrjs pI830->suspended = FALSE; 3167fa225cbcSrjs /* 3168fa225cbcSrjs * Turn the screen saver off when resuming. This seems to be 3169fa225cbcSrjs * needed to stop xscreensaver kicking in (when used). 3170fa225cbcSrjs * 3171fa225cbcSrjs * XXX DoApmEvent() should probably call this just like 3172fa225cbcSrjs * xf86VTSwitch() does. Maybe do it here only in 4.2 3173fa225cbcSrjs * compatibility mode. 3174fa225cbcSrjs */ 3175fa225cbcSrjs SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); 3176fa225cbcSrjs } 3177fa225cbcSrjs break; 3178fa225cbcSrjs /* This is currently used for ACPI */ 3179fa225cbcSrjs case XF86_APM_CAPABILITY_CHANGED: 3180fa225cbcSrjs ErrorF("I830PMEvent: Capability change\n"); 3181fa225cbcSrjs 3182fa225cbcSrjs SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); 3183fa225cbcSrjs if (pI830->quirk_flag & QUIRK_RESET_MODES) 3184fa225cbcSrjs xf86SetDesiredModes(pScrn); 3185fa225cbcSrjs 3186fa225cbcSrjs break; 3187fa225cbcSrjs default: 3188fa225cbcSrjs ErrorF("I830PMEvent: received APM event %d\n", event); 3189fa225cbcSrjs } 3190fa225cbcSrjs return TRUE; 3191fa225cbcSrjs} 3192fa225cbcSrjs 3193fa225cbcSrjsxf86CrtcPtr 3194fa225cbcSrjsi830_pipe_to_crtc(ScrnInfoPtr pScrn, int pipe) 3195fa225cbcSrjs{ 3196fa225cbcSrjs xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); 3197fa225cbcSrjs int c; 3198fa225cbcSrjs 3199fa225cbcSrjs for (c = 0; c < config->num_crtc; c++) { 3200fa225cbcSrjs xf86CrtcPtr crtc = config->crtc[c]; 3201fa225cbcSrjs I830CrtcPrivatePtr intel_crtc = crtc->driver_private; 3202fa225cbcSrjs 3203fa225cbcSrjs if (intel_crtc->pipe == pipe) 3204fa225cbcSrjs return crtc; 3205fa225cbcSrjs } 3206fa225cbcSrjs 3207fa225cbcSrjs return NULL; 3208fa225cbcSrjs} 3209fa225cbcSrjs 3210fa225cbcSrjsvoid 3211fa225cbcSrjsI830InitpScrn(ScrnInfoPtr pScrn) 3212fa225cbcSrjs{ 3213fa225cbcSrjs pScrn->PreInit = I830PreInit; 3214fa225cbcSrjs pScrn->ScreenInit = I830ScreenInit; 3215fa225cbcSrjs pScrn->SwitchMode = I830SwitchMode; 3216fa225cbcSrjs pScrn->AdjustFrame = i830AdjustFrame; 3217fa225cbcSrjs pScrn->EnterVT = I830EnterVT; 3218fa225cbcSrjs pScrn->LeaveVT = I830LeaveVT; 3219fa225cbcSrjs pScrn->FreeScreen = I830FreeScreen; 3220fa225cbcSrjs pScrn->ValidMode = I830ValidMode; 3221fa225cbcSrjs pScrn->PMEvent = I830PMEvent; 3222fa225cbcSrjs} 3223