blob: c6dc2a731e40719f96c9ea0b286bcc3d230b514f [file] [log] [blame]
/*
* Copyright 2016 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "bs_drm.h"
static bool display_filter(int fd)
{
bool has_connection = false;
drmModeRes *res = drmModeGetResources(fd);
if (!res)
return false;
if (res->count_crtcs == 0)
goto out;
for (int connector_index = 0; connector_index < res->count_connectors; connector_index++) {
drmModeConnector *connector =
drmModeGetConnector(fd, res->connectors[connector_index]);
if (connector == NULL)
continue;
has_connection =
connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0;
drmModeFreeConnector(connector);
if (has_connection)
break;
}
out:
drmModeFreeResources(res);
return has_connection;
}
int bs_drm_open_for_display()
{
return bs_open_filtered("/dev/dri/card%u", 0, DRM_MAX_MINOR, display_filter);
}
static bool connector_has_crtc(int fd, drmModeRes *res, drmModeConnector *connector)
{
for (int encoder_index = 0; encoder_index < connector->count_encoders; encoder_index++) {
drmModeEncoder *encoder = drmModeGetEncoder(fd, connector->encoders[encoder_index]);
if (encoder == NULL)
continue;
uint32_t possible_crtcs = encoder->possible_crtcs;
drmModeFreeEncoder(encoder);
for (int crtc_index = 0; crtc_index < res->count_crtcs; crtc_index++)
if ((possible_crtcs & (1 << crtc_index)) != 0)
return true;
}
return false;
}
static uint32_t display_rank_connector_type(uint32_t connector_type)
{
switch (connector_type) {
case DRM_MODE_CONNECTOR_LVDS:
return 0x01;
case DRM_MODE_CONNECTOR_eDP:
return 0x02;
case DRM_MODE_CONNECTOR_DSI:
return 0x03;
}
return 0xFF;
}
static uint32_t display_rank(int fd)
{
drmModeRes *res = drmModeGetResources(fd);
if (!res)
return bs_rank_skip;
uint32_t best_rank = bs_rank_skip;
if (res->count_crtcs == 0)
goto out;
for (int connector_index = 0; connector_index < res->count_connectors; connector_index++) {
drmModeConnector *connector =
drmModeGetConnector(fd, res->connectors[connector_index]);
if (connector == NULL)
continue;
bool has_connection = connector->connection == DRM_MODE_CONNECTED &&
connector->count_modes > 0 &&
connector_has_crtc(fd, res, connector);
if (!has_connection)
continue;
uint32_t rank = display_rank_connector_type(connector->connector_type);
if (best_rank > rank)
best_rank = rank;
drmModeFreeConnector(connector);
}
out:
drmModeFreeResources(res);
return best_rank;
}
int bs_drm_open_main_display()
{
return bs_open_ranked("/dev/dri/card%u", 0, DRM_MAX_MINOR, display_rank);
}
static bool vgem_filter(int fd)
{
drmVersion *version = drmGetVersion(fd);
if (!version)
return false;
bool is_vgem = (strncmp("vgem", version->name, version->name_len) == 0);
drmFreeVersion(version);
return is_vgem;
}
int bs_drm_open_vgem()
{
return bs_open_filtered("/dev/dri/card%u", 0, DRM_MAX_MINOR, vgem_filter);
}