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