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