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 <time.h>
38#include <semaphore.h>
39
40#include "mm_camera_dbg.h"
41#include "mm_camera_interface.h"
42#include "mm_camera.h"
43
44#define MM_CAMERA_MAX_NUM_FRAMES     16
45
46/* internal function decalre */
47int32_t mm_stream_qbuf(mm_stream_t *my_obj,
48                       mm_camera_buf_def_t *buf);
49int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj);
50int32_t mm_stream_set_fmt(mm_stream_t * my_obj);
51int32_t mm_stream_get_offset(mm_stream_t *my_obj);
52int32_t mm_stream_set_cid(mm_stream_t *my_obj,stream_cid_t *in_value);
53int32_t mm_stream_init_bufs(mm_stream_t * my_obj);
54int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj);
55int32_t mm_stream_request_buf(mm_stream_t * my_obj);
56int32_t mm_stream_unreg_buf(mm_stream_t * my_obj);
57int32_t mm_stream_release(mm_stream_t *my_obj);
58int32_t mm_stream_get_crop(mm_stream_t *my_obj,
59                         mm_camera_rect_t *crop);
60int32_t mm_stream_get_cid(mm_stream_t *my_obj,
61                          stream_cid_t *out_value);
62int32_t mm_stream_set_parm_acquire(mm_stream_t *my_obj,
63                         void *value);
64int32_t mm_stream_get_parm_acquire(mm_stream_t *my_obj,
65                         void *value);
66int32_t mm_stream_set_parm_config(mm_stream_t *my_obj,
67                         void *value);
68int32_t mm_stream_get_parm_config(mm_stream_t *my_obj,
69                         void *value);
70int32_t mm_stream_set_parm_start(mm_stream_t *my_obj,
71                         void *value);
72int32_t mm_stream_get_parm_start(mm_stream_t *my_obj,
73                         void *value);
74int32_t mm_stream_streamon(mm_stream_t *my_obj);
75int32_t mm_stream_streamoff(mm_stream_t *my_obj);
76int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
77                                 mm_camera_buf_info_t* buf_info);
78int32_t mm_stream_config(mm_stream_t *my_obj,
79                         mm_camera_stream_config_t *config);
80uint8_t mm_stream_need_stream_on(mm_stream_t *my_obj);
81int32_t mm_stream_reg_buf(mm_stream_t * my_obj);
82int32_t mm_stream_buf_done(mm_stream_t * my_obj,
83                           mm_camera_buf_def_t *frame);
84
85
86/* state machine function declare */
87int32_t mm_stream_fsm_inited(mm_stream_t * my_obj,
88                             mm_stream_evt_type_t evt,
89                             void * in_val,
90                             void * out_val);
91int32_t mm_stream_fsm_acquired(mm_stream_t * my_obj,
92                               mm_stream_evt_type_t evt,
93                               void * in_val,
94                               void * out_val);
95int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
96                          mm_stream_evt_type_t evt,
97                          void * in_val,
98                          void * out_val);
99int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
100                             mm_stream_evt_type_t evt,
101                             void * in_val,
102                             void * out_val);
103int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
104                          mm_stream_evt_type_t evt,
105                          void * in_val,
106                          void * out_val);
107int32_t mm_stream_fsm_active_stream_on(mm_stream_t * my_obj,
108                                       mm_stream_evt_type_t evt,
109                                       void * in_val,
110                                       void * out_val);
111int32_t mm_stream_fsm_active_stream_off(mm_stream_t * my_obj,
112                                        mm_stream_evt_type_t evt,
113                                        void * in_val,
114                                        void * out_val);
115
116extern int32_t mm_camera_send_native_ctrl_cmd(mm_camera_obj_t * my_obj,
117                                       cam_ctrl_type type,
118                                       uint32_t length,
119                                       void *value);
120
121static int get_stream_inst_handle(mm_stream_t *my_obj)
122{
123  int rc = 0;
124  uint32_t inst_handle;
125  struct msm_camera_v4l2_ioctl_t v4l2_ioctl;
126
127  v4l2_ioctl.id = MSM_V4L2_PID_INST_HANDLE;
128  v4l2_ioctl.ioctl_ptr = &inst_handle;
129  v4l2_ioctl.len = sizeof(inst_handle);
130  rc = ioctl(my_obj->fd, MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL, &v4l2_ioctl);
131  if (rc) {
132    CDBG_ERROR("%s Error getting mctl pp inst handle", __func__);
133    return rc;
134  }
135
136  my_obj->inst_hdl = inst_handle;
137  CDBG("%s: inst handle = %x rc = %d\n", __func__,
138    my_obj->inst_hdl, rc);
139  return rc;
140}
141
142void mm_stream_handle_rcvd_buf(mm_stream_t *my_obj,
143                                  mm_camera_buf_info_t *buf_info)
144{
145    int32_t i;
146    uint8_t has_cb = 0;
147
148    /* enqueue to super buf thread */
149    if (my_obj->is_bundled) {
150        mm_camera_cmdcb_t* node = NULL;
151
152        /* send sem_post to wake up channel cmd thread to enqueue to super buffer */
153        node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
154        if (NULL != node) {
155            memset(node, 0, sizeof(mm_camera_cmdcb_t));
156            node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
157            memcpy(&node->u.buf, buf_info, sizeof(mm_camera_buf_info_t));
158
159            /* enqueue to cmd thread */
160            mm_camera_queue_enq(&(my_obj->ch_obj->cmd_thread.cmd_queue), node);
161
162            /* wake up cmd thread */
163            sem_post(&(my_obj->ch_obj->cmd_thread.cmd_sem));
164        } else {
165            CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
166        }
167    }
168
169    /* check if has CB */
170    for (i=0 ; i< MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
171        if(NULL != my_obj->buf_cb[i].cb) {
172            has_cb = 1;
173        }
174    }
175    if(has_cb) {
176        mm_camera_cmdcb_t* node = NULL;
177
178        /* send sem_post to wake up cmd thread to dispatch dataCB */
179        node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
180        if (NULL != node) {
181            memset(node, 0, sizeof(mm_camera_cmdcb_t));
182            node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
183            memcpy(&node->u.buf, buf_info, sizeof(mm_camera_buf_info_t));
184
185            /* enqueue to cmd thread */
186            mm_camera_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
187
188            /* wake up cmd thread */
189            sem_post(&(my_obj->cmd_thread.cmd_sem));
190        } else {
191            CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
192        }
193    }
194}
195
196static void mm_stream_data_notify(void* user_data)
197{
198    mm_stream_t *my_obj = (mm_stream_t*)user_data;
199    int32_t idx = -1, i, rc;
200    uint8_t has_cb = 0;
201    mm_camera_buf_info_t buf_info;
202
203    if (NULL == my_obj) {
204        return;
205    }
206
207    if (MM_STREAM_STATE_ACTIVE_STREAM_ON != my_obj->state) {
208        /* this Cb will only received in active_stream_on state
209         * if not so, return here */
210        CDBG_ERROR("%s: ERROR!! Wrong state (%d) to receive data notify!",
211                   __func__, my_obj->state);
212        return;
213    }
214
215    memset(&buf_info, 0, sizeof(mm_camera_buf_info_t));
216
217    pthread_mutex_lock(&my_obj->buf_lock);
218    rc = mm_stream_read_msm_frame(my_obj, &buf_info);
219    if (rc != 0) {
220        pthread_mutex_unlock(&my_obj->buf_lock);
221        return;
222    }
223    idx = buf_info.buf->buf_idx;
224
225    /* update buffer location */
226    my_obj->buf_status[idx].in_kernel = 0;
227
228    /* update buf ref count */
229    if (my_obj->is_bundled) {
230        /* need to add into super buf since bundled, add ref count */
231        my_obj->buf_status[idx].buf_refcnt++;
232    }
233
234    for (i=0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
235        if(NULL != my_obj->buf_cb[i].cb) {
236            /* for every CB, add ref count */
237            my_obj->buf_status[idx].buf_refcnt++;
238            has_cb = 1;
239        }
240    }
241    pthread_mutex_unlock(&my_obj->buf_lock);
242
243    mm_stream_handle_rcvd_buf(my_obj, &buf_info);
244}
245
246/* special function for dataCB registered at other stream */
247static void mm_stream_buf_notify(mm_camera_super_buf_t *super_buf,
248                                 void *user_data)
249{
250    mm_stream_t * my_obj = (mm_stream_t*)user_data;
251    mm_camera_buf_info_t buf_info;
252    int8_t i;
253    mm_camera_buf_def_t *buf = super_buf->bufs[0];
254
255    CDBG("%s : E",__func__);
256    if (my_obj == NULL) {
257        return;
258    }
259
260    if (MM_STREAM_STATE_ACTIVE_STREAM_OFF != my_obj->state) {
261        /* this CB will only received in active_stream_off state
262         * if not so, return here */
263        return;
264    }
265
266    /* 1) copy buf into local buf */
267    if (my_obj->buf_num <= 0) {
268        CDBG_ERROR("%s: Local buf is not allocated yet", __func__);
269        return;
270    }
271
272    my_obj->buf[0].buf_idx = 0;
273    my_obj->buf[0].stream_id = my_obj->my_hdl;
274    my_obj->buf[0].frame_idx = buf->frame_idx;
275
276    memcpy(&my_obj->buf[0].ts, &buf->ts, sizeof(buf->ts));
277
278    memcpy(&my_obj->buf[0].planes,&buf->planes,buf->num_planes * sizeof(struct v4l2_plane));
279
280    /* set flag to indicate buf be to sent out is from local */
281    my_obj->is_local_buf = 1;
282
283    /* 2) buf_done the buf from other stream */
284    mm_channel_qbuf(my_obj->ch_obj, buf);
285
286    /* 3) handle received buf */
287    memset(&buf_info, 0, sizeof(mm_camera_buf_info_t));
288    buf_info.frame_idx =my_obj->buf[0].frame_idx;
289    buf_info.buf = &my_obj->buf[0];
290    buf_info.stream_id = my_obj->my_hdl;
291    mm_stream_handle_rcvd_buf(my_obj, &buf_info);
292}
293
294static void mm_stream_dispatch_app_data(mm_camera_cmdcb_t *cmd_cb,
295                                        void* user_data)
296{
297    int i;
298    mm_stream_t * my_obj = (mm_stream_t *)user_data;
299    mm_camera_buf_info_t* buf_info = NULL;
300    mm_camera_super_buf_t super_buf;
301
302    if (NULL == my_obj) {
303        return;
304    }
305
306    if (MM_CAMERA_CMD_TYPE_DATA_CB != cmd_cb->cmd_type) {
307        CDBG_ERROR("%s: Wrong cmd_type (%d) for dataCB",
308                   __func__, cmd_cb->cmd_type);
309        return;
310    }
311
312    buf_info = &cmd_cb->u.buf;
313    memset(&super_buf, 0, sizeof(mm_camera_super_buf_t));
314    super_buf.num_bufs = 1;
315    super_buf.bufs[0] = buf_info->buf;
316    super_buf.camera_handle = my_obj->ch_obj->cam_obj->my_hdl;
317    super_buf.ch_id = my_obj->ch_obj->my_hdl;
318
319
320    pthread_mutex_lock(&my_obj->cb_lock);
321    for(i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
322        if(NULL != my_obj->buf_cb[i].cb) {
323            if (my_obj->buf_cb[i].cb_count != 0) {
324                /* if <0, means infinite CB
325                 * if >0, means CB for certain times
326                 * both case we need to call CB */
327                my_obj->buf_cb[i].cb(&super_buf,
328                                     my_obj->buf_cb[i].user_data);
329            }
330
331            /* if >0, reduce count by 1 every time we called CB until reaches 0
332             * when count reach 0, reset the buf_cb to have no CB */
333            if (my_obj->buf_cb[i].cb_count > 0) {
334                my_obj->buf_cb[i].cb_count--;
335                if (0 == my_obj->buf_cb[i].cb_count) {
336                    my_obj->buf_cb[i].cb = NULL;
337                    my_obj->buf_cb[i].user_data = NULL;
338                }
339            }
340        }
341    }
342    pthread_mutex_unlock(&my_obj->cb_lock);
343}
344
345/* state machine entry */
346int32_t mm_stream_fsm_fn(mm_stream_t *my_obj,
347                         mm_stream_evt_type_t evt,
348                         void * in_val,
349                         void * out_val)
350{
351    int32_t rc = -1;
352
353    CDBG("%s : E - evt = %d, my_obj->state = %d",__func__,evt,my_obj->state);
354    switch (my_obj->state) {
355    case MM_STREAM_STATE_NOTUSED:
356        CDBG("%s: Not handling evt in unused state", __func__);
357        break;
358    case MM_STREAM_STATE_INITED:
359        rc = mm_stream_fsm_inited(my_obj, evt, in_val, out_val);
360        break;
361    case MM_STREAM_STATE_ACQUIRED:
362        rc = mm_stream_fsm_acquired(my_obj, evt, in_val, out_val);
363        break;
364    case MM_STREAM_STATE_CFG:
365        rc = mm_stream_fsm_cfg(my_obj, evt, in_val, out_val);
366        break;
367    case MM_STREAM_STATE_BUFFED:
368        rc = mm_stream_fsm_buffed(my_obj, evt, in_val, out_val);
369        break;
370    case MM_STREAM_STATE_REG:
371        rc = mm_stream_fsm_reg(my_obj, evt, in_val, out_val);
372        break;
373    case MM_STREAM_STATE_ACTIVE_STREAM_ON:
374        rc = mm_stream_fsm_active_stream_on(my_obj, evt, in_val, out_val);
375        break;
376    case MM_STREAM_STATE_ACTIVE_STREAM_OFF:
377        rc = mm_stream_fsm_active_stream_off(my_obj, evt, in_val, out_val);
378        break;
379    default:
380        CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
381        break;
382    }
383    CDBG("%s : X rc =%d",__func__,rc);
384    return rc;
385}
386
387int32_t mm_stream_fsm_inited(mm_stream_t *my_obj,
388                             mm_stream_evt_type_t evt,
389                             void * in_val,
390                             void * out_val)
391{
392    int32_t rc = 0;
393    char dev_name[MM_CAMERA_DEV_NAME_LEN];
394
395    CDBG("%s :E evt = %d",__func__,evt);
396    switch(evt) {
397    case MM_STREAM_EVT_ACQUIRE:
398        if ((NULL == my_obj->ch_obj) || (NULL == my_obj->ch_obj->cam_obj)) {
399            CDBG_ERROR("%s: NULL channel or camera obj\n", __func__);
400            rc = -1;
401            break;
402        }
403
404        snprintf(dev_name, sizeof(dev_name), "/dev/%s",
405                 mm_camera_util_get_dev_name(my_obj->ch_obj->cam_obj->my_hdl));
406
407        my_obj->fd = open(dev_name, O_RDWR | O_NONBLOCK);
408        if (my_obj->fd <= 0) {
409            CDBG_ERROR("%s: open dev returned %d\n", __func__, my_obj->fd);
410            rc = -1;
411            break;
412        }
413        CDBG("%s: open dev fd = %d, ext_image_mode = %d, sensor_idx = %d\n",
414                 __func__, my_obj->fd, my_obj->ext_image_mode, my_obj->sensor_idx);
415        rc = mm_stream_set_ext_mode(my_obj);
416        if (0 == rc) {
417            my_obj->state = MM_STREAM_STATE_ACQUIRED;
418        } else {
419            /* failed setting ext_mode
420             * close fd */
421            if(my_obj->fd > 0) {
422                close(my_obj->fd);
423                my_obj->fd = -1;
424            }
425            break;
426        }
427        rc = get_stream_inst_handle(my_obj);
428        if(rc) {
429            if(my_obj->fd > 0) {
430                close(my_obj->fd);
431                my_obj->fd = -1;
432            }
433        }
434        break;
435    default:
436        CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
437                   __func__,evt,my_obj->state);
438        rc = -1;
439        break;
440    }
441    return rc;
442}
443
444int32_t mm_stream_fsm_acquired(mm_stream_t *my_obj,
445                               mm_stream_evt_type_t evt,
446                               void * in_val,
447                               void * out_val)
448{
449    int32_t rc = 0;
450
451    CDBG("%s :E evt = %d",__func__,evt);
452    switch(evt) {
453    case MM_STREAM_EVT_SET_FMT:
454        {
455            mm_camera_stream_config_t *config =
456                (mm_camera_stream_config_t *)in_val;
457
458            rc = mm_stream_config(my_obj, config);
459
460            /* change state to configed */
461            my_obj->state = MM_STREAM_STATE_CFG;
462
463            break;
464        }
465    case MM_STREAM_EVT_RELEASE:
466        rc = mm_stream_release(my_obj);
467        /* change state to not used */
468         my_obj->state = MM_STREAM_STATE_NOTUSED;
469        break;
470    case MM_STREAM_EVT_SET_PARM:
471        rc = mm_stream_set_parm_acquire(my_obj, in_val);
472        break;
473    case MM_STREAM_EVT_GET_PARM:
474        rc = mm_stream_get_parm_acquire(my_obj,out_val);
475        break;
476    default:
477        CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
478                   __func__, evt, my_obj->state);
479        rc = -1;
480    }
481    CDBG("%s :X rc = %d",__func__,rc);
482    return rc;
483}
484
485int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
486                          mm_stream_evt_type_t evt,
487                          void * in_val,
488                          void * out_val)
489{
490    int32_t rc = 0;
491    CDBG("%s :E evt = %d",__func__,evt);
492    switch(evt) {
493    case MM_STREAM_EVT_SET_FMT:
494        {
495            mm_camera_stream_config_t *config =
496                (mm_camera_stream_config_t *)in_val;
497
498            rc = mm_stream_config(my_obj, config);
499
500            /* change state to configed */
501            my_obj->state = MM_STREAM_STATE_CFG;
502
503            break;
504        }
505    case MM_STREAM_EVT_RELEASE:
506        rc = mm_stream_release(my_obj);
507        my_obj->state = MM_STREAM_STATE_NOTUSED;
508        break;
509    case MM_STREAM_EVT_SET_PARM:
510        rc = mm_stream_set_parm_config(my_obj, in_val);
511        break;
512    case MM_STREAM_EVT_GET_PARM:
513        rc = mm_stream_get_parm_config(my_obj, out_val);
514        break;
515    case MM_STREAM_EVT_GET_BUF:
516        rc = mm_stream_init_bufs(my_obj);
517        /* change state to buff allocated */
518        if(0 == rc) {
519            my_obj->state = MM_STREAM_STATE_BUFFED;
520        }
521        break;
522    default:
523        CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
524                   __func__, evt, my_obj->state);
525        rc = -1;
526    }
527    CDBG("%s :X rc = %d",__func__,rc);
528    return rc;
529}
530
531int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
532                             mm_stream_evt_type_t evt,
533                             void * in_val,
534                             void * out_val)
535{
536    int32_t rc = 0;
537    CDBG("%s :E evt = %d",__func__,evt);
538    switch(evt) {
539    case MM_STREAM_EVT_PUT_BUF:
540        rc = mm_stream_deinit_bufs(my_obj);
541        /* change state to configed */
542        if(0 == rc) {
543            my_obj->state = MM_STREAM_STATE_CFG;
544        }
545        break;
546    case MM_STREAM_EVT_REG_BUF:
547        rc = mm_stream_reg_buf(my_obj);
548        /* change state to regged */
549        if(0 == rc) {
550            my_obj->state = MM_STREAM_STATE_REG;
551        }
552        break;
553    case MM_STREAM_EVT_SET_PARM:
554        rc = mm_stream_set_parm_config(my_obj, in_val);
555        break;
556    case MM_STREAM_EVT_GET_PARM:
557        rc = mm_stream_get_parm_config(my_obj, out_val);
558        break;
559    default:
560        CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
561                   __func__, evt, my_obj->state);
562        rc = -1;
563    }
564    CDBG("%s :X rc = %d",__func__,rc);
565    return rc;
566}
567
568int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
569                          mm_stream_evt_type_t evt,
570                          void * in_val,
571                          void * out_val)
572{
573    int32_t rc = 0;
574    CDBG("%s :E evt = %d",__func__,evt);
575
576    switch(evt) {
577    case MM_STREAM_EVT_UNREG_BUF:
578        rc = mm_stream_unreg_buf(my_obj);
579
580        /* change state to buffed */
581        my_obj->state = MM_STREAM_STATE_BUFFED;
582        break;
583    case MM_STREAM_EVT_START:
584        {
585            /* launch cmd thread if CB is not null */
586            if (NULL != my_obj->buf_cb) {
587                mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
588                                mm_stream_dispatch_app_data,
589                                (void *)my_obj);
590
591            }
592
593            if(mm_stream_need_stream_on(my_obj)) {
594                rc = mm_stream_streamon(my_obj);
595                if (0 != rc) {
596                    /* failed stream on, need to release cmd thread if it's launched */
597                    if (NULL != my_obj->buf_cb) {
598                        mm_camera_cmd_thread_release(&my_obj->cmd_thread);
599
600                    }
601                    break;
602                }
603                my_obj->state = MM_STREAM_STATE_ACTIVE_STREAM_ON;
604            } else {
605                /* register one time CB at video fd */
606                CDBG("%s : Video Size snapshot Enabled",__func__);
607                mm_stream_data_cb_t cb;
608                memset(&cb, 0, sizeof(mm_stream_data_cb_t));
609                cb.cb_count = 1; /* one time reigstration */
610                cb.user_data = (void*)my_obj;
611                cb.cb = mm_stream_buf_notify;
612                rc = mm_channel_reg_stream_cb(my_obj->ch_obj, &cb,
613                                              MSM_V4L2_EXT_CAPTURE_MODE_VIDEO,
614                                              my_obj->sensor_idx);
615                my_obj->state = MM_STREAM_STATE_ACTIVE_STREAM_OFF;
616            }
617        }
618        break;
619    case MM_STREAM_EVT_SET_PARM:
620        rc = mm_stream_set_parm_config(my_obj, in_val);
621        break;
622    case MM_STREAM_EVT_GET_PARM:
623        rc = mm_stream_get_parm_config(my_obj, out_val);
624        break;
625    default:
626        CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
627                   __func__, evt, my_obj->state);
628        rc = -1;
629    }
630    CDBG("%s :X rc = %d",__func__,rc);
631    return rc;
632}
633
634int32_t mm_stream_fsm_active_stream_on(mm_stream_t * my_obj,
635                                              mm_stream_evt_type_t evt,
636                                              void * in_val,
637                                              void * out_val)
638{
639    int32_t rc = 0;
640    CDBG("%s :E evt = %d",__func__,evt);
641    switch(evt) {
642    case MM_STREAM_EVT_QBUF:
643        rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val);
644        break;
645    case MM_STREAM_EVT_STOP:
646        {
647            rc = mm_stream_streamoff(my_obj);
648            if (NULL != my_obj->buf_cb) {
649                mm_camera_cmd_thread_release(&my_obj->cmd_thread);
650
651            }
652            my_obj->state = MM_STREAM_STATE_REG;
653        }
654        break;
655    case MM_STREAM_EVT_SET_PARM:
656        rc = mm_stream_set_parm_start(my_obj, in_val);
657        break;
658    case MM_STREAM_EVT_GET_PARM:
659        rc = mm_stream_get_parm_start(my_obj, out_val);
660        break;
661    default:
662        CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
663                   __func__, evt, my_obj->state);
664        return -1;
665    }
666    CDBG("%s :X rc = %d",__func__,rc);
667    return rc;
668}
669
670int32_t mm_stream_fsm_active_stream_off(mm_stream_t * my_obj,
671                                               mm_stream_evt_type_t evt,
672                                               void * in_val,
673                                               void * out_val)
674{
675    int32_t rc = 0;
676    CDBG("%s :E evt = %d",__func__,evt);
677    switch(evt) {
678    case MM_STREAM_EVT_QBUF:
679        rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val);
680        break;
681    case MM_STREAM_EVT_STOP:
682        {
683            if (NULL != my_obj->buf_cb) {
684                rc = mm_camera_cmd_thread_release(&my_obj->cmd_thread);
685
686            }
687            my_obj->state = MM_STREAM_STATE_REG;
688        }
689        break;
690   case MM_STREAM_EVT_SET_PARM:
691        rc = mm_stream_set_parm_config(my_obj, in_val);
692        break;
693    case MM_STREAM_EVT_GET_PARM:
694        rc = mm_stream_get_parm_config(my_obj, out_val);
695        break;
696    default:
697        CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
698                   __func__, evt, my_obj->state);
699        return -1;
700    }
701    CDBG("%s :X rc = %d",__func__,rc);
702    return rc;
703}
704
705int32_t mm_stream_config(mm_stream_t *my_obj,
706                         mm_camera_stream_config_t *config)
707{
708    int32_t rc = 0;
709    memcpy(&my_obj->fmt, &config->fmt, sizeof(mm_camera_image_fmt_t));
710    my_obj->hal_requested_num_bufs = config->num_of_bufs;
711    my_obj->need_stream_on = config->need_stream_on;
712
713    rc = mm_stream_get_offset(my_obj);
714    if(rc != 0) {
715        CDBG_ERROR("%s: Error in offset query",__func__);
716        return rc;
717    }
718    if(mm_stream_need_stream_on(my_obj)) {
719        /* only send fmt to backend if we need streamon */
720        rc = mm_stream_set_fmt(my_obj);
721    }
722    return rc;
723}
724
725int32_t mm_stream_release(mm_stream_t *my_obj)
726{
727    int32_t rc;
728
729    /* close fd */
730    if(my_obj->fd > 0)
731    {
732        close(my_obj->fd);
733    }
734
735    /* destroy mutex */
736    pthread_mutex_destroy(&my_obj->buf_lock);
737    pthread_mutex_destroy(&my_obj->cb_lock);
738
739    /* reset stream obj */
740    memset(my_obj, 0, sizeof(mm_stream_t));
741    my_obj->fd = -1;
742
743    return 0;
744}
745
746uint8_t mm_stream_need_stream_on(mm_stream_t *my_obj)
747{
748    return my_obj->need_stream_on;
749}
750
751int32_t mm_stream_streamon(mm_stream_t *my_obj)
752{
753    int32_t rc;
754    enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
755
756    CDBG("%s :E",__func__);
757    /* Add fd to data poll thread */
758    rc = mm_camera_poll_thread_add_poll_fd(&my_obj->ch_obj->poll_thread[0],
759                                           my_obj->my_hdl,
760                                           my_obj->fd,
761                                           mm_stream_data_notify,
762                                           (void*)my_obj);
763    if (rc < 0) {
764        return rc;
765    }
766    rc = ioctl(my_obj->fd, VIDIOC_STREAMON, &buf_type);
767    if (rc < 0) {
768        CDBG_ERROR("%s: ioctl VIDIOC_STREAMON failed: rc=%d\n",
769                   __func__, rc);
770        /* remove fd from data poll thread in case of failure */
771        mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl);
772    }
773    CDBG("%s :X rc = %d",__func__,rc);
774    return rc;
775}
776
777int32_t mm_stream_streamoff(mm_stream_t *my_obj)
778{
779    int32_t rc;
780    enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
781
782    /* step1: remove fd from data poll thread */
783    mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl);
784
785    /* step2: stream off */
786    rc = ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type);
787    if (rc < 0) {
788        CDBG_ERROR("%s: STREAMOFF failed: %s\n",
789                __func__, strerror(errno));
790    }
791    CDBG("%s :X rc = %d",__func__,rc);
792    return rc;
793}
794
795static uint32_t mm_stream_util_get_v4l2_fmt(cam_format_t fmt,
796                                            uint8_t *num_planes)
797{
798    uint32_t val;
799    switch(fmt) {
800    case CAMERA_YUV_420_NV12:
801        val = V4L2_PIX_FMT_NV12;
802        *num_planes = 2;
803        break;
804    case CAMERA_YUV_420_NV21:
805        val = V4L2_PIX_FMT_NV21;
806        *num_planes = 2;
807        break;
808    case CAMERA_BAYER_SBGGR10:
809    case CAMERA_RDI:
810        val= V4L2_PIX_FMT_SBGGR10;
811        *num_planes = 1;
812        break;
813    case CAMERA_YUV_422_NV61:
814        val= V4L2_PIX_FMT_NV61;
815        *num_planes = 2;
816        break;
817    default:
818        val = 0;
819        *num_planes = 0;
820        break;
821    }
822    return val;
823}
824
825int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
826                                 mm_camera_buf_info_t* buf_info)
827{
828    int32_t idx = -1, rc = 0;
829    struct v4l2_buffer vb;
830    struct v4l2_plane planes[VIDEO_MAX_PLANES];
831    uint32_t i = 0;
832    uint8_t num_planes = 0;
833
834    mm_stream_util_get_v4l2_fmt(my_obj->fmt.fmt,
835                                &num_planes);
836
837    memset(&vb,  0,  sizeof(vb));
838    vb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
839    vb.memory = V4L2_MEMORY_USERPTR;
840    vb.m.planes = &planes[0];
841    vb.length = num_planes;
842
843    rc = ioctl(my_obj->fd, VIDIOC_DQBUF, &vb);
844    if (rc < 0) {
845        CDBG_ERROR("%s: VIDIOC_DQBUF ioctl call failed (rc=%d)\n",
846                   __func__, rc);
847    } else {
848        int8_t idx = vb.index;
849        buf_info->buf = &my_obj->buf[idx];
850        buf_info->frame_idx = vb.sequence;
851        buf_info->stream_id = my_obj->my_hdl;
852        buf_info->need_pp = my_obj->is_pp_needed;
853
854        buf_info->buf->stream_id = my_obj->my_hdl;
855        buf_info->buf->buf_idx = idx;
856        buf_info->buf->frame_idx = vb.sequence;
857        buf_info->buf->ts.tv_sec  = vb.timestamp.tv_sec;
858        buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000;
859
860        for(i = 0; i < vb.length; i++) {
861            CDBG("%s plane %d addr offset: %d data offset:%d\n",
862                 __func__, i, vb.m.planes[i].reserved[0],
863                 vb.m.planes[i].data_offset);
864            buf_info->buf->planes[i].reserved[0] =
865                vb.m.planes[i].reserved[0];
866            buf_info->buf->planes[i].data_offset =
867                vb.m.planes[i].data_offset;
868        }
869
870
871    }
872    CDBG("%s :X rc = %d",__func__,rc);
873    return rc;
874}
875
876int32_t mm_stream_get_crop(mm_stream_t *my_obj,
877                           mm_camera_rect_t *crop)
878{
879    struct v4l2_crop crop_info;
880    int32_t rc = 0;
881
882    memset(&crop_info, 0, sizeof(crop_info));
883    crop_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
884    rc = ioctl(my_obj->fd, VIDIOC_G_CROP, &crop_info);
885    if (0 == rc) {
886        crop->left = crop_info.c.left;
887        crop->top = crop_info.c.top;
888        crop->width = crop_info.c.width;
889        crop->height = crop_info.c.height;
890    }
891    CDBG("%s :X rc = %d",__func__,rc);
892    return rc;
893}
894
895int32_t mm_stream_set_parm_acquire(mm_stream_t *my_obj,
896                         void *in_value)
897{
898    int32_t rc = 0;
899    mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)in_value;
900    mm_camera_stream_parm_t parm_type = payload->parm_type;
901
902    CDBG("%s: parm_type = %d",__func__,(int)parm_type);
903    switch(parm_type) {
904    case MM_CAMERA_STREAM_CID:{
905            stream_cid_t *value = (stream_cid_t *)in_value;
906            mm_stream_set_cid(my_obj,value);
907            break;
908        }
909        default:
910            CDBG_ERROR("%s : Parm -%d set is not supported here",__func__,(int)parm_type);
911            break;
912    }
913    return rc;
914}
915int32_t mm_stream_get_parm_acquire(mm_stream_t *my_obj,
916                         void *out_value)
917{
918    int32_t rc = 0;
919    mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)out_value;
920    mm_camera_stream_parm_t parm_type = payload->parm_type;
921
922    CDBG("%s: parm_type = %d",__func__,(int)parm_type);
923    switch(parm_type) {
924    case MM_CAMERA_STREAM_CID:{
925            stream_cid_t *value = (stream_cid_t *)out_value;
926            rc = mm_stream_get_cid(my_obj,value);
927            break;
928        }
929        case MM_CAMERA_STREAM_CROP:{
930            mm_camera_rect_t *crop = (mm_camera_rect_t *)out_value;
931            rc = mm_stream_get_crop(my_obj, crop);
932            break;
933        }
934        default:
935            CDBG_ERROR("%s : Parm -%d get is not supported here",__func__,(int)parm_type);
936            break;
937    }
938    return rc;
939}
940
941int32_t mm_stream_set_parm_config(mm_stream_t *my_obj,
942                         void *in_value)
943{
944    int32_t rc = 0;
945    mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)in_value;
946    mm_camera_stream_parm_t parm_type = payload->parm_type;
947    void *value = payload->value;
948
949    CDBG("%s: parm_type = %d",__func__,(int)parm_type);
950    switch(parm_type) {
951        default:
952            CDBG_ERROR("%s : Parm -%d set is not supported here",__func__,(int)parm_type);
953            break;
954    }
955    return rc;
956}
957int32_t mm_stream_get_parm_config(mm_stream_t *my_obj,
958                         void *out_value)
959{
960    int32_t rc = 0;
961    mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)out_value;
962
963    if(payload == NULL) {
964        CDBG_ERROR("%s : Invalid Argument",__func__);
965        return -1;
966    }
967    CDBG("%s: parm_type = %d",__func__,(int)payload->parm_type);
968    switch(payload->parm_type) {
969        case MM_CAMERA_STREAM_OFFSET:
970            memcpy(payload->value,(void *)&my_obj->frame_offset,sizeof(mm_camera_frame_len_offset));
971            break;
972        case MM_CAMERA_STREAM_CROP:{
973            mm_camera_rect_t *crop = (mm_camera_rect_t *)payload->value;
974            rc = mm_stream_get_crop(my_obj, crop);
975            break;
976        }
977        default:
978            CDBG_ERROR("%s : Parm -%d get is not supported here",__func__,(int)payload->parm_type);
979            break;
980    }
981    return rc;
982}
983
984int32_t mm_stream_set_parm_start(mm_stream_t *my_obj,
985                         void *in_value)
986{
987    int32_t rc = 0;
988    mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)in_value;
989    mm_camera_stream_parm_t parm_type = payload->parm_type;
990    void *value = payload->value;
991
992    CDBG("%s: parm_type = %d",__func__,(int)parm_type);
993    switch(parm_type) {
994        default:
995            CDBG_ERROR("%s : Parm -%d set is not supported here",__func__,(int)parm_type);
996            break;
997    }
998    return rc;
999}
1000int32_t mm_stream_get_parm_start(mm_stream_t *my_obj,
1001                         void *out_value)
1002{
1003    int32_t rc = 0;
1004    mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)out_value;
1005
1006    if(payload == NULL) {
1007        CDBG_ERROR("%s : Invalid Argument",__func__);
1008        return -1;
1009    }
1010    CDBG("%s: parm_type = %d",__func__,(int)payload->parm_type);
1011    switch(payload->parm_type) {
1012        case MM_CAMERA_STREAM_OFFSET:
1013            memcpy(payload->value,(void *)&my_obj->frame_offset,sizeof(mm_camera_frame_len_offset));
1014            break;
1015        case MM_CAMERA_STREAM_CROP:{
1016            mm_camera_rect_t *crop = (mm_camera_rect_t *)payload->value;
1017            rc = mm_stream_get_crop(my_obj, crop);
1018            break;
1019        }
1020        default:
1021            CDBG_ERROR("%s : Parm -%d get is not supported here",__func__,(int)payload->parm_type);
1022            break;
1023    }
1024    return rc;
1025}
1026int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj)
1027{
1028    int32_t rc = 0;
1029    struct v4l2_streamparm s_parm;
1030
1031    s_parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1032    s_parm.parm.capture.extendedmode = my_obj->ext_image_mode;
1033
1034    rc = ioctl(my_obj->fd, VIDIOC_S_PARM, &s_parm);
1035        CDBG("%s:stream fd=%d, rc=%d, extended_mode=%d\n",
1036                 __func__, my_obj->fd, rc,
1037                 s_parm.parm.capture.extendedmode);
1038    return rc;
1039}
1040
1041int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf)
1042{
1043    int32_t i, rc = 0;
1044    int *ret;
1045    struct v4l2_buffer buffer;
1046
1047    memset(&buffer, 0, sizeof(buffer));
1048    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1049    buffer.memory = V4L2_MEMORY_USERPTR;
1050    buffer.index = buf->buf_idx;
1051    buffer.m.planes = &buf->planes[0];
1052    buffer.length = buf->num_planes;
1053
1054    CDBG("%s:stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d\n", __func__,
1055         buf->stream_id, buf->fd, buffer.index, buffer.length);
1056
1057    rc = ioctl(my_obj->fd, VIDIOC_QBUF, &buffer);
1058    CDBG("%s: qbuf idx:%d, rc:%d", __func__, buffer.index, rc);
1059    return rc;
1060}
1061
1062/* This function let kernel know amount of buffers will be registered */
1063int32_t mm_stream_request_buf(mm_stream_t * my_obj)
1064{
1065    int32_t rc = 0;
1066    uint8_t i,reg = 0;
1067    struct v4l2_requestbuffers bufreq;
1068    uint8_t buf_num = my_obj->buf_num;
1069
1070    if(buf_num > MM_CAMERA_MAX_NUM_FRAMES) {
1071        CDBG_ERROR("%s: buf num %d > max limit %d\n",
1072                 __func__, buf_num, MM_CAMERA_MAX_NUM_FRAMES);
1073        return -1;
1074    }
1075    pthread_mutex_lock(&my_obj->buf_lock);
1076    for(i = 0; i < buf_num; i++){
1077        if (my_obj->buf_status[i].initial_reg_flag){
1078            reg = 1;
1079            break;
1080        }
1081    }
1082    pthread_mutex_unlock(&my_obj->buf_lock);
1083    if(!reg) {
1084        //No need to register a buffer
1085        CDBG_ERROR("No Need to register this buffer");
1086        return rc;
1087    }
1088    memset(&bufreq, 0, sizeof(bufreq));
1089    bufreq.count = buf_num;
1090    bufreq.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1091    bufreq.memory = V4L2_MEMORY_USERPTR;
1092    rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
1093    if (rc < 0) {
1094      CDBG_ERROR("%s: fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d\n",
1095           __func__, my_obj->fd, rc);
1096    }
1097    CDBG("%s :X rc = %d",__func__,rc);
1098    return rc;
1099}
1100
1101int32_t mm_stream_get_frame_len_offset(mm_camera_image_fmt_t* img_fmt,
1102                                       camera_mode_t mode,
1103                                       int image_type,
1104                                       mm_camera_frame_len_offset * frame_offset)
1105{
1106    /* TODO : this function should query the frame len from backend using cmd */
1107    /* for now, it's still use hardcoded value */
1108    uint32_t width, height;
1109    int local_height;
1110
1111    width = img_fmt->width;
1112    height = img_fmt->height;
1113
1114    switch (img_fmt->fmt) {
1115    case CAMERA_YUV_420_NV12:
1116    case CAMERA_YUV_420_NV21:
1117        frame_offset->num_planes = 2;
1118        if (image_type == OUTPUT_TYPE_V) {
1119            frame_offset->mp[0].len = PAD_TO_2K(width * height);
1120            frame_offset->mp[1].len = PAD_TO_2K(width * height/2);
1121            /* TODO: offset to count in meta header*/
1122            frame_offset->mp[0].offset = 0;
1123            frame_offset->mp[1].offset = 0;
1124        } else if (image_type == OUTPUT_TYPE_P) {
1125            frame_offset->mp[0].len = PAD_TO_WORD(width * height);
1126            frame_offset->mp[1].len = PAD_TO_WORD(width * height/2);
1127            /* TODO: offset to count in meta header*/
1128            frame_offset->mp[0].offset = 0;
1129            frame_offset->mp[1].offset = 0;
1130        } else {
1131            frame_offset->mp[0].len = PAD_TO_WORD(width * CEILING16(height));
1132            frame_offset->mp[1].len = PAD_TO_WORD(width * CEILING16(height)/2);
1133            /* TODO: offset to count in meta header*/
1134            frame_offset->mp[0].offset = 0;
1135            frame_offset->mp[1].offset = 0;
1136        }
1137        frame_offset->frame_len =
1138            PAD_TO_4K(frame_offset->mp[0].len + frame_offset->mp[1].len);
1139        break;
1140    case CAMERA_BAYER_SBGGR10:
1141        frame_offset->num_planes = 1;
1142        frame_offset->mp[0].len = PAD_TO_WORD(width * height);
1143        frame_offset->frame_len = frame_offset->mp[0].len;
1144        break;
1145    case CAMERA_YUV_422_NV16:
1146    case CAMERA_YUV_422_NV61:
1147        if( image_type == OUTPUT_TYPE_S || image_type == OUTPUT_TYPE_V) {
1148            local_height = CEILING16(height);
1149        } else {
1150            local_height = height;
1151        }
1152        frame_offset->num_planes = 2;
1153        frame_offset->mp[0].len = PAD_TO_WORD(width * height);
1154        frame_offset->mp[1].len = PAD_TO_WORD(width * height);
1155        /* TODO: offset to count in meta header*/
1156        frame_offset->mp[0].offset = 0;
1157        frame_offset->mp[1].offset = 0;
1158        frame_offset->frame_len =
1159            frame_offset->mp[0].len + frame_offset->mp[1].len;
1160        break;
1161    default:
1162        CDBG("%s: format %d not supported.\n",
1163            __func__, img_fmt->fmt);
1164        frame_offset->frame_len = 0;
1165    }
1166    CDBG("%s:fmt=%d,image_type=%d,width=%d,height=%d,frame_len=%d\n",
1167        __func__, img_fmt->fmt, image_type, width, height, frame_offset->frame_len);
1168    return 0;
1169}
1170
1171int32_t mm_stream_init_bufs(mm_stream_t * my_obj)
1172{
1173    int32_t i, rc = 0, j;
1174    int image_type;
1175    mm_camear_mem_vtbl_t *mem_vtbl = NULL;
1176    mm_camera_frame_len_offset frame_offset;
1177    uint8_t *reg_flags = NULL;
1178
1179    /* deinit buf if it's not NULL*/
1180    if (NULL != my_obj->buf) {
1181        mm_stream_deinit_bufs(my_obj);
1182    }
1183
1184    my_obj->buf_num = my_obj->hal_requested_num_bufs;
1185    /* if stream needs do pp, allocate extra one buf for pp*/
1186    if (my_obj->is_pp_needed) {
1187        my_obj->buf_num++;
1188    }
1189
1190    my_obj->buf =
1191        (mm_camera_buf_def_t*)malloc(sizeof(mm_camera_buf_def_t) * my_obj->buf_num);
1192    my_obj->buf_status =
1193        (mm_stream_buf_status_t*)malloc(sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
1194    reg_flags = (uint8_t *)malloc(sizeof(uint8_t) * my_obj->buf_num);
1195
1196    if (NULL == my_obj->buf ||
1197        NULL == my_obj->buf_status ||
1198        NULL == reg_flags) {
1199        CDBG_ERROR("%s: No memory for buf", __func__);
1200        rc = -1;
1201        goto error_malloc;
1202    }
1203
1204    memset(my_obj->buf, 0, sizeof(mm_camera_buf_def_t) * my_obj->buf_num);
1205    memset(my_obj->buf_status, 0, sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
1206    memset(reg_flags, 0, sizeof(uint8_t) * my_obj->buf_num);
1207
1208    mem_vtbl = my_obj->ch_obj->cam_obj->mem_vtbl;
1209    rc = mem_vtbl->get_buf(my_obj->ch_obj->cam_obj->my_hdl,
1210                           my_obj->ch_obj->my_hdl,
1211                           my_obj->my_hdl,
1212                           mem_vtbl->user_data,
1213                           &my_obj->frame_offset,
1214                           my_obj->buf_num,
1215                           reg_flags,
1216                           my_obj->buf);
1217
1218    if (0 != rc) {
1219        CDBG_ERROR("%s: Error get buf, rc = %d\n", __func__, rc);
1220        goto error_malloc;
1221    }
1222
1223    for (i=0; i < my_obj->buf_num; i++) {
1224        my_obj->buf_status[i].initial_reg_flag = reg_flags[i];
1225        my_obj->buf[i].stream_id = my_obj->my_hdl;
1226    }
1227
1228    free(reg_flags);
1229    reg_flags = NULL;
1230
1231    for (i=0; i < my_obj->buf_num; i++) {
1232        if (my_obj->buf[i].fd > 0) {
1233            if(0 >= (rc = mm_camera_map_buf(my_obj->ch_obj->cam_obj,
1234                          my_obj->ext_image_mode,
1235                          i,
1236                          my_obj->buf[i].fd,
1237                          my_obj->buf[i].frame_len)))
1238            {
1239                CDBG_ERROR("%s: Error mapping buf (rc = %d)", __func__, rc);
1240                goto error_map;
1241            }
1242        } else {
1243            CDBG_ERROR("%s: Invalid fd for buf idx (%d)", __func__, i);
1244        }
1245    }
1246
1247    return 0;
1248
1249error_map:
1250    /* error, unmapping previously mapped bufs */
1251    for (j=0; j<i; j++) {
1252        if (my_obj->buf[j].fd > 0) {
1253            mm_camera_unmap_buf(my_obj->ch_obj->cam_obj,
1254                                my_obj->ext_image_mode,
1255                                j);
1256        }
1257    }
1258
1259    /* put buf back */
1260    mem_vtbl->put_buf(my_obj->ch_obj->cam_obj->my_hdl,
1261                      my_obj->ch_obj->my_hdl,
1262                      my_obj->my_hdl,
1263                      mem_vtbl->user_data,
1264                      my_obj->buf_num,
1265                      my_obj->buf);
1266
1267error_malloc:
1268    if (NULL != my_obj->buf) {
1269        free(my_obj->buf);
1270        my_obj->buf = NULL;
1271    }
1272    if (NULL != my_obj->buf_status) {
1273        free(my_obj->buf_status);
1274        my_obj->buf_status = NULL;
1275    }
1276    if (NULL != reg_flags) {
1277        free(reg_flags);
1278        reg_flags = NULL;
1279    }
1280
1281    return rc;
1282}
1283
1284/* return buffers to surface or release buffers allocated */
1285int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj)
1286{
1287    int32_t rc = 0, i;
1288    mm_camear_mem_vtbl_t *mem_vtbl = NULL;
1289
1290    if (NULL == my_obj->buf) {
1291        CDBG("%s: Buf is NULL, no need to deinit", __func__);
1292        return rc;
1293    }
1294
1295    /* IOMMU unmapping */
1296    for (i=0; i<my_obj->buf_num; i++) {
1297        if (my_obj->buf[i].fd > 0) {
1298            rc = mm_camera_unmap_buf(my_obj->ch_obj->cam_obj,
1299                                     my_obj->ext_image_mode,
1300                                     i);
1301            if (rc < 0 ) {
1302                CDBG_ERROR("%s: Error unmapping bufs at idx(%d) rc=%d",
1303                           __func__, i, rc);
1304            }
1305        }
1306    }
1307
1308    /* release bufs */
1309    mem_vtbl = my_obj->ch_obj->cam_obj->mem_vtbl;
1310    if (NULL != mem_vtbl) {
1311        rc = mem_vtbl->put_buf(my_obj->ch_obj->cam_obj->my_hdl,
1312                          my_obj->ch_obj->my_hdl,
1313                          my_obj->my_hdl,
1314                          mem_vtbl->user_data,
1315                          my_obj->buf_num,
1316                          my_obj->buf);
1317    } else {
1318        CDBG_ERROR("%s: mem table is NULL, cannot release buf", __func__);
1319        rc = -1;
1320    }
1321
1322    free(my_obj->buf);
1323    my_obj->buf = NULL;
1324    free(my_obj->buf_status);
1325    my_obj->buf_status = NULL;
1326
1327    return rc;
1328}
1329
1330int32_t mm_stream_reg_buf(mm_stream_t * my_obj)
1331{
1332    int32_t rc = 0;
1333    uint8_t i;
1334
1335    rc = mm_stream_request_buf(my_obj);
1336    if (rc != 0) {
1337        return rc;
1338    }
1339
1340    pthread_mutex_lock(&my_obj->buf_lock);
1341    for(i = 0; i < my_obj->buf_num; i++){
1342        my_obj->buf[i].buf_idx = i;
1343
1344        /* check if need to qbuf initially */
1345        if (my_obj->buf_status[i].initial_reg_flag) {
1346            rc = mm_stream_qbuf(my_obj, &my_obj->buf[i]);
1347            if (rc != 0) {
1348                CDBG_ERROR("%s: VIDIOC_QBUF rc = %d\n", __func__, rc);
1349                return rc;
1350            }
1351        }
1352
1353        my_obj->buf_status[i].buf_refcnt = 0;
1354        my_obj->buf_status[i].in_kernel = 1;
1355    }
1356    pthread_mutex_unlock(&my_obj->buf_lock);
1357    return rc;
1358}
1359
1360int32_t mm_stream_unreg_buf(mm_stream_t * my_obj)
1361{
1362    struct v4l2_requestbuffers bufreq;
1363    int32_t i, rc = 0,reg = 0;
1364
1365    pthread_mutex_lock(&my_obj->buf_lock);
1366    if (NULL != my_obj->buf_status) {
1367        for(i = 0; i < my_obj->buf_num; i++){
1368            if (my_obj->buf_status[i].initial_reg_flag){
1369                reg = 1;
1370                break;
1371            }
1372        }
1373    }
1374    pthread_mutex_unlock(&my_obj->buf_lock);
1375    if(!reg) {
1376        //No need to unregister a buffer
1377        goto end;
1378    }
1379    bufreq.count = 0;
1380    bufreq.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1381    bufreq.memory = V4L2_MEMORY_USERPTR;
1382    rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
1383    if (rc < 0) {
1384        CDBG_ERROR("%s: fd=%d, VIDIOC_REQBUFS failed, rc=%d\n",
1385              __func__, my_obj->fd, rc);
1386    }
1387
1388end:
1389    /* reset buf reference count */
1390    pthread_mutex_lock(&my_obj->buf_lock);
1391    if (NULL != my_obj->buf_status) {
1392        for(i = 0; i < my_obj->buf_num; i++){
1393            my_obj->buf_status[i].buf_refcnt = 0;
1394            my_obj->buf_status[i].in_kernel = 0;
1395        }
1396    }
1397    pthread_mutex_unlock(&my_obj->buf_lock);
1398
1399    return rc;
1400}
1401
1402int32_t mm_stream_set_fmt(mm_stream_t *my_obj)
1403{
1404    int32_t rc = 0;
1405    struct v4l2_format fmt;
1406
1407    if(my_obj->fmt.width == 0 || my_obj->fmt.height == 0) {
1408        CDBG_ERROR("%s:invalid input[w=%d,h=%d,fmt=%d]\n",
1409                 __func__, my_obj->fmt.width, my_obj->fmt.height, my_obj->fmt.fmt);
1410        return -1;
1411    }
1412
1413    memset(&fmt, 0, sizeof(fmt));
1414    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1415    fmt.fmt.pix_mp.width = my_obj->fmt.width;
1416    fmt.fmt.pix_mp.height= my_obj->fmt.height;
1417    fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
1418    fmt.fmt.pix_mp.pixelformat =
1419            mm_stream_util_get_v4l2_fmt(my_obj->fmt.fmt,
1420                                      &(fmt.fmt.pix_mp.num_planes));
1421    rc = ioctl(my_obj->fd, VIDIOC_S_FMT, &fmt);
1422    CDBG("%s:fd=%d, ext_image_mode=%d, rc=%d\n",
1423             __func__, my_obj->fd, my_obj->ext_image_mode, rc);
1424
1425    return rc;
1426}
1427
1428int32_t mm_stream_get_offset(mm_stream_t *my_obj)
1429{
1430    int32_t rc = 0;
1431    cam_frame_resolution_t frame_offset;
1432
1433    memset(&my_obj->frame_offset,0,sizeof(mm_camera_frame_len_offset));
1434
1435    frame_offset.format = my_obj->fmt.fmt;
1436    frame_offset.image_mode = my_obj->ext_image_mode;
1437    frame_offset.rotation = my_obj->fmt.rotation;
1438    frame_offset.width = my_obj->fmt.width;
1439    frame_offset.height = my_obj->fmt.height;
1440
1441    switch (my_obj->ext_image_mode) {
1442    case MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW:
1443    case MSM_V4L2_EXT_CAPTURE_MODE_MAIN:
1444    case MSM_V4L2_EXT_CAPTURE_MODE_RAW:
1445    case MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL:
1446    case MSM_V4L2_EXT_CAPTURE_MODE_RDI:
1447        frame_offset.padding_format = CAMERA_PAD_TO_WORD;
1448        break;
1449    case MSM_V4L2_EXT_CAPTURE_MODE_VIDEO:
1450    default:
1451        frame_offset.padding_format = CAMERA_PAD_TO_2K;
1452        break;
1453    }
1454
1455    CDBG("%s: format = %d, image_mode = %d, padding_format = %d, rotation = %d,"
1456            "width = %d height = %d",
1457             __func__,frame_offset.format,frame_offset.image_mode,frame_offset.padding_format,
1458             frame_offset.rotation,frame_offset.width,frame_offset.height);
1459
1460    rc = mm_camera_send_native_ctrl_cmd(my_obj->ch_obj->cam_obj,
1461                                            CAMERA_GET_PARM_FRAME_RESOLUTION,
1462                                            sizeof(cam_frame_resolution_t),
1463                                            &frame_offset);
1464    if(rc != 0) {
1465        CDBG_ERROR("%s: Failed to get the stream offset and frame length",__func__);
1466        return rc;
1467    }
1468    my_obj->fmt.width = frame_offset.width;
1469    my_obj->fmt.height = frame_offset.height;
1470    memcpy(&my_obj->frame_offset,&frame_offset.frame_offset,sizeof(mm_camera_frame_len_offset));
1471    CDBG("%s: Frame length = %d width = %d, height = %d, rc = %d",
1472         __func__,my_obj->frame_offset.frame_len,my_obj->fmt.width,my_obj->fmt.height,rc);
1473    return rc;
1474}
1475
1476
1477int32_t mm_stream_set_cid(mm_stream_t *my_obj,stream_cid_t *value)
1478{
1479    int32_t rc = 0;
1480    cam_cid_info_t cam_cid_info;
1481
1482    cam_cid_info.num_cids = 1;
1483    cam_cid_info.cid_entries[0].cid = value->cid;
1484    cam_cid_info.cid_entries[0].dt = value->dt;
1485    cam_cid_info.cid_entries[0].inst_handle = my_obj->inst_hdl;
1486
1487    rc = mm_camera_send_native_ctrl_cmd(my_obj->ch_obj->cam_obj,
1488                                            CAMERA_SET_PARM_CID,
1489                                            sizeof(cam_cid_info_t),
1490                                            &cam_cid_info);
1491    if(rc != 0) {
1492        CDBG_ERROR("%s: Failed to set the CID",__func__);
1493        return rc;
1494    }
1495    return rc;
1496}
1497
1498int32_t mm_stream_get_cid(mm_stream_t *my_obj,stream_cid_t *out_value)
1499{
1500    //TODO: Need to use sensor structure init in camera query
1501    int32_t rc = 0;
1502    return rc;
1503}
1504
1505int32_t mm_stream_buf_done(mm_stream_t * my_obj,
1506                           mm_camera_buf_def_t *frame)
1507{
1508    int32_t rc = 0;
1509
1510    if (my_obj->is_local_buf) {
1511        /* special case for video-sized live snapshot
1512         * buf is local, no need to qbuf to kernel */
1513        return 0;
1514    }
1515
1516    pthread_mutex_lock(&my_obj->buf_lock);
1517
1518    if(my_obj->buf_status[frame->buf_idx].buf_refcnt == 0) {
1519        CDBG("%s: Error Trying to free second time?(idx=%d) count=%d, ext_image_mode=%d\n",
1520                   __func__, frame->buf_idx,
1521                   my_obj->buf_status[frame->buf_idx].buf_refcnt,
1522                   my_obj->ext_image_mode);
1523        rc = -1;
1524    }else{
1525        my_obj->buf_status[frame->buf_idx].buf_refcnt--;
1526        if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) {
1527            CDBG("<DEBUG> : Buf done for buffer:%d:%d", my_obj->ext_image_mode, frame->buf_idx);
1528            rc = mm_stream_qbuf(my_obj, frame);
1529            if(rc < 0) {
1530                CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n",
1531                     __func__, frame->buf_idx, rc);
1532            } else {
1533                my_obj->buf_status[frame->buf_idx].in_kernel = 1;
1534            }
1535        }else{
1536            CDBG("<DEBUG> : Still ref count pending count :%d",
1537                 my_obj->buf_status[frame->buf_idx].buf_refcnt);
1538            CDBG("<DEBUG> : for buffer:%p:%d, ext_image_mode=%d",
1539                 my_obj, frame->buf_idx, my_obj->ext_image_mode);
1540        }
1541    }
1542    pthread_mutex_unlock(&my_obj->buf_lock);
1543    return rc;
1544}
1545
1546int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj,
1547                             mm_stream_data_cb_t *val)
1548{
1549    int32_t rc = -1;
1550    uint8_t i;
1551
1552    pthread_mutex_lock(&my_obj->cb_lock);
1553    for (i=0 ;i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
1554        if(NULL == my_obj->buf_cb[i].cb) {
1555            memcpy(&my_obj->buf_cb[i], val, sizeof(mm_stream_data_cb_t));
1556            rc = 0;
1557            break;
1558        }
1559    }
1560    pthread_mutex_unlock(&my_obj->cb_lock);
1561
1562    return rc;
1563}
1564