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