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         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