Add vkms support

The vkms driver is used to get the Android to work on the BeagleBone
Black. Only a minimum amount of support is needed but the driver can
only be recognized by looking at card DRM nodes. The vkms driver does
not publish a render node.

We refactored the cros_gralloc_driver::init to test both the render
nodes and the card nodes.

Change-Id: Ie750aa45fc359ba7917919904693b1ab8088ad16
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/2213742
Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc
index 259eae2..d9e6cf5 100644
--- a/cros_gralloc/cros_gralloc_driver.cc
+++ b/cros_gralloc/cros_gralloc_driver.cc
@@ -16,6 +16,16 @@
 #include "../helpers.h"
 #include "../util.h"
 
+// Constants taken from pipe_loader_drm.c in Mesa
+
+#define DRM_NUM_NODES 63
+
+// DRM Render nodes start at 128
+#define DRM_RENDER_NODE_START 128
+
+// DRM Card nodes start at 0
+#define DRM_CARD_NODE_START 0
+
 int memfd_create_wrapper(const char *name, unsigned int flags)
 {
 	int fd;
@@ -52,54 +62,57 @@
 	}
 }
 
+static struct driver *init_try_node(int idx, char const *str)
+{
+	int fd;
+	char *node;
+	struct driver *drv;
+
+	if (asprintf(&node, str, DRM_DIR_NAME, idx) < 0)
+		return NULL;
+
+	fd = open(node, O_RDWR, 0);
+	free(node);
+
+	if (fd < 0)
+		return NULL;
+
+	drv = drv_create(fd);
+	if (!drv)
+		close(fd);
+
+	return drv;
+}
+
 int32_t cros_gralloc_driver::init()
 {
 	/*
-	 * Create a driver from rendernode while filtering out
-	 * the specified undesired driver.
+	 * Create a driver from render nodes first, then try card
+	 * nodes.
 	 *
 	 * TODO(gsingh): Enable render nodes on udl/evdi.
 	 */
 
-	int fd;
-	drmVersionPtr version;
-	char const *str = "%s/renderD%d";
-	const char *undesired[2] = { "vgem", nullptr };
-	uint32_t num_nodes = 63;
-	uint32_t min_node = 128;
-	uint32_t max_node = (min_node + num_nodes);
+	char const *render_nodes_fmt = "%s/renderD%d";
+	char const *card_nodes_fmt = "%s/card%d";
+	uint32_t num_nodes = DRM_NUM_NODES;
+	uint32_t min_render_node = DRM_RENDER_NODE_START;
+	uint32_t max_render_node = (min_render_node + num_nodes);
+	uint32_t min_card_node = DRM_CARD_NODE_START;
+	uint32_t max_card_node = (min_card_node + num_nodes);
 
-	for (uint32_t i = 0; i < ARRAY_SIZE(undesired); i++) {
-		for (uint32_t j = min_node; j < max_node; j++) {
-			char *node;
-			if (asprintf(&node, str, DRM_DIR_NAME, j) < 0)
-				continue;
+	// Try render nodes...
+	for (uint32_t i = min_render_node; i < max_render_node; i++) {
+		drv_ = init_try_node(i, render_nodes_fmt);
+		if (drv_)
+			return 0;
+	}
 
-			fd = open(node, O_RDWR | O_CLOEXEC);
-			free(node);
-
-			if (fd < 0)
-				continue;
-
-			version = drmGetVersion(fd);
-			if (!version) {
-				close(fd);
-				continue;
-			}
-
-			if (undesired[i] && !strcmp(version->name, undesired[i])) {
-				close(fd);
-				drmFreeVersion(version);
-				continue;
-			}
-
-			drmFreeVersion(version);
-			drv_ = drv_create(fd);
-			if (drv_)
-				return 0;
-
-			close(fd);
-		}
+	// Try card nodes... for vkms mostly.
+	for (uint32_t i = min_card_node; i < max_card_node; i++) {
+		drv_ = init_try_node(i, card_nodes_fmt);
+		if (drv_)
+			return 0;
 	}
 
 	return -ENODEV;
diff --git a/drv.c b/drv.c
index 233cce7..5c8f9a0 100644
--- a/drv.c
+++ b/drv.c
@@ -60,6 +60,7 @@
 extern const struct backend backend_synaptics;
 extern const struct backend backend_virtio_gpu;
 extern const struct backend backend_udl;
+extern const struct backend backend_vkms;
 
 static const struct backend *drv_get_backend(int fd)
 {
@@ -93,9 +94,9 @@
 #ifdef DRV_VC4
 		&backend_vc4,
 #endif
-		&backend_evdi,	    &backend_marvell,	 &backend_meson,
-		&backend_nouveau,   &backend_komeda,	 &backend_radeon,
-		&backend_synaptics, &backend_virtio_gpu, &backend_udl,
+		&backend_evdi,	   &backend_marvell,	&backend_meson,	    &backend_nouveau,
+		&backend_komeda,   &backend_radeon,	&backend_synaptics, &backend_virtio_gpu,
+		&backend_udl,	   &backend_virtio_gpu, &backend_vkms
 	};
 
 	for (i = 0; i < ARRAY_SIZE(backend_list); i++) {
diff --git a/dumb_driver.c b/dumb_driver.c
index 7d0d8be..f5a62aa 100644
--- a/dumb_driver.c
+++ b/dumb_driver.c
@@ -50,3 +50,4 @@
 INIT_DUMB_DRIVER(radeon)
 INIT_DUMB_DRIVER(synaptics)
 INIT_DUMB_DRIVER(udl)
+INIT_DUMB_DRIVER(vkms)