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