1428d7b3dSmrg/**************************************************************************
2428d7b3dSmrg
3428d7b3dSmrgCopyright 2001 VA Linux Systems Inc., Fremont, California.
4428d7b3dSmrgCopyright © 2002 by David Dawes
5428d7b3dSmrg
6428d7b3dSmrgAll Rights Reserved.
7428d7b3dSmrg
8428d7b3dSmrgPermission is hereby granted, free of charge, to any person obtaining a
9428d7b3dSmrgcopy of this software and associated documentation files (the "Software"),
10428d7b3dSmrgto deal in the Software without restriction, including without limitation
11428d7b3dSmrgon the rights to use, copy, modify, merge, publish, distribute, sub
12428d7b3dSmrglicense, and/or sell copies of the Software, and to permit persons to whom
13428d7b3dSmrgthe Software is furnished to do so, subject to the following conditions:
14428d7b3dSmrg
15428d7b3dSmrgThe above copyright notice and this permission notice (including the next
16428d7b3dSmrgparagraph) shall be included in all copies or substantial portions of the
17428d7b3dSmrgSoftware.
18428d7b3dSmrg
19428d7b3dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20428d7b3dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21428d7b3dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22428d7b3dSmrgTHE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23428d7b3dSmrgDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24428d7b3dSmrgOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25428d7b3dSmrgUSE OR OTHER DEALINGS IN THE SOFTWARE.
26428d7b3dSmrg
27428d7b3dSmrg**************************************************************************/
28428d7b3dSmrg
29428d7b3dSmrg/*
30428d7b3dSmrg * Authors: Jeff Hartmann <jhartmann@valinux.com>
31428d7b3dSmrg *          Abraham van der Merwe <abraham@2d3d.co.za>
32428d7b3dSmrg *          David Dawes <dawes@xfree86.org>
33428d7b3dSmrg *          Alan Hourihane <alanh@tungstengraphics.com>
34428d7b3dSmrg */
35428d7b3dSmrg
36428d7b3dSmrg#ifdef HAVE_CONFIG_H
37428d7b3dSmrg#include "config.h"
38428d7b3dSmrg#endif
39428d7b3dSmrg
40428d7b3dSmrg#include <assert.h>
41428d7b3dSmrg#include <string.h>
42428d7b3dSmrg#include <stdio.h>
43428d7b3dSmrg#include <unistd.h>
44428d7b3dSmrg#include <stdlib.h>
45428d7b3dSmrg#include <stdio.h>
46428d7b3dSmrg#include <errno.h>
47428d7b3dSmrg
48428d7b3dSmrg#include "xorg-server.h"
49428d7b3dSmrg#include "xf86.h"
50428d7b3dSmrg#include "xf86_OSproc.h"
51428d7b3dSmrg#include "xf86cmap.h"
52428d7b3dSmrg#include "xf86drm.h"
53428d7b3dSmrg#include "compiler.h"
54428d7b3dSmrg#include "mipointer.h"
55428d7b3dSmrg#include "micmap.h"
56428d7b3dSmrg#include <X11/extensions/randr.h>
57428d7b3dSmrg#include "fb.h"
58428d7b3dSmrg#include "miscstruct.h"
59428d7b3dSmrg#include "dixstruct.h"
60428d7b3dSmrg#include "xf86xv.h"
61428d7b3dSmrg#include "shadow.h"
62428d7b3dSmrg#include "intel.h"
63428d7b3dSmrg#include "intel_video.h"
64428d7b3dSmrg#include "uxa_module.h"
65428d7b3dSmrg
66428d7b3dSmrg#ifdef INTEL_XVMC
67428d7b3dSmrg#define _INTEL_XVMC_SERVER_
68428d7b3dSmrg#include "intel_xvmc.h"
69428d7b3dSmrg#endif
70428d7b3dSmrg
71428d7b3dSmrg#if USE_UXA
72428d7b3dSmrg#include "intel_uxa.h"
73428d7b3dSmrg#endif
74428d7b3dSmrg
75428d7b3dSmrg#include "intel_options.h"
76428d7b3dSmrg#include "i915_drm.h"
77428d7b3dSmrg
78428d7b3dSmrgstatic void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL);
79428d7b3dSmrgstatic Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL);
80428d7b3dSmrgstatic Bool I830EnterVT(VT_FUNC_ARGS_DECL);
81428d7b3dSmrg
82428d7b3dSmrg/* temporary */
83428d7b3dSmrgextern void xf86SetCursor(ScreenPtr screen, CursorPtr pCurs, int x, int y);
84428d7b3dSmrg
85428d7b3dSmrg/* Export I830 options to i830 driver where necessary */
86428d7b3dSmrgstatic void
87428d7b3dSmrgI830LoadPalette(ScrnInfoPtr scrn, int numColors, int *indices,
88428d7b3dSmrg		LOCO * colors, VisualPtr pVisual)
89428d7b3dSmrg{
90428d7b3dSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
91428d7b3dSmrg	int i, j, index;
92428d7b3dSmrg	int p;
93428d7b3dSmrg	uint16_t lut_r[256], lut_g[256], lut_b[256];
94428d7b3dSmrg
95428d7b3dSmrg	for (p = 0; p < xf86_config->num_crtc; p++) {
96428d7b3dSmrg		xf86CrtcPtr crtc = xf86_config->crtc[p];
97428d7b3dSmrg
98428d7b3dSmrg		switch (scrn->depth) {
99428d7b3dSmrg		case 15:
100428d7b3dSmrg			for (i = 0; i < numColors; i++) {
101428d7b3dSmrg				index = indices[i];
102428d7b3dSmrg				for (j = 0; j < 8; j++) {
103428d7b3dSmrg					lut_r[index * 8 + j] =
104428d7b3dSmrg					    colors[index].red << 8;
105428d7b3dSmrg					lut_g[index * 8 + j] =
106428d7b3dSmrg					    colors[index].green << 8;
107428d7b3dSmrg					lut_b[index * 8 + j] =
108428d7b3dSmrg					    colors[index].blue << 8;
109428d7b3dSmrg				}
110428d7b3dSmrg			}
111428d7b3dSmrg			break;
112428d7b3dSmrg		case 16:
113428d7b3dSmrg			for (i = 0; i < numColors; i++) {
114428d7b3dSmrg				index = indices[i];
115428d7b3dSmrg
116428d7b3dSmrg				if (index <= 31) {
117428d7b3dSmrg					for (j = 0; j < 8; j++) {
118428d7b3dSmrg						lut_r[index * 8 + j] =
119428d7b3dSmrg						    colors[index].red << 8;
120428d7b3dSmrg						lut_b[index * 8 + j] =
121428d7b3dSmrg						    colors[index].blue << 8;
122428d7b3dSmrg					}
123428d7b3dSmrg				}
124428d7b3dSmrg
125428d7b3dSmrg				for (j = 0; j < 4; j++) {
126428d7b3dSmrg					lut_g[index * 4 + j] =
127428d7b3dSmrg					    colors[index].green << 8;
128428d7b3dSmrg				}
129428d7b3dSmrg			}
130428d7b3dSmrg			break;
131428d7b3dSmrg		default:
132428d7b3dSmrg			for (i = 0; i < numColors; i++) {
133428d7b3dSmrg				index = indices[i];
134428d7b3dSmrg				lut_r[index] = colors[index].red << 8;
135428d7b3dSmrg				lut_g[index] = colors[index].green << 8;
136428d7b3dSmrg				lut_b[index] = colors[index].blue << 8;
137428d7b3dSmrg			}
138428d7b3dSmrg			break;
139428d7b3dSmrg		}
140428d7b3dSmrg
141428d7b3dSmrg		/* Make the change through RandR */
142428d7b3dSmrg#ifdef RANDR_12_INTERFACE
143428d7b3dSmrg		RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
144428d7b3dSmrg#else
145428d7b3dSmrg		crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
146428d7b3dSmrg#endif
147428d7b3dSmrg	}
148428d7b3dSmrg}
149428d7b3dSmrg
150428d7b3dSmrg/**
151428d7b3dSmrg * Adjust the screen pixmap for the current location of the front buffer.
152428d7b3dSmrg * This is done at EnterVT when buffers are bound as long as the resources
153428d7b3dSmrg * have already been created, but the first EnterVT happens before
154428d7b3dSmrg * CreateScreenResources.
155428d7b3dSmrg */
156428d7b3dSmrgstatic Bool i830CreateScreenResources(ScreenPtr screen)
157428d7b3dSmrg{
158428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
159428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
160428d7b3dSmrg
161428d7b3dSmrg	screen->CreateScreenResources = intel->CreateScreenResources;
162428d7b3dSmrg	if (!(*screen->CreateScreenResources) (screen))
163428d7b3dSmrg		return FALSE;
164428d7b3dSmrg
165428d7b3dSmrg	if (!intel_uxa_create_screen_resources(screen))
166428d7b3dSmrg		return FALSE;
167428d7b3dSmrg
168428d7b3dSmrg	intel_copy_fb(scrn);
169428d7b3dSmrg	return TRUE;
170428d7b3dSmrg}
171428d7b3dSmrg
172428d7b3dSmrgvoid
173428d7b3dSmrgintel_set_pixmap_bo(PixmapPtr pixmap, dri_bo *bo)
174428d7b3dSmrg{
175428d7b3dSmrg        intel_uxa_set_pixmap_bo(pixmap, bo);
176428d7b3dSmrg}
177428d7b3dSmrg
178428d7b3dSmrgdri_bo *
179428d7b3dSmrgintel_get_pixmap_bo(PixmapPtr pixmap)
180428d7b3dSmrg{
181428d7b3dSmrg        return intel_uxa_get_pixmap_bo(pixmap);
182428d7b3dSmrg}
183428d7b3dSmrg
184428d7b3dSmrgvoid
185428d7b3dSmrgintel_flush(intel_screen_private *intel)
186428d7b3dSmrg{
187428d7b3dSmrg        intel_batch_submit(intel->scrn);
188428d7b3dSmrg}
189428d7b3dSmrg
190428d7b3dSmrgstatic void PreInitCleanup(ScrnInfoPtr scrn)
191428d7b3dSmrg{
192428d7b3dSmrg	if (!scrn || !scrn->driverPrivate)
193428d7b3dSmrg		return;
194428d7b3dSmrg
195428d7b3dSmrg	free(scrn->driverPrivate);
196428d7b3dSmrg	scrn->driverPrivate = NULL;
197428d7b3dSmrg}
198428d7b3dSmrg
199428d7b3dSmrgstatic void intel_check_chipset_option(ScrnInfoPtr scrn)
200428d7b3dSmrg{
201428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
202428d7b3dSmrg	intel_detect_chipset(scrn, intel->dev);
203428d7b3dSmrg}
204428d7b3dSmrg
205428d7b3dSmrgstatic Bool I830GetEarlyOptions(ScrnInfoPtr scrn)
206428d7b3dSmrg{
207428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
208428d7b3dSmrg
209428d7b3dSmrg	/* Process the options */
210428d7b3dSmrg	intel->Options = intel_options_get(scrn);
211428d7b3dSmrg	if (!intel->Options)
212428d7b3dSmrg		return FALSE;
213428d7b3dSmrg
214428d7b3dSmrg#if USE_UXA
215428d7b3dSmrg	intel->fallback_debug = xf86ReturnOptValBool(intel->Options,
216428d7b3dSmrg						     OPTION_FALLBACKDEBUG,
217428d7b3dSmrg						     FALSE);
218428d7b3dSmrg
219428d7b3dSmrg	intel->debug_flush = 0;
220428d7b3dSmrg
221428d7b3dSmrg	if (xf86ReturnOptValBool(intel->Options,
222428d7b3dSmrg				 OPTION_DEBUG_FLUSH_BATCHES,
223428d7b3dSmrg				 FALSE))
224428d7b3dSmrg		intel->debug_flush |= DEBUG_FLUSH_BATCHES;
225428d7b3dSmrg
226428d7b3dSmrg	if (xf86ReturnOptValBool(intel->Options,
227428d7b3dSmrg				 OPTION_DEBUG_FLUSH_CACHES,
228428d7b3dSmrg				 FALSE))
229428d7b3dSmrg		intel->debug_flush |= DEBUG_FLUSH_CACHES;
230428d7b3dSmrg
231428d7b3dSmrg	if (xf86ReturnOptValBool(intel->Options,
232428d7b3dSmrg				 OPTION_DEBUG_WAIT,
233428d7b3dSmrg				 FALSE))
234428d7b3dSmrg		intel->debug_flush |= DEBUG_FLUSH_WAIT;
235428d7b3dSmrg
236428d7b3dSmrg#endif
237428d7b3dSmrg	return TRUE;
238428d7b3dSmrg}
239428d7b3dSmrg
240428d7b3dSmrgstatic Bool intel_option_cast_string_to_bool(intel_screen_private *intel,
241428d7b3dSmrg					     int id, Bool val)
242428d7b3dSmrg{
243428d7b3dSmrg#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
244428d7b3dSmrg	xf86getBoolValue(&val, xf86GetOptValString(intel->Options, id));
245428d7b3dSmrg	return val;
246428d7b3dSmrg#else
247428d7b3dSmrg	return val;
248428d7b3dSmrg#endif
249428d7b3dSmrg}
250428d7b3dSmrg
251428d7b3dSmrgstatic void intel_check_dri_option(ScrnInfoPtr scrn)
252428d7b3dSmrg{
253428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
254428d7b3dSmrg
255428d7b3dSmrg	intel->dri2 = intel->dri3 = DRI_NONE;
256428d7b3dSmrg	if (!intel_option_cast_string_to_bool(intel, OPTION_DRI, TRUE))
257428d7b3dSmrg		intel->dri2 = intel->dri3 = DRI_DISABLED;
258428d7b3dSmrg
259428d7b3dSmrg	if (scrn->depth != 16 && scrn->depth != 24 && scrn->depth != 30) {
260428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
261428d7b3dSmrg			   "DRI is disabled because it "
262428d7b3dSmrg			   "runs only at depths 16, 24, and 30.\n");
263428d7b3dSmrg		intel->dri2 = intel->dri3 = DRI_DISABLED;
264428d7b3dSmrg	}
265428d7b3dSmrg}
266428d7b3dSmrg
267428d7b3dSmrgstatic Bool intel_open_drm_master(ScrnInfoPtr scrn)
268428d7b3dSmrg{
269428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
270428d7b3dSmrg	intel->dev = intel_get_device(scrn, &intel->drmSubFD);
271428d7b3dSmrg	return intel->dev != NULL;
272428d7b3dSmrg}
273428d7b3dSmrg
274428d7b3dSmrgstatic int intel_init_bufmgr(intel_screen_private *intel)
275428d7b3dSmrg{
276428d7b3dSmrg	int batch_size;
277428d7b3dSmrg
278428d7b3dSmrg	batch_size = 4096 * 4;
279428d7b3dSmrg	if (IS_I865G(intel))
280428d7b3dSmrg		/* The 865 has issues with larger-than-page-sized batch buffers. */
281428d7b3dSmrg		batch_size = 4096;
282428d7b3dSmrg
283428d7b3dSmrg	intel->bufmgr = drm_intel_bufmgr_gem_init(intel->drmSubFD, batch_size);
284428d7b3dSmrg	if (!intel->bufmgr)
285428d7b3dSmrg		return FALSE;
286428d7b3dSmrg
287428d7b3dSmrg	if (xf86ReturnOptValBool(intel->Options, OPTION_BUFFER_CACHE, TRUE))
288428d7b3dSmrg		drm_intel_bufmgr_gem_enable_reuse(intel->bufmgr);
289428d7b3dSmrg	drm_intel_bufmgr_gem_set_vma_cache_size(intel->bufmgr, 512);
290428d7b3dSmrg	drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr);
291428d7b3dSmrg
292428d7b3dSmrg	list_init(&intel->batch_pixmaps);
293428d7b3dSmrg
294428d7b3dSmrg	if ((INTEL_INFO(intel)->gen == 060)) {
295428d7b3dSmrg		intel->wa_scratch_bo =
296428d7b3dSmrg			drm_intel_bo_alloc(intel->bufmgr, "wa scratch",
297428d7b3dSmrg					   4096, 4096);
298428d7b3dSmrg	}
299428d7b3dSmrg
300428d7b3dSmrg	return TRUE;
301428d7b3dSmrg}
302428d7b3dSmrg
303428d7b3dSmrgstatic void intel_bufmgr_fini(intel_screen_private *intel)
304428d7b3dSmrg{
305428d7b3dSmrg	if (intel->bufmgr == NULL)
306428d7b3dSmrg		return;
307428d7b3dSmrg
308428d7b3dSmrg	drm_intel_bo_unreference(intel->wa_scratch_bo);
309428d7b3dSmrg	drm_intel_bufmgr_destroy(intel->bufmgr);
310428d7b3dSmrg}
311428d7b3dSmrg
312428d7b3dSmrgstatic void I830XvInit(ScrnInfoPtr scrn)
313428d7b3dSmrg{
314428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
315428d7b3dSmrg	MessageType from = X_PROBED;
316428d7b3dSmrg
317428d7b3dSmrg	intel->XvPreferOverlay =
318428d7b3dSmrg	    xf86ReturnOptValBool(intel->Options, OPTION_PREFER_OVERLAY, FALSE);
319428d7b3dSmrg
320428d7b3dSmrg	if (xf86GetOptValInteger(intel->Options, OPTION_VIDEO_KEY,
321428d7b3dSmrg				 &(intel->colorKey))) {
322428d7b3dSmrg		from = X_CONFIG;
323428d7b3dSmrg	} else if (xf86GetOptValInteger(intel->Options, OPTION_COLOR_KEY,
324428d7b3dSmrg					&(intel->colorKey))) {
325428d7b3dSmrg		from = X_CONFIG;
326428d7b3dSmrg	} else {
327428d7b3dSmrg		intel->colorKey =
328428d7b3dSmrg		    (1 << scrn->offset.red) | (1 << scrn->offset.green) |
329428d7b3dSmrg		    (((scrn->mask.blue >> scrn->offset.blue) - 1) <<
330428d7b3dSmrg		     scrn->offset.blue);
331428d7b3dSmrg		from = X_DEFAULT;
332428d7b3dSmrg	}
333428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, from, "video overlay key set to 0x%x\n",
334428d7b3dSmrg		   intel->colorKey);
335428d7b3dSmrg}
336428d7b3dSmrg
337428d7b3dSmrgstatic Bool drm_has_boolean_param(struct intel_screen_private *intel,
338428d7b3dSmrg				  int param)
339428d7b3dSmrg{
340428d7b3dSmrg	drm_i915_getparam_t gp;
341428d7b3dSmrg	int value;
342428d7b3dSmrg
343428d7b3dSmrg	gp.value = &value;
344428d7b3dSmrg	gp.param = param;
345428d7b3dSmrg	if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp))
346428d7b3dSmrg		return FALSE;
347428d7b3dSmrg
348428d7b3dSmrg	return value;
349428d7b3dSmrg}
350428d7b3dSmrg
351428d7b3dSmrgstatic Bool has_kernel_flush(struct intel_screen_private *intel)
352428d7b3dSmrg{
353428d7b3dSmrg	/* The BLT ring was introduced at the same time as the
354428d7b3dSmrg	 * automatic flush for the busy-ioctl.
355428d7b3dSmrg	 */
356428d7b3dSmrg	return drm_has_boolean_param(intel, I915_PARAM_HAS_BLT);
357428d7b3dSmrg}
358428d7b3dSmrg
359428d7b3dSmrgstatic Bool has_relaxed_fencing(struct intel_screen_private *intel)
360428d7b3dSmrg{
361428d7b3dSmrg	return drm_has_boolean_param(intel, I915_PARAM_HAS_RELAXED_FENCING);
362428d7b3dSmrg}
363428d7b3dSmrg
364428d7b3dSmrgstatic Bool has_prime_vmap_flush(struct intel_screen_private *intel)
365428d7b3dSmrg{
366428d7b3dSmrg	return drm_has_boolean_param(intel, I915_PARAM_HAS_PRIME_VMAP_FLUSH);
367428d7b3dSmrg}
368428d7b3dSmrg
369428d7b3dSmrgstatic Bool can_accelerate_blt(struct intel_screen_private *intel)
370428d7b3dSmrg{
371428d7b3dSmrg	if (INTEL_INFO(intel)->gen == -1)
372428d7b3dSmrg		return FALSE;
373428d7b3dSmrg
374428d7b3dSmrg	if (xf86ReturnOptValBool(intel->Options, OPTION_ACCEL_DISABLE, FALSE) ||
375428d7b3dSmrg	    !intel_option_cast_string_to_bool(intel, OPTION_ACCEL_METHOD, TRUE)) {
376428d7b3dSmrg		xf86DrvMsg(intel->scrn->scrnIndex, X_CONFIG,
377428d7b3dSmrg			   "Disabling hardware acceleration.\n");
378428d7b3dSmrg		return FALSE;
379428d7b3dSmrg	}
380428d7b3dSmrg
381428d7b3dSmrg	if (INTEL_INFO(intel)->gen == 060) {
382428d7b3dSmrg		struct pci_device *const device = xf86GetPciInfoForEntity(intel->pEnt->index);
383428d7b3dSmrg
384428d7b3dSmrg		/* Sandybridge rev07 locks up easily, even with the
385428d7b3dSmrg		 * BLT ring workaround in place.
386428d7b3dSmrg		 * Thus use shadowfb by default.
387428d7b3dSmrg		 */
388428d7b3dSmrg		if (device->revision < 8) {
389428d7b3dSmrg			xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING,
390428d7b3dSmrg				   "Disabling hardware acceleration on this pre-production hardware.\n");
391428d7b3dSmrg
392428d7b3dSmrg			return FALSE;
393428d7b3dSmrg		}
394428d7b3dSmrg	}
395428d7b3dSmrg
396428d7b3dSmrg	if (INTEL_INFO(intel)->gen >= 060) {
397428d7b3dSmrg		drm_i915_getparam_t gp;
398428d7b3dSmrg		int value;
399428d7b3dSmrg
400428d7b3dSmrg		/* On Sandybridge we need the BLT in order to do anything since
401428d7b3dSmrg		 * it so frequently used in the acceleration code paths.
402428d7b3dSmrg		 */
403428d7b3dSmrg		gp.value = &value;
404428d7b3dSmrg		gp.param = I915_PARAM_HAS_BLT;
405428d7b3dSmrg		if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp))
406428d7b3dSmrg			return FALSE;
407428d7b3dSmrg	}
408428d7b3dSmrg
409428d7b3dSmrg	return TRUE;
410428d7b3dSmrg}
411428d7b3dSmrg
412428d7b3dSmrgstatic void intel_setup_capabilities(ScrnInfoPtr scrn)
413428d7b3dSmrg{
414428d7b3dSmrg#ifdef INTEL_PIXMAP_SHARING
415428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
416428d7b3dSmrg	uint64_t value;
417428d7b3dSmrg	int ret;
418428d7b3dSmrg
419428d7b3dSmrg	scrn->capabilities = 0;
420428d7b3dSmrg
421428d7b3dSmrg	ret = drmGetCap(intel->drmSubFD, DRM_CAP_PRIME, &value);
422428d7b3dSmrg	if (ret == 0) {
423428d7b3dSmrg		if (value & DRM_PRIME_CAP_EXPORT)
424428d7b3dSmrg			scrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload;
425428d7b3dSmrg		if (value & DRM_PRIME_CAP_IMPORT)
426428d7b3dSmrg			scrn->capabilities |= RR_Capability_SinkOutput;
427428d7b3dSmrg	}
428428d7b3dSmrg#endif
429428d7b3dSmrg}
430428d7b3dSmrg
431428d7b3dSmrg/**
432428d7b3dSmrg * This is called before ScreenInit to do any require probing of screen
433428d7b3dSmrg * configuration.
434428d7b3dSmrg *
435428d7b3dSmrg * This code generally covers probing, module loading, option handling
436428d7b3dSmrg * card mapping, and RandR setup.
437428d7b3dSmrg *
438428d7b3dSmrg * Since xf86InitialConfiguration ends up requiring that we set video modes
439428d7b3dSmrg * in order to detect configuration, we end up having to do a lot of driver
440428d7b3dSmrg * setup (talking to the DRM, mapping the device, etc.) in this function.
441428d7b3dSmrg * As a result, we want to set up that server initialization once rather
442428d7b3dSmrg * that doing it per generation.
443428d7b3dSmrg */
444428d7b3dSmrgstatic Bool I830PreInit(ScrnInfoPtr scrn, int flags)
445428d7b3dSmrg{
446428d7b3dSmrg	intel_screen_private *intel;
447428d7b3dSmrg	rgb defaultWeight = { 0, 0, 0 };
448428d7b3dSmrg	EntityInfoPtr pEnt;
449428d7b3dSmrg	int flags24;
450428d7b3dSmrg	Gamma zeros = { 0.0, 0.0, 0.0 };
451428d7b3dSmrg
452428d7b3dSmrg	if (scrn->numEntities != 1)
453428d7b3dSmrg		return FALSE;
454428d7b3dSmrg
455428d7b3dSmrg	pEnt = xf86GetEntityInfo(scrn->entityList[0]);
456428d7b3dSmrg	if (pEnt == NULL)
457428d7b3dSmrg		return FALSE;
458428d7b3dSmrg
459428d7b3dSmrg	if (pEnt->location.type != BUS_PCI
460428d7b3dSmrg#ifdef XSERVER_PLATFORM_BUS
461428d7b3dSmrg	    && pEnt->location.type != BUS_PLATFORM
462428d7b3dSmrg#endif
463428d7b3dSmrg		)
464428d7b3dSmrg		return FALSE;
465428d7b3dSmrg
466428d7b3dSmrg	if (flags & PROBE_DETECT)
467428d7b3dSmrg		return TRUE;
468428d7b3dSmrg
469428d7b3dSmrg	if (((uintptr_t)scrn->driverPrivate) & 3) {
470428d7b3dSmrg		intel = xnfcalloc(sizeof(*intel), 1);
471428d7b3dSmrg		if (intel == NULL)
472428d7b3dSmrg			return FALSE;
473428d7b3dSmrg
474428d7b3dSmrg		intel->info = (void *)((uintptr_t)scrn->driverPrivate & ~3);
475428d7b3dSmrg		scrn->driverPrivate = intel;
476428d7b3dSmrg	}
477428d7b3dSmrg	intel = intel_get_screen_private(scrn);
478428d7b3dSmrg	intel->scrn = scrn;
479428d7b3dSmrg	intel->pEnt = pEnt;
480428d7b3dSmrg
481428d7b3dSmrg	scrn->displayWidth = 640;	/* default it */
482428d7b3dSmrg
483428d7b3dSmrg	if (!intel_open_drm_master(scrn)) {
484428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
485428d7b3dSmrg			   "Failed to become DRM master.\n");
486428d7b3dSmrg		return FALSE;
487428d7b3dSmrg	}
488428d7b3dSmrg
489428d7b3dSmrg	scrn->monitor = scrn->confScreen->monitor;
490428d7b3dSmrg	scrn->progClock = TRUE;
491428d7b3dSmrg	scrn->rgbBits = 8;
492428d7b3dSmrg
493428d7b3dSmrg	flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32;
494428d7b3dSmrg
495428d7b3dSmrg	if (!xf86SetDepthBpp(scrn, 0, 0, 0, flags24))
496428d7b3dSmrg		return FALSE;
497428d7b3dSmrg
498428d7b3dSmrg	switch (scrn->depth) {
499428d7b3dSmrg	case 15:
500428d7b3dSmrg	case 16:
501428d7b3dSmrg	case 24:
502428d7b3dSmrg	case 30:
503428d7b3dSmrg		break;
504428d7b3dSmrg	case 8:
505428d7b3dSmrg	default:
506428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
507428d7b3dSmrg			   "Given depth (%d) is not supported by intel driver\n",
508428d7b3dSmrg			   scrn->depth);
509428d7b3dSmrg		return FALSE;
510428d7b3dSmrg	}
511428d7b3dSmrg	xf86PrintDepthBpp(scrn);
512428d7b3dSmrg
513428d7b3dSmrg	if (!xf86SetWeight(scrn, defaultWeight, defaultWeight))
514428d7b3dSmrg		return FALSE;
515428d7b3dSmrg	if (!xf86SetDefaultVisual(scrn, -1))
516428d7b3dSmrg		return FALSE;
517428d7b3dSmrg
518428d7b3dSmrg	intel->cpp = scrn->bitsPerPixel / 8;
519428d7b3dSmrg
520428d7b3dSmrg	if (!I830GetEarlyOptions(scrn))
521428d7b3dSmrg		return FALSE;
522428d7b3dSmrg
523428d7b3dSmrg	intel_setup_capabilities(scrn);
524428d7b3dSmrg	intel_check_chipset_option(scrn);
525428d7b3dSmrg	intel_check_dri_option(scrn);
526428d7b3dSmrg
527428d7b3dSmrg	if (!intel_init_bufmgr(intel)) {
528428d7b3dSmrg		PreInitCleanup(scrn);
529428d7b3dSmrg		return FALSE;
530428d7b3dSmrg	}
531428d7b3dSmrg
532428d7b3dSmrg	intel->force_fallback =
533428d7b3dSmrg		drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE) != 0;
534428d7b3dSmrg
535428d7b3dSmrg	/* Enable tiling by default */
536428d7b3dSmrg	intel->tiling = INTEL_TILING_ALL;
537428d7b3dSmrg
538428d7b3dSmrg	/* Allow user override if they set a value */
539428d7b3dSmrg	if (!xf86ReturnOptValBool(intel->Options, OPTION_TILING_2D, TRUE))
540428d7b3dSmrg		intel->tiling &= ~INTEL_TILING_2D;
541428d7b3dSmrg	if (xf86ReturnOptValBool(intel->Options, OPTION_TILING_FB, FALSE))
542428d7b3dSmrg		intel->tiling &= ~INTEL_TILING_FB;
543428d7b3dSmrg	if (!can_accelerate_blt(intel)) {
544428d7b3dSmrg		intel->force_fallback = TRUE;
545428d7b3dSmrg		intel->tiling &= ~INTEL_TILING_FB;
546428d7b3dSmrg	}
547428d7b3dSmrg
548428d7b3dSmrg	intel->has_kernel_flush = has_kernel_flush(intel);
549428d7b3dSmrg
550428d7b3dSmrg	intel->has_prime_vmap_flush = has_prime_vmap_flush(intel);
551428d7b3dSmrg
552428d7b3dSmrg	intel->has_relaxed_fencing = INTEL_INFO(intel)->gen >= 033;
553428d7b3dSmrg	/* And override the user if there is no kernel support */
554428d7b3dSmrg	if (intel->has_relaxed_fencing)
555428d7b3dSmrg		intel->has_relaxed_fencing = has_relaxed_fencing(intel);
556428d7b3dSmrg
557428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
558428d7b3dSmrg		   "Relaxed fencing %s\n",
559428d7b3dSmrg		   intel->has_relaxed_fencing ? "enabled" : "disabled");
560428d7b3dSmrg
561428d7b3dSmrg	/* SwapBuffers delays to avoid tearing */
562428d7b3dSmrg	intel->swapbuffers_wait = xf86ReturnOptValBool(intel->Options,
563428d7b3dSmrg						       OPTION_SWAPBUFFERS_WAIT,
564428d7b3dSmrg						       TRUE);
565428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Wait on SwapBuffers? %s\n",
566428d7b3dSmrg		   intel->swapbuffers_wait ? "enabled" : "disabled");
567428d7b3dSmrg
568428d7b3dSmrg	intel->use_triple_buffer =
569428d7b3dSmrg		xf86ReturnOptValBool(intel->Options,
570428d7b3dSmrg				     OPTION_TRIPLE_BUFFER,
571428d7b3dSmrg				     TRUE);
572428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Triple buffering? %s\n",
573428d7b3dSmrg		   intel->use_triple_buffer ? "enabled" : "disabled");
574428d7b3dSmrg
575428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Framebuffer %s\n",
576428d7b3dSmrg		   intel->tiling & INTEL_TILING_FB ? "tiled" : "linear");
577428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Pixmaps %s\n",
578428d7b3dSmrg		   intel->tiling & INTEL_TILING_2D ? "tiled" : "linear");
579428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "3D buffers %s\n",
580428d7b3dSmrg		   intel->tiling & INTEL_TILING_3D ? "tiled" : "linear");
581428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "SwapBuffers wait %sabled\n",
582428d7b3dSmrg		   intel->swapbuffers_wait ? "en" : "dis");
583428d7b3dSmrg
584428d7b3dSmrg	I830XvInit(scrn);
585428d7b3dSmrg
586428d7b3dSmrg	if (!intel_mode_pre_init(scrn, intel->drmSubFD, intel->cpp)) {
587428d7b3dSmrg		PreInitCleanup(scrn);
588428d7b3dSmrg		return FALSE;
589428d7b3dSmrg	}
590428d7b3dSmrg
591428d7b3dSmrg	if (!xf86SetGamma(scrn, zeros)) {
592428d7b3dSmrg		PreInitCleanup(scrn);
593428d7b3dSmrg		return FALSE;
594428d7b3dSmrg	}
595428d7b3dSmrg
596428d7b3dSmrg	if (scrn->modes == NULL) {
597428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR, "No modes.\n");
598428d7b3dSmrg		PreInitCleanup(scrn);
599428d7b3dSmrg		return FALSE;
600428d7b3dSmrg	}
601428d7b3dSmrg	scrn->currentMode = scrn->modes;
602428d7b3dSmrg
603428d7b3dSmrg	/* Set display resolution */
604428d7b3dSmrg	xf86SetDpi(scrn, 0, 0);
605428d7b3dSmrg
606428d7b3dSmrg	/* Load the required sub modules */
607428d7b3dSmrg	if (!xf86LoadSubModule(scrn, "fb")) {
608428d7b3dSmrg		PreInitCleanup(scrn);
609428d7b3dSmrg		return FALSE;
610428d7b3dSmrg	}
611428d7b3dSmrg
612428d7b3dSmrg	/* Load the dri modules if requested. */
613428d7b3dSmrg#if HAVE_DRI2
614428d7b3dSmrg	if (intel->dri2 != DRI_DISABLED && !xf86LoadSubModule(scrn, "dri2"))
615428d7b3dSmrg		intel->dri2 = DRI_DISABLED;
616428d7b3dSmrg#endif
617428d7b3dSmrg#if HAVE_DRI3
618428d7b3dSmrg	if (intel->dri3 != DRI_DISABLED && !xf86LoadSubModule(scrn, "dri3"))
619428d7b3dSmrg		intel->dri3 = DRI_DISABLED;
620428d7b3dSmrg#endif
621428d7b3dSmrg
622428d7b3dSmrg	return TRUE;
623428d7b3dSmrg}
624428d7b3dSmrg
625428d7b3dSmrg#ifdef INTEL_PIXMAP_SHARING
626a7f02474Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 25
627a7f02474Smrg#define slave_dst secondary_dst
628a7f02474Smrg#define master_pixmap primary_pixmap
629a7f02474Smrg#endif
630428d7b3dSmrgstatic void
631428d7b3dSmrgredisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
632428d7b3dSmrg{
633428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
634428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
635428d7b3dSmrg	RegionRec pixregion;
636428d7b3dSmrg	int was_blocked;
637428d7b3dSmrg
638428d7b3dSmrg	PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap);
639428d7b3dSmrg	RegionTranslate(&pixregion, dirty->x, dirty->y);
640428d7b3dSmrg	RegionIntersect(&pixregion, &pixregion, DamageRegion(dirty->damage));
641428d7b3dSmrg	RegionTranslate(&pixregion, -dirty->x, -dirty->y);
642428d7b3dSmrg	was_blocked = RegionNil(&pixregion);
643428d7b3dSmrg	DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
644428d7b3dSmrg	RegionUninit(&pixregion);
645428d7b3dSmrg	if (was_blocked)
646428d7b3dSmrg		return;
647428d7b3dSmrg
648428d7b3dSmrg	PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap);
649428d7b3dSmrg#ifdef HAS_DIRTYTRACKING_ROTATION
650428d7b3dSmrg	PixmapSyncDirtyHelper(dirty);
651428d7b3dSmrg#else
652428d7b3dSmrg	PixmapSyncDirtyHelper(dirty, &pixregion);
653428d7b3dSmrg#endif
654428d7b3dSmrg	RegionUninit(&pixregion);
655428d7b3dSmrg
656428d7b3dSmrg        intel_flush(intel);
657428d7b3dSmrg	if (!intel->has_prime_vmap_flush) {
658428d7b3dSmrg		drm_intel_bo *bo = intel_uxa_get_pixmap_bo(dirty->slave_dst->master_pixmap);
659428d7b3dSmrg		was_blocked = xf86BlockSIGIO();
660428d7b3dSmrg		drm_intel_bo_map(bo, FALSE);
661428d7b3dSmrg		drm_intel_bo_unmap(bo);
662428d7b3dSmrg		xf86UnblockSIGIO(was_blocked);
663428d7b3dSmrg	}
664428d7b3dSmrg
665428d7b3dSmrg	DamageRegionProcessPending(&dirty->slave_dst->drawable);
666428d7b3dSmrg	return;
667428d7b3dSmrg}
668428d7b3dSmrg
669428d7b3dSmrgstatic void
670428d7b3dSmrgintel_dirty_update(ScreenPtr screen)
671428d7b3dSmrg{
672428d7b3dSmrg	RegionPtr region;
673428d7b3dSmrg	PixmapDirtyUpdatePtr ent;
674428d7b3dSmrg
675428d7b3dSmrg	if (xorg_list_is_empty(&screen->pixmap_dirty_list))
676428d7b3dSmrg	    return;
677428d7b3dSmrg
678428d7b3dSmrg	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
679428d7b3dSmrg		region = DamageRegion(ent->damage);
680428d7b3dSmrg		if (RegionNotEmpty(region)) {
681428d7b3dSmrg			redisplay_dirty(screen, ent);
682428d7b3dSmrg			DamageEmpty(ent->damage);
683428d7b3dSmrg		}
684428d7b3dSmrg	}
685428d7b3dSmrg}
686428d7b3dSmrg#endif
687428d7b3dSmrg
688428d7b3dSmrgstatic void
689428d7b3dSmrgI830BlockHandler(BLOCKHANDLER_ARGS_DECL)
690428d7b3dSmrg{
691428d7b3dSmrg	SCREEN_PTR(arg);
692428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
693428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
694428d7b3dSmrg
695428d7b3dSmrg	screen->BlockHandler = intel->BlockHandler;
696428d7b3dSmrg
697428d7b3dSmrg	(*screen->BlockHandler) (BLOCKHANDLER_ARGS);
698428d7b3dSmrg
699428d7b3dSmrg	intel->BlockHandler = screen->BlockHandler;
700428d7b3dSmrg	screen->BlockHandler = I830BlockHandler;
701428d7b3dSmrg
702428d7b3dSmrg	intel_uxa_block_handler(intel);
703428d7b3dSmrg	intel_video_block_handler(intel);
704428d7b3dSmrg#ifdef INTEL_PIXMAP_SHARING
705428d7b3dSmrg	intel_dirty_update(screen);
706428d7b3dSmrg#endif
707428d7b3dSmrg}
708428d7b3dSmrg
709428d7b3dSmrgstatic Bool
710428d7b3dSmrgintel_init_initial_framebuffer(ScrnInfoPtr scrn)
711428d7b3dSmrg{
712428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
713428d7b3dSmrg	int width = scrn->virtualX;
714428d7b3dSmrg	int height = scrn->virtualY;
715428d7b3dSmrg	int pitch;
716428d7b3dSmrg	uint32_t tiling;
717428d7b3dSmrg
718428d7b3dSmrg	intel->front_buffer = intel_allocate_framebuffer(scrn,
719428d7b3dSmrg							 width, height,
720428d7b3dSmrg							 intel->cpp,
721428d7b3dSmrg							 &pitch, &tiling);
722428d7b3dSmrg
723428d7b3dSmrg	if (!intel->front_buffer) {
724428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
725428d7b3dSmrg			   "Couldn't allocate initial framebuffer.\n");
726428d7b3dSmrg		return FALSE;
727428d7b3dSmrg	}
728428d7b3dSmrg
729428d7b3dSmrg	intel->front_pitch = pitch;
730428d7b3dSmrg	intel->front_tiling = tiling;
731428d7b3dSmrg	scrn->displayWidth = pitch / intel->cpp;
732428d7b3dSmrg
733428d7b3dSmrg	return TRUE;
734428d7b3dSmrg}
735428d7b3dSmrg
736428d7b3dSmrgstatic void
737428d7b3dSmrgintel_flush_callback(CallbackListPtr *list,
738428d7b3dSmrg		     pointer user_data, pointer call_data)
739428d7b3dSmrg{
740428d7b3dSmrg	ScrnInfoPtr scrn = user_data;
741428d7b3dSmrg	if (scrn->vtSema)
742428d7b3dSmrg                intel_flush(intel_get_screen_private(scrn));
743428d7b3dSmrg}
744428d7b3dSmrg
745428d7b3dSmrg#if HAVE_UDEV
746428d7b3dSmrgstatic void
747428d7b3dSmrgI830HandleUEvents(int fd, void *closure)
748428d7b3dSmrg{
749428d7b3dSmrg	ScrnInfoPtr scrn = closure;
750428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
751428d7b3dSmrg	struct udev_device *dev;
752428d7b3dSmrg	const char *hotplug;
753428d7b3dSmrg	struct stat s;
754428d7b3dSmrg	dev_t udev_devnum;
755428d7b3dSmrg
756428d7b3dSmrg	dev = udev_monitor_receive_device(intel->uevent_monitor);
757428d7b3dSmrg	if (!dev)
758428d7b3dSmrg		return;
759428d7b3dSmrg
760428d7b3dSmrg	udev_devnum = udev_device_get_devnum(dev);
761428d7b3dSmrg	if (fstat(intel->drmSubFD, &s)) {
762428d7b3dSmrg		udev_device_unref(dev);
763428d7b3dSmrg		return;
764428d7b3dSmrg	}
765428d7b3dSmrg	/*
766428d7b3dSmrg	 * Check to make sure this event is directed at our
767428d7b3dSmrg	 * device (by comparing dev_t values), then make
768428d7b3dSmrg	 * sure it's a hotplug event (HOTPLUG=1)
769428d7b3dSmrg	 */
770428d7b3dSmrg
771428d7b3dSmrg	hotplug = udev_device_get_property_value(dev, "HOTPLUG");
772428d7b3dSmrg
773428d7b3dSmrg	if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
774428d7b3dSmrg			hotplug && atoi(hotplug) == 1)
775428d7b3dSmrg	{
776428d7b3dSmrg		intel_mode_hotplug(intel);
777428d7b3dSmrg	}
778428d7b3dSmrg
779428d7b3dSmrg	udev_device_unref(dev);
780428d7b3dSmrg}
781428d7b3dSmrg
782428d7b3dSmrgstatic void
783428d7b3dSmrgI830UeventInit(ScrnInfoPtr scrn)
784428d7b3dSmrg{
785428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
786428d7b3dSmrg	struct udev *u;
787428d7b3dSmrg	struct udev_monitor *mon;
788428d7b3dSmrg	Bool hotplug;
789428d7b3dSmrg	MessageType from = X_CONFIG;
790428d7b3dSmrg
791428d7b3dSmrg	if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) {
792428d7b3dSmrg		from = X_DEFAULT;
793428d7b3dSmrg		hotplug = TRUE;
794428d7b3dSmrg	}
795428d7b3dSmrg
796428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, from, "hotplug detection: \"%s\"\n",
797428d7b3dSmrg			hotplug ? "enabled" : "disabled");
798428d7b3dSmrg	if (!hotplug)
799428d7b3dSmrg		return;
800428d7b3dSmrg
801428d7b3dSmrg	u = udev_new();
802428d7b3dSmrg	if (!u)
803428d7b3dSmrg		return;
804428d7b3dSmrg
805428d7b3dSmrg	mon = udev_monitor_new_from_netlink(u, "udev");
806428d7b3dSmrg
807428d7b3dSmrg	if (!mon) {
808428d7b3dSmrg		udev_unref(u);
809428d7b3dSmrg		return;
810428d7b3dSmrg	}
811428d7b3dSmrg
812428d7b3dSmrg	if (udev_monitor_filter_add_match_subsystem_devtype(mon,
813428d7b3dSmrg				"drm",
814428d7b3dSmrg				"drm_minor") < 0 ||
815428d7b3dSmrg			udev_monitor_enable_receiving(mon) < 0)
816428d7b3dSmrg	{
817428d7b3dSmrg		udev_monitor_unref(mon);
818428d7b3dSmrg		udev_unref(u);
819428d7b3dSmrg		return;
820428d7b3dSmrg	}
821428d7b3dSmrg
822428d7b3dSmrg	intel->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon),
823428d7b3dSmrg						      I830HandleUEvents, scrn);
824428d7b3dSmrg	if (!intel->uevent_handler) {
825428d7b3dSmrg		udev_monitor_unref(mon);
826428d7b3dSmrg		udev_unref(u);
827428d7b3dSmrg		return;
828428d7b3dSmrg	}
829428d7b3dSmrg
830428d7b3dSmrg	intel->uevent_monitor = mon;
831428d7b3dSmrg}
832428d7b3dSmrg
833428d7b3dSmrgstatic void
834428d7b3dSmrgI830UeventFini(ScrnInfoPtr scrn)
835428d7b3dSmrg{
836428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
837428d7b3dSmrg
838428d7b3dSmrg	if (intel->uevent_handler) {
839428d7b3dSmrg		struct udev *u = udev_monitor_get_udev(intel->uevent_monitor);
840428d7b3dSmrg
841428d7b3dSmrg		xf86RemoveGeneralHandler(intel->uevent_handler);
842428d7b3dSmrg
843428d7b3dSmrg		udev_monitor_unref(intel->uevent_monitor);
844428d7b3dSmrg		udev_unref(u);
845428d7b3dSmrg		intel->uevent_handler = NULL;
846428d7b3dSmrg		intel->uevent_monitor = NULL;
847428d7b3dSmrg	}
848428d7b3dSmrg}
849428d7b3dSmrg#endif /* HAVE_UDEV */
850428d7b3dSmrg
851428d7b3dSmrgstatic Bool
852428d7b3dSmrgI830ScreenInit(SCREEN_INIT_ARGS_DECL)
853428d7b3dSmrg{
854428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
855428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
856428d7b3dSmrg	VisualPtr visual;
857428d7b3dSmrg#ifdef INTEL_XVMC
858428d7b3dSmrg	MessageType from;
859428d7b3dSmrg#endif
860428d7b3dSmrg	struct pci_device *const device = xf86GetPciInfoForEntity(intel->pEnt->index);
861428d7b3dSmrg	int fb_bar = IS_GEN2(intel) ? 0 : 2;
862428d7b3dSmrg
863428d7b3dSmrg	scrn->videoRam = device->regions[fb_bar].size / 1024;
864428d7b3dSmrg
865428d7b3dSmrg	intel->last_3d = LAST_3D_OTHER;
866428d7b3dSmrg	intel->overlayOn = FALSE;
867428d7b3dSmrg
868428d7b3dSmrg	/*
869428d7b3dSmrg	 * Set this so that the overlay allocation is factored in when
870428d7b3dSmrg	 * appropriate.
871428d7b3dSmrg	 */
872428d7b3dSmrg	intel->XvEnabled = TRUE;
873428d7b3dSmrg
874428d7b3dSmrg	if (!intel_init_initial_framebuffer(scrn))
875428d7b3dSmrg		return FALSE;
876428d7b3dSmrg
877428d7b3dSmrg	miClearVisualTypes();
878428d7b3dSmrg	if (!miSetVisualTypes(scrn->depth,
879428d7b3dSmrg			      miGetDefaultVisualMask(scrn->depth),
880428d7b3dSmrg			      scrn->rgbBits, scrn->defaultVisual))
881428d7b3dSmrg		return FALSE;
882428d7b3dSmrg	if (!miSetPixmapDepths())
883428d7b3dSmrg		return FALSE;
884428d7b3dSmrg
885428d7b3dSmrg	/* Must be first, before anything else installs screen callbacks. */
886428d7b3dSmrg	if (!fbScreenInit(screen, NULL,
887428d7b3dSmrg			  scrn->virtualX, scrn->virtualY,
888428d7b3dSmrg			  scrn->xDpi, scrn->yDpi,
889428d7b3dSmrg			  scrn->displayWidth, scrn->bitsPerPixel))
890428d7b3dSmrg		return FALSE;
891428d7b3dSmrg
892428d7b3dSmrg	if (scrn->bitsPerPixel > 8) {
893428d7b3dSmrg		/* Fixup RGB ordering */
894428d7b3dSmrg		visual = screen->visuals + screen->numVisuals;
895428d7b3dSmrg		while (--visual >= screen->visuals) {
896428d7b3dSmrg			if ((visual->class | DynamicClass) == DirectColor) {
897428d7b3dSmrg				visual->offsetRed = scrn->offset.red;
898428d7b3dSmrg				visual->offsetGreen = scrn->offset.green;
899428d7b3dSmrg				visual->offsetBlue = scrn->offset.blue;
900428d7b3dSmrg				visual->redMask = scrn->mask.red;
901428d7b3dSmrg				visual->greenMask = scrn->mask.green;
902428d7b3dSmrg				visual->blueMask = scrn->mask.blue;
903428d7b3dSmrg			}
904428d7b3dSmrg		}
905428d7b3dSmrg	}
906428d7b3dSmrg
907428d7b3dSmrg	fbPictureInit(screen, NULL, 0);
908428d7b3dSmrg
909428d7b3dSmrg	xf86SetBlackWhitePixels(screen);
910428d7b3dSmrg
911428d7b3dSmrg	if (!intel_uxa_init(screen)) {
912428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
913428d7b3dSmrg			   "Hardware acceleration initialization failed\n");
914428d7b3dSmrg		return FALSE;
915428d7b3dSmrg	}
916428d7b3dSmrg
917428d7b3dSmrg#if HAVE_DRI2
918428d7b3dSmrg	if (intel->dri2 == DRI_NONE && I830DRI2ScreenInit(screen))
919428d7b3dSmrg		intel->dri2 = DRI_ACTIVE;
920428d7b3dSmrg#endif
921428d7b3dSmrg
922428d7b3dSmrg#if HAVE_DRI3
923428d7b3dSmrg	if (!intel_sync_init(screen))
924428d7b3dSmrg		intel->dri3 = DRI_DISABLED;
925428d7b3dSmrg	if (intel->dri3 == DRI_NONE && intel_dri3_screen_init(screen))
926428d7b3dSmrg		intel->dri3 = DRI_ACTIVE;
927428d7b3dSmrg#endif
928428d7b3dSmrg
929428d7b3dSmrg	if (xf86ReturnOptValBool(intel->Options, OPTION_PRESENT, TRUE))
930428d7b3dSmrg		intel_present_screen_init(screen);
931428d7b3dSmrg
932428d7b3dSmrg	xf86SetBackingStore(screen);
933428d7b3dSmrg	xf86SetSilkenMouse(screen);
934428d7b3dSmrg	miDCInitialize(screen, xf86GetPointerScreenFuncs());
935428d7b3dSmrg
936428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_INFO, "Initializing HW Cursor\n");
937428d7b3dSmrg	if (!xf86_cursors_init(screen, 64, 64,
938428d7b3dSmrg			       (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
939428d7b3dSmrg				HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
940428d7b3dSmrg				HARDWARE_CURSOR_INVERT_MASK |
941428d7b3dSmrg				HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
942428d7b3dSmrg				HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
943428d7b3dSmrg				HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
944428d7b3dSmrg				HARDWARE_CURSOR_UPDATE_UNHIDDEN |
945428d7b3dSmrg				HARDWARE_CURSOR_ARGB))) {
946428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
947428d7b3dSmrg			   "Hardware cursor initialization failed\n");
948428d7b3dSmrg	}
949428d7b3dSmrg
950428d7b3dSmrg	intel->BlockHandler = screen->BlockHandler;
951428d7b3dSmrg	screen->BlockHandler = I830BlockHandler;
952428d7b3dSmrg
953428d7b3dSmrg#ifdef INTEL_PIXMAP_SHARING
954428d7b3dSmrg	screen->StartPixmapTracking = PixmapStartDirtyTracking;
955428d7b3dSmrg	screen->StopPixmapTracking = PixmapStopDirtyTracking;
956428d7b3dSmrg#endif
957428d7b3dSmrg
958428d7b3dSmrg	if (!AddCallback(&FlushCallback, intel_flush_callback, scrn))
959428d7b3dSmrg		return FALSE;
960428d7b3dSmrg
961428d7b3dSmrg	screen->SaveScreen = xf86SaveScreen;
962428d7b3dSmrg	intel->CloseScreen = screen->CloseScreen;
963428d7b3dSmrg	screen->CloseScreen = I830CloseScreen;
964428d7b3dSmrg	intel->CreateScreenResources = screen->CreateScreenResources;
965428d7b3dSmrg	screen->CreateScreenResources = i830CreateScreenResources;
966428d7b3dSmrg
967428d7b3dSmrg	if (!xf86CrtcScreenInit(screen))
968428d7b3dSmrg		return FALSE;
969428d7b3dSmrg
970428d7b3dSmrg	if (!miCreateDefColormap(screen))
971428d7b3dSmrg		return FALSE;
972428d7b3dSmrg
973428d7b3dSmrg	if (!xf86HandleColormaps(screen, 256, 8, I830LoadPalette, NULL,
974428d7b3dSmrg				 CMAP_RELOAD_ON_MODE_SWITCH |
975428d7b3dSmrg				 CMAP_PALETTED_TRUECOLOR)) {
976428d7b3dSmrg		return FALSE;
977428d7b3dSmrg	}
978428d7b3dSmrg
979428d7b3dSmrg	xf86DPMSInit(screen, xf86DPMSSet, 0);
980428d7b3dSmrg
981428d7b3dSmrg#ifdef INTEL_XVMC
982428d7b3dSmrg	if (INTEL_INFO(intel)->gen >= 040)
983428d7b3dSmrg		intel->XvMCEnabled = TRUE;
984428d7b3dSmrg	from = (intel->dri2 == DRI_ACTIVE &&
985428d7b3dSmrg		xf86GetOptValBool(intel->Options, OPTION_XVMC,
986428d7b3dSmrg				  &intel->XvMCEnabled) ? X_CONFIG : X_DEFAULT);
987428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, from, "Intel XvMC decoder %sabled\n",
988428d7b3dSmrg		   intel->XvMCEnabled ? "en" : "dis");
989428d7b3dSmrg#endif
990428d7b3dSmrg	/* Init video */
991428d7b3dSmrg	if (intel->XvEnabled)
992428d7b3dSmrg		intel_video_init(screen);
993428d7b3dSmrg
994428d7b3dSmrg#if HAVE_DRI2
995428d7b3dSmrg	switch (intel->dri2) {
996428d7b3dSmrg	case DRI_ACTIVE:
997428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_INFO,
998428d7b3dSmrg			   "DRI2: Enabled\n");
999428d7b3dSmrg		break;
1000428d7b3dSmrg	case DRI_DISABLED:
1001428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1002428d7b3dSmrg			   "DRI2: Disabled\n");
1003428d7b3dSmrg		break;
1004428d7b3dSmrg	case DRI_NONE:
1005428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1006428d7b3dSmrg			   "DRI2: Failed\n");
1007428d7b3dSmrg		break;
1008428d7b3dSmrg	}
1009428d7b3dSmrg#else
1010428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_INFO,
1011428d7b3dSmrg		   "DRI2: Not available\n");
1012428d7b3dSmrg#endif
1013428d7b3dSmrg
1014428d7b3dSmrg#if HAVE_DRI3
1015428d7b3dSmrg	switch (intel->dri3) {
1016428d7b3dSmrg	case DRI_ACTIVE:
1017428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1018428d7b3dSmrg			   "DRI3: Enabled\n");
1019428d7b3dSmrg		break;
1020428d7b3dSmrg	case DRI_DISABLED:
1021428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1022428d7b3dSmrg			   "DRI3: Disabled\n");
1023428d7b3dSmrg		break;
1024428d7b3dSmrg	case DRI_NONE:
1025428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1026428d7b3dSmrg			   "DRI3: Failed\n");
1027428d7b3dSmrg		break;
1028428d7b3dSmrg	}
1029428d7b3dSmrg#else
1030428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_INFO,
1031428d7b3dSmrg		   "DRI3: Not available\n");
1032428d7b3dSmrg#endif
1033428d7b3dSmrg
1034428d7b3dSmrg	if (serverGeneration == 1)
1035428d7b3dSmrg		xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options);
1036428d7b3dSmrg
1037428d7b3dSmrg	intel_mode_init(intel);
1038428d7b3dSmrg
1039428d7b3dSmrg	intel->suspended = FALSE;
1040428d7b3dSmrg
1041428d7b3dSmrg#if HAVE_UDEV
1042428d7b3dSmrg	I830UeventInit(scrn);
1043428d7b3dSmrg#endif
1044428d7b3dSmrg
1045428d7b3dSmrg	/* Must force it before EnterVT, so we are in control of VT and
1046428d7b3dSmrg	 * later memory should be bound when allocating, e.g rotate_mem */
1047428d7b3dSmrg	scrn->vtSema = TRUE;
1048428d7b3dSmrg
1049428d7b3dSmrg	return I830EnterVT(VT_FUNC_ARGS(0));
1050428d7b3dSmrg}
1051428d7b3dSmrg
1052428d7b3dSmrgstatic void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL)
1053428d7b3dSmrg{
1054428d7b3dSmrg}
1055428d7b3dSmrg
1056428d7b3dSmrgstatic void I830FreeScreen(FREE_SCREEN_ARGS_DECL)
1057428d7b3dSmrg{
1058428d7b3dSmrg	SCRN_INFO_PTR(arg);
1059428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
1060428d7b3dSmrg
1061428d7b3dSmrg	if (intel && !((uintptr_t)intel & 3)) {
1062428d7b3dSmrg		intel_mode_fini(intel);
1063428d7b3dSmrg		intel_bufmgr_fini(intel);
1064428d7b3dSmrg		intel_put_device(intel->dev);
1065428d7b3dSmrg
1066428d7b3dSmrg		free(intel);
1067428d7b3dSmrg		scrn->driverPrivate = NULL;
1068428d7b3dSmrg	}
1069428d7b3dSmrg}
1070428d7b3dSmrg
1071428d7b3dSmrgstatic void I830LeaveVT(VT_FUNC_ARGS_DECL)
1072428d7b3dSmrg{
1073428d7b3dSmrg	SCRN_INFO_PTR(arg);
1074428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
1075428d7b3dSmrg
1076428d7b3dSmrg	xf86RotateFreeShadow(scrn);
1077428d7b3dSmrg
1078428d7b3dSmrg	xf86_hide_cursors(scrn);
1079428d7b3dSmrg
1080428d7b3dSmrg	if (intel_put_master(intel->dev))
1081428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1082428d7b3dSmrg			   "drmDropMaster failed: %s\n", strerror(errno));
1083428d7b3dSmrg}
1084428d7b3dSmrg
1085428d7b3dSmrg/*
1086428d7b3dSmrg * This gets called when gaining control of the VT, and from ScreenInit().
1087428d7b3dSmrg */
1088428d7b3dSmrgstatic Bool I830EnterVT(VT_FUNC_ARGS_DECL)
1089428d7b3dSmrg{
1090428d7b3dSmrg	SCRN_INFO_PTR(arg);
1091428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
1092428d7b3dSmrg
1093428d7b3dSmrg	if (intel_get_master(intel->dev)) {
1094428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1095428d7b3dSmrg			   "drmSetMaster failed: %s\n",
1096428d7b3dSmrg			   strerror(errno));
1097428d7b3dSmrg		return FALSE;
1098428d7b3dSmrg	}
1099428d7b3dSmrg
1100428d7b3dSmrg	if (!xf86SetDesiredModes(scrn))
1101428d7b3dSmrg		return FALSE;
1102428d7b3dSmrg
1103428d7b3dSmrg	intel_mode_disable_unused_functions(scrn);
1104428d7b3dSmrg	return TRUE;
1105428d7b3dSmrg}
1106428d7b3dSmrg
1107428d7b3dSmrgstatic Bool I830SwitchMode(SWITCH_MODE_ARGS_DECL)
1108428d7b3dSmrg{
1109428d7b3dSmrg	SCRN_INFO_PTR(arg);
1110428d7b3dSmrg
1111428d7b3dSmrg	return xf86SetSingleMode(scrn, mode, RR_Rotate_0);
1112428d7b3dSmrg}
1113428d7b3dSmrg
1114428d7b3dSmrgstatic Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL)
1115428d7b3dSmrg{
1116428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1117428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
1118428d7b3dSmrg
1119428d7b3dSmrg#if HAVE_UDEV
1120428d7b3dSmrg	I830UeventFini(scrn);
1121428d7b3dSmrg#endif
1122428d7b3dSmrg
1123428d7b3dSmrg	intel_mode_close(intel);
1124428d7b3dSmrg
1125428d7b3dSmrg	DeleteCallback(&FlushCallback, intel_flush_callback, scrn);
1126428d7b3dSmrg
1127428d7b3dSmrg	TimerFree(intel->cache_expire);
1128428d7b3dSmrg	intel->cache_expire = NULL;
1129428d7b3dSmrg
1130428d7b3dSmrg	if (intel->uxa_driver) {
1131428d7b3dSmrg		uxa_driver_fini(screen);
1132428d7b3dSmrg		free(intel->uxa_driver);
1133428d7b3dSmrg		intel->uxa_driver = NULL;
1134428d7b3dSmrg	}
1135428d7b3dSmrg
1136428d7b3dSmrg	if (intel->back_buffer) {
1137428d7b3dSmrg		drm_intel_bo_unreference(intel->back_buffer);
1138428d7b3dSmrg		intel->back_buffer = NULL;
1139428d7b3dSmrg	}
1140428d7b3dSmrg
1141428d7b3dSmrg	if (intel->front_buffer) {
1142428d7b3dSmrg		intel_mode_remove_fb(intel);
1143428d7b3dSmrg		drm_intel_bo_unreference(intel->front_buffer);
1144428d7b3dSmrg		intel->front_buffer = NULL;
1145428d7b3dSmrg	}
1146428d7b3dSmrg
1147428d7b3dSmrg	if (scrn->vtSema == TRUE) {
1148428d7b3dSmrg		I830LeaveVT(VT_FUNC_ARGS(0));
1149428d7b3dSmrg	}
1150428d7b3dSmrg
1151428d7b3dSmrg	intel_batch_teardown(scrn);
1152428d7b3dSmrg
1153428d7b3dSmrg	if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100)
1154428d7b3dSmrg		gen4_render_state_cleanup(scrn);
1155428d7b3dSmrg
1156428d7b3dSmrg	xf86_cursors_fini(screen);
1157428d7b3dSmrg
1158428d7b3dSmrg	i965_free_video(scrn);
1159428d7b3dSmrg
1160428d7b3dSmrg	screen->CloseScreen = intel->CloseScreen;
1161428d7b3dSmrg	(*screen->CloseScreen) (CLOSE_SCREEN_ARGS);
1162428d7b3dSmrg
1163428d7b3dSmrg	if (intel->dri2 == DRI_ACTIVE) {
1164428d7b3dSmrg		I830DRI2CloseScreen(screen);
1165428d7b3dSmrg		intel->dri2 = DRI_NONE;
1166428d7b3dSmrg	}
1167428d7b3dSmrg
1168428d7b3dSmrg	if (intel->dri3 == DRI_ACTIVE) {
1169428d7b3dSmrg		/* nothing to do here? */
1170428d7b3dSmrg		intel->dri3 = DRI_NONE;
1171428d7b3dSmrg	}
1172428d7b3dSmrg
1173428d7b3dSmrg	intel_sync_close(screen);
1174428d7b3dSmrg
1175428d7b3dSmrg	xf86GARTCloseScreen(scrn->scrnIndex);
1176428d7b3dSmrg
1177428d7b3dSmrg	scrn->vtSema = FALSE;
1178428d7b3dSmrg	return TRUE;
1179428d7b3dSmrg}
1180428d7b3dSmrg
1181428d7b3dSmrgstatic ModeStatus
1182428d7b3dSmrgI830ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
1183428d7b3dSmrg{
1184428d7b3dSmrg	SCRN_INFO_PTR(arg);
1185428d7b3dSmrg	if (mode->Flags & V_INTERLACE) {
1186428d7b3dSmrg		if (verbose) {
1187428d7b3dSmrg			xf86DrvMsg(scrn->scrnIndex, X_PROBED,
1188428d7b3dSmrg				   "Removing interlaced mode \"%s\"\n",
1189428d7b3dSmrg				   mode->name);
1190428d7b3dSmrg		}
1191428d7b3dSmrg		return MODE_BAD;
1192428d7b3dSmrg	}
1193428d7b3dSmrg	return MODE_OK;
1194428d7b3dSmrg}
1195428d7b3dSmrg
1196428d7b3dSmrg#ifndef SUSPEND_SLEEP
1197428d7b3dSmrg#define SUSPEND_SLEEP 0
1198428d7b3dSmrg#endif
1199428d7b3dSmrg#ifndef RESUME_SLEEP
1200428d7b3dSmrg#define RESUME_SLEEP 0
1201428d7b3dSmrg#endif
1202428d7b3dSmrg
1203428d7b3dSmrg/*
1204428d7b3dSmrg * This function is only required if we need to do anything differently from
1205428d7b3dSmrg * DoApmEvent() in common/xf86PM.c, including if we want to see events other
1206428d7b3dSmrg * than suspend/resume.
1207428d7b3dSmrg */
1208428d7b3dSmrgstatic Bool I830PMEvent(SCRN_ARG_TYPE arg, pmEvent event, Bool undo)
1209428d7b3dSmrg{
1210428d7b3dSmrg	SCRN_INFO_PTR(arg);
1211428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
1212428d7b3dSmrg
1213428d7b3dSmrg	switch (event) {
1214428d7b3dSmrg	case XF86_APM_SYS_SUSPEND:
1215428d7b3dSmrg	case XF86_APM_CRITICAL_SUSPEND:	/*do we want to delay a critical suspend? */
1216428d7b3dSmrg	case XF86_APM_USER_SUSPEND:
1217428d7b3dSmrg	case XF86_APM_SYS_STANDBY:
1218428d7b3dSmrg	case XF86_APM_USER_STANDBY:
1219428d7b3dSmrg		if (!undo && !intel->suspended) {
1220428d7b3dSmrg			scrn->LeaveVT(VT_FUNC_ARGS(0));
1221428d7b3dSmrg			intel->suspended = TRUE;
1222428d7b3dSmrg			sleep(SUSPEND_SLEEP);
1223428d7b3dSmrg		} else if (undo && intel->suspended) {
1224428d7b3dSmrg			sleep(RESUME_SLEEP);
1225428d7b3dSmrg			scrn->EnterVT(VT_FUNC_ARGS(0));
1226428d7b3dSmrg			intel->suspended = FALSE;
1227428d7b3dSmrg		}
1228428d7b3dSmrg		break;
1229428d7b3dSmrg	case XF86_APM_STANDBY_RESUME:
1230428d7b3dSmrg	case XF86_APM_NORMAL_RESUME:
1231428d7b3dSmrg	case XF86_APM_CRITICAL_RESUME:
1232428d7b3dSmrg		if (intel->suspended) {
1233428d7b3dSmrg			sleep(RESUME_SLEEP);
1234428d7b3dSmrg			scrn->EnterVT(VT_FUNC_ARGS(0));
1235428d7b3dSmrg			intel->suspended = FALSE;
1236428d7b3dSmrg			/*
1237428d7b3dSmrg			 * Turn the screen saver off when resuming.  This seems to be
1238428d7b3dSmrg			 * needed to stop xscreensaver kicking in (when used).
1239428d7b3dSmrg			 *
1240428d7b3dSmrg			 * XXX DoApmEvent() should probably call this just like
1241428d7b3dSmrg			 * xf86VTSwitch() does.  Maybe do it here only in 4.2
1242428d7b3dSmrg			 * compatibility mode.
1243428d7b3dSmrg			 */
1244428d7b3dSmrg			SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
1245428d7b3dSmrg		}
1246428d7b3dSmrg		break;
1247428d7b3dSmrg		/* This is currently used for ACPI */
1248428d7b3dSmrg	case XF86_APM_CAPABILITY_CHANGED:
1249428d7b3dSmrg		ErrorF("I830PMEvent: Capability change\n");
1250428d7b3dSmrg
1251428d7b3dSmrg		SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
1252428d7b3dSmrg
1253428d7b3dSmrg		break;
1254428d7b3dSmrg	default:
1255428d7b3dSmrg		ErrorF("I830PMEvent: received APM event %d\n", event);
1256428d7b3dSmrg	}
1257428d7b3dSmrg	return TRUE;
1258428d7b3dSmrg}
1259428d7b3dSmrg
1260428d7b3dSmrgBool intel_init_scrn(ScrnInfoPtr scrn)
1261428d7b3dSmrg{
1262428d7b3dSmrg	scrn->PreInit = I830PreInit;
1263428d7b3dSmrg	scrn->ScreenInit = I830ScreenInit;
1264428d7b3dSmrg	scrn->SwitchMode = I830SwitchMode;
1265428d7b3dSmrg	scrn->AdjustFrame = i830AdjustFrame;
1266428d7b3dSmrg	scrn->EnterVT = I830EnterVT;
1267428d7b3dSmrg	scrn->LeaveVT = I830LeaveVT;
1268428d7b3dSmrg	scrn->FreeScreen = I830FreeScreen;
1269428d7b3dSmrg	scrn->ValidMode = I830ValidMode;
1270428d7b3dSmrg	scrn->PMEvent = I830PMEvent;
1271428d7b3dSmrg	return TRUE;
1272428d7b3dSmrg}
1273