1 /* Copyright (c) 2013-2014, 2016, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30 // System dependencies 31 #include <errno.h> 32 #include <fcntl.h> 33 #include <stdio.h> 34 #include <string.h> 35 #include <linux/msm_ion.h> 36 #define MMAN_H <SYSTEM_HEADER_PREFIX/mman.h> 37 #include MMAN_H 38 39 // JPEG dependencies 40 #include "mm_jpeg_ionbuf.h" 41 42 /** buffer_allocate: 43 * 44 * Arguments: 45 * @p_buffer: ION buffer 46 * 47 * Return: 48 * buffer address 49 * 50 * Description: 51 * allocates ION buffer 52 * 53 **/ 54 void *buffer_allocate(buffer_t *p_buffer, int cached) 55 { 56 void *l_buffer = NULL; 57 58 int lrc = 0; 59 struct ion_handle_data lhandle_data; 60 61 p_buffer->alloc.len = p_buffer->size; 62 p_buffer->alloc.align = 4096; 63 p_buffer->alloc.flags = (cached) ? ION_FLAG_CACHED : 0; 64 p_buffer->alloc.heap_id_mask = 0x1 << ION_IOMMU_HEAP_ID; 65 66 p_buffer->ion_fd = open("/dev/ion", O_RDONLY); 67 if(p_buffer->ion_fd < 0) { 68 LOGE("Ion open failed"); 69 goto ION_ALLOC_FAILED; 70 } 71 72 /* Make it page size aligned */ 73 p_buffer->alloc.len = (p_buffer->alloc.len + 4095U) & (~4095U); 74 lrc = ioctl(p_buffer->ion_fd, ION_IOC_ALLOC, &p_buffer->alloc); 75 if (lrc < 0) { 76 LOGE("ION allocation failed len %zu", 77 p_buffer->alloc.len); 78 goto ION_ALLOC_FAILED; 79 } 80 81 p_buffer->ion_info_fd.handle = p_buffer->alloc.handle; 82 lrc = ioctl(p_buffer->ion_fd, ION_IOC_SHARE, 83 &p_buffer->ion_info_fd); 84 if (lrc < 0) { 85 LOGE("ION map failed %s", strerror(errno)); 86 goto ION_MAP_FAILED; 87 } 88 89 p_buffer->p_pmem_fd = p_buffer->ion_info_fd.fd; 90 91 l_buffer = mmap(NULL, p_buffer->alloc.len, PROT_READ | PROT_WRITE, 92 MAP_SHARED,p_buffer->p_pmem_fd, 0); 93 94 if (l_buffer == MAP_FAILED) { 95 LOGE("ION_MMAP_FAILED: %s (%d)", 96 strerror(errno), errno); 97 goto ION_MAP_FAILED; 98 } 99 100 return l_buffer; 101 102 ION_MAP_FAILED: 103 lhandle_data.handle = p_buffer->ion_info_fd.handle; 104 ioctl(p_buffer->ion_fd, ION_IOC_FREE, &lhandle_data); 105 return NULL; 106 ION_ALLOC_FAILED: 107 return NULL; 108 109 } 110 111 /** buffer_deallocate: 112 * 113 * Arguments: 114 * @p_buffer: ION buffer 115 * 116 * Return: 117 * buffer address 118 * 119 * Description: 120 * deallocates ION buffer 121 * 122 **/ 123 int buffer_deallocate(buffer_t *p_buffer) 124 { 125 int lrc = 0; 126 size_t lsize = (p_buffer->size + 4095U) & (~4095U); 127 128 struct ion_handle_data lhandle_data; 129 lrc = munmap(p_buffer->addr, lsize); 130 131 close(p_buffer->ion_info_fd.fd); 132 133 lhandle_data.handle = p_buffer->ion_info_fd.handle; 134 ioctl(p_buffer->ion_fd, ION_IOC_FREE, &lhandle_data); 135 136 close(p_buffer->ion_fd); 137 return lrc; 138 } 139 140 /** buffer_invalidate: 141 * 142 * Arguments: 143 * @p_buffer: ION buffer 144 * 145 * Return: 146 * error val 147 * 148 * Description: 149 * Invalidates the cached buffer 150 * 151 **/ 152 int buffer_invalidate(buffer_t *p_buffer) 153 { 154 int lrc = 0; 155 struct ion_flush_data cache_inv_data; 156 struct ion_custom_data custom_data; 157 158 memset(&cache_inv_data, 0, sizeof(cache_inv_data)); 159 memset(&custom_data, 0, sizeof(custom_data)); 160 cache_inv_data.vaddr = p_buffer->addr; 161 cache_inv_data.fd = p_buffer->ion_info_fd.fd; 162 cache_inv_data.handle = p_buffer->ion_info_fd.handle; 163 cache_inv_data.length = (unsigned int)p_buffer->size; 164 custom_data.cmd = (unsigned int)ION_IOC_INV_CACHES; 165 custom_data.arg = (unsigned long)&cache_inv_data; 166 167 lrc = ioctl(p_buffer->ion_fd, ION_IOC_CUSTOM, &custom_data); 168 if (lrc < 0) 169 LOGW("Cache Invalidate failed: %s\n", strerror(errno)); 170 171 return lrc; 172 } 173 174 /** buffer_clean: 175 * 176 * Arguments: 177 * @p_buffer: ION buffer 178 * 179 * Return: 180 * error val 181 * 182 * Description: 183 * Clean the cached buffer 184 * 185 **/ 186 int buffer_clean(buffer_t *p_buffer) 187 { 188 int lrc = 0; 189 struct ion_flush_data cache_clean_data; 190 struct ion_custom_data custom_data; 191 192 memset(&cache_clean_data, 0, sizeof(cache_clean_data)); 193 memset(&custom_data, 0, sizeof(custom_data)); 194 cache_clean_data.vaddr = p_buffer->addr; 195 cache_clean_data.fd = p_buffer->ion_info_fd.fd; 196 cache_clean_data.handle = p_buffer->ion_info_fd.handle; 197 cache_clean_data.length = (unsigned int)p_buffer->size; 198 custom_data.cmd = (unsigned int)ION_IOC_CLEAN_CACHES; 199 custom_data.arg = (unsigned long)&cache_clean_data; 200 201 lrc = ioctl(p_buffer->ion_fd, ION_IOC_CUSTOM, &custom_data); 202 if (lrc < 0) 203 LOGW("Cache clean failed: %s\n", strerror(errno)); 204 205 return lrc; 206 } 207