drmmode_display.c revision ad43ddac
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 = xcalloc(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 525 526static void 527drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) 528{ 529 xf86CrtcPtr crtc; 530 drmmode_crtc_private_ptr drmmode_crtc; 531 532 crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs); 533 if (crtc == NULL) 534 return; 535 536 drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); 537 drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]); 538 drmmode_crtc->drmmode = drmmode; 539 crtc->driver_private = drmmode_crtc; 540 541 return; 542} 543 544static xf86OutputStatus 545drmmode_output_detect(xf86OutputPtr output) 546{ 547 /* go to the hw and retrieve a new output struct */ 548 drmmode_output_private_ptr drmmode_output = output->driver_private; 549 drmmode_ptr drmmode = drmmode_output->drmmode; 550 xf86OutputStatus status; 551 drmModeFreeConnector(drmmode_output->mode_output); 552 553 drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id); 554 555 switch (drmmode_output->mode_output->connection) { 556 case DRM_MODE_CONNECTED: 557 status = XF86OutputStatusConnected; 558 break; 559 case DRM_MODE_DISCONNECTED: 560 status = XF86OutputStatusDisconnected; 561 break; 562 default: 563 case DRM_MODE_UNKNOWNCONNECTION: 564 status = XF86OutputStatusUnknown; 565 break; 566 } 567 return status; 568} 569 570static Bool 571drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) 572{ 573 return MODE_OK; 574} 575 576static DisplayModePtr 577drmmode_output_get_modes(xf86OutputPtr output) 578{ 579 drmmode_output_private_ptr drmmode_output = output->driver_private; 580 drmModeConnectorPtr koutput = drmmode_output->mode_output; 581 drmmode_ptr drmmode = drmmode_output->drmmode; 582 int i; 583 DisplayModePtr Modes = NULL, Mode; 584 drmModePropertyPtr props; 585 586 /* look for an EDID property */ 587 for (i = 0; i < koutput->count_props; i++) { 588 props = drmModeGetProperty(drmmode->fd, koutput->props[i]); 589 if (props && (props->flags & DRM_MODE_PROP_BLOB)) { 590 if (!strcmp(props->name, "EDID")) { 591 if (drmmode_output->edid_blob) 592 drmModeFreePropertyBlob(drmmode_output->edid_blob); 593 drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]); 594 } 595 drmModeFreeProperty(props); 596 } 597 } 598 599 if (drmmode_output->edid_blob) 600 xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, drmmode_output->edid_blob->data)); 601 else 602 xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, NULL)); 603 604 /* modes should already be available */ 605 for (i = 0; i < koutput->count_modes; i++) { 606 Mode = xnfalloc(sizeof(DisplayModeRec)); 607 608 drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode); 609 Modes = xf86ModesAdd(Modes, Mode); 610 611 } 612 return Modes; 613} 614 615static void 616drmmode_output_destroy(xf86OutputPtr output) 617{ 618 drmmode_output_private_ptr drmmode_output = output->driver_private; 619 int i; 620 621 if (drmmode_output->edid_blob) 622 drmModeFreePropertyBlob(drmmode_output->edid_blob); 623 for (i = 0; i < drmmode_output->num_props; i++) { 624 drmModeFreeProperty(drmmode_output->props[i].mode_prop); 625 xfree(drmmode_output->props[i].atoms); 626 } 627 for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) { 628 drmModeFreeEncoder(drmmode_output->mode_encoders[i]); 629 xfree(drmmode_output->mode_encoders); 630 } 631 xfree(drmmode_output->props); 632 drmModeFreeConnector(drmmode_output->mode_output); 633 xfree(drmmode_output); 634 output->driver_private = NULL; 635} 636 637static void 638drmmode_output_dpms(xf86OutputPtr output, int mode) 639{ 640 drmmode_output_private_ptr drmmode_output = output->driver_private; 641 drmModeConnectorPtr koutput = drmmode_output->mode_output; 642 drmmode_ptr drmmode = drmmode_output->drmmode; 643 644 drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id, 645 drmmode_output->dpms_enum_id, mode); 646 return; 647} 648 649 650static Bool 651drmmode_property_ignore(drmModePropertyPtr prop) 652{ 653 if (!prop) 654 return TRUE; 655 /* ignore blob prop */ 656 if (prop->flags & DRM_MODE_PROP_BLOB) 657 return TRUE; 658 /* ignore standard property */ 659 if (!strcmp(prop->name, "EDID") || 660 !strcmp(prop->name, "DPMS")) 661 return TRUE; 662 663 return FALSE; 664} 665 666static void 667drmmode_output_create_resources(xf86OutputPtr output) 668{ 669 drmmode_output_private_ptr drmmode_output = output->driver_private; 670 drmModeConnectorPtr mode_output = drmmode_output->mode_output; 671 drmmode_ptr drmmode = drmmode_output->drmmode; 672 drmModePropertyPtr drmmode_prop; 673 int i, j, err; 674 675 drmmode_output->props = xcalloc(mode_output->count_props, sizeof(drmmode_prop_rec)); 676 if (!drmmode_output->props) 677 return; 678 679 drmmode_output->num_props = 0; 680 for (i = 0, j = 0; i < mode_output->count_props; i++) { 681 drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]); 682 if (drmmode_property_ignore(drmmode_prop)) { 683 drmModeFreeProperty(drmmode_prop); 684 continue; 685 } 686 drmmode_output->props[j].mode_prop = drmmode_prop; 687 drmmode_output->props[j].value = mode_output->prop_values[i]; 688 drmmode_output->num_props++; 689 j++; 690 } 691 692 for (i = 0; i < drmmode_output->num_props; i++) { 693 drmmode_prop_ptr p = &drmmode_output->props[i]; 694 drmmode_prop = p->mode_prop; 695 696 if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) { 697 INT32 range[2]; 698 699 p->num_atoms = 1; 700 p->atoms = xcalloc(p->num_atoms, sizeof(Atom)); 701 if (!p->atoms) 702 continue; 703 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); 704 range[0] = drmmode_prop->values[0]; 705 range[1] = drmmode_prop->values[1]; 706 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], 707 FALSE, TRUE, 708 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, 709 2, range); 710 if (err != 0) { 711 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 712 "RRConfigureOutputProperty error, %d\n", err); 713 } 714 err = RRChangeOutputProperty(output->randr_output, p->atoms[0], 715 XA_INTEGER, 32, PropModeReplace, 1, &p->value, FALSE, TRUE); 716 if (err != 0) { 717 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 718 "RRChangeOutputProperty error, %d\n", err); 719 } 720 } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) { 721 p->num_atoms = drmmode_prop->count_enums + 1; 722 p->atoms = xcalloc(p->num_atoms, sizeof(Atom)); 723 if (!p->atoms) 724 continue; 725 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); 726 for (j = 1; j <= drmmode_prop->count_enums; j++) { 727 struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1]; 728 p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE); 729 } 730 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], 731 FALSE, FALSE, 732 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, 733 p->num_atoms - 1, (INT32 *)&p->atoms[1]); 734 if (err != 0) { 735 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 736 "RRConfigureOutputProperty error, %d\n", err); 737 } 738 for (j = 0; j < drmmode_prop->count_enums; j++) 739 if (drmmode_prop->enums[j].value == p->value) 740 break; 741 /* there's always a matching value */ 742 err = RRChangeOutputProperty(output->randr_output, p->atoms[0], 743 XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE); 744 if (err != 0) { 745 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 746 "RRChangeOutputProperty error, %d\n", err); 747 } 748 } 749 } 750} 751 752static Bool 753drmmode_output_set_property(xf86OutputPtr output, Atom property, 754 RRPropertyValuePtr value) 755{ 756 drmmode_output_private_ptr drmmode_output = output->driver_private; 757 drmmode_ptr drmmode = drmmode_output->drmmode; 758 int i; 759 760 for (i = 0; i < drmmode_output->num_props; i++) { 761 drmmode_prop_ptr p = &drmmode_output->props[i]; 762 763 if (p->atoms[0] != property) 764 continue; 765 766 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { 767 uint32_t val; 768 769 if (value->type != XA_INTEGER || value->format != 32 || 770 value->size != 1) 771 return FALSE; 772 val = *(uint32_t *)value->data; 773 774 drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, 775 p->mode_prop->prop_id, (uint64_t)val); 776 return TRUE; 777 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { 778 Atom atom; 779 const char *name; 780 int j; 781 782 if (value->type != XA_ATOM || value->format != 32 || value->size != 1) 783 return FALSE; 784 memcpy(&atom, value->data, 4); 785 name = NameForAtom(atom); 786 787 /* search for matching name string, then set its value down */ 788 for (j = 0; j < p->mode_prop->count_enums; j++) { 789 if (!strcmp(p->mode_prop->enums[j].name, name)) { 790 drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, 791 p->mode_prop->prop_id, p->mode_prop->enums[j].value); 792 return TRUE; 793 } 794 } 795 } 796 } 797 798 return TRUE; 799} 800 801static Bool 802drmmode_output_get_property(xf86OutputPtr output, Atom property) 803{ 804 return TRUE; 805} 806 807static const xf86OutputFuncsRec drmmode_output_funcs = { 808 .dpms = drmmode_output_dpms, 809 .create_resources = drmmode_output_create_resources, 810#ifdef RANDR_12_INTERFACE 811 .set_property = drmmode_output_set_property, 812 .get_property = drmmode_output_get_property, 813#endif 814#if 0 815 816 .save = drmmode_crt_save, 817 .restore = drmmode_crt_restore, 818 .mode_fixup = drmmode_crt_mode_fixup, 819 .prepare = drmmode_output_prepare, 820 .mode_set = drmmode_crt_mode_set, 821 .commit = drmmode_output_commit, 822#endif 823 .detect = drmmode_output_detect, 824 .mode_valid = drmmode_output_mode_valid, 825 826 .get_modes = drmmode_output_get_modes, 827 .destroy = drmmode_output_destroy 828}; 829 830static int subpixel_conv_table[7] = { 0, SubPixelUnknown, 831 SubPixelHorizontalRGB, 832 SubPixelHorizontalBGR, 833 SubPixelVerticalRGB, 834 SubPixelVerticalBGR, 835 SubPixelNone }; 836 837const char *output_names[] = { "None", 838 "VGA", 839 "DVI", 840 "DVI", 841 "DVI", 842 "Composite", 843 "S-video", 844 "LVDS", 845 "CTV", 846 "DIN", 847 "DisplayPort", 848 "HDMI", 849 "HDMI", 850 "TV", 851 "eDP" 852}; 853 854static void 855drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) 856{ 857 RADEONInfoPtr info = RADEONPTR(pScrn); 858 xf86OutputPtr output; 859 drmModeConnectorPtr koutput; 860 drmModeEncoderPtr *kencoders = NULL; 861 drmmode_output_private_ptr drmmode_output; 862 drmModePropertyPtr props; 863 char name[32]; 864 int i; 865 const char *s; 866 867 koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]); 868 if (!koutput) 869 return; 870 871 kencoders = xcalloc(sizeof(drmModeEncoderPtr), koutput->count_encoders); 872 if (!kencoders) { 873 goto out_free_encoders; 874 } 875 876 for (i = 0; i < koutput->count_encoders; i++) { 877 kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]); 878 if (!kencoders[i]) { 879 goto out_free_encoders; 880 } 881 } 882 883 /* need to do smart conversion here for compat with non-kms ATI driver */ 884 if (koutput->connector_type_id == 1) { 885 switch(koutput->connector_type) { 886 case DRM_MODE_CONNECTOR_VGA: 887 case DRM_MODE_CONNECTOR_DVII: 888 case DRM_MODE_CONNECTOR_DVID: 889 case DRM_MODE_CONNECTOR_DVIA: 890 case DRM_MODE_CONNECTOR_HDMIA: 891 case DRM_MODE_CONNECTOR_HDMIB: 892 case DRM_MODE_CONNECTOR_DisplayPort: 893 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1); 894 break; 895 default: 896 snprintf(name, 32, "%s", output_names[koutput->connector_type]); 897 break; 898 } 899 } else { 900 snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1); 901 } 902 903 if (xf86IsEntityShared(pScrn->entityList[0])) { 904 if ((s = xf86GetOptValString(info->Options, OPTION_ZAPHOD_HEADS))) { 905 if (!RADEONZaphodStringMatches(pScrn, s, name)) 906 goto out_free_encoders; 907 } else { 908 if (info->IsPrimary && (num != 0)) 909 goto out_free_encoders; 910 else if (info->IsSecondary && (num != 1)) 911 goto out_free_encoders; 912 } 913 } 914 915 output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name); 916 if (!output) { 917 goto out_free_encoders; 918 } 919 920 drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1); 921 if (!drmmode_output) { 922 xf86OutputDestroy(output); 923 goto out_free_encoders; 924 } 925 926 drmmode_output->output_id = drmmode->mode_res->connectors[num]; 927 drmmode_output->mode_output = koutput; 928 drmmode_output->mode_encoders = kencoders; 929 drmmode_output->drmmode = drmmode; 930 output->mm_width = koutput->mmWidth; 931 output->mm_height = koutput->mmHeight; 932 933 output->subpixel_order = subpixel_conv_table[koutput->subpixel]; 934 output->driver_private = drmmode_output; 935 936 output->possible_crtcs = 0xf; 937 for (i = 0; i < koutput->count_encoders; i++) { 938 output->possible_crtcs &= kencoders[i]->possible_crtcs; 939 } 940 /* work out the possible clones later */ 941 output->possible_clones = 0; 942 943 for (i = 0; i < koutput->count_props; i++) { 944 props = drmModeGetProperty(drmmode->fd, koutput->props[i]); 945 if (props && (props->flags && DRM_MODE_PROP_ENUM)) { 946 if (!strcmp(props->name, "DPMS")) { 947 drmmode_output->dpms_enum_id = koutput->props[i]; 948 drmModeFreeProperty(props); 949 break; 950 } 951 drmModeFreeProperty(props); 952 } 953 } 954 955 return; 956out_free_encoders: 957 if (kencoders){ 958 for (i = 0; i < koutput->count_encoders; i++) 959 drmModeFreeEncoder(kencoders[i]); 960 xfree(kencoders); 961 } 962 drmModeFreeConnector(koutput); 963 964} 965 966uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output) 967{ 968 drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout; 969 int i; 970 xf86OutputPtr clone_output; 971 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 972 int index_mask = 0; 973 974 if (drmmode_output->enc_clone_mask == 0) 975 return index_mask; 976 977 for (i = 0; i < xf86_config->num_output; i++) { 978 clone_output = xf86_config->output[i]; 979 clone_drmout = clone_output->driver_private; 980 if (output == clone_output) 981 continue; 982 983 if (clone_drmout->enc_mask == 0) 984 continue; 985 if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask) 986 index_mask |= (1 << i); 987 } 988 return index_mask; 989} 990 991 992static void 993drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode) 994{ 995 int i, j; 996 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 997 998 for (i = 0; i < xf86_config->num_output; i++) { 999 xf86OutputPtr output = xf86_config->output[i]; 1000 drmmode_output_private_ptr drmmode_output; 1001 1002 drmmode_output = output->driver_private; 1003 drmmode_output->enc_clone_mask = 0xff; 1004 /* and all the possible encoder clones for this output together */ 1005 for (j = 0; j < drmmode_output->mode_output->count_encoders; j++) 1006 { 1007 int k; 1008 for (k = 0; k < drmmode->mode_res->count_encoders; k++) { 1009 if (drmmode->mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id) 1010 drmmode_output->enc_mask |= (1 << k); 1011 } 1012 1013 drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones; 1014 } 1015 } 1016 1017 for (i = 0; i < xf86_config->num_output; i++) { 1018 xf86OutputPtr output = xf86_config->output[i]; 1019 output->possible_clones = find_clones(scrn, output); 1020 } 1021} 1022 1023static Bool 1024drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) 1025{ 1026 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1027 drmmode_crtc_private_ptr 1028 drmmode_crtc = xf86_config->crtc[0]->driver_private; 1029 drmmode_ptr drmmode = drmmode_crtc->drmmode; 1030 RADEONInfoPtr info = RADEONPTR(scrn); 1031 struct radeon_bo *old_front = NULL; 1032 Bool ret; 1033 ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; 1034 uint32_t old_fb_id; 1035 int i, pitch, old_width, old_height, old_pitch; 1036 int screen_size; 1037 int cpp = info->CurrentLayout.pixel_bytes; 1038 struct radeon_bo *front_bo; 1039 uint32_t tiling_flags = 0; 1040 PixmapPtr ppix = screen->GetScreenPixmap(screen); 1041 void *fb_shadow; 1042 1043 if (scrn->virtualX == width && scrn->virtualY == height) 1044 return TRUE; 1045 1046 front_bo = info->front_bo; 1047 radeon_cs_flush_indirect(scrn); 1048 1049 if (front_bo) 1050 radeon_bo_wait(front_bo); 1051 1052 pitch = RADEON_ALIGN(width, 64); 1053 height = RADEON_ALIGN(height, 16); 1054 1055 screen_size = pitch * height * cpp; 1056 1057 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1058 "Allocate new frame buffer %dx%d stride %d\n", 1059 width, height, pitch); 1060 1061 old_width = scrn->virtualX; 1062 old_height = scrn->virtualY; 1063 old_pitch = scrn->displayWidth; 1064 old_fb_id = drmmode->fb_id; 1065 old_front = info->front_bo; 1066 1067 scrn->virtualX = width; 1068 scrn->virtualY = height; 1069 scrn->displayWidth = pitch; 1070 1071 info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, 0, RADEON_GEM_DOMAIN_VRAM, 0); 1072 if (!info->front_bo) 1073 goto fail; 1074 1075 if (info->allowColorTiling) 1076 tiling_flags |= RADEON_TILING_MACRO; 1077#if X_BYTE_ORDER == X_BIG_ENDIAN 1078 switch (cpp) { 1079 case 4: 1080 tiling_flags |= RADEON_TILING_SWAP_32BIT; 1081 break; 1082 case 2: 1083 tiling_flags |= RADEON_TILING_SWAP_16BIT; 1084 break; 1085 } 1086#endif 1087 if (tiling_flags) 1088 radeon_bo_set_tiling(info->front_bo, 1089 tiling_flags | RADEON_TILING_SURFACE, pitch * cpp); 1090 1091 ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, 1092 scrn->bitsPerPixel, pitch * cpp, 1093 info->front_bo->handle, 1094 &drmmode->fb_id); 1095 if (ret) 1096 goto fail; 1097 1098 if (!info->r600_shadow_fb) { 1099 radeon_set_pixmap_bo(screen->GetScreenPixmap(screen), info->front_bo); 1100 screen->ModifyPixmapHeader(screen->GetScreenPixmap(screen), 1101 width, height, -1, -1, pitch * cpp, NULL); 1102 } else { 1103 if (radeon_bo_map(info->front_bo, 1)) 1104 goto fail; 1105 fb_shadow = xcalloc(1, screen_size); 1106 if (fb_shadow == NULL) 1107 goto fail; 1108 xfree(info->fb_shadow); 1109 info->fb_shadow = fb_shadow; 1110 screen->ModifyPixmapHeader(screen->GetScreenPixmap(screen), 1111 width, height, -1, -1, pitch * cpp, 1112 info->fb_shadow); 1113 } 1114 scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr; 1115 1116 // xf86DrvMsg(scrn->scrnIndex, X_INFO, "New front buffer at 0x%lx\n", 1117 // info->front_bo-); 1118 1119 for (i = 0; i < xf86_config->num_crtc; i++) { 1120 xf86CrtcPtr crtc = xf86_config->crtc[i]; 1121 1122 if (!crtc->enabled) 1123 continue; 1124 1125 drmmode_set_mode_major(crtc, &crtc->mode, 1126 crtc->rotation, crtc->x, crtc->y); 1127 } 1128 1129 if (old_fb_id) 1130 drmModeRmFB(drmmode->fd, old_fb_id); 1131 if (old_front) 1132 radeon_bo_unref(old_front); 1133 1134 radeon_kms_update_vram_limit(scrn, screen_size); 1135 return TRUE; 1136 1137 fail: 1138 if (info->front_bo) 1139 radeon_bo_unref(info->front_bo); 1140 info->front_bo = old_front; 1141 scrn->virtualX = old_width; 1142 scrn->virtualY = old_height; 1143 scrn->displayWidth = old_pitch; 1144 drmmode->fb_id = old_fb_id; 1145 1146 return FALSE; 1147} 1148 1149static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { 1150 drmmode_xf86crtc_resize 1151}; 1152 1153 1154Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) 1155{ 1156 xf86CrtcConfigPtr xf86_config; 1157 int i; 1158 1159 xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); 1160 xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1161 1162 drmmode->cpp = cpp; 1163 drmmode->mode_res = drmModeGetResources(drmmode->fd); 1164 if (!drmmode->mode_res) 1165 return FALSE; 1166 1167 xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height); 1168 for (i = 0; i < drmmode->mode_res->count_crtcs; i++) 1169 if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i) 1170 drmmode_crtc_init(pScrn, drmmode, i); 1171 1172 for (i = 0; i < drmmode->mode_res->count_connectors; i++) 1173 drmmode_output_init(pScrn, drmmode, i); 1174 1175 /* workout clones */ 1176 drmmode_clones_init(pScrn, drmmode); 1177 1178 xf86InitialConfiguration(pScrn, TRUE); 1179 1180 return TRUE; 1181} 1182 1183Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr) 1184{ 1185 drmmode->bufmgr = bufmgr; 1186 return TRUE; 1187} 1188 1189 1190 1191void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo) 1192{ 1193 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1194 xf86CrtcPtr crtc = xf86_config->crtc[id]; 1195 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1196 1197 drmmode_crtc->cursor_bo = bo; 1198} 1199 1200void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags) 1201{ 1202 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1203 xf86OutputPtr output = config->output[config->compat_output]; 1204 xf86CrtcPtr crtc = output->crtc; 1205 1206 if (crtc && crtc->enabled) { 1207 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, 1208 x, y); 1209 } 1210} 1211 1212Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode) 1213{ 1214 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1215 int c; 1216 1217 drmmode_copy_fb(pScrn, drmmode); 1218 1219 for (c = 0; c < config->num_crtc; c++) { 1220 xf86CrtcPtr crtc = config->crtc[c]; 1221 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1222 xf86OutputPtr output = NULL; 1223 int o; 1224 1225 /* Skip disabled CRTCs */ 1226 if (!crtc->enabled) { 1227 drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 1228 0, 0, 0, NULL, 0, NULL); 1229 continue; 1230 } 1231 1232 if (config->output[config->compat_output]->crtc == crtc) 1233 output = config->output[config->compat_output]; 1234 else 1235 { 1236 for (o = 0; o < config->num_output; o++) 1237 if (config->output[o]->crtc == crtc) 1238 { 1239 output = config->output[o]; 1240 break; 1241 } 1242 } 1243 /* paranoia */ 1244 if (!output) 1245 continue; 1246 1247 /* Mark that we'll need to re-set the mode for sure */ 1248 memset(&crtc->mode, 0, sizeof(crtc->mode)); 1249 if (!crtc->desiredMode.CrtcHDisplay) 1250 { 1251 DisplayModePtr mode = xf86OutputFindClosestMode (output, pScrn->currentMode); 1252 1253 if (!mode) 1254 return FALSE; 1255 crtc->desiredMode = *mode; 1256 crtc->desiredRotation = RR_Rotate_0; 1257 crtc->desiredX = 0; 1258 crtc->desiredY = 0; 1259 } 1260 1261 if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation, 1262 crtc->desiredX, crtc->desiredY)) 1263 return FALSE; 1264 } 1265 return TRUE; 1266} 1267 1268static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors, 1269 int *indices, LOCO *colors, VisualPtr pVisual) 1270{ 1271 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1272 uint16_t lut_r[256], lut_g[256], lut_b[256]; 1273 int index, j, i; 1274 int c; 1275 1276 for (c = 0; c < xf86_config->num_crtc; c++) { 1277 xf86CrtcPtr crtc = xf86_config->crtc[c]; 1278 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1279 1280 for (i = 0 ; i < 256; i++) { 1281 lut_r[i] = drmmode_crtc->lut_r[i] << 6; 1282 lut_g[i] = drmmode_crtc->lut_g[i] << 6; 1283 lut_b[i] = drmmode_crtc->lut_b[i] << 6; 1284 } 1285 1286 switch(pScrn->depth) { 1287 case 15: 1288 for (i = 0; i < numColors; i++) { 1289 index = indices[i]; 1290 for (j = 0; j < 8; j++) { 1291 lut_r[index * 8 + j] = colors[index].red << 6; 1292 lut_g[index * 8 + j] = colors[index].green << 6; 1293 lut_b[index * 8 + j] = colors[index].blue << 6; 1294 } 1295 } 1296 break; 1297 case 16: 1298 for (i = 0; i < numColors; i++) { 1299 index = indices[i]; 1300 1301 if (i <= 31) { 1302 for (j = 0; j < 8; j++) { 1303 lut_r[index * 8 + j] = colors[index].red << 6; 1304 lut_b[index * 8 + j] = colors[index].blue << 6; 1305 } 1306 } 1307 1308 for (j = 0; j < 4; j++) { 1309 lut_g[index * 4 + j] = colors[index].green << 6; 1310 } 1311 } 1312 break; 1313 default: 1314 for (i = 0; i < numColors; i++) { 1315 index = indices[i]; 1316 lut_r[index] = colors[index].red << 6; 1317 lut_g[index] = colors[index].green << 6; 1318 lut_b[index] = colors[index].blue << 6; 1319 } 1320 break; 1321 } 1322 1323 /* Make the change through RandR */ 1324#ifdef RANDR_12_INTERFACE 1325 if (crtc->randr_crtc) 1326 RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); 1327 else 1328#endif 1329 crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); 1330 } 1331} 1332 1333Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn) 1334{ 1335 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 1336 "Initializing kms color map\n"); 1337 if (!miCreateDefColormap(pScreen)) 1338 return FALSE; 1339 /* all radeons support 10 bit CLUTs */ 1340 if (!xf86HandleColormaps(pScreen, 256, 10, 1341 drmmode_load_palette, NULL, 1342 CMAP_PALETTED_TRUECOLOR 1343#if 0 /* This option messes up text mode! (eich@suse.de) */ 1344 | CMAP_LOAD_EVEN_IF_OFFSCREEN 1345#endif 1346 | CMAP_RELOAD_ON_MODE_SWITCH)) 1347 return FALSE; 1348 return TRUE; 1349} 1350#endif 1351