1/*
2** Copyright (c) 2011-2012 The Linux Foundation. All rights reserved.
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/*#error uncomment this for compiler test!*/
18
19//#define ALOG_NDEBUG 0
20#define ALOG_NIDEBUG 0
21#define LOG_TAG "QCameraHWI_Mem"
22#include <utils/Log.h>
23
24#include <utils/Errors.h>
25#include <utils/threads.h>
26//#include <binder/MemoryHeapPmem.h>
27#include <utils/String16.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <cutils/properties.h>
33#include <math.h>
34#include <linux/ioctl.h>
35#include "QCameraParameters.h"
36#include <media/mediarecorder.h>
37#include <gralloc_priv.h>
38
39#include "QCameraHWI_Mem.h"
40
41#define CAMERA_HAL_UNUSED(expr) do { (void)(expr); } while (0)
42
43/* QCameraHardwareInterface class implementation goes here*/
44/* following code implement the contol logic of this class*/
45
46namespace android {
47
48
49static bool register_buf(int size,
50                         int frame_size,
51                         int cbcr_offset,
52                         int yoffset,
53                         int pmempreviewfd,
54                         uint32_t offset,
55                         uint8_t *buf,
56                         int pmem_type,
57                         bool vfe_can_write,
58                         bool register_buffer = true);
59
60#if 0
61MMCameraDL::MMCameraDL(){
62    ALOGV("MMCameraDL: E");
63    libmmcamera = NULL;
64#if DLOPEN_LIBMMCAMERA
65    libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
66#endif
67    ALOGV("Open MM camera DL libeomcamera loaded at %p ", libmmcamera);
68    ALOGV("MMCameraDL: X");
69}
70
71void * MMCameraDL::pointer(){
72    return libmmcamera;
73}
74
75MMCameraDL::~MMCameraDL(){
76    ALOGV("~MMCameraDL: E");
77    LINK_mm_camera_destroy();
78    if (libmmcamera != NULL) {
79        ::dlclose(libmmcamera);
80        ALOGV("closed MM Camera DL ");
81    }
82    libmmcamera = NULL;
83    ALOGV("~MMCameraDL: X");
84}
85
86
87wp<MMCameraDL> MMCameraDL::instance;
88Mutex MMCameraDL::singletonLock;
89
90
91sp<MMCameraDL> MMCameraDL::getInstance(){
92    Mutex::Autolock instanceLock(singletonLock);
93    sp<MMCameraDL> mmCamera = instance.promote();
94    if(mmCamera == NULL){
95        mmCamera = new MMCameraDL();
96        instance = mmCamera;
97    }
98    return mmCamera;
99}
100#endif
101
102MemPool::MemPool(int buffer_size, int num_buffers,
103                                         int frame_size,
104                                         const char *name) :
105    mBufferSize(buffer_size),
106    mNumBuffers(num_buffers),
107    mFrameSize(frame_size),
108    mBuffers(NULL), mName(name)
109{
110    int page_size_minus_1 = getpagesize() - 1;
111    mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
112}
113
114void MemPool::completeInitialization()
115{
116    // If we do not know how big the frame will be, we wait to allocate
117    // the buffers describing the individual frames until we do know their
118    // size.
119
120    if (mFrameSize > 0) {
121        mBuffers = new sp<MemoryBase>[mNumBuffers];
122        for (int i = 0; i < mNumBuffers; i++) {
123            mBuffers[i] = new
124                MemoryBase(mHeap,
125                           i * mAlignedBufferSize,
126                           mFrameSize);
127        }
128    }
129}
130
131AshmemPool::AshmemPool(int buffer_size, int num_buffers,
132                                               int frame_size,
133                                               const char *name) :
134    MemPool(buffer_size,
135                                    num_buffers,
136                                    frame_size,
137                                    name)
138{
139    ALOGV("constructing MemPool %s backed by ashmem: "
140         "%d frames @ %d uint8_ts, "
141         "buffer size %d",
142         mName,
143         num_buffers, frame_size, buffer_size);
144
145    int page_mask = getpagesize() - 1;
146    int ashmem_size = buffer_size * num_buffers;
147    ashmem_size += page_mask;
148    ashmem_size &= ~page_mask;
149
150    mHeap = new MemoryHeapBase(ashmem_size);
151
152    completeInitialization();
153}
154
155static bool register_buf(int size,
156                         int frame_size,
157                         int cbcr_offset,
158                         int yoffset,
159                         int pmempreviewfd,
160                         uint32_t offset,
161                         uint8_t *buf,
162                         int pmem_type,
163                         bool vfe_can_write,
164                         bool register_buffer)
165{
166    /*TODO*/
167    /*
168    struct msm_pmem_info pmemBuf;
169    CAMERA_HAL_UNUSED(frame_size);
170
171    pmemBuf.type     = pmem_type;
172    pmemBuf.fd       = pmempreviewfd;
173    pmemBuf.offset   = offset;
174    pmemBuf.len      = size;
175    pmemBuf.vaddr    = buf;
176    pmemBuf.y_off    = yoffset;
177    pmemBuf.cbcr_off = cbcr_offset;
178
179    pmemBuf.active   = vfe_can_write;
180
181    ALOGV("register_buf:  reg = %d buffer = %p",
182         !register_buffer, buf);
183    if(native_start_ops(register_buffer ? CAMERA_OPS_REGISTER_BUFFER :
184        CAMERA_OPS_UNREGISTER_BUFFER ,(void *)&pmemBuf) < 0) {
185         ALOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM  error %s",
186               strerror(errno));
187         return false;
188         }*/
189
190    return true;
191
192}
193
194#if 0
195bool register_record_buffers(bool register_buffer) {
196    ALOGI("%s: (%d) E", __FUNCTION__, register_buffer);
197    struct msm_pmem_info pmemBuf;
198
199    for (int cnt = 0; cnt < VIDEO_BUFFER_COUNT; ++cnt) {
200        pmemBuf.type     = MSM_PMEM_VIDEO;
201        pmemBuf.fd       = mRecordHeap->mHeap->getHeapID();
202        pmemBuf.offset   = mRecordHeap->mAlignedBufferSize * cnt;
203        pmemBuf.len      = mRecordHeap->mBufferSize;
204        pmemBuf.vaddr    = (uint8_t *)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
205        pmemBuf.y_off    = 0;
206        pmemBuf.cbcr_off = recordframes[0].cbcr_off;
207        if(register_buffer == true) {
208            pmemBuf.active   = (cnt<ACTIVE_VIDEO_BUFFERS);
209            if( (mVpeEnabled) && (cnt == kRecordBufferCount-1)) {
210                pmemBuf.type = MSM_PMEM_VIDEO_VPE;
211                pmemBuf.active = 1;
212            }
213        } else {
214            pmemBuf.active   = false;
215        }
216
217        ALOGV("register_buf:  reg = %d buffer = %p", !register_buffer,
218          (void *)pmemBuf.vaddr);
219        if(native_start_ops(register_buffer ? CAMERA_OPS_REGISTER_BUFFER :
220                CAMERA_OPS_UNREGISTER_BUFFER ,(void *)&pmemBuf) < 0) {
221            ALOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM  error %s",
222                strerror(errno));
223            return false;
224        }
225    }
226    return true;
227}
228#endif
229#if 0
230PmemPool::PmemPool(const char *pmem_pool,
231                                           int flags,
232                                           int pmem_type,
233                                           int buffer_size, int num_buffers,
234                                           int frame_size, int cbcr_offset,
235                                           int yOffset, const char *name) :
236    MemPool(buffer_size,num_buffers,frame_size,name),
237    mPmemType(pmem_type),
238    mCbCrOffset(cbcr_offset),
239    myOffset(yOffset)
240{
241    ALOGI("constructing MemPool %s backed by pmem pool %s: "
242         "%d frames @ %d bytes, buffer size %d",
243         mName,
244         pmem_pool, num_buffers, frame_size,
245         buffer_size);
246
247    //mMMCameraDLRef = MMCameraDL::getInstance();
248
249
250    // Make a new mmap'ed heap that can be shared across processes.
251    // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
252    mAlignedSize = mAlignedBufferSize * num_buffers;
253
254    sp<MemoryHeapBase> masterHeap =
255        new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
256
257    if (masterHeap->getHeapID() < 0) {
258        ALOGE("failed to construct master heap for pmem pool %s", pmem_pool);
259        masterHeap.clear();
260        return;
261    }
262
263    sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
264    if (pmemHeap->getHeapID() >= 0) {
265        pmemHeap->slap();
266        masterHeap.clear();
267        mHeap = pmemHeap;
268        pmemHeap.clear();
269
270        mFd = mHeap->getHeapID();
271        if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
272            ALOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
273                 pmem_pool,
274                 ::strerror(errno), errno);
275            mHeap.clear();
276            return;
277        }
278
279        ALOGE("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
280             pmem_pool,
281             mFd,
282             mSize.len);
283        ALOGE("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
284
285#if 0
286        // Unregister preview buffers with the camera drivers.  Allow the VFE to write
287        // to all preview buffers except for the last one.
288        // Only Register the preview, snapshot and thumbnail buffers with the kernel.
289        if( (strcmp("postview", mName) != 0) ){
290            int num_buf = num_buffers;
291            if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
292            ALOGD("num_buffers = %d", num_buf);
293            for (int cnt = 0; cnt < num_buf; ++cnt) {
294                int active = 1;
295                if(pmem_type == MSM_PMEM_VIDEO){
296                     active = (cnt<ACTIVE_VIDEO_BUFFERS);
297                     //When VPE is enabled, set the last record
298                     //buffer as active and pmem type as PMEM_VIDEO_VPE
299                     //as this is a requirement from VPE operation.
300                     //No need to set this pmem type to VIDEO_VPE while unregistering,
301                     //because as per camera stack design: "the VPE AXI is also configured
302                     //when VFE is configured for VIDEO, which is as part of preview
303                     //initialization/start. So during this VPE AXI config camera stack
304                     //will lookup the PMEM_VIDEO_VPE buffer and give it as o/p of VPE and
305                     //change it's type to PMEM_VIDEO".
306                     if( (mVpeEnabled) && (cnt == kRecordBufferCount-1)) {
307                         active = 1;
308                         pmem_type = MSM_PMEM_VIDEO_VPE;
309                     }
310                     ALOGV(" pmempool creating video buffers : active %d ", active);
311                }
312                else if (pmem_type == MSM_PMEM_PREVIEW){
313                    active = (cnt < ACTIVE_PREVIEW_BUFFERS);
314                }
315                else if ((pmem_type == MSM_PMEM_MAINIMG)
316                     || (pmem_type == MSM_PMEM_THUMBNAIL)){
317                    active = (cnt < ACTIVE_ZSL_BUFFERS);
318                }
319                register_buf(mBufferSize,
320                         mFrameSize, mCbCrOffset, myOffset,
321                         mHeap->getHeapID(),
322                         mAlignedBufferSize * cnt,
323                         (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
324                         pmem_type,
325                         active);
326            }
327        }
328#endif
329        completeInitialization();
330    }
331    else ALOGE("pmem pool %s error: could not create master heap!",
332              pmem_pool);
333    ALOGI("%s: (%s) X ", __FUNCTION__, mName);
334}
335#endif
336
337PmemPool::~PmemPool()
338{
339    ALOGV("%s: %s E", __FUNCTION__, mName);
340#if 0
341    if (mHeap != NULL) {
342        // Unregister preview buffers with the camera drivers.
343        //  Only Unregister the preview, snapshot and thumbnail
344        //  buffers with the kernel.
345        if( (strcmp("postview", mName) != 0) ){
346            int num_buffers = mNumBuffers;
347            if(!strcmp("preview", mName)) num_buffers = PREVIEW_BUFFER_COUNT;
348            for (int cnt = 0; cnt < num_buffers; ++cnt) {
349                register_buf(mBufferSize,
350                         mFrameSize,
351                         mCbCrOffset,
352                         myOffset,
353                         mHeap->getHeapID(),
354                         mAlignedBufferSize * cnt,
355                         (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
356                         mPmemType,
357                         false,
358                         false /* unregister */);
359            }
360        }
361    }
362    mMMCameraDLRef.clear();
363#endif
364    ALOGV("%s: %s X", __FUNCTION__, mName);
365}
366MemPool::~MemPool()
367{
368    ALOGV("destroying MemPool %s", mName);
369    if (mFrameSize > 0)
370        delete [] mBuffers;
371    mHeap.clear();
372    ALOGV("destroying MemPool %s completed", mName);
373}
374
375
376status_t MemPool::dump(int fd, const Vector<String16>& args) const
377{
378    const size_t SIZE = 256;
379    char buffer[SIZE];
380    String8 result;
381    CAMERA_HAL_UNUSED(args);
382    snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
383    result.append(buffer);
384    if (mName) {
385        snprintf(buffer, 255, "mem pool name (%s)\n", mName);
386        result.append(buffer);
387    }
388    if (mHeap != 0) {
389        snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
390                 mHeap->getBase(), mHeap->getSize(),
391                 mHeap->getFlags(), mHeap->getDevice());
392        result.append(buffer);
393    }
394    snprintf(buffer, 255,
395             "buffer size (%d), number of buffers (%d), frame size(%d)",
396             mBufferSize, mNumBuffers, mFrameSize);
397    result.append(buffer);
398    write(fd, result.string(), result.size());
399    return NO_ERROR;
400}
401
402};
403