drmmode_display.c revision 40732134
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#ifdef XF86DRM_MODE 34#include <sys/ioctl.h> 35#include "micmap.h" 36#include "xf86cmap.h" 37#include "radeon.h" 38#include "radeon_reg.h" 39#include "radeon_drm.h" 40#include "sarea.h" 41 42#include "drmmode_display.h" 43 44/* DPMS */ 45#ifdef HAVE_XEXTPROTO_71 46#include <X11/extensions/dpmsconst.h> 47#else 48#define DPMS_SERVER 49#include <X11/extensions/dpms.h> 50#endif 51 52static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, 53 int width, int height, 54 int depth, int bpp, 55 int pitch, int tiling, 56 struct radeon_bo *bo) 57{ 58 RADEONInfoPtr info = RADEONPTR(pScrn); 59 ScreenPtr pScreen = pScrn->pScreen; 60 PixmapPtr pixmap; 61 struct radeon_surface *surface; 62 63 pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0); 64 if (!pixmap) 65 return NULL; 66 67 if (!(*pScreen->ModifyPixmapHeader)(pixmap, width, height, 68 depth, bpp, pitch, NULL)) { 69 return NULL; 70 } 71 72 exaMoveInPixmap(pixmap); 73 radeon_set_pixmap_bo(pixmap, bo); 74 if (info->ChipFamily >= CHIP_FAMILY_R600) { 75 surface = radeon_get_pixmap_surface(pixmap); 76 if (surface) { 77 memset(surface, 0, sizeof(struct radeon_surface)); 78 surface->npix_x = width; 79 surface->npix_y = height; 80 surface->npix_z = 1; 81 surface->blk_w = 1; 82 surface->blk_h = 1; 83 surface->blk_d = 1; 84 surface->array_size = 1; 85 surface->last_level = 0; 86 surface->bpe = bpp / 8; 87 surface->nsamples = 1; 88 surface->flags = RADEON_SURF_SCANOUT; 89 surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); 90 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); 91 if (tiling & RADEON_TILING_MICRO) { 92 surface->flags = RADEON_SURF_CLR(surface->flags, MODE); 93 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 94 } 95 if (tiling & RADEON_TILING_MACRO) { 96 surface->flags = RADEON_SURF_CLR(surface->flags, MODE); 97 surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 98 } 99 if (radeon_surface_best(info->surf_man, surface)) { 100 return NULL; 101 } 102 if (radeon_surface_init(info->surf_man, surface)) { 103 return NULL; 104 } 105 } 106 } 107 108 return pixmap; 109} 110 111static void drmmode_destroy_bo_pixmap(PixmapPtr pixmap) 112{ 113 ScreenPtr pScreen = pixmap->drawable.pScreen; 114 115 (*pScreen->DestroyPixmap)(pixmap); 116} 117 118static void 119drmmode_ConvertFromKMode(ScrnInfoPtr scrn, 120 drmModeModeInfo *kmode, 121 DisplayModePtr mode) 122{ 123 memset(mode, 0, sizeof(DisplayModeRec)); 124 mode->status = MODE_OK; 125 126 mode->Clock = kmode->clock; 127 128 mode->HDisplay = kmode->hdisplay; 129 mode->HSyncStart = kmode->hsync_start; 130 mode->HSyncEnd = kmode->hsync_end; 131 mode->HTotal = kmode->htotal; 132 mode->HSkew = kmode->hskew; 133 134 mode->VDisplay = kmode->vdisplay; 135 mode->VSyncStart = kmode->vsync_start; 136 mode->VSyncEnd = kmode->vsync_end; 137 mode->VTotal = kmode->vtotal; 138 mode->VScan = kmode->vscan; 139 140 mode->Flags = kmode->flags; //& FLAG_BITS; 141 mode->name = strdup(kmode->name); 142 143 if (kmode->type & DRM_MODE_TYPE_DRIVER) 144 mode->type = M_T_DRIVER; 145 if (kmode->type & DRM_MODE_TYPE_PREFERRED) 146 mode->type |= M_T_PREFERRED; 147 xf86SetModeCrtc (mode, scrn->adjustFlags); 148} 149 150static void 151drmmode_ConvertToKMode(ScrnInfoPtr scrn, 152 drmModeModeInfo *kmode, 153 DisplayModePtr mode) 154{ 155 memset(kmode, 0, sizeof(*kmode)); 156 157 kmode->clock = mode->Clock; 158 kmode->hdisplay = mode->HDisplay; 159 kmode->hsync_start = mode->HSyncStart; 160 kmode->hsync_end = mode->HSyncEnd; 161 kmode->htotal = mode->HTotal; 162 kmode->hskew = mode->HSkew; 163 164 kmode->vdisplay = mode->VDisplay; 165 kmode->vsync_start = mode->VSyncStart; 166 kmode->vsync_end = mode->VSyncEnd; 167 kmode->vtotal = mode->VTotal; 168 kmode->vscan = mode->VScan; 169 170 kmode->flags = mode->Flags; //& FLAG_BITS; 171 if (mode->name) 172 strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN); 173 kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; 174 175} 176 177static void 178drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode) 179{ 180#if 0 181 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 182// drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 183// drmmode_ptr drmmode = drmmode_crtc->drmmode; 184 185 /* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */ 186 if (mode == DPMSModeOff) { 187// drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 188// 0, 0, 0, NULL, 0, NULL); 189 } 190#endif 191} 192 193static PixmapPtr 194create_pixmap_for_fbcon(drmmode_ptr drmmode, 195 ScrnInfoPtr pScrn, int crtc_id) 196{ 197 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 198 drmmode_crtc_private_ptr drmmode_crtc; 199 PixmapPtr pixmap; 200 struct radeon_bo *bo; 201 drmModeFBPtr fbcon; 202 struct drm_gem_flink flink; 203 204 drmmode_crtc = xf86_config->crtc[crtc_id]->driver_private; 205 206 fbcon = drmModeGetFB(drmmode->fd, drmmode_crtc->mode_crtc->buffer_id); 207 if (fbcon == NULL) 208 return NULL; 209 210 flink.handle = fbcon->handle; 211 if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { 212 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 213 "Couldn't flink fbcon handle\n"); 214 return NULL; 215 } 216 217 bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0); 218 if (bo == NULL) { 219 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 220 "Couldn't allocate bo for fbcon handle\n"); 221 return NULL; 222 } 223 224 pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height, 225 fbcon->depth, fbcon->bpp, 226 fbcon->pitch, 0, bo); 227 if (!pixmap) 228 return NULL; 229 230 radeon_bo_unref(bo); 231 drmModeFreeFB(fbcon); 232 return pixmap; 233} 234 235void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 236{ 237 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 238 RADEONInfoPtr info = RADEONPTR(pScrn); 239 PixmapPtr src, dst; 240 ScreenPtr pScreen = pScrn->pScreen; 241 int crtc_id = 0; 242 int i; 243 int pitch; 244 uint32_t tiling_flags = 0; 245 Bool ret; 246 247 if (info->accelOn == FALSE) 248 return; 249 250 for (i = 0; i < xf86_config->num_crtc; i++) { 251 xf86CrtcPtr crtc = xf86_config->crtc[i]; 252 drmmode_crtc_private_ptr drmmode_crtc; 253 254 drmmode_crtc = crtc->driver_private; 255 if (drmmode_crtc->mode_crtc->buffer_id) 256 crtc_id = i; 257 } 258 259 src = create_pixmap_for_fbcon(drmmode, pScrn, crtc_id); 260 if (!src) 261 return; 262 263 if (info->allowColorTiling) { 264 if (info->ChipFamily >= CHIP_FAMILY_R600) { 265 if (info->allowColorTiling2D) { 266 tiling_flags |= RADEON_TILING_MACRO; 267 } else { 268 tiling_flags |= RADEON_TILING_MICRO; 269 } 270 } else 271 tiling_flags |= RADEON_TILING_MACRO; 272 } 273 274 pitch = RADEON_ALIGN(pScrn->displayWidth, 275 drmmode_get_pitch_align(pScrn, info->CurrentLayout.pixel_bytes, tiling_flags)) * 276 info->CurrentLayout.pixel_bytes; 277 278 dst = drmmode_create_bo_pixmap(pScrn, pScrn->virtualX, 279 pScrn->virtualY, pScrn->depth, 280 pScrn->bitsPerPixel, pitch, 281 tiling_flags, info->front_bo); 282 if (!dst) 283 goto out_free_src; 284 285 ret = info->accel_state->exa->PrepareCopy (src, dst, 286 -1, -1, GXcopy, FB_ALLONES); 287 if (!ret) 288 goto out_free_src; 289 info->accel_state->exa->Copy (dst, 0, 0, 0, 0, 290 pScrn->virtualX, pScrn->virtualY); 291 info->accel_state->exa->DoneCopy (dst); 292 radeon_cs_flush_indirect(pScrn); 293 294#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10 295 pScreen->canDoBGNoneRoot = TRUE; 296#endif 297 drmmode_destroy_bo_pixmap(dst); 298 out_free_src: 299 drmmode_destroy_bo_pixmap(src); 300 301} 302 303static Bool 304drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, 305 Rotation rotation, int x, int y) 306{ 307 ScrnInfoPtr pScrn = crtc->scrn; 308 RADEONInfoPtr info = RADEONPTR(pScrn); 309 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 310 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 311 drmmode_ptr drmmode = drmmode_crtc->drmmode; 312 int saved_x, saved_y; 313 Rotation saved_rotation; 314 DisplayModeRec saved_mode; 315 uint32_t *output_ids; 316 int output_count = 0; 317 Bool ret = TRUE; 318 int i; 319 int fb_id; 320 drmModeModeInfo kmode; 321 int pitch; 322 uint32_t tiling_flags = 0; 323 int height; 324 325 if (info->allowColorTiling) { 326 if (info->ChipFamily >= CHIP_FAMILY_R600) 327 tiling_flags |= RADEON_TILING_MICRO; 328 else 329 tiling_flags |= RADEON_TILING_MACRO; 330 } 331 332 pitch = RADEON_ALIGN(pScrn->displayWidth, drmmode_get_pitch_align(pScrn, info->CurrentLayout.pixel_bytes, tiling_flags)) * 333 info->CurrentLayout.pixel_bytes; 334 height = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags)); 335 if (info->ChipFamily >= CHIP_FAMILY_R600) { 336 pitch = info->front_surface.level[0].pitch_bytes; 337 } 338 339 if (drmmode->fb_id == 0) { 340 ret = drmModeAddFB(drmmode->fd, 341 pScrn->virtualX, height, 342 pScrn->depth, pScrn->bitsPerPixel, 343 pitch, 344 info->front_bo->handle, 345 &drmmode->fb_id); 346 if (ret < 0) { 347 ErrorF("failed to add fb\n"); 348 return FALSE; 349 } 350 } 351 352 saved_mode = crtc->mode; 353 saved_x = crtc->x; 354 saved_y = crtc->y; 355 saved_rotation = crtc->rotation; 356 357 if (mode) { 358 crtc->mode = *mode; 359 crtc->x = x; 360 crtc->y = y; 361 crtc->rotation = rotation; 362#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,5,99,0,0) 363 crtc->transformPresent = FALSE; 364#endif 365 } 366 367 output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); 368 if (!output_ids) { 369 ret = FALSE; 370 goto done; 371 } 372 373 if (mode) { 374 for (i = 0; i < xf86_config->num_output; i++) { 375 xf86OutputPtr output = xf86_config->output[i]; 376 drmmode_output_private_ptr drmmode_output; 377 378 if (output->crtc != crtc) 379 continue; 380 381 drmmode_output = output->driver_private; 382 output_ids[output_count] = drmmode_output->mode_output->connector_id; 383 output_count++; 384 } 385 386 if (!xf86CrtcRotate(crtc)) { 387 goto done; 388 } 389#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0) 390 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, 391 crtc->gamma_blue, crtc->gamma_size); 392#endif 393 394 drmmode_ConvertToKMode(crtc->scrn, &kmode, mode); 395 396 fb_id = drmmode->fb_id; 397 if (drmmode_crtc->rotate_fb_id) { 398 fb_id = drmmode_crtc->rotate_fb_id; 399 x = y = 0; 400 } 401 ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 402 fb_id, x, y, output_ids, output_count, &kmode); 403 if (ret) 404 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, 405 "failed to set mode: %s", strerror(-ret)); 406 else 407 ret = TRUE; 408 409 if (crtc->scrn->pScreen) 410 xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen); 411 /* go through all the outputs and force DPMS them back on? */ 412 for (i = 0; i < xf86_config->num_output; i++) { 413 xf86OutputPtr output = xf86_config->output[i]; 414 415 if (output->crtc != crtc) 416 continue; 417 418 output->funcs->dpms(output, DPMSModeOn); 419 } 420 } 421 422 if (pScrn->pScreen && 423 !xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) 424 xf86_reload_cursors(pScrn->pScreen); 425 426done: 427 if (!ret) { 428 crtc->x = saved_x; 429 crtc->y = saved_y; 430 crtc->rotation = saved_rotation; 431 crtc->mode = saved_mode; 432 } 433#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3 434 else 435 crtc->active = TRUE; 436#endif 437 438 return ret; 439} 440 441static void 442drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) 443{ 444 445} 446 447static void 448drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) 449{ 450 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 451 drmmode_ptr drmmode = drmmode_crtc->drmmode; 452 453 drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); 454} 455 456static void 457drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) 458{ 459 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 460 int i; 461 uint32_t *ptr; 462 463 /* cursor should be mapped already */ 464 ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr); 465 466 for (i = 0; i < 64 * 64; i++) 467 ptr[i] = cpu_to_le32(image[i]); 468} 469 470 471static void 472drmmode_hide_cursor (xf86CrtcPtr crtc) 473{ 474 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 475 drmmode_ptr drmmode = drmmode_crtc->drmmode; 476 477 drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64); 478 479} 480 481static void 482drmmode_show_cursor (xf86CrtcPtr crtc) 483{ 484 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 485 drmmode_ptr drmmode = drmmode_crtc->drmmode; 486 uint32_t handle = drmmode_crtc->cursor_bo->handle; 487 488 drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64); 489} 490 491static void * 492drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) 493{ 494 ScrnInfoPtr pScrn = crtc->scrn; 495 RADEONInfoPtr info = RADEONPTR(pScrn); 496 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 497 drmmode_ptr drmmode = drmmode_crtc->drmmode; 498 int size; 499 struct radeon_bo *rotate_bo; 500 int ret; 501 unsigned long rotate_pitch; 502 int base_align; 503 504 /* rotation requires acceleration */ 505 if (info->r600_shadow_fb) { 506 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 507 "Rotation requires acceleration!\n"); 508 return NULL; 509 } 510 511 rotate_pitch = 512 RADEON_ALIGN(width, drmmode_get_pitch_align(crtc->scrn, drmmode->cpp, 0)) * drmmode->cpp; 513 height = RADEON_ALIGN(height, drmmode_get_height_align(crtc->scrn, 0)); 514 base_align = drmmode_get_base_align(crtc->scrn, drmmode->cpp, 0); 515 size = RADEON_ALIGN(rotate_pitch * height, RADEON_GPU_PAGE_SIZE); 516 517 rotate_bo = radeon_bo_open(drmmode->bufmgr, 0, size, base_align, RADEON_GEM_DOMAIN_VRAM, 0); 518 if (rotate_bo == NULL) 519 return NULL; 520 521 radeon_bo_map(rotate_bo, 1); 522 523 ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth, 524 crtc->scrn->bitsPerPixel, rotate_pitch, 525 rotate_bo->handle, 526 &drmmode_crtc->rotate_fb_id); 527 if (ret) { 528 ErrorF("failed to add rotate fb\n"); 529 } 530 531 drmmode_crtc->rotate_bo = rotate_bo; 532 return drmmode_crtc->rotate_bo->ptr; 533} 534 535static PixmapPtr 536drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) 537{ 538 ScrnInfoPtr pScrn = crtc->scrn; 539 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 540 drmmode_ptr drmmode = drmmode_crtc->drmmode; 541 unsigned long rotate_pitch; 542 PixmapPtr rotate_pixmap; 543 544 if (!data) 545 data = drmmode_crtc_shadow_allocate (crtc, width, height); 546 547 rotate_pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0)) * drmmode->cpp; 548 549 rotate_pixmap = drmmode_create_bo_pixmap(pScrn, 550 width, height, 551 pScrn->depth, 552 pScrn->bitsPerPixel, 553 rotate_pitch, 554 0, drmmode_crtc->rotate_bo); 555 if (rotate_pixmap == NULL) { 556 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 557 "Couldn't allocate shadow pixmap for rotated CRTC\n"); 558 } 559 return rotate_pixmap; 560 561} 562 563static void 564drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) 565{ 566 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 567 drmmode_ptr drmmode = drmmode_crtc->drmmode; 568 569 if (rotate_pixmap) 570 drmmode_destroy_bo_pixmap(rotate_pixmap); 571 572 if (data) { 573 drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id); 574 drmmode_crtc->rotate_fb_id = 0; 575 radeon_bo_unmap(drmmode_crtc->rotate_bo); 576 radeon_bo_unref(drmmode_crtc->rotate_bo); 577 drmmode_crtc->rotate_bo = NULL; 578 } 579 580} 581 582static void 583drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, 584 uint16_t *blue, int size) 585{ 586 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 587 drmmode_ptr drmmode = drmmode_crtc->drmmode; 588 589 drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 590 size, red, green, blue); 591} 592 593static const xf86CrtcFuncsRec drmmode_crtc_funcs = { 594 .dpms = drmmode_crtc_dpms, 595 .set_mode_major = drmmode_set_mode_major, 596 .set_cursor_colors = drmmode_set_cursor_colors, 597 .set_cursor_position = drmmode_set_cursor_position, 598 .show_cursor = drmmode_show_cursor, 599 .hide_cursor = drmmode_hide_cursor, 600 .load_cursor_argb = drmmode_load_cursor_argb, 601 602 .gamma_set = drmmode_crtc_gamma_set, 603 .shadow_create = drmmode_crtc_shadow_create, 604 .shadow_allocate = drmmode_crtc_shadow_allocate, 605 .shadow_destroy = drmmode_crtc_shadow_destroy, 606 .destroy = NULL, /* XXX */ 607}; 608 609int drmmode_get_crtc_id(xf86CrtcPtr crtc) 610{ 611 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 612 return drmmode_crtc->hw_id; 613} 614 615void drmmode_crtc_hw_id(xf86CrtcPtr crtc) 616{ 617 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 618 ScrnInfoPtr pScrn = crtc->scrn; 619 RADEONInfoPtr info = RADEONPTR(pScrn); 620 struct drm_radeon_info ginfo; 621 int r; 622 uint32_t tmp; 623 624 memset(&ginfo, 0, sizeof(ginfo)); 625 ginfo.request = 0x4; 626 tmp = drmmode_crtc->mode_crtc->crtc_id; 627 ginfo.value = (uintptr_t)&tmp; 628 r = drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INFO, &ginfo, sizeof(ginfo)); 629 if (r) { 630 drmmode_crtc->hw_id = -1; 631 return; 632 } 633 drmmode_crtc->hw_id = tmp; 634} 635 636static void 637drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) 638{ 639 xf86CrtcPtr crtc; 640 drmmode_crtc_private_ptr drmmode_crtc; 641 642 crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs); 643 if (crtc == NULL) 644 return; 645 646 drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); 647 drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]); 648 drmmode_crtc->drmmode = drmmode; 649 crtc->driver_private = drmmode_crtc; 650 drmmode_crtc_hw_id(crtc); 651 652 return; 653} 654 655static xf86OutputStatus 656drmmode_output_detect(xf86OutputPtr output) 657{ 658 /* go to the hw and retrieve a new output struct */ 659 drmmode_output_private_ptr drmmode_output = output->driver_private; 660 drmmode_ptr drmmode = drmmode_output->drmmode; 661 xf86OutputStatus status; 662 drmModeFreeConnector(drmmode_output->mode_output); 663 664 drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id); 665 666 switch (drmmode_output->mode_output->connection) { 667 case DRM_MODE_CONNECTED: 668 status = XF86OutputStatusConnected; 669 break; 670 case DRM_MODE_DISCONNECTED: 671 status = XF86OutputStatusDisconnected; 672 break; 673 default: 674 case DRM_MODE_UNKNOWNCONNECTION: 675 status = XF86OutputStatusUnknown; 676 break; 677 } 678 return status; 679} 680 681static Bool 682drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) 683{ 684 return MODE_OK; 685} 686 687static DisplayModePtr 688drmmode_output_get_modes(xf86OutputPtr output) 689{ 690 drmmode_output_private_ptr drmmode_output = output->driver_private; 691 drmModeConnectorPtr koutput = drmmode_output->mode_output; 692 drmmode_ptr drmmode = drmmode_output->drmmode; 693 int i; 694 DisplayModePtr Modes = NULL, Mode; 695 drmModePropertyPtr props; 696 xf86MonPtr mon = NULL; 697 698 /* look for an EDID property */ 699 for (i = 0; i < koutput->count_props; i++) { 700 props = drmModeGetProperty(drmmode->fd, koutput->props[i]); 701 if (props && (props->flags & DRM_MODE_PROP_BLOB)) { 702 if (!strcmp(props->name, "EDID")) { 703 if (drmmode_output->edid_blob) 704 drmModeFreePropertyBlob(drmmode_output->edid_blob); 705 drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]); 706 } 707 drmModeFreeProperty(props); 708 } 709 } 710 711 if (drmmode_output->edid_blob) { 712 mon = xf86InterpretEDID(output->scrn->scrnIndex, 713 drmmode_output->edid_blob->data); 714 if (mon && drmmode_output->edid_blob->length > 128) 715 mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA; 716 } 717 xf86OutputSetEDID(output, mon); 718 719 /* modes should already be available */ 720 for (i = 0; i < koutput->count_modes; i++) { 721 Mode = xnfalloc(sizeof(DisplayModeRec)); 722 723 drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode); 724 Modes = xf86ModesAdd(Modes, Mode); 725 726 } 727 return Modes; 728} 729 730static void 731drmmode_output_destroy(xf86OutputPtr output) 732{ 733 drmmode_output_private_ptr drmmode_output = output->driver_private; 734 int i; 735 736 if (drmmode_output->edid_blob) 737 drmModeFreePropertyBlob(drmmode_output->edid_blob); 738 for (i = 0; i < drmmode_output->num_props; i++) { 739 drmModeFreeProperty(drmmode_output->props[i].mode_prop); 740 free(drmmode_output->props[i].atoms); 741 } 742 for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) { 743 drmModeFreeEncoder(drmmode_output->mode_encoders[i]); 744 free(drmmode_output->mode_encoders); 745 } 746 free(drmmode_output->props); 747 drmModeFreeConnector(drmmode_output->mode_output); 748 free(drmmode_output); 749 output->driver_private = NULL; 750} 751 752static void 753drmmode_output_dpms(xf86OutputPtr output, int mode) 754{ 755 drmmode_output_private_ptr drmmode_output = output->driver_private; 756 drmModeConnectorPtr koutput = drmmode_output->mode_output; 757 drmmode_ptr drmmode = drmmode_output->drmmode; 758 759 drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id, 760 drmmode_output->dpms_enum_id, mode); 761 return; 762} 763 764 765static Bool 766drmmode_property_ignore(drmModePropertyPtr prop) 767{ 768 if (!prop) 769 return TRUE; 770 /* ignore blob prop */ 771 if (prop->flags & DRM_MODE_PROP_BLOB) 772 return TRUE; 773 /* ignore standard property */ 774 if (!strcmp(prop->name, "EDID") || 775 !strcmp(prop->name, "DPMS")) 776 return TRUE; 777 778 return FALSE; 779} 780 781static void 782drmmode_output_create_resources(xf86OutputPtr output) 783{ 784 drmmode_output_private_ptr drmmode_output = output->driver_private; 785 drmModeConnectorPtr mode_output = drmmode_output->mode_output; 786 drmmode_ptr drmmode = drmmode_output->drmmode; 787 drmModePropertyPtr drmmode_prop; 788 int i, j, err; 789 790 drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec)); 791 if (!drmmode_output->props) 792 return; 793 794 drmmode_output->num_props = 0; 795 for (i = 0, j = 0; i < mode_output->count_props; i++) { 796 drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]); 797 if (drmmode_property_ignore(drmmode_prop)) { 798 drmModeFreeProperty(drmmode_prop); 799 continue; 800 } 801 drmmode_output->props[j].mode_prop = drmmode_prop; 802 drmmode_output->props[j].value = mode_output->prop_values[i]; 803 drmmode_output->num_props++; 804 j++; 805 } 806 807 for (i = 0; i < drmmode_output->num_props; i++) { 808 drmmode_prop_ptr p = &drmmode_output->props[i]; 809 drmmode_prop = p->mode_prop; 810 811 if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) { 812 INT32 range[2]; 813 INT32 value = p->value; 814 815 p->num_atoms = 1; 816 p->atoms = calloc(p->num_atoms, sizeof(Atom)); 817 if (!p->atoms) 818 continue; 819 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); 820 range[0] = drmmode_prop->values[0]; 821 range[1] = drmmode_prop->values[1]; 822 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], 823 FALSE, TRUE, 824 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, 825 2, range); 826 if (err != 0) { 827 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 828 "RRConfigureOutputProperty error, %d\n", err); 829 } 830 err = RRChangeOutputProperty(output->randr_output, p->atoms[0], 831 XA_INTEGER, 32, PropModeReplace, 1, &value, FALSE, TRUE); 832 if (err != 0) { 833 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 834 "RRChangeOutputProperty error, %d\n", err); 835 } 836 } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) { 837 p->num_atoms = drmmode_prop->count_enums + 1; 838 p->atoms = calloc(p->num_atoms, sizeof(Atom)); 839 if (!p->atoms) 840 continue; 841 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); 842 for (j = 1; j <= drmmode_prop->count_enums; j++) { 843 struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1]; 844 p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE); 845 } 846 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], 847 FALSE, FALSE, 848 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, 849 p->num_atoms - 1, (INT32 *)&p->atoms[1]); 850 if (err != 0) { 851 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 852 "RRConfigureOutputProperty error, %d\n", err); 853 } 854 for (j = 0; j < drmmode_prop->count_enums; j++) 855 if (drmmode_prop->enums[j].value == p->value) 856 break; 857 /* there's always a matching value */ 858 err = RRChangeOutputProperty(output->randr_output, p->atoms[0], 859 XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE); 860 if (err != 0) { 861 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 862 "RRChangeOutputProperty error, %d\n", err); 863 } 864 } 865 } 866} 867 868static Bool 869drmmode_output_set_property(xf86OutputPtr output, Atom property, 870 RRPropertyValuePtr value) 871{ 872 drmmode_output_private_ptr drmmode_output = output->driver_private; 873 drmmode_ptr drmmode = drmmode_output->drmmode; 874 int i; 875 876 for (i = 0; i < drmmode_output->num_props; i++) { 877 drmmode_prop_ptr p = &drmmode_output->props[i]; 878 879 if (p->atoms[0] != property) 880 continue; 881 882 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { 883 uint32_t val; 884 885 if (value->type != XA_INTEGER || value->format != 32 || 886 value->size != 1) 887 return FALSE; 888 val = *(uint32_t *)value->data; 889 890 drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, 891 p->mode_prop->prop_id, (uint64_t)val); 892 return TRUE; 893 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { 894 Atom atom; 895 const char *name; 896 int j; 897 898 if (value->type != XA_ATOM || value->format != 32 || value->size != 1) 899 return FALSE; 900 memcpy(&atom, value->data, 4); 901 name = NameForAtom(atom); 902 903 /* search for matching name string, then set its value down */ 904 for (j = 0; j < p->mode_prop->count_enums; j++) { 905 if (!strcmp(p->mode_prop->enums[j].name, name)) { 906 drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, 907 p->mode_prop->prop_id, p->mode_prop->enums[j].value); 908 return TRUE; 909 } 910 } 911 } 912 } 913 914 return TRUE; 915} 916 917static Bool 918drmmode_output_get_property(xf86OutputPtr output, Atom property) 919{ 920 return TRUE; 921} 922 923static const xf86OutputFuncsRec drmmode_output_funcs = { 924 .dpms = drmmode_output_dpms, 925 .create_resources = drmmode_output_create_resources, 926#ifdef RANDR_12_INTERFACE 927 .set_property = drmmode_output_set_property, 928 .get_property = drmmode_output_get_property, 929#endif 930#if 0 931 932 .save = drmmode_crt_save, 933 .restore = drmmode_crt_restore, 934 .mode_fixup = drmmode_crt_mode_fixup, 935 .prepare = drmmode_output_prepare, 936 .mode_set = drmmode_crt_mode_set, 937 .commit = drmmode_output_commit, 938#endif 939 .detect = drmmode_output_detect, 940 .mode_valid = drmmode_output_mode_valid, 941 942 .get_modes = drmmode_output_get_modes, 943 .destroy = drmmode_output_destroy 944}; 945 946static int subpixel_conv_table[7] = { 0, SubPixelUnknown, 947 SubPixelHorizontalRGB, 948 SubPixelHorizontalBGR, 949 SubPixelVerticalRGB, 950 SubPixelVerticalBGR, 951 SubPixelNone }; 952 953const char *output_names[] = { "None", 954 "VGA", 955 "DVI", 956 "DVI", 957 "DVI", 958 "Composite", 959 "S-video", 960 "LVDS", 961 "CTV", 962 "DIN", 963 "DisplayPort", 964 "HDMI", 965 "HDMI", 966 "TV", 967 "eDP" 968}; 969 970static void 971drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dvi, int *num_hdmi) 972{ 973 RADEONInfoPtr info = RADEONPTR(pScrn); 974 xf86OutputPtr output; 975 drmModeConnectorPtr koutput; 976 drmModeEncoderPtr *kencoders = NULL; 977 drmmode_output_private_ptr drmmode_output; 978 drmModePropertyPtr props; 979 char name[32]; 980 int i; 981 const char *s; 982 983 koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]); 984 if (!koutput) 985 return; 986 987 kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders); 988 if (!kencoders) { 989 goto out_free_encoders; 990 } 991 992 for (i = 0; i < koutput->count_encoders; i++) { 993 kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]); 994 if (!kencoders[i]) { 995 goto out_free_encoders; 996 } 997 } 998 999 /* need to do smart conversion here for compat with non-kms ATI driver */ 1000 if (koutput->connector_type_id == 1) { 1001 switch(koutput->connector_type) { 1002 case DRM_MODE_CONNECTOR_DVII: 1003 case DRM_MODE_CONNECTOR_DVID: 1004 case DRM_MODE_CONNECTOR_DVIA: 1005 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi); 1006 (*num_dvi)++; 1007 break; 1008 case DRM_MODE_CONNECTOR_HDMIA: 1009 case DRM_MODE_CONNECTOR_HDMIB: 1010 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi); 1011 (*num_hdmi)++; 1012 break; 1013 case DRM_MODE_CONNECTOR_VGA: 1014 case DRM_MODE_CONNECTOR_DisplayPort: 1015 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1); 1016 break; 1017 default: 1018 snprintf(name, 32, "%s", output_names[koutput->connector_type]); 1019 break; 1020 } 1021 } else { 1022 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1); 1023 } 1024 1025 if (xf86IsEntityShared(pScrn->entityList[0])) { 1026 if ((s = xf86GetOptValString(info->Options, OPTION_ZAPHOD_HEADS))) { 1027 if (!RADEONZaphodStringMatches(pScrn, s, name)) 1028 goto out_free_encoders; 1029 } else { 1030 if (info->IsPrimary && (num != 0)) 1031 goto out_free_encoders; 1032 else if (info->IsSecondary && (num != 1)) 1033 goto out_free_encoders; 1034 } 1035 } 1036 1037 output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name); 1038 if (!output) { 1039 goto out_free_encoders; 1040 } 1041 1042 drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1); 1043 if (!drmmode_output) { 1044 xf86OutputDestroy(output); 1045 goto out_free_encoders; 1046 } 1047 1048 drmmode_output->output_id = drmmode->mode_res->connectors[num]; 1049 drmmode_output->mode_output = koutput; 1050 drmmode_output->mode_encoders = kencoders; 1051 drmmode_output->drmmode = drmmode; 1052 output->mm_width = koutput->mmWidth; 1053 output->mm_height = koutput->mmHeight; 1054 1055 output->subpixel_order = subpixel_conv_table[koutput->subpixel]; 1056 output->interlaceAllowed = TRUE; 1057 output->doubleScanAllowed = TRUE; 1058 output->driver_private = drmmode_output; 1059 1060 output->possible_crtcs = 0xffffffff; 1061 for (i = 0; i < koutput->count_encoders; i++) { 1062 output->possible_crtcs &= kencoders[i]->possible_crtcs; 1063 } 1064 /* work out the possible clones later */ 1065 output->possible_clones = 0; 1066 1067 for (i = 0; i < koutput->count_props; i++) { 1068 props = drmModeGetProperty(drmmode->fd, koutput->props[i]); 1069 if (props && (props->flags & DRM_MODE_PROP_ENUM)) { 1070 if (!strcmp(props->name, "DPMS")) { 1071 drmmode_output->dpms_enum_id = koutput->props[i]; 1072 drmModeFreeProperty(props); 1073 break; 1074 } 1075 drmModeFreeProperty(props); 1076 } 1077 } 1078 1079 return; 1080out_free_encoders: 1081 if (kencoders){ 1082 for (i = 0; i < koutput->count_encoders; i++) 1083 drmModeFreeEncoder(kencoders[i]); 1084 free(kencoders); 1085 } 1086 drmModeFreeConnector(koutput); 1087 1088} 1089 1090uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output) 1091{ 1092 drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout; 1093 int i; 1094 xf86OutputPtr clone_output; 1095 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1096 int index_mask = 0; 1097 1098 if (drmmode_output->enc_clone_mask == 0) 1099 return index_mask; 1100 1101 for (i = 0; i < xf86_config->num_output; i++) { 1102 clone_output = xf86_config->output[i]; 1103 clone_drmout = clone_output->driver_private; 1104 if (output == clone_output) 1105 continue; 1106 1107 if (clone_drmout->enc_mask == 0) 1108 continue; 1109 if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask) 1110 index_mask |= (1 << i); 1111 } 1112 return index_mask; 1113} 1114 1115 1116static void 1117drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode) 1118{ 1119 int i, j; 1120 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1121 1122 for (i = 0; i < xf86_config->num_output; i++) { 1123 xf86OutputPtr output = xf86_config->output[i]; 1124 drmmode_output_private_ptr drmmode_output; 1125 1126 drmmode_output = output->driver_private; 1127 drmmode_output->enc_clone_mask = 0xff; 1128 /* and all the possible encoder clones for this output together */ 1129 for (j = 0; j < drmmode_output->mode_output->count_encoders; j++) 1130 { 1131 int k; 1132 for (k = 0; k < drmmode->mode_res->count_encoders; k++) { 1133 if (drmmode->mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id) 1134 drmmode_output->enc_mask |= (1 << k); 1135 } 1136 1137 drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones; 1138 } 1139 } 1140 1141 for (i = 0; i < xf86_config->num_output; i++) { 1142 xf86OutputPtr output = xf86_config->output[i]; 1143 output->possible_clones = find_clones(scrn, output); 1144 } 1145} 1146 1147/* returns height alignment in pixels */ 1148int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling) 1149{ 1150 RADEONInfoPtr info = RADEONPTR(scrn); 1151 int height_align = 1; 1152 1153 if (info->ChipFamily >= CHIP_FAMILY_R600) { 1154 if (tiling & RADEON_TILING_MACRO) 1155 height_align = info->num_channels * 8; 1156 else if (tiling & RADEON_TILING_MICRO) 1157 height_align = 8; 1158 else 1159 height_align = 8; 1160 } else { 1161 if (tiling) 1162 height_align = 16; 1163 else 1164 height_align = 1; 1165 } 1166 return height_align; 1167} 1168 1169/* returns pitch alignment in pixels */ 1170int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling) 1171{ 1172 RADEONInfoPtr info = RADEONPTR(scrn); 1173 int pitch_align = 1; 1174 1175 if (info->ChipFamily >= CHIP_FAMILY_R600) { 1176 if (tiling & RADEON_TILING_MACRO) { 1177 /* general surface requirements */ 1178 pitch_align = MAX(info->num_banks, 1179 (((info->group_bytes / 8) / bpe) * info->num_banks)) * 8; 1180 /* further restrictions for scanout */ 1181 pitch_align = MAX(info->num_banks * 8, pitch_align); 1182 } else if (tiling & RADEON_TILING_MICRO) { 1183 /* general surface requirements */ 1184 pitch_align = MAX(8, (info->group_bytes / (8 * bpe))); 1185 /* further restrictions for scanout */ 1186 pitch_align = MAX(info->group_bytes / bpe, pitch_align); 1187 } else { 1188 if (info->have_tiling_info) 1189 /* linear aligned requirements */ 1190 pitch_align = MAX(64, info->group_bytes / bpe); 1191 else 1192 /* default to 512 elements if we don't know the real 1193 * group size otherwise the kernel may reject the CS 1194 * if the group sizes don't match as the pitch won't 1195 * be aligned properly. 1196 */ 1197 pitch_align = 512; 1198 } 1199 } else { 1200 /* general surface requirements */ 1201 if (tiling) 1202 pitch_align = 256 / bpe; 1203 else 1204 pitch_align = 64; 1205 } 1206 return pitch_align; 1207} 1208 1209/* returns base alignment in bytes */ 1210int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling) 1211{ 1212 RADEONInfoPtr info = RADEONPTR(scrn); 1213 int pixel_align = drmmode_get_pitch_align(scrn, bpe, tiling); 1214 int height_align = drmmode_get_height_align(scrn, tiling); 1215 int base_align = RADEON_GPU_PAGE_SIZE; 1216 1217 if (info->ChipFamily >= CHIP_FAMILY_R600) { 1218 if (tiling & RADEON_TILING_MACRO) 1219 base_align = MAX(info->num_banks * info->num_channels * 8 * 8 * bpe, 1220 pixel_align * bpe * height_align); 1221 else { 1222 if (info->have_tiling_info) 1223 base_align = info->group_bytes; 1224 else 1225 /* default to 512 if we don't know the real 1226 * group size otherwise the kernel may reject the CS 1227 * if the group sizes don't match as the base won't 1228 * be aligned properly. 1229 */ 1230 base_align = 512; 1231 } 1232 } 1233 return base_align; 1234} 1235 1236static Bool 1237drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) 1238{ 1239 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1240 drmmode_crtc_private_ptr 1241 drmmode_crtc = xf86_config->crtc[0]->driver_private; 1242 drmmode_ptr drmmode = drmmode_crtc->drmmode; 1243 RADEONInfoPtr info = RADEONPTR(scrn); 1244 struct radeon_bo *old_front = NULL; 1245 Bool ret; 1246 ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; 1247 uint32_t old_fb_id; 1248 int i, pitch, old_width, old_height, old_pitch; 1249 int screen_size; 1250 int cpp = info->CurrentLayout.pixel_bytes; 1251 struct radeon_bo *front_bo; 1252 struct radeon_surface surface; 1253 struct radeon_surface *psurface; 1254 uint32_t tiling_flags = 0, base_align; 1255 PixmapPtr ppix = screen->GetScreenPixmap(screen); 1256 void *fb_shadow; 1257 1258 if (scrn->virtualX == width && scrn->virtualY == height) 1259 return TRUE; 1260 1261 front_bo = info->front_bo; 1262 radeon_cs_flush_indirect(scrn); 1263 1264 if (front_bo) 1265 radeon_bo_wait(front_bo); 1266 1267 if (info->allowColorTiling) { 1268 if (info->ChipFamily >= CHIP_FAMILY_R600) { 1269 if (info->allowColorTiling2D) { 1270 tiling_flags |= RADEON_TILING_MACRO; 1271 } else { 1272 tiling_flags |= RADEON_TILING_MICRO; 1273 } 1274 } else 1275 tiling_flags |= RADEON_TILING_MACRO; 1276 } 1277 1278 pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp; 1279 height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags)); 1280 screen_size = RADEON_ALIGN(pitch * height, RADEON_GPU_PAGE_SIZE); 1281 base_align = 4096; 1282 if (info->ChipFamily >= CHIP_FAMILY_R600) { 1283 memset(&surface, 0, sizeof(struct radeon_surface)); 1284 surface.npix_x = width; 1285 surface.npix_y = height; 1286 surface.npix_z = 1; 1287 surface.blk_w = 1; 1288 surface.blk_h = 1; 1289 surface.blk_d = 1; 1290 surface.array_size = 1; 1291 surface.last_level = 0; 1292 surface.bpe = cpp; 1293 surface.nsamples = 1; 1294 surface.flags = RADEON_SURF_SCANOUT; 1295 surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); 1296 surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); 1297 if (tiling_flags & RADEON_TILING_MICRO) { 1298 surface.flags = RADEON_SURF_CLR(surface.flags, MODE); 1299 surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 1300 } 1301 if (tiling_flags & RADEON_TILING_MACRO) { 1302 surface.flags = RADEON_SURF_CLR(surface.flags, MODE); 1303 surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 1304 } 1305 if (radeon_surface_best(info->surf_man, &surface)) { 1306 return FALSE; 1307 } 1308 if (radeon_surface_init(info->surf_man, &surface)) { 1309 return FALSE; 1310 } 1311 screen_size = surface.bo_size; 1312 base_align = surface.bo_alignment; 1313 pitch = surface.level[0].pitch_bytes; 1314 tiling_flags = 0; 1315 switch (surface.level[0].mode) { 1316 case RADEON_SURF_MODE_2D: 1317 tiling_flags |= RADEON_TILING_MACRO; 1318 tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; 1319 tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; 1320 tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; 1321 tiling_flags |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT; 1322 break; 1323 case RADEON_SURF_MODE_1D: 1324 tiling_flags |= RADEON_TILING_MICRO; 1325 break; 1326 default: 1327 break; 1328 } 1329 info->front_surface = surface; 1330 } 1331 1332 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1333 "Allocate new frame buffer %dx%d stride %d\n", 1334 width, height, pitch / cpp); 1335 1336 old_width = scrn->virtualX; 1337 old_height = scrn->virtualY; 1338 old_pitch = scrn->displayWidth; 1339 old_fb_id = drmmode->fb_id; 1340 old_front = info->front_bo; 1341 1342 scrn->virtualX = width; 1343 scrn->virtualY = height; 1344 scrn->displayWidth = pitch / cpp; 1345 1346 info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, RADEON_GEM_DOMAIN_VRAM, 0); 1347 if (!info->front_bo) 1348 goto fail; 1349 1350#if X_BYTE_ORDER == X_BIG_ENDIAN 1351 switch (cpp) { 1352 case 4: 1353 tiling_flags |= RADEON_TILING_SWAP_32BIT; 1354 break; 1355 case 2: 1356 tiling_flags |= RADEON_TILING_SWAP_16BIT; 1357 break; 1358 } 1359#endif 1360 if (tiling_flags) 1361 radeon_bo_set_tiling(info->front_bo, tiling_flags, pitch); 1362 1363 ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, 1364 scrn->bitsPerPixel, pitch, 1365 info->front_bo->handle, 1366 &drmmode->fb_id); 1367 if (ret) 1368 goto fail; 1369 1370 if (!info->r600_shadow_fb) { 1371 radeon_set_pixmap_bo(ppix, info->front_bo); 1372 psurface = radeon_get_pixmap_surface(ppix); 1373 *psurface = info->front_surface; 1374 screen->ModifyPixmapHeader(ppix, 1375 width, height, -1, -1, pitch, NULL); 1376 } else { 1377 if (radeon_bo_map(info->front_bo, 1)) 1378 goto fail; 1379 fb_shadow = calloc(1, screen_size); 1380 if (fb_shadow == NULL) 1381 goto fail; 1382 free(info->fb_shadow); 1383 info->fb_shadow = fb_shadow; 1384 screen->ModifyPixmapHeader(ppix, 1385 width, height, -1, -1, pitch, 1386 info->fb_shadow); 1387 } 1388#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,9,99,1,0) 1389 scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr; 1390#endif 1391 1392 for (i = 0; i < xf86_config->num_crtc; i++) { 1393 xf86CrtcPtr crtc = xf86_config->crtc[i]; 1394 1395 if (!crtc->enabled) 1396 continue; 1397 1398 drmmode_set_mode_major(crtc, &crtc->mode, 1399 crtc->rotation, crtc->x, crtc->y); 1400 } 1401 1402 if (old_fb_id) 1403 drmModeRmFB(drmmode->fd, old_fb_id); 1404 if (old_front) 1405 radeon_bo_unref(old_front); 1406 1407 radeon_kms_update_vram_limit(scrn, screen_size); 1408 return TRUE; 1409 1410 fail: 1411 if (info->front_bo) 1412 radeon_bo_unref(info->front_bo); 1413 info->front_bo = old_front; 1414 scrn->virtualX = old_width; 1415 scrn->virtualY = old_height; 1416 scrn->displayWidth = old_pitch; 1417 drmmode->fb_id = old_fb_id; 1418 1419 return FALSE; 1420} 1421 1422static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { 1423 drmmode_xf86crtc_resize 1424}; 1425 1426static void 1427drmmode_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec, 1428 unsigned int tv_usec, void *event_data) 1429{ 1430 radeon_dri2_frame_event_handler(frame, tv_sec, tv_usec, event_data); 1431} 1432 1433static void 1434drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec, 1435 unsigned int tv_usec, void *event_data) 1436{ 1437 drmmode_flipevtcarrier_ptr flipcarrier = event_data; 1438 drmmode_flipdata_ptr flipdata = flipcarrier->flipdata; 1439 drmmode_ptr drmmode = flipdata->drmmode; 1440 1441 /* Is this the event whose info shall be delivered to higher level? */ 1442 if (flipcarrier->dispatch_me) { 1443 /* Yes: Cache msc, ust for later delivery. */ 1444 flipdata->fe_frame = frame; 1445 flipdata->fe_tv_sec = tv_sec; 1446 flipdata->fe_tv_usec = tv_usec; 1447 } 1448 free(flipcarrier); 1449 1450 /* Last crtc completed flip? */ 1451 flipdata->flip_count--; 1452 if (flipdata->flip_count > 0) 1453 return; 1454 1455 /* Release framebuffer */ 1456 drmModeRmFB(drmmode->fd, flipdata->old_fb_id); 1457 1458 if (flipdata->event_data == NULL) 1459 return; 1460 1461 /* Deliver cached msc, ust from reference crtc to flip event handler */ 1462 radeon_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec, 1463 flipdata->fe_tv_usec, flipdata->event_data); 1464 1465 free(flipdata); 1466} 1467 1468 1469static void 1470drm_wakeup_handler(pointer data, int err, pointer p) 1471{ 1472 drmmode_ptr drmmode = data; 1473 fd_set *read_mask = p; 1474 1475 if (err >= 0 && FD_ISSET(drmmode->fd, read_mask)) { 1476 drmHandleEvent(drmmode->fd, &drmmode->event_context); 1477 } 1478} 1479 1480Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) 1481{ 1482 xf86CrtcConfigPtr xf86_config; 1483 int i, num_dvi = 0, num_hdmi = 0; 1484 1485 xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); 1486 xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1487 1488 drmmode->scrn = pScrn; 1489 drmmode->cpp = cpp; 1490 drmmode->mode_res = drmModeGetResources(drmmode->fd); 1491 if (!drmmode->mode_res) 1492 return FALSE; 1493 1494 xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height); 1495 for (i = 0; i < drmmode->mode_res->count_crtcs; i++) 1496 if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i) 1497 drmmode_crtc_init(pScrn, drmmode, i); 1498 1499 for (i = 0; i < drmmode->mode_res->count_connectors; i++) 1500 drmmode_output_init(pScrn, drmmode, i, &num_dvi, &num_hdmi); 1501 1502 /* workout clones */ 1503 drmmode_clones_init(pScrn, drmmode); 1504 1505 xf86InitialConfiguration(pScrn, TRUE); 1506 1507 drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION; 1508 drmmode->event_context.vblank_handler = drmmode_vblank_handler; 1509 drmmode->event_context.page_flip_handler = drmmode_flip_handler; 1510 1511 return TRUE; 1512} 1513 1514void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 1515{ 1516 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1517 RADEONInfoPtr info = RADEONPTR(pScrn); 1518 1519 if (pRADEONEnt->fd_wakeup_registered != serverGeneration && 1520 info->dri->pKernelDRMVersion->version_minor >= 4) { 1521 AddGeneralSocket(drmmode->fd); 1522 RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, 1523 drm_wakeup_handler, drmmode); 1524 pRADEONEnt->fd_wakeup_registered = serverGeneration; 1525 } 1526} 1527 1528Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr) 1529{ 1530 drmmode->bufmgr = bufmgr; 1531 return TRUE; 1532} 1533 1534 1535 1536void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo) 1537{ 1538 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1539 xf86CrtcPtr crtc = xf86_config->crtc[id]; 1540 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1541 1542 drmmode_crtc->cursor_bo = bo; 1543} 1544 1545void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags) 1546{ 1547 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1548 xf86OutputPtr output = config->output[config->compat_output]; 1549 xf86CrtcPtr crtc = output->crtc; 1550 1551 if (crtc && crtc->enabled) { 1552 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, 1553 x, y); 1554 } 1555} 1556 1557Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 1558{ 1559 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1560 int c; 1561 1562 drmmode_copy_fb(pScrn, drmmode); 1563 1564 for (c = 0; c < config->num_crtc; c++) { 1565 xf86CrtcPtr crtc = config->crtc[c]; 1566 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1567 xf86OutputPtr output = NULL; 1568 int o; 1569 1570 /* Skip disabled CRTCs */ 1571 if (!crtc->enabled) { 1572 drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 1573 0, 0, 0, NULL, 0, NULL); 1574 continue; 1575 } 1576 1577 if (config->output[config->compat_output]->crtc == crtc) 1578 output = config->output[config->compat_output]; 1579 else 1580 { 1581 for (o = 0; o < config->num_output; o++) 1582 if (config->output[o]->crtc == crtc) 1583 { 1584 output = config->output[o]; 1585 break; 1586 } 1587 } 1588 /* paranoia */ 1589 if (!output) 1590 continue; 1591 1592 /* Mark that we'll need to re-set the mode for sure */ 1593 memset(&crtc->mode, 0, sizeof(crtc->mode)); 1594 if (!crtc->desiredMode.CrtcHDisplay) 1595 { 1596 DisplayModePtr mode = xf86OutputFindClosestMode (output, pScrn->currentMode); 1597 1598 if (!mode) 1599 return FALSE; 1600 crtc->desiredMode = *mode; 1601 crtc->desiredRotation = RR_Rotate_0; 1602 crtc->desiredX = 0; 1603 crtc->desiredY = 0; 1604 } 1605 1606 if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation, 1607 crtc->desiredX, crtc->desiredY)) 1608 return FALSE; 1609 } 1610 return TRUE; 1611} 1612 1613static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors, 1614 int *indices, LOCO *colors, VisualPtr pVisual) 1615{ 1616 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1617 uint16_t lut_r[256], lut_g[256], lut_b[256]; 1618 int index, j, i; 1619 int c; 1620 1621 for (c = 0; c < xf86_config->num_crtc; c++) { 1622 xf86CrtcPtr crtc = xf86_config->crtc[c]; 1623 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1624 1625 for (i = 0 ; i < 256; i++) { 1626 lut_r[i] = drmmode_crtc->lut_r[i] << 6; 1627 lut_g[i] = drmmode_crtc->lut_g[i] << 6; 1628 lut_b[i] = drmmode_crtc->lut_b[i] << 6; 1629 } 1630 1631 switch(pScrn->depth) { 1632 case 15: 1633 for (i = 0; i < numColors; i++) { 1634 index = indices[i]; 1635 for (j = 0; j < 8; j++) { 1636 lut_r[index * 8 + j] = colors[index].red << 6; 1637 lut_g[index * 8 + j] = colors[index].green << 6; 1638 lut_b[index * 8 + j] = colors[index].blue << 6; 1639 } 1640 } 1641 break; 1642 case 16: 1643 for (i = 0; i < numColors; i++) { 1644 index = indices[i]; 1645 1646 if (i <= 31) { 1647 for (j = 0; j < 8; j++) { 1648 lut_r[index * 8 + j] = colors[index].red << 6; 1649 lut_b[index * 8 + j] = colors[index].blue << 6; 1650 } 1651 } 1652 1653 for (j = 0; j < 4; j++) { 1654 lut_g[index * 4 + j] = colors[index].green << 6; 1655 } 1656 } 1657 break; 1658 default: 1659 for (i = 0; i < numColors; i++) { 1660 index = indices[i]; 1661 lut_r[index] = colors[index].red << 6; 1662 lut_g[index] = colors[index].green << 6; 1663 lut_b[index] = colors[index].blue << 6; 1664 } 1665 break; 1666 } 1667 1668 /* Make the change through RandR */ 1669#ifdef RANDR_12_INTERFACE 1670 if (crtc->randr_crtc) 1671 RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); 1672 else 1673#endif 1674 crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); 1675 } 1676} 1677 1678Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn) 1679{ 1680 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 1681 "Initializing kms color map\n"); 1682 if (!miCreateDefColormap(pScreen)) 1683 return FALSE; 1684 /* all radeons support 10 bit CLUTs */ 1685 if (!xf86HandleColormaps(pScreen, 256, 10, 1686 drmmode_load_palette, NULL, 1687 CMAP_PALETTED_TRUECOLOR 1688#if 0 /* This option messes up text mode! (eich@suse.de) */ 1689 | CMAP_LOAD_EVEN_IF_OFFSCREEN 1690#endif 1691 | CMAP_RELOAD_ON_MODE_SWITCH)) 1692 return FALSE; 1693 return TRUE; 1694} 1695 1696#ifdef HAVE_LIBUDEV 1697static void 1698drmmode_handle_uevents(int fd, void *closure) 1699{ 1700 drmmode_ptr drmmode = closure; 1701 ScrnInfoPtr scrn = drmmode->scrn; 1702 struct udev_device *dev; 1703 dev = udev_monitor_receive_device(drmmode->uevent_monitor); 1704 if (!dev) 1705 return; 1706 1707 RRGetInfo(screenInfo.screens[scrn->scrnIndex], TRUE); 1708 udev_device_unref(dev); 1709} 1710#endif 1711 1712void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode) 1713{ 1714#ifdef HAVE_LIBUDEV 1715 struct udev *u; 1716 struct udev_monitor *mon; 1717 1718 u = udev_new(); 1719 if (!u) 1720 return; 1721 mon = udev_monitor_new_from_netlink(u, "udev"); 1722 if (!mon) { 1723 udev_unref(u); 1724 return; 1725 } 1726 1727 if (udev_monitor_filter_add_match_subsystem_devtype(mon, 1728 "drm", 1729 "drm_minor") < 0 || 1730 udev_monitor_enable_receiving(mon) < 0) { 1731 udev_monitor_unref(mon); 1732 udev_unref(u); 1733 return; 1734 } 1735 1736 drmmode->uevent_handler = 1737 xf86AddGeneralHandler(udev_monitor_get_fd(mon), 1738 drmmode_handle_uevents, 1739 drmmode); 1740 1741 drmmode->uevent_monitor = mon; 1742#endif 1743} 1744 1745void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode) 1746{ 1747#ifdef HAVE_LIBUDEV 1748 if (drmmode->uevent_handler) { 1749 struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor); 1750 xf86RemoveGeneralHandler(drmmode->uevent_handler); 1751 1752 udev_monitor_unref(drmmode->uevent_monitor); 1753 udev_unref(u); 1754 } 1755#endif 1756} 1757 1758Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id) 1759{ 1760 RADEONInfoPtr info = RADEONPTR(scrn); 1761 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 1762 drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private; 1763 drmmode_ptr drmmode = drmmode_crtc->drmmode; 1764 unsigned int pitch; 1765 int i, old_fb_id; 1766 uint32_t tiling_flags = 0; 1767 int height, emitted = 0; 1768 drmmode_flipdata_ptr flipdata; 1769 drmmode_flipevtcarrier_ptr flipcarrier; 1770 1771 if (info->allowColorTiling) { 1772 if (info->ChipFamily >= CHIP_FAMILY_R600) 1773 tiling_flags |= RADEON_TILING_MICRO; 1774 else 1775 tiling_flags |= RADEON_TILING_MACRO; 1776 } 1777 1778 pitch = RADEON_ALIGN(scrn->displayWidth, drmmode_get_pitch_align(scrn, info->CurrentLayout.pixel_bytes, tiling_flags)) * 1779 info->CurrentLayout.pixel_bytes; 1780 height = RADEON_ALIGN(scrn->virtualY, drmmode_get_height_align(scrn, tiling_flags)); 1781 if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { 1782 pitch = info->front_surface.level[0].pitch_bytes; 1783 } 1784 1785 /* 1786 * Create a new handle for the back buffer 1787 */ 1788 old_fb_id = drmmode->fb_id; 1789 if (drmModeAddFB(drmmode->fd, scrn->virtualX, height, 1790 scrn->depth, scrn->bitsPerPixel, pitch, 1791 new_front->handle, &drmmode->fb_id)) 1792 goto error_out; 1793 1794 flipdata = calloc(1, sizeof(drmmode_flipdata_rec)); 1795 if (!flipdata) { 1796 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1797 "flip queue: data alloc failed.\n"); 1798 goto error_undo; 1799 } 1800 /* 1801 * Queue flips on all enabled CRTCs 1802 * Note that if/when we get per-CRTC buffers, we'll have to update this. 1803 * Right now it assumes a single shared fb across all CRTCs, with the 1804 * kernel fixing up the offset of each CRTC as necessary. 1805 * 1806 * Also, flips queued on disabled or incorrectly configured displays 1807 * may never complete; this is a configuration error. 1808 */ 1809 1810 flipdata->event_data = data; 1811 flipdata->drmmode = drmmode; 1812 1813 for (i = 0; i < config->num_crtc; i++) { 1814 if (!config->crtc[i]->enabled) 1815 continue; 1816 1817 flipdata->flip_count++; 1818 drmmode_crtc = config->crtc[i]->driver_private; 1819 1820 flipcarrier = calloc(1, sizeof(drmmode_flipevtcarrier_rec)); 1821 if (!flipcarrier) { 1822 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1823 "flip queue: carrier alloc failed.\n"); 1824 if (emitted == 0) 1825 free(flipdata); 1826 goto error_undo; 1827 } 1828 1829 /* Only the reference crtc will finally deliver its page flip 1830 * completion event. All other crtc's events will be discarded. 1831 */ 1832 flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id); 1833 flipcarrier->flipdata = flipdata; 1834 1835 if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 1836 drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) { 1837 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1838 "flip queue failed: %s\n", strerror(errno)); 1839 free(flipcarrier); 1840 if (emitted == 0) 1841 free(flipdata); 1842 goto error_undo; 1843 } 1844 emitted++; 1845 } 1846 1847 flipdata->old_fb_id = old_fb_id; 1848 return TRUE; 1849 1850error_undo: 1851 drmModeRmFB(drmmode->fd, drmmode->fb_id); 1852 drmmode->fb_id = old_fb_id; 1853 1854error_out: 1855 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", 1856 strerror(errno)); 1857 return FALSE; 1858} 1859 1860#endif 1861