1/*
2Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
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 Code Aurora Forum, Inc. 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
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF 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
44extern mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler);
45extern mm_channel_t * mm_camera_util_get_channel_by_handler(
46                                    mm_camera_obj_t * cam_obj,
47                                    uint32_t handler);
48extern 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);
52extern 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 */
59int32_t mm_channel_qbuf(mm_channel_t *my_obj,
60                        mm_camera_buf_def_t *buf);
61int32_t mm_channel_init(mm_channel_t *my_obj);
62void mm_channel_release(mm_channel_t *my_obj);
63uint32_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);
66int32_t mm_channel_del_stream(mm_channel_t *my_obj,
67                                   uint32_t stream_id);
68int32_t mm_channel_config_stream(mm_channel_t *my_obj,
69                                 uint32_t stream_id,
70                                 mm_camera_stream_config_t *config);
71int32_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);
77int32_t mm_channel_destroy_bundle(mm_channel_t *my_obj);
78int32_t mm_channel_start_streams(mm_channel_t *my_obj,
79                                 uint8_t num_streams,
80                                 uint32_t *stream_ids);
81int32_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);
85int32_t mm_channel_request_super_buf(mm_channel_t *my_obj);
86int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj);
87int32_t mm_channel_start_focus(mm_channel_t *my_obj,
88                               uint32_t sensor_idx,
89                               uint32_t focus_mode);
90int32_t mm_channel_abort_focus(mm_channel_t *my_obj,
91                               uint32_t sensor_idx);
92int32_t mm_channel_prepare_snapshot(mm_channel_t *my_obj,
93                                    uint32_t sensor_idx);
94int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
95                                   uint32_t s_id,
96                                   void *value);
97int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
98                                   uint32_t s_id,
99                                   void *value);
100uint8_t mm_channel_need_do_pp(mm_channel_t *my_obj,
101                              mm_channel_queue_node_t *super_buf);
102int32_t mm_channel_do_post_processing(mm_channel_t *my_obj,
103                                      mm_channel_queue_node_t *super_buf);
104int32_t mm_channel_cancel_post_processing(mm_channel_t *my_obj);
105int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj,
106                                             mm_channel_queue_t * queue);
107int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj,
108                                 mm_channel_queue_t * queue);
109
110/* state machine function declare */
111int32_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);
115int32_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);
119int32_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);
123int32_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 */
129int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue);
130int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue);
131int32_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);
134mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue);
135
136/* channel utility function */
137mm_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 */
155static 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 */
247static 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 */
332int32_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
364int32_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
381int32_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
478int32_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
605int32_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
619int32_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
631void 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
640uint32_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
691int32_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
711int32_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
734int32_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 */
792int32_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
805int32_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 */
928int32_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
1009int32_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
1037int32_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
1050int32_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
1097int32_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
1106int32_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
1113int32_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
1120int32_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
1136int32_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
1152uint8_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
1167int32_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
1213int32_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
1222int32_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
1249int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)
1250{
1251    return mm_camera_queue_init(&queue->que);
1252}
1253
1254int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue)
1255{
1256    return mm_camera_queue_deinit(&queue->que);
1257}
1258
1259int8_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
1274int32_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
1439mm_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
1468mm_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
1482int32_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
1510int32_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