diff -pruN 1.9.0+dfsg-1/debian/changelog 1.12.0+dfsg-0ubuntu2/debian/changelog
--- 1.9.0+dfsg-1/debian/changelog	2021-01-26 15:32:36.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/debian/changelog	2022-08-31 09:59:24.000000000 +0000
@@ -1,3 +1,51 @@
+evdi (1.12.0+dfsg-0ubuntu2) kinetic; urgency=medium
+
+  * Add build-exclusive dkms.conf key, to prevent FTBFS on incompatible
+    kernels.
+
+ -- Dimitri John Ledkov <dimitri.ledkov@canonical.com>  Wed, 31 Aug 2022 10:59:24 +0100
+
+evdi (1.12.0+dfsg-0ubuntu1) kinetic; urgency=medium
+
+  * New upstream release.
+  * Drop all patches, keep USBLESS patch.
+  * Cherry-pick upstream fixup patch.
+
+ -- Dimitri John Ledkov <dimitri.ledkov@canonical.com>  Tue, 26 Jul 2022 14:25:09 +0100
+
+evdi (1.9.1-1ubuntu5) jammy; urgency=medium
+
+  * Fix build with Linux 5.15 and 5.14.
+
+ -- Paolo Pisati <paolo.pisati@canonical.com>  Fri, 24 Sep 2021 14:38:51 +0000
+
+evdi (1.9.1-1ubuntu4) impish; urgency=medium
+
+  * Support USB-less systems (e.g. s390x). (LP: #1932163)
+
+ -- Andrea Righi <andrea.righi@canonical.com>  Tue, 20 Jul 2021 14:32:12 +0000
+
+evdi (1.9.1-1ubuntu3) impish; urgency=medium
+
+  * Fix regression with Linux 5.11
+
+ -- Paolo Pisati <paolo.pisati@canonical.com>  Wed, 16 Jun 2021 08:33:25 +0000
+
+evdi (1.9.1-1ubuntu2) impish; urgency=medium
+
+  * Fix build with Linux 5.13
+
+ -- Paolo Pisati <paolo.pisati@canonical.com>  Tue, 01 Jun 2021 10:48:39 +0000
+
+evdi (1.9.1-1ubuntu1) hirsute; urgency=medium
+
+  * New upstream release 1.9.1
+  * Fix build with Linux 5.11 (LP: #1923638)
+    - debian/patches/0001-Merge-branch-private-dczerwik-enable-cursor-ioctl-in.patch
+    - debian/patches/0002-Add-support-for-5.11-and-5.12-kernels.patch
+
+ -- Paolo Pisati <paolo.pisati@canonical.com>  Thu, 01 Apr 2021 14:24:23 +0000
+
 evdi (1.9.0+dfsg-1) unstable; urgency=medium
 
   * new upstream release 1.9.0
diff -pruN 1.9.0+dfsg-1/debian/control 1.12.0+dfsg-0ubuntu2/debian/control
--- 1.9.0+dfsg-1/debian/control	2021-01-26 15:32:36.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/debian/control	2021-04-01 14:24:23.000000000 +0000
@@ -1,7 +1,8 @@
 Source: evdi
 Section: misc
 Priority: optional
-Maintainer: Hanno Stock <opensource@hanno-stock.de>
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+XSBC-Original-Maintainer: Hanno Stock <opensource@hanno-stock.de>
 Build-Depends: debhelper-compat (= 13), dkms, dh-exec, libdrm-dev
 Standards-Version: 4.5.0
 Rules-Requires-Root: no
diff -pruN 1.9.0+dfsg-1/debian/evdi-dkms.dkms 1.12.0+dfsg-0ubuntu2/debian/evdi-dkms.dkms
--- 1.9.0+dfsg-1/debian/evdi-dkms.dkms	2021-01-26 15:32:36.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/debian/evdi-dkms.dkms	2022-08-31 09:59:24.000000000 +0000
@@ -15,3 +15,5 @@ DEST_MODULE_LOCATION[0]="/kernel/drivers
 BUILT_MODULE_NAME[0]="$PACKAGE_NAME"
 CLEAN="make -C ${kernel_source_dir} M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build DKMS_BUILD=1 clean"
 
+BUILD_EXCLUSIVE_CONFIG=CONFIG_I2C
+
diff -pruN 1.9.0+dfsg-1/debian/patches/0005-evdi-support-usbless-systems.patch 1.12.0+dfsg-0ubuntu2/debian/patches/0005-evdi-support-usbless-systems.patch
--- 1.9.0+dfsg-1/debian/patches/0005-evdi-support-usbless-systems.patch	1970-01-01 00:00:00.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/debian/patches/0005-evdi-support-usbless-systems.patch	2021-07-20 14:32:12.000000000 +0000
@@ -0,0 +1,99 @@
+From: Andrea Righi <andrea.righi@canonical.com>
+Subject: support USB-less systems
+Description: Allow to compile the module also on systems where
+ CONFIG_USB_SUPPORT is disabled.
+Author: Andrea Righi <andrea.righi@canonical.com>
+
+diff -urpN evdi-1.9.1.orig/module/evdi_platform_drv.c evdi-1.9.1/module/evdi_platform_drv.c
+--- evdi-1.9.1.orig/module/evdi_platform_drv.c	2021-07-20 12:35:10.000000000 +0000
++++ evdi-1.9.1/module/evdi_platform_drv.c	2021-07-20 14:29:04.230957406 +0000
+@@ -12,7 +12,9 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
++#ifdef CONFIG_USB_SUPPORT
+ #include <linux/usb.h>
++#endif
+ 
+ #include "evdi_params.h"
+ #include "evdi_debug.h"
+@@ -30,7 +32,9 @@ static struct evdi_platform_drv_context
+ 	struct device *root_dev;
+ 	unsigned int dev_count;
+ 	struct platform_device *devices[EVDI_DEVICE_COUNT_MAX];
++#ifdef CONFIG_USB_SUPPORT
+ 	struct notifier_block usb_notifier;
++#endif
+ 	struct mutex lock;
+ } g_ctx;
+ 
+@@ -40,6 +44,7 @@ static struct evdi_platform_drv_context
+ #define evdi_platform_drv_context_unlock(ctx) \
+ 		mutex_unlock(&ctx->lock)
+ 
++#ifdef CONFIG_USB_SUPPORT
+ static int evdi_platform_drv_usb(__always_unused struct notifier_block *nb,
+ 		unsigned long action,
+ 		void *data)
+@@ -69,6 +74,7 @@ static int evdi_platform_drv_usb(__alway
+ 	}
+ 	return 0;
+ }
++#endif
+ 
+ static int evdi_platform_drv_get_free_idx(struct evdi_platform_drv_context *ctx)
+ {
+@@ -213,11 +219,15 @@ static int __init evdi_init(void)
+ 
+ 	memset(&g_ctx, 0, sizeof(g_ctx));
+ 	g_ctx.root_dev = root_device_register(DRIVER_NAME);
++#ifdef CONFIG_USB_SUPPORT
+ 	g_ctx.usb_notifier.notifier_call = evdi_platform_drv_usb;
++#endif
+ 	mutex_init(&g_ctx.lock);
+ 	dev_set_drvdata(g_ctx.root_dev, &g_ctx);
+ 
++#ifdef CONFIG_USB_SUPPORT
+ 	usb_register_notify(&g_ctx.usb_notifier);
++#endif
+ 	evdi_sysfs_init(g_ctx.root_dev);
+ 	ret = platform_driver_register(&evdi_platform_driver);
+ 	if (ret)
+@@ -238,7 +248,9 @@ static void __exit evdi_exit(void)
+ 
+ 	if (!PTR_ERR_OR_ZERO(g_ctx.root_dev)) {
+ 		evdi_sysfs_exit(g_ctx.root_dev);
++#ifdef CONFIG_USB_SUPPORT
+ 		usb_unregister_notify(&g_ctx.usb_notifier);
++#endif
+ 		dev_set_drvdata(g_ctx.root_dev, NULL);
+ 		root_device_unregister(g_ctx.root_dev);
+ 	}
+diff -urpN evdi-1.9.1.orig/module/evdi_sysfs.c evdi-1.9.1/module/evdi_sysfs.c
+--- evdi-1.9.1.orig/module/evdi_sysfs.c	2021-07-20 12:35:10.000000000 +0000
++++ evdi-1.9.1/module/evdi_sysfs.c	2021-07-20 14:28:45.940957406 +0000
+@@ -51,6 +51,7 @@ struct evdi_usb_addr {
+ 	struct usb_device *usb;
+ };
+ 
++#ifdef CONFIG_USB_SUPPORT
+ static int evdi_platform_device_attach(struct device *device,
+ 		struct evdi_usb_addr *parent_addr);
+ 
+@@ -166,6 +167,16 @@ static int evdi_platform_device_attach(s
+ 	return evdi_platform_device_add(device, parent);
+ }
+ 
++#else /* !CONFIG_USB_SUPPORT */
++
++static ssize_t add_device_with_usb_path(struct device *dev,
++			 const char *buf, size_t count)
++{
++	return -EINVAL;
++}
++
++#endif /* CONFIG_USB_SUPPORT */
++
+ static ssize_t add_store(struct device *dev,
+ 			 __always_unused struct device_attribute *attr,
+ 			 const char *buf, size_t count)
diff -pruN 1.9.0+dfsg-1/debian/patches/b884877267f11edaeb2a0f05201943e4252e22f2.patch 1.12.0+dfsg-0ubuntu2/debian/patches/b884877267f11edaeb2a0f05201943e4252e22f2.patch
--- 1.9.0+dfsg-1/debian/patches/b884877267f11edaeb2a0f05201943e4252e22f2.patch	1970-01-01 00:00:00.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/debian/patches/b884877267f11edaeb2a0f05201943e4252e22f2.patch	2022-07-26 13:25:09.000000000 +0000
@@ -0,0 +1,32 @@
+From b884877267f11edaeb2a0f05201943e4252e22f2 Mon Sep 17 00:00:00 2001
+From: Ryan Gonzalez <rymg19@gmail.com>
+Date: Fri, 10 Jun 2022 20:35:18 -0500
+Subject: [PATCH] Fix crashes with dmabufs not from external kernel modules
+
+In particular, when software rendering, it is entirely possible to have
+a dmabuf that did not come from an externally loaded kernel module. As a
+result, the owner field is NULL, and checking the owner's name
+segfaults.
+
+Tested on the Asahi Linux kernel, where software rendering is used.
+---
+ module/evdi_gem.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/module/evdi_gem.c b/module/evdi_gem.c
+index 4b3449e..22612c5 100644
+--- a/module/evdi_gem.c
++++ b/module/evdi_gem.c
+@@ -62,10 +62,10 @@ static bool evdi_was_called_by_mutter(void)
+ 
+ static bool evdi_drm_gem_object_use_import_attach(struct drm_gem_object *obj)
+ {
+-	if (!obj || !obj->import_attach)
++	if (!obj || !obj->import_attach || !obj->import_attach->dmabuf->owner)
+ 		return false;
+ 
+-	return obj->import_attach && strcmp(obj->import_attach->dmabuf->owner->name, "amdgpu") != 0;
++	return strcmp(obj->import_attach->dmabuf->owner->name, "amdgpu") != 0;
+ }
+ 
+ uint32_t evdi_gem_object_handle_lookup(struct drm_file *filp,
diff -pruN 1.9.0+dfsg-1/debian/patches/series 1.12.0+dfsg-0ubuntu2/debian/patches/series
--- 1.9.0+dfsg-1/debian/patches/series	1970-01-01 00:00:00.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/debian/patches/series	2022-08-31 09:59:24.000000000 +0000
@@ -0,0 +1,2 @@
+0005-evdi-support-usbless-systems.patch
+b884877267f11edaeb2a0f05201943e4252e22f2.patch
diff -pruN 1.9.0+dfsg-1/library/evdi_lib.c 1.12.0+dfsg-0ubuntu2/library/evdi_lib.c
--- 1.9.0+dfsg-1/library/evdi_lib.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/library/evdi_lib.c	2022-07-13 13:58:06.000000000 +0000
@@ -29,7 +29,7 @@
 #define EVDI_INVALID_DEVICE_INDEX -1
 
 #define EVDI_MODULE_COMPATIBILITY_VERSION_MAJOR 1
-#define EVDI_MODULE_COMPATIBILITY_VERSION_MINOR 8
+#define EVDI_MODULE_COMPATIBILITY_VERSION_MINOR 9
 #define EVDI_MODULE_COMPATIBILITY_VERSION_PATCH 0
 
 #define evdi_log(...) do {						\
@@ -468,15 +468,45 @@ static int get_drm_device_index(const ch
 	return dev_index;
 }
 
-static int find_unused_card_for(const char *sysfs_parent_device_path)
+static bool is_correct_parent_device(const char *dirname, const char *parent_device)
 {
+	char link_path[PATH_MAX];
+
+	snprintf(link_path, PATH_MAX - 7, "%s/device", dirname);
+
+	if (parent_device == NULL)
+		return access(link_path, F_OK) != 0;
+
+	char link_resolution[PATH_MAX];
+	const ssize_t link_resolution_len = readlink(link_path, link_resolution, PATH_MAX);
+
+	if (link_resolution_len == -1 || link_resolution_len == PATH_MAX)
+		return false;
+
+	link_resolution[link_resolution_len] = '\0';
+	char *parent_device_token = strrchr(link_resolution, '/');
+
+	if (strlen(parent_device) < 2)
+		return false;
+
+	parent_device_token++;
+	size_t len = strlen(parent_device_token);
+
+	bool is_same_device = strlen(parent_device) == len && strncmp(parent_device_token, parent_device, len) == 0;
+
+	return is_same_device;
+}
+
+static int find_unused_card_for(const char *parent_device)
+{
+	char evdi_platform_root[] = "/sys/bus/platform/devices";
 	struct dirent *fd_entry;
 	DIR *fd_dir;
 	int device_index = EVDI_INVALID_DEVICE_INDEX;
 
-	fd_dir = opendir(sysfs_parent_device_path);
+	fd_dir = opendir(evdi_platform_root);
 	if (fd_dir == NULL) {
-		evdi_log("Failed to open dir %s", sysfs_parent_device_path);
+		evdi_log("Failed to open dir %s", evdi_platform_root);
 		return device_index;
 	}
 
@@ -484,9 +514,16 @@ static int find_unused_card_for(const ch
 		if (strncmp(fd_entry->d_name, "evdi", 4) != 0)
 			continue;
 
+		char evdi_path[PATH_MAX];
+
+		snprintf(evdi_path, PATH_MAX, "%s/%s", evdi_platform_root, fd_entry->d_name);
+
+		if (!is_correct_parent_device(evdi_path, parent_device))
+			continue;
+
 		char evdi_drm_path[PATH_MAX];
 
-		snprintf(evdi_drm_path, PATH_MAX, "%s/%s/drm", sysfs_parent_device_path, fd_entry->d_name);
+		snprintf(evdi_drm_path, PATH_MAX - strlen(evdi_path), "%s/drm", evdi_path);
 		int dev_index = get_drm_device_index(evdi_drm_path);
 
 		assert(dev_index < EVDI_USAGE_LEN && dev_index >= 0);
@@ -503,37 +540,30 @@ static int find_unused_card_for(const ch
 
 static int get_generic_device(void)
 {
-	char evdi_platform_root[] = "/sys/devices/platform";
 	int device_index = EVDI_INVALID_DEVICE_INDEX;
 
-	device_index = find_unused_card_for(evdi_platform_root);
+	device_index = find_unused_card_for(NULL);
 	if (device_index == EVDI_INVALID_DEVICE_INDEX) {
-		evdi_log("Creating card in %s", evdi_platform_root);
+		evdi_log("Creating card in /sys/devices/platform");
 		write_add_device("1", 1);
-		device_index = find_unused_card_for(evdi_platform_root);
+		device_index = find_unused_card_for(NULL);
 	}
 
 	return device_index;
 }
 
-static int get_device_attached_to_usb(const char *bus_ident)
+static int get_device_attached_to_usb(const char *sysfs_parent_device)
 {
 	int device_index = EVDI_INVALID_DEVICE_INDEX;
-	char evdi_usb_parent_path[PATH_MAX] = "/sys/bus/usb/devices/";
-
-	strncat(evdi_usb_parent_path, bus_ident, PATH_MAX - strlen(evdi_usb_parent_path));
+	const char *parent_device = &sysfs_parent_device[4];
 
-	device_index = find_unused_card_for(evdi_usb_parent_path);
+	device_index = find_unused_card_for(parent_device);
 	if (device_index == EVDI_INVALID_DEVICE_INDEX) {
-		evdi_log("Creating card for %s", bus_ident);
-		char usb_dev_path[PATH_MAX] = "usb:";
-		const size_t current_len = strlen(usb_dev_path);
+		evdi_log("Creating card for usb device %s in /sys/bus/platform/devices", parent_device);
+		const size_t len = strlen(sysfs_parent_device);
 
-		strncat(usb_dev_path, bus_ident, PATH_MAX - current_len);
-		const size_t len = strlen(usb_dev_path);
-
-		write_add_device(usb_dev_path, len);
-		device_index = find_unused_card_for(evdi_usb_parent_path);
+		write_add_device(sysfs_parent_device, len);
+		device_index = find_unused_card_for(parent_device);
 	}
 
 	return device_index;
@@ -616,14 +646,8 @@ evdi_handle evdi_open_attached_to(const
 	if (sysfs_parent_device == NULL)
 		device_index = get_generic_device();
 
-	if (sysfs_parent_device != NULL && strncmp(sysfs_parent_device, "usb:", 4) == 0 && strlen(sysfs_parent_device) > 4) {
-		char bus_ident[PATH_MAX];
-		const size_t len = strlen(sysfs_parent_device) - 4;
-
-		strncpy(bus_ident, &sysfs_parent_device[4], len);
-		bus_ident[len] = 0;
-		device_index = get_device_attached_to_usb(bus_ident);
-	}
+	if (sysfs_parent_device != NULL && strncmp(sysfs_parent_device, "usb:", 4) == 0 && strlen(sysfs_parent_device) > 4)
+		device_index = get_device_attached_to_usb(sysfs_parent_device);
 
 	if (device_index >= 0 && device_index < EVDI_USAGE_LEN)  {
 		evdi_handle handle = evdi_open(device_index);
@@ -651,14 +675,16 @@ void evdi_close(evdi_handle handle)
 void evdi_connect(evdi_handle handle,
 		  const unsigned char *edid,
 		  const unsigned int edid_length,
-		  const uint32_t sku_area_limit)
+		  const uint32_t pixel_area_limit,
+		  const uint32_t pixel_per_second_limit)
 {
 	struct drm_evdi_connect cmd = {
 		.connected = 1,
 		.dev_index = handle->device_index,
 		.edid = edid,
 		.edid_length = edid_length,
-		.sku_area_limit = sku_area_limit,
+		.pixel_area_limit = pixel_area_limit,
+		.pixel_per_second_limit = pixel_per_second_limit,
 	};
 
 	do_ioctl(handle->fd, DRM_IOCTL_EVDI_CONNECT, &cmd, "connect");
@@ -666,44 +692,22 @@ void evdi_connect(evdi_handle handle,
 
 void evdi_disconnect(evdi_handle handle)
 {
-	struct drm_evdi_connect cmd = { 0, 0, 0, 0, 0 };
+	struct drm_evdi_connect cmd = { 0, 0, 0, 0, 0, 0 };
 
 	do_ioctl(handle->fd, DRM_IOCTL_EVDI_CONNECT, &cmd, "disconnect");
 }
 
-void evdi_enable_cursor_events(evdi_handle handle)
+void evdi_enable_cursor_events(evdi_handle handle, bool enable)
 {
-	char path[PATH_MAX] = {0};
-	static const char enable[] = "Y";
-	int path_len = 0;
-	FILE *cursor_evs = NULL;
-	size_t written = 0;
-	const size_t elem_bytes = 1;
-	int errcode = 0;
-
-	if (evdi_device_to_platform(handle->device_index, path) !=
-	    AVAILABLE) {
-		evdi_log("Failed to enable cursor events");
-		evdi_log("Device /dev/dri/card%d, device is not available.",
-			handle->device_index);
-		return;
-	}
+	struct drm_evdi_enable_cursor_events cmd = {
+		.enable = enable,
+	};
 
-	path_len = strlen(path);
-	snprintf(path+path_len, PATH_MAX-path_len, "/cursor_events");
-	cursor_evs = fopen(path, "w");
-	if (cursor_evs == NULL) {
-		evdi_log("Failed to open %s, err: %s", path, strerror(errno));
-		return;
-	}
+	evdi_log("%s cursor events on /dev/dri/card%d",
+		(enable ? "Enabling" : "Disabling"),
+		handle->device_index);
 
-	written = fwrite(enable, elem_bytes, sizeof(enable), cursor_evs);
-	errcode = errno;
-	fclose(cursor_evs);
-	evdi_log("Enabling cursor events on /dev/dri/card%d %s %s",
-		handle->device_index,
-		written < sizeof(enable) ? "failed: " : "succeeded",
-		written < sizeof(enable) ? strerror(errcode) : "");
+	do_ioctl(handle->fd, DRM_IOCTL_EVDI_ENABLE_CURSOR_EVENTS, &cmd, "enable cursor events");
 }
 
 void evdi_grab_pixels(evdi_handle handle,
@@ -861,6 +865,8 @@ static struct evdi_cursor_set to_evdi_cu
 			cursor_set.buffer = malloc(size);
 			memcpy(cursor_set.buffer, ptr, size);
 			munmap(ptr, size);
+		} else {
+			evdi_log("Error: mmap failed with error: %s", strerror(errno));
 		}
 	}
 
@@ -936,10 +942,13 @@ static void evdi_handle_event(evdi_handl
 		if (evtctx->cursor_set_handler) {
 			struct drm_evdi_event_cursor_set *event =
 				(struct drm_evdi_event_cursor_set *) e;
+			struct evdi_cursor_set cursor_set = to_evdi_cursor_set(handle, event);
 
-			evtctx->cursor_set_handler(to_evdi_cursor_set(handle,
-								      event),
-						   evtctx->user_data);
+			if (cursor_set.enabled && cursor_set.buffer == NULL)
+				evdi_log("Error: Cursor buffer is null!");
+			else
+				evtctx->cursor_set_handler(cursor_set,
+							   evtctx->user_data);
 		}
 		break;
 
diff -pruN 1.9.0+dfsg-1/library/evdi_lib.h 1.12.0+dfsg-0ubuntu2/library/evdi_lib.h
--- 1.9.0+dfsg-1/library/evdi_lib.h	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/library/evdi_lib.h	2022-07-13 13:58:06.000000000 +0000
@@ -12,7 +12,7 @@ extern "C" {
 #endif
 
 #define LIBEVDI_VERSION_MAJOR 1
-#define LIBEVDI_VERSION_MINOR 9
+#define LIBEVDI_VERSION_MINOR 12
 #define LIBEVDI_VERSION_PATCH 0
 
 struct evdi_lib_version {
@@ -107,9 +107,10 @@ evdi_handle evdi_open_attached_to(const
 void evdi_close(evdi_handle handle);
 void evdi_connect(evdi_handle handle, const unsigned char *edid,
 		  const unsigned int edid_length,
-		  const uint32_t sku_area_limit);
+		  const uint32_t pixel_area_limit,
+		  const uint32_t pixel_per_second_limit);
 void evdi_disconnect(evdi_handle handle);
-void evdi_enable_cursor_events(evdi_handle handle);
+void evdi_enable_cursor_events(evdi_handle handle, bool enable);
 
 void evdi_grab_pixels(evdi_handle handle,
 		      struct evdi_rect *rects,
diff -pruN 1.9.0+dfsg-1/library/Makefile 1.12.0+dfsg-0ubuntu2/library/Makefile
--- 1.9.0+dfsg-1/library/Makefile	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/library/Makefile	2022-07-13 13:58:06.000000000 +0000
@@ -8,9 +8,9 @@ LN ?= ln
 RM ?= rm
 
 DEPS = evdi_ioctl.h
-CFLAGS := -I../module -std=gnu99 -fPIC $(CFLAGS)
+CFLAGS := -I../module -std=gnu99 -fPIC -D_FILE_OFFSET_BITS=64 $(CFLAGS)
 
-LIBVER := 1.9.0
+LIBVER := 1.12.0
 LIBABI := 0
 
 PREFIX ?= /usr/local
diff -pruN 1.9.0+dfsg-1/module/dkms.conf 1.12.0+dfsg-0ubuntu2/module/dkms.conf
--- 1.9.0+dfsg-1/module/dkms.conf	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/dkms.conf	2022-07-13 13:58:06.000000000 +0000
@@ -7,7 +7,7 @@
 #
 
 PACKAGE_NAME="evdi"
-PACKAGE_VERSION=1.9.0
+PACKAGE_VERSION=1.12.0
 AUTOINSTALL=yes
 
 MAKE[0]="make all INCLUDEDIR=/lib/modules/$kernelver/build/include KVERSION=$kernelver DKMS_BUILD=1"
diff -pruN 1.9.0+dfsg-1/module/evdi_connector.c 1.12.0+dfsg-0ubuntu2/module/evdi_connector.c
--- 1.9.0+dfsg-1/module/evdi_connector.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_connector.c	2022-07-13 13:58:06.000000000 +0000
@@ -50,11 +50,14 @@ static int evdi_get_modes(struct drm_con
 	ret = drm_mode_connector_update_edid_property(connector, edid);
 #endif
 
-	if (!ret)
-		ret = drm_add_edid_modes(connector, edid);
-	else
-		EVDI_ERROR("Failed to set edid modes! error: %d", ret);
+	if (ret) {
+		EVDI_ERROR("Failed to set edid property! error: %d", ret);
+		goto err;
+	}
 
+	ret = drm_add_edid_modes(connector, edid);
+	EVDI_INFO("(card%d) Edid property set", evdi->dev_index);
+err:
 	kfree(edid);
 	return ret;
 }
@@ -63,13 +66,15 @@ static enum drm_mode_status evdi_mode_va
 					    struct drm_display_mode *mode)
 {
 	struct evdi_device *evdi = connector->dev->dev_private;
-	uint32_t mode_area = mode->hdisplay * mode->vdisplay;
+	uint32_t area_limit = mode->hdisplay * mode->vdisplay;
+	uint32_t mode_limit = area_limit * drm_mode_vrefresh(mode);
 
-	if (evdi->sku_area_limit == 0)
+	if (evdi->pixel_per_second_limit == 0)
 		return MODE_OK;
 
-	if (mode_area > evdi->sku_area_limit) {
-		EVDI_WARN("(dev=%d) Mode %dx%d@%d rejected\n",
+	if (area_limit > evdi->pixel_area_limit ||
+	    mode_limit > evdi->pixel_per_second_limit) {
+		EVDI_WARN("(card%d) Mode %dx%d@%d rejected\n",
 			evdi->dev_index,
 			mode->hdisplay,
 			mode->vdisplay,
@@ -87,11 +92,11 @@ evdi_detect(struct drm_connector *connec
 
 	EVDI_CHECKPT();
 	if (evdi_painter_is_connected(evdi->painter)) {
-		EVDI_DEBUG("(dev=%d) poll connector state: connected\n",
+		EVDI_INFO("(card%d) Connector state: connected\n",
 			   evdi->dev_index);
 		return connector_status_connected;
 	}
-	EVDI_DEBUG("(dev=%d) poll connector state: disconnected\n",
+	EVDI_VERBOSE("(card%d) Connector state: disconnected\n",
 		   evdi->dev_index);
 	return connector_status_disconnected;
 }
diff -pruN 1.9.0+dfsg-1/module/evdi_cursor.c 1.12.0+dfsg-0ubuntu2/module/evdi_cursor.c
--- 1.9.0+dfsg-1/module/evdi_cursor.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_cursor.c	2022-07-13 13:58:06.000000000 +0000
@@ -55,7 +55,7 @@ static void evdi_cursor_set_gem(struct e
 	if (obj)
 		drm_gem_object_get(&obj->base);
 	if (cursor->obj)
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
 		drm_gem_object_put(&cursor->obj->base);
 #else
 		drm_gem_object_put_unlocked(&cursor->obj->base);
@@ -232,8 +232,8 @@ int evdi_cursor_compose_and_copy(struct
 			bool const is_pix_sane =
 				mouse_pix_x >= 0 &&
 				mouse_pix_y >= 0 &&
-				mouse_pix_x < fb->width &&
-				mouse_pix_y < fb->height;
+				mouse_pix_x < (int)fb->width &&
+				mouse_pix_y < (int)fb->height;
 
 			if (!is_pix_sane)
 				continue;
diff -pruN 1.9.0+dfsg-1/module/evdi_debug.c 1.12.0+dfsg-0ubuntu2/module/evdi_debug.c
--- 1.9.0+dfsg-1/module/evdi_debug.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_debug.c	2022-07-13 13:58:06.000000000 +0000
@@ -10,7 +10,7 @@
 
 #include "evdi_debug.h"
 
-void evdi_log_process(void)
+void evdi_log_process(char *buf, size_t size)
 {
 	int task_pid = (int)task_pid_nr(current);
 	char task_comm[TASK_COMM_LEN] = { 0 };
@@ -21,13 +21,13 @@ void evdi_log_process(void)
 		char process_comm[TASK_COMM_LEN] = { 0 };
 
 		get_task_comm(process_comm, current->group_leader);
-		EVDI_INFO("Task %d (%s) of process %d (%s)\n",
+		snprintf(buf, size, "Task %d (%s) of process %d (%s)",
 			  task_pid,
 			  task_comm,
 			  (int)task_pid_nr(current->group_leader),
 			  process_comm);
 	} else {
-		EVDI_INFO("Task %d (%s)\n",
+		snprintf(buf, size, "Task %d (%s)",
 			  task_pid,
 			  task_comm);
 	}
diff -pruN 1.9.0+dfsg-1/module/evdi_debug.h 1.12.0+dfsg-0ubuntu2/module/evdi_debug.h
--- 1.9.0+dfsg-1/module/evdi_debug.h	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_debug.h	2022-07-13 13:58:06.000000000 +0000
@@ -11,7 +11,6 @@
 
 #include "evdi_params.h"
 
-#define EVDI_LOGLEVEL_ALWAYS  0
 #define EVDI_LOGLEVEL_FATAL   1
 #define EVDI_LOGLEVEL_ERROR   2
 #define EVDI_LOGLEVEL_WARN    3
@@ -53,6 +52,6 @@
 #define EVDI_ENTER() EVDI_VERBOSE("enter\n")
 #define EVDI_EXIT() EVDI_VERBOSE("exit\n")
 
-void evdi_log_process(void);
+void evdi_log_process(char *buf, size_t size);
 
 #endif /* EVDI_DEBUG_H */
diff -pruN 1.9.0+dfsg-1/module/evdi_drm_drv.c 1.12.0+dfsg-0ubuntu2/module/evdi_drm_drv.c
--- 1.9.0+dfsg-1/module/evdi_drm_drv.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_drm_drv.c	2022-07-13 13:58:06.000000000 +0000
@@ -12,14 +12,22 @@
  */
 
 #include <linux/version.h>
-#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_ioctl.h>
+#include <drm/drm_file.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_vblank.h>
+#elif KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #else
 #include <drm/drmP.h>
 #endif
 #if KERNEL_VERSION(5, 1, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #include <drm/drm_probe_helper.h>
 #endif
-
+#if KERNEL_VERSION(5, 8, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_managed.h>
+#endif
+#include <drm/drm_atomic_helper.h>
 #include "evdi_drm_drv.h"
 #include "evdi_platform_drv.h"
 #include "evdi_cursor.h"
@@ -37,13 +45,18 @@ struct drm_ioctl_desc evdi_painter_ioctl
 			  DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(EVDI_DDCCI_RESPONSE, evdi_painter_ddcci_response_ioctl,
 			  DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(EVDI_ENABLE_CURSOR_EVENTS, evdi_painter_enable_cursor_events_ioctl,
+			  DRM_UNLOCKED),
 };
 
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
 static const struct vm_operations_struct evdi_gem_vm_ops = {
 	.fault = evdi_gem_fault,
 	.open = drm_gem_vm_open,
 	.close = drm_gem_vm_close,
 };
+#endif
 
 static const struct file_operations evdi_driver_fops = {
 	.owner = THIS_MODULE,
@@ -53,12 +66,16 @@ static const struct file_operations evdi
 	.read = drm_read,
 	.unlocked_ioctl = drm_ioctl,
 	.release = drm_release,
+
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = evdi_compat_ioctl,
 #endif
+
 	.llseek = noop_llseek,
 };
 
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
 static int evdi_enable_vblank(__always_unused struct drm_device *dev,
 			      __always_unused unsigned int pipe)
 {
@@ -69,30 +86,39 @@ static void evdi_disable_vblank(__always
 				__always_unused unsigned int pipe)
 {
 }
+#endif
 
 static struct drm_driver driver = {
-#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE || defined(EL8)
 	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
 #else
 	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
 			 | DRIVER_ATOMIC,
 #endif
-	.unload = evdi_driver_unload,
-	.preclose = evdi_driver_preclose,
+	.unload = evdi_drm_device_unload,
 
+	.open = evdi_driver_open,
 	.postclose = evdi_driver_postclose,
 
 	/* gem hooks */
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#elif KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
 	.gem_free_object_unlocked = evdi_gem_free_object,
 #else
 	.gem_free_object = evdi_gem_free_object,
 #endif
+
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
 	.gem_vm_ops = &evdi_gem_vm_ops,
+#endif
 
 	.dumb_create = evdi_dumb_create,
 	.dumb_map_offset = evdi_gem_mmap,
+#if KERNEL_VERSION(5, 12, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
 	.dumb_destroy = drm_gem_dumb_destroy,
+#endif
 
 	.ioctls = evdi_painter_ioctls,
 	.num_ioctls = ARRAY_SIZE(evdi_painter_ioctls),
@@ -102,12 +128,15 @@ static struct drm_driver driver = {
 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
 	.gem_prime_import = drm_gem_prime_import,
 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
+	.preclose = evdi_driver_preclose,
 	.gem_prime_export = drm_gem_prime_export,
 	.gem_prime_get_sg_table = evdi_prime_get_sg_table,
-	.gem_prime_import_sg_table = evdi_prime_import_sg_table,
-
 	.enable_vblank = evdi_enable_vblank,
 	.disable_vblank = evdi_disable_vblank,
+#endif
+	.gem_prime_import_sg_table = evdi_prime_import_sg_table,
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
@@ -117,7 +146,15 @@ static struct drm_driver driver = {
 	.patchlevel = DRIVER_PATCH,
 };
 
-static int evdi_driver_setup(struct drm_device *dev)
+#if KERNEL_VERSION(5, 8, 0) <= LINUX_VERSION_CODE
+static void evdi_drm_device_release_cb(__always_unused struct drm_device *dev,
+				       __always_unused void *ptr)
+{
+	EVDI_INFO("Evdi drm_device removed.\n");
+}
+#endif
+
+static int evdi_drm_device_setup(struct drm_device *dev)
 {
 	struct evdi_device *evdi;
 	int ret;
@@ -129,19 +166,12 @@ static int evdi_driver_setup(struct drm_
 
 	evdi->ddev = dev;
 	dev->dev_private = evdi;
+	evdi->dev_index = dev->primary->index;
 
+	evdi->cursor_events_enabled = false;
 	ret =  evdi_cursor_init(&evdi->cursor);
 	if (ret)
-		goto err;
-
-	evdi->cursor_attr = (struct dev_ext_attribute) {
-	    __ATTR(cursor_events, 0644, device_show_bool, device_store_bool),
-	    &evdi->cursor_events_enabled
-	};
-	ret = device_create_file(dev->dev, &evdi->cursor_attr.attr);
-	if (ret)
-		goto err_fb;
-
+		goto err_free;
 
 	EVDI_CHECKPT();
 	evdi_modeset_init(dev);
@@ -149,7 +179,7 @@ static int evdi_driver_setup(struct drm_
 #ifdef CONFIG_FB
 	ret = evdi_fbdev_init(dev);
 	if (ret)
-		goto err;
+		goto err_cursor;
 #endif /* CONFIG_FB */
 
 	ret = drm_vblank_init(dev, 1);
@@ -162,21 +192,26 @@ static int evdi_driver_setup(struct drm_
 
 	drm_kms_helper_poll_init(dev);
 
+#if KERNEL_VERSION(5, 8, 0) <= LINUX_VERSION_CODE
+	ret = drmm_add_action_or_reset(dev, evdi_drm_device_release_cb, NULL);
+	if (ret)
+		goto err_fb;
+#endif
 	return 0;
 
 err_fb:
 #ifdef CONFIG_FB
 	evdi_fbdev_cleanup(dev);
+err_cursor:
 #endif /* CONFIG_FB */
-err:
-	EVDI_ERROR("%d\n", ret);
-	if (evdi->cursor)
-		evdi_cursor_free(evdi->cursor);
+	evdi_cursor_free(evdi->cursor);
+err_free:
+	EVDI_ERROR("Failed to setup drm device %d\n", ret);
 	kfree(evdi);
 	return ret;
 }
 
-void evdi_driver_unload(struct drm_device *dev)
+void evdi_drm_device_unload(struct drm_device *dev)
 {
 	struct evdi_device *evdi = dev->dev_private;
 
@@ -190,7 +225,6 @@ void evdi_driver_unload(struct drm_devic
 	if (evdi->cursor)
 		evdi_cursor_free(evdi->cursor);
 
-	device_remove_file(dev->dev, &evdi->cursor_attr.attr);
 	evdi_painter_cleanup(evdi->painter);
 #ifdef CONFIG_FB
 	evdi_fbdev_cleanup(dev);
@@ -200,6 +234,16 @@ void evdi_driver_unload(struct drm_devic
 	kfree(evdi);
 }
 
+int evdi_driver_open(struct drm_device *drm_dev, __always_unused struct drm_file *file)
+{
+	struct evdi_device *evdi = drm_dev->dev_private;
+	char buf[100];
+
+	evdi_log_process(buf, sizeof(buf));
+	EVDI_INFO("(card%d) Opened by %s\n", evdi->dev_index, buf);
+	return 0;
+}
+
 static void evdi_driver_close(struct drm_device *drm_dev, struct drm_file *file)
 {
 	struct evdi_device *evdi = drm_dev->dev_private;
@@ -217,10 +261,11 @@ void evdi_driver_preclose(struct drm_dev
 void evdi_driver_postclose(struct drm_device *drm_dev, struct drm_file *file)
 {
 	struct evdi_device *evdi = drm_dev->dev_private;
+	char buf[100];
 
-	EVDI_DEBUG("(dev=%d) Process tries to close us, postclose\n",
-		   evdi ? evdi->dev_index : -1);
-	evdi_log_process();
+	evdi_log_process(buf, sizeof(buf));
+	EVDI_INFO("(card%d) Closed by %s\n",
+		   evdi->dev_index, buf);
 
 	evdi_driver_close(drm_dev, file);
 }
@@ -234,7 +279,7 @@ struct drm_device *evdi_drm_device_creat
 	if (IS_ERR(dev))
 		return dev;
 
-	ret = evdi_driver_setup(dev);
+	ret = evdi_drm_device_setup(dev);
 	if (ret)
 		goto err_free;
 
@@ -252,6 +297,8 @@ err_free:
 int evdi_drm_device_remove(struct drm_device *dev)
 {
 	drm_dev_unplug(dev);
+	drm_atomic_helper_shutdown(dev);
+	drm_dev_put(dev);
 	return 0;
 }
 
diff -pruN 1.9.0+dfsg-1/module/evdi_drm_drv.h 1.12.0+dfsg-0ubuntu2/module/evdi_drm_drv.h
--- 1.9.0+dfsg-1/module/evdi_drm_drv.h	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_drm_drv.h	2022-07-13 13:58:06.000000000 +0000
@@ -15,16 +15,21 @@
 
 #include <linux/module.h>
 #include <linux/version.h>
+#include <linux/mutex.h>
 #include <linux/device.h>
 #if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #include <drm/drm_drv.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_ioctl.h>
-#include <drm/drm_irq.h>
 #include <drm/drm_vblank.h>
 #else
 #include <drm/drmP.h>
 #endif
+#if KERNEL_VERSION(5, 15, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_legacy.h>
+#else
+#include <drm/drm_irq.h>
+#endif
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_rect.h>
@@ -44,10 +49,10 @@ struct evdi_device {
 	struct drm_device *ddev;
 	struct drm_connector *conn;
 	struct evdi_cursor *cursor;
-	struct dev_ext_attribute cursor_attr;
 	bool cursor_events_enabled;
 
-	uint32_t sku_area_limit;
+	uint32_t pixel_area_limit;
+	uint32_t pixel_per_second_limit;
 
 	struct evdi_fbdev *fbdev;
 	struct evdi_painter *painter;
@@ -59,7 +64,12 @@ struct evdi_device {
 struct evdi_gem_object {
 	struct drm_gem_object base;
 	struct page **pages;
+	unsigned int pages_pin_count;
+	struct mutex pages_lock;
 	void *vmapping;
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+	bool vmap_is_iomem;
+#endif
 	struct sg_table *sg;
 #if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE || defined(EL8)
 	struct dma_resv *resv;
@@ -68,6 +78,7 @@ struct evdi_gem_object {
 	struct reservation_object *resv;
 	struct reservation_object _resv;
 #endif
+	bool allow_sw_cursor_rect_updates;
 };
 
 #define to_evdi_bo(x) container_of(x, struct evdi_gem_object, base)
@@ -87,8 +98,8 @@ int evdi_connector_init(struct drm_devic
 
 struct drm_encoder *evdi_encoder_init(struct drm_device *dev);
 
-int evdi_driver_load(struct drm_device *dev, unsigned long flags);
-void evdi_driver_unload(struct drm_device *dev);
+void evdi_drm_device_unload(struct drm_device *dev);
+int evdi_driver_open(struct drm_device *drm_dev, struct drm_file *file);
 void evdi_driver_preclose(struct drm_device *dev, struct drm_file *file_priv);
 void evdi_driver_postclose(struct drm_device *dev, struct drm_file *file_priv);
 
@@ -96,6 +107,7 @@ void evdi_driver_postclose(struct drm_de
 long evdi_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 #endif
 
+
 #ifdef CONFIG_FB
 int evdi_fbdev_init(struct drm_device *dev);
 void evdi_fbdev_cleanup(struct drm_device *dev);
@@ -146,7 +158,6 @@ void evdi_painter_send_update_ready_if_n
 void evdi_painter_dpms_notify(struct evdi_device *evdi, int mode);
 void evdi_painter_mode_changed_notify(struct evdi_device *evdi,
 				      struct drm_display_mode *mode);
-void evdi_painter_crtc_state_notify(struct evdi_device *evdi, int state);
 unsigned int evdi_painter_poll(struct file *filp,
 			       struct poll_table_struct *wait);
 
@@ -160,6 +171,8 @@ int evdi_painter_request_update_ioctl(st
 				      struct drm_file *file);
 int evdi_painter_ddcci_response_ioctl(struct drm_device *drm_dev, void *data,
 				      struct drm_file *file);
+int evdi_painter_enable_cursor_events_ioctl(struct drm_device *drm_dev, void *data,
+					  struct drm_file *file);
 
 int evdi_painter_init(struct evdi_device *evdi);
 void evdi_painter_cleanup(struct evdi_painter *painter);
diff -pruN 1.9.0+dfsg-1/module/evdi_drm.h 1.12.0+dfsg-0ubuntu2/module/evdi_drm.h
--- 1.9.0+dfsg-1/module/evdi_drm.h	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_drm.h	2022-07-13 13:58:06.000000000 +0000
@@ -47,7 +47,8 @@ struct drm_evdi_connect {
 	int32_t dev_index;
 	const unsigned char * __user edid;
 	uint32_t edid_length;
-	uint32_t sku_area_limit;
+	uint32_t pixel_area_limit;
+	uint32_t pixel_per_second_limit;
 };
 
 struct drm_evdi_request_update {
@@ -94,6 +95,11 @@ struct drm_evdi_ddcci_response {
 	uint8_t result;
 };
 
+struct drm_evdi_enable_cursor_events {
+	struct drm_event base;
+	uint8_t enable;
+};
+
 #define DDCCI_BUFFER_SIZE 64
 
 struct drm_evdi_event_ddcci_data {
@@ -109,6 +115,7 @@ struct drm_evdi_event_ddcci_data {
 #define DRM_EVDI_REQUEST_UPDATE   0x01
 #define DRM_EVDI_GRABPIX          0x02
 #define DRM_EVDI_DDCCI_RESPONSE   0x03
+#define DRM_EVDI_ENABLE_CURSOR_EVENTS 0x04
 /* LAST_IOCTL 0x5F -- 96 driver specific ioctls to use */
 
 #define DRM_IOCTL_EVDI_CONNECT DRM_IOWR(DRM_COMMAND_BASE +  \
@@ -119,5 +126,7 @@ struct drm_evdi_event_ddcci_data {
 	DRM_EVDI_GRABPIX, struct drm_evdi_grabpix)
 #define DRM_IOCTL_EVDI_DDCCI_RESPONSE DRM_IOWR(DRM_COMMAND_BASE +  \
 	DRM_EVDI_DDCCI_RESPONSE, struct drm_evdi_ddcci_response)
+#define DRM_IOCTL_EVDI_ENABLE_CURSOR_EVENTS DRM_IOWR(DRM_COMMAND_BASE +  \
+	DRM_EVDI_ENABLE_CURSOR_EVENTS, struct drm_evdi_enable_cursor_events)
 
 #endif /* __EVDI_UAPI_DRM_H__ */
diff -pruN 1.9.0+dfsg-1/module/evdi_fb.c 1.12.0+dfsg-0ubuntu2/module/evdi_fb.c
--- 1.9.0+dfsg-1/module/evdi_fb.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_fb.c	2022-07-13 13:58:06.000000000 +0000
@@ -25,7 +25,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_atomic.h>
-#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #include <drm/drm_damage_helper.h>
 #endif
 #include "evdi_drm_drv.h"
@@ -63,28 +63,29 @@ struct drm_clip_rect evdi_framebuffer_sa
 
 
 	if (rect.x1 > fb->base.width) {
-		EVDI_WARN("Wrong clip rect: x1 > fb.width\n");
+		EVDI_DEBUG("Wrong clip rect: x1 > fb.width\n");
 		rect.x1 = fb->base.width;
 	}
 
 	if (rect.y1 > fb->base.height) {
-		EVDI_WARN("Wrong clip rect: y1 > fb.height\n");
+		EVDI_DEBUG("Wrong clip rect: y1 > fb.height\n");
 		rect.y1 = fb->base.height;
 	}
 
 	if (rect.x2 > fb->base.width) {
-		EVDI_WARN("Wrong clip rect: x2 > fb.width\n");
+		EVDI_DEBUG("Wrong clip rect: x2 > fb.width\n");
 		rect.x2 = fb->base.width;
 	}
 
 	if (rect.y2 > fb->base.height) {
-		EVDI_WARN("Wrong clip rect: y2 > fb.height\n");
+		EVDI_DEBUG("Wrong clip rect: y2 > fb.height\n");
 		rect.y2 = fb->base.height;
 	}
 
 	return rect;
 }
 
+#ifdef CONFIG_FB
 static int evdi_handle_damage(struct evdi_framebuffer *fb,
 		       int x, int y, int width, int height)
 {
@@ -104,7 +105,6 @@ static int evdi_handle_damage(struct evd
 	return 0;
 }
 
-#ifdef CONFIG_FB
 static int evdi_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
 	unsigned long start = vma->vm_start;
@@ -221,7 +221,7 @@ static struct fb_ops evdifb_ops = {
 };
 #endif /* CONFIG_FB */
 
-#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #else
 /*
  * Function taken from
@@ -243,7 +243,7 @@ static int evdi_user_framebuffer_dirty(
 	struct drm_atomic_state *state;
 	struct drm_plane *plane;
 	int ret = 0;
-	int i;
+	unsigned int i;
 
 	EVDI_CHECKPT();
 
@@ -319,7 +319,7 @@ static void evdi_user_framebuffer_destro
 
 	EVDI_CHECKPT();
 	if (efb->obj)
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
 		drm_gem_object_put(&efb->obj->base);
 #else
 		drm_gem_object_put_unlocked(&efb->obj->base);
@@ -331,7 +331,7 @@ static void evdi_user_framebuffer_destro
 static const struct drm_framebuffer_funcs evdifb_funcs = {
 	.create_handle = evdi_user_framebuffer_create_handle,
 	.destroy = evdi_user_framebuffer_destroy,
-#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
 	.dirty = drm_atomic_helper_dirtyfb,
 #else
 	.dirty = evdi_user_framebuffer_dirty,
@@ -441,7 +441,7 @@ static int evdifb_create(struct drm_fb_h
 
 	return ret;
  out_gfree:
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
 	drm_gem_object_put(&efbdev->efb.obj->base);
 #else
 	drm_gem_object_put_unlocked(&efbdev->efb.obj->base);
@@ -471,7 +471,7 @@ static void evdi_fbdev_destroy(__always_
 	if (efbdev->efb.obj) {
 		drm_framebuffer_unregister_private(&efbdev->efb.base);
 		drm_framebuffer_cleanup(&efbdev->efb.base);
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
 		drm_gem_object_put(&efbdev->efb.obj->base);
 #else
 		drm_gem_object_put_unlocked(&efbdev->efb.obj->base);
@@ -493,7 +493,7 @@ int evdi_fbdev_init(struct drm_device *d
 	evdi->fbdev = efbdev;
 	drm_fb_helper_prepare(dev, &efbdev->helper, &evdi_fb_helper_funcs);
 
-#if KERNEL_VERSION(5, 7, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 7, 0) <= LINUX_VERSION_CODE || defined(EL8)
 	ret = drm_fb_helper_init(dev, &efbdev->helper);
 #else
 	ret = drm_fb_helper_init(dev, &efbdev->helper, 1);
@@ -503,7 +503,7 @@ int evdi_fbdev_init(struct drm_device *d
 		return ret;
 	}
 
-#if KERNEL_VERSION(5, 7, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 7, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #else
 	drm_fb_helper_single_add_all_connectors(&efbdev->helper);
 #endif
@@ -541,7 +541,7 @@ void evdi_fbdev_unplug(struct drm_device
 		struct fb_info *info;
 
 		info = efbdev->helper.fbdev;
-#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE || defined(EL8)
 		unregister_framebuffer(info);
 #else
 		unlink_framebuffer(info);
diff -pruN 1.9.0+dfsg-1/module/evdi_gem.c 1.12.0+dfsg-0ubuntu2/module/evdi_gem.c
--- 1.9.0+dfsg-1/module/evdi_gem.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_gem.c	2022-07-13 13:58:06.000000000 +0000
@@ -8,16 +8,66 @@
  * more details.
  */
 
+#include <linux/sched.h>
 #include <linux/version.h>
-#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#if KERNEL_VERSION(5, 18, 0) <= LINUX_VERSION_CODE
+#elif KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE
+#include <linux/dma-buf-map.h>
+#endif
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_prime.h>
+#include <drm/drm_file.h>
+#elif KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #else
 #include <drm/drmP.h>
 #endif
 #include "evdi_drm_drv.h"
+#include "evdi_params.h"
 #include <linux/shmem_fs.h>
 #include <linux/dma-buf.h>
 #include <drm/drm_cache.h>
 
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+MODULE_IMPORT_NS(DMA_BUF);
+#endif
+
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+static int evdi_prime_pin(struct drm_gem_object *obj);
+static void evdi_prime_unpin(struct drm_gem_object *obj);
+
+static const struct vm_operations_struct evdi_gem_vm_ops = {
+	.fault = evdi_gem_fault,
+	.open = drm_gem_vm_open,
+	.close = drm_gem_vm_close,
+};
+
+static struct drm_gem_object_funcs gem_obj_funcs = {
+	.free = evdi_gem_free_object,
+	.pin = evdi_prime_pin,
+	.unpin = evdi_prime_unpin,
+	.vm_ops = &evdi_gem_vm_ops,
+	.export = drm_gem_prime_export,
+	.get_sg_table = evdi_prime_get_sg_table,
+};
+#endif
+
+static bool evdi_was_called_by_mutter(void)
+{
+	char task_comm[TASK_COMM_LEN] = { 0 };
+
+	get_task_comm(task_comm, current);
+
+	return strcmp(task_comm, "gnome-shell") == 0;
+}
+
+static bool evdi_drm_gem_object_use_import_attach(struct drm_gem_object *obj)
+{
+	if (!obj || !obj->import_attach)
+		return false;
+
+	return obj->import_attach && strcmp(obj->import_attach->dmabuf->owner->name, "amdgpu") != 0;
+}
+
 uint32_t evdi_gem_object_handle_lookup(struct drm_file *filp,
 				       struct drm_gem_object *obj)
 {
@@ -58,6 +108,14 @@ struct evdi_gem_object *evdi_gem_alloc_o
 #endif
 	obj->resv = &obj->_resv;
 
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+	obj->base.funcs = &gem_obj_funcs;
+#endif
+
+	obj->allow_sw_cursor_rect_updates = false;
+
+	mutex_init(&obj->pages_lock);
+
 	return obj;
 }
 
@@ -81,11 +139,12 @@ evdi_gem_create(struct drm_file *file,
 		kfree(obj);
 		return ret;
 	}
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
 	drm_gem_object_put(&obj->base);
 #else
 	drm_gem_object_put_unlocked(&obj->base);
 #endif
+	obj->allow_sw_cursor_rect_updates = evdi_was_called_by_mutter();
 	*handle_p = handle;
 	return 0;
 }
@@ -186,7 +245,7 @@ static int evdi_gem_get_pages(struct evd
 	obj->pages = pages;
 
 #if defined(CONFIG_X86)
-	drm_clflush_pages(obj->pages, obj->base.size / PAGE_SIZE);
+	drm_clflush_pages(obj->pages, DIV_ROUND_UP(obj->base.size, PAGE_SIZE));
 #endif
 
 	return 0;
@@ -204,19 +263,55 @@ static void evdi_gem_put_pages(struct ev
 	obj->pages = NULL;
 }
 
+static int evdi_pin_pages(struct evdi_gem_object *obj)
+{
+	int ret = 0;
+
+	mutex_lock(&obj->pages_lock);
+	if (obj->pages_pin_count++ == 0) {
+		ret = evdi_gem_get_pages(obj, GFP_KERNEL);
+		if (ret)
+			obj->pages_pin_count--;
+	}
+	mutex_unlock(&obj->pages_lock);
+	return ret;
+}
+
+static void evdi_unpin_pages(struct evdi_gem_object *obj)
+{
+	mutex_lock(&obj->pages_lock);
+	if (--obj->pages_pin_count == 0)
+		evdi_gem_put_pages(obj);
+	mutex_unlock(&obj->pages_lock);
+}
+
 int evdi_gem_vmap(struct evdi_gem_object *obj)
 {
-	int page_count = obj->base.size / PAGE_SIZE;
+	int page_count = DIV_ROUND_UP(obj->base.size, PAGE_SIZE);
 	int ret;
 
-	if (obj->base.import_attach) {
+	if (evdi_drm_gem_object_use_import_attach(&obj->base)) {
+#if KERNEL_VERSION(5, 18, 0) <= LINUX_VERSION_CODE
+		struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
+#elif KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+		struct dma_buf_map map = DMA_BUF_MAP_INIT_VADDR(NULL);
+#endif
+
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+		ret = dma_buf_vmap(obj->base.import_attach->dmabuf, &map);
+		if (ret)
+			return -ENOMEM;
+		obj->vmapping = map.vaddr;
+		obj->vmap_is_iomem = map.is_iomem;
+#else
 		obj->vmapping = dma_buf_vmap(obj->base.import_attach->dmabuf);
 		if (!obj->vmapping)
 			return -ENOMEM;
+#endif
 		return 0;
 	}
 
-	ret = evdi_gem_get_pages(obj, GFP_KERNEL);
+	ret = evdi_pin_pages(obj);
 	if (ret)
 		return ret;
 
@@ -228,8 +323,29 @@ int evdi_gem_vmap(struct evdi_gem_object
 
 void evdi_gem_vunmap(struct evdi_gem_object *obj)
 {
-	if (obj->base.import_attach) {
+	if (evdi_drm_gem_object_use_import_attach(&obj->base)) {
+#if KERNEL_VERSION(5, 18, 0) <= LINUX_VERSION_CODE
+		struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
+
+		if (obj->vmap_is_iomem)
+			iosys_map_set_vaddr_iomem(&map, obj->vmapping);
+		else
+			iosys_map_set_vaddr(&map, obj->vmapping);
+
+		dma_buf_vunmap(obj->base.import_attach->dmabuf, &map);
+
+#elif KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+		struct dma_buf_map map;
+
+		if (obj->vmap_is_iomem)
+			dma_buf_map_set_vaddr_iomem(&map, obj->vmapping);
+		else
+			dma_buf_map_set_vaddr(&map, obj->vmapping);
+
+		dma_buf_vunmap(obj->base.import_attach->dmabuf, &map);
+#else
 		dma_buf_vunmap(obj->base.import_attach->dmabuf, obj->vmapping);
+#endif
 		obj->vmapping = NULL;
 		return;
 	}
@@ -239,7 +355,7 @@ void evdi_gem_vunmap(struct evdi_gem_obj
 		obj->vmapping = NULL;
 	}
 
-	evdi_gem_put_pages(obj);
+	evdi_unpin_pages(obj);
 }
 
 void evdi_gem_free_object(struct drm_gem_object *gem_obj)
@@ -263,6 +379,7 @@ void evdi_gem_free_object(struct drm_gem
 	reservation_object_fini(&obj->_resv);
 #endif
 	obj->resv = NULL;
+	mutex_destroy(&obj->pages_lock);
 }
 
 /*
@@ -284,7 +401,7 @@ int evdi_gem_mmap(struct drm_file *file,
 	}
 	gobj = to_evdi_bo(obj);
 
-	ret = evdi_gem_get_pages(gobj, GFP_KERNEL);
+	ret = evdi_pin_pages(gobj);
 	if (ret)
 		goto out;
 
@@ -308,12 +425,15 @@ evdi_prime_import_sg_table(struct drm_de
 {
 	struct evdi_gem_object *obj;
 	int npages;
+	bool called_by_mutter;
+
+	called_by_mutter = evdi_was_called_by_mutter();
 
 	obj = evdi_gem_alloc_object(dev, attach->dmabuf->size);
 	if (IS_ERR(obj))
 		return ERR_CAST(obj);
 
-	npages = PAGE_ALIGN(attach->dmabuf->size) / PAGE_SIZE;
+	npages = DIV_ROUND_UP(attach->dmabuf->size, PAGE_SIZE);
 	DRM_DEBUG_PRIME("Importing %d pages\n", npages);
 	obj->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
 	if (!obj->pages) {
@@ -321,15 +441,36 @@ evdi_prime_import_sg_table(struct drm_de
 		return ERR_PTR(-ENOMEM);
 	}
 
+#if KERNEL_VERSION(5, 12, 0) <= LINUX_VERSION_CODE || defined(EL8)
+	drm_prime_sg_to_page_array(sg, obj->pages, npages);
+#else
 	drm_prime_sg_to_page_addr_arrays(sg, obj->pages, NULL, npages);
+#endif
 	obj->sg = sg;
+	obj->allow_sw_cursor_rect_updates = called_by_mutter;
 	return &obj->base;
 }
 
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(EL8)
+static int evdi_prime_pin(struct drm_gem_object *obj)
+{
+	struct evdi_gem_object *bo = to_evdi_bo(obj);
+
+	return evdi_pin_pages(bo);
+}
+
+static void evdi_prime_unpin(struct drm_gem_object *obj)
+{
+	struct evdi_gem_object *bo = to_evdi_bo(obj);
+
+	evdi_unpin_pages(bo);
+}
+#endif
+
 struct sg_table *evdi_prime_get_sg_table(struct drm_gem_object *obj)
 {
 	struct evdi_gem_object *bo = to_evdi_bo(obj);
-	#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
+	#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE || defined(EL8)
 		return drm_prime_pages_to_sg(obj->dev, bo->pages, bo->base.size >> PAGE_SHIFT);
 	#else
 		return drm_prime_pages_to_sg(bo->pages, bo->base.size >> PAGE_SHIFT);
diff -pruN 1.9.0+dfsg-1/module/evdi_ioc32.c 1.12.0+dfsg-0ubuntu2/module/evdi_ioc32.c
--- 1.9.0+dfsg-1/module/evdi_ioc32.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_ioc32.c	2022-07-13 13:58:06.000000000 +0000
@@ -22,7 +22,9 @@
 #include <linux/compat.h>
 
 #include <linux/version.h>
-#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_ioctl.h>
+#elif KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #else
 #include <drm/drmP.h>
 #endif
@@ -36,7 +38,8 @@ struct drm_evdi_connect32 {
 	int32_t dev_index;
 	uint32_t edid_ptr32;
 	uint32_t edid_length;
-	uint32_t sku_area_limit;
+	uint32_t pixel_area_limit;
+	uint32_t pixel_per_second_limit;
 };
 
 struct drm_evdi_grabpix32 {
@@ -59,7 +62,11 @@ static int compat_evdi_connect(struct fi
 	if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
 		return -EFAULT;
 
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE && KERNEL_VERSION(5, 14, 0) >= LINUX_VERSION_CODE || defined(EL8)
 	request = compat_alloc_user_space(sizeof(*request));
+#else
+	request = kmalloc(sizeof(*request), GFP_USER);
+#endif
 #if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
 	if (!access_ok(request, sizeof(*request))
 #else
@@ -70,7 +77,8 @@ static int compat_evdi_connect(struct fi
 		|| __put_user((void __user *)(unsigned long)req32.edid_ptr32,
 			  &request->edid)
 		|| __put_user(req32.edid_length, &request->edid_length)
-		|| __put_user(req32.sku_area_limit, &request->sku_area_limit))
+		|| __put_user(req32.pixel_area_limit, &request->pixel_area_limit)
+		|| __put_user(req32.pixel_per_second_limit, &request->pixel_per_second_limit))
 		return -EFAULT;
 
 	return drm_ioctl(file, DRM_IOCTL_EVDI_CONNECT,
@@ -87,7 +95,11 @@ static int compat_evdi_grabpix(struct fi
 	if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
 		return -EFAULT;
 
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE && KERNEL_VERSION(5, 14, 0) >= LINUX_VERSION_CODE || defined(EL8)
 	request = compat_alloc_user_space(sizeof(*request));
+#else
+	request = kmalloc(sizeof(*request), GFP_USER);
+#endif
 #if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
 	if (!access_ok(request, sizeof(*request))
 #else
diff -pruN 1.9.0+dfsg-1/module/evdi_modeset.c 1.12.0+dfsg-0ubuntu2/module/evdi_modeset.c
--- 1.9.0+dfsg-1/module/evdi_modeset.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_modeset.c	2022-07-13 13:58:06.000000000 +0000
@@ -12,7 +12,11 @@
  */
 
 #include <linux/version.h>
-#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_vblank.h>
+#include <drm/drm_damage_helper.h>
+#elif KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#include <drm/drm_damage_helper.h>
 #else
 #include <drm/drmP.h>
 #endif
@@ -25,7 +29,11 @@
 #include "evdi_drm_drv.h"
 #include "evdi_cursor.h"
 #include "evdi_params.h"
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_gem_atomic_helper.h>
+#else
 #include <drm/drm_gem_framebuffer_helper.h>
+#endif
 
 static void evdi_crtc_dpms(__always_unused struct drm_crtc *crtc,
 			   __always_unused int mode)
@@ -36,6 +44,7 @@ static void evdi_crtc_dpms(__always_unus
 static void evdi_crtc_disable(__always_unused struct drm_crtc *crtc)
 {
 	EVDI_CHECKPT();
+	drm_crtc_vblank_off(crtc);
 }
 
 static void evdi_crtc_destroy(struct drm_crtc *crtc)
@@ -56,25 +65,37 @@ static void evdi_crtc_set_nofb(__always_
 
 static void evdi_crtc_atomic_flush(
 	struct drm_crtc *crtc
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(RPI) || defined(EL8)
+	, struct drm_atomic_state *state
+#else
 	, __always_unused struct drm_crtc_state *old_state
+#endif
 	)
 {
-	struct drm_crtc_state *state = crtc->state;
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(RPI) || defined(EL8)
+	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+#else
+	struct drm_crtc_state *crtc_state = crtc->state;
+#endif
 	struct evdi_device *evdi = crtc->dev->dev_private;
+	bool notify_mode_changed = crtc_state->active &&
+				   (crtc_state->mode_changed || evdi_painter_needs_full_modeset(evdi->painter));
+	bool notify_dpms = crtc_state->active_changed || evdi_painter_needs_full_modeset(evdi->painter);
 
+	if (notify_mode_changed)
+		evdi_painter_mode_changed_notify(evdi, &crtc_state->adjusted_mode);
 
-	if (state->mode_changed && state->active)
-		evdi_painter_mode_changed_notify(evdi, &state->adjusted_mode);
-
-	if (state->active_changed)
+	if (notify_dpms)
 		evdi_painter_dpms_notify(evdi,
-			state->active ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF);
+			crtc_state->active ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF);
 
-	evdi_painter_set_vblank(evdi->painter, crtc, state->event);
+	evdi_painter_set_vblank(evdi->painter, crtc, crtc_state->event);
 	evdi_painter_send_update_ready_if_needed(evdi->painter);
-	state->event = NULL;
+	crtc_state->event = NULL;
 }
 
+#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
 static void evdi_mark_full_screen_dirty(struct evdi_device *evdi)
 {
 	const struct drm_clip_rect rect =
@@ -125,7 +146,7 @@ static int evdi_crtc_cursor_set(struct d
 	evdi_cursor_set(evdi->cursor,
 			eobj, width, height, hot_x, hot_y,
 			format, stride);
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
 	drm_gem_object_put(obj);
 #else
 	drm_gem_object_put_unlocked(obj);
@@ -157,6 +178,7 @@ static int evdi_crtc_cursor_move(struct
 
 	return 0;
 }
+#endif
 
 static struct drm_crtc_helper_funcs evdi_helper_funcs = {
 	.mode_set_nofb  = evdi_crtc_set_nofb,
@@ -167,6 +189,17 @@ static struct drm_crtc_helper_funcs evdi
 	.disable        = evdi_crtc_disable
 };
 
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(RPI) || defined(EL8)
+static int evdi_enable_vblank(__always_unused struct drm_crtc *crtc)
+{
+	return 1;
+}
+
+static void evdi_disable_vblank(__always_unused struct drm_crtc *crtc)
+{
+}
+#endif
+
 static const struct drm_crtc_funcs evdi_crtc_funcs = {
 	.reset                  = drm_atomic_helper_crtc_reset,
 	.destroy                = evdi_crtc_destroy,
@@ -175,18 +208,40 @@ static const struct drm_crtc_funcs evdi_
 	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 	.atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
 
+#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#else
 	.cursor_set2            = evdi_crtc_cursor_set,
-	.cursor_move            = evdi_crtc_cursor_move
+	.cursor_move            = evdi_crtc_cursor_move,
+#endif
+#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE || defined(RPI) || defined(EL8)
+	.enable_vblank          = evdi_enable_vblank,
+	.disable_vblank         = evdi_disable_vblank,
+#endif
 };
 
 static void evdi_plane_atomic_update(struct drm_plane *plane,
-				     struct drm_plane_state *old_state)
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+				     struct drm_atomic_state *atom_state
+#else
+				     struct drm_plane_state *old_state
+#endif
+		)
 {
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+	struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(atom_state, plane);
+#else
+#endif
 	struct drm_plane_state *state;
 	struct evdi_device *evdi;
 	struct evdi_painter *painter;
 	struct drm_crtc *crtc;
 
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
+	struct drm_atomic_helper_damage_iter iter;
+	struct drm_rect rect;
+	struct drm_clip_rect clip_rect;
+#endif
+
 	if (!plane || !plane->state) {
 		EVDI_WARN("Plane state is null\n");
 		return;
@@ -228,10 +283,28 @@ static void evdi_plane_atomic_update(str
 		    evdi_painter_needs_full_modeset(painter)) {
 
 			evdi_painter_set_scanout_buffer(painter, efb);
+
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
+			state->visible = true;
+			state->src.x1 = 0;
+			state->src.y1 = 0;
+			state->src.x2 = fb->width << 16;
+			state->src.y2 = fb->height << 16;
+
+			drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+			while (drm_atomic_helper_damage_iter_next(&iter, &rect)) {
+				clip_rect.x1 = rect.x1;
+				clip_rect.y1 = rect.y1;
+				clip_rect.x2 = rect.x2;
+				clip_rect.y2 = rect.y2;
+				evdi_painter_mark_dirty(evdi, &clip_rect);
+			}
+#endif
+
+		};
+
+		if (evdi_painter_get_num_dirts(painter) == 0)
 			evdi_painter_mark_dirty(evdi, &fullscreen_rect);
-		} else if (evdi_painter_get_num_dirts(painter) == 0) {
-			evdi_painter_mark_dirty(evdi, &fullscreen_rect);
-		}
 	}
 }
 
@@ -245,8 +318,17 @@ static void evdi_cursor_atomic_get_rect(
 }
 
 static void evdi_cursor_atomic_update(struct drm_plane *plane,
-				      struct drm_plane_state *old_state)
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+				     struct drm_atomic_state *atom_state
+#else
+				     struct drm_plane_state *old_state
+#endif
+		)
 {
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+	struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(atom_state, plane);
+#else
+#endif
 	if (plane && plane->state && plane->dev && plane->dev->dev_private) {
 		struct drm_plane_state *state = plane->state;
 		struct evdi_device *evdi = plane->dev->dev_private;
@@ -288,13 +370,20 @@ static void evdi_cursor_atomic_update(st
 
 		mutex_unlock(&plane->dev->struct_mutex);
 		if (!evdi->cursor_events_enabled) {
-			evdi_cursor_atomic_get_rect(&old_rect, old_state);
-			evdi_cursor_atomic_get_rect(&rect, state);
-
-			evdi_painter_mark_dirty(evdi, &old_rect);
-			evdi_painter_mark_dirty(evdi, &rect);
+			if (fb != NULL) {
+				if (efb->obj->allow_sw_cursor_rect_updates) {
+					evdi_cursor_atomic_get_rect(&old_rect, old_state);
+					evdi_cursor_atomic_get_rect(&rect, state);
+
+					evdi_painter_mark_dirty(evdi, &old_rect);
+				} else {
+					rect = evdi_painter_framebuffer_size(evdi->painter);
+				}
+				evdi_painter_mark_dirty(evdi, &rect);
+			}
 			return;
 		}
+
 		if (cursor_changed)
 			evdi_painter_send_cursor_set(evdi->painter,
 						     evdi->cursor);
@@ -306,12 +395,20 @@ static void evdi_cursor_atomic_update(st
 
 static const struct drm_plane_helper_funcs evdi_plane_helper_funcs = {
 	.atomic_update = evdi_plane_atomic_update,
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+	.prepare_fb = drm_gem_plane_helper_prepare_fb
+#else
 	.prepare_fb = drm_gem_fb_prepare_fb
+#endif
 };
 
 static const struct drm_plane_helper_funcs evdi_cursor_helper_funcs = {
 	.atomic_update = evdi_cursor_atomic_update,
+#if KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE
+	.prepare_fb = drm_gem_plane_helper_prepare_fb
+#else
 	.prepare_fb = drm_gem_fb_prepare_fb
+#endif
 };
 
 static const struct drm_plane_funcs evdi_plane_funcs = {
@@ -337,10 +434,11 @@ static struct drm_plane *evdi_create_pla
 {
 	struct drm_plane *plane;
 	int ret;
+	char *plane_type = (type == DRM_PLANE_TYPE_CURSOR) ? "cursor" : "primary";
 
 	plane = kzalloc(sizeof(*plane), GFP_KERNEL);
 	if (plane == NULL) {
-		EVDI_ERROR("Failed to allocate primary plane\n");
+		EVDI_ERROR("Failed to allocate %s plane\n", plane_type);
 		return NULL;
 	}
 	plane->format_default = true;
@@ -357,7 +455,7 @@ static struct drm_plane *evdi_create_pla
 				       );
 
 	if (ret) {
-		EVDI_ERROR("Failed to initialize primary plane\n");
+		EVDI_ERROR("Failed to initialize %s plane\n", plane_type);
 		kfree(plane);
 		return NULL;
 	}
@@ -381,6 +479,16 @@ static int evdi_crtc_init(struct drm_dev
 
 	primary_plane = evdi_create_plane(dev, DRM_PLANE_TYPE_PRIMARY,
 					  &evdi_plane_helper_funcs);
+
+#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE || defined(EL8)
+	cursor_plane = evdi_create_plane(dev, DRM_PLANE_TYPE_CURSOR,
+						&evdi_cursor_helper_funcs);
+#endif
+
+#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE || defined(EL8)
+	drm_plane_enable_fb_damage_clips(primary_plane);
+#endif
+
 	status = drm_crtc_init_with_planes(dev, crtc,
 					   primary_plane, cursor_plane,
 					   &evdi_crtc_funcs,
@@ -393,29 +501,11 @@ static int evdi_crtc_init(struct drm_dev
 	return 0;
 }
 
-static int evdi_atomic_check(struct drm_device *dev,
-			     struct drm_atomic_state *state)
-{
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
-	int i;
-	struct evdi_device *evdi = dev->dev_private;
-
-	if (evdi_painter_needs_full_modeset(evdi->painter)) {
-		for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
-			crtc_state->active_changed = true;
-			crtc_state->mode_changed = true;
-		}
-	}
-
-	return drm_atomic_helper_check(dev, state);
-}
-
 static const struct drm_mode_config_funcs evdi_mode_funcs = {
 	.fb_create = evdi_fb_user_fb_create,
 	.output_poll_changed = NULL,
 	.atomic_commit = drm_atomic_helper_commit,
-	.atomic_check = evdi_atomic_check
+	.atomic_check = drm_atomic_helper_check
 };
 
 void evdi_modeset_init(struct drm_device *dev)
@@ -429,8 +519,8 @@ void evdi_modeset_init(struct drm_device
 	dev->mode_config.min_width = 64;
 	dev->mode_config.min_height = 64;
 
-	dev->mode_config.max_width = 3840;
-	dev->mode_config.max_height = 2160;
+	dev->mode_config.max_width = 7680;
+	dev->mode_config.max_height = 4320;
 
 	dev->mode_config.prefer_shadow = 0;
 	dev->mode_config.preferred_depth = 24;
@@ -446,8 +536,10 @@ void evdi_modeset_init(struct drm_device
 	drm_mode_config_reset(dev);
 }
 
-void evdi_modeset_cleanup(struct drm_device *dev)
+void evdi_modeset_cleanup(__maybe_unused struct drm_device *dev)
 {
-	EVDI_CHECKPT();
+#if KERNEL_VERSION(5, 8, 0) <= LINUX_VERSION_CODE
+#else
 	drm_mode_config_cleanup(dev);
+#endif
 }
diff -pruN 1.9.0+dfsg-1/module/evdi_painter.c 1.12.0+dfsg-0ubuntu2/module/evdi_painter.c
--- 1.9.0+dfsg-1/module/evdi_painter.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_painter.c	2022-07-13 13:58:06.000000000 +0000
@@ -10,7 +10,11 @@
 #include "linux/thread_info.h"
 #include "linux/mm.h"
 #include <linux/version.h>
-#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+#include <drm/drm_file.h>
+#include <drm/drm_vblank.h>
+#include <drm/drm_ioctl.h>
+#elif KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #else
 #include <drm/drmP.h>
 #endif
@@ -27,6 +31,10 @@
 
 #include <linux/dma-buf.h>
 
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+MODULE_IMPORT_NS(DMA_BUF);
+#endif
+
 #if KERNEL_VERSION(5, 1, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #include <drm/drm_probe_helper.h>
 #endif
@@ -239,7 +247,6 @@ u8 *evdi_painter_get_edid_copy(struct ev
 			memcpy(block,
 			       evdi->painter->edid,
 			       evdi->painter->edid_length);
-			EVDI_DEBUG("(dev=%d) EDID valid\n", evdi->dev_index);
 		}
 	}
 	painter_unlock(evdi->painter);
@@ -318,7 +325,7 @@ static void evdi_painter_send_event(stru
 	}
 
 	if (!painter->drm_filp) {
-		EVDI_WARN("Painter is not connected!");
+		EVDI_VERBOSE("Painter is not connected!");
 		drm_event_cancel_free(painter->drm_device, event);
 		return;
 	}
@@ -496,31 +503,6 @@ static void evdi_painter_send_dpms(struc
 	evdi_painter_send_event(painter, event);
 }
 
-static struct drm_pending_event *create_crtc_state_event(int state)
-{
-	struct evdi_event_crtc_state_pending *event;
-
-	event = kzalloc(sizeof(*event), GFP_KERNEL);
-	if (!event) {
-		EVDI_ERROR("Failed to create crtc state event");
-		return NULL;
-	}
-
-	event->crtc_state.base.type = DRM_EVDI_EVENT_CRTC_STATE;
-	event->crtc_state.base.length = sizeof(event->crtc_state);
-	event->crtc_state.state = state;
-	event->base.event = &event->crtc_state.base;
-	return &event->base;
-}
-
-static void evdi_painter_send_crtc_state(struct evdi_painter *painter,
-					 int state)
-{
-	struct drm_pending_event *event = create_crtc_state_event(state);
-
-	evdi_painter_send_event(painter, event);
-}
-
 static struct drm_pending_event *create_mode_changed_event(
 	struct drm_display_mode *current_mode,
 	int32_t bits_per_pixel,
@@ -591,7 +573,8 @@ struct drm_clip_rect evdi_painter_frameb
 	painter_lock(painter);
 	efb = painter->scanout_fb;
 	if (!efb) {
-		EVDI_DEBUG("Scanout buffer not set.");
+		if (painter->is_connected)
+			EVDI_WARN("Scanout buffer not set.");
 		goto unlock;
 	}
 	rect.x1 = 0;
@@ -618,14 +601,15 @@ void evdi_painter_mark_dirty(struct evdi
 	painter_lock(painter);
 	efb = painter->scanout_fb;
 	if (!efb) {
-		EVDI_DEBUG("(dev=%d) Skip clip rect. Scanout buffer not set.\n",
+		if (painter->is_connected)
+			EVDI_WARN("(card%d) Skip clip rect. Scanout buffer not set.\n",
 			   evdi->dev_index);
 		goto unlock;
 	}
 
 	rect = evdi_framebuffer_sanitize_rect(efb, dirty_rect);
 
-	EVDI_VERBOSE("(dev=%d) %d,%d-%d,%d\n", evdi->dev_index, rect.x1,
+	EVDI_VERBOSE("(card%d) %d,%d-%d,%d\n", evdi->dev_index, rect.x1,
 		     rect.y1, rect.x2, rect.y2);
 
 	if (painter->num_dirts == MAX_DIRTS)
@@ -695,8 +679,11 @@ void evdi_painter_send_update_ready_if_n
 	EVDI_CHECKPT();
 	if (painter) {
 		painter_lock(painter);
-
+#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE || defined(EL8)
+		if (painter->was_update_requested && painter->num_dirts) {
+#else
 		if (painter->was_update_requested) {
+#endif
 			evdi_painter_send_update_ready(painter);
 			painter->was_update_requested = false;
 		}
@@ -707,38 +694,47 @@ void evdi_painter_send_update_ready_if_n
 	}
 }
 
+static const char * const dpms_str[] = { "on", "standby", "suspend", "off" };
+
 void evdi_painter_dpms_notify(struct evdi_device *evdi, int mode)
 {
 	struct evdi_painter *painter = evdi->painter;
+	const char *mode_str;
 
-	if (painter) {
-		EVDI_DEBUG("(dev=%d) Notifying dpms mode: %d\n",
-			   evdi->dev_index, mode);
-		evdi_painter_send_dpms(painter, mode);
-	} else {
-		EVDI_WARN("Painter does not exist!");
+	if (!painter) {
+		EVDI_WARN("(card%d) Painter does not exist!", evdi->dev_index);
+		return;
 	}
-}
 
-void evdi_painter_crtc_state_notify(struct evdi_device *evdi, int state)
-{
-	struct evdi_painter *painter = evdi->painter;
+	if (!painter->is_connected)
+		return;
 
-	if (painter) {
-		EVDI_DEBUG("(dev=%d) Notifying crtc state: %d\n",
-			   evdi->dev_index, state);
-		evdi_painter_send_crtc_state(painter, state);
-	} else {
-		EVDI_WARN("Painter does not exist!");
-	}
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		mode_str = dpms_str[mode];
+		break;
+	default:
+		mode_str = "unknown";
+	};
+	EVDI_INFO("(card%d) Notifying display power state: %s",
+		   evdi->dev_index, mode_str);
+	evdi_painter_send_dpms(painter, mode);
 }
 
-static void evdi_log_pixel_format(uint32_t pixel_format)
+static void evdi_log_pixel_format(uint32_t pixel_format,
+		char *buf, size_t size)
 {
+#if KERNEL_VERSION(5, 14, 0) <= LINUX_VERSION_CODE
+	snprintf(buf, size, "pixel format %p4cc", &pixel_format);
+#else
 	struct drm_format_name_buf format_name;
 
 	drm_get_format_name(pixel_format, &format_name);
-	EVDI_DEBUG("pixel format %s\n", format_name.str);
+	snprintf(buf, size, "pixel format %s", format_name.str);
+#endif
 }
 
 void evdi_painter_mode_changed_notify(struct evdi_device *evdi,
@@ -748,6 +744,7 @@ void evdi_painter_mode_changed_notify(st
 	struct drm_framebuffer *fb;
 	int bits_per_pixel;
 	uint32_t pixel_format;
+	char buf[100];
 
 	if (painter == NULL)
 		return;
@@ -759,10 +756,11 @@ void evdi_painter_mode_changed_notify(st
 	bits_per_pixel = fb->format->cpp[0] * 8;
 	pixel_format = fb->format->format;
 
-	EVDI_DEBUG("(dev=%d) Notifying mode changed: %dx%d@%d; bpp %d; ",
+
+	evdi_log_pixel_format(pixel_format, buf, sizeof(buf));
+	EVDI_INFO("(card%d) Notifying mode changed: %dx%d@%d; bpp %d; %s",
 		   evdi->dev_index, new_mode->hdisplay, new_mode->vdisplay,
-		   drm_mode_vrefresh(new_mode), bits_per_pixel);
-	evdi_log_pixel_format(pixel_format);
+		   drm_mode_vrefresh(new_mode), bits_per_pixel, buf);
 
 	evdi_painter_send_mode_changed(painter,
 				       new_mode,
@@ -795,7 +793,7 @@ static void evdi_add_i2c_adapter(struct
 	evdi->i2c_adapter = kzalloc(sizeof(*evdi->i2c_adapter), GFP_KERNEL);
 
 	if (!evdi->i2c_adapter) {
-		EVDI_ERROR("(dev=%d) Failed to allocate for i2c adapter",
+		EVDI_ERROR("(card%d) Failed to allocate for i2c adapter",
 			evdi->dev_index);
 		return;
 	}
@@ -805,19 +803,19 @@ static void evdi_add_i2c_adapter(struct
 	if (result) {
 		kfree(evdi->i2c_adapter);
 		evdi->i2c_adapter = NULL;
-		EVDI_ERROR("(dev=%d) Failed to add i2c adapter, error %d",
+		EVDI_ERROR("(card%d) Failed to add i2c adapter, error %d",
 			evdi->dev_index, result);
 		return;
 	}
 
-	EVDI_DEBUG("(dev=%d) Added i2c adapter bus number %d",
+	EVDI_INFO("(card%d) Added i2c adapter bus number %d",
 		evdi->dev_index, evdi->i2c_adapter->nr);
 
 	result = sysfs_create_link(&evdi->conn->kdev->kobj,
 			&evdi->i2c_adapter->dev.kobj, "ddc");
 
 	if (result) {
-		EVDI_ERROR("(dev=%d) Failed to create sysfs link, error %d",
+		EVDI_ERROR("(card%d) Failed to create sysfs link, error %d",
 			evdi->dev_index, result);
 		return;
 	}
@@ -826,7 +824,7 @@ static void evdi_add_i2c_adapter(struct
 static void evdi_remove_i2c_adapter(struct evdi_device *evdi)
 {
 	if (evdi->i2c_adapter) {
-		EVDI_DEBUG("(dev=%d) Removing i2c adapter bus number %d",
+		EVDI_INFO("(card%d) Removing i2c adapter bus number %d",
 			evdi->dev_index, evdi->i2c_adapter->nr);
 
 		sysfs_remove_link(&evdi->conn->kdev->kobj, "ddc");
@@ -841,16 +839,16 @@ static void evdi_remove_i2c_adapter(stru
 static int
 evdi_painter_connect(struct evdi_device *evdi,
 		     void const __user *edid_data, unsigned int edid_length,
-		     uint32_t sku_area_limit,
-		     struct drm_file *file, int dev_index)
+		     uint32_t pixel_area_limit,
+		     uint32_t pixel_per_second_limit,
+		     struct drm_file *file, __always_unused int dev_index)
 {
 	struct evdi_painter *painter = evdi->painter;
 	struct edid *new_edid = NULL;
-	int expected_edid_size = 0;
+	unsigned int expected_edid_size = 0;
+	char buf[100];
 
-	EVDI_DEBUG("(dev=%d) Process is trying to connect\n",
-		   evdi->dev_index);
-	evdi_log_process();
+	evdi_log_process(buf, sizeof(buf));
 
 	if (edid_length < sizeof(struct edid)) {
 		EVDI_ERROR("Edid length too small\n");
@@ -867,7 +865,7 @@ evdi_painter_connect(struct evdi_device
 		return -ENOMEM;
 
 	if (copy_from_user(new_edid, edid_data, edid_length)) {
-		EVDI_ERROR("(dev=%d) Failed to read edid\n", dev_index);
+		EVDI_ERROR("(card%d) Failed to read edid\n", evdi->dev_index);
 		kfree(new_edid);
 		return -EFAULT;
 	}
@@ -882,13 +880,13 @@ evdi_painter_connect(struct evdi_device
 	}
 
 	if (painter->drm_filp)
-		EVDI_WARN("(dev=%d) Double connect - replacing %p with %p\n",
-			  dev_index, painter->drm_filp, file);
+		EVDI_WARN("(card%d) Double connect - replacing %p with %p\n",
+			  evdi->dev_index, painter->drm_filp, file);
 
 	painter_lock(painter);
 
-	evdi->dev_index = dev_index;
-	evdi->sku_area_limit = sku_area_limit;
+        evdi->pixel_area_limit = pixel_area_limit;
+	evdi->pixel_per_second_limit = pixel_per_second_limit;
 	painter->drm_filp = file;
 	kfree(painter->edid);
 	painter->edid_length = edid_length;
@@ -896,12 +894,12 @@ evdi_painter_connect(struct evdi_device
 	painter->is_connected = true;
 	painter->needs_full_modeset = true;
 
-	evdi_add_i2c_adapter(evdi);
+	if (!evdi->i2c_adapter)
+		evdi_add_i2c_adapter(evdi);
 
 	painter_unlock(painter);
 
-	EVDI_DEBUG("(dev=%d) Connected with %p\n", evdi->dev_index,
-		   painter->drm_filp);
+	EVDI_INFO("(card%d) Connected with %s\n", evdi->dev_index, buf);
 
 	drm_helper_hpd_irq_event(evdi->ddev);
 
@@ -912,6 +910,7 @@ static int evdi_painter_disconnect(struc
 	struct drm_file *file)
 {
 	struct evdi_painter *painter = evdi->painter;
+	char buf[100];
 
 	EVDI_CHECKPT();
 
@@ -929,8 +928,8 @@ static int evdi_painter_disconnect(struc
 
 	painter->is_connected = false;
 
-	EVDI_DEBUG("(dev=%d) Disconnected from %p\n", evdi->dev_index,
-		   painter->drm_filp);
+	evdi_log_process(buf, sizeof(buf));
+	EVDI_INFO("(card%d) Disconnected from %s\n", evdi->dev_index, buf);
 	evdi_painter_events_cleanup(painter);
 
 	evdi_painter_send_vblank(painter);
@@ -944,7 +943,6 @@ static int evdi_painter_disconnect(struc
 	evdi_remove_i2c_adapter(evdi);
 
 	painter->drm_filp = NULL;
-	evdi->dev_index = -1;
 
 	painter->was_update_requested = false;
 	evdi->cursor_events_enabled = false;
@@ -962,10 +960,8 @@ void evdi_painter_close(struct evdi_devi
 {
 	EVDI_CHECKPT();
 
-	if (evdi->painter)
+	if (evdi->painter && file == evdi->painter->drm_filp)
 		evdi_painter_disconnect(evdi, file);
-	else
-		EVDI_WARN("Painter does not exist!");
 }
 
 int evdi_painter_connect_ioctl(struct drm_device *drm_dev, void *data,
@@ -982,19 +978,20 @@ int evdi_painter_connect_ioctl(struct dr
 			ret = evdi_painter_connect(evdi,
 					     cmd->edid,
 					     cmd->edid_length,
-					     cmd->sku_area_limit,
+					     cmd->pixel_area_limit,
+					     cmd->pixel_per_second_limit,
 					     file,
 					     cmd->dev_index);
 		else
 			ret = evdi_painter_disconnect(evdi, file);
 
 		if (ret) {
-			EVDI_WARN("(dev=%d)(pid=%d) disconnect failed\n",
+			EVDI_WARN("(card%d)(pid=%d) disconnect failed\n",
 				  evdi->dev_index, (int)task_pid_nr(current));
 		}
 		return ret;
 	}
-	EVDI_WARN("Painter does not exist!");
+	EVDI_WARN("(card%d) Painter does not exist!", evdi->dev_index);
 	return -ENODEV;
 }
 
@@ -1030,7 +1027,7 @@ int evdi_painter_grabpix_ioctl(struct dr
 	painter_lock(painter);
 
 	if (painter->was_update_requested) {
-		EVDI_WARN("(dev=%d) Update ready not sent,",
+		EVDI_WARN("(card%d) Update ready not sent,",
 			  evdi->dev_index);
 		EVDI_WARN(" but pixels are grabbed.\n");
 	}
@@ -1084,9 +1081,9 @@ int evdi_painter_grabpix_ioctl(struct dr
 		}
 	}
 
-	if (cmd->buf_width != efb->base.width ||
-		cmd->buf_height != efb->base.height) {
-		EVDI_ERROR("Invalid buffer dimension\n");
+	if ((unsigned int)cmd->buf_width != efb->base.width ||
+		(unsigned int)cmd->buf_height != efb->base.height) {
+		EVDI_DEBUG("Invalid buffer dimension\n");
 		err = -EINVAL;
 		goto err_fb;
 	}
@@ -1149,7 +1146,7 @@ int evdi_painter_request_update_ioctl(st
 
 		if (painter->was_update_requested) {
 			EVDI_WARN
-			  ("(dev=%d) Update was already requested - ignoring\n",
+			  ("(card%d) Update was already requested - ignoring\n",
 			   evdi->dev_index);
 		} else {
 			if (painter->num_dirts > 0)
@@ -1210,6 +1207,9 @@ void evdi_painter_cleanup(struct evdi_pa
 	kfree(painter->edid);
 	painter->edid_length = 0;
 	painter->edid = NULL;
+	if (painter->scanout_fb)
+		drm_framebuffer_put(&painter->scanout_fb->base);
+	painter->scanout_fb = NULL;
 
 	evdi_painter_send_vblank(painter);
 
@@ -1318,7 +1318,7 @@ bool evdi_painter_i2c_data_notify(struct
 	}
 
 	if (msg->addr != I2C_ADDRESS_DDCCI) {
-		EVDI_DEBUG("Ignored ddc/ci data for address 0x%x\n", msg->addr);
+		EVDI_WARN("Ignored ddc/ci data for address 0x%x\n", msg->addr);
 		return false;
 	}
 
@@ -1363,3 +1363,14 @@ unlock:
 	painter_unlock(painter);
 	return result;
 }
+
+int evdi_painter_enable_cursor_events_ioctl(struct drm_device *drm_dev, void *data,
+					__always_unused struct drm_file *file)
+{
+	struct evdi_device *evdi = drm_dev->dev_private;
+	struct drm_evdi_enable_cursor_events *cmd = data;
+
+	evdi->cursor_events_enabled = cmd->enable;
+
+	return 0;
+}
diff -pruN 1.9.0+dfsg-1/module/evdi_params.c 1.12.0+dfsg-0ubuntu2/module/evdi_params.c
--- 1.9.0+dfsg-1/module/evdi_params.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_params.c	2022-07-13 13:58:06.000000000 +0000
@@ -13,7 +13,7 @@
 #include "evdi_params.h"
 #include "evdi_debug.h"
 
-unsigned int evdi_loglevel __read_mostly = EVDI_LOGLEVEL_DEBUG;
+unsigned int evdi_loglevel __read_mostly = EVDI_LOGLEVEL_INFO;
 unsigned short int evdi_initial_device_count __read_mostly;
 
 module_param_named(initial_loglevel, evdi_loglevel, int, 0400);
@@ -22,3 +22,4 @@ MODULE_PARM_DESC(initial_loglevel, "Init
 module_param_named(initial_device_count,
 		   evdi_initial_device_count, ushort, 0644);
 MODULE_PARM_DESC(initial_device_count, "Initial DRM device count (default: 0)");
+
diff -pruN 1.9.0+dfsg-1/module/evdi_platform_dev.c 1.12.0+dfsg-0ubuntu2/module/evdi_platform_dev.c
--- 1.9.0+dfsg-1/module/evdi_platform_dev.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_platform_dev.c	2022-07-13 13:58:06.000000000 +0000
@@ -21,7 +21,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #include <linux/iommu.h>
 #endif
 
@@ -41,8 +41,8 @@ struct platform_device *evdi_platform_de
 
 	platform_dev = platform_device_register_full(info);
 	if (dma_set_mask(&platform_dev->dev, DMA_BIT_MASK(64))) {
-		EVDI_DEBUG("Unable to change dma mask to 64 bit. ");
-		EVDI_DEBUG("Sticking with 32 bit\n");
+		EVDI_WARN("Unable to change dma mask to 64 bit. ");
+		EVDI_WARN("Sticking with 32 bit\n");
 	}
 
 	EVDI_INFO("Evdi platform_device create\n");
@@ -58,20 +58,22 @@ void evdi_platform_dev_destroy(struct pl
 
 int evdi_platform_device_probe(struct platform_device *pdev)
 {
-	struct drm_device *dev = NULL;
-	struct evdi_platform_device_data *data =
-		kzalloc(sizeof(struct evdi_platform_device_data), GFP_KERNEL);
+	struct drm_device *dev;
+	struct evdi_platform_device_data *data;
 
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
 #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU)
 	struct dev_iommu iommu;
 #endif
 #endif
 	EVDI_CHECKPT();
 
+	data = kzalloc(sizeof(struct evdi_platform_device_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 /* Intel-IOMMU workaround: platform-bus unsupported, force ID-mapping */
 #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU)
-#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
+#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE || defined(EL8)
 	memset(&iommu, 0, sizeof(iommu));
 	iommu.priv = (void *)-1;
 	pdev->dev.iommu = &iommu;
@@ -83,20 +85,21 @@ int evdi_platform_device_probe(struct pl
 
 	dev = evdi_drm_device_create(&pdev->dev);
 	if (IS_ERR_OR_NULL(dev))
-		kfree(data);
-	else {
-		data->drm_dev = dev;
-		data->symlinked = false;
-		platform_set_drvdata(pdev, data);
-	}
+		goto err_free;
 
+	data->drm_dev = dev;
+	data->symlinked = false;
+	platform_set_drvdata(pdev, data);
+	return PTR_ERR_OR_ZERO(dev);
+
+err_free:
+	kfree(data);
 	return PTR_ERR_OR_ZERO(dev);
 }
 
 int evdi_platform_device_remove(struct platform_device *pdev)
 {
-	struct evdi_platform_device_data *data =
-		(struct evdi_platform_device_data *)platform_get_drvdata(pdev);
+	struct evdi_platform_device_data *data = platform_get_drvdata(pdev);
 
 	EVDI_CHECKPT();
 
@@ -107,8 +110,7 @@ int evdi_platform_device_remove(struct p
 
 bool evdi_platform_device_is_free(struct platform_device *pdev)
 {
-	struct evdi_platform_device_data *data =
-		(struct evdi_platform_device_data *)platform_get_drvdata(pdev);
+	struct evdi_platform_device_data *data = platform_get_drvdata(pdev);
 	struct evdi_device *evdi = data->drm_dev->dev_private;
 
 	if (evdi && !evdi_painter_is_connected(evdi->painter) &&
@@ -121,23 +123,21 @@ void evdi_platform_device_link(struct pl
 				      struct device *parent)
 {
 	struct evdi_platform_device_data *data = NULL;
-	char evdi_name[10] = { 0 };
 	int ret = 0;
 
 	if (!parent || !pdev)
 		return;
 
-	data = (struct evdi_platform_device_data *)platform_get_drvdata(pdev);
+	data = platform_get_drvdata(pdev);
 	if (!evdi_platform_device_is_free(pdev)) {
 		EVDI_FATAL("Device is already attached can't symlink again\n");
 		return;
 	}
 
-	snprintf(evdi_name, sizeof(evdi_name), "evdi.%d", pdev->id);
-	ret = sysfs_create_link(&parent->kobj, &pdev->dev.kobj, evdi_name);
-	if (ret)
-		EVDI_FATAL("Failed to create sysfs link to parent device\n");
-	else {
+	ret = sysfs_create_link(&pdev->dev.kobj, &parent->kobj, "device");
+	if (ret) {
+		EVDI_FATAL("Failed to create sysfs link from evdi to parent device\n");
+	} else {
 		data->symlinked = true;
 		data->parent = parent;
 	}
@@ -146,10 +146,10 @@ void evdi_platform_device_link(struct pl
 void evdi_platform_device_unlink_if_linked_with(struct platform_device *pdev,
 				struct device *parent)
 {
-	struct evdi_platform_device_data *data =
-		(struct evdi_platform_device_data *)platform_get_drvdata(pdev);
+	struct evdi_platform_device_data *data = platform_get_drvdata(pdev);
 
-	if (data->parent == parent) {
+	if (parent && data->parent == parent) {
+		sysfs_remove_link(&pdev->dev.kobj, "device");
 		data->symlinked = false;
 		data->parent = NULL;
 		EVDI_INFO("Detached from parent device\n");
diff -pruN 1.9.0+dfsg-1/module/evdi_platform_drv.c 1.12.0+dfsg-0ubuntu2/module/evdi_platform_drv.c
--- 1.9.0+dfsg-1/module/evdi_platform_drv.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_platform_drv.c	2022-07-13 13:58:06.000000000 +0000
@@ -31,8 +31,15 @@ static struct evdi_platform_drv_context
 	unsigned int dev_count;
 	struct platform_device *devices[EVDI_DEVICE_COUNT_MAX];
 	struct notifier_block usb_notifier;
+	struct mutex lock;
 } g_ctx;
 
+#define evdi_platform_drv_context_lock(ctx) \
+		mutex_lock(&ctx->lock)
+
+#define evdi_platform_drv_context_unlock(ctx) \
+		mutex_unlock(&ctx->lock)
+
 static int evdi_platform_drv_usb(__always_unused struct notifier_block *nb,
 		unsigned long action,
 		void *data)
@@ -54,8 +61,10 @@ static int evdi_platform_drv_usb(__alway
 		if (pdev->dev.parent == &usb_dev->dev) {
 			EVDI_INFO("Parent USB removed. Removing evdi.%d\n", i);
 			evdi_platform_dev_destroy(pdev);
+			evdi_platform_drv_context_lock((&g_ctx));
 			g_ctx.dev_count--;
 			g_ctx.devices[i] = NULL;
+			evdi_platform_drv_context_unlock((&g_ctx));
 		}
 	}
 	return 0;
@@ -116,10 +125,15 @@ int evdi_platform_device_add(struct devi
 {
 	struct evdi_platform_drv_context *ctx =
 		(struct evdi_platform_drv_context *)dev_get_drvdata(device);
-	struct platform_device *pdev = evdi_platform_drv_get_free_device(ctx);
+	struct platform_device *pdev = NULL;
+
+	evdi_platform_drv_context_lock(ctx);
+	if (parent)
+		pdev = evdi_platform_drv_get_free_device(ctx);
 
 	if (IS_ERR_OR_NULL(pdev))
 		pdev = evdi_platform_drv_create_new_device(ctx);
+	evdi_platform_drv_context_unlock(ctx);
 
 	if (IS_ERR_OR_NULL(pdev))
 		return -EINVAL;
@@ -130,19 +144,18 @@ int evdi_platform_device_add(struct devi
 
 int evdi_platform_add_devices(struct device *device, unsigned int val)
 {
-	struct evdi_platform_drv_context *ctx =
-		(struct evdi_platform_drv_context *)dev_get_drvdata(device);
+	unsigned int dev_count = evdi_platform_device_count(device);
 
 	if (val == 0) {
 		EVDI_WARN("Adding 0 devices has no effect\n");
 		return 0;
 	}
-	if (val > EVDI_DEVICE_COUNT_MAX - ctx->dev_count) {
+	if (val > EVDI_DEVICE_COUNT_MAX - dev_count) {
 		EVDI_ERROR("Evdi device add failed. Too many devices.\n");
 		return -EINVAL;
 	}
 
-	EVDI_DEBUG("Increasing device count to %u\n", ctx->dev_count + val);
+	EVDI_INFO("Increasing device count to %u\n", dev_count + val);
 	while (val-- && evdi_platform_device_add(device, NULL) == 0)
 		;
 	return 0;
@@ -154,6 +167,7 @@ void evdi_platform_remove_all_devices(st
 	struct evdi_platform_drv_context *ctx =
 		(struct evdi_platform_drv_context *)dev_get_drvdata(device);
 
+	evdi_platform_drv_context_lock(ctx);
 	for (i = 0; i < EVDI_DEVICE_COUNT_MAX; ++i) {
 		if (ctx->devices[i]) {
 			EVDI_INFO("Removing evdi %d\n", i);
@@ -163,14 +177,21 @@ void evdi_platform_remove_all_devices(st
 		}
 	}
 	ctx->dev_count = 0;
+	evdi_platform_drv_context_unlock(ctx);
 }
 
-int evdi_platform_device_count(struct device *device)
+unsigned int evdi_platform_device_count(struct device *device)
 {
-	struct evdi_platform_drv_context *ctx =
-		(struct evdi_platform_drv_context *)dev_get_drvdata(device);
+	unsigned int count = 0;
+	struct evdi_platform_drv_context *ctx = NULL;
+
+	ctx = (struct evdi_platform_drv_context *)dev_get_drvdata(device);
+	evdi_platform_drv_context_lock(ctx);
+	count = ctx->dev_count;
+	evdi_platform_drv_context_unlock(ctx);
+
+	return count;
 
-	return ctx->dev_count;
 }
 
 static struct platform_driver evdi_platform_driver = {
@@ -193,6 +214,7 @@ static int __init evdi_init(void)
 	memset(&g_ctx, 0, sizeof(g_ctx));
 	g_ctx.root_dev = root_device_register(DRIVER_NAME);
 	g_ctx.usb_notifier.notifier_call = evdi_platform_drv_usb;
+	mutex_init(&g_ctx.lock);
 	dev_set_drvdata(g_ctx.root_dev, &g_ctx);
 
 	usb_register_notify(&g_ctx.usb_notifier);
diff -pruN 1.9.0+dfsg-1/module/evdi_platform_drv.h 1.12.0+dfsg-0ubuntu2/module/evdi_platform_drv.h
--- 1.9.0+dfsg-1/module/evdi_platform_drv.h	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_platform_drv.h	2022-07-13 13:58:06.000000000 +0000
@@ -25,14 +25,14 @@ struct platform_device_info;
 
 #define DRIVER_NAME   "evdi"
 #define DRIVER_DESC   "Extensible Virtual Display Interface"
-#define DRIVER_DATE   "20201210"
+#define DRIVER_DATE   "20220713"
 
 #define DRIVER_MAJOR 1
-#define DRIVER_MINOR 9
+#define DRIVER_MINOR 12
 #define DRIVER_PATCH 0
 
 void evdi_platform_remove_all_devices(struct device *device);
-int evdi_platform_device_count(struct device *device);
+unsigned int evdi_platform_device_count(struct device *device);
 int evdi_platform_add_devices(struct device *device, unsigned int val);
 int evdi_platform_device_add(struct device *device, struct device *parent);
 
diff -pruN 1.9.0+dfsg-1/module/evdi_sysfs.c 1.12.0+dfsg-0ubuntu2/module/evdi_sysfs.c
--- 1.9.0+dfsg-1/module/evdi_sysfs.c	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/evdi_sysfs.c	2022-07-13 13:58:06.000000000 +0000
@@ -28,6 +28,8 @@
 #include "evdi_debug.h"
 #include "evdi_platform_drv.h"
 
+#define MAX_EVDI_USB_ADDR 10
+
 static ssize_t version_show(__always_unused struct device *dev,
 			    __always_unused struct device_attribute *attr,
 			    char *buf)
@@ -44,7 +46,6 @@ static ssize_t count_show(__always_unuse
 }
 
 struct evdi_usb_addr {
-	#define MAX_EVDI_USB_ADDR 10
 	int addr[MAX_EVDI_USB_ADDR];
 	int len;
 	struct usb_device *usb;
@@ -58,15 +59,17 @@ static ssize_t add_device_with_usb_path(
 {
 	char *usb_path = kstrdup(buf, GFP_KERNEL);
 	char *temp_path = usb_path;
-	char *bus_token = NULL;
-	char *usb_token = NULL;
+	char *bus_token;
+	char *usb_token;
 	char *usb_token_copy = NULL;
-	char *itf_token = NULL;
-	char *token = NULL;
-	char *bus = NULL;
-	char *port = NULL;
+	char *token;
+	char *bus;
+	char *port;
 	struct evdi_usb_addr usb_addr;
 
+	if (!usb_path)
+		return -ENOMEM;
+
 	memset(&usb_addr, 0, sizeof(usb_addr));
 	temp_path = strnstr(temp_path, "usb:", count);
 	if (!temp_path)
@@ -83,7 +86,8 @@ static ssize_t add_device_with_usb_path(
 	if (!usb_token)
 		goto err_parse_usb_path;
 
-	itf_token = strsep(&temp_path, ":");
+	/* Separate trailing ':*' from usb_token */
+	strsep(&temp_path, ":");
 
 	token = usb_token_copy = kstrdup(usb_token, GFP_KERNEL);
 	bus = strsep(&token, "-");
@@ -231,7 +235,7 @@ static struct device_attribute evdi_devi
 
 void evdi_sysfs_init(struct device *root)
 {
-	int i;
+	unsigned int i;
 
 	if (!PTR_ERR_OR_ZERO(root))
 		for (i = 0; i < ARRAY_SIZE(evdi_device_attributes); i++)
@@ -240,7 +244,7 @@ void evdi_sysfs_init(struct device *root
 
 void evdi_sysfs_exit(struct device *root)
 {
-	int i;
+	unsigned int i;
 
 	if (PTR_ERR_OR_ZERO(root)) {
 		EVDI_ERROR("root device is null");
diff -pruN 1.9.0+dfsg-1/module/Kconfig 1.12.0+dfsg-0ubuntu2/module/Kconfig
--- 1.9.0+dfsg-1/module/Kconfig	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/Kconfig	2022-07-13 13:58:06.000000000 +0000
@@ -9,6 +9,9 @@
 config DRM_EVDI
 	tristate "Extensible Virtual Display Interface"
 	depends on DRM
+	depends on USB_SUPPORT
+	depends on USB_ARCH_HAS_HCD
+	select USB
 	select DRM_KMS_HELPER
 	help
 		This is a KMS interface driver allowing user-space programs to
diff -pruN 1.9.0+dfsg-1/module/Makefile 1.12.0+dfsg-0ubuntu2/module/Makefile
--- 1.9.0+dfsg-1/module/Makefile	2021-01-26 14:31:59.000000000 +0000
+++ 1.12.0+dfsg-0ubuntu2/module/Makefile	2022-07-13 13:58:06.000000000 +0000
@@ -11,13 +11,18 @@ ifneq (,$(findstring 1, $(EL8)))
 EL8FLAG := -DEL8
 endif
 
+Raspbian := $(shell grep -Eic 'raspb(erry|ian)' /proc/cpuinfo /etc/os-release 2>/dev/null )
+ifeq (,$(findstring 0, $(Raspbian)))
+RPIFLAG := -DRPI
+endif
+
 ifneq ($(DKMS_BUILD),)
 
 # DKMS
 
 KERN_DIR := /lib/modules/$(KERNELRELEASE)/build
 
-ccflags-y := -Iinclude/drm $(EL8FLAG)
+ccflags-y := -Iinclude/drm $(EL8FLAG) $(RPIFLAG)
 evdi-y := evdi_platform_drv.o evdi_platform_dev.o evdi_sysfs.o evdi_modeset.o evdi_connector.o evdi_encoder.o evdi_drm_drv.o evdi_fb.o evdi_gem.o evdi_painter.o evdi_params.o evdi_cursor.o evdi_debug.o evdi_i2c.o
 evdi-$(CONFIG_COMPAT) += evdi_ioc32.o
 obj-m := evdi.o
@@ -40,8 +45,7 @@ ifneq ($(KERNELRELEASE),)
 # inside kbuild
 # Note: this can be removed once it is in kernel tree and Kconfig is properly used
 CONFIG_DRM_EVDI := m
-LINUXINCLUDE := $(subst -I,-isystem,$(LINUXINCLUDE))
-ccflags-y := -isystem include/drm $(CFLAGS) $(EL8FLAG)
+ccflags-y := -isystem include/drm $(CFLAGS) $(EL8FLAG) $(RPIFLAG)
 evdi-y := evdi_platform_drv.o evdi_platform_dev.o evdi_sysfs.o evdi_modeset.o evdi_connector.o evdi_encoder.o evdi_drm_drv.o evdi_fb.o evdi_gem.o evdi_painter.o evdi_params.o evdi_cursor.o evdi_debug.o evdi_i2c.o
 evdi-$(CONFIG_COMPAT) += evdi_ioc32.o
 obj-$(CONFIG_DRM_EVDI) := evdi.o
@@ -53,7 +57,7 @@ CP ?= cp
 DKMS ?= dkms
 RM ?= rm
 
-MODVER=1.9.0
+MODVER=1.12.0
 
 ifeq ($(KVER),)
 	KVER := $(shell uname -r)
