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