Home | History | Annotate | Download | only in src
      1 /*
      2 Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
      3 
      4 Redistribution and use in source and binary forms, with or without
      5 modification, are permitted provided that the following conditions are
      6 met:
      7     * Redistributions of source code must retain the above copyright
      8       notice, this list of conditions and the following disclaimer.
      9     * Redistributions in binary form must reproduce the above
     10       copyright notice, this list of conditions and the following
     11       disclaimer in the documentation and/or other materials provided
     12       with the distribution.
     13     * Neither the name of The Linux Foundation nor the names of its
     14       contributors may be used to endorse or promote products derived
     15       from this software without specific prior written permission.
     16 
     17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     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 <semaphore.h>
     38 
     39 #include "mm_camera_dbg.h"
     40 #include "mm_camera_interface.h"
     41 #include "mm_camera.h"
     42 
     43 extern mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler);
     44 extern mm_channel_t * mm_camera_util_get_channel_by_handler(
     45                                     mm_camera_obj_t * cam_obj,
     46                                     uint32_t handler);
     47 extern int32_t mm_camera_send_native_ctrl_cmd(mm_camera_obj_t * my_obj,
     48                                        cam_ctrl_type type,
     49                                        uint32_t length,
     50                                        void *value);
     51 extern int32_t mm_camera_send_native_ctrl_timeout_cmd(mm_camera_obj_t * my_obj,
     52                                                cam_ctrl_type type,
     53                                                uint32_t length,
     54                                                void *value,
     55                                                int timeout);
     56 
     57 /* internal function declare goes here */
     58 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
     59                         mm_camera_buf_def_t *buf);
     60 int32_t mm_channel_init(mm_channel_t *my_obj);
     61 void mm_channel_release(mm_channel_t *my_obj);
     62 uint32_t mm_channel_add_stream(mm_channel_t *my_obj,
     63                                    mm_camera_buf_notify_t buf_cb, void *user_data,
     64                                    uint32_t ext_image_mode, uint32_t sensor_idx);
     65 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
     66                                    uint32_t stream_id);
     67 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
     68                                  uint32_t stream_id,
     69                                  mm_camera_stream_config_t *config);
     70 int32_t mm_channel_bundle_stream(mm_channel_t *my_obj,
     71                                  mm_camera_buf_notify_t super_frame_notify_cb,
     72                                  void *user_data,
     73                                  mm_camera_bundle_attr_t *attr,
     74                                  uint8_t num_streams,
     75                                  uint32_t *stream_ids);
     76 int32_t mm_channel_destroy_bundle(mm_channel_t *my_obj);
     77 int32_t mm_channel_start_streams(mm_channel_t *my_obj,
     78                                  uint8_t num_streams,
     79                                  uint32_t *stream_ids);
     80 int32_t mm_channel_stop_streams(mm_channel_t *my_obj,
     81                                 uint8_t num_streams,
     82                                 uint32_t *stream_ids,
     83                                 uint8_t tear_down_flag);
     84 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj, uint32_t num_buf_requested);
     85 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj);
     86 int32_t mm_channel_start_focus(mm_channel_t *my_obj,
     87                                uint32_t sensor_idx,
     88                                uint32_t focus_mode);
     89 int32_t mm_channel_abort_focus(mm_channel_t *my_obj,
     90                                uint32_t sensor_idx);
     91 int32_t mm_channel_prepare_snapshot(mm_channel_t *my_obj,
     92                                     uint32_t sensor_idx);
     93 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
     94                                    uint32_t s_id,
     95                                    void *value);
     96 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
     97                                    uint32_t s_id,
     98                                    void *value);
     99 int32_t mm_channel_do_post_processing(mm_channel_t *my_obj,
    100                                       mm_channel_queue_node_t *super_buf);
    101 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t *my_obj,
    102                                              mm_channel_queue_t *queue);
    103 int32_t mm_channel_superbuf_skip(mm_channel_t *my_obj,
    104                                  mm_channel_queue_t *queue);
    105 uint32_t mm_channel_open_repro_isp(mm_channel_t *my_obj,
    106                                    mm_camera_repro_isp_type_t isp_type);
    107 int32_t mm_channel_close_repro_isp(mm_channel_t *my_obj,
    108                                    uint32_t repro_handle);
    109 int32_t mm_channel_config_repro_isp(mm_channel_t *my_obj,
    110                                     uint32_t repro_handle,
    111                                     mm_camera_repro_isp_config_t *config);
    112 int32_t mm_channel_repro_isp_dest_stream_ops(mm_channel_t *my_obj,
    113                                              uint32_t repro_handle,
    114                                              uint32_t stream_handle,
    115                                              uint8_t attach_flag);
    116 int32_t mm_channel_repro_isp_ops(mm_channel_t *my_obj,
    117                                  uint32_t repro_handle,
    118                                  uint32_t stream_id,
    119                                  uint8_t start_flag);
    120 int32_t mm_channel_reprocess(mm_channel_t *my_obj,
    121                              uint32_t repro_handle,
    122                              mm_camera_repro_data_t *repro_data);
    123 
    124 /* state machine function declare */
    125 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
    126                           mm_channel_evt_type_t evt,
    127                           void * in_val,
    128                           void * out_val);
    129 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
    130                           mm_channel_evt_type_t evt,
    131                           void * in_val,
    132                           void * out_val);
    133 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
    134                           mm_channel_evt_type_t evt,
    135                           void * in_val,
    136                           void * out_val);
    137 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
    138                           mm_channel_evt_type_t evt,
    139                           void * in_val,
    140                           void * out_val);
    141 
    142 /* channel super queue functions */
    143 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue);
    144 int32_t mm_channel_superbuf_queue_deinit(mm_channel_t *my_obj,
    145                                          mm_channel_queue_t * queue);
    146 int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj,
    147                                              mm_channel_queue_t * queue,
    148                                              mm_camera_buf_info_t *buf);
    149 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue);
    150 
    151 /* channel utility function */
    152 mm_stream_t * mm_channel_util_get_stream_by_handler(
    153                                     mm_channel_t * ch_obj,
    154                                     uint32_t handler)
    155 {
    156     int i;
    157     mm_stream_t *s_obj = NULL;
    158     uint8_t ch_idx = mm_camera_util_get_index_by_handler(handler);
    159 
    160     for(i = 0; i < MM_CAMEAR_STRAEM_NUM_MAX; i++) {
    161         if (handler == ch_obj->streams[i].my_hdl) {
    162             s_obj = &ch_obj->streams[i];
    163             break;
    164         }
    165     }
    166     return s_obj;
    167 }
    168 
    169 static void mm_channel_dispatch_super_buf(mm_camera_cmdcb_t *cmd_cb,
    170                                           void* user_data)
    171 {
    172     int i;
    173     mm_channel_t * my_obj = (mm_channel_t *)user_data;
    174 
    175     if (NULL == my_obj) {
    176         return;
    177     }
    178 
    179     if (MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB != cmd_cb->cmd_type) {
    180         CDBG_ERROR("%s: Wrong cmd_type (%d) for super buf dataCB",
    181                    __func__, cmd_cb->cmd_type);
    182         return;
    183     }
    184 
    185     if (my_obj->bundle.super_buf_notify_cb) {
    186         my_obj->bundle.super_buf_notify_cb(&cmd_cb->u.superbuf, my_obj->bundle.user_data);
    187     }
    188 }
    189 
    190 /* CB for processing stream buffer */
    191 static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,
    192                                           void *user_data)
    193 {
    194     mm_camera_super_buf_notify_mode_t notify_mode;
    195     mm_channel_queue_node_t *node = NULL;
    196     mm_channel_t *ch_obj = (mm_channel_t *)user_data;
    197     if (NULL == ch_obj) {
    198         return;
    199     }
    200 
    201     if (MM_CAMERA_CMD_TYPE_DATA_CB  == cmd_cb->cmd_type) {
    202         /* comp_and_enqueue */
    203         mm_channel_superbuf_comp_and_enqueue(
    204                         ch_obj,
    205                         &ch_obj->bundle.superbuf_queue,
    206                         &cmd_cb->u.buf);
    207     } else if (MM_CAMERA_CMD_TYPE_REQ_DATA_CB  == cmd_cb->cmd_type) {
    208         /* skip frames if needed */
    209         ch_obj->pending_cnt = cmd_cb->u.req_buf.num_buf_requested;
    210         mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue);
    211     }
    212 
    213     notify_mode = ch_obj->bundle.superbuf_queue.attr.notify_mode;
    214 
    215     /* bufdone for overflowed bufs */
    216     mm_channel_superbuf_bufdone_overflow(ch_obj, &ch_obj->bundle.superbuf_queue);
    217 
    218     /* dispatch frame if pending_cnt>0 or is in continuous streaming mode */
    219     while ( (ch_obj->pending_cnt > 0) ||
    220             (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == notify_mode) ) {
    221 
    222         /* dequeue */
    223         node = mm_channel_superbuf_dequeue(&ch_obj->bundle.superbuf_queue);
    224         if (NULL != node) {
    225             /* decrease pending_cnt */
    226             CDBG("%s: Super Buffer received, Call client callback, pending_cnt=%d",
    227                  __func__, ch_obj->pending_cnt);
    228             if (MM_CAMERA_SUPER_BUF_NOTIFY_BURST == notify_mode) {
    229                 ch_obj->pending_cnt--;
    230             }
    231 
    232             /* do post processing if needed */
    233             /* this is a blocking call */
    234             mm_channel_do_post_processing(ch_obj, node);
    235 
    236             /* dispatch superbuf */
    237             if (NULL != ch_obj->bundle.super_buf_notify_cb) {
    238                 uint8_t i;
    239                 mm_camera_cmdcb_t* cb_node = NULL;
    240 
    241                 CDBG("%s: Send superbuf to HAL, pending_cnt=%d",
    242                      __func__, ch_obj->pending_cnt);
    243 
    244                 /* send sem_post to wake up cb thread to dispatch super buffer */
    245                 cb_node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
    246                 if (NULL != cb_node) {
    247                     memset(cb_node, 0, sizeof(mm_camera_cmdcb_t));
    248                     cb_node->cmd_type = MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB;
    249                     cb_node->u.superbuf.num_bufs = node->num_of_bufs;
    250                     for (i=0; i<node->num_of_bufs; i++) {
    251                         cb_node->u.superbuf.bufs[i] = node->super_buf[i].buf;
    252                     }
    253                     cb_node->u.superbuf.camera_handle = ch_obj->cam_obj->my_hdl;
    254                     cb_node->u.superbuf.ch_id = ch_obj->my_hdl;
    255 
    256                     /* enqueue to cb thread */
    257                     mm_camera_queue_enq(&(ch_obj->cb_thread.cmd_queue), cb_node);
    258 
    259                     /* wake up cb thread */
    260                     sem_post(&(ch_obj->cb_thread.cmd_sem));
    261                 } else {
    262                     CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
    263                     /* buf done with the nonuse super buf */
    264                     for (i=0; i<node->num_of_bufs; i++) {
    265                         mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
    266                     }
    267                 }
    268             } else {
    269                 /* buf done with the nonuse super buf */
    270                 uint8_t i;
    271                 for (i=0; i<node->num_of_bufs; i++) {
    272                     mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
    273                 }
    274             }
    275             free(node);
    276         } else {
    277             /* no superbuf avail, break the loop */
    278             break;
    279         }
    280     }
    281 }
    282 
    283 /* state machine entry */
    284 int32_t mm_channel_fsm_fn(mm_channel_t *my_obj,
    285                           mm_channel_evt_type_t evt,
    286                           void * in_val,
    287                           void * out_val)
    288 {
    289     int32_t rc = -1;
    290 
    291     CDBG("%s : E state = %d",__func__,my_obj->state);
    292     switch (my_obj->state) {
    293     case MM_CHANNEL_STATE_NOTUSED:
    294         rc = mm_channel_fsm_fn_notused(my_obj, evt, in_val, out_val);
    295         break;
    296     case MM_CHANNEL_STATE_STOPPED:
    297         rc = mm_channel_fsm_fn_stopped(my_obj, evt, in_val, out_val);
    298         break;
    299     case MM_CHANNEL_STATE_ACTIVE:
    300         rc = mm_channel_fsm_fn_active(my_obj, evt, in_val, out_val);
    301         break;
    302     case MM_CHANNEL_STATE_PAUSED:
    303         rc = mm_channel_fsm_fn_paused(my_obj, evt, in_val, out_val);
    304         break;
    305     default:
    306         CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
    307         break;
    308     }
    309 
    310     /* unlock ch_lock */
    311     pthread_mutex_unlock(&my_obj->ch_lock);
    312     CDBG("%s : X rc = %d",__func__,rc);
    313     return rc;
    314 }
    315 
    316 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
    317                           mm_channel_evt_type_t evt,
    318                           void * in_val,
    319                           void * out_val)
    320 {
    321     int32_t rc = -1;
    322 
    323     switch (evt) {
    324     default:
    325         CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
    326                    __func__, my_obj->state, evt);
    327         break;
    328     }
    329 
    330     return rc;
    331 }
    332 
    333 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
    334                           mm_channel_evt_type_t evt,
    335                           void * in_val,
    336                           void * out_val)
    337 {
    338     int32_t rc = 0;
    339     CDBG("%s : E evt = %d",__func__,evt);
    340     switch (evt) {
    341     case MM_CHANNEL_EVT_ADD_STREAM:
    342         {
    343             uint32_t s_hdl = 0;
    344             mm_evt_paylod_add_stream_t *payload =
    345                 (mm_evt_paylod_add_stream_t *)in_val;
    346             s_hdl = mm_channel_add_stream(my_obj,
    347                                           payload->buf_cb,
    348                                           payload->user_data,
    349                                           payload->ext_image_mode,
    350                                           payload->sensor_idx);
    351             *((uint32_t*)out_val) = s_hdl;
    352             rc = 0;
    353         }
    354         break;
    355     case MM_CHANNEL_EVT_DEL_STREAM:
    356         {
    357             uint32_t s_id = *((uint32_t *)in_val);
    358             rc = mm_channel_del_stream(my_obj, s_id);
    359         }
    360         break;
    361     case MM_CHANNEL_EVT_START_STREAM:
    362         {
    363             mm_evt_payload_start_stream_t *payload =
    364                 (mm_evt_payload_start_stream_t *)in_val;
    365             rc = mm_channel_start_streams(my_obj,
    366                                           payload->num_streams,
    367                                           payload->stream_ids);
    368             /* first stream started in stopped state
    369              * move to active state */
    370             if (0 == rc) {
    371                 my_obj->state = MM_CHANNEL_STATE_ACTIVE;
    372             }
    373         }
    374         break;
    375     case MM_CHANNEL_EVT_CONFIG_STREAM:
    376         {
    377             mm_evt_paylod_config_stream_t *payload =
    378                 (mm_evt_paylod_config_stream_t *)in_val;
    379             rc = mm_channel_config_stream(my_obj,
    380                                           payload->stream_id,
    381                                           payload->config);
    382         }
    383         break;
    384     case MM_CHANNEL_EVT_INIT_BUNDLE:
    385         {
    386             mm_evt_payload_bundle_stream_t *payload =
    387                 (mm_evt_payload_bundle_stream_t *)in_val;
    388             rc = mm_channel_bundle_stream(my_obj,
    389                                           payload->super_frame_notify_cb,
    390                                           payload->user_data,
    391                                           payload->attr,
    392                                           payload->num_streams,
    393                                           payload->stream_ids);
    394         }
    395         break;
    396     case MM_CHANNEL_EVT_DESTROY_BUNDLE:
    397         rc = mm_channel_destroy_bundle(my_obj);
    398         break;
    399     case MM_CHANNEL_EVT_PREPARE_SNAPSHOT:
    400         {
    401             uint32_t sensor_idx = (uint32_t)in_val;
    402             rc = mm_channel_prepare_snapshot(my_obj, sensor_idx);
    403         }
    404         break;
    405     case MM_CHANNEL_EVT_DELETE:
    406         mm_channel_release(my_obj);
    407         rc = 0;
    408         break;
    409     case MM_CHANNEL_EVT_SET_STREAM_PARM:
    410         {
    411             uint32_t s_id = (uint32_t)in_val;
    412             rc = mm_channel_set_stream_parm(my_obj, s_id, out_val);
    413         }
    414         break;
    415     case MM_CHANNEL_EVT_GET_STREAM_PARM:
    416         {
    417             uint32_t s_id = (uint32_t)in_val;
    418             rc = mm_channel_get_stream_parm(my_obj, s_id, out_val);
    419         }
    420         break;
    421     case MM_CHANNEL_EVT_OPEN_REPRO_ISP:
    422         {
    423             uint32_t repro_hdl = 0;
    424             mm_camera_repro_isp_type_t isp_type =
    425                 (mm_camera_repro_isp_type_t)in_val;
    426             repro_hdl = mm_channel_open_repro_isp(my_obj, isp_type);
    427             *((uint32_t*)out_val) = repro_hdl;
    428             rc = 0;
    429         }
    430         break;
    431     case MM_CHANNEL_EVT_CONFIG_REPRO_ISP:
    432         {
    433             mm_evt_paylod_config_repro_isp_t *payload =
    434                 (mm_evt_paylod_config_repro_isp_t *)in_val;
    435             rc = mm_channel_config_repro_isp(my_obj,
    436                                             payload->repro_isp_handle,
    437                                             payload->config);
    438         }
    439         break;
    440     case MM_CHANNEL_EVT_ATTACH_STREAM_TO_REPRO_ISP:
    441         {
    442             mm_evt_paylod_stream_to_repro_isp_t *payload =
    443                 (mm_evt_paylod_stream_to_repro_isp_t *)in_val;
    444             rc = mm_channel_repro_isp_dest_stream_ops(my_obj,
    445                                                      payload->repro_isp_handle,
    446                                                      payload->stream_id,
    447                                                      TRUE);
    448         }
    449         break;
    450     case MM_CHANNEL_EVT_START_REPRO_ISP:
    451         {
    452             mm_evt_paylod_repro_start_stop_t *payload =
    453                 (mm_evt_paylod_repro_start_stop_t*)in_val;
    454             rc = mm_channel_repro_isp_ops(my_obj,
    455                                           payload->repro_isp_handle,
    456                                           payload->stream_id,
    457                                           TRUE);
    458         }
    459         break;
    460     case MM_CHANNEL_EVT_REPROCESS:
    461         {
    462             mm_evt_paylod_reprocess_t *payload =
    463                 (mm_evt_paylod_reprocess_t *)in_val;
    464             rc = mm_channel_reprocess(my_obj,
    465                                       payload->repro_isp_handle,
    466                                       payload->repro_data);
    467         }
    468         break;
    469     case MM_CHANNEL_EVT_STOP_REPRO_ISP:
    470         {
    471             mm_evt_paylod_repro_start_stop_t *payload =
    472                 (mm_evt_paylod_repro_start_stop_t*)in_val;
    473             rc = mm_channel_repro_isp_ops(my_obj,
    474                                           payload->repro_isp_handle,
    475                                           payload->stream_id,
    476                                           FALSE);
    477         }
    478         break;
    479     case MM_CHANNEL_EVT_DETACH_STREAM_FROM_REPRO_ISP:
    480         {
    481             mm_evt_paylod_stream_to_repro_isp_t *payload =
    482                 (mm_evt_paylod_stream_to_repro_isp_t *)in_val;
    483             rc = mm_channel_repro_isp_dest_stream_ops(my_obj,
    484                                                      payload->repro_isp_handle,
    485                                                      payload->stream_id,
    486                                                      FALSE);
    487         }
    488         break;
    489     case MM_CHANNEL_EVT_CLOSE_REPRO_ISP:
    490         {
    491             uint32_t repro_handle = (uint32_t)in_val;
    492             rc = mm_channel_close_repro_isp(my_obj, repro_handle);
    493         }
    494         break;
    495     default:
    496         CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
    497                    __func__, my_obj->state, evt);
    498         break;
    499     }
    500     CDBG("%s : E rc = %d",__func__,rc);
    501     return rc;
    502 }
    503 
    504 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
    505                           mm_channel_evt_type_t evt,
    506                           void * in_val,
    507                           void * out_val)
    508 {
    509     int32_t rc = 0;
    510 
    511     CDBG("%s : E evt = %d",__func__,evt);
    512     switch (evt) {
    513     case MM_CHANNEL_EVT_CONFIG_STREAM:
    514         {
    515             mm_evt_paylod_config_stream_t *payload =
    516                 (mm_evt_paylod_config_stream_t *)in_val;
    517             rc = mm_channel_config_stream(my_obj,
    518                                           payload->stream_id,
    519                                           payload->config);
    520         }
    521         break;
    522     case MM_CHANNEL_EVT_START_STREAM:
    523         {
    524             mm_evt_payload_start_stream_t *payload =
    525                 (mm_evt_payload_start_stream_t *)in_val;
    526             rc = mm_channel_start_streams(my_obj,
    527                                           payload->num_streams,
    528                                           payload->stream_ids);
    529         }
    530         break;
    531     case MM_CHANNEL_EVT_STOP_STREAM:
    532     case MM_CHANNEL_EVT_TEARDOWN_STREAM:
    533         {
    534             int i;
    535             uint8_t tear_down_flag = (MM_CHANNEL_EVT_TEARDOWN_STREAM == evt)? 1:0;
    536             uint8_t all_stopped = 1;
    537             mm_evt_payload_stop_stream_t *payload =
    538                 (mm_evt_payload_stop_stream_t *)in_val;
    539 
    540             rc = mm_channel_stop_streams(my_obj,
    541                                          payload->num_streams,
    542                                          payload->stream_ids,
    543                                          tear_down_flag);
    544 
    545             /* check if all streams are stopped
    546              * then we move to stopped state */
    547 
    548             for (i=0; i<MM_CAMEAR_STRAEM_NUM_MAX; i++) {
    549                 if (MM_STREAM_STATE_ACTIVE_STREAM_ON == my_obj->streams[i].state ||
    550                     MM_STREAM_STATE_ACTIVE_STREAM_OFF == my_obj->streams[i].state) {
    551                     all_stopped = 0;
    552                     break;
    553                 }
    554             }
    555             if (all_stopped) {
    556                 my_obj->state = MM_CHANNEL_STATE_STOPPED;
    557             }
    558 
    559         }
    560         break;
    561     case MM_CHANNEL_EVT_INIT_BUNDLE:
    562         {
    563             mm_evt_payload_bundle_stream_t *payload =
    564                 (mm_evt_payload_bundle_stream_t *)in_val;
    565             rc = mm_channel_bundle_stream(my_obj,
    566                                           payload->super_frame_notify_cb,
    567                                           payload->user_data,
    568                                           payload->attr,
    569                                           payload->num_streams,
    570                                           payload->stream_ids);
    571         }
    572         break;
    573     case MM_CHANNEL_EVT_DESTROY_BUNDLE:
    574         rc = mm_channel_destroy_bundle(my_obj);
    575         break;
    576     case MM_CHANNEL_EVT_REQUEST_SUPER_BUF:
    577         {
    578             uint32_t num_buf_requested = (uint32_t)in_val;
    579             rc = mm_channel_request_super_buf(my_obj, num_buf_requested);
    580         }
    581         break;
    582     case MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF:
    583         rc = mm_channel_cancel_super_buf_request(my_obj);
    584         break;
    585     case MM_CHANNEL_EVT_START_FOCUS:
    586         {
    587             mm_evt_payload_start_focus_t* payload =
    588                 (mm_evt_payload_start_focus_t *)in_val;
    589             rc = mm_channel_start_focus(my_obj,
    590                                         payload->sensor_idx,
    591                                         payload->focus_mode);
    592         }
    593         break;
    594     case MM_CHANNEL_EVT_ABORT_FOCUS:
    595         {
    596             uint32_t sensor_idx = (uint32_t)in_val;
    597             rc = mm_channel_abort_focus(my_obj, sensor_idx);
    598         }
    599         break;
    600     case MM_CHANNEL_EVT_PREPARE_SNAPSHOT:
    601         {
    602             uint32_t sensor_idx = (uint32_t)in_val;
    603             rc = mm_channel_prepare_snapshot(my_obj, sensor_idx);
    604         }
    605         break;
    606     case MM_CHANNEL_EVT_SET_STREAM_PARM:
    607         {
    608             uint32_t s_id = (uint32_t)in_val;
    609             rc = mm_channel_set_stream_parm(my_obj, s_id, out_val);
    610         }
    611         break;
    612     case MM_CHANNEL_EVT_GET_STREAM_PARM:
    613         {
    614             uint32_t s_id = (uint32_t)in_val;
    615             rc = mm_channel_get_stream_parm(my_obj, s_id, out_val);
    616         }
    617         break;
    618 
    619     case MM_CHANNEL_EVT_DEL_STREAM:
    620         {
    621             uint32_t s_id = *((uint32_t *)in_val);
    622             rc = mm_channel_del_stream(my_obj, s_id);
    623         }
    624         break;
    625     case MM_CHANNEL_EVT_ATTACH_STREAM_TO_REPRO_ISP:
    626         {
    627             mm_evt_paylod_stream_to_repro_isp_t *payload =
    628                 (mm_evt_paylod_stream_to_repro_isp_t *)in_val;
    629             rc = mm_channel_repro_isp_dest_stream_ops(my_obj,
    630                                                      payload->repro_isp_handle,
    631                                                      payload->stream_id,
    632                                                      TRUE);
    633         }
    634         break;
    635     case MM_CHANNEL_EVT_START_REPRO_ISP:
    636         {
    637             mm_evt_paylod_repro_start_stop_t *payload =
    638                 (mm_evt_paylod_repro_start_stop_t*)in_val;
    639             rc = mm_channel_repro_isp_ops(my_obj,
    640                                           payload->repro_isp_handle,
    641                                           payload->stream_id,
    642                                           TRUE);
    643         }
    644         break;
    645     case MM_CHANNEL_EVT_REPROCESS:
    646         {
    647             mm_evt_paylod_reprocess_t *payload =
    648                 (mm_evt_paylod_reprocess_t *)in_val;
    649             rc = mm_channel_reprocess(my_obj,
    650                                       payload->repro_isp_handle,
    651                                       payload->repro_data);
    652         }
    653         break;
    654     case MM_CHANNEL_EVT_STOP_REPRO_ISP:
    655         {
    656             mm_evt_paylod_repro_start_stop_t *payload =
    657                 (mm_evt_paylod_repro_start_stop_t*)in_val;
    658             rc = mm_channel_repro_isp_ops(my_obj,
    659                                           payload->repro_isp_handle,
    660                                           payload->stream_id,
    661                                           FALSE);
    662         }
    663         break;
    664     case MM_CHANNEL_EVT_DETACH_STREAM_FROM_REPRO_ISP:
    665         {
    666             mm_evt_paylod_stream_to_repro_isp_t *payload =
    667                 (mm_evt_paylod_stream_to_repro_isp_t *)in_val;
    668             rc = mm_channel_repro_isp_dest_stream_ops(my_obj,
    669                                                      payload->repro_isp_handle,
    670                                                      payload->stream_id,
    671                                                      FALSE);
    672         }
    673         break;
    674     default:
    675         CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
    676                    __func__, my_obj->state, evt);
    677         break;
    678     }
    679     CDBG("%s : X rc = %d",__func__,rc);
    680     return rc;
    681 }
    682 
    683 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
    684                           mm_channel_evt_type_t evt,
    685                           void * in_val,
    686                           void * out_val)
    687 {
    688     int32_t rc = 0;
    689 
    690     /* currently we are not supporting pause/resume channel */
    691     CDBG_ERROR("%s: evt (%d) not supported in state (%d)",
    692                __func__, evt, my_obj->state);
    693 
    694     return rc;
    695 }
    696 
    697 int32_t mm_channel_init(mm_channel_t *my_obj)
    698 {
    699     int32_t rc = 0;
    700     CDBG("%s : Launch data poll thread in channel open",__func__);
    701     mm_camera_poll_thread_launch(&my_obj->poll_thread[0],
    702                                  MM_CAMERA_POLL_TYPE_CH);
    703 
    704     /* change state to stopped state */
    705     my_obj->state = MM_CHANNEL_STATE_STOPPED;
    706     return rc;
    707 }
    708 
    709 void mm_channel_release(mm_channel_t *my_obj)
    710 {
    711     /* stop data poll thread */
    712     mm_camera_poll_thread_release(&my_obj->poll_thread[0]);
    713 
    714     /* change state to notused state */
    715     my_obj->state = MM_CHANNEL_STATE_NOTUSED;
    716 }
    717 
    718 uint32_t mm_channel_get_ext_mode_from_img_mode(uint32_t img_mode)
    719 {
    720     switch (img_mode) {
    721     case MM_CAMERA_PREVIEW:
    722         return MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
    723     case MM_CAMERA_VIDEO:
    724         return MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
    725     case MM_CAMERA_SNAPSHOT_MAIN:
    726         return MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
    727     case MM_CAMERA_SNAPSHOT_THUMBNAIL:
    728         return MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
    729     case MM_CAMERA_SNAPSHOT_RAW:
    730         return MSM_V4L2_EXT_CAPTURE_MODE_RAW;
    731     case MM_CAMERA_RDI:
    732         return MSM_V4L2_EXT_CAPTURE_MODE_RDI;
    733     case MM_CAMERA_RDI1:
    734         return MSM_V4L2_EXT_CAPTURE_MODE_RDI1;
    735     case MM_CAMERA_RDI2:
    736         return MSM_V4L2_EXT_CAPTURE_MODE_RDI2;
    737 	case MM_CAMERA_SAEC:
    738 		return MSM_V4L2_EXT_CAPTURE_MODE_AEC;
    739 	case MM_CAMERA_SAWB:
    740 		return MSM_V4L2_EXT_CAPTURE_MODE_AWB;
    741 	case MM_CAMERA_SAFC:
    742 		return MSM_V4L2_EXT_CAPTURE_MODE_AF;
    743 	case MM_CAMERA_IHST:
    744 		return MSM_V4L2_EXT_CAPTURE_MODE_IHIST;
    745 	case MM_CAMERA_CS:
    746 		return MSM_V4L2_EXT_CAPTURE_MODE_CS;
    747 	case MM_CAMERA_RS:
    748 		return MSM_V4L2_EXT_CAPTURE_MODE_RS;
    749 	case MM_CAMERA_CSTA:
    750 		return MSM_V4L2_EXT_CAPTURE_MODE_CSTA;
    751     case MM_CAMERA_ISP_PIX_OUTPUT1:
    752         return MSM_V4L2_EXT_CAPTURE_MODE_ISP_PIX_OUTPUT1;
    753     case MM_CAMERA_ISP_PIX_OUTPUT2:
    754         return MSM_V4L2_EXT_CAPTURE_MODE_ISP_PIX_OUTPUT2;
    755     default:
    756         return MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT;
    757     }
    758 }
    759 
    760 uint32_t mm_channel_add_stream(mm_channel_t *my_obj,
    761                               mm_camera_buf_notify_t buf_cb, void *user_data,
    762                               uint32_t ext_image_mode, uint32_t sensor_idx)
    763 {
    764     int32_t rc = 0;
    765     uint8_t idx = 0;
    766     uint32_t s_hdl = 0;
    767     mm_stream_t *stream_obj = NULL;
    768 
    769     CDBG("%s : image mode = %d",__func__,ext_image_mode);
    770     /* check available stream */
    771     for (idx = 0; idx < MM_CAMEAR_STRAEM_NUM_MAX; idx++) {
    772         if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) {
    773             stream_obj = &my_obj->streams[idx];
    774             break;
    775         }
    776     }
    777     if (NULL == stream_obj) {
    778         CDBG_ERROR("%s: streams reach max, no more stream allowed to add", __func__);
    779         return s_hdl;
    780     }
    781 
    782     /* initialize stream object */
    783     memset(stream_obj, 0, sizeof(mm_stream_t));
    784     stream_obj->my_hdl = mm_camera_util_generate_handler(idx);
    785     stream_obj->ch_obj = my_obj;
    786     /* cd through intf always palced at idx 0 of buf_cb */
    787     stream_obj->buf_cb[0].cb = buf_cb;
    788     stream_obj->buf_cb[0].user_data = user_data;
    789     stream_obj->buf_cb[0].cb_count = -1; /* infinite by default */
    790     stream_obj->ext_image_mode =
    791         mm_channel_get_ext_mode_from_img_mode(ext_image_mode);
    792     stream_obj->sensor_idx = sensor_idx;
    793     stream_obj->fd = -1;
    794     pthread_mutex_init(&stream_obj->buf_lock, NULL);
    795     pthread_mutex_init(&stream_obj->cb_lock, NULL);
    796     stream_obj->state = MM_STREAM_STATE_INITED;
    797 
    798     /* acquire stream */
    799     rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL);
    800     if (0 == rc) {
    801         s_hdl = stream_obj->my_hdl;
    802     } else {
    803         /* error during acquire, de-init */
    804         pthread_mutex_destroy(&stream_obj->buf_lock);
    805         pthread_mutex_destroy(&stream_obj->cb_lock);
    806         memset(stream_obj, 0, sizeof(mm_stream_t));
    807     }
    808     CDBG("%s : stream handle = %d",__func__,s_hdl);
    809     return s_hdl;
    810 }
    811 
    812 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
    813                               uint32_t stream_id)
    814 {
    815     int rc = -1;
    816     mm_stream_t * stream_obj = NULL;
    817     stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
    818 
    819     if (NULL == stream_obj) {
    820         CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d",__func__, stream_id);
    821         return rc;
    822     }
    823 
    824     rc = mm_stream_fsm_fn(stream_obj,
    825                           MM_STREAM_EVT_RELEASE,
    826                           NULL,
    827                           NULL);
    828 
    829     return rc;
    830 }
    831 
    832 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
    833                                    uint32_t stream_id,
    834                                    mm_camera_stream_config_t *config)
    835 {
    836     int rc = -1;
    837     mm_stream_t * stream_obj = NULL;
    838     CDBG("%s : E stream ID = %d",__func__,stream_id);
    839     stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
    840 
    841     if (NULL == stream_obj) {
    842         CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d",__func__, stream_id);
    843         return rc;
    844     }
    845 
    846     /* set stream fmt */
    847     rc = mm_stream_fsm_fn(stream_obj,
    848                           MM_STREAM_EVT_SET_FMT,
    849                           (void *)config,
    850                           NULL);
    851     CDBG("%s : X rc = %d",__func__,rc);
    852     return rc;
    853 }
    854 
    855 int32_t mm_channel_bundle_stream(mm_channel_t *my_obj,
    856                                  mm_camera_buf_notify_t super_frame_notify_cb,
    857                                  void *user_data,
    858                                  mm_camera_bundle_attr_t *attr,
    859                                  uint8_t num_streams,
    860                                  uint32_t *stream_ids)
    861 {
    862     int32_t rc = 0;
    863     int i;
    864     cam_stream_bundle_t bundle;
    865     mm_stream_t* s_objs[MM_CAMEAR_MAX_STRAEM_BUNDLE] = {NULL};
    866 
    867     /* first check if all streams to be bundled are valid */
    868     for (i=0; i < num_streams; i++) {
    869         s_objs[i] = mm_channel_util_get_stream_by_handler(my_obj, stream_ids[i]);
    870         if (NULL == s_objs[i]) {
    871             CDBG_ERROR("%s: invalid stream handler %d (idx=%d) to be bundled",
    872                        __func__, stream_ids[i], i);
    873             return -1;
    874         }
    875     }
    876 
    877     /* init superbuf queue */
    878     mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue);
    879 
    880     memset(&bundle, 0, sizeof(bundle));
    881     /* save bundle config */
    882     memcpy(&my_obj->bundle.superbuf_queue.attr, attr, sizeof(mm_camera_bundle_attr_t));
    883     my_obj->bundle.super_buf_notify_cb = super_frame_notify_cb;
    884     my_obj->bundle.user_data = user_data;
    885     my_obj->bundle.superbuf_queue.num_streams = num_streams;
    886     my_obj->bundle.superbuf_queue.expected_frame_id = 0;
    887 
    888     for (i=0; i < num_streams; i++) {
    889         /* set bundled flag to streams */
    890         s_objs[i]->is_bundled = 1;
    891         /* init bundled streams to invalid value -1 */
    892         my_obj->bundle.superbuf_queue.bundled_streams[i] = stream_ids[i];
    893         bundle.stream_handles[bundle.num++] =
    894             s_objs[i]->inst_hdl;
    895     }
    896     /* in the case of 1 bundle , current implementation is nop */
    897     if (bundle.num > 1) {
    898         rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
    899                                                     CAMERA_SET_BUNDLE,
    900                                                     sizeof(bundle),
    901                                                     (void *)&bundle);
    902         if (0 != rc) {
    903             CDBG_ERROR("%s: set_bundle failed (rc=%d)", __func__, rc);
    904             return -1;
    905         }
    906     }
    907 
    908     /* launch cb thread for dispatching super buf through cb */
    909     mm_camera_cmd_thread_launch(&my_obj->cb_thread,
    910                                 mm_channel_dispatch_super_buf,
    911                                 (void*)my_obj);
    912 
    913     /* launch cmd thread for super buf dataCB */
    914     mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
    915                                 mm_channel_process_stream_buf,
    916                                 (void*)my_obj);
    917 
    918     /* set flag to TRUE */
    919     my_obj->bundle.is_active = TRUE;
    920 
    921     return rc;
    922 }
    923 
    924 /* bundled streams must all be stopped before bundle can be destroyed */
    925 int32_t mm_channel_destroy_bundle(mm_channel_t *my_obj)
    926 {
    927     mm_stream_t* s_obj = NULL;
    928     uint8_t i;
    929 
    930     if (FALSE == my_obj->bundle.is_active) {
    931         CDBG("%s: bundle not active, no need to destroy", __func__);
    932         return 0;
    933     }
    934 
    935     /* first check all bundled streams should be stopped already */
    936     for (i=0; i < my_obj->bundle.superbuf_queue.num_streams; i++) {
    937         s_obj = mm_channel_util_get_stream_by_handler(my_obj,
    938                         my_obj->bundle.superbuf_queue.bundled_streams[i]);
    939         if (NULL != s_obj) {
    940             if (MM_STREAM_STATE_ACTIVE_STREAM_ON == s_obj->state ||
    941                 MM_STREAM_STATE_ACTIVE_STREAM_OFF == s_obj->state) {
    942                 CDBG_ERROR("%s: at least one of the bundled streams (%d) is still active",
    943                            __func__, my_obj->bundle.superbuf_queue.bundled_streams[i]);
    944                 return -1;
    945             }
    946         }
    947     }
    948 
    949     /* deinit superbuf queue */
    950     mm_channel_superbuf_queue_deinit(my_obj, &my_obj->bundle.superbuf_queue);
    951 
    952     /* memset bundle info */
    953     memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t));
    954     my_obj->bundle.is_active = FALSE;
    955     return 0;
    956 }
    957 
    958 int32_t mm_channel_start_streams(mm_channel_t *my_obj,
    959                                  uint8_t num_streams,
    960                                  uint32_t *stream_ids)
    961 {
    962     int32_t rc = 0;
    963     int i, j;
    964     mm_stream_t* s_objs[MM_CAMEAR_MAX_STRAEM_BUNDLE] = {NULL};
    965     uint8_t num_streams_to_start = num_streams;
    966     uint32_t streams_to_start[MM_CAMEAR_MAX_STRAEM_BUNDLE];
    967     uint8_t bundle_to_start = 0;
    968 
    969     /* check if any bundled stream to be start,
    970      * then all bundled stream should be started */
    971     memcpy(streams_to_start, stream_ids, sizeof(uint32_t) * num_streams);
    972     for (i=0; i < num_streams; i++) {
    973         for (j=0; j < my_obj->bundle.superbuf_queue.num_streams; j++) {
    974             if (stream_ids[i] == my_obj->bundle.superbuf_queue.bundled_streams[j]) {
    975                 bundle_to_start = 1;
    976                 break;
    977             }
    978         }
    979     }
    980 
    981     if (bundle_to_start) {
    982         uint8_t need_add;
    983         /* add bundled streams into the start list if not already added*/
    984         for (i=0; i<my_obj->bundle.superbuf_queue.num_streams; i++) {
    985             need_add = 1;
    986             for (j=0; j<num_streams; j++) {
    987                 if (stream_ids[j] == my_obj->bundle.superbuf_queue.bundled_streams[i]) {
    988                     need_add = 0;
    989                     break;
    990                 }
    991             }
    992             if (need_add) {
    993                 streams_to_start[num_streams_to_start++] =
    994                     my_obj->bundle.superbuf_queue.bundled_streams[i];
    995             }
    996         }
    997     }
    998 
    999     /* check if all streams to be started are valid */
   1000     for (i=0; i<num_streams_to_start; i++) {
   1001         s_objs[i] = mm_channel_util_get_stream_by_handler(my_obj, streams_to_start[i]);
   1002 
   1003         if (NULL == s_objs[i]) {
   1004             CDBG_ERROR("%s: invalid stream handler %d (idx=%d) to be started",
   1005                        __func__, streams_to_start[i], i);
   1006             return -1;
   1007         }
   1008     }
   1009 
   1010     for (i=0; i<num_streams_to_start; i++) {
   1011         /* if stream is already started, there is no need to start it */
   1012         if (s_objs[i]->state == MM_STREAM_STATE_ACTIVE_STREAM_ON ||
   1013             s_objs[i]->state == MM_STREAM_STATE_ACTIVE_STREAM_OFF) {
   1014             continue;
   1015         }
   1016 
   1017         /* allocate buf */
   1018         rc = mm_stream_fsm_fn(s_objs[i],
   1019                               MM_STREAM_EVT_GET_BUF,
   1020                               NULL,
   1021                               NULL);
   1022         if (0 != rc) {
   1023             CDBG_ERROR("%s: get buf failed at idx(%d)", __func__, i);
   1024             break;
   1025         }
   1026 
   1027         /* reg buf */
   1028         rc = mm_stream_fsm_fn(s_objs[i],
   1029                               MM_STREAM_EVT_REG_BUF,
   1030                               NULL,
   1031                               NULL);
   1032         if (0 != rc) {
   1033             CDBG_ERROR("%s: reg buf failed at idx(%d)", __func__, i);
   1034             break;
   1035         }
   1036 
   1037         /* start stream */
   1038         rc = mm_stream_fsm_fn(s_objs[i],
   1039                               MM_STREAM_EVT_START,
   1040                               NULL,
   1041                               NULL);
   1042         if (0 != rc) {
   1043             CDBG_ERROR("%s: start stream failed at idx(%d)", __func__, i);
   1044             break;
   1045         }
   1046     }
   1047 
   1048     /* error handling */
   1049     if (0 != rc) {
   1050         for (j=0; j<=i; j++) {
   1051             /* stop streams*/
   1052             mm_stream_fsm_fn(s_objs[i],
   1053                              MM_STREAM_EVT_STOP,
   1054                              NULL,
   1055                              NULL);
   1056 
   1057             /* unreg buf */
   1058             mm_stream_fsm_fn(s_objs[i],
   1059                              MM_STREAM_EVT_UNREG_BUF,
   1060                              NULL,
   1061                              NULL);
   1062 
   1063             /* put buf back */
   1064             mm_stream_fsm_fn(s_objs[i],
   1065                              MM_STREAM_EVT_PUT_BUF,
   1066                              NULL,
   1067                              NULL);
   1068         }
   1069     }
   1070 
   1071     return rc;
   1072 }
   1073 
   1074 /* Required: bundled streams need to be stopped together */
   1075 int32_t mm_channel_stop_streams(mm_channel_t *my_obj,
   1076                                 uint8_t num_streams,
   1077                                 uint32_t *stream_ids,
   1078                                 uint8_t tear_down_flag)
   1079 {
   1080     int32_t rc = 0;
   1081     int i, j;
   1082     mm_stream_t* s_objs[MM_CAMEAR_MAX_STRAEM_BUNDLE] = {NULL};
   1083     uint8_t num_streams_to_stop = num_streams;
   1084     uint32_t streams_to_stop[MM_CAMEAR_MAX_STRAEM_BUNDLE];
   1085     uint8_t bundle_to_stop = 0;
   1086 
   1087     /* make sure bundled streams are stopped together */
   1088     memcpy(streams_to_stop, stream_ids, sizeof(uint32_t) * num_streams);
   1089     for (i=0; i<num_streams; i++) {
   1090         for (j=0; j<my_obj->bundle.superbuf_queue.num_streams; j++) {
   1091             if (stream_ids[i] == my_obj->bundle.superbuf_queue.bundled_streams[j]) {
   1092                 bundle_to_stop = 1;
   1093                 break;
   1094             }
   1095         }
   1096     }
   1097     if (bundle_to_stop) {
   1098         /* first stop bundle thread */
   1099         mm_camera_cmd_thread_stop(&my_obj->cmd_thread);
   1100         mm_camera_cmd_thread_stop(&my_obj->cb_thread);
   1101 
   1102         uint8_t need_add;
   1103         /* add bundled streams into the start list if not already added*/
   1104         for (i=0; i<my_obj->bundle.superbuf_queue.num_streams; i++) {
   1105             need_add = 1;
   1106             for (j=0; j<num_streams; j++) {
   1107                 if (stream_ids[j] == my_obj->bundle.superbuf_queue.bundled_streams[i]) {
   1108                     need_add = 0;
   1109                     break;
   1110                 }
   1111             }
   1112             if (need_add) {
   1113                 streams_to_stop[num_streams_to_stop++] =
   1114                     my_obj->bundle.superbuf_queue.bundled_streams[i];
   1115             }
   1116         }
   1117     }
   1118 
   1119     for (i=0; i<num_streams_to_stop; i++) {
   1120         s_objs[i] = mm_channel_util_get_stream_by_handler(my_obj, streams_to_stop[i]);
   1121 
   1122         if (NULL != s_objs[i]) {
   1123             /* stream off */
   1124             mm_stream_fsm_fn(s_objs[i],
   1125                              MM_STREAM_EVT_STOP,
   1126                              NULL,
   1127                              NULL);
   1128 
   1129             /* unreg buf at kernel */
   1130             mm_stream_fsm_fn(s_objs[i],
   1131                              MM_STREAM_EVT_UNREG_BUF,
   1132                              NULL,
   1133                              NULL);
   1134         }
   1135     }
   1136 
   1137     /* destroy super buf cmd thread */
   1138     if (bundle_to_stop) {
   1139         /* first stop bundle thread */
   1140         mm_camera_cmd_thread_destroy(&my_obj->cmd_thread);
   1141         mm_camera_cmd_thread_destroy(&my_obj->cb_thread);
   1142     }
   1143 
   1144     /* since all streams are stopped, we are safe to
   1145      * release all buffers allocated in stream */
   1146     for (i=0; i<num_streams_to_stop; i++) {
   1147         if (NULL != s_objs[i]) {
   1148             /* put buf back */
   1149             mm_stream_fsm_fn(s_objs[i],
   1150                              MM_STREAM_EVT_PUT_BUF,
   1151                              NULL,
   1152                              NULL);
   1153 
   1154             if (tear_down_flag) {
   1155                 /* to tear down stream totally, stream needs to be released */
   1156                 mm_stream_fsm_fn(s_objs[i],
   1157                                  MM_STREAM_EVT_RELEASE,
   1158                                  NULL,
   1159                                  NULL);
   1160             }
   1161         }
   1162     }
   1163 
   1164     return rc;
   1165 }
   1166 
   1167 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj, uint32_t num_buf_requested)
   1168 {
   1169     int32_t rc = 0;
   1170     mm_camera_cmdcb_t* node = NULL;
   1171 
   1172     /* set pending_cnt
   1173      * will trigger dispatching super frames if pending_cnt > 0 */
   1174     /* send sem_post to wake up cmd thread to dispatch super buffer */
   1175     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   1176     if (NULL != node) {
   1177         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   1178         node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB;
   1179         node->u.req_buf.num_buf_requested = num_buf_requested;
   1180 
   1181         /* enqueue to cmd thread */
   1182         mm_camera_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   1183 
   1184         /* wake up cmd thread */
   1185         sem_post(&(my_obj->cmd_thread.cmd_sem));
   1186     } else {
   1187         CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
   1188         rc = -1;
   1189     }
   1190 
   1191     return rc;
   1192 }
   1193 
   1194 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj)
   1195 {
   1196     int32_t rc = 0;
   1197     /* reset pending_cnt */
   1198     my_obj->pending_cnt = 0;
   1199 
   1200     return rc;
   1201 }
   1202 
   1203 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
   1204                         mm_camera_buf_def_t *buf)
   1205 {
   1206     int32_t rc = -1;
   1207     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id);
   1208 
   1209     if (NULL != s_obj) {
   1210         rc = mm_stream_fsm_fn(s_obj,
   1211                               MM_STREAM_EVT_QBUF,
   1212                               (void *)buf,
   1213                               NULL);
   1214     }
   1215 
   1216     return rc;
   1217 }
   1218 
   1219 int32_t mm_channel_start_focus(mm_channel_t *my_obj,
   1220                                uint32_t sensor_idx,
   1221                                uint32_t focus_mode)
   1222 {
   1223     return mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
   1224                                           CAMERA_SET_PARM_AUTO_FOCUS,
   1225                                           sizeof(uint32_t), (void*)focus_mode);
   1226 }
   1227 
   1228 int32_t mm_channel_abort_focus(mm_channel_t *my_obj, uint32_t sensor_idx)
   1229 {
   1230     return mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
   1231                                           CAMERA_AUTO_FOCUS_CANCEL,
   1232                                           0, NULL);
   1233 }
   1234 
   1235 int32_t mm_channel_prepare_snapshot(mm_channel_t *my_obj, uint32_t sensor_idx)
   1236 {
   1237     return mm_camera_send_native_ctrl_timeout_cmd(my_obj->cam_obj,
   1238                                                 CAMERA_PREPARE_SNAPSHOT,
   1239                                                 0, NULL, 2000);
   1240 }
   1241 
   1242 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
   1243                                    uint32_t s_id,
   1244                                    void *value)
   1245 {
   1246     int32_t rc = -1;
   1247     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, s_id);
   1248     if (NULL != s_obj) {
   1249         rc = mm_stream_fsm_fn(s_obj,
   1250                               MM_STREAM_EVT_SET_PARM,
   1251                               value,
   1252                               NULL);
   1253     }
   1254 
   1255     return rc;
   1256 }
   1257 
   1258 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
   1259                                    uint32_t s_id,
   1260                                    void *value)
   1261 {
   1262     int32_t rc = -1;
   1263     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, s_id);
   1264     if (NULL != s_obj) {
   1265         rc = mm_stream_fsm_fn(s_obj,
   1266                               MM_STREAM_EVT_GET_PARM,
   1267                               NULL,
   1268                               value);
   1269     }
   1270 
   1271     return rc;
   1272 }
   1273 
   1274 int32_t mm_channel_do_post_processing(mm_channel_t *my_obj,
   1275                                       mm_channel_queue_node_t *super_buf)
   1276 {
   1277     int32_t rc = 0;
   1278     uint8_t pp_mask = 0;
   1279 
   1280     pp_mask = mm_camera_util_get_pp_mask(my_obj->cam_obj);
   1281 
   1282     if (pp_mask & CAMERA_PP_MASK_TYPE_WNR) {
   1283         mm_camera_wnr_info_t wnr_info;
   1284         uint8_t i, j = 0;
   1285         mm_stream_t* s_obj = NULL;
   1286 
   1287         memset(&wnr_info, 0, sizeof(mm_camera_wnr_info_t));
   1288         for (i = 0; i < super_buf->num_of_bufs; i++) {
   1289             s_obj = mm_channel_util_get_stream_by_handler(my_obj, super_buf->super_buf[i].stream_id);
   1290             if (NULL != s_obj) {
   1291                 wnr_info.frames[j].instance_hdl = s_obj->inst_hdl;
   1292                 wnr_info.frames[j].frame_idx = super_buf->super_buf[i].buf->buf_idx;
   1293                 wnr_info.frames[j].frame_width = s_obj->fmt.width;
   1294                 wnr_info.frames[j].frame_height = s_obj->fmt.height;
   1295                 memcpy(&wnr_info.frames[j].frame_offset,
   1296                        &s_obj->frame_offset,
   1297                        sizeof(cam_frame_len_offset_t));
   1298                 j++;
   1299             }
   1300         }
   1301         wnr_info.num_frames = j;
   1302 
   1303         rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
   1304                                             CAMERA_DO_PP_WNR,
   1305                                             sizeof(mm_camera_wnr_info_t),
   1306                                             (void *)&wnr_info);
   1307         if (0 != rc) {
   1308             CDBG_ERROR("%s: do_pp_wnr failed (rc=%d)", __func__, rc);
   1309         }
   1310     }
   1311 
   1312     return rc;
   1313 }
   1314 
   1315 int32_t mm_channel_reg_stream_cb(mm_channel_t *my_obj,
   1316                                  mm_stream_data_cb_t *cb,
   1317                                  uint32_t ext_image_mode,
   1318                                  uint32_t sensor_idx)
   1319 {
   1320     uint8_t idx;
   1321     mm_stream_t *dest_stream = NULL;
   1322     int32_t rc = -1;
   1323 
   1324     /* browse all streams in channel to find the destination */
   1325     for (idx=0; idx < MM_CAMEAR_STRAEM_NUM_MAX; idx++) {
   1326         if (my_obj->streams[idx].state != MM_STREAM_STATE_NOTUSED &&
   1327             my_obj->streams[idx].ext_image_mode == ext_image_mode &&
   1328             my_obj->streams[idx].sensor_idx == sensor_idx) {
   1329             /* find matching stream as the destination */
   1330             dest_stream = &my_obj->streams[idx];
   1331             break;
   1332         }
   1333     }
   1334 
   1335     if (NULL != dest_stream) {
   1336         rc = mm_stream_reg_buf_cb(dest_stream, cb);
   1337     }
   1338 
   1339     return rc;
   1340 }
   1341 
   1342 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)
   1343 {
   1344     return mm_camera_queue_init(&queue->que);
   1345 }
   1346 
   1347 int32_t mm_channel_superbuf_queue_deinit(mm_channel_t *my_obj,
   1348                                          mm_channel_queue_t * queue)
   1349 {
   1350     return mm_camera_queue_deinit(&queue->que);
   1351 }
   1352 
   1353 int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1,
   1354                                            uint32_t v2)
   1355 {
   1356     int8_t ret = 0;
   1357 
   1358     /* TODO: need to handle the case if v2 roll over to 0 */
   1359     if (v1 > v2) {
   1360         ret = 1;
   1361     } else if (v1 < v2) {
   1362         ret = -1;
   1363     }
   1364 
   1365     return ret;
   1366 }
   1367 
   1368 int32_t mm_channel_superbuf_comp_and_enqueue(
   1369                         mm_channel_t* ch_obj,
   1370                         mm_channel_queue_t * queue,
   1371                         mm_camera_buf_info_t *buf_info)
   1372 {
   1373     mm_camera_q_node_t* node = NULL;
   1374     struct cam_list *head = NULL;
   1375     struct cam_list *pos = NULL;
   1376     mm_channel_queue_node_t* super_buf = NULL;
   1377     uint8_t buf_s_idx, i;
   1378 
   1379     CDBG("%s: E", __func__);
   1380     for (buf_s_idx=0; buf_s_idx < queue->num_streams; buf_s_idx++) {
   1381         if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) {
   1382             break;
   1383         }
   1384     }
   1385     if (buf_s_idx == queue->num_streams) {
   1386         CDBG_ERROR("%s: buf from stream (%d) not bundled", __func__, buf_info->stream_id);
   1387         return -1;
   1388     }
   1389 
   1390     if (mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx,
   1391                                             queue->expected_frame_id) < 0) {
   1392         /* incoming buf is older than expected buf id, will discard it */
   1393         mm_channel_qbuf(ch_obj, buf_info->buf);
   1394         return 0;
   1395     }
   1396 
   1397     if (MM_CAMERA_SUPER_BUF_PRIORITY_NORMAL != queue->attr.priority) {
   1398         /* TODO */
   1399         /* need to decide if we want to queue the frame based on focus or exposure
   1400          * if frame not to be queued, we need to qbuf it back */
   1401     }
   1402 
   1403     /* comp */
   1404     pthread_mutex_lock(&queue->que.lock);
   1405     head = &queue->que.head.list;
   1406     /* get the last one in the queue which is possibly having no matching */
   1407     pos = head->next;
   1408     while (pos != head) {
   1409         node = member_of(pos, mm_camera_q_node_t, list);
   1410         super_buf = (mm_channel_queue_node_t*)node->data;
   1411         if (NULL != super_buf) {
   1412             if (super_buf->matched) {
   1413                 /* find a matched super buf, move to next one */
   1414                 pos = pos->next;
   1415                 continue;
   1416             } else {
   1417                 /* have an unmatched super buf, break the loop */
   1418                 break;
   1419             }
   1420         }
   1421     }
   1422 
   1423     if (pos == head) {
   1424         CDBG("%s: all nodes in queue are mtached, or no node in queue, create a new node", __func__);
   1425         /* all nodes in queue are mtached, or no node in queue
   1426          * create a new node */
   1427         mm_channel_queue_node_t *new_buf = NULL;
   1428         mm_camera_q_node_t* new_node = NULL;
   1429 
   1430         new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t));
   1431         new_node = (mm_camera_q_node_t*)malloc(sizeof(mm_camera_q_node_t));
   1432         if (NULL != new_buf && NULL != new_node) {
   1433             memset(new_buf, 0, sizeof(mm_channel_queue_node_t));
   1434             memset(new_node, 0, sizeof(mm_camera_q_node_t));
   1435             new_node->data = (void *)new_buf;
   1436             new_buf->num_of_bufs = queue->num_streams;
   1437             memcpy(&new_buf->super_buf[buf_s_idx], buf_info, sizeof(mm_camera_buf_info_t));
   1438 
   1439             /* enqueue */
   1440             //cam_list_add_tail_node(&node->list, &queue->que.head.list);
   1441             cam_list_add_tail_node(&new_node->list, &queue->que.head.list);
   1442             queue->que.size++;
   1443 
   1444             if(queue->num_streams == 1) {
   1445                 //TODO : Check. Live snapshot will have one stream in bundle?
   1446                 new_buf->matched = 1;
   1447 
   1448                 if (new_buf->matched) {
   1449                     queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
   1450                     queue->match_cnt++;
   1451                 }
   1452             }
   1453         } else {
   1454             /* No memory */
   1455             if (NULL != new_buf) {
   1456                 free(new_buf);
   1457             }
   1458             if (NULL != new_node) {
   1459                 free(new_node);
   1460             }
   1461             /* qbuf the new buf since we cannot enqueue */
   1462             mm_channel_qbuf(ch_obj, buf_info->buf);
   1463         }
   1464     } else {
   1465         CDBG("%s: find an unmatched super buf", __func__);
   1466         /* find an unmatched super buf */
   1467         if (super_buf->super_buf[buf_s_idx].frame_idx == 0) {
   1468             /* new frame from the stream_id */
   1469             uint8_t is_new = 1;
   1470             uint32_t frame_idx;
   1471 
   1472             for (i=0; i < super_buf->num_of_bufs; i++) {
   1473             //for (i=0; i < buf_s_idx; i++) {
   1474                 if(super_buf->super_buf[i].buf == NULL) {
   1475                     continue;
   1476                 }
   1477                 frame_idx = super_buf->super_buf[i].buf->frame_idx;
   1478                 if (frame_idx == 0) {
   1479                     continue;
   1480                 }
   1481                 if (frame_idx < buf_info->frame_idx) {
   1482                     /* existing frame is older than the new frame, qbuf it */
   1483                     mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
   1484                     memset(&super_buf->super_buf[i], 0, sizeof(mm_camera_buf_info_t));
   1485                 } else if (frame_idx > buf_info->frame_idx) {
   1486                     /* new frame is older */
   1487                     is_new = 0;
   1488                     break;
   1489                 }else{
   1490                     //TODO: reveiw again
   1491                     break;
   1492                 }
   1493             }
   1494             if (is_new) {
   1495                 CDBG("%s: add stream = %d frame id = %d ",
   1496                      __func__, buf_info->stream_id, buf_info->frame_idx);
   1497                 memcpy(&super_buf->super_buf[buf_s_idx], buf_info, sizeof(mm_camera_buf_info_t));
   1498 
   1499                 /* check if superbuf is all matched */
   1500                 super_buf->matched = 1;
   1501                 for (i=0; i < super_buf->num_of_bufs; i++) {
   1502                     if (super_buf->super_buf[i].frame_idx == 0) {
   1503                         super_buf->matched = 0;
   1504                         break;
   1505                     }
   1506                 }
   1507 
   1508                 if (super_buf->matched) {
   1509                     queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
   1510                     queue->match_cnt++;
   1511                     CDBG("%s, match_cnt = %d", __func__, queue->match_cnt);
   1512                 }
   1513             } else {
   1514                 mm_channel_qbuf(ch_obj, buf_info->buf);
   1515             }
   1516         } else {
   1517             if (super_buf->super_buf[buf_s_idx].frame_idx < buf_info->frame_idx) {
   1518                 CDBG("%s: new frame is newer, add into superbuf", __func__);
   1519                 /* current frames in superbuf are older than the new frame
   1520                  * qbuf all current frames */
   1521                 for (i=0; i<super_buf->num_of_bufs; i++) {
   1522                     if (super_buf->super_buf[i].frame_idx != 0) {
   1523                             mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
   1524                             memset(&super_buf->super_buf[i], 0, sizeof(mm_camera_buf_info_t));
   1525                     }
   1526                 }
   1527                 /* add the new frame into the superbuf */
   1528                 memcpy(&super_buf->super_buf[buf_s_idx], buf_info, sizeof(mm_camera_buf_info_t));
   1529             } else {
   1530                 /* the new frame is older, just ignor */
   1531                 mm_channel_qbuf(ch_obj, buf_info->buf);
   1532             }
   1533         }
   1534     }
   1535     pthread_mutex_unlock(&queue->que.lock);
   1536 
   1537     CDBG("%s: X", __func__);
   1538     return 0;
   1539 }
   1540 
   1541 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue)
   1542 {
   1543     mm_camera_q_node_t* node = NULL;
   1544     struct cam_list *head = NULL;
   1545     struct cam_list *pos = NULL;
   1546     mm_channel_queue_node_t* super_buf = NULL;
   1547 
   1548     head = &queue->que.head.list;
   1549     pos = head->next;
   1550     if (pos != head) {
   1551         /* get the first node */
   1552         node = member_of(pos, mm_camera_q_node_t, list);
   1553         super_buf = (mm_channel_queue_node_t*)node->data;
   1554         if (NULL != super_buf) {
   1555             if (super_buf->matched) {
   1556                 /* we found a mtaching super buf, dequeue it */
   1557                 cam_list_del_node(&node->list);
   1558                 queue->que.size--;
   1559                 queue->match_cnt--;
   1560                 free(node);
   1561             } else {
   1562                 super_buf = NULL;
   1563             }
   1564         }
   1565     }
   1566 
   1567     return super_buf;
   1568 }
   1569 
   1570 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue)
   1571 {
   1572     mm_camera_q_node_t* node = NULL;
   1573     struct cam_list *head = NULL;
   1574     struct cam_list *pos = NULL;
   1575     mm_channel_queue_node_t* super_buf = NULL;
   1576 
   1577     pthread_mutex_lock(&queue->que.lock);
   1578     super_buf = mm_channel_superbuf_dequeue_internal(queue);
   1579     pthread_mutex_unlock(&queue->que.lock);
   1580 
   1581     return super_buf;
   1582 }
   1583 
   1584 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj,
   1585                                              mm_channel_queue_t * queue)
   1586 {
   1587     int32_t rc = 0, i;
   1588     mm_channel_queue_node_t* super_buf = NULL;
   1589     if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
   1590         /* for continuous streaming mode, no overflow is needed */
   1591         return 0;
   1592     }
   1593 
   1594     CDBG("%s: before match_cnt=%d, water_mark=%d",
   1595          __func__, queue->match_cnt, queue->attr.water_mark);
   1596     /* bufdone overflowed bufs */
   1597     pthread_mutex_lock(&queue->que.lock);
   1598     while (queue->match_cnt > queue->attr.water_mark) {
   1599         super_buf = mm_channel_superbuf_dequeue_internal(queue);
   1600         if (NULL != super_buf) {
   1601             for (i=0; i<super_buf->num_of_bufs; i++) {
   1602                 if (NULL != super_buf->super_buf[i].buf) {
   1603                     mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   1604                 }
   1605             }
   1606             free(super_buf);
   1607         }
   1608     }
   1609     pthread_mutex_unlock(&queue->que.lock);
   1610     CDBG("%s: after match_cnt=%d, water_mark=%d",
   1611          __func__, queue->match_cnt, queue->attr.water_mark);
   1612 
   1613     return rc;
   1614 }
   1615 
   1616 int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj,
   1617                                  mm_channel_queue_t * queue)
   1618 {
   1619     int32_t rc = 0, i, count;
   1620     mm_channel_queue_node_t* super_buf = NULL;
   1621     if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
   1622         /* for continuous streaming mode, no skip is needed */
   1623         return 0;
   1624     }
   1625 
   1626     /* bufdone overflowed bufs */
   1627     pthread_mutex_lock(&queue->que.lock);
   1628     while (queue->match_cnt > queue->attr.look_back) {
   1629         super_buf = mm_channel_superbuf_dequeue_internal(queue);
   1630         if (NULL != super_buf) {
   1631             for (i=0; i<super_buf->num_of_bufs; i++) {
   1632                 if (NULL != super_buf->super_buf[i].buf) {
   1633                     mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   1634                 }
   1635             }
   1636             free(super_buf);
   1637         }
   1638     }
   1639     pthread_mutex_unlock(&queue->que.lock);
   1640 
   1641     return rc;
   1642 }
   1643 
   1644 uint32_t mm_channel_open_repro_isp(mm_channel_t *my_obj,
   1645                                    mm_camera_repro_isp_type_t isp_type)
   1646 {
   1647     int32_t rc = -1;
   1648     mm_camera_repro_cmd_t repro_cmd;
   1649 
   1650     memset(&repro_cmd, 0, sizeof(mm_camera_repro_cmd_t));
   1651     repro_cmd.cmd = MM_CAMERA_REPRO_CMD_OPEN;
   1652     repro_cmd.payload.open.isp_type = isp_type;
   1653     rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
   1654                                         CAMERA_SEND_PP_PIPELINE_CMD,
   1655                                         sizeof(mm_camera_repro_cmd_t),
   1656                                         (void *)&repro_cmd);
   1657     if (0 != rc) {
   1658         CDBG_ERROR("%s: open repo isp failed (rc=%d)", __func__, rc);
   1659     }
   1660     return repro_cmd.payload.open.repro_handle;
   1661 }
   1662 
   1663 int32_t mm_channel_close_repro_isp(mm_channel_t *my_obj,
   1664                                    uint32_t repro_handle)
   1665 {
   1666     int32_t rc = -1;
   1667     mm_camera_repro_cmd_t repro_cmd;
   1668 
   1669     memset(&repro_cmd, 0, sizeof(mm_camera_repro_cmd_t));
   1670     repro_cmd.cmd = MM_CAMERA_REPRO_CMD_CLOSE;
   1671     repro_cmd.payload.repro_handle = repro_handle;
   1672     rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
   1673                                         CAMERA_SEND_PP_PIPELINE_CMD,
   1674                                         sizeof(mm_camera_repro_cmd_t),
   1675                                         (void *)&repro_cmd);
   1676     if (0 != rc) {
   1677         CDBG_ERROR("%s: close repo isp failed (rc=%d)", __func__, rc);
   1678     }
   1679     return rc;
   1680 }
   1681 
   1682 int32_t mm_channel_config_repro_isp(mm_channel_t *my_obj,
   1683                                     uint32_t repro_handle,
   1684                                     mm_camera_repro_isp_config_t *config)
   1685 {
   1686     int32_t rc = -1;
   1687     mm_camera_repro_cmd_t repro_cmd;
   1688     mm_stream_t *src_stream = NULL;
   1689     mm_stream_t *dest_streams[MM_CAMERA_MAX_NUM_REPROCESS_DEST];
   1690     uint8_t i;
   1691 
   1692     /* first check if src and dest streams are valid */
   1693     src_stream = mm_channel_util_get_stream_by_handler(my_obj, config->src.inst_handle);
   1694     if (NULL == src_stream) {
   1695         CDBG_ERROR("%s: src stream obj not found %d", __func__, config->src.inst_handle);
   1696         return -1;
   1697     }
   1698     for (i = 0; i <  config->num_dest; i++) {
   1699         dest_streams[i] =
   1700             mm_channel_util_get_stream_by_handler(my_obj, config->dest[i].inst_handle);
   1701         if (NULL == dest_streams[i]) {
   1702             CDBG_ERROR("%s: dest stream obj not found %d", __func__, config->dest[i].inst_handle);
   1703             return -1;
   1704         }
   1705     }
   1706 
   1707     /* fill in config */
   1708     memset(&repro_cmd, 0, sizeof(mm_camera_repro_cmd_t));
   1709     repro_cmd.cmd = MM_CAMERA_REPRO_CMD_CONFIG;
   1710     repro_cmd.payload.config.repro_handle = repro_handle;
   1711     /* using instant handler which can be understandable by mctl */
   1712     repro_cmd.payload.config.src.inst_handle = src_stream->inst_hdl;
   1713     /* translate to V4L2 ext image mode */
   1714     repro_cmd.payload.config.src.image_mode =
   1715         mm_channel_get_ext_mode_from_img_mode(config->src.image_mode);
   1716     repro_cmd.payload.config.src.format = config->src.format;
   1717     repro_cmd.payload.config.src.width = config->src.width;
   1718     repro_cmd.payload.config.src.height = config->src.height;
   1719     CDBG("%s: src: inst_hdl=0x%x, image_mode=%d, format=%d, width x height=%dx%d",
   1720          __func__,
   1721          repro_cmd.payload.config.src.inst_handle,
   1722          repro_cmd.payload.config.src.image_mode,
   1723          repro_cmd.payload.config.src.format,
   1724          repro_cmd.payload.config.src.width,
   1725          repro_cmd.payload.config.src.height);
   1726     repro_cmd.payload.config.num_dest = config->num_dest;
   1727     for (i = 0; i < repro_cmd.payload.config.num_dest; i++) {
   1728         /* using instant handler which can be understandable by mctl */
   1729         repro_cmd.payload.config.dest[i].inst_handle = dest_streams[i]->inst_hdl;
   1730         /* translate into V4L2 ext image mode */
   1731         repro_cmd.payload.config.dest[i].image_mode =
   1732             mm_channel_get_ext_mode_from_img_mode(config->dest[i].image_mode);
   1733         repro_cmd.payload.config.dest[i].format = config->dest[i].format;
   1734         repro_cmd.payload.config.dest[i].width = config->dest[i].width;
   1735         repro_cmd.payload.config.dest[i].height = config->dest[i].height;
   1736         CDBG("%s: dest %d: inst_hdl=0x%x, image_mode=%d, format=%d, width x height=%dx%d",
   1737              __func__, i,
   1738              repro_cmd.payload.config.dest[i].inst_handle,
   1739              repro_cmd.payload.config.dest[i].image_mode,
   1740              repro_cmd.payload.config.dest[i].format,
   1741              repro_cmd.payload.config.dest[i].width,
   1742              repro_cmd.payload.config.dest[i].height);
   1743     }
   1744     rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
   1745                                         CAMERA_SEND_PP_PIPELINE_CMD,
   1746                                         sizeof(mm_camera_repro_cmd_t),
   1747                                         (void *)&repro_cmd);
   1748     if (0 != rc) {
   1749         CDBG_ERROR("%s: config repo isp failed (rc=%d)", __func__, rc);
   1750     }
   1751     return rc;
   1752 }
   1753 
   1754 int32_t mm_channel_repro_isp_dest_stream_ops(mm_channel_t *my_obj,
   1755                                              uint32_t repro_handle,
   1756                                              uint32_t stream_handle,
   1757                                              uint8_t attach_flag)
   1758 {
   1759     int32_t rc = -1;
   1760     mm_stream_t *stream_obj = NULL;
   1761     mm_camera_repro_cmd_t repro_cmd;
   1762 
   1763     /* first check if streams are valid */
   1764     stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_handle);
   1765     if (NULL == stream_obj) {
   1766         CDBG_ERROR("%s: stream obj not found %d", __func__, stream_handle);
   1767         return -1;
   1768     }
   1769 
   1770     memset(&repro_cmd, 0, sizeof(mm_camera_repro_cmd_t));
   1771     repro_cmd.cmd = MM_CAMERA_REPRO_CMD_ATTACH_DETACH;
   1772     repro_cmd.payload.attach_detach.repro_handle = repro_handle;
   1773     repro_cmd.payload.attach_detach.attach_flag = attach_flag;
   1774     repro_cmd.payload.attach_detach.inst_handle = stream_obj->inst_hdl;
   1775     rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
   1776                                         CAMERA_SEND_PP_PIPELINE_CMD,
   1777                                         sizeof(mm_camera_repro_cmd_t),
   1778                                         (void *)&repro_cmd);
   1779     if (0 != rc) {
   1780         CDBG_ERROR("%s: repo isp stream operation failed (flag=%d, rc=%d)",
   1781                    __func__, attach_flag, rc);
   1782     }
   1783     return rc;
   1784 }
   1785 
   1786 int32_t mm_channel_repro_isp_ops(mm_channel_t *my_obj,
   1787                                  uint32_t repro_handle,
   1788                                  uint32_t stream_id,
   1789                                  uint8_t start_flag)
   1790 {
   1791     int32_t rc = -1;
   1792     mm_camera_repro_cmd_t repro_cmd;
   1793     mm_stream_t *stream_obj = NULL;
   1794 
   1795     /* first check if streams are valid */
   1796     stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
   1797     if (NULL == stream_obj) {
   1798         CDBG_ERROR("%s: stream obj not found %d", __func__, stream_id);
   1799         return -1;
   1800     }
   1801 
   1802     memset(&repro_cmd, 0, sizeof(mm_camera_repro_cmd_t));
   1803     repro_cmd.cmd = MM_CAMERA_REPRO_CMD_START_STOP;
   1804     repro_cmd.payload.start_stop.repro_handle = repro_handle;
   1805     repro_cmd.payload.start_stop.dest_handle = stream_obj->inst_hdl;
   1806     repro_cmd.payload.start_stop.start_flag = start_flag;
   1807     rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
   1808                                         CAMERA_SEND_PP_PIPELINE_CMD,
   1809                                         sizeof(mm_camera_repro_cmd_t),
   1810                                         (void *)&repro_cmd);
   1811     if (0 != rc) {
   1812         CDBG_ERROR("%s: repo isp stream operation failed (flag=%d, rc=%d)",
   1813                    __func__, start_flag, rc);
   1814     }
   1815     return rc;
   1816 }
   1817 
   1818 int32_t mm_channel_reprocess(mm_channel_t *my_obj,
   1819                              uint32_t repro_handle,
   1820                              mm_camera_repro_data_t *repro_data)
   1821 {
   1822     int32_t rc = -1;
   1823     mm_camera_repro_cmd_t repro_cmd;
   1824     mm_stream_t *stream_obj = NULL;
   1825     uint8_t i;
   1826 
   1827     /* check if input param is valid */
   1828     if (NULL == repro_data || NULL == repro_data->src_frame) {
   1829         CDBG_ERROR("%s: invalid input param", __func__);
   1830         return -1;
   1831     }
   1832 
   1833     /* check if streams are valid */
   1834     stream_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1835                                                        repro_data->src_frame->stream_id);
   1836     if (NULL == stream_obj) {
   1837         CDBG_ERROR("%s: stream obj not found %d",
   1838                    __func__, repro_data->src_frame->stream_id);
   1839         return -1;
   1840     }
   1841 
   1842     memset(&repro_cmd, 0, sizeof(mm_camera_repro_cmd_t));
   1843     repro_cmd.cmd = MM_CAMERA_REPRO_CMD_START_STOP;
   1844     repro_cmd.payload.reprocess.repro_handle = repro_handle;
   1845     repro_cmd.payload.reprocess.inst_handle = stream_obj->inst_hdl;
   1846     repro_cmd.payload.reprocess.buf_idx = repro_data->src_frame->buf_idx;
   1847     repro_cmd.payload.reprocess.frame_id = repro_data->src_frame->frame_idx;
   1848     repro_cmd.payload.reprocess.frame_len = repro_data->src_frame->frame_len;
   1849     repro_cmd.payload.reprocess.timestamp.tv_sec =
   1850         repro_data->src_frame->ts.tv_sec;
   1851     repro_cmd.payload.reprocess.timestamp.tv_usec =
   1852         repro_data->src_frame->ts.tv_nsec/1000;
   1853     repro_cmd.payload.reprocess.num_planes = repro_data->src_frame->num_planes;
   1854     for (i = 0; i < repro_cmd.payload.reprocess.num_planes; i++) {
   1855         repro_cmd.payload.reprocess.planes[i].addr_offset =
   1856             repro_data->src_frame->planes[i].reserved[0];
   1857         repro_cmd.payload.reprocess.planes[i].data_offset =
   1858             repro_data->src_frame->planes[i].data_offset;
   1859         repro_cmd.payload.reprocess.planes[i].length =
   1860             repro_data->src_frame->planes[i].length;
   1861     }
   1862     rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
   1863                                         CAMERA_SEND_PP_PIPELINE_CMD,
   1864                                         sizeof(mm_camera_repro_cmd_t),
   1865                                         (void *)&repro_cmd);
   1866     if (0 != rc) {
   1867         CDBG_ERROR("%s: do reprocess failed (rc=%d)", __func__, rc);
   1868     }
   1869     return rc;
   1870 }
   1871 
   1872