Home | History | Annotate | Download | only in camera
      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