/* * Copyright (C) 2024 Amlogic Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "xf86drmMode.h" #include "xf86drm.h" #include "drm_fourcc.h" #include "BinderClient.h" #include "display_interface.h" #define OBJECT_COUNT 2 struct selected_pipeline { uint32_t connector_id; uint32_t crtc_id; }; static int find_crtc_index(const drmModeRes *resources, uint32_t crtc_id) { int i; for (i = 0; i < resources->count_crtcs; i++) { if (resources->crtcs[i] == crtc_id) return i; } return -1; } static int select_crtc(int fd, const drmModeRes *resources, const drmModeConnector *connector, uint32_t *crtc_id, int *crtc_index) { int encoder_index; if (connector->encoder_id) { drmModeEncoder *encoder = drmModeGetEncoder(fd, connector->encoder_id); if (encoder && encoder->crtc_id) { int index = find_crtc_index(resources, encoder->crtc_id); if (index >= 0) { *crtc_id = encoder->crtc_id; *crtc_index = index; drmModeFreeEncoder(encoder); return 0; } } if (encoder) drmModeFreeEncoder(encoder); } for (encoder_index = 0; encoder_index < connector->count_encoders; encoder_index++) { drmModeEncoder *encoder = drmModeGetEncoder(fd, connector->encoders[encoder_index]); int i; if (!encoder) continue; for (i = 0; i < resources->count_crtcs; i++) { if (encoder->possible_crtcs & (1u << i)) { *crtc_id = resources->crtcs[i]; *crtc_index = i; drmModeFreeEncoder(encoder); return 0; } } drmModeFreeEncoder(encoder); } errno = ENODEV; return -1; } static int select_pipeline(int fd, struct selected_pipeline *pipeline) { drmModeRes *resources = drmModeGetResources(fd); int connector_index; if (!resources) return -1; for (connector_index = 0; connector_index < resources->count_connectors; connector_index++) { drmModeConnector *connector = drmModeGetConnector(fd, resources->connectors[connector_index]); int crtc_index; if (!connector) continue; if (connector->connection != DRM_MODE_CONNECTED || connector->count_modes == 0) { drmModeFreeConnector(connector); continue; } pipeline->connector_id = connector->connector_id; if (select_crtc(fd, resources, connector, &pipeline->crtc_id, &crtc_index) == 0) { drmModeFreeConnector(connector); drmModeFreeResources(resources); return 0; } drmModeFreeConnector(connector); } drmModeFreeResources(resources); errno = ENODEV; return -1; } int create_and_send_lease(int drmFd, uint32_t *lessee_id) { int lease_fd = -1; uint32_t objects[OBJECT_COUNT]; struct selected_pipeline pipeline = { 0 }; if (drmIsMaster(drmFd) != 1) { fprintf(stderr, "[FAIL] %d is not DRM master; stop Weston and other KMS owners\n", drmFd); return -1; } if (drmSetClientCap(drmFd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) { fprintf(stderr, "[FAIL] enable universal planes: %s\n", strerror(errno)); return errno; } if (select_pipeline(drmFd, &pipeline) < 0) { fprintf(stderr, "[FAIL] select display pipeline: %s\n", strerror(errno)); return errno; } objects[0] = pipeline.connector_id; objects[1] = pipeline.crtc_id; lease_fd = drmModeCreateLease(drmFd, objects, OBJECT_COUNT, O_CLOEXEC, lessee_id); if (lease_fd < 0) { fprintf(stderr, "[FAIL] CREATE_LEASE: %s (%d)\n", strerror(-lease_fd), lease_fd); return errno; } sp binder = new BinderClient(NULL); if (binder.get()) binder->setDrmLeaseFd(0, lease_fd); close(lease_fd); return 0; }