1 /*
2 Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above
10       copyright notice, this list of conditions and the following
11       disclaimer in the documentation and/or other materials provided
12       with the distribution.
13     * Neither the name of The Linux Foundation nor the names of its
14       contributors may be used to endorse or promote products derived
15       from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include <pthread.h>
31 #include <errno.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <poll.h>
37 #include <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 */
47 int32_t mm_stream_qbuf(mm_stream_t *my_obj,
48                        mm_camera_buf_def_t *buf);
49 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj);
50 int32_t mm_stream_set_fmt(mm_stream_t * my_obj);
51 int32_t mm_stream_get_offset(mm_stream_t *my_obj);
52 int32_t mm_stream_set_cid(mm_stream_t *my_obj,stream_cid_t *in_value);
53 int32_t mm_stream_init_bufs(mm_stream_t * my_obj);
54 int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj);
55 int32_t mm_stream_request_buf(mm_stream_t * my_obj);
56 int32_t mm_stream_unreg_buf(mm_stream_t * my_obj);
57 int32_t mm_stream_release(mm_stream_t *my_obj);
58 int32_t mm_stream_get_crop(mm_stream_t *my_obj,
59                          mm_camera_rect_t *crop);
60 int32_t mm_stream_get_cid(mm_stream_t *my_obj,
61                           stream_cid_t *out_value);
62 int32_t mm_stream_set_parm_acquire(mm_stream_t *my_obj,
63                          void *value);
64 int32_t mm_stream_get_parm_acquire(mm_stream_t *my_obj,
65                          void *value);
66 int32_t mm_stream_set_parm_config(mm_stream_t *my_obj,
67                          void *value);
68 int32_t mm_stream_get_parm_config(mm_stream_t *my_obj,
69                          void *value);
70 int32_t mm_stream_set_parm_start(mm_stream_t *my_obj,
71                          void *value);
72 int32_t mm_stream_get_parm_start(mm_stream_t *my_obj,
73                          void *value);
74 int32_t mm_stream_streamon(mm_stream_t *my_obj);
75 int32_t mm_stream_streamoff(mm_stream_t *my_obj);
76 int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
77                                  mm_camera_buf_info_t* buf_info);
78 int32_t mm_stream_config(mm_stream_t *my_obj,
79                          mm_camera_stream_config_t *config);
80 uint8_t mm_stream_need_stream_on(mm_stream_t *my_obj);
81 int32_t mm_stream_reg_buf(mm_stream_t * my_obj);
82 int32_t mm_stream_buf_done(mm_stream_t * my_obj,
83                            mm_camera_buf_def_t *frame);
84 
85 
86 /* state machine function declare */
87 int32_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);
91 int32_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);
95 int32_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);
99 int32_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);
103 int32_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);
107 int32_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);
111 int32_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 
116 extern 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 
get_stream_inst_handle(mm_stream_t * my_obj)121 static 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 
mm_stream_handle_rcvd_buf(mm_stream_t * my_obj,mm_camera_buf_info_t * buf_info)142 void 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 
mm_stream_data_notify(void * user_data)196 static 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 */
mm_stream_buf_notify(mm_camera_super_buf_t * super_buf,void * user_data)247 static 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 
mm_stream_dispatch_app_data(mm_camera_cmdcb_t * cmd_cb,void * user_data)294 static 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 */
mm_stream_fsm_fn(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)346 int32_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 
mm_stream_fsm_inited(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)387 int32_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 
mm_stream_fsm_acquired(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)444 int32_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 
mm_stream_fsm_cfg(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)485 int32_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 
mm_stream_fsm_buffed(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)531 int32_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 
mm_stream_fsm_reg(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)568 int32_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 
mm_stream_fsm_active_stream_on(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)634 int32_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 
mm_stream_fsm_active_stream_off(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)670 int32_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 
mm_stream_config(mm_stream_t * my_obj,mm_camera_stream_config_t * config)705 int32_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 
mm_stream_release(mm_stream_t * my_obj)725 int32_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 
mm_stream_need_stream_on(mm_stream_t * my_obj)746 uint8_t mm_stream_need_stream_on(mm_stream_t *my_obj)
747 {
748     return my_obj->need_stream_on;
749 }
750 
mm_stream_streamon(mm_stream_t * my_obj)751 int32_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 
mm_stream_streamoff(mm_stream_t * my_obj)777 int32_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 
mm_stream_util_get_v4l2_fmt(cam_format_t fmt,uint8_t * num_planes)795 static 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 
mm_stream_read_msm_frame(mm_stream_t * my_obj,mm_camera_buf_info_t * buf_info)825 int32_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 
mm_stream_get_crop(mm_stream_t * my_obj,mm_camera_rect_t * crop)876 int32_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 
mm_stream_set_parm_acquire(mm_stream_t * my_obj,void * in_value)895 int32_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 }
mm_stream_get_parm_acquire(mm_stream_t * my_obj,void * out_value)915 int32_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 
mm_stream_set_parm_config(mm_stream_t * my_obj,void * in_value)941 int32_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 }
mm_stream_get_parm_config(mm_stream_t * my_obj,void * out_value)957 int32_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 
mm_stream_set_parm_start(mm_stream_t * my_obj,void * in_value)984 int32_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 }
mm_stream_get_parm_start(mm_stream_t * my_obj,void * out_value)1000 int32_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 }
mm_stream_set_ext_mode(mm_stream_t * my_obj)1026 int32_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 
mm_stream_qbuf(mm_stream_t * my_obj,mm_camera_buf_def_t * buf)1041 int32_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 */
mm_stream_request_buf(mm_stream_t * my_obj)1063 int32_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 
mm_stream_get_frame_len_offset(mm_camera_image_fmt_t * img_fmt,camera_mode_t mode,int image_type,mm_camera_frame_len_offset * frame_offset)1101 int32_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 
mm_stream_init_bufs(mm_stream_t * my_obj)1171 int32_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 
1249 error_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 
1267 error_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 */
mm_stream_deinit_bufs(mm_stream_t * my_obj)1285 int32_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 
mm_stream_reg_buf(mm_stream_t * my_obj)1330 int32_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 
mm_stream_unreg_buf(mm_stream_t * my_obj)1360 int32_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 
1388 end:
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 
mm_stream_set_fmt(mm_stream_t * my_obj)1402 int32_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 
mm_stream_get_offset(mm_stream_t * my_obj)1428 int32_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 
mm_stream_set_cid(mm_stream_t * my_obj,stream_cid_t * value)1477 int32_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 
mm_stream_get_cid(mm_stream_t * my_obj,stream_cid_t * out_value)1498 int32_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 
mm_stream_buf_done(mm_stream_t * my_obj,mm_camera_buf_def_t * frame)1505 int32_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 
mm_stream_reg_buf_cb(mm_stream_t * my_obj,mm_stream_data_cb_t * val)1546 int32_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