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-----------------------------*/
allocateBuffer(int width,int height,const char * format,int & bytes,int numBufs)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
getOffsets()137 uint32_t * MemoryManager::getOffsets()
138 {
139 LOG_FUNCTION_NAME;
140
141 LOG_FUNCTION_NAME_EXIT;
142
143 return NULL;
144 }
145
getFd()146 int MemoryManager::getFd()
147 {
148 LOG_FUNCTION_NAME;
149
150 LOG_FUNCTION_NAME_EXIT;
151
152 return -1;
153 }
154
freeBuffer(void * buf)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
setErrorHandler(ErrorNotifier * errorNotifier)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