intel_display.c revision 03b705cf
1/* 2 * Copyright © 2007 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Dave Airlie <airlied@redhat.com> 25 * 26 */ 27 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include <sys/types.h> 33#include <sys/stat.h> 34#include <sys/poll.h> 35#include <fcntl.h> 36#include <unistd.h> 37#include <errno.h> 38#include <poll.h> 39#include <sys/ioctl.h> 40 41#include "xorgVersion.h" 42 43#include "intel.h" 44#include "intel_bufmgr.h" 45#include "intel_options.h" 46#include "xf86drm.h" 47#include "xf86drmMode.h" 48#include "X11/Xatom.h" 49#include "X11/extensions/dpmsconst.h" 50#include "xf86DDC.h" 51#include "fb.h" 52#include "uxa.h" 53 54#include "intel_glamor.h" 55 56#define KNOWN_MODE_FLAGS ((1<<14)-1) 57 58struct intel_mode { 59 int fd; 60 uint32_t fb_id; 61 drmModeResPtr mode_res; 62 int cpp; 63 64 drmEventContext event_context; 65 DRI2FrameEventPtr flip_info; 66 int old_fb_id; 67 int flip_count; 68 unsigned int fe_frame; 69 unsigned int fe_tv_sec; 70 unsigned int fe_tv_usec; 71 72 struct list outputs; 73 struct list crtcs; 74}; 75 76struct intel_pageflip { 77 struct intel_mode *mode; 78 Bool dispatch_me; 79}; 80 81struct intel_crtc { 82 struct intel_mode *mode; 83 drmModeModeInfo kmode; 84 drmModeCrtcPtr mode_crtc; 85 int pipe; 86 dri_bo *cursor; 87 dri_bo *rotate_bo; 88 uint32_t rotate_pitch; 89 uint32_t rotate_fb_id; 90 xf86CrtcPtr crtc; 91 struct list link; 92 PixmapPtr scanout_pixmap; 93 uint32_t scanout_fb_id; 94}; 95 96struct intel_property { 97 drmModePropertyPtr mode_prop; 98 uint64_t value; 99 int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */ 100 Atom *atoms; 101}; 102 103struct intel_output { 104 struct intel_mode *mode; 105 int output_id; 106 drmModeConnectorPtr mode_output; 107 drmModeEncoderPtr mode_encoder; 108 drmModePropertyBlobPtr edid_blob; 109 int num_props; 110 struct intel_property *props; 111 void *private_data; 112 113 Bool has_panel_limits; 114 int panel_hdisplay; 115 int panel_vdisplay; 116 117 int dpms_mode; 118 const char *backlight_iface; 119 int backlight_active_level; 120 int backlight_max; 121 xf86OutputPtr output; 122 struct list link; 123}; 124 125static void 126intel_output_dpms(xf86OutputPtr output, int mode); 127 128static void 129intel_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode); 130 131static inline int 132crtc_id(struct intel_crtc *crtc) 133{ 134 return crtc->mode_crtc->crtc_id; 135} 136 137#ifdef __OpenBSD__ 138 139#include <dev/wscons/wsconsio.h> 140#include "xf86Priv.h" 141 142static void 143intel_output_backlight_set(xf86OutputPtr output, int level) 144{ 145 struct intel_output *intel_output = output->driver_private; 146 struct wsdisplay_param param; 147 148 if (level > intel_output->backlight_max) 149 level = intel_output->backlight_max; 150 if (! intel_output->backlight_iface || level < 0) 151 return; 152 153 param.param = WSDISPLAYIO_PARAM_BRIGHTNESS; 154 param.curval = level; 155 if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_SETPARAM, ¶m) == -1) { 156 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 157 "Failed to set backlight level: %s\n", 158 strerror(errno)); 159 } 160} 161 162static int 163intel_output_backlight_get(xf86OutputPtr output) 164{ 165 struct wsdisplay_param param; 166 167 param.param = WSDISPLAYIO_PARAM_BRIGHTNESS; 168 if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_GETPARAM, ¶m) == -1) { 169 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 170 "Failed to get backlight level: %s\n", 171 strerror(errno)); 172 return -1; 173 } 174 175 return param.curval; 176} 177 178static void 179intel_output_backlight_init(xf86OutputPtr output) 180{ 181 struct intel_output *intel_output = output->driver_private; 182 struct wsdisplay_param param; 183 184 param.param = WSDISPLAYIO_PARAM_BRIGHTNESS; 185 if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_GETPARAM, ¶m) == -1) { 186 intel_output->backlight_iface = NULL; 187 return; 188 } 189 190 intel_output->backlight_iface = "wscons"; 191 intel_output->backlight_max = param.max; 192 intel_output->backlight_active_level = param.curval; 193} 194 195#else 196 197#define BACKLIGHT_CLASS "/sys/class/backlight" 198 199/* 200 * List of available kernel interfaces in priority order 201 */ 202static const char *backlight_interfaces[] = { 203 "dell_backlight", 204 "gmux_backlight", 205 "asus-laptop", 206 "asus-nb-wmi", 207 "eeepc", 208 "thinkpad_screen", 209 "mbp_backlight", 210 "fujitsu-laptop", 211 "sony", 212 "samsung", 213 "acpi_video1", /* finally fallback to the generic acpi drivers */ 214 "acpi_video0", 215 "intel_backlight", 216 NULL, 217}; 218/* 219 * Must be long enough for BACKLIGHT_CLASS + '/' + longest in above table + 220 * '/' + "max_backlight" 221 */ 222#define BACKLIGHT_PATH_LEN 80 223/* Enough for 10 digits of backlight + '\n' + '\0' */ 224#define BACKLIGHT_VALUE_LEN 12 225 226static void 227intel_output_backlight_set(xf86OutputPtr output, int level) 228{ 229 struct intel_output *intel_output = output->driver_private; 230 char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN]; 231 int fd, len, ret; 232 233 if (level > intel_output->backlight_max) 234 level = intel_output->backlight_max; 235 if (! intel_output->backlight_iface || level < 0) 236 return; 237 238 len = snprintf(val, BACKLIGHT_VALUE_LEN, "%d\n", level); 239 sprintf(path, "%s/%s/brightness", 240 BACKLIGHT_CLASS, intel_output->backlight_iface); 241 fd = open(path, O_RDWR); 242 if (fd == -1) { 243 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "failed to open %s for backlight " 244 "control: %s\n", path, strerror(errno)); 245 return; 246 } 247 248 ret = write(fd, val, len); 249 if (ret == -1) { 250 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "write to %s for backlight " 251 "control failed: %s\n", path, strerror(errno)); 252 } 253 254 close(fd); 255} 256 257static int 258intel_output_backlight_get(xf86OutputPtr output) 259{ 260 struct intel_output *intel_output = output->driver_private; 261 char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN]; 262 int fd, level; 263 264 sprintf(path, "%s/%s/actual_brightness", 265 BACKLIGHT_CLASS, intel_output->backlight_iface); 266 fd = open(path, O_RDONLY); 267 if (fd == -1) { 268 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "failed to open %s " 269 "for backlight control: %s\n", path, strerror(errno)); 270 return -1; 271 } 272 273 memset(val, 0, sizeof(val)); 274 if (read(fd, val, BACKLIGHT_VALUE_LEN) == -1) { 275 close(fd); 276 return -1; 277 } 278 279 close(fd); 280 281 level = atoi(val); 282 if (level > intel_output->backlight_max) 283 level = intel_output->backlight_max; 284 if (level < 0) 285 level = -1; 286 return level; 287} 288 289static int 290intel_output_backlight_get_max(xf86OutputPtr output) 291{ 292 struct intel_output *intel_output = output->driver_private; 293 char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN]; 294 int fd, max = 0; 295 296 sprintf(path, "%s/%s/max_brightness", 297 BACKLIGHT_CLASS, intel_output->backlight_iface); 298 fd = open(path, O_RDONLY); 299 if (fd == -1) { 300 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "failed to open %s " 301 "for backlight control: %s\n", path, strerror(errno)); 302 return -1; 303 } 304 305 memset(val, 0, sizeof(val)); 306 if (read(fd, val, BACKLIGHT_VALUE_LEN) == -1) { 307 close(fd); 308 return -1; 309 } 310 311 close(fd); 312 313 max = atoi(val); 314 if (max <= 0) 315 max = -1; 316 return max; 317} 318 319static void 320intel_output_backlight_init(xf86OutputPtr output) 321{ 322 struct intel_output *intel_output = output->driver_private; 323 intel_screen_private *intel = intel_get_screen_private(output->scrn); 324 char path[BACKLIGHT_PATH_LEN]; 325 struct stat buf; 326 char *str; 327 int i; 328 329 str = xf86GetOptValString(intel->Options, OPTION_BACKLIGHT); 330 if (str != NULL) { 331 sprintf(path, "%s/%s", BACKLIGHT_CLASS, str); 332 if (!stat(path, &buf)) { 333 intel_output->backlight_iface = str; 334 intel_output->backlight_max = intel_output_backlight_get_max(output); 335 if (intel_output->backlight_max > 0) { 336 intel_output->backlight_active_level = intel_output_backlight_get(output); 337 xf86DrvMsg(output->scrn->scrnIndex, X_CONFIG, 338 "found backlight control interface %s\n", path); 339 return; 340 } 341 } 342 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 343 "unrecognised backlight control interface %s\n", str); 344 } 345 346 for (i = 0; backlight_interfaces[i] != NULL; i++) { 347 sprintf(path, "%s/%s", BACKLIGHT_CLASS, backlight_interfaces[i]); 348 if (!stat(path, &buf)) { 349 intel_output->backlight_iface = backlight_interfaces[i]; 350 intel_output->backlight_max = intel_output_backlight_get_max(output); 351 if (intel_output->backlight_max > 0) { 352 intel_output->backlight_active_level = intel_output_backlight_get(output); 353 xf86DrvMsg(output->scrn->scrnIndex, X_PROBED, 354 "found backlight control interface %s\n", path); 355 return; 356 } 357 } 358 } 359 intel_output->backlight_iface = NULL; 360} 361 362#endif 363 364static void 365mode_from_kmode(ScrnInfoPtr scrn, 366 drmModeModeInfoPtr kmode, 367 DisplayModePtr mode) 368{ 369 memset(mode, 0, sizeof(DisplayModeRec)); 370 mode->status = MODE_OK; 371 372 mode->Clock = kmode->clock; 373 374 mode->HDisplay = kmode->hdisplay; 375 mode->HSyncStart = kmode->hsync_start; 376 mode->HSyncEnd = kmode->hsync_end; 377 mode->HTotal = kmode->htotal; 378 mode->HSkew = kmode->hskew; 379 380 mode->VDisplay = kmode->vdisplay; 381 mode->VSyncStart = kmode->vsync_start; 382 mode->VSyncEnd = kmode->vsync_end; 383 mode->VTotal = kmode->vtotal; 384 mode->VScan = kmode->vscan; 385 386 mode->Flags = kmode->flags; 387 mode->name = strdup(kmode->name); 388 389 if (kmode->type & DRM_MODE_TYPE_DRIVER) 390 mode->type = M_T_DRIVER; 391 if (kmode->type & DRM_MODE_TYPE_PREFERRED) 392 mode->type |= M_T_PREFERRED; 393 394 if (mode->status == MODE_OK && kmode->flags & ~KNOWN_MODE_FLAGS) 395 mode->status = MODE_BAD; /* unknown flags => unhandled */ 396 397 xf86SetModeCrtc (mode, scrn->adjustFlags); 398} 399 400static void 401mode_to_kmode(ScrnInfoPtr scrn, 402 drmModeModeInfoPtr kmode, 403 DisplayModePtr mode) 404{ 405 memset(kmode, 0, sizeof(*kmode)); 406 407 kmode->clock = mode->Clock; 408 kmode->hdisplay = mode->HDisplay; 409 kmode->hsync_start = mode->HSyncStart; 410 kmode->hsync_end = mode->HSyncEnd; 411 kmode->htotal = mode->HTotal; 412 kmode->hskew = mode->HSkew; 413 414 kmode->vdisplay = mode->VDisplay; 415 kmode->vsync_start = mode->VSyncStart; 416 kmode->vsync_end = mode->VSyncEnd; 417 kmode->vtotal = mode->VTotal; 418 kmode->vscan = mode->VScan; 419 420 kmode->flags = mode->Flags; 421 if (mode->name) 422 strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN); 423 kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; 424} 425 426static void 427intel_crtc_dpms(xf86CrtcPtr crtc, int mode) 428{ 429} 430 431void 432intel_mode_disable_unused_functions(ScrnInfoPtr scrn) 433{ 434 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 435 struct intel_mode *mode = intel_get_screen_private(scrn)->modes; 436 int i; 437 438 /* Force off for consistency between kernel and ddx */ 439 for (i = 0; i < xf86_config->num_crtc; i++) { 440 xf86CrtcPtr crtc = xf86_config->crtc[i]; 441 if (!crtc->enabled) 442 drmModeSetCrtc(mode->fd, crtc_id(crtc->driver_private), 443 0, 0, 0, NULL, 0, NULL); 444 } 445} 446 447static Bool 448intel_crtc_apply(xf86CrtcPtr crtc) 449{ 450 ScrnInfoPtr scrn = crtc->scrn; 451 struct intel_crtc *intel_crtc = crtc->driver_private; 452 struct intel_mode *mode = intel_crtc->mode; 453 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 454 uint32_t *output_ids; 455 int output_count = 0; 456 int fb_id, x, y; 457 int i, ret = FALSE; 458 459 output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); 460 if (!output_ids) 461 return FALSE; 462 463 for (i = 0; i < xf86_config->num_output; i++) { 464 xf86OutputPtr output = xf86_config->output[i]; 465 struct intel_output *intel_output; 466 467 if (output->crtc != crtc) 468 continue; 469 470 intel_output = output->driver_private; 471 output_ids[output_count] = 472 intel_output->mode_output->connector_id; 473 output_count++; 474 } 475 476 if (!intel_crtc->scanout_fb_id) { 477#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0) 478 if (!xf86CrtcRotate(crtc, mode, rotation)) 479 goto done; 480#else 481 if (!xf86CrtcRotate(crtc)) 482 goto done; 483#endif 484 } 485 486#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0) 487 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, 488 crtc->gamma_blue, crtc->gamma_size); 489#endif 490 491 x = crtc->x; 492 y = crtc->y; 493 fb_id = mode->fb_id; 494 if (intel_crtc->rotate_fb_id) { 495 fb_id = intel_crtc->rotate_fb_id; 496 x = 0; 497 y = 0; 498 } else if (intel_crtc->scanout_fb_id && intel_crtc->scanout_pixmap->drawable.width >= crtc->mode.HDisplay && intel_crtc->scanout_pixmap->drawable.height >= crtc->mode.VDisplay) { 499 fb_id = intel_crtc->scanout_fb_id; 500 x = 0; 501 y = 0; 502 } 503 ret = drmModeSetCrtc(mode->fd, crtc_id(intel_crtc), 504 fb_id, x, y, output_ids, output_count, 505 &intel_crtc->kmode); 506 if (ret) { 507 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, 508 "failed to set mode: %s\n", strerror(-ret)); 509 ret = FALSE; 510 } else { 511 ret = TRUE; 512 513 /* Force DPMS to On for all outputs, which the kernel will have done 514 * with the mode set. Also, restore the backlight level 515 */ 516 for (i = 0; i < xf86_config->num_output; i++) { 517 xf86OutputPtr output = xf86_config->output[i]; 518 struct intel_output *intel_output; 519 520 if (output->crtc != crtc) 521 continue; 522 523 intel_output = output->driver_private; 524 intel_output_dpms_backlight(output, intel_output->dpms_mode, DPMSModeOn); 525 intel_output->dpms_mode = DPMSModeOn; 526 } 527 } 528 529 if (scrn->pScreen) 530 xf86_reload_cursors(scrn->pScreen); 531 532done: 533 free(output_ids); 534 return ret; 535} 536 537static Bool 538intel_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, 539 Rotation rotation, int x, int y) 540{ 541 ScrnInfoPtr scrn = crtc->scrn; 542 intel_screen_private *intel = intel_get_screen_private(scrn); 543 struct intel_crtc *intel_crtc = crtc->driver_private; 544 struct intel_mode *intel_mode = intel_crtc->mode; 545 int saved_x, saved_y; 546 Rotation saved_rotation; 547 DisplayModeRec saved_mode; 548 int ret = TRUE; 549 unsigned int pitch = scrn->displayWidth * intel->cpp; 550 551 if (intel_mode->fb_id == 0) { 552 ret = drmModeAddFB(intel_mode->fd, 553 scrn->virtualX, scrn->virtualY, 554 scrn->depth, scrn->bitsPerPixel, 555 pitch, intel->front_buffer->handle, 556 &intel_mode->fb_id); 557 if (ret < 0) { 558 ErrorF("failed to add fb\n"); 559 return FALSE; 560 } 561 562 drm_intel_bo_disable_reuse(intel->front_buffer); 563 } 564 565 saved_mode = crtc->mode; 566 saved_x = crtc->x; 567 saved_y = crtc->y; 568 saved_rotation = crtc->rotation; 569 570 crtc->mode = *mode; 571 crtc->x = x; 572 crtc->y = y; 573 crtc->rotation = rotation; 574 575 intel_glamor_flush(intel); 576 intel_batch_submit(crtc->scrn); 577 578 mode_to_kmode(crtc->scrn, &intel_crtc->kmode, mode); 579 ret = intel_crtc_apply(crtc); 580 if (!ret) { 581 crtc->x = saved_x; 582 crtc->y = saved_y; 583 crtc->rotation = saved_rotation; 584 crtc->mode = saved_mode; 585 } 586 return ret; 587} 588 589static void 590intel_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) 591{ 592 593} 594 595static void 596intel_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) 597{ 598 struct intel_crtc *intel_crtc = crtc->driver_private; 599 struct intel_mode *mode = intel_crtc->mode; 600 601 drmModeMoveCursor(mode->fd, crtc_id(intel_crtc), x, y); 602} 603 604static void 605intel_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image) 606{ 607 struct intel_crtc *intel_crtc = crtc->driver_private; 608 int ret; 609 610 ret = dri_bo_subdata(intel_crtc->cursor, 0, 64*64*4, image); 611 if (ret) 612 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, 613 "failed to set cursor: %s\n", strerror(-ret)); 614} 615 616static void 617intel_crtc_hide_cursor(xf86CrtcPtr crtc) 618{ 619 struct intel_crtc *intel_crtc = crtc->driver_private; 620 struct intel_mode *mode = intel_crtc->mode; 621 622 drmModeSetCursor(mode->fd, crtc_id(intel_crtc), 0, 64, 64); 623} 624 625static void 626intel_crtc_show_cursor(xf86CrtcPtr crtc) 627{ 628 struct intel_crtc *intel_crtc = crtc->driver_private; 629 struct intel_mode *mode = intel_crtc->mode; 630 631 drmModeSetCursor(mode->fd, crtc_id(intel_crtc), 632 intel_crtc->cursor->handle, 64, 64); 633} 634 635static void * 636intel_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) 637{ 638 ScrnInfoPtr scrn = crtc->scrn; 639 struct intel_crtc *intel_crtc = crtc->driver_private; 640 struct intel_mode *mode = intel_crtc->mode; 641 unsigned long rotate_pitch; 642 uint32_t tiling; 643 int ret; 644 645 intel_crtc->rotate_bo = intel_allocate_framebuffer(scrn, 646 width, height, 647 mode->cpp, 648 &rotate_pitch, 649 &tiling); 650 651 if (!intel_crtc->rotate_bo) { 652 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, 653 "Couldn't allocate shadow memory for rotated CRTC\n"); 654 return NULL; 655 } 656 657 ret = drmModeAddFB(mode->fd, width, height, crtc->scrn->depth, 658 crtc->scrn->bitsPerPixel, rotate_pitch, 659 intel_crtc->rotate_bo->handle, 660 &intel_crtc->rotate_fb_id); 661 if (ret) { 662 ErrorF("failed to add rotate fb\n"); 663 drm_intel_bo_unreference(intel_crtc->rotate_bo); 664 return NULL; 665 } 666 667 drm_intel_bo_disable_reuse(intel_crtc->rotate_bo); 668 669 intel_crtc->rotate_pitch = rotate_pitch; 670 return intel_crtc->rotate_bo; 671} 672 673static PixmapPtr 674intel_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) 675{ 676 ScrnInfoPtr scrn = crtc->scrn; 677 intel_screen_private *intel = intel_get_screen_private(scrn); 678 struct intel_crtc *intel_crtc = crtc->driver_private; 679 PixmapPtr rotate_pixmap; 680 681 if (!data) { 682 data = intel_crtc_shadow_allocate (crtc, width, height); 683 if (!data) { 684 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 685 "Couldn't allocate shadow pixmap for rotated CRTC\n"); 686 return NULL; 687 } 688 } 689 if (intel_crtc->rotate_bo == NULL) { 690 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 691 "Couldn't allocate shadow pixmap for rotated CRTC\n"); 692 return NULL; 693 } 694 695 rotate_pixmap = GetScratchPixmapHeader(scrn->pScreen, 696 width, height, 697 scrn->depth, 698 scrn->bitsPerPixel, 699 intel_crtc->rotate_pitch, 700 NULL); 701 702 if (rotate_pixmap == NULL) { 703 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 704 "Couldn't allocate shadow pixmap for rotated CRTC\n"); 705 return NULL; 706 } 707 708 intel_set_pixmap_bo(rotate_pixmap, intel_crtc->rotate_bo); 709 710 intel->shadow_present = TRUE; 711 712 return rotate_pixmap; 713} 714 715static void 716intel_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) 717{ 718 ScrnInfoPtr scrn = crtc->scrn; 719 intel_screen_private *intel = intel_get_screen_private(scrn); 720 struct intel_crtc *intel_crtc = crtc->driver_private; 721 struct intel_mode *mode = intel_crtc->mode; 722 723 if (rotate_pixmap) { 724 intel_set_pixmap_bo(rotate_pixmap, NULL); 725 FreeScratchPixmapHeader(rotate_pixmap); 726 } 727 728 if (data) { 729 /* Be sure to sync acceleration before the memory gets 730 * unbound. */ 731 drmModeRmFB(mode->fd, intel_crtc->rotate_fb_id); 732 intel_crtc->rotate_fb_id = 0; 733 734 dri_bo_unreference(intel_crtc->rotate_bo); 735 intel_crtc->rotate_bo = NULL; 736 } 737 738 intel->shadow_present = FALSE; 739} 740 741static void 742intel_crtc_gamma_set(xf86CrtcPtr crtc, 743 CARD16 *red, CARD16 *green, CARD16 *blue, int size) 744{ 745 struct intel_crtc *intel_crtc = crtc->driver_private; 746 struct intel_mode *mode = intel_crtc->mode; 747 748 drmModeCrtcSetGamma(mode->fd, crtc_id(intel_crtc), 749 size, red, green, blue); 750} 751 752static void 753intel_crtc_destroy(xf86CrtcPtr crtc) 754{ 755 struct intel_crtc *intel_crtc = crtc->driver_private; 756 757 if (intel_crtc->cursor) { 758 drmModeSetCursor(intel_crtc->mode->fd, crtc_id(intel_crtc), 0, 64, 64); 759 drm_intel_bo_unreference(intel_crtc->cursor); 760 intel_crtc->cursor = NULL; 761 } 762 763 list_del(&intel_crtc->link); 764 free(intel_crtc); 765 766 crtc->driver_private = NULL; 767} 768 769#ifdef INTEL_PIXMAP_SHARING 770static Bool 771intel_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) 772{ 773 struct intel_crtc *intel_crtc = crtc->driver_private; 774 ScrnInfoPtr scrn = crtc->scrn; 775 intel_screen_private *intel = intel_get_screen_private(scrn); 776 dri_bo *bo; 777 778 if (ppix == intel_crtc->scanout_pixmap) 779 return TRUE; 780 781 if (!ppix) { 782 intel_crtc->scanout_pixmap = NULL; 783 if (intel_crtc->scanout_fb_id) { 784 drmModeRmFB(intel->drmSubFD, intel_crtc->scanout_fb_id); 785 intel_crtc->scanout_fb_id = 0; 786 } 787 return TRUE; 788 } 789 790 bo = intel_get_pixmap_bo(ppix); 791 if (intel->front_buffer) { 792 ErrorF("have front buffer\n"); 793 } 794 795 drm_intel_bo_disable_reuse(bo); 796 797 intel_crtc->scanout_pixmap = ppix; 798 return drmModeAddFB(intel->drmSubFD, ppix->drawable.width, 799 ppix->drawable.height, ppix->drawable.depth, 800 ppix->drawable.bitsPerPixel, ppix->devKind, 801 bo->handle, &intel_crtc->scanout_fb_id) == 0; 802} 803#endif 804 805static const xf86CrtcFuncsRec intel_crtc_funcs = { 806 .dpms = intel_crtc_dpms, 807 .set_mode_major = intel_crtc_set_mode_major, 808 .set_cursor_colors = intel_crtc_set_cursor_colors, 809 .set_cursor_position = intel_crtc_set_cursor_position, 810 .show_cursor = intel_crtc_show_cursor, 811 .hide_cursor = intel_crtc_hide_cursor, 812 .load_cursor_argb = intel_crtc_load_cursor_argb, 813 .shadow_create = intel_crtc_shadow_create, 814 .shadow_allocate = intel_crtc_shadow_allocate, 815 .shadow_destroy = intel_crtc_shadow_destroy, 816 .gamma_set = intel_crtc_gamma_set, 817 .destroy = intel_crtc_destroy, 818#ifdef INTEL_PIXMAP_SHARING 819 .set_scanout_pixmap = intel_set_scanout_pixmap, 820#endif 821}; 822 823static void 824intel_crtc_init(ScrnInfoPtr scrn, struct intel_mode *mode, int num) 825{ 826 intel_screen_private *intel = intel_get_screen_private(scrn); 827 xf86CrtcPtr crtc; 828 struct intel_crtc *intel_crtc; 829 830 intel_crtc = calloc(sizeof(struct intel_crtc), 1); 831 if (intel_crtc == NULL) 832 return; 833 834 crtc = xf86CrtcCreate(scrn, &intel_crtc_funcs); 835 if (crtc == NULL) { 836 free(intel_crtc); 837 return; 838 } 839 840 intel_crtc->mode_crtc = drmModeGetCrtc(mode->fd, 841 mode->mode_res->crtcs[num]); 842 if (intel_crtc->mode_crtc == NULL) { 843 free(intel_crtc); 844 return; 845 } 846 847 intel_crtc->mode = mode; 848 crtc->driver_private = intel_crtc; 849 850 intel_crtc->pipe = drm_intel_get_pipe_from_crtc_id(intel->bufmgr, 851 crtc_id(intel_crtc)); 852 853 intel_crtc->cursor = drm_intel_bo_alloc(intel->bufmgr, "ARGB cursor", 854 4*64*64, 4096); 855 856 intel_crtc->crtc = crtc; 857 list_add(&intel_crtc->link, &mode->crtcs); 858} 859 860static Bool 861is_panel(int type) 862{ 863 return (type == DRM_MODE_CONNECTOR_LVDS || 864 type == DRM_MODE_CONNECTOR_eDP); 865} 866 867static xf86OutputStatus 868intel_output_detect(xf86OutputPtr output) 869{ 870 /* go to the hw and retrieve a new output struct */ 871 struct intel_output *intel_output = output->driver_private; 872 struct intel_mode *mode = intel_output->mode; 873 xf86OutputStatus status; 874 875 drmModeFreeConnector(intel_output->mode_output); 876 intel_output->mode_output = 877 drmModeGetConnector(mode->fd, intel_output->output_id); 878 if (intel_output->mode_output == NULL) { 879 /* and hope we are safe everywhere else */ 880 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 881 "drmModeGetConnector failed, reporting output disconnected\n"); 882 return XF86OutputStatusDisconnected; 883 } 884 885 switch (intel_output->mode_output->connection) { 886 case DRM_MODE_CONNECTED: 887 status = XF86OutputStatusConnected; 888 break; 889 case DRM_MODE_DISCONNECTED: 890 status = XF86OutputStatusDisconnected; 891 break; 892 default: 893 case DRM_MODE_UNKNOWNCONNECTION: 894 status = XF86OutputStatusUnknown; 895 break; 896 } 897 return status; 898} 899 900static Bool 901intel_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) 902{ 903 struct intel_output *intel_output = output->driver_private; 904 905 /* 906 * If the connector type is a panel, we will use the panel limit to 907 * verfiy whether the mode is valid. 908 */ 909 if (intel_output->has_panel_limits) { 910 if (pModes->HDisplay > intel_output->panel_hdisplay || 911 pModes->VDisplay > intel_output->panel_vdisplay) 912 return MODE_PANEL; 913 } 914 915 return MODE_OK; 916} 917 918static void 919intel_output_attach_edid(xf86OutputPtr output) 920{ 921 struct intel_output *intel_output = output->driver_private; 922 drmModeConnectorPtr koutput = intel_output->mode_output; 923 struct intel_mode *mode = intel_output->mode; 924 xf86MonPtr mon = NULL; 925 int i; 926 927 /* look for an EDID property */ 928 for (i = 0; i < koutput->count_props; i++) { 929 drmModePropertyPtr props; 930 931 props = drmModeGetProperty(mode->fd, koutput->props[i]); 932 if (!props) 933 continue; 934 935 if (!(props->flags & DRM_MODE_PROP_BLOB)) { 936 drmModeFreeProperty(props); 937 continue; 938 } 939 940 if (!strcmp(props->name, "EDID")) { 941 drmModeFreePropertyBlob(intel_output->edid_blob); 942 intel_output->edid_blob = 943 drmModeGetPropertyBlob(mode->fd, 944 koutput->prop_values[i]); 945 } 946 drmModeFreeProperty(props); 947 } 948 949 if (intel_output->edid_blob) { 950 mon = xf86InterpretEDID(output->scrn->scrnIndex, 951 intel_output->edid_blob->data); 952 953 if (mon && intel_output->edid_blob->length > 128) 954 mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA; 955 } 956 957 xf86OutputSetEDID(output, mon); 958} 959 960static DisplayModePtr 961intel_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes) 962{ 963 xf86MonPtr mon = output->MonInfo; 964 965 if (!mon || !GTF_SUPPORTED(mon->features.msc)) { 966 DisplayModePtr i, m, p = NULL; 967 int max_x = 0, max_y = 0; 968 float max_vrefresh = 0.0; 969 970 for (m = modes; m; m = m->next) { 971 if (m->type & M_T_PREFERRED) 972 p = m; 973 max_x = max(max_x, m->HDisplay); 974 max_y = max(max_y, m->VDisplay); 975 max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m)); 976 } 977 978 max_vrefresh = max(max_vrefresh, 60.0); 979 max_vrefresh *= (1 + SYNC_TOLERANCE); 980 981#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,0,0) 982 m = xf86GetDefaultModes(); 983#else 984 m = xf86GetDefaultModes(0,0); 985#endif 986 987 xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0); 988 989 for (i = m; i; i = i->next) { 990 if (xf86ModeVRefresh(i) > max_vrefresh) 991 i->status = MODE_VSYNC; 992 if (p && i->HDisplay >= p->HDisplay && 993 i->VDisplay >= p->VDisplay && 994 xf86ModeVRefresh(i) >= xf86ModeVRefresh(p)) 995 i->status = MODE_VSYNC; 996 } 997 998 xf86PruneInvalidModes(output->scrn, &m, FALSE); 999 1000 modes = xf86ModesAdd(modes, m); 1001 } 1002 1003 return modes; 1004} 1005 1006static DisplayModePtr 1007intel_output_get_modes(xf86OutputPtr output) 1008{ 1009 struct intel_output *intel_output = output->driver_private; 1010 drmModeConnectorPtr koutput = intel_output->mode_output; 1011 DisplayModePtr Modes = NULL; 1012 int i; 1013 1014 intel_output_attach_edid(output); 1015 1016 /* modes should already be available */ 1017 for (i = 0; i < koutput->count_modes; i++) { 1018 DisplayModePtr Mode; 1019 1020 Mode = calloc(1, sizeof(DisplayModeRec)); 1021 if (Mode) { 1022 mode_from_kmode(output->scrn, &koutput->modes[i], Mode); 1023 Modes = xf86ModesAdd(Modes, Mode); 1024 } 1025 } 1026 1027 /* 1028 * If the connector type is a panel, we will traverse the kernel mode to 1029 * get the panel limit. And then add all the standard modes to fake 1030 * the fullscreen experience. 1031 * If it is incorrect, please fix me. 1032 */ 1033 intel_output->has_panel_limits = FALSE; 1034 if (is_panel(koutput->connector_type)) { 1035 for (i = 0; i < koutput->count_modes; i++) { 1036 drmModeModeInfo *mode_ptr; 1037 1038 mode_ptr = &koutput->modes[i]; 1039 if (mode_ptr->hdisplay > intel_output->panel_hdisplay) 1040 intel_output->panel_hdisplay = mode_ptr->hdisplay; 1041 if (mode_ptr->vdisplay > intel_output->panel_vdisplay) 1042 intel_output->panel_vdisplay = mode_ptr->vdisplay; 1043 } 1044 1045 intel_output->has_panel_limits = 1046 intel_output->panel_hdisplay && 1047 intel_output->panel_vdisplay; 1048 1049 Modes = intel_output_panel_edid(output, Modes); 1050 } 1051 1052 return Modes; 1053} 1054 1055static void 1056intel_output_destroy(xf86OutputPtr output) 1057{ 1058 struct intel_output *intel_output = output->driver_private; 1059 int i; 1060 1061 drmModeFreePropertyBlob(intel_output->edid_blob); 1062 1063 for (i = 0; i < intel_output->num_props; i++) { 1064 drmModeFreeProperty(intel_output->props[i].mode_prop); 1065 free(intel_output->props[i].atoms); 1066 } 1067 free(intel_output->props); 1068 1069 drmModeFreeConnector(intel_output->mode_output); 1070 intel_output->mode_output = NULL; 1071 1072 list_del(&intel_output->link); 1073 free(intel_output); 1074 1075 output->driver_private = NULL; 1076} 1077 1078static void 1079intel_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode) 1080{ 1081 struct intel_output *intel_output = output->driver_private; 1082 1083 if (!intel_output->backlight_iface) 1084 return; 1085 1086 if (mode == DPMSModeOn) { 1087 /* If we're going from off->on we may need to turn on the backlight. */ 1088 if (oldmode != DPMSModeOn) 1089 intel_output_backlight_set(output, 1090 intel_output->backlight_active_level); 1091 } else { 1092 /* Only save the current backlight value if we're going from on to off. */ 1093 if (oldmode == DPMSModeOn) 1094 intel_output->backlight_active_level = intel_output_backlight_get(output); 1095 intel_output_backlight_set(output, 0); 1096 } 1097} 1098 1099static void 1100intel_output_dpms(xf86OutputPtr output, int dpms) 1101{ 1102 struct intel_output *intel_output = output->driver_private; 1103 drmModeConnectorPtr koutput = intel_output->mode_output; 1104 struct intel_mode *mode = intel_output->mode; 1105 int i; 1106 1107 for (i = 0; i < koutput->count_props; i++) { 1108 drmModePropertyPtr props; 1109 1110 props = drmModeGetProperty(mode->fd, koutput->props[i]); 1111 if (!props) 1112 continue; 1113 1114 if (!strcmp(props->name, "DPMS")) { 1115 /* Make sure to reverse the order between on and off. */ 1116 if (dpms == DPMSModeOff) 1117 intel_output_dpms_backlight(output, 1118 intel_output->dpms_mode, 1119 dpms); 1120 drmModeConnectorSetProperty(mode->fd, 1121 intel_output->output_id, 1122 props->prop_id, 1123 dpms); 1124 if (dpms != DPMSModeOff) 1125 intel_output_dpms_backlight(output, 1126 intel_output->dpms_mode, 1127 dpms); 1128 intel_output->dpms_mode = dpms; 1129 drmModeFreeProperty(props); 1130 return; 1131 } 1132 1133 drmModeFreeProperty(props); 1134 } 1135} 1136 1137int 1138intel_output_dpms_status(xf86OutputPtr output) 1139{ 1140 struct intel_output *intel_output = output->driver_private; 1141 return intel_output->dpms_mode; 1142} 1143 1144static Bool 1145intel_property_ignore(drmModePropertyPtr prop) 1146{ 1147 if (!prop) 1148 return TRUE; 1149 1150 /* ignore blob prop */ 1151 if (prop->flags & DRM_MODE_PROP_BLOB) 1152 return TRUE; 1153 1154 /* ignore standard property */ 1155 if (!strcmp(prop->name, "EDID") || 1156 !strcmp(prop->name, "DPMS")) 1157 return TRUE; 1158 1159 return FALSE; 1160} 1161 1162static void 1163intel_output_create_ranged_atom(xf86OutputPtr output, Atom *atom, 1164 const char *name, INT32 min, INT32 max, 1165 uint64_t value, Bool immutable) 1166{ 1167 int err; 1168 INT32 atom_range[2]; 1169 1170 atom_range[0] = min; 1171 atom_range[1] = max; 1172 1173 *atom = MakeAtom(name, strlen(name), TRUE); 1174 1175 err = RRConfigureOutputProperty(output->randr_output, *atom, FALSE, 1176 TRUE, immutable, 2, atom_range); 1177 if (err != 0) 1178 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1179 "RRConfigureOutputProperty error, %d\n", err); 1180 1181 err = RRChangeOutputProperty(output->randr_output, *atom, XA_INTEGER, 1182 32, PropModeReplace, 1, &value, FALSE, 1183 TRUE); 1184 if (err != 0) 1185 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1186 "RRChangeOutputProperty error, %d\n", err); 1187} 1188 1189#define BACKLIGHT_NAME "Backlight" 1190#define BACKLIGHT_DEPRECATED_NAME "BACKLIGHT" 1191static Atom backlight_atom, backlight_deprecated_atom; 1192 1193static void 1194intel_output_create_resources(xf86OutputPtr output) 1195{ 1196 struct intel_output *intel_output = output->driver_private; 1197 drmModeConnectorPtr mode_output = intel_output->mode_output; 1198 struct intel_mode *mode = intel_output->mode; 1199 int i, j, err; 1200 1201 intel_output->props = calloc(mode_output->count_props, 1202 sizeof(struct intel_property)); 1203 if (!intel_output->props) 1204 return; 1205 1206 intel_output->num_props = 0; 1207 for (i = j = 0; i < mode_output->count_props; i++) { 1208 drmModePropertyPtr drmmode_prop; 1209 1210 drmmode_prop = drmModeGetProperty(mode->fd, 1211 mode_output->props[i]); 1212 if (intel_property_ignore(drmmode_prop)) { 1213 drmModeFreeProperty(drmmode_prop); 1214 continue; 1215 } 1216 1217 intel_output->props[j].mode_prop = drmmode_prop; 1218 intel_output->props[j].value = mode_output->prop_values[i]; 1219 j++; 1220 } 1221 intel_output->num_props = j; 1222 1223 for (i = 0; i < intel_output->num_props; i++) { 1224 struct intel_property *p = &intel_output->props[i]; 1225 drmModePropertyPtr drmmode_prop = p->mode_prop; 1226 1227 if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) { 1228 p->num_atoms = 1; 1229 p->atoms = calloc(p->num_atoms, sizeof(Atom)); 1230 if (!p->atoms) 1231 continue; 1232 1233 intel_output_create_ranged_atom(output, &p->atoms[0], 1234 drmmode_prop->name, 1235 drmmode_prop->values[0], 1236 drmmode_prop->values[1], 1237 p->value, 1238 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE); 1239 1240 } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) { 1241 p->num_atoms = drmmode_prop->count_enums + 1; 1242 p->atoms = calloc(p->num_atoms, sizeof(Atom)); 1243 if (!p->atoms) 1244 continue; 1245 1246 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE); 1247 for (j = 1; j <= drmmode_prop->count_enums; j++) { 1248 struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1]; 1249 p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE); 1250 } 1251 1252 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0], 1253 FALSE, FALSE, 1254 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE, 1255 p->num_atoms - 1, (INT32 *)&p->atoms[1]); 1256 if (err != 0) { 1257 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1258 "RRConfigureOutputProperty error, %d\n", err); 1259 } 1260 1261 for (j = 0; j < drmmode_prop->count_enums; j++) 1262 if (drmmode_prop->enums[j].value == p->value) 1263 break; 1264 /* there's always a matching value */ 1265 err = RRChangeOutputProperty(output->randr_output, p->atoms[0], 1266 XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE); 1267 if (err != 0) { 1268 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1269 "RRChangeOutputProperty error, %d\n", err); 1270 } 1271 } 1272 } 1273 1274 if (intel_output->backlight_iface) { 1275 /* Set up the backlight property, which takes effect 1276 * immediately and accepts values only within the 1277 * backlight_range. 1278 */ 1279 intel_output_create_ranged_atom(output, &backlight_atom, 1280 BACKLIGHT_NAME, 0, 1281 intel_output->backlight_max, 1282 intel_output->backlight_active_level, 1283 FALSE); 1284 intel_output_create_ranged_atom(output, 1285 &backlight_deprecated_atom, 1286 BACKLIGHT_DEPRECATED_NAME, 0, 1287 intel_output->backlight_max, 1288 intel_output->backlight_active_level, 1289 FALSE); 1290 } 1291} 1292 1293static Bool 1294intel_output_set_property(xf86OutputPtr output, Atom property, 1295 RRPropertyValuePtr value) 1296{ 1297 struct intel_output *intel_output = output->driver_private; 1298 struct intel_mode *mode = intel_output->mode; 1299 int i; 1300 1301 if (property == backlight_atom || property == backlight_deprecated_atom) { 1302 INT32 val; 1303 1304 if (value->type != XA_INTEGER || value->format != 32 || 1305 value->size != 1) 1306 { 1307 return FALSE; 1308 } 1309 1310 val = *(INT32 *)value->data; 1311 if (val < 0 || val > intel_output->backlight_max) 1312 return FALSE; 1313 1314 if (intel_output->dpms_mode == DPMSModeOn) 1315 intel_output_backlight_set(output, val); 1316 intel_output->backlight_active_level = val; 1317 return TRUE; 1318 } 1319 1320 for (i = 0; i < intel_output->num_props; i++) { 1321 struct intel_property *p = &intel_output->props[i]; 1322 1323 if (p->atoms[0] != property) 1324 continue; 1325 1326 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { 1327 uint32_t val; 1328 1329 if (value->type != XA_INTEGER || value->format != 32 || 1330 value->size != 1) 1331 return FALSE; 1332 val = *(uint32_t *)value->data; 1333 1334 drmModeConnectorSetProperty(mode->fd, intel_output->output_id, 1335 p->mode_prop->prop_id, (uint64_t)val); 1336 return TRUE; 1337 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { 1338 Atom atom; 1339 const char *name; 1340 int j; 1341 1342 if (value->type != XA_ATOM || value->format != 32 || value->size != 1) 1343 return FALSE; 1344 memcpy(&atom, value->data, 4); 1345 name = NameForAtom(atom); 1346 if (name == NULL) 1347 return FALSE; 1348 1349 /* search for matching name string, then set its value down */ 1350 for (j = 0; j < p->mode_prop->count_enums; j++) { 1351 if (!strcmp(p->mode_prop->enums[j].name, name)) { 1352 drmModeConnectorSetProperty(mode->fd, intel_output->output_id, 1353 p->mode_prop->prop_id, p->mode_prop->enums[j].value); 1354 return TRUE; 1355 } 1356 } 1357 return FALSE; 1358 } 1359 } 1360 1361 /* We didn't recognise this property, just report success in order 1362 * to allow the set to continue, otherwise we break setting of 1363 * common properties like EDID. 1364 */ 1365 return TRUE; 1366} 1367 1368static Bool 1369intel_output_get_property(xf86OutputPtr output, Atom property) 1370{ 1371 struct intel_output *intel_output = output->driver_private; 1372 int err; 1373 1374 if (property == backlight_atom || property == backlight_deprecated_atom) { 1375 INT32 val; 1376 1377 if (! intel_output->backlight_iface) 1378 return FALSE; 1379 1380 val = intel_output_backlight_get(output); 1381 if (val < 0) 1382 return FALSE; 1383 1384 err = RRChangeOutputProperty(output->randr_output, property, 1385 XA_INTEGER, 32, PropModeReplace, 1, &val, 1386 FALSE, TRUE); 1387 if (err != 0) { 1388 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, 1389 "RRChangeOutputProperty error, %d\n", err); 1390 return FALSE; 1391 } 1392 1393 return TRUE; 1394 } 1395 1396 return FALSE; 1397} 1398 1399static const xf86OutputFuncsRec intel_output_funcs = { 1400 .create_resources = intel_output_create_resources, 1401#ifdef RANDR_12_INTERFACE 1402 .set_property = intel_output_set_property, 1403 .get_property = intel_output_get_property, 1404#endif 1405 .dpms = intel_output_dpms, 1406#if 0 1407 1408 .save = drmmode_crt_save, 1409 .restore = drmmode_crt_restore, 1410 .mode_fixup = drmmode_crt_mode_fixup, 1411 .prepare = intel_output_prepare, 1412 .mode_set = drmmode_crt_mode_set, 1413 .commit = intel_output_commit, 1414#endif 1415 .detect = intel_output_detect, 1416 .mode_valid = intel_output_mode_valid, 1417 1418 .get_modes = intel_output_get_modes, 1419 .destroy = intel_output_destroy 1420}; 1421 1422static const int subpixel_conv_table[7] = { 1423 0, 1424 SubPixelUnknown, 1425 SubPixelHorizontalRGB, 1426 SubPixelHorizontalBGR, 1427 SubPixelVerticalRGB, 1428 SubPixelVerticalBGR, 1429 SubPixelNone 1430}; 1431 1432static const char *output_names[] = { 1433 "None", 1434 "VGA", 1435 "DVI", 1436 "DVI", 1437 "DVI", 1438 "Composite", 1439 "TV", 1440 "LVDS", 1441 "CTV", 1442 "DIN", 1443 "DP", 1444 "HDMI", 1445 "HDMI", 1446 "TV", 1447 "eDP", 1448}; 1449 1450static void 1451intel_output_init(ScrnInfoPtr scrn, struct intel_mode *mode, int num) 1452{ 1453 xf86OutputPtr output; 1454 drmModeConnectorPtr koutput; 1455 drmModeEncoderPtr kencoder; 1456 struct intel_output *intel_output; 1457 const char *output_name; 1458 char name[32]; 1459 1460 koutput = drmModeGetConnector(mode->fd, 1461 mode->mode_res->connectors[num]); 1462 if (!koutput) 1463 return; 1464 1465 kencoder = drmModeGetEncoder(mode->fd, koutput->encoders[0]); 1466 if (!kencoder) { 1467 drmModeFreeConnector(koutput); 1468 return; 1469 } 1470 1471 if (koutput->connector_type < ARRAY_SIZE(output_names)) 1472 output_name = output_names[koutput->connector_type]; 1473 else 1474 output_name = "UNKNOWN"; 1475 snprintf(name, 32, "%s%d", output_name, koutput->connector_type_id); 1476 1477 output = xf86OutputCreate (scrn, &intel_output_funcs, name); 1478 if (!output) { 1479 drmModeFreeEncoder(kencoder); 1480 drmModeFreeConnector(koutput); 1481 return; 1482 } 1483 1484 intel_output = calloc(sizeof(struct intel_output), 1); 1485 if (!intel_output) { 1486 xf86OutputDestroy(output); 1487 drmModeFreeConnector(koutput); 1488 drmModeFreeEncoder(kencoder); 1489 return; 1490 } 1491 1492 intel_output->output_id = mode->mode_res->connectors[num]; 1493 intel_output->mode_output = koutput; 1494 intel_output->mode_encoder = kencoder; 1495 intel_output->mode = mode; 1496 1497 output->mm_width = koutput->mmWidth; 1498 output->mm_height = koutput->mmHeight; 1499 1500 output->subpixel_order = subpixel_conv_table[koutput->subpixel]; 1501 output->driver_private = intel_output; 1502 1503 if (is_panel(koutput->connector_type)) 1504 intel_output_backlight_init(output); 1505 1506 output->possible_crtcs = kencoder->possible_crtcs; 1507 output->interlaceAllowed = TRUE; 1508 1509 intel_output->output = output; 1510 list_add(&intel_output->link, &mode->outputs); 1511} 1512 1513static Bool 1514intel_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) 1515{ 1516 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1517 struct intel_crtc *intel_crtc = xf86_config->crtc[0]->driver_private; 1518 struct intel_mode *mode = intel_crtc->mode; 1519 intel_screen_private *intel = intel_get_screen_private(scrn); 1520 drm_intel_bo *old_front = NULL; 1521 Bool ret; 1522 uint32_t old_fb_id; 1523 int i, old_width, old_height, old_pitch; 1524 unsigned long pitch; 1525 uint32_t tiling; 1526 ScreenPtr screen; 1527 1528 if (scrn->virtualX == width && scrn->virtualY == height) 1529 return TRUE; 1530 1531 intel_glamor_flush(intel); 1532 intel_batch_submit(scrn); 1533 1534 old_width = scrn->virtualX; 1535 old_height = scrn->virtualY; 1536 old_pitch = scrn->displayWidth; 1537 old_fb_id = mode->fb_id; 1538 old_front = intel->front_buffer; 1539 1540 if (intel->back_pixmap) { 1541 screen = intel->back_pixmap->drawable.pScreen; 1542 screen->DestroyPixmap(intel->back_pixmap); 1543 intel->back_pixmap = NULL; 1544 } 1545 1546 if (intel->back_buffer) { 1547 drm_intel_bo_unreference(intel->back_buffer); 1548 intel->back_buffer = NULL; 1549 } 1550 1551 intel->front_buffer = intel_allocate_framebuffer(scrn, 1552 width, height, 1553 intel->cpp, 1554 &pitch, 1555 &tiling); 1556 if (!intel->front_buffer) 1557 goto fail; 1558 1559 ret = drmModeAddFB(mode->fd, width, height, scrn->depth, 1560 scrn->bitsPerPixel, pitch, 1561 intel->front_buffer->handle, 1562 &mode->fb_id); 1563 if (ret) 1564 goto fail; 1565 1566 drm_intel_bo_disable_reuse(intel->front_buffer); 1567 intel->front_pitch = pitch; 1568 intel->front_tiling = tiling; 1569 1570 scrn->virtualX = width; 1571 scrn->virtualY = height; 1572 1573 for (i = 0; i < xf86_config->num_crtc; i++) { 1574 xf86CrtcPtr crtc = xf86_config->crtc[i]; 1575 1576 if (!crtc->enabled) 1577 continue; 1578 1579 if (!intel_crtc_apply(crtc)) 1580 goto fail; 1581 } 1582 1583 intel_uxa_create_screen_resources(scrn->pScreen); 1584 1585 if (old_fb_id) 1586 drmModeRmFB(mode->fd, old_fb_id); 1587 if (old_front) 1588 drm_intel_bo_unreference(old_front); 1589 1590 return TRUE; 1591 1592fail: 1593 if (intel->front_buffer) 1594 drm_intel_bo_unreference(intel->front_buffer); 1595 intel->front_buffer = old_front; 1596 scrn->virtualX = old_width; 1597 scrn->virtualY = old_height; 1598 scrn->displayWidth = old_pitch; 1599 if (old_fb_id != mode->fb_id) 1600 drmModeRmFB(mode->fd, mode->fb_id); 1601 mode->fb_id = old_fb_id; 1602 1603 return FALSE; 1604} 1605 1606Bool 1607intel_do_pageflip(intel_screen_private *intel, 1608 dri_bo *new_front, 1609 DRI2FrameEventPtr flip_info, int ref_crtc_hw_id) 1610{ 1611 ScrnInfoPtr scrn = intel->scrn; 1612 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 1613 struct intel_crtc *crtc = config->crtc[0]->driver_private; 1614 struct intel_mode *mode = crtc->mode; 1615 unsigned int pitch = scrn->displayWidth * intel->cpp; 1616 struct intel_pageflip *flip; 1617 uint32_t new_fb_id; 1618 int i; 1619 1620 /* 1621 * Create a new handle for the back buffer 1622 */ 1623 if (drmModeAddFB(mode->fd, scrn->virtualX, scrn->virtualY, 1624 scrn->depth, scrn->bitsPerPixel, pitch, 1625 new_front->handle, &new_fb_id)) 1626 goto error_out; 1627 1628 drm_intel_bo_disable_reuse(new_front); 1629 intel_glamor_flush(intel); 1630 intel_batch_submit(scrn); 1631 1632 /* 1633 * Queue flips on all enabled CRTCs 1634 * Note that if/when we get per-CRTC buffers, we'll have to update this. 1635 * Right now it assumes a single shared fb across all CRTCs, with the 1636 * kernel fixing up the offset of each CRTC as necessary. 1637 * 1638 * Also, flips queued on disabled or incorrectly configured displays 1639 * may never complete; this is a configuration error. 1640 */ 1641 mode->fe_frame = 0; 1642 mode->fe_tv_sec = 0; 1643 mode->fe_tv_usec = 0; 1644 1645 for (i = 0; i < config->num_crtc; i++) { 1646 if (!intel_crtc_on(config->crtc[i])) 1647 continue; 1648 1649 mode->flip_info = flip_info; 1650 mode->flip_count++; 1651 1652 crtc = config->crtc[i]->driver_private; 1653 1654 flip = calloc(1, sizeof(struct intel_pageflip)); 1655 if (flip == NULL) { 1656 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1657 "flip queue: carrier alloc failed.\n"); 1658 goto error_undo; 1659 } 1660 1661 /* Only the reference crtc will finally deliver its page flip 1662 * completion event. All other crtc's events will be discarded. 1663 */ 1664 flip->dispatch_me = (intel_crtc_to_pipe(crtc->crtc) == ref_crtc_hw_id); 1665 flip->mode = mode; 1666 1667 if (drmModePageFlip(mode->fd, 1668 crtc_id(crtc), 1669 new_fb_id, 1670 DRM_MODE_PAGE_FLIP_EVENT, flip)) { 1671 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1672 "flip queue failed: %s\n", strerror(errno)); 1673 free(flip); 1674 goto error_undo; 1675 } 1676 } 1677 1678 mode->old_fb_id = mode->fb_id; 1679 mode->fb_id = new_fb_id; 1680 return TRUE; 1681 1682error_undo: 1683 drmModeRmFB(mode->fd, new_fb_id); 1684 for (i = 0; i < config->num_crtc; i++) { 1685 if (config->crtc[i]->enabled) 1686 intel_crtc_apply(config->crtc[i]); 1687 } 1688 1689error_out: 1690 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", 1691 strerror(errno)); 1692 return FALSE; 1693} 1694 1695static const xf86CrtcConfigFuncsRec intel_xf86crtc_config_funcs = { 1696 intel_xf86crtc_resize 1697}; 1698 1699static void 1700intel_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec, 1701 unsigned int tv_usec, void *event) 1702{ 1703 I830DRI2FrameEventHandler(frame, tv_sec, tv_usec, event); 1704} 1705 1706static void 1707intel_page_flip_handler(int fd, unsigned int frame, unsigned int tv_sec, 1708 unsigned int tv_usec, void *event_data) 1709{ 1710 struct intel_pageflip *flip = event_data; 1711 struct intel_mode *mode = flip->mode; 1712 1713 /* Is this the event whose info shall be delivered to higher level? */ 1714 if (flip->dispatch_me) { 1715 /* Yes: Cache msc, ust for later delivery. */ 1716 mode->fe_frame = frame; 1717 mode->fe_tv_sec = tv_sec; 1718 mode->fe_tv_usec = tv_usec; 1719 } 1720 free(flip); 1721 1722 /* Last crtc completed flip? */ 1723 mode->flip_count--; 1724 if (mode->flip_count > 0) 1725 return; 1726 1727 /* Release framebuffer */ 1728 drmModeRmFB(mode->fd, mode->old_fb_id); 1729 1730 if (mode->flip_info == NULL) 1731 return; 1732 1733 /* Deliver cached msc, ust from reference crtc to flip event handler */ 1734 I830DRI2FlipEventHandler(mode->fe_frame, mode->fe_tv_sec, 1735 mode->fe_tv_usec, mode->flip_info); 1736} 1737 1738static void 1739drm_wakeup_handler(pointer data, int err, pointer p) 1740{ 1741 struct intel_mode *mode; 1742 fd_set *read_mask; 1743 1744 if (data == NULL || err < 0) 1745 return; 1746 1747 mode = data; 1748 read_mask = p; 1749 if (FD_ISSET(mode->fd, read_mask)) 1750 drmHandleEvent(mode->fd, &mode->event_context); 1751} 1752 1753static drmModeEncoderPtr 1754intel_get_kencoder(struct intel_mode *mode, int num) 1755{ 1756 struct intel_output *iterator; 1757 int id = mode->mode_res->encoders[num]; 1758 1759 list_for_each_entry(iterator, &mode->outputs, link) 1760 if (iterator->mode_encoder->encoder_id == id) 1761 return iterator->mode_encoder; 1762 1763 return NULL; 1764} 1765 1766/* 1767 * Libdrm's possible_clones is a mask of encoders, Xorg's possible_clones is a 1768 * mask of outputs. This function sets Xorg's possible_clones based on the 1769 * values read from libdrm. 1770 */ 1771static void 1772intel_compute_possible_clones(ScrnInfoPtr scrn, struct intel_mode *mode) 1773{ 1774 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 1775 struct intel_output *intel_output, *clone; 1776 drmModeEncoderPtr cloned_encoder; 1777 uint32_t mask; 1778 int i, j, k; 1779 CARD32 possible_clones; 1780 1781 for (i = 0; i < config->num_output; i++) { 1782 possible_clones = 0; 1783 intel_output = config->output[i]->driver_private; 1784 1785 mask = intel_output->mode_encoder->possible_clones; 1786 for (j = 0; mask != 0; j++, mask >>= 1) { 1787 1788 if ((mask & 1) == 0) 1789 continue; 1790 1791 cloned_encoder = intel_get_kencoder(mode, j); 1792 if (!cloned_encoder) 1793 continue; 1794 1795 for (k = 0; k < config->num_output; k++) { 1796 clone = config->output[k]->driver_private; 1797 if (clone->mode_encoder->encoder_id == 1798 cloned_encoder->encoder_id) 1799 possible_clones |= (1 << k); 1800 } 1801 } 1802 1803 config->output[i]->possible_clones = possible_clones; 1804 } 1805} 1806 1807Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp) 1808{ 1809 intel_screen_private *intel = intel_get_screen_private(scrn); 1810 struct drm_i915_getparam gp; 1811 struct intel_mode *mode; 1812 unsigned int i; 1813 int has_flipping; 1814 1815 mode = calloc(1, sizeof *mode); 1816 if (!mode) 1817 return FALSE; 1818 1819 mode->fd = fd; 1820 1821 list_init(&mode->crtcs); 1822 list_init(&mode->outputs); 1823 1824 xf86CrtcConfigInit(scrn, &intel_xf86crtc_config_funcs); 1825 1826 mode->cpp = cpp; 1827 mode->mode_res = drmModeGetResources(mode->fd); 1828 if (!mode->mode_res) { 1829 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1830 "failed to get resources: %s\n", strerror(errno)); 1831 free(mode); 1832 return FALSE; 1833 } 1834 1835 xf86CrtcSetSizeRange(scrn, 320, 200, mode->mode_res->max_width, 1836 mode->mode_res->max_height); 1837 for (i = 0; i < mode->mode_res->count_crtcs; i++) 1838 intel_crtc_init(scrn, mode, i); 1839 1840 for (i = 0; i < mode->mode_res->count_connectors; i++) 1841 intel_output_init(scrn, mode, i); 1842 1843 intel_compute_possible_clones(scrn, mode); 1844 1845#ifdef INTEL_PIXMAP_SHARING 1846 xf86ProviderSetup(scrn, NULL, "Intel"); 1847#endif 1848 1849 xf86InitialConfiguration(scrn, TRUE); 1850 1851 mode->event_context.version = DRM_EVENT_CONTEXT_VERSION; 1852 mode->event_context.vblank_handler = intel_vblank_handler; 1853 mode->event_context.page_flip_handler = intel_page_flip_handler; 1854 1855 has_flipping = 0; 1856 gp.param = I915_PARAM_HAS_PAGEFLIPPING; 1857 gp.value = &has_flipping; 1858 (void)drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM, &gp, 1859 sizeof(gp)); 1860 if (has_flipping && intel->swapbuffers_wait) { 1861 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1862 "Kernel page flipping support detected, enabling\n"); 1863 intel->use_pageflipping = TRUE; 1864 } 1865 1866 intel->modes = mode; 1867 return TRUE; 1868} 1869 1870void 1871intel_mode_init(struct intel_screen_private *intel) 1872{ 1873 struct intel_mode *mode = intel->modes; 1874 1875 /* We need to re-register the mode->fd for the synchronisation 1876 * feedback on every server generation, so perform the 1877 * registration within ScreenInit and not PreInit. 1878 */ 1879 mode->flip_count = 0; 1880 AddGeneralSocket(mode->fd); 1881 RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, 1882 drm_wakeup_handler, mode); 1883} 1884 1885void 1886intel_mode_remove_fb(intel_screen_private *intel) 1887{ 1888 struct intel_mode *mode = intel->modes; 1889 1890 if (mode->fb_id) { 1891 drmModeRmFB(mode->fd, mode->fb_id); 1892 mode->fb_id = 0; 1893 } 1894} 1895 1896static Bool has_pending_events(int fd) 1897{ 1898 struct pollfd pfd; 1899 pfd.fd = fd; 1900 pfd.events = POLLIN; 1901 return poll(&pfd, 1, 0) == 1; 1902} 1903 1904void 1905intel_mode_close(intel_screen_private *intel) 1906{ 1907 struct intel_mode *mode = intel->modes; 1908 1909 if (mode == NULL) 1910 return; 1911 1912 while (has_pending_events(mode->fd)) 1913 drmHandleEvent(mode->fd, &mode->event_context); 1914 1915 RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, 1916 drm_wakeup_handler, mode); 1917 RemoveGeneralSocket(mode->fd); 1918} 1919 1920void 1921intel_mode_fini(intel_screen_private *intel) 1922{ 1923 struct intel_mode *mode = intel->modes; 1924 1925 if (mode == NULL) 1926 return; 1927 1928 while(!list_is_empty(&mode->crtcs)) { 1929 xf86CrtcDestroy(list_first_entry(&mode->crtcs, 1930 struct intel_crtc, 1931 link)->crtc); 1932 } 1933 1934 while(!list_is_empty(&mode->outputs)) { 1935 xf86OutputDestroy(list_first_entry(&mode->outputs, 1936 struct intel_output, 1937 link)->output); 1938 } 1939 1940 if (mode->fb_id) 1941 drmModeRmFB(mode->fd, mode->fb_id); 1942 1943 /* mode->rotate_fb_id should have been destroyed already */ 1944 1945 free(mode); 1946 intel->modes = NULL; 1947} 1948 1949/* for the mode overlay */ 1950int 1951intel_crtc_id(xf86CrtcPtr crtc) 1952{ 1953 return crtc_id(crtc->driver_private); 1954} 1955 1956int intel_crtc_to_pipe(xf86CrtcPtr crtc) 1957{ 1958 struct intel_crtc *intel_crtc = crtc->driver_private; 1959 return intel_crtc->pipe; 1960} 1961 1962Bool intel_crtc_on(xf86CrtcPtr crtc) 1963{ 1964 struct intel_crtc *intel_crtc = crtc->driver_private; 1965 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 1966 drmModeCrtcPtr drm_crtc; 1967 Bool ret; 1968 int i; 1969 1970 if (!crtc->enabled) 1971 return FALSE; 1972 1973 /* Kernel manages CRTC status based on output config */ 1974 ret = FALSE; 1975 for (i = 0; i < xf86_config->num_output; i++) { 1976 xf86OutputPtr output = xf86_config->output[i]; 1977 if (output->crtc == crtc && 1978 intel_output_dpms_status(output) == DPMSModeOn) { 1979 ret = TRUE; 1980 break; 1981 } 1982 } 1983 if (!ret) 1984 return FALSE; 1985 1986 /* And finally check with the kernel that the fb is bound */ 1987 drm_crtc = drmModeGetCrtc(intel_crtc->mode->fd, crtc_id(intel_crtc)); 1988 if (drm_crtc == NULL) 1989 return FALSE; 1990 1991 ret = (drm_crtc->mode_valid && 1992 intel_crtc->mode->fb_id == drm_crtc->buffer_id); 1993 free(drm_crtc); 1994 1995 return ret; 1996} 1997 1998static PixmapPtr 1999intel_create_pixmap_for_bo(ScreenPtr pScreen, dri_bo *bo, 2000 int width, int height, 2001 int depth, int bpp, 2002 int pitch) 2003{ 2004 PixmapPtr pixmap; 2005 2006 pixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, 0); 2007 if (pixmap == NullPixmap) 2008 return pixmap; 2009 2010 if (!pScreen->ModifyPixmapHeader(pixmap, 2011 width, height, 2012 depth, bpp, 2013 pitch, NULL)) { 2014 pScreen->DestroyPixmap(pixmap); 2015 return NullPixmap; 2016 } 2017 2018 intel_set_pixmap_bo(pixmap, bo); 2019 return pixmap; 2020} 2021 2022static PixmapPtr 2023intel_create_pixmap_for_fbcon(ScrnInfoPtr scrn, int fbcon_id) 2024{ 2025 ScreenPtr pScreen = xf86ScrnToScreen(scrn); 2026 intel_screen_private *intel = intel_get_screen_private(scrn); 2027 struct intel_mode *mode = intel->modes; 2028 int fd = mode->fd; 2029 drmModeFBPtr fbcon; 2030 struct drm_gem_flink flink; 2031 drm_intel_bo *bo; 2032 PixmapPtr pixmap = NullPixmap; 2033 2034 fbcon = drmModeGetFB(fd, fbcon_id); 2035 if (fbcon == NULL) 2036 return NULL; 2037 2038 if (fbcon->depth != scrn->depth || 2039 fbcon->width != scrn->virtualX || 2040 fbcon->height != scrn->virtualY) 2041 goto out_free_fb; 2042 2043 flink.handle = fbcon->handle; 2044 if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { 2045 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 2046 "Couldn't flink fbcon handle\n"); 2047 goto out_free_fb; 2048 } 2049 2050 bo = drm_intel_bo_gem_create_from_name(intel->bufmgr, 2051 "fbcon", flink.name); 2052 if (bo == NULL) { 2053 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 2054 "Couldn't allocate bo for fbcon handle\n"); 2055 goto out_free_fb; 2056 } 2057 2058 pixmap = intel_create_pixmap_for_bo(pScreen, bo, 2059 fbcon->width, fbcon->height, 2060 fbcon->depth, fbcon->bpp, 2061 fbcon->pitch); 2062 if (pixmap == NullPixmap) 2063 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 2064 "Couldn't allocate pixmap fbcon contents\n"); 2065 drm_intel_bo_unreference(bo); 2066out_free_fb: 2067 drmModeFreeFB(fbcon); 2068 2069 return pixmap; 2070} 2071 2072void intel_copy_fb(ScrnInfoPtr scrn) 2073{ 2074 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 2075 ScreenPtr pScreen = xf86ScrnToScreen(scrn); 2076 intel_screen_private *intel = intel_get_screen_private(scrn); 2077 PixmapPtr src, dst; 2078 unsigned int pitch = scrn->displayWidth * intel->cpp; 2079 struct intel_crtc *intel_crtc; 2080 int i, fbcon_id; 2081 2082 if (intel->force_fallback) 2083 return; 2084 2085 fbcon_id = 0; 2086 for (i = 0; i < xf86_config->num_crtc; i++) { 2087 intel_crtc = xf86_config->crtc[i]->driver_private; 2088 if (intel_crtc->mode_crtc->buffer_id) 2089 fbcon_id = intel_crtc->mode_crtc->buffer_id; 2090 } 2091 if (!fbcon_id) 2092 return; 2093 2094 src = intel_create_pixmap_for_fbcon(scrn, fbcon_id); 2095 if (src == NULL) 2096 return; 2097 2098 /* We dont have a screen Pixmap yet */ 2099 dst = intel_create_pixmap_for_bo(pScreen, intel->front_buffer, 2100 scrn->virtualX, scrn->virtualY, 2101 scrn->depth, scrn->bitsPerPixel, 2102 pitch); 2103 if (dst == NullPixmap) 2104 goto cleanup_src; 2105 2106 if (!intel->uxa_driver->prepare_copy(src, dst, 2107 -1, -1, 2108 GXcopy, FB_ALLONES)) 2109 goto cleanup_dst; 2110 2111 intel->uxa_driver->copy(dst, 2112 0, 0, 2113 0, 0, 2114 scrn->virtualX, scrn->virtualY); 2115 intel->uxa_driver->done_copy(dst); 2116#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(10, 0) 2117 pScreen->canDoBGNoneRoot = TRUE; 2118#endif 2119 2120cleanup_dst: 2121 (*pScreen->DestroyPixmap)(dst); 2122cleanup_src: 2123 (*pScreen->DestroyPixmap)(src); 2124} 2125