sna_driver.c revision 13496ba1
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 6003b705cfSriastradh#include <sys/ioctl.h> 6103b705cfSriastradh#include <sys/fcntl.h> 6213496ba1Ssnj#include <sys/poll.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 25213496ba1Ssnj /* Prefer to use the GPU for rendering into the eventual scanout 25313496ba1Ssnj * bo so that we do not unduly stall when it is time to attach 25413496ba1Ssnj * it to the CRTCs. 25513496ba1Ssnj */ 25613496ba1Ssnj (void)sna_pixmap_force_to_gpu(new_front, MOVE_READ | __MOVE_SCANOUT); 25703b705cfSriastradh 25842542f5fSchristos screen->SetScreenPixmap(new_front); 25942542f5fSchristos assert(screen->GetScreenPixmap(screen) == new_front); 26042542f5fSchristos assert(sna->front == new_front); 26142542f5fSchristos screen->DestroyPixmap(new_front); /* transfer ownership to screen */ 26242542f5fSchristos 26342542f5fSchristos sna_mode_set_primary(sna); 26403b705cfSriastradh 26513496ba1Ssnj /* Try to become master and copy the current fbcon before the 26613496ba1Ssnj * actual VT switch. If we fail here, we will try to reset the 26713496ba1Ssnj * mode in the eventual VT switch. This can fail if systemd has 26813496ba1Ssnj * already revoked our KMS privileges, so just carry on regardless, 26913496ba1Ssnj * and hope that everything is sorted after the VT switch. 27013496ba1Ssnj */ 27113496ba1Ssnj if (intel_get_master(sna->dev) == 0) { 27213496ba1Ssnj /* Only preserve the fbcon, not any subsequent server regens */ 27313496ba1Ssnj if (serverGeneration == 1 && (sna->flags & SNA_IS_HOSTED) == 0) 27413496ba1Ssnj sna_copy_fbcon(sna); 27503b705cfSriastradh 27613496ba1Ssnj (void)sna_set_desired_mode(sna); 27703b705cfSriastradh } 27803b705cfSriastradh 27903b705cfSriastradh return TRUE; 28003b705cfSriastradh} 28103b705cfSriastradh 28242542f5fSchristosstatic Bool sna_save_screen(ScreenPtr screen, int mode) 28303b705cfSriastradh{ 28442542f5fSchristos ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 28542542f5fSchristos 28642542f5fSchristos DBG(("%s(mode=%d)\n", __FUNCTION__, mode)); 28742542f5fSchristos if (!scrn->vtSema) 28842542f5fSchristos return FALSE; 28942542f5fSchristos 29042542f5fSchristos xf86SaveScreen(screen, mode); 29142542f5fSchristos sna_crtc_config_notify(screen); 29242542f5fSchristos return TRUE; 29303b705cfSriastradh} 29403b705cfSriastradh 29542542f5fSchristosstatic void sna_dpms_set(ScrnInfoPtr scrn, int mode, int flags) 29603b705cfSriastradh{ 29742542f5fSchristos DBG(("%s(mode=%d, flags=%d)\n", __FUNCTION__, mode)); 29842542f5fSchristos if (!scrn->vtSema) 29942542f5fSchristos return; 30003b705cfSriastradh 30142542f5fSchristos xf86DPMSSet(scrn, mode, flags); 30242542f5fSchristos sna_crtc_config_notify(xf86ScrnToScreen(scrn)); 30342542f5fSchristos} 30403b705cfSriastradh 30542542f5fSchristosstatic void sna_selftest(void) 30642542f5fSchristos{ 30742542f5fSchristos sna_damage_selftest(); 30842542f5fSchristos} 30903b705cfSriastradh 31042542f5fSchristosstatic bool has_vsync(struct sna *sna) 31142542f5fSchristos{ 31242542f5fSchristos if (sna->flags & SNA_IS_HOSTED) 31303b705cfSriastradh return false; 31403b705cfSriastradh 31542542f5fSchristos return true; 31603b705cfSriastradh} 31703b705cfSriastradh 31803b705cfSriastradhstatic void sna_setup_capabilities(ScrnInfoPtr scrn, int fd) 31903b705cfSriastradh{ 32003b705cfSriastradh#if HAS_PIXMAP_SHARING && defined(DRM_CAP_PRIME) 32103b705cfSriastradh uint64_t value; 32203b705cfSriastradh 32303b705cfSriastradh scrn->capabilities = 0; 32403b705cfSriastradh if (drmGetCap(fd, DRM_CAP_PRIME, &value) == 0) { 32503b705cfSriastradh if (value & DRM_PRIME_CAP_EXPORT) 32603b705cfSriastradh scrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload; 32703b705cfSriastradh if (value & DRM_PRIME_CAP_IMPORT) 32803b705cfSriastradh scrn->capabilities |= RR_Capability_SinkOutput; 32903b705cfSriastradh } 33003b705cfSriastradh#endif 33103b705cfSriastradh} 33203b705cfSriastradh 33342542f5fSchristosstatic int 33442542f5fSchristosnamecmp(const char *s1, const char *s2) 33542542f5fSchristos{ 33642542f5fSchristos char c1, c2; 33742542f5fSchristos 33842542f5fSchristos if (!s1 || *s1 == 0) { 33942542f5fSchristos if (!s2 || *s2 == 0) 34042542f5fSchristos return 0; 34142542f5fSchristos else 34242542f5fSchristos return 1; 34342542f5fSchristos } 34442542f5fSchristos 34542542f5fSchristos while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') 34642542f5fSchristos s1++; 34742542f5fSchristos 34842542f5fSchristos while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') 34942542f5fSchristos s2++; 35042542f5fSchristos 35142542f5fSchristos c1 = isupper(*s1) ? tolower(*s1) : *s1; 35242542f5fSchristos c2 = isupper(*s2) ? tolower(*s2) : *s2; 35342542f5fSchristos while (c1 == c2) { 35442542f5fSchristos if (c1 == '\0') 35542542f5fSchristos return 0; 35642542f5fSchristos 35742542f5fSchristos s1++; 35842542f5fSchristos while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') 35942542f5fSchristos s1++; 36042542f5fSchristos 36142542f5fSchristos s2++; 36242542f5fSchristos while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') 36342542f5fSchristos s2++; 36442542f5fSchristos 36542542f5fSchristos c1 = isupper(*s1) ? tolower(*s1) : *s1; 36642542f5fSchristos c2 = isupper(*s2) ? tolower(*s2) : *s2; 36742542f5fSchristos } 36842542f5fSchristos 36942542f5fSchristos return c1 - c2; 37042542f5fSchristos} 37142542f5fSchristos 37203b705cfSriastradhstatic Bool sna_option_cast_to_bool(struct sna *sna, int id, Bool val) 37303b705cfSriastradh{ 37442542f5fSchristos const char *str = xf86GetOptValString(sna->Options, id); 37542542f5fSchristos 37642542f5fSchristos if (str == NULL) 37742542f5fSchristos return val; 37842542f5fSchristos 37942542f5fSchristos if (*str == '\0') 38042542f5fSchristos return TRUE; 38142542f5fSchristos 38242542f5fSchristos if (namecmp(str, "1") == 0) 38342542f5fSchristos return TRUE; 38442542f5fSchristos if (namecmp(str, "on") == 0) 38542542f5fSchristos return TRUE; 38642542f5fSchristos if (namecmp(str, "true") == 0) 38742542f5fSchristos return TRUE; 38842542f5fSchristos if (namecmp(str, "yes") == 0) 38942542f5fSchristos return TRUE; 39042542f5fSchristos 39142542f5fSchristos if (namecmp(str, "0") == 0) 39242542f5fSchristos return FALSE; 39342542f5fSchristos if (namecmp(str, "off") == 0) 39442542f5fSchristos return FALSE; 39542542f5fSchristos if (namecmp(str, "false") == 0) 39642542f5fSchristos return FALSE; 39742542f5fSchristos if (namecmp(str, "no") == 0) 39842542f5fSchristos return FALSE; 39942542f5fSchristos 40042542f5fSchristos return val; 40142542f5fSchristos} 40242542f5fSchristos 40342542f5fSchristosstatic unsigned sna_option_cast_to_unsigned(struct sna *sna, int id, unsigned val) 40442542f5fSchristos{ 40542542f5fSchristos const char *str = xf86GetOptValString(sna->Options, id); 40642542f5fSchristos unsigned v; 40742542f5fSchristos 40842542f5fSchristos if (str == NULL || *str == '\0') 40942542f5fSchristos return val; 41042542f5fSchristos 41142542f5fSchristos if (namecmp(str, "on") == 0) 41242542f5fSchristos return val; 41342542f5fSchristos if (namecmp(str, "true") == 0) 41442542f5fSchristos return val; 41542542f5fSchristos if (namecmp(str, "yes") == 0) 41642542f5fSchristos return val; 41742542f5fSchristos 41842542f5fSchristos if (namecmp(str, "0") == 0) 41942542f5fSchristos return 0; 42042542f5fSchristos if (namecmp(str, "off") == 0) 42142542f5fSchristos return 0; 42242542f5fSchristos if (namecmp(str, "false") == 0) 42342542f5fSchristos return 0; 42442542f5fSchristos if (namecmp(str, "no") == 0) 42542542f5fSchristos return 0; 42642542f5fSchristos 42742542f5fSchristos v = atoi(str); 42842542f5fSchristos if (v) 42942542f5fSchristos return v; 43042542f5fSchristos 43103b705cfSriastradh return val; 43203b705cfSriastradh} 43303b705cfSriastradh 43403b705cfSriastradhstatic Bool fb_supports_depth(int fd, int depth) 43503b705cfSriastradh{ 43603b705cfSriastradh struct drm_i915_gem_create create; 43703b705cfSriastradh struct drm_mode_fb_cmd fb; 43842542f5fSchristos struct drm_mode_card_res res; 43903b705cfSriastradh Bool ret; 44003b705cfSriastradh 44142542f5fSchristos memset(&res, 0, sizeof(res)); 44242542f5fSchristos (void)drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res); 44342542f5fSchristos if (res.count_crtcs == 0) 44442542f5fSchristos return TRUE; 44542542f5fSchristos 44603b705cfSriastradh VG_CLEAR(create); 44703b705cfSriastradh create.handle = 0; 44803b705cfSriastradh create.size = 4096; 44903b705cfSriastradh if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create)) 45003b705cfSriastradh return FALSE; 45103b705cfSriastradh 45203b705cfSriastradh VG_CLEAR(fb); 45303b705cfSriastradh fb.width = 64; 45403b705cfSriastradh fb.height = 16; 45503b705cfSriastradh fb.pitch = 256; 45603b705cfSriastradh fb.bpp = depth <= 8 ? 8 : depth <= 16 ? 16 : 32; 45703b705cfSriastradh fb.depth = depth; 45803b705cfSriastradh fb.handle = create.handle; 45903b705cfSriastradh 46003b705cfSriastradh ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB, &fb) == 0; 46103b705cfSriastradh drmModeRmFB(fd, fb.fb_id); 46203b705cfSriastradh 46342542f5fSchristos (void)drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &create.handle); 46403b705cfSriastradh 46503b705cfSriastradh return ret; 46603b705cfSriastradh} 46703b705cfSriastradh 46842542f5fSchristosstatic void setup_dri(struct sna *sna) 46942542f5fSchristos{ 47042542f5fSchristos unsigned level; 47142542f5fSchristos 47242542f5fSchristos sna->dri2.available = false; 47342542f5fSchristos sna->dri3.available = false; 47442542f5fSchristos 47542542f5fSchristos level = sna_option_cast_to_unsigned(sna, OPTION_DRI, ~0); 47642542f5fSchristos#if HAVE_DRI3 47742542f5fSchristos if (level >= 3) 47842542f5fSchristos sna->dri3.available = !!xf86LoadSubModule(sna->scrn, "dri3"); 47942542f5fSchristos#endif 48042542f5fSchristos#if HAVE_DRI2 48142542f5fSchristos if (level >= 2) 48242542f5fSchristos sna->dri2.available = !!xf86LoadSubModule(sna->scrn, "dri2"); 48342542f5fSchristos#endif 48442542f5fSchristos} 48542542f5fSchristos 48642542f5fSchristosstatic bool enable_tear_free(struct sna *sna) 48742542f5fSchristos{ 48842542f5fSchristos if (sna->flags & SNA_LINEAR_FB) 48942542f5fSchristos return false; 49042542f5fSchristos 49142542f5fSchristos /* Under certain conditions, we should enable TearFree by default, 49242542f5fSchristos * for example when the hardware requires pageflipping to run within 49342542f5fSchristos * its power/performance budget. 49442542f5fSchristos */ 49542542f5fSchristos if (sna_mode_wants_tear_free(sna)) 49642542f5fSchristos return true; 49742542f5fSchristos 49842542f5fSchristos return ENABLE_TEAR_FREE; 49942542f5fSchristos} 50042542f5fSchristos 50142542f5fSchristosstatic void setup_tear_free(struct sna *sna) 50242542f5fSchristos{ 50342542f5fSchristos MessageType from; 50442542f5fSchristos Bool enable; 50542542f5fSchristos 50642542f5fSchristos if (sna->flags & SNA_LINEAR_FB) 50742542f5fSchristos return; 50842542f5fSchristos 50942542f5fSchristos if ((sna->flags & SNA_HAS_FLIP) == 0) { 51042542f5fSchristos from = X_PROBED; 51142542f5fSchristos goto done; 51242542f5fSchristos } 51342542f5fSchristos 51442542f5fSchristos if (!xf86GetOptValBool(sna->Options, OPTION_TEAR_FREE, &enable)) { 51542542f5fSchristos enable = enable_tear_free(sna); 51642542f5fSchristos from = X_DEFAULT; 51742542f5fSchristos } else 51842542f5fSchristos from = X_CONFIG; 51942542f5fSchristos 52042542f5fSchristos if (enable) 52142542f5fSchristos sna->flags |= SNA_TEAR_FREE; 52242542f5fSchristos 52342542f5fSchristosdone: 52442542f5fSchristos xf86DrvMsg(sna->scrn->scrnIndex, from, "TearFree %sabled\n", 52542542f5fSchristos sna->flags & SNA_TEAR_FREE ? "en" : "dis"); 52642542f5fSchristos} 52742542f5fSchristos 52803b705cfSriastradh/** 52903b705cfSriastradh * This is called before ScreenInit to do any require probing of screen 53003b705cfSriastradh * configuration. 53103b705cfSriastradh * 53203b705cfSriastradh * This code generally covers probing, module loading, option handling 53303b705cfSriastradh * card mapping, and RandR setup. 53403b705cfSriastradh * 53503b705cfSriastradh * Since xf86InitialConfiguration ends up requiring that we set video modes 53603b705cfSriastradh * in order to detect configuration, we end up having to do a lot of driver 53703b705cfSriastradh * setup (talking to the DRM, mapping the device, etc.) in this function. 53803b705cfSriastradh * As a result, we want to set up that server initialization once rather 53903b705cfSriastradh * that doing it per generation. 54003b705cfSriastradh */ 54142542f5fSchristosstatic Bool sna_pre_init(ScrnInfoPtr scrn, int probe) 54203b705cfSriastradh{ 54303b705cfSriastradh struct sna *sna; 54403b705cfSriastradh char buf[1024]; 54503b705cfSriastradh rgb defaultWeight = { 0, 0, 0 }; 54603b705cfSriastradh EntityInfoPtr pEnt; 54703b705cfSriastradh Gamma zeros = { 0.0, 0.0, 0.0 }; 54803b705cfSriastradh int fd; 54903b705cfSriastradh 55003b705cfSriastradh DBG(("%s flags=%x, numEntities=%d\n", 55142542f5fSchristos __FUNCTION__, probe, scrn->numEntities)); 55203b705cfSriastradh 55303b705cfSriastradh if (scrn->numEntities != 1) 55403b705cfSriastradh return FALSE; 55503b705cfSriastradh 55603b705cfSriastradh pEnt = xf86GetEntityInfo(scrn->entityList[0]); 55742542f5fSchristos if (pEnt == NULL) { 55842542f5fSchristos ERR(("%s: no EntityInfo found for scrn\n", __FUNCTION__)); 55903b705cfSriastradh return FALSE; 56042542f5fSchristos } 56103b705cfSriastradh 56203b705cfSriastradh if (pEnt->location.type != BUS_PCI 56303b705cfSriastradh#ifdef XSERVER_PLATFORM_BUS 56403b705cfSriastradh && pEnt->location.type != BUS_PLATFORM 56503b705cfSriastradh#endif 56642542f5fSchristos ) { 56742542f5fSchristos ERR(("%s: invalid EntityInfo found for scrn, location=%d\n", __FUNCTION__, pEnt->location.type)); 56803b705cfSriastradh return FALSE; 56942542f5fSchristos } 57003b705cfSriastradh 57142542f5fSchristos if (probe & PROBE_DETECT) 57203b705cfSriastradh return TRUE; 57303b705cfSriastradh 57403b705cfSriastradh sna_selftest(); 57503b705cfSriastradh 57642542f5fSchristos probe = 0; 57742542f5fSchristos if (((uintptr_t)scrn->driverPrivate) & 3) { 57803b705cfSriastradh if (posix_memalign((void **)&sna, 4096, sizeof(*sna))) 57903b705cfSriastradh return FALSE; 58003b705cfSriastradh 58103b705cfSriastradh memset(sna, 0, sizeof(*sna)); /* should be unnecessary */ 58242542f5fSchristos probe = (uintptr_t)scrn->driverPrivate & 1; 58342542f5fSchristos sna->info = (void *)((uintptr_t)scrn->driverPrivate & ~3); 58403b705cfSriastradh scrn->driverPrivate = sna; 58503b705cfSriastradh 58603b705cfSriastradh sna->cpu_features = sna_cpu_detect(); 58742542f5fSchristos sna->acpi.fd = sna_acpi_open(); 58803b705cfSriastradh } 58903b705cfSriastradh sna = to_sna(scrn); 59003b705cfSriastradh sna->scrn = scrn; 59103b705cfSriastradh sna->pEnt = pEnt; 59242542f5fSchristos sna->flags = probe; 59303b705cfSriastradh 59403b705cfSriastradh scrn->displayWidth = 640; /* default it */ 59503b705cfSriastradh 59603b705cfSriastradh scrn->monitor = scrn->confScreen->monitor; 59703b705cfSriastradh scrn->progClock = TRUE; 59803b705cfSriastradh scrn->rgbBits = 8; 59903b705cfSriastradh 60013496ba1Ssnj sna->dev = intel_get_device(scrn, &fd); 60113496ba1Ssnj if (sna->dev == NULL) { 60203b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 60303b705cfSriastradh "Failed to claim DRM device.\n"); 60403b705cfSriastradh goto cleanup; 60503b705cfSriastradh } 60603b705cfSriastradh 60703b705cfSriastradh /* Sanity check */ 60803b705cfSriastradh if (hosted() && (sna->flags & SNA_IS_HOSTED) == 0) { 60903b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 61003b705cfSriastradh "Failed to setup hosted device.\n"); 61103b705cfSriastradh goto cleanup; 61203b705cfSriastradh } 61303b705cfSriastradh 61413496ba1Ssnj intel_detect_chipset(scrn, sna->dev); 61542542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_PROBED, "CPU: %s\n", 61642542f5fSchristos sna_cpu_features_to_string(sna->cpu_features, buf)); 61703b705cfSriastradh 61842542f5fSchristos if (!xf86SetDepthBpp(scrn, 24, 0, 0, 61903b705cfSriastradh Support32bppFb | 62003b705cfSriastradh SupportConvert24to32 | PreferConvert24to32)) 62103b705cfSriastradh goto cleanup; 62203b705cfSriastradh 62303b705cfSriastradh switch (scrn->depth) { 62403b705cfSriastradh case 8: 62503b705cfSriastradh case 15: 62603b705cfSriastradh case 16: 62703b705cfSriastradh case 24: 62803b705cfSriastradh case 30: 62942542f5fSchristos if ((sna->flags & SNA_IS_HOSTED) || 63042542f5fSchristos fb_supports_depth(fd, scrn->depth)) 63103b705cfSriastradh break; 63203b705cfSriastradh default: 63303b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 63403b705cfSriastradh "Given depth (%d) is not supported by the Intel driver and this chipset.\n", 63503b705cfSriastradh scrn->depth); 63603b705cfSriastradh goto cleanup; 63703b705cfSriastradh } 63803b705cfSriastradh xf86PrintDepthBpp(scrn); 63903b705cfSriastradh 64003b705cfSriastradh if (!xf86SetWeight(scrn, defaultWeight, defaultWeight)) 64103b705cfSriastradh goto cleanup; 64203b705cfSriastradh if (!xf86SetDefaultVisual(scrn, -1)) 64303b705cfSriastradh goto cleanup; 64403b705cfSriastradh 64503b705cfSriastradh sna->Options = intel_options_get(scrn); 64603b705cfSriastradh if (sna->Options == NULL) 64703b705cfSriastradh goto cleanup; 64803b705cfSriastradh 64903b705cfSriastradh sna_setup_capabilities(scrn, fd); 65003b705cfSriastradh 65142542f5fSchristos kgem_init(&sna->kgem, fd, 65242542f5fSchristos xf86GetPciInfoForEntity(pEnt->index), 65342542f5fSchristos sna->info->gen); 65403b705cfSriastradh if (xf86ReturnOptValBool(sna->Options, OPTION_ACCEL_DISABLE, FALSE) || 65503b705cfSriastradh !sna_option_cast_to_bool(sna, OPTION_ACCEL_METHOD, TRUE)) { 65603b705cfSriastradh xf86DrvMsg(sna->scrn->scrnIndex, X_CONFIG, 65703b705cfSriastradh "Disabling hardware acceleration.\n"); 65803b705cfSriastradh sna->kgem.wedged = true; 65903b705cfSriastradh } 66003b705cfSriastradh 66103b705cfSriastradh if (xf86ReturnOptValBool(sna->Options, OPTION_TILING_FB, FALSE)) 66242542f5fSchristos sna->flags |= SNA_LINEAR_FB; 66342542f5fSchristos 66442542f5fSchristos if (xf86ReturnOptValBool(sna->Options, OPTION_DELETE_DP12, FALSE)) 66542542f5fSchristos sna->flags |= SNA_REMOVE_OUTPUTS; 66603b705cfSriastradh 66703b705cfSriastradh if (!xf86ReturnOptValBool(sna->Options, OPTION_SWAPBUFFERS_WAIT, TRUE)) 66803b705cfSriastradh sna->flags |= SNA_NO_WAIT; 66942542f5fSchristos DBG(("%s: swapbuffer wait? %s\n", __FUNCTION__, sna->flags & SNA_NO_WAIT ? "disabled" : "enabled")); 67042542f5fSchristos 67142542f5fSchristos if (!has_vsync(sna) || 67242542f5fSchristos !xf86ReturnOptValBool(sna->Options, OPTION_VSYNC, TRUE)) 67342542f5fSchristos sna->flags |= SNA_NO_VSYNC; 67442542f5fSchristos DBG(("%s: vsync? %s\n", __FUNCTION__, sna->flags & SNA_NO_VSYNC ? "disabled" : "enabled")); 67542542f5fSchristos 67642542f5fSchristos if (sna->flags & SNA_IS_HOSTED || 67742542f5fSchristos !xf86ReturnOptValBool(sna->Options, OPTION_PAGEFLIP, TRUE)) 67803b705cfSriastradh sna->flags |= SNA_NO_FLIP; 67942542f5fSchristos DBG(("%s: page flips? %s\n", __FUNCTION__, sna->flags & SNA_NO_FLIP ? "disabled" : "enabled")); 68003b705cfSriastradh 68142542f5fSchristos if ((sna->flags & (SNA_NO_VSYNC | SNA_NO_FLIP | SNA_NO_WAIT)) == 0 && 68242542f5fSchristos xf86ReturnOptValBool(sna->Options, OPTION_TRIPLE_BUFFER, TRUE)) 68342542f5fSchristos sna->flags |= SNA_TRIPLE_BUFFER; 68442542f5fSchristos DBG(("%s: triple buffer? %s\n", __FUNCTION__, sna->flags & SNA_TRIPLE_BUFFER ? "enabled" : "disabled")); 68503b705cfSriastradh 68642542f5fSchristos if (xf86ReturnOptValBool(sna->Options, OPTION_CRTC_PIXMAPS, FALSE)) { 68742542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Forcing per-crtc-pixmaps.\n"); 68842542f5fSchristos sna->flags |= SNA_FORCE_SHADOW; 68942542f5fSchristos } 69003b705cfSriastradh 69103b705cfSriastradh if (!sna_mode_pre_init(scrn, sna)) { 69203b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 69303b705cfSriastradh "No outputs and no modes.\n"); 69403b705cfSriastradh goto cleanup; 69503b705cfSriastradh } 69603b705cfSriastradh scrn->currentMode = scrn->modes; 69703b705cfSriastradh 69842542f5fSchristos setup_tear_free(sna); 69942542f5fSchristos 70003b705cfSriastradh xf86SetGamma(scrn, zeros); 70103b705cfSriastradh xf86SetDpi(scrn, 0, 0); 70203b705cfSriastradh 70342542f5fSchristos setup_dri(sna); 70442542f5fSchristos 70542542f5fSchristos sna->present.available = false; 70642542f5fSchristos if (xf86ReturnOptValBool(sna->Options, OPTION_PRESENT, TRUE)) { 70742542f5fSchristos#if HAVE_PRESENT 70842542f5fSchristos sna->present.available = !!xf86LoadSubModule(scrn, "present"); 70942542f5fSchristos#endif 71042542f5fSchristos } 71142542f5fSchristos 71242542f5fSchristos sna_acpi_init(sna); 71303b705cfSriastradh 71403b705cfSriastradh return TRUE; 71503b705cfSriastradh 71603b705cfSriastradhcleanup: 71742542f5fSchristos scrn->driverPrivate = (void *)((uintptr_t)sna->info | (sna->flags & SNA_IS_SLAVED) | 2); 71813496ba1Ssnj if (sna->dev) 71913496ba1Ssnj intel_put_device(sna->dev); 72003b705cfSriastradh free(sna); 72103b705cfSriastradh return FALSE; 72203b705cfSriastradh} 72303b705cfSriastradh 72442542f5fSchristosstatic bool has_shadow(struct sna *sna) 72542542f5fSchristos{ 72642542f5fSchristos if (!sna->mode.shadow_damage) 72742542f5fSchristos return false; 72842542f5fSchristos 72942542f5fSchristos if (RegionNil(DamageRegion(sna->mode.shadow_damage))) 73042542f5fSchristos return false; 73142542f5fSchristos 73242542f5fSchristos return sna->mode.flip_active == 0; 73342542f5fSchristos} 73442542f5fSchristos 73503b705cfSriastradhstatic void 73603b705cfSriastradhsna_block_handler(BLOCKHANDLER_ARGS_DECL) 73703b705cfSriastradh{ 73803b705cfSriastradh#ifndef XF86_SCRN_INTERFACE 73903b705cfSriastradh struct sna *sna = to_sna(xf86Screens[arg]); 74003b705cfSriastradh#else 74103b705cfSriastradh struct sna *sna = to_sna_from_screen(arg); 74203b705cfSriastradh#endif 74303b705cfSriastradh struct timeval **tv = timeout; 74403b705cfSriastradh 74503b705cfSriastradh DBG(("%s (tv=%ld.%06ld)\n", __FUNCTION__, 74603b705cfSriastradh *tv ? (*tv)->tv_sec : -1, *tv ? (*tv)->tv_usec : 0)); 74703b705cfSriastradh 74803b705cfSriastradh sna->BlockHandler(BLOCKHANDLER_ARGS); 74903b705cfSriastradh 75042542f5fSchristos if (*tv == NULL || ((*tv)->tv_usec | (*tv)->tv_sec) || has_shadow(sna)) 75103b705cfSriastradh sna_accel_block_handler(sna, tv); 75203b705cfSriastradh} 75303b705cfSriastradh 75403b705cfSriastradhstatic void 75503b705cfSriastradhsna_wakeup_handler(WAKEUPHANDLER_ARGS_DECL) 75603b705cfSriastradh{ 75703b705cfSriastradh#ifndef XF86_SCRN_INTERFACE 75803b705cfSriastradh struct sna *sna = to_sna(xf86Screens[arg]); 75903b705cfSriastradh#else 76003b705cfSriastradh struct sna *sna = to_sna_from_screen(arg); 76103b705cfSriastradh#endif 76203b705cfSriastradh 76303b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 76403b705cfSriastradh 76503b705cfSriastradh /* despite all appearances, result is just a signed int */ 76603b705cfSriastradh if ((int)result < 0) 76703b705cfSriastradh return; 76803b705cfSriastradh 76942542f5fSchristos sna_acpi_wakeup(sna, read_mask); 77042542f5fSchristos 77103b705cfSriastradh sna->WakeupHandler(WAKEUPHANDLER_ARGS); 77203b705cfSriastradh 77303b705cfSriastradh sna_accel_wakeup_handler(sna); 77403b705cfSriastradh 77513496ba1Ssnj if (FD_ISSET(sna->kgem.fd, (fd_set*)read_mask)) { 77603b705cfSriastradh sna_mode_wakeup(sna); 77713496ba1Ssnj /* Clear the flag so that subsequent ZaphodHeads don't block */ 77813496ba1Ssnj FD_CLR(sna->kgem.fd, (fd_set*)read_mask); 77913496ba1Ssnj } 78003b705cfSriastradh} 78103b705cfSriastradh 78203b705cfSriastradh#if HAVE_UDEV 78303b705cfSriastradhstatic void 78403b705cfSriastradhsna_handle_uevents(int fd, void *closure) 78503b705cfSriastradh{ 78642542f5fSchristos struct sna *sna = closure; 78703b705cfSriastradh struct udev_device *dev; 78842542f5fSchristos const char *str; 78903b705cfSriastradh struct stat s; 79003b705cfSriastradh dev_t udev_devnum; 79103b705cfSriastradh 79203b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 79303b705cfSriastradh 79403b705cfSriastradh dev = udev_monitor_receive_device(sna->uevent_monitor); 79503b705cfSriastradh if (!dev) 79603b705cfSriastradh return; 79703b705cfSriastradh 79803b705cfSriastradh udev_devnum = udev_device_get_devnum(dev); 79942542f5fSchristos if (fstat(sna->kgem.fd, &s) || memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t))) { 80003b705cfSriastradh udev_device_unref(dev); 80103b705cfSriastradh return; 80203b705cfSriastradh } 80303b705cfSriastradh 80442542f5fSchristos str = udev_device_get_property_value(dev, "HOTPLUG"); 80542542f5fSchristos if (str && atoi(str) == 1) { 80642542f5fSchristos ScrnInfoPtr scrn = sna->scrn; 80703b705cfSriastradh 80842542f5fSchristos DBG(("%s: hotplug event (vtSema?=%d)\n", __FUNCTION__, scrn->vtSema)); 80903b705cfSriastradh 81042542f5fSchristos if (scrn->vtSema) { 81142542f5fSchristos sna_mode_discover(sna); 81242542f5fSchristos sna_mode_check(sna); 81303b705cfSriastradh RRGetInfo(xf86ScrnToScreen(scrn), TRUE); 81403b705cfSriastradh } else 81503b705cfSriastradh sna->flags |= SNA_REPROBE; 81603b705cfSriastradh } 81703b705cfSriastradh 81803b705cfSriastradh udev_device_unref(dev); 81903b705cfSriastradh} 82003b705cfSriastradh 82103b705cfSriastradhstatic void 82242542f5fSchristossna_uevent_init(struct sna *sna) 82303b705cfSriastradh{ 82403b705cfSriastradh struct udev *u; 82503b705cfSriastradh struct udev_monitor *mon; 82603b705cfSriastradh MessageType from = X_CONFIG; 82703b705cfSriastradh 82803b705cfSriastradh if (sna->flags & SNA_IS_HOSTED) 82903b705cfSriastradh return; 83003b705cfSriastradh 83103b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 83203b705cfSriastradh 83303b705cfSriastradh /* RandR will be disabled if Xinerama is active, and so generating 83403b705cfSriastradh * RR hotplug events is then verboten. 83503b705cfSriastradh */ 83603b705cfSriastradh if (!dixPrivateKeyRegistered(rrPrivKey)) 83742542f5fSchristos goto out; 83803b705cfSriastradh 83942542f5fSchristos u = NULL; 84042542f5fSchristos if (xf86ReturnOptValBool(sna->Options, OPTION_HOTPLUG, TRUE)) 84142542f5fSchristos u = udev_new(); 84203b705cfSriastradh if (!u) 84342542f5fSchristos goto out; 84442542f5fSchristos 84542542f5fSchristos from = X_DEFAULT; 84603b705cfSriastradh 84703b705cfSriastradh mon = udev_monitor_new_from_netlink(u, "udev"); 84842542f5fSchristos if (!mon) 84942542f5fSchristos goto err_dev; 85003b705cfSriastradh 85142542f5fSchristos if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") < 0) 85242542f5fSchristos goto err_monitor; 85303b705cfSriastradh 85442542f5fSchristos if (udev_monitor_enable_receiving(mon) < 0) 85542542f5fSchristos goto err_monitor; 85603b705cfSriastradh 85742542f5fSchristos sna->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon), 85842542f5fSchristos sna_handle_uevents, sna); 85942542f5fSchristos if (!sna->uevent_handler) 86042542f5fSchristos goto err_monitor; 86103b705cfSriastradh 86242542f5fSchristos sna->uevent_monitor = mon; 86342542f5fSchristosout: 86442542f5fSchristos xf86DrvMsg(sna->scrn->scrnIndex, from, "display hotplug detection %s\n", 86542542f5fSchristos sna->uevent_monitor ? "enabled" : "disabled"); 86642542f5fSchristos return; 86742542f5fSchristos 86842542f5fSchristoserr_monitor: 86942542f5fSchristos udev_monitor_unref(mon); 87042542f5fSchristoserr_dev: 87142542f5fSchristos udev_unref(u); 87242542f5fSchristos goto out; 87303b705cfSriastradh} 87403b705cfSriastradh 87513496ba1Ssnjstatic bool sna_uevent_poll(struct sna *sna) 87613496ba1Ssnj{ 87713496ba1Ssnj struct pollfd pfd; 87813496ba1Ssnj 87913496ba1Ssnj if (sna->uevent_monitor == NULL) 88013496ba1Ssnj return false; 88113496ba1Ssnj 88213496ba1Ssnj pfd.fd = udev_monitor_get_fd(sna->uevent_monitor); 88313496ba1Ssnj pfd.events = POLLIN; 88413496ba1Ssnj 88513496ba1Ssnj while (poll(&pfd, 1, 0) > 0) 88613496ba1Ssnj sna_handle_uevents(pfd.fd, sna); 88713496ba1Ssnj 88813496ba1Ssnj return true; 88913496ba1Ssnj} 89013496ba1Ssnj 89103b705cfSriastradhstatic void 89242542f5fSchristossna_uevent_fini(struct sna *sna) 89303b705cfSriastradh{ 89403b705cfSriastradh struct udev *u; 89503b705cfSriastradh 89603b705cfSriastradh if (sna->uevent_handler == NULL) 89703b705cfSriastradh return; 89803b705cfSriastradh 89903b705cfSriastradh xf86RemoveGeneralHandler(sna->uevent_handler); 90003b705cfSriastradh 90103b705cfSriastradh u = udev_monitor_get_udev(sna->uevent_monitor); 90203b705cfSriastradh udev_monitor_unref(sna->uevent_monitor); 90303b705cfSriastradh udev_unref(u); 90403b705cfSriastradh 90503b705cfSriastradh sna->uevent_handler = NULL; 90603b705cfSriastradh sna->uevent_monitor = NULL; 90703b705cfSriastradh 90803b705cfSriastradh DBG(("%s: removed uvent handler\n", __FUNCTION__)); 90903b705cfSriastradh} 91003b705cfSriastradh#else 91142542f5fSchristosstatic void sna_uevent_init(struct sna *sna) { } 91213496ba1Ssnjstatic bool sna_uevent_poll(struct sna *sna) { return false; } 91342542f5fSchristosstatic void sna_uevent_fini(struct sna *sna) { } 91403b705cfSriastradh#endif /* HAVE_UDEV */ 91503b705cfSriastradh 91613496ba1Ssnjstatic Bool 91713496ba1Ssnjsna_randr_getinfo(ScreenPtr screen, Rotation *rotations) 91813496ba1Ssnj{ 91913496ba1Ssnj struct sna *sna = to_sna_from_screen(screen); 92013496ba1Ssnj 92113496ba1Ssnj if (!sna_uevent_poll(sna)) 92213496ba1Ssnj sna_mode_discover(sna); 92313496ba1Ssnj 92413496ba1Ssnj return sna->mode.rrGetInfo(screen, rotations); 92513496ba1Ssnj} 92613496ba1Ssnj 92703b705cfSriastradhstatic void sna_leave_vt(VT_FUNC_ARGS_DECL) 92803b705cfSriastradh{ 92903b705cfSriastradh SCRN_INFO_PTR(arg); 93042542f5fSchristos struct sna *sna = to_sna(scrn); 93103b705cfSriastradh 93203b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 93303b705cfSriastradh 93442542f5fSchristos sna_accel_leave(sna); 93542542f5fSchristos sna_mode_reset(sna); 93603b705cfSriastradh 93713496ba1Ssnj if (intel_put_master(sna->dev)) 93803b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, 93903b705cfSriastradh "drmDropMaster failed: %s\n", strerror(errno)); 94003b705cfSriastradh} 94103b705cfSriastradh 94203b705cfSriastradhstatic Bool sna_early_close_screen(CLOSE_SCREEN_ARGS_DECL) 94303b705cfSriastradh{ 94403b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 94503b705cfSriastradh struct sna *sna = to_sna(scrn); 94603b705cfSriastradh 94703b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 94803b705cfSriastradh 94903b705cfSriastradh /* XXX Note that we will leak kernel resources if !vtSema */ 95003b705cfSriastradh 95142542f5fSchristos sna_uevent_fini(sna); 95203b705cfSriastradh sna_mode_close(sna); 95303b705cfSriastradh 95442542f5fSchristos if (sna->present.open) { 95542542f5fSchristos sna_present_close(sna, screen); 95642542f5fSchristos sna->present.open = false; 95742542f5fSchristos } 95842542f5fSchristos 95942542f5fSchristos if (sna->dri3.open) { 96042542f5fSchristos sna_dri3_close(sna, screen); 96142542f5fSchristos sna->dri3.open = false; 96242542f5fSchristos } 96342542f5fSchristos 96442542f5fSchristos if (sna->dri2.open) { 96542542f5fSchristos sna_dri2_close(sna, screen); 96642542f5fSchristos sna->dri2.open = false; 96703b705cfSriastradh } 96803b705cfSriastradh 96903b705cfSriastradh if (sna->front) { 97003b705cfSriastradh screen->DestroyPixmap(sna->front); 97103b705cfSriastradh sna->front = NULL; 97203b705cfSriastradh } 97303b705cfSriastradh 97403b705cfSriastradh if (scrn->vtSema) { 97513496ba1Ssnj intel_put_master(sna->dev); 97603b705cfSriastradh scrn->vtSema = FALSE; 97703b705cfSriastradh } 97803b705cfSriastradh 97903b705cfSriastradh return sna->CloseScreen(CLOSE_SCREEN_ARGS); 98003b705cfSriastradh} 98103b705cfSriastradh 98203b705cfSriastradhstatic Bool sna_late_close_screen(CLOSE_SCREEN_ARGS_DECL) 98303b705cfSriastradh{ 98403b705cfSriastradh struct sna *sna = to_sna_from_screen(screen); 98503b705cfSriastradh DepthPtr depths; 98603b705cfSriastradh int d; 98703b705cfSriastradh 98803b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 98903b705cfSriastradh 99003b705cfSriastradh sna_accel_close(sna); 99142542f5fSchristos sna_video_close(sna); 99203b705cfSriastradh 99303b705cfSriastradh depths = screen->allowedDepths; 99403b705cfSriastradh for (d = 0; d < screen->numDepths; d++) 99503b705cfSriastradh free(depths[d].vids); 99603b705cfSriastradh free(depths); 99703b705cfSriastradh 99803b705cfSriastradh free(screen->visuals); 99903b705cfSriastradh 100003b705cfSriastradh return TRUE; 100103b705cfSriastradh} 100203b705cfSriastradh 100303b705cfSriastradhstatic Bool 100403b705cfSriastradhsna_register_all_privates(void) 100503b705cfSriastradh{ 100603b705cfSriastradh#if HAS_DIXREGISTERPRIVATEKEY 100703b705cfSriastradh if (!dixRegisterPrivateKey(&sna_pixmap_key, PRIVATE_PIXMAP, 100803b705cfSriastradh 3*sizeof(void *))) 100903b705cfSriastradh return FALSE; 101003b705cfSriastradh 101103b705cfSriastradh if (!dixRegisterPrivateKey(&sna_gc_key, PRIVATE_GC, 101203b705cfSriastradh sizeof(FbGCPrivate))) 101303b705cfSriastradh return FALSE; 101403b705cfSriastradh 101503b705cfSriastradh if (!dixRegisterPrivateKey(&sna_glyph_key, PRIVATE_GLYPH, 101603b705cfSriastradh sizeof(struct sna_glyph))) 101703b705cfSriastradh return FALSE; 101803b705cfSriastradh 101903b705cfSriastradh if (!dixRegisterPrivateKey(&sna_window_key, PRIVATE_WINDOW, 102003b705cfSriastradh 3*sizeof(void *))) 102103b705cfSriastradh return FALSE; 102203b705cfSriastradh 102303b705cfSriastradh if (!dixRegisterPrivateKey(&sna_client_key, PRIVATE_CLIENT, 102403b705cfSriastradh sizeof(struct sna_client))) 102503b705cfSriastradh return FALSE; 102603b705cfSriastradh#else 102703b705cfSriastradh if (!dixRequestPrivate(&sna_pixmap_key, 3*sizeof(void *))) 102803b705cfSriastradh return FALSE; 102903b705cfSriastradh 103003b705cfSriastradh if (!dixRequestPrivate(&sna_gc_key, sizeof(FbGCPrivate))) 103103b705cfSriastradh return FALSE; 103203b705cfSriastradh 103303b705cfSriastradh if (!dixRequestPrivate(&sna_glyph_key, sizeof(struct sna_glyph))) 103403b705cfSriastradh return FALSE; 103503b705cfSriastradh 103603b705cfSriastradh if (!dixRequestPrivate(&sna_window_key, 3*sizeof(void *))) 103703b705cfSriastradh return FALSE; 103803b705cfSriastradh 103903b705cfSriastradh if (!dixRequestPrivate(&sna_client_key, sizeof(struct sna_client))) 104003b705cfSriastradh return FALSE; 104103b705cfSriastradh#endif 104203b705cfSriastradh 104303b705cfSriastradh return TRUE; 104403b705cfSriastradh} 104503b705cfSriastradh 104642542f5fSchristosstatic void sna_dri_init(struct sna *sna, ScreenPtr screen) 104742542f5fSchristos{ 104842542f5fSchristos char str[128] = ""; 104942542f5fSchristos 105042542f5fSchristos if (sna->dri2.available) 105142542f5fSchristos sna->dri2.open = sna_dri2_open(sna, screen); 105242542f5fSchristos if (sna->dri2.open) 105342542f5fSchristos strcat(str, "DRI2 "); 105442542f5fSchristos 105542542f5fSchristos if (sna->dri3.available) 105642542f5fSchristos sna->dri3.open = sna_dri3_open(sna, screen); 105742542f5fSchristos if (sna->dri3.open) 105842542f5fSchristos strcat(str, "DRI3 "); 105942542f5fSchristos 106042542f5fSchristos if (*str) 106142542f5fSchristos xf86DrvMsg(sna->scrn->scrnIndex, X_INFO, 106242542f5fSchristos "direct rendering: %senabled\n", str); 106342542f5fSchristos} 106442542f5fSchristos 106513496ba1Ssnjstatic Bool 106613496ba1Ssnjsna_mode_init(struct sna *sna, ScreenPtr screen) 106703b705cfSriastradh{ 106813496ba1Ssnj rrScrPrivPtr rp; 106913496ba1Ssnj 107013496ba1Ssnj if (!xf86CrtcScreenInit(screen)) 107113496ba1Ssnj return FALSE; 107213496ba1Ssnj 107313496ba1Ssnj xf86RandR12SetRotations(screen, RR_Rotate_All | RR_Reflect_All); 107413496ba1Ssnj xf86RandR12SetTransformSupport(screen, TRUE); 107513496ba1Ssnj 107613496ba1Ssnj /* Wrap RR queries to catch pending MST topology changes */ 107713496ba1Ssnj rp = rrGetScrPriv(screen); 107813496ba1Ssnj if (rp) { 107913496ba1Ssnj sna->mode.rrGetInfo = rp->rrGetInfo; 108013496ba1Ssnj rp->rrGetInfo = sna_randr_getinfo; 108113496ba1Ssnj } 108213496ba1Ssnj 108313496ba1Ssnj return TRUE; 108403b705cfSriastradh} 108503b705cfSriastradh 108603b705cfSriastradhstatic Bool 108703b705cfSriastradhsna_screen_init(SCREEN_INIT_ARGS_DECL) 108803b705cfSriastradh{ 108903b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 109003b705cfSriastradh struct sna *sna = to_sna(scrn); 109103b705cfSriastradh VisualPtr visuals; 109203b705cfSriastradh DepthPtr depths; 109303b705cfSriastradh int nvisuals; 109403b705cfSriastradh int ndepths; 109503b705cfSriastradh int rootdepth; 109603b705cfSriastradh VisualID defaultVisual; 109703b705cfSriastradh 109803b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 109903b705cfSriastradh 110003b705cfSriastradh assert(sna->scrn == scrn); 110103b705cfSriastradh assert(scrn->pScreen == NULL); /* set afterwards */ 110203b705cfSriastradh 110303b705cfSriastradh assert(sna->freed_pixmap == NULL); 110403b705cfSriastradh 110503b705cfSriastradh if (!sna_register_all_privates()) 110603b705cfSriastradh return FALSE; 110703b705cfSriastradh 110813496ba1Ssnj scrn->videoRam = sna->kgem.aperture_mappable * 4; /* Page to KiB */ 110903b705cfSriastradh 111003b705cfSriastradh miClearVisualTypes(); 111103b705cfSriastradh if (!miSetVisualTypes(scrn->depth, 111203b705cfSriastradh miGetDefaultVisualMask(scrn->depth), 111303b705cfSriastradh scrn->rgbBits, scrn->defaultVisual)) 111403b705cfSriastradh return FALSE; 111503b705cfSriastradh if (!miSetPixmapDepths()) 111603b705cfSriastradh return FALSE; 111703b705cfSriastradh 111803b705cfSriastradh rootdepth = 0; 111903b705cfSriastradh if (!miInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &rootdepth, 112003b705cfSriastradh &defaultVisual, 112103b705cfSriastradh ((unsigned long)1 << (scrn->bitsPerPixel - 1)), 112203b705cfSriastradh 8, -1)) 112303b705cfSriastradh return FALSE; 112403b705cfSriastradh 112503b705cfSriastradh if (!miScreenInit(screen, NULL, 112603b705cfSriastradh scrn->virtualX, scrn->virtualY, 112703b705cfSriastradh scrn->xDpi, scrn->yDpi, 0, 112803b705cfSriastradh rootdepth, ndepths, depths, 112903b705cfSriastradh defaultVisual, nvisuals, visuals)) 113003b705cfSriastradh return FALSE; 113103b705cfSriastradh 113203b705cfSriastradh if (scrn->bitsPerPixel > 8) { 113303b705cfSriastradh /* Fixup RGB ordering */ 113403b705cfSriastradh VisualPtr visual = screen->visuals + screen->numVisuals; 113503b705cfSriastradh while (--visual >= screen->visuals) { 113603b705cfSriastradh if ((visual->class | DynamicClass) == DirectColor) { 113703b705cfSriastradh visual->offsetRed = scrn->offset.red; 113803b705cfSriastradh visual->offsetGreen = scrn->offset.green; 113903b705cfSriastradh visual->offsetBlue = scrn->offset.blue; 114003b705cfSriastradh visual->redMask = scrn->mask.red; 114103b705cfSriastradh visual->greenMask = scrn->mask.green; 114203b705cfSriastradh visual->blueMask = scrn->mask.blue; 114303b705cfSriastradh } 114403b705cfSriastradh } 114503b705cfSriastradh } 114603b705cfSriastradh 114703b705cfSriastradh assert(screen->CloseScreen == NULL); 114803b705cfSriastradh screen->CloseScreen = sna_late_close_screen; 114903b705cfSriastradh if (!sna_accel_init(screen, sna)) { 115003b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 115103b705cfSriastradh "Hardware acceleration initialization failed\n"); 115203b705cfSriastradh return FALSE; 115303b705cfSriastradh } 115403b705cfSriastradh 115503b705cfSriastradh xf86SetBlackWhitePixels(screen); 115603b705cfSriastradh 115703b705cfSriastradh xf86SetBackingStore(screen); 115803b705cfSriastradh xf86SetSilkenMouse(screen); 115903b705cfSriastradh if (!miDCInitialize(screen, xf86GetPointerScreenFuncs())) 116003b705cfSriastradh return FALSE; 116103b705cfSriastradh 116242542f5fSchristos if (sna_cursors_init(screen, sna)) 116303b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, "HW Cursor enabled\n"); 116403b705cfSriastradh 116503b705cfSriastradh /* Must force it before EnterVT, so we are in control of VT and 116603b705cfSriastradh * later memory should be bound when allocating, e.g rotate_mem */ 116703b705cfSriastradh scrn->vtSema = TRUE; 116803b705cfSriastradh 116903b705cfSriastradh sna->BlockHandler = screen->BlockHandler; 117003b705cfSriastradh screen->BlockHandler = sna_block_handler; 117103b705cfSriastradh 117203b705cfSriastradh sna->WakeupHandler = screen->WakeupHandler; 117303b705cfSriastradh screen->WakeupHandler = sna_wakeup_handler; 117403b705cfSriastradh 117542542f5fSchristos screen->SaveScreen = sna_save_screen; 117603b705cfSriastradh screen->CreateScreenResources = sna_create_screen_resources; 117703b705cfSriastradh 117803b705cfSriastradh sna->CloseScreen = screen->CloseScreen; 117903b705cfSriastradh screen->CloseScreen = sna_early_close_screen; 118003b705cfSriastradh 118113496ba1Ssnj if (!sna_mode_init(sna, screen)) 118203b705cfSriastradh return FALSE; 118303b705cfSriastradh 118403b705cfSriastradh if (!miCreateDefColormap(screen)) 118503b705cfSriastradh return FALSE; 118603b705cfSriastradh 118742542f5fSchristos if (sna->mode.num_real_crtc && 118842542f5fSchristos !xf86HandleColormaps(screen, 256, 8, sna_load_palette, NULL, 118903b705cfSriastradh CMAP_RELOAD_ON_MODE_SWITCH | 119042542f5fSchristos CMAP_PALETTED_TRUECOLOR)) 119103b705cfSriastradh return FALSE; 119203b705cfSriastradh 119342542f5fSchristos xf86DPMSInit(screen, sna_dpms_set, 0); 119403b705cfSriastradh 119513496ba1Ssnj sna_uevent_init(sna); 119603b705cfSriastradh sna_video_init(sna, screen); 119742542f5fSchristos sna_dri_init(sna, screen); 119842542f5fSchristos 119942542f5fSchristos if (sna->present.available) 120042542f5fSchristos sna->present.open = sna_present_open(sna, screen); 120142542f5fSchristos if (sna->present.open) 120242542f5fSchristos xf86DrvMsg(sna->scrn->scrnIndex, X_INFO, 120342542f5fSchristos "hardware support for Present enabled\n"); 120403b705cfSriastradh 120503b705cfSriastradh if (serverGeneration == 1) 120603b705cfSriastradh xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options); 120703b705cfSriastradh 120803b705cfSriastradh sna->suspended = FALSE; 120903b705cfSriastradh 121003b705cfSriastradh return TRUE; 121103b705cfSriastradh} 121203b705cfSriastradh 121303b705cfSriastradhstatic void sna_adjust_frame(ADJUST_FRAME_ARGS_DECL) 121403b705cfSriastradh{ 121503b705cfSriastradh SCRN_INFO_PTR(arg); 121603b705cfSriastradh DBG(("%s(%d, %d)\n", __FUNCTION__, x, y)); 121703b705cfSriastradh sna_mode_adjust_frame(to_sna(scrn), x, y); 121803b705cfSriastradh} 121903b705cfSriastradh 122003b705cfSriastradhstatic void sna_free_screen(FREE_SCREEN_ARGS_DECL) 122103b705cfSriastradh{ 122203b705cfSriastradh SCRN_INFO_PTR(arg); 122303b705cfSriastradh struct sna *sna = to_sna(scrn); 122403b705cfSriastradh 122542542f5fSchristos DBG(("%s [scrn=%p, sna=%p]\n", __FUNCTION__, scrn, sna)); 122642542f5fSchristos if (sna == NULL || (uintptr_t)sna & 3) /* beware thieves */ 122703b705cfSriastradh return; 122803b705cfSriastradh 122942542f5fSchristos scrn->driverPrivate = (void *)((uintptr_t)sna->info | (sna->flags & SNA_IS_SLAVED) | 2); 123003b705cfSriastradh 123103b705cfSriastradh sna_mode_fini(sna); 123242542f5fSchristos sna_acpi_fini(sna); 123303b705cfSriastradh 123413496ba1Ssnj intel_put_device(sna->dev); 123513496ba1Ssnj free(sna); 123603b705cfSriastradh} 123703b705cfSriastradh 123803b705cfSriastradhstatic Bool sna_enter_vt(VT_FUNC_ARGS_DECL) 123903b705cfSriastradh{ 124003b705cfSriastradh SCRN_INFO_PTR(arg); 124103b705cfSriastradh struct sna *sna = to_sna(scrn); 124203b705cfSriastradh 124303b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 124413496ba1Ssnj if (intel_get_master(sna->dev)) 124503b705cfSriastradh return FALSE; 124603b705cfSriastradh 124703b705cfSriastradh if (sna->flags & SNA_REPROBE) { 124842542f5fSchristos DBG(("%s: reporting deferred hotplug event\n", 124942542f5fSchristos __FUNCTION__)); 125042542f5fSchristos sna_mode_discover(sna); 125103b705cfSriastradh RRGetInfo(xf86ScrnToScreen(scrn), TRUE); 125203b705cfSriastradh sna->flags &= ~SNA_REPROBE; 125303b705cfSriastradh } 125403b705cfSriastradh 125542542f5fSchristos if (!sna_set_desired_mode(sna)) { 125613496ba1Ssnj intel_put_master(sna->dev); 125742542f5fSchristos return FALSE; 125842542f5fSchristos } 125942542f5fSchristos 126042542f5fSchristos sna_accel_enter(sna); 126103b705cfSriastradh return TRUE; 126203b705cfSriastradh} 126303b705cfSriastradh 126403b705cfSriastradhstatic Bool sna_switch_mode(SWITCH_MODE_ARGS_DECL) 126503b705cfSriastradh{ 126603b705cfSriastradh SCRN_INFO_PTR(arg); 126703b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 126803b705cfSriastradh return xf86SetSingleMode(scrn, mode, RR_Rotate_0); 126903b705cfSriastradh} 127003b705cfSriastradh 127103b705cfSriastradhstatic ModeStatus 127203b705cfSriastradhsna_valid_mode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 127303b705cfSriastradh{ 127403b705cfSriastradh return MODE_OK; 127503b705cfSriastradh} 127603b705cfSriastradh 127703b705cfSriastradh#ifndef SUSPEND_SLEEP 127803b705cfSriastradh#define SUSPEND_SLEEP 0 127903b705cfSriastradh#endif 128003b705cfSriastradh#ifndef RESUME_SLEEP 128103b705cfSriastradh#define RESUME_SLEEP 0 128203b705cfSriastradh#endif 128303b705cfSriastradh 128403b705cfSriastradh/* 128503b705cfSriastradh * This function is only required if we need to do anything differently from 128603b705cfSriastradh * DoApmEvent() in common/xf86PM.c, including if we want to see events other 128703b705cfSriastradh * than suspend/resume. 128803b705cfSriastradh */ 128903b705cfSriastradhstatic Bool sna_pm_event(SCRN_ARG_TYPE arg, pmEvent event, Bool undo) 129003b705cfSriastradh{ 129103b705cfSriastradh SCRN_INFO_PTR(arg); 129203b705cfSriastradh struct sna *sna = to_sna(scrn); 129303b705cfSriastradh 129403b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 129503b705cfSriastradh 129603b705cfSriastradh switch (event) { 129703b705cfSriastradh case XF86_APM_SYS_SUSPEND: 129803b705cfSriastradh case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend? */ 129903b705cfSriastradh case XF86_APM_USER_SUSPEND: 130003b705cfSriastradh case XF86_APM_SYS_STANDBY: 130103b705cfSriastradh case XF86_APM_USER_STANDBY: 130203b705cfSriastradh if (!undo && !sna->suspended) { 130303b705cfSriastradh scrn->LeaveVT(VT_FUNC_ARGS(0)); 130403b705cfSriastradh sna->suspended = TRUE; 130503b705cfSriastradh sleep(SUSPEND_SLEEP); 130603b705cfSriastradh } else if (undo && sna->suspended) { 130703b705cfSriastradh sleep(RESUME_SLEEP); 130803b705cfSriastradh scrn->EnterVT(VT_FUNC_ARGS(0)); 130903b705cfSriastradh sna->suspended = FALSE; 131003b705cfSriastradh } 131103b705cfSriastradh break; 131203b705cfSriastradh case XF86_APM_STANDBY_RESUME: 131303b705cfSriastradh case XF86_APM_NORMAL_RESUME: 131403b705cfSriastradh case XF86_APM_CRITICAL_RESUME: 131503b705cfSriastradh if (sna->suspended) { 131603b705cfSriastradh sleep(RESUME_SLEEP); 131703b705cfSriastradh scrn->EnterVT(VT_FUNC_ARGS(0)); 131803b705cfSriastradh sna->suspended = FALSE; 131903b705cfSriastradh /* 132003b705cfSriastradh * Turn the screen saver off when resuming. This seems to be 132103b705cfSriastradh * needed to stop xscreensaver kicking in (when used). 132203b705cfSriastradh * 132303b705cfSriastradh * XXX DoApmEvent() should probably call this just like 132403b705cfSriastradh * xf86VTSwitch() does. Maybe do it here only in 4.2 132503b705cfSriastradh * compatibility mode. 132603b705cfSriastradh */ 132703b705cfSriastradh SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); 132803b705cfSriastradh } 132903b705cfSriastradh break; 133003b705cfSriastradh /* This is currently used for ACPI */ 133103b705cfSriastradh case XF86_APM_CAPABILITY_CHANGED: 133203b705cfSriastradh SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); 133303b705cfSriastradh break; 133403b705cfSriastradh 133503b705cfSriastradh default: 133642542f5fSchristos ERR(("sna_pm_event: received APM event %d\n", event)); 133703b705cfSriastradh } 133803b705cfSriastradh return TRUE; 133903b705cfSriastradh} 134003b705cfSriastradh 134103b705cfSriastradhstatic Bool sna_enter_vt__hosted(VT_FUNC_ARGS_DECL) 134203b705cfSriastradh{ 134303b705cfSriastradh return TRUE; 134403b705cfSriastradh} 134503b705cfSriastradh 134603b705cfSriastradhstatic void sna_leave_vt__hosted(VT_FUNC_ARGS_DECL) 134703b705cfSriastradh{ 134803b705cfSriastradh} 134903b705cfSriastradh 135042542f5fSchristosstatic void describe_kms(ScrnInfoPtr scrn) 135142542f5fSchristos{ 135242542f5fSchristos int fd = __intel_peek_fd(scrn); 135342542f5fSchristos drm_version_t version; 135442542f5fSchristos char name[128] = ""; 135542542f5fSchristos char date[128] = ""; 135642542f5fSchristos 135742542f5fSchristos memset(&version, 0, sizeof(version)); 135842542f5fSchristos version.name_len = sizeof(name) - 1; 135942542f5fSchristos version.name = name; 136042542f5fSchristos version.date_len = sizeof(date) - 1; 136142542f5fSchristos version.date = date; 136242542f5fSchristos 136342542f5fSchristos if (drmIoctl(fd, DRM_IOCTL_VERSION, &version)) 136442542f5fSchristos return; 136542542f5fSchristos 136642542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_INFO, 136742542f5fSchristos "Using Kernel Mode Setting driver: %s, version %d.%d.%d %s\n", 136842542f5fSchristos version.name, 136942542f5fSchristos version.version_major, version.version_minor, version.version_patchlevel, 137042542f5fSchristos version.date); 137142542f5fSchristos} 137242542f5fSchristos 137342542f5fSchristosstatic void describe_sna(ScrnInfoPtr scrn) 137403b705cfSriastradh{ 137503b705cfSriastradh#if defined(USE_GIT_DESCRIBE) 137603b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 137703b705cfSriastradh "SNA compiled from %s\n", git_version); 137803b705cfSriastradh#elif defined(BUILDER_DESCRIPTION) 137903b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 138003b705cfSriastradh "SNA compiled: %s\n", BUILDER_DESCRIPTION); 138103b705cfSriastradh#endif 138203b705cfSriastradh#if !NDEBUG 138303b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 138403b705cfSriastradh "SNA compiled with assertions enabled\n"); 138503b705cfSriastradh#endif 138603b705cfSriastradh#if DEBUG_SYNC 138703b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 138803b705cfSriastradh "SNA compiled with synchronous rendering\n"); 138903b705cfSriastradh#endif 139003b705cfSriastradh#if DEBUG_MEMORY 139103b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 139203b705cfSriastradh "SNA compiled with memory allocation reporting enabled\n"); 139303b705cfSriastradh#endif 139403b705cfSriastradh#if DEBUG_PIXMAP 139503b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 139603b705cfSriastradh "SNA compiled with extra pixmap/damage validation\n"); 139742542f5fSchristos#endif 139842542f5fSchristos#ifdef HAVE_VALGRIND 139942542f5fSchristos xf86DrvMsg(scrn->scrnIndex, X_INFO, 140042542f5fSchristos "SNA compiled for use with valgrind\n"); 140142542f5fSchristos VALGRIND_PRINTF("SNA compiled for use with valgrind\n"); 140203b705cfSriastradh#endif 140303b705cfSriastradh DBG(("pixman version: %s\n", pixman_version_string())); 140442542f5fSchristos} 140542542f5fSchristos 140642542f5fSchristosBool sna_init_scrn(ScrnInfoPtr scrn, int entity_num) 140742542f5fSchristos{ 140842542f5fSchristos DBG(("%s: entity_num=%d\n", __FUNCTION__, entity_num)); 140942542f5fSchristos describe_kms(scrn); 141042542f5fSchristos describe_sna(scrn); 141103b705cfSriastradh 141203b705cfSriastradh scrn->PreInit = sna_pre_init; 141303b705cfSriastradh scrn->ScreenInit = sna_screen_init; 141403b705cfSriastradh if (!hosted()) { 141503b705cfSriastradh scrn->SwitchMode = sna_switch_mode; 141603b705cfSriastradh scrn->AdjustFrame = sna_adjust_frame; 141703b705cfSriastradh scrn->EnterVT = sna_enter_vt; 141803b705cfSriastradh scrn->LeaveVT = sna_leave_vt; 141903b705cfSriastradh scrn->ValidMode = sna_valid_mode; 142003b705cfSriastradh scrn->PMEvent = sna_pm_event; 142103b705cfSriastradh } else { 142203b705cfSriastradh scrn->EnterVT = sna_enter_vt__hosted; 142303b705cfSriastradh scrn->LeaveVT = sna_leave_vt__hosted; 142403b705cfSriastradh } 142503b705cfSriastradh scrn->FreeScreen = sna_free_screen; 142603b705cfSriastradh 142703b705cfSriastradh xf86SetEntitySharable(entity_num); 142803b705cfSriastradh xf86SetEntityInstanceForScreen(scrn, entity_num, 142903b705cfSriastradh xf86GetNumEntityInstances(entity_num)-1); 143003b705cfSriastradh 143103b705cfSriastradh sna_threads_init(); 143203b705cfSriastradh 143303b705cfSriastradh return TRUE; 143403b705cfSriastradh} 143542542f5fSchristos 143642542f5fSchristos#if HAS_DEBUG_FULL 143742542f5fSchristos_X_ATTRIBUTE_PRINTF(1, 0) void LogF(const char *f, ...) 143842542f5fSchristos{ 143942542f5fSchristos va_list ap; 144042542f5fSchristos 144142542f5fSchristos /* As we not only may be called from any context, we may also 144242542f5fSchristos * be called from a thread whilst the main thread is handling 144342542f5fSchristos * signals, therefore we have to use the signal-safe variants 144442542f5fSchristos * or else we trip over false positive assertions. 144542542f5fSchristos */ 144642542f5fSchristos 144742542f5fSchristos va_start(ap, f); 144842542f5fSchristos#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0) 144942542f5fSchristos LogVMessageVerbSigSafe(X_NONE, 1, f, ap); 145042542f5fSchristos#else 145142542f5fSchristos LogVMessageVerb(X_NONE, 1, f, ap); 145242542f5fSchristos#endif 145342542f5fSchristos va_end(ap); 145442542f5fSchristos} 145542542f5fSchristos#endif 1456