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 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
getOffsets()131 uint32_t * MemoryManager::getOffsets()
132 {
133 LOG_FUNCTION_NAME;
134
135 LOG_FUNCTION_NAME_EXIT;
136
137 return NULL;
138 }
139
getFd()140 int MemoryManager::getFd()
141 {
142 LOG_FUNCTION_NAME;
143
144 LOG_FUNCTION_NAME_EXIT;
145
146 return -1;
147 }
148
freeBuffer(void * buf)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
setErrorHandler(ErrorNotifier * errorNotifier)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