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