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