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 LOG_FUNCTION_NAME_EXIT; 70 return NULL; 71 } 72 73 ///Initialize the array with zeros - this will help us while freeing the array in case of error 74 ///If a value of an array element is NULL, it means we didnt allocate it 75 memset(bufsArr, 0, sizeof(*bufsArr) * numArrayEntriesC); 76 77 //2D Allocations are not supported currently 78 if(bytes != 0) 79 { 80 struct ion_handle *handle; 81 int mmap_fd; 82 83 ///1D buffers 84 for (int i = 0; i < numBufs; i++) 85 { 86 int ret = ion_alloc(mIonFd, bytes, 0, 1 << ION_HEAP_TYPE_CARVEOUT, &handle); 87 if(ret < 0) 88 { 89 CAMHAL_LOGEB("ion_alloc resulted in error %d", ret); 90 goto error; 91 } 92 93 CAMHAL_LOGDB("Before mapping, handle = %x, nSize = %d", handle, bytes); 94 if ((ret = ion_map(mIonFd, handle, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, 0, 95 (unsigned char**)&bufsArr[i], &mmap_fd)) < 0) 96 { 97 CAMHAL_LOGEB("Userspace mapping of ION buffers returned error %d", ret); 98 ion_free(mIonFd, handle); 99 goto error; 100 } 101 102 mIonHandleMap.add(bufsArr[i], (unsigned int)handle); 103 mIonFdMap.add(bufsArr[i], (unsigned int) mmap_fd); 104 mIonBufLength.add(bufsArr[i], (unsigned int) bytes); 105 } 106 107 } 108 else // If bytes is not zero, then it is a 2-D tiler buffer request 109 { 110 } 111 112 LOG_FUNCTION_NAME_EXIT; 113 114 return (void*)bufsArr; 115 116 error: 117 LOGE("Freeing buffers already allocated after error occurred"); 118 freeBuffer(bufsArr); 119 120 if ( NULL != mErrorNotifier.get() ) 121 { 122 mErrorNotifier->errorNotify(-ENOMEM); 123 } 124 125 LOG_FUNCTION_NAME_EXIT; 126 return NULL; 127 } 128 129 //TODO: Get needed data to map tiler buffers 130 //Return dummy data for now 131 uint32_t * MemoryManager::getOffsets() 132 { 133 LOG_FUNCTION_NAME; 134 135 LOG_FUNCTION_NAME_EXIT; 136 137 return NULL; 138 } 139 140 int MemoryManager::getFd() 141 { 142 LOG_FUNCTION_NAME; 143 144 LOG_FUNCTION_NAME_EXIT; 145 146 return -1; 147 } 148 149 int MemoryManager::freeBuffer(void* buf) 150 { 151 status_t ret = NO_ERROR; 152 LOG_FUNCTION_NAME; 153 154 uint32_t *bufEntry = (uint32_t*)buf; 155 156 if(!bufEntry) 157 { 158 CAMHAL_LOGEA("NULL pointer passed to freebuffer"); 159 LOG_FUNCTION_NAME_EXIT; 160 return BAD_VALUE; 161 } 162 163 while(*bufEntry) 164 { 165 unsigned int ptr = (unsigned int) *bufEntry++; 166 if(mIonBufLength.valueFor(ptr)) 167 { 168 munmap((void *)ptr, mIonBufLength.valueFor(ptr)); 169 close(mIonFdMap.valueFor(ptr)); 170 ion_free(mIonFd, (ion_handle*)mIonHandleMap.valueFor(ptr)); 171 mIonHandleMap.removeItem(ptr); 172 mIonBufLength.removeItem(ptr); 173 mIonFdMap.removeItem(ptr); 174 } 175 else 176 { 177 CAMHAL_LOGEA("Not a valid Memory Manager buffer"); 178 } 179 } 180 181 ///@todo Check if this way of deleting array is correct, else use malloc/free 182 uint32_t * bufArr = (uint32_t*)buf; 183 delete [] bufArr; 184 185 if(mIonBufLength.size() == 0) 186 { 187 if(mIonFd) 188 { 189 ion_close(mIonFd); 190 mIonFd = 0; 191 } 192 } 193 LOG_FUNCTION_NAME_EXIT; 194 return ret; 195 } 196 197 status_t MemoryManager::setErrorHandler(ErrorNotifier *errorNotifier) 198 { 199 status_t ret = NO_ERROR; 200 201 LOG_FUNCTION_NAME; 202 203 if ( NULL == errorNotifier ) 204 { 205 CAMHAL_LOGEA("Invalid Error Notifier reference"); 206 ret = -EINVAL; 207 } 208 209 if ( NO_ERROR == ret ) 210 { 211 mErrorNotifier = errorNotifier; 212 } 213 214 LOG_FUNCTION_NAME_EXIT; 215 216 return ret; 217 } 218 219 }; 220 221 222 /*--------------------MemoryManager Class ENDS here-----------------------------*/ 223