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