intel_driver.c revision 428d7b3d
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
626428d7b3dSmrgstatic void
627428d7b3dSmrgredisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
628428d7b3dSmrg{
629428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
630428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
631428d7b3dSmrg	RegionRec pixregion;
632428d7b3dSmrg	int was_blocked;
633428d7b3dSmrg
634428d7b3dSmrg	PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap);
635428d7b3dSmrg	RegionTranslate(&pixregion, dirty->x, dirty->y);
636428d7b3dSmrg	RegionIntersect(&pixregion, &pixregion, DamageRegion(dirty->damage));
637428d7b3dSmrg	RegionTranslate(&pixregion, -dirty->x, -dirty->y);
638428d7b3dSmrg	was_blocked = RegionNil(&pixregion);
639428d7b3dSmrg	DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
640428d7b3dSmrg	RegionUninit(&pixregion);
641428d7b3dSmrg	if (was_blocked)
642428d7b3dSmrg		return;
643428d7b3dSmrg
644428d7b3dSmrg	PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap);
645428d7b3dSmrg#ifdef HAS_DIRTYTRACKING_ROTATION
646428d7b3dSmrg	PixmapSyncDirtyHelper(dirty);
647428d7b3dSmrg#else
648428d7b3dSmrg	PixmapSyncDirtyHelper(dirty, &pixregion);
649428d7b3dSmrg#endif
650428d7b3dSmrg	RegionUninit(&pixregion);
651428d7b3dSmrg
652428d7b3dSmrg        intel_flush(intel);
653428d7b3dSmrg	if (!intel->has_prime_vmap_flush) {
654428d7b3dSmrg		drm_intel_bo *bo = intel_uxa_get_pixmap_bo(dirty->slave_dst->master_pixmap);
655428d7b3dSmrg		was_blocked = xf86BlockSIGIO();
656428d7b3dSmrg		drm_intel_bo_map(bo, FALSE);
657428d7b3dSmrg		drm_intel_bo_unmap(bo);
658428d7b3dSmrg		xf86UnblockSIGIO(was_blocked);
659428d7b3dSmrg	}
660428d7b3dSmrg
661428d7b3dSmrg	DamageRegionProcessPending(&dirty->slave_dst->drawable);
662428d7b3dSmrg	return;
663428d7b3dSmrg}
664428d7b3dSmrg
665428d7b3dSmrgstatic void
666428d7b3dSmrgintel_dirty_update(ScreenPtr screen)
667428d7b3dSmrg{
668428d7b3dSmrg	RegionPtr region;
669428d7b3dSmrg	PixmapDirtyUpdatePtr ent;
670428d7b3dSmrg
671428d7b3dSmrg	if (xorg_list_is_empty(&screen->pixmap_dirty_list))
672428d7b3dSmrg	    return;
673428d7b3dSmrg
674428d7b3dSmrg	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
675428d7b3dSmrg		region = DamageRegion(ent->damage);
676428d7b3dSmrg		if (RegionNotEmpty(region)) {
677428d7b3dSmrg			redisplay_dirty(screen, ent);
678428d7b3dSmrg			DamageEmpty(ent->damage);
679428d7b3dSmrg		}
680428d7b3dSmrg	}
681428d7b3dSmrg}
682428d7b3dSmrg#endif
683428d7b3dSmrg
684428d7b3dSmrgstatic void
685428d7b3dSmrgI830BlockHandler(BLOCKHANDLER_ARGS_DECL)
686428d7b3dSmrg{
687428d7b3dSmrg	SCREEN_PTR(arg);
688428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
689428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
690428d7b3dSmrg
691428d7b3dSmrg	screen->BlockHandler = intel->BlockHandler;
692428d7b3dSmrg
693428d7b3dSmrg	(*screen->BlockHandler) (BLOCKHANDLER_ARGS);
694428d7b3dSmrg
695428d7b3dSmrg	intel->BlockHandler = screen->BlockHandler;
696428d7b3dSmrg	screen->BlockHandler = I830BlockHandler;
697428d7b3dSmrg
698428d7b3dSmrg	intel_uxa_block_handler(intel);
699428d7b3dSmrg	intel_video_block_handler(intel);
700428d7b3dSmrg#ifdef INTEL_PIXMAP_SHARING
701428d7b3dSmrg	intel_dirty_update(screen);
702428d7b3dSmrg#endif
703428d7b3dSmrg}
704428d7b3dSmrg
705428d7b3dSmrgstatic Bool
706428d7b3dSmrgintel_init_initial_framebuffer(ScrnInfoPtr scrn)
707428d7b3dSmrg{
708428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
709428d7b3dSmrg	int width = scrn->virtualX;
710428d7b3dSmrg	int height = scrn->virtualY;
711428d7b3dSmrg	int pitch;
712428d7b3dSmrg	uint32_t tiling;
713428d7b3dSmrg
714428d7b3dSmrg	intel->front_buffer = intel_allocate_framebuffer(scrn,
715428d7b3dSmrg							 width, height,
716428d7b3dSmrg							 intel->cpp,
717428d7b3dSmrg							 &pitch, &tiling);
718428d7b3dSmrg
719428d7b3dSmrg	if (!intel->front_buffer) {
720428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
721428d7b3dSmrg			   "Couldn't allocate initial framebuffer.\n");
722428d7b3dSmrg		return FALSE;
723428d7b3dSmrg	}
724428d7b3dSmrg
725428d7b3dSmrg	intel->front_pitch = pitch;
726428d7b3dSmrg	intel->front_tiling = tiling;
727428d7b3dSmrg	scrn->displayWidth = pitch / intel->cpp;
728428d7b3dSmrg
729428d7b3dSmrg	return TRUE;
730428d7b3dSmrg}
731428d7b3dSmrg
732428d7b3dSmrgstatic void
733428d7b3dSmrgintel_flush_callback(CallbackListPtr *list,
734428d7b3dSmrg		     pointer user_data, pointer call_data)
735428d7b3dSmrg{
736428d7b3dSmrg	ScrnInfoPtr scrn = user_data;
737428d7b3dSmrg	if (scrn->vtSema)
738428d7b3dSmrg                intel_flush(intel_get_screen_private(scrn));
739428d7b3dSmrg}
740428d7b3dSmrg
741428d7b3dSmrg#if HAVE_UDEV
742428d7b3dSmrgstatic void
743428d7b3dSmrgI830HandleUEvents(int fd, void *closure)
744428d7b3dSmrg{
745428d7b3dSmrg	ScrnInfoPtr scrn = closure;
746428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
747428d7b3dSmrg	struct udev_device *dev;
748428d7b3dSmrg	const char *hotplug;
749428d7b3dSmrg	struct stat s;
750428d7b3dSmrg	dev_t udev_devnum;
751428d7b3dSmrg
752428d7b3dSmrg	dev = udev_monitor_receive_device(intel->uevent_monitor);
753428d7b3dSmrg	if (!dev)
754428d7b3dSmrg		return;
755428d7b3dSmrg
756428d7b3dSmrg	udev_devnum = udev_device_get_devnum(dev);
757428d7b3dSmrg	if (fstat(intel->drmSubFD, &s)) {
758428d7b3dSmrg		udev_device_unref(dev);
759428d7b3dSmrg		return;
760428d7b3dSmrg	}
761428d7b3dSmrg	/*
762428d7b3dSmrg	 * Check to make sure this event is directed at our
763428d7b3dSmrg	 * device (by comparing dev_t values), then make
764428d7b3dSmrg	 * sure it's a hotplug event (HOTPLUG=1)
765428d7b3dSmrg	 */
766428d7b3dSmrg
767428d7b3dSmrg	hotplug = udev_device_get_property_value(dev, "HOTPLUG");
768428d7b3dSmrg
769428d7b3dSmrg	if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
770428d7b3dSmrg			hotplug && atoi(hotplug) == 1)
771428d7b3dSmrg	{
772428d7b3dSmrg		intel_mode_hotplug(intel);
773428d7b3dSmrg	}
774428d7b3dSmrg
775428d7b3dSmrg	udev_device_unref(dev);
776428d7b3dSmrg}
777428d7b3dSmrg
778428d7b3dSmrgstatic void
779428d7b3dSmrgI830UeventInit(ScrnInfoPtr scrn)
780428d7b3dSmrg{
781428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
782428d7b3dSmrg	struct udev *u;
783428d7b3dSmrg	struct udev_monitor *mon;
784428d7b3dSmrg	Bool hotplug;
785428d7b3dSmrg	MessageType from = X_CONFIG;
786428d7b3dSmrg
787428d7b3dSmrg	if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) {
788428d7b3dSmrg		from = X_DEFAULT;
789428d7b3dSmrg		hotplug = TRUE;
790428d7b3dSmrg	}
791428d7b3dSmrg
792428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, from, "hotplug detection: \"%s\"\n",
793428d7b3dSmrg			hotplug ? "enabled" : "disabled");
794428d7b3dSmrg	if (!hotplug)
795428d7b3dSmrg		return;
796428d7b3dSmrg
797428d7b3dSmrg	u = udev_new();
798428d7b3dSmrg	if (!u)
799428d7b3dSmrg		return;
800428d7b3dSmrg
801428d7b3dSmrg	mon = udev_monitor_new_from_netlink(u, "udev");
802428d7b3dSmrg
803428d7b3dSmrg	if (!mon) {
804428d7b3dSmrg		udev_unref(u);
805428d7b3dSmrg		return;
806428d7b3dSmrg	}
807428d7b3dSmrg
808428d7b3dSmrg	if (udev_monitor_filter_add_match_subsystem_devtype(mon,
809428d7b3dSmrg				"drm",
810428d7b3dSmrg				"drm_minor") < 0 ||
811428d7b3dSmrg			udev_monitor_enable_receiving(mon) < 0)
812428d7b3dSmrg	{
813428d7b3dSmrg		udev_monitor_unref(mon);
814428d7b3dSmrg		udev_unref(u);
815428d7b3dSmrg		return;
816428d7b3dSmrg	}
817428d7b3dSmrg
818428d7b3dSmrg	intel->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon),
819428d7b3dSmrg						      I830HandleUEvents, scrn);
820428d7b3dSmrg	if (!intel->uevent_handler) {
821428d7b3dSmrg		udev_monitor_unref(mon);
822428d7b3dSmrg		udev_unref(u);
823428d7b3dSmrg		return;
824428d7b3dSmrg	}
825428d7b3dSmrg
826428d7b3dSmrg	intel->uevent_monitor = mon;
827428d7b3dSmrg}
828428d7b3dSmrg
829428d7b3dSmrgstatic void
830428d7b3dSmrgI830UeventFini(ScrnInfoPtr scrn)
831428d7b3dSmrg{
832428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
833428d7b3dSmrg
834428d7b3dSmrg	if (intel->uevent_handler) {
835428d7b3dSmrg		struct udev *u = udev_monitor_get_udev(intel->uevent_monitor);
836428d7b3dSmrg
837428d7b3dSmrg		xf86RemoveGeneralHandler(intel->uevent_handler);
838428d7b3dSmrg
839428d7b3dSmrg		udev_monitor_unref(intel->uevent_monitor);
840428d7b3dSmrg		udev_unref(u);
841428d7b3dSmrg		intel->uevent_handler = NULL;
842428d7b3dSmrg		intel->uevent_monitor = NULL;
843428d7b3dSmrg	}
844428d7b3dSmrg}
845428d7b3dSmrg#endif /* HAVE_UDEV */
846428d7b3dSmrg
847428d7b3dSmrgstatic Bool
848428d7b3dSmrgI830ScreenInit(SCREEN_INIT_ARGS_DECL)
849428d7b3dSmrg{
850428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
851428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
852428d7b3dSmrg	VisualPtr visual;
853428d7b3dSmrg#ifdef INTEL_XVMC
854428d7b3dSmrg	MessageType from;
855428d7b3dSmrg#endif
856428d7b3dSmrg	struct pci_device *const device = xf86GetPciInfoForEntity(intel->pEnt->index);
857428d7b3dSmrg	int fb_bar = IS_GEN2(intel) ? 0 : 2;
858428d7b3dSmrg
859428d7b3dSmrg	scrn->videoRam = device->regions[fb_bar].size / 1024;
860428d7b3dSmrg
861428d7b3dSmrg	intel->last_3d = LAST_3D_OTHER;
862428d7b3dSmrg	intel->overlayOn = FALSE;
863428d7b3dSmrg
864428d7b3dSmrg	/*
865428d7b3dSmrg	 * Set this so that the overlay allocation is factored in when
866428d7b3dSmrg	 * appropriate.
867428d7b3dSmrg	 */
868428d7b3dSmrg	intel->XvEnabled = TRUE;
869428d7b3dSmrg
870428d7b3dSmrg	if (!intel_init_initial_framebuffer(scrn))
871428d7b3dSmrg		return FALSE;
872428d7b3dSmrg
873428d7b3dSmrg	miClearVisualTypes();
874428d7b3dSmrg	if (!miSetVisualTypes(scrn->depth,
875428d7b3dSmrg			      miGetDefaultVisualMask(scrn->depth),
876428d7b3dSmrg			      scrn->rgbBits, scrn->defaultVisual))
877428d7b3dSmrg		return FALSE;
878428d7b3dSmrg	if (!miSetPixmapDepths())
879428d7b3dSmrg		return FALSE;
880428d7b3dSmrg
881428d7b3dSmrg	/* Must be first, before anything else installs screen callbacks. */
882428d7b3dSmrg	if (!fbScreenInit(screen, NULL,
883428d7b3dSmrg			  scrn->virtualX, scrn->virtualY,
884428d7b3dSmrg			  scrn->xDpi, scrn->yDpi,
885428d7b3dSmrg			  scrn->displayWidth, scrn->bitsPerPixel))
886428d7b3dSmrg		return FALSE;
887428d7b3dSmrg
888428d7b3dSmrg	if (scrn->bitsPerPixel > 8) {
889428d7b3dSmrg		/* Fixup RGB ordering */
890428d7b3dSmrg		visual = screen->visuals + screen->numVisuals;
891428d7b3dSmrg		while (--visual >= screen->visuals) {
892428d7b3dSmrg			if ((visual->class | DynamicClass) == DirectColor) {
893428d7b3dSmrg				visual->offsetRed = scrn->offset.red;
894428d7b3dSmrg				visual->offsetGreen = scrn->offset.green;
895428d7b3dSmrg				visual->offsetBlue = scrn->offset.blue;
896428d7b3dSmrg				visual->redMask = scrn->mask.red;
897428d7b3dSmrg				visual->greenMask = scrn->mask.green;
898428d7b3dSmrg				visual->blueMask = scrn->mask.blue;
899428d7b3dSmrg			}
900428d7b3dSmrg		}
901428d7b3dSmrg	}
902428d7b3dSmrg
903428d7b3dSmrg	fbPictureInit(screen, NULL, 0);
904428d7b3dSmrg
905428d7b3dSmrg	xf86SetBlackWhitePixels(screen);
906428d7b3dSmrg
907428d7b3dSmrg	if (!intel_uxa_init(screen)) {
908428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
909428d7b3dSmrg			   "Hardware acceleration initialization failed\n");
910428d7b3dSmrg		return FALSE;
911428d7b3dSmrg	}
912428d7b3dSmrg
913428d7b3dSmrg#if HAVE_DRI2
914428d7b3dSmrg	if (intel->dri2 == DRI_NONE && I830DRI2ScreenInit(screen))
915428d7b3dSmrg		intel->dri2 = DRI_ACTIVE;
916428d7b3dSmrg#endif
917428d7b3dSmrg
918428d7b3dSmrg#if HAVE_DRI3
919428d7b3dSmrg	if (!intel_sync_init(screen))
920428d7b3dSmrg		intel->dri3 = DRI_DISABLED;
921428d7b3dSmrg	if (intel->dri3 == DRI_NONE && intel_dri3_screen_init(screen))
922428d7b3dSmrg		intel->dri3 = DRI_ACTIVE;
923428d7b3dSmrg#endif
924428d7b3dSmrg
925428d7b3dSmrg	if (xf86ReturnOptValBool(intel->Options, OPTION_PRESENT, TRUE))
926428d7b3dSmrg		intel_present_screen_init(screen);
927428d7b3dSmrg
928428d7b3dSmrg	xf86SetBackingStore(screen);
929428d7b3dSmrg	xf86SetSilkenMouse(screen);
930428d7b3dSmrg	miDCInitialize(screen, xf86GetPointerScreenFuncs());
931428d7b3dSmrg
932428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_INFO, "Initializing HW Cursor\n");
933428d7b3dSmrg	if (!xf86_cursors_init(screen, 64, 64,
934428d7b3dSmrg			       (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
935428d7b3dSmrg				HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
936428d7b3dSmrg				HARDWARE_CURSOR_INVERT_MASK |
937428d7b3dSmrg				HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
938428d7b3dSmrg				HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
939428d7b3dSmrg				HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
940428d7b3dSmrg				HARDWARE_CURSOR_UPDATE_UNHIDDEN |
941428d7b3dSmrg				HARDWARE_CURSOR_ARGB))) {
942428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
943428d7b3dSmrg			   "Hardware cursor initialization failed\n");
944428d7b3dSmrg	}
945428d7b3dSmrg
946428d7b3dSmrg	intel->BlockHandler = screen->BlockHandler;
947428d7b3dSmrg	screen->BlockHandler = I830BlockHandler;
948428d7b3dSmrg
949428d7b3dSmrg#ifdef INTEL_PIXMAP_SHARING
950428d7b3dSmrg	screen->StartPixmapTracking = PixmapStartDirtyTracking;
951428d7b3dSmrg	screen->StopPixmapTracking = PixmapStopDirtyTracking;
952428d7b3dSmrg#endif
953428d7b3dSmrg
954428d7b3dSmrg	if (!AddCallback(&FlushCallback, intel_flush_callback, scrn))
955428d7b3dSmrg		return FALSE;
956428d7b3dSmrg
957428d7b3dSmrg	screen->SaveScreen = xf86SaveScreen;
958428d7b3dSmrg	intel->CloseScreen = screen->CloseScreen;
959428d7b3dSmrg	screen->CloseScreen = I830CloseScreen;
960428d7b3dSmrg	intel->CreateScreenResources = screen->CreateScreenResources;
961428d7b3dSmrg	screen->CreateScreenResources = i830CreateScreenResources;
962428d7b3dSmrg
963428d7b3dSmrg	if (!xf86CrtcScreenInit(screen))
964428d7b3dSmrg		return FALSE;
965428d7b3dSmrg
966428d7b3dSmrg	if (!miCreateDefColormap(screen))
967428d7b3dSmrg		return FALSE;
968428d7b3dSmrg
969428d7b3dSmrg	if (!xf86HandleColormaps(screen, 256, 8, I830LoadPalette, NULL,
970428d7b3dSmrg				 CMAP_RELOAD_ON_MODE_SWITCH |
971428d7b3dSmrg				 CMAP_PALETTED_TRUECOLOR)) {
972428d7b3dSmrg		return FALSE;
973428d7b3dSmrg	}
974428d7b3dSmrg
975428d7b3dSmrg	xf86DPMSInit(screen, xf86DPMSSet, 0);
976428d7b3dSmrg
977428d7b3dSmrg#ifdef INTEL_XVMC
978428d7b3dSmrg	if (INTEL_INFO(intel)->gen >= 040)
979428d7b3dSmrg		intel->XvMCEnabled = TRUE;
980428d7b3dSmrg	from = (intel->dri2 == DRI_ACTIVE &&
981428d7b3dSmrg		xf86GetOptValBool(intel->Options, OPTION_XVMC,
982428d7b3dSmrg				  &intel->XvMCEnabled) ? X_CONFIG : X_DEFAULT);
983428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, from, "Intel XvMC decoder %sabled\n",
984428d7b3dSmrg		   intel->XvMCEnabled ? "en" : "dis");
985428d7b3dSmrg#endif
986428d7b3dSmrg	/* Init video */
987428d7b3dSmrg	if (intel->XvEnabled)
988428d7b3dSmrg		intel_video_init(screen);
989428d7b3dSmrg
990428d7b3dSmrg#if HAVE_DRI2
991428d7b3dSmrg	switch (intel->dri2) {
992428d7b3dSmrg	case DRI_ACTIVE:
993428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_INFO,
994428d7b3dSmrg			   "DRI2: Enabled\n");
995428d7b3dSmrg		break;
996428d7b3dSmrg	case DRI_DISABLED:
997428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_INFO,
998428d7b3dSmrg			   "DRI2: Disabled\n");
999428d7b3dSmrg		break;
1000428d7b3dSmrg	case DRI_NONE:
1001428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1002428d7b3dSmrg			   "DRI2: Failed\n");
1003428d7b3dSmrg		break;
1004428d7b3dSmrg	}
1005428d7b3dSmrg#else
1006428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_INFO,
1007428d7b3dSmrg		   "DRI2: Not available\n");
1008428d7b3dSmrg#endif
1009428d7b3dSmrg
1010428d7b3dSmrg#if HAVE_DRI3
1011428d7b3dSmrg	switch (intel->dri3) {
1012428d7b3dSmrg	case DRI_ACTIVE:
1013428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1014428d7b3dSmrg			   "DRI3: Enabled\n");
1015428d7b3dSmrg		break;
1016428d7b3dSmrg	case DRI_DISABLED:
1017428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1018428d7b3dSmrg			   "DRI3: Disabled\n");
1019428d7b3dSmrg		break;
1020428d7b3dSmrg	case DRI_NONE:
1021428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1022428d7b3dSmrg			   "DRI3: Failed\n");
1023428d7b3dSmrg		break;
1024428d7b3dSmrg	}
1025428d7b3dSmrg#else
1026428d7b3dSmrg	xf86DrvMsg(scrn->scrnIndex, X_INFO,
1027428d7b3dSmrg		   "DRI3: Not available\n");
1028428d7b3dSmrg#endif
1029428d7b3dSmrg
1030428d7b3dSmrg	if (serverGeneration == 1)
1031428d7b3dSmrg		xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options);
1032428d7b3dSmrg
1033428d7b3dSmrg	intel_mode_init(intel);
1034428d7b3dSmrg
1035428d7b3dSmrg	intel->suspended = FALSE;
1036428d7b3dSmrg
1037428d7b3dSmrg#if HAVE_UDEV
1038428d7b3dSmrg	I830UeventInit(scrn);
1039428d7b3dSmrg#endif
1040428d7b3dSmrg
1041428d7b3dSmrg	/* Must force it before EnterVT, so we are in control of VT and
1042428d7b3dSmrg	 * later memory should be bound when allocating, e.g rotate_mem */
1043428d7b3dSmrg	scrn->vtSema = TRUE;
1044428d7b3dSmrg
1045428d7b3dSmrg	return I830EnterVT(VT_FUNC_ARGS(0));
1046428d7b3dSmrg}
1047428d7b3dSmrg
1048428d7b3dSmrgstatic void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL)
1049428d7b3dSmrg{
1050428d7b3dSmrg}
1051428d7b3dSmrg
1052428d7b3dSmrgstatic void I830FreeScreen(FREE_SCREEN_ARGS_DECL)
1053428d7b3dSmrg{
1054428d7b3dSmrg	SCRN_INFO_PTR(arg);
1055428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
1056428d7b3dSmrg
1057428d7b3dSmrg	if (intel && !((uintptr_t)intel & 3)) {
1058428d7b3dSmrg		intel_mode_fini(intel);
1059428d7b3dSmrg		intel_bufmgr_fini(intel);
1060428d7b3dSmrg		intel_put_device(intel->dev);
1061428d7b3dSmrg
1062428d7b3dSmrg		free(intel);
1063428d7b3dSmrg		scrn->driverPrivate = NULL;
1064428d7b3dSmrg	}
1065428d7b3dSmrg}
1066428d7b3dSmrg
1067428d7b3dSmrgstatic void I830LeaveVT(VT_FUNC_ARGS_DECL)
1068428d7b3dSmrg{
1069428d7b3dSmrg	SCRN_INFO_PTR(arg);
1070428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
1071428d7b3dSmrg
1072428d7b3dSmrg	xf86RotateFreeShadow(scrn);
1073428d7b3dSmrg
1074428d7b3dSmrg	xf86_hide_cursors(scrn);
1075428d7b3dSmrg
1076428d7b3dSmrg	if (intel_put_master(intel->dev))
1077428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1078428d7b3dSmrg			   "drmDropMaster failed: %s\n", strerror(errno));
1079428d7b3dSmrg}
1080428d7b3dSmrg
1081428d7b3dSmrg/*
1082428d7b3dSmrg * This gets called when gaining control of the VT, and from ScreenInit().
1083428d7b3dSmrg */
1084428d7b3dSmrgstatic Bool I830EnterVT(VT_FUNC_ARGS_DECL)
1085428d7b3dSmrg{
1086428d7b3dSmrg	SCRN_INFO_PTR(arg);
1087428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
1088428d7b3dSmrg
1089428d7b3dSmrg	if (intel_get_master(intel->dev)) {
1090428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1091428d7b3dSmrg			   "drmSetMaster failed: %s\n",
1092428d7b3dSmrg			   strerror(errno));
1093428d7b3dSmrg		return FALSE;
1094428d7b3dSmrg	}
1095428d7b3dSmrg
1096428d7b3dSmrg	if (!xf86SetDesiredModes(scrn))
1097428d7b3dSmrg		return FALSE;
1098428d7b3dSmrg
1099428d7b3dSmrg	intel_mode_disable_unused_functions(scrn);
1100428d7b3dSmrg	return TRUE;
1101428d7b3dSmrg}
1102428d7b3dSmrg
1103428d7b3dSmrgstatic Bool I830SwitchMode(SWITCH_MODE_ARGS_DECL)
1104428d7b3dSmrg{
1105428d7b3dSmrg	SCRN_INFO_PTR(arg);
1106428d7b3dSmrg
1107428d7b3dSmrg	return xf86SetSingleMode(scrn, mode, RR_Rotate_0);
1108428d7b3dSmrg}
1109428d7b3dSmrg
1110428d7b3dSmrgstatic Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL)
1111428d7b3dSmrg{
1112428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1113428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
1114428d7b3dSmrg
1115428d7b3dSmrg#if HAVE_UDEV
1116428d7b3dSmrg	I830UeventFini(scrn);
1117428d7b3dSmrg#endif
1118428d7b3dSmrg
1119428d7b3dSmrg	intel_mode_close(intel);
1120428d7b3dSmrg
1121428d7b3dSmrg	DeleteCallback(&FlushCallback, intel_flush_callback, scrn);
1122428d7b3dSmrg
1123428d7b3dSmrg	TimerFree(intel->cache_expire);
1124428d7b3dSmrg	intel->cache_expire = NULL;
1125428d7b3dSmrg
1126428d7b3dSmrg	if (intel->uxa_driver) {
1127428d7b3dSmrg		uxa_driver_fini(screen);
1128428d7b3dSmrg		free(intel->uxa_driver);
1129428d7b3dSmrg		intel->uxa_driver = NULL;
1130428d7b3dSmrg	}
1131428d7b3dSmrg
1132428d7b3dSmrg	if (intel->back_buffer) {
1133428d7b3dSmrg		drm_intel_bo_unreference(intel->back_buffer);
1134428d7b3dSmrg		intel->back_buffer = NULL;
1135428d7b3dSmrg	}
1136428d7b3dSmrg
1137428d7b3dSmrg	if (intel->front_buffer) {
1138428d7b3dSmrg		intel_mode_remove_fb(intel);
1139428d7b3dSmrg		drm_intel_bo_unreference(intel->front_buffer);
1140428d7b3dSmrg		intel->front_buffer = NULL;
1141428d7b3dSmrg	}
1142428d7b3dSmrg
1143428d7b3dSmrg	if (scrn->vtSema == TRUE) {
1144428d7b3dSmrg		I830LeaveVT(VT_FUNC_ARGS(0));
1145428d7b3dSmrg	}
1146428d7b3dSmrg
1147428d7b3dSmrg	intel_batch_teardown(scrn);
1148428d7b3dSmrg
1149428d7b3dSmrg	if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100)
1150428d7b3dSmrg		gen4_render_state_cleanup(scrn);
1151428d7b3dSmrg
1152428d7b3dSmrg	xf86_cursors_fini(screen);
1153428d7b3dSmrg
1154428d7b3dSmrg	i965_free_video(scrn);
1155428d7b3dSmrg
1156428d7b3dSmrg	screen->CloseScreen = intel->CloseScreen;
1157428d7b3dSmrg	(*screen->CloseScreen) (CLOSE_SCREEN_ARGS);
1158428d7b3dSmrg
1159428d7b3dSmrg	if (intel->dri2 == DRI_ACTIVE) {
1160428d7b3dSmrg		I830DRI2CloseScreen(screen);
1161428d7b3dSmrg		intel->dri2 = DRI_NONE;
1162428d7b3dSmrg	}
1163428d7b3dSmrg
1164428d7b3dSmrg	if (intel->dri3 == DRI_ACTIVE) {
1165428d7b3dSmrg		/* nothing to do here? */
1166428d7b3dSmrg		intel->dri3 = DRI_NONE;
1167428d7b3dSmrg	}
1168428d7b3dSmrg
1169428d7b3dSmrg	intel_sync_close(screen);
1170428d7b3dSmrg
1171428d7b3dSmrg	xf86GARTCloseScreen(scrn->scrnIndex);
1172428d7b3dSmrg
1173428d7b3dSmrg	scrn->vtSema = FALSE;
1174428d7b3dSmrg	return TRUE;
1175428d7b3dSmrg}
1176428d7b3dSmrg
1177428d7b3dSmrgstatic ModeStatus
1178428d7b3dSmrgI830ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
1179428d7b3dSmrg{
1180428d7b3dSmrg	SCRN_INFO_PTR(arg);
1181428d7b3dSmrg	if (mode->Flags & V_INTERLACE) {
1182428d7b3dSmrg		if (verbose) {
1183428d7b3dSmrg			xf86DrvMsg(scrn->scrnIndex, X_PROBED,
1184428d7b3dSmrg				   "Removing interlaced mode \"%s\"\n",
1185428d7b3dSmrg				   mode->name);
1186428d7b3dSmrg		}
1187428d7b3dSmrg		return MODE_BAD;
1188428d7b3dSmrg	}
1189428d7b3dSmrg	return MODE_OK;
1190428d7b3dSmrg}
1191428d7b3dSmrg
1192428d7b3dSmrg#ifndef SUSPEND_SLEEP
1193428d7b3dSmrg#define SUSPEND_SLEEP 0
1194428d7b3dSmrg#endif
1195428d7b3dSmrg#ifndef RESUME_SLEEP
1196428d7b3dSmrg#define RESUME_SLEEP 0
1197428d7b3dSmrg#endif
1198428d7b3dSmrg
1199428d7b3dSmrg/*
1200428d7b3dSmrg * This function is only required if we need to do anything differently from
1201428d7b3dSmrg * DoApmEvent() in common/xf86PM.c, including if we want to see events other
1202428d7b3dSmrg * than suspend/resume.
1203428d7b3dSmrg */
1204428d7b3dSmrgstatic Bool I830PMEvent(SCRN_ARG_TYPE arg, pmEvent event, Bool undo)
1205428d7b3dSmrg{
1206428d7b3dSmrg	SCRN_INFO_PTR(arg);
1207428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
1208428d7b3dSmrg
1209428d7b3dSmrg	switch (event) {
1210428d7b3dSmrg	case XF86_APM_SYS_SUSPEND:
1211428d7b3dSmrg	case XF86_APM_CRITICAL_SUSPEND:	/*do we want to delay a critical suspend? */
1212428d7b3dSmrg	case XF86_APM_USER_SUSPEND:
1213428d7b3dSmrg	case XF86_APM_SYS_STANDBY:
1214428d7b3dSmrg	case XF86_APM_USER_STANDBY:
1215428d7b3dSmrg		if (!undo && !intel->suspended) {
1216428d7b3dSmrg			scrn->LeaveVT(VT_FUNC_ARGS(0));
1217428d7b3dSmrg			intel->suspended = TRUE;
1218428d7b3dSmrg			sleep(SUSPEND_SLEEP);
1219428d7b3dSmrg		} else if (undo && intel->suspended) {
1220428d7b3dSmrg			sleep(RESUME_SLEEP);
1221428d7b3dSmrg			scrn->EnterVT(VT_FUNC_ARGS(0));
1222428d7b3dSmrg			intel->suspended = FALSE;
1223428d7b3dSmrg		}
1224428d7b3dSmrg		break;
1225428d7b3dSmrg	case XF86_APM_STANDBY_RESUME:
1226428d7b3dSmrg	case XF86_APM_NORMAL_RESUME:
1227428d7b3dSmrg	case XF86_APM_CRITICAL_RESUME:
1228428d7b3dSmrg		if (intel->suspended) {
1229428d7b3dSmrg			sleep(RESUME_SLEEP);
1230428d7b3dSmrg			scrn->EnterVT(VT_FUNC_ARGS(0));
1231428d7b3dSmrg			intel->suspended = FALSE;
1232428d7b3dSmrg			/*
1233428d7b3dSmrg			 * Turn the screen saver off when resuming.  This seems to be
1234428d7b3dSmrg			 * needed to stop xscreensaver kicking in (when used).
1235428d7b3dSmrg			 *
1236428d7b3dSmrg			 * XXX DoApmEvent() should probably call this just like
1237428d7b3dSmrg			 * xf86VTSwitch() does.  Maybe do it here only in 4.2
1238428d7b3dSmrg			 * compatibility mode.
1239428d7b3dSmrg			 */
1240428d7b3dSmrg			SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
1241428d7b3dSmrg		}
1242428d7b3dSmrg		break;
1243428d7b3dSmrg		/* This is currently used for ACPI */
1244428d7b3dSmrg	case XF86_APM_CAPABILITY_CHANGED:
1245428d7b3dSmrg		ErrorF("I830PMEvent: Capability change\n");
1246428d7b3dSmrg
1247428d7b3dSmrg		SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
1248428d7b3dSmrg
1249428d7b3dSmrg		break;
1250428d7b3dSmrg	default:
1251428d7b3dSmrg		ErrorF("I830PMEvent: received APM event %d\n", event);
1252428d7b3dSmrg	}
1253428d7b3dSmrg	return TRUE;
1254428d7b3dSmrg}
1255428d7b3dSmrg
1256428d7b3dSmrgBool intel_init_scrn(ScrnInfoPtr scrn)
1257428d7b3dSmrg{
1258428d7b3dSmrg	scrn->PreInit = I830PreInit;
1259428d7b3dSmrg	scrn->ScreenInit = I830ScreenInit;
1260428d7b3dSmrg	scrn->SwitchMode = I830SwitchMode;
1261428d7b3dSmrg	scrn->AdjustFrame = i830AdjustFrame;
1262428d7b3dSmrg	scrn->EnterVT = I830EnterVT;
1263428d7b3dSmrg	scrn->LeaveVT = I830LeaveVT;
1264428d7b3dSmrg	scrn->FreeScreen = I830FreeScreen;
1265428d7b3dSmrg	scrn->ValidMode = I830ValidMode;
1266428d7b3dSmrg	scrn->PMEvent = I830PMEvent;
1267428d7b3dSmrg	return TRUE;
1268428d7b3dSmrg}
1269