1 /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
2  *
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are
5  * met:
6  *     * Redistributions of source code must retain the above copyright
7  *       notice, this list of conditions and the following disclaimer.
8  *     * Redistributions in binary form must reproduce the above
9  *       copyright notice, this list of conditions and the following
10  *       disclaimer in the documentation and/or other materials provided
11  *       with the distribution.
12  *     * Neither the name of The Linux Foundation nor the names of its
13  *       contributors may be used to endorse or promote products derived
14  *       from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
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 <cam_semaphore.h>
39 #ifdef VENUS_PRESENT
40 #include <media/msm_media_info.h>
41 #endif
42 
43 #include "mm_camera_dbg.h"
44 #include "mm_camera_interface.h"
45 #include "mm_camera.h"
46 
47 /* internal function decalre */
48 int32_t mm_stream_qbuf(mm_stream_t *my_obj,
49                        mm_camera_buf_def_t *buf);
50 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj);
51 int32_t mm_stream_set_fmt(mm_stream_t * my_obj);
52 int32_t mm_stream_sync_info(mm_stream_t *my_obj);
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_set_parm(mm_stream_t *my_obj,
59                            cam_stream_parm_buffer_t *value);
60 int32_t mm_stream_get_parm(mm_stream_t *my_obj,
61                            cam_stream_parm_buffer_t *value);
62 int32_t mm_stream_do_action(mm_stream_t *my_obj,
63                             void *in_value);
64 int32_t mm_stream_streamon(mm_stream_t *my_obj);
65 int32_t mm_stream_streamoff(mm_stream_t *my_obj);
66 int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
67                                  mm_camera_buf_info_t* buf_info,
68                                  uint8_t num_planes);
69 int32_t mm_stream_config(mm_stream_t *my_obj,
70                          mm_camera_stream_config_t *config);
71 int32_t mm_stream_reg_buf(mm_stream_t * my_obj);
72 int32_t mm_stream_buf_done(mm_stream_t * my_obj,
73                            mm_camera_buf_def_t *frame);
74 int32_t mm_stream_calc_offset(mm_stream_t *my_obj);
75 
76 /* state machine function declare */
77 int32_t mm_stream_fsm_inited(mm_stream_t * my_obj,
78                              mm_stream_evt_type_t evt,
79                              void * in_val,
80                              void * out_val);
81 int32_t mm_stream_fsm_acquired(mm_stream_t * my_obj,
82                                mm_stream_evt_type_t evt,
83                                void * in_val,
84                                void * out_val);
85 int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
86                           mm_stream_evt_type_t evt,
87                           void * in_val,
88                           void * out_val);
89 int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
90                              mm_stream_evt_type_t evt,
91                              void * in_val,
92                              void * out_val);
93 int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
94                           mm_stream_evt_type_t evt,
95                           void * in_val,
96                           void * out_val);
97 int32_t mm_stream_fsm_active(mm_stream_t * my_obj,
98                              mm_stream_evt_type_t evt,
99                              void * in_val,
100                              void * out_val);
101 uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt);
102 
103 
104 /*===========================================================================
105  * FUNCTION   : mm_stream_handle_rcvd_buf
106  *
107  * DESCRIPTION: function to handle newly received stream buffer
108  *
109  * PARAMETERS :
110  *   @cam_obj : stream object
111  *   @buf_info: ptr to struct storing buffer information
112  *
113  * RETURN     : none
114  *==========================================================================*/
mm_stream_handle_rcvd_buf(mm_stream_t * my_obj,mm_camera_buf_info_t * buf_info,uint8_t has_cb)115 void mm_stream_handle_rcvd_buf(mm_stream_t *my_obj,
116                                mm_camera_buf_info_t *buf_info,
117                                uint8_t has_cb)
118 {
119     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
120          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
121 
122     /* enqueue to super buf thread */
123     if (my_obj->is_bundled) {
124         mm_camera_cmdcb_t* node = NULL;
125 
126         /* send cam_sem_post to wake up channel cmd thread to enqueue to super buffer */
127         node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
128         if (NULL != node) {
129             memset(node, 0, sizeof(mm_camera_cmdcb_t));
130             node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
131             node->u.buf = *buf_info;
132 
133             /* enqueue to cmd thread */
134             cam_queue_enq(&(my_obj->ch_obj->cmd_thread.cmd_queue), node);
135 
136             /* wake up cmd thread */
137             cam_sem_post(&(my_obj->ch_obj->cmd_thread.cmd_sem));
138         } else {
139             CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
140         }
141     }
142 
143     if(has_cb) {
144         mm_camera_cmdcb_t* node = NULL;
145 
146         /* send cam_sem_post to wake up cmd thread to dispatch dataCB */
147         node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
148         if (NULL != node) {
149             memset(node, 0, sizeof(mm_camera_cmdcb_t));
150             node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
151             node->u.buf = *buf_info;
152 
153             /* enqueue to cmd thread */
154             cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
155 
156             /* wake up cmd thread */
157             cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
158         } else {
159             CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
160         }
161     }
162 }
163 
164 /*===========================================================================
165  * FUNCTION   : mm_stream_data_notify
166  *
167  * DESCRIPTION: callback to handle data notify from kernel
168  *
169  * PARAMETERS :
170  *   @user_data : user data ptr (stream object)
171  *
172  * RETURN     : none
173  *==========================================================================*/
mm_stream_data_notify(void * user_data)174 static void mm_stream_data_notify(void* user_data)
175 {
176     mm_stream_t *my_obj = (mm_stream_t*)user_data;
177     int32_t idx = -1, i, rc;
178     uint8_t has_cb = 0;
179     mm_camera_buf_info_t buf_info;
180 
181     if (NULL == my_obj) {
182         return;
183     }
184 
185     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
186          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
187     if (MM_STREAM_STATE_ACTIVE != my_obj->state) {
188         /* this Cb will only received in active_stream_on state
189          * if not so, return here */
190         CDBG_ERROR("%s: ERROR!! Wrong state (%d) to receive data notify!",
191                    __func__, my_obj->state);
192         return;
193     }
194 
195     memset(&buf_info, 0, sizeof(mm_camera_buf_info_t));
196     rc = mm_stream_read_msm_frame(my_obj, &buf_info, my_obj->frame_offset.num_planes);
197     if (rc != 0) {
198         return;
199     }
200     idx = buf_info.buf->buf_idx;
201 
202     pthread_mutex_lock(&my_obj->cb_lock);
203     for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
204         if(NULL != my_obj->buf_cb[i].cb) {
205             /* for every CB, add ref count */
206             has_cb = 1;
207             break;
208         }
209     }
210     pthread_mutex_unlock(&my_obj->cb_lock);
211 
212     pthread_mutex_lock(&my_obj->buf_lock);
213     /* update buffer location */
214     my_obj->buf_status[idx].in_kernel = 0;
215 
216     /* update buf ref count */
217     if (my_obj->is_bundled) {
218         /* need to add into super buf since bundled, add ref count */
219         my_obj->buf_status[idx].buf_refcnt++;
220     }
221     my_obj->buf_status[idx].buf_refcnt += has_cb;
222     pthread_mutex_unlock(&my_obj->buf_lock);
223 
224     mm_stream_handle_rcvd_buf(my_obj, &buf_info, has_cb);
225 }
226 
227 /*===========================================================================
228  * FUNCTION   : mm_stream_dispatch_app_data
229  *
230  * DESCRIPTION: dispatch stream buffer to registered users
231  *
232  * PARAMETERS :
233  *   @cmd_cb  : ptr storing stream buffer information
234  *   @userdata: user data ptr (stream object)
235  *
236  * RETURN     : none
237  *==========================================================================*/
mm_stream_dispatch_app_data(mm_camera_cmdcb_t * cmd_cb,void * user_data)238 static void mm_stream_dispatch_app_data(mm_camera_cmdcb_t *cmd_cb,
239                                         void* user_data)
240 {
241     int i;
242     mm_stream_t * my_obj = (mm_stream_t *)user_data;
243     mm_camera_buf_info_t* buf_info = NULL;
244     mm_camera_super_buf_t super_buf;
245     mm_camera_cmd_thread_name("mm_cam_stream");
246 
247     if (NULL == my_obj) {
248         return;
249     }
250     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
251          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
252 
253     if (MM_CAMERA_CMD_TYPE_DATA_CB != cmd_cb->cmd_type) {
254         CDBG_ERROR("%s: Wrong cmd_type (%d) for dataCB",
255                    __func__, cmd_cb->cmd_type);
256         return;
257     }
258 
259     buf_info = &cmd_cb->u.buf;
260     memset(&super_buf, 0, sizeof(mm_camera_super_buf_t));
261     super_buf.num_bufs = 1;
262     super_buf.bufs[0] = buf_info->buf;
263     super_buf.camera_handle = my_obj->ch_obj->cam_obj->my_hdl;
264     super_buf.ch_id = my_obj->ch_obj->my_hdl;
265 
266     pthread_mutex_lock(&my_obj->cb_lock);
267     for(i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
268         if(NULL != my_obj->buf_cb[i].cb) {
269             if (my_obj->buf_cb[i].cb_count != 0) {
270                 /* if <0, means infinite CB
271                  * if >0, means CB for certain times
272                  * both case we need to call CB */
273 
274                 /* increase buf ref cnt */
275                 pthread_mutex_lock(&my_obj->buf_lock);
276                 my_obj->buf_status[buf_info->buf->buf_idx].buf_refcnt++;
277                 pthread_mutex_unlock(&my_obj->buf_lock);
278 
279                 /* callback */
280                 my_obj->buf_cb[i].cb(&super_buf,
281                                      my_obj->buf_cb[i].user_data);
282             }
283 
284             /* if >0, reduce count by 1 every time we called CB until reaches 0
285              * when count reach 0, reset the buf_cb to have no CB */
286             if (my_obj->buf_cb[i].cb_count > 0) {
287                 my_obj->buf_cb[i].cb_count--;
288                 if (0 == my_obj->buf_cb[i].cb_count) {
289                     my_obj->buf_cb[i].cb = NULL;
290                     my_obj->buf_cb[i].user_data = NULL;
291                 }
292             }
293         }
294     }
295     pthread_mutex_unlock(&my_obj->cb_lock);
296 
297     /* do buf_done since we increased refcnt by one when has_cb */
298     mm_stream_buf_done(my_obj, buf_info->buf);
299 }
300 
301 /*===========================================================================
302  * FUNCTION   : mm_stream_fsm_fn
303  *
304  * DESCRIPTION: stream finite state machine entry function. Depends on stream
305  *              state, incoming event will be handled differently.
306  *
307  * PARAMETERS :
308  *   @my_obj   : ptr to a stream object
309  *   @evt      : stream event to be processed
310  *   @in_val   : input event payload. Can be NULL if not needed.
311  *   @out_val  : output payload, Can be NULL if not needed.
312  *
313  * RETURN     : int32_t type of status
314  *              0  -- success
315  *              -1 -- failure
316  *==========================================================================*/
mm_stream_fsm_fn(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)317 int32_t mm_stream_fsm_fn(mm_stream_t *my_obj,
318                          mm_stream_evt_type_t evt,
319                          void * in_val,
320                          void * out_val)
321 {
322     int32_t rc = -1;
323 
324     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
325          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
326     switch (my_obj->state) {
327     case MM_STREAM_STATE_NOTUSED:
328         CDBG("%s: Not handling evt in unused state", __func__);
329         break;
330     case MM_STREAM_STATE_INITED:
331         rc = mm_stream_fsm_inited(my_obj, evt, in_val, out_val);
332         break;
333     case MM_STREAM_STATE_ACQUIRED:
334         rc = mm_stream_fsm_acquired(my_obj, evt, in_val, out_val);
335         break;
336     case MM_STREAM_STATE_CFG:
337         rc = mm_stream_fsm_cfg(my_obj, evt, in_val, out_val);
338         break;
339     case MM_STREAM_STATE_BUFFED:
340         rc = mm_stream_fsm_buffed(my_obj, evt, in_val, out_val);
341         break;
342     case MM_STREAM_STATE_REG:
343         rc = mm_stream_fsm_reg(my_obj, evt, in_val, out_val);
344         break;
345     case MM_STREAM_STATE_ACTIVE:
346         rc = mm_stream_fsm_active(my_obj, evt, in_val, out_val);
347         break;
348     default:
349         CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
350         break;
351     }
352     CDBG("%s : X rc =%d",__func__,rc);
353     return rc;
354 }
355 
356 /*===========================================================================
357  * FUNCTION   : mm_stream_fsm_inited
358  *
359  * DESCRIPTION: stream finite state machine function to handle event in INITED
360  *              state.
361  *
362  * PARAMETERS :
363  *   @my_obj   : ptr to a stream object
364  *   @evt      : stream event to be processed
365  *   @in_val   : input event payload. Can be NULL if not needed.
366  *   @out_val  : output payload, Can be NULL if not needed.
367  *
368  * RETURN     : int32_t type of status
369  *              0  -- success
370  *              -1 -- failure
371  *==========================================================================*/
mm_stream_fsm_inited(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)372 int32_t mm_stream_fsm_inited(mm_stream_t *my_obj,
373                              mm_stream_evt_type_t evt,
374                              void * in_val,
375                              void * out_val)
376 {
377     int32_t rc = 0;
378     char dev_name[MM_CAMERA_DEV_NAME_LEN];
379 
380     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
381          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
382     switch(evt) {
383     case MM_STREAM_EVT_ACQUIRE:
384         if ((NULL == my_obj->ch_obj) || (NULL == my_obj->ch_obj->cam_obj)) {
385             CDBG_ERROR("%s: NULL channel or camera obj\n", __func__);
386             rc = -1;
387             break;
388         }
389 
390         snprintf(dev_name, sizeof(dev_name), "/dev/%s",
391                  mm_camera_util_get_dev_name(my_obj->ch_obj->cam_obj->my_hdl));
392 
393         my_obj->fd = open(dev_name, O_RDWR | O_NONBLOCK);
394         if (my_obj->fd < 0) {
395             CDBG_ERROR("%s: open dev returned %d\n", __func__, my_obj->fd);
396             rc = -1;
397             break;
398         }
399         CDBG("%s: open dev fd = %d\n", __func__, my_obj->fd);
400         rc = mm_stream_set_ext_mode(my_obj);
401         if (0 == rc) {
402             my_obj->state = MM_STREAM_STATE_ACQUIRED;
403         } else {
404             /* failed setting ext_mode
405              * close fd */
406             close(my_obj->fd);
407             my_obj->fd = -1;
408             break;
409         }
410         break;
411     default:
412         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
413                    __func__, my_obj->state, evt, in_val, out_val);
414         break;
415     }
416     return rc;
417 }
418 
419 /*===========================================================================
420  * FUNCTION   : mm_stream_fsm_acquired
421  *
422  * DESCRIPTION: stream finite state machine function to handle event in AQUIRED
423  *              state.
424  *
425  * PARAMETERS :
426  *   @my_obj   : ptr to a stream object
427  *   @evt      : stream event to be processed
428  *   @in_val   : input event payload. Can be NULL if not needed.
429  *   @out_val  : output payload, Can be NULL if not needed.
430  *
431  * RETURN     : int32_t type of status
432  *              0  -- success
433  *              -1 -- failure
434  *==========================================================================*/
mm_stream_fsm_acquired(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)435 int32_t mm_stream_fsm_acquired(mm_stream_t *my_obj,
436                                mm_stream_evt_type_t evt,
437                                void * in_val,
438                                void * out_val)
439 {
440     int32_t rc = 0;
441 
442     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
443          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
444     switch(evt) {
445     case MM_STREAM_EVT_SET_FMT:
446         {
447             mm_camera_stream_config_t *config =
448                 (mm_camera_stream_config_t *)in_val;
449 
450             rc = mm_stream_config(my_obj, config);
451 
452             /* change state to configed */
453             my_obj->state = MM_STREAM_STATE_CFG;
454 
455             break;
456         }
457     case MM_STREAM_EVT_RELEASE:
458         rc = mm_stream_release(my_obj);
459         /* change state to not used */
460          my_obj->state = MM_STREAM_STATE_NOTUSED;
461         break;
462     case MM_STREAM_EVT_SET_PARM:
463         {
464             mm_evt_paylod_set_get_stream_parms_t *payload =
465                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
466             rc = mm_stream_set_parm(my_obj, payload->parms);
467         }
468         break;
469     case MM_STREAM_EVT_GET_PARM:
470         {
471             mm_evt_paylod_set_get_stream_parms_t *payload =
472                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
473             rc = mm_stream_get_parm(my_obj, payload->parms);
474         }
475         break;
476     default:
477         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
478                    __func__, my_obj->state, evt, in_val, out_val);
479     }
480     CDBG("%s :X rc = %d", __func__, rc);
481     return rc;
482 }
483 
484 /*===========================================================================
485  * FUNCTION   : mm_stream_fsm_cfg
486  *
487  * DESCRIPTION: stream finite state machine function to handle event in CONFIGURED
488  *              state.
489  *
490  * PARAMETERS :
491  *   @my_obj   : ptr to a stream object
492  *   @evt      : stream event to be processed
493  *   @in_val   : input event payload. Can be NULL if not needed.
494  *   @out_val  : output payload, Can be NULL if not needed.
495  *
496  * RETURN     : int32_t type of status
497  *              0  -- success
498  *              -1 -- failure
499  *==========================================================================*/
mm_stream_fsm_cfg(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)500 int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
501                           mm_stream_evt_type_t evt,
502                           void * in_val,
503                           void * out_val)
504 {
505     int32_t rc = 0;
506     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
507          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
508     switch(evt) {
509     case MM_STREAM_EVT_SET_FMT:
510         {
511             mm_camera_stream_config_t *config =
512                 (mm_camera_stream_config_t *)in_val;
513 
514             rc = mm_stream_config(my_obj, config);
515 
516             /* change state to configed */
517             my_obj->state = MM_STREAM_STATE_CFG;
518 
519             break;
520         }
521     case MM_STREAM_EVT_RELEASE:
522         rc = mm_stream_release(my_obj);
523         my_obj->state = MM_STREAM_STATE_NOTUSED;
524         break;
525     case MM_STREAM_EVT_SET_PARM:
526         {
527             mm_evt_paylod_set_get_stream_parms_t *payload =
528                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
529             rc = mm_stream_set_parm(my_obj, payload->parms);
530         }
531         break;
532     case MM_STREAM_EVT_GET_PARM:
533         {
534             mm_evt_paylod_set_get_stream_parms_t *payload =
535                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
536             rc = mm_stream_get_parm(my_obj, payload->parms);
537         }
538         break;
539     case MM_STREAM_EVT_GET_BUF:
540         rc = mm_stream_init_bufs(my_obj);
541         /* change state to buff allocated */
542         if(0 == rc) {
543             my_obj->state = MM_STREAM_STATE_BUFFED;
544         }
545         break;
546     default:
547         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
548                    __func__, my_obj->state, evt, in_val, out_val);
549     }
550     CDBG("%s :X rc = %d", __func__, rc);
551     return rc;
552 }
553 
554 /*===========================================================================
555  * FUNCTION   : mm_stream_fsm_buffed
556  *
557  * DESCRIPTION: stream finite state machine function to handle event in BUFFED
558  *              state.
559  *
560  * PARAMETERS :
561  *   @my_obj   : ptr to a stream object
562  *   @evt      : stream event to be processed
563  *   @in_val   : input event payload. Can be NULL if not needed.
564  *   @out_val  : output payload, Can be NULL if not needed.
565  *
566  * RETURN     : int32_t type of status
567  *              0  -- success
568  *              -1 -- failure
569  *==========================================================================*/
mm_stream_fsm_buffed(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)570 int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
571                              mm_stream_evt_type_t evt,
572                              void * in_val,
573                              void * out_val)
574 {
575     int32_t rc = 0;
576     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
577          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
578     switch(evt) {
579     case MM_STREAM_EVT_PUT_BUF:
580         rc = mm_stream_deinit_bufs(my_obj);
581         /* change state to configed */
582         if(0 == rc) {
583             my_obj->state = MM_STREAM_STATE_CFG;
584         }
585         break;
586     case MM_STREAM_EVT_REG_BUF:
587         rc = mm_stream_reg_buf(my_obj);
588         /* change state to regged */
589         if(0 == rc) {
590             my_obj->state = MM_STREAM_STATE_REG;
591         }
592         break;
593     case MM_STREAM_EVT_SET_PARM:
594         {
595             mm_evt_paylod_set_get_stream_parms_t *payload =
596                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
597             rc = mm_stream_set_parm(my_obj, payload->parms);
598         }
599         break;
600     case MM_STREAM_EVT_GET_PARM:
601         {
602             mm_evt_paylod_set_get_stream_parms_t *payload =
603                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
604             rc = mm_stream_get_parm(my_obj, payload->parms);
605         }
606         break;
607     default:
608         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
609                    __func__, my_obj->state, evt, in_val, out_val);
610     }
611     CDBG("%s :X rc = %d", __func__, rc);
612     return rc;
613 }
614 
615 /*===========================================================================
616  * FUNCTION   : mm_stream_fsm_reg
617  *
618  * DESCRIPTION: stream finite state machine function to handle event in REGGED
619  *              state.
620  *
621  * PARAMETERS :
622  *   @my_obj   : ptr to a stream object
623  *   @evt      : stream event to be processed
624  *   @in_val   : input event payload. Can be NULL if not needed.
625  *   @out_val  : output payload, Can be NULL if not needed.
626  *
627  * RETURN     : int32_t type of status
628  *              0  -- success
629  *              -1 -- failure
630  *==========================================================================*/
mm_stream_fsm_reg(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)631 int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
632                           mm_stream_evt_type_t evt,
633                           void * in_val,
634                           void * out_val)
635 {
636     int32_t rc = 0;
637     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
638          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
639 
640     switch(evt) {
641     case MM_STREAM_EVT_UNREG_BUF:
642         rc = mm_stream_unreg_buf(my_obj);
643 
644         /* change state to buffed */
645         my_obj->state = MM_STREAM_STATE_BUFFED;
646         break;
647     case MM_STREAM_EVT_START:
648         {
649             uint8_t has_cb = 0;
650             uint8_t i;
651             /* launch cmd thread if CB is not null */
652             pthread_mutex_lock(&my_obj->cb_lock);
653             for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
654                 if(NULL != my_obj->buf_cb[i].cb) {
655                     has_cb = 1;
656                     break;
657                 }
658             }
659             pthread_mutex_unlock(&my_obj->cb_lock);
660 
661             if (has_cb) {
662                 mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
663                                             mm_stream_dispatch_app_data,
664                                             (void *)my_obj);
665             }
666 
667             my_obj->state = MM_STREAM_STATE_ACTIVE;
668             rc = mm_stream_streamon(my_obj);
669             if (0 != rc) {
670                 /* failed stream on, need to release cmd thread if it's launched */
671                 if (has_cb) {
672                     mm_camera_cmd_thread_release(&my_obj->cmd_thread);
673                 }
674                 my_obj->state = MM_STREAM_STATE_REG;
675                 break;
676             }
677         }
678         break;
679     case MM_STREAM_EVT_SET_PARM:
680         {
681             mm_evt_paylod_set_get_stream_parms_t *payload =
682                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
683             rc = mm_stream_set_parm(my_obj, payload->parms);
684         }
685         break;
686     case MM_STREAM_EVT_GET_PARM:
687         {
688             mm_evt_paylod_set_get_stream_parms_t *payload =
689                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
690             rc = mm_stream_get_parm(my_obj, payload->parms);
691         }
692         break;
693     default:
694         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
695                    __func__, my_obj->state, evt, in_val, out_val);
696     }
697     CDBG("%s :X rc = %d", __func__, rc);
698     return rc;
699 }
700 
701 /*===========================================================================
702  * FUNCTION   : mm_stream_fsm_active
703  *
704  * DESCRIPTION: stream finite state machine function to handle event in ACTIVE
705  *              state.
706  *
707  * PARAMETERS :
708  *   @my_obj   : ptr to a stream object
709  *   @evt      : stream event to be processed
710  *   @in_val   : input event payload. Can be NULL if not needed.
711  *   @out_val  : output payload, Can be NULL if not needed.
712  *
713  * RETURN     : int32_t type of status
714  *              0  -- success
715  *              -1 -- failure
716  *==========================================================================*/
mm_stream_fsm_active(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)717 int32_t mm_stream_fsm_active(mm_stream_t * my_obj,
718                              mm_stream_evt_type_t evt,
719                              void * in_val,
720                              void * out_val)
721 {
722     int32_t rc = 0;
723     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
724          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
725     switch(evt) {
726     case MM_STREAM_EVT_QBUF:
727         rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val);
728         break;
729     case MM_STREAM_EVT_STOP:
730         {
731             uint8_t has_cb = 0;
732             uint8_t i;
733             rc = mm_stream_streamoff(my_obj);
734 
735             pthread_mutex_lock(&my_obj->cb_lock);
736             for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
737                 if(NULL != my_obj->buf_cb[i].cb) {
738                     has_cb = 1;
739                     break;
740                 }
741             }
742             pthread_mutex_unlock(&my_obj->cb_lock);
743 
744             if (has_cb) {
745                 mm_camera_cmd_thread_release(&my_obj->cmd_thread);
746             }
747             my_obj->state = MM_STREAM_STATE_REG;
748         }
749         break;
750     case MM_STREAM_EVT_SET_PARM:
751         {
752             mm_evt_paylod_set_get_stream_parms_t *payload =
753                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
754             rc = mm_stream_set_parm(my_obj, payload->parms);
755         }
756         break;
757     case MM_STREAM_EVT_GET_PARM:
758         {
759             mm_evt_paylod_set_get_stream_parms_t *payload =
760                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
761             rc = mm_stream_get_parm(my_obj, payload->parms);
762         }
763         break;
764     case MM_STREAM_EVT_DO_ACTION:
765         rc = mm_stream_do_action(my_obj, in_val);
766         break;
767     default:
768         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
769                    __func__, my_obj->state, evt, in_val, out_val);
770     }
771     CDBG("%s :X rc = %d", __func__, rc);
772     return rc;
773 }
774 
775 /*===========================================================================
776  * FUNCTION   : mm_stream_config
777  *
778  * DESCRIPTION: configure a stream
779  *
780  * PARAMETERS :
781  *   @my_obj       : stream object
782  *   @config       : stream configuration
783  *
784  * RETURN     : int32_t type of status
785  *              0  -- success
786  *              -1 -- failure
787  *==========================================================================*/
mm_stream_config(mm_stream_t * my_obj,mm_camera_stream_config_t * config)788 int32_t mm_stream_config(mm_stream_t *my_obj,
789                          mm_camera_stream_config_t *config)
790 {
791     int32_t rc = 0;
792     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
793          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
794     my_obj->stream_info = config->stream_info;
795     my_obj->buf_num = 0;
796     my_obj->mem_vtbl = config->mem_vtbl;
797     my_obj->padding_info = config->padding_info;
798     /* cd through intf always palced at idx 0 of buf_cb */
799     my_obj->buf_cb[0].cb = config->stream_cb;
800     my_obj->buf_cb[0].user_data = config->userdata;
801     my_obj->buf_cb[0].cb_count = -1; /* infinite by default */
802 
803     rc = mm_stream_sync_info(my_obj);
804     if (rc == 0) {
805         rc = mm_stream_set_fmt(my_obj);
806     }
807     return rc;
808 }
809 
810 /*===========================================================================
811  * FUNCTION   : mm_stream_release
812  *
813  * DESCRIPTION: release a stream resource
814  *
815  * PARAMETERS :
816  *   @my_obj       : stream object
817  *
818  * RETURN     : int32_t type of status
819  *              0  -- success
820  *              -1 -- failure
821  *==========================================================================*/
mm_stream_release(mm_stream_t * my_obj)822 int32_t mm_stream_release(mm_stream_t *my_obj)
823 {
824     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
825          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
826 
827     /* close fd */
828     if(my_obj->fd >= 0)
829     {
830         close(my_obj->fd);
831     }
832 
833     /* destroy mutex */
834     pthread_mutex_destroy(&my_obj->buf_lock);
835     pthread_mutex_destroy(&my_obj->cb_lock);
836 
837     /* reset stream obj */
838     memset(my_obj, 0, sizeof(mm_stream_t));
839     my_obj->fd = -1;
840 
841     return 0;
842 }
843 
844 /*===========================================================================
845  * FUNCTION   : mm_stream_streamon
846  *
847  * DESCRIPTION: stream on a stream. sending v4l2 request to kernel
848  *
849  * PARAMETERS :
850  *   @my_obj       : stream object
851  *
852  * RETURN     : int32_t type of status
853  *              0  -- success
854  *              -1 -- failure
855  *==========================================================================*/
mm_stream_streamon(mm_stream_t * my_obj)856 int32_t mm_stream_streamon(mm_stream_t *my_obj)
857 {
858     int32_t rc;
859     enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
860 
861     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
862          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
863 
864     rc = ioctl(my_obj->fd, VIDIOC_STREAMON, &buf_type);
865     if (rc < 0) {
866         CDBG_ERROR("%s: ioctl VIDIOC_STREAMON failed: rc=%d\n",
867                    __func__, rc);
868         /* remove fd from data poll thread in case of failure */
869         mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl, mm_camera_sync_call);
870     }
871     CDBG("%s :X rc = %d",__func__,rc);
872     return rc;
873 }
874 
875 /*===========================================================================
876  * FUNCTION   : mm_stream_streamoff
877  *
878  * DESCRIPTION: stream off a stream. sending v4l2 request to kernel
879  *
880  * PARAMETERS :
881  *   @my_obj       : stream object
882  *
883  * RETURN     : int32_t type of status
884  *              0  -- success
885  *              -1 -- failure
886  *==========================================================================*/
mm_stream_streamoff(mm_stream_t * my_obj)887 int32_t mm_stream_streamoff(mm_stream_t *my_obj)
888 {
889     int32_t rc;
890     enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
891     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
892          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
893 
894     /* step1: remove fd from data poll thread */
895     rc = mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
896             my_obj->my_hdl, mm_camera_sync_call);
897     if (rc < 0) {
898         /* The error might be due to async update. In this case
899          * wait for all updates to complete before proceeding. */
900         rc = mm_camera_poll_thread_commit_updates(&my_obj->ch_obj->poll_thread[0]);
901         if (rc < 0) {
902             CDBG_ERROR("%s: Poll sync failed %d",
903                  __func__, rc);
904         }
905     }
906 
907     /* step2: stream off */
908     rc = ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type);
909     if (rc < 0) {
910         CDBG_ERROR("%s: STREAMOFF failed: %s\n",
911                 __func__, strerror(errno));
912     }
913     CDBG("%s :X rc = %d",__func__,rc);
914     return rc;
915 }
916 
917 /*===========================================================================
918  * FUNCTION   : mm_stream_read_msm_frame
919  *
920  * DESCRIPTION: dequeue a stream buffer from kernel queue
921  *
922  * PARAMETERS :
923  *   @my_obj       : stream object
924  *   @buf_info     : ptr to a struct storing buffer information
925  *   @num_planes   : number of planes in the buffer
926  *
927  * RETURN     : int32_t type of status
928  *              0  -- success
929  *              -1 -- failure
930  *==========================================================================*/
mm_stream_read_msm_frame(mm_stream_t * my_obj,mm_camera_buf_info_t * buf_info,uint8_t num_planes)931 int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
932                                  mm_camera_buf_info_t* buf_info,
933                                  uint8_t num_planes)
934 {
935     int32_t rc = 0;
936     struct v4l2_buffer vb;
937     struct v4l2_plane planes[VIDEO_MAX_PLANES];
938     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
939          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
940 
941     memset(&vb,  0,  sizeof(vb));
942     vb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
943     vb.memory = V4L2_MEMORY_USERPTR;
944     vb.m.planes = &planes[0];
945     vb.length = num_planes;
946 
947     rc = ioctl(my_obj->fd, VIDIOC_DQBUF, &vb);
948     if (rc < 0) {
949         CDBG_ERROR("%s: VIDIOC_DQBUF ioctl call failed (rc=%d)\n",
950                    __func__, rc);
951     } else {
952         pthread_mutex_lock(&my_obj->buf_lock);
953         my_obj->queued_buffer_count--;
954         if(my_obj->queued_buffer_count == 0) {
955             CDBG_HIGH("%s: Stoping poll on stream %p type :%d", __func__, my_obj, my_obj->stream_info->stream_type);
956             mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl, mm_camera_async_call);
957             CDBG_HIGH("%s: Stopped poll on stream %p type :%d", __func__, my_obj, my_obj->stream_info->stream_type);
958         }
959         pthread_mutex_unlock(&my_obj->buf_lock);
960         int8_t idx = vb.index;
961         buf_info->buf = &my_obj->buf[idx];
962         buf_info->frame_idx = vb.sequence;
963         buf_info->stream_id = my_obj->my_hdl;
964 
965         buf_info->buf->stream_id = my_obj->my_hdl;
966         buf_info->buf->buf_idx = idx;
967         buf_info->buf->frame_idx = vb.sequence;
968         buf_info->buf->ts.tv_sec  = vb.timestamp.tv_sec;
969         buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000;
970         CDBG("%s: VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d\n",
971              __func__, vb.index, buf_info->buf->frame_idx, my_obj->stream_info->stream_type);
972         if ( NULL != my_obj->mem_vtbl.clean_invalidate_buf ) {
973             rc = my_obj->mem_vtbl.clean_invalidate_buf(idx,
974                                                        my_obj->mem_vtbl.user_data);
975             if ( 0 > rc ) {
976                 CDBG_ERROR("%s: Clean invalidate cache failed on buffer index: %d",
977                            __func__,
978                            idx);
979                 return rc;
980             }
981         } else {
982             CDBG_ERROR(" %s : Clean invalidate cache op not supported\n", __func__);
983         }
984     }
985 
986     CDBG("%s :X rc = %d",__func__,rc);
987     return rc;
988 }
989 
990 /*===========================================================================
991  * FUNCTION   : mm_stream_set_parms
992  *
993  * DESCRIPTION: set parameters per stream
994  *
995  * PARAMETERS :
996  *   @my_obj       : stream object
997  *   @in_value     : ptr to a param struct to be set to server
998  *
999  * RETURN     : int32_t type of status
1000  *              0  -- success
1001  *              -1 -- failure
1002  * NOTE       : Assume the parms struct buf is already mapped to server via
1003  *              domain socket. Corresponding fields of parameters to be set
1004  *              are already filled in by upper layer caller.
1005  *==========================================================================*/
mm_stream_set_parm(mm_stream_t * my_obj,cam_stream_parm_buffer_t * in_value)1006 int32_t mm_stream_set_parm(mm_stream_t *my_obj,
1007                            cam_stream_parm_buffer_t *in_value)
1008 {
1009     int32_t rc = -1;
1010     int32_t value = 0;
1011     if (in_value != NULL) {
1012         rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
1013     }
1014     return rc;
1015 }
1016 
1017 /*===========================================================================
1018  * FUNCTION   : mm_stream_get_parms
1019  *
1020  * DESCRIPTION: get parameters per stream
1021  *
1022  * PARAMETERS :
1023  *   @my_obj       : stream object
1024  *   @in_value     : ptr to a param struct to be get from server
1025  *
1026  * RETURN     : int32_t type of status
1027  *              0  -- success
1028  *              -1 -- failure
1029  * NOTE       : Assume the parms struct buf is already mapped to server via
1030  *              domain socket. Corresponding fields of parameters to be get
1031  *              are already filled in by upper layer caller.
1032  *==========================================================================*/
mm_stream_get_parm(mm_stream_t * my_obj,cam_stream_parm_buffer_t * in_value)1033 int32_t mm_stream_get_parm(mm_stream_t *my_obj,
1034                            cam_stream_parm_buffer_t *in_value)
1035 {
1036     int32_t rc = -1;
1037     int32_t value = 0;
1038     if (in_value != NULL) {
1039         rc = mm_camera_util_g_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
1040     }
1041     return rc;
1042 }
1043 
1044 /*===========================================================================
1045  * FUNCTION   : mm_stream_do_actions
1046  *
1047  * DESCRIPTION: request server to perform stream based actions
1048  *
1049  * PARAMETERS :
1050  *   @my_obj       : stream object
1051  *   @in_value     : ptr to a struct of actions to be performed by the server
1052  *
1053  * RETURN     : int32_t type of status
1054  *              0  -- success
1055  *              -1 -- failure
1056  * NOTE       : Assume the action struct buf is already mapped to server via
1057  *              domain socket. Corresponding fields of actions to be performed
1058  *              are already filled in by upper layer caller.
1059  *==========================================================================*/
mm_stream_do_action(mm_stream_t * my_obj,void * in_value)1060 int32_t mm_stream_do_action(mm_stream_t *my_obj,
1061                             void *in_value)
1062 {
1063     int32_t rc = -1;
1064     int32_t value = 0;
1065     if (in_value != NULL) {
1066         rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
1067     }
1068     return rc;
1069 }
1070 
1071 /*===========================================================================
1072  * FUNCTION   : mm_stream_set_ext_mode
1073  *
1074  * DESCRIPTION: set stream extended mode to server via v4l2 ioctl
1075  *
1076  * PARAMETERS :
1077  *   @my_obj       : stream object
1078  *
1079  * RETURN     : int32_t type of status
1080  *              0  -- success
1081  *              -1 -- failure
1082  * NOTE       : Server will return a server stream id that uniquely identify
1083  *              this stream on server side. Later on communication to server
1084  *              per stream should use this server stream id.
1085  *==========================================================================*/
mm_stream_set_ext_mode(mm_stream_t * my_obj)1086 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj)
1087 {
1088     int32_t rc = 0;
1089     struct v4l2_streamparm s_parm;
1090     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1091          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1092 
1093     memset(&s_parm, 0, sizeof(s_parm));
1094     s_parm.type =  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1095 
1096     rc = ioctl(my_obj->fd, VIDIOC_S_PARM, &s_parm);
1097     CDBG("%s:stream fd=%d, rc=%d, extended_mode=%d\n",
1098          __func__, my_obj->fd, rc, s_parm.parm.capture.extendedmode);
1099     if (rc == 0) {
1100         /* get server stream id */
1101         my_obj->server_stream_id = s_parm.parm.capture.extendedmode;
1102     }
1103     return rc;
1104 }
1105 
1106 /*===========================================================================
1107  * FUNCTION   : mm_stream_qbuf
1108  *
1109  * DESCRIPTION: enqueue buffer back to kernel queue for furture use
1110  *
1111  * PARAMETERS :
1112  *   @my_obj       : stream object
1113  *   @buf          : ptr to a struct storing buffer information
1114  *
1115  * RETURN     : int32_t type of status
1116  *              0  -- success
1117  *              -1 -- failure
1118  *==========================================================================*/
mm_stream_qbuf(mm_stream_t * my_obj,mm_camera_buf_def_t * buf)1119 int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf)
1120 {
1121     int32_t rc = 0;
1122     struct v4l2_buffer buffer;
1123     struct v4l2_plane planes[VIDEO_MAX_PLANES];
1124     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1125          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1126 
1127     memcpy(planes, buf->planes, sizeof(planes));
1128     memset(&buffer, 0, sizeof(buffer));
1129     buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1130     buffer.memory = V4L2_MEMORY_USERPTR;
1131     buffer.index = buf->buf_idx;
1132     buffer.m.planes = &planes[0];
1133     buffer.length = buf->num_planes;
1134 
1135     CDBG("%s:plane 0: stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d, offset = %d, data_offset = %d\n", __func__,
1136          buf->stream_id, buf->fd, buffer.index, buffer.length, buf->planes[0].reserved[0], buf->planes[0].data_offset);
1137     CDBG("%s:plane 1: stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d, offset = %d, data_offset = %d\n", __func__,
1138          buf->stream_id, buf->fd, buffer.index, buffer.length, buf->planes[1].reserved[0], buf->planes[1].data_offset);
1139 
1140     if ( NULL != my_obj->mem_vtbl.invalidate_buf ) {
1141         rc = my_obj->mem_vtbl.invalidate_buf(buffer.index,
1142                                              my_obj->mem_vtbl.user_data);
1143         if ( 0 > rc ) {
1144             CDBG_ERROR("%s: Cache invalidate failed on buffer index: %d",
1145                        __func__,
1146                        buffer.index);
1147             return rc;
1148         }
1149     } else {
1150         CDBG_ERROR("%s: Cache invalidate op not added", __func__);
1151     }
1152 
1153     my_obj->queued_buffer_count++;
1154     if(my_obj->queued_buffer_count == 1) {
1155         /* Add fd to data poll thread */
1156         CDBG_HIGH("%s: Starting poll on stream %p type :%d", __func__, my_obj,my_obj->stream_info->stream_type);
1157         rc = mm_camera_poll_thread_add_poll_fd(&my_obj->ch_obj->poll_thread[0],
1158                 my_obj->my_hdl,
1159                 my_obj->fd,
1160                 mm_stream_data_notify,
1161                 (void*)my_obj,
1162                 mm_camera_async_call);
1163         CDBG_HIGH("%s: Started poll on stream %p type :%d", __func__, my_obj,my_obj->stream_info->stream_type);
1164         if (rc < 0) {
1165             CDBG_ERROR("%s: add poll fd error", __func__);
1166             return rc;
1167         }
1168     }
1169 
1170     rc = ioctl(my_obj->fd, VIDIOC_QBUF, &buffer);
1171     CDBG("%s: qbuf idx:%d, rc:%d", __func__, buffer.index, rc);
1172     return rc;
1173 }
1174 
1175 /*===========================================================================
1176  * FUNCTION   : mm_stream_request_buf
1177  *
1178  * DESCRIPTION: This function let kernel know the amount of buffers need to
1179  *              be registered via v4l2 ioctl.
1180  *
1181  * PARAMETERS :
1182  *   @my_obj       : stream object
1183  *
1184  * RETURN     : int32_t type of status
1185  *              0  -- success
1186  *              -1 -- failure
1187  *==========================================================================*/
mm_stream_request_buf(mm_stream_t * my_obj)1188 int32_t mm_stream_request_buf(mm_stream_t * my_obj)
1189 {
1190     int32_t rc = 0;
1191     struct v4l2_requestbuffers bufreq;
1192     uint8_t buf_num = my_obj->buf_num;
1193     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1194          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1195 
1196     if(buf_num > MM_CAMERA_MAX_NUM_FRAMES) {
1197         CDBG_ERROR("%s: buf num %d > max limit %d\n",
1198                    __func__, buf_num, MM_CAMERA_MAX_NUM_FRAMES);
1199         return -1;
1200     }
1201 
1202     memset(&bufreq, 0, sizeof(bufreq));
1203     bufreq.count = buf_num;
1204     bufreq.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1205     bufreq.memory = V4L2_MEMORY_USERPTR;
1206     rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
1207     if (rc < 0) {
1208       CDBG_ERROR("%s: fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d\n",
1209            __func__, my_obj->fd, rc);
1210     }
1211     CDBG("%s :X rc = %d",__func__,rc);
1212     return rc;
1213 }
1214 
1215 /*===========================================================================
1216  * FUNCTION   : mm_stream_map_buf
1217  *
1218  * DESCRIPTION: mapping stream buffer via domain socket to server
1219  *
1220  * PARAMETERS :
1221  *   @my_obj       : stream object
1222  *   @buf_type     : type of buffer to be mapped. could be following values:
1223  *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1224  *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1225  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1226  *   @frame_idx    : index of buffer within the stream buffers, only valid if
1227  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1228  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1229  *   @plane_idx    : plane index. If all planes share the same fd,
1230  *                   plane_idx = -1; otherwise, plean_idx is the
1231  *                   index to plane (0..num_of_planes)
1232  *   @fd           : file descriptor of the buffer
1233  *   @size         : size of the buffer
1234  *
1235  * RETURN     : int32_t type of status
1236  *              0  -- success
1237  *              -1 -- failure
1238  *==========================================================================*/
mm_stream_map_buf(mm_stream_t * my_obj,uint8_t buf_type,uint32_t frame_idx,int32_t plane_idx,int fd,uint32_t size)1239 int32_t mm_stream_map_buf(mm_stream_t * my_obj,
1240                           uint8_t buf_type,
1241                           uint32_t frame_idx,
1242                           int32_t plane_idx,
1243                           int fd,
1244                           uint32_t size)
1245 {
1246     if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
1247         CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__);
1248         return -1;
1249     }
1250 
1251     cam_sock_packet_t packet;
1252     memset(&packet, 0, sizeof(cam_sock_packet_t));
1253     packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;
1254     packet.payload.buf_map.type = buf_type;
1255     packet.payload.buf_map.fd = fd;
1256     packet.payload.buf_map.size = size;
1257     packet.payload.buf_map.stream_id = my_obj->server_stream_id;
1258     packet.payload.buf_map.frame_idx = frame_idx;
1259     packet.payload.buf_map.plane_idx = plane_idx;
1260     return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
1261                                   &packet,
1262                                   sizeof(cam_sock_packet_t),
1263                                   fd);
1264 }
1265 
1266 /*===========================================================================
1267  * FUNCTION   : mm_stream_unmap_buf
1268  *
1269  * DESCRIPTION: unmapping stream buffer via domain socket to server
1270  *
1271  * PARAMETERS :
1272  *   @my_obj       : stream object
1273  *   @buf_type     : type of buffer to be unmapped. could be following values:
1274  *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1275  *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1276  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1277  *   @frame_idx    : index of buffer within the stream buffers, only valid if
1278  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1279  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1280  *   @plane_idx    : plane index. If all planes share the same fd,
1281  *                   plane_idx = -1; otherwise, plean_idx is the
1282  *                   index to plane (0..num_of_planes)
1283  *
1284  * RETURN     : int32_t type of status
1285  *              0  -- success
1286  *              -1 -- failure
1287  *==========================================================================*/
mm_stream_unmap_buf(mm_stream_t * my_obj,uint8_t buf_type,uint32_t frame_idx,int32_t plane_idx)1288 int32_t mm_stream_unmap_buf(mm_stream_t * my_obj,
1289                             uint8_t buf_type,
1290                             uint32_t frame_idx,
1291                             int32_t plane_idx)
1292 {
1293     if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
1294         CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__);
1295         return -1;
1296     }
1297 
1298     cam_sock_packet_t packet;
1299     memset(&packet, 0, sizeof(cam_sock_packet_t));
1300     packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING;
1301     packet.payload.buf_unmap.type = buf_type;
1302     packet.payload.buf_unmap.stream_id = my_obj->server_stream_id;
1303     packet.payload.buf_unmap.frame_idx = frame_idx;
1304     packet.payload.buf_unmap.plane_idx = plane_idx;
1305     return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
1306                                   &packet,
1307                                   sizeof(cam_sock_packet_t),
1308                                   0);
1309 }
1310 
1311 /*===========================================================================
1312  * FUNCTION   : mm_stream_map_buf_ops
1313  *
1314  * DESCRIPTION: ops for mapping stream buffer via domain socket to server.
1315  *              This function will be passed to upper layer as part of ops table
1316  *              to be used by upper layer when allocating stream buffers and mapping
1317  *              buffers to server via domain socket.
1318  *
1319  * PARAMETERS :
1320  *   @frame_idx    : index of buffer within the stream buffers, only valid if
1321  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1322  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1323  *   @plane_idx    : plane index. If all planes share the same fd,
1324  *                   plane_idx = -1; otherwise, plean_idx is the
1325  *                   index to plane (0..num_of_planes)
1326  *   @fd           : file descriptor of the buffer
1327  *   @size         : size of the buffer
1328  *   @userdata     : user data ptr (stream object)
1329  *
1330  * RETURN     : int32_t type of status
1331  *              0  -- success
1332  *              -1 -- failure
1333  *==========================================================================*/
mm_stream_map_buf_ops(uint32_t frame_idx,int32_t plane_idx,int fd,uint32_t size,void * userdata)1334 static int32_t mm_stream_map_buf_ops(uint32_t frame_idx,
1335                                      int32_t plane_idx,
1336                                      int fd,
1337                                      uint32_t size,
1338                                      void *userdata)
1339 {
1340     mm_stream_t *my_obj = (mm_stream_t *)userdata;
1341     return mm_stream_map_buf(my_obj,
1342                              CAM_MAPPING_BUF_TYPE_STREAM_BUF,
1343                              frame_idx, plane_idx, fd, size);
1344 }
1345 
1346 /*===========================================================================
1347  * FUNCTION   : mm_stream_unmap_buf_ops
1348  *
1349  * DESCRIPTION: ops for unmapping stream buffer via domain socket to server.
1350  *              This function will be passed to upper layer as part of ops table
1351  *              to be used by upper layer when allocating stream buffers and unmapping
1352  *              buffers to server via domain socket.
1353  *
1354  * PARAMETERS :
1355  *   @frame_idx    : index of buffer within the stream buffers, only valid if
1356  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1357  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1358  *   @plane_idx    : plane index. If all planes share the same fd,
1359  *                   plane_idx = -1; otherwise, plean_idx is the
1360  *                   index to plane (0..num_of_planes)
1361  *   @userdata     : user data ptr (stream object)
1362  *
1363  * RETURN     : int32_t type of status
1364  *              0  -- success
1365  *              -1 -- failure
1366  *==========================================================================*/
mm_stream_unmap_buf_ops(uint32_t frame_idx,int32_t plane_idx,void * userdata)1367 static int32_t mm_stream_unmap_buf_ops(uint32_t frame_idx,
1368                                        int32_t plane_idx,
1369                                        void *userdata)
1370 {
1371     mm_stream_t *my_obj = (mm_stream_t *)userdata;
1372     return mm_stream_unmap_buf(my_obj,
1373                                CAM_MAPPING_BUF_TYPE_STREAM_BUF,
1374                                frame_idx,
1375                                plane_idx);
1376 }
1377 
1378 /*===========================================================================
1379  * FUNCTION   : mm_stream_init_bufs
1380  *
1381  * DESCRIPTION: initialize stream buffers needed. This function will request
1382  *              buffers needed from upper layer through the mem ops table passed
1383  *              during configuration stage.
1384  *
1385  * PARAMETERS :
1386  *   @my_obj  : stream object
1387  *
1388  * RETURN     : int32_t type of status
1389  *              0  -- success
1390  *              -1 -- failure
1391  *==========================================================================*/
mm_stream_init_bufs(mm_stream_t * my_obj)1392 int32_t mm_stream_init_bufs(mm_stream_t * my_obj)
1393 {
1394     int32_t i, rc = 0;
1395     uint8_t *reg_flags = NULL;
1396     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1397          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1398 
1399     /* deinit buf if it's not NULL*/
1400     if (NULL != my_obj->buf) {
1401         mm_stream_deinit_bufs(my_obj);
1402     }
1403 
1404     my_obj->map_ops.map_ops = mm_stream_map_buf_ops;
1405     my_obj->map_ops.unmap_ops = mm_stream_unmap_buf_ops;
1406     my_obj->map_ops.userdata = my_obj;
1407 
1408     rc = my_obj->mem_vtbl.get_bufs(&my_obj->frame_offset,
1409                                    &my_obj->buf_num,
1410                                    &reg_flags,
1411                                    &my_obj->buf,
1412                                    &my_obj->map_ops,
1413                                    my_obj->mem_vtbl.user_data);
1414 
1415     if (0 != rc) {
1416         CDBG_ERROR("%s: Error get buf, rc = %d\n", __func__, rc);
1417         return rc;
1418     }
1419 
1420     my_obj->buf_status =
1421         (mm_stream_buf_status_t *)malloc(sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
1422 
1423     if (NULL == my_obj->buf_status) {
1424         CDBG_ERROR("%s: No memory for buf_status", __func__);
1425         mm_stream_deinit_bufs(my_obj);
1426         free(reg_flags);
1427         return -1;
1428     }
1429 
1430     memset(my_obj->buf_status, 0, sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
1431     for (i = 0; i < my_obj->buf_num; i++) {
1432         my_obj->buf_status[i].initial_reg_flag = reg_flags[i];
1433         my_obj->buf[i].stream_id = my_obj->my_hdl;
1434         my_obj->buf[i].stream_type = my_obj->stream_info->stream_type;
1435     }
1436 
1437     free(reg_flags);
1438     reg_flags = NULL;
1439 
1440     return rc;
1441 }
1442 
1443 /*===========================================================================
1444  * FUNCTION   : mm_stream_deinit_bufs
1445  *
1446  * DESCRIPTION: return stream buffers to upper layer through the mem ops table
1447  *              passed during configuration stage.
1448  *
1449  * PARAMETERS :
1450  *   @my_obj  : stream object
1451  *
1452  * RETURN     : int32_t type of status
1453  *              0  -- success
1454  *              -1 -- failure
1455  *==========================================================================*/
mm_stream_deinit_bufs(mm_stream_t * my_obj)1456 int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj)
1457 {
1458     int32_t rc = 0;
1459     mm_camera_map_unmap_ops_tbl_t ops_tbl;
1460     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1461          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1462 
1463     if (NULL == my_obj->buf) {
1464         CDBG("%s: Buf is NULL, no need to deinit", __func__);
1465         return rc;
1466     }
1467 
1468     /* release bufs */
1469     ops_tbl.map_ops = mm_stream_map_buf_ops;
1470     ops_tbl.unmap_ops = mm_stream_unmap_buf_ops;
1471     ops_tbl.userdata = my_obj;
1472 
1473     rc = my_obj->mem_vtbl.put_bufs(&ops_tbl,
1474                                    my_obj->mem_vtbl.user_data);
1475 
1476     free(my_obj->buf);
1477     my_obj->buf = NULL;
1478     if (my_obj->buf_status != NULL) {
1479         free(my_obj->buf_status);
1480         my_obj->buf_status = NULL;
1481     }
1482 
1483     return rc;
1484 }
1485 
1486 /*===========================================================================
1487  * FUNCTION   : mm_stream_reg_buf
1488  *
1489  * DESCRIPTION: register buffers with kernel by calling v4l2 ioctl QBUF for
1490  *              each buffer in the stream
1491  *
1492  * PARAMETERS :
1493  *   @my_obj  : stream object
1494  *
1495  * RETURN     : int32_t type of status
1496  *              0  -- success
1497  *              -1 -- failure
1498  *==========================================================================*/
mm_stream_reg_buf(mm_stream_t * my_obj)1499 int32_t mm_stream_reg_buf(mm_stream_t * my_obj)
1500 {
1501     int32_t rc = 0;
1502     uint8_t i;
1503     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1504          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1505 
1506     rc = mm_stream_request_buf(my_obj);
1507     if (rc != 0) {
1508         return rc;
1509     }
1510 
1511     pthread_mutex_lock(&my_obj->buf_lock);
1512     my_obj->queued_buffer_count = 0;
1513     for(i = 0; i < my_obj->buf_num; i++){
1514         /* check if need to qbuf initially */
1515         if (my_obj->buf_status[i].initial_reg_flag) {
1516             rc = mm_stream_qbuf(my_obj, &my_obj->buf[i]);
1517             if (rc != 0) {
1518                 CDBG_ERROR("%s: VIDIOC_QBUF rc = %d, errno is %s\n",
1519                         __func__, rc, strerror(errno));
1520                 break;
1521             }
1522             my_obj->buf_status[i].buf_refcnt = 0;
1523             my_obj->buf_status[i].in_kernel = 1;
1524         } else {
1525             /* the buf is held by upper layer, will not queue into kernel.
1526              * add buf reference count */
1527             my_obj->buf_status[i].buf_refcnt = 1;
1528             my_obj->buf_status[i].in_kernel = 0;
1529         }
1530     }
1531     pthread_mutex_unlock(&my_obj->buf_lock);
1532 
1533     return rc;
1534 }
1535 
1536 /*===========================================================================
1537  * FUNCTION   : mm_stream_unreg buf
1538  *
1539  * DESCRIPTION: unregister all stream buffers from kernel
1540  *
1541  * PARAMETERS :
1542  *   @my_obj  : stream object
1543  *
1544  * RETURN     : int32_t type of status
1545  *              0  -- success
1546  *              -1 -- failure
1547  *==========================================================================*/
mm_stream_unreg_buf(mm_stream_t * my_obj)1548 int32_t mm_stream_unreg_buf(mm_stream_t * my_obj)
1549 {
1550     struct v4l2_requestbuffers bufreq;
1551     int32_t i, rc = 0;
1552     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1553          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1554 
1555     /* unreg buf to kernel */
1556     bufreq.count = 0;
1557     bufreq.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1558     bufreq.memory = V4L2_MEMORY_USERPTR;
1559     rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
1560     if (rc < 0) {
1561         CDBG_ERROR("%s: fd=%d, VIDIOC_REQBUFS failed, rc=%d\n",
1562               __func__, my_obj->fd, rc);
1563     }
1564 
1565     /* reset buf reference count */
1566     pthread_mutex_lock(&my_obj->buf_lock);
1567     if (NULL != my_obj->buf_status) {
1568         for(i = 0; i < my_obj->buf_num; i++){
1569             my_obj->buf_status[i].buf_refcnt = 0;
1570             my_obj->buf_status[i].in_kernel = 0;
1571         }
1572     }
1573     pthread_mutex_unlock(&my_obj->buf_lock);
1574 
1575     return rc;
1576 }
1577 
1578 /*===========================================================================
1579  * FUNCTION   : mm_stream_get_v4l2_fmt
1580  *
1581  * DESCRIPTION: translate camera image format into FOURCC code
1582  *
1583  * PARAMETERS :
1584  *   @fmt     : camera image format
1585  *
1586  * RETURN     : FOURCC code for image format
1587  *==========================================================================*/
mm_stream_get_v4l2_fmt(cam_format_t fmt)1588 uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt)
1589 {
1590     uint32_t val;
1591     switch(fmt) {
1592     case CAM_FORMAT_YUV_420_NV12:
1593         val = V4L2_PIX_FMT_NV12;
1594         break;
1595     case CAM_FORMAT_YUV_420_NV21:
1596         val = V4L2_PIX_FMT_NV21;
1597         break;
1598     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG:
1599     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG:
1600     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB:
1601     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR:
1602         val= V4L2_PIX_FMT_SBGGR10;
1603         break;
1604     case CAM_FORMAT_YUV_422_NV61:
1605         val= V4L2_PIX_FMT_NV61;
1606         break;
1607     case CAM_FORMAT_YUV_RAW_8BIT_YUYV:
1608         val= V4L2_PIX_FMT_YUYV;
1609         break;
1610     case CAM_FORMAT_YUV_RAW_8BIT_YVYU:
1611         val= V4L2_PIX_FMT_YVYU;
1612         break;
1613     case CAM_FORMAT_YUV_RAW_8BIT_UYVY:
1614         val= V4L2_PIX_FMT_UYVY;
1615         break;
1616     case CAM_FORMAT_YUV_RAW_8BIT_VYUY:
1617         val= V4L2_PIX_FMT_VYUY;
1618         break;
1619     case CAM_FORMAT_YUV_420_YV12:
1620         val= V4L2_PIX_FMT_NV12;
1621         break;
1622     case CAM_FORMAT_YUV_422_NV16:
1623         val= V4L2_PIX_FMT_NV16;
1624         break;
1625     default:
1626         val = 0;
1627         CDBG_ERROR("%s: Unknown fmt=%d", __func__, fmt);
1628         break;
1629     }
1630     CDBG("%s: fmt=%d, val =%d", __func__, fmt, val);
1631     return val;
1632 }
1633 
1634 /*===========================================================================
1635  * FUNCTION   : mm_stream_calc_offset_preview
1636  *
1637  * DESCRIPTION: calculate preview/postview frame offset based on format and
1638  *              padding information
1639  *
1640  * PARAMETERS :
1641  *   @fmt     : image format
1642  *   @dim     : image dimension
1643  *   @buf_planes : [out] buffer plane information
1644  *
1645  * RETURN     : int32_t type of status
1646  *              0  -- success
1647  *              -1 -- failure
1648  *==========================================================================*/
mm_stream_calc_offset_preview(cam_format_t fmt,cam_dimension_t * dim,cam_stream_buf_plane_info_t * buf_planes)1649 int32_t mm_stream_calc_offset_preview(cam_format_t fmt,
1650                                       cam_dimension_t *dim,
1651                                       cam_stream_buf_plane_info_t *buf_planes)
1652 {
1653     int32_t rc = 0;
1654     int stride = 0, scanline = 0;
1655 
1656     switch (fmt) {
1657     case CAM_FORMAT_YUV_420_NV12:
1658     case CAM_FORMAT_YUV_420_NV21:
1659         /* 2 planes: Y + CbCr */
1660         buf_planes->plane_info.num_planes = 2;
1661 
1662         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1663         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
1664         buf_planes->plane_info.mp[0].offset = 0;
1665         buf_planes->plane_info.mp[0].len = stride * scanline;
1666         buf_planes->plane_info.mp[0].offset_x = 0;
1667         buf_planes->plane_info.mp[0].offset_y = 0;
1668         buf_planes->plane_info.mp[0].stride = stride;
1669         buf_planes->plane_info.mp[0].scanline = scanline;
1670 
1671         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1672         scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_2);
1673         buf_planes->plane_info.mp[1].offset = 0;
1674         buf_planes->plane_info.mp[1].len =
1675             stride * scanline;
1676         buf_planes->plane_info.mp[1].offset_x = 0;
1677         buf_planes->plane_info.mp[1].offset_y = 0;
1678         buf_planes->plane_info.mp[1].stride = stride;
1679         buf_planes->plane_info.mp[1].scanline = scanline;
1680 
1681         buf_planes->plane_info.frame_len =
1682             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1683                         buf_planes->plane_info.mp[1].len,
1684                         CAM_PAD_TO_4K);
1685         break;
1686     case CAM_FORMAT_YUV_420_NV21_ADRENO:
1687         /* 2 planes: Y + CbCr */
1688         buf_planes->plane_info.num_planes = 2;
1689 
1690         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
1691         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32);
1692         buf_planes->plane_info.mp[0].offset = 0;
1693         buf_planes->plane_info.mp[0].len =
1694             PAD_TO_SIZE(stride * scanline,
1695                         CAM_PAD_TO_4K);
1696         buf_planes->plane_info.mp[0].offset_x = 0;
1697         buf_planes->plane_info.mp[0].offset_y = 0;
1698         buf_planes->plane_info.mp[0].stride = stride;
1699         buf_planes->plane_info.mp[0].scanline = scanline;
1700 
1701         stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2;
1702         scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32);
1703         buf_planes->plane_info.mp[1].offset = 0;
1704         buf_planes->plane_info.mp[1].len =
1705             PAD_TO_SIZE(stride * scanline,
1706                         CAM_PAD_TO_4K);
1707         buf_planes->plane_info.mp[1].offset_x = 0;
1708         buf_planes->plane_info.mp[1].offset_y = 0;
1709         buf_planes->plane_info.mp[1].stride = stride;
1710         buf_planes->plane_info.mp[1].scanline = scanline;
1711 
1712         buf_planes->plane_info.frame_len =
1713             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1714                         buf_planes->plane_info.mp[1].len,
1715                         CAM_PAD_TO_4K);
1716         break;
1717     case CAM_FORMAT_YUV_420_YV12:
1718         /* 3 planes: Y + Cr + Cb */
1719         buf_planes->plane_info.num_planes = 3;
1720 
1721         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1722         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
1723         buf_planes->plane_info.mp[0].offset = 0;
1724         buf_planes->plane_info.mp[0].len = stride * scanline;
1725         buf_planes->plane_info.mp[0].offset_x = 0;
1726         buf_planes->plane_info.mp[0].offset_y = 0;
1727         buf_planes->plane_info.mp[0].stride = stride;
1728         buf_planes->plane_info.mp[0].scanline = scanline;
1729 
1730         stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
1731         scanline = scanline / 2;
1732         buf_planes->plane_info.mp[1].offset = 0;
1733         buf_planes->plane_info.mp[1].len =
1734             stride * scanline;
1735         buf_planes->plane_info.mp[1].offset_x = 0;
1736         buf_planes->plane_info.mp[1].offset_y = 0;
1737         buf_planes->plane_info.mp[1].stride = stride;
1738         buf_planes->plane_info.mp[1].scanline = scanline;
1739 
1740         buf_planes->plane_info.mp[2].offset = 0;
1741         buf_planes->plane_info.mp[2].len =
1742             stride * scanline;
1743         buf_planes->plane_info.mp[2].offset_x = 0;
1744         buf_planes->plane_info.mp[2].offset_y = 0;
1745         buf_planes->plane_info.mp[2].stride = stride;
1746         buf_planes->plane_info.mp[2].scanline = scanline;
1747 
1748         buf_planes->plane_info.frame_len =
1749             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1750                         buf_planes->plane_info.mp[1].len +
1751                         buf_planes->plane_info.mp[2].len,
1752                         CAM_PAD_TO_4K);
1753         break;
1754     case CAM_FORMAT_YUV_422_NV16:
1755     case CAM_FORMAT_YUV_422_NV61:
1756         /* 2 planes: Y + CbCr */
1757         buf_planes->plane_info.num_planes = 2;
1758 
1759         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1760         scanline = dim->height;
1761         buf_planes->plane_info.mp[0].offset = 0;
1762         buf_planes->plane_info.mp[0].len = stride * scanline;
1763         buf_planes->plane_info.mp[0].offset_x = 0;
1764         buf_planes->plane_info.mp[0].offset_y = 0;
1765         buf_planes->plane_info.mp[0].stride = stride;
1766         buf_planes->plane_info.mp[0].scanline = scanline;
1767 
1768         buf_planes->plane_info.mp[1].offset = 0;
1769         buf_planes->plane_info.mp[1].len = stride * scanline;
1770         buf_planes->plane_info.mp[1].offset_x = 0;
1771         buf_planes->plane_info.mp[1].offset_y = 0;
1772         buf_planes->plane_info.mp[1].stride = stride;
1773         buf_planes->plane_info.mp[1].scanline = scanline;
1774 
1775         buf_planes->plane_info.frame_len =
1776             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1777                         buf_planes->plane_info.mp[1].len,
1778                         CAM_PAD_TO_4K);
1779         break;
1780     default:
1781         CDBG_ERROR("%s: Invalid cam_format for preview %d",
1782                    __func__, fmt);
1783         rc = -1;
1784         break;
1785     }
1786 
1787     return rc;
1788 }
1789 
1790 /*===========================================================================
1791  * FUNCTION   : mm_stream_calc_offset_snapshot
1792  *
1793  * DESCRIPTION: calculate snapshot/postproc frame offset based on format and
1794  *              padding information
1795  *
1796  * PARAMETERS :
1797  *   @fmt     : image format
1798  *   @dim     : image dimension
1799  *   @padding : padding information
1800  *   @buf_planes : [out] buffer plane information
1801  *
1802  * RETURN     : int32_t type of status
1803  *              0  -- success
1804  *              -1 -- failure
1805  *==========================================================================*/
mm_stream_calc_offset_snapshot(cam_format_t fmt,cam_dimension_t * dim,cam_padding_info_t * padding,cam_stream_buf_plane_info_t * buf_planes)1806 int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt,
1807                                        cam_dimension_t *dim,
1808                                        cam_padding_info_t *padding,
1809                                        cam_stream_buf_plane_info_t *buf_planes)
1810 {
1811     int32_t rc = 0;
1812     uint8_t isAFamily = mm_camera_util_chip_is_a_family();
1813     int offset_x = 0, offset_y = 0;
1814     int stride = 0, scanline = 0;
1815 
1816     if (isAFamily) {
1817         stride = dim->width;
1818         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_16);
1819         offset_x = 0;
1820         offset_y = scanline - dim->height;
1821         scanline += offset_y; /* double padding */
1822     } else {
1823         stride = PAD_TO_SIZE(dim->width,
1824                              padding->width_padding);
1825         scanline = PAD_TO_SIZE(dim->height,
1826                                padding->height_padding);
1827         offset_x = 0;
1828         offset_y = 0;
1829     }
1830 
1831     switch (fmt) {
1832     case CAM_FORMAT_YUV_420_NV12:
1833     case CAM_FORMAT_YUV_420_NV21:
1834         /* 2 planes: Y + CbCr */
1835         buf_planes->plane_info.num_planes = 2;
1836 
1837         buf_planes->plane_info.mp[0].len =
1838             PAD_TO_SIZE(stride * scanline,
1839                         padding->plane_padding);
1840         buf_planes->plane_info.mp[0].offset =
1841             PAD_TO_SIZE(offset_x + stride * offset_y,
1842                         padding->plane_padding);
1843         buf_planes->plane_info.mp[0].offset_x = offset_x;
1844         buf_planes->plane_info.mp[0].offset_y = offset_y;
1845         buf_planes->plane_info.mp[0].stride = stride;
1846         buf_planes->plane_info.mp[0].scanline = scanline;
1847 
1848         scanline = scanline / 2;
1849         buf_planes->plane_info.mp[1].len =
1850             PAD_TO_SIZE(stride * scanline,
1851                         padding->plane_padding);
1852         buf_planes->plane_info.mp[1].offset =
1853             PAD_TO_SIZE(offset_x + stride * offset_y,
1854                         padding->plane_padding);
1855         buf_planes->plane_info.mp[1].offset_x = offset_x;
1856         buf_planes->plane_info.mp[1].offset_y = offset_y;
1857         buf_planes->plane_info.mp[1].stride = stride;
1858         buf_planes->plane_info.mp[1].scanline = scanline;
1859 
1860         buf_planes->plane_info.frame_len =
1861             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1862                         buf_planes->plane_info.mp[1].len,
1863                         CAM_PAD_TO_4K);
1864         break;
1865     case CAM_FORMAT_YUV_420_YV12:
1866         /* 3 planes: Y + Cr + Cb */
1867         buf_planes->plane_info.num_planes = 3;
1868 
1869         buf_planes->plane_info.mp[0].offset =
1870             PAD_TO_SIZE(offset_x + stride * offset_y,
1871                         padding->plane_padding);
1872         buf_planes->plane_info.mp[0].len =
1873             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
1874         buf_planes->plane_info.mp[0].offset_x = offset_x;
1875         buf_planes->plane_info.mp[0].offset_y = offset_y;
1876         buf_planes->plane_info.mp[0].stride = stride;
1877         buf_planes->plane_info.mp[0].scanline = scanline;
1878 
1879         stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
1880         scanline = scanline / 2;
1881         buf_planes->plane_info.mp[1].offset =
1882             PAD_TO_SIZE(offset_x + stride * offset_y,
1883                         padding->plane_padding);
1884         buf_planes->plane_info.mp[1].len =
1885             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
1886         buf_planes->plane_info.mp[1].offset_x = offset_x;
1887         buf_planes->plane_info.mp[1].offset_y = offset_y;
1888         buf_planes->plane_info.mp[1].stride = stride;
1889         buf_planes->plane_info.mp[1].scanline = scanline;
1890 
1891         buf_planes->plane_info.mp[2].offset =
1892             PAD_TO_SIZE(offset_x + stride * offset_y,
1893                         padding->plane_padding);
1894         buf_planes->plane_info.mp[2].len =
1895             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
1896         buf_planes->plane_info.mp[2].offset_x = offset_x;
1897         buf_planes->plane_info.mp[2].offset_y = offset_y;
1898         buf_planes->plane_info.mp[2].stride = stride;
1899         buf_planes->plane_info.mp[2].scanline = scanline;
1900 
1901         buf_planes->plane_info.frame_len =
1902             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1903                         buf_planes->plane_info.mp[1].len +
1904                         buf_planes->plane_info.mp[2].len,
1905                         CAM_PAD_TO_4K);
1906         break;
1907     case CAM_FORMAT_YUV_422_NV16:
1908     case CAM_FORMAT_YUV_422_NV61:
1909         /* 2 planes: Y + CbCr */
1910         buf_planes->plane_info.num_planes = 2;
1911         buf_planes->plane_info.mp[0].len =
1912             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
1913         buf_planes->plane_info.mp[0].offset =
1914             PAD_TO_SIZE(offset_x + stride * offset_y,
1915                         padding->plane_padding);
1916         buf_planes->plane_info.mp[0].offset_x = offset_x;
1917         buf_planes->plane_info.mp[0].offset_y = offset_y;
1918         buf_planes->plane_info.mp[0].stride = stride;
1919         buf_planes->plane_info.mp[0].scanline = scanline;
1920 
1921         buf_planes->plane_info.mp[1].len =
1922             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
1923         buf_planes->plane_info.mp[1].offset =
1924             PAD_TO_SIZE(offset_x + stride * offset_y,
1925                         padding->plane_padding);
1926         buf_planes->plane_info.mp[1].offset_x = offset_x;
1927         buf_planes->plane_info.mp[1].offset_y = offset_y;
1928         buf_planes->plane_info.mp[1].stride = stride;
1929         buf_planes->plane_info.mp[1].scanline = scanline;
1930 
1931         buf_planes->plane_info.frame_len = PAD_TO_SIZE(
1932             buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len,
1933             CAM_PAD_TO_4K);
1934         break;
1935     default:
1936         CDBG_ERROR("%s: Invalid cam_format for snapshot %d",
1937                    __func__, fmt);
1938         rc = -1;
1939         break;
1940     }
1941 
1942     return rc;
1943 }
1944 
1945 /*===========================================================================
1946  * FUNCTION   : mm_stream_calc_offset_raw
1947  *
1948  * DESCRIPTION: calculate raw frame offset based on format and padding information
1949  *
1950  * PARAMETERS :
1951  *   @fmt     : image format
1952  *   @dim     : image dimension
1953  *   @padding : padding information
1954  *   @buf_planes : [out] buffer plane information
1955  *
1956  * RETURN     : int32_t type of status
1957  *              0  -- success
1958  *              -1 -- failure
1959  *==========================================================================*/
mm_stream_calc_offset_raw(cam_format_t fmt,cam_dimension_t * dim,cam_padding_info_t * padding,cam_stream_buf_plane_info_t * buf_planes)1960 int32_t mm_stream_calc_offset_raw(cam_format_t fmt,
1961                                   cam_dimension_t *dim,
1962                                   cam_padding_info_t *padding,
1963                                   cam_stream_buf_plane_info_t *buf_planes)
1964 {
1965     int32_t rc = 0;
1966     int stride = 0;
1967     int scanline = dim->height;
1968 
1969     switch (fmt) {
1970     case CAM_FORMAT_YUV_RAW_8BIT_YUYV:
1971     case CAM_FORMAT_YUV_RAW_8BIT_YVYU:
1972     case CAM_FORMAT_YUV_RAW_8BIT_UYVY:
1973     case CAM_FORMAT_YUV_RAW_8BIT_VYUY:
1974     case CAM_FORMAT_JPEG_RAW_8BIT:
1975     case CAM_FORMAT_META_RAW_8BIT:
1976         /* 1 plane */
1977         /* Every 16 pixels occupy 16 bytes */
1978         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1979         buf_planes->plane_info.num_planes = 1;
1980         buf_planes->plane_info.mp[0].offset = 0;
1981         buf_planes->plane_info.mp[0].len =
1982             PAD_TO_SIZE(stride * scanline * 2, padding->plane_padding);
1983         buf_planes->plane_info.frame_len =
1984             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
1985         buf_planes->plane_info.mp[0].offset_x =0;
1986         buf_planes->plane_info.mp[0].offset_y = 0;
1987         buf_planes->plane_info.mp[0].stride = stride;
1988         buf_planes->plane_info.mp[0].scanline = scanline;
1989         break;
1990     case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GBRG:
1991     case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GRBG:
1992     case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_RGGB:
1993     case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_BGGR:
1994     case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GBRG:
1995     case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GRBG:
1996     case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_RGGB:
1997     case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_BGGR:
1998     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GBRG:
1999     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GRBG:
2000     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_RGGB:
2001     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_BGGR:
2002     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GBRG:
2003     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GRBG:
2004     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_RGGB:
2005     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_BGGR:
2006     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GBRG:
2007     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GRBG:
2008     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_RGGB:
2009     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_BGGR:
2010         /* 1 plane */
2011         /* Every 16 pixels occupy 16 bytes */
2012         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2013         buf_planes->plane_info.num_planes = 1;
2014         buf_planes->plane_info.mp[0].offset = 0;
2015         buf_planes->plane_info.mp[0].len =
2016             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2017         buf_planes->plane_info.frame_len =
2018             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2019         buf_planes->plane_info.mp[0].offset_x =0;
2020         buf_planes->plane_info.mp[0].offset_y = 0;
2021         buf_planes->plane_info.mp[0].stride = stride;
2022         buf_planes->plane_info.mp[0].scanline = scanline;
2023         break;
2024     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG:
2025     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG:
2026     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB:
2027     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR:
2028     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GBRG:
2029     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GRBG:
2030     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_RGGB:
2031     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_BGGR:
2032         /* Every 12 pixels occupy 16 bytes */
2033         stride = (dim->width + 11)/12 * 16;
2034         buf_planes->plane_info.num_planes = 1;
2035         buf_planes->plane_info.mp[0].offset = 0;
2036         buf_planes->plane_info.mp[0].len =
2037             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2038         buf_planes->plane_info.frame_len =
2039             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2040         buf_planes->plane_info.mp[0].offset_x =0;
2041         buf_planes->plane_info.mp[0].offset_y = 0;
2042         buf_planes->plane_info.mp[0].stride = stride;
2043         buf_planes->plane_info.mp[0].scanline = scanline;
2044         break;
2045     case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GBRG:
2046     case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GRBG:
2047     case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_RGGB:
2048     case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_BGGR:
2049     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GBRG:
2050     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GRBG:
2051     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_RGGB:
2052     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_BGGR:
2053         /* Every 10 pixels occupy 16 bytes */
2054         stride = (dim->width + 9)/10 * 16;
2055         buf_planes->plane_info.num_planes = 1;
2056         buf_planes->plane_info.mp[0].offset = 0;
2057         buf_planes->plane_info.mp[0].len =
2058             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2059         buf_planes->plane_info.frame_len =
2060             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2061         buf_planes->plane_info.mp[0].offset_x =0;
2062         buf_planes->plane_info.mp[0].offset_y = 0;
2063         buf_planes->plane_info.mp[0].stride = stride;
2064         buf_planes->plane_info.mp[0].scanline = scanline;
2065         break;
2066     case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG:
2067     case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GRBG:
2068     case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_RGGB:
2069     case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_BGGR:
2070     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GBRG:
2071     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GRBG:
2072     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_RGGB:
2073     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_BGGR:
2074         /* Every 64 pixels occupy 80 bytes */
2075         stride = PAD_TO_SIZE(
2076                 PAD_TO_SIZE(dim->width, CAM_PAD_TO_4)*5/4, CAM_PAD_TO_16);
2077         buf_planes->plane_info.num_planes = 1;
2078         buf_planes->plane_info.mp[0].offset = 0;
2079         buf_planes->plane_info.mp[0].len =
2080             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2081         buf_planes->plane_info.frame_len =
2082             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2083         buf_planes->plane_info.mp[0].offset_x =0;
2084         buf_planes->plane_info.mp[0].offset_y = 0;
2085         buf_planes->plane_info.mp[0].stride = stride;
2086         buf_planes->plane_info.mp[0].scanline = scanline;
2087         break;
2088     case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GBRG:
2089     case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GRBG:
2090     case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_RGGB:
2091     case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_BGGR:
2092     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GBRG:
2093     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GRBG:
2094     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_RGGB:
2095     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_BGGR:
2096         /* Every 32 pixels occupy 48 bytes */
2097         stride = PAD_TO_SIZE(PAD_TO_SIZE(dim->width, 2)*3/2, CAM_PAD_TO_16);
2098         buf_planes->plane_info.num_planes = 1;
2099         buf_planes->plane_info.mp[0].offset = 0;
2100         buf_planes->plane_info.mp[0].len =
2101             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2102         buf_planes->plane_info.frame_len =
2103             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2104         buf_planes->plane_info.mp[0].offset_x =0;
2105         buf_planes->plane_info.mp[0].offset_y = 0;
2106         buf_planes->plane_info.mp[0].stride = stride;
2107         buf_planes->plane_info.mp[0].scanline = scanline;
2108         break;
2109     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GBRG:
2110     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GRBG:
2111     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_RGGB:
2112     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_BGGR:
2113     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GBRG:
2114     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GRBG:
2115     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_RGGB:
2116     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_BGGR:
2117     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GBRG:
2118     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GRBG:
2119     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_RGGB:
2120     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_BGGR:
2121         /* Every 8 pixels occupy 16 bytes */
2122         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_8) * 2;
2123         buf_planes->plane_info.num_planes = 1;
2124         buf_planes->plane_info.mp[0].offset = 0;
2125         buf_planes->plane_info.mp[0].len =
2126             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2127         buf_planes->plane_info.frame_len =
2128             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2129         buf_planes->plane_info.mp[0].offset_x =0;
2130         buf_planes->plane_info.mp[0].offset_y = 0;
2131         buf_planes->plane_info.mp[0].stride = stride;
2132         buf_planes->plane_info.mp[0].scanline = scanline;
2133         break;
2134     default:
2135         CDBG_ERROR("%s: Invalid cam_format %d for raw stream",
2136                    __func__, fmt);
2137         rc = -1;
2138         break;
2139     }
2140 
2141     return rc;
2142 }
2143 
2144 /*===========================================================================
2145  * FUNCTION   : mm_stream_calc_offset_video
2146  *
2147  * DESCRIPTION: calculate video frame offset based on format and
2148  *              padding information
2149  *
2150  * PARAMETERS :
2151  *   @dim     : image dimension
2152  *   @buf_planes : [out] buffer plane information
2153  *
2154  * RETURN     : int32_t type of status
2155  *              0  -- success
2156  *              -1 -- failure
2157  *==========================================================================*/
2158 #ifdef VENUS_PRESENT
mm_stream_calc_offset_video(cam_dimension_t * dim,cam_stream_buf_plane_info_t * buf_planes)2159 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim,
2160                                     cam_stream_buf_plane_info_t *buf_planes)
2161 {
2162     int stride = 0, scanline = 0;
2163 
2164     // using Venus
2165     stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
2166     scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
2167 
2168     buf_planes->plane_info.frame_len =
2169         VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height);
2170     buf_planes->plane_info.num_planes = 2;
2171     buf_planes->plane_info.mp[0].len = stride * scanline;
2172     buf_planes->plane_info.mp[0].offset = 0;
2173     buf_planes->plane_info.mp[0].offset_x =0;
2174     buf_planes->plane_info.mp[0].offset_y = 0;
2175     buf_planes->plane_info.mp[0].stride = stride;
2176     buf_planes->plane_info.mp[0].scanline = scanline;
2177     stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
2178     scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
2179     buf_planes->plane_info.mp[1].len =
2180         buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
2181     buf_planes->plane_info.mp[1].offset = 0;
2182     buf_planes->plane_info.mp[1].offset_x =0;
2183     buf_planes->plane_info.mp[1].offset_y = 0;
2184     buf_planes->plane_info.mp[1].stride = stride;
2185     buf_planes->plane_info.mp[1].scanline = scanline;
2186 
2187     return 0;
2188 }
2189 #else
mm_stream_calc_offset_video(cam_dimension_t * dim,cam_stream_buf_plane_info_t * buf_planes)2190 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim,
2191                                     cam_stream_buf_plane_info_t *buf_planes)
2192 {
2193     int stride = 0, scanline = 0;
2194 
2195     buf_planes->plane_info.num_planes = 2;
2196 
2197     stride = dim->width;
2198     scanline = dim->height;
2199     buf_planes->plane_info.mp[0].len =
2200         PAD_TO_SIZE(stride * scanline, CAM_PAD_TO_2K);
2201     buf_planes->plane_info.mp[0].offset = 0;
2202     buf_planes->plane_info.mp[0].offset_x =0;
2203     buf_planes->plane_info.mp[0].offset_y = 0;
2204     buf_planes->plane_info.mp[0].stride = stride;
2205     buf_planes->plane_info.mp[0].scanline = scanline;
2206 
2207     stride = dim->width;
2208     scanline = dim->height / 2;
2209     buf_planes->plane_info.mp[1].len =
2210         PAD_TO_SIZE(stride * scanline, CAM_PAD_TO_2K);
2211     buf_planes->plane_info.mp[1].offset = 0;
2212     buf_planes->plane_info.mp[1].offset_x =0;
2213     buf_planes->plane_info.mp[1].offset_y = 0;
2214     buf_planes->plane_info.mp[1].stride = stride;
2215     buf_planes->plane_info.mp[1].scanline = scanline;
2216 
2217     buf_planes->plane_info.frame_len =
2218         PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2219                     buf_planes->plane_info.mp[1].len,
2220                     CAM_PAD_TO_4K);
2221 
2222     return 0;
2223 }
2224 #endif
2225 
2226 /*===========================================================================
2227  * FUNCTION   : mm_stream_calc_offset_metadata
2228  *
2229  * DESCRIPTION: calculate metadata frame offset based on format and
2230  *              padding information
2231  *
2232  * PARAMETERS :
2233  *   @dim     : image dimension
2234  *   @padding : padding information
2235  *   @buf_planes : [out] buffer plane information
2236  *
2237  * RETURN     : int32_t type of status
2238  *              0  -- success
2239  *              -1 -- failure
2240  *==========================================================================*/
mm_stream_calc_offset_metadata(cam_dimension_t * dim,cam_padding_info_t * padding,cam_stream_buf_plane_info_t * buf_planes)2241 int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim,
2242                                        cam_padding_info_t *padding,
2243                                        cam_stream_buf_plane_info_t *buf_planes)
2244 {
2245     int32_t rc = 0;
2246     buf_planes->plane_info.num_planes = 1;
2247     buf_planes->plane_info.mp[0].offset = 0;
2248     buf_planes->plane_info.mp[0].len =
2249         PAD_TO_SIZE(dim->width * dim->height, padding->plane_padding);
2250     buf_planes->plane_info.frame_len =
2251         buf_planes->plane_info.mp[0].len;
2252 
2253     buf_planes->plane_info.mp[0].offset_x =0;
2254     buf_planes->plane_info.mp[0].offset_y = 0;
2255     buf_planes->plane_info.mp[0].stride = dim->width;
2256     buf_planes->plane_info.mp[0].scanline = dim->height;
2257     return rc;
2258 }
2259 
2260 /*===========================================================================
2261  * FUNCTION   : mm_stream_calc_offset_postproc
2262  *
2263  * DESCRIPTION: calculate postprocess frame offset
2264  *
2265  * PARAMETERS :
2266  *   @stream_info: ptr to stream info
2267  *   @padding : padding information
2268  *   @buf_planes : [out] buffer plane information
2269  *
2270  * RETURN     : int32_t type of status
2271  *              0  -- success
2272  *              -1 -- failure
2273  *==========================================================================*/
mm_stream_calc_offset_postproc(cam_stream_info_t * stream_info,cam_padding_info_t * padding,cam_stream_buf_plane_info_t * buf_planes)2274 int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info,
2275                                        cam_padding_info_t *padding,
2276                                        cam_stream_buf_plane_info_t *buf_planes)
2277 {
2278     int32_t rc = 0;
2279     cam_stream_type_t type = CAM_STREAM_TYPE_DEFAULT;
2280     if (stream_info->reprocess_config.pp_type == CAM_OFFLINE_REPROCESS_TYPE) {
2281         type = stream_info->reprocess_config.offline.input_stream_type;
2282         if (CAM_STREAM_TYPE_DEFAULT == type) {
2283             if (buf_planes->plane_info.frame_len == 0) {
2284                 // take offset from input source
2285                 *buf_planes = stream_info->reprocess_config.offline.input_buf_planes;
2286                 return rc;
2287             }
2288         } else {
2289             type = stream_info->reprocess_config.offline.input_stream_type;
2290         }
2291     } else {
2292         type = stream_info->reprocess_config.online.input_stream_type;
2293     }
2294 
2295     switch (type) {
2296     case CAM_STREAM_TYPE_PREVIEW:
2297     case CAM_STREAM_TYPE_CALLBACK:
2298     case CAM_STREAM_TYPE_POSTVIEW:
2299         rc = mm_stream_calc_offset_preview(stream_info->fmt,
2300                                            &stream_info->dim,
2301                                            buf_planes);
2302         break;
2303     case CAM_STREAM_TYPE_SNAPSHOT:
2304     case CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT:
2305         rc = mm_stream_calc_offset_snapshot(stream_info->fmt,
2306                                             &stream_info->dim,
2307                                             padding,
2308                                             buf_planes);
2309         break;
2310     case CAM_STREAM_TYPE_VIDEO:
2311         rc = mm_stream_calc_offset_video(&stream_info->dim,
2312                                          buf_planes);
2313         break;
2314     case CAM_STREAM_TYPE_RAW:
2315         rc = mm_stream_calc_offset_raw(stream_info->fmt,
2316                                        &stream_info->dim,
2317                                        padding,
2318                                        buf_planes);
2319         break;
2320     case CAM_STREAM_TYPE_METADATA:
2321         rc = mm_stream_calc_offset_metadata(&stream_info->dim,
2322                                             padding,
2323                                             buf_planes);
2324         break;
2325     default:
2326         CDBG_ERROR("%s: not supported for stream type %d",
2327                    __func__, type);
2328         rc = -1;
2329         break;
2330     }
2331     return rc;
2332 }
2333 
2334 /*===========================================================================
2335  * FUNCTION   : mm_stream_calc_offset
2336  *
2337  * DESCRIPTION: calculate frame offset based on format and padding information
2338  *
2339  * PARAMETERS :
2340  *   @my_obj  : stream object
2341  *
2342  * RETURN     : int32_t type of status
2343  *              0  -- success
2344  *              -1 -- failure
2345  *==========================================================================*/
mm_stream_calc_offset(mm_stream_t * my_obj)2346 int32_t mm_stream_calc_offset(mm_stream_t *my_obj)
2347 {
2348     int32_t rc = 0;
2349 
2350     cam_dimension_t dim = my_obj->stream_info->dim;
2351     if (my_obj->stream_info->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
2352         if (my_obj->stream_info->pp_config.rotation == ROTATE_90 ||
2353             my_obj->stream_info->pp_config.rotation == ROTATE_270) {
2354             // rotated by 90 or 270, need to switch width and height
2355             dim.width = my_obj->stream_info->dim.height;
2356             dim.height = my_obj->stream_info->dim.width;
2357         }
2358     }
2359 
2360     switch (my_obj->stream_info->stream_type) {
2361     case CAM_STREAM_TYPE_PREVIEW:
2362     case CAM_STREAM_TYPE_CALLBACK:
2363     case CAM_STREAM_TYPE_POSTVIEW:
2364         rc = mm_stream_calc_offset_preview(my_obj->stream_info->fmt,
2365                                            &dim,
2366                                            &my_obj->stream_info->buf_planes);
2367         break;
2368     case CAM_STREAM_TYPE_SNAPSHOT:
2369     case CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT:
2370         rc = mm_stream_calc_offset_snapshot(my_obj->stream_info->fmt,
2371                                             &dim,
2372                                             &my_obj->padding_info,
2373                                             &my_obj->stream_info->buf_planes);
2374         break;
2375     case CAM_STREAM_TYPE_OFFLINE_PROC:
2376         rc = mm_stream_calc_offset_postproc(my_obj->stream_info,
2377                                             &my_obj->padding_info,
2378                                             &my_obj->stream_info->buf_planes);
2379         break;
2380     case CAM_STREAM_TYPE_VIDEO:
2381         rc = mm_stream_calc_offset_video(&dim,
2382                                          &my_obj->stream_info->buf_planes);
2383         break;
2384     case CAM_STREAM_TYPE_RAW:
2385         rc = mm_stream_calc_offset_raw(my_obj->stream_info->fmt,
2386                                        &dim,
2387                                        &my_obj->padding_info,
2388                                        &my_obj->stream_info->buf_planes);
2389         break;
2390     case CAM_STREAM_TYPE_METADATA:
2391         rc = mm_stream_calc_offset_metadata(&dim,
2392                                             &my_obj->padding_info,
2393                                             &my_obj->stream_info->buf_planes);
2394         break;
2395     default:
2396         CDBG_ERROR("%s: not supported for stream type %d",
2397                    __func__, my_obj->stream_info->stream_type);
2398         rc = -1;
2399         break;
2400     }
2401 
2402     my_obj->frame_offset = my_obj->stream_info->buf_planes.plane_info;
2403     return rc;
2404 }
2405 
2406 /*===========================================================================
2407  * FUNCTION   : mm_stream_sync_info
2408  *
2409  * DESCRIPTION: synchronize stream information with server
2410  *
2411  * PARAMETERS :
2412  *   @my_obj  : stream object
2413  *
2414  * RETURN     : int32_t type of status
2415  *              0  -- success
2416  *              -1 -- failure
2417  * NOTE       : assume stream info buffer is mapped to server and filled in with
2418  *              stream information by upper layer. This call will let server to
2419  *              synchornize the stream information with HAL. If server find any
2420  *              fields that need to be changed accroding to hardware configuration,
2421  *              server will modify corresponding fields so that HAL could know
2422  *              about it.
2423  *==========================================================================*/
mm_stream_sync_info(mm_stream_t * my_obj)2424 int32_t mm_stream_sync_info(mm_stream_t *my_obj)
2425 {
2426     int32_t rc = 0;
2427     int32_t value = 0;
2428     my_obj->stream_info->stream_svr_id = my_obj->server_stream_id;
2429     rc = mm_stream_calc_offset(my_obj);
2430 
2431     if (rc == 0) {
2432         rc = mm_camera_util_s_ctrl(my_obj->fd,
2433                                    CAM_PRIV_STREAM_INFO_SYNC,
2434                                    &value);
2435     }
2436     return rc;
2437 }
2438 
2439 /*===========================================================================
2440  * FUNCTION   : mm_stream_set_fmt
2441  *
2442  * DESCRIPTION: set stream format to kernel via v4l2 ioctl
2443  *
2444  * PARAMETERS :
2445  *   @my_obj  : stream object
2446  *
2447  * RETURN     : int32_t type of status
2448  *              0  -- success
2449  *              -1 -- failure
2450  *==========================================================================*/
mm_stream_set_fmt(mm_stream_t * my_obj)2451 int32_t mm_stream_set_fmt(mm_stream_t *my_obj)
2452 {
2453     int32_t rc = 0;
2454     struct v4l2_format fmt;
2455     struct msm_v4l2_format_data msm_fmt;
2456     int i;
2457 
2458     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
2459          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
2460 
2461     if (my_obj->stream_info->dim.width == 0 ||
2462         my_obj->stream_info->dim.height == 0) {
2463         CDBG_ERROR("%s:invalid input[w=%d,h=%d,fmt=%d]\n",
2464                    __func__,
2465                    my_obj->stream_info->dim.width,
2466                    my_obj->stream_info->dim.height,
2467                    my_obj->stream_info->fmt);
2468         return -1;
2469     }
2470 
2471     memset(&fmt, 0, sizeof(fmt));
2472     memset(&msm_fmt, 0, sizeof(msm_fmt));
2473     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2474     msm_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2475     msm_fmt.width = my_obj->stream_info->dim.width;
2476     msm_fmt.height = my_obj->stream_info->dim.height;
2477     msm_fmt.pixelformat = mm_stream_get_v4l2_fmt(my_obj->stream_info->fmt);
2478     msm_fmt.num_planes = my_obj->frame_offset.num_planes;
2479     for (i = 0; i < msm_fmt.num_planes; i++) {
2480         msm_fmt.plane_sizes[i] = my_obj->frame_offset.mp[i].len;
2481     }
2482 
2483     memcpy(fmt.fmt.raw_data, &msm_fmt, sizeof(msm_fmt));
2484     rc = ioctl(my_obj->fd, VIDIOC_S_FMT, &fmt);
2485     return rc;
2486 }
2487 
2488 /*===========================================================================
2489  * FUNCTION   : mm_stream_buf_done
2490  *
2491  * DESCRIPTION: enqueue buffer back to kernel
2492  *
2493  * PARAMETERS :
2494  *   @my_obj       : stream object
2495  *   @frame        : frame to be enqueued back to kernel
2496  *
2497  * RETURN     : int32_t type of status
2498  *              0  -- success
2499  *              -1 -- failure
2500  *==========================================================================*/
mm_stream_buf_done(mm_stream_t * my_obj,mm_camera_buf_def_t * frame)2501 int32_t mm_stream_buf_done(mm_stream_t * my_obj,
2502                            mm_camera_buf_def_t *frame)
2503 {
2504     int32_t rc = 0;
2505     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
2506          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
2507 
2508     pthread_mutex_lock(&my_obj->buf_lock);
2509     if(my_obj->buf_status[frame->buf_idx].buf_refcnt == 0) {
2510         CDBG("%s: Error Trying to free second time?(idx=%d) count=%d\n",
2511                    __func__, frame->buf_idx,
2512                    my_obj->buf_status[frame->buf_idx].buf_refcnt);
2513         rc = -1;
2514     }else{
2515         my_obj->buf_status[frame->buf_idx].buf_refcnt--;
2516         if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) {
2517             CDBG("<DEBUG> : Buf done for buffer:%d, stream:%d", frame->buf_idx, frame->stream_type);
2518             rc = mm_stream_qbuf(my_obj, frame);
2519             if(rc < 0) {
2520                 CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) errno=%d, %s\n",
2521                            __func__, frame->buf_idx, errno, strerror(errno));
2522             } else {
2523                 my_obj->buf_status[frame->buf_idx].in_kernel = 1;
2524             }
2525         }else{
2526             CDBG("<DEBUG> : Still ref count pending count :%d",
2527                  my_obj->buf_status[frame->buf_idx].buf_refcnt);
2528             CDBG("<DEBUG> : for buffer:%p:%d",
2529                  my_obj, frame->buf_idx);
2530         }
2531     }
2532     pthread_mutex_unlock(&my_obj->buf_lock);
2533     return rc;
2534 }
2535 
2536 /*===========================================================================
2537  * FUNCTION   : mm_stream_reg_buf_cb
2538  *
2539  * DESCRIPTION: Allow other stream to register dataCB at this stream.
2540  *
2541  * PARAMETERS :
2542  *   @my_obj       : stream object
2543  *   @val          : ptr to info about the callback to be registered
2544  *
2545  * RETURN     : int32_t type of status
2546  *              0  -- success
2547  *              -1 -- failure
2548  *==========================================================================*/
mm_stream_reg_buf_cb(mm_stream_t * my_obj,mm_stream_data_cb_t * val)2549 int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj,
2550                              mm_stream_data_cb_t *val)
2551 {
2552     int32_t rc = -1;
2553     uint8_t i;
2554     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
2555          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
2556 
2557     pthread_mutex_lock(&my_obj->cb_lock);
2558     for (i=0 ;i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
2559         if(NULL == my_obj->buf_cb[i].cb) {
2560             my_obj->buf_cb[i] = *val;
2561             rc = 0;
2562             break;
2563         }
2564     }
2565     pthread_mutex_unlock(&my_obj->cb_lock);
2566 
2567     return rc;
2568 }
2569