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 "pvr_instance.h"
#include <fcntl.h>
#include <xf86drm.h> #include <xf86drm.h>
#include <xf86drmMode.h>
#include "vk_alloc.h" #include "vk_alloc.h"
#include "vk_log.h" #include "vk_log.h"
@ -38,22 +40,20 @@ struct pvr_drm_device_config {
struct pvr_drm_device_info { struct pvr_drm_device_info {
const char *name; const char *name;
size_t len; size_t len;
} render, display; } render;
}; };
#define DEF_CONFIG(render_, display_) \ #define DEF_CONFIG(render_) \
{ \ { \
.render = { .name = render_, .len = sizeof(render_) - 1 }, \ .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[] = { static const struct pvr_drm_device_config pvr_drm_configs[] = {
DEF_CONFIG("mediatek,mt8173-gpu", "mediatek-drm"), DEF_CONFIG("mediatek,mt8173-gpu"),
DEF_CONFIG("ti,am62-gpu", "ti,am625-dss"), DEF_CONFIG("ti,am62-gpu"),
DEF_CONFIG("ti,j721s2-gpu", "ti,j721e-dss"), DEF_CONFIG("ti,j721s2-gpu"),
}; };
#undef DEF_CONFIG #undef DEF_CONFIG
static const struct vk_instance_extension_table pvr_instance_extensions = { 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; 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 static VkResult
pvr_physical_device_enumerate(struct vk_instance *const vk_instance) pvr_physical_device_enumerate(struct vk_instance *const vk_instance)
{ {
@ -183,29 +233,25 @@ pvr_physical_device_enumerate(struct vk_instance *const vk_instance)
mesa_logd("Found compatible render device '%s'.", mesa_logd("Found compatible render device '%s'.",
drm_render_device->nodes[DRM_NODE_RENDER]); 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++) { for (int i = 0; i < num_drm_devices; i++) {
drmDevice *const drm_dev = 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))) if (!(drm_dev->available_nodes & BITFIELD_BIT(DRM_NODE_PRIMARY)))
continue; continue;
if (pvr_drm_device_compatible(&config->display, drm_dev)) { if (!pvr_drm_device_is_compatible_display(drm_devices[i]))
drm_display_device = drm_dev; continue;
break;
}
}
if (!drm_display_device) { drm_display_device = drm_dev;
mesa_loge("Render device '%s' has no compatible display device.", mesa_logd("Found a compatible display device: '%s'.",
drm_render_device->nodes[DRM_NODE_RENDER]); drm_display_device->nodes[DRM_NODE_PRIMARY]);
result = VK_SUCCESS; break;
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, pdevice = vk_alloc(&vk_instance->alloc,
sizeof(*pdevice), sizeof(*pdevice),
8, 8,
@ -229,7 +275,9 @@ pvr_physical_device_enumerate(struct vk_instance *const vk_instance)
if (PVR_IS_DEBUG_SET(INFO)) { if (PVR_IS_DEBUG_SET(INFO)) {
pvr_physical_device_dump_info( pvr_physical_device_dump_info(
pdevice, pdevice,
drm_display_device->deviceinfo.platform->compatible, drm_display_device
? drm_display_device->deviceinfo.platform->compatible
: NULL,
drm_render_device->deviceinfo.platform->compatible); 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_display,
char *const *comp_render) char *const *comp_render)
{ {
drmVersionPtr version_display, version_render; drmVersionPtr version_display = NULL, version_render;
struct pvr_device_dump_info info; struct pvr_device_dump_info info = { 0 };
if (pdevice->ws->display_fd >= 0)
version_display = drmGetVersion(pdevice->ws->display_fd);
version_display = drmGetVersion(pdevice->ws->display_fd);
if (!version_display) if (!version_display)
return; return;
@ -56,12 +58,14 @@ pvr_physical_device_dump_info(const struct pvr_physical_device *pdevice,
info.device_info = &pdevice->dev_info; info.device_info = &pdevice->dev_info;
info.device_runtime_info = &pdevice->dev_runtime_info; info.device_runtime_info = &pdevice->dev_runtime_info;
info.drm_display.patchlevel = version_display->version_patchlevel; if (version_display) {
info.drm_display.major = version_display->version_major; info.drm_display.patchlevel = version_display->version_patchlevel;
info.drm_display.minor = version_display->version_minor; info.drm_display.major = version_display->version_major;
info.drm_display.name = version_display->name; info.drm_display.minor = version_display->version_minor;
info.drm_display.date = version_display->date; info.drm_display.name = version_display->name;
info.drm_display.comp = comp_display; info.drm_display.date = version_display->date;
info.drm_display.comp = comp_display;
}
info.drm_render.patchlevel = version_render->version_patchlevel; info.drm_render.patchlevel = version_render->version_patchlevel;
info.drm_render.major = version_render->version_major; info.drm_render.major = version_render->version_major;
info.drm_render.minor = version_render->version_minor; 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; 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, display_path = vk_strdup(&instance->vk.alloc,
drm_display_device->nodes[DRM_NODE_PRIMARY], drm_display_device->nodes[DRM_NODE_PRIMARY],
VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);