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