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