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 #include <linux/msm_ion.h>
     39 
     40 #include "mm_camera_dbg.h"
     41 #include "mm_camera_interface.h"
     42 #include "mm_camera.h"
     43 
     44 extern mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler);
     45 extern mm_channel_t * mm_camera_util_get_channel_by_handler(
     46                                     mm_camera_obj_t * cam_obj,
     47                                     uint32_t handler);
     48 extern int32_t mm_camera_send_native_ctrl_cmd(mm_camera_obj_t * my_obj,
     49                                        cam_ctrl_type type,
     50                                        uint32_t length,
     51                                        void *value);
     52 extern int32_t mm_camera_send_native_ctrl_timeout_cmd(mm_camera_obj_t * my_obj,
     53                                                cam_ctrl_type type,
     54                                                uint32_t length,
     55                                                void *value,
     56                                                int timeout);
     57 
     58 /* internal function declare goes here */
     59 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
     60                         mm_camera_buf_def_t *buf);
     61 int32_t mm_channel_init(mm_channel_t *my_obj);
     62 void mm_channel_release(mm_channel_t *my_obj);
     63 uint32_t mm_channel_add_stream(mm_channel_t *my_obj,
     64                                    mm_camera_buf_notify_t buf_cb, void *user_data,
     65                                    uint32_t ext_image_mode, uint32_t sensor_idx);
     66 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
     67                                    uint32_t stream_id);
     68 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
     69                                  uint32_t stream_id,
     70                                  mm_camera_stream_config_t *config);
     71 int32_t mm_channel_bundle_stream(mm_channel_t *my_obj,
     72                                  mm_camera_buf_notify_t super_frame_notify_cb,
     73                                  void *user_data,
     74                                  mm_camera_bundle_attr_t *attr,
     75                                  uint8_t num_streams,
     76                                  uint32_t *stream_ids);
     77 int32_t mm_channel_destroy_bundle(mm_channel_t *my_obj);
     78 int32_t mm_channel_start_streams(mm_channel_t *my_obj,
     79                                  uint8_t num_streams,
     80                                  uint32_t *stream_ids);
     81 int32_t mm_channel_stop_streams(mm_channel_t *my_obj,
     82                                 uint8_t num_streams,
     83                                 uint32_t *stream_ids,
     84                                 uint8_t tear_down_flag);
     85 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj);
     86 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj);
     87 int32_t mm_channel_start_focus(mm_channel_t *my_obj,
     88                                uint32_t sensor_idx,
     89                                uint32_t focus_mode);
     90 int32_t mm_channel_abort_focus(mm_channel_t *my_obj,
     91                                uint32_t sensor_idx);
     92 int32_t mm_channel_prepare_snapshot(mm_channel_t *my_obj,
     93                                     uint32_t sensor_idx);
     94 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
     95                                    uint32_t s_id,
     96                                    void *value);
     97 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
     98                                    uint32_t s_id,
     99                                    void *value);
    100 uint8_t mm_channel_need_do_pp(mm_channel_t *my_obj,
    101                               mm_channel_queue_node_t *super_buf);
    102 int32_t mm_channel_do_post_processing(mm_channel_t *my_obj,
    103                                       mm_channel_queue_node_t *super_buf);
    104 int32_t mm_channel_cancel_post_processing(mm_channel_t *my_obj);
    105 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj,
    106                                              mm_channel_queue_t * queue);
    107 int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj,
    108                                  mm_channel_queue_t * queue);
    109 
    110 /* state machine function declare */
    111 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
    112                           mm_channel_evt_type_t evt,
    113                           void * in_val,
    114                           void * out_val);
    115 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
    116                           mm_channel_evt_type_t evt,
    117                           void * in_val,
    118                           void * out_val);
    119 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
    120                           mm_channel_evt_type_t evt,
    121                           void * in_val,
    122                           void * out_val);
    123 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
    124                           mm_channel_evt_type_t evt,
    125                           void * in_val,
    126                           void * out_val);
    127 
    128 /* channel super queue functions */
    129 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue);
    130 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue);
    131 int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj,
    132                                              mm_channel_queue_t * queue,
    133                                              mm_camera_buf_info_t *buf);
    134 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue);
    135 
    136 /* channel utility function */
    137 mm_stream_t * mm_channel_util_get_stream_by_handler(
    138                                     mm_channel_t * ch_obj,
    139                                     uint32_t handler)
    140 {
    141     int i;
    142     mm_stream_t *s_obj = NULL;
    143     uint8_t ch_idx = mm_camera_util_get_index_by_handler(handler);
    144 
    145     for(i = 0; i < MM_CAMEAR_STRAEM_NUM_MAX; i++) {
    146         if (handler == ch_obj->streams[i].my_hdl) {
    147             s_obj = &ch_obj->streams[i];
    148             break;
    149         }
    150     }
    151     return s_obj;
    152 }
    153 
    154 /* CB for handling post processing result from ctrl evt */
    155 static void mm_channel_pp_result_notify(uint32_t camera_handler,
    156                                         mm_camera_event_t *evt,
    157                                         void *user_data)
    158 {
    159     uint32_t ch_hdl = (uint32_t)user_data;
    160     mm_camera_obj_t *cam_obj = NULL;
    161     mm_channel_t *ch_obj = NULL;
    162     mm_channel_queue_node_t * node = NULL;
    163     mm_channel_pp_info_t* pp_info = NULL;
    164 
    165     cam_obj = mm_camera_util_get_camera_by_handler(camera_handler);
    166     if (NULL == cam_obj) {
    167         CDBG("%s: No matching camera handler", __func__);
    168         return;
    169     }
    170 
    171     ch_obj = mm_camera_util_get_channel_by_handler(cam_obj, ch_hdl);
    172     if (NULL == ch_obj) {
    173         CDBG("%s: No matching channel handler", __func__);
    174         return;
    175     }
    176 
    177     pthread_mutex_lock(&ch_obj->ch_lock);
    178     if (ch_obj->pending_pp_cnt > 0) {
    179         if (MM_CAMERA_EVT_TYPE_CTRL == evt->event_type) {
    180             /* PP result is sent as CTRL event
    181              * currently we only have WNR */
    182             if (MM_CAMERA_CTRL_EVT_WDN_DONE == evt->e.ctrl.evt) {
    183                 /* WNR result */
    184                 pp_info = (mm_channel_pp_info_t *)evt->e.ctrl.cookie;
    185                 if (NULL != pp_info) {
    186                     node = pp_info->super_buf;
    187                 }
    188             }
    189         }
    190 
    191         if (NULL != node) {
    192             uint8_t pp_done = 1;
    193             if (CAM_CTRL_SUCCESS == evt->e.ctrl.status) {
    194                 uint8_t i;
    195                 /* 1) update need_pp flag as action done */
    196                 for (i=0; i<node->num_of_bufs; i++) {
    197                     if (node->super_buf[i].stream_id == pp_info->stream_hdl) {
    198                         /* stream pp is done, set the flag to 0*/
    199                         node->super_buf[i].need_pp = 0;
    200                         break;
    201                     }
    202                 }
    203 
    204                 /* 2) check if all bufs done with pp */
    205                 for (i=0; i<node->num_of_bufs; i++) {
    206                     if (node->super_buf[i].need_pp) {
    207                         pp_done = 0;
    208                         break;
    209                     }
    210                 }
    211             }
    212 
    213             if (pp_done) {
    214                 /* send super buf to CB */
    215                 if (NULL != ch_obj->bundle.super_buf_notify_cb) {
    216                     mm_camera_super_buf_t super_buf;
    217                     uint8_t i;
    218 
    219                     memset(&super_buf, 0, sizeof(mm_camera_super_buf_t));
    220                     super_buf.num_bufs = node->num_of_bufs;
    221                     for (i=0; i<node->num_of_bufs; i++) {
    222                         super_buf.bufs[i] = node->super_buf[i].buf;
    223                     }
    224                     super_buf.camera_handle = ch_obj->cam_obj->my_hdl;
    225                     super_buf.ch_id = ch_obj->my_hdl;
    226 
    227                     ch_obj->bundle.super_buf_notify_cb(&super_buf,
    228                                                        ch_obj->bundle.user_data);
    229                     ch_obj->pending_pp_cnt--;
    230                 } else {
    231                     /* buf done with the nonuse super buf */
    232                     uint8_t i;
    233                     for (i=0; i<node->num_of_bufs; i++) {
    234                         mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
    235                     }
    236                 }
    237 
    238                 /* done with node, free it */
    239                 free(node);
    240             }
    241         }
    242     }
    243     pthread_mutex_unlock(&ch_obj->ch_lock);
    244 }
    245 
    246 /* CB for processing stream buffer */
    247 static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,
    248                                           void *user_data)
    249 {
    250     mm_camera_super_buf_notify_mode_t notify_mode;
    251     mm_channel_queue_node_t *node = NULL;
    252     mm_channel_t *ch_obj = (mm_channel_t *)user_data;
    253     if (NULL == ch_obj) {
    254         return;
    255     }
    256 
    257     if (MM_CAMERA_CMD_TYPE_DATA_CB  == cmd_cb->cmd_type) {
    258         /* comp_and_enqueue */
    259         mm_channel_superbuf_comp_and_enqueue(
    260                         ch_obj,
    261                         &ch_obj->bundle.superbuf_queue,
    262                         &cmd_cb->u.buf);
    263     }
    264 
    265     notify_mode = ch_obj->bundle.superbuf_queue.attr.notify_mode;
    266 
    267     /* bufdone for overflowed bufs */
    268     mm_channel_superbuf_bufdone_overflow(ch_obj, &ch_obj->bundle.superbuf_queue);
    269 
    270     /* lock ch_lock */
    271     pthread_mutex_lock(&ch_obj->ch_lock);
    272 
    273     /* dispatch frame if pending_cnt>0 or is in continuous streaming mode */
    274     while ( (ch_obj->pending_cnt > 0) ||
    275             (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == notify_mode) ) {
    276 
    277         /* skip frames if needed */
    278         mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue);
    279 
    280         /* dequeue */
    281         node = mm_channel_superbuf_dequeue(&ch_obj->bundle.superbuf_queue);
    282         if (NULL != node) {
    283             /* decrease pending_cnt */
    284             CDBG("%s: Super Buffer received, Call client callback",__func__);
    285             if (MM_CAMERA_SUPER_BUF_NOTIFY_BURST == notify_mode) {
    286                 ch_obj->pending_cnt--;
    287             }
    288 
    289             if (mm_channel_need_do_pp(ch_obj, node)) {
    290                 /* do post processing */
    291                 ch_obj->pending_pp_cnt++;
    292                 mm_channel_do_post_processing(ch_obj, node);
    293                 /* no need to free node here
    294                  * node will be as cookie sent to backend doing pp */
    295             } else {
    296                 /* dispatch superbuf */
    297                 if (NULL != ch_obj->bundle.super_buf_notify_cb) {
    298                     mm_camera_super_buf_t super_buf;
    299                     uint8_t i;
    300 
    301                     memset(&super_buf, 0, sizeof(mm_camera_super_buf_t));
    302                     super_buf.num_bufs = node->num_of_bufs;
    303                     for (i=0; i<node->num_of_bufs; i++) {
    304                         super_buf.bufs[i] = node->super_buf[i].buf;
    305                     }
    306                     super_buf.camera_handle = ch_obj->cam_obj->my_hdl;
    307                     super_buf.ch_id = ch_obj->my_hdl;
    308 
    309                     ch_obj->bundle.super_buf_notify_cb(&super_buf,
    310                                                        ch_obj->bundle.user_data);
    311                 } else {
    312                     /* buf done with the nonuse super buf */
    313                     uint8_t i;
    314                     for (i=0; i<node->num_of_bufs; i++) {
    315                         mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
    316                     }
    317                 }
    318                 free(node);
    319             }
    320         } else {
    321             /* no superbuf avail, break the loop */
    322             CDBG_ERROR("%s : Superbuffer not available",__func__);
    323             break;
    324         }
    325     }
    326 
    327     /* unlock ch_lock */
    328     pthread_mutex_unlock(&ch_obj->ch_lock);
    329 }
    330 
    331 /* state machine entry */
    332 int32_t mm_channel_fsm_fn(mm_channel_t *my_obj,
    333                           mm_channel_evt_type_t evt,
    334                           void * in_val,
    335                           void * out_val)
    336 {
    337     int32_t rc = -1;
    338 
    339     CDBG("%s : E state = %d",__func__,my_obj->state);
    340     switch (my_obj->state) {
    341     case MM_CHANNEL_STATE_NOTUSED:
    342         rc = mm_channel_fsm_fn_notused(my_obj, evt, in_val, out_val);
    343         break;
    344     case MM_CHANNEL_STATE_STOPPED:
    345         rc = mm_channel_fsm_fn_stopped(my_obj, evt, in_val, out_val);
    346         break;
    347     case MM_CHANNEL_STATE_ACTIVE:
    348         rc = mm_channel_fsm_fn_active(my_obj, evt, in_val, out_val);
    349         break;
    350     case MM_CHANNEL_STATE_PAUSED:
    351         rc = mm_channel_fsm_fn_paused(my_obj, evt, in_val, out_val);
    352         break;
    353     default:
    354         CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
    355         break;
    356     }
    357 
    358     /* unlock ch_lock */
    359     pthread_mutex_unlock(&my_obj->ch_lock);
    360     CDBG("%s : X rc = %d",__func__,rc);
    361     return rc;
    362 }
    363 
    364 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
    365                           mm_channel_evt_type_t evt,
    366                           void * in_val,
    367                           void * out_val)
    368 {
    369     int32_t rc = -1;
    370 
    371     switch (evt) {
    372     default:
    373         CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
    374                    __func__, my_obj->state, evt);
    375         break;
    376     }
    377 
    378     return rc;
    379 }
    380 
    381 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
    382                           mm_channel_evt_type_t evt,
    383                           void * in_val,
    384                           void * out_val)
    385 {
    386     int32_t rc = -1;
    387     CDBG("%s : E evt = %d",__func__,evt);
    388     switch (evt) {
    389     case MM_CHANNEL_EVT_ADD_STREAM:
    390         {
    391             uint32_t s_hdl = 0;
    392             mm_evt_paylod_add_stream_t *payload =
    393                 (mm_evt_paylod_add_stream_t *)in_val;
    394             s_hdl = mm_channel_add_stream(my_obj,
    395                                           payload->buf_cb,
    396                                           payload->user_data,
    397                                           payload->ext_image_mode,
    398                                           payload->sensor_idx);
    399             *((uint32_t*)out_val) = s_hdl;
    400             rc = 0;
    401         }
    402         break;
    403     case MM_CHANNEL_EVT_DEL_STREAM:
    404         {
    405             uint32_t s_id = *((uint32_t *)in_val);
    406             rc = mm_channel_del_stream(my_obj, s_id);
    407         }
    408         break;
    409     case MM_CHANNEL_EVT_START_STREAM:
    410         {
    411             mm_evt_payload_start_stream_t *payload =
    412                 (mm_evt_payload_start_stream_t *)in_val;
    413             rc = mm_channel_start_streams(my_obj,
    414                                           payload->num_streams,
    415                                           payload->stream_ids);
    416             /* first stream started in stopped state
    417              * move to active state */
    418             if (0 == rc) {
    419                 my_obj->state = MM_CHANNEL_STATE_ACTIVE;
    420             }
    421         }
    422         break;
    423     case MM_CHANNEL_EVT_CONFIG_STREAM:
    424         {
    425             mm_evt_paylod_config_stream_t *payload =
    426                 (mm_evt_paylod_config_stream_t *)in_val;
    427             rc = mm_channel_config_stream(my_obj,
    428                                           payload->stream_id,
    429                                           payload->config);
    430         }
    431         break;
    432     case MM_CHANNEL_EVT_INIT_BUNDLE:
    433         {
    434             mm_evt_payload_bundle_stream_t *payload =
    435                 (mm_evt_payload_bundle_stream_t *)in_val;
    436             rc = mm_channel_bundle_stream(my_obj,
    437                                           payload->super_frame_notify_cb,
    438                                           payload->user_data,
    439                                           payload->attr,
    440                                           payload->num_streams,
    441                                           payload->stream_ids);
    442         }
    443         break;
    444     case MM_CHANNEL_EVT_DESTROY_BUNDLE:
    445         rc = mm_channel_destroy_bundle(my_obj);
    446         break;
    447     case MM_CHANNEL_EVT_PREPARE_SNAPSHOT:
    448         {
    449             uint32_t sensor_idx = (uint32_t)in_val;
    450             rc = mm_channel_prepare_snapshot(my_obj, sensor_idx);
    451         }
    452         break;
    453     case MM_CHANNEL_EVT_DELETE:
    454         mm_channel_release(my_obj);
    455         rc = 0;
    456         break;
    457     case MM_CHANNEL_EVT_SET_STREAM_PARM:
    458         {
    459             uint32_t s_id = (uint32_t)in_val;
    460             rc = mm_channel_set_stream_parm(my_obj, s_id, out_val);
    461         }
    462         break;
    463     case MM_CHANNEL_EVT_GET_STREAM_PARM:
    464         {
    465             uint32_t s_id = (uint32_t)in_val;
    466             rc = mm_channel_get_stream_parm(my_obj, s_id, out_val);
    467         }
    468         break;
    469     default:
    470         CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
    471                    __func__, my_obj->state, evt);
    472         break;
    473     }
    474     CDBG("%s : E rc = %d",__func__,rc);
    475     return rc;
    476 }
    477 
    478 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
    479                           mm_channel_evt_type_t evt,
    480                           void * in_val,
    481                           void * out_val)
    482 {
    483     int32_t rc = -1;
    484 
    485     CDBG("%s : E evt = %d",__func__,evt);
    486     switch (evt) {
    487     case MM_CHANNEL_EVT_CONFIG_STREAM:
    488         {
    489             mm_evt_paylod_config_stream_t *payload =
    490                 (mm_evt_paylod_config_stream_t *)in_val;
    491             rc = mm_channel_config_stream(my_obj,
    492                                           payload->stream_id,
    493                                           payload->config);
    494         }
    495         break;
    496     case MM_CHANNEL_EVT_START_STREAM:
    497         {
    498             mm_evt_payload_start_stream_t *payload =
    499                 (mm_evt_payload_start_stream_t *)in_val;
    500             rc = mm_channel_start_streams(my_obj,
    501                                           payload->num_streams,
    502                                           payload->stream_ids);
    503         }
    504         break;
    505     case MM_CHANNEL_EVT_STOP_STREAM:
    506     case MM_CHANNEL_EVT_TEARDOWN_STREAM:
    507         {
    508             int i;
    509             uint8_t tear_down_flag = (MM_CHANNEL_EVT_TEARDOWN_STREAM == evt)? 1:0;
    510             uint8_t all_stopped = 1;
    511             mm_evt_payload_stop_stream_t *payload =
    512                 (mm_evt_payload_stop_stream_t *)in_val;
    513 
    514             rc = mm_channel_stop_streams(my_obj,
    515                                          payload->num_streams,
    516                                          payload->stream_ids,
    517                                          tear_down_flag);
    518 
    519             /* check if all streams are stopped
    520              * then we move to stopped state */
    521 
    522             for (i=0; i<MM_CAMEAR_STRAEM_NUM_MAX; i++) {
    523                 if (MM_STREAM_STATE_ACTIVE_STREAM_ON == my_obj->streams[i].state ||
    524                     MM_STREAM_STATE_ACTIVE_STREAM_OFF == my_obj->streams[i].state) {
    525                     all_stopped = 0;
    526                     break;
    527                 }
    528             }
    529             if (all_stopped) {
    530                 my_obj->state = MM_CHANNEL_STATE_STOPPED;
    531             }
    532 
    533         }
    534         break;
    535     case MM_CHANNEL_EVT_INIT_BUNDLE:
    536         {
    537             mm_evt_payload_bundle_stream_t *payload =
    538                 (mm_evt_payload_bundle_stream_t *)in_val;
    539             rc = mm_channel_bundle_stream(my_obj,
    540                                           payload->super_frame_notify_cb,
    541                                           payload->user_data,
    542                                           payload->attr,
    543                                           payload->num_streams,
    544                                           payload->stream_ids);
    545         }
    546         break;
    547     case MM_CHANNEL_EVT_DESTROY_BUNDLE:
    548         rc = mm_channel_destroy_bundle(my_obj);
    549         break;
    550     case MM_CHANNEL_EVT_REQUEST_SUPER_BUF:
    551         rc = mm_channel_request_super_buf(my_obj);
    552         break;
    553     case MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF:
    554         rc = mm_channel_cancel_super_buf_request(my_obj);
    555         break;
    556     case MM_CHANNEL_EVT_START_FOCUS:
    557         {
    558             mm_evt_payload_start_focus_t* payload =
    559                 (mm_evt_payload_start_focus_t *)in_val;
    560             rc = mm_channel_start_focus(my_obj,
    561                                         payload->sensor_idx,
    562                                         payload->focus_mode);
    563         }
    564         break;
    565     case MM_CHANNEL_EVT_ABORT_FOCUS:
    566         {
    567             uint32_t sensor_idx = (uint32_t)in_val;
    568             rc = mm_channel_abort_focus(my_obj, sensor_idx);
    569         }
    570         break;
    571     case MM_CHANNEL_EVT_PREPARE_SNAPSHOT:
    572         {
    573             uint32_t sensor_idx = (uint32_t)in_val;
    574             rc = mm_channel_prepare_snapshot(my_obj, sensor_idx);
    575         }
    576         break;
    577     case MM_CHANNEL_EVT_SET_STREAM_PARM:
    578         {
    579             uint32_t s_id = (uint32_t)in_val;
    580             rc = mm_channel_set_stream_parm(my_obj, s_id, out_val);
    581         }
    582         break;
    583     case MM_CHANNEL_EVT_GET_STREAM_PARM:
    584         {
    585             uint32_t s_id = (uint32_t)in_val;
    586             rc = mm_channel_get_stream_parm(my_obj, s_id, out_val);
    587         }
    588         break;
    589 
    590     case MM_CHANNEL_EVT_DEL_STREAM:
    591         {
    592             uint32_t s_id = *((uint32_t *)in_val);
    593             rc = mm_channel_del_stream(my_obj, s_id);
    594         }
    595         break;
    596     default:
    597         CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
    598                    __func__, my_obj->state, evt);
    599         break;
    600     }
    601     CDBG("%s : X rc = %d",__func__,rc);
    602     return rc;
    603 }
    604 
    605 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
    606                           mm_channel_evt_type_t evt,
    607                           void * in_val,
    608                           void * out_val)
    609 {
    610     int32_t rc = -1;
    611 
    612     /* currently we are not supporting pause/resume channel */
    613     CDBG_ERROR("%s: evt (%d) not supported in state (%d)",
    614                __func__, evt, my_obj->state);
    615 
    616     return rc;
    617 }
    618 
    619 int32_t mm_channel_init(mm_channel_t *my_obj)
    620 {
    621     int32_t rc = 0;
    622     CDBG("%s : Launch data poll thread in channel open",__func__);
    623     mm_camera_poll_thread_launch(&my_obj->poll_thread[0],
    624                                  MM_CAMERA_POLL_TYPE_CH);
    625 
    626     /* change state to stopped state */
    627     my_obj->state = MM_CHANNEL_STATE_STOPPED;
    628     return rc;
    629 }
    630 
    631 void mm_channel_release(mm_channel_t *my_obj)
    632 {
    633     /* stop data poll thread */
    634     mm_camera_poll_thread_release(&my_obj->poll_thread[0]);
    635 
    636     /* change state to notused state */
    637     my_obj->state = MM_CHANNEL_STATE_NOTUSED;
    638 }
    639 
    640 uint32_t mm_channel_add_stream(mm_channel_t *my_obj,
    641                               mm_camera_buf_notify_t buf_cb, void *user_data,
    642                               uint32_t ext_image_mode, uint32_t sensor_idx)
    643 {
    644     int32_t rc = 0;
    645     uint8_t idx = 0;
    646     uint32_t s_hdl = 0;
    647     mm_stream_t *stream_obj = NULL;
    648 
    649     CDBG("%s : image mode = %d",__func__,ext_image_mode);
    650     /* check available stream */
    651     for (idx = 0; idx < MM_CAMEAR_STRAEM_NUM_MAX; idx++) {
    652         if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) {
    653             stream_obj = &my_obj->streams[idx];
    654             break;
    655         }
    656     }
    657     if (NULL == stream_obj) {
    658         CDBG_ERROR("%s: streams reach max, no more stream allowed to add", __func__);
    659         return s_hdl;
    660     }
    661 
    662     /* initialize stream object */
    663     memset(stream_obj, 0, sizeof(mm_stream_t));
    664     stream_obj->my_hdl = mm_camera_util_generate_handler(idx);
    665     stream_obj->ch_obj = my_obj;
    666     /* cd through intf always palced at idx 0 of buf_cb */
    667     stream_obj->buf_cb[0].cb = buf_cb;
    668     stream_obj->buf_cb[0].user_data = user_data;
    669     stream_obj->buf_cb[0].cb_count = -1; /* infinite by default */
    670     stream_obj->ext_image_mode = ext_image_mode + 1;
    671     stream_obj->sensor_idx = sensor_idx;
    672     stream_obj->fd = -1;
    673     pthread_mutex_init(&stream_obj->buf_lock, NULL);
    674     pthread_mutex_init(&stream_obj->cb_lock, NULL);
    675     stream_obj->state = MM_STREAM_STATE_INITED;
    676 
    677     /* acquire stream */
    678     rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL);
    679     if (0 == rc) {
    680         s_hdl = stream_obj->my_hdl;
    681     } else {
    682         /* error during acquire, de-init */
    683         pthread_mutex_destroy(&stream_obj->buf_lock);
    684         pthread_mutex_destroy(&stream_obj->cb_lock);
    685         memset(stream_obj, 0, sizeof(mm_stream_t));
    686     }
    687     CDBG("%s : stream handle = %d",__func__,s_hdl);
    688     return s_hdl;
    689 }
    690 
    691 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
    692                               uint32_t stream_id)
    693 {
    694     int rc = -1;
    695     mm_stream_t * stream_obj = NULL;
    696     stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
    697 
    698     if (NULL == stream_obj) {
    699         CDBG_ERROR("%s :Invalid Stream Object",__func__);
    700         return rc;
    701     }
    702 
    703     rc = mm_stream_fsm_fn(stream_obj,
    704                           MM_STREAM_EVT_RELEASE,
    705                           NULL,
    706                           NULL);
    707 
    708     return rc;
    709 }
    710 
    711 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
    712                                    uint32_t stream_id,
    713                                    mm_camera_stream_config_t *config)
    714 {
    715     int rc = -1;
    716     mm_stream_t * stream_obj = NULL;
    717     CDBG("%s : E stream ID = %d",__func__,stream_id);
    718     stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
    719 
    720     if (NULL == stream_obj) {
    721         CDBG_ERROR("%s : X rc = %d",__func__,rc);
    722         return rc;
    723     }
    724 
    725     /* set stream fmt */
    726     rc = mm_stream_fsm_fn(stream_obj,
    727                           MM_STREAM_EVT_SET_FMT,
    728                           (void *)config,
    729                           NULL);
    730     CDBG("%s : X rc = %d",__func__,rc);
    731     return rc;
    732 }
    733 
    734 int32_t mm_channel_bundle_stream(mm_channel_t *my_obj,
    735                                  mm_camera_buf_notify_t super_frame_notify_cb,
    736                                  void *user_data,
    737                                  mm_camera_bundle_attr_t *attr,
    738                                  uint8_t num_streams,
    739                                  uint32_t *stream_ids)
    740 {
    741     int32_t rc = 0;
    742     int i;
    743     mm_stream_t* s_objs[MM_CAMEAR_MAX_STRAEM_BUNDLE] = {NULL};
    744 
    745     /* first check if all streams to be bundled are valid */
    746     for (i=0; i < num_streams; i++) {
    747         s_objs[i] = mm_channel_util_get_stream_by_handler(my_obj, stream_ids[i]);
    748         if (NULL == s_objs[i]) {
    749             CDBG_ERROR("%s: invalid stream handler %d (idx=%d) to be bundled",
    750                        __func__, stream_ids[i], i);
    751             return -1;
    752         }
    753     }
    754 
    755     /* init superbuf queue */
    756     mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue);
    757 
    758     /* save bundle config */
    759     memcpy(&my_obj->bundle.superbuf_queue.attr, attr, sizeof(mm_camera_bundle_attr_t));
    760     my_obj->bundle.super_buf_notify_cb = super_frame_notify_cb;
    761     my_obj->bundle.user_data = user_data;
    762     my_obj->bundle.superbuf_queue.num_streams = num_streams;
    763     my_obj->bundle.superbuf_queue.expected_frame_id = 0;
    764 
    765     for (i=0; i < num_streams; i++) {
    766         /* set bundled flag to streams */
    767         s_objs[i]->is_bundled = 1;
    768         /* init bundled streams to invalid value -1 */
    769         //my_obj->bundle.superbuf_queue.bundled_streams[i] = -1;
    770         my_obj->bundle.superbuf_queue.bundled_streams[i] = stream_ids[i];
    771     }
    772 
    773     /* launch cmd thread for super buf dataCB */
    774     mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
    775                                 mm_channel_process_stream_buf,
    776                                 (void*)my_obj);
    777 
    778     /* check if we need to do post-processing */
    779     if (my_obj->cam_obj->need_pp) {
    780         /* register postProcessingCB at camera evt polling thread
    781          * because pp result is coming from ctrl evt */
    782         mm_camera_register_event_notify_internal(my_obj->cam_obj,
    783                                                  mm_channel_pp_result_notify,
    784                                                  (void *)my_obj->my_hdl,
    785                                                  MM_CAMERA_EVT_TYPE_CTRL);
    786     }
    787 
    788     return rc;
    789 }
    790 
    791 /* bundled streams must all be stopped before bundle can be destroyed */
    792 int32_t mm_channel_destroy_bundle(mm_channel_t *my_obj)
    793 {
    794 
    795     mm_camera_cmd_thread_release(&my_obj->cmd_thread);
    796 
    797     /* deinit superbuf queue */
    798     mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
    799 
    800     /* memset bundle info */
    801     memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t));
    802     return 0;
    803 }
    804 
    805 int32_t mm_channel_start_streams(mm_channel_t *my_obj,
    806                                  uint8_t num_streams,
    807                                  uint32_t *stream_ids)
    808 {
    809     int32_t rc = 0;
    810     int i, j;
    811     mm_stream_t* s_objs[MM_CAMEAR_MAX_STRAEM_BUNDLE] = {NULL};
    812     uint8_t num_streams_to_start = num_streams;
    813     uint32_t streams_to_start[MM_CAMEAR_MAX_STRAEM_BUNDLE];
    814     uint8_t bundle_to_start = 0;
    815 
    816     /* check if any bundled stream to be start,
    817      * then all bundled stream should be started */
    818     memcpy(streams_to_start, stream_ids, sizeof(uint32_t) * num_streams);
    819     for (i=0; i < num_streams; i++) {
    820         for (j=0; j < my_obj->bundle.superbuf_queue.num_streams; j++) {
    821             if (stream_ids[i] == my_obj->bundle.superbuf_queue.bundled_streams[j]) {
    822                 bundle_to_start = 1;
    823                 break;
    824             }
    825         }
    826     }
    827 
    828     if (bundle_to_start) {
    829         uint8_t need_add;
    830         /* add bundled streams into the start list if not already added*/
    831         for (i=0; i<my_obj->bundle.superbuf_queue.num_streams; i++) {
    832             need_add = 1;
    833             for (j=0; j<num_streams; j++) {
    834                 if (stream_ids[j] == my_obj->bundle.superbuf_queue.bundled_streams[i]) {
    835                     need_add = 0;
    836                     break;
    837                 }
    838             }
    839             if (need_add) {
    840                 streams_to_start[num_streams_to_start++] =
    841                     my_obj->bundle.superbuf_queue.bundled_streams[i];
    842             }
    843         }
    844     }
    845 
    846     /* check if all streams to be started are valid */
    847     for (i=0; i<num_streams_to_start; i++) {
    848         s_objs[i] = mm_channel_util_get_stream_by_handler(my_obj, streams_to_start[i]);
    849 
    850         if (NULL == s_objs[i]) {
    851             CDBG_ERROR("%s: invalid stream handler %d (idx=%d) to be started",
    852                        __func__, streams_to_start[i], i);
    853             return -1;
    854         }
    855     }
    856 
    857     for (i=0; i<num_streams_to_start; i++) {
    858         /* allocate buf */
    859         rc = mm_stream_fsm_fn(s_objs[i],
    860                               MM_STREAM_EVT_GET_BUF,
    861                               NULL,
    862                               NULL);
    863         if (0 != rc) {
    864             CDBG_ERROR("%s: get buf failed at idx(%d)", __func__, i);
    865             break;
    866         }
    867 
    868         /* reg buf */
    869         rc = mm_stream_fsm_fn(s_objs[i],
    870                               MM_STREAM_EVT_REG_BUF,
    871                               NULL,
    872                               NULL);
    873         if (0 != rc) {
    874             CDBG_ERROR("%s: reg buf failed at idx(%d)", __func__, i);
    875             break;
    876         }
    877 
    878         /* TODO */
    879         /* for now, hard-coded to 1 for main image stream */
    880         /* Query if stream need to do pp under current hardware configuration,
    881          * when camera has offline pp capability */
    882         if (my_obj->cam_obj->need_pp) {
    883             if (MSM_V4L2_EXT_CAPTURE_MODE_MAIN == s_objs[i]->ext_image_mode) {
    884                 s_objs[i]->is_pp_needed = 1;
    885             } else {
    886                 s_objs[i]->is_pp_needed = 0;
    887             }
    888         }
    889 
    890         /* start stream */
    891         rc = mm_stream_fsm_fn(s_objs[i],
    892                               MM_STREAM_EVT_START,
    893                               NULL,
    894                               NULL);
    895         if (0 != rc) {
    896             CDBG_ERROR("%s: start stream failed at idx(%d)", __func__, i);
    897             break;
    898         }
    899     }
    900 
    901     /* error handling */
    902     if (0 != rc) {
    903         for (j=0; j<=i; j++) {
    904             /* stop streams*/
    905             mm_stream_fsm_fn(s_objs[i],
    906                              MM_STREAM_EVT_STOP,
    907                              NULL,
    908                              NULL);
    909 
    910             /* unreg buf */
    911             mm_stream_fsm_fn(s_objs[i],
    912                              MM_STREAM_EVT_UNREG_BUF,
    913                              NULL,
    914                              NULL);
    915 
    916             /* put buf back */
    917             mm_stream_fsm_fn(s_objs[i],
    918                              MM_STREAM_EVT_PUT_BUF,
    919                              NULL,
    920                              NULL);
    921         }
    922     }
    923 
    924     return rc;
    925 }
    926 
    927 /* Required: bundled streams need to be stopped together */
    928 int32_t mm_channel_stop_streams(mm_channel_t *my_obj,
    929                                 uint8_t num_streams,
    930                                 uint32_t *stream_ids,
    931                                 uint8_t tear_down_flag)
    932 {
    933     int32_t rc = 0;
    934     int i, j;
    935     mm_stream_t* s_objs[MM_CAMEAR_MAX_STRAEM_BUNDLE] = {NULL};
    936     uint8_t num_streams_to_stop = num_streams;
    937     uint32_t streams_to_stop[MM_CAMEAR_MAX_STRAEM_BUNDLE];
    938     uint8_t bundle_to_stop = 0;
    939 
    940     /* make sure bundled streams are stopped together */
    941     memcpy(streams_to_stop, stream_ids, sizeof(uint32_t) * num_streams);
    942     for (i=0; i<num_streams; i++) {
    943         for (j=0; j<my_obj->bundle.superbuf_queue.num_streams; j++) {
    944             if (stream_ids[i] == my_obj->bundle.superbuf_queue.bundled_streams[j]) {
    945                 bundle_to_stop = 1;
    946                 break;
    947             }
    948         }
    949     }
    950     if (bundle_to_stop) {
    951         uint8_t need_add;
    952         /* add bundled streams into the start list if not already added*/
    953         for (i=0; i<my_obj->bundle.superbuf_queue.num_streams; i++) {
    954             need_add = 1;
    955             for (j=0; j<num_streams; j++) {
    956                 if (stream_ids[j] == my_obj->bundle.superbuf_queue.bundled_streams[i]) {
    957                     need_add = 0;
    958                     break;
    959                 }
    960             }
    961             if (need_add) {
    962                 streams_to_stop[num_streams_to_stop++] =
    963                     my_obj->bundle.superbuf_queue.bundled_streams[i];
    964             }
    965         }
    966     }
    967 
    968     for (i=0; i<num_streams_to_stop; i++) {
    969         s_objs[i] = mm_channel_util_get_stream_by_handler(my_obj, streams_to_stop[i]);
    970 
    971         if (NULL != s_objs[i]) {
    972             /* stream off */
    973             mm_stream_fsm_fn(s_objs[i],
    974                              MM_STREAM_EVT_STOP,
    975                              NULL,
    976                              NULL);
    977 
    978             /* unreg buf at kernel */
    979             mm_stream_fsm_fn(s_objs[i],
    980                              MM_STREAM_EVT_UNREG_BUF,
    981                              NULL,
    982                              NULL);
    983         }
    984     }
    985 
    986     /* since all streams are stopped, we are safe to
    987      * release all buffers allocated in stream */
    988     for (i=0; i<num_streams_to_stop; i++) {
    989         if (NULL != s_objs[i]) {
    990             /* put buf back */
    991             mm_stream_fsm_fn(s_objs[i],
    992                              MM_STREAM_EVT_PUT_BUF,
    993                              NULL,
    994                              NULL);
    995 
    996             if (tear_down_flag) {
    997                 /* to tear down stream totally, stream needs to be released */
    998                 mm_stream_fsm_fn(s_objs[i],
    999                                  MM_STREAM_EVT_RELEASE,
   1000                                  NULL,
   1001                                  NULL);
   1002             }
   1003         }
   1004     }
   1005 
   1006     return rc;
   1007 }
   1008 
   1009 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj)
   1010 {
   1011     int32_t rc = 0;
   1012     mm_camera_cmdcb_t* node = NULL;
   1013 
   1014     /* set pending_cnt
   1015      * will trigger dispatching super frames if pending_cnt > 0 */
   1016     my_obj->pending_cnt = my_obj->bundle.superbuf_queue.attr.burst_num;
   1017 
   1018     /* send sem_post to wake up cmd thread to dispatch super buffer */
   1019     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   1020     if (NULL != node) {
   1021         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   1022         node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB;
   1023 
   1024         /* enqueue to cmd thread */
   1025         mm_camera_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   1026 
   1027         /* wake up cmd thread */
   1028         sem_post(&(my_obj->cmd_thread.cmd_sem));
   1029     } else {
   1030         CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
   1031         rc = -1;
   1032     }
   1033 
   1034     return rc;
   1035 }
   1036 
   1037 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj)
   1038 {
   1039     int32_t rc = 0;
   1040     /* reset pending_cnt */
   1041     my_obj->pending_cnt = 0;
   1042 
   1043     if (my_obj->pending_pp_cnt > 0) {
   1044         rc = mm_channel_cancel_post_processing(my_obj);
   1045     }
   1046     my_obj->pending_pp_cnt = 0;
   1047     return rc;
   1048 }
   1049 
   1050 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
   1051                         mm_camera_buf_def_t *buf)
   1052 {
   1053     int32_t rc = -1;
   1054     struct ion_flush_data cache_inv_data;
   1055     int ion_fd;
   1056     struct msm_frame *cache_frame;
   1057     struct msm_frame *cache_frame1 = NULL;
   1058 
   1059     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id);
   1060 
   1061     if (NULL != s_obj) {
   1062         rc = mm_stream_fsm_fn(s_obj,
   1063                               MM_STREAM_EVT_QBUF,
   1064                               (void *)buf,
   1065                               NULL);
   1066     }
   1067 
   1068 #ifdef USE_ION
   1069     cache_inv_data.vaddr = cache_frame->buffer;
   1070     cache_inv_data.fd = cache_frame->fd;
   1071     cache_inv_data.handle = cache_frame->fd_data.handle;
   1072     cache_inv_data.length = cache_frame->ion_alloc.len;
   1073     ion_fd = cache_frame->ion_dev_fd;
   1074     if(ion_fd > 0) {
   1075         if(ioctl(ion_fd, ION_IOC_INV_CACHES, &cache_inv_data) < 0)
   1076             CDBG_ERROR("%s: Cache Invalidate failed\n", __func__);
   1077         else {
   1078             CDBG("%s: Successful cache invalidate\n", __func__);
   1079             if(cache_frame1) {
   1080                 ion_fd = cache_frame1->ion_dev_fd;
   1081                 cache_inv_data.vaddr = cache_frame1->buffer;
   1082                 cache_inv_data.fd = cache_frame1->fd;
   1083                 cache_inv_data.handle = cache_frame1->fd_data.handle;
   1084                 cache_inv_data.length = cache_frame1->ion_alloc.len;
   1085                 if(ioctl(ion_fd, ION_IOC_INV_CACHES, &cache_inv_data) < 0)
   1086                     CDBG_ERROR("%s: Cache Invalidate failed\n", __func__);
   1087                 else
   1088                     CDBG("%s: Successful cache invalidate\n", __func__);
   1089             }
   1090         }
   1091     }
   1092 #endif
   1093 
   1094     return rc;
   1095 }
   1096 
   1097 int32_t mm_channel_start_focus(mm_channel_t *my_obj,
   1098                                uint32_t sensor_idx,
   1099                                uint32_t focus_mode)
   1100 {
   1101     return mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
   1102                                           CAMERA_SET_PARM_AUTO_FOCUS,
   1103                                           sizeof(uint32_t), (void*)focus_mode);
   1104 }
   1105 
   1106 int32_t mm_channel_abort_focus(mm_channel_t *my_obj, uint32_t sensor_idx)
   1107 {
   1108     return mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
   1109                                           CAMERA_AUTO_FOCUS_CANCEL,
   1110                                           0, NULL);
   1111 }
   1112 
   1113 int32_t mm_channel_prepare_snapshot(mm_channel_t *my_obj, uint32_t sensor_idx)
   1114 {
   1115     return mm_camera_send_native_ctrl_timeout_cmd(my_obj->cam_obj,
   1116                                                 CAMERA_PREPARE_SNAPSHOT,
   1117                                                 0, NULL, 2000);
   1118 }
   1119 
   1120 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
   1121                                    uint32_t s_id,
   1122                                    void *value)
   1123 {
   1124     int32_t rc = -1;
   1125     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, s_id);
   1126     if (NULL != s_obj) {
   1127         rc = mm_stream_fsm_fn(s_obj,
   1128                               MM_STREAM_EVT_SET_PARM,
   1129                               value,
   1130                               NULL);
   1131     }
   1132 
   1133     return rc;
   1134 }
   1135 
   1136 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
   1137                                    uint32_t s_id,
   1138                                    void *value)
   1139 {
   1140     int32_t rc = -1;
   1141     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, s_id);
   1142     if (NULL != s_obj) {
   1143         rc = mm_stream_fsm_fn(s_obj,
   1144                               MM_STREAM_EVT_GET_PARM,
   1145                               NULL,
   1146                               value);
   1147     }
   1148 
   1149     return rc;
   1150 }
   1151 
   1152 uint8_t mm_channel_need_do_pp(mm_channel_t *my_obj,
   1153                               mm_channel_queue_node_t *super_buf)
   1154 {
   1155     uint8_t need_pp = 0;
   1156     uint8_t i;
   1157 
   1158     for (i=0; i<super_buf->num_of_bufs; i++) {
   1159         if (super_buf->super_buf[i].need_pp) {
   1160             need_pp = 1;
   1161             break;
   1162         }
   1163     }
   1164     return need_pp;
   1165 }
   1166 
   1167 int32_t mm_channel_do_post_processing(mm_channel_t *my_obj,
   1168                                       mm_channel_queue_node_t *super_buf)
   1169 {
   1170     int32_t rc = 0;
   1171     cam_sock_packet_t packet;
   1172     uint8_t i;
   1173     mm_stream_t* s_obj = NULL;
   1174     mm_channel_pp_info_t *cookie = NULL;
   1175 
   1176     /* TODO : currently we only do WNR, may need extended PP */
   1177     /* send cmd to backend to start pp */
   1178     for (i=0; i<super_buf->num_of_bufs; i++) {
   1179         if (super_buf->super_buf[i].need_pp) {
   1180             s_obj = mm_channel_util_get_stream_by_handler(my_obj, super_buf->super_buf[i].stream_id);
   1181             if (NULL != s_obj) {
   1182                 cookie = (mm_channel_pp_info_t*)malloc(sizeof(mm_channel_pp_info_t));
   1183                 if (NULL != cookie) {
   1184                     memset(&packet, 0, sizeof(cam_sock_packet_t));
   1185                     memset(cookie, 0, sizeof(mm_channel_pp_info_t));
   1186                     cookie->cam_hdl = my_obj->cam_obj->my_hdl;
   1187                     cookie->ch_hdl = my_obj->my_hdl;
   1188                     cookie->stream_hdl = s_obj->my_hdl;
   1189                     cookie->super_buf = super_buf;
   1190 
   1191                     packet.msg_type = CAM_SOCK_MSG_TYPE_WDN_START;
   1192                     packet.payload.wdn_start.cookie = (unsigned long)cookie;
   1193                     packet.payload.wdn_start.num_frames = 1;
   1194                     packet.payload.wdn_start.ext_mode[0] = s_obj->ext_image_mode;
   1195                     packet.payload.wdn_start.frame_idx[0] = super_buf->super_buf[i].buf->buf_idx;
   1196                     rc = mm_camera_util_sendmsg(my_obj->cam_obj, &packet, sizeof(packet), 0);
   1197                     if (0 != rc) {
   1198                         CDBG_ERROR("%s: Send DoPP msg failed (rc=%d)", __func__, rc);
   1199                         free(cookie);
   1200                         break;
   1201                     }
   1202                 } else {
   1203                     CDBG_ERROR("%s: No memory for mm_channel_pp_info_t", __func__);
   1204                     break;
   1205                 }
   1206             }
   1207         }
   1208     }
   1209 
   1210     return rc;
   1211 }
   1212 
   1213 int32_t mm_channel_cancel_post_processing(mm_channel_t *my_obj)
   1214 {
   1215     int32_t rc = 0;
   1216     /* TODO */
   1217     /* need send cmd to backend to cancel all pp request */
   1218 
   1219     return rc;
   1220 }
   1221 
   1222 int32_t mm_channel_reg_stream_cb(mm_channel_t *my_obj,
   1223                                  mm_stream_data_cb_t *cb,
   1224                                  uint32_t ext_image_mode,
   1225                                  uint32_t sensor_idx)
   1226 {
   1227     uint8_t idx;
   1228     mm_stream_t *dest_stream = NULL;
   1229     int32_t rc = -1;
   1230 
   1231     /* browse all streams in channel to find the destination */
   1232     for (idx=0; idx < MM_CAMEAR_STRAEM_NUM_MAX; idx++) {
   1233         if (my_obj->streams[idx].state != MM_STREAM_STATE_NOTUSED &&
   1234             my_obj->streams[idx].ext_image_mode == ext_image_mode &&
   1235             my_obj->streams[idx].sensor_idx == sensor_idx) {
   1236             /* find matching stream as the destination */
   1237             dest_stream = &my_obj->streams[idx];
   1238             break;
   1239         }
   1240     }
   1241 
   1242     if (NULL != dest_stream) {
   1243         rc = mm_stream_reg_buf_cb(dest_stream, cb);
   1244     }
   1245 
   1246     return rc;
   1247 }
   1248 
   1249 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)
   1250 {
   1251     return mm_camera_queue_init(&queue->que);
   1252 }
   1253 
   1254 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue)
   1255 {
   1256     return mm_camera_queue_deinit(&queue->que);
   1257 }
   1258 
   1259 int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1,
   1260                                            uint32_t v2)
   1261 {
   1262     int8_t ret = 0;
   1263 
   1264     /* TODO: need to handle the case if v2 roll over to 0 */
   1265     if (v1 > v2) {
   1266         ret = 1;
   1267     } else if (v1 < v2) {
   1268         ret = -1;
   1269     }
   1270 
   1271     return ret;
   1272 }
   1273 
   1274 int32_t mm_channel_superbuf_comp_and_enqueue(
   1275                         mm_channel_t* ch_obj,
   1276                         mm_channel_queue_t * queue,
   1277                         mm_camera_buf_info_t *buf_info)
   1278 {
   1279     mm_camera_q_node_t* node = NULL;
   1280     struct cam_list *head = NULL;
   1281     struct cam_list *pos = NULL;
   1282     mm_channel_queue_node_t* super_buf = NULL;
   1283     uint8_t buf_s_idx, i;
   1284 
   1285     for (buf_s_idx=0; buf_s_idx < queue->num_streams; buf_s_idx++) {
   1286         if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) {
   1287             break;
   1288         }
   1289     }
   1290     if (buf_s_idx == queue->num_streams) {
   1291         CDBG_ERROR("%s: buf from stream (%d) not bundled", __func__, buf_info->stream_id);
   1292         return -1;
   1293     }
   1294 
   1295     if (mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx,
   1296                                             queue->expected_frame_id) < 0) {
   1297         /* incoming buf is older than expected buf id, will discard it */
   1298         mm_channel_qbuf(ch_obj, buf_info->buf);
   1299         return 0;
   1300     }
   1301 
   1302     if (MM_CAMERA_SUPER_BUF_PRIORITY_NORMAL != queue->attr.priority) {
   1303         /* TODO */
   1304         /* need to decide if we want to queue the frame based on focus or exposure
   1305          * if frame not to be queued, we need to qbuf it back */
   1306     }
   1307 
   1308     /* comp */
   1309     pthread_mutex_lock(&queue->que.lock);
   1310     head = &queue->que.head.list;
   1311     /* get the last one in the queue which is possibly having no matching */
   1312     pos = head->next;
   1313     while (pos != head) {
   1314         node = member_of(pos, mm_camera_q_node_t, list);
   1315         super_buf = (mm_channel_queue_node_t*)node->data;
   1316         if (NULL != super_buf) {
   1317             if (super_buf->matched) {
   1318                 /* find a matched super buf, move to next one */
   1319                 pos = pos->next;
   1320                 continue;
   1321             } else {
   1322                 /* have an unmatched super buf, break the loop */
   1323                 break;
   1324             }
   1325         }
   1326     }
   1327 
   1328     if (pos == head) {
   1329         /* all nodes in queue are mtached, or no node in queue
   1330          * create a new node */
   1331         mm_channel_queue_node_t *new_buf = NULL;
   1332         mm_camera_q_node_t* new_node = NULL;
   1333 
   1334         new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t));
   1335         new_node = (mm_camera_q_node_t*)malloc(sizeof(mm_camera_q_node_t));
   1336         if (NULL != new_buf && NULL != new_node) {
   1337             memset(new_buf, 0, sizeof(mm_channel_queue_node_t));
   1338             memset(new_node, 0, sizeof(mm_camera_q_node_t));
   1339             new_node->data = (void *)new_buf;
   1340             new_buf->num_of_bufs = queue->num_streams;
   1341             memcpy(&new_buf->super_buf[buf_s_idx], buf_info, sizeof(mm_camera_buf_info_t));
   1342 
   1343             /* enqueue */
   1344             //cam_list_add_tail_node(&node->list, &queue->que.head.list);
   1345             cam_list_add_tail_node(&new_node->list, &queue->que.head.list);
   1346             queue->que.size++;
   1347 
   1348             if(queue->num_streams == 1) {
   1349                 //TODO : Check. Live snapshot will have one stream in bundle?
   1350                 new_buf->matched = 1;
   1351 
   1352                 if (new_buf->matched) {
   1353                     queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
   1354                     queue->match_cnt++;
   1355                 }
   1356             }
   1357         } else {
   1358             /* No memory */
   1359             if (NULL != new_buf) {
   1360                 free(new_buf);
   1361             }
   1362             if (NULL != new_node) {
   1363                 free(new_node);
   1364             }
   1365             /* qbuf the new buf since we cannot enqueue */
   1366             mm_channel_qbuf(ch_obj, buf_info->buf);
   1367         }
   1368     } else {
   1369         /* find an unmatched super buf */
   1370         if (super_buf->super_buf[buf_s_idx].frame_idx == 0) {
   1371             /* new frame from the stream_id */
   1372             uint8_t is_new = 1;
   1373             uint32_t frame_idx;
   1374 
   1375             for (i=0; i < super_buf->num_of_bufs; i++) {
   1376             //for (i=0; i < buf_s_idx; i++) {
   1377                 if(super_buf->super_buf[i].buf == NULL) {
   1378                     continue;
   1379                 }
   1380                 frame_idx = super_buf->super_buf[i].buf->frame_idx;
   1381                 if (frame_idx == 0) {
   1382                     continue;
   1383                 }
   1384                 if (frame_idx < buf_info->frame_idx) {
   1385                     /* existing frame is older than the new frame, qbuf it */
   1386                     mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
   1387                     memset(&super_buf->super_buf[i], 0, sizeof(mm_camera_buf_info_t));
   1388                 } else if (frame_idx > buf_info->frame_idx) {
   1389                     /* new frame is older */
   1390                     is_new = 0;
   1391                     break;
   1392                 }else{
   1393                     //TODO: reveiw again
   1394                     break;
   1395                 }
   1396             }
   1397             if (is_new) {
   1398                 memcpy(&super_buf->super_buf[buf_s_idx], buf_info, sizeof(mm_camera_buf_info_t));
   1399 
   1400                 /* check if superbuf is all matched */
   1401                 super_buf->matched = 1;
   1402                 for (i=0; i < super_buf->num_of_bufs; i++) {
   1403                     if (super_buf->super_buf[i].frame_idx == 0) {
   1404                         super_buf->matched = 0;
   1405                         break;
   1406                     }
   1407                 }
   1408 
   1409                 if (super_buf->matched) {
   1410                     queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
   1411                     queue->match_cnt++;
   1412                 }
   1413             } else {
   1414                 mm_channel_qbuf(ch_obj, buf_info->buf);
   1415             }
   1416         } else {
   1417             if (super_buf->super_buf[buf_s_idx].frame_idx < buf_info->frame_idx) {
   1418                 /* current frames in superbuf are older than the new frame
   1419                  * qbuf all current frames */
   1420                 for (i=0; i<super_buf->num_of_bufs; i++) {
   1421                     if (super_buf->super_buf[i].frame_idx != 0) {
   1422                             mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
   1423                             memset(&super_buf->super_buf[i], 0, sizeof(mm_camera_buf_info_t));
   1424                     }
   1425                 }
   1426                 /* add the new frame into the superbuf */
   1427                 memcpy(&super_buf->super_buf[buf_s_idx], buf_info, sizeof(mm_camera_buf_info_t));
   1428             } else {
   1429                 /* the new frame is older, just ignor */
   1430                 mm_channel_qbuf(ch_obj, buf_info->buf);
   1431             }
   1432         }
   1433     }
   1434     pthread_mutex_unlock(&queue->que.lock);
   1435 
   1436     return 0;
   1437 }
   1438 
   1439 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue)
   1440 {
   1441     mm_camera_q_node_t* node = NULL;
   1442     struct cam_list *head = NULL;
   1443     struct cam_list *pos = NULL;
   1444     mm_channel_queue_node_t* super_buf = NULL;
   1445 
   1446     head = &queue->que.head.list;
   1447     pos = head->next;
   1448     if (pos != head) {
   1449         /* get the first node */
   1450         node = member_of(pos, mm_camera_q_node_t, list);
   1451         super_buf = (mm_channel_queue_node_t*)node->data;
   1452         if (NULL != super_buf) {
   1453             if (super_buf->matched) {
   1454                 /* we found a mtaching super buf, dequeue it */
   1455                 cam_list_del_node(&node->list);
   1456                 queue->que.size--;
   1457                 queue->match_cnt--;
   1458                 free(node);
   1459             } else {
   1460                 super_buf = NULL;
   1461             }
   1462         }
   1463     }
   1464 
   1465     return super_buf;
   1466 }
   1467 
   1468 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue)
   1469 {
   1470     mm_camera_q_node_t* node = NULL;
   1471     struct cam_list *head = NULL;
   1472     struct cam_list *pos = NULL;
   1473     mm_channel_queue_node_t* super_buf = NULL;
   1474 
   1475     pthread_mutex_lock(&queue->que.lock);
   1476     super_buf = mm_channel_superbuf_dequeue_internal(queue);
   1477     pthread_mutex_unlock(&queue->que.lock);
   1478 
   1479     return super_buf;
   1480 }
   1481 
   1482 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj,
   1483                                              mm_channel_queue_t * queue)
   1484 {
   1485     int32_t rc = 0, i;
   1486     mm_channel_queue_node_t* super_buf = NULL;
   1487     if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
   1488         /* for continuous streaming mode, no overflow is needed */
   1489         return 0;
   1490     }
   1491 
   1492     /* bufdone overflowed bufs */
   1493     pthread_mutex_lock(&queue->que.lock);
   1494     while (queue->match_cnt > queue->attr.water_mark) {
   1495         super_buf = mm_channel_superbuf_dequeue_internal(queue);
   1496         if (NULL != super_buf) {
   1497             for (i=0; i<super_buf->num_of_bufs; i++) {
   1498                 if (NULL != super_buf->super_buf[i].buf) {
   1499                     mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   1500                 }
   1501             }
   1502             free(super_buf);
   1503         }
   1504     }
   1505     pthread_mutex_unlock(&queue->que.lock);
   1506 
   1507     return rc;
   1508 }
   1509 
   1510 int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj,
   1511                                  mm_channel_queue_t * queue)
   1512 {
   1513     int32_t rc = 0, i, count;
   1514     mm_channel_queue_node_t* super_buf = NULL;
   1515     if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
   1516         /* for continuous streaming mode, no skip is needed */
   1517         return 0;
   1518     }
   1519 
   1520     /* bufdone overflowed bufs */
   1521     pthread_mutex_lock(&queue->que.lock);
   1522     while (queue->match_cnt > queue->attr.look_back) {
   1523         super_buf = mm_channel_superbuf_dequeue_internal(queue);
   1524         if (NULL != super_buf) {
   1525             for (i=0; i<super_buf->num_of_bufs; i++) {
   1526                 if (NULL != super_buf->super_buf[i].buf) {
   1527                     mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   1528                 }
   1529             }
   1530             free(super_buf);
   1531         }
   1532     }
   1533     pthread_mutex_unlock(&queue->que.lock);
   1534 
   1535     return rc;
   1536 }
   1537 
   1538