intel_display.c revision 603fc0a3
1/* 2 * Copyright © 2007 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Dave Airlie <airlied@redhat.com> 25 * 26 */ 27 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include <sys/types.h> 33#include <sys/stat.h> 34#include <sys/poll.h> 35#include <fcntl.h> 36#include <unistd.h> 37#include <errno.h> 38#include <sys/ioctl.h> 39 40#include "xorg-server.h" 41#include "xorgVersion.h" 42 43#include "intel.h" 44#include "intel_bufmgr.h" 45#include "intel_options.h" 46#include "backlight.h" 47#include "xf86drm.h" 48#include "xf86drmMode.h" 49#include "X11/Xatom.h" 50#if defined(HAVE_X11_EXTENSIONS_DPMSCONST_H) 51#include <X11/extensions/dpmsconst.h> 52#else 53#define DPMSModeOn 0 54#define DPMSModeOff 3 55#endif 56#include "xf86DDC.h" 57#include "fb.h" 58 59#if USE_UXA 60#include "intel_uxa.h" 61#endif 62 63#define KNOWN_MODE_FLAGS ((1<<14)-1) 64 65struct intel_drm_queue { 66 struct list list; 67 xf86CrtcPtr crtc; 68 uint32_t seq; 69 void *data; 70 ScrnInfoPtr scrn; 71 intel_drm_handler_proc handler; 72 intel_drm_abort_proc abort; 73}; 74 75static uint32_t intel_drm_seq; 76static struct list intel_drm_queue; 77 78struct intel_mode { 79 int fd; 80 uint32_t fb_id; 81 int cpp; 82 83 drmEventContext event_context; 84 int old_fb_id; 85 int flip_count; 86 uint64_t fe_msc; 87 uint64_t fe_usec; 88 89 struct list outputs; 90 struct list crtcs; 91 92 struct { 93 intel_pageflip_handler_proc handler; 94 intel_pageflip_abort_proc abort; 95 void *data; 96 } pageflip; 97}; 98 99struct intel_pageflip { 100 struct intel_mode *mode; 101 Bool dispatch_me; 102}; 103 104struct intel_crtc { 105 struct intel_mode *mode; 106 drmModeModeInfo kmode; 107 drmModeCrtcPtr mode_crtc; 108 int pipe; 109 dri_bo *cursor; 110 dri_bo *rotate_bo; 111 uint32_t rotate_pitch; 112 uint32_t rotate_fb_id; 113 xf86CrtcPtr crtc; 114 struct list link; 115 PixmapPtr scanout_pixmap; 116 uint32_t scanout_fb_id; 117 uint32_t msc_prev; 118 uint64_t msc_high; 119}; 120 121struct intel_property { 122 drmModePropertyPtr mode_prop; 123 uint64_t value; 124 int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */ 125 Atom *atoms; 126}; 127 128struct intel_output { 129 struct intel_mode *mode; 130 int output_id; 131 drmModeConnectorPtr mode_output; 132 drmModeEncoderPtr *mode_encoders; 133 drmModePropertyBlobPtr edid_blob; 134 int num_props; 135 struct intel_property *props; 136 void *private_data; 137 138 Bool has_panel_limits; 139 int panel_hdisplay; 140 int panel_vdisplay; 141 142 int dpms_mode; 143 struct backlight backlight; 144 int backlight_active_level; 145 xf86OutputPtr output; 146 struct list link; 147 int enc_mask; 148 int enc_clone_mask; 149}; 150 151static void 152intel_output_dpms(xf86OutputPtr output, int mode); 153 154static void 155intel_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode); 156 157static inline int 158crtc_id(struct intel_crtc *crtc) 159{ 160 return crtc->mode_crtc->crtc_id; 161} 162 163static void 164intel_output_backlight_set(xf86OutputPtr output, int level) 165{ 166 struct intel_output *intel_output = output->driver_private; 167 if (backlight_set(&intel_output->backlight, level) < 0) { 168 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 169 "failed to set backlight %s to brightness level %d, disabling\n", 170 intel_output->backlight.iface, level); 171 backlight_disable(&intel_output->backlight); 172 } 173} 174 175static int 176intel_output_backlight_get(xf86OutputPtr output) 177{ 178 struct intel_output *intel_output = output->driver_private; 179 return backlight_get(&intel_output->backlight); 180} 181 182static void 183intel_output_backlight_init(xf86OutputPtr output) 184{ 185 struct intel_output *intel_output = output->driver_private; 186 intel_screen_private *intel = intel_get_screen_private(output->scrn); 187 const char *str; 188 189#if !USE_BACKLIGHT 190 return; 191#endif 192 193 str = xf86GetOptValString(intel->Options, OPTION_BACKLIGHT); 194 if (str != NULL) { 195 if (backlight_exists(str)) { 196 intel_output->backlight_active_level = 197 backlight_open(&intel_output->backlight, 198 strdup(str)); 199 if (intel_output->backlight_active_level != -1) { 200 xf86DrvMsg(output->scrn->scrnIndex, X_CONFIG, 201 "found backlight control interface %s\n", str); 202 return; 203 } 204 } 205 206 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 207 "unrecognised backlight control interface %s\n", str); 208 } 209 210 intel_output->backlight_active_level = 211 backlight_open(&intel_output->backlight, NULL); 212 if (intel_output->backlight_active_level != -1) { 213 xf86DrvMsg(output->scrn->scrnIndex, X_PROBED, 214 "found backlight control interface %s\n", 215 intel_output->backlight.iface); 216 return; 217 } 218} 219 220static void 221mode_from_kmode(ScrnInfoPtr scrn, 222 drmModeModeInfoPtr kmode, 223 DisplayModePtr mode) 224{ 225 memset(mode, 0, sizeof(DisplayModeRec)); 226 mode->status = MODE_OK; 227 228 mode->Clock = kmode->clock; 229 230 mode->HDisplay = kmode->hdisplay; 231 mode->HSyncStart = kmode->hsync_start; 232 mode->HSyncEnd = kmode->hsync_end; 233 mode->HTotal = kmode->htotal; 234 mode->HSkew = kmode->hskew; 235 236 mode->VDisplay = kmode->vdisplay; 237 mode->VSyncStart = kmode->vsync_start; 238 mode->VSyncEnd = kmode->vsync_end; 239 mode->VTotal = kmode->vtotal; 240 mode->VScan = kmode->vscan; 241 242 mode->Flags = kmode->flags; 243 mode->name = strdup(kmode->name); 244 245 if (kmode->type & DRM_MODE_TYPE_DRIVER) 246 mode->type = M_T_DRIVER; 247 if (kmode->type & DRM_MODE_TYPE_PREFERRED) 248 mode->type |= M_T_PREFERRED; 249 250 if (mode->status == MODE_OK && kmode->flags & ~KNOWN_MODE_FLAGS) 251 mode->status = MODE_BAD; /* unknown flags => unhandled */ 252 253 xf86SetModeCrtc (mode, scrn->adjustFlags); 254} 255 256static void 257mode_to_kmode(ScrnInfoPtr scrn, 258 drmModeModeInfoPtr kmode, 259 DisplayModePtr mode) 260{ 261 memset(kmode, 0, sizeof(*kmode)); 262 263 kmode->clock = mode->Clock; 264 kmode->hdisplay = mode->HDisplay; 265 kmode->hsync_start = mode->HSyncStart; 266 kmode->hsync_end = mode->HSyncEnd; 267 kmode->htotal = mode->HTotal; 268 kmode->hskew = mode->HSkew; 269 270 kmode->vdisplay = mode->VDisplay; 271 kmode->vsync_start = mode->VSyncStart; 272 kmode->vsync_end = mode->VSyncEnd; 273 kmode->vtotal = mode->VTotal; 274 kmode->vscan = mode->VScan; 275 276 kmode->flags = mode->Flags; 277 if (mode->name) 278 strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN); 279 kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; 280} 281 282static void 283intel_crtc_dpms(xf86CrtcPtr crtc, int mode) 284{ 285} 286 287void 288intel_mode_disable_unused_functions(ScrnInfoPtr scrn) 289{ 290 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 291 struct intel_mode *mode = intel_get_screen_private(scrn)->modes; 292 int i; 293 294 /* Force off for consistency between kernel and ddx */ 295 for (i = 0; i < xf86_config->num_crtc; i++) { 296 xf86CrtcPtr crtc = xf86_config->crtc[i]; 297 if (!crtc->enabled) 298 drmModeSetCrtc(mode->fd, crtc_id(crtc->driver_private), 299 0, 0, 0, NULL, 0, NULL); 300 } 301} 302 303static Bool 304intel_crtc_apply(xf86CrtcPtr crtc) 305{ 306 ScrnInfoPtr scrn = crtc->scrn; 307 struct intel_crtc *intel_crtc = crtc->driver_private; 308 struct intel_mode *mode = intel_crtc->mode; 309 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 310 uint32_t *output_ids; 311 int output_count = 0; 312 int fb_id, x, y; 313 int i, ret = FALSE; 314 315 output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); 316 if (!output_ids) 317 return FALSE; 318 319 for (i = 0; i < xf86_config->num_output; i++) { 320 xf86OutputPtr output = xf86_config->output[i]; 321 struct intel_output *intel_output; 322 323 /* Make sure we mark the output as off (and save the backlight) 324 * before the kernel turns it off due to changing the pipe. 325 * This is necessary as the kernel may turn off the backlight 326 * and we lose track of the user settings. 327 */ 328 if (output->crtc == NULL) 329 output->funcs->dpms(output, DPMSModeOff); 330 331 if (output->crtc != crtc) 332 continue; 333 334 intel_output = output->driver_private; 335 if (!intel_output->mode_output) 336 return FALSE; 337 338 output_ids[output_count] = 339 intel_output->mode_output->connector_id; 340 output_count++; 341 } 342 343 if (!intel_crtc->scanout_fb_id) { 344#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0) 345 if (!xf86CrtcRotate(crtc, mode, rotation)) 346 goto done; 347#else 348 if (!xf86CrtcRotate(crtc)) 349 goto done; 350#endif 351 } 352 353#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0) 354 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, 355 crtc->gamma_blue, crtc->gamma_size); 356#endif 357 358 x = crtc->x; 359 y = crtc->y; 360 fb_id = mode->fb_id; 361 if (intel_crtc->rotate_fb_id) { 362 fb_id = intel_crtc->rotate_fb_id; 363 x = 0; 364 y = 0; 365 } else if (intel_crtc->scanout_fb_id && intel_crtc->scanout_pixmap->drawable.width >= crtc->mode.HDisplay && intel_crtc->scanout_pixmap->drawable.height >= crtc->mode.VDisplay) { 366 fb_id = intel_crtc->scanout_fb_id; 367 x = 0; 368 y = 0; 369 } 370 ret = drmModeSetCrtc(mode->fd, crtc_id(intel_crtc), 371 fb_id, x, y, output_ids, output_count, 372 &intel_crtc->kmode); 373 if (ret) { 374 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, 375 "failed to set mode: %s\n", strerror(-ret)); 376 ret = FALSE; 377 } else { 378 ret = TRUE; 379 380 /* Force DPMS to On for all outputs, which the kernel will have done 381 * with the mode set. Also, restore the backlight level 382 */ 383 for (i = 0; i < xf86_config->num_output; i++) { 384 xf86OutputPtr output = xf86_config->output[i]; 385 struct intel_output *intel_output; 386 387 if (output->crtc != crtc) 388 continue; 389 390 intel_output = output->driver_private; 391 intel_output_dpms_backlight(output, intel_output->dpms_mode, DPMSModeOn); 392 intel_output->dpms_mode = DPMSModeOn; 393 } 394 } 395 396 if (scrn->pScreen) { 397#ifdef HAVE_XF86_CURSOR_RESET_CURSOR 398 xf86CursorResetCursor(scrn->pScreen); 399#else 400 xf86_reload_cursors(scrn->pScreen); 401#endif 402 } 403 404done: 405 free(output_ids); 406 return ret; 407} 408 409static Bool 410intel_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, 411 Rotation rotation, int x, int y) 412{ 413 ScrnInfoPtr scrn = crtc->scrn; 414 intel_screen_private *intel = intel_get_screen_private(scrn); 415 struct intel_crtc *intel_crtc = crtc->driver_private; 416 struct intel_mode *intel_mode = intel_crtc->mode; 417 int saved_x, saved_y; 418 Rotation saved_rotation; 419 DisplayModeRec saved_mode; 420 int ret = TRUE; 421 unsigned int pitch = scrn->displayWidth * intel->cpp; 422 423 if (intel_mode->fb_id == 0) { 424 ret = drmModeAddFB(intel_mode->fd, 425 scrn->virtualX, scrn->virtualY, 426 scrn->depth, scrn->bitsPerPixel, 427 pitch, intel->front_buffer->handle, 428 &intel_mode->fb_id); 429 if (ret < 0) { 430 ErrorF("failed to add fb\n"); 431 return FALSE; 432 } 433 434 drm_intel_bo_disable_reuse(intel->front_buffer); 435 } 436 437 saved_mode = crtc->mode; 438 saved_x = crtc->x; 439 saved_y = crtc->y; 440 saved_rotation = crtc->rotation; 441 442 crtc->mode = *mode; 443 crtc->x = x; 444 crtc->y = y; 445 crtc->rotation = rotation; 446 447 intel_flush(intel); 448 449 mode_to_kmode(crtc->scrn, &intel_crtc->kmode, mode); 450 ret = intel_crtc_apply(crtc); 451 if (!ret) { 452 crtc->x = saved_x; 453 crtc->y = saved_y; 454 crtc->rotation = saved_rotation; 455 crtc->mode = saved_mode; 456 } 457 return ret; 458} 459 460static void 461intel_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) 462{ 463 464} 465 466static void 467intel_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) 468{ 469 struct intel_crtc *intel_crtc = crtc->driver_private; 470 struct intel_mode *mode = intel_crtc->mode; 471 472 drmModeMoveCursor(mode->fd, crtc_id(intel_crtc), x, y); 473} 474 475static int 476__intel_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image) 477{ 478 struct intel_crtc *intel_crtc = crtc->driver_private; 479 int ret; 480 481 ret = dri_bo_subdata(intel_crtc->cursor, 0, 64*64*4, image); 482 if (ret) 483 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, 484 "failed to set cursor: %s\n", strerror(-ret)); 485 486 return ret; 487} 488 489#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,902,2) 490static Bool 491intel_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image) 492{ 493 return __intel_crtc_load_cursor_argb(crtc, image) == 0; 494} 495#else 496static void 497intel_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image) 498{ 499 __intel_crtc_load_cursor_argb(crtc, image); 500} 501#endif 502 503static void 504intel_crtc_hide_cursor(xf86CrtcPtr crtc) 505{ 506 struct intel_crtc *intel_crtc = crtc->driver_private; 507 struct intel_mode *mode = intel_crtc->mode; 508 509 drmModeSetCursor(mode->fd, crtc_id(intel_crtc), 0, 64, 64); 510} 511 512static void 513intel_crtc_show_cursor(xf86CrtcPtr crtc) 514{ 515 struct intel_crtc *intel_crtc = crtc->driver_private; 516 struct intel_mode *mode = intel_crtc->mode; 517 518 drmModeSetCursor(mode->fd, crtc_id(intel_crtc), 519 intel_crtc->cursor->handle, 64, 64); 520} 521 522static void * 523intel_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) 524{ 525 ScrnInfoPtr scrn = crtc->scrn; 526 struct intel_crtc *intel_crtc = crtc->driver_private; 527 struct intel_mode *mode = intel_crtc->mode; 528 int rotate_pitch; 529 uint32_t tiling; 530 int ret; 531 532 intel_crtc->rotate_bo = intel_allocate_framebuffer(scrn, 533 width, height, 534 mode->cpp, 535 &rotate_pitch, 536 &tiling); 537 538 if (!intel_crtc->rotate_bo) { 539 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, 540 "Couldn't allocate shadow memory for rotated CRTC\n"); 541 return NULL; 542 } 543 544 ret = drmModeAddFB(mode->fd, width, height, crtc->scrn->depth, 545 crtc->scrn->bitsPerPixel, rotate_pitch, 546 intel_crtc->rotate_bo->handle, 547 &intel_crtc->rotate_fb_id); 548 if (ret) { 549 ErrorF("failed to add rotate fb\n"); 550 drm_intel_bo_unreference(intel_crtc->rotate_bo); 551 return NULL; 552 } 553 554 intel_crtc->rotate_pitch = rotate_pitch; 555 return intel_crtc->rotate_bo; 556} 557 558static PixmapPtr 559intel_create_pixmap_header(ScreenPtr pScreen, int width, int height, int depth, 560 int bitsPerPixel, int devKind, void *pPixData) 561{ 562 PixmapPtr pixmap; 563 564 /* width and height of 0 means don't allocate any pixmap data */ 565 pixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, 0); 566 567 if (pixmap) { 568 if ((*pScreen->ModifyPixmapHeader) (pixmap, width, height, depth, 569 bitsPerPixel, devKind, pPixData)) 570 { 571 return pixmap; 572 } 573 (*pScreen->DestroyPixmap) (pixmap); 574 } 575 return NullPixmap; 576} 577 578static PixmapPtr 579intel_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) 580{ 581 ScrnInfoPtr scrn = crtc->scrn; 582 intel_screen_private *intel = intel_get_screen_private(scrn); 583 struct intel_crtc *intel_crtc = crtc->driver_private; 584 PixmapPtr rotate_pixmap; 585 586 if (!data) { 587 data = intel_crtc_shadow_allocate (crtc, width, height); 588 if (!data) { 589 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 590 "Couldn't allocate shadow pixmap for rotated CRTC\n"); 591 return NULL; 592 } 593 } 594 if (intel_crtc->rotate_bo == NULL) { 595 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 596 "Couldn't allocate shadow pixmap for rotated CRTC\n"); 597 return NULL; 598 } 599 600 rotate_pixmap = intel_create_pixmap_header(scrn->pScreen, 601 width, height, 602 scrn->depth, 603 scrn->bitsPerPixel, 604 intel_crtc->rotate_pitch, 605 NULL); 606 607 if (rotate_pixmap == NULL) { 608 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 609 "Couldn't allocate shadow pixmap for rotated CRTC\n"); 610 return NULL; 611 } 612 613 intel_set_pixmap_bo(rotate_pixmap, intel_crtc->rotate_bo); 614 615 intel->shadow_present = TRUE; 616 617 return rotate_pixmap; 618} 619 620static void 621intel_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) 622{ 623 ScrnInfoPtr scrn = crtc->scrn; 624 intel_screen_private *intel = intel_get_screen_private(scrn); 625 struct intel_crtc *intel_crtc = crtc->driver_private; 626 struct intel_mode *mode = intel_crtc->mode; 627 628 if (rotate_pixmap) { 629 intel_set_pixmap_bo(rotate_pixmap, NULL); 630 rotate_pixmap->drawable.pScreen->DestroyPixmap(rotate_pixmap); 631 } 632 633 if (data) { 634 /* Be sure to sync acceleration before the memory gets 635 * unbound. */ 636 drmModeRmFB(mode->fd, intel_crtc->rotate_fb_id); 637 intel_crtc->rotate_fb_id = 0; 638 639 dri_bo_unreference(intel_crtc->rotate_bo); 640 intel_crtc->rotate_bo = NULL; 641 } 642 643 intel->shadow_present = FALSE; 644} 645 646static void 647intel_crtc_gamma_set(xf86CrtcPtr crtc, 648 CARD16 *red, CARD16 *green, CARD16 *blue, int size) 649{ 650 struct intel_crtc *intel_crtc = crtc->driver_private; 651 struct intel_mode *mode = intel_crtc->mode; 652 653 drmModeCrtcSetGamma(mode->fd, crtc_id(intel_crtc), 654 size, red, green, blue); 655} 656 657static void 658intel_crtc_destroy(xf86CrtcPtr crtc) 659{ 660 struct intel_crtc *intel_crtc = crtc->driver_private; 661 662 if (intel_crtc->cursor) { 663 drmModeSetCursor(intel_crtc->mode->fd, crtc_id(intel_crtc), 0, 64, 64); 664 drm_intel_bo_unreference(intel_crtc->cursor); 665 intel_crtc->cursor = NULL; 666 } 667 668 list_del(&intel_crtc->link); 669 free(intel_crtc); 670 671 crtc->driver_private = NULL; 672} 673 674#ifdef INTEL_PIXMAP_SHARING 675static Bool 676intel_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) 677{ 678 struct intel_crtc *intel_crtc = crtc->driver_private; 679 ScrnInfoPtr scrn = crtc->scrn; 680 intel_screen_private *intel = intel_get_screen_private(scrn); 681 dri_bo *bo; 682 683 if (ppix == intel_crtc->scanout_pixmap) 684 return TRUE; 685 686 if (!ppix) { 687 intel_crtc->scanout_pixmap = NULL; 688 if (intel_crtc->scanout_fb_id) { 689 drmModeRmFB(intel->drmSubFD, intel_crtc->scanout_fb_id); 690 intel_crtc->scanout_fb_id = 0; 691 } 692 return TRUE; 693 } 694 695 bo = intel_get_pixmap_bo(ppix); 696 if (!bo) 697 return FALSE; 698 699 if (intel->front_buffer) 700 return FALSE; 701 702 drm_intel_bo_disable_reuse(bo); 703 704 intel_crtc->scanout_pixmap = ppix; 705 return drmModeAddFB(intel->drmSubFD, ppix->drawable.width, 706 ppix->drawable.height, ppix->drawable.depth, 707 ppix->drawable.bitsPerPixel, ppix->devKind, 708 bo->handle, &intel_crtc->scanout_fb_id) == 0; 709} 710#endif 711 712static const xf86CrtcFuncsRec intel_crtc_funcs = { 713 .dpms = intel_crtc_dpms, 714 .set_mode_major = intel_crtc_set_mode_major, 715 .set_cursor_colors = intel_crtc_set_cursor_colors, 716 .set_cursor_position = intel_crtc_set_cursor_position, 717 .show_cursor = intel_crtc_show_cursor, 718 .hide_cursor = intel_crtc_hide_cursor, 719#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,902,3) 720 .load_cursor_argb_check = intel_crtc_load_cursor_argb, 721#else 722 .load_cursor_argb = intel_crtc_load_cursor_argb, 723#endif 724 .shadow_create = intel_crtc_shadow_create, 725 .shadow_allocate = intel_crtc_shadow_allocate, 726 .shadow_destroy = intel_crtc_shadow_destroy, 727 .gamma_set = intel_crtc_gamma_set, 728 .destroy = intel_crtc_destroy, 729#ifdef INTEL_PIXMAP_SHARING 730 .set_scanout_pixmap = intel_set_scanout_pixmap, 731#endif 732}; 733 734static void 735intel_crtc_init(ScrnInfoPtr scrn, struct intel_mode *mode, drmModeResPtr mode_res, int num) 736{ 737 intel_screen_private *intel = intel_get_screen_private(scrn); 738 xf86CrtcPtr crtc; 739 struct intel_crtc *intel_crtc; 740 741 intel_crtc = calloc(sizeof(struct intel_crtc), 1); 742 if (intel_crtc == NULL) 743 return; 744 745 crtc = xf86CrtcCreate(scrn, &intel_crtc_funcs); 746 if (crtc == NULL) { 747 free(intel_crtc); 748 return; 749 } 750 751 intel_crtc->mode_crtc = drmModeGetCrtc(mode->fd, 752 mode_res->crtcs[num]); 753 if (intel_crtc->mode_crtc == NULL) { 754 free(intel_crtc); 755 return; 756 } 757 758 intel_crtc->mode = mode; 759 crtc->driver_private = intel_crtc; 760 761 intel_crtc->pipe = drm_intel_get_pipe_from_crtc_id(intel->bufmgr, 762 crtc_id(intel_crtc)); 763 764 intel_crtc->cursor = drm_intel_bo_alloc(intel->bufmgr, "ARGB cursor", 765 4*64*64, 4096); 766 767 intel_crtc->crtc = crtc; 768 list_add(&intel_crtc->link, &mode->crtcs); 769} 770 771static Bool 772is_panel(int type) 773{ 774 return (type == DRM_MODE_CONNECTOR_LVDS || 775 type == DRM_MODE_CONNECTOR_eDP); 776} 777 778static xf86OutputStatus 779intel_output_detect(xf86OutputPtr output) 780{ 781 /* go to the hw and retrieve a new output struct */ 782 struct intel_output *intel_output = output->driver_private; 783 struct intel_mode *mode = intel_output->mode; 784 xf86OutputStatus status; 785 786 drmModeFreeConnector(intel_output->mode_output); 787 intel_output->mode_output = 788 drmModeGetConnector(mode->fd, intel_output->output_id); 789 if (intel_output->mode_output == NULL) { 790 /* and hope we are safe everywhere else */ 791 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 792 "drmModeGetConnector failed, reporting output disconnected\n"); 793 return XF86OutputStatusDisconnected; 794 } 795 796 switch (intel_output->mode_output->connection) { 797 case DRM_MODE_CONNECTED: 798 status = XF86OutputStatusConnected; 799 break; 800 case DRM_MODE_DISCONNECTED: 801 status = XF86OutputStatusDisconnected; 802 break; 803 default: 804 case DRM_MODE_UNKNOWNCONNECTION: 805 status = XF86OutputStatusUnknown; 806 break; 807 } 808 return status; 809} 810 811static Bool 812intel_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) 813{ 814 struct intel_output *intel_output = output->driver_private; 815 816 /* 817 * If the connector type is a panel, we will use the panel limit to 818 * verfiy whether the mode is valid. 819 */ 820 if (intel_output->has_panel_limits) { 821 if (pModes->HDisplay > intel_output->panel_hdisplay || 822 pModes->VDisplay > intel_output->panel_vdisplay) 823 return MODE_PANEL; 824 } 825 826 return MODE_OK; 827} 828 829static void 830intel_output_attach_edid(xf86OutputPtr output) 831{ 832 struct intel_output *intel_output = output->driver_private; 833 drmModeConnectorPtr koutput = intel_output->mode_output; 834 struct intel_mode *mode = intel_output->mode; 835 xf86MonPtr mon = NULL; 836 int i; 837 838 if (!koutput) { 839 xf86OutputSetEDID(output, mon); 840 return; 841 } 842 843 /* look for an EDID property */ 844 for (i = 0; i < koutput->count_props; i++) { 845 drmModePropertyPtr props; 846 847 props = drmModeGetProperty(mode->fd, koutput->props[i]); 848 if (!props) 849 continue; 850 851 if (!(props->flags & DRM_MODE_PROP_BLOB)) { 852 drmModeFreeProperty(props); 853 continue; 854 } 855 856 if (!strcmp(props->name, "EDID")) { 857 drmModeFreePropertyBlob(intel_output->edid_blob); 858 intel_output->edid_blob = 859 drmModeGetPropertyBlob(mode->fd, 860 koutput->prop_values[i]); 861 } 862 drmModeFreeProperty(props); 863 } 864 865 if (intel_output->edid_blob) { 866 mon = xf86InterpretEDID(output->scrn->scrnIndex, 867 intel_output->edid_blob->data); 868 869 if (mon && intel_output->edid_blob->length > 128) 870 mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA; 871 } 872 873 xf86OutputSetEDID(output, mon); 874} 875 876static void 877intel_output_attach_tile(xf86OutputPtr output) 878{ 879#if XF86_OUTPUT_VERSION >= 3 880 struct intel_output *intel_output = output->driver_private; 881 drmModeConnectorPtr koutput = intel_output->mode_output; 882 struct intel_mode *mode = intel_output->mode; 883 drmModePropertyBlobPtr blob = NULL; 884 struct xf86CrtcTileInfo tile_info, *set = NULL; 885 int i; 886 887 for (i = 0; koutput && i < koutput->count_props; i++) { 888 drmModePropertyPtr props; 889 890 props = drmModeGetProperty(mode->fd, koutput->props[i]); 891 if (!props) 892 continue; 893 894 if (!(props->flags & DRM_MODE_PROP_BLOB)) { 895 drmModeFreeProperty(props); 896 continue; 897 } 898 899 if (!strcmp(props->name, "TILE")) { 900 blob = drmModeGetPropertyBlob(mode->fd, 901 koutput->prop_values[i]); 902 } 903 drmModeFreeProperty(props); 904 } 905 906 if (blob) { 907 if (xf86OutputParseKMSTile(blob->data, 908 blob->length, 909 &tile_info)) 910 set = &tile_info; 911 drmModeFreePropertyBlob(blob); 912 } 913 914 xf86OutputSetTile(output, set); 915#endif 916} 917 918static DisplayModePtr 919intel_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes) 920{ 921 xf86MonPtr mon = output->MonInfo; 922 923 if (!mon || !GTF_SUPPORTED(mon->features.msc)) { 924 DisplayModePtr i, m, p = NULL; 925 int max_x = 0, max_y = 0; 926 float max_vrefresh = 0.0; 927 928 for (m = modes; m; m = m->next) { 929 if (m->type & M_T_PREFERRED) 930 p = m; 931 max_x = max(max_x, m->HDisplay); 932 max_y = max(max_y, m->VDisplay); 933 max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m)); 934 } 935 936 max_vrefresh = max(max_vrefresh, 60.0); 937 max_vrefresh *= (1 + SYNC_TOLERANCE); 938 939#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,0,0) 940 m = xf86GetDefaultModes(); 941#else 942 m = xf86GetDefaultModes(0,0); 943#endif 944 945 xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0); 946 947 for (i = m; i; i = i->next) { 948 if (xf86ModeVRefresh(i) > max_vrefresh) 949 i->status = MODE_VSYNC; 950 if (p && i->HDisplay >= p->HDisplay && 951 i->VDisplay >= p->VDisplay && 952 xf86ModeVRefresh(i) >= xf86ModeVRefresh(p)) 953 i->status = MODE_VSYNC; 954 } 955 956 xf86PruneInvalidModes(output->scrn, &m, FALSE); 957 958 modes = xf86ModesAdd(modes, m); 959 } 960 961 return modes; 962} 963 964static DisplayModePtr 965intel_output_get_modes(xf86OutputPtr output) 966{ 967 struct intel_output *intel_output = output->driver_private; 968 drmModeConnectorPtr koutput = intel_output->mode_output; 969 DisplayModePtr Modes = NULL; 970 int i; 971 972 intel_output_attach_edid(output); 973 intel_output_attach_tile(output); 974 975 if (!koutput) 976 return Modes; 977 978 /* modes should already be available */ 979 for (i = 0; i < koutput->count_modes; i++) { 980 DisplayModePtr Mode; 981 982 Mode = calloc(1, sizeof(DisplayModeRec)); 983 if (Mode) { 984 mode_from_kmode(output->scrn, &koutput->modes[i], Mode); 985 Modes = xf86ModesAdd(Modes, Mode); 986 } 987 } 988 989 /* 990 * If the connector type is a panel, we will traverse the kernel mode to 991 * get the panel limit. And then add all the standard modes to fake 992 * the fullscreen experience. 993 * If it is incorrect, please fix me. 994 */ 995 intel_output->has_panel_limits = FALSE; 996 if (is_panel(koutput->connector_type)) { 997 for (i = 0; i < koutput->count_modes; i++) { 998 drmModeModeInfo *mode_ptr; 999 1000 mode_ptr = &koutput->modes[i]; 1001 if (mode_ptr->hdisplay > intel_output->panel_hdisplay) 1002 intel_output->panel_hdisplay = mode_ptr->hdisplay; 1003 if (mode_ptr->vdisplay > intel_output->panel_vdisplay) 1004 intel_output->panel_vdisplay = mode_ptr->vdisplay; 1005 } 1006 1007 intel_output->has_panel_limits = 1008 intel_output->panel_hdisplay && 1009 intel_output->panel_vdisplay; 1010 1011 Modes = intel_output_panel_edid(output, Modes); 1012 } 1013 1014 return Modes; 1015} 1016 1017static void 1018intel_output_destroy(xf86OutputPtr output) 1019{ 1020 struct intel_output *intel_output = output->driver_private; 1021 int i; 1022 1023 drmModeFreePropertyBlob(intel_output->edid_blob); 1024 1025 for (i = 0; i < intel_output->num_props; i++) { 1026 drmModeFreeProperty(intel_output->props[i].mode_prop); 1027 free(intel_output->props[i].atoms); 1028 } 1029 free(intel_output->props); 1030 for (i = 0; i < intel_output->mode_output->count_encoders; i++) { 1031 drmModeFreeEncoder(intel_output->mode_encoders[i]); 1032 } 1033 free(intel_output->mode_encoders); 1034 drmModeFreeConnector(intel_output->mode_output); 1035 intel_output->mode_output = NULL; 1036 1037 list_del(&intel_output->link); 1038 backlight_close(&intel_output->backlight); 1039 free(intel_output); 1040 1041 output->driver_private = NULL; 1042} 1043 1044static void 1045intel_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode) 1046{ 1047 struct intel_output *intel_output = output->driver_private; 1048 1049 if (!intel_output->backlight.iface) 1050 return; 1051 1052 if (mode == DPMSModeOn) { 1053 /* If we're going from off->on we may need to turn on the backlight. */ 1054 if (oldmode != DPMSModeOn) 1055 intel_output_backlight_set(output, 1056 intel_output->backlight_active_level); 1057 } else { 1058 /* Only save the current backlight value if we're going from on to off. */ 1059 if (oldmode == DPMSModeOn) 1060 intel_output->backlight_active_level = intel_output_backlight_get(output); 1061 intel_output_backlight_set(output, 0); 1062 } 1063} 1064 1065static void 1066intel_output_dpms(xf86OutputPtr output, int dpms) 1067{ 1068 struct intel_output *intel_output = output->driver_private; 1069 drmModeConnectorPtr koutput = intel_output->mode_output; 1070 struct intel_mode *mode = intel_output->mode; 1071 int i; 1072 1073 if (!koutput) 1074 return; 1075 1076 for (i = 0; i < koutput->count_props; i++) { 1077 drmModePropertyPtr props; 1078 1079 props = drmModeGetProperty(mode->fd, koutput->props[i]); 1080 if (!props) 1081 continue; 1082 1083 if (!strcmp(props->name, "DPMS")) { 1084 /* Make sure to reverse the order between on and off. */ 1085 if (dpms != DPMSModeOn) 1086 intel_output_dpms_backlight(output, 1087 intel_output->dpms_mode, 1088 dpms); 1089 1090 drmModeConnectorSetProperty(mode->fd, 1091 intel_output->output_id, 1092 props->prop_id, 1093 dpms); 1094 1095 if (dpms == DPMSModeOn) 1096 intel_output_dpms_backlight(output, 1097 intel_output->dpms_mode, 1098 dpms); 1099 intel_output->dpms_mode = dpms; 1100 drmModeFreeProperty(props); 1101 return; 1102 } 1103 1104 drmModeFreeProperty(props); 1105 } 1106} 1107 1108int 1109intel_output_dpms_status(xf86OutputPtr output) 1110{ 1111 struct intel_output *intel_output = output->driver_private; 1112 return intel_output->dpms_mode; 1113} 1114 1115static Bool 1116intel_property_ignore(drmModePropertyPtr prop) 1117{ 1118 if (!prop) 1119 return TRUE; 1120 1121 /* ignore blob prop */ 1122 if (prop->flags & DRM_MODE_PROP_BLOB) 1123 return TRUE; 1124 1125 /* ignore standard property */ 1126 if (!strcmp(prop->name, "EDID") || 1127 !strcmp(prop->name, "DPMS")) 1128 return TRUE; 1129 1130 return FALSE; 1131} 1132 1133static void 1134intel_output_create_ranged_atom(xf86OutputPtr output, Atom *atom, 1135 const char *name, INT32 min, INT32 max, 1136 uint64_t value, Bool immutable) 1137{ 1138 int err; 1139 INT32 atom_range[2]; 1140 1141 atom_range[0] = min; 1142 atom_range[1] = max; 1143 1144 *atom = MakeAtom(name, strlen(name), TRUE); 1145 1146 err = RRConfigureOutputProperty(output->randr_output, *atom, FALSE, 1147 TRUE, immutable, 2, atom_range); 1148 if (err != 0) 1149 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1150 "RRConfigureOutputProperty error, %d\n", err); 1151 1152 err = RRChangeOutputProperty(output->randr_output, *atom, XA_INTEGER, 1153 32, PropModeReplace, 1, &value, FALSE, 1154 FALSE); 1155 if (err != 0) 1156 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1157 "RRChangeOutputProperty error, %d\n", err); 1158} 1159 1160#define BACKLIGHT_NAME "Backlight" 1161#define BACKLIGHT_DEPRECATED_NAME "BACKLIGHT" 1162static Atom backlight_atom, backlight_deprecated_atom; 1163 1164static void 1165intel_output_create_resources(xf86OutputPtr output) 1166{ 1167 struct intel_output *intel_output = output->driver_private; 1168 drmModeConnectorPtr mode_output = intel_output->mode_output; 1169 struct intel_mode *mode = intel_output->mode; 1170 int i, j, err; 1171 1172 intel_output->props = calloc(mode_output->count_props, 1173 sizeof(struct intel_property)); 1174 if (!intel_output->props) 1175 return; 1176 1177 intel_output->num_props = 0; 1178 for (i = j = 0; i < mode_output->count_props; i++) { 1179 drmModePropertyPtr drmmode_prop; 1180 1181 drmmode_prop = drmModeGetProperty(mode->fd, 1182 mode_output->props[i]); 1183 if (intel_property_ignore(drmmode_prop)) { 1184 drmModeFreeProperty(drmmode_prop); 1185 continue; 1186 } 1187 1188 intel_output->props[j].mode_prop = drmmode_prop; 1189 intel_output->props[j].value = mode_output->prop_values[i]; 1190 j++; 1191 } 1192 intel_output->num_props = j; 1193 1194 for (i = 0; i < intel_output->num_props; i++) { 1195 struct intel_property *p = &intel_output->props[i]; 1196 drmModePropertyPtr drmmode_prop = p->mode_prop; 1197 1198 if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) { 1199 p->num_atoms = 1; 1200 p->atoms = calloc(p->num_atoms, sizeof(Atom)); 1201 if (!p->atoms) 1202 continue; 1203 1204 intel_output_create_ranged_atom(output, &p->atoms[0], 1205 drmmode_prop->name, 1206 drmmode_prop->values[0], 1207 drmmode_prop->values[1], 1208 p->value, 1209 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE); 1210 1211 } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) { 1212 p->num_atoms = drmmode_prop->count_enums + 1; 1213 p->atoms = calloc(p->num_atoms, sizeof(Atom)); 1214 if (!p->atoms) 1215 continue; 1216 1217 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); 1218 for (j = 1; j <= drmmode_prop->count_enums; j++) { 1219 struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1]; 1220 p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE); 1221 } 1222 1223 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], 1224 FALSE, FALSE, 1225 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, 1226 p->num_atoms - 1, (INT32 *)&p->atoms[1]); 1227 if (err != 0) { 1228 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1229 "RRConfigureOutputProperty error, %d\n", err); 1230 } 1231 1232 for (j = 0; j < drmmode_prop->count_enums; j++) 1233 if (drmmode_prop->enums[j].value == p->value) 1234 break; 1235 /* there's always a matching value */ 1236 err = RRChangeOutputProperty(output->randr_output, p->atoms[0], 1237 XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, FALSE); 1238 if (err != 0) { 1239 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1240 "RRChangeOutputProperty error, %d\n", err); 1241 } 1242 } 1243 } 1244 1245 if (intel_output->backlight.iface) { 1246 /* Set up the backlight property, which takes effect 1247 * immediately and accepts values only within the 1248 * backlight_range. 1249 */ 1250 intel_output_create_ranged_atom(output, &backlight_atom, 1251 BACKLIGHT_NAME, 0, 1252 intel_output->backlight.max, 1253 intel_output->backlight_active_level, 1254 FALSE); 1255 intel_output_create_ranged_atom(output, 1256 &backlight_deprecated_atom, 1257 BACKLIGHT_DEPRECATED_NAME, 0, 1258 intel_output->backlight.max, 1259 intel_output->backlight_active_level, 1260 FALSE); 1261 } 1262} 1263 1264static Bool 1265intel_output_set_property(xf86OutputPtr output, Atom property, 1266 RRPropertyValuePtr value) 1267{ 1268 struct intel_output *intel_output = output->driver_private; 1269 struct intel_mode *mode = intel_output->mode; 1270 int i; 1271 1272 if (property == backlight_atom || property == backlight_deprecated_atom) { 1273 INT32 val; 1274 1275 if (value->type != XA_INTEGER || value->format != 32 || 1276 value->size != 1) 1277 { 1278 return FALSE; 1279 } 1280 1281 val = *(INT32 *)value->data; 1282 if (val < 0 || val > intel_output->backlight.max) 1283 return FALSE; 1284 1285 if (intel_output->dpms_mode == DPMSModeOn) 1286 intel_output_backlight_set(output, val); 1287 intel_output->backlight_active_level = val; 1288 return TRUE; 1289 } 1290 1291 for (i = 0; i < intel_output->num_props; i++) { 1292 struct intel_property *p = &intel_output->props[i]; 1293 1294 if (p->atoms[0] != property) 1295 continue; 1296 1297 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { 1298 uint32_t val; 1299 1300 if (value->type != XA_INTEGER || value->format != 32 || 1301 value->size != 1) 1302 return FALSE; 1303 val = *(uint32_t *)value->data; 1304 1305 drmModeConnectorSetProperty(mode->fd, intel_output->output_id, 1306 p->mode_prop->prop_id, (uint64_t)val); 1307 return TRUE; 1308 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { 1309 Atom atom; 1310 const char *name; 1311 int j; 1312 1313 if (value->type != XA_ATOM || value->format != 32 || value->size != 1) 1314 return FALSE; 1315 memcpy(&atom, value->data, 4); 1316 name = NameForAtom(atom); 1317 if (name == NULL) 1318 return FALSE; 1319 1320 /* search for matching name string, then set its value down */ 1321 for (j = 0; j < p->mode_prop->count_enums; j++) { 1322 if (!strcmp(p->mode_prop->enums[j].name, name)) { 1323 drmModeConnectorSetProperty(mode->fd, intel_output->output_id, 1324 p->mode_prop->prop_id, p->mode_prop->enums[j].value); 1325 return TRUE; 1326 } 1327 } 1328 return FALSE; 1329 } 1330 } 1331 1332 /* We didn't recognise this property, just report success in order 1333 * to allow the set to continue, otherwise we break setting of 1334 * common properties like EDID. 1335 */ 1336 return TRUE; 1337} 1338 1339static Bool 1340intel_output_get_property(xf86OutputPtr output, Atom property) 1341{ 1342 struct intel_output *intel_output = output->driver_private; 1343 int err; 1344 1345 if (property == backlight_atom || property == backlight_deprecated_atom) { 1346 INT32 val; 1347 1348 if (!intel_output->backlight.iface) 1349 return FALSE; 1350 1351 if (intel_output->dpms_mode == DPMSModeOn) { 1352 val = intel_output_backlight_get(output); 1353 if (val < 0) 1354 return FALSE; 1355 } else { 1356 val = intel_output->backlight_active_level; 1357 } 1358 1359 err = RRChangeOutputProperty(output->randr_output, property, 1360 XA_INTEGER, 32, PropModeReplace, 1, &val, 1361 FALSE, FALSE); 1362 if (err != 0) { 1363 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1364 "RRChangeOutputProperty error, %d\n", err); 1365 return FALSE; 1366 } 1367 1368 return TRUE; 1369 } 1370 1371 return FALSE; 1372} 1373 1374static const xf86OutputFuncsRec intel_output_funcs = { 1375 .create_resources = intel_output_create_resources, 1376#ifdef RANDR_12_INTERFACE 1377 .set_property = intel_output_set_property, 1378 .get_property = intel_output_get_property, 1379#endif 1380 .dpms = intel_output_dpms, 1381#if 0 1382 1383 .save = drmmode_crt_save, 1384 .restore = drmmode_crt_restore, 1385 .mode_fixup = drmmode_crt_mode_fixup, 1386 .prepare = intel_output_prepare, 1387 .mode_set = drmmode_crt_mode_set, 1388 .commit = intel_output_commit, 1389#endif 1390 .detect = intel_output_detect, 1391 .mode_valid = intel_output_mode_valid, 1392 1393 .get_modes = intel_output_get_modes, 1394 .destroy = intel_output_destroy 1395}; 1396 1397static const int subpixel_conv_table[7] = { 1398 0, 1399 SubPixelUnknown, 1400 SubPixelHorizontalRGB, 1401 SubPixelHorizontalBGR, 1402 SubPixelVerticalRGB, 1403 SubPixelVerticalBGR, 1404 SubPixelNone 1405}; 1406 1407static const char *output_names[] = { 1408 "None", 1409 "VGA", 1410 "DVI", 1411 "DVI", 1412 "DVI", 1413 "Composite", 1414 "TV", 1415 "LVDS", 1416 "CTV", 1417 "DIN", 1418 "DP", 1419 "HDMI", 1420 "HDMI", 1421 "TV", 1422 "eDP", 1423}; 1424 1425static xf86OutputPtr find_output(ScrnInfoPtr pScrn, int id) 1426{ 1427 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1428 int i; 1429 for (i = 0; i < xf86_config->num_output; i++) { 1430 xf86OutputPtr output = xf86_config->output[i]; 1431 struct intel_output *intel_output; 1432 1433 intel_output = output->driver_private; 1434 if (intel_output->output_id == id) 1435 return output; 1436 } 1437 return NULL; 1438} 1439 1440static int parse_path_blob(drmModePropertyBlobPtr path_blob, int *conn_base_id, char **path) 1441{ 1442 char *conn; 1443 char conn_id[5]; 1444 int id, len; 1445 char *blob_data; 1446 1447 if (!path_blob) 1448 return -1; 1449 1450 blob_data = path_blob->data; 1451 /* we only handle MST paths for now */ 1452 if (strncmp(blob_data, "mst:", 4)) 1453 return -1; 1454 1455 conn = strchr(blob_data + 4, '-'); 1456 if (!conn) 1457 return -1; 1458 len = conn - (blob_data + 4); 1459 if (len + 1 > 5) 1460 return -1; 1461 memcpy(conn_id, blob_data + 4, len); 1462 conn_id[len] = '\0'; 1463 id = strtoul(conn_id, NULL, 10); 1464 1465 *conn_base_id = id; 1466 1467 *path = conn + 1; 1468 return 0; 1469} 1470 1471static void 1472drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name, 1473 drmModePropertyBlobPtr path_blob) 1474{ 1475 xf86OutputPtr output; 1476 int conn_id; 1477 char *extra_path; 1478 1479 output = NULL; 1480 if (parse_path_blob(path_blob, &conn_id, &extra_path) == 0) 1481 output = find_output(pScrn, conn_id); 1482 if (output) { 1483 snprintf(name, 32, "%s-%s", output->name, extra_path); 1484 } else { 1485 const char *output_name; 1486 1487 if (koutput->connector_type < ARRAY_SIZE(output_names)) 1488 output_name = output_names[koutput->connector_type]; 1489 else 1490 output_name = "UNKNOWN"; 1491 1492 snprintf(name, 32, "%s%d", 1493 output_name, koutput->connector_type_id); 1494 } 1495} 1496 1497static void 1498intel_output_init(ScrnInfoPtr scrn, struct intel_mode *mode, drmModeResPtr mode_res, int num, int dynamic) 1499{ 1500 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1501 xf86OutputPtr output; 1502 drmModeConnectorPtr koutput; 1503 drmModeEncoderPtr *kencoders = NULL; 1504 struct intel_output *intel_output; 1505 char name[32]; 1506 drmModePropertyPtr props; 1507 drmModePropertyBlobPtr path_blob = NULL; 1508 int i; 1509 1510 koutput = drmModeGetConnector(mode->fd, 1511 mode_res->connectors[num]); 1512 if (!koutput) 1513 return; 1514 for (i = 0; i < koutput->count_props; i++) { 1515 props = drmModeGetProperty(mode->fd, koutput->props[i]); 1516 if (props && (props->flags & DRM_MODE_PROP_BLOB)) { 1517 if (!strcmp(props->name, "PATH")) { 1518 path_blob = drmModeGetPropertyBlob(mode->fd, koutput->prop_values[i]); 1519 1520 drmModeFreeProperty(props); 1521 break; 1522 } 1523 drmModeFreeProperty(props); 1524 } 1525 } 1526 1527 drmmode_create_name(scrn, koutput, name, path_blob); 1528 if (path_blob) 1529 drmModeFreePropertyBlob(path_blob); 1530 1531 if (path_blob && dynamic) { 1532 /* See if we have an output with this name already 1533 * and hook stuff up. 1534 */ 1535 for (i = 0; i < xf86_config->num_output; i++) { 1536 output = xf86_config->output[i]; 1537 1538 if (strncmp(output->name, name, 32)) 1539 continue; 1540 1541 intel_output = output->driver_private; 1542 intel_output->output_id = mode_res->connectors[num]; 1543 intel_output->mode_output = koutput; 1544 RROutputChanged(output->randr_output, TRUE); 1545 return; 1546 } 1547 } 1548 kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders); 1549 if (!kencoders) { 1550 goto out_free_encoders; 1551 } 1552 1553 for (i = 0; i < koutput->count_encoders; i++) { 1554 kencoders[i] = drmModeGetEncoder(mode->fd, koutput->encoders[i]); 1555 if (!kencoders[i]) 1556 goto out_free_encoders; 1557 } 1558 1559 output = xf86OutputCreate (scrn, &intel_output_funcs, name); 1560 if (!output) { 1561 goto out_free_encoders; 1562 } 1563 1564 intel_output = calloc(sizeof(struct intel_output), 1); 1565 if (!intel_output) { 1566 xf86OutputDestroy(output); 1567 goto out_free_encoders; 1568 } 1569 1570 intel_output->output_id = mode_res->connectors[num]; 1571 intel_output->mode_output = koutput; 1572 intel_output->mode_encoders = kencoders; 1573 intel_output->mode = mode; 1574 1575 output->mm_width = koutput->mmWidth; 1576 output->mm_height = koutput->mmHeight; 1577 1578 output->subpixel_order = subpixel_conv_table[koutput->subpixel]; 1579 output->driver_private = intel_output; 1580 1581 if (is_panel(koutput->connector_type)) 1582 intel_output_backlight_init(output); 1583 1584 output->possible_crtcs = 0x7f; 1585 for (i = 0; i < koutput->count_encoders; i++) { 1586 output->possible_crtcs &= kencoders[i]->possible_crtcs; 1587 } 1588 output->interlaceAllowed = TRUE; 1589 1590 intel_output->output = output; 1591 1592 if (dynamic) { 1593 output->randr_output = RROutputCreate(xf86ScrnToScreen(scrn), output->name, strlen(output->name), output); 1594 intel_output_create_resources(output); 1595 } 1596 1597 list_add(&intel_output->link, &mode->outputs); 1598 return; 1599 1600out_free_encoders: 1601 if (kencoders) { 1602 for (i = 0; i < koutput->count_encoders; i++) 1603 drmModeFreeEncoder(kencoders[i]); 1604 free(kencoders); 1605 } 1606 drmModeFreeConnector(koutput); 1607} 1608 1609static Bool 1610intel_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) 1611{ 1612 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1613 struct intel_crtc *intel_crtc = xf86_config->crtc[0]->driver_private; 1614 struct intel_mode *mode = intel_crtc->mode; 1615 intel_screen_private *intel = intel_get_screen_private(scrn); 1616 drm_intel_bo *old_front = NULL; 1617 Bool ret; 1618 uint32_t old_fb_id; 1619 int i, old_width, old_height, old_pitch; 1620 int pitch; 1621 uint32_t tiling; 1622 1623 if (scrn->virtualX == width && scrn->virtualY == height) 1624 return TRUE; 1625 1626 intel_flush(intel); 1627 1628 old_width = scrn->virtualX; 1629 old_height = scrn->virtualY; 1630 old_pitch = scrn->displayWidth; 1631 old_fb_id = mode->fb_id; 1632 old_front = intel->front_buffer; 1633 1634 if (intel->back_buffer) { 1635 drm_intel_bo_unreference(intel->back_buffer); 1636 intel->back_buffer = NULL; 1637 } 1638 1639 intel->front_buffer = intel_allocate_framebuffer(scrn, 1640 width, height, 1641 intel->cpp, 1642 &pitch, &tiling); 1643 if (!intel->front_buffer) 1644 goto fail; 1645 1646 ret = drmModeAddFB(mode->fd, width, height, scrn->depth, 1647 scrn->bitsPerPixel, pitch, 1648 intel->front_buffer->handle, 1649 &mode->fb_id); 1650 if (ret) 1651 goto fail; 1652 1653 intel->front_pitch = pitch; 1654 intel->front_tiling = tiling; 1655 1656 scrn->virtualX = width; 1657 scrn->virtualY = height; 1658 1659 if (!intel_uxa_create_screen_resources(scrn->pScreen)) 1660 goto fail; 1661 1662 for (i = 0; i < xf86_config->num_crtc; i++) { 1663 xf86CrtcPtr crtc = xf86_config->crtc[i]; 1664 1665 if (!crtc->enabled) 1666 continue; 1667 1668 if (!intel_crtc_apply(crtc)) 1669 goto fail; 1670 } 1671 1672 if (old_fb_id) 1673 drmModeRmFB(mode->fd, old_fb_id); 1674 if (old_front) 1675 drm_intel_bo_unreference(old_front); 1676 1677 return TRUE; 1678 1679fail: 1680 if (intel->front_buffer) 1681 drm_intel_bo_unreference(intel->front_buffer); 1682 intel->front_buffer = old_front; 1683 scrn->virtualX = old_width; 1684 scrn->virtualY = old_height; 1685 scrn->displayWidth = old_pitch; 1686 if (old_fb_id != mode->fb_id) 1687 drmModeRmFB(mode->fd, mode->fb_id); 1688 mode->fb_id = old_fb_id; 1689 1690 return FALSE; 1691} 1692 1693static void 1694intel_pageflip_handler(ScrnInfoPtr scrn, xf86CrtcPtr crtc, 1695 uint64_t frame, uint64_t usec, void *data); 1696 1697static void 1698intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data); 1699 1700static void 1701intel_pageflip_complete(struct intel_mode *mode); 1702 1703Bool 1704intel_do_pageflip(intel_screen_private *intel, 1705 dri_bo *new_front, 1706 int ref_crtc_hw_id, 1707 Bool async, 1708 void *pageflip_data, 1709 intel_pageflip_handler_proc pageflip_handler, 1710 intel_pageflip_abort_proc pageflip_abort) 1711{ 1712 ScrnInfoPtr scrn = intel->scrn; 1713 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 1714 struct intel_crtc *crtc = config->crtc[0]->driver_private; 1715 struct intel_mode *mode = crtc->mode; 1716 unsigned int pitch = scrn->displayWidth * intel->cpp; 1717 struct intel_pageflip *flip; 1718 uint32_t new_fb_id; 1719 uint32_t flags; 1720 uint32_t seq; 1721 int err = 0; 1722 int i; 1723 1724 /* 1725 * We only have a single length queue in the kernel, so any 1726 * attempts to schedule a second flip before processing the first 1727 * is a bug. Punt it back to the caller. 1728 */ 1729 if (mode->flip_count) 1730 return FALSE; 1731 1732 /* 1733 * Create a new handle for the back buffer 1734 */ 1735 if (drmModeAddFB(mode->fd, scrn->virtualX, scrn->virtualY, 1736 scrn->depth, scrn->bitsPerPixel, pitch, 1737 new_front->handle, &new_fb_id)) { 1738 err = errno; 1739 goto error_out; 1740 } 1741 1742 drm_intel_bo_disable_reuse(new_front); 1743 intel_flush(intel); 1744 1745 /* 1746 * Queue flips on all enabled CRTCs 1747 * Note that if/when we get per-CRTC buffers, we'll have to update this. 1748 * Right now it assumes a single shared fb across all CRTCs, with the 1749 * kernel fixing up the offset of each CRTC as necessary. 1750 * 1751 * Also, flips queued on disabled or incorrectly configured displays 1752 * may never complete; this is a configuration error. 1753 */ 1754 mode->fe_msc = 0; 1755 mode->fe_usec = 0; 1756 memset(&mode->pageflip, 0, sizeof(mode->pageflip)); 1757 1758 flags = DRM_MODE_PAGE_FLIP_EVENT; 1759 if (async) 1760 flags |= DRM_MODE_PAGE_FLIP_ASYNC; 1761 for (i = 0; i < config->num_crtc; i++) { 1762 if (!intel_crtc_on(config->crtc[i])) 1763 continue; 1764 1765 crtc = config->crtc[i]->driver_private; 1766 1767 flip = calloc(1, sizeof(struct intel_pageflip)); 1768 if (flip == NULL) { 1769 err = errno; 1770 goto error_undo; 1771 } 1772 1773 /* Only the reference crtc will finally deliver its page flip 1774 * completion event. All other crtc's events will be discarded. 1775 */ 1776 flip->dispatch_me = (intel_crtc_to_pipe(crtc->crtc) == ref_crtc_hw_id); 1777 flip->mode = mode; 1778 1779 seq = intel_drm_queue_alloc(scrn, config->crtc[i], flip, intel_pageflip_handler, intel_pageflip_abort); 1780 if (!seq) { 1781 err = errno; 1782 free(flip); 1783 goto error_undo; 1784 } 1785 1786 mode->flip_count++; 1787 1788 if (drmModePageFlip(mode->fd, 1789 crtc_id(crtc), 1790 new_fb_id, 1791 flags, (void *)(uintptr_t)seq)) { 1792 err = errno; 1793 intel_drm_abort_seq(scrn, seq); 1794 goto error_undo; 1795 } 1796 } 1797 1798 mode->old_fb_id = mode->fb_id; 1799 mode->fb_id = new_fb_id; 1800 1801 mode->pageflip.data = pageflip_data; 1802 mode->pageflip.handler = pageflip_handler; 1803 mode->pageflip.abort = pageflip_abort; 1804 1805 if (!mode->flip_count) 1806 intel_pageflip_complete(mode); 1807 1808 return TRUE; 1809 1810error_undo: 1811 drmModeRmFB(mode->fd, new_fb_id); 1812 for (i = 0; i < config->num_crtc; i++) { 1813 if (config->crtc[i]->enabled) 1814 intel_crtc_apply(config->crtc[i]); 1815 } 1816 1817error_out: 1818 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", 1819 strerror(err)); 1820 1821 mode->flip_count = 0; 1822 return FALSE; 1823} 1824 1825static const xf86CrtcConfigFuncsRec intel_xf86crtc_config_funcs = { 1826 intel_xf86crtc_resize 1827}; 1828 1829/* 1830 * Enqueue a potential drm response; when the associated response 1831 * appears, we've got data to pass to the handler from here 1832 */ 1833uint32_t 1834intel_drm_queue_alloc(ScrnInfoPtr scrn, 1835 xf86CrtcPtr crtc, 1836 void *data, 1837 intel_drm_handler_proc handler, 1838 intel_drm_abort_proc abort) 1839{ 1840 struct intel_drm_queue *q; 1841 1842 q = calloc(1, sizeof(struct intel_drm_queue)); 1843 if (!q) 1844 return 0; 1845 1846 if (!intel_drm_seq) 1847 ++intel_drm_seq; 1848 q->seq = intel_drm_seq++; 1849 q->scrn = scrn; 1850 q->crtc = crtc; 1851 q->data = data; 1852 q->handler = handler; 1853 q->abort = abort; 1854 1855 list_add(&q->list, &intel_drm_queue); 1856 1857 return q->seq; 1858} 1859 1860/* 1861 * Abort one queued DRM entry, removing it 1862 * from the list, calling the abort function and 1863 * freeing the memory 1864 */ 1865static void 1866intel_drm_abort_one(struct intel_drm_queue *q) 1867{ 1868 list_del(&q->list); 1869 q->abort(q->scrn, q->crtc, q->data); 1870 free(q); 1871} 1872 1873/* 1874 * Externally usable abort function that uses a callback to match a single queued 1875 * entry to abort 1876 */ 1877void 1878intel_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data), void *match_data) 1879{ 1880 struct intel_drm_queue *q; 1881 1882 list_for_each_entry(q, &intel_drm_queue, list) { 1883 if (match(q->data, match_data)) { 1884 intel_drm_abort_one(q); 1885 break; 1886 } 1887 } 1888} 1889 1890/* 1891 * Abort by drm queue sequence number 1892 */ 1893void 1894intel_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq) 1895{ 1896 struct intel_drm_queue *q; 1897 1898 list_for_each_entry(q, &intel_drm_queue, list) { 1899 if (q->seq == seq) { 1900 intel_drm_abort_one(q); 1901 break; 1902 } 1903 } 1904} 1905 1906/* 1907 * Abort all queued entries on a specific scrn, used 1908 * when resetting the X server 1909 */ 1910static void 1911intel_drm_abort_scrn(ScrnInfoPtr scrn) 1912{ 1913 struct intel_drm_queue *q, *tmp; 1914 1915 list_for_each_entry_safe(q, tmp, &intel_drm_queue, list) { 1916 if (q->scrn == scrn) 1917 intel_drm_abort_one(q); 1918 } 1919} 1920 1921static uint32_t pipe_select(int pipe) 1922{ 1923 if (pipe > 1) 1924 return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT; 1925 else if (pipe > 0) 1926 return DRM_VBLANK_SECONDARY; 1927 else 1928 return 0; 1929} 1930 1931/* 1932 * Get the current msc/ust value from the kernel 1933 */ 1934static int 1935intel_get_msc_ust(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint32_t *msc, uint64_t *ust) 1936{ 1937 intel_screen_private *intel = intel_get_screen_private(scrn); 1938 drmVBlank vbl; 1939 1940 /* Get current count */ 1941 vbl.request.type = DRM_VBLANK_RELATIVE | pipe_select(intel_crtc_to_pipe(crtc)); 1942 vbl.request.sequence = 0; 1943 vbl.request.signal = 0; 1944 if (drmWaitVBlank(intel->drmSubFD, &vbl)) { 1945 *msc = 0; 1946 *ust = 0; 1947 return BadMatch; 1948 } else { 1949 *msc = vbl.reply.sequence; 1950 *ust = (CARD64) vbl.reply.tval_sec * 1000000 + vbl.reply.tval_usec; 1951 return Success; 1952 } 1953} 1954 1955/* 1956 * Convert a 32-bit kernel MSC sequence number to a 64-bit local sequence 1957 * number, adding in the vblank_offset and high 32 bits, and dealing 1958 * with 64-bit wrapping 1959 */ 1960uint64_t 1961intel_sequence_to_crtc_msc(xf86CrtcPtr crtc, uint32_t sequence) 1962{ 1963 struct intel_crtc *intel_crtc = crtc->driver_private; 1964 1965 if ((int32_t) (sequence - intel_crtc->msc_prev) < -0x40000000) 1966 intel_crtc->msc_high += 0x100000000L; 1967 intel_crtc->msc_prev = sequence; 1968 return intel_crtc->msc_high + sequence; 1969} 1970 1971/* 1972 * Get the current 64-bit adjust MSC and UST value 1973 */ 1974int 1975intel_get_crtc_msc_ust(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t *msc, uint64_t *ust) 1976{ 1977 uint32_t sequence; 1978 int ret; 1979 1980 ret = intel_get_msc_ust(scrn, crtc, &sequence, ust); 1981 if (ret) 1982 return ret; 1983 1984 *msc = intel_sequence_to_crtc_msc(crtc, sequence); 1985 return 0; 1986} 1987 1988uint32_t 1989intel_crtc_msc_to_sequence(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t expect) 1990{ 1991 return (uint32_t)expect; 1992} 1993 1994/* 1995 * General DRM kernel handler. Looks for the matching sequence number in the 1996 * drm event queue and calls the handler for it. 1997 */ 1998static void 1999intel_drm_handler(int fd, uint32_t frame, uint32_t sec, uint32_t usec, void *user_ptr) 2000{ 2001 uint32_t user_data = (intptr_t)user_ptr; 2002 struct intel_drm_queue *q; 2003 2004 list_for_each_entry(q, &intel_drm_queue, list) { 2005 if (q->seq == user_data) { 2006 list_del(&q->list); 2007 q->handler(q->scrn, q->crtc, 2008 intel_sequence_to_crtc_msc(q->crtc, frame), 2009 (uint64_t)sec * 1000000 + usec, q->data); 2010 free(q); 2011 break; 2012 } 2013 } 2014} 2015 2016 2017/* 2018 * Notify the page flip caller that the flip is 2019 * complete 2020 */ 2021static void 2022intel_pageflip_complete(struct intel_mode *mode) 2023{ 2024 if (!mode->pageflip.handler) 2025 return; 2026 2027 /* Release framebuffer */ 2028 drmModeRmFB(mode->fd, mode->old_fb_id); 2029 mode->pageflip.handler(mode->fe_msc, mode->fe_usec, 2030 mode->pageflip.data); 2031} 2032 2033/* 2034 * One pageflip event has completed. Update the saved msc/ust values 2035 * as needed, then check to see if the whole set of events are 2036 * complete and notify the application at that point 2037 */ 2038static struct intel_mode * 2039intel_handle_pageflip(struct intel_pageflip *flip, uint64_t msc, uint64_t usec) 2040{ 2041 struct intel_mode *mode = flip->mode; 2042 2043 if (flip->dispatch_me) { 2044 /* Yes: Cache msc, ust for later delivery. */ 2045 mode->fe_msc = msc; 2046 mode->fe_usec = usec; 2047 } 2048 free(flip); 2049 2050 /* Last crtc completed flip? */ 2051 mode->flip_count--; 2052 if (mode->flip_count > 0) 2053 return NULL; 2054 2055 return mode; 2056} 2057 2058/* 2059 * Called from the DRM event queue when a single flip has completed 2060 */ 2061static void 2062intel_pageflip_handler(ScrnInfoPtr scrn, xf86CrtcPtr crtc, 2063 uint64_t msc, uint64_t usec, void *data) 2064{ 2065 struct intel_pageflip *flip = data; 2066 struct intel_mode *mode = intel_handle_pageflip(flip, msc, usec); 2067 2068 if (!mode) 2069 return; 2070 2071 intel_pageflip_complete(mode); 2072} 2073 2074/* 2075 * Called from the DRM queue abort code when a flip has been aborted 2076 */ 2077static void 2078intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data) 2079{ 2080 struct intel_pageflip *flip = data; 2081 struct intel_mode *mode = intel_handle_pageflip(flip, 0, 0); 2082 2083 if (!mode) 2084 return; 2085 2086 if (!mode->pageflip.abort) 2087 return; 2088 2089 /* Release framebuffer */ 2090 drmModeRmFB(mode->fd, mode->old_fb_id); 2091 mode->pageflip.abort(mode->pageflip.data); 2092} 2093 2094/* 2095 * Check for pending DRM events and process them. 2096 */ 2097#if !HAVE_NOTIFY_FD 2098static void 2099drm_wakeup_handler(pointer data, int err, pointer p) 2100{ 2101 struct intel_mode *mode; 2102 fd_set *read_mask; 2103 2104 if (data == NULL || err < 0) 2105 return; 2106 2107 mode = data; 2108 read_mask = p; 2109 if (FD_ISSET(mode->fd, read_mask)) 2110 drmHandleEvent(mode->fd, &mode->event_context); 2111} 2112#else 2113static void 2114drm_notify_fd(int fd, int ready, void *data) 2115{ 2116 struct intel_mode *mode = data; 2117 drmHandleEvent(mode->fd, &mode->event_context); 2118} 2119#endif 2120 2121/* 2122 * If there are any available, read drm_events 2123 */ 2124int 2125intel_mode_read_drm_events(struct intel_screen_private *intel) 2126{ 2127 struct intel_mode *mode = intel->modes; 2128 struct pollfd p = { .fd = mode->fd, .events = POLLIN }; 2129 int r; 2130 2131 do { 2132 r = poll(&p, 1, 0); 2133 } while (r == -1 && (errno == EINTR || errno == EAGAIN)); 2134 2135 if (r <= 0) 2136 return 0; 2137 2138 return drmHandleEvent(mode->fd, &mode->event_context); 2139} 2140 2141/* 2142 * Libdrm's possible_clones is a mask of encoders, Xorg's possible_clones is a 2143 * mask of outputs. This function sets Xorg's possible_clones based on the 2144 * values read from libdrm. 2145 */ 2146static uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output) 2147{ 2148 struct intel_output *intel_output = output->driver_private, *clone_drmout; 2149 int i; 2150 xf86OutputPtr clone_output; 2151 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 2152 int index_mask = 0; 2153 2154 if (intel_output->enc_clone_mask == 0) 2155 return index_mask; 2156 2157 for (i = 0; i < xf86_config->num_output; i++) { 2158 clone_output = xf86_config->output[i]; 2159 clone_drmout = clone_output->driver_private; 2160 if (output == clone_output) 2161 continue; 2162 2163 if (clone_drmout->enc_mask == 0) 2164 continue; 2165 if (intel_output->enc_clone_mask == clone_drmout->enc_mask) 2166 index_mask |= (1 << i); 2167 } 2168 return index_mask; 2169} 2170static void 2171intel_compute_possible_clones(ScrnInfoPtr scrn, struct intel_mode *mode, drmModeResPtr mode_res) 2172{ 2173 int i, j; 2174 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 2175 2176 for (i = 0; i < xf86_config->num_output; i++) { 2177 xf86OutputPtr output = xf86_config->output[i]; 2178 struct intel_output *intel_output; 2179 2180 intel_output = output->driver_private; 2181 intel_output->enc_clone_mask = 0xff; 2182 /* and all the possible encoder clones for this output together */ 2183 for (j = 0; j < intel_output->mode_output->count_encoders; j++) 2184 { 2185 int k; 2186 for (k = 0; k < mode_res->count_encoders; k++) { 2187 if (mode_res->encoders[k] == intel_output->mode_encoders[j]->encoder_id) 2188 intel_output->enc_mask |= (1 << k); 2189 } 2190 2191 intel_output->enc_clone_mask &= intel_output->mode_encoders[j]->possible_clones; 2192 } 2193 } 2194 2195 for (i = 0; i < xf86_config->num_output; i++) { 2196 xf86OutputPtr output = xf86_config->output[i]; 2197 output->possible_clones = find_clones(scrn, output); 2198 } 2199} 2200 2201Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp) 2202{ 2203 intel_screen_private *intel = intel_get_screen_private(scrn); 2204 struct drm_i915_getparam gp; 2205 struct intel_mode *mode; 2206 unsigned int i; 2207 int has_flipping; 2208 drmModeResPtr mode_res; 2209 2210 mode = calloc(1, sizeof *mode); 2211 if (!mode) 2212 return FALSE; 2213 2214 mode->fd = fd; 2215 2216 list_init(&mode->crtcs); 2217 list_init(&mode->outputs); 2218 2219 xf86CrtcConfigInit(scrn, &intel_xf86crtc_config_funcs); 2220 2221 mode->cpp = cpp; 2222 mode_res = drmModeGetResources(mode->fd); 2223 if (!mode_res) { 2224 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 2225 "failed to get resources: %s\n", strerror(errno)); 2226 free(mode); 2227 return FALSE; 2228 } 2229 2230 xf86CrtcSetSizeRange(scrn, 320, 200, mode_res->max_width, 2231 mode_res->max_height); 2232 for (i = 0; i < mode_res->count_crtcs; i++) 2233 intel_crtc_init(scrn, mode, mode_res, i); 2234 2235 for (i = 0; i < mode_res->count_connectors; i++) 2236 intel_output_init(scrn, mode, mode_res, i, 0); 2237 2238 intel_compute_possible_clones(scrn, mode, mode_res); 2239 2240#ifdef INTEL_PIXMAP_SHARING 2241 xf86ProviderSetup(scrn, NULL, "Intel"); 2242#endif 2243 2244 xf86InitialConfiguration(scrn, TRUE); 2245 2246 mode->event_context.version = DRM_EVENT_CONTEXT_VERSION; 2247 mode->event_context.vblank_handler = intel_drm_handler; 2248 mode->event_context.page_flip_handler = intel_drm_handler; 2249 2250 /* XXX assumes only one intel screen */ 2251 list_init(&intel_drm_queue); 2252 intel_drm_seq = 0; 2253 2254 has_flipping = 0; 2255 gp.param = I915_PARAM_HAS_PAGEFLIPPING; 2256 gp.value = &has_flipping; 2257 (void)drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM, &gp, 2258 sizeof(gp)); 2259 if (has_flipping && intel->swapbuffers_wait) { 2260 xf86DrvMsg(scrn->scrnIndex, X_INFO, 2261 "Kernel page flipping support detected, enabling\n"); 2262 intel->use_pageflipping = TRUE; 2263 } 2264 2265 intel->modes = mode; 2266 drmModeFreeResources(mode_res); 2267 return TRUE; 2268} 2269 2270void 2271intel_mode_init(struct intel_screen_private *intel) 2272{ 2273 struct intel_mode *mode = intel->modes; 2274 2275 /* We need to re-register the mode->fd for the synchronisation 2276 * feedback on every server generation, so perform the 2277 * registration within ScreenInit and not PreInit. 2278 */ 2279 mode->flip_count = 0; 2280 SetNotifyFd(mode->fd, drm_notify_fd, X_NOTIFY_READ, mode); 2281#if !HAVE_NOTIFY_FD 2282 RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, 2283 drm_wakeup_handler, mode); 2284#endif 2285} 2286 2287void 2288intel_mode_remove_fb(intel_screen_private *intel) 2289{ 2290 struct intel_mode *mode = intel->modes; 2291 2292 if (mode->fb_id) { 2293 drmModeRmFB(mode->fd, mode->fb_id); 2294 mode->fb_id = 0; 2295 } 2296} 2297 2298void 2299intel_mode_close(intel_screen_private *intel) 2300{ 2301 struct intel_mode *mode = intel->modes; 2302 2303 if (mode == NULL) 2304 return; 2305 2306 intel_drm_abort_scrn(intel->scrn); 2307 2308#if !HAVE_NOTIFY_FD 2309 RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, 2310 drm_wakeup_handler, mode); 2311#endif 2312 RemoveNotifyFd(mode->fd); 2313} 2314 2315void 2316intel_mode_fini(intel_screen_private *intel) 2317{ 2318 struct intel_mode *mode = intel->modes; 2319 2320 if (mode == NULL) 2321 return; 2322 2323 while(!list_is_empty(&mode->crtcs)) { 2324 xf86CrtcDestroy(list_first_entry(&mode->crtcs, 2325 struct intel_crtc, 2326 link)->crtc); 2327 } 2328 2329 while(!list_is_empty(&mode->outputs)) { 2330 xf86OutputDestroy(list_first_entry(&mode->outputs, 2331 struct intel_output, 2332 link)->output); 2333 } 2334 2335 if (mode->fb_id) 2336 drmModeRmFB(mode->fd, mode->fb_id); 2337 2338 /* mode->rotate_fb_id should have been destroyed already */ 2339 2340 free(mode); 2341 intel->modes = NULL; 2342} 2343 2344/* for the mode overlay */ 2345int 2346intel_crtc_id(xf86CrtcPtr crtc) 2347{ 2348 return crtc_id(crtc->driver_private); 2349} 2350 2351int intel_crtc_to_pipe(xf86CrtcPtr crtc) 2352{ 2353 struct intel_crtc *intel_crtc = crtc->driver_private; 2354 return intel_crtc->pipe; 2355} 2356 2357Bool intel_crtc_on(xf86CrtcPtr crtc) 2358{ 2359 struct intel_crtc *intel_crtc = crtc->driver_private; 2360 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 2361 drmModeCrtcPtr drm_crtc; 2362 Bool ret; 2363 int i; 2364 2365 if (!crtc->enabled) 2366 return FALSE; 2367 2368 /* Kernel manages CRTC status based on output config */ 2369 ret = FALSE; 2370 for (i = 0; i < xf86_config->num_output; i++) { 2371 xf86OutputPtr output = xf86_config->output[i]; 2372 if (output->crtc == crtc && 2373 intel_output_dpms_status(output) == DPMSModeOn) { 2374 ret = TRUE; 2375 break; 2376 } 2377 } 2378 if (!ret) 2379 return FALSE; 2380 2381 /* And finally check with the kernel that the fb is bound */ 2382 drm_crtc = drmModeGetCrtc(intel_crtc->mode->fd, crtc_id(intel_crtc)); 2383 if (drm_crtc == NULL) 2384 return FALSE; 2385 2386 ret = (drm_crtc->mode_valid && 2387 (intel_crtc->mode->fb_id == drm_crtc->buffer_id || 2388 intel_crtc->mode->old_fb_id == drm_crtc->buffer_id)); 2389 free(drm_crtc); 2390 2391 return ret; 2392} 2393 2394 2395static PixmapPtr 2396intel_create_pixmap_for_bo(ScreenPtr pScreen, dri_bo *bo, 2397 int width, int height, 2398 int depth, int bpp, 2399 int pitch) 2400{ 2401 PixmapPtr pixmap; 2402 2403 pixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, 0); 2404 if (pixmap == NullPixmap) 2405 return pixmap; 2406 2407 if (!pScreen->ModifyPixmapHeader(pixmap, 2408 width, height, 2409 depth, bpp, 2410 pitch, NULL)) { 2411 pScreen->DestroyPixmap(pixmap); 2412 return NullPixmap; 2413 } 2414 2415 intel_set_pixmap_bo(pixmap, bo); 2416 return pixmap; 2417} 2418 2419static PixmapPtr 2420intel_create_pixmap_for_fbcon(ScrnInfoPtr scrn, int fbcon_id) 2421{ 2422 ScreenPtr pScreen = xf86ScrnToScreen(scrn); 2423 intel_screen_private *intel = intel_get_screen_private(scrn); 2424 struct intel_mode *mode = intel->modes; 2425 int fd = mode->fd; 2426 drmModeFBPtr fbcon; 2427 struct drm_gem_flink flink; 2428 drm_intel_bo *bo; 2429 PixmapPtr pixmap = NullPixmap; 2430 2431 fbcon = drmModeGetFB(fd, fbcon_id); 2432 if (fbcon == NULL) 2433 return NULL; 2434 2435 if (fbcon->depth != scrn->depth || 2436 fbcon->width != scrn->virtualX || 2437 fbcon->height != scrn->virtualY) 2438 goto out_free_fb; 2439 2440 flink.handle = fbcon->handle; 2441 if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { 2442 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 2443 "Couldn't flink fbcon handle\n"); 2444 goto out_free_fb; 2445 } 2446 2447 bo = drm_intel_bo_gem_create_from_name(intel->bufmgr, 2448 "fbcon", flink.name); 2449 if (bo == NULL) { 2450 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 2451 "Couldn't allocate bo for fbcon handle\n"); 2452 goto out_free_fb; 2453 } 2454 2455 pixmap = intel_create_pixmap_for_bo(pScreen, bo, 2456 fbcon->width, fbcon->height, 2457 fbcon->depth, fbcon->bpp, 2458 fbcon->pitch); 2459 if (pixmap == NullPixmap) 2460 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 2461 "Couldn't allocate pixmap fbcon contents\n"); 2462 drm_intel_bo_unreference(bo); 2463out_free_fb: 2464 drmModeFreeFB(fbcon); 2465 2466 return pixmap; 2467} 2468 2469void intel_copy_fb(ScrnInfoPtr scrn) 2470{ 2471 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 2472 ScreenPtr pScreen = xf86ScrnToScreen(scrn); 2473 intel_screen_private *intel = intel_get_screen_private(scrn); 2474 PixmapPtr src, dst; 2475 unsigned int pitch = scrn->displayWidth * intel->cpp; 2476 struct intel_crtc *intel_crtc; 2477 int i, fbcon_id; 2478 2479 if (intel->force_fallback) 2480 return; 2481 2482 fbcon_id = 0; 2483 for (i = 0; i < xf86_config->num_crtc; i++) { 2484 intel_crtc = xf86_config->crtc[i]->driver_private; 2485 if (intel_crtc->mode_crtc->buffer_id) 2486 fbcon_id = intel_crtc->mode_crtc->buffer_id; 2487 } 2488 if (!fbcon_id) 2489 return; 2490 2491 src = intel_create_pixmap_for_fbcon(scrn, fbcon_id); 2492 if (src == NULL) 2493 return; 2494 2495 /* We dont have a screen Pixmap yet */ 2496 dst = intel_create_pixmap_for_bo(pScreen, intel->front_buffer, 2497 scrn->virtualX, scrn->virtualY, 2498 scrn->depth, scrn->bitsPerPixel, 2499 pitch); 2500 if (dst == NullPixmap) 2501 goto cleanup_src; 2502 2503 if (!intel->uxa_driver->prepare_copy(src, dst, 2504 -1, -1, 2505 GXcopy, FB_ALLONES)) 2506 goto cleanup_dst; 2507 2508 intel->uxa_driver->copy(dst, 2509 0, 0, 2510 0, 0, 2511 scrn->virtualX, scrn->virtualY); 2512 intel->uxa_driver->done_copy(dst); 2513#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(10, 0) 2514 pScreen->canDoBGNoneRoot = TRUE; 2515#endif 2516 2517cleanup_dst: 2518 (*pScreen->DestroyPixmap)(dst); 2519cleanup_src: 2520 (*pScreen->DestroyPixmap)(src); 2521} 2522 2523void 2524intel_mode_hotplug(struct intel_screen_private *intel) 2525{ 2526 ScrnInfoPtr scrn = intel->scrn; 2527 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 2528 drmModeResPtr mode_res; 2529 int i, j; 2530 Bool found; 2531 Bool changed = FALSE; 2532 2533 mode_res = drmModeGetResources(intel->drmSubFD); 2534 if (!mode_res) 2535 goto out; 2536 2537 for (i = 0; i < config->num_output; i++) { 2538 xf86OutputPtr output = config->output[i]; 2539 struct intel_output *intel_output; 2540 2541 intel_output = output->driver_private; 2542 found = FALSE; 2543 for (j = 0; j < mode_res->count_connectors; j++) { 2544 if (mode_res->connectors[j] == intel_output->output_id) { 2545 found = TRUE; 2546 break; 2547 } 2548 } 2549 if (found) 2550 continue; 2551 2552 drmModeFreeConnector(intel_output->mode_output); 2553 intel_output->mode_output = NULL; 2554 intel_output->output_id = -1; 2555 RROutputChanged(output->randr_output, TRUE); 2556 2557 changed = TRUE; 2558 } 2559 2560 /* find new output ids we don't have outputs for */ 2561 for (i = 0; i < mode_res->count_connectors; i++) { 2562 found = FALSE; 2563 2564 for (j = 0; j < config->num_output; j++) { 2565 xf86OutputPtr output = config->output[j]; 2566 struct intel_output *intel_output; 2567 2568 intel_output = output->driver_private; 2569 if (mode_res->connectors[i] == intel_output->output_id) { 2570 found = TRUE; 2571 break; 2572 } 2573 } 2574 if (found) 2575 continue; 2576 2577 changed = TRUE; 2578 intel_output_init(scrn, intel->modes, mode_res, i, 1); 2579 } 2580 2581 if (changed) 2582 RRTellChanged(xf86ScrnToScreen(scrn)); 2583 2584 drmModeFreeResources(mode_res); 2585out: 2586 RRGetInfo(xf86ScrnToScreen(scrn), TRUE); 2587} 2588 2589void intel_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) 2590{ 2591 dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; 2592 dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; 2593 if (dest->x1 >= dest->x2) { 2594 dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; 2595 return; 2596 } 2597 2598 dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; 2599 dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; 2600 if (dest->y1 >= dest->y2) 2601 dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; 2602} 2603 2604void intel_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) 2605{ 2606 if (crtc->enabled) { 2607 crtc_box->x1 = crtc->x; 2608 crtc_box->x2 = 2609 crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); 2610 crtc_box->y1 = crtc->y; 2611 crtc_box->y2 = 2612 crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); 2613 } else 2614 crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; 2615} 2616 2617static int intel_box_area(BoxPtr box) 2618{ 2619 return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1); 2620} 2621 2622/* 2623 * Return the crtc covering 'box'. If two crtcs cover a portion of 2624 * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc 2625 * with greater coverage 2626 */ 2627 2628xf86CrtcPtr 2629intel_covering_crtc(ScrnInfoPtr scrn, 2630 BoxPtr box, xf86CrtcPtr desired, BoxPtr crtc_box_ret) 2631{ 2632 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 2633 xf86CrtcPtr crtc, best_crtc; 2634 int coverage, best_coverage; 2635 int c; 2636 BoxRec crtc_box, cover_box; 2637 2638 best_crtc = NULL; 2639 best_coverage = 0; 2640 crtc_box_ret->x1 = 0; 2641 crtc_box_ret->x2 = 0; 2642 crtc_box_ret->y1 = 0; 2643 crtc_box_ret->y2 = 0; 2644 for (c = 0; c < xf86_config->num_crtc; c++) { 2645 crtc = xf86_config->crtc[c]; 2646 2647 /* If the CRTC is off, treat it as not covering */ 2648 if (!intel_crtc_on(crtc)) 2649 continue; 2650 2651 intel_crtc_box(crtc, &crtc_box); 2652 intel_box_intersect(&cover_box, &crtc_box, box); 2653 coverage = intel_box_area(&cover_box); 2654 if (coverage && crtc == desired) { 2655 *crtc_box_ret = crtc_box; 2656 return crtc; 2657 } 2658 if (coverage > best_coverage) { 2659 *crtc_box_ret = crtc_box; 2660 best_crtc = crtc; 2661 best_coverage = coverage; 2662 } 2663 } 2664 return best_crtc; 2665} 2666