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 <string.h>
4103b705cfSriastradh#include <stdio.h>
4203b705cfSriastradh#include <unistd.h>
4303b705cfSriastradh#include <stdlib.h>
4403b705cfSriastradh#include <stdio.h>
4503b705cfSriastradh#include <errno.h>
4603b705cfSriastradh
4703b705cfSriastradh#include "sna.h"
4803b705cfSriastradh#include "sna_module.h"
4903b705cfSriastradh#include "sna_video.h"
5003b705cfSriastradh
5103b705cfSriastradh#include "intel_driver.h"
5203b705cfSriastradh#include "intel_options.h"
5303b705cfSriastradh
5442542f5fSchristos#include <xf86cmap.h>
5542542f5fSchristos#include <xf86drm.h>
5642542f5fSchristos#include <xf86RandR12.h>
5742542f5fSchristos#include <mi.h>
5842542f5fSchristos#include <micmap.h>
5942542f5fSchristos
6063ef14f0Smrg#if defined(HAVE_X11_EXTENSIONS_DPMSCONST_H)
6163ef14f0Smrg#include <X11/extensions/dpmsconst.h>
6263ef14f0Smrg#else
6363ef14f0Smrg#define DPMSModeOn 0
6463ef14f0Smrg#define DPMSModeOff 3
6563ef14f0Smrg#endif
6663ef14f0Smrg
6703b705cfSriastradh#include <sys/ioctl.h>
6803b705cfSriastradh#include <sys/fcntl.h>
6913496ba1Ssnj#include <sys/poll.h>
7003b705cfSriastradh#include "i915_drm.h"
7103b705cfSriastradh
7203b705cfSriastradh#ifdef HAVE_VALGRIND
7303b705cfSriastradh#include <valgrind.h>
7403b705cfSriastradh#include <memcheck.h>
7503b705cfSriastradh#endif
7603b705cfSriastradh
7703b705cfSriastradh#if HAVE_DOT_GIT
7803b705cfSriastradh#include "git_version.h"
7963ef14f0Smrg#else
8063ef14f0Smrg#define git_version "not compiled from git"
8103b705cfSriastradh#endif
8203b705cfSriastradh
8342542f5fSchristos#ifdef TEARFREE
8442542f5fSchristos#define ENABLE_TEAR_FREE TRUE
8542542f5fSchristos#else
8642542f5fSchristos#define ENABLE_TEAR_FREE FALSE
8742542f5fSchristos#endif
8842542f5fSchristos
8903b705cfSriastradhDevPrivateKeyRec sna_pixmap_key;
9003b705cfSriastradhDevPrivateKeyRec sna_gc_key;
9103b705cfSriastradhDevPrivateKeyRec sna_window_key;
9203b705cfSriastradhDevPrivateKeyRec sna_glyph_key;
9303b705cfSriastradhDevPrivateKeyRec sna_client_key;
9403b705cfSriastradh
9503b705cfSriastradhstatic void
9603b705cfSriastradhsna_load_palette(ScrnInfoPtr scrn, int numColors, int *indices,
9703b705cfSriastradh		 LOCO * colors, VisualPtr pVisual)
9803b705cfSriastradh{
9903b705cfSriastradh	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
10042542f5fSchristos	int p, n, i, j;
10103b705cfSriastradh	uint16_t lut_r[256], lut_g[256], lut_b[256];
10203b705cfSriastradh
10303b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
10403b705cfSriastradh
10503b705cfSriastradh	for (p = 0; p < xf86_config->num_crtc; p++) {
10603b705cfSriastradh		xf86CrtcPtr crtc = xf86_config->crtc[p];
10703b705cfSriastradh
10842542f5fSchristos#define C(I,RGB) (colors[I].RGB << 8 | colors[I].RGB)
10903b705cfSriastradh		switch (scrn->depth) {
11003b705cfSriastradh		case 15:
11142542f5fSchristos			for (n = 0; n < numColors; n++) {
11242542f5fSchristos				i = indices[n];
11303b705cfSriastradh				for (j = 0; j < 8; j++) {
11442542f5fSchristos					lut_r[8*i + j] = C(i, red);
11542542f5fSchristos					lut_g[8*i + j] = C(i, green);
11642542f5fSchristos					lut_b[8*i + j] = C(i, blue);
11703b705cfSriastradh				}
11803b705cfSriastradh			}
11903b705cfSriastradh			break;
12003b705cfSriastradh		case 16:
12142542f5fSchristos			for (n = 0; n < numColors; n++) {
12242542f5fSchristos				i = indices[n];
12303b705cfSriastradh
12442542f5fSchristos				if (i <= 31) {
12503b705cfSriastradh					for (j = 0; j < 8; j++) {
12642542f5fSchristos						lut_r[8*i + j] = C(i, red);
12742542f5fSchristos						lut_b[8*i + j] = C(i, blue);
12803b705cfSriastradh					}
12903b705cfSriastradh				}
13003b705cfSriastradh
13142542f5fSchristos				for (j = 0; j < 4; j++)
13242542f5fSchristos					lut_g[4*i + j] = C(i, green);
13303b705cfSriastradh			}
13403b705cfSriastradh			break;
13503b705cfSriastradh		default:
13642542f5fSchristos			for (n = 0; n < numColors; n++) {
13742542f5fSchristos				i = indices[n];
13842542f5fSchristos				lut_r[i] = C(i, red);
13942542f5fSchristos				lut_g[i] = C(i, green);
14042542f5fSchristos				lut_b[i] = C(i, blue);
14103b705cfSriastradh			}
14203b705cfSriastradh			break;
14303b705cfSriastradh		}
14442542f5fSchristos#undef C
14503b705cfSriastradh
14603b705cfSriastradh		/* Make the change through RandR */
14703b705cfSriastradh#ifdef RANDR_12_INTERFACE
14803b705cfSriastradh		RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
14903b705cfSriastradh#else
15003b705cfSriastradh		crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
15103b705cfSriastradh#endif
15203b705cfSriastradh	}
15303b705cfSriastradh}
15403b705cfSriastradh
15503b705cfSriastradhstatic void
15603b705cfSriastradhsna_set_fallback_mode(ScrnInfoPtr scrn)
15703b705cfSriastradh{
15803b705cfSriastradh	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
15903b705cfSriastradh	xf86OutputPtr output = NULL;
16003b705cfSriastradh	xf86CrtcPtr crtc = NULL;
16103b705cfSriastradh	int n;
16203b705cfSriastradh
16303b705cfSriastradh	if ((unsigned)config->compat_output < config->num_output) {
16403b705cfSriastradh		output = config->output[config->compat_output];
16503b705cfSriastradh		crtc = output->crtc;
16603b705cfSriastradh	}
16703b705cfSriastradh
16803b705cfSriastradh	for (n = 0; n < config->num_output; n++)
16903b705cfSriastradh		config->output[n]->crtc = NULL;
17003b705cfSriastradh	for (n = 0; n < config->num_crtc; n++)
17103b705cfSriastradh		config->crtc[n]->enabled = FALSE;
17203b705cfSriastradh
17303b705cfSriastradh	if (output && crtc) {
17403b705cfSriastradh		DisplayModePtr mode;
17503b705cfSriastradh
17603b705cfSriastradh		output->crtc = crtc;
17703b705cfSriastradh
17803b705cfSriastradh		mode = xf86OutputFindClosestMode(output, scrn->currentMode);
17903b705cfSriastradh		if (mode &&
18003b705cfSriastradh		    xf86CrtcSetModeTransform(crtc, mode, RR_Rotate_0, NULL, 0, 0)) {
18103b705cfSriastradh			crtc->desiredMode = *mode;
18203b705cfSriastradh			crtc->desiredMode.prev = crtc->desiredMode.next = NULL;
18303b705cfSriastradh			crtc->desiredMode.name = NULL;
18403b705cfSriastradh			crtc->desiredMode.PrivSize = 0;
18503b705cfSriastradh			crtc->desiredMode.PrivFlags = 0;
18603b705cfSriastradh			crtc->desiredMode.Private = NULL;
18703b705cfSriastradh			crtc->desiredRotation = RR_Rotate_0;
18803b705cfSriastradh			crtc->desiredTransformPresent = FALSE;
18903b705cfSriastradh			crtc->desiredX = 0;
19003b705cfSriastradh			crtc->desiredY = 0;
19103b705cfSriastradh			crtc->enabled = TRUE;
19203b705cfSriastradh		}
19303b705cfSriastradh	}
19403b705cfSriastradh
19503b705cfSriastradh	xf86DisableUnusedFunctions(scrn);
19603b705cfSriastradh#ifdef RANDR_12_INTERFACE
19763ef14f0Smrg	if (get_root_window(xf86ScrnToScreen(scrn)))
19863ef14f0Smrg		xf86RandR12TellChanged(xf86ScrnToScreen(scrn));
19903b705cfSriastradh#endif
20003b705cfSriastradh}
20103b705cfSriastradh
20263ef14f0Smrgstatic void sna_set_desired_mode(struct sna *sna)
20303b705cfSriastradh{
20403b705cfSriastradh	ScrnInfoPtr scrn = sna->scrn;
20503b705cfSriastradh
20603b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
20703b705cfSriastradh
20803b705cfSriastradh	if (!xf86SetDesiredModes(scrn)) {
20903b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
21003b705cfSriastradh			   "failed to restore desired modes on VT switch\n");
21103b705cfSriastradh		sna_set_fallback_mode(scrn);
21203b705cfSriastradh	}
21303b705cfSriastradh
21442542f5fSchristos	sna_mode_check(sna);
21503b705cfSriastradh}
21603b705cfSriastradh
21703b705cfSriastradh/**
21803b705cfSriastradh * Adjust the screen pixmap for the current location of the front buffer.
21903b705cfSriastradh * This is done at EnterVT when buffers are bound as long as the resources
22003b705cfSriastradh * have already been created, but the first EnterVT happens before
22103b705cfSriastradh * CreateScreenResources.
22203b705cfSriastradh */
22303b705cfSriastradhstatic Bool sna_create_screen_resources(ScreenPtr screen)
22403b705cfSriastradh{
22503b705cfSriastradh	struct sna *sna = to_sna_from_screen(screen);
22642542f5fSchristos	PixmapPtr new_front;
22742542f5fSchristos	unsigned hint;
22803b705cfSriastradh
22903b705cfSriastradh	DBG(("%s(%dx%d@%d)\n", __FUNCTION__,
23003b705cfSriastradh	     screen->width, screen->height, screen->rootDepth));
23103b705cfSriastradh
23203b705cfSriastradh	assert(sna->scrn == xf86ScreenToScrn(screen));
23363ef14f0Smrg	assert(to_screen_from_sna(sna) == screen);
23403b705cfSriastradh
23542542f5fSchristos	/* free the data used during miInitScreen */
23603b705cfSriastradh	free(screen->devPrivate);
23703b705cfSriastradh	screen->devPrivate = NULL;
23803b705cfSriastradh
23903b705cfSriastradh	sna_accel_create(sna);
24003b705cfSriastradh
24142542f5fSchristos	hint = SNA_CREATE_FB;
24242542f5fSchristos	if (sna->flags & SNA_IS_HOSTED)
24342542f5fSchristos		hint = 0;
24442542f5fSchristos
24542542f5fSchristos	new_front = screen->CreatePixmap(screen,
24642542f5fSchristos					 screen->width,
24742542f5fSchristos					 screen->height,
24842542f5fSchristos					 screen->rootDepth,
24942542f5fSchristos					 hint);
25042542f5fSchristos	if (!new_front) {
25103b705cfSriastradh		xf86DrvMsg(screen->myNum, X_ERROR,
25203b705cfSriastradh			   "[intel] Unable to create front buffer %dx%d at depth %d\n",
25303b705cfSriastradh			   screen->width,
25403b705cfSriastradh			   screen->height,
25503b705cfSriastradh			   screen->rootDepth);
25603b705cfSriastradh
25703b705cfSriastradh		return FALSE;
25803b705cfSriastradh	}
25903b705cfSriastradh
26013496ba1Ssnj	/* Prefer to use the GPU for rendering into the eventual scanout
26113496ba1Ssnj	 * bo so that we do not unduly stall when it is time to attach
26213496ba1Ssnj	 * it to the CRTCs.
26313496ba1Ssnj	 */
26413496ba1Ssnj	(void)sna_pixmap_force_to_gpu(new_front, MOVE_READ | __MOVE_SCANOUT);
26503b705cfSriastradh
26642542f5fSchristos	screen->SetScreenPixmap(new_front);
26742542f5fSchristos	assert(screen->GetScreenPixmap(screen) == new_front);
26842542f5fSchristos	assert(sna->front == new_front);
26942542f5fSchristos	screen->DestroyPixmap(new_front); /* transfer ownership to screen */
27042542f5fSchristos
27142542f5fSchristos	sna_mode_set_primary(sna);
27203b705cfSriastradh
27313496ba1Ssnj	/* Try to become master and copy the current fbcon before the
27413496ba1Ssnj	 * actual VT switch. If we fail here, we will try to reset the
27513496ba1Ssnj	 * mode in the eventual VT switch. This can fail if systemd has
27613496ba1Ssnj	 * already revoked our KMS privileges, so just carry on regardless,
27713496ba1Ssnj	 * and hope that everything is sorted after the VT switch.
27813496ba1Ssnj	 */
27913496ba1Ssnj	if (intel_get_master(sna->dev) == 0) {
28013496ba1Ssnj		/* Only preserve the fbcon, not any subsequent server regens */
28113496ba1Ssnj		if (serverGeneration == 1 && (sna->flags & SNA_IS_HOSTED) == 0)
28213496ba1Ssnj			sna_copy_fbcon(sna);
28303b705cfSriastradh
28463ef14f0Smrg		sna_set_desired_mode(sna);
28503b705cfSriastradh	}
28603b705cfSriastradh
28703b705cfSriastradh	return TRUE;
28803b705cfSriastradh}
28903b705cfSriastradh
29063ef14f0Smrgstatic void sna_dpms_set(ScrnInfoPtr scrn, int mode, int flags)
29103b705cfSriastradh{
29263ef14f0Smrg	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
29363ef14f0Smrg	struct sna *sna = to_sna(scrn);
29463ef14f0Smrg	bool changed = false;
29563ef14f0Smrg	int i;
29642542f5fSchristos
29763ef14f0Smrg	DBG(("%s(mode=%d, flags=%d), vtSema=%d => off?=%d\n",
29863ef14f0Smrg	     __FUNCTION__, mode, flags, scrn->vtSema, mode!=DPMSModeOn));
29942542f5fSchristos	if (!scrn->vtSema)
30063ef14f0Smrg		return;
30142542f5fSchristos
30263ef14f0Smrg	/* Opencoded version of xf86DPMSSet().
30363ef14f0Smrg	 *
30463ef14f0Smrg	 * The principle difference is to skip calling crtc->dpms() when
30563ef14f0Smrg	 * turning off the display. This (on recent enough kernels at
30663ef14f0Smrg	 * least) should be equivalent in power consumption, but require
30763ef14f0Smrg	 * less work (hence quicker and less likely to fail) when switching
30863ef14f0Smrg	 * back on.
30963ef14f0Smrg	 */
31063ef14f0Smrg	if (mode != DPMSModeOn) {
31163ef14f0Smrg		if (sna->mode.hidden == 0 && !(sna->flags & SNA_NO_DPMS)) {
31263ef14f0Smrg			DBG(("%s: hiding %d outputs\n",
31363ef14f0Smrg			     __FUNCTION__, config->num_output));
31463ef14f0Smrg			for (i = 0; i < config->num_output; i++) {
31563ef14f0Smrg				xf86OutputPtr output = config->output[i];
31663ef14f0Smrg				if (output->crtc != NULL)
31763ef14f0Smrg					output->funcs->dpms(output, mode);
31863ef14f0Smrg			}
31963ef14f0Smrg			sna->mode.hidden = sna->mode.front_active + 1;
32063ef14f0Smrg			sna->mode.front_active = 0;
32163ef14f0Smrg			changed = true;
32263ef14f0Smrg		}
32363ef14f0Smrg	} else {
32463ef14f0Smrg		/* Re-enable CRTC that have been forced off via other means */
32563ef14f0Smrg		if (sna->mode.hidden != 0) {
32663ef14f0Smrg			DBG(("%s: unhiding %d crtc, %d outputs\n",
32763ef14f0Smrg			     __FUNCTION__, config->num_crtc, config->num_output));
32863ef14f0Smrg			sna->mode.front_active = sna->mode.hidden - 1;
32963ef14f0Smrg			sna->mode.hidden = 0;
33063ef14f0Smrg			for (i = 0; i < config->num_crtc; i++) {
33163ef14f0Smrg				xf86CrtcPtr crtc = config->crtc[i];
33263ef14f0Smrg				if (crtc->enabled)
33363ef14f0Smrg					crtc->funcs->dpms(crtc, mode);
33463ef14f0Smrg			}
33563ef14f0Smrg
33663ef14f0Smrg			for (i = 0; i < config->num_output; i++) {
33763ef14f0Smrg				xf86OutputPtr output = config->output[i];
33863ef14f0Smrg				if (output->crtc != NULL)
33963ef14f0Smrg					output->funcs->dpms(output, mode);
34063ef14f0Smrg			}
34163ef14f0Smrg			changed = true;
34263ef14f0Smrg		}
34363ef14f0Smrg	}
34463ef14f0Smrg
34563ef14f0Smrg	DBG(("%s: hiding outputs? %d, front active? %d, changed? %d\n",
34663ef14f0Smrg	     __FUNCTION__, sna->mode.hidden, sna->mode.front_active, changed));
34763ef14f0Smrg
34863ef14f0Smrg	if (changed)
34963ef14f0Smrg		sna_crtc_config_notify(xf86ScrnToScreen(scrn));
35003b705cfSriastradh}
35103b705cfSriastradh
35263ef14f0Smrgstatic Bool sna_save_screen(ScreenPtr screen, int mode)
35303b705cfSriastradh{
35463ef14f0Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
35563ef14f0Smrg
35663ef14f0Smrg	DBG(("%s(mode=%d [unblank=%d])\n",
35763ef14f0Smrg	     __FUNCTION__, mode, xf86IsUnblank(mode)));
35803b705cfSriastradh
35963ef14f0Smrg	/* We have to unroll xf86SaveScreen() here as it is called
36063ef14f0Smrg	 * by DPMSSet() nullifying our special handling crtc->dpms()
36163ef14f0Smrg	 * in sna_dpms_set().
36263ef14f0Smrg	 */
36363ef14f0Smrg	sna_dpms_set(scrn,
36463ef14f0Smrg		     xf86IsUnblank(mode) ? DPMSModeOn : DPMSModeOff,
36563ef14f0Smrg		     0);
36663ef14f0Smrg	return TRUE;
36742542f5fSchristos}
36803b705cfSriastradh
36942542f5fSchristosstatic void sna_selftest(void)
37042542f5fSchristos{
37142542f5fSchristos	sna_damage_selftest();
37242542f5fSchristos}
37303b705cfSriastradh
37442542f5fSchristosstatic bool has_vsync(struct sna *sna)
37542542f5fSchristos{
37642542f5fSchristos	if (sna->flags & SNA_IS_HOSTED)
37703b705cfSriastradh		return false;
37803b705cfSriastradh
37942542f5fSchristos	return true;
38003b705cfSriastradh}
38103b705cfSriastradh
38203b705cfSriastradhstatic void sna_setup_capabilities(ScrnInfoPtr scrn, int fd)
38303b705cfSriastradh{
38403b705cfSriastradh#if HAS_PIXMAP_SHARING && defined(DRM_CAP_PRIME)
38503b705cfSriastradh	uint64_t value;
38603b705cfSriastradh
38703b705cfSriastradh	scrn->capabilities = 0;
38803b705cfSriastradh	if (drmGetCap(fd, DRM_CAP_PRIME, &value) == 0) {
38903b705cfSriastradh		if (value & DRM_PRIME_CAP_EXPORT)
39003b705cfSriastradh			scrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload;
39103b705cfSriastradh		if (value & DRM_PRIME_CAP_IMPORT)
39203b705cfSriastradh			scrn->capabilities |= RR_Capability_SinkOutput;
39303b705cfSriastradh	}
39403b705cfSriastradh#endif
39503b705cfSriastradh}
39603b705cfSriastradh
39703b705cfSriastradhstatic Bool fb_supports_depth(int fd, int depth)
39803b705cfSriastradh{
39903b705cfSriastradh	struct drm_i915_gem_create create;
40003b705cfSriastradh	struct drm_mode_fb_cmd fb;
40142542f5fSchristos	struct drm_mode_card_res res;
40203b705cfSriastradh	Bool ret;
40303b705cfSriastradh
40442542f5fSchristos	memset(&res, 0, sizeof(res));
40542542f5fSchristos	(void)drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res);
40642542f5fSchristos	if (res.count_crtcs == 0)
40742542f5fSchristos		return TRUE;
40842542f5fSchristos
40903b705cfSriastradh	VG_CLEAR(create);
41003b705cfSriastradh	create.handle = 0;
41103b705cfSriastradh	create.size = 4096;
41203b705cfSriastradh	if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create))
41303b705cfSriastradh		return FALSE;
41403b705cfSriastradh
41503b705cfSriastradh	VG_CLEAR(fb);
41603b705cfSriastradh	fb.width = 64;
41703b705cfSriastradh	fb.height = 16;
41803b705cfSriastradh	fb.pitch = 256;
41903b705cfSriastradh	fb.bpp = depth <= 8 ? 8 : depth <= 16 ? 16 : 32;
42003b705cfSriastradh	fb.depth = depth;
42103b705cfSriastradh	fb.handle = create.handle;
42203b705cfSriastradh
42303b705cfSriastradh	ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB, &fb) == 0;
42403b705cfSriastradh	drmModeRmFB(fd, fb.fb_id);
42503b705cfSriastradh
42642542f5fSchristos	(void)drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &create.handle);
42703b705cfSriastradh
42803b705cfSriastradh	return ret;
42903b705cfSriastradh}
43003b705cfSriastradh
43142542f5fSchristosstatic void setup_dri(struct sna *sna)
43242542f5fSchristos{
43342542f5fSchristos	unsigned level;
43442542f5fSchristos
43542542f5fSchristos	sna->dri2.available = false;
43663ef14f0Smrg	sna->dri2.enable = false;
43742542f5fSchristos	sna->dri3.available = false;
43863ef14f0Smrg	sna->dri3.enable = false;
43963ef14f0Smrg	sna->dri3.override = false;
44042542f5fSchristos
44163ef14f0Smrg	level = intel_option_cast_to_unsigned(sna->Options, OPTION_DRI, DEFAULT_DRI_LEVEL);
44242542f5fSchristos#if HAVE_DRI3
44363ef14f0Smrg	sna->dri3.available = !!xf86LoadSubModule(sna->scrn, "dri3");
44463ef14f0Smrg	sna->dri3.override =
44563ef14f0Smrg		!sna->dri3.available ||
44663ef14f0Smrg		xf86IsOptionSet(sna->Options, OPTION_DRI);
44763ef14f0Smrg	if (level >= 3 && sna->kgem.gen >= 040)
44863ef14f0Smrg		sna->dri3.enable = sna->dri3.available;
44942542f5fSchristos#endif
45042542f5fSchristos#if HAVE_DRI2
45163ef14f0Smrg	sna->dri2.available = !!xf86LoadSubModule(sna->scrn, "dri2");
45242542f5fSchristos	if (level >= 2)
45363ef14f0Smrg		sna->dri2.enable = sna->dri2.available;
45442542f5fSchristos#endif
45542542f5fSchristos}
45642542f5fSchristos
45742542f5fSchristosstatic bool enable_tear_free(struct sna *sna)
45842542f5fSchristos{
45942542f5fSchristos	if (sna->flags & SNA_LINEAR_FB)
46042542f5fSchristos		return false;
46142542f5fSchristos
46242542f5fSchristos	/* Under certain conditions, we should enable TearFree by default,
46342542f5fSchristos	 * for example when the hardware requires pageflipping to run within
46442542f5fSchristos	 * its power/performance budget.
46542542f5fSchristos	 */
46642542f5fSchristos	if (sna_mode_wants_tear_free(sna))
46742542f5fSchristos		return true;
46842542f5fSchristos
46942542f5fSchristos	return ENABLE_TEAR_FREE;
47042542f5fSchristos}
47142542f5fSchristos
47263ef14f0Smrgstatic bool setup_tear_free(struct sna *sna)
47342542f5fSchristos{
47442542f5fSchristos	MessageType from;
47542542f5fSchristos	Bool enable;
47642542f5fSchristos
47742542f5fSchristos	if (sna->flags & SNA_LINEAR_FB)
47863ef14f0Smrg		return false;
47942542f5fSchristos
48042542f5fSchristos	if ((sna->flags & SNA_HAS_FLIP) == 0) {
48142542f5fSchristos		from = X_PROBED;
48242542f5fSchristos		goto done;
48342542f5fSchristos	}
48442542f5fSchristos
48542542f5fSchristos	if (!xf86GetOptValBool(sna->Options, OPTION_TEAR_FREE, &enable)) {
48642542f5fSchristos		enable = enable_tear_free(sna);
48742542f5fSchristos		from = X_DEFAULT;
48842542f5fSchristos	} else
48942542f5fSchristos		from = X_CONFIG;
49042542f5fSchristos
49142542f5fSchristos	if (enable)
49263ef14f0Smrg		sna->flags |= SNA_WANT_TEAR_FREE | SNA_TEAR_FREE;
49342542f5fSchristos
49442542f5fSchristosdone:
49542542f5fSchristos	xf86DrvMsg(sna->scrn->scrnIndex, from, "TearFree %sabled\n",
49642542f5fSchristos		   sna->flags & SNA_TEAR_FREE ? "en" : "dis");
49763ef14f0Smrg	return sna->flags & SNA_TEAR_FREE;
49842542f5fSchristos}
49942542f5fSchristos
50003b705cfSriastradh/**
50103b705cfSriastradh * This is called before ScreenInit to do any require probing of screen
50203b705cfSriastradh * configuration.
50303b705cfSriastradh *
50403b705cfSriastradh * This code generally covers probing, module loading, option handling
50503b705cfSriastradh * card mapping, and RandR setup.
50603b705cfSriastradh *
50703b705cfSriastradh * Since xf86InitialConfiguration ends up requiring that we set video modes
50803b705cfSriastradh * in order to detect configuration, we end up having to do a lot of driver
50903b705cfSriastradh * setup (talking to the DRM, mapping the device, etc.) in this function.
51003b705cfSriastradh * As a result, we want to set up that server initialization once rather
51103b705cfSriastradh * that doing it per generation.
51203b705cfSriastradh */
51342542f5fSchristosstatic Bool sna_pre_init(ScrnInfoPtr scrn, int probe)
51403b705cfSriastradh{
51503b705cfSriastradh	struct sna *sna;
51603b705cfSriastradh	char buf[1024];
51703b705cfSriastradh	rgb defaultWeight = { 0, 0, 0 };
51803b705cfSriastradh	EntityInfoPtr pEnt;
51903b705cfSriastradh	Gamma zeros = { 0.0, 0.0, 0.0 };
52003b705cfSriastradh	int fd;
52103b705cfSriastradh
52203b705cfSriastradh	DBG(("%s flags=%x, numEntities=%d\n",
52342542f5fSchristos	     __FUNCTION__, probe, scrn->numEntities));
52403b705cfSriastradh
52503b705cfSriastradh	if (scrn->numEntities != 1)
52603b705cfSriastradh		return FALSE;
52703b705cfSriastradh
52803b705cfSriastradh	pEnt = xf86GetEntityInfo(scrn->entityList[0]);
52942542f5fSchristos	if (pEnt == NULL) {
53042542f5fSchristos		ERR(("%s: no EntityInfo found for scrn\n", __FUNCTION__));
53103b705cfSriastradh		return FALSE;
53242542f5fSchristos	}
53303b705cfSriastradh
53403b705cfSriastradh	if (pEnt->location.type != BUS_PCI
53503b705cfSriastradh#ifdef XSERVER_PLATFORM_BUS
53603b705cfSriastradh	    && pEnt->location.type != BUS_PLATFORM
53703b705cfSriastradh#endif
53842542f5fSchristos		) {
53942542f5fSchristos		ERR(("%s: invalid EntityInfo found for scrn, location=%d\n", __FUNCTION__, pEnt->location.type));
54003b705cfSriastradh		return FALSE;
54142542f5fSchristos	}
54203b705cfSriastradh
54342542f5fSchristos	if (probe & PROBE_DETECT)
54403b705cfSriastradh		return TRUE;
54503b705cfSriastradh
54603b705cfSriastradh	sna_selftest();
54703b705cfSriastradh
54842542f5fSchristos	probe = 0;
54942542f5fSchristos	if (((uintptr_t)scrn->driverPrivate) & 3) {
55003b705cfSriastradh		if (posix_memalign((void **)&sna, 4096, sizeof(*sna)))
55103b705cfSriastradh			return FALSE;
55203b705cfSriastradh
55303b705cfSriastradh		memset(sna, 0, sizeof(*sna)); /* should be unnecessary */
55442542f5fSchristos		probe = (uintptr_t)scrn->driverPrivate & 1;
55542542f5fSchristos		sna->info = (void *)((uintptr_t)scrn->driverPrivate & ~3);
55603b705cfSriastradh		scrn->driverPrivate = sna;
55763ef14f0Smrg		sna->scrn = scrn;
55803b705cfSriastradh
55903b705cfSriastradh		sna->cpu_features = sna_cpu_detect();
56042542f5fSchristos		sna->acpi.fd = sna_acpi_open();
56103b705cfSriastradh	}
56203b705cfSriastradh	sna = to_sna(scrn);
56303b705cfSriastradh	sna->pEnt = pEnt;
56442542f5fSchristos	sna->flags = probe;
56503b705cfSriastradh
56603b705cfSriastradh	scrn->displayWidth = 640;	/* default it */
56703b705cfSriastradh
56803b705cfSriastradh	scrn->monitor = scrn->confScreen->monitor;
56903b705cfSriastradh	scrn->progClock = TRUE;
57003b705cfSriastradh	scrn->rgbBits = 8;
57103b705cfSriastradh
57213496ba1Ssnj	sna->dev = intel_get_device(scrn, &fd);
57313496ba1Ssnj	if (sna->dev == NULL) {
57403b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
57503b705cfSriastradh			   "Failed to claim DRM device.\n");
57603b705cfSriastradh		goto cleanup;
57703b705cfSriastradh	}
57803b705cfSriastradh
57903b705cfSriastradh	/* Sanity check */
58003b705cfSriastradh	if (hosted() && (sna->flags & SNA_IS_HOSTED) == 0) {
58103b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
58203b705cfSriastradh			   "Failed to setup hosted device.\n");
58303b705cfSriastradh		goto cleanup;
58403b705cfSriastradh	}
58503b705cfSriastradh
58613496ba1Ssnj	intel_detect_chipset(scrn, sna->dev);
58763ef14f0Smrg	xf86DrvMsg(scrn->scrnIndex, X_PROBED,
58863ef14f0Smrg		   "CPU: %s; using a maximum of %d threads\n",
58963ef14f0Smrg		   sna_cpu_features_to_string(sna->cpu_features, buf),
59063ef14f0Smrg		   sna_use_threads(64*1024, 64*1024, 1));
59103b705cfSriastradh
59242542f5fSchristos	if (!xf86SetDepthBpp(scrn, 24, 0, 0,
59303b705cfSriastradh			     Support32bppFb |
59403b705cfSriastradh			     SupportConvert24to32 | PreferConvert24to32))
59503b705cfSriastradh		goto cleanup;
59603b705cfSriastradh
59703b705cfSriastradh	switch (scrn->depth) {
59803b705cfSriastradh	case 8:
59903b705cfSriastradh	case 15:
60003b705cfSriastradh	case 16:
60103b705cfSriastradh	case 24:
60203b705cfSriastradh	case 30:
60342542f5fSchristos		if ((sna->flags & SNA_IS_HOSTED) ||
60442542f5fSchristos		    fb_supports_depth(fd, scrn->depth))
60503b705cfSriastradh			break;
60603b705cfSriastradh	default:
60703b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
60803b705cfSriastradh			   "Given depth (%d) is not supported by the Intel driver and this chipset.\n",
60903b705cfSriastradh			   scrn->depth);
61003b705cfSriastradh		goto cleanup;
61103b705cfSriastradh	}
61203b705cfSriastradh	xf86PrintDepthBpp(scrn);
61303b705cfSriastradh
61403b705cfSriastradh	if (!xf86SetWeight(scrn, defaultWeight, defaultWeight))
61503b705cfSriastradh		goto cleanup;
61603b705cfSriastradh	if (!xf86SetDefaultVisual(scrn, -1))
61703b705cfSriastradh		goto cleanup;
61803b705cfSriastradh
61903b705cfSriastradh	sna->Options = intel_options_get(scrn);
62003b705cfSriastradh	if (sna->Options == NULL)
62103b705cfSriastradh		goto cleanup;
62203b705cfSriastradh
62303b705cfSriastradh	sna_setup_capabilities(scrn, fd);
62403b705cfSriastradh
62542542f5fSchristos	kgem_init(&sna->kgem, fd,
62642542f5fSchristos		  xf86GetPciInfoForEntity(pEnt->index),
62742542f5fSchristos		  sna->info->gen);
62803b705cfSriastradh
62903b705cfSriastradh	if (xf86ReturnOptValBool(sna->Options, OPTION_TILING_FB, FALSE))
63042542f5fSchristos		sna->flags |= SNA_LINEAR_FB;
63163ef14f0Smrg	if (!sna->kgem.can_fence)
63263ef14f0Smrg		sna->flags |= SNA_LINEAR_FB;
63303b705cfSriastradh
63403b705cfSriastradh	if (!xf86ReturnOptValBool(sna->Options, OPTION_SWAPBUFFERS_WAIT, TRUE))
63503b705cfSriastradh		sna->flags |= SNA_NO_WAIT;
63642542f5fSchristos	DBG(("%s: swapbuffer wait? %s\n", __FUNCTION__, sna->flags & SNA_NO_WAIT ? "disabled" : "enabled"));
63742542f5fSchristos
63842542f5fSchristos	if (!has_vsync(sna) ||
63942542f5fSchristos	    !xf86ReturnOptValBool(sna->Options, OPTION_VSYNC, TRUE))
64042542f5fSchristos		sna->flags |= SNA_NO_VSYNC;
64142542f5fSchristos	DBG(("%s: vsync? %s\n", __FUNCTION__, sna->flags & SNA_NO_VSYNC ? "disabled" : "enabled"));
64242542f5fSchristos
64342542f5fSchristos	if (sna->flags & SNA_IS_HOSTED ||
64442542f5fSchristos	    !xf86ReturnOptValBool(sna->Options, OPTION_PAGEFLIP, TRUE))
64503b705cfSriastradh		sna->flags |= SNA_NO_FLIP;
64642542f5fSchristos	DBG(("%s: page flips? %s\n", __FUNCTION__, sna->flags & SNA_NO_FLIP ? "disabled" : "enabled"));
64703b705cfSriastradh
64842542f5fSchristos	if ((sna->flags & (SNA_NO_VSYNC | SNA_NO_FLIP | SNA_NO_WAIT)) == 0 &&
64942542f5fSchristos	    xf86ReturnOptValBool(sna->Options, OPTION_TRIPLE_BUFFER, TRUE))
65042542f5fSchristos		sna->flags |= SNA_TRIPLE_BUFFER;
65142542f5fSchristos	DBG(("%s: triple buffer? %s\n", __FUNCTION__, sna->flags & SNA_TRIPLE_BUFFER ? "enabled" : "disabled"));
65203b705cfSriastradh
65342542f5fSchristos	if (xf86ReturnOptValBool(sna->Options, OPTION_CRTC_PIXMAPS, FALSE)) {
65442542f5fSchristos		xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Forcing per-crtc-pixmaps.\n");
65542542f5fSchristos		sna->flags |= SNA_FORCE_SHADOW;
65642542f5fSchristos	}
65703b705cfSriastradh
65803b705cfSriastradh	if (!sna_mode_pre_init(scrn, sna)) {
65903b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
66003b705cfSriastradh			   "No outputs and no modes.\n");
66103b705cfSriastradh		goto cleanup;
66203b705cfSriastradh	}
66303b705cfSriastradh	scrn->currentMode = scrn->modes;
66403b705cfSriastradh
66563ef14f0Smrg	if (!setup_tear_free(sna) && sna_mode_wants_tear_free(sna))
66663ef14f0Smrg		sna->kgem.needs_dirtyfb = sna->kgem.has_dirtyfb;
66742542f5fSchristos
66803b705cfSriastradh	xf86SetGamma(scrn, zeros);
66903b705cfSriastradh	xf86SetDpi(scrn, 0, 0);
67003b705cfSriastradh
67142542f5fSchristos	setup_dri(sna);
67242542f5fSchristos
67342542f5fSchristos	sna->present.available = false;
67442542f5fSchristos	if (xf86ReturnOptValBool(sna->Options, OPTION_PRESENT, TRUE)) {
67542542f5fSchristos#if HAVE_PRESENT
67642542f5fSchristos		sna->present.available = !!xf86LoadSubModule(scrn, "present");
67742542f5fSchristos#endif
67842542f5fSchristos	}
67942542f5fSchristos
68042542f5fSchristos	sna_acpi_init(sna);
68103b705cfSriastradh
68203b705cfSriastradh	return TRUE;
68303b705cfSriastradh
68403b705cfSriastradhcleanup:
68542542f5fSchristos	scrn->driverPrivate = (void *)((uintptr_t)sna->info | (sna->flags & SNA_IS_SLAVED) | 2);
68613496ba1Ssnj	if (sna->dev)
68713496ba1Ssnj		intel_put_device(sna->dev);
68803b705cfSriastradh	free(sna);
68903b705cfSriastradh	return FALSE;
69003b705cfSriastradh}
69103b705cfSriastradh
69242542f5fSchristosstatic bool has_shadow(struct sna *sna)
69342542f5fSchristos{
69463ef14f0Smrg	if (!sna->mode.shadow_enabled)
69542542f5fSchristos		return false;
69642542f5fSchristos
69763ef14f0Smrg	assert(sna->mode.shadow_damage);
69842542f5fSchristos	if (RegionNil(DamageRegion(sna->mode.shadow_damage)))
69942542f5fSchristos		return false;
70042542f5fSchristos
70142542f5fSchristos	return sna->mode.flip_active == 0;
70242542f5fSchristos}
70342542f5fSchristos
70463ef14f0Smrg#if !HAVE_NOTIFY_FD
70503b705cfSriastradhstatic void
70603b705cfSriastradhsna_block_handler(BLOCKHANDLER_ARGS_DECL)
70703b705cfSriastradh{
70803b705cfSriastradh#ifndef XF86_SCRN_INTERFACE
70903b705cfSriastradh	struct sna *sna = to_sna(xf86Screens[arg]);
71003b705cfSriastradh#else
71103b705cfSriastradh	struct sna *sna = to_sna_from_screen(arg);
71203b705cfSriastradh#endif
71303b705cfSriastradh	struct timeval **tv = timeout;
71403b705cfSriastradh
71563ef14f0Smrg	DBG(("%s (tv=%ld.%06ld), has_shadow?=%d\n", __FUNCTION__,
71663ef14f0Smrg	     *tv ? (*tv)->tv_sec : -1, *tv ? (*tv)->tv_usec : 0,
71763ef14f0Smrg	     has_shadow(sna)));
71803b705cfSriastradh
71903b705cfSriastradh	sna->BlockHandler(BLOCKHANDLER_ARGS);
72003b705cfSriastradh
72142542f5fSchristos	if (*tv == NULL || ((*tv)->tv_usec | (*tv)->tv_sec) || has_shadow(sna))
72263ef14f0Smrg		sna_accel_block(sna, tv);
72303b705cfSriastradh}
72403b705cfSriastradh
72503b705cfSriastradhstatic void
72603b705cfSriastradhsna_wakeup_handler(WAKEUPHANDLER_ARGS_DECL)
72703b705cfSriastradh{
72803b705cfSriastradh#ifndef XF86_SCRN_INTERFACE
72903b705cfSriastradh	struct sna *sna = to_sna(xf86Screens[arg]);
73003b705cfSriastradh#else
73103b705cfSriastradh	struct sna *sna = to_sna_from_screen(arg);
73203b705cfSriastradh#endif
73303b705cfSriastradh
73403b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
73503b705cfSriastradh
73603b705cfSriastradh	/* despite all appearances, result is just a signed int */
73703b705cfSriastradh	if ((int)result < 0)
73803b705cfSriastradh		return;
73903b705cfSriastradh
74063ef14f0Smrg	sna_acpi_wakeup(sna, read_mask);
74142542f5fSchristos
74203b705cfSriastradh	sna->WakeupHandler(WAKEUPHANDLER_ARGS);
74303b705cfSriastradh
74463ef14f0Smrg	if (FD_ISSET(sna->kgem.fd, (fd_set*)read_mask)) {
74563ef14f0Smrg		sna_mode_wakeup(sna);
74663ef14f0Smrg		/* Clear the flag so that subsequent ZaphodHeads don't block  */
74763ef14f0Smrg		FD_CLR(sna->kgem.fd, (fd_set*)read_mask);
74863ef14f0Smrg	}
74963ef14f0Smrg}
75063ef14f0Smrg#else
75163ef14f0Smrgstatic void
75263ef14f0Smrgsna_block_handler(void *data, void *_timeout)
75363ef14f0Smrg{
75463ef14f0Smrg	struct sna *sna = data;
75563ef14f0Smrg	int *timeout = _timeout;
75663ef14f0Smrg	struct timeval tv, *tvp;
75763ef14f0Smrg
75863ef14f0Smrg	DBG(("%s (timeout=%d, has_shadow=%d)\n", __FUNCTION__,
75963ef14f0Smrg	     *timeout, has_shadow(sna)));
76063ef14f0Smrg
76163ef14f0Smrg	if (*timeout < 0) {
76263ef14f0Smrg		tvp = NULL;
76363ef14f0Smrg	} else if (*timeout == 0) {
76463ef14f0Smrg		if (!has_shadow(sna))
76563ef14f0Smrg			return;
76663ef14f0Smrg
76763ef14f0Smrg		tv.tv_sec = 0;
76863ef14f0Smrg		tv.tv_usec = 0;
76963ef14f0Smrg		tvp = &tv;
77063ef14f0Smrg	} else {
77163ef14f0Smrg		tv.tv_sec = *timeout / 1000;
77263ef14f0Smrg		tv.tv_usec = (*timeout % 1000) * 1000;
77363ef14f0Smrg		tvp = &tv;
77463ef14f0Smrg	}
77503b705cfSriastradh
77663ef14f0Smrg	sna_accel_block(sna, &tvp);
77763ef14f0Smrg	if (tvp)
77863ef14f0Smrg		*timeout = tvp->tv_sec * 1000 + tvp->tv_usec / 1000;
77903b705cfSriastradh}
78063ef14f0Smrg#endif
78103b705cfSriastradh
78203b705cfSriastradh#if HAVE_UDEV
78363ef14f0Smrg#include <sys/stat.h>
78463ef14f0Smrg
78503b705cfSriastradhstatic void
78603b705cfSriastradhsna_handle_uevents(int fd, void *closure)
78703b705cfSriastradh{
78842542f5fSchristos	struct sna *sna = closure;
78903b705cfSriastradh	struct stat s;
79063ef14f0Smrg	struct pollfd pfd;
79163ef14f0Smrg	bool hotplug = false;
79203b705cfSriastradh
79303b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
79403b705cfSriastradh
79563ef14f0Smrg	pfd.fd = udev_monitor_get_fd(sna->uevent_monitor);
79663ef14f0Smrg	pfd.events = POLLIN;
79763ef14f0Smrg
79863ef14f0Smrg	if (fstat(sna->kgem.fd, &s))
79963ef14f0Smrg		memset(&s, 0, sizeof(s));
80063ef14f0Smrg
80163ef14f0Smrg	while (poll(&pfd, 1, 0) > 0) {
80263ef14f0Smrg		struct udev_device *dev;
80363ef14f0Smrg		dev_t devnum;
80463ef14f0Smrg
80563ef14f0Smrg		errno = 0;
80663ef14f0Smrg		dev = udev_monitor_receive_device(sna->uevent_monitor);
80763ef14f0Smrg		if (dev == NULL) {
80863ef14f0Smrg			if (errno == EINTR || errno == EAGAIN)
80963ef14f0Smrg				continue;
81063ef14f0Smrg
81163ef14f0Smrg			break;
81263ef14f0Smrg		}
81363ef14f0Smrg
81463ef14f0Smrg		devnum = udev_device_get_devnum(dev);
81563ef14f0Smrg		if (memcmp(&s.st_rdev, &devnum, sizeof(dev_t)) == 0) {
81663ef14f0Smrg			const char *str;
81763ef14f0Smrg
81863ef14f0Smrg			str = udev_device_get_property_value(dev, "HOTPLUG");
81963ef14f0Smrg			if (str && atoi(str) == 1) {
82063ef14f0Smrg				str = udev_device_get_property_value(dev, "CONNECTOR");
82163ef14f0Smrg				if (str) {
82263ef14f0Smrg					hotplug |= sna_mode_find_hotplug_connector(sna, atoi(str));
82363ef14f0Smrg				} else {
82463ef14f0Smrg					sna->flags |= SNA_REPROBE;
82563ef14f0Smrg					hotplug = true;
82663ef14f0Smrg				}
82763ef14f0Smrg			}
82863ef14f0Smrg		}
82903b705cfSriastradh
83003b705cfSriastradh		udev_device_unref(dev);
83103b705cfSriastradh	}
83203b705cfSriastradh
83363ef14f0Smrg	if (hotplug) {
83463ef14f0Smrg		DBG(("%s: hotplug event (vtSema?=%d)\n",
83563ef14f0Smrg		     __FUNCTION__, sna->scrn->vtSema));
83603b705cfSriastradh
83763ef14f0Smrg		if (sna->scrn->vtSema)
83863ef14f0Smrg			sna_mode_discover(sna, true);
83963ef14f0Smrg		else
84003b705cfSriastradh			sna->flags |= SNA_REPROBE;
84103b705cfSriastradh	}
84263ef14f0Smrg}
84303b705cfSriastradh
84463ef14f0Smrgstatic bool has_randr(void)
84563ef14f0Smrg{
84663ef14f0Smrg#if HAS_DIXREGISTERPRIVATEKEY
84763ef14f0Smrg	return dixPrivateKeyRegistered(rrPrivKey);
84863ef14f0Smrg#else
84963ef14f0Smrg	return *rrPrivKey;
85063ef14f0Smrg#endif
85103b705cfSriastradh}
85203b705cfSriastradh
85303b705cfSriastradhstatic void
85442542f5fSchristossna_uevent_init(struct sna *sna)
85503b705cfSriastradh{
85603b705cfSriastradh	struct udev *u;
85703b705cfSriastradh	struct udev_monitor *mon;
85803b705cfSriastradh	MessageType from = X_CONFIG;
85903b705cfSriastradh
86003b705cfSriastradh	if (sna->flags & SNA_IS_HOSTED)
86103b705cfSriastradh		return;
86203b705cfSriastradh
86303b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
86403b705cfSriastradh
86503b705cfSriastradh	/* RandR will be disabled if Xinerama is active, and so generating
86603b705cfSriastradh	 * RR hotplug events is then verboten.
86703b705cfSriastradh	 */
86863ef14f0Smrg	if (!has_randr())
86942542f5fSchristos		goto out;
87003b705cfSriastradh
87142542f5fSchristos	u = NULL;
87242542f5fSchristos	if (xf86ReturnOptValBool(sna->Options, OPTION_HOTPLUG, TRUE))
87342542f5fSchristos		u = udev_new();
87403b705cfSriastradh	if (!u)
87542542f5fSchristos		goto out;
87642542f5fSchristos
87742542f5fSchristos	from = X_DEFAULT;
87803b705cfSriastradh
87903b705cfSriastradh	mon = udev_monitor_new_from_netlink(u, "udev");
88042542f5fSchristos	if (!mon)
88142542f5fSchristos		goto err_dev;
88203b705cfSriastradh
88342542f5fSchristos	if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") < 0)
88442542f5fSchristos		goto err_monitor;
88503b705cfSriastradh
88642542f5fSchristos	if (udev_monitor_enable_receiving(mon) < 0)
88742542f5fSchristos		goto err_monitor;
88803b705cfSriastradh
88942542f5fSchristos	sna->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon),
89042542f5fSchristos						    sna_handle_uevents, sna);
89142542f5fSchristos	if (!sna->uevent_handler)
89242542f5fSchristos		goto err_monitor;
89303b705cfSriastradh
89442542f5fSchristos	sna->uevent_monitor = mon;
89542542f5fSchristosout:
89663ef14f0Smrg	xf86DrvMsg(sna->scrn->scrnIndex, from,
89763ef14f0Smrg		   "Display hotplug detection %s\n",
89842542f5fSchristos		   sna->uevent_monitor ? "enabled" : "disabled");
89942542f5fSchristos	return;
90042542f5fSchristos
90142542f5fSchristoserr_monitor:
90242542f5fSchristos	udev_monitor_unref(mon);
90342542f5fSchristoserr_dev:
90442542f5fSchristos	udev_unref(u);
90542542f5fSchristos	goto out;
90603b705cfSriastradh}
90703b705cfSriastradh
90813496ba1Ssnjstatic bool sna_uevent_poll(struct sna *sna)
90913496ba1Ssnj{
91013496ba1Ssnj	if (sna->uevent_monitor == NULL)
91113496ba1Ssnj		return false;
91213496ba1Ssnj
91363ef14f0Smrg	sna_handle_uevents(udev_monitor_get_fd(sna->uevent_monitor), sna);
91413496ba1Ssnj	return true;
91513496ba1Ssnj}
91613496ba1Ssnj
91703b705cfSriastradhstatic void
91842542f5fSchristossna_uevent_fini(struct sna *sna)
91903b705cfSriastradh{
92003b705cfSriastradh	struct udev *u;
92103b705cfSriastradh
92203b705cfSriastradh	if (sna->uevent_handler == NULL)
92303b705cfSriastradh		return;
92403b705cfSriastradh
92503b705cfSriastradh	xf86RemoveGeneralHandler(sna->uevent_handler);
92603b705cfSriastradh
92703b705cfSriastradh	u = udev_monitor_get_udev(sna->uevent_monitor);
92803b705cfSriastradh	udev_monitor_unref(sna->uevent_monitor);
92903b705cfSriastradh	udev_unref(u);
93003b705cfSriastradh
93103b705cfSriastradh	sna->uevent_handler = NULL;
93203b705cfSriastradh	sna->uevent_monitor = NULL;
93303b705cfSriastradh
93403b705cfSriastradh	DBG(("%s: removed uvent handler\n", __FUNCTION__));
93503b705cfSriastradh}
93603b705cfSriastradh#else
93742542f5fSchristosstatic void sna_uevent_init(struct sna *sna) { }
93813496ba1Ssnjstatic bool sna_uevent_poll(struct sna *sna) { return false; }
93942542f5fSchristosstatic void sna_uevent_fini(struct sna *sna) { }
94003b705cfSriastradh#endif /* HAVE_UDEV */
94103b705cfSriastradh
94213496ba1Ssnjstatic Bool
94313496ba1Ssnjsna_randr_getinfo(ScreenPtr screen, Rotation *rotations)
94413496ba1Ssnj{
94513496ba1Ssnj	struct sna *sna = to_sna_from_screen(screen);
94613496ba1Ssnj
94763ef14f0Smrg	DBG(("%s()\n", __FUNCTION__));
94863ef14f0Smrg
94913496ba1Ssnj	if (!sna_uevent_poll(sna))
95063ef14f0Smrg		sna_mode_discover(sna, false);
95113496ba1Ssnj
95213496ba1Ssnj	return sna->mode.rrGetInfo(screen, rotations);
95313496ba1Ssnj}
95413496ba1Ssnj
95503b705cfSriastradhstatic void sna_leave_vt(VT_FUNC_ARGS_DECL)
95603b705cfSriastradh{
95703b705cfSriastradh	SCRN_INFO_PTR(arg);
95842542f5fSchristos	struct sna *sna = to_sna(scrn);
95903b705cfSriastradh
96063ef14f0Smrg	DBG(("%s(vtSema=%d)\n", __FUNCTION__, scrn->vtSema));
96103b705cfSriastradh
96242542f5fSchristos	sna_mode_reset(sna);
96363ef14f0Smrg	sna_accel_leave(sna);
96403b705cfSriastradh
96563ef14f0Smrg	if (scrn->vtSema && intel_put_master(sna->dev))
96603b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
96703b705cfSriastradh			   "drmDropMaster failed: %s\n", strerror(errno));
96863ef14f0Smrg
96963ef14f0Smrg	scrn->vtSema = FALSE;
97003b705cfSriastradh}
97103b705cfSriastradh
97203b705cfSriastradhstatic Bool sna_early_close_screen(CLOSE_SCREEN_ARGS_DECL)
97303b705cfSriastradh{
97403b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
97503b705cfSriastradh	struct sna *sna = to_sna(scrn);
97603b705cfSriastradh
97703b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
97803b705cfSriastradh
97903b705cfSriastradh	/* XXX Note that we will leak kernel resources if !vtSema */
98003b705cfSriastradh
98163ef14f0Smrg#if HAVE_NOTIFY_FD
98263ef14f0Smrg	RemoveBlockAndWakeupHandlers(sna_block_handler,
98363ef14f0Smrg				     (ServerWakeupHandlerProcPtr)NoopDDA,
98463ef14f0Smrg				     sna);
98563ef14f0Smrg#endif
98663ef14f0Smrg
98742542f5fSchristos	sna_uevent_fini(sna);
98803b705cfSriastradh	sna_mode_close(sna);
98903b705cfSriastradh
99042542f5fSchristos	if (sna->present.open) {
99142542f5fSchristos		sna_present_close(sna, screen);
99242542f5fSchristos		sna->present.open = false;
99342542f5fSchristos	}
99442542f5fSchristos
99542542f5fSchristos	if (sna->dri3.open) {
99642542f5fSchristos		sna_dri3_close(sna, screen);
99742542f5fSchristos		sna->dri3.open = false;
99842542f5fSchristos	}
99942542f5fSchristos
100042542f5fSchristos	if (sna->dri2.open) {
100142542f5fSchristos		sna_dri2_close(sna, screen);
100242542f5fSchristos		sna->dri2.open = false;
100303b705cfSriastradh	}
100403b705cfSriastradh
100503b705cfSriastradh	if (sna->front) {
100603b705cfSriastradh		screen->DestroyPixmap(sna->front);
100703b705cfSriastradh		sna->front = NULL;
100803b705cfSriastradh	}
100903b705cfSriastradh
101003b705cfSriastradh	if (scrn->vtSema) {
101113496ba1Ssnj		intel_put_master(sna->dev);
101203b705cfSriastradh		scrn->vtSema = FALSE;
101303b705cfSriastradh	}
101403b705cfSriastradh
101503b705cfSriastradh	return sna->CloseScreen(CLOSE_SCREEN_ARGS);
101603b705cfSriastradh}
101703b705cfSriastradh
101803b705cfSriastradhstatic Bool sna_late_close_screen(CLOSE_SCREEN_ARGS_DECL)
101903b705cfSriastradh{
102003b705cfSriastradh	struct sna *sna = to_sna_from_screen(screen);
102103b705cfSriastradh	DepthPtr depths;
102203b705cfSriastradh	int d;
102303b705cfSriastradh
102403b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
102503b705cfSriastradh
102603b705cfSriastradh	sna_accel_close(sna);
102742542f5fSchristos	sna_video_close(sna);
102803b705cfSriastradh
102903b705cfSriastradh	depths = screen->allowedDepths;
103003b705cfSriastradh	for (d = 0; d < screen->numDepths; d++)
103103b705cfSriastradh		free(depths[d].vids);
103203b705cfSriastradh	free(depths);
103303b705cfSriastradh
103403b705cfSriastradh	free(screen->visuals);
103503b705cfSriastradh
103603b705cfSriastradh	return TRUE;
103703b705cfSriastradh}
103803b705cfSriastradh
103903b705cfSriastradhstatic Bool
104003b705cfSriastradhsna_register_all_privates(void)
104103b705cfSriastradh{
104203b705cfSriastradh#if HAS_DIXREGISTERPRIVATEKEY
104303b705cfSriastradh	if (!dixRegisterPrivateKey(&sna_pixmap_key, PRIVATE_PIXMAP,
104403b705cfSriastradh				   3*sizeof(void *)))
104503b705cfSriastradh		return FALSE;
104603b705cfSriastradh
104703b705cfSriastradh	if (!dixRegisterPrivateKey(&sna_gc_key, PRIVATE_GC,
104803b705cfSriastradh				   sizeof(FbGCPrivate)))
104903b705cfSriastradh		return FALSE;
105003b705cfSriastradh
105103b705cfSriastradh	if (!dixRegisterPrivateKey(&sna_glyph_key, PRIVATE_GLYPH,
105203b705cfSriastradh				   sizeof(struct sna_glyph)))
105303b705cfSriastradh		return FALSE;
105403b705cfSriastradh
105503b705cfSriastradh	if (!dixRegisterPrivateKey(&sna_window_key, PRIVATE_WINDOW,
105603b705cfSriastradh				   3*sizeof(void *)))
105703b705cfSriastradh		return FALSE;
105803b705cfSriastradh
105903b705cfSriastradh	if (!dixRegisterPrivateKey(&sna_client_key, PRIVATE_CLIENT,
106003b705cfSriastradh				   sizeof(struct sna_client)))
106103b705cfSriastradh		return FALSE;
106203b705cfSriastradh#else
106303b705cfSriastradh	if (!dixRequestPrivate(&sna_pixmap_key, 3*sizeof(void *)))
106403b705cfSriastradh		return FALSE;
106503b705cfSriastradh
106603b705cfSriastradh	if (!dixRequestPrivate(&sna_gc_key, sizeof(FbGCPrivate)))
106703b705cfSriastradh		return FALSE;
106803b705cfSriastradh
106903b705cfSriastradh	if (!dixRequestPrivate(&sna_glyph_key, sizeof(struct sna_glyph)))
107003b705cfSriastradh		return FALSE;
107103b705cfSriastradh
107203b705cfSriastradh	if (!dixRequestPrivate(&sna_window_key, 3*sizeof(void *)))
107303b705cfSriastradh		return FALSE;
107403b705cfSriastradh
107503b705cfSriastradh	if (!dixRequestPrivate(&sna_client_key, sizeof(struct sna_client)))
107603b705cfSriastradh		return FALSE;
107703b705cfSriastradh#endif
107803b705cfSriastradh
107903b705cfSriastradh	return TRUE;
108003b705cfSriastradh}
108103b705cfSriastradh
108242542f5fSchristosstatic void sna_dri_init(struct sna *sna, ScreenPtr screen)
108342542f5fSchristos{
108442542f5fSchristos	char str[128] = "";
108542542f5fSchristos
108663ef14f0Smrg	if (sna->dri2.enable)
108742542f5fSchristos		sna->dri2.open = sna_dri2_open(sna, screen);
108842542f5fSchristos	if (sna->dri2.open)
108942542f5fSchristos		strcat(str, "DRI2 ");
109042542f5fSchristos
109163ef14f0Smrg	/* Load DRI3 in case DRI2 doesn't work, e.g. vgaarb */
109263ef14f0Smrg	if (sna->dri3.enable || (!sna->dri2.open && !sna->dri3.override))
109342542f5fSchristos		sna->dri3.open = sna_dri3_open(sna, screen);
109442542f5fSchristos	if (sna->dri3.open)
109542542f5fSchristos		strcat(str, "DRI3 ");
109642542f5fSchristos
109742542f5fSchristos	if (*str)
109842542f5fSchristos		xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
109942542f5fSchristos			   "direct rendering: %senabled\n", str);
110042542f5fSchristos}
110142542f5fSchristos
110213496ba1Ssnjstatic Bool
110313496ba1Ssnjsna_mode_init(struct sna *sna, ScreenPtr screen)
110403b705cfSriastradh{
110513496ba1Ssnj	rrScrPrivPtr rp;
110613496ba1Ssnj
110713496ba1Ssnj	if (!xf86CrtcScreenInit(screen))
110813496ba1Ssnj		return FALSE;
110913496ba1Ssnj
111013496ba1Ssnj	xf86RandR12SetRotations(screen, RR_Rotate_All | RR_Reflect_All);
111113496ba1Ssnj	xf86RandR12SetTransformSupport(screen, TRUE);
111213496ba1Ssnj
111313496ba1Ssnj	/* Wrap RR queries to catch pending MST topology changes */
111413496ba1Ssnj	rp = rrGetScrPriv(screen);
111513496ba1Ssnj	if (rp) {
111613496ba1Ssnj		sna->mode.rrGetInfo = rp->rrGetInfo;
111713496ba1Ssnj		rp->rrGetInfo = sna_randr_getinfo;
111863ef14f0Smrg
111963ef14f0Smrg		/* Simulate a hotplug event on wakeup to force a RR probe */
112063ef14f0Smrg		TimerSet(NULL, 0, COLDPLUG_DELAY_MS, sna_mode_coldplug, sna);
112113496ba1Ssnj	}
112213496ba1Ssnj
112313496ba1Ssnj	return TRUE;
112403b705cfSriastradh}
112503b705cfSriastradh
112603b705cfSriastradhstatic Bool
112703b705cfSriastradhsna_screen_init(SCREEN_INIT_ARGS_DECL)
112803b705cfSriastradh{
112903b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
113003b705cfSriastradh	struct sna *sna = to_sna(scrn);
113103b705cfSriastradh	VisualPtr visuals;
113203b705cfSriastradh	DepthPtr depths;
113303b705cfSriastradh	int nvisuals;
113403b705cfSriastradh	int ndepths;
113503b705cfSriastradh	int rootdepth;
113603b705cfSriastradh	VisualID defaultVisual;
113703b705cfSriastradh
113803b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
113903b705cfSriastradh
114003b705cfSriastradh	assert(sna->scrn == scrn);
114163ef14f0Smrg	assert(to_screen_from_sna(sna) == NULL || /* set afterwards */
114263ef14f0Smrg	       to_screen_from_sna(sna) == screen);
114303b705cfSriastradh
114403b705cfSriastradh	assert(sna->freed_pixmap == NULL);
114503b705cfSriastradh
114603b705cfSriastradh	if (!sna_register_all_privates())
114703b705cfSriastradh		return FALSE;
114803b705cfSriastradh
114913496ba1Ssnj	scrn->videoRam = sna->kgem.aperture_mappable * 4; /* Page to KiB */
115003b705cfSriastradh
115103b705cfSriastradh	miClearVisualTypes();
115203b705cfSriastradh	if (!miSetVisualTypes(scrn->depth,
115303b705cfSriastradh			      miGetDefaultVisualMask(scrn->depth),
115403b705cfSriastradh			      scrn->rgbBits, scrn->defaultVisual))
115503b705cfSriastradh		return FALSE;
115603b705cfSriastradh	if (!miSetPixmapDepths())
115703b705cfSriastradh		return FALSE;
115803b705cfSriastradh
115903b705cfSriastradh	rootdepth = 0;
116003b705cfSriastradh	if (!miInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &rootdepth,
116103b705cfSriastradh			   &defaultVisual,
116203b705cfSriastradh			   ((unsigned long)1 << (scrn->bitsPerPixel - 1)),
116363ef14f0Smrg			   scrn->rgbBits, -1))
116403b705cfSriastradh		return FALSE;
116503b705cfSriastradh
116603b705cfSriastradh	if (!miScreenInit(screen, NULL,
116703b705cfSriastradh			  scrn->virtualX, scrn->virtualY,
116803b705cfSriastradh			  scrn->xDpi, scrn->yDpi, 0,
116903b705cfSriastradh			  rootdepth, ndepths, depths,
117003b705cfSriastradh			  defaultVisual, nvisuals, visuals))
117103b705cfSriastradh		return FALSE;
117203b705cfSriastradh
117303b705cfSriastradh	if (scrn->bitsPerPixel > 8) {
117403b705cfSriastradh		/* Fixup RGB ordering */
117503b705cfSriastradh		VisualPtr visual = screen->visuals + screen->numVisuals;
117603b705cfSriastradh		while (--visual >= screen->visuals) {
117703b705cfSriastradh			if ((visual->class | DynamicClass) == DirectColor) {
117803b705cfSriastradh				visual->offsetRed = scrn->offset.red;
117903b705cfSriastradh				visual->offsetGreen = scrn->offset.green;
118003b705cfSriastradh				visual->offsetBlue = scrn->offset.blue;
118103b705cfSriastradh				visual->redMask = scrn->mask.red;
118203b705cfSriastradh				visual->greenMask = scrn->mask.green;
118303b705cfSriastradh				visual->blueMask = scrn->mask.blue;
118403b705cfSriastradh			}
118503b705cfSriastradh		}
118603b705cfSriastradh	}
118703b705cfSriastradh
118803b705cfSriastradh	assert(screen->CloseScreen == NULL);
118903b705cfSriastradh	screen->CloseScreen = sna_late_close_screen;
119003b705cfSriastradh	if (!sna_accel_init(screen, sna)) {
119103b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
119203b705cfSriastradh			   "Hardware acceleration initialization failed\n");
119303b705cfSriastradh		return FALSE;
119403b705cfSriastradh	}
119503b705cfSriastradh
119603b705cfSriastradh	xf86SetBlackWhitePixels(screen);
119703b705cfSriastradh
119803b705cfSriastradh	xf86SetBackingStore(screen);
119903b705cfSriastradh	xf86SetSilkenMouse(screen);
120003b705cfSriastradh	if (!miDCInitialize(screen, xf86GetPointerScreenFuncs()))
120103b705cfSriastradh		return FALSE;
120203b705cfSriastradh
120342542f5fSchristos	if (sna_cursors_init(screen, sna))
120403b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_INFO, "HW Cursor enabled\n");
120503b705cfSriastradh
120603b705cfSriastradh	/* Must force it before EnterVT, so we are in control of VT and
120703b705cfSriastradh	 * later memory should be bound when allocating, e.g rotate_mem */
120803b705cfSriastradh	scrn->vtSema = TRUE;
120903b705cfSriastradh
121063ef14f0Smrg#if !HAVE_NOTIFY_FD
121103b705cfSriastradh	sna->BlockHandler = screen->BlockHandler;
121203b705cfSriastradh	screen->BlockHandler = sna_block_handler;
121303b705cfSriastradh
121403b705cfSriastradh	sna->WakeupHandler = screen->WakeupHandler;
121503b705cfSriastradh	screen->WakeupHandler = sna_wakeup_handler;
121663ef14f0Smrg#else
121763ef14f0Smrg	RegisterBlockAndWakeupHandlers(sna_block_handler,
121863ef14f0Smrg				       (ServerWakeupHandlerProcPtr)NoopDDA,
121963ef14f0Smrg				       sna);
122063ef14f0Smrg#endif
122103b705cfSriastradh
122242542f5fSchristos	screen->SaveScreen = sna_save_screen;
122303b705cfSriastradh	screen->CreateScreenResources = sna_create_screen_resources;
122403b705cfSriastradh
122503b705cfSriastradh	sna->CloseScreen = screen->CloseScreen;
122603b705cfSriastradh	screen->CloseScreen = sna_early_close_screen;
122703b705cfSriastradh
122813496ba1Ssnj	if (!sna_mode_init(sna, screen))
122903b705cfSriastradh		return FALSE;
123003b705cfSriastradh
123103b705cfSriastradh	if (!miCreateDefColormap(screen))
123203b705cfSriastradh		return FALSE;
123303b705cfSriastradh
123463ef14f0Smrg	/* X-Server < 1.20 mishandles > 256 slots / > 8 bpc color maps. */
123563ef14f0Smrg	if (sna->mode.num_real_crtc && (scrn->rgbBits <= 8 ||
123663ef14f0Smrg	    XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,20,0,0,0)) &&
123763ef14f0Smrg	    !xf86HandleColormaps(screen, 1 << scrn->rgbBits, scrn->rgbBits,
123863ef14f0Smrg				 sna_load_palette, NULL,
123903b705cfSriastradh				 CMAP_RELOAD_ON_MODE_SWITCH |
124042542f5fSchristos				 CMAP_PALETTED_TRUECOLOR))
124103b705cfSriastradh		return FALSE;
124203b705cfSriastradh
124363ef14f0Smrg	if (!xf86CheckBoolOption(scrn->options, "dpms", TRUE))
124463ef14f0Smrg		sna->flags |= SNA_NO_DPMS;
124542542f5fSchristos	xf86DPMSInit(screen, sna_dpms_set, 0);
124603b705cfSriastradh
124713496ba1Ssnj	sna_uevent_init(sna);
124803b705cfSriastradh	sna_video_init(sna, screen);
124942542f5fSchristos	sna_dri_init(sna, screen);
125042542f5fSchristos
125142542f5fSchristos	if (sna->present.available)
125242542f5fSchristos		sna->present.open = sna_present_open(sna, screen);
125342542f5fSchristos	if (sna->present.open)
125442542f5fSchristos		xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
125542542f5fSchristos			   "hardware support for Present enabled\n");
125603b705cfSriastradh
125703b705cfSriastradh	if (serverGeneration == 1)
125803b705cfSriastradh		xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options);
125903b705cfSriastradh
126003b705cfSriastradh	sna->suspended = FALSE;
126103b705cfSriastradh
126203b705cfSriastradh	return TRUE;
126303b705cfSriastradh}
126403b705cfSriastradh
126503b705cfSriastradhstatic void sna_adjust_frame(ADJUST_FRAME_ARGS_DECL)
126603b705cfSriastradh{
126703b705cfSriastradh	SCRN_INFO_PTR(arg);
126803b705cfSriastradh	DBG(("%s(%d, %d)\n", __FUNCTION__, x, y));
126903b705cfSriastradh	sna_mode_adjust_frame(to_sna(scrn), x, y);
127003b705cfSriastradh}
127103b705cfSriastradh
127203b705cfSriastradhstatic void sna_free_screen(FREE_SCREEN_ARGS_DECL)
127303b705cfSriastradh{
127403b705cfSriastradh	SCRN_INFO_PTR(arg);
127503b705cfSriastradh	struct sna *sna = to_sna(scrn);
127603b705cfSriastradh
127742542f5fSchristos	DBG(("%s [scrn=%p, sna=%p]\n", __FUNCTION__, scrn, sna));
127842542f5fSchristos	if (sna == NULL || (uintptr_t)sna & 3) /* beware thieves */
127903b705cfSriastradh		return;
128003b705cfSriastradh
128142542f5fSchristos	scrn->driverPrivate = (void *)((uintptr_t)sna->info | (sna->flags & SNA_IS_SLAVED) | 2);
128203b705cfSriastradh
128303b705cfSriastradh	sna_mode_fini(sna);
128442542f5fSchristos	sna_acpi_fini(sna);
128503b705cfSriastradh
128613496ba1Ssnj	intel_put_device(sna->dev);
128713496ba1Ssnj	free(sna);
128803b705cfSriastradh}
128903b705cfSriastradh
129003b705cfSriastradhstatic Bool sna_enter_vt(VT_FUNC_ARGS_DECL)
129103b705cfSriastradh{
129203b705cfSriastradh	SCRN_INFO_PTR(arg);
129303b705cfSriastradh	struct sna *sna = to_sna(scrn);
129403b705cfSriastradh
129563ef14f0Smrg	DBG(("%s(vtSema=%d)\n", __FUNCTION__, scrn->vtSema));
129613496ba1Ssnj	if (intel_get_master(sna->dev))
129703b705cfSriastradh		return FALSE;
129803b705cfSriastradh
129963ef14f0Smrg	scrn->vtSema = TRUE;
130063ef14f0Smrg	sna_accel_enter(sna);
130163ef14f0Smrg
130203b705cfSriastradh	if (sna->flags & SNA_REPROBE) {
130363ef14f0Smrg		DBG(("%s: reporting deferred hotplug event\n", __FUNCTION__));
130463ef14f0Smrg		sna_mode_discover(sna, true);
130503b705cfSriastradh	}
130603b705cfSriastradh
130763ef14f0Smrg	sna_set_desired_mode(sna);
130842542f5fSchristos
130903b705cfSriastradh	return TRUE;
131003b705cfSriastradh}
131103b705cfSriastradh
131203b705cfSriastradhstatic Bool sna_switch_mode(SWITCH_MODE_ARGS_DECL)
131303b705cfSriastradh{
131403b705cfSriastradh	SCRN_INFO_PTR(arg);
131503b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
131603b705cfSriastradh	return xf86SetSingleMode(scrn, mode, RR_Rotate_0);
131703b705cfSriastradh}
131803b705cfSriastradh
131903b705cfSriastradhstatic ModeStatus
132003b705cfSriastradhsna_valid_mode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
132103b705cfSriastradh{
132203b705cfSriastradh	return MODE_OK;
132303b705cfSriastradh}
132403b705cfSriastradh
132503b705cfSriastradh#ifndef SUSPEND_SLEEP
132603b705cfSriastradh#define SUSPEND_SLEEP 0
132703b705cfSriastradh#endif
132803b705cfSriastradh#ifndef RESUME_SLEEP
132903b705cfSriastradh#define RESUME_SLEEP 0
133003b705cfSriastradh#endif
133103b705cfSriastradh
133203b705cfSriastradh/*
133303b705cfSriastradh * This function is only required if we need to do anything differently from
133403b705cfSriastradh * DoApmEvent() in common/xf86PM.c, including if we want to see events other
133503b705cfSriastradh * than suspend/resume.
133603b705cfSriastradh */
133703b705cfSriastradhstatic Bool sna_pm_event(SCRN_ARG_TYPE arg, pmEvent event, Bool undo)
133803b705cfSriastradh{
133903b705cfSriastradh	SCRN_INFO_PTR(arg);
134003b705cfSriastradh	struct sna *sna = to_sna(scrn);
134103b705cfSriastradh
134203b705cfSriastradh	DBG(("%s\n", __FUNCTION__));
134303b705cfSriastradh
134403b705cfSriastradh	switch (event) {
134503b705cfSriastradh	case XF86_APM_SYS_SUSPEND:
134603b705cfSriastradh	case XF86_APM_CRITICAL_SUSPEND:	/*do we want to delay a critical suspend? */
134703b705cfSriastradh	case XF86_APM_USER_SUSPEND:
134803b705cfSriastradh	case XF86_APM_SYS_STANDBY:
134903b705cfSriastradh	case XF86_APM_USER_STANDBY:
135003b705cfSriastradh		if (!undo && !sna->suspended) {
135103b705cfSriastradh			scrn->LeaveVT(VT_FUNC_ARGS(0));
135203b705cfSriastradh			sna->suspended = TRUE;
135303b705cfSriastradh			sleep(SUSPEND_SLEEP);
135403b705cfSriastradh		} else if (undo && sna->suspended) {
135503b705cfSriastradh			sleep(RESUME_SLEEP);
135603b705cfSriastradh			scrn->EnterVT(VT_FUNC_ARGS(0));
135703b705cfSriastradh			sna->suspended = FALSE;
135803b705cfSriastradh		}
135903b705cfSriastradh		break;
136003b705cfSriastradh	case XF86_APM_STANDBY_RESUME:
136103b705cfSriastradh	case XF86_APM_NORMAL_RESUME:
136203b705cfSriastradh	case XF86_APM_CRITICAL_RESUME:
136303b705cfSriastradh		if (sna->suspended) {
136403b705cfSriastradh			sleep(RESUME_SLEEP);
136503b705cfSriastradh			scrn->EnterVT(VT_FUNC_ARGS(0));
136603b705cfSriastradh			sna->suspended = FALSE;
136703b705cfSriastradh			/*
136803b705cfSriastradh			 * Turn the screen saver off when resuming.  This seems to be
136903b705cfSriastradh			 * needed to stop xscreensaver kicking in (when used).
137003b705cfSriastradh			 *
137103b705cfSriastradh			 * XXX DoApmEvent() should probably call this just like
137203b705cfSriastradh			 * xf86VTSwitch() does.  Maybe do it here only in 4.2
137303b705cfSriastradh			 * compatibility mode.
137403b705cfSriastradh			 */
137503b705cfSriastradh			SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
137603b705cfSriastradh		}
137703b705cfSriastradh		break;
137803b705cfSriastradh		/* This is currently used for ACPI */
137903b705cfSriastradh	case XF86_APM_CAPABILITY_CHANGED:
138003b705cfSriastradh		SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
138103b705cfSriastradh		break;
138203b705cfSriastradh
138303b705cfSriastradh	default:
138442542f5fSchristos		ERR(("sna_pm_event: received APM event %d\n", event));
138503b705cfSriastradh	}
138603b705cfSriastradh	return TRUE;
138703b705cfSriastradh}
138803b705cfSriastradh
138903b705cfSriastradhstatic Bool sna_enter_vt__hosted(VT_FUNC_ARGS_DECL)
139003b705cfSriastradh{
139103b705cfSriastradh	return TRUE;
139203b705cfSriastradh}
139303b705cfSriastradh
139403b705cfSriastradhstatic void sna_leave_vt__hosted(VT_FUNC_ARGS_DECL)
139503b705cfSriastradh{
139603b705cfSriastradh}
139703b705cfSriastradh
139842542f5fSchristosstatic void describe_kms(ScrnInfoPtr scrn)
139942542f5fSchristos{
140042542f5fSchristos	int fd = __intel_peek_fd(scrn);
140142542f5fSchristos	drm_version_t version;
140242542f5fSchristos	char name[128] = "";
140342542f5fSchristos	char date[128] = "";
140442542f5fSchristos
140542542f5fSchristos	memset(&version, 0, sizeof(version));
140642542f5fSchristos	version.name_len = sizeof(name) - 1;
140742542f5fSchristos	version.name = name;
140842542f5fSchristos	version.date_len = sizeof(date) - 1;
140942542f5fSchristos	version.date = date;
141042542f5fSchristos
141142542f5fSchristos	if (drmIoctl(fd, DRM_IOCTL_VERSION, &version))
141242542f5fSchristos		return;
141342542f5fSchristos
141442542f5fSchristos	xf86DrvMsg(scrn->scrnIndex, X_INFO,
141542542f5fSchristos		   "Using Kernel Mode Setting driver: %s, version %d.%d.%d %s\n",
141642542f5fSchristos		   version.name,
141742542f5fSchristos		   version.version_major, version.version_minor, version.version_patchlevel,
141842542f5fSchristos		   version.date);
141942542f5fSchristos}
142042542f5fSchristos
142142542f5fSchristosstatic void describe_sna(ScrnInfoPtr scrn)
142203b705cfSriastradh{
142303b705cfSriastradh#if defined(USE_GIT_DESCRIBE)
142403b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
142503b705cfSriastradh		   "SNA compiled from %s\n", git_version);
142603b705cfSriastradh#elif defined(BUILDER_DESCRIPTION)
142703b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
142803b705cfSriastradh		   "SNA compiled: %s\n", BUILDER_DESCRIPTION);
142903b705cfSriastradh#endif
143063ef14f0Smrg#if HAS_DEBUG_FULL
143163ef14f0Smrg	ErrorF("SNA compiled with full debug logging; expect to run slowly\n");
143263ef14f0Smrg#endif
143303b705cfSriastradh#if !NDEBUG
143403b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
143503b705cfSriastradh		   "SNA compiled with assertions enabled\n");
143603b705cfSriastradh#endif
143703b705cfSriastradh#if DEBUG_SYNC
143803b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
143903b705cfSriastradh		   "SNA compiled with synchronous rendering\n");
144003b705cfSriastradh#endif
144103b705cfSriastradh#if DEBUG_MEMORY
144203b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
144303b705cfSriastradh		   "SNA compiled with memory allocation reporting enabled\n");
144403b705cfSriastradh#endif
144503b705cfSriastradh#if DEBUG_PIXMAP
144603b705cfSriastradh	xf86DrvMsg(scrn->scrnIndex, X_INFO,
144703b705cfSriastradh		   "SNA compiled with extra pixmap/damage validation\n");
144842542f5fSchristos#endif
144942542f5fSchristos#ifdef HAVE_VALGRIND
145042542f5fSchristos	xf86DrvMsg(scrn->scrnIndex, X_INFO,
145142542f5fSchristos		   "SNA compiled for use with valgrind\n");
145242542f5fSchristos	VALGRIND_PRINTF("SNA compiled for use with valgrind\n");
145303b705cfSriastradh#endif
145463ef14f0Smrg	DBG(("xf86-video-intel version: %s\n", git_version));
145503b705cfSriastradh	DBG(("pixman version: %s\n", pixman_version_string()));
145642542f5fSchristos}
145742542f5fSchristos
145842542f5fSchristosBool sna_init_scrn(ScrnInfoPtr scrn, int entity_num)
145942542f5fSchristos{
146042542f5fSchristos	DBG(("%s: entity_num=%d\n", __FUNCTION__, entity_num));
146142542f5fSchristos	describe_kms(scrn);
146242542f5fSchristos	describe_sna(scrn);
146303b705cfSriastradh
146403b705cfSriastradh	scrn->PreInit = sna_pre_init;
146503b705cfSriastradh	scrn->ScreenInit = sna_screen_init;
146603b705cfSriastradh	if (!hosted()) {
146703b705cfSriastradh		scrn->SwitchMode = sna_switch_mode;
146803b705cfSriastradh		scrn->AdjustFrame = sna_adjust_frame;
146903b705cfSriastradh		scrn->EnterVT = sna_enter_vt;
147003b705cfSriastradh		scrn->LeaveVT = sna_leave_vt;
147103b705cfSriastradh		scrn->ValidMode = sna_valid_mode;
147203b705cfSriastradh		scrn->PMEvent = sna_pm_event;
147303b705cfSriastradh	} else {
147403b705cfSriastradh		scrn->EnterVT = sna_enter_vt__hosted;
147503b705cfSriastradh		scrn->LeaveVT = sna_leave_vt__hosted;
147603b705cfSriastradh	}
147703b705cfSriastradh	scrn->FreeScreen = sna_free_screen;
147803b705cfSriastradh
147903b705cfSriastradh	xf86SetEntitySharable(entity_num);
148003b705cfSriastradh	xf86SetEntityInstanceForScreen(scrn, entity_num,
148103b705cfSriastradh				       xf86GetNumEntityInstances(entity_num)-1);
148203b705cfSriastradh
148303b705cfSriastradh	sna_threads_init();
148403b705cfSriastradh
148503b705cfSriastradh	return TRUE;
148603b705cfSriastradh}
148742542f5fSchristos
148842542f5fSchristos#if HAS_DEBUG_FULL
148942542f5fSchristos_X_ATTRIBUTE_PRINTF(1, 0) void LogF(const char *f, ...)
149042542f5fSchristos{
149142542f5fSchristos	va_list ap;
149242542f5fSchristos
149342542f5fSchristos	/* As we not only may be called from any context, we may also
149442542f5fSchristos	 * be called from a thread whilst the main thread is handling
149542542f5fSchristos	 * signals, therefore we have to use the signal-safe variants
149642542f5fSchristos	 * or else we trip over false positive assertions.
149742542f5fSchristos	 */
149842542f5fSchristos
149942542f5fSchristos	va_start(ap, f);
150042542f5fSchristos#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
150142542f5fSchristos	LogVMessageVerbSigSafe(X_NONE, 1, f, ap);
150242542f5fSchristos#else
150342542f5fSchristos	LogVMessageVerb(X_NONE, 1, f, ap);
150442542f5fSchristos#endif
150542542f5fSchristos	va_end(ap);
150642542f5fSchristos}
150742542f5fSchristos#endif
1508