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