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