drmmode_display.c revision 39413783
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 <errno.h> 33#include <sys/ioctl.h> 34#include <time.h> 35#include "cursorstr.h" 36#include "damagestr.h" 37#include "inputstr.h" 38#include "list.h" 39#include "micmap.h" 40#include "mipointrst.h" 41#include "xf86cmap.h" 42#include "xf86Priv.h" 43#include "radeon.h" 44#include "radeon_bo_helper.h" 45#include "radeon_glamor.h" 46#include "radeon_reg.h" 47 48#include <dri.h> 49 50#include "drmmode_display.h" 51 52/* DPMS */ 53#ifdef HAVE_XEXTPROTO_71 54#include <X11/extensions/dpmsconst.h> 55#else 56#define DPMS_SERVER 57#include <X11/extensions/dpms.h> 58#endif 59 60#define DEFAULT_NOMINAL_FRAME_RATE 60 61 62#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 22 63#define HAVE_NOTIFY_FD 1 64#endif 65 66static Bool 67drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height); 68 69static Bool 70RADEONZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name) 71{ 72 int i = 0; 73 char s1[20]; 74 75 do { 76 switch(*s) { 77 case ',': 78 s1[i] = '\0'; 79 i = 0; 80 if (strcmp(s1, output_name) == 0) 81 return TRUE; 82 break; 83 case ' ': 84 case '\t': 85 case '\n': 86 case '\r': 87 break; 88 default: 89 s1[i] = *s; 90 i++; 91 break; 92 } 93 } while(*s++); 94 95 s1[i] = '\0'; 96 if (strcmp(s1, output_name) == 0) 97 return TRUE; 98 99 return FALSE; 100} 101 102 103static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, 104 int width, int height, 105 int depth, int bpp, 106 int pitch, 107 struct radeon_buffer *bo) 108{ 109 RADEONInfoPtr info = RADEONPTR(pScrn); 110 ScreenPtr pScreen = pScrn->pScreen; 111 PixmapPtr pixmap; 112 113 pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 114 RADEON_CREATE_PIXMAP_SCANOUT); 115 if (!pixmap) 116 return NULL; 117 118 if (!(*pScreen->ModifyPixmapHeader)(pixmap, width, height, 119 depth, bpp, pitch, NULL)) { 120 goto fail; 121 } 122 123 if (!info->use_glamor) 124 exaMoveInPixmap(pixmap); 125 126 if (!radeon_set_pixmap_bo(pixmap, bo)) 127 goto fail; 128 129 if (info->surf_man && !info->use_glamor) { 130 struct radeon_surface *surface = radeon_get_pixmap_surface(pixmap); 131 132 if (!radeon_surface_initialize(info, surface, width, height, bpp / 8, 133 radeon_get_pixmap_tiling_flags(pixmap), 0)) 134 goto fail; 135 } 136 137 if (!info->use_glamor || 138 radeon_glamor_create_textured_pixmap(pixmap, bo)) 139 return pixmap; 140 141fail: 142 pScreen->DestroyPixmap(pixmap); 143 return NULL; 144} 145 146static void drmmode_destroy_bo_pixmap(PixmapPtr pixmap) 147{ 148 ScreenPtr pScreen = pixmap->drawable.pScreen; 149 150 (*pScreen->DestroyPixmap)(pixmap); 151} 152 153static void 154drmmode_ConvertFromKMode(ScrnInfoPtr scrn, 155 drmModeModeInfo *kmode, 156 DisplayModePtr mode) 157{ 158 memset(mode, 0, sizeof(DisplayModeRec)); 159 mode->status = MODE_OK; 160 161 mode->Clock = kmode->clock; 162 163 mode->HDisplay = kmode->hdisplay; 164 mode->HSyncStart = kmode->hsync_start; 165 mode->HSyncEnd = kmode->hsync_end; 166 mode->HTotal = kmode->htotal; 167 mode->HSkew = kmode->hskew; 168 169 mode->VDisplay = kmode->vdisplay; 170 mode->VSyncStart = kmode->vsync_start; 171 mode->VSyncEnd = kmode->vsync_end; 172 mode->VTotal = kmode->vtotal; 173 mode->VScan = kmode->vscan; 174 175 mode->Flags = kmode->flags; //& FLAG_BITS; 176 mode->name = strdup(kmode->name); 177 178 if (kmode->type & DRM_MODE_TYPE_DRIVER) 179 mode->type = M_T_DRIVER; 180 if (kmode->type & DRM_MODE_TYPE_PREFERRED) 181 mode->type |= M_T_PREFERRED; 182 xf86SetModeCrtc (mode, scrn->adjustFlags); 183} 184 185static void 186drmmode_ConvertToKMode(ScrnInfoPtr scrn, 187 drmModeModeInfo *kmode, 188 DisplayModePtr mode) 189{ 190 memset(kmode, 0, sizeof(*kmode)); 191 192 kmode->clock = mode->Clock; 193 kmode->hdisplay = mode->HDisplay; 194 kmode->hsync_start = mode->HSyncStart; 195 kmode->hsync_end = mode->HSyncEnd; 196 kmode->htotal = mode->HTotal; 197 kmode->hskew = mode->HSkew; 198 199 kmode->vdisplay = mode->VDisplay; 200 kmode->vsync_start = mode->VSyncStart; 201 kmode->vsync_end = mode->VSyncEnd; 202 kmode->vtotal = mode->VTotal; 203 kmode->vscan = mode->VScan; 204 205 kmode->flags = mode->Flags; //& FLAG_BITS; 206 if (mode->name) 207 strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN); 208 kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; 209 210} 211 212/* 213 * Utility helper for drmWaitVBlank 214 */ 215Bool 216drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type, 217 uint32_t target_seq, unsigned long signal, uint64_t *ust, 218 uint32_t *result_seq) 219{ 220 int crtc_id = drmmode_get_crtc_id(crtc); 221 ScrnInfoPtr scrn = crtc->scrn; 222 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 223 drmVBlank vbl; 224 225 if (crtc_id == 1) 226 type |= DRM_VBLANK_SECONDARY; 227 else if (crtc_id > 1) 228 type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) & 229 DRM_VBLANK_HIGH_CRTC_MASK; 230 231 vbl.request.type = type; 232 vbl.request.sequence = target_seq; 233 vbl.request.signal = signal; 234 235 if (drmWaitVBlank(pRADEONEnt->fd, &vbl) != 0) 236 return FALSE; 237 238 if (ust) 239 *ust = (uint64_t)vbl.reply.tval_sec * 1000000 + 240 vbl.reply.tval_usec; 241 if (result_seq) 242 *result_seq = vbl.reply.sequence; 243 244 return TRUE; 245} 246 247/* 248 * Retrieves present time in microseconds that is compatible 249 * with units used by vblank timestamps. Depending on the kernel 250 * version and DRM kernel module configuration, the vblank 251 * timestamp can either be in real time or monotonic time 252 */ 253int drmmode_get_current_ust(int drm_fd, CARD64 *ust) 254{ 255 uint64_t cap_value; 256 int ret; 257 struct timespec now; 258 259 ret = drmGetCap(drm_fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap_value); 260 if (ret || !cap_value) 261 /* old kernel or drm_timestamp_monotonic turned off */ 262 ret = clock_gettime(CLOCK_REALTIME, &now); 263 else 264 ret = clock_gettime(CLOCK_MONOTONIC, &now); 265 if (ret) 266 return ret; 267 *ust = ((CARD64)now.tv_sec * 1000000) + ((CARD64)now.tv_nsec / 1000); 268 return 0; 269} 270 271/* 272 * Get current frame count and frame count timestamp of the crtc. 273 */ 274int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc) 275{ 276 ScrnInfoPtr scrn = crtc->scrn; 277 uint32_t seq; 278 279 if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, ust, &seq)) { 280 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 281 "get vblank counter failed: %s\n", strerror(errno)); 282 return -1; 283 } 284 285 *msc = seq; 286 287 return Success; 288} 289 290static void 291drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode) 292{ 293 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 294 ScrnInfoPtr scrn = crtc->scrn; 295 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 296 CARD64 ust; 297 int ret; 298 299 if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) { 300 uint32_t seq; 301 302 radeon_drm_wait_pending_flip(crtc); 303 304 /* 305 * On->Off transition: record the last vblank time, 306 * sequence number and frame period. 307 */ 308 if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, &ust, 309 &seq)) 310 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 311 "%s cannot get last vblank counter\n", 312 __func__); 313 else { 314 CARD64 nominal_frame_rate, pix_in_frame; 315 316 drmmode_crtc->dpms_last_ust = ust; 317 drmmode_crtc->dpms_last_seq = seq; 318 nominal_frame_rate = crtc->mode.Clock; 319 nominal_frame_rate *= 1000; 320 pix_in_frame = crtc->mode.HTotal * crtc->mode.VTotal; 321 if (nominal_frame_rate == 0 || pix_in_frame == 0) 322 nominal_frame_rate = DEFAULT_NOMINAL_FRAME_RATE; 323 else 324 nominal_frame_rate /= pix_in_frame; 325 drmmode_crtc->dpms_last_fps = nominal_frame_rate; 326 } 327 328 drmmode_crtc->dpms_mode = mode; 329 radeon_drm_queue_handle_deferred(crtc); 330 } else if (drmmode_crtc->dpms_mode != DPMSModeOn && mode == DPMSModeOn) { 331 /* 332 * Off->On transition: calculate and accumulate the 333 * number of interpolated vblanks while we were in Off state 334 */ 335 ret = drmmode_get_current_ust(pRADEONEnt->fd, &ust); 336 if (ret) 337 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 338 "%s cannot get current time\n", __func__); 339 else if (drmmode_crtc->dpms_last_ust) { 340 CARD64 time_elapsed, delta_seq; 341 time_elapsed = ust - drmmode_crtc->dpms_last_ust; 342 delta_seq = time_elapsed * drmmode_crtc->dpms_last_fps; 343 delta_seq /= 1000000; 344 drmmode_crtc->interpolated_vblanks += delta_seq; 345 346 } 347 348 drmmode_crtc->dpms_mode = DPMSModeOn; 349 } 350} 351 352static void 353drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode) 354{ 355 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 356 RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 357 358 /* Disable unused CRTCs */ 359 if (!crtc->enabled || mode != DPMSModeOn) { 360 drmmode_do_crtc_dpms(crtc, DPMSModeOff); 361 drmModeSetCrtc(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 362 0, 0, 0, NULL, 0, NULL); 363 drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL); 364 } else if (drmmode_crtc->dpms_mode != DPMSModeOn) 365 crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, 366 crtc->x, crtc->y); 367} 368 369static PixmapPtr 370create_pixmap_for_fbcon(drmmode_ptr drmmode, 371 ScrnInfoPtr pScrn, int fbcon_id) 372{ 373 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 374 RADEONInfoPtr info = RADEONPTR(pScrn); 375 PixmapPtr pixmap = info->fbcon_pixmap; 376 struct radeon_buffer *bo; 377 drmModeFBPtr fbcon; 378 struct drm_gem_flink flink; 379 380 if (pixmap) 381 return pixmap; 382 383 fbcon = drmModeGetFB(pRADEONEnt->fd, fbcon_id); 384 if (!fbcon) 385 return NULL; 386 387 if (fbcon->depth != pScrn->depth || 388 fbcon->width != pScrn->virtualX || 389 fbcon->height != pScrn->virtualY) 390 goto out_free_fb; 391 392 flink.handle = fbcon->handle; 393 if (ioctl(pRADEONEnt->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { 394 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 395 "Couldn't flink fbcon handle\n"); 396 goto out_free_fb; 397 } 398 399 bo = calloc(1, sizeof(struct radeon_buffer)); 400 if (!bo) { 401 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 402 "Couldn't allocate BO for fbcon handle\n"); 403 goto out_free_fb; 404 } 405 bo->ref_count = 1; 406 407 bo->bo.radeon = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0); 408 if (!bo) { 409 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 410 "Couldn't open BO for fbcon handle\n"); 411 goto out_free_fb; 412 } 413 414 pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height, 415 fbcon->depth, fbcon->bpp, fbcon->pitch, 416 bo); 417 info->fbcon_pixmap = pixmap; 418 radeon_buffer_unref(&bo); 419out_free_fb: 420 drmModeFreeFB(fbcon); 421 return pixmap; 422} 423 424static void 425destroy_pixmap_for_fbcon(ScrnInfoPtr pScrn) 426{ 427 RADEONInfoPtr info = RADEONPTR(pScrn); 428 429 /* XXX: The current GPUVM support in the kernel doesn't allow removing 430 * the virtual address range for this BO, so we need to keep around 431 * the pixmap to avoid breaking glamor with GPUVM 432 * 433 * Similarly, need to keep around the pixmap with current glamor, to 434 * avoid issues due to a GEM handle lifetime conflict between us and 435 * Mesa 436 */ 437 if (info->use_glamor && 438 (info->ChipFamily >= CHIP_FAMILY_CAYMAN || 439 xorgGetVersion() >= XORG_VERSION_NUMERIC(1,19,99,1,0))) 440 return; 441 442 if (info->fbcon_pixmap) 443 pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap); 444 info->fbcon_pixmap = NULL; 445} 446 447void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 448{ 449 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 450 RADEONInfoPtr info = RADEONPTR(pScrn); 451 ScreenPtr pScreen = pScrn->pScreen; 452 PixmapPtr src, dst = pScreen->GetScreenPixmap(pScreen); 453 struct drmmode_fb *fb = radeon_pixmap_get_fb(dst); 454 int fbcon_id = 0; 455 Bool force; 456 GCPtr gc; 457 int i; 458 459 for (i = 0; i < xf86_config->num_crtc; i++) { 460 drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[i]->driver_private; 461 462 if (drmmode_crtc->mode_crtc->buffer_id) 463 fbcon_id = drmmode_crtc->mode_crtc->buffer_id; 464 } 465 466 if (!fbcon_id) 467 return; 468 469 if (fbcon_id == fb->handle) { 470 /* in some rare case there might be no fbcon and we might already 471 * be the one with the current fb to avoid a false deadlck in 472 * kernel ttm code just do nothing as anyway there is nothing 473 * to do 474 */ 475 return; 476 } 477 478 src = create_pixmap_for_fbcon(drmmode, pScrn, fbcon_id); 479 if (!src) 480 return; 481 482 gc = GetScratchGC(pScrn->depth, pScreen); 483 ValidateGC(&dst->drawable, gc); 484 485 force = info->accel_state->force; 486 info->accel_state->force = TRUE; 487 (*gc->ops->CopyArea)(&src->drawable, &dst->drawable, gc, 0, 0, 488 pScrn->virtualX, pScrn->virtualY, 0, 0); 489 info->accel_state->force = force; 490 491 FreeScratchGC(gc); 492 493 pScreen->canDoBGNoneRoot = TRUE; 494 destroy_pixmap_for_fbcon(pScrn); 495 return; 496} 497 498void 499drmmode_crtc_scanout_destroy(drmmode_ptr drmmode, 500 struct drmmode_scanout *scanout) 501{ 502 if (scanout->pixmap) { 503 drmmode_destroy_bo_pixmap(scanout->pixmap); 504 scanout->pixmap = NULL; 505 } 506 507 radeon_buffer_unref(&scanout->bo); 508} 509 510void 511drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc) 512{ 513 drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, 514 &drmmode_crtc->scanout[0]); 515 drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, 516 &drmmode_crtc->scanout[1]); 517 518 if (drmmode_crtc->scanout_damage) 519 DamageDestroy(drmmode_crtc->scanout_damage); 520} 521 522PixmapPtr 523drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, 524 int width, int height) 525{ 526 ScrnInfoPtr pScrn = crtc->scrn; 527 RADEONInfoPtr info = RADEONPTR(pScrn); 528 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 529 drmmode_ptr drmmode = drmmode_crtc->drmmode; 530 struct radeon_surface surface; 531 uint32_t tiling = RADEON_CREATE_PIXMAP_TILING_MACRO; 532 int pitch; 533 534 if (scanout->pixmap) { 535 if (scanout->width == width && scanout->height == height) 536 return scanout->pixmap; 537 538 drmmode_crtc_scanout_destroy(drmmode, scanout); 539 } 540 541 if (info->ChipFamily >= CHIP_FAMILY_R600) 542 tiling |= RADEON_CREATE_PIXMAP_TILING_MICRO; 543 scanout->bo = radeon_alloc_pixmap_bo(pScrn, width, height, pScrn->depth, 544 tiling, pScrn->bitsPerPixel, 545 &pitch, &surface, &tiling); 546 if (!scanout->bo) { 547 ErrorF("failed to create CRTC scanout BO\n"); 548 return NULL; 549 } 550 551 scanout->pixmap = drmmode_create_bo_pixmap(pScrn, 552 width, height, 553 pScrn->depth, 554 pScrn->bitsPerPixel, 555 pitch, scanout->bo); 556 if (!scanout->pixmap) { 557 ErrorF("failed to create CRTC scanout pixmap\n"); 558 goto error; 559 } 560 561 if (radeon_pixmap_get_fb(scanout->pixmap)) { 562 scanout->width = width; 563 scanout->height = height; 564 } else { 565 ErrorF("failed to create CRTC scanout FB\n"); 566error: 567 drmmode_crtc_scanout_destroy(drmmode, scanout); 568 } 569 570 return scanout->pixmap; 571} 572 573static void 574radeon_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure) 575{ 576 drmmode_crtc_private_ptr drmmode_crtc = closure; 577 578 if (drmmode_crtc->ignore_damage) { 579 RegionEmpty(&damage->damage); 580 drmmode_crtc->ignore_damage = FALSE; 581 return; 582 } 583 584 /* Only keep track of the extents */ 585 RegionUninit(&damage->damage); 586 damage->damage.data = NULL; 587} 588 589static void 590drmmode_screen_damage_destroy(DamagePtr damage, void *closure) 591{ 592 drmmode_crtc_private_ptr drmmode_crtc = closure; 593 594 drmmode_crtc->scanout_damage = NULL; 595 RegionUninit(&drmmode_crtc->scanout_last_region); 596} 597 598static Bool 599drmmode_can_use_hw_cursor(xf86CrtcPtr crtc) 600{ 601 RADEONInfoPtr info = RADEONPTR(crtc->scrn); 602 603 /* Check for Option "SWcursor" */ 604 if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) 605 return FALSE; 606 607 /* Fall back to SW cursor if the CRTC is transformed */ 608 if (crtc->transformPresent) 609 return FALSE; 610 611#if XF86_CRTC_VERSION < 7 612 /* Xorg doesn't correctly handle cursor position transform in the 613 * rotation case 614 */ 615 if (crtc->driverIsPerformingTransform && 616 (crtc->rotation & 0xf) != RR_Rotate_0) 617 return FALSE; 618#endif 619 620 /* HW cursor not supported with RandR 1.4 multihead up to 1.18.99.901 */ 621 if (xorgGetVersion() <= XORG_VERSION_NUMERIC(1,18,99,901,0) && 622 !xorg_list_is_empty(&crtc->scrn->pScreen->pixmap_dirty_list)) 623 return FALSE; 624 625 return TRUE; 626} 627 628static void 629drmmode_crtc_update_tear_free(xf86CrtcPtr crtc) 630{ 631 RADEONInfoPtr info = RADEONPTR(crtc->scrn); 632 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 633 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 634 int i; 635 636 drmmode_crtc->tear_free = FALSE; 637 638 for (i = 0; i < xf86_config->num_output; i++) { 639 xf86OutputPtr output = xf86_config->output[i]; 640 drmmode_output_private_ptr drmmode_output = output->driver_private; 641 642 if (output->crtc != crtc) 643 continue; 644 645 if (drmmode_output->tear_free == 1 || 646 (drmmode_output->tear_free == 2 && 647 (crtc->scrn->pScreen->isGPU || 648 info->shadow_primary || 649 crtc->transformPresent || crtc->rotation != RR_Rotate_0))) { 650 drmmode_crtc->tear_free = TRUE; 651 return; 652 } 653 } 654} 655 656#if XF86_CRTC_VERSION < 7 657#define XF86DriverTransformOutput TRUE 658#define XF86DriverTransformNone FALSE 659#endif 660 661static Bool 662drmmode_handle_transform(xf86CrtcPtr crtc) 663{ 664 Bool ret; 665 666#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0) 667 crtc->driverIsPerformingTransform = XF86DriverTransformOutput; 668#else 669 crtc->driverIsPerformingTransform = !crtc->transformPresent && 670 (crtc->rotation & 0xf) == RR_Rotate_0; 671#endif 672 673 ret = xf86CrtcRotate(crtc); 674 675 crtc->driverIsPerformingTransform &= ret && crtc->transform_in_use; 676 677 return ret; 678} 679 680 681static void 682drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, 683 unsigned scanout_id, struct drmmode_fb **fb, 684 int *x, int *y) 685{ 686 ScrnInfoPtr scrn = crtc->scrn; 687 ScreenPtr screen = scrn->pScreen; 688 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 689 690 if (drmmode_crtc->tear_free && 691 !drmmode_crtc->scanout[1].pixmap) { 692 RegionPtr region; 693 BoxPtr box; 694 695 drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1], 696 mode->HDisplay, 697 mode->VDisplay); 698 region = &drmmode_crtc->scanout_last_region; 699 RegionUninit(region); 700 region->data = NULL; 701 box = RegionExtents(region); 702 box->x1 = crtc->x; 703 box->y1 = crtc->y; 704 box->x2 = crtc->x + mode->HDisplay; 705 box->y2 = crtc->y + mode->VDisplay; 706 } 707 708 if (scanout_id != drmmode_crtc->scanout_id) { 709 PixmapDirtyUpdatePtr dirty = NULL; 710 711 xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, 712 ent) { 713 if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { 714 dirty->slave_dst = 715 drmmode_crtc->scanout[scanout_id].pixmap; 716 break; 717 } 718 } 719 720 if (!drmmode_crtc->tear_free) { 721 GCPtr gc = GetScratchGC(scrn->depth, screen); 722 723 ValidateGC(&drmmode_crtc->scanout[0].pixmap->drawable, gc); 724 gc->ops->CopyArea(&drmmode_crtc->scanout[1].pixmap->drawable, 725 &drmmode_crtc->scanout[0].pixmap->drawable, 726 gc, 0, 0, mode->HDisplay, mode->VDisplay, 727 0, 0); 728 FreeScratchGC(gc); 729 radeon_finish(scrn, drmmode_crtc->scanout[0].bo); 730 } 731 } 732 733 *fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); 734 *x = *y = 0; 735 drmmode_crtc->scanout_id = scanout_id; 736} 737 738 739static void 740drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, 741 unsigned scanout_id, struct drmmode_fb **fb, int *x, 742 int *y) 743{ 744 ScrnInfoPtr scrn = crtc->scrn; 745 ScreenPtr screen = scrn->pScreen; 746 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 747 748 drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[scanout_id], 749 mode->HDisplay, mode->VDisplay); 750 if (drmmode_crtc->tear_free) { 751 drmmode_crtc_scanout_create(crtc, 752 &drmmode_crtc->scanout[scanout_id ^ 1], 753 mode->HDisplay, mode->VDisplay); 754 } 755 756 if (drmmode_crtc->scanout[scanout_id].pixmap && 757 (!drmmode_crtc->tear_free || 758 drmmode_crtc->scanout[scanout_id ^ 1].pixmap)) { 759 BoxRec extents = { .x1 = 0, .y1 = 0, 760 .x2 = scrn->virtualX, .y2 = scrn->virtualY }; 761 762 if (!drmmode_crtc->scanout_damage) { 763 drmmode_crtc->scanout_damage = 764 DamageCreate(radeon_screen_damage_report, 765 drmmode_screen_damage_destroy, 766 DamageReportRawRegion, 767 TRUE, screen, drmmode_crtc); 768 DamageRegister(&screen->root->drawable, 769 drmmode_crtc->scanout_damage); 770 } 771 772 *fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); 773 *x = *y = 0; 774 775 radeon_scanout_do_update(crtc, scanout_id, 776 screen->GetWindowPixmap(screen->root), 777 extents); 778 RegionEmpty(DamageRegion(drmmode_crtc->scanout_damage)); 779 radeon_finish(scrn, drmmode_crtc->scanout[scanout_id].bo); 780 } 781} 782 783static void 784drmmode_crtc_gamma_do_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, 785 uint16_t *blue, int size) 786{ 787 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 788 RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 789 790 drmModeCrtcSetGamma(pRADEONEnt->fd, 791 drmmode_crtc->mode_crtc->crtc_id, size, red, green, 792 blue); 793} 794 795Bool 796drmmode_set_mode(xf86CrtcPtr crtc, struct drmmode_fb *fb, DisplayModePtr mode, 797 int x, int y) 798{ 799 ScrnInfoPtr scrn = crtc->scrn; 800 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 801 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 802 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 803 uint32_t *output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); 804 int output_count = 0; 805 drmModeModeInfo kmode; 806 Bool ret; 807 int i; 808 809 if (!output_ids) 810 return FALSE; 811 812 for (i = 0; i < xf86_config->num_output; i++) { 813 xf86OutputPtr output = xf86_config->output[i]; 814 drmmode_output_private_ptr drmmode_output = output->driver_private; 815 816 if (output->crtc != crtc) 817 continue; 818 819 output_ids[output_count] = drmmode_output->mode_output->connector_id; 820 output_count++; 821 } 822 823 drmmode_ConvertToKMode(scrn, &kmode, mode); 824 825 ret = drmModeSetCrtc(pRADEONEnt->fd, 826 drmmode_crtc->mode_crtc->crtc_id, 827 fb->handle, x, y, output_ids, 828 output_count, &kmode) == 0; 829 830 if (ret) { 831 drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, fb); 832 } else { 833 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 834 "failed to set mode: %s\n", strerror(errno)); 835 } 836 837 free(output_ids); 838 return ret; 839} 840 841static Bool 842drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, 843 Rotation rotation, int x, int y) 844{ 845 ScrnInfoPtr pScrn = crtc->scrn; 846 ScreenPtr pScreen = pScrn->pScreen; 847 RADEONInfoPtr info = RADEONPTR(pScrn); 848 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 849 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 850 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 851 unsigned scanout_id = 0; 852 drmmode_ptr drmmode = drmmode_crtc->drmmode; 853 int saved_x, saved_y; 854 Rotation saved_rotation; 855 DisplayModeRec saved_mode; 856 Bool ret = FALSE; 857 int i; 858 struct drmmode_fb *fb = NULL; 859 860 /* The root window contents may be undefined before the WindowExposures 861 * hook is called for it, so bail if we get here before that 862 */ 863 if (pScreen->WindowExposures == RADEONWindowExposures_oneshot) 864 return FALSE; 865 866 saved_mode = crtc->mode; 867 saved_x = crtc->x; 868 saved_y = crtc->y; 869 saved_rotation = crtc->rotation; 870 871 if (mode) { 872 crtc->mode = *mode; 873 crtc->x = x; 874 crtc->y = y; 875 crtc->rotation = rotation; 876 877 if (!drmmode_handle_transform(crtc)) 878 goto done; 879 880 drmmode_crtc_update_tear_free(crtc); 881 if (drmmode_crtc->tear_free) 882 scanout_id = drmmode_crtc->scanout_id; 883 else 884 drmmode_crtc->scanout_id = 0; 885 886 if (drmmode_crtc->prime_scanout_pixmap) { 887 drmmode_crtc_prime_scanout_update(crtc, mode, scanout_id, 888 &fb, &x, &y); 889 } else if (drmmode_crtc->rotate.pixmap) { 890 fb = radeon_pixmap_get_fb(drmmode_crtc->rotate.pixmap); 891 x = y = 0; 892 893 } else if (!pScreen->isGPU && 894 (drmmode_crtc->tear_free || 895 crtc->driverIsPerformingTransform || 896 info->shadow_primary)) { 897 drmmode_crtc_scanout_update(crtc, mode, scanout_id, 898 &fb, &x, &y); 899 } 900 901 if (!fb) 902 fb = radeon_pixmap_get_fb(pScreen->GetWindowPixmap(pScreen->root)); 903 if (!fb) { 904 fb = radeon_fb_create(pScrn, pRADEONEnt->fd, 905 pScrn->virtualX, pScrn->virtualY, 906 pScrn->displayWidth * info->pixel_bytes, 907 info->front_buffer->bo.radeon->handle); 908 /* Prevent refcnt of ad-hoc FBs from reaching 2 */ 909 drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL); 910 drmmode_crtc->fb = fb; 911 } 912 if (!fb) { 913 ErrorF("failed to add FB for modeset\n"); 914 goto done; 915 } 916 917 radeon_drm_wait_pending_flip(crtc); 918 919 if (!drmmode_set_mode(crtc, fb, mode, x, y)) 920 goto done; 921 922 ret = TRUE; 923 924 if (pScreen) 925 xf86CrtcSetScreenSubpixelOrder(pScreen); 926 927 drmmode_crtc->need_modeset = FALSE; 928 929 /* go through all the outputs and force DPMS them back on? */ 930 for (i = 0; i < xf86_config->num_output; i++) { 931 xf86OutputPtr output = xf86_config->output[i]; 932 933 if (output->crtc != crtc) 934 continue; 935 936 output->funcs->dpms(output, DPMSModeOn); 937 } 938 } 939 940 /* Compute index of this CRTC into xf86_config->crtc */ 941 for (i = 0; i < xf86_config->num_crtc; i++) { 942 if (xf86_config->crtc[i] != crtc) 943 continue; 944 945 if (!crtc->enabled || drmmode_can_use_hw_cursor(crtc)) 946 info->hwcursor_disabled &= ~(1 << i); 947 else 948 info->hwcursor_disabled |= 1 << i; 949 950 break; 951 } 952 953#ifndef HAVE_XF86_CURSOR_RESET_CURSOR 954 if (!info->hwcursor_disabled) 955 xf86_reload_cursors(pScreen); 956#endif 957 958done: 959 if (!ret) { 960 crtc->x = saved_x; 961 crtc->y = saved_y; 962 crtc->rotation = saved_rotation; 963 crtc->mode = saved_mode; 964 } else { 965 crtc->active = TRUE; 966 967 if (drmmode_crtc->scanout[scanout_id].pixmap && 968 fb != radeon_pixmap_get_fb(drmmode_crtc-> 969 scanout[scanout_id].pixmap)) { 970 radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending); 971 drmmode_crtc->scanout_update_pending = 0; 972 drmmode_crtc_scanout_free(drmmode_crtc); 973 } else if (!drmmode_crtc->tear_free) { 974 drmmode_crtc_scanout_destroy(drmmode, 975 &drmmode_crtc->scanout[1]); 976 } 977 } 978 979 radeon_drm_queue_handle_deferred(crtc); 980 return ret; 981} 982 983static void 984drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) 985{ 986 987} 988 989static void 990drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) 991{ 992 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 993 RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 994 995#if XF86_CRTC_VERSION < 7 996 if (crtc->driverIsPerformingTransform) { 997 x += crtc->x; 998 y += crtc->y; 999 xf86CrtcTransformCursorPos(crtc, &x, &y); 1000 } 1001#endif 1002 1003 drmModeMoveCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); 1004} 1005 1006#if XF86_CRTC_VERSION < 7 1007 1008static int 1009drmmode_cursor_src_offset(Rotation rotation, int width, int height, 1010 int x_dst, int y_dst) 1011{ 1012 int t; 1013 1014 switch (rotation & 0xf) { 1015 case RR_Rotate_90: 1016 t = x_dst; 1017 x_dst = height - y_dst - 1; 1018 y_dst = t; 1019 break; 1020 case RR_Rotate_180: 1021 x_dst = width - x_dst - 1; 1022 y_dst = height - y_dst - 1; 1023 break; 1024 case RR_Rotate_270: 1025 t = x_dst; 1026 x_dst = y_dst; 1027 y_dst = width - t - 1; 1028 break; 1029 } 1030 1031 if (rotation & RR_Reflect_X) 1032 x_dst = width - x_dst - 1; 1033 if (rotation & RR_Reflect_Y) 1034 y_dst = height - y_dst - 1; 1035 1036 return y_dst * height + x_dst; 1037} 1038 1039#endif 1040 1041static uint32_t 1042drmmode_cursor_gamma(xf86CrtcPtr crtc, uint32_t argb) 1043{ 1044 uint32_t alpha = argb >> 24; 1045 uint32_t rgb[3]; 1046 int i; 1047 1048 if (!alpha) 1049 return 0; 1050 1051 if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32) 1052 return argb; 1053 1054 /* Un-premultiply alpha */ 1055 for (i = 0; i < 3; i++) 1056 rgb[i] = ((argb >> (i * 8)) & 0xff) * 0xff / alpha; 1057 1058 /* Apply gamma correction and pre-multiply alpha */ 1059 rgb[0] = (crtc->gamma_blue[rgb[0]] >> 8) * alpha / 0xff; 1060 rgb[1] = (crtc->gamma_green[rgb[1]] >> 8) * alpha / 0xff; 1061 rgb[2] = (crtc->gamma_red[rgb[2]] >> 8) * alpha / 0xff; 1062 1063 return alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0]; 1064} 1065 1066static void 1067drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) 1068{ 1069 ScrnInfoPtr pScrn = crtc->scrn; 1070 RADEONInfoPtr info = RADEONPTR(pScrn); 1071 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1072 uint32_t *ptr; 1073 1074 /* cursor should be mapped already */ 1075 ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr); 1076 1077#if XF86_CRTC_VERSION < 7 1078 if (crtc->driverIsPerformingTransform) { 1079 uint32_t cursor_w = info->cursor_w, cursor_h = info->cursor_h; 1080 int dstx, dsty; 1081 int srcoffset; 1082 1083 for (dsty = 0; dsty < cursor_h; dsty++) { 1084 for (dstx = 0; dstx < cursor_w; dstx++) { 1085 srcoffset = drmmode_cursor_src_offset(crtc->rotation, 1086 cursor_w, 1087 cursor_h, 1088 dstx, dsty); 1089 1090 ptr[dsty * info->cursor_w + dstx] = 1091 cpu_to_le32(drmmode_cursor_gamma(crtc, 1092 image[srcoffset])); 1093 } 1094 } 1095 } else 1096#endif 1097 { 1098 uint32_t cursor_size = info->cursor_w * info->cursor_h; 1099 int i; 1100 1101 for (i = 0; i < cursor_size; i++) 1102 ptr[i] = cpu_to_le32(drmmode_cursor_gamma(crtc, image[i])); 1103 } 1104} 1105 1106#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0) 1107 1108static Bool drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 * image) 1109{ 1110 if (!drmmode_can_use_hw_cursor(crtc)) 1111 return FALSE; 1112 1113 drmmode_load_cursor_argb(crtc, image); 1114 return TRUE; 1115} 1116 1117#endif 1118 1119static void 1120drmmode_hide_cursor (xf86CrtcPtr crtc) 1121{ 1122 ScrnInfoPtr pScrn = crtc->scrn; 1123 RADEONInfoPtr info = RADEONPTR(pScrn); 1124 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1125 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1126 1127 drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 1128 info->cursor_w, info->cursor_h); 1129 1130} 1131 1132static void 1133drmmode_show_cursor (xf86CrtcPtr crtc) 1134{ 1135 ScrnInfoPtr pScrn = crtc->scrn; 1136 RADEONInfoPtr info = RADEONPTR(pScrn); 1137 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1138 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1139 uint32_t handle = drmmode_crtc->cursor_bo->handle; 1140 static Bool use_set_cursor2 = TRUE; 1141 1142 if (use_set_cursor2) { 1143 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 1144 CursorPtr cursor = xf86_config->cursor; 1145 int xhot = cursor->bits->xhot; 1146 int yhot = cursor->bits->yhot; 1147 int ret; 1148 1149 if (crtc->rotation != RR_Rotate_0 && 1150 crtc->rotation != (RR_Rotate_180 | RR_Reflect_X | 1151 RR_Reflect_Y)) { 1152 int t; 1153 1154 /* Reflect & rotate hotspot position */ 1155 if (crtc->rotation & RR_Reflect_X) 1156 xhot = info->cursor_w - xhot - 1; 1157 if (crtc->rotation & RR_Reflect_Y) 1158 yhot = info->cursor_h - yhot - 1; 1159 1160 switch (crtc->rotation & 0xf) { 1161 case RR_Rotate_90: 1162 t = xhot; 1163 xhot = yhot; 1164 yhot = info->cursor_w - t - 1; 1165 break; 1166 case RR_Rotate_180: 1167 xhot = info->cursor_w - xhot - 1; 1168 yhot = info->cursor_h - yhot - 1; 1169 break; 1170 case RR_Rotate_270: 1171 t = xhot; 1172 xhot = info->cursor_h - yhot - 1; 1173 yhot = t; 1174 } 1175 } 1176 1177 ret = 1178 drmModeSetCursor2(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 1179 handle, info->cursor_w, info->cursor_h, 1180 xhot, yhot); 1181 if (ret == -EINVAL) 1182 use_set_cursor2 = FALSE; 1183 else 1184 return; 1185 } 1186 1187 drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 1188 info->cursor_w, info->cursor_h); 1189} 1190 1191/* Xorg expects a non-NULL return value from drmmode_crtc_shadow_allocate, and 1192 * passes that back to drmmode_crtc_scanout_create; it doesn't use it for 1193 * anything else. 1194 */ 1195static void * 1196drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) 1197{ 1198 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1199 1200 if (!drmmode_crtc_scanout_create(crtc, &drmmode_crtc->rotate, width, 1201 height)) 1202 return NULL; 1203 1204 return (void*)~0UL; 1205} 1206 1207static PixmapPtr 1208drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) 1209{ 1210 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1211 1212 if (!data) { 1213 drmmode_crtc_scanout_create(crtc, &drmmode_crtc->rotate, width, 1214 height); 1215 } 1216 1217 return drmmode_crtc->rotate.pixmap; 1218} 1219 1220static void 1221drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) 1222{ 1223 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1224 drmmode_ptr drmmode = drmmode_crtc->drmmode; 1225 1226 drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->rotate); 1227} 1228 1229static void 1230drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, 1231 uint16_t *blue, int size) 1232{ 1233 ScrnInfoPtr scrn = crtc->scrn; 1234 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1235 RADEONInfoPtr info = RADEONPTR(scrn); 1236 int i; 1237 1238 drmmode_crtc_gamma_do_set(crtc, red, green, blue, size); 1239 1240 /* Compute index of this CRTC into xf86_config->crtc */ 1241 for (i = 0; xf86_config->crtc[i] != crtc; i++) {} 1242 1243 if (info->hwcursor_disabled & (1 << i)) 1244 return; 1245 1246#ifdef HAVE_XF86_CURSOR_RESET_CURSOR 1247 xf86CursorResetCursor(scrn->pScreen); 1248#else 1249 xf86_reload_cursors(scrn->pScreen); 1250#endif 1251} 1252 1253static Bool 1254drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) 1255{ 1256 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1257 unsigned scanout_id = drmmode_crtc->scanout_id; 1258 ScreenPtr screen = crtc->scrn->pScreen; 1259 PixmapDirtyUpdatePtr dirty; 1260 1261 xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) { 1262 if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { 1263 PixmapStopDirtyTracking(dirty->src, dirty->slave_dst); 1264 break; 1265 } 1266 } 1267 1268 drmmode_crtc_scanout_free(drmmode_crtc); 1269 drmmode_crtc->prime_scanout_pixmap = NULL; 1270 1271 if (!ppix) 1272 return TRUE; 1273 1274 if (!drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[0], 1275 ppix->drawable.width, 1276 ppix->drawable.height)) 1277 return FALSE; 1278 1279 if (drmmode_crtc->tear_free && 1280 !drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1], 1281 ppix->drawable.width, 1282 ppix->drawable.height)) { 1283 drmmode_crtc_scanout_free(drmmode_crtc); 1284 return FALSE; 1285 } 1286 1287 drmmode_crtc->prime_scanout_pixmap = ppix; 1288 1289#ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC 1290 PixmapStartDirtyTracking(&ppix->drawable, 1291 drmmode_crtc->scanout[scanout_id].pixmap, 1292 0, 0, 0, 0, RR_Rotate_0); 1293#elif defined(HAS_DIRTYTRACKING_ROTATION) 1294 PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[scanout_id].pixmap, 1295 0, 0, 0, 0, RR_Rotate_0); 1296#elif defined(HAS_DIRTYTRACKING2) 1297 PixmapStartDirtyTracking2(ppix, drmmode_crtc->scanout[scanout_id].pixmap, 1298 0, 0, 0, 0); 1299#else 1300 PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[scanout_id].pixmap, 0, 0); 1301#endif 1302 return TRUE; 1303} 1304 1305static xf86CrtcFuncsRec drmmode_crtc_funcs = { 1306 .dpms = drmmode_crtc_dpms, 1307 .set_mode_major = drmmode_set_mode_major, 1308 .set_cursor_colors = drmmode_set_cursor_colors, 1309 .set_cursor_position = drmmode_set_cursor_position, 1310 .show_cursor = drmmode_show_cursor, 1311 .hide_cursor = drmmode_hide_cursor, 1312 .load_cursor_argb = drmmode_load_cursor_argb, 1313#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0) 1314 .load_cursor_argb_check = drmmode_load_cursor_argb_check, 1315#endif 1316 1317 .gamma_set = drmmode_crtc_gamma_set, 1318 .shadow_create = drmmode_crtc_shadow_create, 1319 .shadow_allocate = drmmode_crtc_shadow_allocate, 1320 .shadow_destroy = drmmode_crtc_shadow_destroy, 1321 .destroy = NULL, /* XXX */ 1322 .set_scanout_pixmap = drmmode_set_scanout_pixmap, 1323}; 1324 1325int drmmode_get_crtc_id(xf86CrtcPtr crtc) 1326{ 1327 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1328 return drmmode_crtc->hw_id; 1329} 1330 1331void drmmode_crtc_hw_id(xf86CrtcPtr crtc) 1332{ 1333 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1334 RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 1335 struct drm_radeon_info ginfo; 1336 int r; 1337 uint32_t tmp; 1338 1339 memset(&ginfo, 0, sizeof(ginfo)); 1340 ginfo.request = 0x4; 1341 tmp = drmmode_crtc->mode_crtc->crtc_id; 1342 ginfo.value = (uintptr_t)&tmp; 1343 r = drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); 1344 if (r) { 1345 drmmode_crtc->hw_id = -1; 1346 return; 1347 } 1348 drmmode_crtc->hw_id = tmp; 1349} 1350 1351static unsigned int 1352drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num) 1353{ 1354 xf86CrtcPtr crtc; 1355 drmmode_crtc_private_ptr drmmode_crtc; 1356 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1357 RADEONInfoPtr info = RADEONPTR(pScrn); 1358 1359 crtc = xf86CrtcCreate(pScrn, &info->drmmode_crtc_funcs); 1360 if (!crtc) 1361 return 0; 1362 1363 drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); 1364 drmmode_crtc->mode_crtc = drmModeGetCrtc(pRADEONEnt->fd, mode_res->crtcs[num]); 1365 drmmode_crtc->drmmode = drmmode; 1366 drmmode_crtc->dpms_mode = DPMSModeOff; 1367 crtc->driver_private = drmmode_crtc; 1368 drmmode_crtc_hw_id(crtc); 1369 1370 /* Mark num'th crtc as in use on this device. */ 1371 pRADEONEnt->assigned_crtcs |= (1 << num); 1372 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 1373 "Allocated crtc nr. %d to this screen.\n", num); 1374 1375 return 1; 1376} 1377 1378/* 1379 * Update all of the property values for an output 1380 */ 1381static void 1382drmmode_output_update_properties(xf86OutputPtr output) 1383{ 1384 drmmode_output_private_ptr drmmode_output = output->driver_private; 1385 int i, j, k; 1386 int err; 1387 drmModeConnectorPtr koutput; 1388 1389 /* Use the most recently fetched values from the kernel */ 1390 koutput = drmmode_output->mode_output; 1391 1392 if (!koutput) 1393 return; 1394 1395 for (i = 0; i < drmmode_output->num_props; i++) { 1396 drmmode_prop_ptr p = &drmmode_output->props[i]; 1397 1398 for (j = 0; j < koutput->count_props; j++) { 1399 if (koutput->props[j] != p->mode_prop->prop_id) 1400 continue; 1401 1402 /* Check to see if the property value has changed */ 1403 if (koutput->prop_values[j] == p->value) 1404 break; 1405 1406 p->value = koutput->prop_values[j]; 1407 1408 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { 1409 INT32 value = p->value; 1410 1411 err = RRChangeOutputProperty(output->randr_output, 1412 p->atoms[0], XA_INTEGER, 1413 32, PropModeReplace, 1, 1414 &value, FALSE, TRUE); 1415 if (err != 0) { 1416 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1417 "RRChangeOutputProperty error, %d\n", 1418 err); 1419 } 1420 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { 1421 for (k = 0; k < p->mode_prop->count_enums; k++) { 1422 if (p->mode_prop->enums[k].value == p->value) 1423 break; 1424 } 1425 if (k < p->mode_prop->count_enums) { 1426 err = RRChangeOutputProperty(output->randr_output, 1427 p->atoms[0], XA_ATOM, 1428 32, PropModeReplace, 1, 1429 &p->atoms[k + 1], FALSE, 1430 TRUE); 1431 if (err != 0) { 1432 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1433 "RRChangeOutputProperty error, %d\n", 1434 err); 1435 } 1436 } 1437 } 1438 1439 break; 1440 } 1441 } 1442} 1443 1444static xf86OutputStatus 1445drmmode_output_detect(xf86OutputPtr output) 1446{ 1447 /* go to the hw and retrieve a new output struct */ 1448 drmmode_output_private_ptr drmmode_output = output->driver_private; 1449 RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); 1450 xf86OutputStatus status; 1451 drmModeFreeConnector(drmmode_output->mode_output); 1452 1453 drmmode_output->mode_output = 1454 drmModeGetConnector(pRADEONEnt->fd, drmmode_output->output_id); 1455 if (!drmmode_output->mode_output) { 1456 drmmode_output->output_id = -1; 1457 return XF86OutputStatusDisconnected; 1458 } 1459 1460 drmmode_output_update_properties(output); 1461 1462 switch (drmmode_output->mode_output->connection) { 1463 case DRM_MODE_CONNECTED: 1464 status = XF86OutputStatusConnected; 1465 break; 1466 case DRM_MODE_DISCONNECTED: 1467 status = XF86OutputStatusDisconnected; 1468 break; 1469 default: 1470 case DRM_MODE_UNKNOWNCONNECTION: 1471 status = XF86OutputStatusUnknown; 1472 break; 1473 } 1474 return status; 1475} 1476 1477static Bool 1478drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) 1479{ 1480 return MODE_OK; 1481} 1482 1483static int 1484koutput_get_prop_idx(int fd, drmModeConnectorPtr koutput, 1485 int type, const char *name) 1486{ 1487 int idx = -1; 1488 1489 for (int i = 0; i < koutput->count_props; i++) { 1490 drmModePropertyPtr prop = drmModeGetProperty(fd, koutput->props[i]); 1491 1492 if (!prop) 1493 continue; 1494 1495 if (drm_property_type_is(prop, type) && !strcmp(prop->name, name)) 1496 idx = i; 1497 1498 drmModeFreeProperty(prop); 1499 1500 if (idx > -1) 1501 break; 1502 } 1503 1504 return idx; 1505} 1506 1507static int 1508koutput_get_prop_id(int fd, drmModeConnectorPtr koutput, 1509 int type, const char *name) 1510{ 1511 int idx = koutput_get_prop_idx(fd, koutput, type, name); 1512 1513 return (idx > -1) ? koutput->props[idx] : -1; 1514} 1515 1516static drmModePropertyBlobPtr 1517koutput_get_prop_blob(int fd, drmModeConnectorPtr koutput, const char *name) 1518{ 1519 drmModePropertyBlobPtr blob = NULL; 1520 int idx = koutput_get_prop_idx(fd, koutput, DRM_MODE_PROP_BLOB, name); 1521 1522 if (idx > -1) 1523 blob = drmModeGetPropertyBlob(fd, koutput->prop_values[idx]); 1524 1525 return blob; 1526} 1527 1528static DisplayModePtr 1529drmmode_output_get_modes(xf86OutputPtr output) 1530{ 1531 drmmode_output_private_ptr drmmode_output = output->driver_private; 1532 drmModeConnectorPtr koutput = drmmode_output->mode_output; 1533 RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); 1534 int i; 1535 DisplayModePtr Modes = NULL, Mode; 1536 xf86MonPtr mon = NULL; 1537 1538 if (!koutput) 1539 return NULL; 1540 1541 drmModeFreePropertyBlob(drmmode_output->edid_blob); 1542 1543 /* look for an EDID property */ 1544 drmmode_output->edid_blob = 1545 koutput_get_prop_blob(pRADEONEnt->fd, koutput, "EDID"); 1546 1547 if (drmmode_output->edid_blob) { 1548 mon = xf86InterpretEDID(output->scrn->scrnIndex, 1549 drmmode_output->edid_blob->data); 1550 if (mon && drmmode_output->edid_blob->length > 128) 1551 mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA; 1552 } 1553 xf86OutputSetEDID(output, mon); 1554 1555 /* modes should already be available */ 1556 for (i = 0; i < koutput->count_modes; i++) { 1557 Mode = xnfalloc(sizeof(DisplayModeRec)); 1558 1559 drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode); 1560 Modes = xf86ModesAdd(Modes, Mode); 1561 1562 } 1563 return Modes; 1564} 1565 1566static void 1567drmmode_output_destroy(xf86OutputPtr output) 1568{ 1569 drmmode_output_private_ptr drmmode_output = output->driver_private; 1570 int i; 1571 1572 if (drmmode_output->edid_blob) 1573 drmModeFreePropertyBlob(drmmode_output->edid_blob); 1574 for (i = 0; i < drmmode_output->num_props; i++) { 1575 drmModeFreeProperty(drmmode_output->props[i].mode_prop); 1576 free(drmmode_output->props[i].atoms); 1577 } 1578 for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) { 1579 drmModeFreeEncoder(drmmode_output->mode_encoders[i]); 1580 } 1581 free(drmmode_output->mode_encoders); 1582 free(drmmode_output->props); 1583 drmModeFreeConnector(drmmode_output->mode_output); 1584 free(drmmode_output); 1585 output->driver_private = NULL; 1586} 1587 1588static void 1589drmmode_output_dpms(xf86OutputPtr output, int mode) 1590{ 1591 drmmode_output_private_ptr drmmode_output = output->driver_private; 1592 xf86CrtcPtr crtc = output->crtc; 1593 drmModeConnectorPtr koutput = drmmode_output->mode_output; 1594 RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); 1595 1596 if (!koutput) 1597 return; 1598 1599 if (mode != DPMSModeOn && crtc) 1600 drmmode_do_crtc_dpms(crtc, mode); 1601 1602 drmModeConnectorSetProperty(pRADEONEnt->fd, koutput->connector_id, 1603 drmmode_output->dpms_enum_id, mode); 1604 1605 if (mode == DPMSModeOn && crtc) { 1606 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1607 1608 if (drmmode_crtc->need_modeset) 1609 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x, 1610 crtc->y); 1611 else 1612 drmmode_do_crtc_dpms(crtc, mode); 1613 } 1614} 1615 1616 1617static Bool 1618drmmode_property_ignore(drmModePropertyPtr prop) 1619{ 1620 if (!prop) 1621 return TRUE; 1622 /* ignore blob prop */ 1623 if (prop->flags & DRM_MODE_PROP_BLOB) 1624 return TRUE; 1625 /* ignore standard property */ 1626 if (!strcmp(prop->name, "EDID") || 1627 !strcmp(prop->name, "DPMS")) 1628 return TRUE; 1629 1630 return FALSE; 1631} 1632 1633static void 1634drmmode_output_create_resources(xf86OutputPtr output) 1635{ 1636 RADEONInfoPtr info = RADEONPTR(output->scrn); 1637 drmmode_output_private_ptr drmmode_output = output->driver_private; 1638 drmModeConnectorPtr mode_output = drmmode_output->mode_output; 1639 RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); 1640 drmModePropertyPtr drmmode_prop, tearfree_prop; 1641 int i, j, err; 1642 Atom name; 1643 1644 /* Create CONNECTOR_ID property */ 1645 name = MakeAtom("CONNECTOR_ID", 12, TRUE); 1646 if (name != BAD_RESOURCE) { 1647 INT32 value = mode_output->connector_id; 1648 1649 err = RRConfigureOutputProperty(output->randr_output, name, 1650 FALSE, FALSE, TRUE, 1, &value); 1651 if (err != Success) { 1652 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1653 "RRConfigureOutputProperty error, %d\n", err); 1654 } 1655 1656 err = RRChangeOutputProperty(output->randr_output, name, 1657 XA_INTEGER, 32, PropModeReplace, 1, 1658 &value, FALSE, FALSE); 1659 if (err != Success) { 1660 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1661 "RRChangeOutputProperty error, %d\n", err); 1662 } 1663 } 1664 1665 drmmode_output->props = calloc(mode_output->count_props + 1, sizeof(drmmode_prop_rec)); 1666 if (!drmmode_output->props) 1667 return; 1668 1669 drmmode_output->num_props = 0; 1670 for (i = 0, j = 0; i < mode_output->count_props; i++) { 1671 drmmode_prop = drmModeGetProperty(pRADEONEnt->fd, mode_output->props[i]); 1672 if (drmmode_property_ignore(drmmode_prop)) { 1673 drmModeFreeProperty(drmmode_prop); 1674 continue; 1675 } 1676 drmmode_output->props[j].mode_prop = drmmode_prop; 1677 drmmode_output->props[j].value = mode_output->prop_values[i]; 1678 drmmode_output->num_props++; 1679 j++; 1680 } 1681 1682 /* Userspace-only property for TearFree */ 1683 tearfree_prop = calloc(1, sizeof(*tearfree_prop)); 1684 tearfree_prop->flags = DRM_MODE_PROP_ENUM; 1685 strcpy(tearfree_prop->name, "TearFree"); 1686 tearfree_prop->count_enums = 3; 1687 tearfree_prop->enums = calloc(tearfree_prop->count_enums, 1688 sizeof(*tearfree_prop->enums)); 1689 strcpy(tearfree_prop->enums[0].name, "off"); 1690 strcpy(tearfree_prop->enums[1].name, "on"); 1691 tearfree_prop->enums[1].value = 1; 1692 strcpy(tearfree_prop->enums[2].name, "auto"); 1693 tearfree_prop->enums[2].value = 2; 1694 drmmode_output->props[j].mode_prop = tearfree_prop; 1695 drmmode_output->props[j].value = info->tear_free; 1696 drmmode_output->tear_free = info->tear_free; 1697 drmmode_output->num_props++; 1698 1699 for (i = 0; i < drmmode_output->num_props; i++) { 1700 drmmode_prop_ptr p = &drmmode_output->props[i]; 1701 drmmode_prop = p->mode_prop; 1702 1703 if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) { 1704 INT32 range[2]; 1705 INT32 value = p->value; 1706 1707 p->num_atoms = 1; 1708 p->atoms = calloc(p->num_atoms, sizeof(Atom)); 1709 if (!p->atoms) 1710 continue; 1711 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); 1712 range[0] = drmmode_prop->values[0]; 1713 range[1] = drmmode_prop->values[1]; 1714 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], 1715 FALSE, TRUE, 1716 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, 1717 2, range); 1718 if (err != 0) { 1719 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1720 "RRConfigureOutputProperty error, %d\n", err); 1721 } 1722 err = RRChangeOutputProperty(output->randr_output, p->atoms[0], 1723 XA_INTEGER, 32, PropModeReplace, 1, &value, FALSE, TRUE); 1724 if (err != 0) { 1725 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1726 "RRChangeOutputProperty error, %d\n", err); 1727 } 1728 } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) { 1729 p->num_atoms = drmmode_prop->count_enums + 1; 1730 p->atoms = calloc(p->num_atoms, sizeof(Atom)); 1731 if (!p->atoms) 1732 continue; 1733 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); 1734 for (j = 1; j <= drmmode_prop->count_enums; j++) { 1735 struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1]; 1736 p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE); 1737 } 1738 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], 1739 FALSE, FALSE, 1740 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, 1741 p->num_atoms - 1, (INT32 *)&p->atoms[1]); 1742 if (err != 0) { 1743 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1744 "RRConfigureOutputProperty error, %d\n", err); 1745 } 1746 for (j = 0; j < drmmode_prop->count_enums; j++) 1747 if (drmmode_prop->enums[j].value == p->value) 1748 break; 1749 /* there's always a matching value */ 1750 err = RRChangeOutputProperty(output->randr_output, p->atoms[0], 1751 XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE); 1752 if (err != 0) { 1753 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1754 "RRChangeOutputProperty error, %d\n", err); 1755 } 1756 } 1757 } 1758} 1759 1760static void 1761drmmode_output_set_tear_free(RADEONEntPtr pRADEONEnt, 1762 drmmode_output_private_ptr drmmode_output, 1763 xf86CrtcPtr crtc, int tear_free) 1764{ 1765 if (drmmode_output->tear_free == tear_free) 1766 return; 1767 1768 drmmode_output->tear_free = tear_free; 1769 1770 if (crtc) { 1771 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, 1772 crtc->x, crtc->y); 1773 } 1774} 1775 1776static Bool 1777drmmode_output_set_property(xf86OutputPtr output, Atom property, 1778 RRPropertyValuePtr value) 1779{ 1780 drmmode_output_private_ptr drmmode_output = output->driver_private; 1781 RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); 1782 int i; 1783 1784 for (i = 0; i < drmmode_output->num_props; i++) { 1785 drmmode_prop_ptr p = &drmmode_output->props[i]; 1786 1787 if (p->atoms[0] != property) 1788 continue; 1789 1790 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { 1791 uint32_t val; 1792 1793 if (value->type != XA_INTEGER || value->format != 32 || 1794 value->size != 1) 1795 return FALSE; 1796 val = *(uint32_t *)value->data; 1797 1798 drmModeConnectorSetProperty(pRADEONEnt->fd, drmmode_output->output_id, 1799 p->mode_prop->prop_id, (uint64_t)val); 1800 return TRUE; 1801 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { 1802 Atom atom; 1803 const char *name; 1804 int j; 1805 1806 if (value->type != XA_ATOM || value->format != 32 || value->size != 1) 1807 return FALSE; 1808 memcpy(&atom, value->data, 4); 1809 if (!(name = NameForAtom(atom))) 1810 return FALSE; 1811 1812 /* search for matching name string, then set its value down */ 1813 for (j = 0; j < p->mode_prop->count_enums; j++) { 1814 if (!strcmp(p->mode_prop->enums[j].name, name)) { 1815 if (i == (drmmode_output->num_props - 1)) { 1816 drmmode_output_set_tear_free(pRADEONEnt, drmmode_output, 1817 output->crtc, j); 1818 } else { 1819 drmModeConnectorSetProperty(pRADEONEnt->fd, 1820 drmmode_output->output_id, 1821 p->mode_prop->prop_id, 1822 p->mode_prop->enums[j].value); 1823 } 1824 1825 return TRUE; 1826 } 1827 } 1828 } 1829 } 1830 1831 return TRUE; 1832} 1833 1834static Bool 1835drmmode_output_get_property(xf86OutputPtr output, Atom property) 1836{ 1837 return TRUE; 1838} 1839 1840static const xf86OutputFuncsRec drmmode_output_funcs = { 1841 .dpms = drmmode_output_dpms, 1842 .create_resources = drmmode_output_create_resources, 1843 .set_property = drmmode_output_set_property, 1844 .get_property = drmmode_output_get_property, 1845 .detect = drmmode_output_detect, 1846 .mode_valid = drmmode_output_mode_valid, 1847 1848 .get_modes = drmmode_output_get_modes, 1849 .destroy = drmmode_output_destroy 1850}; 1851 1852static int subpixel_conv_table[7] = { 0, SubPixelUnknown, 1853 SubPixelHorizontalRGB, 1854 SubPixelHorizontalBGR, 1855 SubPixelVerticalRGB, 1856 SubPixelVerticalBGR, 1857 SubPixelNone }; 1858 1859const char *output_names[] = { "None", 1860 "VGA", 1861 "DVI", 1862 "DVI", 1863 "DVI", 1864 "Composite", 1865 "S-video", 1866 "LVDS", 1867 "CTV", 1868 "DIN", 1869 "DisplayPort", 1870 "HDMI", 1871 "HDMI", 1872 "TV", 1873 "eDP" 1874}; 1875 1876#define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0])) 1877 1878static xf86OutputPtr find_output(ScrnInfoPtr pScrn, int id) 1879{ 1880 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1881 int i; 1882 for (i = 0; i < xf86_config->num_output; i++) { 1883 xf86OutputPtr output = xf86_config->output[i]; 1884 drmmode_output_private_ptr drmmode_output; 1885 1886 drmmode_output = output->driver_private; 1887 if (drmmode_output->output_id == id) 1888 return output; 1889 } 1890 return NULL; 1891} 1892 1893static int parse_path_blob(drmModePropertyBlobPtr path_blob, int *conn_base_id, char **path) 1894{ 1895 char *conn; 1896 char conn_id[5]; 1897 int id, len; 1898 char *blob_data; 1899 1900 if (!path_blob) 1901 return -1; 1902 1903 blob_data = path_blob->data; 1904 /* we only handle MST paths for now */ 1905 if (strncmp(blob_data, "mst:", 4)) 1906 return -1; 1907 1908 conn = strchr(blob_data + 4, '-'); 1909 if (!conn) 1910 return -1; 1911 len = conn - (blob_data + 4); 1912 if (len + 1 > 5) 1913 return -1; 1914 memcpy(conn_id, blob_data + 4, len); 1915 conn_id[len] = '\0'; 1916 id = strtoul(conn_id, NULL, 10); 1917 1918 *conn_base_id = id; 1919 1920 *path = conn + 1; 1921 return 0; 1922} 1923 1924static void 1925drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name, 1926 drmModePropertyBlobPtr path_blob, int *num_dvi, int *num_hdmi) 1927{ 1928 xf86OutputPtr output; 1929 int conn_id; 1930 char *extra_path; 1931 1932 output = NULL; 1933 if (parse_path_blob(path_blob, &conn_id, &extra_path) == 0) 1934 output = find_output(pScrn, conn_id); 1935 if (output) { 1936 snprintf(name, 32, "%s-%s", output->name, extra_path); 1937 } else { 1938 if (koutput->connector_type >= NUM_OUTPUT_NAMES) { 1939 snprintf(name, 32, "Unknown%d-%d", koutput->connector_type, 1940 koutput->connector_type_id - 1); 1941 } else if (pScrn->is_gpu) { 1942 snprintf(name, 32, "%s-%d-%d", 1943 output_names[koutput->connector_type], pScrn->scrnIndex - GPU_SCREEN_OFFSET + 1, 1944 koutput->connector_type_id - 1); 1945 } else { 1946 /* need to do smart conversion here for compat with non-kms ATI driver */ 1947 if (koutput->connector_type_id == 1) { 1948 switch(koutput->connector_type) { 1949 case DRM_MODE_CONNECTOR_DVII: 1950 case DRM_MODE_CONNECTOR_DVID: 1951 case DRM_MODE_CONNECTOR_DVIA: 1952 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi); 1953 (*num_dvi)++; 1954 break; 1955 case DRM_MODE_CONNECTOR_HDMIA: 1956 case DRM_MODE_CONNECTOR_HDMIB: 1957 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi); 1958 (*num_hdmi)++; 1959 break; 1960 case DRM_MODE_CONNECTOR_VGA: 1961 case DRM_MODE_CONNECTOR_DisplayPort: 1962 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], 1963 koutput->connector_type_id - 1); 1964 break; 1965 default: 1966 snprintf(name, 32, "%s", output_names[koutput->connector_type]); 1967 break; 1968 } 1969 } else { 1970 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], 1971 koutput->connector_type_id - 1); 1972 } 1973 } 1974 } 1975} 1976 1977static unsigned int 1978drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, int *num_dvi, int *num_hdmi, int dynamic) 1979{ 1980 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1981 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1982 RADEONInfoPtr info = RADEONPTR(pScrn); 1983 xf86OutputPtr output; 1984 drmModeConnectorPtr koutput; 1985 drmModeEncoderPtr *kencoders = NULL; 1986 drmmode_output_private_ptr drmmode_output; 1987 drmModePropertyBlobPtr path_blob = NULL; 1988#if XF86_CRTC_VERSION >= 8 1989 Bool nonDesktop = FALSE; 1990#endif 1991 char name[32]; 1992 int i; 1993 const char *s; 1994 1995 koutput = drmModeGetConnector(pRADEONEnt->fd, mode_res->connectors[num]); 1996 if (!koutput) 1997 return 0; 1998 1999 path_blob = koutput_get_prop_blob(pRADEONEnt->fd, koutput, "PATH"); 2000 2001#if XF86_CRTC_VERSION >= 8 2002 i = koutput_get_prop_idx(pRADEONEnt->fd, koutput, DRM_MODE_PROP_RANGE, 2003 "non-desktop"); 2004 if (i >= 0) 2005 nonDesktop = koutput->prop_values[i] != 0; 2006#endif 2007 2008 kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders); 2009 if (!kencoders) { 2010 goto out_free_encoders; 2011 } 2012 2013 for (i = 0; i < koutput->count_encoders; i++) { 2014 kencoders[i] = drmModeGetEncoder(pRADEONEnt->fd, koutput->encoders[i]); 2015 if (!kencoders[i]) { 2016 goto out_free_encoders; 2017 } 2018 } 2019 2020 drmmode_create_name(pScrn, koutput, name, path_blob, num_dvi, num_hdmi); 2021 if (path_blob) 2022 drmModeFreePropertyBlob(path_blob); 2023 2024 if (path_blob && dynamic) { 2025 /* See if we have an output with this name already 2026 * and hook stuff up. 2027 */ 2028 for (i = 0; i < xf86_config->num_output; i++) { 2029 output = xf86_config->output[i]; 2030 2031 if (strncmp(output->name, name, 32)) 2032 continue; 2033 2034 drmmode_output = output->driver_private; 2035 drmmode_output->output_id = mode_res->connectors[num]; 2036 drmmode_output->mode_output = koutput; 2037#if XF86_CRTC_VERSION >= 8 2038 output->non_desktop = nonDesktop; 2039#endif 2040 for (i = 0; i < koutput->count_encoders; i++) 2041 drmModeFreeEncoder(kencoders[i]); 2042 free(kencoders); 2043 return 0; 2044 } 2045 } 2046 2047 if (xf86IsEntityShared(pScrn->entityList[0])) { 2048 if ((s = xf86GetOptValString(info->Options, OPTION_ZAPHOD_HEADS))) { 2049 if (!RADEONZaphodStringMatches(pScrn, s, name)) 2050 goto out_free_encoders; 2051 } else { 2052 if (!info->IsSecondary && (num != 0)) 2053 goto out_free_encoders; 2054 else if (info->IsSecondary && (num != 1)) 2055 goto out_free_encoders; 2056 } 2057 } 2058 2059 output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name); 2060 if (!output) { 2061 goto out_free_encoders; 2062 } 2063 2064 drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1); 2065 if (!drmmode_output) { 2066 xf86OutputDestroy(output); 2067 goto out_free_encoders; 2068 } 2069 2070 drmmode_output->output_id = mode_res->connectors[num]; 2071 drmmode_output->mode_output = koutput; 2072 drmmode_output->mode_encoders = kencoders; 2073 drmmode_output->drmmode = drmmode; 2074 output->mm_width = koutput->mmWidth; 2075 output->mm_height = koutput->mmHeight; 2076 2077 output->subpixel_order = subpixel_conv_table[koutput->subpixel]; 2078 output->interlaceAllowed = TRUE; 2079 output->doubleScanAllowed = TRUE; 2080 output->driver_private = drmmode_output; 2081#if XF86_CRTC_VERSION >= 8 2082 output->non_desktop = nonDesktop; 2083#endif 2084 2085 output->possible_crtcs = 0xffffffff; 2086 for (i = 0; i < koutput->count_encoders; i++) { 2087 output->possible_crtcs &= kencoders[i]->possible_crtcs; 2088 } 2089 /* work out the possible clones later */ 2090 output->possible_clones = 0; 2091 2092 drmmode_output->dpms_enum_id = 2093 koutput_get_prop_id(pRADEONEnt->fd, koutput, DRM_MODE_PROP_ENUM, 2094 "DPMS"); 2095 2096 if (dynamic) { 2097 output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output); 2098 drmmode_output_create_resources(output); 2099 } 2100 2101 return 1; 2102out_free_encoders: 2103 if (kencoders){ 2104 for (i = 0; i < koutput->count_encoders; i++) 2105 drmModeFreeEncoder(kencoders[i]); 2106 free(kencoders); 2107 } 2108 drmModeFreeConnector(koutput); 2109 return 0; 2110} 2111 2112uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output) 2113{ 2114 drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout; 2115 int i; 2116 xf86OutputPtr clone_output; 2117 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 2118 int index_mask = 0; 2119 2120 if (drmmode_output->enc_clone_mask == 0) 2121 return index_mask; 2122 2123 for (i = 0; i < xf86_config->num_output; i++) { 2124 clone_output = xf86_config->output[i]; 2125 clone_drmout = clone_output->driver_private; 2126 if (output == clone_output) 2127 continue; 2128 2129 if (clone_drmout->enc_mask == 0) 2130 continue; 2131 if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask) 2132 index_mask |= (1 << i); 2133 } 2134 return index_mask; 2135} 2136 2137 2138static void 2139drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, drmModeResPtr mode_res) 2140{ 2141 int i, j; 2142 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 2143 2144 for (i = 0; i < xf86_config->num_output; i++) { 2145 xf86OutputPtr output = xf86_config->output[i]; 2146 drmmode_output_private_ptr drmmode_output; 2147 2148 drmmode_output = output->driver_private; 2149 drmmode_output->enc_clone_mask = 0xff; 2150 /* and all the possible encoder clones for this output together */ 2151 for (j = 0; j < drmmode_output->mode_output->count_encoders; j++) 2152 { 2153 int k; 2154 for (k = 0; k < mode_res->count_encoders; k++) { 2155 if (mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id) 2156 drmmode_output->enc_mask |= (1 << k); 2157 } 2158 2159 drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones; 2160 } 2161 } 2162 2163 for (i = 0; i < xf86_config->num_output; i++) { 2164 xf86OutputPtr output = xf86_config->output[i]; 2165 output->possible_clones = find_clones(scrn, output); 2166 } 2167} 2168 2169/* returns height alignment in pixels */ 2170int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling) 2171{ 2172 RADEONInfoPtr info = RADEONPTR(scrn); 2173 int height_align = 1; 2174 2175 if (info->ChipFamily >= CHIP_FAMILY_R600) { 2176 if (tiling & RADEON_TILING_MACRO) 2177 height_align = info->num_channels * 8; 2178 else if (tiling & RADEON_TILING_MICRO) 2179 height_align = 8; 2180 else 2181 height_align = 8; 2182 } else { 2183 if (tiling & RADEON_TILING_MICRO_SQUARE) 2184 height_align = 32; 2185 else if (tiling) 2186 height_align = 16; 2187 else 2188 height_align = 1; 2189 } 2190 return height_align; 2191} 2192 2193/* returns pitch alignment in pixels */ 2194int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling) 2195{ 2196 RADEONInfoPtr info = RADEONPTR(scrn); 2197 int pitch_align = 1; 2198 2199 if (info->ChipFamily >= CHIP_FAMILY_R600) { 2200 if (tiling & RADEON_TILING_MACRO) { 2201 /* general surface requirements */ 2202 pitch_align = MAX(info->num_banks, 2203 (((info->group_bytes / 8) / bpe) * info->num_banks)) * 8; 2204 /* further restrictions for scanout */ 2205 pitch_align = MAX(info->num_banks * 8, pitch_align); 2206 } else if (tiling & RADEON_TILING_MICRO) { 2207 /* general surface requirements */ 2208 pitch_align = MAX(8, (info->group_bytes / (8 * bpe))); 2209 /* further restrictions for scanout */ 2210 pitch_align = MAX(info->group_bytes / bpe, pitch_align); 2211 } else { 2212 if (info->have_tiling_info) 2213 /* linear aligned requirements */ 2214 pitch_align = MAX(64, info->group_bytes / bpe); 2215 else 2216 /* default to 512 elements if we don't know the real 2217 * group size otherwise the kernel may reject the CS 2218 * if the group sizes don't match as the pitch won't 2219 * be aligned properly. 2220 */ 2221 pitch_align = 512; 2222 } 2223 } else { 2224 /* general surface requirements */ 2225 if (tiling) 2226 pitch_align = 256 / bpe; 2227 else 2228 pitch_align = 64; 2229 } 2230 return pitch_align; 2231} 2232 2233/* returns base alignment in bytes */ 2234int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling) 2235{ 2236 RADEONInfoPtr info = RADEONPTR(scrn); 2237 int pixel_align = drmmode_get_pitch_align(scrn, bpe, tiling); 2238 int height_align = drmmode_get_height_align(scrn, tiling); 2239 int base_align = RADEON_GPU_PAGE_SIZE; 2240 2241 if (info->ChipFamily >= CHIP_FAMILY_R600) { 2242 if (tiling & RADEON_TILING_MACRO) 2243 base_align = MAX(info->num_banks * info->num_channels * 8 * 8 * bpe, 2244 pixel_align * bpe * height_align); 2245 else { 2246 if (info->have_tiling_info) 2247 base_align = info->group_bytes; 2248 else 2249 /* default to 512 if we don't know the real 2250 * group size otherwise the kernel may reject the CS 2251 * if the group sizes don't match as the base won't 2252 * be aligned properly. 2253 */ 2254 base_align = 512; 2255 } 2256 } 2257 return base_align; 2258} 2259 2260static Bool 2261drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) 2262{ 2263 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 2264 RADEONInfoPtr info = RADEONPTR(scrn); 2265 struct radeon_buffer *old_front = NULL; 2266 ScreenPtr screen = xf86ScrnToScreen(scrn); 2267 int i, pitch, old_width, old_height, old_pitch; 2268 int usage = CREATE_PIXMAP_USAGE_BACKING_PIXMAP; 2269 int cpp = info->pixel_bytes; 2270 uint32_t tiling_flags; 2271 PixmapPtr ppix = screen->GetScreenPixmap(screen); 2272 void *fb_shadow; 2273 2274 if (scrn->virtualX == width && scrn->virtualY == height) 2275 return TRUE; 2276 2277 if (width > xf86_config->maxWidth || height > xf86_config->maxHeight) { 2278 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 2279 "Xorg tried resizing screen to %dx%d, but maximum " 2280 "supported is %dx%d\n", width, height, 2281 xf86_config->maxWidth, xf86_config->maxHeight); 2282 return FALSE; 2283 } 2284 2285 if (info->allowColorTiling && !info->shadow_primary) { 2286 if (info->ChipFamily < CHIP_FAMILY_R600 || info->allowColorTiling2D) 2287 usage |= RADEON_CREATE_PIXMAP_TILING_MACRO; 2288 else 2289 usage |= RADEON_CREATE_PIXMAP_TILING_MICRO; 2290 } 2291 2292 xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocate new frame buffer %dx%d\n", 2293 width, height); 2294 2295 old_width = scrn->virtualX; 2296 old_height = scrn->virtualY; 2297 old_pitch = scrn->displayWidth; 2298 old_front = info->front_buffer; 2299 2300 scrn->virtualX = width; 2301 scrn->virtualY = height; 2302 2303 info->front_buffer = radeon_alloc_pixmap_bo(scrn, scrn->virtualX, 2304 scrn->virtualY, scrn->depth, 2305 usage, scrn->bitsPerPixel, 2306 &pitch, 2307 &info->front_surface, 2308 &tiling_flags); 2309 if (!info->front_buffer) 2310 goto fail; 2311 2312 scrn->displayWidth = pitch / cpp; 2313 2314 if (!info->use_glamor) { 2315#if X_BYTE_ORDER == X_BIG_ENDIAN 2316 switch (cpp) { 2317 case 4: 2318 tiling_flags |= RADEON_TILING_SWAP_32BIT; 2319 break; 2320 case 2: 2321 tiling_flags |= RADEON_TILING_SWAP_16BIT; 2322 break; 2323 } 2324 if (info->ChipFamily < CHIP_FAMILY_R600 && 2325 info->r600_shadow_fb && tiling_flags) 2326 tiling_flags |= RADEON_TILING_SURFACE; 2327#endif 2328 if (tiling_flags) 2329 radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch); 2330 } 2331 2332 if (!info->r600_shadow_fb) { 2333 if (info->surf_man && !info->use_glamor) 2334 *radeon_get_pixmap_surface(ppix) = info->front_surface; 2335 screen->ModifyPixmapHeader(ppix, 2336 width, height, -1, -1, pitch, NULL); 2337 } else { 2338 if (radeon_bo_map(info->front_buffer->bo.radeon, 1)) 2339 goto fail; 2340 fb_shadow = calloc(1, pitch * scrn->virtualY); 2341 if (!fb_shadow) 2342 goto fail; 2343 free(info->fb_shadow); 2344 info->fb_shadow = fb_shadow; 2345 screen->ModifyPixmapHeader(ppix, 2346 width, height, -1, -1, pitch, 2347 info->fb_shadow); 2348 } 2349 2350 if (info->use_glamor) 2351 radeon_glamor_create_screen_resources(scrn->pScreen); 2352 2353 if (!info->r600_shadow_fb) { 2354 if (!radeon_set_pixmap_bo(ppix, info->front_buffer)) 2355 goto fail; 2356 } 2357 2358 radeon_pixmap_clear(ppix); 2359 radeon_finish(scrn, info->front_buffer); 2360 2361 for (i = 0; i < xf86_config->num_crtc; i++) { 2362 xf86CrtcPtr crtc = xf86_config->crtc[i]; 2363 2364 if (!crtc->enabled) 2365 continue; 2366 2367 drmmode_set_mode_major(crtc, &crtc->mode, 2368 crtc->rotation, crtc->x, crtc->y); 2369 } 2370 2371 radeon_buffer_unref(&old_front); 2372 2373 radeon_kms_update_vram_limit(scrn, pitch * scrn->virtualY); 2374 return TRUE; 2375 2376 fail: 2377 radeon_buffer_unref(&info->front_buffer); 2378 info->front_buffer = old_front; 2379 scrn->virtualX = old_width; 2380 scrn->virtualY = old_height; 2381 scrn->displayWidth = old_pitch; 2382 2383 return FALSE; 2384} 2385 2386static void 2387drmmode_validate_leases(ScrnInfoPtr scrn) 2388{ 2389#ifdef XF86_LEASE_VERSION 2390 ScreenPtr screen = scrn->pScreen; 2391 rrScrPrivPtr scr_priv = rrGetScrPriv(screen); 2392 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 2393 drmModeLesseeListPtr lessees; 2394 RRLeasePtr lease, next; 2395 int l; 2396 2397 /* We can't talk to the kernel about leases when VT switched */ 2398 if (!scrn->vtSema) 2399 return; 2400 2401 lessees = drmModeListLessees(pRADEONEnt->fd); 2402 if (!lessees) 2403 return; 2404 2405 xorg_list_for_each_entry_safe(lease, next, &scr_priv->leases, list) { 2406 drmmode_lease_private_ptr lease_private = lease->devPrivate; 2407 2408 for (l = 0; l < lessees->count; l++) { 2409 if (lessees->lessees[l] == lease_private->lessee_id) 2410 break; 2411 } 2412 2413 /* check to see if the lease has gone away */ 2414 if (l == lessees->count) { 2415 free(lease_private); 2416 lease->devPrivate = NULL; 2417 xf86CrtcLeaseTerminated(lease); 2418 } 2419 } 2420 2421 free(lessees); 2422#endif 2423} 2424 2425#ifdef XF86_LEASE_VERSION 2426 2427static int 2428drmmode_create_lease(RRLeasePtr lease, int *fd) 2429{ 2430 ScreenPtr screen = lease->screen; 2431 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 2432 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 2433 drmmode_lease_private_ptr lease_private; 2434 int noutput = lease->numOutputs; 2435 int ncrtc = lease->numCrtcs; 2436 uint32_t *objects; 2437 size_t nobjects; 2438 int lease_fd; 2439 int c, o; 2440 int i; 2441 2442 nobjects = ncrtc + noutput; 2443 if (nobjects == 0 || nobjects > (SIZE_MAX / 4) || 2444 ncrtc > (SIZE_MAX - noutput)) 2445 return BadValue; 2446 2447 lease_private = calloc(1, sizeof (drmmode_lease_private_rec)); 2448 if (!lease_private) 2449 return BadAlloc; 2450 2451 objects = malloc(nobjects * 4); 2452 if (!objects) { 2453 free(lease_private); 2454 return BadAlloc; 2455 } 2456 2457 i = 0; 2458 2459 /* Add CRTC ids */ 2460 for (c = 0; c < ncrtc; c++) { 2461 xf86CrtcPtr crtc = lease->crtcs[c]->devPrivate; 2462 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 2463 2464 objects[i++] = drmmode_crtc->mode_crtc->crtc_id; 2465 } 2466 2467 /* Add connector ids */ 2468 for (o = 0; o < noutput; o++) { 2469 xf86OutputPtr output = lease->outputs[o]->devPrivate; 2470 drmmode_output_private_ptr drmmode_output = output->driver_private; 2471 2472 objects[i++] = drmmode_output->mode_output->connector_id; 2473 } 2474 2475 /* call kernel to create lease */ 2476 assert (i == nobjects); 2477 2478 lease_fd = drmModeCreateLease(pRADEONEnt->fd, objects, nobjects, 0, 2479 &lease_private->lessee_id); 2480 2481 free(objects); 2482 2483 if (lease_fd < 0) { 2484 free(lease_private); 2485 return BadMatch; 2486 } 2487 2488 lease->devPrivate = lease_private; 2489 2490 xf86CrtcLeaseStarted(lease); 2491 2492 *fd = lease_fd; 2493 return Success; 2494} 2495 2496static void 2497drmmode_terminate_lease(RRLeasePtr lease) 2498{ 2499 drmmode_lease_private_ptr lease_private = lease->devPrivate; 2500 ScreenPtr screen = lease->screen; 2501 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 2502 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 2503 2504 if (drmModeRevokeLease(pRADEONEnt->fd, lease_private->lessee_id) == 0) { 2505 free(lease_private); 2506 lease->devPrivate = NULL; 2507 xf86CrtcLeaseTerminated(lease); 2508 } 2509} 2510 2511#endif // XF86_LEASE_VERSION 2512 2513static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { 2514 .resize = drmmode_xf86crtc_resize, 2515#ifdef XF86_LEASE_VERSION 2516 .create_lease = drmmode_create_lease, 2517 .terminate_lease = drmmode_terminate_lease 2518#endif 2519}; 2520 2521static void 2522drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data) 2523{ 2524 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 2525 RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 2526 drmmode_flipdata_ptr flipdata = event_data; 2527 int crtc_id = drmmode_get_crtc_id(crtc); 2528 struct drmmode_fb **fb = &flipdata->fb[crtc_id]; 2529 2530 if (drmmode_crtc->flip_pending == *fb) { 2531 drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, 2532 NULL); 2533 } 2534 drmmode_fb_reference(pRADEONEnt->fd, fb, NULL); 2535 2536 if (--flipdata->flip_count == 0) { 2537 if (!flipdata->fe_crtc) 2538 flipdata->fe_crtc = crtc; 2539 flipdata->abort(flipdata->fe_crtc, flipdata->event_data); 2540 free(flipdata); 2541 } 2542} 2543 2544static void 2545drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *event_data) 2546{ 2547 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 2548 RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); 2549 drmmode_flipdata_ptr flipdata = event_data; 2550 int crtc_id = drmmode_get_crtc_id(crtc); 2551 struct drmmode_fb **fb = &flipdata->fb[crtc_id]; 2552 2553 /* Is this the event whose info shall be delivered to higher level? */ 2554 if (crtc == flipdata->fe_crtc) { 2555 /* Yes: Cache msc, ust for later delivery. */ 2556 flipdata->fe_frame = frame; 2557 flipdata->fe_usec = usec; 2558 } 2559 2560 if (drmmode_crtc->flip_pending == *fb) { 2561 drmmode_fb_reference(pRADEONEnt->fd, 2562 &drmmode_crtc->flip_pending, NULL); 2563 } 2564 drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, *fb); 2565 drmmode_fb_reference(pRADEONEnt->fd, fb, NULL); 2566 2567 if (--flipdata->flip_count == 0) { 2568 /* Deliver MSC & UST from reference/current CRTC to flip event 2569 * handler 2570 */ 2571 if (flipdata->fe_crtc) 2572 flipdata->handler(flipdata->fe_crtc, flipdata->fe_frame, 2573 flipdata->fe_usec, flipdata->event_data); 2574 else 2575 flipdata->handler(crtc, frame, usec, flipdata->event_data); 2576 2577 free(flipdata); 2578 } 2579} 2580 2581 2582#if HAVE_NOTIFY_FD 2583static void 2584drm_notify_fd(int fd, int ready, void *data) 2585#else 2586static void 2587drm_wakeup_handler(pointer data, int err, pointer p) 2588#endif 2589{ 2590 drmmode_ptr drmmode = data; 2591 RADEONEntPtr pRADEONEnt = RADEONEntPriv(drmmode->scrn); 2592 2593#if !HAVE_NOTIFY_FD 2594 fd_set *read_mask = p; 2595 2596 if (err >= 0 && FD_ISSET(pRADEONEnt->fd, read_mask)) 2597#endif 2598 { 2599 radeon_drm_handle_event(pRADEONEnt->fd, &drmmode->event_context); 2600 } 2601} 2602 2603static Bool drmmode_probe_page_flip_target(RADEONEntPtr pRADEONEnt) 2604{ 2605#ifdef DRM_CAP_PAGE_FLIP_TARGET 2606 uint64_t cap_value; 2607 2608 return drmGetCap(pRADEONEnt->fd, DRM_CAP_PAGE_FLIP_TARGET, 2609 &cap_value) == 0 && cap_value != 0; 2610#else 2611 return FALSE; 2612#endif 2613} 2614 2615static int 2616drmmode_page_flip(RADEONEntPtr pRADEONEnt, 2617 drmmode_crtc_private_ptr drmmode_crtc, int fb_id, 2618 uint32_t flags, uintptr_t drm_queue_seq) 2619{ 2620 flags |= DRM_MODE_PAGE_FLIP_EVENT; 2621 return drmModePageFlip(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 2622 fb_id, flags, (void*)drm_queue_seq); 2623} 2624 2625int 2626drmmode_page_flip_target_absolute(RADEONEntPtr pRADEONEnt, 2627 drmmode_crtc_private_ptr drmmode_crtc, 2628 int fb_id, uint32_t flags, 2629 uintptr_t drm_queue_seq, uint32_t target_msc) 2630{ 2631#ifdef DRM_MODE_PAGE_FLIP_TARGET 2632 if (pRADEONEnt->has_page_flip_target) { 2633 flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE; 2634 return drmModePageFlipTarget(pRADEONEnt->fd, 2635 drmmode_crtc->mode_crtc->crtc_id, 2636 fb_id, flags, (void*)drm_queue_seq, 2637 target_msc); 2638 } 2639#endif 2640 2641 return drmmode_page_flip(pRADEONEnt, drmmode_crtc, fb_id, flags, 2642 drm_queue_seq); 2643} 2644 2645int 2646drmmode_page_flip_target_relative(RADEONEntPtr pRADEONEnt, 2647 drmmode_crtc_private_ptr drmmode_crtc, 2648 int fb_id, uint32_t flags, 2649 uintptr_t drm_queue_seq, uint32_t target_msc) 2650{ 2651#ifdef DRM_MODE_PAGE_FLIP_TARGET 2652 if (pRADEONEnt->has_page_flip_target) { 2653 flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_PAGE_FLIP_TARGET_RELATIVE; 2654 return drmModePageFlipTarget(pRADEONEnt->fd, 2655 drmmode_crtc->mode_crtc->crtc_id, 2656 fb_id, flags, (void*)drm_queue_seq, 2657 target_msc); 2658 } 2659#endif 2660 2661 return drmmode_page_flip(pRADEONEnt, drmmode_crtc, fb_id, flags, 2662 drm_queue_seq); 2663} 2664 2665Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) 2666{ 2667 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2668 RADEONInfoPtr info = RADEONPTR(pScrn); 2669 int i, num_dvi = 0, num_hdmi = 0; 2670 drmModeResPtr mode_res; 2671 unsigned int crtcs_needed = 0; 2672 char *bus_id_string, *provider_name; 2673 2674 xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); 2675 2676 drmmode->scrn = pScrn; 2677 mode_res = drmModeGetResources(pRADEONEnt->fd); 2678 if (!mode_res) 2679 return FALSE; 2680 2681 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 2682 "Initializing outputs ...\n"); 2683 for (i = 0; i < mode_res->count_connectors; i++) 2684 crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res, 2685 i, &num_dvi, &num_hdmi, 0); 2686 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 2687 "%d crtcs needed for screen.\n", crtcs_needed); 2688 2689 /* Need per-screen drmmode_crtc_funcs, based on our global template, 2690 * so we can disable some functions, depending on screen settings. 2691 */ 2692 info->drmmode_crtc_funcs = drmmode_crtc_funcs; 2693 2694 if (info->r600_shadow_fb) { 2695 /* Rotation requires hardware acceleration */ 2696 info->drmmode_crtc_funcs.shadow_allocate = NULL; 2697 info->drmmode_crtc_funcs.shadow_create = NULL; 2698 info->drmmode_crtc_funcs.shadow_destroy = NULL; 2699 } 2700 2701 /* Hw gamma lut's are currently bypassed by the hw at color depth 30, 2702 * so spare the server the effort to compute and update the cluts. 2703 */ 2704 if (pScrn->depth == 30) 2705 info->drmmode_crtc_funcs.gamma_set = NULL; 2706 2707 drmmode->count_crtcs = mode_res->count_crtcs; 2708 xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width, mode_res->max_height); 2709 2710 for (i = 0; i < mode_res->count_crtcs; i++) 2711 if (!xf86IsEntityShared(pScrn->entityList[0]) || 2712 (crtcs_needed && !(pRADEONEnt->assigned_crtcs & (1 << i)))) 2713 crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i); 2714 2715 /* All ZaphodHeads outputs provided with matching crtcs? */ 2716 if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0)) 2717 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2718 "%d ZaphodHeads crtcs unavailable. Some outputs will stay off.\n", 2719 crtcs_needed); 2720 2721 /* workout clones */ 2722 drmmode_clones_init(pScrn, drmmode, mode_res); 2723 2724 bus_id_string = DRICreatePCIBusID(info->PciInfo); 2725 XNFasprintf(&provider_name, "%s @ %s", pScrn->chipset, bus_id_string); 2726 free(bus_id_string); 2727 xf86ProviderSetup(pScrn, NULL, provider_name); 2728 free(provider_name); 2729 2730 xf86InitialConfiguration(pScrn, TRUE); 2731 2732 pRADEONEnt->has_page_flip_target = drmmode_probe_page_flip_target(pRADEONEnt); 2733 2734 drmModeFreeResources(mode_res); 2735 return TRUE; 2736} 2737 2738void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 2739{ 2740 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2741 RADEONInfoPtr info = RADEONPTR(pScrn); 2742 2743 if (info->dri2.pKernelDRMVersion->version_minor < 4) 2744 return; 2745 2746 info->drmmode_inited = TRUE; 2747 if (pRADEONEnt->fd_wakeup_registered != serverGeneration) { 2748#if HAVE_NOTIFY_FD 2749 SetNotifyFd(pRADEONEnt->fd, drm_notify_fd, X_NOTIFY_READ, 2750 &info->drmmode); 2751#else 2752 AddGeneralSocket(pRADEONEnt->fd); 2753 RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, 2754 drm_wakeup_handler, 2755 &info->drmmode); 2756#endif 2757 pRADEONEnt->fd_wakeup_registered = serverGeneration; 2758 pRADEONEnt->fd_wakeup_ref = 1; 2759 } else 2760 pRADEONEnt->fd_wakeup_ref++; 2761} 2762 2763void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 2764{ 2765 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 2766 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2767 RADEONInfoPtr info = RADEONPTR(pScrn); 2768 int c; 2769 2770 if (info->dri2.pKernelDRMVersion->version_minor < 4 || !info->drmmode_inited) 2771 return; 2772 2773 if (pRADEONEnt->fd_wakeup_registered == serverGeneration && 2774 !--pRADEONEnt->fd_wakeup_ref) { 2775#if HAVE_NOTIFY_FD 2776 RemoveNotifyFd(pRADEONEnt->fd); 2777#else 2778 RemoveGeneralSocket(pRADEONEnt->fd); 2779 RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, 2780 drm_wakeup_handler, pScrn); 2781#endif 2782 } 2783 2784 for (c = 0; c < config->num_crtc; c++) 2785 drmmode_crtc_scanout_free(config->crtc[c]->driver_private); 2786} 2787 2788 2789Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr) 2790{ 2791 drmmode->bufmgr = bufmgr; 2792 return TRUE; 2793} 2794 2795 2796static void drmmode_sprite_do_set_cursor(struct radeon_device_priv *device_priv, 2797 ScrnInfoPtr scrn, int x, int y) 2798{ 2799 RADEONInfoPtr info = RADEONPTR(scrn); 2800 CursorPtr cursor = device_priv->cursor; 2801 Bool sprite_visible = device_priv->sprite_visible; 2802 2803 if (cursor) { 2804 x -= cursor->bits->xhot; 2805 y -= cursor->bits->yhot; 2806 2807 device_priv->sprite_visible = 2808 x < scrn->virtualX && y < scrn->virtualY && 2809 (x + cursor->bits->width > 0) && 2810 (y + cursor->bits->height > 0); 2811 } else { 2812 device_priv->sprite_visible = FALSE; 2813 } 2814 2815 info->sprites_visible += device_priv->sprite_visible - sprite_visible; 2816} 2817 2818static void drmmode_sprite_set_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, 2819 CursorPtr pCursor, int x, int y) 2820{ 2821 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 2822 RADEONInfoPtr info = RADEONPTR(scrn); 2823 struct radeon_device_priv *device_priv = 2824 dixLookupScreenPrivate(&pDev->devPrivates, 2825 &radeon_device_private_key, pScreen); 2826 2827 device_priv->cursor = pCursor; 2828 drmmode_sprite_do_set_cursor(device_priv, scrn, x, y); 2829 2830 info->SpriteFuncs->SetCursor(pDev, pScreen, pCursor, x, y); 2831} 2832 2833static void drmmode_sprite_move_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, 2834 int x, int y) 2835{ 2836 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 2837 RADEONInfoPtr info = RADEONPTR(scrn); 2838 struct radeon_device_priv *device_priv = 2839 dixLookupScreenPrivate(&pDev->devPrivates, 2840 &radeon_device_private_key, pScreen); 2841 2842 drmmode_sprite_do_set_cursor(device_priv, scrn, x, y); 2843 2844 info->SpriteFuncs->MoveCursor(pDev, pScreen, x, y); 2845} 2846 2847static Bool drmmode_sprite_realize_realize_cursor(DeviceIntPtr pDev, 2848 ScreenPtr pScreen, 2849 CursorPtr pCursor) 2850{ 2851 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 2852 RADEONInfoPtr info = RADEONPTR(scrn); 2853 2854 return info->SpriteFuncs->RealizeCursor(pDev, pScreen, pCursor); 2855} 2856 2857static Bool drmmode_sprite_realize_unrealize_cursor(DeviceIntPtr pDev, 2858 ScreenPtr pScreen, 2859 CursorPtr pCursor) 2860{ 2861 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 2862 RADEONInfoPtr info = RADEONPTR(scrn); 2863 2864 return info->SpriteFuncs->UnrealizeCursor(pDev, pScreen, pCursor); 2865} 2866 2867static Bool drmmode_sprite_device_cursor_initialize(DeviceIntPtr pDev, 2868 ScreenPtr pScreen) 2869{ 2870 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 2871 RADEONInfoPtr info = RADEONPTR(scrn); 2872 2873 return info->SpriteFuncs->DeviceCursorInitialize(pDev, pScreen); 2874} 2875 2876static void drmmode_sprite_device_cursor_cleanup(DeviceIntPtr pDev, 2877 ScreenPtr pScreen) 2878{ 2879 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 2880 RADEONInfoPtr info = RADEONPTR(scrn); 2881 2882 info->SpriteFuncs->DeviceCursorCleanup(pDev, pScreen); 2883} 2884 2885miPointerSpriteFuncRec drmmode_sprite_funcs = { 2886 .RealizeCursor = drmmode_sprite_realize_realize_cursor, 2887 .UnrealizeCursor = drmmode_sprite_realize_unrealize_cursor, 2888 .SetCursor = drmmode_sprite_set_cursor, 2889 .MoveCursor = drmmode_sprite_move_cursor, 2890 .DeviceCursorInitialize = drmmode_sprite_device_cursor_initialize, 2891 .DeviceCursorCleanup = drmmode_sprite_device_cursor_cleanup, 2892}; 2893 2894 2895void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo) 2896{ 2897 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 2898 xf86CrtcPtr crtc = xf86_config->crtc[id]; 2899 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 2900 2901 drmmode_crtc->cursor_bo = bo; 2902} 2903 2904void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y) 2905{ 2906 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 2907 xf86OutputPtr output = config->output[config->compat_output]; 2908 xf86CrtcPtr crtc = output->crtc; 2909 2910 if (crtc && crtc->enabled) { 2911 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, 2912 x, y); 2913 } 2914} 2915 2916Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, 2917 Bool set_hw) 2918{ 2919 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 2920 unsigned num_desired = 0, num_on = 0; 2921 int c; 2922 2923 /* First, disable all unused CRTCs */ 2924 if (set_hw) { 2925 for (c = 0; c < config->num_crtc; c++) { 2926 xf86CrtcPtr crtc = config->crtc[c]; 2927 2928 /* Skip disabled CRTCs */ 2929 if (crtc->enabled) 2930 continue; 2931 2932 drmmode_crtc_dpms(crtc, DPMSModeOff); 2933 } 2934 } 2935 2936 /* Then, try setting the chosen mode on each CRTC */ 2937 for (c = 0; c < config->num_crtc; c++) { 2938 xf86CrtcPtr crtc = config->crtc[c]; 2939 xf86OutputPtr output = NULL; 2940 int o; 2941 2942 if (!crtc->enabled) 2943 continue; 2944 2945 if (config->output[config->compat_output]->crtc == crtc) 2946 output = config->output[config->compat_output]; 2947 else 2948 { 2949 for (o = 0; o < config->num_output; o++) 2950 if (config->output[o]->crtc == crtc) 2951 { 2952 output = config->output[o]; 2953 break; 2954 } 2955 } 2956 /* paranoia */ 2957 if (!output) 2958 continue; 2959 2960 num_desired++; 2961 2962 /* Mark that we'll need to re-set the mode for sure */ 2963 memset(&crtc->mode, 0, sizeof(crtc->mode)); 2964 if (!crtc->desiredMode.CrtcHDisplay) 2965 { 2966 DisplayModePtr mode = xf86OutputFindClosestMode (output, pScrn->currentMode); 2967 2968 if (!mode) { 2969 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2970 "Failed to find mode for CRTC %d\n", c); 2971 continue; 2972 } 2973 crtc->desiredMode = *mode; 2974 crtc->desiredRotation = RR_Rotate_0; 2975 crtc->desiredX = 0; 2976 crtc->desiredY = 0; 2977 } 2978 2979 if (set_hw) { 2980 if (crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, 2981 crtc->desiredRotation, 2982 crtc->desiredX, 2983 crtc->desiredY)) { 2984 num_on++; 2985 } else { 2986 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2987 "Failed to set mode on CRTC %d\n", c); 2988 RRCrtcSet(crtc->randr_crtc, NULL, crtc->x, crtc->y, 2989 crtc->rotation, 0, NULL); 2990 } 2991 } else { 2992 crtc->mode = crtc->desiredMode; 2993 crtc->rotation = crtc->desiredRotation; 2994 crtc->x = crtc->desiredX; 2995 crtc->y = crtc->desiredY; 2996 if (drmmode_handle_transform(crtc)) 2997 num_on++; 2998 } 2999 } 3000 3001 if (num_on == 0 && num_desired > 0) { 3002 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to enable any CRTC\n"); 3003 return FALSE; 3004 } 3005 3006 /* Validate leases on VT re-entry */ 3007 drmmode_validate_leases(pScrn); 3008 3009 return TRUE; 3010} 3011 3012Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn) 3013{ 3014 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 3015 int i; 3016 3017 if (xf86_config->num_crtc) { 3018 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 3019 "Initializing kms color map\n"); 3020 if (!miCreateDefColormap(pScreen)) 3021 return FALSE; 3022 3023 /* All radeons support 10 bit CLUTs. They get bypassed at depth 30. */ 3024 if (pScrn->depth != 30) { 3025 if (!xf86HandleColormaps(pScreen, 256, 10, NULL, NULL, 3026 CMAP_PALETTED_TRUECOLOR 3027 | CMAP_RELOAD_ON_MODE_SWITCH)) 3028 return FALSE; 3029 3030 for (i = 0; i < xf86_config->num_crtc; i++) { 3031 xf86CrtcPtr crtc = xf86_config->crtc[i]; 3032 3033 drmmode_crtc_gamma_do_set(crtc, crtc->gamma_red, 3034 crtc->gamma_green, 3035 crtc->gamma_blue, 3036 crtc->gamma_size); 3037 } 3038 } 3039 } 3040 3041 return TRUE; 3042} 3043 3044static Bool 3045drmmode_find_output(ScrnInfoPtr scrn, int output_id, int *num_dvi, 3046 int *num_hdmi) 3047{ 3048 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 3049 int i; 3050 3051 for (i = 0; i < config->num_output; i++) { 3052 xf86OutputPtr output = config->output[i]; 3053 drmmode_output_private_ptr drmmode_output = output->driver_private; 3054 3055 if (drmmode_output->output_id == output_id) { 3056 switch(drmmode_output->mode_output->connector_type) { 3057 case DRM_MODE_CONNECTOR_DVII: 3058 case DRM_MODE_CONNECTOR_DVID: 3059 case DRM_MODE_CONNECTOR_DVIA: 3060 (*num_dvi)++; 3061 break; 3062 case DRM_MODE_CONNECTOR_HDMIA: 3063 case DRM_MODE_CONNECTOR_HDMIB: 3064 (*num_hdmi)++; 3065 break; 3066 } 3067 3068 return TRUE; 3069 } 3070 } 3071 3072 return FALSE; 3073} 3074 3075void 3076radeon_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode) 3077{ 3078 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 3079 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 3080 drmModeResPtr mode_res; 3081 int i, j; 3082 Bool found; 3083 Bool changed = FALSE; 3084 int num_dvi = 0, num_hdmi = 0; 3085 3086 /* Try to re-set the mode on all the connectors with a BAD link-state: 3087 * This may happen if a link degrades and a new modeset is necessary, using 3088 * different link-training parameters. If the kernel found that the current 3089 * mode is not achievable anymore, it should have pruned the mode before 3090 * sending the hotplug event. Try to re-set the currently-set mode to keep 3091 * the display alive, this will fail if the mode has been pruned. 3092 * In any case, we will send randr events for the Desktop Environment to 3093 * deal with it, if it wants to. 3094 */ 3095 for (i = 0; i < config->num_output; i++) { 3096 xf86OutputPtr output = config->output[i]; 3097 xf86CrtcPtr crtc = output->crtc; 3098 drmmode_output_private_ptr drmmode_output = output->driver_private; 3099 3100 drmmode_output_detect(output); 3101 3102 if (!crtc || !drmmode_output->mode_output) 3103 continue; 3104 3105 /* Get an updated view of the properties for the current connector and 3106 * look for the link-status property 3107 */ 3108 for (j = 0; j < drmmode_output->num_props; j++) { 3109 drmmode_prop_ptr p = &drmmode_output->props[j]; 3110 3111 if (!strcmp(p->mode_prop->name, "link-status")) { 3112 if (p->value != DRM_MODE_LINK_STATUS_BAD) 3113 break; 3114 3115 /* the connector got a link failure, re-set the current mode */ 3116 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, 3117 crtc->x, crtc->y); 3118 3119 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 3120 "hotplug event: connector %u's link-state is BAD, " 3121 "tried resetting the current mode. You may be left" 3122 "with a black screen if this fails...\n", 3123 drmmode_output->mode_output->connector_id); 3124 3125 break; 3126 } 3127 } 3128 } 3129 3130 mode_res = drmModeGetResources(pRADEONEnt->fd); 3131 if (!mode_res) 3132 goto out; 3133 3134restart_destroy: 3135 for (i = 0; i < config->num_output; i++) { 3136 xf86OutputPtr output = config->output[i]; 3137 drmmode_output_private_ptr drmmode_output = output->driver_private; 3138 found = FALSE; 3139 for (j = 0; j < mode_res->count_connectors; j++) { 3140 if (mode_res->connectors[j] == drmmode_output->output_id) { 3141 found = TRUE; 3142 break; 3143 } 3144 } 3145 if (found) 3146 continue; 3147 3148 drmModeFreeConnector(drmmode_output->mode_output); 3149 drmmode_output->mode_output = NULL; 3150 drmmode_output->output_id = -1; 3151 3152 changed = TRUE; 3153 if (drmmode->delete_dp_12_displays) { 3154 RROutputDestroy(output->randr_output); 3155 xf86OutputDestroy(output); 3156 goto restart_destroy; 3157 } 3158 } 3159 3160 /* find new output ids we don't have outputs for */ 3161 for (i = 0; i < mode_res->count_connectors; i++) { 3162 if (drmmode_find_output(pRADEONEnt->primary_scrn, 3163 mode_res->connectors[i], 3164 &num_dvi, &num_hdmi) || 3165 (pRADEONEnt->secondary_scrn && 3166 drmmode_find_output(pRADEONEnt->secondary_scrn, 3167 mode_res->connectors[i], 3168 &num_dvi, &num_hdmi))) 3169 continue; 3170 3171 if (drmmode_output_init(scrn, drmmode, mode_res, i, &num_dvi, 3172 &num_hdmi, 1) != 0) 3173 changed = TRUE; 3174 } 3175 3176 /* Check to see if a lessee has disappeared */ 3177 drmmode_validate_leases(scrn); 3178 3179 if (changed && dixPrivateKeyRegistered(rrPrivKey)) { 3180#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0) 3181 RRSetChanged(xf86ScrnToScreen(scrn)); 3182#else 3183 rrScrPrivPtr rrScrPriv = rrGetScrPriv(scrn->pScreen); 3184 rrScrPriv->changed = TRUE; 3185#endif 3186 RRTellChanged(xf86ScrnToScreen(scrn)); 3187 } 3188 3189 drmModeFreeResources(mode_res); 3190out: 3191 RRGetInfo(xf86ScrnToScreen(scrn), TRUE); 3192} 3193#ifdef HAVE_LIBUDEV 3194static void 3195drmmode_handle_uevents(int fd, void *closure) 3196{ 3197 drmmode_ptr drmmode = closure; 3198 ScrnInfoPtr scrn = drmmode->scrn; 3199 struct udev_device *dev; 3200 Bool received = FALSE; 3201 struct timeval tv = { 0, 0 }; 3202 fd_set readfd; 3203 3204 FD_ZERO(&readfd); 3205 FD_SET(fd, &readfd); 3206 3207 while (select(fd + 1, &readfd, NULL, NULL, &tv) > 0 && 3208 FD_ISSET(fd, &readfd)) { 3209 /* select() ensured that this will not block */ 3210 dev = udev_monitor_receive_device(drmmode->uevent_monitor); 3211 if (dev) { 3212 udev_device_unref(dev); 3213 received = TRUE; 3214 } 3215 } 3216 3217 if (received) 3218 radeon_mode_hotplug(scrn, drmmode); 3219} 3220#endif 3221 3222void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode) 3223{ 3224#ifdef HAVE_LIBUDEV 3225 struct udev *u; 3226 struct udev_monitor *mon; 3227 3228 u = udev_new(); 3229 if (!u) 3230 return; 3231 mon = udev_monitor_new_from_netlink(u, "udev"); 3232 if (!mon) { 3233 udev_unref(u); 3234 return; 3235 } 3236 3237 if (udev_monitor_filter_add_match_subsystem_devtype(mon, 3238 "drm", 3239 "drm_minor") < 0 || 3240 udev_monitor_enable_receiving(mon) < 0) { 3241 udev_monitor_unref(mon); 3242 udev_unref(u); 3243 return; 3244 } 3245 3246 drmmode->uevent_handler = 3247 xf86AddGeneralHandler(udev_monitor_get_fd(mon), 3248 drmmode_handle_uevents, 3249 drmmode); 3250 3251 drmmode->uevent_monitor = mon; 3252#endif 3253} 3254 3255void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode) 3256{ 3257#ifdef HAVE_LIBUDEV 3258 if (drmmode->uevent_handler) { 3259 struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor); 3260 xf86RemoveGeneralHandler(drmmode->uevent_handler); 3261 3262 udev_monitor_unref(drmmode->uevent_monitor); 3263 udev_unref(u); 3264 } 3265#endif 3266} 3267 3268Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, 3269 PixmapPtr new_front, uint64_t id, void *data, 3270 xf86CrtcPtr ref_crtc, radeon_drm_handler_proc handler, 3271 radeon_drm_abort_proc abort, 3272 enum drmmode_flip_sync flip_sync, 3273 uint32_t target_msc) 3274{ 3275 RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 3276 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 3277 xf86CrtcPtr crtc = NULL; 3278 drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private; 3279 uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0; 3280 drmmode_flipdata_ptr flipdata; 3281 Bool handle_deferred = FALSE; 3282 uintptr_t drm_queue_seq = 0; 3283 struct drmmode_fb *fb; 3284 int i = 0; 3285 3286 flipdata = calloc(1, sizeof(*flipdata) + config->num_crtc * 3287 sizeof(flipdata->fb[0])); 3288 if (!flipdata) { 3289 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 3290 "flip queue: data alloc failed.\n"); 3291 goto error; 3292 } 3293 3294 fb = radeon_pixmap_get_fb(new_front); 3295 if (!fb) { 3296 ErrorF("Failed to get FB for flip\n"); 3297 goto error; 3298 } 3299 3300 /* 3301 * Queue flips on all enabled CRTCs 3302 * Note that if/when we get per-CRTC buffers, we'll have to update this. 3303 * Right now it assumes a single shared fb across all CRTCs, with the 3304 * kernel fixing up the offset of each CRTC as necessary. 3305 * 3306 * Also, flips queued on disabled or incorrectly configured displays 3307 * may never complete; this is a configuration error. 3308 */ 3309 3310 flipdata->event_data = data; 3311 flipdata->handler = handler; 3312 flipdata->abort = abort; 3313 flipdata->fe_crtc = ref_crtc; 3314 3315 for (i = 0; i < config->num_crtc; i++) { 3316 crtc = config->crtc[i]; 3317 drmmode_crtc = crtc->driver_private; 3318 3319 if (!drmmode_crtc_can_flip(crtc) || 3320 (drmmode_crtc->tear_free && crtc != ref_crtc)) 3321 continue; 3322 3323 flipdata->flip_count++; 3324 3325 drm_queue_seq = radeon_drm_queue_alloc(crtc, client, id, 3326 flipdata, 3327 drmmode_flip_handler, 3328 drmmode_flip_abort); 3329 if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { 3330 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 3331 "Allocating DRM queue event entry failed.\n"); 3332 goto error; 3333 } 3334 3335 if (drmmode_crtc->tear_free) { 3336 BoxRec extents = { .x1 = 0, .y1 = 0, 3337 .x2 = new_front->drawable.width, 3338 .y2 = new_front->drawable.height }; 3339 int scanout_id = drmmode_crtc->scanout_id ^ 1; 3340 3341 if (flip_sync == FLIP_ASYNC) { 3342 if (!drmmode_wait_vblank(crtc, 3343 DRM_VBLANK_RELATIVE | 3344 DRM_VBLANK_EVENT, 3345 0, drm_queue_seq, 3346 NULL, NULL)) 3347 goto flip_error; 3348 goto next; 3349 } 3350 3351 drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[i], 3352 radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); 3353 if (!flipdata->fb[i]) { 3354 ErrorF("Failed to get FB for TearFree flip\n"); 3355 goto error; 3356 } 3357 3358 radeon_scanout_do_update(crtc, scanout_id, new_front, 3359 extents); 3360 radeon_cs_flush_indirect(crtc->scrn); 3361 3362 if (drmmode_crtc->scanout_update_pending) { 3363 radeon_drm_wait_pending_flip(crtc); 3364 handle_deferred = TRUE; 3365 radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending); 3366 drmmode_crtc->scanout_update_pending = 0; 3367 } 3368 } else { 3369 drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[i], fb); 3370 } 3371 3372 if (crtc == ref_crtc) { 3373 if (drmmode_page_flip_target_absolute(pRADEONEnt, 3374 drmmode_crtc, 3375 flipdata->fb[i]->handle, 3376 flip_flags, 3377 drm_queue_seq, 3378 target_msc) != 0) 3379 goto flip_error; 3380 } else { 3381 if (drmmode_page_flip_target_relative(pRADEONEnt, 3382 drmmode_crtc, 3383 flipdata->fb[i]->handle, 3384 flip_flags, 3385 drm_queue_seq, 0) != 0) 3386 goto flip_error; 3387 } 3388 3389 if (drmmode_crtc->tear_free) { 3390 drmmode_crtc->scanout_id ^= 1; 3391 drmmode_crtc->ignore_damage = TRUE; 3392 } 3393 3394 next: 3395 drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, 3396 flipdata->fb[i]); 3397 drm_queue_seq = 0; 3398 } 3399 3400 if (handle_deferred) 3401 radeon_drm_queue_handle_deferred(ref_crtc); 3402 if (flipdata->flip_count > 0) 3403 return TRUE; 3404 3405flip_error: 3406 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed: %s\n", 3407 strerror(errno)); 3408 3409error: 3410 if (drm_queue_seq) 3411 radeon_drm_abort_entry(drm_queue_seq); 3412 else if (crtc) 3413 drmmode_flip_abort(crtc, flipdata); 3414 else { 3415 abort(NULL, data); 3416 free(flipdata); 3417 } 3418 3419 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", 3420 strerror(errno)); 3421 if (handle_deferred) 3422 radeon_drm_queue_handle_deferred(ref_crtc); 3423 return FALSE; 3424} 3425