intel_driver.c revision 42542f5f
103b705cfSriastradh/**************************************************************************
203b705cfSriastradh
303b705cfSriastradhCopyright 2001 VA Linux Systems Inc., Fremont, California.
403b705cfSriastradhCopyright © 2002 by David Dawes
503b705cfSriastradh
603b705cfSriastradhAll Rights Reserved.
703b705cfSriastradh
803b705cfSriastradhPermission is hereby granted, free of charge, to any person obtaining a
903b705cfSriastradhcopy of this software and associated documentation files (the "Software"),
1003b705cfSriastradhto deal in the Software without restriction, including without limitation
1103b705cfSriastradhon the rights to use, copy, modify, merge, publish, distribute, sub
1203b705cfSriastradhlicense, and/or sell copies of the Software, and to permit persons to whom
1303b705cfSriastradhthe Software is furnished to do so, subject to the following conditions:
1403b705cfSriastradh
1503b705cfSriastradhThe above copyright notice and this permission notice (including the next
1603b705cfSriastradhparagraph) shall be included in all copies or substantial portions of the
1703b705cfSriastradhSoftware.
1803b705cfSriastradh
1903b705cfSriastradhTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2003b705cfSriastradhIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2103b705cfSriastradhFITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
2203b705cfSriastradhTHE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
2303b705cfSriastradhDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
2403b705cfSriastradhOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
2503b705cfSriastradhUSE OR OTHER DEALINGS IN THE SOFTWARE.
2603b705cfSriastradh
2703b705cfSriastradh**************************************************************************/
2803b705cfSriastradh
2903b705cfSriastradh/*
3003b705cfSriastradh * Authors: Jeff Hartmann <jhartmann@valinux.com>
3103b705cfSriastradh *          Abraham van der Merwe <abraham@2d3d.co.za>
3203b705cfSriastradh *          David Dawes <dawes@xfree86.org>
3303b705cfSriastradh *          Alan Hourihane <alanh@tungstengraphics.com>
3403b705cfSriastradh */
3503b705cfSriastradh
3603b705cfSriastradh#ifdef HAVE_CONFIG_H
3703b705cfSriastradh#include "config.h"
3803b705cfSriastradh#endif
3903b705cfSriastradh
4003b705cfSriastradh#include <assert.h>
4103b705cfSriastradh#include <string.h>
4203b705cfSriastradh#include <stdio.h>
4303b705cfSriastradh#include <unistd.h>
4403b705cfSriastradh#include <stdlib.h>
4503b705cfSriastradh#include <stdio.h>
4603b705cfSriastradh#include <errno.h>
4703b705cfSriastradh
4842542f5fSchristos#include "xorg-server.h"
4903b705cfSriastradh#include "xf86.h"
5003b705cfSriastradh#include "xf86_OSproc.h"
5103b705cfSriastradh#include "xf86cmap.h"
5203b705cfSriastradh#include "xf86drm.h"
5303b705cfSriastradh#include "compiler.h"
5403b705cfSriastradh#include "mipointer.h"
5503b705cfSriastradh#include "micmap.h"
5603b705cfSriastradh#include <X11/extensions/randr.h>
5703b705cfSriastradh#include "fb.h"
5803b705cfSriastradh#include "miscstruct.h"
5903b705cfSriastradh#include "dixstruct.h"
6003b705cfSriastradh#include "xf86xv.h"
6103b705cfSriastradh#include "shadow.h"
6203b705cfSriastradh#include "intel.h"
6303b705cfSriastradh#include "intel_video.h"
6403b705cfSriastradh#include "uxa_module.h"
6503b705cfSriastradh
6603b705cfSriastradh#ifdef INTEL_XVMC
6703b705cfSriastradh#define _INTEL_XVMC_SERVER_
6803b705cfSriastradh#include "intel_xvmc.h"
6903b705cfSriastradh#endif
7003b705cfSriastradh
7103b705cfSriastradh#include "uxa.h"
7203b705cfSriastradh
7303b705cfSriastradh#include "i915_drm.h"
7403b705cfSriastradh
7503b705cfSriastradh#include "intel_glamor.h"
7603b705cfSriastradh#include "intel_options.h"
7703b705cfSriastradh
7803b705cfSriastradhstatic void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL);
7903b705cfSriastradhstatic Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL);
8003b705cfSriastradhstatic Bool I830EnterVT(VT_FUNC_ARGS_DECL);
8103b705cfSriastradh
8203b705cfSriastradh/* temporary */
8303b705cfSriastradhextern void xf86SetCursor(ScreenPtr screen, CursorPtr pCurs, int x, int y);
8403b705cfSriastradh
8503b705cfSriastradh/* Export I830 options to i830 driver where necessary */
8603b705cfSriastradhstatic void
8703b705cfSriastradhI830LoadPalette(ScrnInfoPtr scrn, int numColors, int *indices,
8803b705cfSriastradh		LOCO * colors, VisualPtr pVisual)
8903b705cfSriastradh{
9003b705cfSriastradh	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
9103b705cfSriastradh	int i, j, index;
9203b705cfSriastradh	int p;
9303b705cfSriastradh	uint16_t lut_r[256], lut_g[256], lut_b[256];
9403b705cfSriastradh
9503b705cfSriastradh	for (p = 0; p < xf86_config->num_crtc; p++) {
9603b705cfSriastradh		xf86CrtcPtr crtc = xf86_config->crtc[p];
9703b705cfSriastradh
9803b705cfSriastradh		switch (scrn->depth) {
9903b705cfSriastradh		case 15:
10003b705cfSriastradh			for (i = 0; i < numColors; i++) {
10103b705cfSriastradh				index = indices[i];
10203b705cfSriastradh				for (j = 0; j < 8; j++) {
10303b705cfSriastradh					lut_r[index * 8 + j] =
10403b705cfSriastradh					    colors[index].red << 8;
10503b705cfSriastradh					lut_g[index * 8 + j] =
10603b705cfSriastradh					    colors[index].green << 8;
10703b705cfSriastradh					lut_b[index * 8 + j] =
10803b705cfSriastradh					    colors[index].blue << 8;
10903b705cfSriastradh				}
11003b705cfSriastradh			}
11103b705cfSriastradh			break;
11203b705cfSriastradh		case 16:
11303b705cfSriastradh			for (i = 0; i < numColors; i++) {
11403b705cfSriastradh				index = indices[i];
11503b705cfSriastradh
11603b705cfSriastradh				if (index <= 31) {
11703b705cfSriastradh					for (j = 0; j < 8; j++) {
11803b705cfSriastradh						lut_r[index * 8 + j] =
11903b705cfSriastradh						    colors[index].red << 8;
12003b705cfSriastradh						lut_b[index * 8 + j] =
12103b705cfSriastradh						    colors[index].blue << 8;
12203b705cfSriastradh					}
12303b705cfSriastradh				}
12403b705cfSriastradh
12503b705cfSriastradh				for (j = 0; j < 4; j++) {
12603b705cfSriastradh					lut_g[index * 4 + j] =
12703b705cfSriastradh					    colors[index].green << 8;
12803b705cfSriastradh				}
12903b705cfSriastradh			}
13003b705cfSriastradh			break;
13103b705cfSriastradh		default:
13203b705cfSriastradh			for (i = 0; i < numColors; i++) {
13303b705cfSriastradh				index = indices[i];
13403b705cfSriastradh				lut_r[index] = colors[index].red << 8;
13503b705cfSriastradh				lut_g[index] = colors[index].green << 8;
13603b705cfSriastradh				lut_b[index] = colors[index].blue << 8;
13703b705cfSriastradh			}
13803b705cfSriastradh			break;
13903b705cfSriastradh		}
14003b705cfSriastradh
14103b705cfSriastradh		/* Make the change through RandR */
14203b705cfSriastradh#ifdef RANDR_12_INTERFACE
14303b705cfSriastradh		RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
14403b705cfSriastradh#else
14503b705cfSriastradh		crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
14603b705cfSriastradh#endif
14703b705cfSriastradh	}
14803b705cfSriastradh}
14903b705cfSriastradh
15003b705cfSriastradh/**
15103b705cfSriastradh * Adjust the screen pixmap for the current location of the front buffer.
15203b705cfSriastradh * This is done at EnterVT when buffers are bound as long as the resources
15303b705cfSriastradh * have already been created, but the first EnterVT happens before
15403b705cfSriastradh * CreateScreenResources.
15503b705cfSriastradh */
15603b705cfSriastradhstatic Bool i830CreateScreenResources(ScreenPtr screen)
15703b705cfSriastradh{
15803b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
15903b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
16003b705cfSriastradh
16103b705cfSriastradh	screen->CreateScreenResources = intel->CreateScreenResources;
16203b705cfSriastradh	if (!(*screen->CreateScreenResources) (screen))
16303b705cfSriastradh		return FALSE;
16403b705cfSriastradh
16503b705cfSriastradh	if (!intel_uxa_create_screen_resources(screen))
16603b705cfSriastradh		return FALSE;
16703b705cfSriastradh
16803b705cfSriastradh	intel_copy_fb(scrn);
16903b705cfSriastradh	return TRUE;
17003b705cfSriastradh}
17103b705cfSriastradh
17203b705cfSriastradhstatic void PreInitCleanup(ScrnInfoPtr scrn)
17303b705cfSriastradh{
17403b705cfSriastradh	if (!scrn || !scrn->driverPrivate)
17503b705cfSriastradh		return;
17603b705cfSriastradh
17703b705cfSriastradh	free(scrn->driverPrivate);
17803b705cfSriastradh	scrn->driverPrivate = NULL;
17903b705cfSriastradh}
18003b705cfSriastradh
18103b705cfSriastradhstatic void intel_check_chipset_option(ScrnInfoPtr scrn)
18203b705cfSriastradh{
18303b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
18442542f5fSchristos	intel_detect_chipset(scrn, intel->pEnt);
18503b705cfSriastradh}
18603b705cfSriastradh
18703b705cfSriastradhstatic Bool I830GetEarlyOptions(ScrnInfoPtr scrn)
18803b705cfSriastradh{
18903b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
19003b705cfSriastradh
19103b705cfSriastradh	/* Process the options */
19203b705cfSriastradh	intel->Options = intel_options_get(scrn);
19303b705cfSriastradh	if (!intel->Options)
19403b705cfSriastradh		return FALSE;
19503b705cfSriastradh
19603b705cfSriastradh	intel->fallback_debug = xf86ReturnOptValBool(intel->Options,
19703b705cfSriastradh						     OPTION_FALLBACKDEBUG,
19803b705cfSriastradh						     FALSE);
19903b705cfSriastradh
20003b705cfSriastradh	intel->debug_flush = 0;
20103b705cfSriastradh
20203b705cfSriastradh	if (xf86ReturnOptValBool(intel->Options,
20303b705cfSriastradh				 OPTION_DEBUG_FLUSH_BATCHES,
20403b705cfSriastradh				 FALSE))
20503b705cfSriastradh		intel->debug_flush |= DEBUG_FLUSH_BATCHES;
20603b705cfSriastradh
20703b705cfSriastradh	if (xf86ReturnOptValBool(intel->Options,
20803b705cfSriastradh				 OPTION_DEBUG_FLUSH_CACHES,
20903b705cfSriastradh				 FALSE))
21003b705cfSriastradh		intel->debug_flush |= DEBUG_FLUSH_CACHES;
21103b705cfSriastradh
21203b705cfSriastradh	if (xf86ReturnOptValBool(intel->Options,
21303b705cfSriastradh				 OPTION_DEBUG_WAIT,
21403b705cfSriastradh				 FALSE))
21503b705cfSriastradh		intel->debug_flush |= DEBUG_FLUSH_WAIT;
21603b705cfSriastradh
21703b705cfSriastradh	return TRUE;
21803b705cfSriastradh}
21903b705cfSriastradh
22003b705cfSriastradhstatic Bool intel_option_cast_string_to_bool(intel_screen_private *intel,
22103b705cfSriastradh					     int id, Bool val)
22203b705cfSriastradh{
22342542f5fSchristos#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
22403b705cfSriastradh	xf86getBoolValue(&val, xf86GetOptValString(intel->Options, id));
22503b705cfSriastradh	return val;
22642542f5fSchristos#else
22742542f5fSchristos	return val;
22842542f5fSchristos#endif
22903b705cfSriastradh}
23003b705cfSriastradh
23103b705cfSriastradhstatic void intel_check_dri_option(ScrnInfoPtr scrn)
23203b705cfSriastradh{
23303b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
23403b705cfSriastradh
23542542f5fSchristos	intel->dri2 = intel->dri3 = DRI_NONE;
23603b705cfSriastradh	if (!intel_option_cast_string_to_bool(intel, OPTION_DRI, TRUE))
23742542f5fSchristos		intel->dri2 = intel->dri3 = DRI_DISABLED;
23803b705cfSriastradh
23903b705cfSriastradh	if (scrn->depth != 16 && scrn->depth != 24 && scrn->depth != 30) {
24003b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
24103b705cfSriastradh			   "DRI is disabled because it "
24203b705cfSriastradh			   "runs only at depths 16, 24, and 30.\n");
24342542f5fSchristos		intel->dri2 = intel->dri3 = DRI_DISABLED;
24403b705cfSriastradh	}
24503b705cfSriastradh}
24603b705cfSriastradh
24703b705cfSriastradhstatic Bool intel_open_drm_master(ScrnInfoPtr scrn)
24803b705cfSriastradh{
24903b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
25003b705cfSriastradh
25142542f5fSchristos	intel->drmSubFD = intel_get_device(scrn);
25242542f5fSchristos	return intel->drmSubFD != -1;
25303b705cfSriastradh}
25403b705cfSriastradh
25503b705cfSriastradhstatic int intel_init_bufmgr(intel_screen_private *intel)
25603b705cfSriastradh{
25703b705cfSriastradh	int batch_size;
25803b705cfSriastradh
25903b705cfSriastradh	batch_size = 4096 * 4;
26003b705cfSriastradh	if (IS_I865G(intel))
26103b705cfSriastradh		/* The 865 has issues with larger-than-page-sized batch buffers. */
26203b705cfSriastradh		batch_size = 4096;
26303b705cfSriastradh
26403b705cfSriastradh	intel->bufmgr = drm_intel_bufmgr_gem_init(intel->drmSubFD, batch_size);
26503b705cfSriastradh	if (!intel->bufmgr)
26603b705cfSriastradh		return FALSE;
26703b705cfSriastradh
26803b705cfSriastradh	if (xf86ReturnOptValBool(intel->Options, OPTION_BUFFER_CACHE, TRUE))
26903b705cfSriastradh		drm_intel_bufmgr_gem_enable_reuse(intel->bufmgr);
27003b705cfSriastradh	drm_intel_bufmgr_gem_set_vma_cache_size(intel->bufmgr, 512);
27103b705cfSriastradh	drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr);
27203b705cfSriastradh
27303b705cfSriastradh	list_init(&intel->batch_pixmaps);
27403b705cfSriastradh
27503b705cfSriastradh	if ((INTEL_INFO(intel)->gen == 060)) {
27603b705cfSriastradh		intel->wa_scratch_bo =
27703b705cfSriastradh			drm_intel_bo_alloc(intel->bufmgr, "wa scratch",
27803b705cfSriastradh					   4096, 4096);
27903b705cfSriastradh	}
28003b705cfSriastradh
28103b705cfSriastradh	return TRUE;
28203b705cfSriastradh}
28303b705cfSriastradh
28403b705cfSriastradhstatic void intel_bufmgr_fini(intel_screen_private *intel)
28503b705cfSriastradh{
28603b705cfSriastradh	if (intel->bufmgr == NULL)
28703b705cfSriastradh		return;
28803b705cfSriastradh
28903b705cfSriastradh	drm_intel_bo_unreference(intel->wa_scratch_bo);
29003b705cfSriastradh	drm_intel_bufmgr_destroy(intel->bufmgr);
29103b705cfSriastradh}
29203b705cfSriastradh
29303b705cfSriastradhstatic void I830XvInit(ScrnInfoPtr scrn)
29403b705cfSriastradh{
29503b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
29603b705cfSriastradh	MessageType from = X_PROBED;
29703b705cfSriastradh
29803b705cfSriastradh	intel->XvPreferOverlay =
29903b705cfSriastradh	    xf86ReturnOptValBool(intel->Options, OPTION_PREFER_OVERLAY, FALSE);
30003b705cfSriastradh
30103b705cfSriastradh	if (xf86GetOptValInteger(intel->Options, OPTION_VIDEO_KEY,
30203b705cfSriastradh				 &(intel->colorKey))) {
30303b705cfSriastradh		from = X_CONFIG;
30403b705cfSriastradh	} else if (xf86GetOptValInteger(intel->Options, OPTION_COLOR_KEY,
30503b705cfSriastradh					&(intel->colorKey))) {
30603b705cfSriastradh		from = X_CONFIG;
30703b705cfSriastradh	} else {
30803b705cfSriastradh		intel->colorKey =
30903b705cfSriastradh		    (1 << scrn->offset.red) | (1 << scrn->offset.green) |
31003b705cfSriastradh		    (((scrn->mask.blue >> scrn->offset.blue) - 1) <<
31103b705cfSriastradh		     scrn->offset.blue);
31203b705cfSriastradh		from = X_DEFAULT;
31303b705cfSriastradh	}
31403b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, from, "video overlay key set to 0x%x\n",
31503b705cfSriastradh		   intel->colorKey);
31603b705cfSriastradh}
31703b705cfSriastradh
31803b705cfSriastradhstatic Bool drm_has_boolean_param(struct intel_screen_private *intel,
31903b705cfSriastradh				  int param)
32003b705cfSriastradh{
32103b705cfSriastradh	drm_i915_getparam_t gp;
32203b705cfSriastradh	int value;
32303b705cfSriastradh
32403b705cfSriastradh	gp.value = &value;
32503b705cfSriastradh	gp.param = param;
32603b705cfSriastradh	if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp))
32703b705cfSriastradh		return FALSE;
32803b705cfSriastradh
32903b705cfSriastradh	return value;
33003b705cfSriastradh}
33103b705cfSriastradh
33203b705cfSriastradhstatic Bool has_kernel_flush(struct intel_screen_private *intel)
33303b705cfSriastradh{
33403b705cfSriastradh	/* The BLT ring was introduced at the same time as the
33503b705cfSriastradh	 * automatic flush for the busy-ioctl.
33603b705cfSriastradh	 */
33703b705cfSriastradh	return drm_has_boolean_param(intel, I915_PARAM_HAS_BLT);
33803b705cfSriastradh}
33903b705cfSriastradh
34003b705cfSriastradhstatic Bool has_relaxed_fencing(struct intel_screen_private *intel)
34103b705cfSriastradh{
34203b705cfSriastradh	return drm_has_boolean_param(intel, I915_PARAM_HAS_RELAXED_FENCING);
34303b705cfSriastradh}
34403b705cfSriastradh
34503b705cfSriastradhstatic Bool has_prime_vmap_flush(struct intel_screen_private *intel)
34603b705cfSriastradh{
34703b705cfSriastradh	return drm_has_boolean_param(intel, I915_PARAM_HAS_PRIME_VMAP_FLUSH);
34803b705cfSriastradh}
34903b705cfSriastradh
35003b705cfSriastradhstatic Bool can_accelerate_blt(struct intel_screen_private *intel)
35103b705cfSriastradh{
35203b705cfSriastradh	if (INTEL_INFO(intel)->gen == -1)
35303b705cfSriastradh		return FALSE;
35403b705cfSriastradh
35503b705cfSriastradh	if (xf86ReturnOptValBool(intel->Options, OPTION_ACCEL_DISABLE, FALSE) ||
35603b705cfSriastradh	    !intel_option_cast_string_to_bool(intel, OPTION_ACCEL_METHOD, TRUE)) {
35703b705cfSriastradh		xf86DrvMsg(intel->scrn->scrnIndex, X_CONFIG,
35803b705cfSriastradh			   "Disabling hardware acceleration.\n");
35903b705cfSriastradh		return FALSE;
36003b705cfSriastradh	}
36103b705cfSriastradh
36203b705cfSriastradh	if (INTEL_INFO(intel)->gen == 060) {
36303b705cfSriastradh		struct pci_device *const device = intel->PciInfo;
36403b705cfSriastradh
36503b705cfSriastradh		/* Sandybridge rev07 locks up easily, even with the
36603b705cfSriastradh		 * BLT ring workaround in place.
36703b705cfSriastradh		 * Thus use shadowfb by default.
36803b705cfSriastradh		 */
36903b705cfSriastradh		if (device->revision < 8) {
37003b705cfSriastradh			xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING,
37103b705cfSriastradh				   "Disabling hardware acceleration on this pre-production hardware.\n");
37203b705cfSriastradh
37303b705cfSriastradh			return FALSE;
37403b705cfSriastradh		}
37503b705cfSriastradh	}
37603b705cfSriastradh
37703b705cfSriastradh	if (INTEL_INFO(intel)->gen >= 060) {
37803b705cfSriastradh		drm_i915_getparam_t gp;
37903b705cfSriastradh		int value;
38003b705cfSriastradh
38103b705cfSriastradh		/* On Sandybridge we need the BLT in order to do anything since
38203b705cfSriastradh		 * it so frequently used in the acceleration code paths.
38303b705cfSriastradh		 */
38403b705cfSriastradh		gp.value = &value;
38503b705cfSriastradh		gp.param = I915_PARAM_HAS_BLT;
38603b705cfSriastradh		if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp))
38703b705cfSriastradh			return FALSE;
38803b705cfSriastradh	}
38903b705cfSriastradh
39003b705cfSriastradh	return TRUE;
39103b705cfSriastradh}
39203b705cfSriastradh
39303b705cfSriastradhstatic void intel_setup_capabilities(ScrnInfoPtr scrn)
39403b705cfSriastradh{
39503b705cfSriastradh#ifdef INTEL_PIXMAP_SHARING
39603b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
39703b705cfSriastradh	uint64_t value;
39803b705cfSriastradh	int ret;
39903b705cfSriastradh
40003b705cfSriastradh	scrn->capabilities = 0;
40103b705cfSriastradh
40203b705cfSriastradh	ret = drmGetCap(intel->drmSubFD, DRM_CAP_PRIME, &value);
40303b705cfSriastradh	if (ret == 0) {
40403b705cfSriastradh		if (value & DRM_PRIME_CAP_EXPORT)
40503b705cfSriastradh			scrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload;
40603b705cfSriastradh		if (value & DRM_PRIME_CAP_IMPORT)
40703b705cfSriastradh			scrn->capabilities |= RR_Capability_SinkOutput;
40803b705cfSriastradh	}
40903b705cfSriastradh#endif
41003b705cfSriastradh}
41103b705cfSriastradh
41203b705cfSriastradh/**
41303b705cfSriastradh * This is called before ScreenInit to do any require probing of screen
41403b705cfSriastradh * configuration.
41503b705cfSriastradh *
41603b705cfSriastradh * This code generally covers probing, module loading, option handling
41703b705cfSriastradh * card mapping, and RandR setup.
41803b705cfSriastradh *
41903b705cfSriastradh * Since xf86InitialConfiguration ends up requiring that we set video modes
42003b705cfSriastradh * in order to detect configuration, we end up having to do a lot of driver
42103b705cfSriastradh * setup (talking to the DRM, mapping the device, etc.) in this function.
42203b705cfSriastradh * As a result, we want to set up that server initialization once rather
42303b705cfSriastradh * that doing it per generation.
42403b705cfSriastradh */
42503b705cfSriastradhstatic Bool I830PreInit(ScrnInfoPtr scrn, int flags)
42603b705cfSriastradh{
42703b705cfSriastradh	intel_screen_private *intel;
42803b705cfSriastradh	rgb defaultWeight = { 0, 0, 0 };
42903b705cfSriastradh	EntityInfoPtr pEnt;
43003b705cfSriastradh	int flags24;
43103b705cfSriastradh	Gamma zeros = { 0.0, 0.0, 0.0 };
43203b705cfSriastradh
43303b705cfSriastradh	if (scrn->numEntities != 1)
43403b705cfSriastradh		return FALSE;
43503b705cfSriastradh
43603b705cfSriastradh	pEnt = xf86GetEntityInfo(scrn->entityList[0]);
43703b705cfSriastradh	if (pEnt == NULL)
43803b705cfSriastradh		return FALSE;
43903b705cfSriastradh
44003b705cfSriastradh	if (pEnt->location.type != BUS_PCI
44103b705cfSriastradh#ifdef XSERVER_PLATFORM_BUS
44203b705cfSriastradh	    && pEnt->location.type != BUS_PLATFORM
44303b705cfSriastradh#endif
44403b705cfSriastradh		)
44503b705cfSriastradh		return FALSE;
44603b705cfSriastradh
44703b705cfSriastradh	if (flags & PROBE_DETECT)
44803b705cfSriastradh		return TRUE;
44903b705cfSriastradh
45042542f5fSchristos	if (((uintptr_t)scrn->driverPrivate) & 3) {
45103b705cfSriastradh		intel = xnfcalloc(sizeof(*intel), 1);
45203b705cfSriastradh		if (intel == NULL)
45303b705cfSriastradh			return FALSE;
45403b705cfSriastradh
45542542f5fSchristos		intel->info = (void *)((uintptr_t)scrn->driverPrivate & ~3);
45603b705cfSriastradh		scrn->driverPrivate = intel;
45703b705cfSriastradh	}
45803b705cfSriastradh	intel = intel_get_screen_private(scrn);
45903b705cfSriastradh	intel->scrn = scrn;
46003b705cfSriastradh	intel->pEnt = pEnt;
46103b705cfSriastradh
46203b705cfSriastradh	scrn->displayWidth = 640;	/* default it */
46303b705cfSriastradh
46403b705cfSriastradh	intel->PciInfo = xf86GetPciInfoForEntity(intel->pEnt->index);
46503b705cfSriastradh
46603b705cfSriastradh	if (!intel_open_drm_master(scrn)) {
46703b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
46803b705cfSriastradh			   "Failed to become DRM master.\n");
46903b705cfSriastradh		return FALSE;
47003b705cfSriastradh	}
47103b705cfSriastradh
47203b705cfSriastradh	scrn->monitor = scrn->confScreen->monitor;
47303b705cfSriastradh	scrn->progClock = TRUE;
47403b705cfSriastradh	scrn->rgbBits = 8;
47503b705cfSriastradh
47603b705cfSriastradh	flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32;
47703b705cfSriastradh
47803b705cfSriastradh	if (!xf86SetDepthBpp(scrn, 0, 0, 0, flags24))
47903b705cfSriastradh		return FALSE;
48003b705cfSriastradh
48103b705cfSriastradh	switch (scrn->depth) {
48203b705cfSriastradh	case 15:
48303b705cfSriastradh	case 16:
48403b705cfSriastradh	case 24:
48503b705cfSriastradh	case 30:
48603b705cfSriastradh		break;
48703b705cfSriastradh	case 8:
48803b705cfSriastradh	default:
48903b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
49003b705cfSriastradh			   "Given depth (%d) is not supported by intel driver\n",
49103b705cfSriastradh			   scrn->depth);
49203b705cfSriastradh		return FALSE;
49303b705cfSriastradh	}
49403b705cfSriastradh	xf86PrintDepthBpp(scrn);
49503b705cfSriastradh
49603b705cfSriastradh	if (!xf86SetWeight(scrn, defaultWeight, defaultWeight))
49703b705cfSriastradh		return FALSE;
49803b705cfSriastradh	if (!xf86SetDefaultVisual(scrn, -1))
49903b705cfSriastradh		return FALSE;
50003b705cfSriastradh
50103b705cfSriastradh	intel->cpp = scrn->bitsPerPixel / 8;
50203b705cfSriastradh
50303b705cfSriastradh	if (!I830GetEarlyOptions(scrn))
50403b705cfSriastradh		return FALSE;
50503b705cfSriastradh
50603b705cfSriastradh	intel_setup_capabilities(scrn);
50703b705cfSriastradh	intel_check_chipset_option(scrn);
50803b705cfSriastradh	intel_check_dri_option(scrn);
50903b705cfSriastradh
51003b705cfSriastradh	if (!intel_init_bufmgr(intel)) {
51103b705cfSriastradh		PreInitCleanup(scrn);
51203b705cfSriastradh		return FALSE;
51303b705cfSriastradh	}
51403b705cfSriastradh
51503b705cfSriastradh	intel->force_fallback =
51603b705cfSriastradh		drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE) != 0;
51703b705cfSriastradh
51803b705cfSriastradh	/* Enable tiling by default */
51903b705cfSriastradh	intel->tiling = INTEL_TILING_ALL;
52003b705cfSriastradh
52103b705cfSriastradh	/* Allow user override if they set a value */
52203b705cfSriastradh	if (!xf86ReturnOptValBool(intel->Options, OPTION_TILING_2D, TRUE))
52303b705cfSriastradh		intel->tiling &= ~INTEL_TILING_2D;
52403b705cfSriastradh	if (xf86ReturnOptValBool(intel->Options, OPTION_TILING_FB, FALSE))
52503b705cfSriastradh		intel->tiling &= ~INTEL_TILING_FB;
52603b705cfSriastradh	if (!can_accelerate_blt(intel)) {
52703b705cfSriastradh		intel->force_fallback = TRUE;
52803b705cfSriastradh		intel->tiling &= ~INTEL_TILING_FB;
52903b705cfSriastradh	}
53003b705cfSriastradh
53103b705cfSriastradh	intel->has_kernel_flush = has_kernel_flush(intel);
53203b705cfSriastradh
53303b705cfSriastradh	intel->has_prime_vmap_flush = has_prime_vmap_flush(intel);
53403b705cfSriastradh
53503b705cfSriastradh	intel->has_relaxed_fencing = INTEL_INFO(intel)->gen >= 033;
53603b705cfSriastradh	/* And override the user if there is no kernel support */
53703b705cfSriastradh	if (intel->has_relaxed_fencing)
53803b705cfSriastradh		intel->has_relaxed_fencing = has_relaxed_fencing(intel);
53903b705cfSriastradh
54003b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
54103b705cfSriastradh		   "Relaxed fencing %s\n",
54203b705cfSriastradh		   intel->has_relaxed_fencing ? "enabled" : "disabled");
54303b705cfSriastradh
54403b705cfSriastradh	/* SwapBuffers delays to avoid tearing */
54503b705cfSriastradh	intel->swapbuffers_wait = xf86ReturnOptValBool(intel->Options,
54603b705cfSriastradh						       OPTION_SWAPBUFFERS_WAIT,
54703b705cfSriastradh						       TRUE);
54803b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Wait on SwapBuffers? %s\n",
54903b705cfSriastradh		   intel->swapbuffers_wait ? "enabled" : "disabled");
55003b705cfSriastradh
55103b705cfSriastradh	intel->use_triple_buffer =
55203b705cfSriastradh		xf86ReturnOptValBool(intel->Options,
55303b705cfSriastradh				     OPTION_TRIPLE_BUFFER,
55403b705cfSriastradh				     TRUE);
55503b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Triple buffering? %s\n",
55603b705cfSriastradh		   intel->use_triple_buffer ? "enabled" : "disabled");
55703b705cfSriastradh
55803b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Framebuffer %s\n",
55903b705cfSriastradh		   intel->tiling & INTEL_TILING_FB ? "tiled" : "linear");
56003b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Pixmaps %s\n",
56103b705cfSriastradh		   intel->tiling & INTEL_TILING_2D ? "tiled" : "linear");
56203b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "3D buffers %s\n",
56303b705cfSriastradh		   intel->tiling & INTEL_TILING_3D ? "tiled" : "linear");
56403b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "SwapBuffers wait %sabled\n",
56503b705cfSriastradh		   intel->swapbuffers_wait ? "en" : "dis");
56603b705cfSriastradh
56703b705cfSriastradh	I830XvInit(scrn);
56803b705cfSriastradh
56903b705cfSriastradh	if (!intel_mode_pre_init(scrn, intel->drmSubFD, intel->cpp)) {
57003b705cfSriastradh		PreInitCleanup(scrn);
57103b705cfSriastradh		return FALSE;
57203b705cfSriastradh	}
57303b705cfSriastradh
57403b705cfSriastradh	if (!xf86SetGamma(scrn, zeros)) {
57503b705cfSriastradh		PreInitCleanup(scrn);
57603b705cfSriastradh		return FALSE;
57703b705cfSriastradh	}
57803b705cfSriastradh
57903b705cfSriastradh	if (scrn->modes == NULL) {
58003b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR, "No modes.\n");
58103b705cfSriastradh		PreInitCleanup(scrn);
58203b705cfSriastradh		return FALSE;
58303b705cfSriastradh	}
58403b705cfSriastradh	scrn->currentMode = scrn->modes;
58503b705cfSriastradh
58603b705cfSriastradh	/* Set display resolution */
58703b705cfSriastradh	xf86SetDpi(scrn, 0, 0);
58803b705cfSriastradh
58903b705cfSriastradh	/* Load the required sub modules */
59003b705cfSriastradh	if (!xf86LoadSubModule(scrn, "fb")) {
59103b705cfSriastradh		PreInitCleanup(scrn);
59203b705cfSriastradh		return FALSE;
59303b705cfSriastradh	}
59403b705cfSriastradh
59503b705cfSriastradh	if (!intel_glamor_pre_init(scrn)) {
59603b705cfSriastradh		PreInitCleanup(scrn);
59703b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
59803b705cfSriastradh			"Failed to pre init glamor display.\n");
59903b705cfSriastradh		return FALSE;
60003b705cfSriastradh	}
60103b705cfSriastradh
60242542f5fSchristos	/* Load the dri modules if requested. */
60342542f5fSchristos#if HAVE_DRI2
60442542f5fSchristos	if (intel->dri2 != DRI_DISABLED && !xf86LoadSubModule(scrn, "dri2"))
60542542f5fSchristos		intel->dri2 = DRI_DISABLED;
60642542f5fSchristos#endif
60742542f5fSchristos#if HAVE_DRI3
60842542f5fSchristos	if (intel->dri3 != DRI_DISABLED && !xf86LoadSubModule(scrn, "dri3"))
60942542f5fSchristos		intel->dri3 = DRI_DISABLED;
61042542f5fSchristos#endif
61103b705cfSriastradh
61203b705cfSriastradh	return TRUE;
61303b705cfSriastradh}
61403b705cfSriastradh
61503b705cfSriastradh/**
61603b705cfSriastradh * Intialiazes the hardware for the 3D pipeline use in the 2D driver.
61703b705cfSriastradh *
61803b705cfSriastradh * Some state caching is performed to avoid redundant state emits.  This
61903b705cfSriastradh * function is also responsible for marking the state as clobbered for DRI
62003b705cfSriastradh * clients.
62103b705cfSriastradh */
62203b705cfSriastradhvoid IntelEmitInvarientState(ScrnInfoPtr scrn)
62303b705cfSriastradh{
62403b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
62503b705cfSriastradh
62603b705cfSriastradh	/* If we've emitted our state since the last clobber by another client,
62703b705cfSriastradh	 * skip it.
62803b705cfSriastradh	 */
62903b705cfSriastradh	if (intel->last_3d != LAST_3D_OTHER)
63003b705cfSriastradh		return;
63103b705cfSriastradh
63203b705cfSriastradh	if (IS_GEN2(intel))
63303b705cfSriastradh		I830EmitInvarientState(scrn);
63403b705cfSriastradh	else if IS_GEN3(intel)
63503b705cfSriastradh		I915EmitInvarientState(scrn);
63603b705cfSriastradh}
63703b705cfSriastradh
63803b705cfSriastradh#ifdef INTEL_PIXMAP_SHARING
63903b705cfSriastradhstatic void
64003b705cfSriastradhredisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
64103b705cfSriastradh{
64203b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
64303b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
64403b705cfSriastradh	RegionRec pixregion;
64503b705cfSriastradh	int was_blocked;
64603b705cfSriastradh
64703b705cfSriastradh	PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap);
64803b705cfSriastradh	RegionTranslate(&pixregion, dirty->x, dirty->y);
64903b705cfSriastradh	RegionIntersect(&pixregion, &pixregion, DamageRegion(dirty->damage));
65003b705cfSriastradh	RegionTranslate(&pixregion, -dirty->x, -dirty->y);
65103b705cfSriastradh	was_blocked = RegionNil(&pixregion);
65203b705cfSriastradh	DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
65303b705cfSriastradh	RegionUninit(&pixregion);
65403b705cfSriastradh	if (was_blocked)
65503b705cfSriastradh		return;
65603b705cfSriastradh
65703b705cfSriastradh	PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap);
65803b705cfSriastradh	PixmapSyncDirtyHelper(dirty, &pixregion);
65903b705cfSriastradh	RegionUninit(&pixregion);
66003b705cfSriastradh
66103b705cfSriastradh	intel_batch_submit(scrn);
66203b705cfSriastradh	if (!intel->has_prime_vmap_flush) {
66303b705cfSriastradh		drm_intel_bo *bo = intel_get_pixmap_bo(dirty->slave_dst->master_pixmap);
66403b705cfSriastradh		was_blocked = xf86BlockSIGIO();
66503b705cfSriastradh		drm_intel_bo_map(bo, FALSE);
66603b705cfSriastradh		drm_intel_bo_unmap(bo);
66703b705cfSriastradh		xf86UnblockSIGIO(was_blocked);
66803b705cfSriastradh	}
66903b705cfSriastradh
67003b705cfSriastradh	DamageRegionProcessPending(&dirty->slave_dst->drawable);
67103b705cfSriastradh	return;
67203b705cfSriastradh}
67303b705cfSriastradh
67403b705cfSriastradhstatic void
67503b705cfSriastradhintel_dirty_update(ScreenPtr screen)
67603b705cfSriastradh{
67703b705cfSriastradh	RegionPtr region;
67803b705cfSriastradh	PixmapDirtyUpdatePtr ent;
67903b705cfSriastradh
68003b705cfSriastradh	if (xorg_list_is_empty(&screen->pixmap_dirty_list))
68103b705cfSriastradh	    return;
68203b705cfSriastradh
68303b705cfSriastradh	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
68403b705cfSriastradh		region = DamageRegion(ent->damage);
68503b705cfSriastradh		if (RegionNotEmpty(region)) {
68603b705cfSriastradh			redisplay_dirty(screen, ent);
68703b705cfSriastradh			DamageEmpty(ent->damage);
68803b705cfSriastradh		}
68903b705cfSriastradh	}
69003b705cfSriastradh}
69103b705cfSriastradh#endif
69203b705cfSriastradh
69303b705cfSriastradhstatic void
69403b705cfSriastradhI830BlockHandler(BLOCKHANDLER_ARGS_DECL)
69503b705cfSriastradh{
69603b705cfSriastradh	SCREEN_PTR(arg);
69703b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
69803b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
69903b705cfSriastradh
70003b705cfSriastradh	screen->BlockHandler = intel->BlockHandler;
70103b705cfSriastradh
70203b705cfSriastradh	(*screen->BlockHandler) (BLOCKHANDLER_ARGS);
70303b705cfSriastradh
70403b705cfSriastradh	intel->BlockHandler = screen->BlockHandler;
70503b705cfSriastradh	screen->BlockHandler = I830BlockHandler;
70603b705cfSriastradh
70703b705cfSriastradh	intel_uxa_block_handler(intel);
70803b705cfSriastradh	intel_video_block_handler(intel);
70903b705cfSriastradh#ifdef INTEL_PIXMAP_SHARING
71003b705cfSriastradh	intel_dirty_update(screen);
71103b705cfSriastradh#endif
71203b705cfSriastradh}
71303b705cfSriastradh
71403b705cfSriastradhstatic Bool
71503b705cfSriastradhintel_init_initial_framebuffer(ScrnInfoPtr scrn)
71603b705cfSriastradh{
71703b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
71803b705cfSriastradh	int width = scrn->virtualX;
71903b705cfSriastradh	int height = scrn->virtualY;
72042542f5fSchristos	int pitch;
72103b705cfSriastradh	uint32_t tiling;
72203b705cfSriastradh
72303b705cfSriastradh	intel->front_buffer = intel_allocate_framebuffer(scrn,
72403b705cfSriastradh							 width, height,
72503b705cfSriastradh							 intel->cpp,
72642542f5fSchristos							 &pitch, &tiling);
72703b705cfSriastradh
72803b705cfSriastradh	if (!intel->front_buffer) {
72903b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
73003b705cfSriastradh			   "Couldn't allocate initial framebuffer.\n");
73103b705cfSriastradh		return FALSE;
73203b705cfSriastradh	}
73303b705cfSriastradh
73403b705cfSriastradh	intel->front_pitch = pitch;
73503b705cfSriastradh	intel->front_tiling = tiling;
73603b705cfSriastradh	scrn->displayWidth = pitch / intel->cpp;
73703b705cfSriastradh
73803b705cfSriastradh	return TRUE;
73903b705cfSriastradh}
74003b705cfSriastradh
74103b705cfSriastradhstatic void
74203b705cfSriastradhintel_flush_callback(CallbackListPtr *list,
74303b705cfSriastradh		     pointer user_data, pointer call_data)
74403b705cfSriastradh{
74503b705cfSriastradh	ScrnInfoPtr scrn = user_data;
74603b705cfSriastradh	if (scrn->vtSema) {
74703b705cfSriastradh		intel_batch_submit(scrn);
74803b705cfSriastradh		intel_glamor_flush(intel_get_screen_private(scrn));
74903b705cfSriastradh	}
75003b705cfSriastradh}
75103b705cfSriastradh
75203b705cfSriastradh#if HAVE_UDEV
75303b705cfSriastradhstatic void
75403b705cfSriastradhI830HandleUEvents(int fd, void *closure)
75503b705cfSriastradh{
75603b705cfSriastradh	ScrnInfoPtr scrn = closure;
75703b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
75803b705cfSriastradh	struct udev_device *dev;
75903b705cfSriastradh	const char *hotplug;
76003b705cfSriastradh	struct stat s;
76103b705cfSriastradh	dev_t udev_devnum;
76203b705cfSriastradh
76303b705cfSriastradh	dev = udev_monitor_receive_device(intel->uevent_monitor);
76403b705cfSriastradh	if (!dev)
76503b705cfSriastradh		return;
76603b705cfSriastradh
76703b705cfSriastradh	udev_devnum = udev_device_get_devnum(dev);
76803b705cfSriastradh	if (fstat(intel->drmSubFD, &s)) {
76903b705cfSriastradh		udev_device_unref(dev);
77003b705cfSriastradh		return;
77103b705cfSriastradh	}
77203b705cfSriastradh	/*
77303b705cfSriastradh	 * Check to make sure this event is directed at our
77403b705cfSriastradh	 * device (by comparing dev_t values), then make
77503b705cfSriastradh	 * sure it's a hotplug event (HOTPLUG=1)
77603b705cfSriastradh	 */
77703b705cfSriastradh
77803b705cfSriastradh	hotplug = udev_device_get_property_value(dev, "HOTPLUG");
77903b705cfSriastradh
78003b705cfSriastradh	if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
78103b705cfSriastradh			hotplug && atoi(hotplug) == 1)
78242542f5fSchristos	{
78342542f5fSchristos		intel_mode_hotplug(intel);
78442542f5fSchristos	}
78503b705cfSriastradh
78603b705cfSriastradh	udev_device_unref(dev);
78703b705cfSriastradh}
78803b705cfSriastradh
78903b705cfSriastradhstatic void
79003b705cfSriastradhI830UeventInit(ScrnInfoPtr scrn)
79103b705cfSriastradh{
79203b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
79303b705cfSriastradh	struct udev *u;
79403b705cfSriastradh	struct udev_monitor *mon;
79503b705cfSriastradh	Bool hotplug;
79603b705cfSriastradh	MessageType from = X_CONFIG;
79703b705cfSriastradh
79803b705cfSriastradh	if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) {
79903b705cfSriastradh		from = X_DEFAULT;
80003b705cfSriastradh		hotplug = TRUE;
80103b705cfSriastradh	}
80203b705cfSriastradh
80303b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, from, "hotplug detection: \"%s\"\n",
80403b705cfSriastradh			hotplug ? "enabled" : "disabled");
80503b705cfSriastradh	if (!hotplug)
80603b705cfSriastradh		return;
80703b705cfSriastradh
80803b705cfSriastradh	u = udev_new();
80903b705cfSriastradh	if (!u)
81003b705cfSriastradh		return;
81103b705cfSriastradh
81203b705cfSriastradh	mon = udev_monitor_new_from_netlink(u, "udev");
81303b705cfSriastradh
81403b705cfSriastradh	if (!mon) {
81503b705cfSriastradh		udev_unref(u);
81603b705cfSriastradh		return;
81703b705cfSriastradh	}
81803b705cfSriastradh
81903b705cfSriastradh	if (udev_monitor_filter_add_match_subsystem_devtype(mon,
82003b705cfSriastradh				"drm",
82103b705cfSriastradh				"drm_minor") < 0 ||
82203b705cfSriastradh			udev_monitor_enable_receiving(mon) < 0)
82303b705cfSriastradh	{
82403b705cfSriastradh		udev_monitor_unref(mon);
82503b705cfSriastradh		udev_unref(u);
82603b705cfSriastradh		return;
82703b705cfSriastradh	}
82803b705cfSriastradh
82942542f5fSchristos	intel->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon),
83042542f5fSchristos						      I830HandleUEvents, scrn);
83103b705cfSriastradh	if (!intel->uevent_handler) {
83203b705cfSriastradh		udev_monitor_unref(mon);
83303b705cfSriastradh		udev_unref(u);
83403b705cfSriastradh		return;
83503b705cfSriastradh	}
83603b705cfSriastradh
83703b705cfSriastradh	intel->uevent_monitor = mon;
83803b705cfSriastradh}
83903b705cfSriastradh
84003b705cfSriastradhstatic void
84103b705cfSriastradhI830UeventFini(ScrnInfoPtr scrn)
84203b705cfSriastradh{
84303b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
84403b705cfSriastradh
84503b705cfSriastradh	if (intel->uevent_handler) {
84603b705cfSriastradh		struct udev *u = udev_monitor_get_udev(intel->uevent_monitor);
84703b705cfSriastradh
84803b705cfSriastradh		xf86RemoveGeneralHandler(intel->uevent_handler);
84903b705cfSriastradh
85003b705cfSriastradh		udev_monitor_unref(intel->uevent_monitor);
85103b705cfSriastradh		udev_unref(u);
85203b705cfSriastradh		intel->uevent_handler = NULL;
85303b705cfSriastradh		intel->uevent_monitor = NULL;
85403b705cfSriastradh	}
85503b705cfSriastradh}
85603b705cfSriastradh#endif /* HAVE_UDEV */
85703b705cfSriastradh
85803b705cfSriastradhstatic Bool
85903b705cfSriastradhI830ScreenInit(SCREEN_INIT_ARGS_DECL)
86003b705cfSriastradh{
86103b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
86203b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
86303b705cfSriastradh	VisualPtr visual;
86403b705cfSriastradh#ifdef INTEL_XVMC
86503b705cfSriastradh	MessageType from;
86603b705cfSriastradh#endif
86703b705cfSriastradh	struct pci_device *const device = intel->PciInfo;
86803b705cfSriastradh	int fb_bar = IS_GEN2(intel) ? 0 : 2;
86903b705cfSriastradh
87003b705cfSriastradh	scrn->videoRam = device->regions[fb_bar].size / 1024;
87103b705cfSriastradh
87203b705cfSriastradh	intel->last_3d = LAST_3D_OTHER;
87303b705cfSriastradh	intel->overlayOn = FALSE;
87403b705cfSriastradh
87503b705cfSriastradh	/*
87603b705cfSriastradh	 * Set this so that the overlay allocation is factored in when
87703b705cfSriastradh	 * appropriate.
87803b705cfSriastradh	 */
87903b705cfSriastradh	intel->XvEnabled = TRUE;
88003b705cfSriastradh
88103b705cfSriastradh	if (!intel_init_initial_framebuffer(scrn))
88203b705cfSriastradh		return FALSE;
88303b705cfSriastradh
88403b705cfSriastradh	intel_batch_init(scrn);
88503b705cfSriastradh
88642542f5fSchristos	if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100)
88703b705cfSriastradh		gen4_render_state_init(scrn);
88803b705cfSriastradh
88903b705cfSriastradh	miClearVisualTypes();
89003b705cfSriastradh	if (!miSetVisualTypes(scrn->depth,
89103b705cfSriastradh			      miGetDefaultVisualMask(scrn->depth),
89203b705cfSriastradh			      scrn->rgbBits, scrn->defaultVisual))
89303b705cfSriastradh		return FALSE;
89403b705cfSriastradh	if (!miSetPixmapDepths())
89503b705cfSriastradh		return FALSE;
89603b705cfSriastradh
89742542f5fSchristos	/* Must be first, before anything else installs screen callbacks. */
89803b705cfSriastradh	if (!fbScreenInit(screen, NULL,
89903b705cfSriastradh			  scrn->virtualX, scrn->virtualY,
90003b705cfSriastradh			  scrn->xDpi, scrn->yDpi,
90103b705cfSriastradh			  scrn->displayWidth, scrn->bitsPerPixel))
90203b705cfSriastradh		return FALSE;
90303b705cfSriastradh
90403b705cfSriastradh	if (scrn->bitsPerPixel > 8) {
90503b705cfSriastradh		/* Fixup RGB ordering */
90603b705cfSriastradh		visual = screen->visuals + screen->numVisuals;
90703b705cfSriastradh		while (--visual >= screen->visuals) {
90803b705cfSriastradh			if ((visual->class | DynamicClass) == DirectColor) {
90903b705cfSriastradh				visual->offsetRed = scrn->offset.red;
91003b705cfSriastradh				visual->offsetGreen = scrn->offset.green;
91103b705cfSriastradh				visual->offsetBlue = scrn->offset.blue;
91203b705cfSriastradh				visual->redMask = scrn->mask.red;
91303b705cfSriastradh				visual->greenMask = scrn->mask.green;
91403b705cfSriastradh				visual->blueMask = scrn->mask.blue;
91503b705cfSriastradh			}
91603b705cfSriastradh		}
91703b705cfSriastradh	}
91803b705cfSriastradh
91903b705cfSriastradh	fbPictureInit(screen, NULL, 0);
92003b705cfSriastradh
92103b705cfSriastradh	xf86SetBlackWhitePixels(screen);
92203b705cfSriastradh
92303b705cfSriastradh	if (!intel_uxa_init(screen)) {
92403b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
92503b705cfSriastradh			   "Hardware acceleration initialization failed\n");
92603b705cfSriastradh		return FALSE;
92703b705cfSriastradh	}
92803b705cfSriastradh
92942542f5fSchristos#if HAVE_DRI2
93042542f5fSchristos	if (intel->dri2 == DRI_NONE && I830DRI2ScreenInit(screen))
93142542f5fSchristos		intel->dri2 = DRI_ACTIVE;
93242542f5fSchristos#endif
93342542f5fSchristos
93442542f5fSchristos#if HAVE_DRI3
93542542f5fSchristos	if (!intel_sync_init(screen))
93642542f5fSchristos		intel->dri3 = DRI_DISABLED;
93742542f5fSchristos	if (intel->dri3 == DRI_NONE && intel_dri3_screen_init(screen))
93842542f5fSchristos		intel->dri3 = DRI_ACTIVE;
93942542f5fSchristos#endif
94042542f5fSchristos
94142542f5fSchristos	if (xf86ReturnOptValBool(intel->Options, OPTION_PRESENT, TRUE))
94242542f5fSchristos		intel_present_screen_init(screen);
94342542f5fSchristos
94403b705cfSriastradh	xf86SetBackingStore(screen);
94503b705cfSriastradh	xf86SetSilkenMouse(screen);
94603b705cfSriastradh	miDCInitialize(screen, xf86GetPointerScreenFuncs());
94703b705cfSriastradh
94803b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO, "Initializing HW Cursor\n");
94903b705cfSriastradh	if (!xf86_cursors_init(screen, 64, 64,
95003b705cfSriastradh			       (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
95103b705cfSriastradh				HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
95203b705cfSriastradh				HARDWARE_CURSOR_INVERT_MASK |
95303b705cfSriastradh				HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
95403b705cfSriastradh				HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
95503b705cfSriastradh				HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
95603b705cfSriastradh				HARDWARE_CURSOR_UPDATE_UNHIDDEN |
95703b705cfSriastradh				HARDWARE_CURSOR_ARGB))) {
95803b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
95903b705cfSriastradh			   "Hardware cursor initialization failed\n");
96003b705cfSriastradh	}
96103b705cfSriastradh
96203b705cfSriastradh	intel->BlockHandler = screen->BlockHandler;
96303b705cfSriastradh	screen->BlockHandler = I830BlockHandler;
96403b705cfSriastradh
96503b705cfSriastradh#ifdef INTEL_PIXMAP_SHARING
96603b705cfSriastradh	screen->StartPixmapTracking = PixmapStartDirtyTracking;
96703b705cfSriastradh	screen->StopPixmapTracking = PixmapStopDirtyTracking;
96803b705cfSriastradh#endif
96903b705cfSriastradh
97003b705cfSriastradh	if (!AddCallback(&FlushCallback, intel_flush_callback, scrn))
97103b705cfSriastradh		return FALSE;
97203b705cfSriastradh
97303b705cfSriastradh	screen->SaveScreen = xf86SaveScreen;
97403b705cfSriastradh	intel->CloseScreen = screen->CloseScreen;
97503b705cfSriastradh	screen->CloseScreen = I830CloseScreen;
97603b705cfSriastradh	intel->CreateScreenResources = screen->CreateScreenResources;
97703b705cfSriastradh	screen->CreateScreenResources = i830CreateScreenResources;
97803b705cfSriastradh
97903b705cfSriastradh	intel_glamor_init(screen);
98003b705cfSriastradh	if (!xf86CrtcScreenInit(screen))
98103b705cfSriastradh		return FALSE;
98203b705cfSriastradh
98303b705cfSriastradh	if (!miCreateDefColormap(screen))
98403b705cfSriastradh		return FALSE;
98503b705cfSriastradh
98603b705cfSriastradh	if (!xf86HandleColormaps(screen, 256, 8, I830LoadPalette, NULL,
98703b705cfSriastradh				 CMAP_RELOAD_ON_MODE_SWITCH |
98803b705cfSriastradh				 CMAP_PALETTED_TRUECOLOR)) {
98903b705cfSriastradh		return FALSE;
99003b705cfSriastradh	}
99103b705cfSriastradh
99203b705cfSriastradh	xf86DPMSInit(screen, xf86DPMSSet, 0);
99303b705cfSriastradh
99403b705cfSriastradh#ifdef INTEL_XVMC
99503b705cfSriastradh	if (INTEL_INFO(intel)->gen >= 040)
99603b705cfSriastradh		intel->XvMCEnabled = TRUE;
99742542f5fSchristos	from = (intel->dri2 == DRI_ACTIVE &&
99803b705cfSriastradh		xf86GetOptValBool(intel->Options, OPTION_XVMC,
99903b705cfSriastradh				  &intel->XvMCEnabled) ? X_CONFIG : X_DEFAULT);
100003b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, from, "Intel XvMC decoder %sabled\n",
100103b705cfSriastradh		   intel->XvMCEnabled ? "en" : "dis");
100203b705cfSriastradh#endif
100303b705cfSriastradh	/* Init video */
100403b705cfSriastradh	if (intel->XvEnabled)
100503b705cfSriastradh		I830InitVideo(screen);
100603b705cfSriastradh
100742542f5fSchristos#if HAVE_DRI2
100842542f5fSchristos	switch (intel->dri2) {
100942542f5fSchristos	case DRI_ACTIVE:
101042542f5fSchristos		xf86DrvMsg(scrn->scrnIndex, X_INFO,
101142542f5fSchristos			   "DRI2: Enabled\n");
101242542f5fSchristos		break;
101342542f5fSchristos	case DRI_DISABLED:
101442542f5fSchristos		xf86DrvMsg(scrn->scrnIndex, X_INFO,
101542542f5fSchristos			   "DRI2: Disabled\n");
101642542f5fSchristos		break;
101742542f5fSchristos	case DRI_NONE:
101842542f5fSchristos		xf86DrvMsg(scrn->scrnIndex, X_INFO,
101942542f5fSchristos			   "DRI2: Failed\n");
102042542f5fSchristos		break;
102142542f5fSchristos	}
102242542f5fSchristos#else
102342542f5fSchristos	xf86DrvMsg(scrn->scrnIndex, X_INFO,
102442542f5fSchristos		   "DRI2: Not available\n");
102542542f5fSchristos#endif
102642542f5fSchristos
102742542f5fSchristos#if HAVE_DRI3
102842542f5fSchristos	switch (intel->dri3) {
102942542f5fSchristos	case DRI_ACTIVE:
103003b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_INFO,
103142542f5fSchristos			   "DRI3: Enabled\n");
103203b705cfSriastradh		break;
103303b705cfSriastradh	case DRI_DISABLED:
103403b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_INFO,
103542542f5fSchristos			   "DRI3: Disabled\n");
103603b705cfSriastradh		break;
103703b705cfSriastradh	case DRI_NONE:
103803b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_INFO,
103942542f5fSchristos			   "DRI3: Failed\n");
104003b705cfSriastradh		break;
104103b705cfSriastradh	}
104203b705cfSriastradh#else
104303b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
104442542f5fSchristos		   "DRI3: Not available\n");
104503b705cfSriastradh#endif
104603b705cfSriastradh
104703b705cfSriastradh	if (serverGeneration == 1)
104803b705cfSriastradh		xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options);
104903b705cfSriastradh
105003b705cfSriastradh	intel_mode_init(intel);
105103b705cfSriastradh
105203b705cfSriastradh	intel->suspended = FALSE;
105303b705cfSriastradh
105403b705cfSriastradh#if HAVE_UDEV
105503b705cfSriastradh	I830UeventInit(scrn);
105603b705cfSriastradh#endif
105703b705cfSriastradh
105803b705cfSriastradh	/* Must force it before EnterVT, so we are in control of VT and
105903b705cfSriastradh	 * later memory should be bound when allocating, e.g rotate_mem */
106003b705cfSriastradh	scrn->vtSema = TRUE;
106103b705cfSriastradh
106203b705cfSriastradh	return I830EnterVT(VT_FUNC_ARGS(0));
106303b705cfSriastradh}
106403b705cfSriastradh
106503b705cfSriastradhstatic void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL)
106603b705cfSriastradh{
106703b705cfSriastradh}
106803b705cfSriastradh
106903b705cfSriastradhstatic void I830FreeScreen(FREE_SCREEN_ARGS_DECL)
107003b705cfSriastradh{
107103b705cfSriastradh	SCRN_INFO_PTR(arg);
107203b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
107303b705cfSriastradh
107442542f5fSchristos	if (intel && !((uintptr_t)intel & 3)) {
107503b705cfSriastradh		intel_mode_fini(intel);
107603b705cfSriastradh		intel_bufmgr_fini(intel);
107742542f5fSchristos		intel_put_device(scrn);
107803b705cfSriastradh
107903b705cfSriastradh		free(intel);
108003b705cfSriastradh		scrn->driverPrivate = NULL;
108103b705cfSriastradh	}
108203b705cfSriastradh}
108303b705cfSriastradh
108403b705cfSriastradhstatic void I830LeaveVT(VT_FUNC_ARGS_DECL)
108503b705cfSriastradh{
108603b705cfSriastradh	SCRN_INFO_PTR(arg);
108703b705cfSriastradh
108803b705cfSriastradh	xf86RotateFreeShadow(scrn);
108903b705cfSriastradh
109003b705cfSriastradh	xf86_hide_cursors(scrn);
109103b705cfSriastradh
109242542f5fSchristos	if (intel_put_master(scrn))
109303b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
109403b705cfSriastradh			   "drmDropMaster failed: %s\n", strerror(errno));
109503b705cfSriastradh}
109603b705cfSriastradh
109703b705cfSriastradh/*
109803b705cfSriastradh * This gets called when gaining control of the VT, and from ScreenInit().
109903b705cfSriastradh */
110003b705cfSriastradhstatic Bool I830EnterVT(VT_FUNC_ARGS_DECL)
110103b705cfSriastradh{
110203b705cfSriastradh	SCRN_INFO_PTR(arg);
110303b705cfSriastradh
110442542f5fSchristos	if (intel_get_master(scrn)) {
110503b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
110603b705cfSriastradh			   "drmSetMaster failed: %s\n",
110703b705cfSriastradh			   strerror(errno));
110842542f5fSchristos		return FALSE;
110903b705cfSriastradh	}
111003b705cfSriastradh
111103b705cfSriastradh	if (!xf86SetDesiredModes(scrn))
111203b705cfSriastradh		return FALSE;
111303b705cfSriastradh
111403b705cfSriastradh	intel_mode_disable_unused_functions(scrn);
111503b705cfSriastradh	return TRUE;
111603b705cfSriastradh}
111703b705cfSriastradh
111803b705cfSriastradhstatic Bool I830SwitchMode(SWITCH_MODE_ARGS_DECL)
111903b705cfSriastradh{
112003b705cfSriastradh	SCRN_INFO_PTR(arg);
112103b705cfSriastradh
112203b705cfSriastradh	return xf86SetSingleMode(scrn, mode, RR_Rotate_0);
112303b705cfSriastradh}
112403b705cfSriastradh
112503b705cfSriastradhstatic Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL)
112603b705cfSriastradh{
112703b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
112803b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
112903b705cfSriastradh
113003b705cfSriastradh#if HAVE_UDEV
113103b705cfSriastradh	I830UeventFini(scrn);
113203b705cfSriastradh#endif
113303b705cfSriastradh
113403b705cfSriastradh	intel_mode_close(intel);
113503b705cfSriastradh
113603b705cfSriastradh	DeleteCallback(&FlushCallback, intel_flush_callback, scrn);
113703b705cfSriastradh
113803b705cfSriastradh	intel_glamor_close_screen(screen);
113903b705cfSriastradh
114003b705cfSriastradh	TimerFree(intel->cache_expire);
114103b705cfSriastradh	intel->cache_expire = NULL;
114203b705cfSriastradh
114303b705cfSriastradh	if (intel->uxa_driver) {
114403b705cfSriastradh		uxa_driver_fini(screen);
114503b705cfSriastradh		free(intel->uxa_driver);
114603b705cfSriastradh		intel->uxa_driver = NULL;
114703b705cfSriastradh	}
114803b705cfSriastradh
114903b705cfSriastradh	if (intel->back_pixmap) {
115003b705cfSriastradh		screen->DestroyPixmap(intel->back_pixmap);
115103b705cfSriastradh		intel->back_pixmap = NULL;
115203b705cfSriastradh	}
115303b705cfSriastradh
115403b705cfSriastradh	if (intel->back_buffer) {
115503b705cfSriastradh		drm_intel_bo_unreference(intel->back_buffer);
115603b705cfSriastradh		intel->back_buffer = NULL;
115703b705cfSriastradh	}
115803b705cfSriastradh
115903b705cfSriastradh	if (intel->front_buffer) {
116003b705cfSriastradh		intel_mode_remove_fb(intel);
116103b705cfSriastradh		drm_intel_bo_unreference(intel->front_buffer);
116203b705cfSriastradh		intel->front_buffer = NULL;
116303b705cfSriastradh	}
116403b705cfSriastradh
116503b705cfSriastradh	if (scrn->vtSema == TRUE) {
116603b705cfSriastradh		I830LeaveVT(VT_FUNC_ARGS(0));
116703b705cfSriastradh	}
116803b705cfSriastradh
116903b705cfSriastradh	intel_batch_teardown(scrn);
117003b705cfSriastradh
117142542f5fSchristos	if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100)
117203b705cfSriastradh		gen4_render_state_cleanup(scrn);
117303b705cfSriastradh
117403b705cfSriastradh	xf86_cursors_fini(screen);
117503b705cfSriastradh
117603b705cfSriastradh	i965_free_video(scrn);
117703b705cfSriastradh
117803b705cfSriastradh	screen->CloseScreen = intel->CloseScreen;
117903b705cfSriastradh	(*screen->CloseScreen) (CLOSE_SCREEN_ARGS);
118003b705cfSriastradh
118142542f5fSchristos	if (intel->dri2 == DRI_ACTIVE) {
118203b705cfSriastradh		I830DRI2CloseScreen(screen);
118342542f5fSchristos		intel->dri2 = DRI_NONE;
118403b705cfSriastradh	}
118503b705cfSriastradh
118642542f5fSchristos	if (intel->dri3 == DRI_ACTIVE) {
118742542f5fSchristos		/* nothing to do here? */
118842542f5fSchristos		intel->dri3 = DRI_NONE;
118942542f5fSchristos	}
119042542f5fSchristos
119142542f5fSchristos	intel_sync_close(screen);
119242542f5fSchristos
119303b705cfSriastradh	xf86GARTCloseScreen(scrn->scrnIndex);
119403b705cfSriastradh
119503b705cfSriastradh	scrn->vtSema = FALSE;
119603b705cfSriastradh	return TRUE;
119703b705cfSriastradh}
119803b705cfSriastradh
119903b705cfSriastradhstatic ModeStatus
120003b705cfSriastradhI830ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
120103b705cfSriastradh{
120203b705cfSriastradh	SCRN_INFO_PTR(arg);
120303b705cfSriastradh	if (mode->Flags & V_INTERLACE) {
120403b705cfSriastradh		if (verbose) {
120503b705cfSriastradh			xf86DrvMsg(scrn->scrnIndex, X_PROBED,
120603b705cfSriastradh				   "Removing interlaced mode \"%s\"\n",
120703b705cfSriastradh				   mode->name);
120803b705cfSriastradh		}
120903b705cfSriastradh		return MODE_BAD;
121003b705cfSriastradh	}
121103b705cfSriastradh	return MODE_OK;
121203b705cfSriastradh}
121303b705cfSriastradh
121403b705cfSriastradh#ifndef SUSPEND_SLEEP
121503b705cfSriastradh#define SUSPEND_SLEEP 0
121603b705cfSriastradh#endif
121703b705cfSriastradh#ifndef RESUME_SLEEP
121803b705cfSriastradh#define RESUME_SLEEP 0
121903b705cfSriastradh#endif
122003b705cfSriastradh
122103b705cfSriastradh/*
122203b705cfSriastradh * This function is only required if we need to do anything differently from
122303b705cfSriastradh * DoApmEvent() in common/xf86PM.c, including if we want to see events other
122403b705cfSriastradh * than suspend/resume.
122503b705cfSriastradh */
122603b705cfSriastradhstatic Bool I830PMEvent(SCRN_ARG_TYPE arg, pmEvent event, Bool undo)
122703b705cfSriastradh{
122803b705cfSriastradh	SCRN_INFO_PTR(arg);
122903b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
123003b705cfSriastradh
123103b705cfSriastradh	switch (event) {
123203b705cfSriastradh	case XF86_APM_SYS_SUSPEND:
123303b705cfSriastradh	case XF86_APM_CRITICAL_SUSPEND:	/*do we want to delay a critical suspend? */
123403b705cfSriastradh	case XF86_APM_USER_SUSPEND:
123503b705cfSriastradh	case XF86_APM_SYS_STANDBY:
123603b705cfSriastradh	case XF86_APM_USER_STANDBY:
123703b705cfSriastradh		if (!undo && !intel->suspended) {
123803b705cfSriastradh			scrn->LeaveVT(VT_FUNC_ARGS(0));
123903b705cfSriastradh			intel->suspended = TRUE;
124003b705cfSriastradh			sleep(SUSPEND_SLEEP);
124103b705cfSriastradh		} else if (undo && intel->suspended) {
124203b705cfSriastradh			sleep(RESUME_SLEEP);
124303b705cfSriastradh			scrn->EnterVT(VT_FUNC_ARGS(0));
124403b705cfSriastradh			intel->suspended = FALSE;
124503b705cfSriastradh		}
124603b705cfSriastradh		break;
124703b705cfSriastradh	case XF86_APM_STANDBY_RESUME:
124803b705cfSriastradh	case XF86_APM_NORMAL_RESUME:
124903b705cfSriastradh	case XF86_APM_CRITICAL_RESUME:
125003b705cfSriastradh		if (intel->suspended) {
125103b705cfSriastradh			sleep(RESUME_SLEEP);
125203b705cfSriastradh			scrn->EnterVT(VT_FUNC_ARGS(0));
125303b705cfSriastradh			intel->suspended = FALSE;
125403b705cfSriastradh			/*
125503b705cfSriastradh			 * Turn the screen saver off when resuming.  This seems to be
125603b705cfSriastradh			 * needed to stop xscreensaver kicking in (when used).
125703b705cfSriastradh			 *
125803b705cfSriastradh			 * XXX DoApmEvent() should probably call this just like
125903b705cfSriastradh			 * xf86VTSwitch() does.  Maybe do it here only in 4.2
126003b705cfSriastradh			 * compatibility mode.
126103b705cfSriastradh			 */
126203b705cfSriastradh			SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
126303b705cfSriastradh		}
126403b705cfSriastradh		break;
126503b705cfSriastradh		/* This is currently used for ACPI */
126603b705cfSriastradh	case XF86_APM_CAPABILITY_CHANGED:
126703b705cfSriastradh		ErrorF("I830PMEvent: Capability change\n");
126803b705cfSriastradh
126903b705cfSriastradh		SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
127003b705cfSriastradh
127103b705cfSriastradh		break;
127203b705cfSriastradh	default:
127303b705cfSriastradh		ErrorF("I830PMEvent: received APM event %d\n", event);
127403b705cfSriastradh	}
127503b705cfSriastradh	return TRUE;
127603b705cfSriastradh}
127703b705cfSriastradh
127803b705cfSriastradhBool intel_init_scrn(ScrnInfoPtr scrn)
127903b705cfSriastradh{
128003b705cfSriastradh	scrn->PreInit = I830PreInit;
128103b705cfSriastradh	scrn->ScreenInit = I830ScreenInit;
128203b705cfSriastradh	scrn->SwitchMode = I830SwitchMode;
128303b705cfSriastradh	scrn->AdjustFrame = i830AdjustFrame;
128403b705cfSriastradh	scrn->EnterVT = I830EnterVT;
128503b705cfSriastradh	scrn->LeaveVT = I830LeaveVT;
128603b705cfSriastradh	scrn->FreeScreen = I830FreeScreen;
128703b705cfSriastradh	scrn->ValidMode = I830ValidMode;
128803b705cfSriastradh	scrn->PMEvent = I830PMEvent;
128903b705cfSriastradh	return TRUE;
129003b705cfSriastradh}
1291