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