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 delete [] data->allowed_attachments; 136 delete [] static_cast<char *>(data->custom_data); 137 } 138 139 int adf_device_post(struct adf_device *dev, 140 adf_id_t *interfaces, size_t n_interfaces, 141 struct adf_buffer_config *bufs, size_t n_bufs, 142 void *custom_data, size_t custom_data_size) 143 { 144 int err; 145 struct adf_post_config data; 146 147 memset(&data, 0, sizeof(data)); 148 data.interfaces = interfaces; 149 data.n_interfaces = n_interfaces; 150 data.bufs = bufs; 151 data.n_bufs = n_bufs; 152 data.custom_data = custom_data; 153 data.custom_data_size = custom_data_size; 154 155 err = ioctl(dev->fd, ADF_POST_CONFIG, &data); 156 if (err < 0) 157 return -errno; 158 159 return (int)data.complete_fence; 160 } 161 162 int adf_device_post_v2(struct adf_device *dev, 163 adf_id_t *interfaces, __u32 n_interfaces, 164 struct adf_buffer_config *bufs, __u32 n_bufs, 165 void *custom_data, __u64 custom_data_size, 166 enum adf_complete_fence_type complete_fence_type, 167 int *complete_fence) 168 { 169 int err; 170 struct adf_post_config_v2 data; 171 172 memset(&data, 0, sizeof(data)); 173 data.interfaces = (uintptr_t)interfaces; 174 data.n_interfaces = n_interfaces; 175 data.bufs = (uintptr_t)bufs; 176 data.n_bufs = n_bufs; 177 data.custom_data = (uintptr_t)custom_data; 178 data.custom_data_size = custom_data_size; 179 data.complete_fence_type = complete_fence_type; 180 181 err = ioctl(dev->fd, ADF_POST_CONFIG_V2, &data); 182 if (err < 0) 183 return -errno; 184 185 if (complete_fence) 186 *complete_fence = data.complete_fence; 187 else if (data.complete_fence >= 0) 188 close(data.complete_fence); 189 190 return 0; 191 } 192 193 static int adf_device_attachment(struct adf_device *dev, 194 adf_id_t overlay_engine, adf_id_t interface, bool attach) 195 { 196 int err; 197 struct adf_attachment_config data; 198 199 memset(&data, 0, sizeof(data)); 200 data.overlay_engine = overlay_engine; 201 data.interface = interface; 202 203 err = ioctl(dev->fd, attach ? ADF_ATTACH : ADF_DETACH, &data); 204 if (err < 0) 205 return -errno; 206 207 return 0; 208 } 209 210 int adf_device_attach(struct adf_device *dev, adf_id_t overlay_engine, 211 adf_id_t interface) 212 { 213 return adf_device_attachment(dev, overlay_engine, interface, true); 214 } 215 216 int adf_device_detach(struct adf_device *dev, adf_id_t overlay_engine, 217 adf_id_t interface) 218 { 219 return adf_device_attachment(dev, overlay_engine, interface, false); 220 } 221 222 ssize_t adf_interfaces(struct adf_device *dev, adf_id_t **interfaces) 223 { 224 char pattern[64]; 225 226 snprintf(pattern, sizeof(pattern), "adf-interface%u.%%u", dev->id); 227 return adf_find_nodes(pattern, interfaces); 228 } 229 230 ssize_t adf_interfaces_for_overlay_engine(struct adf_device *dev, 231 adf_id_t overlay_engine, adf_id_t **interfaces) 232 { 233 struct adf_device_data data; 234 auto err = adf_get_device_data(dev, &data); 235 if (err < 0) 236 return err; 237 238 std::vector<adf_id_t> ids; 239 for (size_t i = 0; i < data.n_allowed_attachments; i++) 240 if (data.allowed_attachments[i].overlay_engine == overlay_engine) 241 ids.push_back(data.allowed_attachments[i].interface); 242 243 adf_free_device_data(&data); 244 return adf_id_vector_to_array(ids, interfaces); 245 } 246 247 static ssize_t adf_interfaces_filter(struct adf_device *dev, 248 adf_id_t *in, size_t n_in, adf_id_t **out, 249 bool (*filter)(struct adf_interface_data *data, __u32 match), 250 __u32 match) 251 { 252 std::vector<adf_id_t> ids; 253 for (size_t i = 0; i < n_in; i++) { 254 int fd = adf_interface_open(dev, in[i], O_RDONLY); 255 if (fd < 0) 256 return fd; 257 258 struct adf_interface_data data; 259 auto ret = adf_get_interface_data(fd, &data); 260 close(fd); 261 if (ret < 0) 262 return ret; 263 264 if (filter(&data, match)) 265 ids.push_back(in[i]); 266 } 267 268 return adf_id_vector_to_array(ids, out); 269 } 270 271 static bool adf_interface_type_filter(struct adf_interface_data *data, 272 __u32 type) 273 { 274 return data->type == (enum adf_interface_type)type; 275 } 276 277 ssize_t adf_interfaces_filter_by_type(struct adf_device *dev, 278 enum adf_interface_type type, 279 adf_id_t *in, size_t n_in, adf_id_t **out) 280 { 281 return adf_interfaces_filter(dev, in, n_in, out, adf_interface_type_filter, 282 type); 283 } 284 285 static bool adf_interface_flags_filter(struct adf_interface_data *data, 286 __u32 flag) 287 { 288 return !!(data->flags & flag); 289 } 290 291 ssize_t adf_interfaces_filter_by_flag(struct adf_device *dev, __u32 flag, 292 adf_id_t *in, size_t n_in, adf_id_t **out) 293 { 294 return adf_interfaces_filter(dev, in, n_in, out, adf_interface_flags_filter, 295 flag); 296 } 297 298 int adf_interface_open(struct adf_device *dev, adf_id_t id, int flags) 299 { 300 char filename[64]; 301 302 snprintf(filename, sizeof(filename), ADF_BASE_PATH "adf-interface%u.%u", 303 dev->id, id); 304 305 int fd = open(filename, flags); 306 if (fd < 0) 307 return -errno; 308 return fd; 309 } 310 311 int adf_get_interface_data(int fd, struct adf_interface_data *data) 312 { 313 int err; 314 int ret = 0; 315 316 memset(data, 0, sizeof(*data)); 317 318 err = ioctl(fd, ADF_GET_INTERFACE_DATA, data); 319 if (err < 0) 320 return -errno; 321 322 if (data->n_available_modes) 323 data->available_modes = new drm_mode_modeinfo[data->n_available_modes]; 324 325 if (data->custom_data_size) 326 data->custom_data = new char[data->custom_data_size]; 327 328 err = ioctl(fd, ADF_GET_INTERFACE_DATA, data); 329 if (err < 0) { 330 ret = -errno; 331 adf_free_interface_data(data); 332 } 333 return ret; 334 } 335 336 void adf_free_interface_data(struct adf_interface_data *data) 337 { 338 delete [] data->available_modes; 339 delete [] static_cast<char *>(data->custom_data); 340 } 341 342 int adf_interface_blank(int fd, __u8 mode) 343 { 344 int err = ioctl(fd, ADF_BLANK, mode); 345 if (err < 0) 346 return -errno; 347 return 0; 348 } 349 350 int adf_interface_set_mode(int fd, struct drm_mode_modeinfo *mode) 351 { 352 int err = ioctl(fd, ADF_SET_MODE, mode); 353 if (err < 0) 354 return -errno; 355 return 0; 356 } 357 358 int adf_interface_simple_buffer_alloc(int fd, __u32 w, __u32 h, 359 __u32 format, __u32 *offset, __u32 *pitch) 360 { 361 int err; 362 struct adf_simple_buffer_alloc data; 363 364 memset(&data, 0, sizeof(data)); 365 data.w = w; 366 data.h = h; 367 data.format = format; 368 369 err = ioctl(fd, ADF_SIMPLE_BUFFER_ALLOC, &data); 370 if (err < 0) 371 return -errno; 372 373 *offset = data.offset; 374 *pitch = data.pitch; 375 return (int)data.fd; 376 } 377 378 static void adf_interface_simple_post_config_buf(struct adf_buffer_config *buf, 379 __u32 overlay_engine, __u32 w, __u32 h, __u32 format, int buf_fd, 380 __u32 offset, __u32 pitch, int acquire_fence) 381 { 382 buf->overlay_engine = overlay_engine; 383 buf->w = w; 384 buf->h = h; 385 buf->format = format; 386 buf->fd[0] = buf_fd; 387 buf->offset[0] = offset; 388 buf->pitch[0] = pitch; 389 buf->n_planes = 1; 390 buf->acquire_fence = acquire_fence; 391 } 392 393 int adf_interface_simple_post(int fd, __u32 overlay_engine, 394 __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset, 395 __u32 pitch, int acquire_fence) 396 { 397 int ret; 398 struct adf_simple_post_config data; 399 400 memset(&data, 0, sizeof(data)); 401 adf_interface_simple_post_config_buf(&data.buf, overlay_engine, w, h, format, 402 buf_fd, offset, pitch, acquire_fence); 403 ret = ioctl(fd, ADF_SIMPLE_POST_CONFIG, &data); 404 if (ret < 0) 405 return -errno; 406 407 return (int)data.complete_fence; 408 } 409 410 int adf_interface_simple_post_v2(int fd, adf_id_t overlay_engine, 411 __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset, 412 __u32 pitch, int acquire_fence, 413 enum adf_complete_fence_type complete_fence_type, 414 int *complete_fence) 415 { 416 int ret; 417 struct adf_simple_post_config_v2 data; 418 419 memset(&data, 0, sizeof(data)); 420 adf_interface_simple_post_config_buf(&data.buf, overlay_engine, w, h, format, 421 buf_fd, offset, pitch, acquire_fence); 422 data.complete_fence_type = complete_fence_type; 423 424 ret = ioctl(fd, ADF_SIMPLE_POST_CONFIG_V2, &data); 425 if (ret < 0) 426 return -errno; 427 428 if (complete_fence) 429 *complete_fence = data.complete_fence; 430 else if (data.complete_fence >= 0) 431 close(data.complete_fence); 432 433 return 0; 434 } 435 436 ssize_t adf_overlay_engines(struct adf_device *dev, adf_id_t **overlay_engines) 437 { 438 char pattern[64]; 439 440 snprintf(pattern, sizeof(pattern), "adf-overlay-engine%u.%%u", dev->id); 441 return adf_find_nodes(pattern, overlay_engines); 442 } 443 444 ssize_t adf_overlay_engines_for_interface(struct adf_device *dev, 445 adf_id_t interface, adf_id_t **overlay_engines) 446 { 447 struct adf_device_data data; 448 auto err = adf_get_device_data(dev, &data); 449 if (err < 0) 450 return err; 451 452 std::vector<adf_id_t> ids; 453 for (size_t i = 0; i < data.n_allowed_attachments; i++) 454 if (data.allowed_attachments[i].interface == interface) 455 ids.push_back(data.allowed_attachments[i].overlay_engine); 456 457 return adf_id_vector_to_array(ids, overlay_engines); 458 } 459 460 static ssize_t adf_overlay_engines_filter(struct adf_device *dev, 461 adf_id_t *in, size_t n_in, adf_id_t **out, 462 bool (*filter)(struct adf_overlay_engine_data *data, void *cookie), 463 void *cookie) 464 { 465 std::vector<adf_id_t> ids; 466 size_t i; 467 for (i = 0; i < n_in; i++) { 468 int fd = adf_overlay_engine_open(dev, in[i], O_RDONLY); 469 if (fd < 0) 470 return fd; 471 472 struct adf_overlay_engine_data data; 473 auto ret = adf_get_overlay_engine_data(fd, &data); 474 close(fd); 475 if (ret < 0) 476 return ret; 477 478 if (filter(&data, cookie)) 479 ids.push_back(in[i]); 480 } 481 482 return adf_id_vector_to_array(ids, out); 483 } 484 485 struct format_filter_cookie { 486 const __u32 *formats; 487 size_t n_formats; 488 }; 489 490 static bool adf_overlay_engine_format_filter( 491 struct adf_overlay_engine_data *data, void *cookie) 492 { 493 auto c = static_cast<format_filter_cookie *>(cookie); 494 size_t i; 495 for (i = 0; i < data->n_supported_formats; i++) { 496 size_t j; 497 for (j = 0; j < c->n_formats; j++) 498 if (data->supported_formats[i] == c->formats[j]) 499 return true; 500 } 501 return false; 502 } 503 504 ssize_t adf_overlay_engines_filter_by_format(struct adf_device *dev, 505 const __u32 *formats, size_t n_formats, adf_id_t *in, size_t n_in, 506 adf_id_t **out) 507 { 508 struct format_filter_cookie cookie = { formats, n_formats }; 509 return adf_overlay_engines_filter(dev, in, n_in, out, 510 adf_overlay_engine_format_filter, &cookie); 511 } 512 513 int adf_overlay_engine_open(struct adf_device *dev, adf_id_t id, int flags) 514 { 515 char filename[64]; 516 517 snprintf(filename, sizeof(filename), 518 ADF_BASE_PATH "adf-overlay-engine%u.%u", dev->id, id); 519 520 int fd = open(filename, flags); 521 if (fd < 0) 522 return -errno; 523 return fd; 524 } 525 526 int adf_get_overlay_engine_data(int fd, struct adf_overlay_engine_data *data) 527 { 528 int err; 529 int ret = 0; 530 531 memset(data, 0, sizeof(*data)); 532 533 err = ioctl(fd, ADF_GET_OVERLAY_ENGINE_DATA, data); 534 if (err < 0) 535 return -errno; 536 537 if (data->n_supported_formats) 538 data->supported_formats = new __u32[data->n_supported_formats]; 539 540 if (data->custom_data_size) 541 data->custom_data = new char[data->custom_data_size]; 542 543 err = ioctl(fd, ADF_GET_OVERLAY_ENGINE_DATA, data); 544 if (err < 0) { 545 ret = -errno; 546 adf_free_overlay_engine_data(data); 547 } 548 return ret; 549 } 550 551 void adf_free_overlay_engine_data(struct adf_overlay_engine_data *data) 552 { 553 delete [] data->supported_formats; 554 delete [] static_cast<char *>(data->custom_data); 555 } 556 557 bool adf_overlay_engine_supports_format(int fd, __u32 format) 558 { 559 struct adf_overlay_engine_data data; 560 bool ret = false; 561 size_t i; 562 563 int err = adf_get_overlay_engine_data(fd, &data); 564 if (err < 0) 565 return false; 566 567 for (i = 0; i < data.n_supported_formats; i++) { 568 if (data.supported_formats[i] == format) { 569 ret = true; 570 break; 571 } 572 } 573 574 adf_free_overlay_engine_data(&data); 575 return ret; 576 } 577 578 int adf_set_event(int fd, enum adf_event_type type, bool enabled) 579 { 580 struct adf_set_event data; 581 582 data.type = type; 583 data.enabled = enabled; 584 585 int err = ioctl(fd, ADF_SET_EVENT, &data); 586 if (err < 0) 587 return -errno; 588 return 0; 589 } 590 591 int adf_read_event(int fd, struct adf_event **event) 592 { 593 struct adf_event header; 594 struct event_with_data { 595 struct adf_event base; 596 uint8_t data[0]; 597 }; 598 using unique_event = std::unique_ptr<event_with_data, decltype(&free)>; 599 size_t data_size; 600 601 int err = read(fd, &header, sizeof(header)); 602 if (err < 0) 603 return -errno; 604 if ((size_t)err < sizeof(header)) 605 return -EIO; 606 if (header.length < sizeof(header)) 607 return -EIO; 608 609 // Again, we can't use new[] since the existing API says the caller should 610 // free() the returned event 611 auto event_ptr = static_cast<event_with_data *>(malloc(header.length)); 612 unique_event event_ret{event_ptr, free}; 613 if (!event_ret) 614 return -ENOMEM; 615 data_size = header.length - sizeof(header); 616 617 memcpy(event_ret.get(), &header, sizeof(header)); 618 ssize_t read_size = read(fd, &event_ret->data, data_size); 619 if (read_size < 0) 620 return -errno; 621 if ((size_t)read_size < data_size) 622 return -EIO; 623 624 *event = &event_ret.release()->base; 625 return 0; 626 } 627 628 void adf_format_str(__u32 format, char buf[ADF_FORMAT_STR_SIZE]) 629 { 630 buf[0] = format & 0xFF; 631 buf[1] = (format >> 8) & 0xFF; 632 buf[2] = (format >> 16) & 0xFF; 633 buf[3] = (format >> 24) & 0xFF; 634 buf[4] = '\0'; 635 } 636 637 static bool adf_find_simple_post_overlay_engine(struct adf_device *dev, 638 const __u32 *formats, size_t n_formats, 639 adf_id_t interface, adf_id_t *overlay_engine) 640 { 641 adf_id_t *engs; 642 ssize_t n_engs = adf_overlay_engines_for_interface(dev, interface, &engs); 643 644 if (n_engs <= 0) 645 return false; 646 647 adf_id_t *filtered_engs; 648 ssize_t n_filtered_engs = adf_overlay_engines_filter_by_format(dev, 649 formats, n_formats, engs, n_engs, &filtered_engs); 650 free(engs); 651 652 if (n_filtered_engs <= 0) 653 return false; 654 655 *overlay_engine = filtered_engs[0]; 656 free(filtered_engs); 657 return true; 658 } 659 660 static const __u32 any_rgb_format[] = { 661 DRM_FORMAT_C8, 662 DRM_FORMAT_RGB332, 663 DRM_FORMAT_BGR233, 664 DRM_FORMAT_XRGB1555, 665 DRM_FORMAT_XBGR1555, 666 DRM_FORMAT_RGBX5551, 667 DRM_FORMAT_BGRX5551, 668 DRM_FORMAT_ARGB1555, 669 DRM_FORMAT_ABGR1555, 670 DRM_FORMAT_RGBA5551, 671 DRM_FORMAT_BGRA5551, 672 DRM_FORMAT_RGB565, 673 DRM_FORMAT_BGR565, 674 DRM_FORMAT_RGB888, 675 DRM_FORMAT_BGR888, 676 DRM_FORMAT_XRGB8888, 677 DRM_FORMAT_XBGR8888, 678 DRM_FORMAT_RGBX8888, 679 DRM_FORMAT_BGRX8888, 680 DRM_FORMAT_XRGB2101010, 681 DRM_FORMAT_XBGR2101010, 682 DRM_FORMAT_RGBX1010102, 683 DRM_FORMAT_BGRX1010102, 684 DRM_FORMAT_ARGB2101010, 685 DRM_FORMAT_ABGR2101010, 686 DRM_FORMAT_RGBA1010102, 687 DRM_FORMAT_BGRA1010102, 688 DRM_FORMAT_ARGB8888, 689 DRM_FORMAT_ABGR8888, 690 DRM_FORMAT_RGBA8888, 691 DRM_FORMAT_BGRA8888, 692 }; 693 694 int adf_find_simple_post_configuration(struct adf_device *dev, 695 const __u32 *formats, size_t n_formats, 696 adf_id_t *interface, adf_id_t *overlay_engine) 697 { 698 adf_id_t *intfs = NULL; 699 ssize_t n_intfs = adf_interfaces(dev, &intfs); 700 701 if (n_intfs < 0) 702 return n_intfs; 703 else if (!n_intfs) 704 return -ENODEV; 705 706 adf_id_t *primary_intfs; 707 ssize_t n_primary_intfs = adf_interfaces_filter_by_flag(dev, 708 ADF_INTF_FLAG_PRIMARY, intfs, n_intfs, &primary_intfs); 709 free(intfs); 710 711 if (n_primary_intfs < 0) 712 return n_primary_intfs; 713 else if (!n_primary_intfs) 714 return -ENODEV; 715 716 if (!formats) { 717 formats = any_rgb_format; 718 n_formats = sizeof(any_rgb_format) / sizeof(any_rgb_format[0]); 719 } 720 721 bool found = false; 722 ssize_t i = 0; 723 for (i = 0; i < n_primary_intfs; i++) { 724 found = adf_find_simple_post_overlay_engine(dev, formats, n_formats, 725 primary_intfs[i], overlay_engine); 726 if (found) { 727 *interface = primary_intfs[i]; 728 break; 729 } 730 } 731 free(primary_intfs); 732 733 if (!found) 734 return -ENODEV; 735 736 return 0; 737 } 738