diff --git a/android/common14-5.15_abi_gki_aarch64_amlogic b/android/common14-5.15_abi_gki_aarch64_amlogic index 5e6ce9fb8..2e0506d37 100644 --- a/android/common14-5.15_abi_gki_aarch64_amlogic +++ b/android/common14-5.15_abi_gki_aarch64_amlogic @@ -1,3 +1,4 @@ spi_finalize_current_message strim bpf_trace_run8 + dma_fence_get_stub diff --git a/drivers/drm/meson_drv.c b/drivers/drm/meson_drv.c index cc9bd8a2d..14d24b436 100644 --- a/drivers/drm/meson_drv.c +++ b/drivers/drm/meson_drv.c @@ -40,7 +40,7 @@ #include "meson_sysfs.h" #include "meson_writeback.h" #include "meson_logo.h" - +#include "meson_plane.h" #include #include #include @@ -90,6 +90,10 @@ static const struct drm_ioctl_desc meson_ioctls[] = { #endif DRM_IOCTL_DEF_DRV(MESON_ASYNC_ATOMIC, meson_async_atomic_ioctl, DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW), + #if IS_ENABLED(CONFIG_SYNC_FILE) + DRM_IOCTL_DEF_DRV(MESON_DMABUF_EXPORT_SYNC_FILE, am_meson_dmabuf_export_sync_file_ioctl, + DRM_MASTER), + #endif }; DEFINE_DRM_GEM_FOPS(meson_drm_fops); diff --git a/drivers/drm/meson_plane.c b/drivers/drm/meson_plane.c index 3b2811a7d..d6affb9ea 100644 --- a/drivers/drm/meson_plane.c +++ b/drivers/drm/meson_plane.c @@ -4,9 +4,15 @@ */ #include +#include +#include +#include +#include +#include #ifdef CONFIG_AMLOGIC_MEDIA_FB #include #endif + #include "meson_plane.h" #include "meson_crtc.h" #include "meson_vpu.h" @@ -125,6 +131,67 @@ static const u32 video_supported_drm_formats[] = { DRM_FORMAT_VUY888, }; +#if IS_ENABLED(CONFIG_SYNC_FILE) +int am_meson_dmabuf_export_sync_file_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_meson_dma_buf_export_sync_file *arg = data; + struct dma_fence *fence = NULL; + struct dma_buf *dmabuf = NULL; + struct sync_file *sync_file; + int fd, ret; + + DRM_DEBUG("dmabuf-%px fence-%px", dmabuf, fence); + if (arg->flags & ~DMA_BUF_SYNC_RW) + return -EINVAL; + + if ((arg->flags & DMA_BUF_SYNC_RW) == 0) + return -EINVAL; + + fd = get_unused_fd_flags(O_CLOEXEC); + if (fd < 0) + return fd; + if (arg->dmabuf_fd <= 0) + return -EINVAL; + + dmabuf = dma_buf_get(arg->dmabuf_fd); + if (IS_ERR_OR_NULL(dmabuf)) + return -EINVAL; + + if (arg->flags & DMA_BUF_SYNC_WRITE) { + //fence = dma_resv_get_singleton_unlocked(dmabuf->resv); + //if (IS_ERR(fence)) { + // ret = PTR_ERR(fence); + // goto err_put_fd; + //} + } else if (arg->flags & DMA_BUF_SYNC_READ) { + fence = dma_resv_get_excl_unlocked(dmabuf->resv); + } + if (!fence) + fence = dma_fence_get_stub(); + + sync_file = sync_file_create(fence); + + dma_fence_put(fence); + dma_buf_put(dmabuf); + + if (!sync_file) { + ret = -ENOMEM; + goto err_put_fd; + } + + fd_install(fd, sync_file->file); + + arg->fd = fd; + DRM_DEBUG("dmabuf-%px fence-%px fd-%d", dmabuf, fence, fd); + return 0; + +err_put_fd: + put_unused_fd(fd); + return ret; +} +#endif + static void meson_plane_position_calc(struct meson_vpu_osd_layer_info *plane_info, struct drm_plane_state *state, diff --git a/drivers/drm/meson_plane.h b/drivers/drm/meson_plane.h index 524486775..f4e33abab 100644 --- a/drivers/drm/meson_plane.h +++ b/drivers/drm/meson_plane.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -109,4 +110,8 @@ meson_create_scaling_filter_prop(struct drm_device *dev, void meson_video_set_vfmmode(struct device_node *of_node, struct meson_drm *priv); +#if IS_ENABLED(CONFIG_SYNC_FILE) +int am_meson_dmabuf_export_sync_file_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +#endif #endif diff --git a/include/uapi/amlogic/drm/meson_drm.h b/include/uapi/amlogic/drm/meson_drm.h index d8fa13215..0c60213d6 100644 --- a/include/uapi/amlogic/drm/meson_drm.h +++ b/include/uapi/amlogic/drm/meson_drm.h @@ -36,9 +36,46 @@ struct drm_meson_gem_create { __u32 handle; }; +/** + * struct drm_meson_dma_buf_export_sync_file - Get a sync_file from a dma-buf + * + * Userspace can perform a DMA_BUF_IOCTL_EXPORT_SYNC_FILE to retrieve the + * current set of fences on a dma-buf file descriptor as a sync_file. CPU + * waits via poll() or other driver-specific mechanisms typically wait on + * whatever fences are on the dma-buf at the time the wait begins. This + * is similar except that it takes a snapshot of the current fences on the + * dma-buf for waiting later instead of waiting immediately. This is + * useful for modern graphics APIs such as Vulkan which assume an explicit + * synchronization model but still need to inter-operate with dma-buf. + */ +struct drm_meson_dma_buf_export_sync_file { + /** + * @flags: Read/write flags + * + * Must be DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE, or both. + * + * If DMA_BUF_SYNC_READ is set and DMA_BUF_SYNC_WRITE is not set, + * the returned sync file waits on any writers of the dma-buf to + * complete. Waiting on the returned sync file is equivalent to + * poll() with POLLIN. + * + * If DMA_BUF_SYNC_WRITE is set, the returned sync file waits on + * any users of the dma-buf (read or write) to complete. Waiting + * on the returned sync file is equivalent to poll() with POLLOUT. + * If both DMA_BUF_SYNC_WRITE and DMA_BUF_SYNC_READ are set, this + * is equivalent to just DMA_BUF_SYNC_WRITE. + */ + __u32 flags; + __u32 dmabuf_fd; + /** @fd: Returned sync file descriptor */ + __s32 fd; +}; + /*Memory related.*/ #define DRM_IOCTL_MESON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ 0x00, struct drm_meson_gem_create) +#define DRM_IOCTL_MESON_DMABUF_EXPORT_SYNC_FILE DRM_IOWR(DRM_COMMAND_BASE + \ + 0x02, struct drm_meson_dma_buf_export_sync_file) /*KMS related.*/ #define DRM_IOCTL_MESON_ASYNC_ATOMIC DRM_IOWR(DRM_COMMAND_BASE + \