Module Name:    xsrc
Committed By:   mrg
Date:           Thu Jul  4 09:22:57 UTC 2024

Modified Files:
        xsrc/external/mit/libdrm/dist: configure libsync.h xf86drm.c xf86drm.h
            xf86drmMode.c xf86drmMode.h
        xsrc/external/mit/libdrm/dist/amdgpu: amdgpu.h amdgpu_bo.c
            amdgpu_vamgr.c
        xsrc/external/mit/libdrm/dist/include/drm: drm.h
        xsrc/external/mit/libdrm/dist/intel: intel_bufmgr_gem.c uthash.h
        xsrc/external/mit/libdrm/dist/radeon: radeon_surface.c
        xsrc/external/mit/libdrm/dist/tests/modetest: modetest.c
Removed Files:
        xsrc/external/mit/libdrm/dist/intel: i915_pciids.h intel_chipset.c

Log Message:
merge libdrm 2.4.122


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 xsrc/external/mit/libdrm/dist/configure
cvs rdiff -u -r1.3 -r1.4 xsrc/external/mit/libdrm/dist/libsync.h
cvs rdiff -u -r1.32 -r1.33 xsrc/external/mit/libdrm/dist/xf86drm.c
cvs rdiff -u -r1.16 -r1.17 xsrc/external/mit/libdrm/dist/xf86drm.h
cvs rdiff -u -r1.21 -r1.22 xsrc/external/mit/libdrm/dist/xf86drmMode.c
cvs rdiff -u -r1.14 -r1.15 xsrc/external/mit/libdrm/dist/xf86drmMode.h
cvs rdiff -u -r1.4 -r1.5 xsrc/external/mit/libdrm/dist/amdgpu/amdgpu.h \
    xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_vamgr.c
cvs rdiff -u -r1.6 -r1.7 xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_bo.c
cvs rdiff -u -r1.14 -r1.15 xsrc/external/mit/libdrm/dist/include/drm/drm.h
cvs rdiff -u -r1.1.1.9 -r0 xsrc/external/mit/libdrm/dist/intel/i915_pciids.h
cvs rdiff -u -r1.22 -r1.23 \
    xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c
cvs rdiff -u -r1.1.1.6 -r0 \
    xsrc/external/mit/libdrm/dist/intel/intel_chipset.c
cvs rdiff -u -r1.2 -r1.3 xsrc/external/mit/libdrm/dist/intel/uthash.h
cvs rdiff -u -r1.11 -r1.12 \
    xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c
cvs rdiff -u -r1.19 -r1.20 \
    xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: xsrc/external/mit/libdrm/dist/configure
diff -u xsrc/external/mit/libdrm/dist/configure:1.5 xsrc/external/mit/libdrm/dist/configure:1.6
--- xsrc/external/mit/libdrm/dist/configure:1.5	Fri Nov  3 17:05:41 2023
+++ xsrc/external/mit/libdrm/dist/configure	Thu Jul  4 09:22:57 2024
@@ -3,6 +3,6 @@
 # Identity of this package.
 PACKAGE_NAME='libdrm'
 PACKAGE_TARNAME='libdrm'
-PACKAGE_VERSION='2.4.114'
-PACKAGE_STRING='libdrm 2.4.114'
+PACKAGE_VERSION='2.4.122'
+PACKAGE_STRING='libdrm 2.4.122'
 PACKAGE_URL=''

Index: xsrc/external/mit/libdrm/dist/libsync.h
diff -u xsrc/external/mit/libdrm/dist/libsync.h:1.3 xsrc/external/mit/libdrm/dist/libsync.h:1.4
--- xsrc/external/mit/libdrm/dist/libsync.h:1.3	Tue Mar  7 16:28:42 2017
+++ xsrc/external/mit/libdrm/dist/libsync.h	Thu Jul  4 09:22:57 2024
@@ -33,7 +33,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <sys/ioctl.h>
-#include <sys/poll.h>
+#include <poll.h>
 #include <unistd.h>
 
 #if defined(__cplusplus)

Index: xsrc/external/mit/libdrm/dist/xf86drm.c
diff -u xsrc/external/mit/libdrm/dist/xf86drm.c:1.32 xsrc/external/mit/libdrm/dist/xf86drm.c:1.33
--- xsrc/external/mit/libdrm/dist/xf86drm.c:1.32	Sat Nov 12 02:07:07 2022
+++ xsrc/external/mit/libdrm/dist/xf86drm.c	Thu Jul  4 09:22:57 2024
@@ -60,7 +60,6 @@
 #if HAVE_SYS_SYSCTL_H
 #include <sys/sysctl.h>
 #endif
-#include <math.h>
 #include <inttypes.h>
 
 #if defined(__FreeBSD__)
@@ -179,11 +178,15 @@ drmGetFormatModifierNameFromAmd(uint64_t
 static char *
 drmGetFormatModifierNameFromAmlogic(uint64_t modifier);
 
+static char *
+drmGetFormatModifierNameFromVivante(uint64_t modifier);
+
 static const struct drmVendorInfo modifier_format_vendor_table[] = {
     { DRM_FORMAT_MOD_VENDOR_ARM, drmGetFormatModifierNameFromArm },
     { DRM_FORMAT_MOD_VENDOR_NVIDIA, drmGetFormatModifierNameFromNvidia },
     { DRM_FORMAT_MOD_VENDOR_AMD, drmGetFormatModifierNameFromAmd },
     { DRM_FORMAT_MOD_VENDOR_AMLOGIC, drmGetFormatModifierNameFromAmlogic },
+    { DRM_FORMAT_MOD_VENDOR_VIVANTE, drmGetFormatModifierNameFromVivante },
 };
 
 #ifndef AFBC_FORMAT_MOD_MODE_VALUE_MASK
@@ -478,6 +481,9 @@ drmGetFormatModifierNameFromAmd(uint64_t
     case AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS:
         str_tile_version = "GFX10_RBPLUS";
         break;
+    case AMD_FMT_MOD_TILE_VER_GFX11:
+        str_tile_version = "GFX11";
+        break;
     }
 
     if (str_tile_version) {
@@ -505,6 +511,9 @@ drmGetFormatModifierNameFromAmd(uint64_t
     case AMD_FMT_MOD_TILE_GFX9_64K_R_X:
         str_tile = "GFX9_64K_R_X";
         break;
+    case AMD_FMT_MOD_TILE_GFX11_256K_R_X:
+        str_tile = "GFX11_256K_R_X";
+        break;
     }
 
     if (str_tile)
@@ -551,6 +560,70 @@ drmGetFormatModifierNameFromAmlogic(uint
     return mod_amlogic;
 }
 
+static char *
+drmGetFormatModifierNameFromVivante(uint64_t modifier)
+{
+    const char *color_tiling, *tile_status, *compression;
+    char *mod_vivante = NULL;
+
+    switch (modifier & VIVANTE_MOD_TS_MASK) {
+    case 0:
+        tile_status = "";
+        break;
+    case VIVANTE_MOD_TS_64_4:
+        tile_status = ",TS=64B_4";
+        break;
+    case VIVANTE_MOD_TS_64_2:
+        tile_status = ",TS=64B_2";
+        break;
+    case VIVANTE_MOD_TS_128_4:
+        tile_status = ",TS=128B_4";
+        break;
+    case VIVANTE_MOD_TS_256_4:
+        tile_status = ",TS=256B_4";
+        break;
+    default:
+        tile_status = ",TS=UNKNOWN";
+        break;
+    }
+
+    switch (modifier & VIVANTE_MOD_COMP_MASK) {
+    case 0:
+        compression = "";
+        break;
+    case VIVANTE_MOD_COMP_DEC400:
+        compression = ",COMP=DEC400";
+        break;
+    default:
+        compression = ",COMP=UNKNOWN";
+	break;
+    }
+
+    switch (modifier & ~VIVANTE_MOD_EXT_MASK) {
+    case 0:
+        color_tiling = "LINEAR";
+	break;
+    case DRM_FORMAT_MOD_VIVANTE_TILED:
+        color_tiling = "TILED";
+	break;
+    case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
+        color_tiling = "SUPER_TILED";
+	break;
+    case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED:
+        color_tiling = "SPLIT_TILED";
+	break;
+    case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED:
+        color_tiling = "SPLIT_SUPER_TILED";
+	break;
+    default:
+        color_tiling = "UNKNOWN";
+	break;
+    }
+
+    asprintf(&mod_vivante, "%s%s%s", color_tiling, tile_status, compression);
+    return mod_vivante;
+}
+
 static unsigned log2_int(unsigned x)
 {
     unsigned l;
@@ -759,8 +832,6 @@ static const char *drmGetDeviceName(int 
     switch (type) {
     case DRM_NODE_PRIMARY:
         return DRM_DEV_NAME;
-    case DRM_NODE_CONTROL:
-        return DRM_CONTROL_DEV_NAME;
     case DRM_NODE_RENDER:
         return DRM_RENDER_DEV_NAME;
     }
@@ -956,8 +1027,6 @@ static int drmGetMinorBase(int type)
     switch (type) {
     case DRM_NODE_PRIMARY:
         return 0;
-    case DRM_NODE_CONTROL:
-        return 64;
     case DRM_NODE_RENDER:
         return 128;
     default:
@@ -978,8 +1047,6 @@ static int drmGetMinorType(int major, in
         // If not in /dev/drm/ we have the type in the name
         if (sscanf(name, "dri/card%d\n", &id) >= 1)
            return DRM_NODE_PRIMARY;
-        else if (sscanf(name, "dri/control%d\n", &id) >= 1)
-           return DRM_NODE_CONTROL;
         else if (sscanf(name, "dri/renderD%d\n", &id) >= 1)
            return DRM_NODE_RENDER;
         return -1;
@@ -987,19 +1054,20 @@ static int drmGetMinorType(int major, in
 
     minor = id;
 #endif
-    int type = minor >> 6;
-
-    if (minor < 0)
-        return -1;
+    char path[DRM_NODE_NAME_MAX];
+    const char *dev_name;
+    int i;
 
-    switch (type) {
-    case DRM_NODE_PRIMARY:
-    case DRM_NODE_CONTROL:
-    case DRM_NODE_RENDER:
-        return type;
-    default:
-        return -1;
+    for (i = DRM_NODE_PRIMARY; i < DRM_NODE_MAX; i++) {
+        dev_name = drmGetDeviceName(i);
+        if (!dev_name)
+           continue;
+        snprintf(path, sizeof(path), dev_name, DRM_DIR_NAME, minor);
+        if (!access(path, F_OK))
+           return i;
     }
+
+    return -1;
 }
 
 static const char *drmGetMinorName(int type)
@@ -1007,8 +1075,6 @@ static const char *drmGetMinorName(int t
     switch (type) {
     case DRM_NODE_PRIMARY:
         return DRM_PRIMARY_MINOR_NAME;
-    case DRM_NODE_CONTROL:
-        return DRM_CONTROL_MINOR_NAME;
     case DRM_NODE_RENDER:
         return DRM_RENDER_MINOR_NAME;
     default:
@@ -1195,7 +1261,7 @@ drm_public int drmOpen(const char *name,
  *
  * \param name driver name. Not referenced if bus ID is supplied.
  * \param busid bus ID. Zero if not known.
- * \param type the device node type to open, PRIMARY, CONTROL or RENDER
+ * \param type the device node type to open, PRIMARY or RENDER
  *
  * \return a file descriptor on success, or a negative value on error.
  *
@@ -1228,7 +1294,7 @@ drm_public int drmOpenWithType(const cha
 
 drm_public int drmOpenControl(int minor)
 {
-    return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
+    return -EINVAL;
 }
 
 drm_public int drmOpenRender(int minor)
@@ -3692,12 +3758,9 @@ static int get_sysctl_pci_bus_info(int m
     switch (type) {
     case DRM_NODE_PRIMARY:
          break;
-    case DRM_NODE_CONTROL:
-         id -= 64;
-         break;
     case DRM_NODE_RENDER:
          id -= 128;
-          break;
+         break;
     }
     if (id < 0)
         return -EINVAL;
@@ -3876,10 +3939,6 @@ drm_public int drmDevicesEqual(drmDevice
 
 static int drmGetNodeType(const char *name)
 {
-    if (strncmp(name, DRM_CONTROL_MINOR_NAME,
-        sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0)
-        return DRM_NODE_CONTROL;
-
     if (strncmp(name, DRM_RENDER_MINOR_NAME,
         sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0)
         return DRM_NODE_RENDER;
@@ -4582,14 +4641,24 @@ process_device(drmDevicePtr *device, con
 {
     struct stat sbuf;
     char node[PATH_MAX + 1];
-    int node_type, subsystem_type;
+    int node_type, subsystem_type, written;
     unsigned int maj, min;
+    const int max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *));
 
     node_type = drmGetNodeType(d_name);
     if (node_type < 0)
         return -1;
 
-    snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name);
+    written = snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name);
+    if (written < 0)
+        return -1;
+
+    /* anything longer than this will be truncated in drmDeviceAlloc.
+     * Account for NULL byte
+     */
+    if (written + 1 > max_node_length)
+        return -1;
+
     if (stat(node, &sbuf))
         return -1;
 
@@ -4696,6 +4765,8 @@ drm_public int drmGetDeviceFromDevId(dev
     const char      *dev_name;
     int              node_type, subsystem_type;
     int              maj, min, n, ret;
+    const int        max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *));
+    struct stat      sbuf;
 
     if (device == NULL)
         return -EINVAL;
@@ -4714,9 +4785,14 @@ drm_public int drmGetDeviceFromDevId(dev
     if (!dev_name)
         return -EINVAL;
 
+    /* anything longer than this will be truncated in drmDeviceAlloc.
+     * Account for NULL byte
+     */
     n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min);
     if (n == -1 || n >= PATH_MAX)
       return -errno;
+    if (n + 1 > max_node_length)
+        return -EINVAL;
     if (stat(node, &sbuf))
         return -EINVAL;
 
@@ -4798,6 +4874,23 @@ drm_public int drmGetDeviceFromDevId(dev
 #endif
 }
 
+drm_public int drmGetNodeTypeFromDevId(dev_t devid)
+{
+    int maj, min, node_type;
+
+    maj = major(devid);
+    min = minor(devid);
+
+    if (!drmNodeIsDRM(maj, min))
+        return -EINVAL;
+
+    node_type = drmGetMinorType(maj, min);
+    if (node_type == -1)
+        return -ENODEV;
+
+    return node_type;
+}
+
 /**
  * Get information about the opened drm device
  *
@@ -5215,6 +5308,20 @@ drm_public int drmSyncobjTransfer(int fd
     return ret;
 }
 
+drm_public int drmSyncobjEventfd(int fd, uint32_t handle, uint64_t point, int ev_fd,
+                                 uint32_t flags)
+{
+    struct drm_syncobj_eventfd args;
+
+    memclear(args);
+    args.handle = handle;
+    args.point = point;
+    args.fd = ev_fd;
+    args.flags = flags;
+
+    return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_EVENTFD, &args);
+}
+
 static char *
 drmGetFormatModifierFromSimpleTokens(uint64_t modifier)
 {

Index: xsrc/external/mit/libdrm/dist/xf86drm.h
diff -u xsrc/external/mit/libdrm/dist/xf86drm.h:1.16 xsrc/external/mit/libdrm/dist/xf86drm.h:1.17
--- xsrc/external/mit/libdrm/dist/xf86drm.h:1.16	Sat Nov 12 02:07:07 2022
+++ xsrc/external/mit/libdrm/dist/xf86drm.h	Thu Jul  4 09:22:57 2024
@@ -48,7 +48,7 @@ extern "C" {
 #endif
 
 #ifndef DRM_MAX_MINOR
-#define DRM_MAX_MINOR   16
+#define DRM_MAX_MINOR   64 /* deprecated */
 #endif
 
 #if defined(__linux__)
@@ -83,18 +83,18 @@ extern "C" {
 #ifdef __OpenBSD__
 #define DRM_DIR_NAME  "/dev"
 #define DRM_PRIMARY_MINOR_NAME  "drm"
-#define DRM_CONTROL_MINOR_NAME  "drmC"
+#define DRM_CONTROL_MINOR_NAME  "drmC" /* deprecated */
 #define DRM_RENDER_MINOR_NAME   "drmR"
 #else
 #define DRM_DIR_NAME  "/dev/dri"
 #define DRM_PRIMARY_MINOR_NAME  "card"
-#define DRM_CONTROL_MINOR_NAME  "controlD"
+#define DRM_CONTROL_MINOR_NAME  "controlD" /* deprecated */
 #define DRM_RENDER_MINOR_NAME   "renderD"
 #define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */
 #endif
 
 #define DRM_DEV_NAME          "%s/" DRM_PRIMARY_MINOR_NAME "%d"
-#define DRM_CONTROL_DEV_NAME  "%s/" DRM_CONTROL_MINOR_NAME "%d"
+#define DRM_CONTROL_DEV_NAME  "%s/" DRM_CONTROL_MINOR_NAME "%d" /* deprecated */
 #define DRM_RENDER_DEV_NAME   "%s/" DRM_RENDER_MINOR_NAME  "%d"
 
 #define DRM_NODE_NAME_MAX \
@@ -102,7 +102,7 @@ extern "C" {
      + MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), \
             sizeof(DRM_CONTROL_MINOR_NAME), \
             sizeof(DRM_RENDER_MINOR_NAME)) \
-     + sizeof("144") /* highest possible node number */ \
+     + sizeof("1048575") /* highest possible node number 2^MINORBITS - 1 */ \
      + 1) /* NULL-terminator */
 
 #define DRM_ERR_NO_DEVICE  (-1001)
@@ -605,14 +605,14 @@ extern int           drmAvailable(void);
 extern int           drmOpen(const char *name, const char *busid);
 
 #define DRM_NODE_PRIMARY 0
-#define DRM_NODE_CONTROL 1
+#define DRM_NODE_CONTROL 1 /* deprecated: never returned */
 #define DRM_NODE_RENDER  2
 #define DRM_NODE_MAX     3
 
 extern int           drmOpenWithType(const char *name, const char *busid,
                                      int type);
 
-extern int           drmOpenControl(int minor);
+extern int           drmOpenControl(int minor); /* deprecated: always fails */
 extern int           drmOpenRender(int minor);
 extern int           drmClose(int fd);
 extern drmVersionPtr drmGetVersion(int fd);
@@ -817,7 +817,7 @@ extern int drmHandleEvent(int fd, drmEve
 extern char *drmGetDeviceNameFromFd(int fd);
 
 /* Improved version of drmGetDeviceNameFromFd which attributes for any type of
- * device/node - card, control or renderD.
+ * device/node - card or renderD.
  */
 extern char *drmGetDeviceNameFromFd2(int fd);
 extern int drmGetNodeTypeFromFd(int fd);
@@ -928,6 +928,18 @@ extern int drmGetDevices2(uint32_t flags
 
 extern int drmGetDeviceFromDevId(dev_t dev_id, uint32_t flags, drmDevicePtr *device);
 
+/**
+ * Get the node type (DRM_NODE_PRIMARY or DRM_NODE_RENDER) from a device ID.
+ *
+ * Returns negative errno on error.
+ */
+extern int drmGetNodeTypeFromDevId(dev_t devid);
+
+/**
+ * Check if two drmDevice pointers represent the same DRM device.
+ *
+ * Returns 1 if the devices are equal, 0 otherwise.
+ */
 extern int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b);
 
 extern int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle);
@@ -956,6 +968,8 @@ extern int drmSyncobjTransfer(int fd,
 			      uint32_t dst_handle, uint64_t dst_point,
 			      uint32_t src_handle, uint64_t src_point,
 			      uint32_t flags);
+extern int drmSyncobjEventfd(int fd, uint32_t handle, uint64_t point, int ev_fd,
+                             uint32_t flags);
 
 extern char *
 drmGetFormatModifierVendor(uint64_t modifier);

Index: xsrc/external/mit/libdrm/dist/xf86drmMode.c
diff -u xsrc/external/mit/libdrm/dist/xf86drmMode.c:1.21 xsrc/external/mit/libdrm/dist/xf86drmMode.c:1.22
--- xsrc/external/mit/libdrm/dist/xf86drmMode.c:1.21	Sat Nov 12 02:07:07 2022
+++ xsrc/external/mit/libdrm/dist/xf86drmMode.c	Thu Jul  4 09:22:57 2024
@@ -320,6 +320,16 @@ drm_public int drmModeRmFB(int fd, uint3
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
 }
 
+drm_public int drmModeCloseFB(int fd, uint32_t buffer_id)
+{
+	struct drm_mode_closefb closefb;
+
+	memclear(closefb);
+	closefb.fb_id = buffer_id;
+
+	return DRM_IOCTL(fd, DRM_IOCTL_MODE_CLOSEFB, &closefb);
+}
+
 drm_public drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
 {
 	struct drm_mode_fb_cmd info;
@@ -1004,8 +1014,8 @@ drm_public int drmModeCrtcGetGamma(int f
 }
 
 drm_public int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
-								   uint16_t *red, uint16_t *green,
-								   uint16_t *blue)
+								   const uint16_t *red, const uint16_t *green,
+								   const uint16_t *blue)
 {
 	struct drm_mode_crtc_lut l;
 

Index: xsrc/external/mit/libdrm/dist/xf86drmMode.h
diff -u xsrc/external/mit/libdrm/dist/xf86drmMode.h:1.14 xsrc/external/mit/libdrm/dist/xf86drmMode.h:1.15
--- xsrc/external/mit/libdrm/dist/xf86drmMode.h:1.14	Sat Nov 12 02:07:07 2022
+++ xsrc/external/mit/libdrm/dist/xf86drmMode.h	Thu Jul  4 09:22:57 2024
@@ -315,6 +315,13 @@ int drmModeAddFB2WithModifiers(int fd, u
 extern int drmModeRmFB(int fd, uint32_t bufferId);
 
 /**
+ * Close a framebuffer.
+ *
+ * Same as drmModeRmFB(), except it doesn't implicitly disable planes and CRTCs.
+ */
+extern int drmModeCloseFB(int fd, uint32_t buffer_id);
+
+/**
  * Mark a region of a framebuffer as dirty.
  */
 extern int drmModeDirtyFB(int fd, uint32_t bufferId,
@@ -416,7 +423,7 @@ extern int drmModeConnectorSetProperty(i
 extern int drmCheckModesettingSupported(const char *busid);
 
 extern int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
-			       uint16_t *red, uint16_t *green, uint16_t *blue);
+			       const uint16_t *red, const uint16_t *green, const uint16_t *blue);
 extern int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
 			       uint16_t *red, uint16_t *green, uint16_t *blue);
 extern int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id,

Index: xsrc/external/mit/libdrm/dist/amdgpu/amdgpu.h
diff -u xsrc/external/mit/libdrm/dist/amdgpu/amdgpu.h:1.4 xsrc/external/mit/libdrm/dist/amdgpu/amdgpu.h:1.5
--- xsrc/external/mit/libdrm/dist/amdgpu/amdgpu.h:1.4	Mon Jul 11 19:26:44 2022
+++ xsrc/external/mit/libdrm/dist/amdgpu/amdgpu.h	Thu Jul  4 09:22:57 2024
@@ -142,6 +142,12 @@ typedef struct amdgpu_bo_list *amdgpu_bo
 typedef struct amdgpu_va *amdgpu_va_handle;
 
 /**
+ * Define handle dealing with VA allocation. An amdgpu_device
+ * owns one of these, but they can also be used without a device.
+ */
+typedef struct amdgpu_va_manager *amdgpu_va_manager_handle;
+
+/**
  * Define handle for semaphore
  */
 typedef struct amdgpu_semaphore *amdgpu_semaphore_handle;
@@ -531,6 +537,20 @@ int amdgpu_device_initialize(int fd,
 			     amdgpu_device_handle *device_handle);
 
 /**
+ * Same as amdgpu_device_initialize() except when deduplicate_device
+ * is false *and* fd points to a device that was already initialized.
+ * In this case, amdgpu_device_initialize would return the same
+ * amdgpu_device_handle while here amdgpu_device_initialize2 would
+ * return a new handle.
+ * amdgpu_device_initialize() should be preferred in most situations;
+ * the only use-case where not-deduplicating devices make sense is
+ * when one wants to have isolated device handles in the same process.
+ */
+int amdgpu_device_initialize2(int fd, bool deduplicate_device,
+			      uint32_t *major_version,
+			      uint32_t *minor_version,
+			      amdgpu_device_handle *device_handle);
+/**
  *
  * When access to such library does not needed any more the special
  * function must be call giving opportunity to clean up any
@@ -1286,6 +1306,22 @@ int amdgpu_query_video_caps_info(amdgpu_
                                  unsigned size, void *value);
 
 /**
+ * Query information about VM faults
+ *
+ * The return sizeof(struct drm_amdgpu_info_gpuvm_fault)
+ *
+ * \param   dev         - \c [in] Device handle. See #amdgpu_device_initialize()
+ * \param   size        - \c [in] Size of the returned value.
+ * \param   value       - \c [out] Pointer to the return value.
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+*/
+int amdgpu_query_gpuvm_fault_info(amdgpu_device_handle dev, unsigned size,
+				  void *value);
+
+/**
  * Read a set of consecutive memory-mapped registers.
  * Not all registers are allowed to be read by userspace.
  *
@@ -1372,6 +1408,11 @@ int amdgpu_va_range_alloc(amdgpu_device_
 int amdgpu_va_range_free(amdgpu_va_handle va_range_handle);
 
 /**
+ * Return the starting address of the allocated virtual address range.
+ */
+uint64_t amdgpu_va_get_start_addr(amdgpu_va_handle va_handle);
+
+/**
 * Query virtual address range
 *
 * UMD can query GPU VM range supported by each device
@@ -1393,6 +1434,37 @@ int amdgpu_va_range_query(amdgpu_device_
 			  uint64_t *end);
 
 /**
+ * Allocate a amdgpu_va_manager object.
+ * The returned object has be initialized with the amdgpu_va_manager_init
+ * before use.
+ * On release, amdgpu_va_manager_deinit needs to be called, then the memory
+ * can be released using free().
+ */
+amdgpu_va_manager_handle amdgpu_va_manager_alloc(void);
+
+void amdgpu_va_manager_init(amdgpu_va_manager_handle va_mgr,
+			    uint64_t low_va_offset, uint64_t low_va_max,
+			    uint64_t high_va_offset, uint64_t high_va_max,
+			    uint32_t virtual_address_alignment);
+
+void amdgpu_va_manager_deinit(amdgpu_va_manager_handle va_mgr);
+
+/**
+ * Similar to #amdgpu_va_range_alloc() but allocates VA
+ * directly from an amdgpu_va_manager_handle instead of using
+ * the manager from an amdgpu_device.
+ */
+
+int amdgpu_va_range_alloc2(amdgpu_va_manager_handle va_mgr,
+			   enum amdgpu_gpu_va_range va_range_type,
+			   uint64_t size,
+			   uint64_t va_base_alignment,
+			   uint64_t va_base_required,
+			   uint64_t *va_base_allocated,
+			   amdgpu_va_handle *va_range_handle,
+			   uint64_t flags);
+
+/**
  *  VA mapping/unmapping for the buffer object
  *
  * \param  bo		- \c [in] BO handle
Index: xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_vamgr.c
diff -u xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_vamgr.c:1.4 xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_vamgr.c:1.5
--- xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_vamgr.c:1.4	Sun Jul 11 00:41:13 2021
+++ xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_vamgr.c	Thu Jul  4 09:22:57 2024
@@ -229,24 +229,39 @@ drm_public int amdgpu_va_range_alloc(amd
 				     amdgpu_va_handle *va_range_handle,
 				     uint64_t flags)
 {
+	return amdgpu_va_range_alloc2(&dev->va_mgr, va_range_type, size,
+				      va_base_alignment, va_base_required,
+				      va_base_allocated, va_range_handle,
+				      flags);
+}
+
+drm_public int amdgpu_va_range_alloc2(amdgpu_va_manager_handle va_mgr,
+				      enum amdgpu_gpu_va_range va_range_type,
+				      uint64_t size,
+				      uint64_t va_base_alignment,
+				      uint64_t va_base_required,
+				      uint64_t *va_base_allocated,
+				      amdgpu_va_handle *va_range_handle,
+				      uint64_t flags)
+{
 	struct amdgpu_bo_va_mgr *vamgr;
 	bool search_from_top = !!(flags & AMDGPU_VA_RANGE_REPLAYABLE);
 	int ret;
 
 	/* Clear the flag when the high VA manager is not initialized */
-	if (flags & AMDGPU_VA_RANGE_HIGH && !dev->vamgr_high_32.va_max)
+	if (flags & AMDGPU_VA_RANGE_HIGH && !va_mgr->vamgr_high_32.va_max)
 		flags &= ~AMDGPU_VA_RANGE_HIGH;
 
 	if (flags & AMDGPU_VA_RANGE_HIGH) {
 		if (flags & AMDGPU_VA_RANGE_32_BIT)
-			vamgr = &dev->vamgr_high_32;
+			vamgr = &va_mgr->vamgr_high_32;
 		else
-			vamgr = &dev->vamgr_high;
+			vamgr = &va_mgr->vamgr_high;
 	} else {
 		if (flags & AMDGPU_VA_RANGE_32_BIT)
-			vamgr = &dev->vamgr_32;
+			vamgr = &va_mgr->vamgr_32;
 		else
-			vamgr = &dev->vamgr;
+			vamgr = &va_mgr->vamgr_low;
 	}
 
 	va_base_alignment = MAX2(va_base_alignment, vamgr->va_alignment);
@@ -259,9 +274,9 @@ drm_public int amdgpu_va_range_alloc(amd
 	if (!(flags & AMDGPU_VA_RANGE_32_BIT) && ret) {
 		/* fallback to 32bit address */
 		if (flags & AMDGPU_VA_RANGE_HIGH)
-			vamgr = &dev->vamgr_high_32;
+			vamgr = &va_mgr->vamgr_high_32;
 		else
-			vamgr = &dev->vamgr_32;
+			vamgr = &va_mgr->vamgr_32;
 		ret = amdgpu_vamgr_find_va(vamgr, size,
 					   va_base_alignment, va_base_required,
 					   search_from_top, va_base_allocated);
@@ -274,7 +289,6 @@ drm_public int amdgpu_va_range_alloc(amd
 			amdgpu_vamgr_free_va(vamgr, *va_base_allocated, size);
 			return -ENOMEM;
 		}
-		va->dev = dev;
 		va->address = *va_base_allocated;
 		va->size = size;
 		va->range = va_range_type;
@@ -296,3 +310,50 @@ drm_public int amdgpu_va_range_free(amdg
 	free(va_range_handle);
 	return 0;
 }
+
+drm_public uint64_t amdgpu_va_get_start_addr(amdgpu_va_handle va_handle)
+{
+   return va_handle->address;
+}
+
+drm_public amdgpu_va_manager_handle amdgpu_va_manager_alloc(void)
+{
+	amdgpu_va_manager_handle r = calloc(1, sizeof(struct amdgpu_va_manager));
+	return r;
+}
+
+drm_public void amdgpu_va_manager_init(struct amdgpu_va_manager *va_mgr,
+					uint64_t low_va_offset, uint64_t low_va_max,
+					uint64_t high_va_offset, uint64_t high_va_max,
+					uint32_t virtual_address_alignment)
+{
+	uint64_t start, max;
+
+	start = low_va_offset;
+	max = MIN2(low_va_max, 0x100000000ULL);
+	amdgpu_vamgr_init(&va_mgr->vamgr_32, start, max,
+			  virtual_address_alignment);
+
+	start = max;
+	max = MAX2(low_va_max, 0x100000000ULL);
+	amdgpu_vamgr_init(&va_mgr->vamgr_low, start, max,
+			  virtual_address_alignment);
+
+	start = high_va_offset;
+	max = MIN2(high_va_max, (start & ~0xffffffffULL) + 0x100000000ULL);
+	amdgpu_vamgr_init(&va_mgr->vamgr_high_32, start, max,
+			  virtual_address_alignment);
+
+	start = max;
+	max = MAX2(high_va_max, (start & ~0xffffffffULL) + 0x100000000ULL);
+	amdgpu_vamgr_init(&va_mgr->vamgr_high, start, max,
+			  virtual_address_alignment);
+}
+
+drm_public void amdgpu_va_manager_deinit(struct amdgpu_va_manager *va_mgr)
+{
+	amdgpu_vamgr_deinit(&va_mgr->vamgr_32);
+	amdgpu_vamgr_deinit(&va_mgr->vamgr_low);
+	amdgpu_vamgr_deinit(&va_mgr->vamgr_high_32);
+	amdgpu_vamgr_deinit(&va_mgr->vamgr_high);
+}

Index: xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_bo.c
diff -u xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_bo.c:1.6 xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_bo.c:1.7
--- xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_bo.c:1.6	Sat Nov 12 02:07:07 2022
+++ xsrc/external/mit/libdrm/dist/amdgpu/amdgpu_bo.c	Thu Jul  4 09:22:57 2024
@@ -551,7 +551,7 @@ drm_public int amdgpu_find_bo_by_cpu_map
 		if (!bo || !bo->cpu_ptr || size > bo->alloc_size)
 			continue;
 		if (cpu >= bo->cpu_ptr &&
-		    cpu < (void*)((char *)bo->cpu_ptr + bo->alloc_size))
+		    cpu < (void*)((uintptr_t)bo->cpu_ptr + (size_t)bo->alloc_size))
 			break;
 	}
 

Index: xsrc/external/mit/libdrm/dist/include/drm/drm.h
diff -u xsrc/external/mit/libdrm/dist/include/drm/drm.h:1.14 xsrc/external/mit/libdrm/dist/include/drm/drm.h:1.15
--- xsrc/external/mit/libdrm/dist/include/drm/drm.h:1.14	Sun Jan  9 09:05:35 2022
+++ xsrc/external/mit/libdrm/dist/include/drm/drm.h	Thu Jul  4 09:22:57 2024
@@ -632,8 +632,8 @@ struct drm_gem_open {
 /**
  * DRM_CAP_VBLANK_HIGH_CRTC
  *
- * If set to 1, the kernel supports specifying a CRTC index in the high bits of
- * &drm_wait_vblank_request.type.
+ * If set to 1, the kernel supports specifying a :ref:`CRTC index<crtc_index>`
+ * in the high bits of &drm_wait_vblank_request.type.
  *
  * Starting kernel version 2.6.39, this capability is always set to 1.
  */
@@ -670,8 +670,11 @@ struct drm_gem_open {
  * Bitfield of supported PRIME sharing capabilities. See &DRM_PRIME_CAP_IMPORT
  * and &DRM_PRIME_CAP_EXPORT.
  *
- * PRIME buffers are exposed as dma-buf file descriptors. See
- * Documentation/gpu/drm-mm.rst, section "PRIME Buffer Sharing".
+ * Starting from kernel version 6.6, both &DRM_PRIME_CAP_IMPORT and
+ * &DRM_PRIME_CAP_EXPORT are always advertised.
+ *
+ * PRIME buffers are exposed as dma-buf file descriptors.
+ * See :ref:`prime_buffer_sharing`.
  */
 #define DRM_CAP_PRIME			0x5
 /**
@@ -679,6 +682,8 @@ struct drm_gem_open {
  *
  * If this bit is set in &DRM_CAP_PRIME, the driver supports importing PRIME
  * buffers via the &DRM_IOCTL_PRIME_FD_TO_HANDLE ioctl.
+ *
+ * Starting from kernel version 6.6, this bit is always set in &DRM_CAP_PRIME.
  */
 #define  DRM_PRIME_CAP_IMPORT		0x1
 /**
@@ -686,6 +691,8 @@ struct drm_gem_open {
  *
  * If this bit is set in &DRM_CAP_PRIME, the driver supports exporting PRIME
  * buffers via the &DRM_IOCTL_PRIME_HANDLE_TO_FD ioctl.
+ *
+ * Starting from kernel version 6.6, this bit is always set in &DRM_CAP_PRIME.
  */
 #define  DRM_PRIME_CAP_EXPORT		0x2
 /**
@@ -703,7 +710,8 @@ struct drm_gem_open {
 /**
  * DRM_CAP_ASYNC_PAGE_FLIP
  *
- * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC.
+ * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC for legacy
+ * page-flips.
  */
 #define DRM_CAP_ASYNC_PAGE_FLIP		0x7
 /**
@@ -753,17 +761,23 @@ struct drm_gem_open {
 /**
  * DRM_CAP_SYNCOBJ
  *
- * If set to 1, the driver supports sync objects. See
- * Documentation/gpu/drm-mm.rst, section "DRM Sync Objects".
+ * If set to 1, the driver supports sync objects. See :ref:`drm_sync_objects`.
  */
 #define DRM_CAP_SYNCOBJ		0x13
 /**
  * DRM_CAP_SYNCOBJ_TIMELINE
  *
  * If set to 1, the driver supports timeline operations on sync objects. See
- * Documentation/gpu/drm-mm.rst, section "DRM Sync Objects".
+ * :ref:`drm_sync_objects`.
  */
 #define DRM_CAP_SYNCOBJ_TIMELINE	0x14
+/**
+ * DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP
+ *
+ * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC for atomic
+ * commits.
+ */
+#define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP	0x15
 
 /* DRM_IOCTL_GET_CAP ioctl argument type */
 struct drm_get_cap {
@@ -833,6 +847,31 @@ struct drm_get_cap {
  */
 #define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS	5
 
+/**
+ * DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT
+ *
+ * Drivers for para-virtualized hardware (e.g. vmwgfx, qxl, virtio and
+ * virtualbox) have additional restrictions for cursor planes (thus
+ * making cursor planes on those drivers not truly universal,) e.g.
+ * they need cursor planes to act like one would expect from a mouse
+ * cursor and have correctly set hotspot properties.
+ * If this client cap is not set the DRM core will hide cursor plane on
+ * those virtualized drivers because not setting it implies that the
+ * client is not capable of dealing with those extra restictions.
+ * Clients which do set cursor hotspot and treat the cursor plane
+ * like a mouse cursor should set this property.
+ * The client must enable &DRM_CLIENT_CAP_ATOMIC first.
+ *
+ * Setting this property on drivers which do not special case
+ * cursor planes (i.e. non-virtualized drivers) will return
+ * EOPNOTSUPP, which can be used by userspace to gauge
+ * requirements of the hardware/drivers they're running on.
+ *
+ * This capability is always supported for atomic-capable virtualized
+ * drivers starting from kernel version 6.6.
+ */
+#define DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT	6
+
 /* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
 	__u64 capability;
@@ -884,6 +923,7 @@ struct drm_syncobj_transfer {
 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point to become available */
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE (1 << 3) /* set fence deadline to deadline_nsec */
 struct drm_syncobj_wait {
 	__u64 handles;
 	/* absolute timeout */
@@ -892,6 +932,14 @@ struct drm_syncobj_wait {
 	__u32 flags;
 	__u32 first_signaled; /* only valid when not waiting all */
 	__u32 pad;
+	/**
+	 * @deadline_nsec - fence deadline hint
+	 *
+	 * Deadline hint, in absolute CLOCK_MONOTONIC, to set on backing
+	 * fence(s) if the DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE flag is
+	 * set.
+	 */
+	__u64 deadline_nsec;
 };
 
 struct drm_syncobj_timeline_wait {
@@ -904,6 +952,35 @@ struct drm_syncobj_timeline_wait {
 	__u32 flags;
 	__u32 first_signaled; /* only valid when not waiting all */
 	__u32 pad;
+	/**
+	 * @deadline_nsec - fence deadline hint
+	 *
+	 * Deadline hint, in absolute CLOCK_MONOTONIC, to set on backing
+	 * fence(s) if the DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE flag is
+	 * set.
+	 */
+	__u64 deadline_nsec;
+};
+
+/**
+ * struct drm_syncobj_eventfd
+ * @handle: syncobj handle.
+ * @flags: Zero to wait for the point to be signalled, or
+ *         &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE to wait for a fence to be
+ *         available for the point.
+ * @point: syncobj timeline point (set to zero for binary syncobjs).
+ * @fd: Existing eventfd to sent events to.
+ * @pad: Must be zero.
+ *
+ * Register an eventfd to be signalled by a syncobj. The eventfd counter will
+ * be incremented by one.
+ */
+struct drm_syncobj_eventfd {
+	__u32 handle;
+	__u32 flags;
+	__u64 point;
+	__s32 fd;
+	__u32 pad;
 };
 
 
@@ -969,6 +1046,19 @@ extern "C" {
 #define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
 #define DRM_IOCTL_SET_VERSION		DRM_IOWR(0x07, struct drm_set_version)
 #define DRM_IOCTL_MODESET_CTL           DRM_IOW(0x08, struct drm_modeset_ctl)
+/**
+ * DRM_IOCTL_GEM_CLOSE - Close a GEM handle.
+ *
+ * GEM handles are not reference-counted by the kernel. User-space is
+ * responsible for managing their lifetime. For example, if user-space imports
+ * the same memory object twice on the same DRM file description, the same GEM
+ * handle is returned by both imports, and user-space needs to ensure
+ * &DRM_IOCTL_GEM_CLOSE is performed once only. The same situation can happen
+ * when a memory object is allocated, then exported and imported again on the
+ * same DRM file description. The &DRM_IOCTL_MODE_GETFB2 IOCTL is an exception
+ * and always returns fresh new GEM handles even if an existing GEM handle
+ * already refers to the same memory object before the IOCTL is performed.
+ */
 #define DRM_IOCTL_GEM_CLOSE		DRM_IOW (0x09, struct drm_gem_close)
 #define DRM_IOCTL_GEM_FLINK		DRM_IOWR(0x0a, struct drm_gem_flink)
 #define DRM_IOCTL_GEM_OPEN		DRM_IOWR(0x0b, struct drm_gem_open)
@@ -1009,7 +1099,37 @@ extern "C" {
 #define DRM_IOCTL_UNLOCK		DRM_IOW( 0x2b, struct drm_lock)
 #define DRM_IOCTL_FINISH		DRM_IOW( 0x2c, struct drm_lock)
 
+/**
+ * DRM_IOCTL_PRIME_HANDLE_TO_FD - Convert a GEM handle to a DMA-BUF FD.
+ *
+ * User-space sets &drm_prime_handle.handle with the GEM handle to export and
+ * &drm_prime_handle.flags, and gets back a DMA-BUF file descriptor in
+ * &drm_prime_handle.fd.
+ *
+ * The export can fail for any driver-specific reason, e.g. because export is
+ * not supported for this specific GEM handle (but might be for others).
+ *
+ * Support for exporting DMA-BUFs is advertised via &DRM_PRIME_CAP_EXPORT.
+ */
 #define DRM_IOCTL_PRIME_HANDLE_TO_FD    DRM_IOWR(0x2d, struct drm_prime_handle)
+/**
+ * DRM_IOCTL_PRIME_FD_TO_HANDLE - Convert a DMA-BUF FD to a GEM handle.
+ *
+ * User-space sets &drm_prime_handle.fd with a DMA-BUF file descriptor to
+ * import, and gets back a GEM handle in &drm_prime_handle.handle.
+ * &drm_prime_handle.flags is unused.
+ *
+ * If an existing GEM handle refers to the memory object backing the DMA-BUF,
+ * that GEM handle is returned. Therefore user-space which needs to handle
+ * arbitrary DMA-BUFs must have a user-space lookup data structure to manually
+ * reference-count duplicated GEM handles. For more information see
+ * &DRM_IOCTL_GEM_CLOSE.
+ *
+ * The import can fail for any driver-specific reason, e.g. because import is
+ * only supported for DMA-BUFs allocated on this DRM device.
+ *
+ * Support for importing DMA-BUFs is advertised via &DRM_PRIME_CAP_IMPORT.
+ */
 #define DRM_IOCTL_PRIME_FD_TO_HANDLE    DRM_IOWR(0x2e, struct drm_prime_handle)
 
 #define DRM_IOCTL_AGP_ACQUIRE		DRM_IO(  0x30)
@@ -1047,10 +1167,40 @@ extern "C" {
 #define DRM_IOCTL_MODE_GETPROPBLOB	DRM_IOWR(0xAC, struct drm_mode_get_blob)
 #define DRM_IOCTL_MODE_GETFB		DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
 #define DRM_IOCTL_MODE_ADDFB		DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
+/**
+ * DRM_IOCTL_MODE_RMFB - Remove a framebuffer.
+ *
+ * This removes a framebuffer previously added via ADDFB/ADDFB2. The IOCTL
+ * argument is a framebuffer object ID.
+ *
+ * Warning: removing a framebuffer currently in-use on an enabled plane will
+ * disable that plane. The CRTC the plane is linked to may also be disabled
+ * (depending on driver capabilities).
+ */
 #define DRM_IOCTL_MODE_RMFB		DRM_IOWR(0xAF, unsigned int)
 #define DRM_IOCTL_MODE_PAGE_FLIP	DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
 #define DRM_IOCTL_MODE_DIRTYFB		DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)
 
+/**
+ * DRM_IOCTL_MODE_CREATE_DUMB - Create a new dumb buffer object.
+ *
+ * KMS dumb buffers provide a very primitive way to allocate a buffer object
+ * suitable for scanout and map it for software rendering. KMS dumb buffers are
+ * not suitable for hardware-accelerated rendering nor video decoding. KMS dumb
+ * buffers are not suitable to be displayed on any other device than the KMS
+ * device where they were allocated from. Also see
+ * :ref:`kms_dumb_buffer_objects`.
+ *
+ * The IOCTL argument is a struct drm_mode_create_dumb.
+ *
+ * User-space is expected to create a KMS dumb buffer via this IOCTL, then add
+ * it as a KMS framebuffer via &DRM_IOCTL_MODE_ADDFB and map it via
+ * &DRM_IOCTL_MODE_MAP_DUMB.
+ *
+ * &DRM_CAP_DUMB_BUFFER indicates whether this IOCTL is supported.
+ * &DRM_CAP_DUMB_PREFERRED_DEPTH and &DRM_CAP_DUMB_PREFER_SHADOW indicate
+ * driver preferences for dumb buffers.
+ */
 #define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
 #define DRM_IOCTL_MODE_MAP_DUMB    DRM_IOWR(0xB3, struct drm_mode_map_dumb)
 #define DRM_IOCTL_MODE_DESTROY_DUMB    DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
@@ -1083,8 +1233,58 @@ extern "C" {
 #define DRM_IOCTL_SYNCOBJ_TRANSFER	DRM_IOWR(0xCC, struct drm_syncobj_transfer)
 #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL	DRM_IOWR(0xCD, struct drm_syncobj_timeline_array)
 
+/**
+ * DRM_IOCTL_MODE_GETFB2 - Get framebuffer metadata.
+ *
+ * This queries metadata about a framebuffer. User-space fills
+ * &drm_mode_fb_cmd2.fb_id as the input, and the kernels fills the rest of the
+ * struct as the output.
+ *
+ * If the client is DRM master or has &CAP_SYS_ADMIN, &drm_mode_fb_cmd2.handles
+ * will be filled with GEM buffer handles. Fresh new GEM handles are always
+ * returned, even if another GEM handle referring to the same memory object
+ * already exists on the DRM file description. The caller is responsible for
+ * removing the new handles, e.g. via the &DRM_IOCTL_GEM_CLOSE IOCTL. The same
+ * new handle will be returned for multiple planes in case they use the same
+ * memory object. Planes are valid until one has a zero handle -- this can be
+ * used to compute the number of planes.
+ *
+ * Otherwise, &drm_mode_fb_cmd2.handles will be zeroed and planes are valid
+ * until one has a zero &drm_mode_fb_cmd2.pitches.
+ *
+ * If the framebuffer has a format modifier, &DRM_MODE_FB_MODIFIERS will be set
+ * in &drm_mode_fb_cmd2.flags and &drm_mode_fb_cmd2.modifier will contain the
+ * modifier. Otherwise, user-space must ignore &drm_mode_fb_cmd2.modifier.
+ *
+ * To obtain DMA-BUF FDs for each plane without leaking GEM handles, user-space
+ * can export each handle via &DRM_IOCTL_PRIME_HANDLE_TO_FD, then immediately
+ * close each unique handle via &DRM_IOCTL_GEM_CLOSE, making sure to not
+ * double-close handles which are specified multiple times in the array.
+ */
 #define DRM_IOCTL_MODE_GETFB2		DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
 
+#define DRM_IOCTL_SYNCOBJ_EVENTFD	DRM_IOWR(0xCF, struct drm_syncobj_eventfd)
+
+/**
+ * DRM_IOCTL_MODE_CLOSEFB - Close a framebuffer.
+ *
+ * This closes a framebuffer previously added via ADDFB/ADDFB2. The IOCTL
+ * argument is a framebuffer object ID.
+ *
+ * This IOCTL is similar to &DRM_IOCTL_MODE_RMFB, except it doesn't disable
+ * planes and CRTCs. As long as the framebuffer is used by a plane, it's kept
+ * alive. When the plane no longer uses the framebuffer (because the
+ * framebuffer is replaced with another one, or the plane is disabled), the
+ * framebuffer is cleaned up.
+ *
+ * This is useful to implement flicker-free transitions between two processes.
+ *
+ * Depending on the threat model, user-space may want to ensure that the
+ * framebuffer doesn't expose any sensitive user information: closed
+ * framebuffers attached to a plane can be read back by the next DRM master.
+ */
+#define DRM_IOCTL_MODE_CLOSEFB		DRM_IOWR(0xD0, struct drm_mode_closefb)
+
 /*
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
@@ -1096,25 +1296,50 @@ extern "C" {
 #define DRM_COMMAND_BASE                0x40
 #define DRM_COMMAND_END			0xA0
 
-/*
- * Header for events written back to userspace on the drm fd.  The
- * type defines the type of event, the length specifies the total
- * length of the event (including the header), and user_data is
- * typically a 64 bit value passed with the ioctl that triggered the
- * event.  A read on the drm fd will always only return complete
- * events, that is, if for example the read buffer is 100 bytes, and
- * there are two 64 byte events pending, only one will be returned.
- *
- * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and
- * up are chipset specific.
+/**
+ * struct drm_event - Header for DRM events
+ * @type: event type.
+ * @length: total number of payload bytes (including header).
+ *
+ * This struct is a header for events written back to user-space on the DRM FD.
+ * A read on the DRM FD will always only return complete events: e.g. if the
+ * read buffer is 100 bytes large and there are two 64 byte events pending,
+ * only one will be returned.
+ *
+ * Event types 0 - 0x7fffffff are generic DRM events, 0x80000000 and
+ * up are chipset specific. Generic DRM events include &DRM_EVENT_VBLANK,
+ * &DRM_EVENT_FLIP_COMPLETE and &DRM_EVENT_CRTC_SEQUENCE.
  */
 struct drm_event {
 	__u32 type;
 	__u32 length;
 };
 
+/**
+ * DRM_EVENT_VBLANK - vertical blanking event
+ *
+ * This event is sent in response to &DRM_IOCTL_WAIT_VBLANK with the
+ * &_DRM_VBLANK_EVENT flag set.
+ *
+ * The event payload is a struct drm_event_vblank.
+ */
 #define DRM_EVENT_VBLANK 0x01
+/**
+ * DRM_EVENT_FLIP_COMPLETE - page-flip completion event
+ *
+ * This event is sent in response to an atomic commit or legacy page-flip with
+ * the &DRM_MODE_PAGE_FLIP_EVENT flag set.
+ *
+ * The event payload is a struct drm_event_vblank.
+ */
 #define DRM_EVENT_FLIP_COMPLETE 0x02
+/**
+ * DRM_EVENT_CRTC_SEQUENCE - CRTC sequence event
+ *
+ * This event is sent in response to &DRM_IOCTL_CRTC_QUEUE_SEQUENCE.
+ *
+ * The event payload is a struct drm_event_crtc_sequence.
+ */
 #define DRM_EVENT_CRTC_SEQUENCE	0x03
 
 struct drm_event_vblank {

Index: xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c
diff -u xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c:1.22 xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c:1.23
--- xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c:1.22	Sat Nov 12 02:07:08 2022
+++ xsrc/external/mit/libdrm/dist/intel/intel_bufmgr_gem.c	Thu Jul  4 09:22:57 2024
@@ -3590,13 +3590,9 @@ drm_intel_bufmgr_gem_init(int fd, int ba
 		bufmgr_gem->gen = 6;
 	else if (IS_GEN7(bufmgr_gem->pci_device))
 		bufmgr_gem->gen = 7;
-	else if (IS_GEN8(bufmgr_gem->pci_device))
+	else
+		/* Treat all further unmatched platforms the same as gen8 */
 		bufmgr_gem->gen = 8;
-	else if (!intel_get_genx(bufmgr_gem->pci_device, &bufmgr_gem->gen)) {
-		free(bufmgr_gem);
-		bufmgr_gem = NULL;
-		goto exit;
-	}
 
 	if (IS_GEN3(bufmgr_gem->pci_device) &&
 	    bufmgr_gem->gtt_size > 256*1024*1024) {

Index: xsrc/external/mit/libdrm/dist/intel/uthash.h
diff -u xsrc/external/mit/libdrm/dist/intel/uthash.h:1.2 xsrc/external/mit/libdrm/dist/intel/uthash.h:1.3
--- xsrc/external/mit/libdrm/dist/intel/uthash.h:1.2	Mon Mar  6 23:11:39 2017
+++ xsrc/external/mit/libdrm/dist/intel/uthash.h	Thu Jul  4 09:22:57 2024
@@ -648,11 +648,11 @@ do {                                    
 #define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL)
 #define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL)
 #define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
-#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
+#ifdef HAVE_BIG_ENDIAN
 #define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
 #define MUR_TWO_TWO(p)   ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
 #define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >>  8))
-#else /* assume little endian non-intel */
+#else /* little endian non-intel */
 #define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
 #define MUR_TWO_TWO(p)   ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
 #define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) <<  8))

Index: xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c
diff -u xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c:1.11 xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c:1.12
--- xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c:1.11	Thu Jan 10 08:59:43 2019
+++ xsrc/external/mit/libdrm/dist/radeon/radeon_surface.c	Thu Jul  4 09:22:57 2024
@@ -2205,6 +2205,7 @@ static int cik_surface_sanity(struct rad
         break;
     case RADEON_SURF_MODE_LINEAR_ALIGNED:
     default:
+        *stencil_tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
         *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
     }
 

Index: xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c
diff -u xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c:1.19 xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c:1.20
--- xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c:1.19	Sat Nov 12 02:07:08 2022
+++ xsrc/external/mit/libdrm/dist/tests/modetest/modetest.c	Thu Jul  4 09:22:57 2024
@@ -70,6 +70,7 @@
 
 static enum util_fill_pattern primary_fill = UTIL_PATTERN_SMPTE;
 static enum util_fill_pattern secondary_fill = UTIL_PATTERN_TILES;
+static drmModeModeInfo user_mode;
 
 struct crtc {
 	drmModeCrtc *crtc;
@@ -128,6 +129,7 @@ struct device {
 
 	int use_atomic;
 	drmModeAtomicReq *req;
+	int32_t writeback_fence_fd;
 };
 
 static inline int64_t U642I64(uint64_t val)
@@ -137,8 +139,19 @@ static inline int64_t U642I64(uint64_t v
 
 static float mode_vrefresh(drmModeModeInfo *mode)
 {
-	return  mode->clock * 1000.00
-			/ (mode->htotal * mode->vtotal);
+	unsigned int num, den;
+
+	num = mode->clock;
+	den = mode->htotal * mode->vtotal;
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		num *= 2;
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		den *= 2;
+	if (mode->vscan > 1)
+		den *= mode->vscan;
+
+	return num * 1000.00 / den;
 }
 
 #define bit_name_fn(res)					\
@@ -317,7 +330,7 @@ static void dump_in_formats(struct devic
 			printf(": ");
 		}
 
-		printf(" %s", modifier_to_string(iter.mod));
+		printf(" %s(0x%"PRIx64")", modifier_to_string(iter.mod), iter.mod);
 	}
 
 	printf("\n");
@@ -804,13 +817,15 @@ struct pipe_arg {
 	unsigned int num_cons;
 	uint32_t crtc_id;
 	char mode_str[64];
-	char format_str[5];
+	char format_str[8]; /* need to leave room for "_BE" and terminating \0 */
 	float vrefresh;
 	unsigned int fourcc;
 	drmModeModeInfo *mode;
 	struct crtc *crtc;
 	unsigned int fb_id[2], current_fb_id;
 	struct timeval start;
+	unsigned int out_fb_id;
+	struct bo *out_bo;
 
 	int swap_count;
 };
@@ -826,7 +841,7 @@ struct plane_arg {
 	unsigned int old_fb_id;
 	struct bo *bo;
 	struct bo *old_bo;
-	char format_str[5]; /* need to leave room for terminating \0 */
+	char format_str[8]; /* need to leave room for "_BE" and terminating \0 */
 	unsigned int fourcc;
 };
 
@@ -839,7 +854,25 @@ connector_find_mode(struct device *dev, 
 	int i;
 
 	connector = get_connector_by_id(dev, con_id);
-	if (!connector || !connector->count_modes)
+	if (!connector)
+		return NULL;
+
+	if (strchr(mode_str, ',')) {
+		i = sscanf(mode_str, "%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu",
+			     &user_mode.hdisplay, &user_mode.hsync_start,
+			     &user_mode.hsync_end, &user_mode.htotal,
+			     &user_mode.vdisplay, &user_mode.vsync_start,
+			     &user_mode.vsync_end, &user_mode.vtotal);
+		if (i == 8) {
+			user_mode.clock = roundf(user_mode.htotal * user_mode.vtotal * vrefresh / 1000);
+			user_mode.vrefresh = roundf(vrefresh);
+			snprintf(user_mode.name, sizeof(user_mode.name), "custom%dx%d", user_mode.hdisplay, user_mode.vdisplay);
+
+			return &user_mode;
+		}
+	}
+
+	if (!connector->count_modes)
 		return NULL;
 
 	/* Pick by Index */
@@ -1040,7 +1073,7 @@ static bool set_property(struct device *
 
 	if (ret < 0)
 		fprintf(stderr, "failed to set %s %i property %s to %" PRIu64 ": %s\n",
-			obj_type, p->obj_id, p->name, p->value, strerror(errno));
+			obj_type, p->obj_id, p->name, p->value, strerror(-ret));
 
 	return true;
 }
@@ -1116,15 +1149,23 @@ static bool add_property_optional(struct
 static void set_gamma(struct device *dev, unsigned crtc_id, unsigned fourcc)
 {
 	unsigned blob_id = 0;
+	const struct util_format_info *info;
 	/* TODO: support 1024-sized LUTs, when the use-case arises */
 	struct drm_color_lut gamma_lut[256];
 	int i, ret;
 
-	if (fourcc == DRM_FORMAT_C8) {
-		/* TODO: Add C8 support for more patterns */
-		util_smpte_c8_gamma(256, gamma_lut);
+	info = util_format_info_find(fourcc);
+	if (info->ncolors) {
+		memset(gamma_lut, 0, sizeof(gamma_lut));
+		/* TODO: Add index support for more patterns */
+		util_smpte_fill_lut(info->ncolors, gamma_lut);
 		drmModeCreatePropertyBlob(dev->fd, gamma_lut, sizeof(gamma_lut), &blob_id);
 	} else {
+		/*
+		 * Initialize gamma_lut to a linear table for the legacy API below.
+		 * The modern property API resets to a linear/pass-thru table if blob_id
+		 * is 0, hence no PropertyBlob is created here.
+		 */
 		for (i = 0; i < 256; i++) {
 			gamma_lut[i].red =
 			gamma_lut[i].green =
@@ -1135,6 +1176,7 @@ static void set_gamma(struct device *dev
 	add_property_optional(dev, crtc_id, "DEGAMMA_LUT", 0);
 	add_property_optional(dev, crtc_id, "CTM", 0);
 	if (!add_property_optional(dev, crtc_id, "GAMMA_LUT", blob_id)) {
+		/* If we can't add the GAMMA_LUT property, try the legacy API. */
 		uint16_t r[256], g[256], b[256];
 
 		for (i = 0; i < 256; i++) {
@@ -1144,7 +1186,7 @@ static void set_gamma(struct device *dev
 		}
 
 		ret = drmModeCrtcSetGamma(dev->fd, crtc_id, 256, r, g, b);
-		if (ret)
+		if (ret && errno != ENOSYS)
 			fprintf(stderr, "failed to set gamma: %s\n", strerror(errno));
 	}
 }
@@ -1441,6 +1483,24 @@ static int pipe_resolve_connectors(struc
 	return 0;
 }
 
+static bool pipe_has_writeback_connector(struct device *dev, struct pipe_arg *pipes,
+		unsigned int count)
+{
+	drmModeConnector *connector;
+	unsigned int i, j;
+
+	for (j = 0; j < count; j++) {
+		struct pipe_arg *pipe = &pipes[j];
+
+		for (i = 0; i < pipe->num_cons; i++) {
+			connector = get_connector_by_id(dev, pipe->con_ids[i]);
+			if (connector && connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+				return true;
+		}
+	}
+	return false;
+}
+
 static int pipe_attempt_connector(struct device *dev, drmModeConnector *con,
 		struct pipe_arg *pipe)
 {
@@ -1503,7 +1563,8 @@ static int pipe_find_preferred(struct de
 
 	for (i = 0; i < res->count_connectors; i++) {
 		con = res->connectors[i].connector;
-		if (!con || con->connection != DRM_MODE_CONNECTED)
+		if (!con || con->connection != DRM_MODE_CONNECTED ||
+		    con->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
 			continue;
 		connected++;
 	}
@@ -1550,32 +1611,35 @@ static struct plane *get_primary_plane_b
 	return NULL;
 }
 
-static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+static unsigned int set_mode(struct device *dev, struct pipe_arg **pipe_args, unsigned int count)
 {
 	unsigned int i, j;
 	int ret, x = 0;
 	int preferred = count == 0;
+	struct pipe_arg *pipes;
 
-	for (i = 0; i < count; i++) {
-		struct pipe_arg *pipe = &pipes[i];
-
-		ret = pipe_resolve_connectors(dev, pipe);
-		if (ret < 0)
-			return;
-
-		ret = pipe_find_crtc_and_mode(dev, pipe);
-		if (ret < 0)
-			continue;
-	}
 	if (preferred) {
-		struct pipe_arg *pipe_args;
-
-		count = pipe_find_preferred(dev, &pipe_args);
+		count = pipe_find_preferred(dev, pipe_args);
 		if (!count) {
 			fprintf(stderr, "can't find any preferred connector/mode.\n");
-			return;
+			return 0;
+		}
+
+		pipes = *pipe_args;
+	} else {
+		pipes = *pipe_args;
+
+		for (i = 0; i < count; i++) {
+			struct pipe_arg *pipe = &pipes[i];
+
+			ret = pipe_resolve_connectors(dev, pipe);
+			if (ret < 0)
+				return 0;
+
+			ret = pipe_find_crtc_and_mode(dev, pipe);
+			if (ret < 0)
+				continue;
 		}
-		pipes = pipe_args;
 	}
 
 	if (!dev->use_atomic) {
@@ -1602,7 +1666,7 @@ static void set_mode(struct device *dev,
 
 		if (bo_fb_create(dev->fd, pipes[0].fourcc, dev->mode.width, dev->mode.height,
 			             primary_fill, &dev->mode.bo, &dev->mode.fb_id))
-			return;
+			return 0;
 	}
 
 	for (i = 0; i < count; i++) {
@@ -1634,7 +1698,7 @@ static void set_mode(struct device *dev,
 
 			if (ret) {
 				fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
-				return;
+				return 0;
 			}
 
 			set_gamma(dev, pipe->crtc_id, pipe->fourcc);
@@ -1660,6 +1724,77 @@ static void set_mode(struct device *dev,
 			}
 		}
 	}
+
+	return count;
+}
+
+static void writeback_config(struct device *dev, struct pipe_arg *pipes, unsigned int count)
+{
+	drmModeConnector *connector;
+	unsigned int i, j;
+
+	for (j = 0; j < count; j++) {
+		struct pipe_arg *pipe = &pipes[j];
+
+		for (i = 0; i < pipe->num_cons; i++) {
+			connector = get_connector_by_id(dev, pipe->con_ids[i]);
+			if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) {
+				if (!pipe->mode) {
+					fprintf(stderr, "no mode for writeback\n");
+					return;
+				}
+				bo_fb_create(dev->fd, pipes[j].fourcc,
+					     pipe->mode->hdisplay, pipe->mode->vdisplay,
+					     UTIL_PATTERN_PLAIN,
+					     &pipe->out_bo, &pipe->out_fb_id);
+				add_property(dev, pipe->con_ids[i], "WRITEBACK_FB_ID",
+					     pipe->out_fb_id);
+				add_property(dev, pipe->con_ids[i], "WRITEBACK_OUT_FENCE_PTR",
+					     (uintptr_t)(&dev->writeback_fence_fd));
+			}
+		}
+	}
+}
+
+static int poll_writeback_fence(int fd, int timeout)
+{
+	struct pollfd fds = { fd, POLLIN };
+	int ret;
+
+	do {
+		ret = poll(&fds, 1, timeout);
+		if (ret > 0) {
+			if (fds.revents & (POLLERR | POLLNVAL))
+				return -EINVAL;
+
+			return 0;
+		} else if (ret == 0) {
+			return -ETIMEDOUT;
+		} else {
+			ret = -errno;
+			if (ret == -EINTR || ret == -EAGAIN)
+				continue;
+			return ret;
+		}
+	} while (1);
+
+}
+
+static void dump_output_fb(struct device *dev, struct pipe_arg *pipes, char *dump_path,
+			   unsigned int count)
+{
+	drmModeConnector *connector;
+	unsigned int i, j;
+
+	for (j = 0; j < count; j++) {
+		struct pipe_arg *pipe = &pipes[j];
+
+		for (i = 0; i < pipe->num_cons; i++) {
+			connector = get_connector_by_id(dev, pipe->con_ids[i]);
+			if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+				bo_dump(pipe->out_bo, dump_path);
+		}
+	}
 }
 
 static void atomic_clear_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
@@ -1897,8 +2032,9 @@ static int parse_connector(struct pipe_a
 	}
 
 	if (*p == '@') {
-		strncpy(pipe->format_str, p + 1, 4);
-		pipe->format_str[4] = '\0';
+		len = sizeof(pipe->format_str) - 1;
+		strncpy(pipe->format_str, p + 1, len);
+		pipe->format_str[len] = '\0';
 	}
 
 	pipe->fourcc = util_format_fourcc(pipe->format_str);
@@ -1912,6 +2048,7 @@ static int parse_connector(struct pipe_a
 
 static int parse_plane(struct plane_arg *plane, const char *p)
 {
+	unsigned int len;
 	char *end;
 
 	plane->plane_id = strtoul(p, &end, 10);
@@ -1950,8 +2087,9 @@ static int parse_plane(struct plane_arg 
 	}
 
 	if (*end == '@') {
-		strncpy(plane->format_str, end + 1, 4);
-		plane->format_str[4] = '\0';
+		len = sizeof(plane->format_str) - 1;
+		strncpy(plane->format_str, end + 1, len);
+		plane->format_str[len] = '\0';
 	} else {
 		strcpy(plane->format_str, "XR24");
 	}
@@ -1990,7 +2128,7 @@ static void parse_fill_patterns(char *ar
 
 static void usage(char *name)
 {
-	fprintf(stderr, "usage: %s [-acDdefMPpsCvrw]\n", name);
+	fprintf(stderr, "usage: %s [-acDdefMoPpsCvrw]\n", name);
 
 	fprintf(stderr, "\n Query options:\n\n");
 	fprintf(stderr, "\t-c\tlist connectors\n");
@@ -1999,14 +2137,19 @@ static void usage(char *name)
 	fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n");
 
 	fprintf(stderr, "\n Test options:\n\n");
-	fprintf(stderr, "\t-P <plane_id>@<crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]\tset a plane\n");
-	fprintf(stderr, "\t-s <connector_id>[,<connector_id>][@<crtc_id>]:[#<mode index>]<mode>[-<vrefresh>][@<format>]\tset a mode\n");
+	fprintf(stderr, "\t-P <plane_id>@<crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]\tset a plane, see 'plane-topology'\n");
+	fprintf(stderr, "\t-s <connector_id>[,<connector_id>][@<crtc_id>]:mode[@<format>]\tset a mode, see 'mode-topology'\n");
+	fprintf(stderr, "\t\twhere mode can be specified as:\n");
+	fprintf(stderr, "\t\t<hdisp>x<vdisp>[-<vrefresh>]\n");
+	fprintf(stderr, "\t\t<hdisp>,<hss>,<hse>,<htot>,<vdisp>,<vss>,<vse>,<vtot>-<vrefresh>\n");
+	fprintf(stderr, "\t\t#<mode index>\n");
 	fprintf(stderr, "\t-C\ttest hw cursor\n");
 	fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
 	fprintf(stderr, "\t-r\tset the preferred mode for all connectors\n");
-	fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property\n");
+	fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property, see 'property'\n");
 	fprintf(stderr, "\t-a \tuse atomic API\n");
 	fprintf(stderr, "\t-F pattern1,pattern2\tspecify fill patterns\n");
+	fprintf(stderr, "\t-o <desired file path> \t Dump writeback output buffer to file\n");
 
 	fprintf(stderr, "\n Generic options:\n\n");
 	fprintf(stderr, "\t-d\tdrop master after mode set\n");
@@ -2014,10 +2157,29 @@ static void usage(char *name)
 	fprintf(stderr, "\t-D device\tuse the given device\n");
 
 	fprintf(stderr, "\n\tDefault is to dump all info.\n");
+
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Plane Topology is defined as:\n");
+	fprintf(stderr, "\tplane-topology\t::= plane-id '@' crtc-id ':' width 'x' height ( <plane-offsets> )? ;\n");
+	fprintf(stderr, "\tplane-offsets\t::= '+' x-offset '+' y-offset ( <plane-scale> )? ;\n");
+	fprintf(stderr, "\tplane-scale\t::= '*' scale ( <plane-format> )? ;\n");
+	fprintf(stderr, "\tplane-format\t::= '@' format ;\n");
+
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Mode Topology is defined as:\n");
+	fprintf(stderr, "\tmode-topology\t::= connector-id ( ',' connector-id )* ( '@' crtc-id )? ':' <mode-selection> ( '@' format )? ;\n");
+	fprintf(stderr, "\tmode-selection\t::=  <indexed-mode> | <named-mode> | <custom-mode> ;\n");
+	fprintf(stderr, "\tindexed-mode\t::=  '#' mode-index ;\n");
+	fprintf(stderr, "\tnamed-mode\t::=  width 'x' height ( '-' vrefresh )? ;\n");
+	fprintf(stderr, "\tcustom-mode\t::=  hdisplay ',' hsyncstart ',' hsyncend ',' htotal ',' vdisplay ',' vsyncstart ',' vsyncend ',' vtotal '-' vrefresh ;\n");
+
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Property is defined as:\n");
+	fprintf(stderr, "\tproperty\t::= object-id ':' property-name ':' value ;\n");
 	exit(0);
 }
 
-static char optstr[] = "acdD:efF:M:P:ps:Cvrw:";
+static char optstr[] = "acdD:efF:M:P:ps:Cvrw:o:";
 
 int main(int argc, char **argv)
 {
@@ -2040,6 +2202,7 @@ int main(int argc, char **argv)
 	struct property_arg *prop_args = NULL;
 	unsigned int args = 0;
 	int ret;
+	char *dump_path = NULL;
 
 	memset(&dev, 0, sizeof dev);
 
@@ -2078,6 +2241,9 @@ int main(int argc, char **argv)
 			/* Preserve the default behaviour of dumping all information. */
 			args--;
 			break;
+		case 'o':
+			dump_path = optarg;
+			break;
 		case 'P':
 			plane_args = realloc(plane_args,
 					     (plane_count + 1) * sizeof *plane_args);
@@ -2143,8 +2309,8 @@ int main(int argc, char **argv)
 	if (!args)
 		encoders = connectors = crtcs = planes = framebuffers = 1;
 
-	if (test_vsync && !count) {
-		fprintf(stderr, "page flipping requires at least one -s option.\n");
+	if (test_vsync && !count && !set_preferred) {
+		fprintf(stderr, "page flipping requires at least one -s or -r option.\n");
 		return -1;
 	}
 	if (set_preferred && count) {
@@ -2152,17 +2318,13 @@ int main(int argc, char **argv)
 		return -1;
 	}
 
-	if (set_preferred && plane_count) {
-		fprintf(stderr, "cannot use -r (preferred) when -P (plane) is set\n");
-		return -1;
-	}
-
 	dev.fd = util_open(device, module);
 	if (dev.fd < 0)
 		return -1;
 
 	if (use_atomic) {
 		ret = drmSetClientCap(dev.fd, DRM_CLIENT_CAP_ATOMIC, 1);
+		drmSetClientCap(dev.fd, DRM_CLIENT_CAP_WRITEBACK_CONNECTORS, 1);
 		if (ret) {
 			fprintf(stderr, "no atomic modesetting support: %s\n", strerror(errno));
 			drmClose(dev.fd);
@@ -2186,12 +2348,13 @@ int main(int argc, char **argv)
 	dump_resource(&dev, planes);
 	dump_resource(&dev, framebuffers);
 
+	if (dev.use_atomic)
+		dev.req = drmModeAtomicAlloc();
+
 	for (i = 0; i < prop_count; ++i)
 		set_property(&dev, &prop_args[i]);
 
 	if (dev.use_atomic) {
-		dev.req = drmModeAtomicAlloc();
-
 		if (set_preferred || (count && plane_count)) {
 			uint64_t cap = 0;
 
@@ -2202,7 +2365,16 @@ int main(int argc, char **argv)
 			}
 
 			if (set_preferred || count)
-				set_mode(&dev, pipe_args, count);
+				count = set_mode(&dev, &pipe_args, count);
+
+			if (dump_path) {
+				if (!pipe_has_writeback_connector(&dev, pipe_args, count)) {
+					fprintf(stderr, "No writeback connector found, can not dump.\n");
+					return 1;
+				}
+
+				writeback_config(&dev, pipe_args, count);
+			}
 
 			if (plane_count)
 				atomic_set_planes(&dev, plane_args, plane_count, false);
@@ -2213,6 +2385,18 @@ int main(int argc, char **argv)
 				return 1;
 			}
 
+			/*
+			 * Since only writeback connectors have an output fb, this should only be
+			 * called for writeback.
+			 */
+			if (dump_path) {
+				ret = poll_writeback_fence(dev.writeback_fence_fd, 1000);
+				if (ret)
+					fprintf(stderr, "Poll for writeback error: %d. Skipping Dump.\n",
+							ret);
+				dump_output_fb(&dev, pipe_args, dump_path, count);
+			}
+
 			if (test_vsync)
 				atomic_test_page_flip(&dev, pipe_args, plane_args, plane_count);
 
@@ -2230,17 +2414,22 @@ int main(int argc, char **argv)
 
 			if (count)
 				atomic_clear_mode(&dev, pipe_args, count);
+		}
 
-			ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
-			if (ret)
-				fprintf(stderr, "Atomic Commit failed\n");
+		ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+		if (ret)
+			fprintf(stderr, "Atomic Commit failed\n");
 
-			if (plane_count)
-				atomic_clear_FB(&dev, plane_args, plane_count);
-		}
+		if (count && plane_count)
+			atomic_clear_FB(&dev, plane_args, plane_count);
 
 		drmModeAtomicFree(dev.req);
 	} else {
+		if (dump_path) {
+			fprintf(stderr, "writeback / dump is only supported in atomic mode\n");
+			return 1;
+		}
+
 		if (set_preferred || count || plane_count) {
 			uint64_t cap = 0;
 
@@ -2251,7 +2440,7 @@ int main(int argc, char **argv)
 			}
 
 			if (set_preferred || count)
-				set_mode(&dev, pipe_args, count);
+				count = set_mode(&dev, &pipe_args, count);
 
 			if (plane_count)
 				set_planes(&dev, plane_args, plane_count);

Reply via email to