X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=drm-lease-manager%2Flease-manager.c;h=51a4613f84b5b94e17eb175d0bebd101548caeca;hb=HEAD;hp=9627f0dc89f6923f6c5467e2c9397a6136409bff;hpb=e81466892689b6814d5e9bf0e80b792bfee47c83;p=src%2Fdrm-lease-manager.git diff --git a/drm-lease-manager/lease-manager.c b/drm-lease-manager/lease-manager.c index 9627f0d..7147078 100644 --- a/drm-lease-manager/lease-manager.c +++ b/drm-lease-manager/lease-manager.c @@ -64,6 +64,9 @@ struct lm { drmModePlaneResPtr drm_plane_resource; uint32_t available_crtcs; + char **connector_names; + int nconnectors; + struct lease **leases; int nleases; }; @@ -90,8 +93,7 @@ static const char *const connector_type_names[] = { [DRM_MODE_CONNECTOR_WRITEBACK] = "Writeback", }; -static char *drm_create_default_lease_name(struct lm *lm, - drmModeConnectorPtr connector) +static char *drm_create_connector_name(drmModeConnectorPtr connector) { uint32_t type = connector->connector_type; uint32_t id = connector->connector_type_id; @@ -105,8 +107,18 @@ static char *drm_create_default_lease_name(struct lm *lm, id = connector->connector_id; char *name; - if (asprintf(&name, "card%d-%s-%d", minor(lm->dev_id), - connector_type_names[type], id) < 0) + if (asprintf(&name, "%s-%d", connector_type_names[type], id) < 0) + return NULL; + + return name; +} + +static char *drm_create_default_lease_name(struct lm *lm, int cindex) +{ + char *connector_name = lm->connector_names[cindex]; + + char *name; + if (asprintf(&name, "card%d-%s", minor(lm->dev_id), connector_name) < 0) return NULL; return name; @@ -190,17 +202,62 @@ static void drm_find_available_crtcs(struct lm *lm) } } -static bool lease_add_planes(struct lm *lm, struct lease *lease, int crtc_index) +static bool drm_find_connector(struct lm *lm, char *name, uint32_t *id) +{ + int connectors = lm->drm_resource->count_connectors; + + for (int i = 0; i < connectors; i++) { + if (strcmp(lm->connector_names[i], name)) + continue; + if (id) + *id = lm->drm_resource->connectors[i]; + return true; + } + return false; +} + +static void config_get_planes(struct lm *lm, + const struct connector_config *config, + int *nplanes, uint32_t **planes) +{ + if (config && config->planes) { + *nplanes = config->nplanes; + *planes = config->planes; + } else { + *nplanes = (int)lm->drm_plane_resource->count_planes; + *planes = lm->drm_plane_resource->planes; + } +} + +static bool lease_add_planes(struct lm *lm, struct lease *lease, + uint32_t crtc_index, + const struct connector_config *con_config) { - for (uint32_t i = 0; i < lm->drm_plane_resource->count_planes; i++) { - uint32_t plane_id = lm->drm_plane_resource->planes[i]; + int nplanes; + uint32_t *planes; + uint32_t crtc_mask = (1 << crtc_index); + + /* Only allow shared planes when plane list is explicitly set */ + bool allow_shared = con_config && con_config->planes; + + config_get_planes(lm, con_config, &nplanes, &planes); + + for (int i = 0; i < nplanes; i++) { + uint32_t plane_id = planes[i]; drmModePlanePtr plane = drmModeGetPlane(lm->drm_fd, plane_id); - assert(plane); + if (!plane) { + ERROR_LOG( + "Unknown plane id %d configured in lease: %s\n", + plane_id, lease->base.name); + return false; + } - // Exclude planes that can be used with multiple CRTCs for now - if (plane->possible_crtcs == (1u << crtc_index)) { - lease->object_ids[lease->nobject_ids++] = plane_id; + if (plane->possible_crtcs & crtc_mask) { + bool shared_plane = plane->possible_crtcs != crtc_mask; + if (allow_shared || !shared_plane) + lease->object_ids[lease->nobject_ids++] = + plane_id; } drmModeFreePlane(plane); } @@ -317,8 +374,10 @@ static struct lease *lease_create(struct lm *lm, goto err; } + int nconnectors = + config->nconnectors > 0 ? config->nconnectors : config->ncids; int nobjects = lm->drm_plane_resource->count_planes + - config->ncids * DRM_OBJECTS_PER_CONNECTOR; + nconnectors * DRM_OBJECTS_PER_CONNECTOR; lease->object_ids = calloc(nobjects, sizeof(uint32_t)); if (!lease->object_ids) { @@ -326,35 +385,63 @@ static struct lease *lease_create(struct lm *lm, goto err; } - for (int i = 0; i < config->ncids; i++) { + for (int i = 0; i < nconnectors; i++) { + uint32_t cid; + struct connector_config *con_config = NULL; + + if (config->nconnectors > 0) + con_config = &config->connectors[i]; + + if (con_config) { + char *connector_name = con_config->name; + bool optional = con_config->optional; + + bool found = + drm_find_connector(lm, connector_name, &cid); + + bool missing_mandatory = !found && !optional; + bool missing_optional = !found && optional; + + if (missing_mandatory) { + ERROR_LOG("Lease: %s, " + "mandatory connector %s not found\n", + config->lease_name, connector_name); + goto err; + } else if (missing_optional) { + WARN_LOG("Lease: %s, " + "unknown DRM connector: %s\n", + config->lease_name, connector_name); + continue; + } + } else { + cid = config->connector_ids[i]; + } + drmModeConnectorPtr connector = - drmModeGetConnector(lm->drm_fd, config->connector_ids[i]); + drmModeGetConnector(lm->drm_fd, cid); if (connector == NULL) { - ERROR_LOG("Can't find connector id: %d\n", - config->connector_ids); + ERROR_LOG("Can't find connector id: %d\n", cid); goto err; } - uint32_t connector_id = connector->connector_id; - int crtc_index = drm_get_crtc_index(lm, connector); drmModeFreeConnector(connector); if (crtc_index < 0) { DEBUG_LOG("No crtc found for connector: %d, lease %s\n", - connector_id, lease->base.name); + cid, lease->base.name); goto err; } - if (!lease_add_planes(lm, lease, crtc_index)) + if (!lease_add_planes(lm, lease, crtc_index, con_config)) goto err; uint32_t crtc_id = lm->drm_resource->crtcs[crtc_index]; lease->crtc_id = crtc_id; lease->object_ids[lease->nobject_ids++] = crtc_id; - lease->object_ids[lease->nobject_ids++] = connector_id; + lease->object_ids[lease->nobject_ids++] = cid; } lease->is_granted = false; lease->lease_fd = -1; @@ -402,19 +489,8 @@ static int create_default_lease_configs(struct lm *lm, goto err; } - drmModeConnectorPtr connector; - connector = drmModeGetConnector(lm->drm_fd, cid); def_configs[i].lease_name = - drm_create_default_lease_name(lm, connector); - - if (!def_configs[i].lease_name) { - DEBUG_LOG( - "Can't create lease name for connector %d: %s\n", - cid, strerror(errno)); - goto err; - } - - drmModeFreeConnector(connector); + drm_create_default_lease_name(lm, i); def_configs[i].connector_ids[0] = cid; def_configs[i].ncids = 1; @@ -428,9 +504,12 @@ err: return -1; } -static struct lm *drm_device_get_resources(const char *device) +static struct lm *drm_device_get_resources(const char *device, + bool universal_plane) { struct lm *lm = calloc(1, sizeof(struct lm)); + uint64_t value = 0; + if (!lm) { DEBUG_LOG("Memory allocation failed: %s\n", strerror(errno)); return NULL; @@ -442,6 +521,20 @@ static struct lm *drm_device_get_resources(const char *device) goto err; } + /* When -u option set at args. Enable universal planes so that ALL + planes, even primary and cursor planes can be assigned from lease + configurations. */ + if (universal_plane == true) { + DEBUG_LOG("Enable universal plean mode.\n"); + value = 1; + } + + if (drmSetClientCap(lm->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, + value)) { + DEBUG_LOG("drmSetClientCap failed\n"); + goto err; + } + lm->drm_resource = drmModeGetResources(lm->drm_fd); if (!lm->drm_resource) { ERROR_LOG("Invalid DRM device(%s)\n", device); @@ -449,6 +542,13 @@ static struct lm *drm_device_get_resources(const char *device) goto err; } + if (lm->drm_resource->count_connectors <= 0 || + lm->drm_resource->count_crtcs <= 0 || + lm->drm_resource->count_encoders <= 0) { + DEBUG_LOG("Insufficient DRM resources on device(%s)\n", device); + goto err; + } + lm->drm_plane_resource = drmModeGetPlaneResources(lm->drm_fd); if (!lm->drm_plane_resource) { DEBUG_LOG("drmModeGetPlaneResources failed: %s\n", @@ -464,12 +564,52 @@ static struct lm *drm_device_get_resources(const char *device) lm->dev_id = st.st_rdev; + lm->nconnectors = lm->drm_resource->count_connectors; + lm->connector_names = calloc(lm->nconnectors, sizeof(char *)); + + for (int i = 0; i < lm->nconnectors; i++) { + drmModeConnectorPtr connector; + uint32_t cid = lm->drm_resource->connectors[i]; + + connector = drmModeGetConnector(lm->drm_fd, cid); + lm->connector_names[i] = drm_create_connector_name(connector); + drmModeFreeConnector(connector); + + if (!lm->connector_names[i]) { + DEBUG_LOG("Can't create name for connector %d: %s\n", + cid, strerror(errno)); + goto err; + } + } return lm; err: lm_destroy(lm); return NULL; } +static struct lm *drm_find_drm_device(const char *device, bool universal_plane) +{ + drmDevicePtr devices[64]; + int ndevs; + struct lm *lm = NULL; + + if (device) + return drm_device_get_resources(device, universal_plane); + + ndevs = drmGetDevices2(0, devices, 64); + + for (int i = 0; i < ndevs; i++) { + lm = drm_device_get_resources( + devices[i]->nodes[DRM_NODE_PRIMARY], universal_plane); + if (lm) + break; + } + + drmFreeDevices(devices, ndevs); + + return lm; +} + static int lm_create_leases(struct lm *lm, int num_leases, const struct lease_config *configs) { @@ -496,15 +636,18 @@ static int lm_create_leases(struct lm *lm, int num_leases, } struct lm *lm_create_with_config(const char *device, int num_leases, - struct lease_config *configs) + struct lease_config *configs, + bool universal_plane) { struct lease_config *default_configs = NULL; - struct lm *lm = drm_device_get_resources(device); + struct lm *lm = drm_find_drm_device(device, universal_plane); - if (!lm) + if (!lm) { + ERROR_LOG("No available DRM device found\n"); return NULL; + } - if (configs == NULL) { + if (configs == NULL || num_leases == 0) { num_leases = create_default_lease_configs(lm, &default_configs); if (num_leases < 0) { lm_destroy(lm); @@ -526,7 +669,7 @@ struct lm *lm_create_with_config(const char *device, int num_leases, struct lm *lm_create(const char *device) { - return lm_create_with_config(device, 0, NULL); + return lm_create_with_config(device, 0, NULL, false); } void lm_destroy(struct lm *lm) @@ -541,6 +684,11 @@ void lm_destroy(struct lm *lm) } free(lm->leases); + + for (int i = 0; i < lm->nconnectors; i++) + free(lm->connector_names[i]); + free(lm->connector_names); + drmModeFreeResources(lm->drm_resource); drmModeFreePlaneResources(lm->drm_plane_resource); close(lm->drm_fd);