diff --git a/repos/libports/include/libdrm/ioctl_dispatch.h b/repos/libports/include/libdrm/ioctl_dispatch.h
new file mode 100644
index 0000000000..182961b55d
--- /dev/null
+++ b/repos/libports/include/libdrm/ioctl_dispatch.h
@@ -0,0 +1,24 @@
+/*
+ * \brief  Libdrm ioctl back end dispatcher
+ * \author Josef Soentgen
+ * \date   2022-07-15
+ */
+
+/*
+ * Copyright (C) 2022 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+
+#ifndef _INCLUDE__LIBDRM__IOCTL_DISPATCH_H_
+#define _INCLUDE__LIBDRM__IOCTL_DISPATCH_H_
+
+namespace Libdrm {
+	enum Driver { INVALID, ETNAVIV };
+}; /* namespace Libdrm */
+
+void drm_init(Libdrm::Driver);
+
+#endif /* #ifndef _INCLUDE__LIBDRM__IOCTL_DISPATCH_H_ */
diff --git a/repos/libports/lib/import/import-libdrm.mk b/repos/libports/lib/import/import-libdrm.mk
index 2e233fbbb4..e9761840d1 100644
--- a/repos/libports/lib/import/import-libdrm.mk
+++ b/repos/libports/lib/import/import-libdrm.mk
@@ -5,6 +5,7 @@ DRM_SRC_DIR = $(call select_from_ports,libdrm)/src/lib/libdrm
 endif
 
 INC_DIR += $(DRM_SRC_DIR)
+INC_DIR += $(DRM_SRC_DIR)/include
 INC_DIR += $(addprefix $(DRM_SRC_DIR)/,include/etnaviv include/drm include)
 INC_DIR += $(addprefix $(DRM_SRC_DIR)/,etnaviv)
 INC_DIR += $(addprefix $(DRM_SRC_DIR)/,iris)
diff --git a/repos/libports/lib/mk/libdrm.inc b/repos/libports/lib/mk/libdrm.inc
index c2b873a469..36e9a5b868 100644
--- a/repos/libports/lib/mk/libdrm.inc
+++ b/repos/libports/lib/mk/libdrm.inc
@@ -2,9 +2,11 @@ LIB_DIR := $(REP_DIR)/src/lib/libdrm
 
 # include before to shadow libdrm_macros.h
 INC_DIR += $(LIB_DIR)/include
+INC_DIR += $(REP_DIR)/src/lib/libdrm
 
 LIBDRM_PORT_DIR := $(call select_from_ports,libdrm)/src/lib/libdrm
 
+REP_INC_DIR += include/libdrm
 REP_INC_DIR += include/drm
 
 LIBS        := libc
diff --git a/repos/libports/lib/mk/spec/arm_v8/libdrm.mk b/repos/libports/lib/mk/spec/arm_v8/libdrm.mk
index ebc65c86eb..38d22b67ed 100644
--- a/repos/libports/lib/mk/spec/arm_v8/libdrm.mk
+++ b/repos/libports/lib/mk/spec/arm_v8/libdrm.mk
@@ -4,4 +4,4 @@ LIBS += vfs_gpu
 
 include $(call select_from_repositories,lib/import/import-libdrm.mk)
 
-SRC_CC := ioctl_etnaviv.cc
+SRC_CC := ioctl_dispatch.cc ioctl_etnaviv.cc
diff --git a/repos/libports/recipes/api/libdrm/content.mk b/repos/libports/recipes/api/libdrm/content.mk
index 9938d01386..3790641f41 100644
--- a/repos/libports/recipes/api/libdrm/content.mk
+++ b/repos/libports/recipes/api/libdrm/content.mk
@@ -19,6 +19,8 @@ include:
 	cp -r $(PORT_DIR)/src/lib/libdrm/intel/*.h $@/intel
 	mkdir -p $@/etnaviv
 	cp -r $(PORT_DIR)/src/lib/libdrm/etnaviv/*.h $@/etnaviv
+	mkdir -p $@/libdrm
+	cp $(REP_DIR)/include/libdrm/ioctl_dispatch.h $@/libdrm
 
 content: LICENSE
 
diff --git a/repos/libports/recipes/src/libdrm/content.mk b/repos/libports/recipes/src/libdrm/content.mk
index 9810c29aef..7872ba245b 100644
--- a/repos/libports/recipes/src/libdrm/content.mk
+++ b/repos/libports/recipes/src/libdrm/content.mk
@@ -2,11 +2,13 @@ MIRROR_FROM_REP_DIR := lib/mk/libdrm.mk \
                        lib/mk/libdrm.inc \
                        lib/mk/spec/arm_v8/libdrm.mk \
                        lib/mk/spec/x86_64/libdrm.mk \
+                       include/libdrm/ioctl_dispatch.h \
                        src/lib/libdrm/include \
                        src/lib/libdrm/dummies.c \
                        src/lib/libdrm/ioctl_dummy.cc \
                        src/lib/libdrm/ioctl_iris.cc \
                        src/lib/libdrm/ioctl_etnaviv.cc \
+                       src/lib/libdrm/ioctl_dispatch.cc
 
 content: $(MIRROR_FROM_REP_DIR) src/lib/libdrm/target.mk
 
diff --git a/repos/libports/src/lib/libdrm/ioctl_dispatch.cc b/repos/libports/src/lib/libdrm/ioctl_dispatch.cc
new file mode 100644
index 0000000000..0f8fee1b41
--- /dev/null
+++ b/repos/libports/src/lib/libdrm/ioctl_dispatch.cc
@@ -0,0 +1,98 @@
+/*
+ * \brief  DRM ioctl back end dispatcher
+ * \author Josef Soentgen
+ * \date   2022-07-15
+ */
+
+/*
+ * Copyright (C) 2022 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+/* Genode includes */
+#include <base/log.h>
+#include <libdrm/ioctl_dispatch.h>
+
+extern "C" {
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <poll.h>
+}
+
+
+/* etnaviv driver */
+
+extern void  etnaviv_drm_init();
+extern int   etnaviv_drm_ioctl(unsigned long, void *);
+extern void *etnaviv_drm_mmap(off_t, size_t);
+extern int   etnaviv_drm_munmap(void *);
+
+
+static Libdrm::Driver drm_backend_type = Libdrm::Driver::INVALID;
+
+
+/**
+ * Initialize DRM back end and set type
+ */
+void drm_init(Libdrm::Driver driver)
+{
+	switch (driver) {
+	case Libdrm::Driver::ETNAVIV:
+		etnaviv_drm_init();
+		drm_backend_type = Libdrm::Driver::ETNAVIV;
+		break;
+	default:
+		Genode::error(__func__, ": unknown back end, abort");
+		abort();
+	}
+}
+
+
+/**
+ * Perfom I/O control request
+ */
+extern "C" int genode_ioctl(int /* fd */, unsigned long request, void *arg)
+{
+	switch (drm_backend_type) {
+	case Libdrm::Driver::ETNAVIV: return etnaviv_drm_ioctl(request, arg);
+	default:          return -1;
+	}
+}
+
+
+/**
+ * Map DRM buffer-object
+ */
+extern "C" void *drm_mmap(void *addr, size_t length, int prot, int flags,
+               int fd, off_t offset)
+{
+	(void)addr;
+	(void)prot;
+	(void)flags;
+	(void)fd;
+
+	switch (drm_backend_type) {
+	case Libdrm::Driver::ETNAVIV: return etnaviv_drm_mmap(offset, length);
+	default:          return NULL;
+	}
+}
+
+
+/**
+ * Unmap DRM buffer-object
+ */
+extern "C" int drm_munmap(void *addr, size_t length)
+{
+	(void)length;
+
+	switch (drm_backend_type) {
+	case Libdrm::Driver::ETNAVIV: return etnaviv_drm_munmap(addr);
+	default:          return -1;
+	}
+}
diff --git a/repos/libports/src/lib/libdrm/ioctl_etnaviv.cc b/repos/libports/src/lib/libdrm/ioctl_etnaviv.cc
index 0a15bc2749..f8a0994926 100644
--- a/repos/libports/src/lib/libdrm/ioctl_etnaviv.cc
+++ b/repos/libports/src/lib/libdrm/ioctl_etnaviv.cc
@@ -24,6 +24,8 @@
 #include <vfs_gpu.h>
 
 extern "C" {
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
@@ -36,6 +38,7 @@ extern "C" {
 
 enum { verbose_ioctl = false };
 
+namespace {
 
 /**
  * Get DRM command number
@@ -105,8 +108,10 @@ const char *command_name(unsigned long request)
 	}
 }
 
+} /* anonymous namespace */
 
-namespace Drm {
+
+namespace Etnaviv {
 
 	size_t get_payload_size(drm_etnaviv_gem_submit const &submit);
 
@@ -128,7 +133,7 @@ namespace Drm {
 } /* anonymous namespace */
 
 
-size_t Drm::get_payload_size(drm_etnaviv_gem_submit const &submit)
+size_t Etnaviv::get_payload_size(drm_etnaviv_gem_submit const &submit)
 {
 	size_t size = 0;
 
@@ -141,7 +146,7 @@ size_t Drm::get_payload_size(drm_etnaviv_gem_submit const &submit)
 }
 
 
-void Drm::serialize(drm_etnaviv_gem_submit *submit, char *content)
+void Etnaviv::serialize(drm_etnaviv_gem_submit *submit, char *content)
 {
 	size_t offset = 0;
 
@@ -204,7 +209,7 @@ void Drm::serialize(drm_etnaviv_gem_submit *submit, char *content)
 }
 
 
-size_t Drm::get_payload_size(drm_version const &version)
+size_t Etnaviv::get_payload_size(drm_version const &version)
 {
 	size_t size = 0;
 	size += version.name_len;
@@ -214,7 +219,7 @@ size_t Drm::get_payload_size(drm_version const &version)
 }
 
 
-void Drm::serialize(drm_version *version, char *content)
+void Etnaviv::serialize(drm_version *version, char *content)
 {
 	size_t offset = 0;
 	char *start = 0;
@@ -236,7 +241,7 @@ void Drm::serialize(drm_version *version, char *content)
 }
 
 
-void Drm::deserialize(drm_version *version, char *content)
+void Etnaviv::deserialize(drm_version *version, char *content)
 {
 	drm_version *cversion = reinterpret_cast<drm_version*>(content);
 
@@ -258,8 +263,9 @@ void Drm::deserialize(drm_version *version, char *content)
 }
 
 
-namespace Gpu {
+namespace Etnaviv {
 	using namespace Genode;
+	using namespace Gpu;
 
 	struct Call;
 } /* namespace Gpu */
@@ -269,16 +275,16 @@ struct Gpu::Buffer
 {
 	Gpu::Connection &_gpu;
 
-	Id_space<Gpu::Buffer>::Element const _elem;
+	Genode::Id_space<Gpu::Buffer>::Element const _elem;
 
-	Dataspace_capability const cap;
-	size_t               const size;
+	Genode::Dataspace_capability const cap;
+	size_t                       const size;
 
-	Constructible<Genode::Attached_dataspace> _attached_buffer { };
+	Genode::Constructible<Genode::Attached_dataspace> _attached_buffer { };
 
-	Buffer(Gpu::Connection      &gpu,
-	       size_t                 size,
-	       Id_space<Gpu::Buffer> &space)
+	Buffer(Gpu::Connection               &gpu,
+	       size_t                         size,
+	       Genode::Id_space<Gpu::Buffer> &space)
 	:
 		_gpu  { gpu },
 		_elem { *this, space },
@@ -312,7 +318,7 @@ struct Gpu::Buffer
 };
 
 
-class Gpu::Call
+class Etnaviv::Call
 {
 	private:
 
@@ -477,7 +483,7 @@ class Gpu::Call
 
 		int _drm_etnaviv_gem_submit(drm_etnaviv_gem_submit &arg)
 		{
-			size_t const payload_size = Drm::get_payload_size(arg);
+			size_t const payload_size = Etnaviv::get_payload_size(arg);
 			if (payload_size > EXEC_BUFFER_SIZE) {
 				Genode::error(__func__, ": exec buffer too small (",
 				              (unsigned)EXEC_BUFFER_SIZE, ") needed ", payload_size);
@@ -490,7 +496,7 @@ class Gpu::Call
 			 */
 			char *local_exec_buffer = (char*)_exec_buffer->mmap_addr();
 			Genode::memset(local_exec_buffer, 0, EXEC_BUFFER_SIZE);
-			Drm::serialize(&arg, local_exec_buffer);
+			Etnaviv::serialize(&arg, local_exec_buffer);
 
 			try {
 				Genode::uint64_t const pending_exec_buffer =
@@ -673,10 +679,10 @@ class Gpu::Call
 };
 
 
-static Genode::Constructible<Gpu::Call> _drm;
+static Genode::Constructible<Etnaviv::Call> _drm;
 
 
-void drm_init()
+void etnaviv_drm_init()
 {
 	struct ::stat buf;
 	if (stat("/dev/gpu", &buf) < 0) {
@@ -689,9 +695,6 @@ void drm_init()
 }
 
 
-/**
- * Dump I/O control request to LOG
- */
 static void dump_ioctl(unsigned long request)
 {
 	using namespace Genode;
@@ -705,10 +708,7 @@ static void dump_ioctl(unsigned long request)
 }
 
 
-/**
- * Perfom I/O control request
- */
-extern "C" int genode_ioctl(int /* fd */, unsigned long request, void *arg)
+int etnaviv_drm_ioctl(unsigned long request, void *arg)
 {
 	if (verbose_ioctl)
 		dump_ioctl(request);
@@ -726,28 +726,14 @@ extern "C" int genode_ioctl(int /* fd */, unsigned long request, void *arg)
 }
 
 
-/**
- * Map DRM buffer-object
- */
-void *drm_mmap(void *addr, size_t length, int prot, int flags,
-               int fd, off_t offset)
+void *etnaviv_drm_mmap(off_t offset, size_t length)
 {
-	(void)addr;
-	(void)prot;
-	(void)flags;
-	(void)fd;
-
 	return _drm->mmap(offset, length);
 }
 
 
-/**
- * Unmap DRM buffer-object
- */
-int drm_munmap(void *addr, size_t length)
+int etnaviv_drm_munmap(void *addr)
 {
-	(void)length;
-
 	_drm->munmap(addr);
 	return 0;
 }
diff --git a/repos/libports/src/lib/mesa/etnaviv/drm_init.cc b/repos/libports/src/lib/mesa/etnaviv/drm_init.cc
index 027c8459a5..90a8306551 100644
--- a/repos/libports/src/lib/mesa/etnaviv/drm_init.cc
+++ b/repos/libports/src/lib/mesa/etnaviv/drm_init.cc
@@ -5,7 +5,7 @@
  */
 
 /*
- * Copyright (C) 2021 Genode Labs GmbH
+ * Copyright (C) 2021-2022 Genode Labs GmbH
  *
  * This file is part of the Genode OS framework, which is distributed
  * under the terms of the GNU Affero General Public License version 3.
@@ -15,13 +15,13 @@
 #include <../include/util/list.h>
 #include <base/env.h>
 
+#include <libdrm/ioctl_dispatch.h>
+
 extern "C" {
 #include <platform.h>
 }
 
-extern void drm_init();
-
 void genode_drm_init()
 {
-	drm_init();
+	drm_init(Libdrm::Driver::ETNAVIV);
 }