sna_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
4803b705cfSriastradh#include "sna.h"
4903b705cfSriastradh#include "sna_module.h"
5003b705cfSriastradh#include "sna_video.h"
5103b705cfSriastradh
5203b705cfSriastradh#include "intel_driver.h"
5303b705cfSriastradh#include "intel_options.h"
5403b705cfSriastradh
5542542f5fSchristos#include <xf86cmap.h>
5642542f5fSchristos#include <xf86drm.h>
5742542f5fSchristos#include <xf86RandR12.h>
5842542f5fSchristos#include <mi.h>
5942542f5fSchristos#include <micmap.h>
6042542f5fSchristos
6103b705cfSriastradh#include <sys/ioctl.h>
6203b705cfSriastradh#include <sys/fcntl.h>
6303b705cfSriastradh#include "i915_drm.h"
6403b705cfSriastradh
6503b705cfSriastradh#ifdef HAVE_VALGRIND
6603b705cfSriastradh#include <valgrind.h>
6703b705cfSriastradh#include <memcheck.h>
6803b705cfSriastradh#endif
6903b705cfSriastradh
7003b705cfSriastradh#if HAVE_DOT_GIT
7103b705cfSriastradh#include "git_version.h"
7203b705cfSriastradh#endif
7303b705cfSriastradh
7442542f5fSchristos#ifdef TEARFREE
7542542f5fSchristos#define ENABLE_TEAR_FREE TRUE
7642542f5fSchristos#else
7742542f5fSchristos#define ENABLE_TEAR_FREE FALSE
7842542f5fSchristos#endif
7942542f5fSchristos
8003b705cfSriastradhDevPrivateKeyRec sna_pixmap_key;
8103b705cfSriastradhDevPrivateKeyRec sna_gc_key;
8203b705cfSriastradhDevPrivateKeyRec sna_window_key;
8303b705cfSriastradhDevPrivateKeyRec sna_glyph_key;
8403b705cfSriastradhDevPrivateKeyRec sna_client_key;
8503b705cfSriastradh
8603b705cfSriastradhstatic void
8703b705cfSriastradhsna_load_palette(ScrnInfoPtr scrn, int numColors, int *indices,
8803b705cfSriastradh		 LOCO * colors, VisualPtr pVisual)
8903b705cfSriastradh{
9003b705cfSriastradh	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
9142542f5fSchristos	int p, n, i, j;
9203b705cfSriastradh	uint16_t lut_r[256], lut_g[256], lut_b[256];
9303b705cfSriastradh
9403b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
9503b705cfSriastradh
9603b705cfSriastradh	for (p = 0; p < xf86_config->num_crtc; p++) {
9703b705cfSriastradh		xf86CrtcPtr crtc = xf86_config->crtc[p];
9803b705cfSriastradh
9942542f5fSchristos#define C(I,RGB) (colors[I].RGB << 8 | colors[I].RGB)
10003b705cfSriastradh		switch (scrn->depth) {
10103b705cfSriastradh		case 15:
10242542f5fSchristos			for (n = 0; n < numColors; n++) {
10342542f5fSchristos				i = indices[n];
10403b705cfSriastradh				for (j = 0; j < 8; j++) {
10542542f5fSchristos					lut_r[8*i + j] = C(i, red);
10642542f5fSchristos					lut_g[8*i + j] = C(i, green);
10742542f5fSchristos					lut_b[8*i + j] = C(i, blue);
10803b705cfSriastradh				}
10903b705cfSriastradh			}
11003b705cfSriastradh			break;
11103b705cfSriastradh		case 16:
11242542f5fSchristos			for (n = 0; n < numColors; n++) {
11342542f5fSchristos				i = indices[n];
11403b705cfSriastradh
11542542f5fSchristos				if (i <= 31) {
11603b705cfSriastradh					for (j = 0; j < 8; j++) {
11742542f5fSchristos						lut_r[8*i + j] = C(i, red);
11842542f5fSchristos						lut_b[8*i + j] = C(i, blue);
11903b705cfSriastradh					}
12003b705cfSriastradh				}
12103b705cfSriastradh
12242542f5fSchristos				for (j = 0; j < 4; j++)
12342542f5fSchristos					lut_g[4*i + j] = C(i, green);
12403b705cfSriastradh			}
12503b705cfSriastradh			break;
12603b705cfSriastradh		default:
12742542f5fSchristos			for (n = 0; n < numColors; n++) {
12842542f5fSchristos				i = indices[n];
12942542f5fSchristos				lut_r[i] = C(i, red);
13042542f5fSchristos				lut_g[i] = C(i, green);
13142542f5fSchristos				lut_b[i] = C(i, blue);
13203b705cfSriastradh			}
13303b705cfSriastradh			break;
13403b705cfSriastradh		}
13542542f5fSchristos#undef C
13603b705cfSriastradh
13703b705cfSriastradh		/* Make the change through RandR */
13803b705cfSriastradh#ifdef RANDR_12_INTERFACE
13903b705cfSriastradh		RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
14003b705cfSriastradh#else
14103b705cfSriastradh		crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
14203b705cfSriastradh#endif
14303b705cfSriastradh	}
14403b705cfSriastradh}
14503b705cfSriastradh
14603b705cfSriastradhstatic void
14703b705cfSriastradhsna_set_fallback_mode(ScrnInfoPtr scrn)
14803b705cfSriastradh{
14903b705cfSriastradh	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
15003b705cfSriastradh	xf86OutputPtr output = NULL;
15103b705cfSriastradh	xf86CrtcPtr crtc = NULL;
15203b705cfSriastradh	int n;
15303b705cfSriastradh
15403b705cfSriastradh	if ((unsigned)config->compat_output < config->num_output) {
15503b705cfSriastradh		output = config->output[config->compat_output];
15603b705cfSriastradh		crtc = output->crtc;
15703b705cfSriastradh	}
15803b705cfSriastradh
15903b705cfSriastradh	for (n = 0; n < config->num_output; n++)
16003b705cfSriastradh		config->output[n]->crtc = NULL;
16103b705cfSriastradh	for (n = 0; n < config->num_crtc; n++)
16203b705cfSriastradh		config->crtc[n]->enabled = FALSE;
16303b705cfSriastradh
16403b705cfSriastradh	if (output && crtc) {
16503b705cfSriastradh		DisplayModePtr mode;
16603b705cfSriastradh
16703b705cfSriastradh		output->crtc = crtc;
16803b705cfSriastradh
16903b705cfSriastradh		mode = xf86OutputFindClosestMode(output, scrn->currentMode);
17003b705cfSriastradh		if (mode &&
17103b705cfSriastradh		    xf86CrtcSetModeTransform(crtc, mode, RR_Rotate_0, NULL, 0, 0)) {
17203b705cfSriastradh			crtc->desiredMode = *mode;
17303b705cfSriastradh			crtc->desiredMode.prev = crtc->desiredMode.next = NULL;
17403b705cfSriastradh			crtc->desiredMode.name = NULL;
17503b705cfSriastradh			crtc->desiredMode.PrivSize = 0;
17603b705cfSriastradh			crtc->desiredMode.PrivFlags = 0;
17703b705cfSriastradh			crtc->desiredMode.Private = NULL;
17803b705cfSriastradh			crtc->desiredRotation = RR_Rotate_0;
17903b705cfSriastradh			crtc->desiredTransformPresent = FALSE;
18003b705cfSriastradh			crtc->desiredX = 0;
18103b705cfSriastradh			crtc->desiredY = 0;
18203b705cfSriastradh			crtc->enabled = TRUE;
18303b705cfSriastradh		}
18403b705cfSriastradh	}
18503b705cfSriastradh
18603b705cfSriastradh	xf86DisableUnusedFunctions(scrn);
18703b705cfSriastradh#ifdef RANDR_12_INTERFACE
18803b705cfSriastradh	if (get_root_window(scrn->pScreen))
18903b705cfSriastradh		xf86RandR12TellChanged(scrn->pScreen);
19003b705cfSriastradh#endif
19103b705cfSriastradh}
19203b705cfSriastradh
19342542f5fSchristosstatic Bool sna_set_desired_mode(struct sna *sna)
19403b705cfSriastradh{
19503b705cfSriastradh	ScrnInfoPtr scrn = sna->scrn;
19603b705cfSriastradh
19703b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
19803b705cfSriastradh
19903b705cfSriastradh	if (!xf86SetDesiredModes(scrn)) {
20003b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
20103b705cfSriastradh			   "failed to restore desired modes on VT switch\n");
20203b705cfSriastradh		sna_set_fallback_mode(scrn);
20303b705cfSriastradh	}
20403b705cfSriastradh
20542542f5fSchristos	sna_mode_check(sna);
20603b705cfSriastradh	return TRUE;
20703b705cfSriastradh}
20803b705cfSriastradh
20903b705cfSriastradh/**
21003b705cfSriastradh * Adjust the screen pixmap for the current location of the front buffer.
21103b705cfSriastradh * This is done at EnterVT when buffers are bound as long as the resources
21203b705cfSriastradh * have already been created, but the first EnterVT happens before
21303b705cfSriastradh * CreateScreenResources.
21403b705cfSriastradh */
21503b705cfSriastradhstatic Bool sna_create_screen_resources(ScreenPtr screen)
21603b705cfSriastradh{
21703b705cfSriastradh	struct sna *sna = to_sna_from_screen(screen);
21842542f5fSchristos	PixmapPtr new_front;
21942542f5fSchristos	unsigned hint;
22003b705cfSriastradh
22103b705cfSriastradh	DBG(("%s(%dx%d@%d)\n", __FUNCTION__,
22203b705cfSriastradh	     screen->width, screen->height, screen->rootDepth));
22303b705cfSriastradh
22403b705cfSriastradh	assert(sna->scrn == xf86ScreenToScrn(screen));
22503b705cfSriastradh	assert(sna->scrn->pScreen == screen);
22603b705cfSriastradh
22742542f5fSchristos	/* free the data used during miInitScreen */
22803b705cfSriastradh	free(screen->devPrivate);
22903b705cfSriastradh	screen->devPrivate = NULL;
23003b705cfSriastradh
23103b705cfSriastradh	sna_accel_create(sna);
23203b705cfSriastradh
23342542f5fSchristos	hint = SNA_CREATE_FB;
23442542f5fSchristos	if (sna->flags & SNA_IS_HOSTED)
23542542f5fSchristos		hint = 0;
23642542f5fSchristos
23742542f5fSchristos	new_front = screen->CreatePixmap(screen,
23842542f5fSchristos					 screen->width,
23942542f5fSchristos					 screen->height,
24042542f5fSchristos					 screen->rootDepth,
24142542f5fSchristos					 hint);
24242542f5fSchristos	if (!new_front) {
24303b705cfSriastradh		xf86DrvMsg(screen->myNum, X_ERROR,
24403b705cfSriastradh			   "[intel] Unable to create front buffer %dx%d at depth %d\n",
24503b705cfSriastradh			   screen->width,
24603b705cfSriastradh			   screen->height,
24703b705cfSriastradh			   screen->rootDepth);
24803b705cfSriastradh
24903b705cfSriastradh		return FALSE;
25003b705cfSriastradh	}
25103b705cfSriastradh
25242542f5fSchristos	if (!sna_pixmap_force_to_gpu(new_front, MOVE_READ)) {
25303b705cfSriastradh		xf86DrvMsg(screen->myNum, X_ERROR,
25403b705cfSriastradh			   "[intel] Failed to allocate video resources for front buffer %dx%d at depth %d\n",
25503b705cfSriastradh			   screen->width,
25603b705cfSriastradh			   screen->height,
25703b705cfSriastradh			   screen->rootDepth);
25842542f5fSchristos		screen->DestroyPixmap(new_front);
25942542f5fSchristos		return FALSE;
26003b705cfSriastradh	}
26103b705cfSriastradh
26242542f5fSchristos	screen->SetScreenPixmap(new_front);
26342542f5fSchristos	assert(screen->GetScreenPixmap(screen) == new_front);
26442542f5fSchristos	assert(sna->front == new_front);
26542542f5fSchristos	screen->DestroyPixmap(new_front); /* transfer ownership to screen */
26642542f5fSchristos
26742542f5fSchristos	if (intel_get_master(sna->scrn)) {
26842542f5fSchristos		xf86DrvMsg(screen->myNum, X_ERROR,
26942542f5fSchristos			   "[intel] Failed to become DRM master\n");
27042542f5fSchristos		screen->DestroyPixmap(sna->front);
27142542f5fSchristos		sna->front = NULL;
27242542f5fSchristos		return FALSE;
27342542f5fSchristos	}
27442542f5fSchristos
27542542f5fSchristos	sna_mode_set_primary(sna);
27603b705cfSriastradh
27703b705cfSriastradh	/* Only preserve the fbcon, not any subsequent server regens */
27842542f5fSchristos	if (serverGeneration == 1 && (sna->flags & SNA_IS_HOSTED) == 0)
27903b705cfSriastradh		sna_copy_fbcon(sna);
28003b705cfSriastradh
28142542f5fSchristos	if (!sna_set_desired_mode(sna)) {
28203b705cfSriastradh		xf86DrvMsg(screen->myNum, X_ERROR,
28342542f5fSchristos			   "[intel] Failed to set initial mode\n");
28442542f5fSchristos		screen->DestroyPixmap(sna->front);
28542542f5fSchristos		sna->front = NULL;
28642542f5fSchristos		return FALSE;
28703b705cfSriastradh	}
28803b705cfSriastradh
28903b705cfSriastradh	return TRUE;
29003b705cfSriastradh}
29103b705cfSriastradh
29242542f5fSchristosstatic Bool sna_save_screen(ScreenPtr screen, int mode)
29303b705cfSriastradh{
29442542f5fSchristos	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
29542542f5fSchristos
29642542f5fSchristos	DBG(("%s(mode=%d)\n", __FUNCTION__, mode));
29742542f5fSchristos	if (!scrn->vtSema)
29842542f5fSchristos		return FALSE;
29942542f5fSchristos
30042542f5fSchristos	xf86SaveScreen(screen, mode);
30142542f5fSchristos	sna_crtc_config_notify(screen);
30242542f5fSchristos	return TRUE;
30303b705cfSriastradh}
30403b705cfSriastradh
30542542f5fSchristosstatic void sna_dpms_set(ScrnInfoPtr scrn, int mode, int flags)
30603b705cfSriastradh{
30742542f5fSchristos	DBG(("%s(mode=%d, flags=%d)\n", __FUNCTION__, mode));
30842542f5fSchristos	if (!scrn->vtSema)
30942542f5fSchristos		return;
31003b705cfSriastradh
31142542f5fSchristos	xf86DPMSSet(scrn, mode, flags);
31242542f5fSchristos	sna_crtc_config_notify(xf86ScrnToScreen(scrn));
31342542f5fSchristos}
31403b705cfSriastradh
31542542f5fSchristosstatic void sna_selftest(void)
31642542f5fSchristos{
31742542f5fSchristos	sna_damage_selftest();
31842542f5fSchristos}
31903b705cfSriastradh
32042542f5fSchristosstatic bool has_vsync(struct sna *sna)
32142542f5fSchristos{
32242542f5fSchristos	if (sna->flags & SNA_IS_HOSTED)
32303b705cfSriastradh		return false;
32403b705cfSriastradh
32542542f5fSchristos	return true;
32603b705cfSriastradh}
32703b705cfSriastradh
32803b705cfSriastradhstatic void sna_setup_capabilities(ScrnInfoPtr scrn, int fd)
32903b705cfSriastradh{
33003b705cfSriastradh#if HAS_PIXMAP_SHARING && defined(DRM_CAP_PRIME)
33103b705cfSriastradh	uint64_t value;
33203b705cfSriastradh
33303b705cfSriastradh	scrn->capabilities = 0;
33403b705cfSriastradh	if (drmGetCap(fd, DRM_CAP_PRIME, &value) == 0) {
33503b705cfSriastradh		if (value & DRM_PRIME_CAP_EXPORT)
33603b705cfSriastradh			scrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload;
33703b705cfSriastradh		if (value & DRM_PRIME_CAP_IMPORT)
33803b705cfSriastradh			scrn->capabilities |= RR_Capability_SinkOutput;
33903b705cfSriastradh	}
34003b705cfSriastradh#endif
34103b705cfSriastradh}
34203b705cfSriastradh
34342542f5fSchristosstatic int
34442542f5fSchristosnamecmp(const char *s1, const char *s2)
34542542f5fSchristos{
34642542f5fSchristos	char c1, c2;
34742542f5fSchristos
34842542f5fSchristos	if (!s1 || *s1 == 0) {
34942542f5fSchristos		if (!s2 || *s2 == 0)
35042542f5fSchristos			return 0;
35142542f5fSchristos		else
35242542f5fSchristos			return 1;
35342542f5fSchristos	}
35442542f5fSchristos
35542542f5fSchristos	while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
35642542f5fSchristos		s1++;
35742542f5fSchristos
35842542f5fSchristos	while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
35942542f5fSchristos		s2++;
36042542f5fSchristos
36142542f5fSchristos	c1 = isupper(*s1) ? tolower(*s1) : *s1;
36242542f5fSchristos	c2 = isupper(*s2) ? tolower(*s2) : *s2;
36342542f5fSchristos	while (c1 == c2) {
36442542f5fSchristos		if (c1 == '\0')
36542542f5fSchristos			return 0;
36642542f5fSchristos
36742542f5fSchristos		s1++;
36842542f5fSchristos		while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
36942542f5fSchristos			s1++;
37042542f5fSchristos
37142542f5fSchristos		s2++;
37242542f5fSchristos		while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
37342542f5fSchristos			s2++;
37442542f5fSchristos
37542542f5fSchristos		c1 = isupper(*s1) ? tolower(*s1) : *s1;
37642542f5fSchristos		c2 = isupper(*s2) ? tolower(*s2) : *s2;
37742542f5fSchristos	}
37842542f5fSchristos
37942542f5fSchristos	return c1 - c2;
38042542f5fSchristos}
38142542f5fSchristos
38203b705cfSriastradhstatic Bool sna_option_cast_to_bool(struct sna *sna, int id, Bool val)
38303b705cfSriastradh{
38442542f5fSchristos	const char *str = xf86GetOptValString(sna->Options, id);
38542542f5fSchristos
38642542f5fSchristos	if (str == NULL)
38742542f5fSchristos		return val;
38842542f5fSchristos
38942542f5fSchristos	if (*str == '\0')
39042542f5fSchristos		return TRUE;
39142542f5fSchristos
39242542f5fSchristos	if (namecmp(str, "1") == 0)
39342542f5fSchristos		return TRUE;
39442542f5fSchristos	if (namecmp(str, "on") == 0)
39542542f5fSchristos		return TRUE;
39642542f5fSchristos	if (namecmp(str, "true") == 0)
39742542f5fSchristos		return TRUE;
39842542f5fSchristos	if (namecmp(str, "yes") == 0)
39942542f5fSchristos		return TRUE;
40042542f5fSchristos
40142542f5fSchristos	if (namecmp(str, "0") == 0)
40242542f5fSchristos		return FALSE;
40342542f5fSchristos	if (namecmp(str, "off") == 0)
40442542f5fSchristos		return FALSE;
40542542f5fSchristos	if (namecmp(str, "false") == 0)
40642542f5fSchristos		return FALSE;
40742542f5fSchristos	if (namecmp(str, "no") == 0)
40842542f5fSchristos		return FALSE;
40942542f5fSchristos
41042542f5fSchristos	return val;
41142542f5fSchristos}
41242542f5fSchristos
41342542f5fSchristosstatic unsigned sna_option_cast_to_unsigned(struct sna *sna, int id, unsigned val)
41442542f5fSchristos{
41542542f5fSchristos	const char *str = xf86GetOptValString(sna->Options, id);
41642542f5fSchristos	unsigned v;
41742542f5fSchristos
41842542f5fSchristos	if (str == NULL || *str == '\0')
41942542f5fSchristos		return val;
42042542f5fSchristos
42142542f5fSchristos	if (namecmp(str, "on") == 0)
42242542f5fSchristos		return val;
42342542f5fSchristos	if (namecmp(str, "true") == 0)
42442542f5fSchristos		return val;
42542542f5fSchristos	if (namecmp(str, "yes") == 0)
42642542f5fSchristos		return val;
42742542f5fSchristos
42842542f5fSchristos	if (namecmp(str, "0") == 0)
42942542f5fSchristos		return 0;
43042542f5fSchristos	if (namecmp(str, "off") == 0)
43142542f5fSchristos		return 0;
43242542f5fSchristos	if (namecmp(str, "false") == 0)
43342542f5fSchristos		return 0;
43442542f5fSchristos	if (namecmp(str, "no") == 0)
43542542f5fSchristos		return 0;
43642542f5fSchristos
43742542f5fSchristos	v = atoi(str);
43842542f5fSchristos	if (v)
43942542f5fSchristos		return v;
44042542f5fSchristos
44103b705cfSriastradh	return val;
44203b705cfSriastradh}
44303b705cfSriastradh
44403b705cfSriastradhstatic Bool fb_supports_depth(int fd, int depth)
44503b705cfSriastradh{
44603b705cfSriastradh	struct drm_i915_gem_create create;
44703b705cfSriastradh	struct drm_mode_fb_cmd fb;
44842542f5fSchristos	struct drm_mode_card_res res;
44903b705cfSriastradh	Bool ret;
45003b705cfSriastradh
45142542f5fSchristos	memset(&res, 0, sizeof(res));
45242542f5fSchristos	(void)drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res);
45342542f5fSchristos	if (res.count_crtcs == 0)
45442542f5fSchristos		return TRUE;
45542542f5fSchristos
45603b705cfSriastradh	VG_CLEAR(create);
45703b705cfSriastradh	create.handle = 0;
45803b705cfSriastradh	create.size = 4096;
45903b705cfSriastradh	if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create))
46003b705cfSriastradh		return FALSE;
46103b705cfSriastradh
46203b705cfSriastradh	VG_CLEAR(fb);
46303b705cfSriastradh	fb.width = 64;
46403b705cfSriastradh	fb.height = 16;
46503b705cfSriastradh	fb.pitch = 256;
46603b705cfSriastradh	fb.bpp = depth <= 8 ? 8 : depth <= 16 ? 16 : 32;
46703b705cfSriastradh	fb.depth = depth;
46803b705cfSriastradh	fb.handle = create.handle;
46903b705cfSriastradh
47003b705cfSriastradh	ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB, &fb) == 0;
47103b705cfSriastradh	drmModeRmFB(fd, fb.fb_id);
47203b705cfSriastradh
47342542f5fSchristos	(void)drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &create.handle);
47403b705cfSriastradh
47503b705cfSriastradh	return ret;
47603b705cfSriastradh}
47703b705cfSriastradh
47842542f5fSchristosstatic void setup_dri(struct sna *sna)
47942542f5fSchristos{
48042542f5fSchristos	unsigned level;
48142542f5fSchristos
48242542f5fSchristos	sna->dri2.available = false;
48342542f5fSchristos	sna->dri3.available = false;
48442542f5fSchristos
48542542f5fSchristos	level = sna_option_cast_to_unsigned(sna, OPTION_DRI, ~0);
48642542f5fSchristos#if HAVE_DRI3
48742542f5fSchristos	if (level >= 3)
48842542f5fSchristos		sna->dri3.available = !!xf86LoadSubModule(sna->scrn, "dri3");
48942542f5fSchristos#endif
49042542f5fSchristos#if HAVE_DRI2
49142542f5fSchristos	if (level >= 2)
49242542f5fSchristos		sna->dri2.available = !!xf86LoadSubModule(sna->scrn, "dri2");
49342542f5fSchristos#endif
49442542f5fSchristos}
49542542f5fSchristos
49642542f5fSchristosstatic bool enable_tear_free(struct sna *sna)
49742542f5fSchristos{
49842542f5fSchristos	if (sna->flags & SNA_LINEAR_FB)
49942542f5fSchristos		return false;
50042542f5fSchristos
50142542f5fSchristos	/* Under certain conditions, we should enable TearFree by default,
50242542f5fSchristos	 * for example when the hardware requires pageflipping to run within
50342542f5fSchristos	 * its power/performance budget.
50442542f5fSchristos	 */
50542542f5fSchristos	if (sna_mode_wants_tear_free(sna))
50642542f5fSchristos		return true;
50742542f5fSchristos
50842542f5fSchristos	return ENABLE_TEAR_FREE;
50942542f5fSchristos}
51042542f5fSchristos
51142542f5fSchristosstatic void setup_tear_free(struct sna *sna)
51242542f5fSchristos{
51342542f5fSchristos	MessageType from;
51442542f5fSchristos	Bool enable;
51542542f5fSchristos
51642542f5fSchristos	if (sna->flags & SNA_LINEAR_FB)
51742542f5fSchristos		return;
51842542f5fSchristos
51942542f5fSchristos	if ((sna->flags & SNA_HAS_FLIP) == 0) {
52042542f5fSchristos		from = X_PROBED;
52142542f5fSchristos		goto done;
52242542f5fSchristos	}
52342542f5fSchristos
52442542f5fSchristos	if (!xf86GetOptValBool(sna->Options, OPTION_TEAR_FREE, &enable)) {
52542542f5fSchristos		enable = enable_tear_free(sna);
52642542f5fSchristos		from = X_DEFAULT;
52742542f5fSchristos	} else
52842542f5fSchristos		from = X_CONFIG;
52942542f5fSchristos
53042542f5fSchristos	if (enable)
53142542f5fSchristos		sna->flags |= SNA_TEAR_FREE;
53242542f5fSchristos
53342542f5fSchristosdone:
53442542f5fSchristos	xf86DrvMsg(sna->scrn->scrnIndex, from, "TearFree %sabled\n",
53542542f5fSchristos		   sna->flags & SNA_TEAR_FREE ? "en" : "dis");
53642542f5fSchristos}
53742542f5fSchristos
53803b705cfSriastradh/**
53903b705cfSriastradh * This is called before ScreenInit to do any require probing of screen
54003b705cfSriastradh * configuration.
54103b705cfSriastradh *
54203b705cfSriastradh * This code generally covers probing, module loading, option handling
54303b705cfSriastradh * card mapping, and RandR setup.
54403b705cfSriastradh *
54503b705cfSriastradh * Since xf86InitialConfiguration ends up requiring that we set video modes
54603b705cfSriastradh * in order to detect configuration, we end up having to do a lot of driver
54703b705cfSriastradh * setup (talking to the DRM, mapping the device, etc.) in this function.
54803b705cfSriastradh * As a result, we want to set up that server initialization once rather
54903b705cfSriastradh * that doing it per generation.
55003b705cfSriastradh */
55142542f5fSchristosstatic Bool sna_pre_init(ScrnInfoPtr scrn, int probe)
55203b705cfSriastradh{
55303b705cfSriastradh	struct sna *sna;
55403b705cfSriastradh	char buf[1024];
55503b705cfSriastradh	rgb defaultWeight = { 0, 0, 0 };
55603b705cfSriastradh	EntityInfoPtr pEnt;
55703b705cfSriastradh	Gamma zeros = { 0.0, 0.0, 0.0 };
55803b705cfSriastradh	int fd;
55903b705cfSriastradh
56003b705cfSriastradh	DBG(("%s flags=%x, numEntities=%d\n",
56142542f5fSchristos	     __FUNCTION__, probe, scrn->numEntities));
56203b705cfSriastradh
56303b705cfSriastradh	if (scrn->numEntities != 1)
56403b705cfSriastradh		return FALSE;
56503b705cfSriastradh
56603b705cfSriastradh	pEnt = xf86GetEntityInfo(scrn->entityList[0]);
56742542f5fSchristos	if (pEnt == NULL) {
56842542f5fSchristos		ERR(("%s: no EntityInfo found for scrn\n", __FUNCTION__));
56903b705cfSriastradh		return FALSE;
57042542f5fSchristos	}
57103b705cfSriastradh
57203b705cfSriastradh	if (pEnt->location.type != BUS_PCI
57303b705cfSriastradh#ifdef XSERVER_PLATFORM_BUS
57403b705cfSriastradh	    && pEnt->location.type != BUS_PLATFORM
57503b705cfSriastradh#endif
57642542f5fSchristos		) {
57742542f5fSchristos		ERR(("%s: invalid EntityInfo found for scrn, location=%d\n", __FUNCTION__, pEnt->location.type));
57803b705cfSriastradh		return FALSE;
57942542f5fSchristos	}
58003b705cfSriastradh
58142542f5fSchristos	if (probe & PROBE_DETECT)
58203b705cfSriastradh		return TRUE;
58303b705cfSriastradh
58403b705cfSriastradh	sna_selftest();
58503b705cfSriastradh
58642542f5fSchristos	probe = 0;
58742542f5fSchristos	if (((uintptr_t)scrn->driverPrivate) & 3) {
58803b705cfSriastradh		if (posix_memalign((void **)&sna, 4096, sizeof(*sna)))
58903b705cfSriastradh			return FALSE;
59003b705cfSriastradh
59103b705cfSriastradh		memset(sna, 0, sizeof(*sna)); /* should be unnecessary */
59242542f5fSchristos		probe = (uintptr_t)scrn->driverPrivate & 1;
59342542f5fSchristos		sna->info = (void *)((uintptr_t)scrn->driverPrivate & ~3);
59403b705cfSriastradh		scrn->driverPrivate = sna;
59503b705cfSriastradh
59603b705cfSriastradh		sna->cpu_features = sna_cpu_detect();
59742542f5fSchristos		sna->acpi.fd = sna_acpi_open();
59803b705cfSriastradh	}
59903b705cfSriastradh	sna = to_sna(scrn);
60003b705cfSriastradh	sna->scrn = scrn;
60103b705cfSriastradh	sna->pEnt = pEnt;
60242542f5fSchristos	sna->flags = probe;
60303b705cfSriastradh
60403b705cfSriastradh	scrn->displayWidth = 640;	/* default it */
60503b705cfSriastradh
60603b705cfSriastradh	scrn->monitor = scrn->confScreen->monitor;
60703b705cfSriastradh	scrn->progClock = TRUE;
60803b705cfSriastradh	scrn->rgbBits = 8;
60903b705cfSriastradh
61003b705cfSriastradh	fd = intel_get_device(scrn);
61103b705cfSriastradh	if (fd == -1) {
61203b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
61303b705cfSriastradh			   "Failed to claim DRM device.\n");
61403b705cfSriastradh		goto cleanup;
61503b705cfSriastradh	}
61603b705cfSriastradh
61703b705cfSriastradh	/* Sanity check */
61803b705cfSriastradh	if (hosted() && (sna->flags & SNA_IS_HOSTED) == 0) {
61903b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
62003b705cfSriastradh			   "Failed to setup hosted device.\n");
62103b705cfSriastradh		goto cleanup;
62203b705cfSriastradh	}
62303b705cfSriastradh
62442542f5fSchristos	intel_detect_chipset(scrn, pEnt);
62542542f5fSchristos	xf86DrvMsg(scrn->scrnIndex, X_PROBED, "CPU: %s\n",
62642542f5fSchristos		   sna_cpu_features_to_string(sna->cpu_features, buf));
62703b705cfSriastradh
62842542f5fSchristos	if (!xf86SetDepthBpp(scrn, 24, 0, 0,
62903b705cfSriastradh			     Support32bppFb |
63003b705cfSriastradh			     SupportConvert24to32 | PreferConvert24to32))
63103b705cfSriastradh		goto cleanup;
63203b705cfSriastradh
63303b705cfSriastradh	switch (scrn->depth) {
63403b705cfSriastradh	case 8:
63503b705cfSriastradh	case 15:
63603b705cfSriastradh	case 16:
63703b705cfSriastradh	case 24:
63803b705cfSriastradh	case 30:
63942542f5fSchristos		if ((sna->flags & SNA_IS_HOSTED) ||
64042542f5fSchristos		    fb_supports_depth(fd, scrn->depth))
64103b705cfSriastradh			break;
64203b705cfSriastradh	default:
64303b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
64403b705cfSriastradh			   "Given depth (%d) is not supported by the Intel driver and this chipset.\n",
64503b705cfSriastradh			   scrn->depth);
64603b705cfSriastradh		goto cleanup;
64703b705cfSriastradh	}
64803b705cfSriastradh	xf86PrintDepthBpp(scrn);
64903b705cfSriastradh
65003b705cfSriastradh	if (!xf86SetWeight(scrn, defaultWeight, defaultWeight))
65103b705cfSriastradh		goto cleanup;
65203b705cfSriastradh	if (!xf86SetDefaultVisual(scrn, -1))
65303b705cfSriastradh		goto cleanup;
65403b705cfSriastradh
65503b705cfSriastradh	sna->Options = intel_options_get(scrn);
65603b705cfSriastradh	if (sna->Options == NULL)
65703b705cfSriastradh		goto cleanup;
65803b705cfSriastradh
65903b705cfSriastradh	sna_setup_capabilities(scrn, fd);
66003b705cfSriastradh
66142542f5fSchristos	kgem_init(&sna->kgem, fd,
66242542f5fSchristos		  xf86GetPciInfoForEntity(pEnt->index),
66342542f5fSchristos		  sna->info->gen);
66403b705cfSriastradh	if (xf86ReturnOptValBool(sna->Options, OPTION_ACCEL_DISABLE, FALSE) ||
66503b705cfSriastradh	    !sna_option_cast_to_bool(sna, OPTION_ACCEL_METHOD, TRUE)) {
66603b705cfSriastradh		xf86DrvMsg(sna->scrn->scrnIndex, X_CONFIG,
66703b705cfSriastradh			   "Disabling hardware acceleration.\n");
66803b705cfSriastradh		sna->kgem.wedged = true;
66903b705cfSriastradh	}
67003b705cfSriastradh
67103b705cfSriastradh	if (xf86ReturnOptValBool(sna->Options, OPTION_TILING_FB, FALSE))
67242542f5fSchristos		sna->flags |= SNA_LINEAR_FB;
67342542f5fSchristos
67442542f5fSchristos	if (xf86ReturnOptValBool(sna->Options, OPTION_DELETE_DP12, FALSE))
67542542f5fSchristos		sna->flags |= SNA_REMOVE_OUTPUTS;
67603b705cfSriastradh
67703b705cfSriastradh	if (!xf86ReturnOptValBool(sna->Options, OPTION_SWAPBUFFERS_WAIT, TRUE))
67803b705cfSriastradh		sna->flags |= SNA_NO_WAIT;
67942542f5fSchristos	DBG(("%s: swapbuffer wait? %s\n", __FUNCTION__, sna->flags & SNA_NO_WAIT ? "disabled" : "enabled"));
68042542f5fSchristos
68142542f5fSchristos	if (!has_vsync(sna) ||
68242542f5fSchristos	    !xf86ReturnOptValBool(sna->Options, OPTION_VSYNC, TRUE))
68342542f5fSchristos		sna->flags |= SNA_NO_VSYNC;
68442542f5fSchristos	DBG(("%s: vsync? %s\n", __FUNCTION__, sna->flags & SNA_NO_VSYNC ? "disabled" : "enabled"));
68542542f5fSchristos
68642542f5fSchristos	if (sna->flags & SNA_IS_HOSTED ||
68742542f5fSchristos	    !xf86ReturnOptValBool(sna->Options, OPTION_PAGEFLIP, TRUE))
68803b705cfSriastradh		sna->flags |= SNA_NO_FLIP;
68942542f5fSchristos	DBG(("%s: page flips? %s\n", __FUNCTION__, sna->flags & SNA_NO_FLIP ? "disabled" : "enabled"));
69003b705cfSriastradh
69142542f5fSchristos	if ((sna->flags & (SNA_NO_VSYNC | SNA_NO_FLIP | SNA_NO_WAIT)) == 0 &&
69242542f5fSchristos	    xf86ReturnOptValBool(sna->Options, OPTION_TRIPLE_BUFFER, TRUE))
69342542f5fSchristos		sna->flags |= SNA_TRIPLE_BUFFER;
69442542f5fSchristos	DBG(("%s: triple buffer? %s\n", __FUNCTION__, sna->flags & SNA_TRIPLE_BUFFER ? "enabled" : "disabled"));
69503b705cfSriastradh
69642542f5fSchristos	if (xf86ReturnOptValBool(sna->Options, OPTION_CRTC_PIXMAPS, FALSE)) {
69742542f5fSchristos		xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Forcing per-crtc-pixmaps.\n");
69842542f5fSchristos		sna->flags |= SNA_FORCE_SHADOW;
69942542f5fSchristos	}
70003b705cfSriastradh
70103b705cfSriastradh	if (!sna_mode_pre_init(scrn, sna)) {
70203b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
70303b705cfSriastradh			   "No outputs and no modes.\n");
70403b705cfSriastradh		goto cleanup;
70503b705cfSriastradh	}
70603b705cfSriastradh	scrn->currentMode = scrn->modes;
70703b705cfSriastradh
70842542f5fSchristos	setup_tear_free(sna);
70942542f5fSchristos
71003b705cfSriastradh	xf86SetGamma(scrn, zeros);
71103b705cfSriastradh	xf86SetDpi(scrn, 0, 0);
71203b705cfSriastradh
71342542f5fSchristos	setup_dri(sna);
71442542f5fSchristos
71542542f5fSchristos	sna->present.available = false;
71642542f5fSchristos	if (xf86ReturnOptValBool(sna->Options, OPTION_PRESENT, TRUE)) {
71742542f5fSchristos#if HAVE_PRESENT
71842542f5fSchristos		sna->present.available = !!xf86LoadSubModule(scrn, "present");
71942542f5fSchristos#endif
72042542f5fSchristos	}
72142542f5fSchristos
72242542f5fSchristos	sna_acpi_init(sna);
72303b705cfSriastradh
72403b705cfSriastradh	return TRUE;
72503b705cfSriastradh
72603b705cfSriastradhcleanup:
72742542f5fSchristos	scrn->driverPrivate = (void *)((uintptr_t)sna->info | (sna->flags & SNA_IS_SLAVED) | 2);
72803b705cfSriastradh	free(sna);
72903b705cfSriastradh	return FALSE;
73003b705cfSriastradh}
73103b705cfSriastradh
73242542f5fSchristosstatic bool has_shadow(struct sna *sna)
73342542f5fSchristos{
73442542f5fSchristos	if (!sna->mode.shadow_damage)
73542542f5fSchristos		return false;
73642542f5fSchristos
73742542f5fSchristos	if (RegionNil(DamageRegion(sna->mode.shadow_damage)))
73842542f5fSchristos		return false;
73942542f5fSchristos
74042542f5fSchristos	return sna->mode.flip_active == 0;
74142542f5fSchristos}
74242542f5fSchristos
74303b705cfSriastradhstatic void
74403b705cfSriastradhsna_block_handler(BLOCKHANDLER_ARGS_DECL)
74503b705cfSriastradh{
74603b705cfSriastradh#ifndef XF86_SCRN_INTERFACE
74703b705cfSriastradh	struct sna *sna = to_sna(xf86Screens[arg]);
74803b705cfSriastradh#else
74903b705cfSriastradh	struct sna *sna = to_sna_from_screen(arg);
75003b705cfSriastradh#endif
75103b705cfSriastradh	struct timeval **tv = timeout;
75203b705cfSriastradh
75303b705cfSriastradh	DBG(("%s (tv=%ld.%06ld)\n", __FUNCTION__,
75403b705cfSriastradh	     *tv ? (*tv)->tv_sec : -1, *tv ? (*tv)->tv_usec : 0));
75503b705cfSriastradh
75603b705cfSriastradh	sna->BlockHandler(BLOCKHANDLER_ARGS);
75703b705cfSriastradh
75842542f5fSchristos	if (*tv == NULL || ((*tv)->tv_usec | (*tv)->tv_sec) || has_shadow(sna))
75903b705cfSriastradh		sna_accel_block_handler(sna, tv);
76003b705cfSriastradh}
76103b705cfSriastradh
76203b705cfSriastradhstatic void
76303b705cfSriastradhsna_wakeup_handler(WAKEUPHANDLER_ARGS_DECL)
76403b705cfSriastradh{
76503b705cfSriastradh#ifndef XF86_SCRN_INTERFACE
76603b705cfSriastradh	struct sna *sna = to_sna(xf86Screens[arg]);
76703b705cfSriastradh#else
76803b705cfSriastradh	struct sna *sna = to_sna_from_screen(arg);
76903b705cfSriastradh#endif
77003b705cfSriastradh
77103b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
77203b705cfSriastradh
77303b705cfSriastradh	/* despite all appearances, result is just a signed int */
77403b705cfSriastradh	if ((int)result < 0)
77503b705cfSriastradh		return;
77603b705cfSriastradh
77742542f5fSchristos	sna_acpi_wakeup(sna, read_mask);
77842542f5fSchristos
77903b705cfSriastradh	sna->WakeupHandler(WAKEUPHANDLER_ARGS);
78003b705cfSriastradh
78103b705cfSriastradh	sna_accel_wakeup_handler(sna);
78203b705cfSriastradh
78303b705cfSriastradh	if (FD_ISSET(sna->kgem.fd, (fd_set*)read_mask))
78403b705cfSriastradh		sna_mode_wakeup(sna);
78503b705cfSriastradh}
78603b705cfSriastradh
78703b705cfSriastradh#if HAVE_UDEV
78803b705cfSriastradhstatic void
78903b705cfSriastradhsna_handle_uevents(int fd, void *closure)
79003b705cfSriastradh{
79142542f5fSchristos	struct sna *sna = closure;
79203b705cfSriastradh	struct udev_device *dev;
79342542f5fSchristos	const char *str;
79403b705cfSriastradh	struct stat s;
79503b705cfSriastradh	dev_t udev_devnum;
79603b705cfSriastradh
79703b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
79803b705cfSriastradh
79903b705cfSriastradh	dev = udev_monitor_receive_device(sna->uevent_monitor);
80003b705cfSriastradh	if (!dev)
80103b705cfSriastradh		return;
80203b705cfSriastradh
80303b705cfSriastradh	udev_devnum = udev_device_get_devnum(dev);
80442542f5fSchristos	if (fstat(sna->kgem.fd, &s) || memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t))) {
80503b705cfSriastradh		udev_device_unref(dev);
80603b705cfSriastradh		return;
80703b705cfSriastradh	}
80803b705cfSriastradh
80942542f5fSchristos	str = udev_device_get_property_value(dev, "HOTPLUG");
81042542f5fSchristos	if (str && atoi(str) == 1) {
81142542f5fSchristos		ScrnInfoPtr scrn = sna->scrn;
81203b705cfSriastradh
81342542f5fSchristos		DBG(("%s: hotplug event (vtSema?=%d)\n", __FUNCTION__, scrn->vtSema));
81403b705cfSriastradh
81542542f5fSchristos		if (scrn->vtSema) {
81642542f5fSchristos			sna_mode_discover(sna);
81742542f5fSchristos			sna_mode_check(sna);
81803b705cfSriastradh			RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
81903b705cfSriastradh		} else
82003b705cfSriastradh			sna->flags |= SNA_REPROBE;
82103b705cfSriastradh	}
82203b705cfSriastradh
82303b705cfSriastradh	udev_device_unref(dev);
82403b705cfSriastradh}
82503b705cfSriastradh
82603b705cfSriastradhstatic void
82742542f5fSchristossna_uevent_init(struct sna *sna)
82803b705cfSriastradh{
82903b705cfSriastradh	struct udev *u;
83003b705cfSriastradh	struct udev_monitor *mon;
83103b705cfSriastradh	MessageType from = X_CONFIG;
83203b705cfSriastradh
83303b705cfSriastradh	if (sna->flags & SNA_IS_HOSTED)
83403b705cfSriastradh		return;
83503b705cfSriastradh
83603b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
83703b705cfSriastradh
83803b705cfSriastradh	/* RandR will be disabled if Xinerama is active, and so generating
83903b705cfSriastradh	 * RR hotplug events is then verboten.
84003b705cfSriastradh	 */
84103b705cfSriastradh	if (!dixPrivateKeyRegistered(rrPrivKey))
84242542f5fSchristos		goto out;
84303b705cfSriastradh
84442542f5fSchristos	u = NULL;
84542542f5fSchristos	if (xf86ReturnOptValBool(sna->Options, OPTION_HOTPLUG, TRUE))
84642542f5fSchristos		u = udev_new();
84703b705cfSriastradh	if (!u)
84842542f5fSchristos		goto out;
84942542f5fSchristos
85042542f5fSchristos	from = X_DEFAULT;
85103b705cfSriastradh
85203b705cfSriastradh	mon = udev_monitor_new_from_netlink(u, "udev");
85342542f5fSchristos	if (!mon)
85442542f5fSchristos		goto err_dev;
85503b705cfSriastradh
85642542f5fSchristos	if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") < 0)
85742542f5fSchristos		goto err_monitor;
85803b705cfSriastradh
85942542f5fSchristos	if (udev_monitor_enable_receiving(mon) < 0)
86042542f5fSchristos		goto err_monitor;
86103b705cfSriastradh
86242542f5fSchristos	sna->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon),
86342542f5fSchristos						    sna_handle_uevents, sna);
86442542f5fSchristos	if (!sna->uevent_handler)
86542542f5fSchristos		goto err_monitor;
86603b705cfSriastradh
86742542f5fSchristos	sna->uevent_monitor = mon;
86842542f5fSchristosout:
86942542f5fSchristos	xf86DrvMsg(sna->scrn->scrnIndex, from, "display hotplug detection %s\n",
87042542f5fSchristos		   sna->uevent_monitor ? "enabled" : "disabled");
87142542f5fSchristos	return;
87242542f5fSchristos
87342542f5fSchristoserr_monitor:
87442542f5fSchristos	udev_monitor_unref(mon);
87542542f5fSchristoserr_dev:
87642542f5fSchristos	udev_unref(u);
87742542f5fSchristos	goto out;
87803b705cfSriastradh}
87903b705cfSriastradh
88003b705cfSriastradhstatic void
88142542f5fSchristossna_uevent_fini(struct sna *sna)
88203b705cfSriastradh{
88303b705cfSriastradh	struct udev *u;
88403b705cfSriastradh
88503b705cfSriastradh	if (sna->uevent_handler == NULL)
88603b705cfSriastradh		return;
88703b705cfSriastradh
88803b705cfSriastradh	xf86RemoveGeneralHandler(sna->uevent_handler);
88903b705cfSriastradh
89003b705cfSriastradh	u = udev_monitor_get_udev(sna->uevent_monitor);
89103b705cfSriastradh	udev_monitor_unref(sna->uevent_monitor);
89203b705cfSriastradh	udev_unref(u);
89303b705cfSriastradh
89403b705cfSriastradh	sna->uevent_handler = NULL;
89503b705cfSriastradh	sna->uevent_monitor = NULL;
89603b705cfSriastradh
89703b705cfSriastradh	DBG(("%s: removed uvent handler\n", __FUNCTION__));
89803b705cfSriastradh}
89903b705cfSriastradh#else
90042542f5fSchristosstatic void sna_uevent_init(struct sna *sna) { }
90142542f5fSchristosstatic void sna_uevent_fini(struct sna *sna) { }
90203b705cfSriastradh#endif /* HAVE_UDEV */
90303b705cfSriastradh
90403b705cfSriastradhstatic void sna_leave_vt(VT_FUNC_ARGS_DECL)
90503b705cfSriastradh{
90603b705cfSriastradh	SCRN_INFO_PTR(arg);
90742542f5fSchristos	struct sna *sna = to_sna(scrn);
90803b705cfSriastradh
90903b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
91003b705cfSriastradh
91142542f5fSchristos	sna_accel_leave(sna);
91242542f5fSchristos	sna_mode_reset(sna);
91303b705cfSriastradh
91403b705cfSriastradh	if (intel_put_master(scrn))
91503b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
91603b705cfSriastradh			   "drmDropMaster failed: %s\n", strerror(errno));
91703b705cfSriastradh}
91803b705cfSriastradh
91903b705cfSriastradhstatic Bool sna_early_close_screen(CLOSE_SCREEN_ARGS_DECL)
92003b705cfSriastradh{
92103b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
92203b705cfSriastradh	struct sna *sna = to_sna(scrn);
92303b705cfSriastradh
92403b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
92503b705cfSriastradh
92603b705cfSriastradh	/* XXX Note that we will leak kernel resources if !vtSema */
92703b705cfSriastradh
92842542f5fSchristos	sna_uevent_fini(sna);
92903b705cfSriastradh	sna_mode_close(sna);
93003b705cfSriastradh
93142542f5fSchristos	if (sna->present.open) {
93242542f5fSchristos		sna_present_close(sna, screen);
93342542f5fSchristos		sna->present.open = false;
93442542f5fSchristos	}
93542542f5fSchristos
93642542f5fSchristos	if (sna->dri3.open) {
93742542f5fSchristos		sna_dri3_close(sna, screen);
93842542f5fSchristos		sna->dri3.open = false;
93942542f5fSchristos	}
94042542f5fSchristos
94142542f5fSchristos	if (sna->dri2.open) {
94242542f5fSchristos		sna_dri2_close(sna, screen);
94342542f5fSchristos		sna->dri2.open = false;
94403b705cfSriastradh	}
94503b705cfSriastradh
94603b705cfSriastradh	if (sna->front) {
94703b705cfSriastradh		screen->DestroyPixmap(sna->front);
94803b705cfSriastradh		sna->front = NULL;
94903b705cfSriastradh	}
95003b705cfSriastradh
95103b705cfSriastradh	if (scrn->vtSema) {
95203b705cfSriastradh		intel_put_master(scrn);
95303b705cfSriastradh		scrn->vtSema = FALSE;
95403b705cfSriastradh	}
95503b705cfSriastradh
95603b705cfSriastradh	return sna->CloseScreen(CLOSE_SCREEN_ARGS);
95703b705cfSriastradh}
95803b705cfSriastradh
95903b705cfSriastradhstatic Bool sna_late_close_screen(CLOSE_SCREEN_ARGS_DECL)
96003b705cfSriastradh{
96103b705cfSriastradh	struct sna *sna = to_sna_from_screen(screen);
96203b705cfSriastradh	DepthPtr depths;
96303b705cfSriastradh	int d;
96403b705cfSriastradh
96503b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
96603b705cfSriastradh
96703b705cfSriastradh	sna_accel_close(sna);
96842542f5fSchristos	sna_video_close(sna);
96903b705cfSriastradh
97003b705cfSriastradh	depths = screen->allowedDepths;
97103b705cfSriastradh	for (d = 0; d < screen->numDepths; d++)
97203b705cfSriastradh		free(depths[d].vids);
97303b705cfSriastradh	free(depths);
97403b705cfSriastradh
97503b705cfSriastradh	free(screen->visuals);
97603b705cfSriastradh
97703b705cfSriastradh	return TRUE;
97803b705cfSriastradh}
97903b705cfSriastradh
98003b705cfSriastradhstatic Bool
98103b705cfSriastradhsna_register_all_privates(void)
98203b705cfSriastradh{
98303b705cfSriastradh#if HAS_DIXREGISTERPRIVATEKEY
98403b705cfSriastradh	if (!dixRegisterPrivateKey(&sna_pixmap_key, PRIVATE_PIXMAP,
98503b705cfSriastradh				   3*sizeof(void *)))
98603b705cfSriastradh		return FALSE;
98703b705cfSriastradh
98803b705cfSriastradh	if (!dixRegisterPrivateKey(&sna_gc_key, PRIVATE_GC,
98903b705cfSriastradh				   sizeof(FbGCPrivate)))
99003b705cfSriastradh		return FALSE;
99103b705cfSriastradh
99203b705cfSriastradh	if (!dixRegisterPrivateKey(&sna_glyph_key, PRIVATE_GLYPH,
99303b705cfSriastradh				   sizeof(struct sna_glyph)))
99403b705cfSriastradh		return FALSE;
99503b705cfSriastradh
99603b705cfSriastradh	if (!dixRegisterPrivateKey(&sna_window_key, PRIVATE_WINDOW,
99703b705cfSriastradh				   3*sizeof(void *)))
99803b705cfSriastradh		return FALSE;
99903b705cfSriastradh
100003b705cfSriastradh	if (!dixRegisterPrivateKey(&sna_client_key, PRIVATE_CLIENT,
100103b705cfSriastradh				   sizeof(struct sna_client)))
100203b705cfSriastradh		return FALSE;
100303b705cfSriastradh#else
100403b705cfSriastradh	if (!dixRequestPrivate(&sna_pixmap_key, 3*sizeof(void *)))
100503b705cfSriastradh		return FALSE;
100603b705cfSriastradh
100703b705cfSriastradh	if (!dixRequestPrivate(&sna_gc_key, sizeof(FbGCPrivate)))
100803b705cfSriastradh		return FALSE;
100903b705cfSriastradh
101003b705cfSriastradh	if (!dixRequestPrivate(&sna_glyph_key, sizeof(struct sna_glyph)))
101103b705cfSriastradh		return FALSE;
101203b705cfSriastradh
101303b705cfSriastradh	if (!dixRequestPrivate(&sna_window_key, 3*sizeof(void *)))
101403b705cfSriastradh		return FALSE;
101503b705cfSriastradh
101603b705cfSriastradh	if (!dixRequestPrivate(&sna_client_key, sizeof(struct sna_client)))
101703b705cfSriastradh		return FALSE;
101803b705cfSriastradh#endif
101903b705cfSriastradh
102003b705cfSriastradh	return TRUE;
102103b705cfSriastradh}
102203b705cfSriastradh
102342542f5fSchristosstatic void sna_dri_init(struct sna *sna, ScreenPtr screen)
102442542f5fSchristos{
102542542f5fSchristos	char str[128] = "";
102642542f5fSchristos
102742542f5fSchristos	if (sna->dri2.available)
102842542f5fSchristos		sna->dri2.open = sna_dri2_open(sna, screen);
102942542f5fSchristos	if (sna->dri2.open)
103042542f5fSchristos		strcat(str, "DRI2 ");
103142542f5fSchristos
103242542f5fSchristos	if (sna->dri3.available)
103342542f5fSchristos		sna->dri3.open = sna_dri3_open(sna, screen);
103442542f5fSchristos	if (sna->dri3.open)
103542542f5fSchristos		strcat(str, "DRI3 ");
103642542f5fSchristos
103742542f5fSchristos	if (*str)
103842542f5fSchristos		xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
103942542f5fSchristos			   "direct rendering: %senabled\n", str);
104042542f5fSchristos}
104142542f5fSchristos
104203b705cfSriastradhstatic size_t
104303b705cfSriastradhagp_aperture_size(struct pci_device *dev, int gen)
104403b705cfSriastradh{
104503b705cfSriastradh	return dev->regions[gen < 030 ? 0 : 2].size;
104603b705cfSriastradh}
104703b705cfSriastradh
104803b705cfSriastradhstatic Bool
104903b705cfSriastradhsna_screen_init(SCREEN_INIT_ARGS_DECL)
105003b705cfSriastradh{
105103b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
105203b705cfSriastradh	struct sna *sna = to_sna(scrn);
105342542f5fSchristos	struct pci_device *pci;
105403b705cfSriastradh	VisualPtr visuals;
105503b705cfSriastradh	DepthPtr depths;
105603b705cfSriastradh	int nvisuals;
105703b705cfSriastradh	int ndepths;
105803b705cfSriastradh	int rootdepth;
105903b705cfSriastradh	VisualID defaultVisual;
106003b705cfSriastradh
106103b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
106203b705cfSriastradh
106303b705cfSriastradh	assert(sna->scrn == scrn);
106403b705cfSriastradh	assert(scrn->pScreen == NULL); /* set afterwards */
106503b705cfSriastradh
106603b705cfSriastradh	assert(sna->freed_pixmap == NULL);
106703b705cfSriastradh
106803b705cfSriastradh	if (!sna_register_all_privates())
106903b705cfSriastradh		return FALSE;
107003b705cfSriastradh
107142542f5fSchristos	pci = xf86GetPciInfoForEntity(sna->pEnt->index);
107242542f5fSchristos	if (pci != NULL)
107342542f5fSchristos		scrn->videoRam = agp_aperture_size(pci, sna->kgem.gen) / 1024;
107442542f5fSchristos	else
107542542f5fSchristos		scrn->videoRam = 256;
107603b705cfSriastradh
107703b705cfSriastradh	miClearVisualTypes();
107803b705cfSriastradh	if (!miSetVisualTypes(scrn->depth,
107903b705cfSriastradh			      miGetDefaultVisualMask(scrn->depth),
108003b705cfSriastradh			      scrn->rgbBits, scrn->defaultVisual))
108103b705cfSriastradh		return FALSE;
108203b705cfSriastradh	if (!miSetPixmapDepths())
108303b705cfSriastradh		return FALSE;
108403b705cfSriastradh
108503b705cfSriastradh	rootdepth = 0;
108603b705cfSriastradh	if (!miInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &rootdepth,
108703b705cfSriastradh			   &defaultVisual,
108803b705cfSriastradh			   ((unsigned long)1 << (scrn->bitsPerPixel - 1)),
108903b705cfSriastradh			   8, -1))
109003b705cfSriastradh		return FALSE;
109103b705cfSriastradh
109203b705cfSriastradh	if (!miScreenInit(screen, NULL,
109303b705cfSriastradh			  scrn->virtualX, scrn->virtualY,
109403b705cfSriastradh			  scrn->xDpi, scrn->yDpi, 0,
109503b705cfSriastradh			  rootdepth, ndepths, depths,
109603b705cfSriastradh			  defaultVisual, nvisuals, visuals))
109703b705cfSriastradh		return FALSE;
109803b705cfSriastradh
109903b705cfSriastradh	if (scrn->bitsPerPixel > 8) {
110003b705cfSriastradh		/* Fixup RGB ordering */
110103b705cfSriastradh		VisualPtr visual = screen->visuals + screen->numVisuals;
110203b705cfSriastradh		while (--visual >= screen->visuals) {
110303b705cfSriastradh			if ((visual->class | DynamicClass) == DirectColor) {
110403b705cfSriastradh				visual->offsetRed = scrn->offset.red;
110503b705cfSriastradh				visual->offsetGreen = scrn->offset.green;
110603b705cfSriastradh				visual->offsetBlue = scrn->offset.blue;
110703b705cfSriastradh				visual->redMask = scrn->mask.red;
110803b705cfSriastradh				visual->greenMask = scrn->mask.green;
110903b705cfSriastradh				visual->blueMask = scrn->mask.blue;
111003b705cfSriastradh			}
111103b705cfSriastradh		}
111203b705cfSriastradh	}
111303b705cfSriastradh
111403b705cfSriastradh	assert(screen->CloseScreen == NULL);
111503b705cfSriastradh	screen->CloseScreen = sna_late_close_screen;
111603b705cfSriastradh	if (!sna_accel_init(screen, sna)) {
111703b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
111803b705cfSriastradh			   "Hardware acceleration initialization failed\n");
111903b705cfSriastradh		return FALSE;
112003b705cfSriastradh	}
112103b705cfSriastradh
112203b705cfSriastradh	xf86SetBlackWhitePixels(screen);
112303b705cfSriastradh
112403b705cfSriastradh	xf86SetBackingStore(screen);
112503b705cfSriastradh	xf86SetSilkenMouse(screen);
112603b705cfSriastradh	if (!miDCInitialize(screen, xf86GetPointerScreenFuncs()))
112703b705cfSriastradh		return FALSE;
112803b705cfSriastradh
112942542f5fSchristos	if (sna_cursors_init(screen, sna))
113003b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_INFO, "HW Cursor enabled\n");
113103b705cfSriastradh
113203b705cfSriastradh	/* Must force it before EnterVT, so we are in control of VT and
113303b705cfSriastradh	 * later memory should be bound when allocating, e.g rotate_mem */
113403b705cfSriastradh	scrn->vtSema = TRUE;
113503b705cfSriastradh
113603b705cfSriastradh	sna->BlockHandler = screen->BlockHandler;
113703b705cfSriastradh	screen->BlockHandler = sna_block_handler;
113803b705cfSriastradh
113903b705cfSriastradh	sna->WakeupHandler = screen->WakeupHandler;
114003b705cfSriastradh	screen->WakeupHandler = sna_wakeup_handler;
114103b705cfSriastradh
114242542f5fSchristos	screen->SaveScreen = sna_save_screen;
114303b705cfSriastradh	screen->CreateScreenResources = sna_create_screen_resources;
114403b705cfSriastradh
114503b705cfSriastradh	sna->CloseScreen = screen->CloseScreen;
114603b705cfSriastradh	screen->CloseScreen = sna_early_close_screen;
114703b705cfSriastradh
114803b705cfSriastradh	if (!xf86CrtcScreenInit(screen))
114903b705cfSriastradh		return FALSE;
115003b705cfSriastradh
115142542f5fSchristos	xf86RandR12SetRotations(screen, RR_Rotate_All | RR_Reflect_All);
115203b705cfSriastradh	xf86RandR12SetTransformSupport(screen, TRUE);
115303b705cfSriastradh
115403b705cfSriastradh	if (!miCreateDefColormap(screen))
115503b705cfSriastradh		return FALSE;
115603b705cfSriastradh
115742542f5fSchristos	if (sna->mode.num_real_crtc &&
115842542f5fSchristos	    !xf86HandleColormaps(screen, 256, 8, sna_load_palette, NULL,
115903b705cfSriastradh				 CMAP_RELOAD_ON_MODE_SWITCH |
116042542f5fSchristos				 CMAP_PALETTED_TRUECOLOR))
116103b705cfSriastradh		return FALSE;
116203b705cfSriastradh
116342542f5fSchristos	xf86DPMSInit(screen, sna_dpms_set, 0);
116403b705cfSriastradh
116503b705cfSriastradh	sna_video_init(sna, screen);
116642542f5fSchristos	sna_dri_init(sna, screen);
116742542f5fSchristos
116842542f5fSchristos	if (sna->present.available)
116942542f5fSchristos		sna->present.open = sna_present_open(sna, screen);
117042542f5fSchristos	if (sna->present.open)
117142542f5fSchristos		xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
117242542f5fSchristos			   "hardware support for Present enabled\n");
117303b705cfSriastradh
117403b705cfSriastradh	if (serverGeneration == 1)
117503b705cfSriastradh		xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options);
117603b705cfSriastradh
117703b705cfSriastradh	sna->suspended = FALSE;
117803b705cfSriastradh
117942542f5fSchristos	sna_uevent_init(sna);
118003b705cfSriastradh
118103b705cfSriastradh	return TRUE;
118203b705cfSriastradh}
118303b705cfSriastradh
118403b705cfSriastradhstatic void sna_adjust_frame(ADJUST_FRAME_ARGS_DECL)
118503b705cfSriastradh{
118603b705cfSriastradh	SCRN_INFO_PTR(arg);
118703b705cfSriastradh	DBG(("%s(%d, %d)\n", __FUNCTION__, x, y));
118803b705cfSriastradh	sna_mode_adjust_frame(to_sna(scrn), x, y);
118903b705cfSriastradh}
119003b705cfSriastradh
119103b705cfSriastradhstatic void sna_free_screen(FREE_SCREEN_ARGS_DECL)
119203b705cfSriastradh{
119303b705cfSriastradh	SCRN_INFO_PTR(arg);
119403b705cfSriastradh	struct sna *sna = to_sna(scrn);
119503b705cfSriastradh
119642542f5fSchristos	DBG(("%s [scrn=%p, sna=%p]\n", __FUNCTION__, scrn, sna));
119742542f5fSchristos	if (sna == NULL || (uintptr_t)sna & 3) /* beware thieves */
119803b705cfSriastradh		return;
119903b705cfSriastradh
120042542f5fSchristos	scrn->driverPrivate = (void *)((uintptr_t)sna->info | (sna->flags & SNA_IS_SLAVED) | 2);
120103b705cfSriastradh
120203b705cfSriastradh	sna_mode_fini(sna);
120342542f5fSchristos	sna_acpi_fini(sna);
120403b705cfSriastradh	free(sna);
120503b705cfSriastradh
120603b705cfSriastradh	intel_put_device(scrn);
120703b705cfSriastradh}
120803b705cfSriastradh
120903b705cfSriastradhstatic Bool sna_enter_vt(VT_FUNC_ARGS_DECL)
121003b705cfSriastradh{
121103b705cfSriastradh	SCRN_INFO_PTR(arg);
121203b705cfSriastradh	struct sna *sna = to_sna(scrn);
121303b705cfSriastradh
121403b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
121542542f5fSchristos	if (intel_get_master(scrn))
121603b705cfSriastradh		return FALSE;
121703b705cfSriastradh
121803b705cfSriastradh	if (sna->flags & SNA_REPROBE) {
121942542f5fSchristos		DBG(("%s: reporting deferred hotplug event\n",
122042542f5fSchristos		     __FUNCTION__));
122142542f5fSchristos		sna_mode_discover(sna);
122203b705cfSriastradh		RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
122303b705cfSriastradh		sna->flags &= ~SNA_REPROBE;
122403b705cfSriastradh	}
122503b705cfSriastradh
122642542f5fSchristos	if (!sna_set_desired_mode(sna)) {
122742542f5fSchristos		intel_put_master(scrn);
122842542f5fSchristos		return FALSE;
122942542f5fSchristos	}
123042542f5fSchristos
123142542f5fSchristos	sna_accel_enter(sna);
123203b705cfSriastradh	return TRUE;
123303b705cfSriastradh}
123403b705cfSriastradh
123503b705cfSriastradhstatic Bool sna_switch_mode(SWITCH_MODE_ARGS_DECL)
123603b705cfSriastradh{
123703b705cfSriastradh	SCRN_INFO_PTR(arg);
123803b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
123903b705cfSriastradh	return xf86SetSingleMode(scrn, mode, RR_Rotate_0);
124003b705cfSriastradh}
124103b705cfSriastradh
124203b705cfSriastradhstatic ModeStatus
124303b705cfSriastradhsna_valid_mode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
124403b705cfSriastradh{
124503b705cfSriastradh	return MODE_OK;
124603b705cfSriastradh}
124703b705cfSriastradh
124803b705cfSriastradh#ifndef SUSPEND_SLEEP
124903b705cfSriastradh#define SUSPEND_SLEEP 0
125003b705cfSriastradh#endif
125103b705cfSriastradh#ifndef RESUME_SLEEP
125203b705cfSriastradh#define RESUME_SLEEP 0
125303b705cfSriastradh#endif
125403b705cfSriastradh
125503b705cfSriastradh/*
125603b705cfSriastradh * This function is only required if we need to do anything differently from
125703b705cfSriastradh * DoApmEvent() in common/xf86PM.c, including if we want to see events other
125803b705cfSriastradh * than suspend/resume.
125903b705cfSriastradh */
126003b705cfSriastradhstatic Bool sna_pm_event(SCRN_ARG_TYPE arg, pmEvent event, Bool undo)
126103b705cfSriastradh{
126203b705cfSriastradh	SCRN_INFO_PTR(arg);
126303b705cfSriastradh	struct sna *sna = to_sna(scrn);
126403b705cfSriastradh
126503b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
126603b705cfSriastradh
126703b705cfSriastradh	switch (event) {
126803b705cfSriastradh	case XF86_APM_SYS_SUSPEND:
126903b705cfSriastradh	case XF86_APM_CRITICAL_SUSPEND:	/*do we want to delay a critical suspend? */
127003b705cfSriastradh	case XF86_APM_USER_SUSPEND:
127103b705cfSriastradh	case XF86_APM_SYS_STANDBY:
127203b705cfSriastradh	case XF86_APM_USER_STANDBY:
127303b705cfSriastradh		if (!undo && !sna->suspended) {
127403b705cfSriastradh			scrn->LeaveVT(VT_FUNC_ARGS(0));
127503b705cfSriastradh			sna->suspended = TRUE;
127603b705cfSriastradh			sleep(SUSPEND_SLEEP);
127703b705cfSriastradh		} else if (undo && sna->suspended) {
127803b705cfSriastradh			sleep(RESUME_SLEEP);
127903b705cfSriastradh			scrn->EnterVT(VT_FUNC_ARGS(0));
128003b705cfSriastradh			sna->suspended = FALSE;
128103b705cfSriastradh		}
128203b705cfSriastradh		break;
128303b705cfSriastradh	case XF86_APM_STANDBY_RESUME:
128403b705cfSriastradh	case XF86_APM_NORMAL_RESUME:
128503b705cfSriastradh	case XF86_APM_CRITICAL_RESUME:
128603b705cfSriastradh		if (sna->suspended) {
128703b705cfSriastradh			sleep(RESUME_SLEEP);
128803b705cfSriastradh			scrn->EnterVT(VT_FUNC_ARGS(0));
128903b705cfSriastradh			sna->suspended = FALSE;
129003b705cfSriastradh			/*
129103b705cfSriastradh			 * Turn the screen saver off when resuming.  This seems to be
129203b705cfSriastradh			 * needed to stop xscreensaver kicking in (when used).
129303b705cfSriastradh			 *
129403b705cfSriastradh			 * XXX DoApmEvent() should probably call this just like
129503b705cfSriastradh			 * xf86VTSwitch() does.  Maybe do it here only in 4.2
129603b705cfSriastradh			 * compatibility mode.
129703b705cfSriastradh			 */
129803b705cfSriastradh			SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
129903b705cfSriastradh		}
130003b705cfSriastradh		break;
130103b705cfSriastradh		/* This is currently used for ACPI */
130203b705cfSriastradh	case XF86_APM_CAPABILITY_CHANGED:
130303b705cfSriastradh		SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
130403b705cfSriastradh		break;
130503b705cfSriastradh
130603b705cfSriastradh	default:
130742542f5fSchristos		ERR(("sna_pm_event: received APM event %d\n", event));
130803b705cfSriastradh	}
130903b705cfSriastradh	return TRUE;
131003b705cfSriastradh}
131103b705cfSriastradh
131203b705cfSriastradhstatic Bool sna_enter_vt__hosted(VT_FUNC_ARGS_DECL)
131303b705cfSriastradh{
131403b705cfSriastradh	return TRUE;
131503b705cfSriastradh}
131603b705cfSriastradh
131703b705cfSriastradhstatic void sna_leave_vt__hosted(VT_FUNC_ARGS_DECL)
131803b705cfSriastradh{
131903b705cfSriastradh}
132003b705cfSriastradh
132142542f5fSchristosstatic void describe_kms(ScrnInfoPtr scrn)
132242542f5fSchristos{
132342542f5fSchristos	int fd = __intel_peek_fd(scrn);
132442542f5fSchristos	drm_version_t version;
132542542f5fSchristos	char name[128] = "";
132642542f5fSchristos	char date[128] = "";
132742542f5fSchristos
132842542f5fSchristos	memset(&version, 0, sizeof(version));
132942542f5fSchristos	version.name_len = sizeof(name) - 1;
133042542f5fSchristos	version.name = name;
133142542f5fSchristos	version.date_len = sizeof(date) - 1;
133242542f5fSchristos	version.date = date;
133342542f5fSchristos
133442542f5fSchristos	if (drmIoctl(fd, DRM_IOCTL_VERSION, &version))
133542542f5fSchristos		return;
133642542f5fSchristos
133742542f5fSchristos	xf86DrvMsg(scrn->scrnIndex, X_INFO,
133842542f5fSchristos		   "Using Kernel Mode Setting driver: %s, version %d.%d.%d %s\n",
133942542f5fSchristos		   version.name,
134042542f5fSchristos		   version.version_major, version.version_minor, version.version_patchlevel,
134142542f5fSchristos		   version.date);
134242542f5fSchristos}
134342542f5fSchristos
134442542f5fSchristosstatic void describe_sna(ScrnInfoPtr scrn)
134503b705cfSriastradh{
134603b705cfSriastradh#if defined(USE_GIT_DESCRIBE)
134703b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
134803b705cfSriastradh		   "SNA compiled from %s\n", git_version);
134903b705cfSriastradh#elif defined(BUILDER_DESCRIPTION)
135003b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
135103b705cfSriastradh		   "SNA compiled: %s\n", BUILDER_DESCRIPTION);
135203b705cfSriastradh#endif
135303b705cfSriastradh#if !NDEBUG
135403b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
135503b705cfSriastradh		   "SNA compiled with assertions enabled\n");
135603b705cfSriastradh#endif
135703b705cfSriastradh#if DEBUG_SYNC
135803b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
135903b705cfSriastradh		   "SNA compiled with synchronous rendering\n");
136003b705cfSriastradh#endif
136103b705cfSriastradh#if DEBUG_MEMORY
136203b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
136303b705cfSriastradh		   "SNA compiled with memory allocation reporting enabled\n");
136403b705cfSriastradh#endif
136503b705cfSriastradh#if DEBUG_PIXMAP
136603b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
136703b705cfSriastradh		   "SNA compiled with extra pixmap/damage validation\n");
136842542f5fSchristos#endif
136942542f5fSchristos#ifdef HAVE_VALGRIND
137042542f5fSchristos	xf86DrvMsg(scrn->scrnIndex, X_INFO,
137142542f5fSchristos		   "SNA compiled for use with valgrind\n");
137242542f5fSchristos	VALGRIND_PRINTF("SNA compiled for use with valgrind\n");
137303b705cfSriastradh#endif
137403b705cfSriastradh	DBG(("pixman version: %s\n", pixman_version_string()));
137542542f5fSchristos}
137642542f5fSchristos
137742542f5fSchristosBool sna_init_scrn(ScrnInfoPtr scrn, int entity_num)
137842542f5fSchristos{
137942542f5fSchristos	DBG(("%s: entity_num=%d\n", __FUNCTION__, entity_num));
138042542f5fSchristos	describe_kms(scrn);
138142542f5fSchristos	describe_sna(scrn);
138203b705cfSriastradh
138303b705cfSriastradh	scrn->PreInit = sna_pre_init;
138403b705cfSriastradh	scrn->ScreenInit = sna_screen_init;
138503b705cfSriastradh	if (!hosted()) {
138603b705cfSriastradh		scrn->SwitchMode = sna_switch_mode;
138703b705cfSriastradh		scrn->AdjustFrame = sna_adjust_frame;
138803b705cfSriastradh		scrn->EnterVT = sna_enter_vt;
138903b705cfSriastradh		scrn->LeaveVT = sna_leave_vt;
139003b705cfSriastradh		scrn->ValidMode = sna_valid_mode;
139103b705cfSriastradh		scrn->PMEvent = sna_pm_event;
139203b705cfSriastradh	} else {
139303b705cfSriastradh		scrn->EnterVT = sna_enter_vt__hosted;
139403b705cfSriastradh		scrn->LeaveVT = sna_leave_vt__hosted;
139503b705cfSriastradh	}
139603b705cfSriastradh	scrn->FreeScreen = sna_free_screen;
139703b705cfSriastradh
139803b705cfSriastradh	xf86SetEntitySharable(entity_num);
139903b705cfSriastradh	xf86SetEntityInstanceForScreen(scrn, entity_num,
140003b705cfSriastradh				       xf86GetNumEntityInstances(entity_num)-1);
140103b705cfSriastradh
140203b705cfSriastradh	sna_threads_init();
140303b705cfSriastradh
140403b705cfSriastradh	return TRUE;
140503b705cfSriastradh}
140642542f5fSchristos
140742542f5fSchristos#if HAS_DEBUG_FULL
140842542f5fSchristos_X_ATTRIBUTE_PRINTF(1, 0) void LogF(const char *f, ...)
140942542f5fSchristos{
141042542f5fSchristos	va_list ap;
141142542f5fSchristos
141242542f5fSchristos	/* As we not only may be called from any context, we may also
141342542f5fSchristos	 * be called from a thread whilst the main thread is handling
141442542f5fSchristos	 * signals, therefore we have to use the signal-safe variants
141542542f5fSchristos	 * or else we trip over false positive assertions.
141642542f5fSchristos	 */
141742542f5fSchristos
141842542f5fSchristos	va_start(ap, f);
141942542f5fSchristos#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
142042542f5fSchristos	LogVMessageVerbSigSafe(X_NONE, 1, f, ap);
142142542f5fSchristos#else
142242542f5fSchristos	LogVMessageVerb(X_NONE, 1, f, ap);
142342542f5fSchristos#endif
142442542f5fSchristos	va_end(ap);
142542542f5fSchristos}
142642542f5fSchristos#endif
1427