^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) Rockchip Electronics Co.Ltd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Felix Zeng <felix.zeng@rock-chips.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #ifndef __LINUX_RKNPU_GEM_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #define __LINUX_RKNPU_GEM_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mm_types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/version.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <drm/drm_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <drm/drm_vma_manager.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <drm/drm_gem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <drm/drm_mode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #if KERNEL_VERSION(4, 14, 0) > LINUX_VERSION_CODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <drm/drm_mem_util.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "rknpu_mm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define to_rknpu_obj(x) container_of(x, struct rknpu_gem_object, base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * rknpu drm buffer structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * @base: a gem object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * - a new handle to this gem object would be created
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * by drm_gem_handle_create().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * @flags: indicate memory type to allocated buffer and cache attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * @size: size requested from user, in bytes and this size is aligned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * in page unit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * @cookie: cookie returned by dma_alloc_attrs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * @kv_addr: kernel virtual address to allocated memory region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * @dma_addr: bus address(accessed by dma) to allocated memory region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * - this address could be physical address without IOMMU and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * device address with IOMMU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * @pages: Array of backing pages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * @sgt: Imported sg_table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * P.S. this object would be transferred to user as kms_bo.handle so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * user can access the buffer through kms_bo.handle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct rknpu_gem_object {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct drm_gem_object base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned long sram_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct rknpu_mm_obj *sram_obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) dma_addr_t iova_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned long iova_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) void *cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) void __iomem *kv_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) dma_addr_t dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned long dma_attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned long num_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct page **pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct sg_table *sgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct drm_mm_node mm_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* create a new buffer with gem object */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct rknpu_gem_object *rknpu_gem_object_create(struct drm_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned long size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned long sram_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* destroy a buffer with gem object */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) void rknpu_gem_object_destroy(struct rknpu_gem_object *rknpu_obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* request gem object creation and buffer allocation as the size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int rknpu_gem_create_ioctl(struct drm_device *dev, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct drm_file *file_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* get fake-offset of gem object that can be used with mmap. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int rknpu_gem_map_ioctl(struct drm_device *dev, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct drm_file *file_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int rknpu_gem_destroy_ioctl(struct drm_device *dev, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct drm_file *file_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * get rknpu drm object,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * gem object reference count would be increased.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static inline void rknpu_gem_object_get(struct drm_gem_object *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #if KERNEL_VERSION(4, 13, 0) < LINUX_VERSION_CODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) drm_gem_object_get(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) drm_gem_object_reference(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * put rknpu drm object acquired from rknpu_gem_object_find() or rknpu_gem_object_get(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * gem object reference count would be decreased.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static inline void rknpu_gem_object_put(struct drm_gem_object *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) drm_gem_object_put(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #elif KERNEL_VERSION(4, 13, 0) < LINUX_VERSION_CODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) drm_gem_object_put_unlocked(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) drm_gem_object_unreference_unlocked(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * get rknpu drm object from gem handle, this function could be used for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * other drivers such as 2d/3d acceleration drivers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * with this function call, gem object reference count would be increased.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static inline struct rknpu_gem_object *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) rknpu_gem_object_find(struct drm_file *filp, unsigned int handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct drm_gem_object *obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) obj = drm_gem_object_lookup(filp, handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (!obj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) // DRM_ERROR("failed to lookup gem object.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) rknpu_gem_object_put(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return to_rknpu_obj(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* get buffer information to memory region allocated by gem. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int rknpu_gem_get_ioctl(struct drm_device *dev, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct drm_file *file_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* free gem object. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) void rknpu_gem_free_object(struct drm_gem_object *obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* create memory region for drm framebuffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int rknpu_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct drm_mode_create_dumb *args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #if KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* map memory region for drm framebuffer to user space. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int rknpu_gem_dumb_map_offset(struct drm_file *file_priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct drm_device *dev, uint32_t handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) uint64_t *offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* page fault handler and mmap fault address(virtual) to physical memory. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) vm_fault_t rknpu_gem_fault(struct vm_fault *vmf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #elif KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int rknpu_gem_fault(struct vm_fault *vmf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) int rknpu_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* set vm_flags and we can change the vm attribute to other one at here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int rknpu_gem_mmap(struct file *filp, struct vm_area_struct *vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* low-level interface prime helpers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #if KERNEL_VERSION(4, 13, 0) <= LINUX_VERSION_CODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct drm_gem_object *rknpu_gem_prime_import(struct drm_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct dma_buf *dma_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct sg_table *rknpu_gem_prime_get_sg_table(struct drm_gem_object *obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct drm_gem_object *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) rknpu_gem_prime_import_sg_table(struct drm_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct dma_buf_attachment *attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct sg_table *sgt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) void *rknpu_gem_prime_vmap(struct drm_gem_object *obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) void rknpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int rknpu_gem_prime_mmap(struct drm_gem_object *obj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct vm_area_struct *vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int rknpu_gem_sync_ioctl(struct drm_device *dev, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct drm_file *file_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static inline void *rknpu_gem_alloc_page(size_t nr_pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #if KERNEL_VERSION(4, 13, 0) <= LINUX_VERSION_CODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return kvmalloc_array(nr_pages, sizeof(struct page *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) GFP_KERNEL | __GFP_ZERO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return drm_calloc_large(nr_pages, sizeof(struct page *));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static inline void rknpu_gem_free_page(void *pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #if KERNEL_VERSION(4, 13, 0) <= LINUX_VERSION_CODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) kvfree(pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) drm_free_large(pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #endif