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
7113496ba1Ssnj#if USE_UXA
7213496ba1Ssnj#include "intel_uxa.h"
7313496ba1Ssnj#endif
7403b705cfSriastradh
7503b705cfSriastradh#include "intel_options.h"
7613496ba1Ssnj#include "i915_drm.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
17213496ba1Ssnjvoid
17313496ba1Ssnjintel_set_pixmap_bo(PixmapPtr pixmap, dri_bo *bo)
17413496ba1Ssnj{
17513496ba1Ssnj        intel_uxa_set_pixmap_bo(pixmap, bo);
17613496ba1Ssnj}
17713496ba1Ssnj
17813496ba1Ssnjdri_bo *
17913496ba1Ssnjintel_get_pixmap_bo(PixmapPtr pixmap)
18013496ba1Ssnj{
18113496ba1Ssnj        return intel_uxa_get_pixmap_bo(pixmap);
18213496ba1Ssnj}
18313496ba1Ssnj
18413496ba1Ssnjvoid
18513496ba1Ssnjintel_flush(intel_screen_private *intel)
18613496ba1Ssnj{
18713496ba1Ssnj        intel_batch_submit(intel->scrn);
18813496ba1Ssnj}
18913496ba1Ssnj
19003b705cfSriastradhstatic void PreInitCleanup(ScrnInfoPtr scrn)
19103b705cfSriastradh{
19203b705cfSriastradh	if (!scrn || !scrn->driverPrivate)
19303b705cfSriastradh		return;
19403b705cfSriastradh
19503b705cfSriastradh	free(scrn->driverPrivate);
19603b705cfSriastradh	scrn->driverPrivate = NULL;
19703b705cfSriastradh}
19803b705cfSriastradh
19903b705cfSriastradhstatic void intel_check_chipset_option(ScrnInfoPtr scrn)
20003b705cfSriastradh{
20103b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
20213496ba1Ssnj	intel_detect_chipset(scrn, intel->dev);
20303b705cfSriastradh}
20403b705cfSriastradh
20503b705cfSriastradhstatic Bool I830GetEarlyOptions(ScrnInfoPtr scrn)
20603b705cfSriastradh{
20703b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
20803b705cfSriastradh
20903b705cfSriastradh	/* Process the options */
21003b705cfSriastradh	intel->Options = intel_options_get(scrn);
21103b705cfSriastradh	if (!intel->Options)
21203b705cfSriastradh		return FALSE;
21303b705cfSriastradh
21413496ba1Ssnj#if USE_UXA
21503b705cfSriastradh	intel->fallback_debug = xf86ReturnOptValBool(intel->Options,
21603b705cfSriastradh						     OPTION_FALLBACKDEBUG,
21703b705cfSriastradh						     FALSE);
21803b705cfSriastradh
21903b705cfSriastradh	intel->debug_flush = 0;
22003b705cfSriastradh
22103b705cfSriastradh	if (xf86ReturnOptValBool(intel->Options,
22203b705cfSriastradh				 OPTION_DEBUG_FLUSH_BATCHES,
22303b705cfSriastradh				 FALSE))
22403b705cfSriastradh		intel->debug_flush |= DEBUG_FLUSH_BATCHES;
22503b705cfSriastradh
22603b705cfSriastradh	if (xf86ReturnOptValBool(intel->Options,
22703b705cfSriastradh				 OPTION_DEBUG_FLUSH_CACHES,
22803b705cfSriastradh				 FALSE))
22903b705cfSriastradh		intel->debug_flush |= DEBUG_FLUSH_CACHES;
23003b705cfSriastradh
23103b705cfSriastradh	if (xf86ReturnOptValBool(intel->Options,
23203b705cfSriastradh				 OPTION_DEBUG_WAIT,
23303b705cfSriastradh				 FALSE))
23403b705cfSriastradh		intel->debug_flush |= DEBUG_FLUSH_WAIT;
23503b705cfSriastradh
23613496ba1Ssnj#endif
23703b705cfSriastradh	return TRUE;
23803b705cfSriastradh}
23903b705cfSriastradh
24003b705cfSriastradhstatic void intel_check_dri_option(ScrnInfoPtr scrn)
24103b705cfSriastradh{
24203b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
24363ef14f0Smrg	unsigned level;
24403b705cfSriastradh
24542542f5fSchristos	intel->dri2 = intel->dri3 = DRI_NONE;
24663ef14f0Smrg	level = intel_option_cast_to_unsigned(intel->Options, OPTION_DRI, DEFAULT_DRI_LEVEL);
24763ef14f0Smrg	if (level < 3 || INTEL_INFO(intel)->gen < 040)
24863ef14f0Smrg		intel->dri3 = DRI_DISABLED;
24963ef14f0Smrg	if (level < 2)
25063ef14f0Smrg		intel->dri2 = DRI_DISABLED;
25103b705cfSriastradh
25203b705cfSriastradh	if (scrn->depth != 16 && scrn->depth != 24 && scrn->depth != 30) {
25303b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
25403b705cfSriastradh			   "DRI is disabled because it "
25503b705cfSriastradh			   "runs only at depths 16, 24, and 30.\n");
25642542f5fSchristos		intel->dri2 = intel->dri3 = DRI_DISABLED;
25703b705cfSriastradh	}
25803b705cfSriastradh}
25903b705cfSriastradh
26003b705cfSriastradhstatic Bool intel_open_drm_master(ScrnInfoPtr scrn)
26103b705cfSriastradh{
26203b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
26313496ba1Ssnj	intel->dev = intel_get_device(scrn, &intel->drmSubFD);
26413496ba1Ssnj	return intel->dev != NULL;
26503b705cfSriastradh}
26603b705cfSriastradh
26703b705cfSriastradhstatic int intel_init_bufmgr(intel_screen_private *intel)
26803b705cfSriastradh{
26903b705cfSriastradh	int batch_size;
27003b705cfSriastradh
27103b705cfSriastradh	batch_size = 4096 * 4;
27203b705cfSriastradh	if (IS_I865G(intel))
27303b705cfSriastradh		/* The 865 has issues with larger-than-page-sized batch buffers. */
27403b705cfSriastradh		batch_size = 4096;
27503b705cfSriastradh
27603b705cfSriastradh	intel->bufmgr = drm_intel_bufmgr_gem_init(intel->drmSubFD, batch_size);
27703b705cfSriastradh	if (!intel->bufmgr)
27803b705cfSriastradh		return FALSE;
27903b705cfSriastradh
28003b705cfSriastradh	if (xf86ReturnOptValBool(intel->Options, OPTION_BUFFER_CACHE, TRUE))
28103b705cfSriastradh		drm_intel_bufmgr_gem_enable_reuse(intel->bufmgr);
28203b705cfSriastradh	drm_intel_bufmgr_gem_set_vma_cache_size(intel->bufmgr, 512);
28303b705cfSriastradh	drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr);
28403b705cfSriastradh
28503b705cfSriastradh	list_init(&intel->batch_pixmaps);
28603b705cfSriastradh
28703b705cfSriastradh	if ((INTEL_INFO(intel)->gen == 060)) {
28803b705cfSriastradh		intel->wa_scratch_bo =
28903b705cfSriastradh			drm_intel_bo_alloc(intel->bufmgr, "wa scratch",
29003b705cfSriastradh					   4096, 4096);
29103b705cfSriastradh	}
29203b705cfSriastradh
29303b705cfSriastradh	return TRUE;
29403b705cfSriastradh}
29503b705cfSriastradh
29603b705cfSriastradhstatic void intel_bufmgr_fini(intel_screen_private *intel)
29703b705cfSriastradh{
29803b705cfSriastradh	if (intel->bufmgr == NULL)
29903b705cfSriastradh		return;
30003b705cfSriastradh
30103b705cfSriastradh	drm_intel_bo_unreference(intel->wa_scratch_bo);
30203b705cfSriastradh	drm_intel_bufmgr_destroy(intel->bufmgr);
30303b705cfSriastradh}
30403b705cfSriastradh
30503b705cfSriastradhstatic void I830XvInit(ScrnInfoPtr scrn)
30603b705cfSriastradh{
30703b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
30803b705cfSriastradh	MessageType from = X_PROBED;
30903b705cfSriastradh
31003b705cfSriastradh	intel->XvPreferOverlay =
31103b705cfSriastradh	    xf86ReturnOptValBool(intel->Options, OPTION_PREFER_OVERLAY, FALSE);
31203b705cfSriastradh
31303b705cfSriastradh	if (xf86GetOptValInteger(intel->Options, OPTION_VIDEO_KEY,
31403b705cfSriastradh				 &(intel->colorKey))) {
31503b705cfSriastradh		from = X_CONFIG;
31603b705cfSriastradh	} else if (xf86GetOptValInteger(intel->Options, OPTION_COLOR_KEY,
31703b705cfSriastradh					&(intel->colorKey))) {
31803b705cfSriastradh		from = X_CONFIG;
31903b705cfSriastradh	} else {
32003b705cfSriastradh		intel->colorKey =
32103b705cfSriastradh		    (1 << scrn->offset.red) | (1 << scrn->offset.green) |
32203b705cfSriastradh		    (((scrn->mask.blue >> scrn->offset.blue) - 1) <<
32303b705cfSriastradh		     scrn->offset.blue);
32403b705cfSriastradh		from = X_DEFAULT;
32503b705cfSriastradh	}
32603b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, from, "video overlay key set to 0x%x\n",
32703b705cfSriastradh		   intel->colorKey);
32803b705cfSriastradh}
32903b705cfSriastradh
33003b705cfSriastradhstatic Bool drm_has_boolean_param(struct intel_screen_private *intel,
33103b705cfSriastradh				  int param)
33203b705cfSriastradh{
33303b705cfSriastradh	drm_i915_getparam_t gp;
33403b705cfSriastradh	int value;
33503b705cfSriastradh
33603b705cfSriastradh	gp.value = &value;
33703b705cfSriastradh	gp.param = param;
33803b705cfSriastradh	if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp))
33903b705cfSriastradh		return FALSE;
34003b705cfSriastradh
34103b705cfSriastradh	return value;
34203b705cfSriastradh}
34303b705cfSriastradh
34403b705cfSriastradhstatic Bool has_kernel_flush(struct intel_screen_private *intel)
34503b705cfSriastradh{
34603b705cfSriastradh	/* The BLT ring was introduced at the same time as the
34703b705cfSriastradh	 * automatic flush for the busy-ioctl.
34803b705cfSriastradh	 */
34903b705cfSriastradh	return drm_has_boolean_param(intel, I915_PARAM_HAS_BLT);
35003b705cfSriastradh}
35103b705cfSriastradh
35203b705cfSriastradhstatic Bool has_relaxed_fencing(struct intel_screen_private *intel)
35303b705cfSriastradh{
35403b705cfSriastradh	return drm_has_boolean_param(intel, I915_PARAM_HAS_RELAXED_FENCING);
35503b705cfSriastradh}
35603b705cfSriastradh
35703b705cfSriastradhstatic Bool has_prime_vmap_flush(struct intel_screen_private *intel)
35803b705cfSriastradh{
35903b705cfSriastradh	return drm_has_boolean_param(intel, I915_PARAM_HAS_PRIME_VMAP_FLUSH);
36003b705cfSriastradh}
36103b705cfSriastradh
36203b705cfSriastradhstatic Bool can_accelerate_blt(struct intel_screen_private *intel)
36303b705cfSriastradh{
36403b705cfSriastradh	if (INTEL_INFO(intel)->gen == -1)
36503b705cfSriastradh		return FALSE;
36603b705cfSriastradh
36763ef14f0Smrg	if (!xf86ReturnOptValBool(intel->Options, OPTION_ACCEL_ENABLE, TRUE) ||
36863ef14f0Smrg	    !intel_option_cast_to_bool(intel->Options, OPTION_ACCEL_METHOD, TRUE)) {
36903b705cfSriastradh		xf86DrvMsg(intel->scrn->scrnIndex, X_CONFIG,
37003b705cfSriastradh			   "Disabling hardware acceleration.\n");
37103b705cfSriastradh		return FALSE;
37203b705cfSriastradh	}
37303b705cfSriastradh
37403b705cfSriastradh	if (INTEL_INFO(intel)->gen == 060) {
37513496ba1Ssnj		struct pci_device *const device = xf86GetPciInfoForEntity(intel->pEnt->index);
37603b705cfSriastradh
37703b705cfSriastradh		/* Sandybridge rev07 locks up easily, even with the
37803b705cfSriastradh		 * BLT ring workaround in place.
37903b705cfSriastradh		 * Thus use shadowfb by default.
38003b705cfSriastradh		 */
38103b705cfSriastradh		if (device->revision < 8) {
38203b705cfSriastradh			xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING,
38303b705cfSriastradh				   "Disabling hardware acceleration on this pre-production hardware.\n");
38403b705cfSriastradh
38503b705cfSriastradh			return FALSE;
38603b705cfSriastradh		}
38703b705cfSriastradh	}
38803b705cfSriastradh
38903b705cfSriastradh	if (INTEL_INFO(intel)->gen >= 060) {
39003b705cfSriastradh		drm_i915_getparam_t gp;
39103b705cfSriastradh		int value;
39203b705cfSriastradh
39303b705cfSriastradh		/* On Sandybridge we need the BLT in order to do anything since
39403b705cfSriastradh		 * it so frequently used in the acceleration code paths.
39503b705cfSriastradh		 */
39603b705cfSriastradh		gp.value = &value;
39703b705cfSriastradh		gp.param = I915_PARAM_HAS_BLT;
39803b705cfSriastradh		if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp))
39903b705cfSriastradh			return FALSE;
40003b705cfSriastradh	}
40103b705cfSriastradh
40203b705cfSriastradh	return TRUE;
40303b705cfSriastradh}
40403b705cfSriastradh
40503b705cfSriastradhstatic void intel_setup_capabilities(ScrnInfoPtr scrn)
40603b705cfSriastradh{
40703b705cfSriastradh#ifdef INTEL_PIXMAP_SHARING
40803b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
40903b705cfSriastradh	uint64_t value;
41003b705cfSriastradh	int ret;
41103b705cfSriastradh
41203b705cfSriastradh	scrn->capabilities = 0;
41303b705cfSriastradh
41403b705cfSriastradh	ret = drmGetCap(intel->drmSubFD, DRM_CAP_PRIME, &value);
41503b705cfSriastradh	if (ret == 0) {
41603b705cfSriastradh		if (value & DRM_PRIME_CAP_EXPORT)
41703b705cfSriastradh			scrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload;
41803b705cfSriastradh		if (value & DRM_PRIME_CAP_IMPORT)
41903b705cfSriastradh			scrn->capabilities |= RR_Capability_SinkOutput;
42003b705cfSriastradh	}
42103b705cfSriastradh#endif
42203b705cfSriastradh}
42303b705cfSriastradh
42403b705cfSriastradh/**
42503b705cfSriastradh * This is called before ScreenInit to do any require probing of screen
42603b705cfSriastradh * configuration.
42703b705cfSriastradh *
42803b705cfSriastradh * This code generally covers probing, module loading, option handling
42903b705cfSriastradh * card mapping, and RandR setup.
43003b705cfSriastradh *
43103b705cfSriastradh * Since xf86InitialConfiguration ends up requiring that we set video modes
43203b705cfSriastradh * in order to detect configuration, we end up having to do a lot of driver
43303b705cfSriastradh * setup (talking to the DRM, mapping the device, etc.) in this function.
43403b705cfSriastradh * As a result, we want to set up that server initialization once rather
43503b705cfSriastradh * that doing it per generation.
43603b705cfSriastradh */
43703b705cfSriastradhstatic Bool I830PreInit(ScrnInfoPtr scrn, int flags)
43803b705cfSriastradh{
43903b705cfSriastradh	intel_screen_private *intel;
44003b705cfSriastradh	rgb defaultWeight = { 0, 0, 0 };
44103b705cfSriastradh	EntityInfoPtr pEnt;
44203b705cfSriastradh	int flags24;
44303b705cfSriastradh	Gamma zeros = { 0.0, 0.0, 0.0 };
44403b705cfSriastradh
44503b705cfSriastradh	if (scrn->numEntities != 1)
44603b705cfSriastradh		return FALSE;
44703b705cfSriastradh
44803b705cfSriastradh	pEnt = xf86GetEntityInfo(scrn->entityList[0]);
44903b705cfSriastradh	if (pEnt == NULL)
45003b705cfSriastradh		return FALSE;
45103b705cfSriastradh
45203b705cfSriastradh	if (pEnt->location.type != BUS_PCI
45303b705cfSriastradh#ifdef XSERVER_PLATFORM_BUS
45403b705cfSriastradh	    && pEnt->location.type != BUS_PLATFORM
45503b705cfSriastradh#endif
45603b705cfSriastradh		)
45703b705cfSriastradh		return FALSE;
45803b705cfSriastradh
45903b705cfSriastradh	if (flags & PROBE_DETECT)
46003b705cfSriastradh		return TRUE;
46103b705cfSriastradh
46242542f5fSchristos	if (((uintptr_t)scrn->driverPrivate) & 3) {
46303b705cfSriastradh		intel = xnfcalloc(sizeof(*intel), 1);
46403b705cfSriastradh		if (intel == NULL)
46503b705cfSriastradh			return FALSE;
46603b705cfSriastradh
46742542f5fSchristos		intel->info = (void *)((uintptr_t)scrn->driverPrivate & ~3);
46803b705cfSriastradh		scrn->driverPrivate = intel;
46903b705cfSriastradh	}
47003b705cfSriastradh	intel = intel_get_screen_private(scrn);
47103b705cfSriastradh	intel->scrn = scrn;
47203b705cfSriastradh	intel->pEnt = pEnt;
47303b705cfSriastradh
47403b705cfSriastradh	scrn->displayWidth = 640;	/* default it */
47503b705cfSriastradh
47603b705cfSriastradh	if (!intel_open_drm_master(scrn)) {
47703b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
47803b705cfSriastradh			   "Failed to become DRM master.\n");
47903b705cfSriastradh		return FALSE;
48003b705cfSriastradh	}
48103b705cfSriastradh
48203b705cfSriastradh	scrn->monitor = scrn->confScreen->monitor;
48303b705cfSriastradh	scrn->progClock = TRUE;
48403b705cfSriastradh	scrn->rgbBits = 8;
48503b705cfSriastradh
48603b705cfSriastradh	flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32;
48703b705cfSriastradh
48803b705cfSriastradh	if (!xf86SetDepthBpp(scrn, 0, 0, 0, flags24))
48903b705cfSriastradh		return FALSE;
49003b705cfSriastradh
49103b705cfSriastradh	switch (scrn->depth) {
49203b705cfSriastradh	case 15:
49303b705cfSriastradh	case 16:
49403b705cfSriastradh	case 24:
49503b705cfSriastradh	case 30:
49603b705cfSriastradh		break;
49703b705cfSriastradh	case 8:
49803b705cfSriastradh	default:
49903b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
50003b705cfSriastradh			   "Given depth (%d) is not supported by intel driver\n",
50103b705cfSriastradh			   scrn->depth);
50203b705cfSriastradh		return FALSE;
50303b705cfSriastradh	}
50403b705cfSriastradh	xf86PrintDepthBpp(scrn);
50503b705cfSriastradh
50603b705cfSriastradh	if (!xf86SetWeight(scrn, defaultWeight, defaultWeight))
50703b705cfSriastradh		return FALSE;
50803b705cfSriastradh	if (!xf86SetDefaultVisual(scrn, -1))
50903b705cfSriastradh		return FALSE;
51003b705cfSriastradh
51103b705cfSriastradh	intel->cpp = scrn->bitsPerPixel / 8;
51203b705cfSriastradh
51303b705cfSriastradh	if (!I830GetEarlyOptions(scrn))
51403b705cfSriastradh		return FALSE;
51503b705cfSriastradh
51603b705cfSriastradh	intel_setup_capabilities(scrn);
51703b705cfSriastradh	intel_check_chipset_option(scrn);
51803b705cfSriastradh	intel_check_dri_option(scrn);
51903b705cfSriastradh
52003b705cfSriastradh	if (!intel_init_bufmgr(intel)) {
52103b705cfSriastradh		PreInitCleanup(scrn);
52203b705cfSriastradh		return FALSE;
52303b705cfSriastradh	}
52403b705cfSriastradh
52503b705cfSriastradh	intel->force_fallback =
52603b705cfSriastradh		drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE) != 0;
52703b705cfSriastradh
52803b705cfSriastradh	/* Enable tiling by default */
52903b705cfSriastradh	intel->tiling = INTEL_TILING_ALL;
53003b705cfSriastradh
53103b705cfSriastradh	/* Allow user override if they set a value */
53203b705cfSriastradh	if (!xf86ReturnOptValBool(intel->Options, OPTION_TILING_2D, TRUE))
53303b705cfSriastradh		intel->tiling &= ~INTEL_TILING_2D;
53403b705cfSriastradh	if (xf86ReturnOptValBool(intel->Options, OPTION_TILING_FB, FALSE))
53503b705cfSriastradh		intel->tiling &= ~INTEL_TILING_FB;
53603b705cfSriastradh	if (!can_accelerate_blt(intel)) {
53703b705cfSriastradh		intel->force_fallback = TRUE;
53803b705cfSriastradh		intel->tiling &= ~INTEL_TILING_FB;
53903b705cfSriastradh	}
54003b705cfSriastradh
54103b705cfSriastradh	intel->has_kernel_flush = has_kernel_flush(intel);
54203b705cfSriastradh
54303b705cfSriastradh	intel->has_prime_vmap_flush = has_prime_vmap_flush(intel);
54403b705cfSriastradh
54503b705cfSriastradh	intel->has_relaxed_fencing = INTEL_INFO(intel)->gen >= 033;
54603b705cfSriastradh	/* And override the user if there is no kernel support */
54703b705cfSriastradh	if (intel->has_relaxed_fencing)
54803b705cfSriastradh		intel->has_relaxed_fencing = has_relaxed_fencing(intel);
54903b705cfSriastradh
55003b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
55103b705cfSriastradh		   "Relaxed fencing %s\n",
55203b705cfSriastradh		   intel->has_relaxed_fencing ? "enabled" : "disabled");
55303b705cfSriastradh
55403b705cfSriastradh	/* SwapBuffers delays to avoid tearing */
55503b705cfSriastradh	intel->swapbuffers_wait = xf86ReturnOptValBool(intel->Options,
55603b705cfSriastradh						       OPTION_SWAPBUFFERS_WAIT,
55703b705cfSriastradh						       TRUE);
55803b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Wait on SwapBuffers? %s\n",
55903b705cfSriastradh		   intel->swapbuffers_wait ? "enabled" : "disabled");
56003b705cfSriastradh
56103b705cfSriastradh	intel->use_triple_buffer =
56203b705cfSriastradh		xf86ReturnOptValBool(intel->Options,
56303b705cfSriastradh				     OPTION_TRIPLE_BUFFER,
56403b705cfSriastradh				     TRUE);
56503b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Triple buffering? %s\n",
56603b705cfSriastradh		   intel->use_triple_buffer ? "enabled" : "disabled");
56703b705cfSriastradh
56803b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Framebuffer %s\n",
56903b705cfSriastradh		   intel->tiling & INTEL_TILING_FB ? "tiled" : "linear");
57003b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Pixmaps %s\n",
57103b705cfSriastradh		   intel->tiling & INTEL_TILING_2D ? "tiled" : "linear");
57203b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "3D buffers %s\n",
57303b705cfSriastradh		   intel->tiling & INTEL_TILING_3D ? "tiled" : "linear");
57403b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "SwapBuffers wait %sabled\n",
57503b705cfSriastradh		   intel->swapbuffers_wait ? "en" : "dis");
57603b705cfSriastradh
57703b705cfSriastradh	I830XvInit(scrn);
57803b705cfSriastradh
57903b705cfSriastradh	if (!intel_mode_pre_init(scrn, intel->drmSubFD, intel->cpp)) {
58003b705cfSriastradh		PreInitCleanup(scrn);
58103b705cfSriastradh		return FALSE;
58203b705cfSriastradh	}
58303b705cfSriastradh
58403b705cfSriastradh	if (!xf86SetGamma(scrn, zeros)) {
58503b705cfSriastradh		PreInitCleanup(scrn);
58603b705cfSriastradh		return FALSE;
58703b705cfSriastradh	}
58803b705cfSriastradh
58903b705cfSriastradh	if (scrn->modes == NULL) {
59003b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR, "No modes.\n");
59103b705cfSriastradh		PreInitCleanup(scrn);
59203b705cfSriastradh		return FALSE;
59303b705cfSriastradh	}
59403b705cfSriastradh	scrn->currentMode = scrn->modes;
59503b705cfSriastradh
59603b705cfSriastradh	/* Set display resolution */
59703b705cfSriastradh	xf86SetDpi(scrn, 0, 0);
59803b705cfSriastradh
59903b705cfSriastradh	/* Load the required sub modules */
60003b705cfSriastradh	if (!xf86LoadSubModule(scrn, "fb")) {
60103b705cfSriastradh		PreInitCleanup(scrn);
60203b705cfSriastradh		return FALSE;
60303b705cfSriastradh	}
60403b705cfSriastradh
60542542f5fSchristos	/* Load the dri modules if requested. */
60642542f5fSchristos#if HAVE_DRI2
60742542f5fSchristos	if (intel->dri2 != DRI_DISABLED && !xf86LoadSubModule(scrn, "dri2"))
60842542f5fSchristos		intel->dri2 = DRI_DISABLED;
60942542f5fSchristos#endif
61042542f5fSchristos#if HAVE_DRI3
61142542f5fSchristos	if (intel->dri3 != DRI_DISABLED && !xf86LoadSubModule(scrn, "dri3"))
61242542f5fSchristos		intel->dri3 = DRI_DISABLED;
61342542f5fSchristos#endif
61403b705cfSriastradh
61503b705cfSriastradh	return TRUE;
61603b705cfSriastradh}
61703b705cfSriastradh
61803b705cfSriastradh#ifdef INTEL_PIXMAP_SHARING
619a7f02474Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 25
620a7f02474Smrg#define slave_dst secondary_dst
621a7f02474Smrg#define master_pixmap primary_pixmap
622a7f02474Smrg#endif
62303b705cfSriastradhstatic void
62403b705cfSriastradhredisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
62503b705cfSriastradh{
62603b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
62703b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
62803b705cfSriastradh	RegionRec pixregion;
62903b705cfSriastradh	int was_blocked;
63003b705cfSriastradh
63103b705cfSriastradh	PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap);
63203b705cfSriastradh	RegionTranslate(&pixregion, dirty->x, dirty->y);
63303b705cfSriastradh	RegionIntersect(&pixregion, &pixregion, DamageRegion(dirty->damage));
63403b705cfSriastradh	RegionTranslate(&pixregion, -dirty->x, -dirty->y);
63503b705cfSriastradh	was_blocked = RegionNil(&pixregion);
63603b705cfSriastradh	DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
63703b705cfSriastradh	RegionUninit(&pixregion);
63803b705cfSriastradh	if (was_blocked)
63903b705cfSriastradh		return;
64003b705cfSriastradh
64103b705cfSriastradh	PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap);
64203b705cfSriastradh	PixmapSyncDirtyHelper(dirty, &pixregion);
64303b705cfSriastradh	RegionUninit(&pixregion);
64403b705cfSriastradh
64513496ba1Ssnj        intel_flush(intel);
64603b705cfSriastradh	if (!intel->has_prime_vmap_flush) {
64713496ba1Ssnj		drm_intel_bo *bo = intel_uxa_get_pixmap_bo(dirty->slave_dst->master_pixmap);
64803b705cfSriastradh		was_blocked = xf86BlockSIGIO();
64903b705cfSriastradh		drm_intel_bo_map(bo, FALSE);
65003b705cfSriastradh		drm_intel_bo_unmap(bo);
65103b705cfSriastradh		xf86UnblockSIGIO(was_blocked);
65203b705cfSriastradh	}
65303b705cfSriastradh
65403b705cfSriastradh	DamageRegionProcessPending(&dirty->slave_dst->drawable);
65503b705cfSriastradh	return;
65603b705cfSriastradh}
65703b705cfSriastradh
65803b705cfSriastradhstatic void
65963ef14f0Smrgintel_dirty_update(intel_screen_private *intel)
66003b705cfSriastradh{
66163ef14f0Smrg	ScreenPtr screen = xf86ScrnToScreen(intel->scrn);
66203b705cfSriastradh	RegionPtr region;
66303b705cfSriastradh	PixmapDirtyUpdatePtr ent;
66403b705cfSriastradh
66503b705cfSriastradh	if (xorg_list_is_empty(&screen->pixmap_dirty_list))
66603b705cfSriastradh	    return;
66703b705cfSriastradh
66803b705cfSriastradh	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
66903b705cfSriastradh		region = DamageRegion(ent->damage);
67003b705cfSriastradh		if (RegionNotEmpty(region)) {
67103b705cfSriastradh			redisplay_dirty(screen, ent);
67203b705cfSriastradh			DamageEmpty(ent->damage);
67303b705cfSriastradh		}
67403b705cfSriastradh	}
67503b705cfSriastradh}
67603b705cfSriastradh#endif
67703b705cfSriastradh
67863ef14f0Smrg#if !HAVE_NOTIFY_FD
67903b705cfSriastradhstatic void
68003b705cfSriastradhI830BlockHandler(BLOCKHANDLER_ARGS_DECL)
68103b705cfSriastradh{
68203b705cfSriastradh	SCREEN_PTR(arg);
68303b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
68403b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
68503b705cfSriastradh
68603b705cfSriastradh	screen->BlockHandler = intel->BlockHandler;
68703b705cfSriastradh
68803b705cfSriastradh	(*screen->BlockHandler) (BLOCKHANDLER_ARGS);
68903b705cfSriastradh
69003b705cfSriastradh	intel->BlockHandler = screen->BlockHandler;
69103b705cfSriastradh	screen->BlockHandler = I830BlockHandler;
69203b705cfSriastradh
69303b705cfSriastradh	intel_uxa_block_handler(intel);
69403b705cfSriastradh	intel_video_block_handler(intel);
69503b705cfSriastradh#ifdef INTEL_PIXMAP_SHARING
69663ef14f0Smrg	intel_dirty_update(intel);
69703b705cfSriastradh#endif
69803b705cfSriastradh}
69963ef14f0Smrg#else
70063ef14f0Smrgstatic void
70163ef14f0SmrgI830BlockHandler(void *data, void *timeout)
70263ef14f0Smrg{
70363ef14f0Smrg	intel_screen_private *intel = data;
70463ef14f0Smrg
70563ef14f0Smrg	intel_uxa_block_handler(intel);
70663ef14f0Smrg	intel_video_block_handler(intel);
70763ef14f0Smrg#ifdef INTEL_PIXMAP_SHARING
70863ef14f0Smrg	intel_dirty_update(intel);
70963ef14f0Smrg#endif
71063ef14f0Smrg}
71163ef14f0Smrg#endif
71203b705cfSriastradh
71303b705cfSriastradhstatic Bool
71403b705cfSriastradhintel_init_initial_framebuffer(ScrnInfoPtr scrn)
71503b705cfSriastradh{
71603b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
71703b705cfSriastradh	int width = scrn->virtualX;
71803b705cfSriastradh	int height = scrn->virtualY;
71942542f5fSchristos	int pitch;
72003b705cfSriastradh	uint32_t tiling;
72103b705cfSriastradh
72203b705cfSriastradh	intel->front_buffer = intel_allocate_framebuffer(scrn,
72303b705cfSriastradh							 width, height,
72403b705cfSriastradh							 intel->cpp,
72542542f5fSchristos							 &pitch, &tiling);
72603b705cfSriastradh
72703b705cfSriastradh	if (!intel->front_buffer) {
72803b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
72903b705cfSriastradh			   "Couldn't allocate initial framebuffer.\n");
73003b705cfSriastradh		return FALSE;
73103b705cfSriastradh	}
73203b705cfSriastradh
73303b705cfSriastradh	intel->front_pitch = pitch;
73403b705cfSriastradh	intel->front_tiling = tiling;
73503b705cfSriastradh	scrn->displayWidth = pitch / intel->cpp;
73603b705cfSriastradh
73703b705cfSriastradh	return TRUE;
73803b705cfSriastradh}
73903b705cfSriastradh
74003b705cfSriastradhstatic void
74103b705cfSriastradhintel_flush_callback(CallbackListPtr *list,
74203b705cfSriastradh		     pointer user_data, pointer call_data)
74303b705cfSriastradh{
74403b705cfSriastradh	ScrnInfoPtr scrn = user_data;
74513496ba1Ssnj	if (scrn->vtSema)
74613496ba1Ssnj                intel_flush(intel_get_screen_private(scrn));
74703b705cfSriastradh}
74803b705cfSriastradh
74903b705cfSriastradh#if HAVE_UDEV
75063ef14f0Smrg#include <sys/stat.h>
75163ef14f0Smrg
75203b705cfSriastradhstatic void
75303b705cfSriastradhI830HandleUEvents(int fd, void *closure)
75403b705cfSriastradh{
75503b705cfSriastradh	ScrnInfoPtr scrn = closure;
75603b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
75703b705cfSriastradh	struct udev_device *dev;
75803b705cfSriastradh	const char *hotplug;
75903b705cfSriastradh	struct stat s;
76003b705cfSriastradh	dev_t udev_devnum;
76103b705cfSriastradh
76203b705cfSriastradh	dev = udev_monitor_receive_device(intel->uevent_monitor);
76303b705cfSriastradh	if (!dev)
76403b705cfSriastradh		return;
76503b705cfSriastradh
76603b705cfSriastradh	udev_devnum = udev_device_get_devnum(dev);
76703b705cfSriastradh	if (fstat(intel->drmSubFD, &s)) {
76803b705cfSriastradh		udev_device_unref(dev);
76903b705cfSriastradh		return;
77003b705cfSriastradh	}
77103b705cfSriastradh	/*
77203b705cfSriastradh	 * Check to make sure this event is directed at our
77303b705cfSriastradh	 * device (by comparing dev_t values), then make
77403b705cfSriastradh	 * sure it's a hotplug event (HOTPLUG=1)
77503b705cfSriastradh	 */
77603b705cfSriastradh
77703b705cfSriastradh	hotplug = udev_device_get_property_value(dev, "HOTPLUG");
77803b705cfSriastradh
77903b705cfSriastradh	if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
78003b705cfSriastradh			hotplug && atoi(hotplug) == 1)
78142542f5fSchristos	{
78242542f5fSchristos		intel_mode_hotplug(intel);
78342542f5fSchristos	}
78403b705cfSriastradh
78503b705cfSriastradh	udev_device_unref(dev);
78603b705cfSriastradh}
78703b705cfSriastradh
78863ef14f0Smrgstatic int has_randr(void)
78963ef14f0Smrg{
79063ef14f0Smrg#if HAS_DIXREGISTERPRIVATEKEY
79163ef14f0Smrg	return dixPrivateKeyRegistered(rrPrivKey);
79263ef14f0Smrg#else
79363ef14f0Smrg	return *rrPrivKey;
79463ef14f0Smrg#endif
79563ef14f0Smrg}
79663ef14f0Smrg
79703b705cfSriastradhstatic void
79803b705cfSriastradhI830UeventInit(ScrnInfoPtr scrn)
79903b705cfSriastradh{
80003b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
80103b705cfSriastradh	struct udev *u;
80203b705cfSriastradh	struct udev_monitor *mon;
80303b705cfSriastradh	Bool hotplug;
80403b705cfSriastradh	MessageType from = X_CONFIG;
80503b705cfSriastradh
80663ef14f0Smrg	/* Without RR, nothing we can do here */
80763ef14f0Smrg	if (!has_randr())
80863ef14f0Smrg		return;
80963ef14f0Smrg
81003b705cfSriastradh	if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) {
81103b705cfSriastradh		from = X_DEFAULT;
81203b705cfSriastradh		hotplug = TRUE;
81303b705cfSriastradh	}
81403b705cfSriastradh
81503b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, from, "hotplug detection: \"%s\"\n",
81603b705cfSriastradh			hotplug ? "enabled" : "disabled");
81703b705cfSriastradh	if (!hotplug)
81803b705cfSriastradh		return;
81903b705cfSriastradh
82003b705cfSriastradh	u = udev_new();
82103b705cfSriastradh	if (!u)
82203b705cfSriastradh		return;
82303b705cfSriastradh
82403b705cfSriastradh	mon = udev_monitor_new_from_netlink(u, "udev");
82503b705cfSriastradh
82603b705cfSriastradh	if (!mon) {
82703b705cfSriastradh		udev_unref(u);
82803b705cfSriastradh		return;
82903b705cfSriastradh	}
83003b705cfSriastradh
83103b705cfSriastradh	if (udev_monitor_filter_add_match_subsystem_devtype(mon,
83203b705cfSriastradh				"drm",
83303b705cfSriastradh				"drm_minor") < 0 ||
83403b705cfSriastradh			udev_monitor_enable_receiving(mon) < 0)
83503b705cfSriastradh	{
83603b705cfSriastradh		udev_monitor_unref(mon);
83703b705cfSriastradh		udev_unref(u);
83803b705cfSriastradh		return;
83903b705cfSriastradh	}
84003b705cfSriastradh
84142542f5fSchristos	intel->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon),
84242542f5fSchristos						      I830HandleUEvents, scrn);
84303b705cfSriastradh	if (!intel->uevent_handler) {
84403b705cfSriastradh		udev_monitor_unref(mon);
84503b705cfSriastradh		udev_unref(u);
84603b705cfSriastradh		return;
84703b705cfSriastradh	}
84803b705cfSriastradh
84903b705cfSriastradh	intel->uevent_monitor = mon;
85003b705cfSriastradh}
85103b705cfSriastradh
85203b705cfSriastradhstatic void
85303b705cfSriastradhI830UeventFini(ScrnInfoPtr scrn)
85403b705cfSriastradh{
85503b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
85603b705cfSriastradh
85703b705cfSriastradh	if (intel->uevent_handler) {
85803b705cfSriastradh		struct udev *u = udev_monitor_get_udev(intel->uevent_monitor);
85903b705cfSriastradh
86003b705cfSriastradh		xf86RemoveGeneralHandler(intel->uevent_handler);
86103b705cfSriastradh
86203b705cfSriastradh		udev_monitor_unref(intel->uevent_monitor);
86303b705cfSriastradh		udev_unref(u);
86403b705cfSriastradh		intel->uevent_handler = NULL;
86503b705cfSriastradh		intel->uevent_monitor = NULL;
86603b705cfSriastradh	}
86703b705cfSriastradh}
86803b705cfSriastradh#endif /* HAVE_UDEV */
86903b705cfSriastradh
87003b705cfSriastradhstatic Bool
87103b705cfSriastradhI830ScreenInit(SCREEN_INIT_ARGS_DECL)
87203b705cfSriastradh{
87303b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
87403b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
87503b705cfSriastradh	VisualPtr visual;
87603b705cfSriastradh#ifdef INTEL_XVMC
87703b705cfSriastradh	MessageType from;
87803b705cfSriastradh#endif
87913496ba1Ssnj	struct pci_device *const device = xf86GetPciInfoForEntity(intel->pEnt->index);
88003b705cfSriastradh	int fb_bar = IS_GEN2(intel) ? 0 : 2;
88103b705cfSriastradh
88203b705cfSriastradh	scrn->videoRam = device->regions[fb_bar].size / 1024;
88303b705cfSriastradh
88403b705cfSriastradh	intel->last_3d = LAST_3D_OTHER;
88503b705cfSriastradh	intel->overlayOn = FALSE;
88603b705cfSriastradh
88703b705cfSriastradh	/*
88803b705cfSriastradh	 * Set this so that the overlay allocation is factored in when
88903b705cfSriastradh	 * appropriate.
89003b705cfSriastradh	 */
89103b705cfSriastradh	intel->XvEnabled = TRUE;
89203b705cfSriastradh
89303b705cfSriastradh	if (!intel_init_initial_framebuffer(scrn))
89403b705cfSriastradh		return FALSE;
89503b705cfSriastradh
89603b705cfSriastradh	miClearVisualTypes();
89703b705cfSriastradh	if (!miSetVisualTypes(scrn->depth,
89803b705cfSriastradh			      miGetDefaultVisualMask(scrn->depth),
89903b705cfSriastradh			      scrn->rgbBits, scrn->defaultVisual))
90003b705cfSriastradh		return FALSE;
90103b705cfSriastradh	if (!miSetPixmapDepths())
90203b705cfSriastradh		return FALSE;
90303b705cfSriastradh
90442542f5fSchristos	/* Must be first, before anything else installs screen callbacks. */
90503b705cfSriastradh	if (!fbScreenInit(screen, NULL,
90603b705cfSriastradh			  scrn->virtualX, scrn->virtualY,
90703b705cfSriastradh			  scrn->xDpi, scrn->yDpi,
90803b705cfSriastradh			  scrn->displayWidth, scrn->bitsPerPixel))
90903b705cfSriastradh		return FALSE;
91003b705cfSriastradh
91103b705cfSriastradh	if (scrn->bitsPerPixel > 8) {
91203b705cfSriastradh		/* Fixup RGB ordering */
91303b705cfSriastradh		visual = screen->visuals + screen->numVisuals;
91403b705cfSriastradh		while (--visual >= screen->visuals) {
91503b705cfSriastradh			if ((visual->class | DynamicClass) == DirectColor) {
91603b705cfSriastradh				visual->offsetRed = scrn->offset.red;
91703b705cfSriastradh				visual->offsetGreen = scrn->offset.green;
91803b705cfSriastradh				visual->offsetBlue = scrn->offset.blue;
91903b705cfSriastradh				visual->redMask = scrn->mask.red;
92003b705cfSriastradh				visual->greenMask = scrn->mask.green;
92103b705cfSriastradh				visual->blueMask = scrn->mask.blue;
92203b705cfSriastradh			}
92303b705cfSriastradh		}
92403b705cfSriastradh	}
92503b705cfSriastradh
92603b705cfSriastradh	fbPictureInit(screen, NULL, 0);
92703b705cfSriastradh
92803b705cfSriastradh	xf86SetBlackWhitePixels(screen);
92903b705cfSriastradh
93003b705cfSriastradh	if (!intel_uxa_init(screen)) {
93103b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
93203b705cfSriastradh			   "Hardware acceleration initialization failed\n");
93303b705cfSriastradh		return FALSE;
93403b705cfSriastradh	}
93503b705cfSriastradh
93642542f5fSchristos#if HAVE_DRI2
93742542f5fSchristos	if (intel->dri2 == DRI_NONE && I830DRI2ScreenInit(screen))
93842542f5fSchristos		intel->dri2 = DRI_ACTIVE;
93942542f5fSchristos#endif
94042542f5fSchristos
94142542f5fSchristos#if HAVE_DRI3
94242542f5fSchristos	if (!intel_sync_init(screen))
94342542f5fSchristos		intel->dri3 = DRI_DISABLED;
94442542f5fSchristos	if (intel->dri3 == DRI_NONE && intel_dri3_screen_init(screen))
94542542f5fSchristos		intel->dri3 = DRI_ACTIVE;
94642542f5fSchristos#endif
94742542f5fSchristos
94842542f5fSchristos	if (xf86ReturnOptValBool(intel->Options, OPTION_PRESENT, TRUE))
94942542f5fSchristos		intel_present_screen_init(screen);
95042542f5fSchristos
95103b705cfSriastradh	xf86SetBackingStore(screen);
95203b705cfSriastradh	xf86SetSilkenMouse(screen);
95303b705cfSriastradh	miDCInitialize(screen, xf86GetPointerScreenFuncs());
95403b705cfSriastradh
95503b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO, "Initializing HW Cursor\n");
95603b705cfSriastradh	if (!xf86_cursors_init(screen, 64, 64,
95703b705cfSriastradh			       (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
95803b705cfSriastradh				HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
95903b705cfSriastradh				HARDWARE_CURSOR_INVERT_MASK |
96003b705cfSriastradh				HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
96103b705cfSriastradh				HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
96203b705cfSriastradh				HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
96303b705cfSriastradh				HARDWARE_CURSOR_UPDATE_UNHIDDEN |
96403b705cfSriastradh				HARDWARE_CURSOR_ARGB))) {
96503b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
96603b705cfSriastradh			   "Hardware cursor initialization failed\n");
96703b705cfSriastradh	}
96803b705cfSriastradh
96963ef14f0Smrg#if !HAVE_NOTIFY_FD
97003b705cfSriastradh	intel->BlockHandler = screen->BlockHandler;
97103b705cfSriastradh	screen->BlockHandler = I830BlockHandler;
97263ef14f0Smrg#else
97363ef14f0Smrg	RegisterBlockAndWakeupHandlers(I830BlockHandler,
97463ef14f0Smrg				       (ServerWakeupHandlerProcPtr)NoopDDA,
97563ef14f0Smrg				       intel);
97663ef14f0Smrg#endif
97703b705cfSriastradh
97803b705cfSriastradh#ifdef INTEL_PIXMAP_SHARING
97903b705cfSriastradh	screen->StartPixmapTracking = PixmapStartDirtyTracking;
98003b705cfSriastradh	screen->StopPixmapTracking = PixmapStopDirtyTracking;
98103b705cfSriastradh#endif
98203b705cfSriastradh
98303b705cfSriastradh	if (!AddCallback(&FlushCallback, intel_flush_callback, scrn))
98403b705cfSriastradh		return FALSE;
98503b705cfSriastradh
98603b705cfSriastradh	screen->SaveScreen = xf86SaveScreen;
98703b705cfSriastradh	intel->CloseScreen = screen->CloseScreen;
98803b705cfSriastradh	screen->CloseScreen = I830CloseScreen;
98903b705cfSriastradh	intel->CreateScreenResources = screen->CreateScreenResources;
99003b705cfSriastradh	screen->CreateScreenResources = i830CreateScreenResources;
99103b705cfSriastradh
99203b705cfSriastradh	if (!xf86CrtcScreenInit(screen))
99303b705cfSriastradh		return FALSE;
99403b705cfSriastradh
99503b705cfSriastradh	if (!miCreateDefColormap(screen))
99603b705cfSriastradh		return FALSE;
99703b705cfSriastradh
99863ef14f0Smrg	/* X-Server < 1.20 mishandles > 256 slots / > 8 bpc color maps. */
99963ef14f0Smrg	if ((scrn->rgbBits <= 8 ||
100063ef14f0Smrg	    XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,20,0,0,0)) &&
100163ef14f0Smrg	    !xf86HandleColormaps(screen, 1 << scrn->rgbBits, scrn->rgbBits,
100263ef14f0Smrg				 I830LoadPalette, NULL,
100303b705cfSriastradh				 CMAP_RELOAD_ON_MODE_SWITCH |
100403b705cfSriastradh				 CMAP_PALETTED_TRUECOLOR)) {
100503b705cfSriastradh		return FALSE;
100603b705cfSriastradh	}
100703b705cfSriastradh
100803b705cfSriastradh	xf86DPMSInit(screen, xf86DPMSSet, 0);
100903b705cfSriastradh
101003b705cfSriastradh#ifdef INTEL_XVMC
101103b705cfSriastradh	if (INTEL_INFO(intel)->gen >= 040)
101203b705cfSriastradh		intel->XvMCEnabled = TRUE;
101342542f5fSchristos	from = (intel->dri2 == DRI_ACTIVE &&
101403b705cfSriastradh		xf86GetOptValBool(intel->Options, OPTION_XVMC,
101503b705cfSriastradh				  &intel->XvMCEnabled) ? X_CONFIG : X_DEFAULT);
101603b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, from, "Intel XvMC decoder %sabled\n",
101703b705cfSriastradh		   intel->XvMCEnabled ? "en" : "dis");
101803b705cfSriastradh#endif
101903b705cfSriastradh	/* Init video */
102003b705cfSriastradh	if (intel->XvEnabled)
102113496ba1Ssnj		intel_video_init(screen);
102203b705cfSriastradh
102342542f5fSchristos#if HAVE_DRI2
102442542f5fSchristos	switch (intel->dri2) {
102542542f5fSchristos	case DRI_ACTIVE:
102642542f5fSchristos		xf86DrvMsg(scrn->scrnIndex, X_INFO,
102742542f5fSchristos			   "DRI2: Enabled\n");
102842542f5fSchristos		break;
102942542f5fSchristos	case DRI_DISABLED:
103042542f5fSchristos		xf86DrvMsg(scrn->scrnIndex, X_INFO,
103142542f5fSchristos			   "DRI2: Disabled\n");
103242542f5fSchristos		break;
103342542f5fSchristos	case DRI_NONE:
103442542f5fSchristos		xf86DrvMsg(scrn->scrnIndex, X_INFO,
103542542f5fSchristos			   "DRI2: Failed\n");
103642542f5fSchristos		break;
103742542f5fSchristos	}
103842542f5fSchristos#else
103942542f5fSchristos	xf86DrvMsg(scrn->scrnIndex, X_INFO,
104042542f5fSchristos		   "DRI2: Not available\n");
104142542f5fSchristos#endif
104242542f5fSchristos
104342542f5fSchristos#if HAVE_DRI3
104442542f5fSchristos	switch (intel->dri3) {
104542542f5fSchristos	case DRI_ACTIVE:
104603b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_INFO,
104742542f5fSchristos			   "DRI3: Enabled\n");
104803b705cfSriastradh		break;
104903b705cfSriastradh	case DRI_DISABLED:
105003b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_INFO,
105142542f5fSchristos			   "DRI3: Disabled\n");
105203b705cfSriastradh		break;
105303b705cfSriastradh	case DRI_NONE:
105403b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_INFO,
105542542f5fSchristos			   "DRI3: Failed\n");
105603b705cfSriastradh		break;
105703b705cfSriastradh	}
105803b705cfSriastradh#else
105903b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
106042542f5fSchristos		   "DRI3: Not available\n");
106103b705cfSriastradh#endif
106203b705cfSriastradh
106303b705cfSriastradh	if (serverGeneration == 1)
106403b705cfSriastradh		xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options);
106503b705cfSriastradh
106603b705cfSriastradh	intel_mode_init(intel);
106703b705cfSriastradh
106803b705cfSriastradh	intel->suspended = FALSE;
106903b705cfSriastradh
107003b705cfSriastradh#if HAVE_UDEV
107103b705cfSriastradh	I830UeventInit(scrn);
107203b705cfSriastradh#endif
107303b705cfSriastradh
107403b705cfSriastradh	/* Must force it before EnterVT, so we are in control of VT and
107503b705cfSriastradh	 * later memory should be bound when allocating, e.g rotate_mem */
107603b705cfSriastradh	scrn->vtSema = TRUE;
107703b705cfSriastradh
107803b705cfSriastradh	return I830EnterVT(VT_FUNC_ARGS(0));
107903b705cfSriastradh}
108003b705cfSriastradh
108103b705cfSriastradhstatic void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL)
108203b705cfSriastradh{
108303b705cfSriastradh}
108403b705cfSriastradh
108503b705cfSriastradhstatic void I830FreeScreen(FREE_SCREEN_ARGS_DECL)
108603b705cfSriastradh{
108703b705cfSriastradh	SCRN_INFO_PTR(arg);
108803b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
108903b705cfSriastradh
109042542f5fSchristos	if (intel && !((uintptr_t)intel & 3)) {
109103b705cfSriastradh		intel_mode_fini(intel);
109203b705cfSriastradh		intel_bufmgr_fini(intel);
109313496ba1Ssnj		intel_put_device(intel->dev);
109403b705cfSriastradh
109503b705cfSriastradh		free(intel);
109603b705cfSriastradh		scrn->driverPrivate = NULL;
109703b705cfSriastradh	}
109803b705cfSriastradh}
109903b705cfSriastradh
110003b705cfSriastradhstatic void I830LeaveVT(VT_FUNC_ARGS_DECL)
110103b705cfSriastradh{
110203b705cfSriastradh	SCRN_INFO_PTR(arg);
110313496ba1Ssnj	intel_screen_private *intel = intel_get_screen_private(scrn);
110403b705cfSriastradh
110503b705cfSriastradh	xf86RotateFreeShadow(scrn);
110603b705cfSriastradh
110703b705cfSriastradh	xf86_hide_cursors(scrn);
110803b705cfSriastradh
110913496ba1Ssnj	if (intel_put_master(intel->dev))
111003b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
111103b705cfSriastradh			   "drmDropMaster failed: %s\n", strerror(errno));
111203b705cfSriastradh}
111303b705cfSriastradh
111403b705cfSriastradh/*
111503b705cfSriastradh * This gets called when gaining control of the VT, and from ScreenInit().
111603b705cfSriastradh */
111703b705cfSriastradhstatic Bool I830EnterVT(VT_FUNC_ARGS_DECL)
111803b705cfSriastradh{
111903b705cfSriastradh	SCRN_INFO_PTR(arg);
112013496ba1Ssnj	intel_screen_private *intel = intel_get_screen_private(scrn);
112103b705cfSriastradh
112213496ba1Ssnj	if (intel_get_master(intel->dev)) {
112303b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
112403b705cfSriastradh			   "drmSetMaster failed: %s\n",
112503b705cfSriastradh			   strerror(errno));
112642542f5fSchristos		return FALSE;
112703b705cfSriastradh	}
112803b705cfSriastradh
112903b705cfSriastradh	if (!xf86SetDesiredModes(scrn))
113003b705cfSriastradh		return FALSE;
113103b705cfSriastradh
113203b705cfSriastradh	intel_mode_disable_unused_functions(scrn);
113303b705cfSriastradh	return TRUE;
113403b705cfSriastradh}
113503b705cfSriastradh
113603b705cfSriastradhstatic Bool I830SwitchMode(SWITCH_MODE_ARGS_DECL)
113703b705cfSriastradh{
113803b705cfSriastradh	SCRN_INFO_PTR(arg);
113903b705cfSriastradh
114003b705cfSriastradh	return xf86SetSingleMode(scrn, mode, RR_Rotate_0);
114103b705cfSriastradh}
114203b705cfSriastradh
114303b705cfSriastradhstatic Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL)
114403b705cfSriastradh{
114503b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
114603b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
114703b705cfSriastradh
114803b705cfSriastradh#if HAVE_UDEV
114903b705cfSriastradh	I830UeventFini(scrn);
115003b705cfSriastradh#endif
115103b705cfSriastradh
115203b705cfSriastradh	intel_mode_close(intel);
115303b705cfSriastradh
115403b705cfSriastradh	DeleteCallback(&FlushCallback, intel_flush_callback, scrn);
115503b705cfSriastradh
115603b705cfSriastradh	TimerFree(intel->cache_expire);
115703b705cfSriastradh	intel->cache_expire = NULL;
115803b705cfSriastradh
115903b705cfSriastradh	if (intel->uxa_driver) {
116003b705cfSriastradh		uxa_driver_fini(screen);
116103b705cfSriastradh		free(intel->uxa_driver);
116203b705cfSriastradh		intel->uxa_driver = NULL;
116303b705cfSriastradh	}
116403b705cfSriastradh
116503b705cfSriastradh	if (intel->back_buffer) {
116603b705cfSriastradh		drm_intel_bo_unreference(intel->back_buffer);
116703b705cfSriastradh		intel->back_buffer = NULL;
116803b705cfSriastradh	}
116903b705cfSriastradh
117003b705cfSriastradh	if (intel->front_buffer) {
117103b705cfSriastradh		intel_mode_remove_fb(intel);
117203b705cfSriastradh		drm_intel_bo_unreference(intel->front_buffer);
117303b705cfSriastradh		intel->front_buffer = NULL;
117403b705cfSriastradh	}
117503b705cfSriastradh
117603b705cfSriastradh	if (scrn->vtSema == TRUE) {
117703b705cfSriastradh		I830LeaveVT(VT_FUNC_ARGS(0));
117803b705cfSriastradh	}
117903b705cfSriastradh
118003b705cfSriastradh	intel_batch_teardown(scrn);
118103b705cfSriastradh
118242542f5fSchristos	if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100)
118303b705cfSriastradh		gen4_render_state_cleanup(scrn);
118403b705cfSriastradh
118503b705cfSriastradh	xf86_cursors_fini(screen);
118603b705cfSriastradh
118703b705cfSriastradh	i965_free_video(scrn);
118803b705cfSriastradh
118903b705cfSriastradh	screen->CloseScreen = intel->CloseScreen;
119003b705cfSriastradh	(*screen->CloseScreen) (CLOSE_SCREEN_ARGS);
119103b705cfSriastradh
119242542f5fSchristos	if (intel->dri2 == DRI_ACTIVE) {
119303b705cfSriastradh		I830DRI2CloseScreen(screen);
119442542f5fSchristos		intel->dri2 = DRI_NONE;
119503b705cfSriastradh	}
119603b705cfSriastradh
119742542f5fSchristos	if (intel->dri3 == DRI_ACTIVE) {
119842542f5fSchristos		/* nothing to do here? */
119942542f5fSchristos		intel->dri3 = DRI_NONE;
120042542f5fSchristos	}
120142542f5fSchristos
120242542f5fSchristos	intel_sync_close(screen);
120342542f5fSchristos
120403b705cfSriastradh	scrn->vtSema = FALSE;
120503b705cfSriastradh	return TRUE;
120603b705cfSriastradh}
120703b705cfSriastradh
120803b705cfSriastradhstatic ModeStatus
120903b705cfSriastradhI830ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
121003b705cfSriastradh{
121103b705cfSriastradh	SCRN_INFO_PTR(arg);
121203b705cfSriastradh	if (mode->Flags & V_INTERLACE) {
121303b705cfSriastradh		if (verbose) {
121403b705cfSriastradh			xf86DrvMsg(scrn->scrnIndex, X_PROBED,
121503b705cfSriastradh				   "Removing interlaced mode \"%s\"\n",
121603b705cfSriastradh				   mode->name);
121703b705cfSriastradh		}
121803b705cfSriastradh		return MODE_BAD;
121903b705cfSriastradh	}
122003b705cfSriastradh	return MODE_OK;
122103b705cfSriastradh}
122203b705cfSriastradh
122303b705cfSriastradh#ifndef SUSPEND_SLEEP
122403b705cfSriastradh#define SUSPEND_SLEEP 0
122503b705cfSriastradh#endif
122603b705cfSriastradh#ifndef RESUME_SLEEP
122703b705cfSriastradh#define RESUME_SLEEP 0
122803b705cfSriastradh#endif
122903b705cfSriastradh
123003b705cfSriastradh/*
123103b705cfSriastradh * This function is only required if we need to do anything differently from
123203b705cfSriastradh * DoApmEvent() in common/xf86PM.c, including if we want to see events other
123303b705cfSriastradh * than suspend/resume.
123403b705cfSriastradh */
123503b705cfSriastradhstatic Bool I830PMEvent(SCRN_ARG_TYPE arg, pmEvent event, Bool undo)
123603b705cfSriastradh{
123703b705cfSriastradh	SCRN_INFO_PTR(arg);
123803b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
123903b705cfSriastradh
124003b705cfSriastradh	switch (event) {
124103b705cfSriastradh	case XF86_APM_SYS_SUSPEND:
124203b705cfSriastradh	case XF86_APM_CRITICAL_SUSPEND:	/*do we want to delay a critical suspend? */
124303b705cfSriastradh	case XF86_APM_USER_SUSPEND:
124403b705cfSriastradh	case XF86_APM_SYS_STANDBY:
124503b705cfSriastradh	case XF86_APM_USER_STANDBY:
124603b705cfSriastradh		if (!undo && !intel->suspended) {
124703b705cfSriastradh			scrn->LeaveVT(VT_FUNC_ARGS(0));
124803b705cfSriastradh			intel->suspended = TRUE;
124903b705cfSriastradh			sleep(SUSPEND_SLEEP);
125003b705cfSriastradh		} else if (undo && intel->suspended) {
125103b705cfSriastradh			sleep(RESUME_SLEEP);
125203b705cfSriastradh			scrn->EnterVT(VT_FUNC_ARGS(0));
125303b705cfSriastradh			intel->suspended = FALSE;
125403b705cfSriastradh		}
125503b705cfSriastradh		break;
125603b705cfSriastradh	case XF86_APM_STANDBY_RESUME:
125703b705cfSriastradh	case XF86_APM_NORMAL_RESUME:
125803b705cfSriastradh	case XF86_APM_CRITICAL_RESUME:
125903b705cfSriastradh		if (intel->suspended) {
126003b705cfSriastradh			sleep(RESUME_SLEEP);
126103b705cfSriastradh			scrn->EnterVT(VT_FUNC_ARGS(0));
126203b705cfSriastradh			intel->suspended = FALSE;
126303b705cfSriastradh			/*
126403b705cfSriastradh			 * Turn the screen saver off when resuming.  This seems to be
126503b705cfSriastradh			 * needed to stop xscreensaver kicking in (when used).
126603b705cfSriastradh			 *
126703b705cfSriastradh			 * XXX DoApmEvent() should probably call this just like
126803b705cfSriastradh			 * xf86VTSwitch() does.  Maybe do it here only in 4.2
126903b705cfSriastradh			 * compatibility mode.
127003b705cfSriastradh			 */
127103b705cfSriastradh			SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
127203b705cfSriastradh		}
127303b705cfSriastradh		break;
127403b705cfSriastradh		/* This is currently used for ACPI */
127503b705cfSriastradh	case XF86_APM_CAPABILITY_CHANGED:
127603b705cfSriastradh		ErrorF("I830PMEvent: Capability change\n");
127703b705cfSriastradh
127803b705cfSriastradh		SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
127903b705cfSriastradh
128003b705cfSriastradh		break;
128103b705cfSriastradh	default:
128203b705cfSriastradh		ErrorF("I830PMEvent: received APM event %d\n", event);
128303b705cfSriastradh	}
128403b705cfSriastradh	return TRUE;
128503b705cfSriastradh}
128603b705cfSriastradh
128703b705cfSriastradhBool intel_init_scrn(ScrnInfoPtr scrn)
128803b705cfSriastradh{
128903b705cfSriastradh	scrn->PreInit = I830PreInit;
129003b705cfSriastradh	scrn->ScreenInit = I830ScreenInit;
129103b705cfSriastradh	scrn->SwitchMode = I830SwitchMode;
129203b705cfSriastradh	scrn->AdjustFrame = i830AdjustFrame;
129303b705cfSriastradh	scrn->EnterVT = I830EnterVT;
129403b705cfSriastradh	scrn->LeaveVT = I830LeaveVT;
129503b705cfSriastradh	scrn->FreeScreen = I830FreeScreen;
129603b705cfSriastradh	scrn->ValidMode = I830ValidMode;
129703b705cfSriastradh	scrn->PMEvent = I830PMEvent;
129803b705cfSriastradh	return TRUE;
129903b705cfSriastradh}
1300