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