1 /* 2 * Copyright (C) Texas Instruments - http://www.ti.com/ 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 19 #define LOG_TAG "CameraHAL" 20 21 22 #include "CameraHal.h" 23 #include "TICameraParameters.h" 24 25 extern "C" { 26 27 #include <ion.h> 28 29 //#include <timm_osal_interfaces.h> 30 //#include <timm_osal_trace.h> 31 32 33 }; 34 35 namespace android { 36 37 ///@todo Move these constants to a common header file, preferably in tiler.h 38 #define STRIDE_8BIT (4 * 1024) 39 #define STRIDE_16BIT (4 * 1024) 40 41 #define ALLOCATION_2D 2 42 43 ///Utility Macro Declarations 44 45 /*--------------------MemoryManager Class STARTS here-----------------------------*/ 46 void* MemoryManager::allocateBuffer(int width, int height, const char* format, int &bytes, int numBufs) 47 { 48 LOG_FUNCTION_NAME; 49 50 if(mIonFd < 0) 51 { 52 mIonFd = ion_open(); 53 if(mIonFd < 0) 54 { 55 CAMHAL_LOGEA("ion_open failed!!!"); 56 return NULL; 57 } 58 } 59 60 ///We allocate numBufs+1 because the last entry will be marked NULL to indicate end of array, which is used when freeing 61 ///the buffers 62 const uint numArrayEntriesC = (uint)(numBufs+1); 63 64 ///Allocate a buffer array 65 uint32_t *bufsArr = new uint32_t [numArrayEntriesC]; 66 if(!bufsArr) 67 { 68 CAMHAL_LOGEB("Allocation failed when creating buffers array of %d uint32_t elements", numArrayEntriesC); 69 goto error; 70 } 71 72 ///Initialize the array with zeros - this will help us while freeing the array in case of error 73 ///If a value of an array element is NULL, it means we didnt allocate it 74 memset(bufsArr, 0, sizeof(*bufsArr) * numArrayEntriesC); 75 76 //2D Allocations are not supported currently 77 if(bytes != 0) 78 { 79 struct ion_handle *handle; 80 int mmap_fd; 81 82 ///1D buffers 83 for (int i = 0; i < numBufs; i++) 84 { 85 int ret = ion_alloc(mIonFd, bytes, 0, 1 << ION_HEAP_TYPE_CARVEOUT, &handle); 86 if(ret < 0) 87 { 88 CAMHAL_LOGEB("ion_alloc resulted in error %d", ret); 89 goto error; 90 } 91 92 CAMHAL_LOGDB("Before mapping, handle = %x, nSize = %d", handle, bytes); 93 if ((ret = ion_map(mIonFd, handle, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, 0, 94 (unsigned char**)&bufsArr[i], &mmap_fd)) < 0) 95 { 96 CAMHAL_LOGEB("Userspace mapping of ION buffers returned error %d", ret); 97 ion_free(mIonFd, handle); 98 goto error; 99 } 100 101 mIonHandleMap.add(bufsArr[i], (unsigned int)handle); 102 mIonFdMap.add(bufsArr[i], (unsigned int) mmap_fd); 103 mIonBufLength.add(bufsArr[i], (unsigned int) bytes); 104 } 105 106 } 107 else // If bytes is not zero, then it is a 2-D tiler buffer request 108 { 109 } 110 111 LOG_FUNCTION_NAME_EXIT; 112 113 return (void*)bufsArr; 114 115 error: 116 ALOGE("Freeing buffers already allocated after error occurred"); 117 if(bufsArr) 118 freeBuffer(bufsArr); 119 120 if ( NULL != mErrorNotifier.get() ) 121 { 122 mErrorNotifier->errorNotify(-ENOMEM); 123 } 124 125 if (mIonFd >= 0) 126 { 127 ion_close(mIonFd); 128 mIonFd = -1; 129 } 130 131 LOG_FUNCTION_NAME_EXIT; 132 return NULL; 133 } 134 135 //TODO: Get needed data to map tiler buffers 136 //Return dummy data for now 137 uint32_t * MemoryManager::getOffsets() 138 { 139 LOG_FUNCTION_NAME; 140 141 LOG_FUNCTION_NAME_EXIT; 142 143 return NULL; 144 } 145 146 int MemoryManager::getFd() 147 { 148 LOG_FUNCTION_NAME; 149 150 LOG_FUNCTION_NAME_EXIT; 151 152 return -1; 153 } 154 155 int MemoryManager::freeBuffer(void* buf) 156 { 157 status_t ret = NO_ERROR; 158 LOG_FUNCTION_NAME; 159 160 uint32_t *bufEntry = (uint32_t*)buf; 161 162 if(!bufEntry) 163 { 164 CAMHAL_LOGEA("NULL pointer passed to freebuffer"); 165 LOG_FUNCTION_NAME_EXIT; 166 return BAD_VALUE; 167 } 168 169 while(*bufEntry) 170 { 171 unsigned int ptr = (unsigned int) *bufEntry++; 172 if(mIonBufLength.valueFor(ptr)) 173 { 174 munmap((void *)ptr, mIonBufLength.valueFor(ptr)); 175 close(mIonFdMap.valueFor(ptr)); 176 ion_free(mIonFd, (ion_handle*)mIonHandleMap.valueFor(ptr)); 177 mIonHandleMap.removeItem(ptr); 178 mIonBufLength.removeItem(ptr); 179 mIonFdMap.removeItem(ptr); 180 } 181 else 182 { 183 CAMHAL_LOGEA("Not a valid Memory Manager buffer"); 184 } 185 } 186 187 ///@todo Check if this way of deleting array is correct, else use malloc/free 188 uint32_t * bufArr = (uint32_t*)buf; 189 delete [] bufArr; 190 191 if(mIonBufLength.size() == 0) 192 { 193 if(mIonFd >= 0) 194 { 195 ion_close(mIonFd); 196 mIonFd = -1; 197 } 198 } 199 LOG_FUNCTION_NAME_EXIT; 200 return ret; 201 } 202 203 status_t MemoryManager::setErrorHandler(ErrorNotifier *errorNotifier) 204 { 205 status_t ret = NO_ERROR; 206 207 LOG_FUNCTION_NAME; 208 209 if ( NULL == errorNotifier ) 210 { 211 CAMHAL_LOGEA("Invalid Error Notifier reference"); 212 ret = -EINVAL; 213 } 214 215 if ( NO_ERROR == ret ) 216 { 217 mErrorNotifier = errorNotifier; 218 } 219 220 LOG_FUNCTION_NAME_EXIT; 221 222 return ret; 223 } 224 225 }; 226 227 228 /*--------------------MemoryManager Class ENDS here-----------------------------*/ 229