You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							145 lines
						
					
					
						
							3.7 KiB
						
					
					
				
			
		
		
	
	
							145 lines
						
					
					
						
							3.7 KiB
						
					
					
				| #include <stdlib.h>
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <assert.h>
 | |
| #include <sys/mman.h>
 | |
| #include <sys/ioctl.h>
 | |
| #include <sys/types.h>
 | |
| #include <sys/stat.h>
 | |
| #include <fcntl.h>
 | |
| 
 | |
| #include <linux/ion.h>
 | |
| #include <CL/cl_ext.h>
 | |
| 
 | |
| #include <msm_ion.h>
 | |
| 
 | |
| #include "visionbuf.h"
 | |
| 
 | |
| 
 | |
| // just hard-code these for convenience
 | |
| // size_t device_page_size = 0;
 | |
| // clGetDeviceInfo(device_id, CL_DEVICE_PAGE_SIZE_QCOM,
 | |
| //                 sizeof(device_page_size), &device_page_size,
 | |
| //                 NULL);
 | |
| 
 | |
| // size_t padding_cl = 0;
 | |
| // clGetDeviceInfo(device_id, CL_DEVICE_EXT_MEM_PADDING_IN_BYTES_QCOM,
 | |
| //                 sizeof(padding_cl), &padding_cl,
 | |
| //                 NULL);
 | |
| #define DEVICE_PAGE_SIZE_CL 4096
 | |
| #define PADDING_CL 0
 | |
| 
 | |
| static int ion_fd = -1;
 | |
| static void ion_init() {
 | |
|   if (ion_fd == -1) {
 | |
|     ion_fd = open("/dev/ion", O_RDWR | O_NONBLOCK);
 | |
|   }
 | |
| }
 | |
| 
 | |
| VisionBuf visionbuf_allocate(size_t len) {
 | |
|   int err;
 | |
| 
 | |
|   ion_init();
 | |
| 
 | |
|   struct ion_allocation_data ion_alloc = {0};
 | |
|   ion_alloc.len = len + PADDING_CL;
 | |
|   ion_alloc.align = 4096;
 | |
|   ion_alloc.heap_id_mask = 1 << ION_IOMMU_HEAP_ID;
 | |
|   ion_alloc.flags = ION_FLAG_CACHED;
 | |
| 
 | |
|   err = ioctl(ion_fd, ION_IOC_ALLOC, &ion_alloc);
 | |
|   assert(err == 0);
 | |
| 
 | |
|   struct ion_fd_data ion_fd_data = {0};
 | |
|   ion_fd_data.handle = ion_alloc.handle;
 | |
|   err = ioctl(ion_fd, ION_IOC_SHARE, &ion_fd_data);
 | |
|   assert(err == 0);
 | |
| 
 | |
|   void *addr = mmap(NULL, ion_alloc.len,
 | |
|                     PROT_READ | PROT_WRITE,
 | |
|                     MAP_SHARED, ion_fd_data.fd, 0);
 | |
|   assert(addr != MAP_FAILED);
 | |
| 
 | |
|   memset(addr, 0, ion_alloc.len);
 | |
| 
 | |
|   return (VisionBuf){
 | |
|     .len = len,
 | |
|     .addr = addr,
 | |
|     .handle = ion_alloc.handle,
 | |
|     .fd = ion_fd_data.fd,
 | |
|   };
 | |
| }
 | |
| 
 | |
| VisionBuf visionbuf_allocate_cl(size_t len, cl_device_id device_id, cl_context ctx, cl_mem *out_mem) {
 | |
|   VisionBuf r = visionbuf_allocate(len);
 | |
|   *out_mem = visionbuf_to_cl(&r, device_id, ctx);
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| cl_mem visionbuf_to_cl(const VisionBuf* buf, cl_device_id device_id, cl_context ctx) {
 | |
|   int err = 0;
 | |
| 
 | |
|   assert(((uintptr_t)buf->addr % DEVICE_PAGE_SIZE_CL) == 0);
 | |
| 
 | |
|   cl_mem_ion_host_ptr ion_cl = {0};
 | |
|   ion_cl.ext_host_ptr.allocation_type = CL_MEM_ION_HOST_PTR_QCOM;
 | |
|   ion_cl.ext_host_ptr.host_cache_policy = CL_MEM_HOST_UNCACHED_QCOM;
 | |
|   ion_cl.ion_filedesc = buf->fd;
 | |
|   ion_cl.ion_hostptr = buf->addr;
 | |
| 
 | |
|   cl_mem mem = clCreateBuffer(ctx,
 | |
|                               CL_MEM_USE_HOST_PTR | CL_MEM_EXT_HOST_PTR_QCOM,
 | |
|                               buf->len, &ion_cl, &err);
 | |
|   assert(err == 0);
 | |
| 
 | |
|   return mem;
 | |
| }
 | |
| 
 | |
| void visionbuf_sync(const VisionBuf* buf, int dir) {
 | |
|   int err;
 | |
| 
 | |
|   struct ion_fd_data fd_data = {0};
 | |
|   fd_data.fd = buf->fd;
 | |
|   err = ioctl(ion_fd, ION_IOC_IMPORT, &fd_data);
 | |
|   assert(err == 0);
 | |
| 
 | |
|   struct ion_flush_data flush_data = {0};
 | |
|   flush_data.handle = fd_data.handle;
 | |
|   flush_data.vaddr = buf->addr;
 | |
|   flush_data.offset = 0;
 | |
|   flush_data.length = buf->len;
 | |
| 
 | |
|   // ION_IOC_INV_CACHES ~= DMA_FROM_DEVICE
 | |
|   // ION_IOC_CLEAN_CACHES ~= DMA_TO_DEVICE
 | |
|   // ION_IOC_CLEAN_INV_CACHES ~= DMA_BIDIRECTIONAL
 | |
| 
 | |
|   struct ion_custom_data custom_data = {0};
 | |
| 
 | |
|   switch (dir) {
 | |
|   case VISIONBUF_SYNC_FROM_DEVICE:
 | |
|     custom_data.cmd = ION_IOC_INV_CACHES;
 | |
|     break;
 | |
|   case VISIONBUF_SYNC_TO_DEVICE:
 | |
|     custom_data.cmd = ION_IOC_CLEAN_CACHES;
 | |
|     break;
 | |
|   default:
 | |
|     assert(0);
 | |
|   }
 | |
| 
 | |
|   custom_data.arg = (unsigned long)&flush_data;
 | |
|   err = ioctl(ion_fd, ION_IOC_CUSTOM, &custom_data);
 | |
|   assert(err == 0);
 | |
| 
 | |
|   struct ion_handle_data handle_data = {0};
 | |
|   handle_data.handle = fd_data.handle;
 | |
|   err = ioctl(ion_fd, ION_IOC_FREE, &handle_data);
 | |
|   assert(err == 0);
 | |
| }
 | |
| 
 | |
| void visionbuf_free(const VisionBuf* buf) {
 | |
|   struct ion_handle_data handle_data = {
 | |
|     .handle = buf->handle,
 | |
|   };
 | |
|   int ret = ioctl(ion_fd, ION_IOC_FREE, &handle_data);
 | |
|   assert(ret == 0);
 | |
| }
 | |
| 
 |