1428d7b3dSmrg/************************************************************************** 2428d7b3dSmrg 3428d7b3dSmrgCopyright 2001 VA Linux Systems Inc., Fremont, California. 4428d7b3dSmrgCopyright © 2002 by David Dawes 5428d7b3dSmrg 6428d7b3dSmrgAll Rights Reserved. 7428d7b3dSmrg 8428d7b3dSmrgPermission is hereby granted, free of charge, to any person obtaining a 9428d7b3dSmrgcopy of this software and associated documentation files (the "Software"), 10428d7b3dSmrgto deal in the Software without restriction, including without limitation 11428d7b3dSmrgon the rights to use, copy, modify, merge, publish, distribute, sub 12428d7b3dSmrglicense, and/or sell copies of the Software, and to permit persons to whom 13428d7b3dSmrgthe Software is furnished to do so, subject to the following conditions: 14428d7b3dSmrg 15428d7b3dSmrgThe above copyright notice and this permission notice (including the next 16428d7b3dSmrgparagraph) shall be included in all copies or substantial portions of the 17428d7b3dSmrgSoftware. 18428d7b3dSmrg 19428d7b3dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20428d7b3dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21428d7b3dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 22428d7b3dSmrgTHE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 23428d7b3dSmrgDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24428d7b3dSmrgOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 25428d7b3dSmrgUSE OR OTHER DEALINGS IN THE SOFTWARE. 26428d7b3dSmrg 27428d7b3dSmrg**************************************************************************/ 28428d7b3dSmrg 29428d7b3dSmrg/* 30428d7b3dSmrg * Authors: Jeff Hartmann <jhartmann@valinux.com> 31428d7b3dSmrg * Abraham van der Merwe <abraham@2d3d.co.za> 32428d7b3dSmrg * David Dawes <dawes@xfree86.org> 33428d7b3dSmrg * Alan Hourihane <alanh@tungstengraphics.com> 34428d7b3dSmrg */ 35428d7b3dSmrg 36428d7b3dSmrg#ifdef HAVE_CONFIG_H 37428d7b3dSmrg#include "config.h" 38428d7b3dSmrg#endif 39428d7b3dSmrg 40428d7b3dSmrg#include <string.h> 41428d7b3dSmrg#include <stdio.h> 42428d7b3dSmrg#include <unistd.h> 43428d7b3dSmrg#include <stdlib.h> 44428d7b3dSmrg#include <stdio.h> 45428d7b3dSmrg#include <errno.h> 46428d7b3dSmrg 47428d7b3dSmrg#include "sna.h" 48428d7b3dSmrg#include "sna_module.h" 49428d7b3dSmrg#include "sna_video.h" 50428d7b3dSmrg 51428d7b3dSmrg#include "intel_driver.h" 52428d7b3dSmrg#include "intel_options.h" 53428d7b3dSmrg 54428d7b3dSmrg#include <xf86cmap.h> 55428d7b3dSmrg#include <xf86drm.h> 56428d7b3dSmrg#include <xf86RandR12.h> 57428d7b3dSmrg#include <mi.h> 58428d7b3dSmrg#include <micmap.h> 59428d7b3dSmrg 60428d7b3dSmrg#include <sys/ioctl.h> 61428d7b3dSmrg#include <sys/fcntl.h> 62428d7b3dSmrg#include <sys/poll.h> 63428d7b3dSmrg#include "i915_drm.h" 64428d7b3dSmrg 65428d7b3dSmrg#ifdef HAVE_VALGRIND 66428d7b3dSmrg#include <valgrind.h> 67428d7b3dSmrg#include <memcheck.h> 68428d7b3dSmrg#endif 69428d7b3dSmrg 70428d7b3dSmrg#if HAVE_DOT_GIT 71428d7b3dSmrg#include "git_version.h" 72428d7b3dSmrg#endif 73428d7b3dSmrg 74428d7b3dSmrg#ifdef TEARFREE 75428d7b3dSmrg#define ENABLE_TEAR_FREE TRUE 76428d7b3dSmrg#else 77428d7b3dSmrg#define ENABLE_TEAR_FREE FALSE 78428d7b3dSmrg#endif 79428d7b3dSmrg 80428d7b3dSmrgDevPrivateKeyRec sna_pixmap_key; 81428d7b3dSmrgDevPrivateKeyRec sna_gc_key; 82428d7b3dSmrgDevPrivateKeyRec sna_window_key; 83428d7b3dSmrgDevPrivateKeyRec sna_glyph_key; 84428d7b3dSmrgDevPrivateKeyRec sna_client_key; 85428d7b3dSmrg 86428d7b3dSmrgstatic void 87428d7b3dSmrgsna_load_palette(ScrnInfoPtr scrn, int numColors, int *indices, 88428d7b3dSmrg LOCO * colors, VisualPtr pVisual) 89428d7b3dSmrg{ 90428d7b3dSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 91428d7b3dSmrg int p, n, i, j; 92428d7b3dSmrg uint16_t lut_r[256], lut_g[256], lut_b[256]; 93428d7b3dSmrg 94428d7b3dSmrg DBG(("%s\n", __FUNCTION__)); 95428d7b3dSmrg 96428d7b3dSmrg for (p = 0; p < xf86_config->num_crtc; p++) { 97428d7b3dSmrg xf86CrtcPtr crtc = xf86_config->crtc[p]; 98428d7b3dSmrg 99428d7b3dSmrg#define C(I,RGB) (colors[I].RGB << 8 | colors[I].RGB) 100428d7b3dSmrg switch (scrn->depth) { 101428d7b3dSmrg case 15: 102428d7b3dSmrg for (n = 0; n < numColors; n++) { 103428d7b3dSmrg i = indices[n]; 104428d7b3dSmrg for (j = 0; j < 8; j++) { 105428d7b3dSmrg lut_r[8*i + j] = C(i, red); 106428d7b3dSmrg lut_g[8*i + j] = C(i, green); 107428d7b3dSmrg lut_b[8*i + j] = C(i, blue); 108428d7b3dSmrg } 109428d7b3dSmrg } 110428d7b3dSmrg break; 111428d7b3dSmrg case 16: 112428d7b3dSmrg for (n = 0; n < numColors; n++) { 113428d7b3dSmrg i = indices[n]; 114428d7b3dSmrg 115428d7b3dSmrg if (i <= 31) { 116428d7b3dSmrg for (j = 0; j < 8; j++) { 117428d7b3dSmrg lut_r[8*i + j] = C(i, red); 118428d7b3dSmrg lut_b[8*i + j] = C(i, blue); 119428d7b3dSmrg } 120428d7b3dSmrg } 121428d7b3dSmrg 122428d7b3dSmrg for (j = 0; j < 4; j++) 123428d7b3dSmrg lut_g[4*i + j] = C(i, green); 124428d7b3dSmrg } 125428d7b3dSmrg break; 126428d7b3dSmrg default: 127428d7b3dSmrg for (n = 0; n < numColors; n++) { 128428d7b3dSmrg i = indices[n]; 129428d7b3dSmrg lut_r[i] = C(i, red); 130428d7b3dSmrg lut_g[i] = C(i, green); 131428d7b3dSmrg lut_b[i] = C(i, blue); 132428d7b3dSmrg } 133428d7b3dSmrg break; 134428d7b3dSmrg } 135428d7b3dSmrg#undef C 136428d7b3dSmrg 137428d7b3dSmrg /* Make the change through RandR */ 138428d7b3dSmrg#ifdef RANDR_12_INTERFACE 139428d7b3dSmrg RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); 140428d7b3dSmrg#else 141428d7b3dSmrg crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); 142428d7b3dSmrg#endif 143428d7b3dSmrg } 144428d7b3dSmrg} 145428d7b3dSmrg 146428d7b3dSmrgstatic void 147428d7b3dSmrgsna_set_fallback_mode(ScrnInfoPtr scrn) 148428d7b3dSmrg{ 149428d7b3dSmrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 150428d7b3dSmrg xf86OutputPtr output = NULL; 151428d7b3dSmrg xf86CrtcPtr crtc = NULL; 152428d7b3dSmrg int n; 153428d7b3dSmrg 154428d7b3dSmrg if ((unsigned)config->compat_output < config->num_output) { 155428d7b3dSmrg output = config->output[config->compat_output]; 156428d7b3dSmrg crtc = output->crtc; 157428d7b3dSmrg } 158428d7b3dSmrg 159428d7b3dSmrg for (n = 0; n < config->num_output; n++) 160428d7b3dSmrg config->output[n]->crtc = NULL; 161428d7b3dSmrg for (n = 0; n < config->num_crtc; n++) 162428d7b3dSmrg config->crtc[n]->enabled = FALSE; 163428d7b3dSmrg 164428d7b3dSmrg if (output && crtc) { 165428d7b3dSmrg DisplayModePtr mode; 166428d7b3dSmrg 167428d7b3dSmrg output->crtc = crtc; 168428d7b3dSmrg 169428d7b3dSmrg mode = xf86OutputFindClosestMode(output, scrn->currentMode); 170428d7b3dSmrg if (mode && 171428d7b3dSmrg xf86CrtcSetModeTransform(crtc, mode, RR_Rotate_0, NULL, 0, 0)) { 172428d7b3dSmrg crtc->desiredMode = *mode; 173428d7b3dSmrg crtc->desiredMode.prev = crtc->desiredMode.next = NULL; 174428d7b3dSmrg crtc->desiredMode.name = NULL; 175428d7b3dSmrg crtc->desiredMode.PrivSize = 0; 176428d7b3dSmrg crtc->desiredMode.PrivFlags = 0; 177428d7b3dSmrg crtc->desiredMode.Private = NULL; 178428d7b3dSmrg crtc->desiredRotation = RR_Rotate_0; 179428d7b3dSmrg crtc->desiredTransformPresent = FALSE; 180428d7b3dSmrg crtc->desiredX = 0; 181428d7b3dSmrg crtc->desiredY = 0; 182428d7b3dSmrg crtc->enabled = TRUE; 183428d7b3dSmrg } 184428d7b3dSmrg } 185428d7b3dSmrg 186428d7b3dSmrg xf86DisableUnusedFunctions(scrn); 187428d7b3dSmrg#ifdef RANDR_12_INTERFACE 188428d7b3dSmrg if (get_root_window(scrn->pScreen)) 189428d7b3dSmrg xf86RandR12TellChanged(scrn->pScreen); 190428d7b3dSmrg#endif 191428d7b3dSmrg} 192428d7b3dSmrg 193428d7b3dSmrgstatic Bool sna_set_desired_mode(struct sna *sna) 194428d7b3dSmrg{ 195428d7b3dSmrg ScrnInfoPtr scrn = sna->scrn; 196428d7b3dSmrg 197428d7b3dSmrg DBG(("%s\n", __FUNCTION__)); 198428d7b3dSmrg 199428d7b3dSmrg if (!xf86SetDesiredModes(scrn)) { 200428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 201428d7b3dSmrg "failed to restore desired modes on VT switch\n"); 202428d7b3dSmrg sna_set_fallback_mode(scrn); 203428d7b3dSmrg } 204428d7b3dSmrg 205428d7b3dSmrg sna_mode_check(sna); 206428d7b3dSmrg return TRUE; 207428d7b3dSmrg} 208428d7b3dSmrg 209428d7b3dSmrg/** 210428d7b3dSmrg * Adjust the screen pixmap for the current location of the front buffer. 211428d7b3dSmrg * This is done at EnterVT when buffers are bound as long as the resources 212428d7b3dSmrg * have already been created, but the first EnterVT happens before 213428d7b3dSmrg * CreateScreenResources. 214428d7b3dSmrg */ 215428d7b3dSmrgstatic Bool sna_create_screen_resources(ScreenPtr screen) 216428d7b3dSmrg{ 217428d7b3dSmrg struct sna *sna = to_sna_from_screen(screen); 218428d7b3dSmrg PixmapPtr new_front; 219428d7b3dSmrg unsigned hint; 220428d7b3dSmrg 221428d7b3dSmrg DBG(("%s(%dx%d@%d)\n", __FUNCTION__, 222428d7b3dSmrg screen->width, screen->height, screen->rootDepth)); 223428d7b3dSmrg 224428d7b3dSmrg assert(sna->scrn == xf86ScreenToScrn(screen)); 225428d7b3dSmrg assert(sna->scrn->pScreen == screen); 226428d7b3dSmrg 227428d7b3dSmrg /* free the data used during miInitScreen */ 228428d7b3dSmrg free(screen->devPrivate); 229428d7b3dSmrg screen->devPrivate = NULL; 230428d7b3dSmrg 231428d7b3dSmrg sna_accel_create(sna); 232428d7b3dSmrg 233428d7b3dSmrg hint = SNA_CREATE_FB; 234428d7b3dSmrg if (sna->flags & SNA_IS_HOSTED) 235428d7b3dSmrg hint = 0; 236428d7b3dSmrg 237428d7b3dSmrg new_front = screen->CreatePixmap(screen, 238428d7b3dSmrg screen->width, 239428d7b3dSmrg screen->height, 240428d7b3dSmrg screen->rootDepth, 241428d7b3dSmrg hint); 242428d7b3dSmrg if (!new_front) { 243428d7b3dSmrg xf86DrvMsg(screen->myNum, X_ERROR, 244428d7b3dSmrg "[intel] Unable to create front buffer %dx%d at depth %d\n", 245428d7b3dSmrg screen->width, 246428d7b3dSmrg screen->height, 247428d7b3dSmrg screen->rootDepth); 248428d7b3dSmrg 249428d7b3dSmrg return FALSE; 250428d7b3dSmrg } 251428d7b3dSmrg 252428d7b3dSmrg /* Prefer to use the GPU for rendering into the eventual scanout 253428d7b3dSmrg * bo so that we do not unduly stall when it is time to attach 254428d7b3dSmrg * it to the CRTCs. 255428d7b3dSmrg */ 256428d7b3dSmrg (void)sna_pixmap_force_to_gpu(new_front, MOVE_READ | __MOVE_SCANOUT); 257428d7b3dSmrg 258428d7b3dSmrg screen->SetScreenPixmap(new_front); 259428d7b3dSmrg assert(screen->GetScreenPixmap(screen) == new_front); 260428d7b3dSmrg assert(sna->front == new_front); 261428d7b3dSmrg screen->DestroyPixmap(new_front); /* transfer ownership to screen */ 262428d7b3dSmrg 263428d7b3dSmrg sna_mode_set_primary(sna); 264428d7b3dSmrg 265428d7b3dSmrg /* Try to become master and copy the current fbcon before the 266428d7b3dSmrg * actual VT switch. If we fail here, we will try to reset the 267428d7b3dSmrg * mode in the eventual VT switch. This can fail if systemd has 268428d7b3dSmrg * already revoked our KMS privileges, so just carry on regardless, 269428d7b3dSmrg * and hope that everything is sorted after the VT switch. 270428d7b3dSmrg */ 271428d7b3dSmrg if (intel_get_master(sna->dev) == 0) { 272428d7b3dSmrg /* Only preserve the fbcon, not any subsequent server regens */ 273428d7b3dSmrg if (serverGeneration == 1 && (sna->flags & SNA_IS_HOSTED) == 0) 274428d7b3dSmrg sna_copy_fbcon(sna); 275428d7b3dSmrg 276428d7b3dSmrg (void)sna_set_desired_mode(sna); 277428d7b3dSmrg } 278428d7b3dSmrg 279428d7b3dSmrg return TRUE; 280428d7b3dSmrg} 281428d7b3dSmrg 282428d7b3dSmrgstatic Bool sna_save_screen(ScreenPtr screen, int mode) 283428d7b3dSmrg{ 284428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 285428d7b3dSmrg 286428d7b3dSmrg DBG(("%s(mode=%d)\n", __FUNCTION__, mode)); 287428d7b3dSmrg if (!scrn->vtSema) 288428d7b3dSmrg return FALSE; 289428d7b3dSmrg 290428d7b3dSmrg xf86SaveScreen(screen, mode); 291428d7b3dSmrg sna_crtc_config_notify(screen); 292428d7b3dSmrg return TRUE; 293428d7b3dSmrg} 294428d7b3dSmrg 295428d7b3dSmrgstatic void sna_dpms_set(ScrnInfoPtr scrn, int mode, int flags) 296428d7b3dSmrg{ 297428d7b3dSmrg DBG(("%s(mode=%d, flags=%d)\n", __FUNCTION__, mode)); 298428d7b3dSmrg if (!scrn->vtSema) 299428d7b3dSmrg return; 300428d7b3dSmrg 301428d7b3dSmrg xf86DPMSSet(scrn, mode, flags); 302428d7b3dSmrg sna_crtc_config_notify(xf86ScrnToScreen(scrn)); 303428d7b3dSmrg} 304428d7b3dSmrg 305428d7b3dSmrgstatic void sna_selftest(void) 306428d7b3dSmrg{ 307428d7b3dSmrg sna_damage_selftest(); 308428d7b3dSmrg} 309428d7b3dSmrg 310428d7b3dSmrgstatic bool has_vsync(struct sna *sna) 311428d7b3dSmrg{ 312428d7b3dSmrg if (sna->flags & SNA_IS_HOSTED) 313428d7b3dSmrg return false; 314428d7b3dSmrg 315428d7b3dSmrg return true; 316428d7b3dSmrg} 317428d7b3dSmrg 318428d7b3dSmrgstatic void sna_setup_capabilities(ScrnInfoPtr scrn, int fd) 319428d7b3dSmrg{ 320428d7b3dSmrg#if HAS_PIXMAP_SHARING && defined(DRM_CAP_PRIME) 321428d7b3dSmrg uint64_t value; 322428d7b3dSmrg 323428d7b3dSmrg scrn->capabilities = 0; 324428d7b3dSmrg if (drmGetCap(fd, DRM_CAP_PRIME, &value) == 0) { 325428d7b3dSmrg if (value & DRM_PRIME_CAP_EXPORT) 326428d7b3dSmrg scrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload; 327428d7b3dSmrg if (value & DRM_PRIME_CAP_IMPORT) 328428d7b3dSmrg scrn->capabilities |= RR_Capability_SinkOutput; 329428d7b3dSmrg } 330428d7b3dSmrg#endif 331428d7b3dSmrg} 332428d7b3dSmrg 333428d7b3dSmrgstatic int 334428d7b3dSmrgnamecmp(const char *s1, const char *s2) 335428d7b3dSmrg{ 336428d7b3dSmrg char c1, c2; 337428d7b3dSmrg 338428d7b3dSmrg if (!s1 || *s1 == 0) { 339428d7b3dSmrg if (!s2 || *s2 == 0) 340428d7b3dSmrg return 0; 341428d7b3dSmrg else 342428d7b3dSmrg return 1; 343428d7b3dSmrg } 344428d7b3dSmrg 345428d7b3dSmrg while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') 346428d7b3dSmrg s1++; 347428d7b3dSmrg 348428d7b3dSmrg while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') 349428d7b3dSmrg s2++; 350428d7b3dSmrg 351428d7b3dSmrg c1 = isupper(*s1) ? tolower(*s1) : *s1; 352428d7b3dSmrg c2 = isupper(*s2) ? tolower(*s2) : *s2; 353428d7b3dSmrg while (c1 == c2) { 354428d7b3dSmrg if (c1 == '\0') 355428d7b3dSmrg return 0; 356428d7b3dSmrg 357428d7b3dSmrg s1++; 358428d7b3dSmrg while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') 359428d7b3dSmrg s1++; 360428d7b3dSmrg 361428d7b3dSmrg s2++; 362428d7b3dSmrg while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') 363428d7b3dSmrg s2++; 364428d7b3dSmrg 365428d7b3dSmrg c1 = isupper(*s1) ? tolower(*s1) : *s1; 366428d7b3dSmrg c2 = isupper(*s2) ? tolower(*s2) : *s2; 367428d7b3dSmrg } 368428d7b3dSmrg 369428d7b3dSmrg return c1 - c2; 370428d7b3dSmrg} 371428d7b3dSmrg 372428d7b3dSmrgstatic Bool sna_option_cast_to_bool(struct sna *sna, int id, Bool val) 373428d7b3dSmrg{ 374428d7b3dSmrg const char *str = xf86GetOptValString(sna->Options, id); 375428d7b3dSmrg 376428d7b3dSmrg if (str == NULL) 377428d7b3dSmrg return val; 378428d7b3dSmrg 379428d7b3dSmrg if (*str == '\0') 380428d7b3dSmrg return TRUE; 381428d7b3dSmrg 382428d7b3dSmrg if (namecmp(str, "1") == 0) 383428d7b3dSmrg return TRUE; 384428d7b3dSmrg if (namecmp(str, "on") == 0) 385428d7b3dSmrg return TRUE; 386428d7b3dSmrg if (namecmp(str, "true") == 0) 387428d7b3dSmrg return TRUE; 388428d7b3dSmrg if (namecmp(str, "yes") == 0) 389428d7b3dSmrg return TRUE; 390428d7b3dSmrg 391428d7b3dSmrg if (namecmp(str, "0") == 0) 392428d7b3dSmrg return FALSE; 393428d7b3dSmrg if (namecmp(str, "off") == 0) 394428d7b3dSmrg return FALSE; 395428d7b3dSmrg if (namecmp(str, "false") == 0) 396428d7b3dSmrg return FALSE; 397428d7b3dSmrg if (namecmp(str, "no") == 0) 398428d7b3dSmrg return FALSE; 399428d7b3dSmrg 400428d7b3dSmrg return val; 401428d7b3dSmrg} 402428d7b3dSmrg 403428d7b3dSmrgstatic unsigned sna_option_cast_to_unsigned(struct sna *sna, int id, unsigned val) 404428d7b3dSmrg{ 405428d7b3dSmrg const char *str = xf86GetOptValString(sna->Options, id); 406428d7b3dSmrg unsigned v; 407428d7b3dSmrg 408428d7b3dSmrg if (str == NULL || *str == '\0') 409428d7b3dSmrg return val; 410428d7b3dSmrg 411428d7b3dSmrg if (namecmp(str, "on") == 0) 412428d7b3dSmrg return val; 413428d7b3dSmrg if (namecmp(str, "true") == 0) 414428d7b3dSmrg return val; 415428d7b3dSmrg if (namecmp(str, "yes") == 0) 416428d7b3dSmrg return val; 417428d7b3dSmrg 418428d7b3dSmrg if (namecmp(str, "0") == 0) 419428d7b3dSmrg return 0; 420428d7b3dSmrg if (namecmp(str, "off") == 0) 421428d7b3dSmrg return 0; 422428d7b3dSmrg if (namecmp(str, "false") == 0) 423428d7b3dSmrg return 0; 424428d7b3dSmrg if (namecmp(str, "no") == 0) 425428d7b3dSmrg return 0; 426428d7b3dSmrg 427428d7b3dSmrg v = atoi(str); 428428d7b3dSmrg if (v) 429428d7b3dSmrg return v; 430428d7b3dSmrg 431428d7b3dSmrg return val; 432428d7b3dSmrg} 433428d7b3dSmrg 434428d7b3dSmrgstatic Bool fb_supports_depth(int fd, int depth) 435428d7b3dSmrg{ 436428d7b3dSmrg struct drm_i915_gem_create create; 437428d7b3dSmrg struct drm_mode_fb_cmd fb; 438428d7b3dSmrg struct drm_mode_card_res res; 439428d7b3dSmrg Bool ret; 440428d7b3dSmrg 441428d7b3dSmrg memset(&res, 0, sizeof(res)); 442428d7b3dSmrg (void)drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res); 443428d7b3dSmrg if (res.count_crtcs == 0) 444428d7b3dSmrg return TRUE; 445428d7b3dSmrg 446428d7b3dSmrg VG_CLEAR(create); 447428d7b3dSmrg create.handle = 0; 448428d7b3dSmrg create.size = 4096; 449428d7b3dSmrg if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create)) 450428d7b3dSmrg return FALSE; 451428d7b3dSmrg 452428d7b3dSmrg VG_CLEAR(fb); 453428d7b3dSmrg fb.width = 64; 454428d7b3dSmrg fb.height = 16; 455428d7b3dSmrg fb.pitch = 256; 456428d7b3dSmrg fb.bpp = depth <= 8 ? 8 : depth <= 16 ? 16 : 32; 457428d7b3dSmrg fb.depth = depth; 458428d7b3dSmrg fb.handle = create.handle; 459428d7b3dSmrg 460428d7b3dSmrg ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB, &fb) == 0; 461428d7b3dSmrg drmModeRmFB(fd, fb.fb_id); 462428d7b3dSmrg 463428d7b3dSmrg (void)drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &create.handle); 464428d7b3dSmrg 465428d7b3dSmrg return ret; 466428d7b3dSmrg} 467428d7b3dSmrg 468428d7b3dSmrgstatic void setup_dri(struct sna *sna) 469428d7b3dSmrg{ 470428d7b3dSmrg unsigned level; 471428d7b3dSmrg 472428d7b3dSmrg sna->dri2.available = false; 473428d7b3dSmrg sna->dri3.available = false; 474428d7b3dSmrg 475428d7b3dSmrg level = sna_option_cast_to_unsigned(sna, OPTION_DRI, ~0); 476428d7b3dSmrg#if HAVE_DRI3 477428d7b3dSmrg if (level >= 3) 478428d7b3dSmrg sna->dri3.available = !!xf86LoadSubModule(sna->scrn, "dri3"); 479428d7b3dSmrg#endif 480428d7b3dSmrg#if HAVE_DRI2 481428d7b3dSmrg if (level >= 2) 482428d7b3dSmrg sna->dri2.available = !!xf86LoadSubModule(sna->scrn, "dri2"); 483428d7b3dSmrg#endif 484428d7b3dSmrg} 485428d7b3dSmrg 486428d7b3dSmrgstatic bool enable_tear_free(struct sna *sna) 487428d7b3dSmrg{ 488428d7b3dSmrg if (sna->flags & SNA_LINEAR_FB) 489428d7b3dSmrg return false; 490428d7b3dSmrg 491428d7b3dSmrg /* Under certain conditions, we should enable TearFree by default, 492428d7b3dSmrg * for example when the hardware requires pageflipping to run within 493428d7b3dSmrg * its power/performance budget. 494428d7b3dSmrg */ 495428d7b3dSmrg if (sna_mode_wants_tear_free(sna)) 496428d7b3dSmrg return true; 497428d7b3dSmrg 498428d7b3dSmrg return ENABLE_TEAR_FREE; 499428d7b3dSmrg} 500428d7b3dSmrg 501428d7b3dSmrgstatic void setup_tear_free(struct sna *sna) 502428d7b3dSmrg{ 503428d7b3dSmrg MessageType from; 504428d7b3dSmrg Bool enable; 505428d7b3dSmrg 506428d7b3dSmrg if (sna->flags & SNA_LINEAR_FB) 507428d7b3dSmrg return; 508428d7b3dSmrg 509428d7b3dSmrg if ((sna->flags & SNA_HAS_FLIP) == 0) { 510428d7b3dSmrg from = X_PROBED; 511428d7b3dSmrg goto done; 512428d7b3dSmrg } 513428d7b3dSmrg 514428d7b3dSmrg if (!xf86GetOptValBool(sna->Options, OPTION_TEAR_FREE, &enable)) { 515428d7b3dSmrg enable = enable_tear_free(sna); 516428d7b3dSmrg from = X_DEFAULT; 517428d7b3dSmrg } else 518428d7b3dSmrg from = X_CONFIG; 519428d7b3dSmrg 520428d7b3dSmrg if (enable) 521428d7b3dSmrg sna->flags |= SNA_TEAR_FREE; 522428d7b3dSmrg 523428d7b3dSmrgdone: 524428d7b3dSmrg xf86DrvMsg(sna->scrn->scrnIndex, from, "TearFree %sabled\n", 525428d7b3dSmrg sna->flags & SNA_TEAR_FREE ? "en" : "dis"); 526428d7b3dSmrg} 527428d7b3dSmrg 528428d7b3dSmrg/** 529428d7b3dSmrg * This is called before ScreenInit to do any require probing of screen 530428d7b3dSmrg * configuration. 531428d7b3dSmrg * 532428d7b3dSmrg * This code generally covers probing, module loading, option handling 533428d7b3dSmrg * card mapping, and RandR setup. 534428d7b3dSmrg * 535428d7b3dSmrg * Since xf86InitialConfiguration ends up requiring that we set video modes 536428d7b3dSmrg * in order to detect configuration, we end up having to do a lot of driver 537428d7b3dSmrg * setup (talking to the DRM, mapping the device, etc.) in this function. 538428d7b3dSmrg * As a result, we want to set up that server initialization once rather 539428d7b3dSmrg * that doing it per generation. 540428d7b3dSmrg */ 541428d7b3dSmrgstatic Bool sna_pre_init(ScrnInfoPtr scrn, int probe) 542428d7b3dSmrg{ 543428d7b3dSmrg struct sna *sna; 544428d7b3dSmrg char buf[1024]; 545428d7b3dSmrg rgb defaultWeight = { 0, 0, 0 }; 546428d7b3dSmrg EntityInfoPtr pEnt; 547428d7b3dSmrg Gamma zeros = { 0.0, 0.0, 0.0 }; 548428d7b3dSmrg int fd; 549428d7b3dSmrg 550428d7b3dSmrg DBG(("%s flags=%x, numEntities=%d\n", 551428d7b3dSmrg __FUNCTION__, probe, scrn->numEntities)); 552428d7b3dSmrg 553428d7b3dSmrg if (scrn->numEntities != 1) 554428d7b3dSmrg return FALSE; 555428d7b3dSmrg 556428d7b3dSmrg pEnt = xf86GetEntityInfo(scrn->entityList[0]); 557428d7b3dSmrg if (pEnt == NULL) { 558428d7b3dSmrg ERR(("%s: no EntityInfo found for scrn\n", __FUNCTION__)); 559428d7b3dSmrg return FALSE; 560428d7b3dSmrg } 561428d7b3dSmrg 562428d7b3dSmrg if (pEnt->location.type != BUS_PCI 563428d7b3dSmrg#ifdef XSERVER_PLATFORM_BUS 564428d7b3dSmrg && pEnt->location.type != BUS_PLATFORM 565428d7b3dSmrg#endif 566428d7b3dSmrg ) { 567428d7b3dSmrg ERR(("%s: invalid EntityInfo found for scrn, location=%d\n", __FUNCTION__, pEnt->location.type)); 568428d7b3dSmrg return FALSE; 569428d7b3dSmrg } 570428d7b3dSmrg 571428d7b3dSmrg if (probe & PROBE_DETECT) 572428d7b3dSmrg return TRUE; 573428d7b3dSmrg 574428d7b3dSmrg sna_selftest(); 575428d7b3dSmrg 576428d7b3dSmrg probe = 0; 577428d7b3dSmrg if (((uintptr_t)scrn->driverPrivate) & 3) { 578428d7b3dSmrg if (posix_memalign((void **)&sna, 4096, sizeof(*sna))) 579428d7b3dSmrg return FALSE; 580428d7b3dSmrg 581428d7b3dSmrg memset(sna, 0, sizeof(*sna)); /* should be unnecessary */ 582428d7b3dSmrg probe = (uintptr_t)scrn->driverPrivate & 1; 583428d7b3dSmrg sna->info = (void *)((uintptr_t)scrn->driverPrivate & ~3); 584428d7b3dSmrg scrn->driverPrivate = sna; 585428d7b3dSmrg 586428d7b3dSmrg sna->cpu_features = sna_cpu_detect(); 587428d7b3dSmrg sna->acpi.fd = sna_acpi_open(); 588428d7b3dSmrg } 589428d7b3dSmrg sna = to_sna(scrn); 590428d7b3dSmrg sna->scrn = scrn; 591428d7b3dSmrg sna->pEnt = pEnt; 592428d7b3dSmrg sna->flags = probe; 593428d7b3dSmrg 594428d7b3dSmrg scrn->displayWidth = 640; /* default it */ 595428d7b3dSmrg 596428d7b3dSmrg scrn->monitor = scrn->confScreen->monitor; 597428d7b3dSmrg scrn->progClock = TRUE; 598428d7b3dSmrg scrn->rgbBits = 8; 599428d7b3dSmrg 600428d7b3dSmrg sna->dev = intel_get_device(scrn, &fd); 601428d7b3dSmrg if (sna->dev == NULL) { 602428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 603428d7b3dSmrg "Failed to claim DRM device.\n"); 604428d7b3dSmrg goto cleanup; 605428d7b3dSmrg } 606428d7b3dSmrg 607428d7b3dSmrg /* Sanity check */ 608428d7b3dSmrg if (hosted() && (sna->flags & SNA_IS_HOSTED) == 0) { 609428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 610428d7b3dSmrg "Failed to setup hosted device.\n"); 611428d7b3dSmrg goto cleanup; 612428d7b3dSmrg } 613428d7b3dSmrg 614428d7b3dSmrg intel_detect_chipset(scrn, sna->dev); 615428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_PROBED, "CPU: %s\n", 616428d7b3dSmrg sna_cpu_features_to_string(sna->cpu_features, buf)); 617428d7b3dSmrg 618428d7b3dSmrg if (!xf86SetDepthBpp(scrn, 24, 0, 0, 619428d7b3dSmrg Support32bppFb | 620428d7b3dSmrg SupportConvert24to32 | PreferConvert24to32)) 621428d7b3dSmrg goto cleanup; 622428d7b3dSmrg 623428d7b3dSmrg switch (scrn->depth) { 624428d7b3dSmrg case 8: 625428d7b3dSmrg case 15: 626428d7b3dSmrg case 16: 627428d7b3dSmrg case 24: 628428d7b3dSmrg case 30: 629428d7b3dSmrg if ((sna->flags & SNA_IS_HOSTED) || 630428d7b3dSmrg fb_supports_depth(fd, scrn->depth)) 631428d7b3dSmrg break; 632428d7b3dSmrg default: 633428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 634428d7b3dSmrg "Given depth (%d) is not supported by the Intel driver and this chipset.\n", 635428d7b3dSmrg scrn->depth); 636428d7b3dSmrg goto cleanup; 637428d7b3dSmrg } 638428d7b3dSmrg xf86PrintDepthBpp(scrn); 639428d7b3dSmrg 640428d7b3dSmrg if (!xf86SetWeight(scrn, defaultWeight, defaultWeight)) 641428d7b3dSmrg goto cleanup; 642428d7b3dSmrg if (!xf86SetDefaultVisual(scrn, -1)) 643428d7b3dSmrg goto cleanup; 644428d7b3dSmrg 645428d7b3dSmrg sna->Options = intel_options_get(scrn); 646428d7b3dSmrg if (sna->Options == NULL) 647428d7b3dSmrg goto cleanup; 648428d7b3dSmrg 649428d7b3dSmrg sna_setup_capabilities(scrn, fd); 650428d7b3dSmrg 651428d7b3dSmrg kgem_init(&sna->kgem, fd, 652428d7b3dSmrg xf86GetPciInfoForEntity(pEnt->index), 653428d7b3dSmrg sna->info->gen); 654428d7b3dSmrg if (xf86ReturnOptValBool(sna->Options, OPTION_ACCEL_DISABLE, FALSE) || 655428d7b3dSmrg !sna_option_cast_to_bool(sna, OPTION_ACCEL_METHOD, TRUE)) { 656428d7b3dSmrg xf86DrvMsg(sna->scrn->scrnIndex, X_CONFIG, 657428d7b3dSmrg "Disabling hardware acceleration.\n"); 658428d7b3dSmrg sna->kgem.wedged = true; 659428d7b3dSmrg } 660428d7b3dSmrg 661428d7b3dSmrg if (xf86ReturnOptValBool(sna->Options, OPTION_TILING_FB, FALSE)) 662428d7b3dSmrg sna->flags |= SNA_LINEAR_FB; 663428d7b3dSmrg 664428d7b3dSmrg if (xf86ReturnOptValBool(sna->Options, OPTION_DELETE_DP12, FALSE)) 665428d7b3dSmrg sna->flags |= SNA_REMOVE_OUTPUTS; 666428d7b3dSmrg 667428d7b3dSmrg if (!xf86ReturnOptValBool(sna->Options, OPTION_SWAPBUFFERS_WAIT, TRUE)) 668428d7b3dSmrg sna->flags |= SNA_NO_WAIT; 669428d7b3dSmrg DBG(("%s: swapbuffer wait? %s\n", __FUNCTION__, sna->flags & SNA_NO_WAIT ? "disabled" : "enabled")); 670428d7b3dSmrg 671428d7b3dSmrg if (!has_vsync(sna) || 672428d7b3dSmrg !xf86ReturnOptValBool(sna->Options, OPTION_VSYNC, TRUE)) 673428d7b3dSmrg sna->flags |= SNA_NO_VSYNC; 674428d7b3dSmrg DBG(("%s: vsync? %s\n", __FUNCTION__, sna->flags & SNA_NO_VSYNC ? "disabled" : "enabled")); 675428d7b3dSmrg 676428d7b3dSmrg if (sna->flags & SNA_IS_HOSTED || 677428d7b3dSmrg !xf86ReturnOptValBool(sna->Options, OPTION_PAGEFLIP, TRUE)) 678428d7b3dSmrg sna->flags |= SNA_NO_FLIP; 679428d7b3dSmrg DBG(("%s: page flips? %s\n", __FUNCTION__, sna->flags & SNA_NO_FLIP ? "disabled" : "enabled")); 680428d7b3dSmrg 681428d7b3dSmrg if ((sna->flags & (SNA_NO_VSYNC | SNA_NO_FLIP | SNA_NO_WAIT)) == 0 && 682428d7b3dSmrg xf86ReturnOptValBool(sna->Options, OPTION_TRIPLE_BUFFER, TRUE)) 683428d7b3dSmrg sna->flags |= SNA_TRIPLE_BUFFER; 684428d7b3dSmrg DBG(("%s: triple buffer? %s\n", __FUNCTION__, sna->flags & SNA_TRIPLE_BUFFER ? "enabled" : "disabled")); 685428d7b3dSmrg 686428d7b3dSmrg if (xf86ReturnOptValBool(sna->Options, OPTION_CRTC_PIXMAPS, FALSE)) { 687428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Forcing per-crtc-pixmaps.\n"); 688428d7b3dSmrg sna->flags |= SNA_FORCE_SHADOW; 689428d7b3dSmrg } 690428d7b3dSmrg 691428d7b3dSmrg if (!sna_mode_pre_init(scrn, sna)) { 692428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 693428d7b3dSmrg "No outputs and no modes.\n"); 694428d7b3dSmrg goto cleanup; 695428d7b3dSmrg } 696428d7b3dSmrg scrn->currentMode = scrn->modes; 697428d7b3dSmrg 698428d7b3dSmrg setup_tear_free(sna); 699428d7b3dSmrg 700428d7b3dSmrg xf86SetGamma(scrn, zeros); 701428d7b3dSmrg xf86SetDpi(scrn, 0, 0); 702428d7b3dSmrg 703428d7b3dSmrg setup_dri(sna); 704428d7b3dSmrg 705428d7b3dSmrg sna->present.available = false; 706428d7b3dSmrg if (xf86ReturnOptValBool(sna->Options, OPTION_PRESENT, TRUE)) { 707428d7b3dSmrg#if HAVE_PRESENT 708428d7b3dSmrg sna->present.available = !!xf86LoadSubModule(scrn, "present"); 709428d7b3dSmrg#endif 710428d7b3dSmrg } 711428d7b3dSmrg 712428d7b3dSmrg sna_acpi_init(sna); 713428d7b3dSmrg 714428d7b3dSmrg return TRUE; 715428d7b3dSmrg 716428d7b3dSmrgcleanup: 717428d7b3dSmrg scrn->driverPrivate = (void *)((uintptr_t)sna->info | (sna->flags & SNA_IS_SLAVED) | 2); 718428d7b3dSmrg if (sna->dev) 719428d7b3dSmrg intel_put_device(sna->dev); 720428d7b3dSmrg free(sna); 721428d7b3dSmrg return FALSE; 722428d7b3dSmrg} 723428d7b3dSmrg 724428d7b3dSmrgstatic bool has_shadow(struct sna *sna) 725428d7b3dSmrg{ 726428d7b3dSmrg if (!sna->mode.shadow_damage) 727428d7b3dSmrg return false; 728428d7b3dSmrg 729428d7b3dSmrg if (RegionNil(DamageRegion(sna->mode.shadow_damage))) 730428d7b3dSmrg return false; 731428d7b3dSmrg 732428d7b3dSmrg return sna->mode.flip_active == 0; 733428d7b3dSmrg} 734428d7b3dSmrg 735428d7b3dSmrgstatic void 736428d7b3dSmrgsna_block_handler(BLOCKHANDLER_ARGS_DECL) 737428d7b3dSmrg{ 738428d7b3dSmrg#ifndef XF86_SCRN_INTERFACE 739428d7b3dSmrg struct sna *sna = to_sna(xf86Screens[arg]); 740428d7b3dSmrg#else 741428d7b3dSmrg struct sna *sna = to_sna_from_screen(arg); 742428d7b3dSmrg#endif 743428d7b3dSmrg#if ABI_VIDEODRV_VERSION < SET_ABI_VERSION(23, 0) 744428d7b3dSmrg struct timeval **tv = timeout; 745428d7b3dSmrg 746428d7b3dSmrg DBG(("%s (tv=%ld.%06ld)\n", __FUNCTION__, 747428d7b3dSmrg *tv ? (*tv)->tv_sec : -1, *tv ? (*tv)->tv_usec : 0)); 748428d7b3dSmrg#else 749428d7b3dSmrg int *tv = timeout; 750428d7b3dSmrg 751428d7b3dSmrg DBG(("%s (tv=%ld.%06ld)\n", __FUNCTION__, 752428d7b3dSmrg *tv / 1000, *tv % (1000 * 1000))); 753428d7b3dSmrg#endif 754428d7b3dSmrg 755428d7b3dSmrg sna->BlockHandler(BLOCKHANDLER_ARGS); 756428d7b3dSmrg 757428d7b3dSmrg#if ABI_VIDEODRV_VERSION < SET_ABI_VERSION(23, 0) 758428d7b3dSmrg if (*tv == NULL || ((*tv)->tv_usec | (*tv)->tv_sec) || has_shadow(sna)) 759428d7b3dSmrg#endif 760428d7b3dSmrg sna_accel_block_handler(sna, tv); 761428d7b3dSmrg} 762428d7b3dSmrg 763428d7b3dSmrgstatic void 764428d7b3dSmrgsna_wakeup_handler(WAKEUPHANDLER_ARGS_DECL) 765428d7b3dSmrg{ 766428d7b3dSmrg#ifndef XF86_SCRN_INTERFACE 767428d7b3dSmrg struct sna *sna = to_sna(xf86Screens[arg]); 768428d7b3dSmrg#else 769428d7b3dSmrg struct sna *sna = to_sna_from_screen(arg); 770428d7b3dSmrg#endif 771428d7b3dSmrg 772428d7b3dSmrg DBG(("%s\n", __FUNCTION__)); 773428d7b3dSmrg 774428d7b3dSmrg /* despite all appearances, result is just a signed int */ 775428d7b3dSmrg if ((int)result < 0) 776428d7b3dSmrg return; 777428d7b3dSmrg 778428d7b3dSmrg sna_acpi_wakeup(sna); 779428d7b3dSmrg 780428d7b3dSmrg sna->WakeupHandler(WAKEUPHANDLER_ARGS); 781428d7b3dSmrg 782428d7b3dSmrg sna_accel_wakeup_handler(sna); 783428d7b3dSmrg 784428d7b3dSmrg sna_mode_wakeup(sna); 785428d7b3dSmrg} 786428d7b3dSmrg 787428d7b3dSmrg#if HAVE_UDEV 788428d7b3dSmrgstatic void 789428d7b3dSmrgsna_handle_uevents(int fd, void *closure) 790428d7b3dSmrg{ 791428d7b3dSmrg struct sna *sna = closure; 792428d7b3dSmrg struct udev_device *dev; 793428d7b3dSmrg const char *str; 794428d7b3dSmrg struct stat s; 795428d7b3dSmrg dev_t udev_devnum; 796428d7b3dSmrg 797428d7b3dSmrg DBG(("%s\n", __FUNCTION__)); 798428d7b3dSmrg 799428d7b3dSmrg dev = udev_monitor_receive_device(sna->uevent_monitor); 800428d7b3dSmrg if (!dev) 801428d7b3dSmrg return; 802428d7b3dSmrg 803428d7b3dSmrg udev_devnum = udev_device_get_devnum(dev); 804428d7b3dSmrg if (fstat(sna->kgem.fd, &s) || memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t))) { 805428d7b3dSmrg udev_device_unref(dev); 806428d7b3dSmrg return; 807428d7b3dSmrg } 808428d7b3dSmrg 809428d7b3dSmrg str = udev_device_get_property_value(dev, "HOTPLUG"); 810428d7b3dSmrg if (str && atoi(str) == 1) { 811428d7b3dSmrg ScrnInfoPtr scrn = sna->scrn; 812428d7b3dSmrg 813428d7b3dSmrg DBG(("%s: hotplug event (vtSema?=%d)\n", __FUNCTION__, scrn->vtSema)); 814428d7b3dSmrg 815428d7b3dSmrg if (scrn->vtSema) { 816428d7b3dSmrg sna_mode_discover(sna); 817428d7b3dSmrg sna_mode_check(sna); 818428d7b3dSmrg RRGetInfo(xf86ScrnToScreen(scrn), TRUE); 819428d7b3dSmrg } else 820428d7b3dSmrg sna->flags |= SNA_REPROBE; 821428d7b3dSmrg } 822428d7b3dSmrg 823428d7b3dSmrg udev_device_unref(dev); 824428d7b3dSmrg} 825428d7b3dSmrg 826428d7b3dSmrgstatic void 827428d7b3dSmrgsna_uevent_init(struct sna *sna) 828428d7b3dSmrg{ 829428d7b3dSmrg struct udev *u; 830428d7b3dSmrg struct udev_monitor *mon; 831428d7b3dSmrg MessageType from = X_CONFIG; 832428d7b3dSmrg 833428d7b3dSmrg if (sna->flags & SNA_IS_HOSTED) 834428d7b3dSmrg return; 835428d7b3dSmrg 836428d7b3dSmrg DBG(("%s\n", __FUNCTION__)); 837428d7b3dSmrg 838428d7b3dSmrg /* RandR will be disabled if Xinerama is active, and so generating 839428d7b3dSmrg * RR hotplug events is then verboten. 840428d7b3dSmrg */ 841428d7b3dSmrg if (!dixPrivateKeyRegistered(rrPrivKey)) 842428d7b3dSmrg goto out; 843428d7b3dSmrg 844428d7b3dSmrg u = NULL; 845428d7b3dSmrg if (xf86ReturnOptValBool(sna->Options, OPTION_HOTPLUG, TRUE)) 846428d7b3dSmrg u = udev_new(); 847428d7b3dSmrg if (!u) 848428d7b3dSmrg goto out; 849428d7b3dSmrg 850428d7b3dSmrg from = X_DEFAULT; 851428d7b3dSmrg 852428d7b3dSmrg mon = udev_monitor_new_from_netlink(u, "udev"); 853428d7b3dSmrg if (!mon) 854428d7b3dSmrg goto err_dev; 855428d7b3dSmrg 856428d7b3dSmrg if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") < 0) 857428d7b3dSmrg goto err_monitor; 858428d7b3dSmrg 859428d7b3dSmrg if (udev_monitor_enable_receiving(mon) < 0) 860428d7b3dSmrg goto err_monitor; 861428d7b3dSmrg 862428d7b3dSmrg sna->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon), 863428d7b3dSmrg sna_handle_uevents, sna); 864428d7b3dSmrg if (!sna->uevent_handler) 865428d7b3dSmrg goto err_monitor; 866428d7b3dSmrg 867428d7b3dSmrg sna->uevent_monitor = mon; 868428d7b3dSmrgout: 869428d7b3dSmrg xf86DrvMsg(sna->scrn->scrnIndex, from, "display hotplug detection %s\n", 870428d7b3dSmrg sna->uevent_monitor ? "enabled" : "disabled"); 871428d7b3dSmrg return; 872428d7b3dSmrg 873428d7b3dSmrgerr_monitor: 874428d7b3dSmrg udev_monitor_unref(mon); 875428d7b3dSmrgerr_dev: 876428d7b3dSmrg udev_unref(u); 877428d7b3dSmrg goto out; 878428d7b3dSmrg} 879428d7b3dSmrg 880428d7b3dSmrgstatic bool sna_uevent_poll(struct sna *sna) 881428d7b3dSmrg{ 882428d7b3dSmrg struct pollfd pfd; 883428d7b3dSmrg 884428d7b3dSmrg if (sna->uevent_monitor == NULL) 885428d7b3dSmrg return false; 886428d7b3dSmrg 887428d7b3dSmrg pfd.fd = udev_monitor_get_fd(sna->uevent_monitor); 888428d7b3dSmrg pfd.events = POLLIN; 889428d7b3dSmrg 890428d7b3dSmrg while (poll(&pfd, 1, 0) > 0) 891428d7b3dSmrg sna_handle_uevents(pfd.fd, sna); 892428d7b3dSmrg 893428d7b3dSmrg return true; 894428d7b3dSmrg} 895428d7b3dSmrg 896428d7b3dSmrgstatic void 897428d7b3dSmrgsna_uevent_fini(struct sna *sna) 898428d7b3dSmrg{ 899428d7b3dSmrg struct udev *u; 900428d7b3dSmrg 901428d7b3dSmrg if (sna->uevent_handler == NULL) 902428d7b3dSmrg return; 903428d7b3dSmrg 904428d7b3dSmrg xf86RemoveGeneralHandler(sna->uevent_handler); 905428d7b3dSmrg 906428d7b3dSmrg u = udev_monitor_get_udev(sna->uevent_monitor); 907428d7b3dSmrg udev_monitor_unref(sna->uevent_monitor); 908428d7b3dSmrg udev_unref(u); 909428d7b3dSmrg 910428d7b3dSmrg sna->uevent_handler = NULL; 911428d7b3dSmrg sna->uevent_monitor = NULL; 912428d7b3dSmrg 913428d7b3dSmrg DBG(("%s: removed uvent handler\n", __FUNCTION__)); 914428d7b3dSmrg} 915428d7b3dSmrg#else 916428d7b3dSmrgstatic void sna_uevent_init(struct sna *sna) { } 917428d7b3dSmrgstatic bool sna_uevent_poll(struct sna *sna) { return false; } 918428d7b3dSmrgstatic void sna_uevent_fini(struct sna *sna) { } 919428d7b3dSmrg#endif /* HAVE_UDEV */ 920428d7b3dSmrg 921428d7b3dSmrgstatic Bool 922428d7b3dSmrgsna_randr_getinfo(ScreenPtr screen, Rotation *rotations) 923428d7b3dSmrg{ 924428d7b3dSmrg struct sna *sna = to_sna_from_screen(screen); 925428d7b3dSmrg 926428d7b3dSmrg if (!sna_uevent_poll(sna)) 927428d7b3dSmrg sna_mode_discover(sna); 928428d7b3dSmrg 929428d7b3dSmrg return sna->mode.rrGetInfo(screen, rotations); 930428d7b3dSmrg} 931428d7b3dSmrg 932428d7b3dSmrgstatic void sna_leave_vt(VT_FUNC_ARGS_DECL) 933428d7b3dSmrg{ 934428d7b3dSmrg SCRN_INFO_PTR(arg); 935428d7b3dSmrg struct sna *sna = to_sna(scrn); 936428d7b3dSmrg 937428d7b3dSmrg DBG(("%s\n", __FUNCTION__)); 938428d7b3dSmrg 939428d7b3dSmrg sna_accel_leave(sna); 940428d7b3dSmrg sna_mode_reset(sna); 941428d7b3dSmrg 942428d7b3dSmrg if (intel_put_master(sna->dev)) 943428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 944428d7b3dSmrg "drmDropMaster failed: %s\n", strerror(errno)); 945428d7b3dSmrg} 946428d7b3dSmrg 947428d7b3dSmrgstatic Bool sna_early_close_screen(CLOSE_SCREEN_ARGS_DECL) 948428d7b3dSmrg{ 949428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 950428d7b3dSmrg struct sna *sna = to_sna(scrn); 951428d7b3dSmrg 952428d7b3dSmrg DBG(("%s\n", __FUNCTION__)); 953428d7b3dSmrg 954428d7b3dSmrg /* XXX Note that we will leak kernel resources if !vtSema */ 955428d7b3dSmrg 956428d7b3dSmrg sna_uevent_fini(sna); 957428d7b3dSmrg sna_mode_close(sna); 958428d7b3dSmrg 959428d7b3dSmrg if (sna->present.open) { 960428d7b3dSmrg sna_present_close(sna, screen); 961428d7b3dSmrg sna->present.open = false; 962428d7b3dSmrg } 963428d7b3dSmrg 964428d7b3dSmrg if (sna->dri3.open) { 965428d7b3dSmrg sna_dri3_close(sna, screen); 966428d7b3dSmrg sna->dri3.open = false; 967428d7b3dSmrg } 968428d7b3dSmrg 969428d7b3dSmrg if (sna->dri2.open) { 970428d7b3dSmrg sna_dri2_close(sna, screen); 971428d7b3dSmrg sna->dri2.open = false; 972428d7b3dSmrg } 973428d7b3dSmrg 974428d7b3dSmrg if (sna->front) { 975428d7b3dSmrg screen->DestroyPixmap(sna->front); 976428d7b3dSmrg sna->front = NULL; 977428d7b3dSmrg } 978428d7b3dSmrg 979428d7b3dSmrg if (scrn->vtSema) { 980428d7b3dSmrg intel_put_master(sna->dev); 981428d7b3dSmrg scrn->vtSema = FALSE; 982428d7b3dSmrg } 983428d7b3dSmrg 984428d7b3dSmrg return sna->CloseScreen(CLOSE_SCREEN_ARGS); 985428d7b3dSmrg} 986428d7b3dSmrg 987428d7b3dSmrgstatic Bool sna_late_close_screen(CLOSE_SCREEN_ARGS_DECL) 988428d7b3dSmrg{ 989428d7b3dSmrg struct sna *sna = to_sna_from_screen(screen); 990428d7b3dSmrg DepthPtr depths; 991428d7b3dSmrg int d; 992428d7b3dSmrg 993428d7b3dSmrg DBG(("%s\n", __FUNCTION__)); 994428d7b3dSmrg 995428d7b3dSmrg sna_accel_close(sna); 996428d7b3dSmrg sna_video_close(sna); 997428d7b3dSmrg 998428d7b3dSmrg depths = screen->allowedDepths; 999428d7b3dSmrg for (d = 0; d < screen->numDepths; d++) 1000428d7b3dSmrg free(depths[d].vids); 1001428d7b3dSmrg free(depths); 1002428d7b3dSmrg 1003428d7b3dSmrg free(screen->visuals); 1004428d7b3dSmrg 1005428d7b3dSmrg return TRUE; 1006428d7b3dSmrg} 1007428d7b3dSmrg 1008428d7b3dSmrgstatic Bool 1009428d7b3dSmrgsna_register_all_privates(void) 1010428d7b3dSmrg{ 1011428d7b3dSmrg#if HAS_DIXREGISTERPRIVATEKEY 1012428d7b3dSmrg if (!dixRegisterPrivateKey(&sna_pixmap_key, PRIVATE_PIXMAP, 1013428d7b3dSmrg 3*sizeof(void *))) 1014428d7b3dSmrg return FALSE; 1015428d7b3dSmrg 1016428d7b3dSmrg if (!dixRegisterPrivateKey(&sna_gc_key, PRIVATE_GC, 1017428d7b3dSmrg sizeof(FbGCPrivate))) 1018428d7b3dSmrg return FALSE; 1019428d7b3dSmrg 1020428d7b3dSmrg if (!dixRegisterPrivateKey(&sna_glyph_key, PRIVATE_GLYPH, 1021428d7b3dSmrg sizeof(struct sna_glyph))) 1022428d7b3dSmrg return FALSE; 1023428d7b3dSmrg 1024428d7b3dSmrg if (!dixRegisterPrivateKey(&sna_window_key, PRIVATE_WINDOW, 1025428d7b3dSmrg 3*sizeof(void *))) 1026428d7b3dSmrg return FALSE; 1027428d7b3dSmrg 1028428d7b3dSmrg if (!dixRegisterPrivateKey(&sna_client_key, PRIVATE_CLIENT, 1029428d7b3dSmrg sizeof(struct sna_client))) 1030428d7b3dSmrg return FALSE; 1031428d7b3dSmrg#else 1032428d7b3dSmrg if (!dixRequestPrivate(&sna_pixmap_key, 3*sizeof(void *))) 1033428d7b3dSmrg return FALSE; 1034428d7b3dSmrg 1035428d7b3dSmrg if (!dixRequestPrivate(&sna_gc_key, sizeof(FbGCPrivate))) 1036428d7b3dSmrg return FALSE; 1037428d7b3dSmrg 1038428d7b3dSmrg if (!dixRequestPrivate(&sna_glyph_key, sizeof(struct sna_glyph))) 1039428d7b3dSmrg return FALSE; 1040428d7b3dSmrg 1041428d7b3dSmrg if (!dixRequestPrivate(&sna_window_key, 3*sizeof(void *))) 1042428d7b3dSmrg return FALSE; 1043428d7b3dSmrg 1044428d7b3dSmrg if (!dixRequestPrivate(&sna_client_key, sizeof(struct sna_client))) 1045428d7b3dSmrg return FALSE; 1046428d7b3dSmrg#endif 1047428d7b3dSmrg 1048428d7b3dSmrg return TRUE; 1049428d7b3dSmrg} 1050428d7b3dSmrg 1051428d7b3dSmrgstatic void sna_dri_init(struct sna *sna, ScreenPtr screen) 1052428d7b3dSmrg{ 1053428d7b3dSmrg char str[128] = ""; 1054428d7b3dSmrg 1055428d7b3dSmrg if (sna->dri2.available) 1056428d7b3dSmrg sna->dri2.open = sna_dri2_open(sna, screen); 1057428d7b3dSmrg if (sna->dri2.open) 1058428d7b3dSmrg strcat(str, "DRI2 "); 1059428d7b3dSmrg 1060428d7b3dSmrg if (sna->dri3.available) 1061428d7b3dSmrg sna->dri3.open = sna_dri3_open(sna, screen); 1062428d7b3dSmrg if (sna->dri3.open) 1063428d7b3dSmrg strcat(str, "DRI3 "); 1064428d7b3dSmrg 1065428d7b3dSmrg if (*str) 1066428d7b3dSmrg xf86DrvMsg(sna->scrn->scrnIndex, X_INFO, 1067428d7b3dSmrg "direct rendering: %senabled\n", str); 1068428d7b3dSmrg} 1069428d7b3dSmrg 1070428d7b3dSmrgstatic Bool 1071428d7b3dSmrgsna_mode_init(struct sna *sna, ScreenPtr screen) 1072428d7b3dSmrg{ 1073428d7b3dSmrg rrScrPrivPtr rp; 1074428d7b3dSmrg 1075428d7b3dSmrg if (!xf86CrtcScreenInit(screen)) 1076428d7b3dSmrg return FALSE; 1077428d7b3dSmrg 1078428d7b3dSmrg xf86RandR12SetRotations(screen, RR_Rotate_All | RR_Reflect_All); 1079428d7b3dSmrg xf86RandR12SetTransformSupport(screen, TRUE); 1080428d7b3dSmrg 1081428d7b3dSmrg /* Wrap RR queries to catch pending MST topology changes */ 1082428d7b3dSmrg rp = rrGetScrPriv(screen); 1083428d7b3dSmrg if (rp) { 1084428d7b3dSmrg sna->mode.rrGetInfo = rp->rrGetInfo; 1085428d7b3dSmrg rp->rrGetInfo = sna_randr_getinfo; 1086428d7b3dSmrg } 1087428d7b3dSmrg 1088428d7b3dSmrg return TRUE; 1089428d7b3dSmrg} 1090428d7b3dSmrg 1091428d7b3dSmrgstatic Bool 1092428d7b3dSmrgsna_screen_init(SCREEN_INIT_ARGS_DECL) 1093428d7b3dSmrg{ 1094428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1095428d7b3dSmrg struct sna *sna = to_sna(scrn); 1096428d7b3dSmrg VisualPtr visuals; 1097428d7b3dSmrg DepthPtr depths; 1098428d7b3dSmrg int nvisuals; 1099428d7b3dSmrg int ndepths; 1100428d7b3dSmrg int rootdepth; 1101428d7b3dSmrg VisualID defaultVisual; 1102428d7b3dSmrg 1103428d7b3dSmrg DBG(("%s\n", __FUNCTION__)); 1104428d7b3dSmrg 1105428d7b3dSmrg assert(sna->scrn == scrn); 1106428d7b3dSmrg assert(scrn->pScreen == NULL); /* set afterwards */ 1107428d7b3dSmrg 1108428d7b3dSmrg assert(sna->freed_pixmap == NULL); 1109428d7b3dSmrg 1110428d7b3dSmrg if (!sna_register_all_privates()) 1111428d7b3dSmrg return FALSE; 1112428d7b3dSmrg 1113428d7b3dSmrg scrn->videoRam = sna->kgem.aperture_mappable * 4; /* Page to KiB */ 1114428d7b3dSmrg 1115428d7b3dSmrg miClearVisualTypes(); 1116428d7b3dSmrg if (!miSetVisualTypes(scrn->depth, 1117428d7b3dSmrg miGetDefaultVisualMask(scrn->depth), 1118428d7b3dSmrg scrn->rgbBits, scrn->defaultVisual)) 1119428d7b3dSmrg return FALSE; 1120428d7b3dSmrg if (!miSetPixmapDepths()) 1121428d7b3dSmrg return FALSE; 1122428d7b3dSmrg 1123428d7b3dSmrg rootdepth = 0; 1124428d7b3dSmrg if (!miInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &rootdepth, 1125428d7b3dSmrg &defaultVisual, 1126428d7b3dSmrg ((unsigned long)1 << (scrn->bitsPerPixel - 1)), 1127428d7b3dSmrg 8, -1)) 1128428d7b3dSmrg return FALSE; 1129428d7b3dSmrg 1130428d7b3dSmrg if (!miScreenInit(screen, NULL, 1131428d7b3dSmrg scrn->virtualX, scrn->virtualY, 1132428d7b3dSmrg scrn->xDpi, scrn->yDpi, 0, 1133428d7b3dSmrg rootdepth, ndepths, depths, 1134428d7b3dSmrg defaultVisual, nvisuals, visuals)) 1135428d7b3dSmrg return FALSE; 1136428d7b3dSmrg 1137428d7b3dSmrg if (scrn->bitsPerPixel > 8) { 1138428d7b3dSmrg /* Fixup RGB ordering */ 1139428d7b3dSmrg VisualPtr visual = screen->visuals + screen->numVisuals; 1140428d7b3dSmrg while (--visual >= screen->visuals) { 1141428d7b3dSmrg if ((visual->class | DynamicClass) == DirectColor) { 1142428d7b3dSmrg visual->offsetRed = scrn->offset.red; 1143428d7b3dSmrg visual->offsetGreen = scrn->offset.green; 1144428d7b3dSmrg visual->offsetBlue = scrn->offset.blue; 1145428d7b3dSmrg visual->redMask = scrn->mask.red; 1146428d7b3dSmrg visual->greenMask = scrn->mask.green; 1147428d7b3dSmrg visual->blueMask = scrn->mask.blue; 1148428d7b3dSmrg } 1149428d7b3dSmrg } 1150428d7b3dSmrg } 1151428d7b3dSmrg 1152428d7b3dSmrg assert(screen->CloseScreen == NULL); 1153428d7b3dSmrg screen->CloseScreen = sna_late_close_screen; 1154428d7b3dSmrg if (!sna_accel_init(screen, sna)) { 1155428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1156428d7b3dSmrg "Hardware acceleration initialization failed\n"); 1157428d7b3dSmrg return FALSE; 1158428d7b3dSmrg } 1159428d7b3dSmrg 1160428d7b3dSmrg xf86SetBlackWhitePixels(screen); 1161428d7b3dSmrg 1162428d7b3dSmrg xf86SetBackingStore(screen); 1163428d7b3dSmrg xf86SetSilkenMouse(screen); 1164428d7b3dSmrg if (!miDCInitialize(screen, xf86GetPointerScreenFuncs())) 1165428d7b3dSmrg return FALSE; 1166428d7b3dSmrg 1167428d7b3dSmrg if (sna_cursors_init(screen, sna)) 1168428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, "HW Cursor enabled\n"); 1169428d7b3dSmrg 1170428d7b3dSmrg /* Must force it before EnterVT, so we are in control of VT and 1171428d7b3dSmrg * later memory should be bound when allocating, e.g rotate_mem */ 1172428d7b3dSmrg scrn->vtSema = TRUE; 1173428d7b3dSmrg 1174428d7b3dSmrg sna->BlockHandler = screen->BlockHandler; 1175428d7b3dSmrg screen->BlockHandler = sna_block_handler; 1176428d7b3dSmrg 1177428d7b3dSmrg sna->WakeupHandler = screen->WakeupHandler; 1178428d7b3dSmrg screen->WakeupHandler = sna_wakeup_handler; 1179428d7b3dSmrg 1180428d7b3dSmrg screen->SaveScreen = sna_save_screen; 1181428d7b3dSmrg screen->CreateScreenResources = sna_create_screen_resources; 1182428d7b3dSmrg 1183428d7b3dSmrg sna->CloseScreen = screen->CloseScreen; 1184428d7b3dSmrg screen->CloseScreen = sna_early_close_screen; 1185428d7b3dSmrg 1186428d7b3dSmrg if (!sna_mode_init(sna, screen)) 1187428d7b3dSmrg return FALSE; 1188428d7b3dSmrg 1189428d7b3dSmrg if (!miCreateDefColormap(screen)) 1190428d7b3dSmrg return FALSE; 1191428d7b3dSmrg 1192428d7b3dSmrg if (sna->mode.num_real_crtc && 1193428d7b3dSmrg !xf86HandleColormaps(screen, 256, 8, sna_load_palette, NULL, 1194428d7b3dSmrg CMAP_RELOAD_ON_MODE_SWITCH | 1195428d7b3dSmrg CMAP_PALETTED_TRUECOLOR)) 1196428d7b3dSmrg return FALSE; 1197428d7b3dSmrg 1198428d7b3dSmrg xf86DPMSInit(screen, sna_dpms_set, 0); 1199428d7b3dSmrg 1200428d7b3dSmrg sna_uevent_init(sna); 1201428d7b3dSmrg sna_video_init(sna, screen); 1202428d7b3dSmrg sna_dri_init(sna, screen); 1203428d7b3dSmrg 1204428d7b3dSmrg if (sna->present.available) 1205428d7b3dSmrg sna->present.open = sna_present_open(sna, screen); 1206428d7b3dSmrg if (sna->present.open) 1207428d7b3dSmrg xf86DrvMsg(sna->scrn->scrnIndex, X_INFO, 1208428d7b3dSmrg "hardware support for Present enabled\n"); 1209428d7b3dSmrg 1210428d7b3dSmrg if (serverGeneration == 1) 1211428d7b3dSmrg xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options); 1212428d7b3dSmrg 1213428d7b3dSmrg sna->suspended = FALSE; 1214428d7b3dSmrg 1215428d7b3dSmrg return TRUE; 1216428d7b3dSmrg} 1217428d7b3dSmrg 1218428d7b3dSmrgstatic void sna_adjust_frame(ADJUST_FRAME_ARGS_DECL) 1219428d7b3dSmrg{ 1220428d7b3dSmrg SCRN_INFO_PTR(arg); 1221428d7b3dSmrg DBG(("%s(%d, %d)\n", __FUNCTION__, x, y)); 1222428d7b3dSmrg sna_mode_adjust_frame(to_sna(scrn), x, y); 1223428d7b3dSmrg} 1224428d7b3dSmrg 1225428d7b3dSmrgstatic void sna_free_screen(FREE_SCREEN_ARGS_DECL) 1226428d7b3dSmrg{ 1227428d7b3dSmrg SCRN_INFO_PTR(arg); 1228428d7b3dSmrg struct sna *sna = to_sna(scrn); 1229428d7b3dSmrg 1230428d7b3dSmrg DBG(("%s [scrn=%p, sna=%p]\n", __FUNCTION__, scrn, sna)); 1231428d7b3dSmrg if (sna == NULL || (uintptr_t)sna & 3) /* beware thieves */ 1232428d7b3dSmrg return; 1233428d7b3dSmrg 1234428d7b3dSmrg scrn->driverPrivate = (void *)((uintptr_t)sna->info | (sna->flags & SNA_IS_SLAVED) | 2); 1235428d7b3dSmrg 1236428d7b3dSmrg sna_mode_fini(sna); 1237428d7b3dSmrg sna_acpi_fini(sna); 1238428d7b3dSmrg 1239428d7b3dSmrg intel_put_device(sna->dev); 1240428d7b3dSmrg free(sna); 1241428d7b3dSmrg} 1242428d7b3dSmrg 1243428d7b3dSmrgstatic Bool sna_enter_vt(VT_FUNC_ARGS_DECL) 1244428d7b3dSmrg{ 1245428d7b3dSmrg SCRN_INFO_PTR(arg); 1246428d7b3dSmrg struct sna *sna = to_sna(scrn); 1247428d7b3dSmrg 1248428d7b3dSmrg DBG(("%s\n", __FUNCTION__)); 1249428d7b3dSmrg if (intel_get_master(sna->dev)) 1250428d7b3dSmrg return FALSE; 1251428d7b3dSmrg 1252428d7b3dSmrg if (sna->flags & SNA_REPROBE) { 1253428d7b3dSmrg DBG(("%s: reporting deferred hotplug event\n", 1254428d7b3dSmrg __FUNCTION__)); 1255428d7b3dSmrg sna_mode_discover(sna); 1256428d7b3dSmrg RRGetInfo(xf86ScrnToScreen(scrn), TRUE); 1257428d7b3dSmrg sna->flags &= ~SNA_REPROBE; 1258428d7b3dSmrg } 1259428d7b3dSmrg 1260428d7b3dSmrg if (!sna_set_desired_mode(sna)) { 1261428d7b3dSmrg intel_put_master(sna->dev); 1262428d7b3dSmrg return FALSE; 1263428d7b3dSmrg } 1264428d7b3dSmrg 1265428d7b3dSmrg sna_accel_enter(sna); 1266428d7b3dSmrg return TRUE; 1267428d7b3dSmrg} 1268428d7b3dSmrg 1269428d7b3dSmrgstatic Bool sna_switch_mode(SWITCH_MODE_ARGS_DECL) 1270428d7b3dSmrg{ 1271428d7b3dSmrg SCRN_INFO_PTR(arg); 1272428d7b3dSmrg DBG(("%s\n", __FUNCTION__)); 1273428d7b3dSmrg return xf86SetSingleMode(scrn, mode, RR_Rotate_0); 1274428d7b3dSmrg} 1275428d7b3dSmrg 1276428d7b3dSmrgstatic ModeStatus 1277428d7b3dSmrgsna_valid_mode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 1278428d7b3dSmrg{ 1279428d7b3dSmrg return MODE_OK; 1280428d7b3dSmrg} 1281428d7b3dSmrg 1282428d7b3dSmrg#ifndef SUSPEND_SLEEP 1283428d7b3dSmrg#define SUSPEND_SLEEP 0 1284428d7b3dSmrg#endif 1285428d7b3dSmrg#ifndef RESUME_SLEEP 1286428d7b3dSmrg#define RESUME_SLEEP 0 1287428d7b3dSmrg#endif 1288428d7b3dSmrg 1289428d7b3dSmrg/* 1290428d7b3dSmrg * This function is only required if we need to do anything differently from 1291428d7b3dSmrg * DoApmEvent() in common/xf86PM.c, including if we want to see events other 1292428d7b3dSmrg * than suspend/resume. 1293428d7b3dSmrg */ 1294428d7b3dSmrgstatic Bool sna_pm_event(SCRN_ARG_TYPE arg, pmEvent event, Bool undo) 1295428d7b3dSmrg{ 1296428d7b3dSmrg SCRN_INFO_PTR(arg); 1297428d7b3dSmrg struct sna *sna = to_sna(scrn); 1298428d7b3dSmrg 1299428d7b3dSmrg DBG(("%s\n", __FUNCTION__)); 1300428d7b3dSmrg 1301428d7b3dSmrg switch (event) { 1302428d7b3dSmrg case XF86_APM_SYS_SUSPEND: 1303428d7b3dSmrg case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend? */ 1304428d7b3dSmrg case XF86_APM_USER_SUSPEND: 1305428d7b3dSmrg case XF86_APM_SYS_STANDBY: 1306428d7b3dSmrg case XF86_APM_USER_STANDBY: 1307428d7b3dSmrg if (!undo && !sna->suspended) { 1308428d7b3dSmrg scrn->LeaveVT(VT_FUNC_ARGS(0)); 1309428d7b3dSmrg sna->suspended = TRUE; 1310428d7b3dSmrg sleep(SUSPEND_SLEEP); 1311428d7b3dSmrg } else if (undo && sna->suspended) { 1312428d7b3dSmrg sleep(RESUME_SLEEP); 1313428d7b3dSmrg scrn->EnterVT(VT_FUNC_ARGS(0)); 1314428d7b3dSmrg sna->suspended = FALSE; 1315428d7b3dSmrg } 1316428d7b3dSmrg break; 1317428d7b3dSmrg case XF86_APM_STANDBY_RESUME: 1318428d7b3dSmrg case XF86_APM_NORMAL_RESUME: 1319428d7b3dSmrg case XF86_APM_CRITICAL_RESUME: 1320428d7b3dSmrg if (sna->suspended) { 1321428d7b3dSmrg sleep(RESUME_SLEEP); 1322428d7b3dSmrg scrn->EnterVT(VT_FUNC_ARGS(0)); 1323428d7b3dSmrg sna->suspended = FALSE; 1324428d7b3dSmrg /* 1325428d7b3dSmrg * Turn the screen saver off when resuming. This seems to be 1326428d7b3dSmrg * needed to stop xscreensaver kicking in (when used). 1327428d7b3dSmrg * 1328428d7b3dSmrg * XXX DoApmEvent() should probably call this just like 1329428d7b3dSmrg * xf86VTSwitch() does. Maybe do it here only in 4.2 1330428d7b3dSmrg * compatibility mode. 1331428d7b3dSmrg */ 1332428d7b3dSmrg SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); 1333428d7b3dSmrg } 1334428d7b3dSmrg break; 1335428d7b3dSmrg /* This is currently used for ACPI */ 1336428d7b3dSmrg case XF86_APM_CAPABILITY_CHANGED: 1337428d7b3dSmrg SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); 1338428d7b3dSmrg break; 1339428d7b3dSmrg 1340428d7b3dSmrg default: 1341428d7b3dSmrg ERR(("sna_pm_event: received APM event %d\n", event)); 1342428d7b3dSmrg } 1343428d7b3dSmrg return TRUE; 1344428d7b3dSmrg} 1345428d7b3dSmrg 1346428d7b3dSmrgstatic Bool sna_enter_vt__hosted(VT_FUNC_ARGS_DECL) 1347428d7b3dSmrg{ 1348428d7b3dSmrg return TRUE; 1349428d7b3dSmrg} 1350428d7b3dSmrg 1351428d7b3dSmrgstatic void sna_leave_vt__hosted(VT_FUNC_ARGS_DECL) 1352428d7b3dSmrg{ 1353428d7b3dSmrg} 1354428d7b3dSmrg 1355428d7b3dSmrgstatic void describe_kms(ScrnInfoPtr scrn) 1356428d7b3dSmrg{ 1357428d7b3dSmrg int fd = __intel_peek_fd(scrn); 1358428d7b3dSmrg drm_version_t version; 1359428d7b3dSmrg char name[128] = ""; 1360428d7b3dSmrg char date[128] = ""; 1361428d7b3dSmrg 1362428d7b3dSmrg memset(&version, 0, sizeof(version)); 1363428d7b3dSmrg version.name_len = sizeof(name) - 1; 1364428d7b3dSmrg version.name = name; 1365428d7b3dSmrg version.date_len = sizeof(date) - 1; 1366428d7b3dSmrg version.date = date; 1367428d7b3dSmrg 1368428d7b3dSmrg if (drmIoctl(fd, DRM_IOCTL_VERSION, &version)) 1369428d7b3dSmrg return; 1370428d7b3dSmrg 1371428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 1372428d7b3dSmrg "Using Kernel Mode Setting driver: %s, version %d.%d.%d %s\n", 1373428d7b3dSmrg version.name, 1374428d7b3dSmrg version.version_major, version.version_minor, version.version_patchlevel, 1375428d7b3dSmrg version.date); 1376428d7b3dSmrg} 1377428d7b3dSmrg 1378428d7b3dSmrgstatic void describe_sna(ScrnInfoPtr scrn) 1379428d7b3dSmrg{ 1380428d7b3dSmrg#if defined(USE_GIT_DESCRIBE) 1381428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 1382428d7b3dSmrg "SNA compiled from %s\n", git_version); 1383428d7b3dSmrg#elif defined(BUILDER_DESCRIPTION) 1384428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 1385428d7b3dSmrg "SNA compiled: %s\n", BUILDER_DESCRIPTION); 1386428d7b3dSmrg#endif 1387428d7b3dSmrg#if !NDEBUG 1388428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 1389428d7b3dSmrg "SNA compiled with assertions enabled\n"); 1390428d7b3dSmrg#endif 1391428d7b3dSmrg#if DEBUG_SYNC 1392428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 1393428d7b3dSmrg "SNA compiled with synchronous rendering\n"); 1394428d7b3dSmrg#endif 1395428d7b3dSmrg#if DEBUG_MEMORY 1396428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 1397428d7b3dSmrg "SNA compiled with memory allocation reporting enabled\n"); 1398428d7b3dSmrg#endif 1399428d7b3dSmrg#if DEBUG_PIXMAP 1400428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 1401428d7b3dSmrg "SNA compiled with extra pixmap/damage validation\n"); 1402428d7b3dSmrg#endif 1403428d7b3dSmrg#ifdef HAVE_VALGRIND 1404428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 1405428d7b3dSmrg "SNA compiled for use with valgrind\n"); 1406428d7b3dSmrg VALGRIND_PRINTF("SNA compiled for use with valgrind\n"); 1407428d7b3dSmrg#endif 1408428d7b3dSmrg DBG(("pixman version: %s\n", pixman_version_string())); 1409428d7b3dSmrg} 1410428d7b3dSmrg 1411428d7b3dSmrgBool sna_init_scrn(ScrnInfoPtr scrn, int entity_num) 1412428d7b3dSmrg{ 1413428d7b3dSmrg DBG(("%s: entity_num=%d\n", __FUNCTION__, entity_num)); 1414428d7b3dSmrg describe_kms(scrn); 1415428d7b3dSmrg describe_sna(scrn); 1416428d7b3dSmrg 1417428d7b3dSmrg scrn->PreInit = sna_pre_init; 1418428d7b3dSmrg scrn->ScreenInit = sna_screen_init; 1419428d7b3dSmrg if (!hosted()) { 1420428d7b3dSmrg scrn->SwitchMode = sna_switch_mode; 1421428d7b3dSmrg scrn->AdjustFrame = sna_adjust_frame; 1422428d7b3dSmrg scrn->EnterVT = sna_enter_vt; 1423428d7b3dSmrg scrn->LeaveVT = sna_leave_vt; 1424428d7b3dSmrg scrn->ValidMode = sna_valid_mode; 1425428d7b3dSmrg scrn->PMEvent = sna_pm_event; 1426428d7b3dSmrg } else { 1427428d7b3dSmrg scrn->EnterVT = sna_enter_vt__hosted; 1428428d7b3dSmrg scrn->LeaveVT = sna_leave_vt__hosted; 1429428d7b3dSmrg } 1430428d7b3dSmrg scrn->FreeScreen = sna_free_screen; 1431428d7b3dSmrg 1432428d7b3dSmrg xf86SetEntitySharable(entity_num); 1433428d7b3dSmrg xf86SetEntityInstanceForScreen(scrn, entity_num, 1434428d7b3dSmrg xf86GetNumEntityInstances(entity_num)-1); 1435428d7b3dSmrg 1436428d7b3dSmrg sna_threads_init(); 1437428d7b3dSmrg 1438428d7b3dSmrg return TRUE; 1439428d7b3dSmrg} 1440428d7b3dSmrg 1441428d7b3dSmrg#if HAS_DEBUG_FULL 1442428d7b3dSmrg_X_ATTRIBUTE_PRINTF(1, 0) void LogF(const char *f, ...) 1443428d7b3dSmrg{ 1444428d7b3dSmrg va_list ap; 1445428d7b3dSmrg 1446428d7b3dSmrg /* As we not only may be called from any context, we may also 1447428d7b3dSmrg * be called from a thread whilst the main thread is handling 1448428d7b3dSmrg * signals, therefore we have to use the signal-safe variants 1449428d7b3dSmrg * or else we trip over false positive assertions. 1450428d7b3dSmrg */ 1451428d7b3dSmrg 1452428d7b3dSmrg va_start(ap, f); 1453428d7b3dSmrg#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0) 1454428d7b3dSmrg LogVMessageVerbSigSafe(X_NONE, 1, f, ap); 1455428d7b3dSmrg#else 1456428d7b3dSmrg LogVMessageVerb(X_NONE, 1, f, ap); 1457428d7b3dSmrg#endif 1458428d7b3dSmrg va_end(ap); 1459428d7b3dSmrg} 1460428d7b3dSmrg#endif 1461