xf86drmMode.c revision d049871a
1/* 2 * \file xf86drmMode.c 3 * Header for DRM modesetting interface. 4 * 5 * \author Jakob Bornecrantz <wallbraker@gmail.com> 6 * 7 * \par Acknowledgements: 8 * Feb 2007, Dave Airlie <airlied@linux.ie> 9 */ 10 11/* 12 * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. 13 * Copyright (c) 2007-2008 Dave Airlie <airlied@linux.ie> 14 * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com> 15 * 16 * Permission is hereby granted, free of charge, to any person obtaining a 17 * copy of this software and associated documentation files (the "Software"), 18 * to deal in the Software without restriction, including without limitation 19 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 * and/or sell copies of the Software, and to permit persons to whom the 21 * Software is furnished to do so, subject to the following conditions: 22 * 23 * The above copyright notice and this permission notice shall be included in 24 * all copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 31 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 32 * IN THE SOFTWARE. 33 * 34 */ 35 36/* 37 * TODO the types we are after are defined in diffrent headers on diffrent 38 * platforms find which headers to include to get uint32_t 39 */ 40#include <stdint.h> 41#include <sys/ioctl.h> 42#include <stdio.h> 43 44#include "xf86drmMode.h" 45#include "xf86drm.h" 46#include <drm.h> 47#include <string.h> 48#include <dirent.h> 49#include <unistd.h> 50#include <errno.h> 51 52#define U642VOID(x) ((void *)(unsigned long)(x)) 53#define VOID2U64(x) ((uint64_t)(unsigned long)(x)) 54 55static inline DRM_IOCTL(int fd, int cmd, void *arg) 56{ 57 int ret = drmIoctl(fd, cmd, arg); 58 return ret < 0 ? -errno : ret; 59} 60 61/* 62 * Util functions 63 */ 64 65void* drmAllocCpy(void *array, int count, int entry_size) 66{ 67 char *r; 68 int i; 69 70 if (!count || !array || !entry_size) 71 return 0; 72 73 if (!(r = drmMalloc(count*entry_size))) 74 return 0; 75 76 for (i = 0; i < count; i++) 77 memcpy(r+(entry_size*i), array+(entry_size*i), entry_size); 78 79 return r; 80} 81 82/* 83 * A couple of free functions. 84 */ 85 86void drmModeFreeModeInfo(drmModeModeInfoPtr ptr) 87{ 88 if (!ptr) 89 return; 90 91 drmFree(ptr); 92} 93 94void drmModeFreeResources(drmModeResPtr ptr) 95{ 96 if (!ptr) 97 return; 98 99 drmFree(ptr); 100 101} 102 103void drmModeFreeFB(drmModeFBPtr ptr) 104{ 105 if (!ptr) 106 return; 107 108 /* we might add more frees later. */ 109 drmFree(ptr); 110} 111 112void drmModeFreeCrtc(drmModeCrtcPtr ptr) 113{ 114 if (!ptr) 115 return; 116 117 drmFree(ptr); 118 119} 120 121void drmModeFreeConnector(drmModeConnectorPtr ptr) 122{ 123 if (!ptr) 124 return; 125 126 drmFree(ptr->encoders); 127 drmFree(ptr->prop_values); 128 drmFree(ptr->props); 129 drmFree(ptr->modes); 130 drmFree(ptr); 131 132} 133 134void drmModeFreeEncoder(drmModeEncoderPtr ptr) 135{ 136 drmFree(ptr); 137} 138 139/* 140 * ModeSetting functions. 141 */ 142 143drmModeResPtr drmModeGetResources(int fd) 144{ 145 struct drm_mode_card_res res, counts; 146 drmModeResPtr r = 0; 147 148retry: 149 memset(&res, 0, sizeof(struct drm_mode_card_res)); 150 if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) 151 return 0; 152 153 counts = res; 154 155 if (res.count_fbs) { 156 res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t))); 157 if (!res.fb_id_ptr) 158 goto err_allocs; 159 } 160 if (res.count_crtcs) { 161 res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t))); 162 if (!res.crtc_id_ptr) 163 goto err_allocs; 164 } 165 if (res.count_connectors) { 166 res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t))); 167 if (!res.connector_id_ptr) 168 goto err_allocs; 169 } 170 if (res.count_encoders) { 171 res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t))); 172 if (!res.encoder_id_ptr) 173 goto err_allocs; 174 } 175 176 if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) 177 goto err_allocs; 178 179 /* The number of available connectors and etc may have changed with a 180 * hotplug event in between the ioctls, in which case the field is 181 * silently ignored by the kernel. 182 */ 183 if (counts.count_fbs < res.count_fbs || 184 counts.count_crtcs < res.count_crtcs || 185 counts.count_connectors < res.count_connectors || 186 counts.count_encoders < res.count_encoders) 187 { 188 drmFree(U642VOID(res.fb_id_ptr)); 189 drmFree(U642VOID(res.crtc_id_ptr)); 190 drmFree(U642VOID(res.connector_id_ptr)); 191 drmFree(U642VOID(res.encoder_id_ptr)); 192 193 goto retry; 194 } 195 196 /* 197 * return 198 */ 199 if (!(r = drmMalloc(sizeof(*r)))) 200 goto err_allocs; 201 202 r->min_width = res.min_width; 203 r->max_width = res.max_width; 204 r->min_height = res.min_height; 205 r->max_height = res.max_height; 206 r->count_fbs = res.count_fbs; 207 r->count_crtcs = res.count_crtcs; 208 r->count_connectors = res.count_connectors; 209 r->count_encoders = res.count_encoders; 210 211 r->fbs = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t)); 212 r->crtcs = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t)); 213 r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t)); 214 r->encoders = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t)); 215 if ((res.count_fbs && !r->fbs) || 216 (res.count_crtcs && !r->crtcs) || 217 (res.count_connectors && !r->connectors) || 218 (res.count_encoders && !r->encoders)) 219 { 220 drmFree(r->fbs); 221 drmFree(r->crtcs); 222 drmFree(r->connectors); 223 drmFree(r->encoders); 224 drmFree(r); 225 r = 0; 226 } 227 228err_allocs: 229 drmFree(U642VOID(res.fb_id_ptr)); 230 drmFree(U642VOID(res.crtc_id_ptr)); 231 drmFree(U642VOID(res.connector_id_ptr)); 232 drmFree(U642VOID(res.encoder_id_ptr)); 233 234 return r; 235} 236 237int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, 238 uint8_t bpp, uint32_t pitch, uint32_t bo_handle, 239 uint32_t *buf_id) 240{ 241 struct drm_mode_fb_cmd f; 242 int ret; 243 244 f.width = width; 245 f.height = height; 246 f.pitch = pitch; 247 f.bpp = bpp; 248 f.depth = depth; 249 f.handle = bo_handle; 250 251 if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f))) 252 return ret; 253 254 *buf_id = f.fb_id; 255 return 0; 256} 257 258int drmModeRmFB(int fd, uint32_t bufferId) 259{ 260 return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId); 261 262 263} 264 265drmModeFBPtr drmModeGetFB(int fd, uint32_t buf) 266{ 267 struct drm_mode_fb_cmd info; 268 drmModeFBPtr r; 269 270 info.fb_id = buf; 271 272 if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info)) 273 return NULL; 274 275 if (!(r = drmMalloc(sizeof(*r)))) 276 return NULL; 277 278 r->fb_id = info.fb_id; 279 r->width = info.width; 280 r->height = info.height; 281 r->pitch = info.pitch; 282 r->bpp = info.bpp; 283 r->handle = info.handle; 284 r->depth = info.depth; 285 286 return r; 287} 288 289int drmModeDirtyFB(int fd, uint32_t bufferId, 290 drmModeClipPtr clips, uint32_t num_clips) 291{ 292 struct drm_mode_fb_dirty_cmd dirty = { 0 }; 293 294 dirty.fb_id = bufferId; 295 dirty.clips_ptr = VOID2U64(clips); 296 dirty.num_clips = num_clips; 297 298 return DRM_IOCTL(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty); 299} 300 301 302/* 303 * Crtc functions 304 */ 305 306drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) 307{ 308 struct drm_mode_crtc crtc; 309 drmModeCrtcPtr r; 310 311 crtc.crtc_id = crtcId; 312 313 if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc)) 314 return 0; 315 316 /* 317 * return 318 */ 319 320 if (!(r = drmMalloc(sizeof(*r)))) 321 return 0; 322 323 r->crtc_id = crtc.crtc_id; 324 r->x = crtc.x; 325 r->y = crtc.y; 326 r->mode_valid = crtc.mode_valid; 327 if (r->mode_valid) 328 memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo)); 329 r->buffer_id = crtc.fb_id; 330 r->gamma_size = crtc.gamma_size; 331 return r; 332} 333 334 335int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, 336 uint32_t x, uint32_t y, uint32_t *connectors, int count, 337 drmModeModeInfoPtr mode) 338{ 339 struct drm_mode_crtc crtc; 340 341 crtc.x = x; 342 crtc.y = y; 343 crtc.crtc_id = crtcId; 344 crtc.fb_id = bufferId; 345 crtc.set_connectors_ptr = VOID2U64(connectors); 346 crtc.count_connectors = count; 347 if (mode) { 348 memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo)); 349 crtc.mode_valid = 1; 350 } else 351 crtc.mode_valid = 0; 352 353 return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc); 354} 355 356/* 357 * Cursor manipulation 358 */ 359 360int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height) 361{ 362 struct drm_mode_cursor arg; 363 364 arg.flags = DRM_MODE_CURSOR_BO; 365 arg.crtc_id = crtcId; 366 arg.width = width; 367 arg.height = height; 368 arg.handle = bo_handle; 369 370 return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); 371} 372 373int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) 374{ 375 struct drm_mode_cursor arg; 376 377 arg.flags = DRM_MODE_CURSOR_MOVE; 378 arg.crtc_id = crtcId; 379 arg.x = x; 380 arg.y = y; 381 382 return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); 383} 384 385/* 386 * Encoder get 387 */ 388drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id) 389{ 390 struct drm_mode_get_encoder enc; 391 drmModeEncoderPtr r = NULL; 392 393 enc.encoder_id = encoder_id; 394 enc.encoder_type = 0; 395 enc.possible_crtcs = 0; 396 enc.possible_clones = 0; 397 398 if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc)) 399 return 0; 400 401 if (!(r = drmMalloc(sizeof(*r)))) 402 return 0; 403 404 r->encoder_id = enc.encoder_id; 405 r->crtc_id = enc.crtc_id; 406 r->encoder_type = enc.encoder_type; 407 r->possible_crtcs = enc.possible_crtcs; 408 r->possible_clones = enc.possible_clones; 409 410 return r; 411} 412 413/* 414 * Connector manipulation 415 */ 416 417drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) 418{ 419 struct drm_mode_get_connector conn, counts; 420 drmModeConnectorPtr r = NULL; 421 422retry: 423 memset(&conn, 0, sizeof(struct drm_mode_get_connector)); 424 conn.connector_id = connector_id; 425 426 if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) 427 return 0; 428 429 counts = conn; 430 431 if (conn.count_props) { 432 conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t))); 433 if (!conn.props_ptr) 434 goto err_allocs; 435 conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t))); 436 if (!conn.prop_values_ptr) 437 goto err_allocs; 438 } 439 440 if (conn.count_modes) { 441 conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo))); 442 if (!conn.modes_ptr) 443 goto err_allocs; 444 } 445 446 if (conn.count_encoders) { 447 conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t))); 448 if (!conn.encoders_ptr) 449 goto err_allocs; 450 } 451 452 if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) 453 goto err_allocs; 454 455 /* The number of available connectors and etc may have changed with a 456 * hotplug event in between the ioctls, in which case the field is 457 * silently ignored by the kernel. 458 */ 459 if (counts.count_props < conn.count_props || 460 counts.count_modes < conn.count_modes || 461 counts.count_encoders < conn.count_encoders) { 462 drmFree(U642VOID(conn.props_ptr)); 463 drmFree(U642VOID(conn.prop_values_ptr)); 464 drmFree(U642VOID(conn.modes_ptr)); 465 drmFree(U642VOID(conn.encoders_ptr)); 466 467 goto retry; 468 } 469 470 if(!(r = drmMalloc(sizeof(*r)))) { 471 goto err_allocs; 472 } 473 474 r->connector_id = conn.connector_id; 475 r->encoder_id = conn.encoder_id; 476 r->connection = conn.connection; 477 r->mmWidth = conn.mm_width; 478 r->mmHeight = conn.mm_height; 479 /* convert subpixel from kernel to userspace */ 480 r->subpixel = conn.subpixel + 1; 481 r->count_modes = conn.count_modes; 482 r->count_props = conn.count_props; 483 r->props = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t)); 484 r->prop_values = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t)); 485 r->modes = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo)); 486 r->count_encoders = conn.count_encoders; 487 r->encoders = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t)); 488 r->connector_type = conn.connector_type; 489 r->connector_type_id = conn.connector_type_id; 490 491 if ((r->count_props && !r->props) || 492 (r->count_props && !r->prop_values) || 493 (r->count_modes && !r->modes) || 494 (r->count_encoders && !r->encoders)) { 495 drmFree(r->props); 496 drmFree(r->prop_values); 497 drmFree(r->modes); 498 drmFree(r->encoders); 499 drmFree(r); 500 r = 0; 501 } 502 503err_allocs: 504 drmFree(U642VOID(conn.prop_values_ptr)); 505 drmFree(U642VOID(conn.props_ptr)); 506 drmFree(U642VOID(conn.modes_ptr)); 507 drmFree(U642VOID(conn.encoders_ptr)); 508 509 return r; 510} 511 512int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) 513{ 514 struct drm_mode_mode_cmd res; 515 516 memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); 517 res.connector_id = connector_id; 518 519 return DRM_IOCTL(fd, DRM_IOCTL_MODE_ATTACHMODE, &res); 520} 521 522int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) 523{ 524 struct drm_mode_mode_cmd res; 525 526 memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); 527 res.connector_id = connector_id; 528 529 return DRM_IOCTL(fd, DRM_IOCTL_MODE_DETACHMODE, &res); 530} 531 532 533drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) 534{ 535 struct drm_mode_get_property prop; 536 drmModePropertyPtr r; 537 538 prop.prop_id = property_id; 539 prop.count_enum_blobs = 0; 540 prop.count_values = 0; 541 prop.flags = 0; 542 prop.enum_blob_ptr = 0; 543 prop.values_ptr = 0; 544 545 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) 546 return 0; 547 548 if (prop.count_values) 549 prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t))); 550 551 if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM)) 552 prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum))); 553 554 if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) { 555 prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); 556 prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); 557 } 558 559 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) { 560 r = NULL; 561 goto err_allocs; 562 } 563 564 if (!(r = drmMalloc(sizeof(*r)))) 565 return NULL; 566 567 r->prop_id = prop.prop_id; 568 r->count_values = prop.count_values; 569 570 r->flags = prop.flags; 571 if (prop.count_values) 572 r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t)); 573 if (prop.flags & DRM_MODE_PROP_ENUM) { 574 r->count_enums = prop.count_enum_blobs; 575 r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum)); 576 } else if (prop.flags & DRM_MODE_PROP_BLOB) { 577 r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t)); 578 r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t)); 579 r->count_blobs = prop.count_enum_blobs; 580 } 581 strncpy(r->name, prop.name, DRM_PROP_NAME_LEN); 582 r->name[DRM_PROP_NAME_LEN-1] = 0; 583 584err_allocs: 585 drmFree(U642VOID(prop.values_ptr)); 586 drmFree(U642VOID(prop.enum_blob_ptr)); 587 588 return r; 589} 590 591void drmModeFreeProperty(drmModePropertyPtr ptr) 592{ 593 if (!ptr) 594 return; 595 596 drmFree(ptr->values); 597 drmFree(ptr->enums); 598 drmFree(ptr); 599} 600 601drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id) 602{ 603 struct drm_mode_get_blob blob; 604 drmModePropertyBlobPtr r; 605 606 blob.length = 0; 607 blob.data = 0; 608 blob.blob_id = blob_id; 609 610 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) 611 return NULL; 612 613 if (blob.length) 614 blob.data = VOID2U64(drmMalloc(blob.length)); 615 616 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) { 617 r = NULL; 618 goto err_allocs; 619 } 620 621 if (!(r = drmMalloc(sizeof(*r)))) 622 goto err_allocs; 623 624 r->id = blob.blob_id; 625 r->length = blob.length; 626 r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length); 627 628err_allocs: 629 drmFree(U642VOID(blob.data)); 630 return r; 631} 632 633void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr) 634{ 635 if (!ptr) 636 return; 637 638 drmFree(ptr->data); 639 drmFree(ptr); 640} 641 642int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id, 643 uint64_t value) 644{ 645 struct drm_mode_connector_set_property osp; 646 647 osp.connector_id = connector_id; 648 osp.prop_id = property_id; 649 osp.value = value; 650 651 return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp); 652} 653 654/* 655 * checks if a modesetting capable driver has attached to the pci id 656 * returns 0 if modesetting supported. 657 * -EINVAL or invalid bus id 658 * -ENOSYS if no modesetting support 659*/ 660int drmCheckModesettingSupported(const char *busid) 661{ 662#ifdef __linux__ 663 char pci_dev_dir[1024]; 664 int domain, bus, dev, func; 665 DIR *sysdir; 666 struct dirent *dent; 667 int found = 0, ret; 668 669 ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func); 670 if (ret != 4) 671 return -EINVAL; 672 673 sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm", 674 domain, bus, dev, func); 675 676 sysdir = opendir(pci_dev_dir); 677 if (sysdir) { 678 dent = readdir(sysdir); 679 while (dent) { 680 if (!strncmp(dent->d_name, "controlD", 8)) { 681 found = 1; 682 break; 683 } 684 685 dent = readdir(sysdir); 686 } 687 closedir(sysdir); 688 if (found) 689 return 0; 690 } 691 692 sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/", 693 domain, bus, dev, func); 694 695 sysdir = opendir(pci_dev_dir); 696 if (!sysdir) 697 return -EINVAL; 698 699 dent = readdir(sysdir); 700 while (dent) { 701 if (!strncmp(dent->d_name, "drm:controlD", 12)) { 702 found = 1; 703 break; 704 } 705 706 dent = readdir(sysdir); 707 } 708 709 closedir(sysdir); 710 if (found) 711 return 0; 712#endif 713 return -ENOSYS; 714 715} 716 717int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, 718 uint16_t *red, uint16_t *green, uint16_t *blue) 719{ 720 struct drm_mode_crtc_lut l; 721 722 l.crtc_id = crtc_id; 723 l.gamma_size = size; 724 l.red = VOID2U64(red); 725 l.green = VOID2U64(green); 726 l.blue = VOID2U64(blue); 727 728 return DRM_IOCTL(fd, DRM_IOCTL_MODE_GETGAMMA, &l); 729} 730 731int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, 732 uint16_t *red, uint16_t *green, uint16_t *blue) 733{ 734 struct drm_mode_crtc_lut l; 735 736 l.crtc_id = crtc_id; 737 l.gamma_size = size; 738 l.red = VOID2U64(red); 739 l.green = VOID2U64(green); 740 l.blue = VOID2U64(blue); 741 742 return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l); 743} 744 745int drmHandleEvent(int fd, drmEventContextPtr evctx) 746{ 747 char buffer[1024]; 748 int len, i; 749 struct drm_event *e; 750 struct drm_event_vblank *vblank; 751 752 /* The DRM read semantics guarantees that we always get only 753 * complete events. */ 754 755 len = read(fd, buffer, sizeof buffer); 756 if (len == 0) 757 return 0; 758 if (len < sizeof *e) 759 return -1; 760 761 i = 0; 762 while (i < len) { 763 e = (struct drm_event *) &buffer[i]; 764 switch (e->type) { 765 case DRM_EVENT_VBLANK: 766 if (evctx->version < 1 || 767 evctx->vblank_handler == NULL) 768 break; 769 vblank = (struct drm_event_vblank *) e; 770 evctx->vblank_handler(fd, 771 vblank->sequence, 772 vblank->tv_sec, 773 vblank->tv_usec, 774 U642VOID (vblank->user_data)); 775 break; 776 case DRM_EVENT_FLIP_COMPLETE: 777 if (evctx->version < 2 || 778 evctx->page_flip_handler == NULL) 779 break; 780 vblank = (struct drm_event_vblank *) e; 781 evctx->page_flip_handler(fd, 782 vblank->sequence, 783 vblank->tv_sec, 784 vblank->tv_usec, 785 U642VOID (vblank->user_data)); 786 break; 787 default: 788 break; 789 } 790 i += e->length; 791 } 792 793 return 0; 794} 795 796int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, 797 uint32_t flags, void *user_data) 798{ 799 struct drm_mode_crtc_page_flip flip; 800 801 flip.fb_id = fb_id; 802 flip.crtc_id = crtc_id; 803 flip.user_data = VOID2U64(user_data); 804 flip.flags = flags; 805 flip.reserved = 0; 806 807 return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip); 808} 809