1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <dirent.h> 18 #include <errno.h> 19 #include <fcntl.h> 20 #include <malloc.h> 21 #include <stdint.h> 22 #include <stdio.h> 23 #include <string.h> 24 #include <unistd.h> 25 26 #include <algorithm> 27 #include <memory> 28 #include <vector> 29 30 #include <linux/limits.h> 31 32 #include <sys/ioctl.h> 33 34 #include <adf/adf.h> 35 36 #define ADF_BASE_PATH "/dev/" 37 38 static ssize_t adf_id_vector_to_array(const std::vector<adf_id_t> &in, 39 adf_id_t **out) 40 { 41 auto size = sizeof(in[0]) * in.size(); 42 // We can't use new[] since the existing API says the caller should free() 43 // the returned array 44 auto ret = static_cast<adf_id_t *>(malloc(size)); 45 if (!ret) 46 return -ENOMEM; 47 48 std::copy(in.begin(), in.end(), ret); 49 *out = ret; 50 return in.size(); 51 } 52 53 static ssize_t adf_find_nodes(const char *pattern, adf_id_t **ids_out) 54 { 55 struct dirent *dirent; 56 std::unique_ptr<DIR, decltype(&closedir)> 57 dir{opendir(ADF_BASE_PATH), closedir}; 58 if (!dir) 59 return -errno; 60 61 std::vector<adf_id_t> ids; 62 errno = 0; 63 while ((dirent = readdir(dir.get()))) { 64 adf_id_t id; 65 int matched = sscanf(dirent->d_name, pattern, &id); 66 67 if (matched < 0) 68 return -errno; 69 else if (matched == 1) 70 ids.push_back(id); 71 } 72 if (errno) 73 return -errno; 74 75 return adf_id_vector_to_array(ids, ids_out); 76 } 77 78 ssize_t adf_devices(adf_id_t **ids) 79 { 80 return adf_find_nodes("adf%u", ids); 81 } 82 83 int adf_device_open(adf_id_t id, int flags, struct adf_device *dev) 84 { 85 char filename[64]; 86 87 dev->id = id; 88 89 snprintf(filename, sizeof(filename), ADF_BASE_PATH "adf%u", id); 90 dev->fd = open(filename, flags); 91 if (dev->fd < 0) 92 return -errno; 93 94 return 0; 95 } 96 97 void adf_device_close(struct adf_device *dev) 98 { 99 if (dev->fd >= 0) 100 close(dev->fd); 101 } 102 103 int adf_get_device_data(struct adf_device *dev, struct adf_device_data *data) 104 { 105 int err; 106 int ret = 0; 107 108 memset(data, 0, sizeof(*data)); 109 110 err = ioctl(dev->fd, ADF_GET_DEVICE_DATA, data); 111 if (err < 0) 112 return -ENOMEM; 113 114 if (data->n_attachments) 115 data->attachments = new adf_attachment_config[data->n_attachments]; 116 117 if (data->n_allowed_attachments) 118 data->allowed_attachments = 119 new adf_attachment_config[data->n_allowed_attachments]; 120 121 if (data->custom_data_size) 122 data->custom_data = new char[data->custom_data_size]; 123 124 err = ioctl(dev->fd, ADF_GET_DEVICE_DATA, data); 125 if (err < 0) { 126 ret = -errno; 127 adf_free_device_data(data); 128 } 129 return ret; 130 } 131 132 void adf_free_device_data(struct adf_device_data *data) 133 { 134 delete [] data->attachments; 135 data->attachments = nullptr; 136 delete [] data->allowed_attachments; 137 data->allowed_attachments = nullptr; 138 delete [] static_cast<char *>(data->custom_data); 139 data->custom_data = nullptr; 140 } 141 142 int adf_device_post(struct adf_device *dev, 143 adf_id_t *interfaces, size_t n_interfaces, 144 struct adf_buffer_config *bufs, size_t n_bufs, 145 void *custom_data, size_t custom_data_size) 146 { 147 int err; 148 struct adf_post_config data; 149 150 memset(&data, 0, sizeof(data)); 151 data.interfaces = interfaces; 152 data.n_interfaces = n_interfaces; 153 data.bufs = bufs; 154 data.n_bufs = n_bufs; 155 data.custom_data = custom_data; 156 data.custom_data_size = custom_data_size; 157 158 err = ioctl(dev->fd, ADF_POST_CONFIG, &data); 159 if (err < 0) 160 return -errno; 161 162 return (int)data.complete_fence; 163 } 164 165 int adf_device_post_v2(struct adf_device *dev, 166 adf_id_t *interfaces, __u32 n_interfaces, 167 struct adf_buffer_config *bufs, __u32 n_bufs, 168 void *custom_data, __u64 custom_data_size, 169 enum adf_complete_fence_type complete_fence_type, 170 int *complete_fence) 171 { 172 int err; 173 struct adf_post_config_v2 data; 174 175 memset(&data, 0, sizeof(data)); 176 data.interfaces = (uintptr_t)interfaces; 177 data.n_interfaces = n_interfaces; 178 data.bufs = (uintptr_t)bufs; 179 data.n_bufs = n_bufs; 180 data.custom_data = (uintptr_t)custom_data; 181 data.custom_data_size = custom_data_size; 182 data.complete_fence_type = complete_fence_type; 183 184 err = ioctl(dev->fd, ADF_POST_CONFIG_V2, &data); 185 if (err < 0) 186 return -errno; 187 188 if (complete_fence) 189 *complete_fence = data.complete_fence; 190 else if (data.complete_fence >= 0) 191 close(data.complete_fence); 192 193 return 0; 194 } 195 196 static int adf_device_attachment(struct adf_device *dev, 197 adf_id_t overlay_engine, adf_id_t interface, bool attach) 198 { 199 int err; 200 struct adf_attachment_config data; 201 202 memset(&data, 0, sizeof(data)); 203 data.overlay_engine = overlay_engine; 204 data.interface = interface; 205 206 err = ioctl(dev->fd, attach ? ADF_ATTACH : ADF_DETACH, &data); 207 if (err < 0) 208 return -errno; 209 210 return 0; 211 } 212 213 int adf_device_attach(struct adf_device *dev, adf_id_t overlay_engine, 214 adf_id_t interface) 215 { 216 return adf_device_attachment(dev, overlay_engine, interface, true); 217 } 218 219 int adf_device_detach(struct adf_device *dev, adf_id_t overlay_engine, 220 adf_id_t interface) 221 { 222 return adf_device_attachment(dev, overlay_engine, interface, false); 223 } 224 225 ssize_t adf_interfaces(struct adf_device *dev, adf_id_t **interfaces) 226 { 227 char pattern[64]; 228 229 snprintf(pattern, sizeof(pattern), "adf-interface%u.%%u", dev->id); 230 return adf_find_nodes(pattern, interfaces); 231 } 232 233 ssize_t adf_interfaces_for_overlay_engine(struct adf_device *dev, 234 adf_id_t overlay_engine, adf_id_t **interfaces) 235 { 236 struct adf_device_data data; 237 auto err = adf_get_device_data(dev, &data); 238 if (err < 0) 239 return err; 240 241 std::vector<adf_id_t> ids; 242 if (data.allowed_attachments != nullptr) 243 for (size_t i = 0; i < data.n_allowed_attachments; i++) 244 if (data.allowed_attachments[i].overlay_engine == overlay_engine) 245 ids.push_back(data.allowed_attachments[i].interface); 246 247 adf_free_device_data(&data); 248 return adf_id_vector_to_array(ids, interfaces); 249 } 250 251 static ssize_t adf_interfaces_filter(struct adf_device *dev, 252 adf_id_t *in, size_t n_in, adf_id_t **out, 253 bool (*filter)(struct adf_interface_data *data, __u32 match), 254 __u32 match) 255 { 256 std::vector<adf_id_t> ids; 257 for (size_t i = 0; i < n_in; i++) { 258 int fd = adf_interface_open(dev, in[i], O_RDONLY); 259 if (fd < 0) 260 return fd; 261 262 struct adf_interface_data data; 263 auto ret = adf_get_interface_data(fd, &data); 264 close(fd); 265 if (ret < 0) 266 return ret; 267 268 if (filter(&data, match)) 269 ids.push_back(in[i]); 270 } 271 272 return adf_id_vector_to_array(ids, out); 273 } 274 275 static bool adf_interface_type_filter(struct adf_interface_data *data, 276 __u32 type) 277 { 278 return data->type == (enum adf_interface_type)type; 279 } 280 281 ssize_t adf_interfaces_filter_by_type(struct adf_device *dev, 282 enum adf_interface_type type, 283 adf_id_t *in, size_t n_in, adf_id_t **out) 284 { 285 return adf_interfaces_filter(dev, in, n_in, out, adf_interface_type_filter, 286 type); 287 } 288 289 static bool adf_interface_flags_filter(struct adf_interface_data *data, 290 __u32 flag) 291 { 292 return !!(data->flags & flag); 293 } 294 295 ssize_t adf_interfaces_filter_by_flag(struct adf_device *dev, __u32 flag, 296 adf_id_t *in, size_t n_in, adf_id_t **out) 297 { 298 return adf_interfaces_filter(dev, in, n_in, out, adf_interface_flags_filter, 299 flag); 300 } 301 302 int adf_interface_open(struct adf_device *dev, adf_id_t id, int flags) 303 { 304 char filename[64]; 305 306 snprintf(filename, sizeof(filename), ADF_BASE_PATH "adf-interface%u.%u", 307 dev->id, id); 308 309 int fd = open(filename, flags); 310 if (fd < 0) 311 return -errno; 312 return fd; 313 } 314 315 int adf_get_interface_data(int fd, struct adf_interface_data *data) 316 { 317 int err; 318 int ret = 0; 319 320 memset(data, 0, sizeof(*data)); 321 322 err = ioctl(fd, ADF_GET_INTERFACE_DATA, data); 323 if (err < 0) 324 return -errno; 325 326 if (data->n_available_modes) 327 data->available_modes = new drm_mode_modeinfo[data->n_available_modes]; 328 329 if (data->custom_data_size) 330 data->custom_data = new char[data->custom_data_size]; 331 332 err = ioctl(fd, ADF_GET_INTERFACE_DATA, data); 333 if (err < 0) { 334 ret = -errno; 335 adf_free_interface_data(data); 336 } 337 return ret; 338 } 339 340 void adf_free_interface_data(struct adf_interface_data *data) 341 { 342 delete [] data->available_modes; 343 delete [] static_cast<char *>(data->custom_data); 344 } 345 346 int adf_interface_blank(int fd, __u8 mode) 347 { 348 int err = ioctl(fd, ADF_BLANK, mode); 349 if (err < 0) 350 return -errno; 351 return 0; 352 } 353 354 int adf_interface_set_mode(int fd, struct drm_mode_modeinfo *mode) 355 { 356 int err = ioctl(fd, ADF_SET_MODE, mode); 357 if (err < 0) 358 return -errno; 359 return 0; 360 } 361 362 int adf_interface_simple_buffer_alloc(int fd, __u32 w, __u32 h, 363 __u32 format, __u32 *offset, __u32 *pitch) 364 { 365 int err; 366 struct adf_simple_buffer_alloc data; 367 368 memset(&data, 0, sizeof(data)); 369 data.w = w; 370 data.h = h; 371 data.format = format; 372 373 err = ioctl(fd, ADF_SIMPLE_BUFFER_ALLOC, &data); 374 if (err < 0) 375 return -errno; 376 377 *offset = data.offset; 378 *pitch = data.pitch; 379 return (int)data.fd; 380 } 381 382 static void adf_interface_simple_post_config_buf(struct adf_buffer_config *buf, 383 __u32 overlay_engine, __u32 w, __u32 h, __u32 format, int buf_fd, 384 __u32 offset, __u32 pitch, int acquire_fence) 385 { 386 buf->overlay_engine = overlay_engine; 387 buf->w = w; 388 buf->h = h; 389 buf->format = format; 390 buf->fd[0] = buf_fd; 391 buf->offset[0] = offset; 392 buf->pitch[0] = pitch; 393 buf->n_planes = 1; 394 buf->acquire_fence = acquire_fence; 395 } 396 397 int adf_interface_simple_post(int fd, __u32 overlay_engine, 398 __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset, 399 __u32 pitch, int acquire_fence) 400 { 401 int ret; 402 struct adf_simple_post_config data; 403 404 memset(&data, 0, sizeof(data)); 405 adf_interface_simple_post_config_buf(&data.buf, overlay_engine, w, h, format, 406 buf_fd, offset, pitch, acquire_fence); 407 ret = ioctl(fd, ADF_SIMPLE_POST_CONFIG, &data); 408 if (ret < 0) 409 return -errno; 410 411 return (int)data.complete_fence; 412 } 413 414 int adf_interface_simple_post_v2(int fd, adf_id_t overlay_engine, 415 __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset, 416 __u32 pitch, int acquire_fence, 417 enum adf_complete_fence_type complete_fence_type, 418 int *complete_fence) 419 { 420 int ret; 421 struct adf_simple_post_config_v2 data; 422 423 memset(&data, 0, sizeof(data)); 424 adf_interface_simple_post_config_buf(&data.buf, overlay_engine, w, h, format, 425 buf_fd, offset, pitch, acquire_fence); 426 data.complete_fence_type = complete_fence_type; 427 428 ret = ioctl(fd, ADF_SIMPLE_POST_CONFIG_V2, &data); 429 if (ret < 0) 430 return -errno; 431 432 if (complete_fence) 433 *complete_fence = data.complete_fence; 434 else if (data.complete_fence >= 0) 435 close(data.complete_fence); 436 437 return 0; 438 } 439 440 ssize_t adf_overlay_engines(struct adf_device *dev, adf_id_t **overlay_engines) 441 { 442 char pattern[64]; 443 444 snprintf(pattern, sizeof(pattern), "adf-overlay-engine%u.%%u", dev->id); 445 return adf_find_nodes(pattern, overlay_engines); 446 } 447 448 ssize_t adf_overlay_engines_for_interface(struct adf_device *dev, 449 adf_id_t interface, adf_id_t **overlay_engines) 450 { 451 struct adf_device_data data; 452 auto err = adf_get_device_data(dev, &data); 453 if (err < 0) 454 return err; 455 456 std::vector<adf_id_t> ids; 457 if (data.allowed_attachments != nullptr) 458 for (size_t i = 0; i < data.n_allowed_attachments; i++) 459 if (data.allowed_attachments[i].interface == interface) 460 ids.push_back(data.allowed_attachments[i].overlay_engine); 461 462 return adf_id_vector_to_array(ids, overlay_engines); 463 } 464 465 static ssize_t adf_overlay_engines_filter(struct adf_device *dev, 466 adf_id_t *in, size_t n_in, adf_id_t **out, 467 bool (*filter)(struct adf_overlay_engine_data *data, void *cookie), 468 void *cookie) 469 { 470 std::vector<adf_id_t> ids; 471 size_t i; 472 for (i = 0; i < n_in; i++) { 473 int fd = adf_overlay_engine_open(dev, in[i], O_RDONLY); 474 if (fd < 0) 475 return fd; 476 477 struct adf_overlay_engine_data data; 478 auto ret = adf_get_overlay_engine_data(fd, &data); 479 close(fd); 480 if (ret < 0) 481 return ret; 482 483 if (filter(&data, cookie)) 484 ids.push_back(in[i]); 485 } 486 487 return adf_id_vector_to_array(ids, out); 488 } 489 490 struct format_filter_cookie { 491 const __u32 *formats; 492 size_t n_formats; 493 }; 494 495 static bool adf_overlay_engine_format_filter( 496 struct adf_overlay_engine_data *data, void *cookie) 497 { 498 auto c = static_cast<format_filter_cookie *>(cookie); 499 size_t i; 500 for (i = 0; i < data->n_supported_formats; i++) { 501 size_t j; 502 for (j = 0; j < c->n_formats; j++) 503 if (data->supported_formats[i] == c->formats[j]) 504 return true; 505 } 506 return false; 507 } 508 509 ssize_t adf_overlay_engines_filter_by_format(struct adf_device *dev, 510 const __u32 *formats, size_t n_formats, adf_id_t *in, size_t n_in, 511 adf_id_t **out) 512 { 513 struct format_filter_cookie cookie = { formats, n_formats }; 514 return adf_overlay_engines_filter(dev, in, n_in, out, 515 adf_overlay_engine_format_filter, &cookie); 516 } 517 518 int adf_overlay_engine_open(struct adf_device *dev, adf_id_t id, int flags) 519 { 520 char filename[64]; 521 522 snprintf(filename, sizeof(filename), 523 ADF_BASE_PATH "adf-overlay-engine%u.%u", dev->id, id); 524 525 int fd = open(filename, flags); 526 if (fd < 0) 527 return -errno; 528 return fd; 529 } 530 531 int adf_get_overlay_engine_data(int fd, struct adf_overlay_engine_data *data) 532 { 533 int err; 534 int ret = 0; 535 536 memset(data, 0, sizeof(*data)); 537 538 err = ioctl(fd, ADF_GET_OVERLAY_ENGINE_DATA, data); 539 if (err < 0) 540 return -errno; 541 542 if (data->n_supported_formats) 543 data->supported_formats = new __u32[data->n_supported_formats]; 544 545 if (data->custom_data_size) 546 data->custom_data = new char[data->custom_data_size]; 547 548 err = ioctl(fd, ADF_GET_OVERLAY_ENGINE_DATA, data); 549 if (err < 0) { 550 ret = -errno; 551 adf_free_overlay_engine_data(data); 552 } 553 return ret; 554 } 555 556 void adf_free_overlay_engine_data(struct adf_overlay_engine_data *data) 557 { 558 delete [] data->supported_formats; 559 data->supported_formats = nullptr; 560 delete [] static_cast<char *>(data->custom_data); 561 data->custom_data = nullptr; 562 } 563 564 bool adf_overlay_engine_supports_format(int fd, __u32 format) 565 { 566 struct adf_overlay_engine_data data; 567 bool ret = false; 568 size_t i; 569 570 int err = adf_get_overlay_engine_data(fd, &data); 571 if (err < 0) 572 return false; 573 574 if (data.supported_formats != nullptr) { 575 for (i = 0; i < data.n_supported_formats; i++) { 576 if (data.supported_formats[i] == format) { 577 ret = true; 578 break; 579 } 580 } 581 } 582 583 adf_free_overlay_engine_data(&data); 584 return ret; 585 } 586 587 int adf_set_event(int fd, enum adf_event_type type, bool enabled) 588 { 589 struct adf_set_event data; 590 591 data.type = type; 592 data.enabled = enabled; 593 594 int err = ioctl(fd, ADF_SET_EVENT, &data); 595 if (err < 0) 596 return -errno; 597 return 0; 598 } 599 600 int adf_read_event(int fd, struct adf_event **event) 601 { 602 struct adf_event header; 603 struct event_with_data { 604 struct adf_event base; 605 uint8_t data[0]; 606 }; 607 using unique_event = std::unique_ptr<event_with_data, decltype(&free)>; 608 size_t data_size; 609 610 int err = read(fd, &header, sizeof(header)); 611 if (err < 0) 612 return -errno; 613 if ((size_t)err < sizeof(header)) 614 return -EIO; 615 if (header.length < sizeof(header)) 616 return -EIO; 617 618 // Again, we can't use new[] since the existing API says the caller should 619 // free() the returned event 620 auto event_ptr = static_cast<event_with_data *>(malloc(header.length)); 621 unique_event event_ret{event_ptr, free}; 622 if (!event_ret) 623 return -ENOMEM; 624 data_size = header.length - sizeof(header); 625 626 memcpy(event_ret.get(), &header, sizeof(header)); 627 ssize_t read_size = read(fd, &event_ret->data, data_size); 628 if (read_size < 0) 629 return -errno; 630 if ((size_t)read_size < data_size) 631 return -EIO; 632 633 *event = &event_ret.release()->base; 634 return 0; 635 } 636 637 void adf_format_str(__u32 format, char buf[ADF_FORMAT_STR_SIZE]) 638 { 639 buf[0] = format & 0xFF; 640 buf[1] = (format >> 8) & 0xFF; 641 buf[2] = (format >> 16) & 0xFF; 642 buf[3] = (format >> 24) & 0xFF; 643 buf[4] = '\0'; 644 } 645 646 static bool adf_find_simple_post_overlay_engine(struct adf_device *dev, 647 const __u32 *formats, size_t n_formats, 648 adf_id_t interface, adf_id_t *overlay_engine) 649 { 650 adf_id_t *engs = nullptr; 651 ssize_t n_engs = adf_overlay_engines_for_interface(dev, interface, &engs); 652 653 if (engs == nullptr) 654 return false; 655 656 adf_id_t *filtered_engs = nullptr; 657 ssize_t n_filtered_engs = adf_overlay_engines_filter_by_format(dev, 658 formats, n_formats, engs, n_engs, &filtered_engs); 659 free(engs); 660 661 if (filtered_engs == nullptr) 662 return false; 663 664 *overlay_engine = filtered_engs[0]; 665 free(filtered_engs); 666 return true; 667 } 668 669 static const __u32 any_rgb_format[] = { 670 DRM_FORMAT_C8, 671 DRM_FORMAT_RGB332, 672 DRM_FORMAT_BGR233, 673 DRM_FORMAT_XRGB1555, 674 DRM_FORMAT_XBGR1555, 675 DRM_FORMAT_RGBX5551, 676 DRM_FORMAT_BGRX5551, 677 DRM_FORMAT_ARGB1555, 678 DRM_FORMAT_ABGR1555, 679 DRM_FORMAT_RGBA5551, 680 DRM_FORMAT_BGRA5551, 681 DRM_FORMAT_RGB565, 682 DRM_FORMAT_BGR565, 683 DRM_FORMAT_RGB888, 684 DRM_FORMAT_BGR888, 685 DRM_FORMAT_XRGB8888, 686 DRM_FORMAT_XBGR8888, 687 DRM_FORMAT_RGBX8888, 688 DRM_FORMAT_BGRX8888, 689 DRM_FORMAT_XRGB2101010, 690 DRM_FORMAT_XBGR2101010, 691 DRM_FORMAT_RGBX1010102, 692 DRM_FORMAT_BGRX1010102, 693 DRM_FORMAT_ARGB2101010, 694 DRM_FORMAT_ABGR2101010, 695 DRM_FORMAT_RGBA1010102, 696 DRM_FORMAT_BGRA1010102, 697 DRM_FORMAT_ARGB8888, 698 DRM_FORMAT_ABGR8888, 699 DRM_FORMAT_RGBA8888, 700 DRM_FORMAT_BGRA8888, 701 }; 702 703 int adf_find_simple_post_configuration(struct adf_device *dev, 704 const __u32 *formats, size_t n_formats, 705 adf_id_t *interface, adf_id_t *overlay_engine) 706 { 707 adf_id_t *intfs = NULL; 708 ssize_t n_intfs = adf_interfaces(dev, &intfs); 709 710 if (n_intfs < 0) 711 return n_intfs; 712 else if (!intfs) 713 return -ENODEV; 714 715 adf_id_t *primary_intfs = nullptr; 716 ssize_t n_primary_intfs = adf_interfaces_filter_by_flag(dev, 717 ADF_INTF_FLAG_PRIMARY, intfs, n_intfs, &primary_intfs); 718 free(intfs); 719 720 if (n_primary_intfs < 0) 721 return n_primary_intfs; 722 else if (!primary_intfs) 723 return -ENODEV; 724 725 if (!formats) { 726 formats = any_rgb_format; 727 n_formats = sizeof(any_rgb_format) / sizeof(any_rgb_format[0]); 728 } 729 730 bool found = false; 731 ssize_t i = 0; 732 for (i = 0; i < n_primary_intfs; i++) { 733 found = adf_find_simple_post_overlay_engine(dev, formats, n_formats, 734 primary_intfs[i], overlay_engine); 735 if (found) { 736 *interface = primary_intfs[i]; 737 break; 738 } 739 } 740 free(primary_intfs); 741 742 if (!found) 743 return -ENODEV; 744 745 return 0; 746 } 747