pvr: Make display node optional

Allow the driver to work without a display (card) node by removing
strict display controller checks.

Signed-off-by: Ashish Chauhan <ashish.chauhan@imgtec.com>
Reviewed-by: Frank Binns <frank.binns@imgtec.com>
Tested-by: Icenowy Zheng <uwu@icenowy.me>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38082>
This commit is contained in:
Ashish Chauhan 2025-10-27 09:22:30 +00:00 committed by Marge Bot
parent 7f2c53200f
commit 8825c91dcb
2 changed files with 87 additions and 35 deletions

View file

@ -12,7 +12,9 @@
#include "pvr_instance.h"
#include <fcntl.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "vk_alloc.h"
#include "vk_log.h"
@ -38,22 +40,20 @@ struct pvr_drm_device_config {
struct pvr_drm_device_info {
const char *name;
size_t len;
} render, display;
} render;
};
#define DEF_CONFIG(render_, display_) \
#define DEF_CONFIG(render_) \
{ \
.render = { .name = render_, .len = sizeof(render_) - 1 }, \
.display = { .name = display_, .len = sizeof(display_) - 1 }, \
}
/* This is the list of supported DRM render/display driver configs. */
/* This is the list of supported DRM render driver configs. */
static const struct pvr_drm_device_config pvr_drm_configs[] = {
DEF_CONFIG("mediatek,mt8173-gpu", "mediatek-drm"),
DEF_CONFIG("ti,am62-gpu", "ti,am625-dss"),
DEF_CONFIG("ti,j721s2-gpu", "ti,j721e-dss"),
DEF_CONFIG("mediatek,mt8173-gpu"),
DEF_CONFIG("ti,am62-gpu"),
DEF_CONFIG("ti,j721s2-gpu"),
};
#undef DEF_CONFIG
static const struct vk_instance_extension_table pvr_instance_extensions = {
@ -121,6 +121,56 @@ pvr_drm_device_get_config(drmDevice *const drm_dev)
return NULL;
}
static bool pvr_drm_device_is_compatible_display(drmDevicePtr drm_dev)
{
uint64_t has_dumb_buffer = 0;
uint64_t prime_caps = 0;
bool ret = false;
int32_t fd;
mesa_logd("Checking DRM primary node for compatibility: %s",
drm_dev->nodes[DRM_NODE_PRIMARY]);
fd = open(drm_dev->nodes[DRM_NODE_PRIMARY], O_RDWR | O_CLOEXEC);
if (fd < 0) {
mesa_logd("Failed to open display node: %s\n",
drm_dev->nodes[DRM_NODE_PRIMARY]);
return ret;
}
/* Must support KMS */
if (!drmIsKMS(fd)) {
mesa_logd("DRM device does not support KMS");
goto out;
}
/* Must support dumb buffers, as these are used by the PVR winsys to
* allocate device memory for PVR_WINSYS_BO_TYPE_DISPLAY buffer objects.
*/
if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb_buffer) ||
!has_dumb_buffer) {
mesa_logd("DRM device does not support dumb buffers");
goto out;
}
/* Must support PRIME export (so GPU can import dumb buffers) */
if (drmGetCap(fd, DRM_CAP_PRIME, &prime_caps)) {
mesa_loge("Failed to query DRM_CAP_PRIME: %s", strerror(errno));
goto out;
}
if (!(prime_caps & DRM_PRIME_CAP_EXPORT)) {
mesa_logd("DRM device lacks PRIME export support (caps: 0x%" PRIx64 ")",
prime_caps);
goto out;
}
ret = true;
out:
close(fd);
return ret;
}
static VkResult
pvr_physical_device_enumerate(struct vk_instance *const vk_instance)
{
@ -183,28 +233,24 @@ pvr_physical_device_enumerate(struct vk_instance *const vk_instance)
mesa_logd("Found compatible render device '%s'.",
drm_render_device->nodes[DRM_NODE_RENDER]);
/* ...then find the compatible display node. */
/* ...then find a compatible display node, if available. */
for (int i = 0; i < num_drm_devices; i++) {
drmDevice *const drm_dev = drm_devices[i];
if (drm_dev->bustype != DRM_BUS_PLATFORM)
continue;
if (!(drm_dev->available_nodes & BITFIELD_BIT(DRM_NODE_PRIMARY)))
continue;
if (pvr_drm_device_compatible(&config->display, drm_dev)) {
if (!pvr_drm_device_is_compatible_display(drm_devices[i]))
continue;
drm_display_device = drm_dev;
mesa_logd("Found a compatible display device: '%s'.",
drm_display_device->nodes[DRM_NODE_PRIMARY]);
break;
}
}
if (!drm_display_device) {
mesa_loge("Render device '%s' has no compatible display device.",
drm_render_device->nodes[DRM_NODE_RENDER]);
result = VK_SUCCESS;
goto out_free_drm_devices;
}
mesa_logd("Found compatible display device '%s'.",
drm_display_device->nodes[DRM_NODE_PRIMARY]);
pdevice = vk_alloc(&vk_instance->alloc,
sizeof(*pdevice),
@ -229,7 +275,9 @@ pvr_physical_device_enumerate(struct vk_instance *const vk_instance)
if (PVR_IS_DEBUG_SET(INFO)) {
pvr_physical_device_dump_info(
pdevice,
drm_display_device->deviceinfo.platform->compatible,
drm_display_device
? drm_display_device->deviceinfo.platform->compatible
: NULL,
drm_render_device->deviceinfo.platform->compatible);
}

View file

@ -41,10 +41,12 @@ pvr_physical_device_dump_info(const struct pvr_physical_device *pdevice,
char *const *comp_display,
char *const *comp_render)
{
drmVersionPtr version_display, version_render;
struct pvr_device_dump_info info;
drmVersionPtr version_display = NULL, version_render;
struct pvr_device_dump_info info = { 0 };
if (pdevice->ws->display_fd >= 0)
version_display = drmGetVersion(pdevice->ws->display_fd);
if (!version_display)
return;
@ -56,12 +58,14 @@ pvr_physical_device_dump_info(const struct pvr_physical_device *pdevice,
info.device_info = &pdevice->dev_info;
info.device_runtime_info = &pdevice->dev_runtime_info;
if (version_display) {
info.drm_display.patchlevel = version_display->version_patchlevel;
info.drm_display.major = version_display->version_major;
info.drm_display.minor = version_display->version_minor;
info.drm_display.name = version_display->name;
info.drm_display.date = version_display->date;
info.drm_display.comp = comp_display;
}
info.drm_render.patchlevel = version_render->version_patchlevel;
info.drm_render.major = version_render->version_major;
info.drm_render.minor = version_render->version_minor;
@ -975,7 +979,7 @@ VkResult pvr_physical_device_init(struct pvr_physical_device *pdevice,
goto err_out;
}
if (instance->vk.enabled_extensions.KHR_display) {
if (instance->vk.enabled_extensions.KHR_display && drm_display_device) {
display_path = vk_strdup(&instance->vk.alloc,
drm_display_device->nodes[DRM_NODE_PRIMARY],
VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);