Home | History | Annotate | Download | only in src
      1 /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
      2  *
      3  * Redistribution and use in source and binary forms, with or without
      4  * modification, are permitted provided that the following conditions are
      5  * met:
      6  *     * Redistributions of source code must retain the above copyright
      7  *       notice, this list of conditions and the following disclaimer.
      8  *     * Redistributions in binary form must reproduce the above
      9  *       copyright notice, this list of conditions and the following
     10  *       disclaimer in the documentation and/or other materials provided
     11  *       with the distribution.
     12  *     * Neither the name of The Linux Foundation nor the names of its
     13  *       contributors may be used to endorse or promote products derived
     14  *       from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  *
     28  */
     29 
     30 #include <pthread.h>
     31 #include <errno.h>
     32 #include <sys/ioctl.h>
     33 #include <sys/types.h>
     34 #include <sys/stat.h>
     35 #include <fcntl.h>
     36 #include <poll.h>
     37 #include <time.h>
     38 #include <cam_semaphore.h>
     39 #ifdef VENUS_PRESENT
     40 #include <media/msm_media_info.h>
     41 #endif
     42 
     43 #include "mm_camera_dbg.h"
     44 #include "mm_camera_interface.h"
     45 #include "mm_camera.h"
     46 
     47 /* internal function decalre */
     48 int32_t mm_stream_qbuf(mm_stream_t *my_obj,
     49                        mm_camera_buf_def_t *buf);
     50 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj);
     51 int32_t mm_stream_set_fmt(mm_stream_t * my_obj);
     52 int32_t mm_stream_sync_info(mm_stream_t *my_obj);
     53 int32_t mm_stream_init_bufs(mm_stream_t * my_obj);
     54 int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj);
     55 int32_t mm_stream_request_buf(mm_stream_t * my_obj);
     56 int32_t mm_stream_unreg_buf(mm_stream_t * my_obj);
     57 int32_t mm_stream_release(mm_stream_t *my_obj);
     58 int32_t mm_stream_set_parm(mm_stream_t *my_obj,
     59                            cam_stream_parm_buffer_t *value);
     60 int32_t mm_stream_get_parm(mm_stream_t *my_obj,
     61                            cam_stream_parm_buffer_t *value);
     62 int32_t mm_stream_do_action(mm_stream_t *my_obj,
     63                             void *in_value);
     64 int32_t mm_stream_streamon(mm_stream_t *my_obj);
     65 int32_t mm_stream_streamoff(mm_stream_t *my_obj);
     66 int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
     67                                  mm_camera_buf_info_t* buf_info,
     68                                  uint8_t num_planes);
     69 int32_t mm_stream_config(mm_stream_t *my_obj,
     70                          mm_camera_stream_config_t *config);
     71 int32_t mm_stream_reg_buf(mm_stream_t * my_obj);
     72 int32_t mm_stream_buf_done(mm_stream_t * my_obj,
     73                            mm_camera_buf_def_t *frame);
     74 int32_t mm_stream_calc_offset(mm_stream_t *my_obj);
     75 
     76 /* state machine function declare */
     77 int32_t mm_stream_fsm_inited(mm_stream_t * my_obj,
     78                              mm_stream_evt_type_t evt,
     79                              void * in_val,
     80                              void * out_val);
     81 int32_t mm_stream_fsm_acquired(mm_stream_t * my_obj,
     82                                mm_stream_evt_type_t evt,
     83                                void * in_val,
     84                                void * out_val);
     85 int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
     86                           mm_stream_evt_type_t evt,
     87                           void * in_val,
     88                           void * out_val);
     89 int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
     90                              mm_stream_evt_type_t evt,
     91                              void * in_val,
     92                              void * out_val);
     93 int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
     94                           mm_stream_evt_type_t evt,
     95                           void * in_val,
     96                           void * out_val);
     97 int32_t mm_stream_fsm_active(mm_stream_t * my_obj,
     98                              mm_stream_evt_type_t evt,
     99                              void * in_val,
    100                              void * out_val);
    101 uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt);
    102 
    103 
    104 /*===========================================================================
    105  * FUNCTION   : mm_stream_handle_rcvd_buf
    106  *
    107  * DESCRIPTION: function to handle newly received stream buffer
    108  *
    109  * PARAMETERS :
    110  *   @cam_obj : stream object
    111  *   @buf_info: ptr to struct storing buffer information
    112  *
    113  * RETURN     : none
    114  *==========================================================================*/
    115 void mm_stream_handle_rcvd_buf(mm_stream_t *my_obj,
    116                                mm_camera_buf_info_t *buf_info,
    117                                uint8_t has_cb)
    118 {
    119     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    120          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    121 
    122     /* enqueue to super buf thread */
    123     if (my_obj->is_bundled) {
    124         mm_camera_cmdcb_t* node = NULL;
    125 
    126         /* send cam_sem_post to wake up channel cmd thread to enqueue to super buffer */
    127         node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
    128         if (NULL != node) {
    129             memset(node, 0, sizeof(mm_camera_cmdcb_t));
    130             node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
    131             node->u.buf = *buf_info;
    132 
    133             /* enqueue to cmd thread */
    134             cam_queue_enq(&(my_obj->ch_obj->cmd_thread.cmd_queue), node);
    135 
    136             /* wake up cmd thread */
    137             cam_sem_post(&(my_obj->ch_obj->cmd_thread.cmd_sem));
    138         } else {
    139             CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
    140         }
    141     }
    142 
    143     if(has_cb) {
    144         mm_camera_cmdcb_t* node = NULL;
    145 
    146         /* send cam_sem_post to wake up cmd thread to dispatch dataCB */
    147         node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
    148         if (NULL != node) {
    149             memset(node, 0, sizeof(mm_camera_cmdcb_t));
    150             node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
    151             node->u.buf = *buf_info;
    152 
    153             /* enqueue to cmd thread */
    154             cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
    155 
    156             /* wake up cmd thread */
    157             cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
    158         } else {
    159             CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
    160         }
    161     }
    162 }
    163 
    164 /*===========================================================================
    165  * FUNCTION   : mm_stream_data_notify
    166  *
    167  * DESCRIPTION: callback to handle data notify from kernel
    168  *
    169  * PARAMETERS :
    170  *   @user_data : user data ptr (stream object)
    171  *
    172  * RETURN     : none
    173  *==========================================================================*/
    174 static void mm_stream_data_notify(void* user_data)
    175 {
    176     mm_stream_t *my_obj = (mm_stream_t*)user_data;
    177     int32_t idx = -1, i, rc;
    178     uint8_t has_cb = 0;
    179     mm_camera_buf_info_t buf_info;
    180 
    181     if (NULL == my_obj) {
    182         return;
    183     }
    184 
    185     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    186          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    187     if (MM_STREAM_STATE_ACTIVE != my_obj->state) {
    188         /* this Cb will only received in active_stream_on state
    189          * if not so, return here */
    190         CDBG_ERROR("%s: ERROR!! Wrong state (%d) to receive data notify!",
    191                    __func__, my_obj->state);
    192         return;
    193     }
    194 
    195     memset(&buf_info, 0, sizeof(mm_camera_buf_info_t));
    196     rc = mm_stream_read_msm_frame(my_obj, &buf_info, my_obj->frame_offset.num_planes);
    197     if (rc != 0) {
    198         return;
    199     }
    200     idx = buf_info.buf->buf_idx;
    201 
    202     pthread_mutex_lock(&my_obj->cb_lock);
    203     for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
    204         if(NULL != my_obj->buf_cb[i].cb) {
    205             /* for every CB, add ref count */
    206             has_cb = 1;
    207             break;
    208         }
    209     }
    210     pthread_mutex_unlock(&my_obj->cb_lock);
    211 
    212     pthread_mutex_lock(&my_obj->buf_lock);
    213     /* update buffer location */
    214     my_obj->buf_status[idx].in_kernel = 0;
    215 
    216     /* update buf ref count */
    217     if (my_obj->is_bundled) {
    218         /* need to add into super buf since bundled, add ref count */
    219         my_obj->buf_status[idx].buf_refcnt++;
    220     }
    221     my_obj->buf_status[idx].buf_refcnt += has_cb;
    222     pthread_mutex_unlock(&my_obj->buf_lock);
    223 
    224     mm_stream_handle_rcvd_buf(my_obj, &buf_info, has_cb);
    225 }
    226 
    227 /*===========================================================================
    228  * FUNCTION   : mm_stream_dispatch_app_data
    229  *
    230  * DESCRIPTION: dispatch stream buffer to registered users
    231  *
    232  * PARAMETERS :
    233  *   @cmd_cb  : ptr storing stream buffer information
    234  *   @userdata: user data ptr (stream object)
    235  *
    236  * RETURN     : none
    237  *==========================================================================*/
    238 static void mm_stream_dispatch_app_data(mm_camera_cmdcb_t *cmd_cb,
    239                                         void* user_data)
    240 {
    241     int i;
    242     mm_stream_t * my_obj = (mm_stream_t *)user_data;
    243     mm_camera_buf_info_t* buf_info = NULL;
    244     mm_camera_super_buf_t super_buf;
    245     mm_camera_cmd_thread_name("mm_cam_stream");
    246 
    247     if (NULL == my_obj) {
    248         return;
    249     }
    250     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    251          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    252 
    253     if (MM_CAMERA_CMD_TYPE_DATA_CB != cmd_cb->cmd_type) {
    254         CDBG_ERROR("%s: Wrong cmd_type (%d) for dataCB",
    255                    __func__, cmd_cb->cmd_type);
    256         return;
    257     }
    258 
    259     buf_info = &cmd_cb->u.buf;
    260     memset(&super_buf, 0, sizeof(mm_camera_super_buf_t));
    261     super_buf.num_bufs = 1;
    262     super_buf.bufs[0] = buf_info->buf;
    263     super_buf.camera_handle = my_obj->ch_obj->cam_obj->my_hdl;
    264     super_buf.ch_id = my_obj->ch_obj->my_hdl;
    265 
    266     pthread_mutex_lock(&my_obj->cb_lock);
    267     for(i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
    268         if(NULL != my_obj->buf_cb[i].cb) {
    269             if (my_obj->buf_cb[i].cb_count != 0) {
    270                 /* if <0, means infinite CB
    271                  * if >0, means CB for certain times
    272                  * both case we need to call CB */
    273 
    274                 /* increase buf ref cnt */
    275                 pthread_mutex_lock(&my_obj->buf_lock);
    276                 my_obj->buf_status[buf_info->buf->buf_idx].buf_refcnt++;
    277                 pthread_mutex_unlock(&my_obj->buf_lock);
    278 
    279                 /* callback */
    280                 my_obj->buf_cb[i].cb(&super_buf,
    281                                      my_obj->buf_cb[i].user_data);
    282             }
    283 
    284             /* if >0, reduce count by 1 every time we called CB until reaches 0
    285              * when count reach 0, reset the buf_cb to have no CB */
    286             if (my_obj->buf_cb[i].cb_count > 0) {
    287                 my_obj->buf_cb[i].cb_count--;
    288                 if (0 == my_obj->buf_cb[i].cb_count) {
    289                     my_obj->buf_cb[i].cb = NULL;
    290                     my_obj->buf_cb[i].user_data = NULL;
    291                 }
    292             }
    293         }
    294     }
    295     pthread_mutex_unlock(&my_obj->cb_lock);
    296 
    297     /* do buf_done since we increased refcnt by one when has_cb */
    298     mm_stream_buf_done(my_obj, buf_info->buf);
    299 }
    300 
    301 /*===========================================================================
    302  * FUNCTION   : mm_stream_fsm_fn
    303  *
    304  * DESCRIPTION: stream finite state machine entry function. Depends on stream
    305  *              state, incoming event will be handled differently.
    306  *
    307  * PARAMETERS :
    308  *   @my_obj   : ptr to a stream object
    309  *   @evt      : stream event to be processed
    310  *   @in_val   : input event payload. Can be NULL if not needed.
    311  *   @out_val  : output payload, Can be NULL if not needed.
    312  *
    313  * RETURN     : int32_t type of status
    314  *              0  -- success
    315  *              -1 -- failure
    316  *==========================================================================*/
    317 int32_t mm_stream_fsm_fn(mm_stream_t *my_obj,
    318                          mm_stream_evt_type_t evt,
    319                          void * in_val,
    320                          void * out_val)
    321 {
    322     int32_t rc = -1;
    323 
    324     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    325          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    326     switch (my_obj->state) {
    327     case MM_STREAM_STATE_NOTUSED:
    328         CDBG("%s: Not handling evt in unused state", __func__);
    329         break;
    330     case MM_STREAM_STATE_INITED:
    331         rc = mm_stream_fsm_inited(my_obj, evt, in_val, out_val);
    332         break;
    333     case MM_STREAM_STATE_ACQUIRED:
    334         rc = mm_stream_fsm_acquired(my_obj, evt, in_val, out_val);
    335         break;
    336     case MM_STREAM_STATE_CFG:
    337         rc = mm_stream_fsm_cfg(my_obj, evt, in_val, out_val);
    338         break;
    339     case MM_STREAM_STATE_BUFFED:
    340         rc = mm_stream_fsm_buffed(my_obj, evt, in_val, out_val);
    341         break;
    342     case MM_STREAM_STATE_REG:
    343         rc = mm_stream_fsm_reg(my_obj, evt, in_val, out_val);
    344         break;
    345     case MM_STREAM_STATE_ACTIVE:
    346         rc = mm_stream_fsm_active(my_obj, evt, in_val, out_val);
    347         break;
    348     default:
    349         CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
    350         break;
    351     }
    352     CDBG("%s : X rc =%d",__func__,rc);
    353     return rc;
    354 }
    355 
    356 /*===========================================================================
    357  * FUNCTION   : mm_stream_fsm_inited
    358  *
    359  * DESCRIPTION: stream finite state machine function to handle event in INITED
    360  *              state.
    361  *
    362  * PARAMETERS :
    363  *   @my_obj   : ptr to a stream object
    364  *   @evt      : stream event to be processed
    365  *   @in_val   : input event payload. Can be NULL if not needed.
    366  *   @out_val  : output payload, Can be NULL if not needed.
    367  *
    368  * RETURN     : int32_t type of status
    369  *              0  -- success
    370  *              -1 -- failure
    371  *==========================================================================*/
    372 int32_t mm_stream_fsm_inited(mm_stream_t *my_obj,
    373                              mm_stream_evt_type_t evt,
    374                              void * in_val,
    375                              void * out_val)
    376 {
    377     int32_t rc = 0;
    378     char dev_name[MM_CAMERA_DEV_NAME_LEN];
    379 
    380     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    381          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    382     switch(evt) {
    383     case MM_STREAM_EVT_ACQUIRE:
    384         if ((NULL == my_obj->ch_obj) || (NULL == my_obj->ch_obj->cam_obj)) {
    385             CDBG_ERROR("%s: NULL channel or camera obj\n", __func__);
    386             rc = -1;
    387             break;
    388         }
    389 
    390         snprintf(dev_name, sizeof(dev_name), "/dev/%s",
    391                  mm_camera_util_get_dev_name(my_obj->ch_obj->cam_obj->my_hdl));
    392 
    393         my_obj->fd = open(dev_name, O_RDWR | O_NONBLOCK);
    394         if (my_obj->fd < 0) {
    395             CDBG_ERROR("%s: open dev returned %d\n", __func__, my_obj->fd);
    396             rc = -1;
    397             break;
    398         }
    399         CDBG("%s: open dev fd = %d\n", __func__, my_obj->fd);
    400         rc = mm_stream_set_ext_mode(my_obj);
    401         if (0 == rc) {
    402             my_obj->state = MM_STREAM_STATE_ACQUIRED;
    403         } else {
    404             /* failed setting ext_mode
    405              * close fd */
    406             close(my_obj->fd);
    407             my_obj->fd = -1;
    408             break;
    409         }
    410         break;
    411     default:
    412         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
    413                    __func__, my_obj->state, evt, in_val, out_val);
    414         break;
    415     }
    416     return rc;
    417 }
    418 
    419 /*===========================================================================
    420  * FUNCTION   : mm_stream_fsm_acquired
    421  *
    422  * DESCRIPTION: stream finite state machine function to handle event in AQUIRED
    423  *              state.
    424  *
    425  * PARAMETERS :
    426  *   @my_obj   : ptr to a stream object
    427  *   @evt      : stream event to be processed
    428  *   @in_val   : input event payload. Can be NULL if not needed.
    429  *   @out_val  : output payload, Can be NULL if not needed.
    430  *
    431  * RETURN     : int32_t type of status
    432  *              0  -- success
    433  *              -1 -- failure
    434  *==========================================================================*/
    435 int32_t mm_stream_fsm_acquired(mm_stream_t *my_obj,
    436                                mm_stream_evt_type_t evt,
    437                                void * in_val,
    438                                void * out_val)
    439 {
    440     int32_t rc = 0;
    441 
    442     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    443          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    444     switch(evt) {
    445     case MM_STREAM_EVT_SET_FMT:
    446         {
    447             mm_camera_stream_config_t *config =
    448                 (mm_camera_stream_config_t *)in_val;
    449 
    450             rc = mm_stream_config(my_obj, config);
    451 
    452             /* change state to configed */
    453             my_obj->state = MM_STREAM_STATE_CFG;
    454 
    455             break;
    456         }
    457     case MM_STREAM_EVT_RELEASE:
    458         rc = mm_stream_release(my_obj);
    459         /* change state to not used */
    460          my_obj->state = MM_STREAM_STATE_NOTUSED;
    461         break;
    462     case MM_STREAM_EVT_SET_PARM:
    463         {
    464             mm_evt_paylod_set_get_stream_parms_t *payload =
    465                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    466             rc = mm_stream_set_parm(my_obj, payload->parms);
    467         }
    468         break;
    469     case MM_STREAM_EVT_GET_PARM:
    470         {
    471             mm_evt_paylod_set_get_stream_parms_t *payload =
    472                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    473             rc = mm_stream_get_parm(my_obj, payload->parms);
    474         }
    475         break;
    476     default:
    477         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
    478                    __func__, my_obj->state, evt, in_val, out_val);
    479     }
    480     CDBG("%s :X rc = %d", __func__, rc);
    481     return rc;
    482 }
    483 
    484 /*===========================================================================
    485  * FUNCTION   : mm_stream_fsm_cfg
    486  *
    487  * DESCRIPTION: stream finite state machine function to handle event in CONFIGURED
    488  *              state.
    489  *
    490  * PARAMETERS :
    491  *   @my_obj   : ptr to a stream object
    492  *   @evt      : stream event to be processed
    493  *   @in_val   : input event payload. Can be NULL if not needed.
    494  *   @out_val  : output payload, Can be NULL if not needed.
    495  *
    496  * RETURN     : int32_t type of status
    497  *              0  -- success
    498  *              -1 -- failure
    499  *==========================================================================*/
    500 int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
    501                           mm_stream_evt_type_t evt,
    502                           void * in_val,
    503                           void * out_val)
    504 {
    505     int32_t rc = 0;
    506     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    507          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    508     switch(evt) {
    509     case MM_STREAM_EVT_SET_FMT:
    510         {
    511             mm_camera_stream_config_t *config =
    512                 (mm_camera_stream_config_t *)in_val;
    513 
    514             rc = mm_stream_config(my_obj, config);
    515 
    516             /* change state to configed */
    517             my_obj->state = MM_STREAM_STATE_CFG;
    518 
    519             break;
    520         }
    521     case MM_STREAM_EVT_RELEASE:
    522         rc = mm_stream_release(my_obj);
    523         my_obj->state = MM_STREAM_STATE_NOTUSED;
    524         break;
    525     case MM_STREAM_EVT_SET_PARM:
    526         {
    527             mm_evt_paylod_set_get_stream_parms_t *payload =
    528                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    529             rc = mm_stream_set_parm(my_obj, payload->parms);
    530         }
    531         break;
    532     case MM_STREAM_EVT_GET_PARM:
    533         {
    534             mm_evt_paylod_set_get_stream_parms_t *payload =
    535                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    536             rc = mm_stream_get_parm(my_obj, payload->parms);
    537         }
    538         break;
    539     case MM_STREAM_EVT_GET_BUF:
    540         rc = mm_stream_init_bufs(my_obj);
    541         /* change state to buff allocated */
    542         if(0 == rc) {
    543             my_obj->state = MM_STREAM_STATE_BUFFED;
    544         }
    545         break;
    546     default:
    547         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
    548                    __func__, my_obj->state, evt, in_val, out_val);
    549     }
    550     CDBG("%s :X rc = %d", __func__, rc);
    551     return rc;
    552 }
    553 
    554 /*===========================================================================
    555  * FUNCTION   : mm_stream_fsm_buffed
    556  *
    557  * DESCRIPTION: stream finite state machine function to handle event in BUFFED
    558  *              state.
    559  *
    560  * PARAMETERS :
    561  *   @my_obj   : ptr to a stream object
    562  *   @evt      : stream event to be processed
    563  *   @in_val   : input event payload. Can be NULL if not needed.
    564  *   @out_val  : output payload, Can be NULL if not needed.
    565  *
    566  * RETURN     : int32_t type of status
    567  *              0  -- success
    568  *              -1 -- failure
    569  *==========================================================================*/
    570 int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
    571                              mm_stream_evt_type_t evt,
    572                              void * in_val,
    573                              void * out_val)
    574 {
    575     int32_t rc = 0;
    576     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    577          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    578     switch(evt) {
    579     case MM_STREAM_EVT_PUT_BUF:
    580         rc = mm_stream_deinit_bufs(my_obj);
    581         /* change state to configed */
    582         if(0 == rc) {
    583             my_obj->state = MM_STREAM_STATE_CFG;
    584         }
    585         break;
    586     case MM_STREAM_EVT_REG_BUF:
    587         rc = mm_stream_reg_buf(my_obj);
    588         /* change state to regged */
    589         if(0 == rc) {
    590             my_obj->state = MM_STREAM_STATE_REG;
    591         }
    592         break;
    593     case MM_STREAM_EVT_SET_PARM:
    594         {
    595             mm_evt_paylod_set_get_stream_parms_t *payload =
    596                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    597             rc = mm_stream_set_parm(my_obj, payload->parms);
    598         }
    599         break;
    600     case MM_STREAM_EVT_GET_PARM:
    601         {
    602             mm_evt_paylod_set_get_stream_parms_t *payload =
    603                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    604             rc = mm_stream_get_parm(my_obj, payload->parms);
    605         }
    606         break;
    607     default:
    608         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
    609                    __func__, my_obj->state, evt, in_val, out_val);
    610     }
    611     CDBG("%s :X rc = %d", __func__, rc);
    612     return rc;
    613 }
    614 
    615 /*===========================================================================
    616  * FUNCTION   : mm_stream_fsm_reg
    617  *
    618  * DESCRIPTION: stream finite state machine function to handle event in REGGED
    619  *              state.
    620  *
    621  * PARAMETERS :
    622  *   @my_obj   : ptr to a stream object
    623  *   @evt      : stream event to be processed
    624  *   @in_val   : input event payload. Can be NULL if not needed.
    625  *   @out_val  : output payload, Can be NULL if not needed.
    626  *
    627  * RETURN     : int32_t type of status
    628  *              0  -- success
    629  *              -1 -- failure
    630  *==========================================================================*/
    631 int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
    632                           mm_stream_evt_type_t evt,
    633                           void * in_val,
    634                           void * out_val)
    635 {
    636     int32_t rc = 0;
    637     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    638          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    639 
    640     switch(evt) {
    641     case MM_STREAM_EVT_UNREG_BUF:
    642         rc = mm_stream_unreg_buf(my_obj);
    643 
    644         /* change state to buffed */
    645         my_obj->state = MM_STREAM_STATE_BUFFED;
    646         break;
    647     case MM_STREAM_EVT_START:
    648         {
    649             uint8_t has_cb = 0;
    650             uint8_t i;
    651             /* launch cmd thread if CB is not null */
    652             pthread_mutex_lock(&my_obj->cb_lock);
    653             for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
    654                 if(NULL != my_obj->buf_cb[i].cb) {
    655                     has_cb = 1;
    656                     break;
    657                 }
    658             }
    659             pthread_mutex_unlock(&my_obj->cb_lock);
    660 
    661             if (has_cb) {
    662                 mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
    663                                             mm_stream_dispatch_app_data,
    664                                             (void *)my_obj);
    665             }
    666 
    667             my_obj->state = MM_STREAM_STATE_ACTIVE;
    668             rc = mm_stream_streamon(my_obj);
    669             if (0 != rc) {
    670                 /* failed stream on, need to release cmd thread if it's launched */
    671                 if (has_cb) {
    672                     mm_camera_cmd_thread_release(&my_obj->cmd_thread);
    673                 }
    674                 my_obj->state = MM_STREAM_STATE_REG;
    675                 break;
    676             }
    677         }
    678         break;
    679     case MM_STREAM_EVT_SET_PARM:
    680         {
    681             mm_evt_paylod_set_get_stream_parms_t *payload =
    682                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    683             rc = mm_stream_set_parm(my_obj, payload->parms);
    684         }
    685         break;
    686     case MM_STREAM_EVT_GET_PARM:
    687         {
    688             mm_evt_paylod_set_get_stream_parms_t *payload =
    689                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    690             rc = mm_stream_get_parm(my_obj, payload->parms);
    691         }
    692         break;
    693     default:
    694         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
    695                    __func__, my_obj->state, evt, in_val, out_val);
    696     }
    697     CDBG("%s :X rc = %d", __func__, rc);
    698     return rc;
    699 }
    700 
    701 /*===========================================================================
    702  * FUNCTION   : mm_stream_fsm_active
    703  *
    704  * DESCRIPTION: stream finite state machine function to handle event in ACTIVE
    705  *              state.
    706  *
    707  * PARAMETERS :
    708  *   @my_obj   : ptr to a stream object
    709  *   @evt      : stream event to be processed
    710  *   @in_val   : input event payload. Can be NULL if not needed.
    711  *   @out_val  : output payload, Can be NULL if not needed.
    712  *
    713  * RETURN     : int32_t type of status
    714  *              0  -- success
    715  *              -1 -- failure
    716  *==========================================================================*/
    717 int32_t mm_stream_fsm_active(mm_stream_t * my_obj,
    718                              mm_stream_evt_type_t evt,
    719                              void * in_val,
    720                              void * out_val)
    721 {
    722     int32_t rc = 0;
    723     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    724          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    725     switch(evt) {
    726     case MM_STREAM_EVT_QBUF:
    727         rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val);
    728         break;
    729     case MM_STREAM_EVT_STOP:
    730         {
    731             uint8_t has_cb = 0;
    732             uint8_t i;
    733             rc = mm_stream_streamoff(my_obj);
    734 
    735             pthread_mutex_lock(&my_obj->cb_lock);
    736             for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
    737                 if(NULL != my_obj->buf_cb[i].cb) {
    738                     has_cb = 1;
    739                     break;
    740                 }
    741             }
    742             pthread_mutex_unlock(&my_obj->cb_lock);
    743 
    744             if (has_cb) {
    745                 mm_camera_cmd_thread_release(&my_obj->cmd_thread);
    746             }
    747             my_obj->state = MM_STREAM_STATE_REG;
    748         }
    749         break;
    750     case MM_STREAM_EVT_SET_PARM:
    751         {
    752             mm_evt_paylod_set_get_stream_parms_t *payload =
    753                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    754             rc = mm_stream_set_parm(my_obj, payload->parms);
    755         }
    756         break;
    757     case MM_STREAM_EVT_GET_PARM:
    758         {
    759             mm_evt_paylod_set_get_stream_parms_t *payload =
    760                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    761             rc = mm_stream_get_parm(my_obj, payload->parms);
    762         }
    763         break;
    764     case MM_STREAM_EVT_DO_ACTION:
    765         rc = mm_stream_do_action(my_obj, in_val);
    766         break;
    767     default:
    768         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
    769                    __func__, my_obj->state, evt, in_val, out_val);
    770     }
    771     CDBG("%s :X rc = %d", __func__, rc);
    772     return rc;
    773 }
    774 
    775 /*===========================================================================
    776  * FUNCTION   : mm_stream_config
    777  *
    778  * DESCRIPTION: configure a stream
    779  *
    780  * PARAMETERS :
    781  *   @my_obj       : stream object
    782  *   @config       : stream configuration
    783  *
    784  * RETURN     : int32_t type of status
    785  *              0  -- success
    786  *              -1 -- failure
    787  *==========================================================================*/
    788 int32_t mm_stream_config(mm_stream_t *my_obj,
    789                          mm_camera_stream_config_t *config)
    790 {
    791     int32_t rc = 0;
    792     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    793          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    794     my_obj->stream_info = config->stream_info;
    795     my_obj->buf_num = 0;
    796     my_obj->mem_vtbl = config->mem_vtbl;
    797     my_obj->padding_info = config->padding_info;
    798     /* cd through intf always palced at idx 0 of buf_cb */
    799     my_obj->buf_cb[0].cb = config->stream_cb;
    800     my_obj->buf_cb[0].user_data = config->userdata;
    801     my_obj->buf_cb[0].cb_count = -1; /* infinite by default */
    802 
    803     rc = mm_stream_sync_info(my_obj);
    804     if (rc == 0) {
    805         rc = mm_stream_set_fmt(my_obj);
    806     }
    807     return rc;
    808 }
    809 
    810 /*===========================================================================
    811  * FUNCTION   : mm_stream_release
    812  *
    813  * DESCRIPTION: release a stream resource
    814  *
    815  * PARAMETERS :
    816  *   @my_obj       : stream object
    817  *
    818  * RETURN     : int32_t type of status
    819  *              0  -- success
    820  *              -1 -- failure
    821  *==========================================================================*/
    822 int32_t mm_stream_release(mm_stream_t *my_obj)
    823 {
    824     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    825          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    826 
    827     /* close fd */
    828     if(my_obj->fd >= 0)
    829     {
    830         close(my_obj->fd);
    831     }
    832 
    833     /* destroy mutex */
    834     pthread_mutex_destroy(&my_obj->buf_lock);
    835     pthread_mutex_destroy(&my_obj->cb_lock);
    836 
    837     /* reset stream obj */
    838     memset(my_obj, 0, sizeof(mm_stream_t));
    839     my_obj->fd = -1;
    840 
    841     return 0;
    842 }
    843 
    844 /*===========================================================================
    845  * FUNCTION   : mm_stream_streamon
    846  *
    847  * DESCRIPTION: stream on a stream. sending v4l2 request to kernel
    848  *
    849  * PARAMETERS :
    850  *   @my_obj       : stream object
    851  *
    852  * RETURN     : int32_t type of status
    853  *              0  -- success
    854  *              -1 -- failure
    855  *==========================================================================*/
    856 int32_t mm_stream_streamon(mm_stream_t *my_obj)
    857 {
    858     int32_t rc;
    859     enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    860 
    861     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    862          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    863 
    864     rc = ioctl(my_obj->fd, VIDIOC_STREAMON, &buf_type);
    865     if (rc < 0) {
    866         CDBG_ERROR("%s: ioctl VIDIOC_STREAMON failed: rc=%d\n",
    867                    __func__, rc);
    868         /* remove fd from data poll thread in case of failure */
    869         mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl, mm_camera_sync_call);
    870     }
    871     CDBG("%s :X rc = %d",__func__,rc);
    872     return rc;
    873 }
    874 
    875 /*===========================================================================
    876  * FUNCTION   : mm_stream_streamoff
    877  *
    878  * DESCRIPTION: stream off a stream. sending v4l2 request to kernel
    879  *
    880  * PARAMETERS :
    881  *   @my_obj       : stream object
    882  *
    883  * RETURN     : int32_t type of status
    884  *              0  -- success
    885  *              -1 -- failure
    886  *==========================================================================*/
    887 int32_t mm_stream_streamoff(mm_stream_t *my_obj)
    888 {
    889     int32_t rc;
    890     enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    891     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    892          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    893 
    894     /* step1: remove fd from data poll thread */
    895     rc = mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
    896             my_obj->my_hdl, mm_camera_sync_call);
    897     if (rc < 0) {
    898         /* The error might be due to async update. In this case
    899          * wait for all updates to complete before proceeding. */
    900         rc = mm_camera_poll_thread_commit_updates(&my_obj->ch_obj->poll_thread[0]);
    901         if (rc < 0) {
    902             CDBG_ERROR("%s: Poll sync failed %d",
    903                  __func__, rc);
    904         }
    905     }
    906 
    907     /* step2: stream off */
    908     rc = ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type);
    909     if (rc < 0) {
    910         CDBG_ERROR("%s: STREAMOFF failed: %s\n",
    911                 __func__, strerror(errno));
    912     }
    913     CDBG("%s :X rc = %d",__func__,rc);
    914     return rc;
    915 }
    916 
    917 /*===========================================================================
    918  * FUNCTION   : mm_stream_read_msm_frame
    919  *
    920  * DESCRIPTION: dequeue a stream buffer from kernel queue
    921  *
    922  * PARAMETERS :
    923  *   @my_obj       : stream object
    924  *   @buf_info     : ptr to a struct storing buffer information
    925  *   @num_planes   : number of planes in the buffer
    926  *
    927  * RETURN     : int32_t type of status
    928  *              0  -- success
    929  *              -1 -- failure
    930  *==========================================================================*/
    931 int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
    932                                  mm_camera_buf_info_t* buf_info,
    933                                  uint8_t num_planes)
    934 {
    935     int32_t rc = 0;
    936     struct v4l2_buffer vb;
    937     struct v4l2_plane planes[VIDEO_MAX_PLANES];
    938     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
    939          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
    940 
    941     memset(&vb,  0,  sizeof(vb));
    942     vb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    943     vb.memory = V4L2_MEMORY_USERPTR;
    944     vb.m.planes = &planes[0];
    945     vb.length = num_planes;
    946 
    947     rc = ioctl(my_obj->fd, VIDIOC_DQBUF, &vb);
    948     if (rc < 0) {
    949         CDBG_ERROR("%s: VIDIOC_DQBUF ioctl call failed (rc=%d)\n",
    950                    __func__, rc);
    951     } else {
    952         pthread_mutex_lock(&my_obj->buf_lock);
    953         my_obj->queued_buffer_count--;
    954         if(my_obj->queued_buffer_count == 0) {
    955             CDBG_HIGH("%s: Stoping poll on stream %p type :%d", __func__, my_obj, my_obj->stream_info->stream_type);
    956             mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl, mm_camera_async_call);
    957             CDBG_HIGH("%s: Stopped poll on stream %p type :%d", __func__, my_obj, my_obj->stream_info->stream_type);
    958         }
    959         pthread_mutex_unlock(&my_obj->buf_lock);
    960         int8_t idx = vb.index;
    961         buf_info->buf = &my_obj->buf[idx];
    962         buf_info->frame_idx = vb.sequence;
    963         buf_info->stream_id = my_obj->my_hdl;
    964 
    965         buf_info->buf->stream_id = my_obj->my_hdl;
    966         buf_info->buf->buf_idx = idx;
    967         buf_info->buf->frame_idx = vb.sequence;
    968         buf_info->buf->ts.tv_sec  = vb.timestamp.tv_sec;
    969         buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000;
    970         CDBG("%s: VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d\n",
    971              __func__, vb.index, buf_info->buf->frame_idx, my_obj->stream_info->stream_type);
    972         if ( NULL != my_obj->mem_vtbl.clean_invalidate_buf ) {
    973             rc = my_obj->mem_vtbl.clean_invalidate_buf(idx,
    974                                                        my_obj->mem_vtbl.user_data);
    975             if ( 0 > rc ) {
    976                 CDBG_ERROR("%s: Clean invalidate cache failed on buffer index: %d",
    977                            __func__,
    978                            idx);
    979                 return rc;
    980             }
    981         } else {
    982             CDBG_ERROR(" %s : Clean invalidate cache op not supported\n", __func__);
    983         }
    984     }
    985 
    986     CDBG("%s :X rc = %d",__func__,rc);
    987     return rc;
    988 }
    989 
    990 /*===========================================================================
    991  * FUNCTION   : mm_stream_set_parms
    992  *
    993  * DESCRIPTION: set parameters per stream
    994  *
    995  * PARAMETERS :
    996  *   @my_obj       : stream object
    997  *   @in_value     : ptr to a param struct to be set to server
    998  *
    999  * RETURN     : int32_t type of status
   1000  *              0  -- success
   1001  *              -1 -- failure
   1002  * NOTE       : Assume the parms struct buf is already mapped to server via
   1003  *              domain socket. Corresponding fields of parameters to be set
   1004  *              are already filled in by upper layer caller.
   1005  *==========================================================================*/
   1006 int32_t mm_stream_set_parm(mm_stream_t *my_obj,
   1007                            cam_stream_parm_buffer_t *in_value)
   1008 {
   1009     int32_t rc = -1;
   1010     int32_t value = 0;
   1011     if (in_value != NULL) {
   1012         rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
   1013     }
   1014     return rc;
   1015 }
   1016 
   1017 /*===========================================================================
   1018  * FUNCTION   : mm_stream_get_parms
   1019  *
   1020  * DESCRIPTION: get parameters per stream
   1021  *
   1022  * PARAMETERS :
   1023  *   @my_obj       : stream object
   1024  *   @in_value     : ptr to a param struct to be get from server
   1025  *
   1026  * RETURN     : int32_t type of status
   1027  *              0  -- success
   1028  *              -1 -- failure
   1029  * NOTE       : Assume the parms struct buf is already mapped to server via
   1030  *              domain socket. Corresponding fields of parameters to be get
   1031  *              are already filled in by upper layer caller.
   1032  *==========================================================================*/
   1033 int32_t mm_stream_get_parm(mm_stream_t *my_obj,
   1034                            cam_stream_parm_buffer_t *in_value)
   1035 {
   1036     int32_t rc = -1;
   1037     int32_t value = 0;
   1038     if (in_value != NULL) {
   1039         rc = mm_camera_util_g_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
   1040     }
   1041     return rc;
   1042 }
   1043 
   1044 /*===========================================================================
   1045  * FUNCTION   : mm_stream_do_actions
   1046  *
   1047  * DESCRIPTION: request server to perform stream based actions
   1048  *
   1049  * PARAMETERS :
   1050  *   @my_obj       : stream object
   1051  *   @in_value     : ptr to a struct of actions to be performed by the server
   1052  *
   1053  * RETURN     : int32_t type of status
   1054  *              0  -- success
   1055  *              -1 -- failure
   1056  * NOTE       : Assume the action struct buf is already mapped to server via
   1057  *              domain socket. Corresponding fields of actions to be performed
   1058  *              are already filled in by upper layer caller.
   1059  *==========================================================================*/
   1060 int32_t mm_stream_do_action(mm_stream_t *my_obj,
   1061                             void *in_value)
   1062 {
   1063     int32_t rc = -1;
   1064     int32_t value = 0;
   1065     if (in_value != NULL) {
   1066         rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
   1067     }
   1068     return rc;
   1069 }
   1070 
   1071 /*===========================================================================
   1072  * FUNCTION   : mm_stream_set_ext_mode
   1073  *
   1074  * DESCRIPTION: set stream extended mode to server via v4l2 ioctl
   1075  *
   1076  * PARAMETERS :
   1077  *   @my_obj       : stream object
   1078  *
   1079  * RETURN     : int32_t type of status
   1080  *              0  -- success
   1081  *              -1 -- failure
   1082  * NOTE       : Server will return a server stream id that uniquely identify
   1083  *              this stream on server side. Later on communication to server
   1084  *              per stream should use this server stream id.
   1085  *==========================================================================*/
   1086 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj)
   1087 {
   1088     int32_t rc = 0;
   1089     struct v4l2_streamparm s_parm;
   1090     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
   1091          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
   1092 
   1093     memset(&s_parm, 0, sizeof(s_parm));
   1094     s_parm.type =  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1095 
   1096     rc = ioctl(my_obj->fd, VIDIOC_S_PARM, &s_parm);
   1097     CDBG("%s:stream fd=%d, rc=%d, extended_mode=%d\n",
   1098          __func__, my_obj->fd, rc, s_parm.parm.capture.extendedmode);
   1099     if (rc == 0) {
   1100         /* get server stream id */
   1101         my_obj->server_stream_id = s_parm.parm.capture.extendedmode;
   1102     }
   1103     return rc;
   1104 }
   1105 
   1106 /*===========================================================================
   1107  * FUNCTION   : mm_stream_qbuf
   1108  *
   1109  * DESCRIPTION: enqueue buffer back to kernel queue for furture use
   1110  *
   1111  * PARAMETERS :
   1112  *   @my_obj       : stream object
   1113  *   @buf          : ptr to a struct storing buffer information
   1114  *
   1115  * RETURN     : int32_t type of status
   1116  *              0  -- success
   1117  *              -1 -- failure
   1118  *==========================================================================*/
   1119 int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf)
   1120 {
   1121     int32_t rc = 0;
   1122     struct v4l2_buffer buffer;
   1123     struct v4l2_plane planes[VIDEO_MAX_PLANES];
   1124     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
   1125          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
   1126 
   1127     memcpy(planes, buf->planes, sizeof(planes));
   1128     memset(&buffer, 0, sizeof(buffer));
   1129     buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1130     buffer.memory = V4L2_MEMORY_USERPTR;
   1131     buffer.index = buf->buf_idx;
   1132     buffer.m.planes = &planes[0];
   1133     buffer.length = buf->num_planes;
   1134 
   1135     CDBG("%s:plane 0: stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d, offset = %d, data_offset = %d\n", __func__,
   1136          buf->stream_id, buf->fd, buffer.index, buffer.length, buf->planes[0].reserved[0], buf->planes[0].data_offset);
   1137     CDBG("%s:plane 1: stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d, offset = %d, data_offset = %d\n", __func__,
   1138          buf->stream_id, buf->fd, buffer.index, buffer.length, buf->planes[1].reserved[0], buf->planes[1].data_offset);
   1139 
   1140     if ( NULL != my_obj->mem_vtbl.invalidate_buf ) {
   1141         rc = my_obj->mem_vtbl.invalidate_buf(buffer.index,
   1142                                              my_obj->mem_vtbl.user_data);
   1143         if ( 0 > rc ) {
   1144             CDBG_ERROR("%s: Cache invalidate failed on buffer index: %d",
   1145                        __func__,
   1146                        buffer.index);
   1147             return rc;
   1148         }
   1149     } else {
   1150         CDBG_ERROR("%s: Cache invalidate op not added", __func__);
   1151     }
   1152 
   1153     my_obj->queued_buffer_count++;
   1154     if(my_obj->queued_buffer_count == 1) {
   1155         /* Add fd to data poll thread */
   1156         CDBG_HIGH("%s: Starting poll on stream %p type :%d", __func__, my_obj,my_obj->stream_info->stream_type);
   1157         rc = mm_camera_poll_thread_add_poll_fd(&my_obj->ch_obj->poll_thread[0],
   1158                 my_obj->my_hdl,
   1159                 my_obj->fd,
   1160                 mm_stream_data_notify,
   1161                 (void*)my_obj,
   1162                 mm_camera_async_call);
   1163         CDBG_HIGH("%s: Started poll on stream %p type :%d", __func__, my_obj,my_obj->stream_info->stream_type);
   1164         if (rc < 0) {
   1165             CDBG_ERROR("%s: add poll fd error", __func__);
   1166             return rc;
   1167         }
   1168     }
   1169 
   1170     rc = ioctl(my_obj->fd, VIDIOC_QBUF, &buffer);
   1171     CDBG("%s: qbuf idx:%d, rc:%d", __func__, buffer.index, rc);
   1172     return rc;
   1173 }
   1174 
   1175 /*===========================================================================
   1176  * FUNCTION   : mm_stream_request_buf
   1177  *
   1178  * DESCRIPTION: This function let kernel know the amount of buffers need to
   1179  *              be registered via v4l2 ioctl.
   1180  *
   1181  * PARAMETERS :
   1182  *   @my_obj       : stream object
   1183  *
   1184  * RETURN     : int32_t type of status
   1185  *              0  -- success
   1186  *              -1 -- failure
   1187  *==========================================================================*/
   1188 int32_t mm_stream_request_buf(mm_stream_t * my_obj)
   1189 {
   1190     int32_t rc = 0;
   1191     struct v4l2_requestbuffers bufreq;
   1192     uint8_t buf_num = my_obj->buf_num;
   1193     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
   1194          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
   1195 
   1196     if(buf_num > MM_CAMERA_MAX_NUM_FRAMES) {
   1197         CDBG_ERROR("%s: buf num %d > max limit %d\n",
   1198                    __func__, buf_num, MM_CAMERA_MAX_NUM_FRAMES);
   1199         return -1;
   1200     }
   1201 
   1202     memset(&bufreq, 0, sizeof(bufreq));
   1203     bufreq.count = buf_num;
   1204     bufreq.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1205     bufreq.memory = V4L2_MEMORY_USERPTR;
   1206     rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
   1207     if (rc < 0) {
   1208       CDBG_ERROR("%s: fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d\n",
   1209            __func__, my_obj->fd, rc);
   1210     }
   1211     CDBG("%s :X rc = %d",__func__,rc);
   1212     return rc;
   1213 }
   1214 
   1215 /*===========================================================================
   1216  * FUNCTION   : mm_stream_map_buf
   1217  *
   1218  * DESCRIPTION: mapping stream buffer via domain socket to server
   1219  *
   1220  * PARAMETERS :
   1221  *   @my_obj       : stream object
   1222  *   @buf_type     : type of buffer to be mapped. could be following values:
   1223  *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
   1224  *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
   1225  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
   1226  *   @frame_idx    : index of buffer within the stream buffers, only valid if
   1227  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
   1228  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
   1229  *   @plane_idx    : plane index. If all planes share the same fd,
   1230  *                   plane_idx = -1; otherwise, plean_idx is the
   1231  *                   index to plane (0..num_of_planes)
   1232  *   @fd           : file descriptor of the buffer
   1233  *   @size         : size of the buffer
   1234  *
   1235  * RETURN     : int32_t type of status
   1236  *              0  -- success
   1237  *              -1 -- failure
   1238  *==========================================================================*/
   1239 int32_t mm_stream_map_buf(mm_stream_t * my_obj,
   1240                           uint8_t buf_type,
   1241                           uint32_t frame_idx,
   1242                           int32_t plane_idx,
   1243                           int fd,
   1244                           uint32_t size)
   1245 {
   1246     if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
   1247         CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__);
   1248         return -1;
   1249     }
   1250 
   1251     cam_sock_packet_t packet;
   1252     memset(&packet, 0, sizeof(cam_sock_packet_t));
   1253     packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;
   1254     packet.payload.buf_map.type = buf_type;
   1255     packet.payload.buf_map.fd = fd;
   1256     packet.payload.buf_map.size = size;
   1257     packet.payload.buf_map.stream_id = my_obj->server_stream_id;
   1258     packet.payload.buf_map.frame_idx = frame_idx;
   1259     packet.payload.buf_map.plane_idx = plane_idx;
   1260     return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
   1261                                   &packet,
   1262                                   sizeof(cam_sock_packet_t),
   1263                                   fd);
   1264 }
   1265 
   1266 /*===========================================================================
   1267  * FUNCTION   : mm_stream_unmap_buf
   1268  *
   1269  * DESCRIPTION: unmapping stream buffer via domain socket to server
   1270  *
   1271  * PARAMETERS :
   1272  *   @my_obj       : stream object
   1273  *   @buf_type     : type of buffer to be unmapped. could be following values:
   1274  *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
   1275  *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
   1276  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
   1277  *   @frame_idx    : index of buffer within the stream buffers, only valid if
   1278  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
   1279  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
   1280  *   @plane_idx    : plane index. If all planes share the same fd,
   1281  *                   plane_idx = -1; otherwise, plean_idx is the
   1282  *                   index to plane (0..num_of_planes)
   1283  *
   1284  * RETURN     : int32_t type of status
   1285  *              0  -- success
   1286  *              -1 -- failure
   1287  *==========================================================================*/
   1288 int32_t mm_stream_unmap_buf(mm_stream_t * my_obj,
   1289                             uint8_t buf_type,
   1290                             uint32_t frame_idx,
   1291                             int32_t plane_idx)
   1292 {
   1293     if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
   1294         CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__);
   1295         return -1;
   1296     }
   1297 
   1298     cam_sock_packet_t packet;
   1299     memset(&packet, 0, sizeof(cam_sock_packet_t));
   1300     packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING;
   1301     packet.payload.buf_unmap.type = buf_type;
   1302     packet.payload.buf_unmap.stream_id = my_obj->server_stream_id;
   1303     packet.payload.buf_unmap.frame_idx = frame_idx;
   1304     packet.payload.buf_unmap.plane_idx = plane_idx;
   1305     return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
   1306                                   &packet,
   1307                                   sizeof(cam_sock_packet_t),
   1308                                   0);
   1309 }
   1310 
   1311 /*===========================================================================
   1312  * FUNCTION   : mm_stream_map_buf_ops
   1313  *
   1314  * DESCRIPTION: ops for mapping stream buffer via domain socket to server.
   1315  *              This function will be passed to upper layer as part of ops table
   1316  *              to be used by upper layer when allocating stream buffers and mapping
   1317  *              buffers to server via domain socket.
   1318  *
   1319  * PARAMETERS :
   1320  *   @frame_idx    : index of buffer within the stream buffers, only valid if
   1321  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
   1322  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
   1323  *   @plane_idx    : plane index. If all planes share the same fd,
   1324  *                   plane_idx = -1; otherwise, plean_idx is the
   1325  *                   index to plane (0..num_of_planes)
   1326  *   @fd           : file descriptor of the buffer
   1327  *   @size         : size of the buffer
   1328  *   @userdata     : user data ptr (stream object)
   1329  *
   1330  * RETURN     : int32_t type of status
   1331  *              0  -- success
   1332  *              -1 -- failure
   1333  *==========================================================================*/
   1334 static int32_t mm_stream_map_buf_ops(uint32_t frame_idx,
   1335                                      int32_t plane_idx,
   1336                                      int fd,
   1337                                      uint32_t size,
   1338                                      void *userdata)
   1339 {
   1340     mm_stream_t *my_obj = (mm_stream_t *)userdata;
   1341     return mm_stream_map_buf(my_obj,
   1342                              CAM_MAPPING_BUF_TYPE_STREAM_BUF,
   1343                              frame_idx, plane_idx, fd, size);
   1344 }
   1345 
   1346 /*===========================================================================
   1347  * FUNCTION   : mm_stream_unmap_buf_ops
   1348  *
   1349  * DESCRIPTION: ops for unmapping stream buffer via domain socket to server.
   1350  *              This function will be passed to upper layer as part of ops table
   1351  *              to be used by upper layer when allocating stream buffers and unmapping
   1352  *              buffers to server via domain socket.
   1353  *
   1354  * PARAMETERS :
   1355  *   @frame_idx    : index of buffer within the stream buffers, only valid if
   1356  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
   1357  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
   1358  *   @plane_idx    : plane index. If all planes share the same fd,
   1359  *                   plane_idx = -1; otherwise, plean_idx is the
   1360  *                   index to plane (0..num_of_planes)
   1361  *   @userdata     : user data ptr (stream object)
   1362  *
   1363  * RETURN     : int32_t type of status
   1364  *              0  -- success
   1365  *              -1 -- failure
   1366  *==========================================================================*/
   1367 static int32_t mm_stream_unmap_buf_ops(uint32_t frame_idx,
   1368                                        int32_t plane_idx,
   1369                                        void *userdata)
   1370 {
   1371     mm_stream_t *my_obj = (mm_stream_t *)userdata;
   1372     return mm_stream_unmap_buf(my_obj,
   1373                                CAM_MAPPING_BUF_TYPE_STREAM_BUF,
   1374                                frame_idx,
   1375                                plane_idx);
   1376 }
   1377 
   1378 /*===========================================================================
   1379  * FUNCTION   : mm_stream_init_bufs
   1380  *
   1381  * DESCRIPTION: initialize stream buffers needed. This function will request
   1382  *              buffers needed from upper layer through the mem ops table passed
   1383  *              during configuration stage.
   1384  *
   1385  * PARAMETERS :
   1386  *   @my_obj  : stream object
   1387  *
   1388  * RETURN     : int32_t type of status
   1389  *              0  -- success
   1390  *              -1 -- failure
   1391  *==========================================================================*/
   1392 int32_t mm_stream_init_bufs(mm_stream_t * my_obj)
   1393 {
   1394     int32_t i, rc = 0;
   1395     uint8_t *reg_flags = NULL;
   1396     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
   1397          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
   1398 
   1399     /* deinit buf if it's not NULL*/
   1400     if (NULL != my_obj->buf) {
   1401         mm_stream_deinit_bufs(my_obj);
   1402     }
   1403 
   1404     my_obj->map_ops.map_ops = mm_stream_map_buf_ops;
   1405     my_obj->map_ops.unmap_ops = mm_stream_unmap_buf_ops;
   1406     my_obj->map_ops.userdata = my_obj;
   1407 
   1408     rc = my_obj->mem_vtbl.get_bufs(&my_obj->frame_offset,
   1409                                    &my_obj->buf_num,
   1410                                    &reg_flags,
   1411                                    &my_obj->buf,
   1412                                    &my_obj->map_ops,
   1413                                    my_obj->mem_vtbl.user_data);
   1414 
   1415     if (0 != rc) {
   1416         CDBG_ERROR("%s: Error get buf, rc = %d\n", __func__, rc);
   1417         return rc;
   1418     }
   1419 
   1420     my_obj->buf_status =
   1421         (mm_stream_buf_status_t *)malloc(sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
   1422 
   1423     if (NULL == my_obj->buf_status) {
   1424         CDBG_ERROR("%s: No memory for buf_status", __func__);
   1425         mm_stream_deinit_bufs(my_obj);
   1426         free(reg_flags);
   1427         return -1;
   1428     }
   1429 
   1430     memset(my_obj->buf_status, 0, sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
   1431     for (i = 0; i < my_obj->buf_num; i++) {
   1432         my_obj->buf_status[i].initial_reg_flag = reg_flags[i];
   1433         my_obj->buf[i].stream_id = my_obj->my_hdl;
   1434         my_obj->buf[i].stream_type = my_obj->stream_info->stream_type;
   1435     }
   1436 
   1437     free(reg_flags);
   1438     reg_flags = NULL;
   1439 
   1440     return rc;
   1441 }
   1442 
   1443 /*===========================================================================
   1444  * FUNCTION   : mm_stream_deinit_bufs
   1445  *
   1446  * DESCRIPTION: return stream buffers to upper layer through the mem ops table
   1447  *              passed during configuration stage.
   1448  *
   1449  * PARAMETERS :
   1450  *   @my_obj  : stream object
   1451  *
   1452  * RETURN     : int32_t type of status
   1453  *              0  -- success
   1454  *              -1 -- failure
   1455  *==========================================================================*/
   1456 int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj)
   1457 {
   1458     int32_t rc = 0;
   1459     mm_camera_map_unmap_ops_tbl_t ops_tbl;
   1460     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
   1461          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
   1462 
   1463     if (NULL == my_obj->buf) {
   1464         CDBG("%s: Buf is NULL, no need to deinit", __func__);
   1465         return rc;
   1466     }
   1467 
   1468     /* release bufs */
   1469     ops_tbl.map_ops = mm_stream_map_buf_ops;
   1470     ops_tbl.unmap_ops = mm_stream_unmap_buf_ops;
   1471     ops_tbl.userdata = my_obj;
   1472 
   1473     rc = my_obj->mem_vtbl.put_bufs(&ops_tbl,
   1474                                    my_obj->mem_vtbl.user_data);
   1475 
   1476     free(my_obj->buf);
   1477     my_obj->buf = NULL;
   1478     if (my_obj->buf_status != NULL) {
   1479         free(my_obj->buf_status);
   1480         my_obj->buf_status = NULL;
   1481     }
   1482 
   1483     return rc;
   1484 }
   1485 
   1486 /*===========================================================================
   1487  * FUNCTION   : mm_stream_reg_buf
   1488  *
   1489  * DESCRIPTION: register buffers with kernel by calling v4l2 ioctl QBUF for
   1490  *              each buffer in the stream
   1491  *
   1492  * PARAMETERS :
   1493  *   @my_obj  : stream object
   1494  *
   1495  * RETURN     : int32_t type of status
   1496  *              0  -- success
   1497  *              -1 -- failure
   1498  *==========================================================================*/
   1499 int32_t mm_stream_reg_buf(mm_stream_t * my_obj)
   1500 {
   1501     int32_t rc = 0;
   1502     uint8_t i;
   1503     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
   1504          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
   1505 
   1506     rc = mm_stream_request_buf(my_obj);
   1507     if (rc != 0) {
   1508         return rc;
   1509     }
   1510 
   1511     pthread_mutex_lock(&my_obj->buf_lock);
   1512     my_obj->queued_buffer_count = 0;
   1513     for(i = 0; i < my_obj->buf_num; i++){
   1514         /* check if need to qbuf initially */
   1515         if (my_obj->buf_status[i].initial_reg_flag) {
   1516             rc = mm_stream_qbuf(my_obj, &my_obj->buf[i]);
   1517             if (rc != 0) {
   1518                 CDBG_ERROR("%s: VIDIOC_QBUF rc = %d, errno is %s\n",
   1519                         __func__, rc, strerror(errno));
   1520                 break;
   1521             }
   1522             my_obj->buf_status[i].buf_refcnt = 0;
   1523             my_obj->buf_status[i].in_kernel = 1;
   1524         } else {
   1525             /* the buf is held by upper layer, will not queue into kernel.
   1526              * add buf reference count */
   1527             my_obj->buf_status[i].buf_refcnt = 1;
   1528             my_obj->buf_status[i].in_kernel = 0;
   1529         }
   1530     }
   1531     pthread_mutex_unlock(&my_obj->buf_lock);
   1532 
   1533     return rc;
   1534 }
   1535 
   1536 /*===========================================================================
   1537  * FUNCTION   : mm_stream_unreg buf
   1538  *
   1539  * DESCRIPTION: unregister all stream buffers from kernel
   1540  *
   1541  * PARAMETERS :
   1542  *   @my_obj  : stream object
   1543  *
   1544  * RETURN     : int32_t type of status
   1545  *              0  -- success
   1546  *              -1 -- failure
   1547  *==========================================================================*/
   1548 int32_t mm_stream_unreg_buf(mm_stream_t * my_obj)
   1549 {
   1550     struct v4l2_requestbuffers bufreq;
   1551     int32_t i, rc = 0;
   1552     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
   1553          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
   1554 
   1555     /* unreg buf to kernel */
   1556     bufreq.count = 0;
   1557     bufreq.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   1558     bufreq.memory = V4L2_MEMORY_USERPTR;
   1559     rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
   1560     if (rc < 0) {
   1561         CDBG_ERROR("%s: fd=%d, VIDIOC_REQBUFS failed, rc=%d\n",
   1562               __func__, my_obj->fd, rc);
   1563     }
   1564 
   1565     /* reset buf reference count */
   1566     pthread_mutex_lock(&my_obj->buf_lock);
   1567     if (NULL != my_obj->buf_status) {
   1568         for(i = 0; i < my_obj->buf_num; i++){
   1569             my_obj->buf_status[i].buf_refcnt = 0;
   1570             my_obj->buf_status[i].in_kernel = 0;
   1571         }
   1572     }
   1573     pthread_mutex_unlock(&my_obj->buf_lock);
   1574 
   1575     return rc;
   1576 }
   1577 
   1578 /*===========================================================================
   1579  * FUNCTION   : mm_stream_get_v4l2_fmt
   1580  *
   1581  * DESCRIPTION: translate camera image format into FOURCC code
   1582  *
   1583  * PARAMETERS :
   1584  *   @fmt     : camera image format
   1585  *
   1586  * RETURN     : FOURCC code for image format
   1587  *==========================================================================*/
   1588 uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt)
   1589 {
   1590     uint32_t val;
   1591     switch(fmt) {
   1592     case CAM_FORMAT_YUV_420_NV12:
   1593         val = V4L2_PIX_FMT_NV12;
   1594         break;
   1595     case CAM_FORMAT_YUV_420_NV21:
   1596         val = V4L2_PIX_FMT_NV21;
   1597         break;
   1598     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG:
   1599     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG:
   1600     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB:
   1601     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR:
   1602         val= V4L2_PIX_FMT_SBGGR10;
   1603         break;
   1604     case CAM_FORMAT_YUV_422_NV61:
   1605         val= V4L2_PIX_FMT_NV61;
   1606         break;
   1607     case CAM_FORMAT_YUV_RAW_8BIT_YUYV:
   1608         val= V4L2_PIX_FMT_YUYV;
   1609         break;
   1610     case CAM_FORMAT_YUV_RAW_8BIT_YVYU:
   1611         val= V4L2_PIX_FMT_YVYU;
   1612         break;
   1613     case CAM_FORMAT_YUV_RAW_8BIT_UYVY:
   1614         val= V4L2_PIX_FMT_UYVY;
   1615         break;
   1616     case CAM_FORMAT_YUV_RAW_8BIT_VYUY:
   1617         val= V4L2_PIX_FMT_VYUY;
   1618         break;
   1619     case CAM_FORMAT_YUV_420_YV12:
   1620         val= V4L2_PIX_FMT_NV12;
   1621         break;
   1622     case CAM_FORMAT_YUV_422_NV16:
   1623         val= V4L2_PIX_FMT_NV16;
   1624         break;
   1625     default:
   1626         val = 0;
   1627         CDBG_ERROR("%s: Unknown fmt=%d", __func__, fmt);
   1628         break;
   1629     }
   1630     CDBG("%s: fmt=%d, val =%d", __func__, fmt, val);
   1631     return val;
   1632 }
   1633 
   1634 /*===========================================================================
   1635  * FUNCTION   : mm_stream_calc_offset_preview
   1636  *
   1637  * DESCRIPTION: calculate preview/postview frame offset based on format and
   1638  *              padding information
   1639  *
   1640  * PARAMETERS :
   1641  *   @fmt     : image format
   1642  *   @dim     : image dimension
   1643  *   @buf_planes : [out] buffer plane information
   1644  *
   1645  * RETURN     : int32_t type of status
   1646  *              0  -- success
   1647  *              -1 -- failure
   1648  *==========================================================================*/
   1649 int32_t mm_stream_calc_offset_preview(cam_format_t fmt,
   1650                                       cam_dimension_t *dim,
   1651                                       cam_stream_buf_plane_info_t *buf_planes)
   1652 {
   1653     int32_t rc = 0;
   1654     int stride = 0, scanline = 0;
   1655 
   1656     switch (fmt) {
   1657     case CAM_FORMAT_YUV_420_NV12:
   1658     case CAM_FORMAT_YUV_420_NV21:
   1659         /* 2 planes: Y + CbCr */
   1660         buf_planes->plane_info.num_planes = 2;
   1661 
   1662         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
   1663         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
   1664         buf_planes->plane_info.mp[0].offset = 0;
   1665         buf_planes->plane_info.mp[0].len = stride * scanline;
   1666         buf_planes->plane_info.mp[0].offset_x = 0;
   1667         buf_planes->plane_info.mp[0].offset_y = 0;
   1668         buf_planes->plane_info.mp[0].stride = stride;
   1669         buf_planes->plane_info.mp[0].scanline = scanline;
   1670 
   1671         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
   1672         scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_2);
   1673         buf_planes->plane_info.mp[1].offset = 0;
   1674         buf_planes->plane_info.mp[1].len =
   1675             stride * scanline;
   1676         buf_planes->plane_info.mp[1].offset_x = 0;
   1677         buf_planes->plane_info.mp[1].offset_y = 0;
   1678         buf_planes->plane_info.mp[1].stride = stride;
   1679         buf_planes->plane_info.mp[1].scanline = scanline;
   1680 
   1681         buf_planes->plane_info.frame_len =
   1682             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
   1683                         buf_planes->plane_info.mp[1].len,
   1684                         CAM_PAD_TO_4K);
   1685         break;
   1686     case CAM_FORMAT_YUV_420_NV21_ADRENO:
   1687         /* 2 planes: Y + CbCr */
   1688         buf_planes->plane_info.num_planes = 2;
   1689 
   1690         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
   1691         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32);
   1692         buf_planes->plane_info.mp[0].offset = 0;
   1693         buf_planes->plane_info.mp[0].len =
   1694             PAD_TO_SIZE(stride * scanline,
   1695                         CAM_PAD_TO_4K);
   1696         buf_planes->plane_info.mp[0].offset_x = 0;
   1697         buf_planes->plane_info.mp[0].offset_y = 0;
   1698         buf_planes->plane_info.mp[0].stride = stride;
   1699         buf_planes->plane_info.mp[0].scanline = scanline;
   1700 
   1701         stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2;
   1702         scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32);
   1703         buf_planes->plane_info.mp[1].offset = 0;
   1704         buf_planes->plane_info.mp[1].len =
   1705             PAD_TO_SIZE(stride * scanline,
   1706                         CAM_PAD_TO_4K);
   1707         buf_planes->plane_info.mp[1].offset_x = 0;
   1708         buf_planes->plane_info.mp[1].offset_y = 0;
   1709         buf_planes->plane_info.mp[1].stride = stride;
   1710         buf_planes->plane_info.mp[1].scanline = scanline;
   1711 
   1712         buf_planes->plane_info.frame_len =
   1713             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
   1714                         buf_planes->plane_info.mp[1].len,
   1715                         CAM_PAD_TO_4K);
   1716         break;
   1717     case CAM_FORMAT_YUV_420_YV12:
   1718         /* 3 planes: Y + Cr + Cb */
   1719         buf_planes->plane_info.num_planes = 3;
   1720 
   1721         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
   1722         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
   1723         buf_planes->plane_info.mp[0].offset = 0;
   1724         buf_planes->plane_info.mp[0].len = stride * scanline;
   1725         buf_planes->plane_info.mp[0].offset_x = 0;
   1726         buf_planes->plane_info.mp[0].offset_y = 0;
   1727         buf_planes->plane_info.mp[0].stride = stride;
   1728         buf_planes->plane_info.mp[0].scanline = scanline;
   1729 
   1730         stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
   1731         scanline = scanline / 2;
   1732         buf_planes->plane_info.mp[1].offset = 0;
   1733         buf_planes->plane_info.mp[1].len =
   1734             stride * scanline;
   1735         buf_planes->plane_info.mp[1].offset_x = 0;
   1736         buf_planes->plane_info.mp[1].offset_y = 0;
   1737         buf_planes->plane_info.mp[1].stride = stride;
   1738         buf_planes->plane_info.mp[1].scanline = scanline;
   1739 
   1740         buf_planes->plane_info.mp[2].offset = 0;
   1741         buf_planes->plane_info.mp[2].len =
   1742             stride * scanline;
   1743         buf_planes->plane_info.mp[2].offset_x = 0;
   1744         buf_planes->plane_info.mp[2].offset_y = 0;
   1745         buf_planes->plane_info.mp[2].stride = stride;
   1746         buf_planes->plane_info.mp[2].scanline = scanline;
   1747 
   1748         buf_planes->plane_info.frame_len =
   1749             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
   1750                         buf_planes->plane_info.mp[1].len +
   1751                         buf_planes->plane_info.mp[2].len,
   1752                         CAM_PAD_TO_4K);
   1753         break;
   1754     case CAM_FORMAT_YUV_422_NV16:
   1755     case CAM_FORMAT_YUV_422_NV61:
   1756         /* 2 planes: Y + CbCr */
   1757         buf_planes->plane_info.num_planes = 2;
   1758 
   1759         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
   1760         scanline = dim->height;
   1761         buf_planes->plane_info.mp[0].offset = 0;
   1762         buf_planes->plane_info.mp[0].len = stride * scanline;
   1763         buf_planes->plane_info.mp[0].offset_x = 0;
   1764         buf_planes->plane_info.mp[0].offset_y = 0;
   1765         buf_planes->plane_info.mp[0].stride = stride;
   1766         buf_planes->plane_info.mp[0].scanline = scanline;
   1767 
   1768         buf_planes->plane_info.mp[1].offset = 0;
   1769         buf_planes->plane_info.mp[1].len = stride * scanline;
   1770         buf_planes->plane_info.mp[1].offset_x = 0;
   1771         buf_planes->plane_info.mp[1].offset_y = 0;
   1772         buf_planes->plane_info.mp[1].stride = stride;
   1773         buf_planes->plane_info.mp[1].scanline = scanline;
   1774 
   1775         buf_planes->plane_info.frame_len =
   1776             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
   1777                         buf_planes->plane_info.mp[1].len,
   1778                         CAM_PAD_TO_4K);
   1779         break;
   1780     default:
   1781         CDBG_ERROR("%s: Invalid cam_format for preview %d",
   1782                    __func__, fmt);
   1783         rc = -1;
   1784         break;
   1785     }
   1786 
   1787     return rc;
   1788 }
   1789 
   1790 /*===========================================================================
   1791  * FUNCTION   : mm_stream_calc_offset_snapshot
   1792  *
   1793  * DESCRIPTION: calculate snapshot/postproc frame offset based on format and
   1794  *              padding information
   1795  *
   1796  * PARAMETERS :
   1797  *   @fmt     : image format
   1798  *   @dim     : image dimension
   1799  *   @padding : padding information
   1800  *   @buf_planes : [out] buffer plane information
   1801  *
   1802  * RETURN     : int32_t type of status
   1803  *              0  -- success
   1804  *              -1 -- failure
   1805  *==========================================================================*/
   1806 int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt,
   1807                                        cam_dimension_t *dim,
   1808                                        cam_padding_info_t *padding,
   1809                                        cam_stream_buf_plane_info_t *buf_planes)
   1810 {
   1811     int32_t rc = 0;
   1812     uint8_t isAFamily = mm_camera_util_chip_is_a_family();
   1813     int offset_x = 0, offset_y = 0;
   1814     int stride = 0, scanline = 0;
   1815 
   1816     if (isAFamily) {
   1817         stride = dim->width;
   1818         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_16);
   1819         offset_x = 0;
   1820         offset_y = scanline - dim->height;
   1821         scanline += offset_y; /* double padding */
   1822     } else {
   1823         stride = PAD_TO_SIZE(dim->width,
   1824                              padding->width_padding);
   1825         scanline = PAD_TO_SIZE(dim->height,
   1826                                padding->height_padding);
   1827         offset_x = 0;
   1828         offset_y = 0;
   1829     }
   1830 
   1831     switch (fmt) {
   1832     case CAM_FORMAT_YUV_420_NV12:
   1833     case CAM_FORMAT_YUV_420_NV21:
   1834         /* 2 planes: Y + CbCr */
   1835         buf_planes->plane_info.num_planes = 2;
   1836 
   1837         buf_planes->plane_info.mp[0].len =
   1838             PAD_TO_SIZE(stride * scanline,
   1839                         padding->plane_padding);
   1840         buf_planes->plane_info.mp[0].offset =
   1841             PAD_TO_SIZE(offset_x + stride * offset_y,
   1842                         padding->plane_padding);
   1843         buf_planes->plane_info.mp[0].offset_x = offset_x;
   1844         buf_planes->plane_info.mp[0].offset_y = offset_y;
   1845         buf_planes->plane_info.mp[0].stride = stride;
   1846         buf_planes->plane_info.mp[0].scanline = scanline;
   1847 
   1848         scanline = scanline / 2;
   1849         buf_planes->plane_info.mp[1].len =
   1850             PAD_TO_SIZE(stride * scanline,
   1851                         padding->plane_padding);
   1852         buf_planes->plane_info.mp[1].offset =
   1853             PAD_TO_SIZE(offset_x + stride * offset_y,
   1854                         padding->plane_padding);
   1855         buf_planes->plane_info.mp[1].offset_x = offset_x;
   1856         buf_planes->plane_info.mp[1].offset_y = offset_y;
   1857         buf_planes->plane_info.mp[1].stride = stride;
   1858         buf_planes->plane_info.mp[1].scanline = scanline;
   1859 
   1860         buf_planes->plane_info.frame_len =
   1861             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
   1862                         buf_planes->plane_info.mp[1].len,
   1863                         CAM_PAD_TO_4K);
   1864         break;
   1865     case CAM_FORMAT_YUV_420_YV12:
   1866         /* 3 planes: Y + Cr + Cb */
   1867         buf_planes->plane_info.num_planes = 3;
   1868 
   1869         buf_planes->plane_info.mp[0].offset =
   1870             PAD_TO_SIZE(offset_x + stride * offset_y,
   1871                         padding->plane_padding);
   1872         buf_planes->plane_info.mp[0].len =
   1873             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
   1874         buf_planes->plane_info.mp[0].offset_x = offset_x;
   1875         buf_planes->plane_info.mp[0].offset_y = offset_y;
   1876         buf_planes->plane_info.mp[0].stride = stride;
   1877         buf_planes->plane_info.mp[0].scanline = scanline;
   1878 
   1879         stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
   1880         scanline = scanline / 2;
   1881         buf_planes->plane_info.mp[1].offset =
   1882             PAD_TO_SIZE(offset_x + stride * offset_y,
   1883                         padding->plane_padding);
   1884         buf_planes->plane_info.mp[1].len =
   1885             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
   1886         buf_planes->plane_info.mp[1].offset_x = offset_x;
   1887         buf_planes->plane_info.mp[1].offset_y = offset_y;
   1888         buf_planes->plane_info.mp[1].stride = stride;
   1889         buf_planes->plane_info.mp[1].scanline = scanline;
   1890 
   1891         buf_planes->plane_info.mp[2].offset =
   1892             PAD_TO_SIZE(offset_x + stride * offset_y,
   1893                         padding->plane_padding);
   1894         buf_planes->plane_info.mp[2].len =
   1895             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
   1896         buf_planes->plane_info.mp[2].offset_x = offset_x;
   1897         buf_planes->plane_info.mp[2].offset_y = offset_y;
   1898         buf_planes->plane_info.mp[2].stride = stride;
   1899         buf_planes->plane_info.mp[2].scanline = scanline;
   1900 
   1901         buf_planes->plane_info.frame_len =
   1902             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
   1903                         buf_planes->plane_info.mp[1].len +
   1904                         buf_planes->plane_info.mp[2].len,
   1905                         CAM_PAD_TO_4K);
   1906         break;
   1907     case CAM_FORMAT_YUV_422_NV16:
   1908     case CAM_FORMAT_YUV_422_NV61:
   1909         /* 2 planes: Y + CbCr */
   1910         buf_planes->plane_info.num_planes = 2;
   1911         buf_planes->plane_info.mp[0].len =
   1912             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
   1913         buf_planes->plane_info.mp[0].offset =
   1914             PAD_TO_SIZE(offset_x + stride * offset_y,
   1915                         padding->plane_padding);
   1916         buf_planes->plane_info.mp[0].offset_x = offset_x;
   1917         buf_planes->plane_info.mp[0].offset_y = offset_y;
   1918         buf_planes->plane_info.mp[0].stride = stride;
   1919         buf_planes->plane_info.mp[0].scanline = scanline;
   1920 
   1921         buf_planes->plane_info.mp[1].len =
   1922             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
   1923         buf_planes->plane_info.mp[1].offset =
   1924             PAD_TO_SIZE(offset_x + stride * offset_y,
   1925                         padding->plane_padding);
   1926         buf_planes->plane_info.mp[1].offset_x = offset_x;
   1927         buf_planes->plane_info.mp[1].offset_y = offset_y;
   1928         buf_planes->plane_info.mp[1].stride = stride;
   1929         buf_planes->plane_info.mp[1].scanline = scanline;
   1930 
   1931         buf_planes->plane_info.frame_len = PAD_TO_SIZE(
   1932             buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len,
   1933             CAM_PAD_TO_4K);
   1934         break;
   1935     default:
   1936         CDBG_ERROR("%s: Invalid cam_format for snapshot %d",
   1937                    __func__, fmt);
   1938         rc = -1;
   1939         break;
   1940     }
   1941 
   1942     return rc;
   1943 }
   1944 
   1945 /*===========================================================================
   1946  * FUNCTION   : mm_stream_calc_offset_raw
   1947  *
   1948  * DESCRIPTION: calculate raw frame offset based on format and padding information
   1949  *
   1950  * PARAMETERS :
   1951  *   @fmt     : image format
   1952  *   @dim     : image dimension
   1953  *   @padding : padding information
   1954  *   @buf_planes : [out] buffer plane information
   1955  *
   1956  * RETURN     : int32_t type of status
   1957  *              0  -- success
   1958  *              -1 -- failure
   1959  *==========================================================================*/
   1960 int32_t mm_stream_calc_offset_raw(cam_format_t fmt,
   1961                                   cam_dimension_t *dim,
   1962                                   cam_padding_info_t *padding,
   1963                                   cam_stream_buf_plane_info_t *buf_planes)
   1964 {
   1965     int32_t rc = 0;
   1966     int stride = 0;
   1967     int scanline = dim->height;
   1968 
   1969     switch (fmt) {
   1970     case CAM_FORMAT_YUV_RAW_8BIT_YUYV:
   1971     case CAM_FORMAT_YUV_RAW_8BIT_YVYU:
   1972     case CAM_FORMAT_YUV_RAW_8BIT_UYVY:
   1973     case CAM_FORMAT_YUV_RAW_8BIT_VYUY:
   1974     case CAM_FORMAT_JPEG_RAW_8BIT:
   1975     case CAM_FORMAT_META_RAW_8BIT:
   1976         /* 1 plane */
   1977         /* Every 16 pixels occupy 16 bytes */
   1978         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
   1979         buf_planes->plane_info.num_planes = 1;
   1980         buf_planes->plane_info.mp[0].offset = 0;
   1981         buf_planes->plane_info.mp[0].len =
   1982             PAD_TO_SIZE(stride * scanline * 2, padding->plane_padding);
   1983         buf_planes->plane_info.frame_len =
   1984             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
   1985         buf_planes->plane_info.mp[0].offset_x =0;
   1986         buf_planes->plane_info.mp[0].offset_y = 0;
   1987         buf_planes->plane_info.mp[0].stride = stride;
   1988         buf_planes->plane_info.mp[0].scanline = scanline;
   1989         break;
   1990     case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GBRG:
   1991     case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GRBG:
   1992     case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_RGGB:
   1993     case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_BGGR:
   1994     case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GBRG:
   1995     case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GRBG:
   1996     case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_RGGB:
   1997     case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_BGGR:
   1998     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GBRG:
   1999     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GRBG:
   2000     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_RGGB:
   2001     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_BGGR:
   2002     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GBRG:
   2003     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GRBG:
   2004     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_RGGB:
   2005     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_BGGR:
   2006     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GBRG:
   2007     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GRBG:
   2008     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_RGGB:
   2009     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_BGGR:
   2010         /* 1 plane */
   2011         /* Every 16 pixels occupy 16 bytes */
   2012         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
   2013         buf_planes->plane_info.num_planes = 1;
   2014         buf_planes->plane_info.mp[0].offset = 0;
   2015         buf_planes->plane_info.mp[0].len =
   2016             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
   2017         buf_planes->plane_info.frame_len =
   2018             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
   2019         buf_planes->plane_info.mp[0].offset_x =0;
   2020         buf_planes->plane_info.mp[0].offset_y = 0;
   2021         buf_planes->plane_info.mp[0].stride = stride;
   2022         buf_planes->plane_info.mp[0].scanline = scanline;
   2023         break;
   2024     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG:
   2025     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG:
   2026     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB:
   2027     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR:
   2028     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GBRG:
   2029     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GRBG:
   2030     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_RGGB:
   2031     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_BGGR:
   2032         /* Every 12 pixels occupy 16 bytes */
   2033         stride = (dim->width + 11)/12 * 16;
   2034         buf_planes->plane_info.num_planes = 1;
   2035         buf_planes->plane_info.mp[0].offset = 0;
   2036         buf_planes->plane_info.mp[0].len =
   2037             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
   2038         buf_planes->plane_info.frame_len =
   2039             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
   2040         buf_planes->plane_info.mp[0].offset_x =0;
   2041         buf_planes->plane_info.mp[0].offset_y = 0;
   2042         buf_planes->plane_info.mp[0].stride = stride;
   2043         buf_planes->plane_info.mp[0].scanline = scanline;
   2044         break;
   2045     case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GBRG:
   2046     case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GRBG:
   2047     case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_RGGB:
   2048     case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_BGGR:
   2049     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GBRG:
   2050     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GRBG:
   2051     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_RGGB:
   2052     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_BGGR:
   2053         /* Every 10 pixels occupy 16 bytes */
   2054         stride = (dim->width + 9)/10 * 16;
   2055         buf_planes->plane_info.num_planes = 1;
   2056         buf_planes->plane_info.mp[0].offset = 0;
   2057         buf_planes->plane_info.mp[0].len =
   2058             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
   2059         buf_planes->plane_info.frame_len =
   2060             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
   2061         buf_planes->plane_info.mp[0].offset_x =0;
   2062         buf_planes->plane_info.mp[0].offset_y = 0;
   2063         buf_planes->plane_info.mp[0].stride = stride;
   2064         buf_planes->plane_info.mp[0].scanline = scanline;
   2065         break;
   2066     case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG:
   2067     case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GRBG:
   2068     case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_RGGB:
   2069     case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_BGGR:
   2070     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GBRG:
   2071     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GRBG:
   2072     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_RGGB:
   2073     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_BGGR:
   2074         /* Every 64 pixels occupy 80 bytes */
   2075         stride = PAD_TO_SIZE(
   2076                 PAD_TO_SIZE(dim->width, CAM_PAD_TO_4)*5/4, CAM_PAD_TO_16);
   2077         buf_planes->plane_info.num_planes = 1;
   2078         buf_planes->plane_info.mp[0].offset = 0;
   2079         buf_planes->plane_info.mp[0].len =
   2080             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
   2081         buf_planes->plane_info.frame_len =
   2082             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
   2083         buf_planes->plane_info.mp[0].offset_x =0;
   2084         buf_planes->plane_info.mp[0].offset_y = 0;
   2085         buf_planes->plane_info.mp[0].stride = stride;
   2086         buf_planes->plane_info.mp[0].scanline = scanline;
   2087         break;
   2088     case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GBRG:
   2089     case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GRBG:
   2090     case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_RGGB:
   2091     case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_BGGR:
   2092     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GBRG:
   2093     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GRBG:
   2094     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_RGGB:
   2095     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_BGGR:
   2096         /* Every 32 pixels occupy 48 bytes */
   2097         stride = PAD_TO_SIZE(PAD_TO_SIZE(dim->width, 2)*3/2, CAM_PAD_TO_16);
   2098         buf_planes->plane_info.num_planes = 1;
   2099         buf_planes->plane_info.mp[0].offset = 0;
   2100         buf_planes->plane_info.mp[0].len =
   2101             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
   2102         buf_planes->plane_info.frame_len =
   2103             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
   2104         buf_planes->plane_info.mp[0].offset_x =0;
   2105         buf_planes->plane_info.mp[0].offset_y = 0;
   2106         buf_planes->plane_info.mp[0].stride = stride;
   2107         buf_planes->plane_info.mp[0].scanline = scanline;
   2108         break;
   2109     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GBRG:
   2110     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GRBG:
   2111     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_RGGB:
   2112     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_BGGR:
   2113     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GBRG:
   2114     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GRBG:
   2115     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_RGGB:
   2116     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_BGGR:
   2117     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GBRG:
   2118     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GRBG:
   2119     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_RGGB:
   2120     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_BGGR:
   2121         /* Every 8 pixels occupy 16 bytes */
   2122         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_8) * 2;
   2123         buf_planes->plane_info.num_planes = 1;
   2124         buf_planes->plane_info.mp[0].offset = 0;
   2125         buf_planes->plane_info.mp[0].len =
   2126             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
   2127         buf_planes->plane_info.frame_len =
   2128             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
   2129         buf_planes->plane_info.mp[0].offset_x =0;
   2130         buf_planes->plane_info.mp[0].offset_y = 0;
   2131         buf_planes->plane_info.mp[0].stride = stride;
   2132         buf_planes->plane_info.mp[0].scanline = scanline;
   2133         break;
   2134     default:
   2135         CDBG_ERROR("%s: Invalid cam_format %d for raw stream",
   2136                    __func__, fmt);
   2137         rc = -1;
   2138         break;
   2139     }
   2140 
   2141     return rc;
   2142 }
   2143 
   2144 /*===========================================================================
   2145  * FUNCTION   : mm_stream_calc_offset_video
   2146  *
   2147  * DESCRIPTION: calculate video frame offset based on format and
   2148  *              padding information
   2149  *
   2150  * PARAMETERS :
   2151  *   @dim     : image dimension
   2152  *   @buf_planes : [out] buffer plane information
   2153  *
   2154  * RETURN     : int32_t type of status
   2155  *              0  -- success
   2156  *              -1 -- failure
   2157  *==========================================================================*/
   2158 #ifdef VENUS_PRESENT
   2159 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim,
   2160                                     cam_stream_buf_plane_info_t *buf_planes)
   2161 {
   2162     int stride = 0, scanline = 0;
   2163 
   2164     // using Venus
   2165     stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
   2166     scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
   2167 
   2168     buf_planes->plane_info.frame_len =
   2169         VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height);
   2170     buf_planes->plane_info.num_planes = 2;
   2171     buf_planes->plane_info.mp[0].len = stride * scanline;
   2172     buf_planes->plane_info.mp[0].offset = 0;
   2173     buf_planes->plane_info.mp[0].offset_x =0;
   2174     buf_planes->plane_info.mp[0].offset_y = 0;
   2175     buf_planes->plane_info.mp[0].stride = stride;
   2176     buf_planes->plane_info.mp[0].scanline = scanline;
   2177     stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
   2178     scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
   2179     buf_planes->plane_info.mp[1].len =
   2180         buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
   2181     buf_planes->plane_info.mp[1].offset = 0;
   2182     buf_planes->plane_info.mp[1].offset_x =0;
   2183     buf_planes->plane_info.mp[1].offset_y = 0;
   2184     buf_planes->plane_info.mp[1].stride = stride;
   2185     buf_planes->plane_info.mp[1].scanline = scanline;
   2186 
   2187     return 0;
   2188 }
   2189 #else
   2190 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim,
   2191                                     cam_stream_buf_plane_info_t *buf_planes)
   2192 {
   2193     int stride = 0, scanline = 0;
   2194 
   2195     buf_planes->plane_info.num_planes = 2;
   2196 
   2197     stride = dim->width;
   2198     scanline = dim->height;
   2199     buf_planes->plane_info.mp[0].len =
   2200         PAD_TO_SIZE(stride * scanline, CAM_PAD_TO_2K);
   2201     buf_planes->plane_info.mp[0].offset = 0;
   2202     buf_planes->plane_info.mp[0].offset_x =0;
   2203     buf_planes->plane_info.mp[0].offset_y = 0;
   2204     buf_planes->plane_info.mp[0].stride = stride;
   2205     buf_planes->plane_info.mp[0].scanline = scanline;
   2206 
   2207     stride = dim->width;
   2208     scanline = dim->height / 2;
   2209     buf_planes->plane_info.mp[1].len =
   2210         PAD_TO_SIZE(stride * scanline, CAM_PAD_TO_2K);
   2211     buf_planes->plane_info.mp[1].offset = 0;
   2212     buf_planes->plane_info.mp[1].offset_x =0;
   2213     buf_planes->plane_info.mp[1].offset_y = 0;
   2214     buf_planes->plane_info.mp[1].stride = stride;
   2215     buf_planes->plane_info.mp[1].scanline = scanline;
   2216 
   2217     buf_planes->plane_info.frame_len =
   2218         PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
   2219                     buf_planes->plane_info.mp[1].len,
   2220                     CAM_PAD_TO_4K);
   2221 
   2222     return 0;
   2223 }
   2224 #endif
   2225 
   2226 /*===========================================================================
   2227  * FUNCTION   : mm_stream_calc_offset_metadata
   2228  *
   2229  * DESCRIPTION: calculate metadata frame offset based on format and
   2230  *              padding information
   2231  *
   2232  * PARAMETERS :
   2233  *   @dim     : image dimension
   2234  *   @padding : padding information
   2235  *   @buf_planes : [out] buffer plane information
   2236  *
   2237  * RETURN     : int32_t type of status
   2238  *              0  -- success
   2239  *              -1 -- failure
   2240  *==========================================================================*/
   2241 int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim,
   2242                                        cam_padding_info_t *padding,
   2243                                        cam_stream_buf_plane_info_t *buf_planes)
   2244 {
   2245     int32_t rc = 0;
   2246     buf_planes->plane_info.num_planes = 1;
   2247     buf_planes->plane_info.mp[0].offset = 0;
   2248     buf_planes->plane_info.mp[0].len =
   2249         PAD_TO_SIZE(dim->width * dim->height, padding->plane_padding);
   2250     buf_planes->plane_info.frame_len =
   2251         buf_planes->plane_info.mp[0].len;
   2252 
   2253     buf_planes->plane_info.mp[0].offset_x =0;
   2254     buf_planes->plane_info.mp[0].offset_y = 0;
   2255     buf_planes->plane_info.mp[0].stride = dim->width;
   2256     buf_planes->plane_info.mp[0].scanline = dim->height;
   2257     return rc;
   2258 }
   2259 
   2260 /*===========================================================================
   2261  * FUNCTION   : mm_stream_calc_offset_postproc
   2262  *
   2263  * DESCRIPTION: calculate postprocess frame offset
   2264  *
   2265  * PARAMETERS :
   2266  *   @stream_info: ptr to stream info
   2267  *   @padding : padding information
   2268  *   @buf_planes : [out] buffer plane information
   2269  *
   2270  * RETURN     : int32_t type of status
   2271  *              0  -- success
   2272  *              -1 -- failure
   2273  *==========================================================================*/
   2274 int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info,
   2275                                        cam_padding_info_t *padding,
   2276                                        cam_stream_buf_plane_info_t *buf_planes)
   2277 {
   2278     int32_t rc = 0;
   2279     cam_stream_type_t type = CAM_STREAM_TYPE_DEFAULT;
   2280     if (stream_info->reprocess_config.pp_type == CAM_OFFLINE_REPROCESS_TYPE) {
   2281         type = stream_info->reprocess_config.offline.input_stream_type;
   2282         if (CAM_STREAM_TYPE_DEFAULT == type) {
   2283             if (buf_planes->plane_info.frame_len == 0) {
   2284                 // take offset from input source
   2285                 *buf_planes = stream_info->reprocess_config.offline.input_buf_planes;
   2286                 return rc;
   2287             }
   2288         } else {
   2289             type = stream_info->reprocess_config.offline.input_stream_type;
   2290         }
   2291     } else {
   2292         type = stream_info->reprocess_config.online.input_stream_type;
   2293     }
   2294 
   2295     switch (type) {
   2296     case CAM_STREAM_TYPE_PREVIEW:
   2297     case CAM_STREAM_TYPE_CALLBACK:
   2298     case CAM_STREAM_TYPE_POSTVIEW:
   2299         rc = mm_stream_calc_offset_preview(stream_info->fmt,
   2300                                            &stream_info->dim,
   2301                                            buf_planes);
   2302         break;
   2303     case CAM_STREAM_TYPE_SNAPSHOT:
   2304     case CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT:
   2305         rc = mm_stream_calc_offset_snapshot(stream_info->fmt,
   2306                                             &stream_info->dim,
   2307                                             padding,
   2308                                             buf_planes);
   2309         break;
   2310     case CAM_STREAM_TYPE_VIDEO:
   2311         rc = mm_stream_calc_offset_video(&stream_info->dim,
   2312                                          buf_planes);
   2313         break;
   2314     case CAM_STREAM_TYPE_RAW:
   2315         rc = mm_stream_calc_offset_raw(stream_info->fmt,
   2316                                        &stream_info->dim,
   2317                                        padding,
   2318                                        buf_planes);
   2319         break;
   2320     case CAM_STREAM_TYPE_METADATA:
   2321         rc = mm_stream_calc_offset_metadata(&stream_info->dim,
   2322                                             padding,
   2323                                             buf_planes);
   2324         break;
   2325     default:
   2326         CDBG_ERROR("%s: not supported for stream type %d",
   2327                    __func__, type);
   2328         rc = -1;
   2329         break;
   2330     }
   2331     return rc;
   2332 }
   2333 
   2334 /*===========================================================================
   2335  * FUNCTION   : mm_stream_calc_offset
   2336  *
   2337  * DESCRIPTION: calculate frame offset based on format and padding information
   2338  *
   2339  * PARAMETERS :
   2340  *   @my_obj  : stream object
   2341  *
   2342  * RETURN     : int32_t type of status
   2343  *              0  -- success
   2344  *              -1 -- failure
   2345  *==========================================================================*/
   2346 int32_t mm_stream_calc_offset(mm_stream_t *my_obj)
   2347 {
   2348     int32_t rc = 0;
   2349 
   2350     cam_dimension_t dim = my_obj->stream_info->dim;
   2351     if (my_obj->stream_info->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
   2352         if (my_obj->stream_info->pp_config.rotation == ROTATE_90 ||
   2353             my_obj->stream_info->pp_config.rotation == ROTATE_270) {
   2354             // rotated by 90 or 270, need to switch width and height
   2355             dim.width = my_obj->stream_info->dim.height;
   2356             dim.height = my_obj->stream_info->dim.width;
   2357         }
   2358     }
   2359 
   2360     switch (my_obj->stream_info->stream_type) {
   2361     case CAM_STREAM_TYPE_PREVIEW:
   2362     case CAM_STREAM_TYPE_CALLBACK:
   2363     case CAM_STREAM_TYPE_POSTVIEW:
   2364         rc = mm_stream_calc_offset_preview(my_obj->stream_info->fmt,
   2365                                            &dim,
   2366                                            &my_obj->stream_info->buf_planes);
   2367         break;
   2368     case CAM_STREAM_TYPE_SNAPSHOT:
   2369     case CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT:
   2370         rc = mm_stream_calc_offset_snapshot(my_obj->stream_info->fmt,
   2371                                             &dim,
   2372                                             &my_obj->padding_info,
   2373                                             &my_obj->stream_info->buf_planes);
   2374         break;
   2375     case CAM_STREAM_TYPE_OFFLINE_PROC:
   2376         rc = mm_stream_calc_offset_postproc(my_obj->stream_info,
   2377                                             &my_obj->padding_info,
   2378                                             &my_obj->stream_info->buf_planes);
   2379         break;
   2380     case CAM_STREAM_TYPE_VIDEO:
   2381         rc = mm_stream_calc_offset_video(&dim,
   2382                                          &my_obj->stream_info->buf_planes);
   2383         break;
   2384     case CAM_STREAM_TYPE_RAW:
   2385         rc = mm_stream_calc_offset_raw(my_obj->stream_info->fmt,
   2386                                        &dim,
   2387                                        &my_obj->padding_info,
   2388                                        &my_obj->stream_info->buf_planes);
   2389         break;
   2390     case CAM_STREAM_TYPE_METADATA:
   2391         rc = mm_stream_calc_offset_metadata(&dim,
   2392                                             &my_obj->padding_info,
   2393                                             &my_obj->stream_info->buf_planes);
   2394         break;
   2395     default:
   2396         CDBG_ERROR("%s: not supported for stream type %d",
   2397                    __func__, my_obj->stream_info->stream_type);
   2398         rc = -1;
   2399         break;
   2400     }
   2401 
   2402     my_obj->frame_offset = my_obj->stream_info->buf_planes.plane_info;
   2403     return rc;
   2404 }
   2405 
   2406 /*===========================================================================
   2407  * FUNCTION   : mm_stream_sync_info
   2408  *
   2409  * DESCRIPTION: synchronize stream information with server
   2410  *
   2411  * PARAMETERS :
   2412  *   @my_obj  : stream object
   2413  *
   2414  * RETURN     : int32_t type of status
   2415  *              0  -- success
   2416  *              -1 -- failure
   2417  * NOTE       : assume stream info buffer is mapped to server and filled in with
   2418  *              stream information by upper layer. This call will let server to
   2419  *              synchornize the stream information with HAL. If server find any
   2420  *              fields that need to be changed accroding to hardware configuration,
   2421  *              server will modify corresponding fields so that HAL could know
   2422  *              about it.
   2423  *==========================================================================*/
   2424 int32_t mm_stream_sync_info(mm_stream_t *my_obj)
   2425 {
   2426     int32_t rc = 0;
   2427     int32_t value = 0;
   2428     my_obj->stream_info->stream_svr_id = my_obj->server_stream_id;
   2429     rc = mm_stream_calc_offset(my_obj);
   2430 
   2431     if (rc == 0) {
   2432         rc = mm_camera_util_s_ctrl(my_obj->fd,
   2433                                    CAM_PRIV_STREAM_INFO_SYNC,
   2434                                    &value);
   2435     }
   2436     return rc;
   2437 }
   2438 
   2439 /*===========================================================================
   2440  * FUNCTION   : mm_stream_set_fmt
   2441  *
   2442  * DESCRIPTION: set stream format to kernel via v4l2 ioctl
   2443  *
   2444  * PARAMETERS :
   2445  *   @my_obj  : stream object
   2446  *
   2447  * RETURN     : int32_t type of status
   2448  *              0  -- success
   2449  *              -1 -- failure
   2450  *==========================================================================*/
   2451 int32_t mm_stream_set_fmt(mm_stream_t *my_obj)
   2452 {
   2453     int32_t rc = 0;
   2454     struct v4l2_format fmt;
   2455     struct msm_v4l2_format_data msm_fmt;
   2456     int i;
   2457 
   2458     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
   2459          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
   2460 
   2461     if (my_obj->stream_info->dim.width == 0 ||
   2462         my_obj->stream_info->dim.height == 0) {
   2463         CDBG_ERROR("%s:invalid input[w=%d,h=%d,fmt=%d]\n",
   2464                    __func__,
   2465                    my_obj->stream_info->dim.width,
   2466                    my_obj->stream_info->dim.height,
   2467                    my_obj->stream_info->fmt);
   2468         return -1;
   2469     }
   2470 
   2471     memset(&fmt, 0, sizeof(fmt));
   2472     memset(&msm_fmt, 0, sizeof(msm_fmt));
   2473     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   2474     msm_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
   2475     msm_fmt.width = my_obj->stream_info->dim.width;
   2476     msm_fmt.height = my_obj->stream_info->dim.height;
   2477     msm_fmt.pixelformat = mm_stream_get_v4l2_fmt(my_obj->stream_info->fmt);
   2478     msm_fmt.num_planes = my_obj->frame_offset.num_planes;
   2479     for (i = 0; i < msm_fmt.num_planes; i++) {
   2480         msm_fmt.plane_sizes[i] = my_obj->frame_offset.mp[i].len;
   2481     }
   2482 
   2483     memcpy(fmt.fmt.raw_data, &msm_fmt, sizeof(msm_fmt));
   2484     rc = ioctl(my_obj->fd, VIDIOC_S_FMT, &fmt);
   2485     return rc;
   2486 }
   2487 
   2488 /*===========================================================================
   2489  * FUNCTION   : mm_stream_buf_done
   2490  *
   2491  * DESCRIPTION: enqueue buffer back to kernel
   2492  *
   2493  * PARAMETERS :
   2494  *   @my_obj       : stream object
   2495  *   @frame        : frame to be enqueued back to kernel
   2496  *
   2497  * RETURN     : int32_t type of status
   2498  *              0  -- success
   2499  *              -1 -- failure
   2500  *==========================================================================*/
   2501 int32_t mm_stream_buf_done(mm_stream_t * my_obj,
   2502                            mm_camera_buf_def_t *frame)
   2503 {
   2504     int32_t rc = 0;
   2505     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
   2506          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
   2507 
   2508     pthread_mutex_lock(&my_obj->buf_lock);
   2509     if(my_obj->buf_status[frame->buf_idx].buf_refcnt == 0) {
   2510         CDBG("%s: Error Trying to free second time?(idx=%d) count=%d\n",
   2511                    __func__, frame->buf_idx,
   2512                    my_obj->buf_status[frame->buf_idx].buf_refcnt);
   2513         rc = -1;
   2514     }else{
   2515         my_obj->buf_status[frame->buf_idx].buf_refcnt--;
   2516         if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) {
   2517             CDBG("<DEBUG> : Buf done for buffer:%d, stream:%d", frame->buf_idx, frame->stream_type);
   2518             rc = mm_stream_qbuf(my_obj, frame);
   2519             if(rc < 0) {
   2520                 CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) errno=%d, %s\n",
   2521                            __func__, frame->buf_idx, errno, strerror(errno));
   2522             } else {
   2523                 my_obj->buf_status[frame->buf_idx].in_kernel = 1;
   2524             }
   2525         }else{
   2526             CDBG("<DEBUG> : Still ref count pending count :%d",
   2527                  my_obj->buf_status[frame->buf_idx].buf_refcnt);
   2528             CDBG("<DEBUG> : for buffer:%p:%d",
   2529                  my_obj, frame->buf_idx);
   2530         }
   2531     }
   2532     pthread_mutex_unlock(&my_obj->buf_lock);
   2533     return rc;
   2534 }
   2535 
   2536 /*===========================================================================
   2537  * FUNCTION   : mm_stream_reg_buf_cb
   2538  *
   2539  * DESCRIPTION: Allow other stream to register dataCB at this stream.
   2540  *
   2541  * PARAMETERS :
   2542  *   @my_obj       : stream object
   2543  *   @val          : ptr to info about the callback to be registered
   2544  *
   2545  * RETURN     : int32_t type of status
   2546  *              0  -- success
   2547  *              -1 -- failure
   2548  *==========================================================================*/
   2549 int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj,
   2550                              mm_stream_data_cb_t *val)
   2551 {
   2552     int32_t rc = -1;
   2553     uint8_t i;
   2554     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
   2555          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
   2556 
   2557     pthread_mutex_lock(&my_obj->cb_lock);
   2558     for (i=0 ;i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
   2559         if(NULL == my_obj->buf_cb[i].cb) {
   2560             my_obj->buf_cb[i] = *val;
   2561             rc = 0;
   2562             break;
   2563         }
   2564     }
   2565     pthread_mutex_unlock(&my_obj->cb_lock);
   2566 
   2567     return rc;
   2568 }
   2569