drm: add support for DP-MST connectors

These are created/destroyed dynamically by the kernel.
This commit is contained in:
Simon Ser 2022-02-15 18:19:43 +01:00 committed by Joshie
parent 483e2729ec
commit 7004d98223

View file

@ -326,8 +326,52 @@ static bool compare_modes( drmModeModeInfo mode1, drmModeModeInfo mode2 )
static bool refresh_state( drm_t *drm )
{
// TODO: refresh list of connectors for DP-MST
drmModeRes *resources = drmModeGetResources(drm->fd);
if (resources == nullptr) {
drm_log.errorf_errno("drmModeGetResources failed");
return false;
}
// Add connectors which appeared
for (int i = 0; i < resources->count_connectors; i++) {
uint32_t conn_id = resources->connectors[i];
if (drm->connectors.count(conn_id) == 0) {
struct connector conn = { .id = conn_id };
drm->connectors[conn_id] = conn;
}
}
// Remove connectors which disappeared
auto it = drm->connectors.begin();
while (it != drm->connectors.end()) {
struct connector *conn = &it->second;
bool found = false;
for (int j = 0; j < resources->count_connectors; j++) {
if (resources->connectors[j] == conn->id) {
found = true;
break;
}
}
if (!found) {
if (drm->connector == conn) {
drm_log.infof("current connector '%s' disconnected", conn->name);
drm->connector = nullptr;
}
free(conn->name);
drmModeFreeConnector(conn->connector);
it = drm->connectors.erase(it);
} else {
it++;
}
}
drmModeFreeResources(resources);
// Re-probe connectors props and status
for (auto &kv : drm->connectors) {
struct connector *conn = &kv.second;
if (!get_object_properties(drm, conn->id, DRM_MODE_OBJECT_CONNECTOR, conn->props, conn->initial_prop_values)) {
@ -346,6 +390,20 @@ static bool refresh_state( drm_t *drm )
/* sort modes by preference: preferred flag, then highest area, then
* highest refresh rate */
std::stable_sort(conn->connector->modes, conn->connector->modes + conn->connector->count_modes, compare_modes);
if ( conn->name != nullptr )
continue;
const char *type_str = "Unknown";
if ( connector_types.count( conn->connector->connector_type ) > 0 )
type_str = connector_types[ conn->connector->connector_type ];
char name[128] = {};
snprintf(name, sizeof(name), "%s-%d", type_str, conn->connector->connector_type_id);
conn->name = strdup(name);
conn->possible_crtcs = get_connector_possible_crtcs(drm, conn->connector);
}
for (size_t i = 0; i < drm->crtcs.size(); i++) {
@ -375,11 +433,6 @@ static bool get_resources(struct drm_t *drm)
return false;
}
for (int i = 0; i < resources->count_connectors; i++) {
struct connector conn = { .id = resources->connectors[i] };
drm->connectors[conn.id] = conn;
}
for (int i = 0; i < resources->count_crtcs; i++) {
struct crtc crtc = { .id = resources->crtcs[i] };
@ -417,21 +470,6 @@ static bool get_resources(struct drm_t *drm)
if (!refresh_state(drm))
return false;
for (auto &kv : drm->connectors) {
struct connector *conn = &kv.second;
const char *type_str = "Unknown";
if ( connector_types.count( conn->connector->connector_type ) > 0 )
type_str = connector_types[ conn->connector->connector_type ];
char name[128] = {};
snprintf(name, sizeof(name), "%s-%d", type_str, conn->connector->connector_type_id);
conn->name = strdup(name);
conn->possible_crtcs = get_connector_possible_crtcs(drm, conn->connector);
}
for (size_t i = 0; i < drm->crtcs.size(); i++) {
struct crtc *crtc = &drm->crtcs[i];
crtc->pending = crtc->current;