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