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
25extern "C" {
26
27#include <ion.h>
28
29//#include <timm_osal_interfaces.h>
30//#include <timm_osal_trace.h>
31
32
33};
34
35namespace 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-----------------------------*/
46void* 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
115error:
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
137uint32_t * MemoryManager::getOffsets()
138{
139    LOG_FUNCTION_NAME;
140
141    LOG_FUNCTION_NAME_EXIT;
142
143    return NULL;
144}
145
146int MemoryManager::getFd()
147{
148    LOG_FUNCTION_NAME;
149
150    LOG_FUNCTION_NAME_EXIT;
151
152    return -1;
153}
154
155int 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
203status_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