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         if (NULL == my_obj) {
391             CDBG_ERROR("%s: NULL camera object\n", __func__);
392             rc = -1;
393             break;
394         }
395         snprintf(dev_name, sizeof(dev_name), "/dev/%s",
396                  mm_camera_util_get_dev_name(my_obj->ch_obj->cam_obj->my_hdl));
397 
398         my_obj->fd = open(dev_name, O_RDWR | O_NONBLOCK);
399         if (my_obj->fd < 0) {
400             CDBG_ERROR("%s: open dev returned %d\n", __func__, my_obj->fd);
401             rc = -1;
402             break;
403         }
404         CDBG("%s: open dev fd = %d\n", __func__, my_obj->fd);
405         rc = mm_stream_set_ext_mode(my_obj);
406         if (0 == rc) {
407             my_obj->state = MM_STREAM_STATE_ACQUIRED;
408         } else {
409             /* failed setting ext_mode
410              * close fd */
411             close(my_obj->fd);
412             my_obj->fd = -1;
413             break;
414         }
415         break;
416     default:
417         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
418                    __func__, my_obj->state, evt, in_val, out_val);
419         break;
420     }
421     return rc;
422 }
423 
424 /*===========================================================================
425  * FUNCTION   : mm_stream_fsm_acquired
426  *
427  * DESCRIPTION: stream finite state machine function to handle event in AQUIRED
428  *              state.
429  *
430  * PARAMETERS :
431  *   @my_obj   : ptr to a stream object
432  *   @evt      : stream event to be processed
433  *   @in_val   : input event payload. Can be NULL if not needed.
434  *   @out_val  : output payload, Can be NULL if not needed.
435  *
436  * RETURN     : int32_t type of status
437  *              0  -- success
438  *              -1 -- failure
439  *==========================================================================*/
mm_stream_fsm_acquired(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)440 int32_t mm_stream_fsm_acquired(mm_stream_t *my_obj,
441                                mm_stream_evt_type_t evt,
442                                void * in_val,
443                                void * out_val)
444 {
445     int32_t rc = 0;
446 
447     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
448          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
449     switch(evt) {
450     case MM_STREAM_EVT_SET_FMT:
451         {
452             mm_camera_stream_config_t *config =
453                 (mm_camera_stream_config_t *)in_val;
454 
455             rc = mm_stream_config(my_obj, config);
456 
457             /* change state to configed */
458             my_obj->state = MM_STREAM_STATE_CFG;
459 
460             break;
461         }
462     case MM_STREAM_EVT_RELEASE:
463         rc = mm_stream_release(my_obj);
464         /* change state to not used */
465          my_obj->state = MM_STREAM_STATE_NOTUSED;
466         break;
467     case MM_STREAM_EVT_SET_PARM:
468         {
469             mm_evt_paylod_set_get_stream_parms_t *payload =
470                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
471             rc = mm_stream_set_parm(my_obj, payload->parms);
472         }
473         break;
474     case MM_STREAM_EVT_GET_PARM:
475         {
476             mm_evt_paylod_set_get_stream_parms_t *payload =
477                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
478             rc = mm_stream_get_parm(my_obj, payload->parms);
479         }
480         break;
481     default:
482         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
483                    __func__, my_obj->state, evt, in_val, out_val);
484     }
485     CDBG("%s :X rc = %d", __func__, rc);
486     return rc;
487 }
488 
489 /*===========================================================================
490  * FUNCTION   : mm_stream_fsm_cfg
491  *
492  * DESCRIPTION: stream finite state machine function to handle event in CONFIGURED
493  *              state.
494  *
495  * PARAMETERS :
496  *   @my_obj   : ptr to a stream object
497  *   @evt      : stream event to be processed
498  *   @in_val   : input event payload. Can be NULL if not needed.
499  *   @out_val  : output payload, Can be NULL if not needed.
500  *
501  * RETURN     : int32_t type of status
502  *              0  -- success
503  *              -1 -- failure
504  *==========================================================================*/
mm_stream_fsm_cfg(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)505 int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
506                           mm_stream_evt_type_t evt,
507                           void * in_val,
508                           void * out_val)
509 {
510     int32_t rc = 0;
511     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
512          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
513     switch(evt) {
514     case MM_STREAM_EVT_SET_FMT:
515         {
516             mm_camera_stream_config_t *config =
517                 (mm_camera_stream_config_t *)in_val;
518 
519             rc = mm_stream_config(my_obj, config);
520 
521             /* change state to configed */
522             my_obj->state = MM_STREAM_STATE_CFG;
523 
524             break;
525         }
526     case MM_STREAM_EVT_RELEASE:
527         rc = mm_stream_release(my_obj);
528         my_obj->state = MM_STREAM_STATE_NOTUSED;
529         break;
530     case MM_STREAM_EVT_SET_PARM:
531         {
532             mm_evt_paylod_set_get_stream_parms_t *payload =
533                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
534             rc = mm_stream_set_parm(my_obj, payload->parms);
535         }
536         break;
537     case MM_STREAM_EVT_GET_PARM:
538         {
539             mm_evt_paylod_set_get_stream_parms_t *payload =
540                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
541             rc = mm_stream_get_parm(my_obj, payload->parms);
542         }
543         break;
544     case MM_STREAM_EVT_GET_BUF:
545         rc = mm_stream_init_bufs(my_obj);
546         /* change state to buff allocated */
547         if(0 == rc) {
548             my_obj->state = MM_STREAM_STATE_BUFFED;
549         }
550         break;
551     default:
552         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
553                    __func__, my_obj->state, evt, in_val, out_val);
554     }
555     CDBG("%s :X rc = %d", __func__, rc);
556     return rc;
557 }
558 
559 /*===========================================================================
560  * FUNCTION   : mm_stream_fsm_buffed
561  *
562  * DESCRIPTION: stream finite state machine function to handle event in BUFFED
563  *              state.
564  *
565  * PARAMETERS :
566  *   @my_obj   : ptr to a stream object
567  *   @evt      : stream event to be processed
568  *   @in_val   : input event payload. Can be NULL if not needed.
569  *   @out_val  : output payload, Can be NULL if not needed.
570  *
571  * RETURN     : int32_t type of status
572  *              0  -- success
573  *              -1 -- failure
574  *==========================================================================*/
mm_stream_fsm_buffed(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)575 int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
576                              mm_stream_evt_type_t evt,
577                              void * in_val,
578                              void * out_val)
579 {
580     int32_t rc = 0;
581     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
582          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
583     switch(evt) {
584     case MM_STREAM_EVT_PUT_BUF:
585         rc = mm_stream_deinit_bufs(my_obj);
586         /* change state to configed */
587         my_obj->state = MM_STREAM_STATE_CFG;
588         break;
589     case MM_STREAM_EVT_REG_BUF:
590         rc = mm_stream_reg_buf(my_obj);
591         /* change state to regged */
592         if(0 == rc) {
593             my_obj->state = MM_STREAM_STATE_REG;
594         }
595         break;
596     case MM_STREAM_EVT_SET_PARM:
597         {
598             mm_evt_paylod_set_get_stream_parms_t *payload =
599                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
600             rc = mm_stream_set_parm(my_obj, payload->parms);
601         }
602         break;
603     case MM_STREAM_EVT_GET_PARM:
604         {
605             mm_evt_paylod_set_get_stream_parms_t *payload =
606                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
607             rc = mm_stream_get_parm(my_obj, payload->parms);
608         }
609         break;
610     default:
611         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
612                    __func__, my_obj->state, evt, in_val, out_val);
613     }
614     CDBG("%s :X rc = %d", __func__, rc);
615     return rc;
616 }
617 
618 /*===========================================================================
619  * FUNCTION   : mm_stream_fsm_reg
620  *
621  * DESCRIPTION: stream finite state machine function to handle event in REGGED
622  *              state.
623  *
624  * PARAMETERS :
625  *   @my_obj   : ptr to a stream object
626  *   @evt      : stream event to be processed
627  *   @in_val   : input event payload. Can be NULL if not needed.
628  *   @out_val  : output payload, Can be NULL if not needed.
629  *
630  * RETURN     : int32_t type of status
631  *              0  -- success
632  *              -1 -- failure
633  *==========================================================================*/
mm_stream_fsm_reg(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)634 int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
635                           mm_stream_evt_type_t evt,
636                           void * in_val,
637                           void * out_val)
638 {
639     int32_t rc = 0;
640     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
641          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
642 
643     switch(evt) {
644     case MM_STREAM_EVT_UNREG_BUF:
645         rc = mm_stream_unreg_buf(my_obj);
646 
647         /* change state to buffed */
648         my_obj->state = MM_STREAM_STATE_BUFFED;
649         break;
650     case MM_STREAM_EVT_START:
651         {
652             uint8_t has_cb = 0;
653             uint8_t i;
654             /* launch cmd thread if CB is not null */
655             pthread_mutex_lock(&my_obj->cb_lock);
656             for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
657                 if(NULL != my_obj->buf_cb[i].cb) {
658                     has_cb = 1;
659                     break;
660                 }
661             }
662             pthread_mutex_unlock(&my_obj->cb_lock);
663 
664             if (has_cb) {
665                 mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
666                                             mm_stream_dispatch_app_data,
667                                             (void *)my_obj);
668             }
669 
670             my_obj->state = MM_STREAM_STATE_ACTIVE;
671             rc = mm_stream_streamon(my_obj);
672             if (0 != rc) {
673                 /* failed stream on, need to release cmd thread if it's launched */
674                 if (has_cb) {
675                     mm_camera_cmd_thread_release(&my_obj->cmd_thread);
676                 }
677                 my_obj->state = MM_STREAM_STATE_REG;
678                 break;
679             }
680         }
681         break;
682     case MM_STREAM_EVT_SET_PARM:
683         {
684             mm_evt_paylod_set_get_stream_parms_t *payload =
685                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
686             rc = mm_stream_set_parm(my_obj, payload->parms);
687         }
688         break;
689     case MM_STREAM_EVT_GET_PARM:
690         {
691             mm_evt_paylod_set_get_stream_parms_t *payload =
692                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
693             rc = mm_stream_get_parm(my_obj, payload->parms);
694         }
695         break;
696     default:
697         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
698                    __func__, my_obj->state, evt, in_val, out_val);
699     }
700     CDBG("%s :X rc = %d", __func__, rc);
701     return rc;
702 }
703 
704 /*===========================================================================
705  * FUNCTION   : mm_stream_fsm_active
706  *
707  * DESCRIPTION: stream finite state machine function to handle event in ACTIVE
708  *              state.
709  *
710  * PARAMETERS :
711  *   @my_obj   : ptr to a stream object
712  *   @evt      : stream event to be processed
713  *   @in_val   : input event payload. Can be NULL if not needed.
714  *   @out_val  : output payload, Can be NULL if not needed.
715  *
716  * RETURN     : int32_t type of status
717  *              0  -- success
718  *              -1 -- failure
719  *==========================================================================*/
mm_stream_fsm_active(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)720 int32_t mm_stream_fsm_active(mm_stream_t * my_obj,
721                              mm_stream_evt_type_t evt,
722                              void * in_val,
723                              void * out_val)
724 {
725     int32_t rc = 0;
726     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
727          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
728     switch(evt) {
729     case MM_STREAM_EVT_QBUF:
730         rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val);
731         break;
732     case MM_STREAM_EVT_STOP:
733         {
734             uint8_t has_cb = 0;
735             uint8_t i;
736             rc = mm_stream_streamoff(my_obj);
737 
738             pthread_mutex_lock(&my_obj->cb_lock);
739             for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
740                 if(NULL != my_obj->buf_cb[i].cb) {
741                     has_cb = 1;
742                     break;
743                 }
744             }
745             pthread_mutex_unlock(&my_obj->cb_lock);
746 
747             if (has_cb) {
748                 mm_camera_cmd_thread_release(&my_obj->cmd_thread);
749             }
750             my_obj->state = MM_STREAM_STATE_REG;
751         }
752         break;
753     case MM_STREAM_EVT_SET_PARM:
754         {
755             mm_evt_paylod_set_get_stream_parms_t *payload =
756                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
757             rc = mm_stream_set_parm(my_obj, payload->parms);
758         }
759         break;
760     case MM_STREAM_EVT_GET_PARM:
761         {
762             mm_evt_paylod_set_get_stream_parms_t *payload =
763                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
764             rc = mm_stream_get_parm(my_obj, payload->parms);
765         }
766         break;
767     case MM_STREAM_EVT_DO_ACTION:
768         rc = mm_stream_do_action(my_obj, in_val);
769         break;
770     default:
771         CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
772                    __func__, my_obj->state, evt, in_val, out_val);
773     }
774     CDBG("%s :X rc = %d", __func__, rc);
775     return rc;
776 }
777 
778 /*===========================================================================
779  * FUNCTION   : mm_stream_config
780  *
781  * DESCRIPTION: configure a stream
782  *
783  * PARAMETERS :
784  *   @my_obj       : stream object
785  *   @config       : stream configuration
786  *
787  * RETURN     : int32_t type of status
788  *              0  -- success
789  *              -1 -- failure
790  *==========================================================================*/
mm_stream_config(mm_stream_t * my_obj,mm_camera_stream_config_t * config)791 int32_t mm_stream_config(mm_stream_t *my_obj,
792                          mm_camera_stream_config_t *config)
793 {
794     int32_t rc = 0;
795     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
796          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
797     my_obj->stream_info = config->stream_info;
798     my_obj->buf_num = config->stream_info->num_bufs;
799     my_obj->mem_vtbl = config->mem_vtbl;
800     my_obj->padding_info = config->padding_info;
801     /* cd through intf always palced at idx 0 of buf_cb */
802     my_obj->buf_cb[0].cb = config->stream_cb;
803     my_obj->buf_cb[0].user_data = config->userdata;
804     my_obj->buf_cb[0].cb_count = -1; /* infinite by default */
805 
806     rc = mm_stream_sync_info(my_obj);
807     if (rc == 0) {
808         rc = mm_stream_set_fmt(my_obj);
809     }
810     return rc;
811 }
812 
813 /*===========================================================================
814  * FUNCTION   : mm_stream_release
815  *
816  * DESCRIPTION: release a stream resource
817  *
818  * PARAMETERS :
819  *   @my_obj       : stream object
820  *
821  * RETURN     : int32_t type of status
822  *              0  -- success
823  *              -1 -- failure
824  *==========================================================================*/
mm_stream_release(mm_stream_t * my_obj)825 int32_t mm_stream_release(mm_stream_t *my_obj)
826 {
827     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
828          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
829 
830     /* close fd */
831     if(my_obj->fd >= 0)
832     {
833         close(my_obj->fd);
834     }
835 
836     /* destroy mutex */
837     pthread_mutex_destroy(&my_obj->buf_lock);
838     pthread_mutex_destroy(&my_obj->cb_lock);
839 
840     /* reset stream obj */
841     memset(my_obj, 0, sizeof(mm_stream_t));
842     my_obj->fd = -1;
843 
844     return 0;
845 }
846 
847 /*===========================================================================
848  * FUNCTION   : mm_stream_streamon
849  *
850  * DESCRIPTION: stream on a stream. sending v4l2 request to kernel
851  *
852  * PARAMETERS :
853  *   @my_obj       : stream object
854  *
855  * RETURN     : int32_t type of status
856  *              0  -- success
857  *              -1 -- failure
858  *==========================================================================*/
mm_stream_streamon(mm_stream_t * my_obj)859 int32_t mm_stream_streamon(mm_stream_t *my_obj)
860 {
861     int32_t rc;
862     enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
863 
864     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
865          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
866 
867     rc = ioctl(my_obj->fd, VIDIOC_STREAMON, &buf_type);
868     if (rc < 0) {
869         CDBG_ERROR("%s: ioctl VIDIOC_STREAMON failed: rc=%d\n",
870                    __func__, rc);
871         /* remove fd from data poll thread in case of failure */
872         mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl, mm_camera_sync_call);
873     }
874     CDBG("%s :X rc = %d",__func__,rc);
875     return rc;
876 }
877 
878 /*===========================================================================
879  * FUNCTION   : mm_stream_streamoff
880  *
881  * DESCRIPTION: stream off a stream. sending v4l2 request to kernel
882  *
883  * PARAMETERS :
884  *   @my_obj       : stream object
885  *
886  * RETURN     : int32_t type of status
887  *              0  -- success
888  *              -1 -- failure
889  *==========================================================================*/
mm_stream_streamoff(mm_stream_t * my_obj)890 int32_t mm_stream_streamoff(mm_stream_t *my_obj)
891 {
892     int32_t rc;
893     enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
894     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
895          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
896 
897     /* step1: remove fd from data poll thread */
898     rc = mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
899             my_obj->my_hdl, mm_camera_sync_call);
900     if (rc < 0) {
901         /* The error might be due to async update. In this case
902          * wait for all updates to complete before proceeding. */
903         rc = mm_camera_poll_thread_commit_updates(&my_obj->ch_obj->poll_thread[0]);
904         if (rc < 0) {
905             CDBG_ERROR("%s: Poll sync failed %d",
906                  __func__, rc);
907         }
908     }
909 
910     /* step2: stream off */
911     rc = ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type);
912     if (rc < 0) {
913         CDBG_ERROR("%s: STREAMOFF failed: %s\n",
914                 __func__, strerror(errno));
915     }
916     CDBG("%s :X rc = %d",__func__,rc);
917     return rc;
918 }
919 
920 /*===========================================================================
921  * FUNCTION   : mm_stream_read_msm_frame
922  *
923  * DESCRIPTION: dequeue a stream buffer from kernel queue
924  *
925  * PARAMETERS :
926  *   @my_obj       : stream object
927  *   @buf_info     : ptr to a struct storing buffer information
928  *   @num_planes   : number of planes in the buffer
929  *
930  * RETURN     : int32_t type of status
931  *              0  -- success
932  *              -1 -- failure
933  *==========================================================================*/
mm_stream_read_msm_frame(mm_stream_t * my_obj,mm_camera_buf_info_t * buf_info,uint8_t num_planes)934 int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
935                                  mm_camera_buf_info_t* buf_info,
936                                  uint8_t num_planes)
937 {
938     int32_t rc = 0;
939     struct v4l2_buffer vb;
940     struct v4l2_plane planes[VIDEO_MAX_PLANES];
941     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
942          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
943 
944     memset(&vb,  0,  sizeof(vb));
945     vb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
946     vb.memory = V4L2_MEMORY_USERPTR;
947     vb.m.planes = &planes[0];
948     vb.length = num_planes;
949 
950     rc = ioctl(my_obj->fd, VIDIOC_DQBUF, &vb);
951     if (0 > rc) {
952         CDBG_ERROR("%s: VIDIOC_DQBUF ioctl call failed on stream type %d (rc=%d): %s",
953             __func__, my_obj->stream_info->stream_type, rc, strerror(errno));
954     } else {
955         pthread_mutex_lock(&my_obj->buf_lock);
956         my_obj->queued_buffer_count--;
957         if (0 == my_obj->queued_buffer_count) {
958             CDBG_HIGH("%s: Stoping poll on stream %p type: %d", __func__,
959                 my_obj, my_obj->stream_info->stream_type);
960             mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
961                 my_obj->my_hdl, mm_camera_async_call);
962             CDBG_HIGH("%s: Stopped poll on stream %p type: %d", __func__,
963                 my_obj, my_obj->stream_info->stream_type);
964         }
965         pthread_mutex_unlock(&my_obj->buf_lock);
966         int8_t idx = vb.index;
967         buf_info->buf = &my_obj->buf[idx];
968         buf_info->frame_idx = vb.sequence;
969         buf_info->stream_id = my_obj->my_hdl;
970 
971         buf_info->buf->stream_id = my_obj->my_hdl;
972         buf_info->buf->buf_idx = idx;
973         buf_info->buf->frame_idx = vb.sequence;
974         buf_info->buf->ts.tv_sec  = vb.timestamp.tv_sec;
975         buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000;
976         CDBG("%s: VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d, rc %d",
977             __func__, vb.index, buf_info->buf->frame_idx,
978             my_obj->stream_info->stream_type, rc);
979 
980         buf_info->buf->is_uv_subsampled =
981             (vb.reserved == V4L2_PIX_FMT_NV14 || vb.reserved == V4L2_PIX_FMT_NV41);
982 
983         if ( NULL != my_obj->mem_vtbl.clean_invalidate_buf ) {
984             rc = my_obj->mem_vtbl.clean_invalidate_buf(idx,
985                 my_obj->mem_vtbl.user_data);
986             if (0 > rc) {
987                 CDBG_ERROR("%s: Clean invalidate cache failed on buffer index: %d",
988                     __func__, idx);
989             }
990         } else {
991             CDBG_ERROR("%s: Clean invalidate cache op not supported", __func__);
992         }
993     }
994 
995     CDBG("%s :X rc = %d",__func__,rc);
996     return rc;
997 }
998 
999 /*===========================================================================
1000  * FUNCTION   : mm_stream_set_parms
1001  *
1002  * DESCRIPTION: set parameters per stream
1003  *
1004  * PARAMETERS :
1005  *   @my_obj       : stream object
1006  *   @in_value     : ptr to a param struct to be set to server
1007  *
1008  * RETURN     : int32_t type of status
1009  *              0  -- success
1010  *              -1 -- failure
1011  * NOTE       : Assume the parms struct buf is already mapped to server via
1012  *              domain socket. Corresponding fields of parameters to be set
1013  *              are already filled in by upper layer caller.
1014  *==========================================================================*/
mm_stream_set_parm(mm_stream_t * my_obj,cam_stream_parm_buffer_t * in_value)1015 int32_t mm_stream_set_parm(mm_stream_t *my_obj,
1016                            cam_stream_parm_buffer_t *in_value)
1017 {
1018     int32_t rc = -1;
1019     int32_t value = 0;
1020     if (in_value != NULL) {
1021         rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
1022     }
1023     return rc;
1024 }
1025 
1026 /*===========================================================================
1027  * FUNCTION   : mm_stream_get_parms
1028  *
1029  * DESCRIPTION: get parameters per stream
1030  *
1031  * PARAMETERS :
1032  *   @my_obj       : stream object
1033  *   @in_value     : ptr to a param struct to be get from server
1034  *
1035  * RETURN     : int32_t type of status
1036  *              0  -- success
1037  *              -1 -- failure
1038  * NOTE       : Assume the parms struct buf is already mapped to server via
1039  *              domain socket. Corresponding fields of parameters to be get
1040  *              are already filled in by upper layer caller.
1041  *==========================================================================*/
mm_stream_get_parm(mm_stream_t * my_obj,cam_stream_parm_buffer_t * in_value)1042 int32_t mm_stream_get_parm(mm_stream_t *my_obj,
1043                            cam_stream_parm_buffer_t *in_value)
1044 {
1045     int32_t rc = -1;
1046     int32_t value = 0;
1047     if (in_value != NULL) {
1048         rc = mm_camera_util_g_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
1049     }
1050     return rc;
1051 }
1052 
1053 /*===========================================================================
1054  * FUNCTION   : mm_stream_do_actions
1055  *
1056  * DESCRIPTION: request server to perform stream based actions
1057  *
1058  * PARAMETERS :
1059  *   @my_obj       : stream object
1060  *   @in_value     : ptr to a struct of actions to be performed by the server
1061  *
1062  * RETURN     : int32_t type of status
1063  *              0  -- success
1064  *              -1 -- failure
1065  * NOTE       : Assume the action struct buf is already mapped to server via
1066  *              domain socket. Corresponding fields of actions to be performed
1067  *              are already filled in by upper layer caller.
1068  *==========================================================================*/
mm_stream_do_action(mm_stream_t * my_obj,void * in_value)1069 int32_t mm_stream_do_action(mm_stream_t *my_obj,
1070                             void *in_value)
1071 {
1072     int32_t rc = -1;
1073     int32_t value = 0;
1074     if (in_value != NULL) {
1075         rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
1076     }
1077     return rc;
1078 }
1079 
1080 /*===========================================================================
1081  * FUNCTION   : mm_stream_set_ext_mode
1082  *
1083  * DESCRIPTION: set stream extended mode to server via v4l2 ioctl
1084  *
1085  * PARAMETERS :
1086  *   @my_obj       : stream object
1087  *
1088  * RETURN     : int32_t type of status
1089  *              0  -- success
1090  *              -1 -- failure
1091  * NOTE       : Server will return a server stream id that uniquely identify
1092  *              this stream on server side. Later on communication to server
1093  *              per stream should use this server stream id.
1094  *==========================================================================*/
mm_stream_set_ext_mode(mm_stream_t * my_obj)1095 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj)
1096 {
1097     int32_t rc = 0;
1098     struct v4l2_streamparm s_parm;
1099     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1100          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1101 
1102     memset(&s_parm, 0, sizeof(s_parm));
1103     s_parm.type =  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1104 
1105     rc = ioctl(my_obj->fd, VIDIOC_S_PARM, &s_parm);
1106     CDBG("%s:stream fd=%d, rc=%d, extended_mode=%d\n",
1107          __func__, my_obj->fd, rc, s_parm.parm.capture.extendedmode);
1108     if (rc == 0) {
1109         /* get server stream id */
1110         my_obj->server_stream_id = s_parm.parm.capture.extendedmode;
1111     }
1112     return rc;
1113 }
1114 
1115 /*===========================================================================
1116  * FUNCTION   : mm_stream_qbuf
1117  *
1118  * DESCRIPTION: enqueue buffer back to kernel queue for furture use
1119  *
1120  * PARAMETERS :
1121  *   @my_obj       : stream object
1122  *   @buf          : ptr to a struct storing buffer information
1123  *
1124  * RETURN     : int32_t type of status
1125  *              0  -- success
1126  *              -1 -- failure
1127  *==========================================================================*/
mm_stream_qbuf(mm_stream_t * my_obj,mm_camera_buf_def_t * buf)1128 int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf)
1129 {
1130     int32_t rc = 0;
1131     struct v4l2_buffer buffer;
1132     struct v4l2_plane planes[VIDEO_MAX_PLANES];
1133     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d, stream type = %d",
1134          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state,
1135          my_obj->stream_info->stream_type);
1136 
1137     memcpy(planes, buf->planes, sizeof(planes));
1138     memset(&buffer, 0, sizeof(buffer));
1139     buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1140     buffer.memory = V4L2_MEMORY_USERPTR;
1141     buffer.index = buf->buf_idx;
1142     buffer.m.planes = &planes[0];
1143     buffer.length = buf->num_planes;
1144 
1145     CDBG("%s:plane 0: stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d, offset = %d, data_offset = %d\n", __func__,
1146          buf->stream_id, buf->fd, buffer.index, buffer.length, buf->planes[0].reserved[0], buf->planes[0].data_offset);
1147     CDBG("%s:plane 1: stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d, offset = %d, data_offset = %d\n", __func__,
1148          buf->stream_id, buf->fd, buffer.index, buffer.length, buf->planes[1].reserved[0], buf->planes[1].data_offset);
1149 
1150     if ( NULL != my_obj->mem_vtbl.invalidate_buf ) {
1151         rc = my_obj->mem_vtbl.invalidate_buf(buffer.index,
1152                                              my_obj->mem_vtbl.user_data);
1153         if ( 0 > rc ) {
1154             CDBG_ERROR("%s: Cache invalidate failed on buffer index: %d",
1155                        __func__,
1156                        buffer.index);
1157             return rc;
1158         }
1159     } else {
1160         CDBG_ERROR("%s: Cache invalidate op not added", __func__);
1161     }
1162 
1163     my_obj->queued_buffer_count++;
1164     if (1 == my_obj->queued_buffer_count) {
1165         /* Add fd to data poll thread */
1166         CDBG_HIGH("%s: Starting poll on stream %p type: %d", __func__,
1167             my_obj,my_obj->stream_info->stream_type);
1168         rc = mm_camera_poll_thread_add_poll_fd(&my_obj->ch_obj->poll_thread[0],
1169             my_obj->my_hdl, my_obj->fd, mm_stream_data_notify, (void*)my_obj,
1170             mm_camera_async_call);
1171         if (0 > rc) {
1172             CDBG_ERROR("%s: Add poll on stream %p type: %d fd error (rc=%d)",
1173                 __func__, my_obj, my_obj->stream_info->stream_type, rc);
1174         } else {
1175             CDBG_HIGH("%s: Started poll on stream %p type: %d", __func__,
1176                 my_obj, my_obj->stream_info->stream_type);
1177         }
1178     }
1179 
1180     rc = ioctl(my_obj->fd, VIDIOC_QBUF, &buffer);
1181     if (0 > rc) {
1182         CDBG_ERROR("%s: VIDIOC_QBUF ioctl call failed on stream type %d (rc=%d): %s",
1183             __func__, my_obj->stream_info->stream_type, rc, strerror(errno));
1184         my_obj->queued_buffer_count--;
1185         if (0 == my_obj->queued_buffer_count) {
1186             /* Remove fd from data poll in case of failing
1187              * first buffer queuing attempt */
1188             CDBG_HIGH("%s: Stoping poll on stream %p type: %d", __func__,
1189                 my_obj, my_obj->stream_info->stream_type);
1190             mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
1191                 my_obj->my_hdl, mm_camera_async_call);
1192             CDBG_HIGH("%s: Stopped poll on stream %p type: %d", __func__,
1193                 my_obj, my_obj->stream_info->stream_type);
1194         }
1195     } else {
1196         CDBG("%s: VIDIOC_QBUF buf_index %d, stream type %d, rc %d", __func__,
1197             buffer.index, my_obj->stream_info->stream_type, rc);
1198     }
1199 
1200     return rc;
1201 }
1202 
1203 /*===========================================================================
1204  * FUNCTION   : mm_stream_request_buf
1205  *
1206  * DESCRIPTION: This function let kernel know the amount of buffers need to
1207  *              be registered via v4l2 ioctl.
1208  *
1209  * PARAMETERS :
1210  *   @my_obj       : stream object
1211  *
1212  * RETURN     : int32_t type of status
1213  *              0  -- success
1214  *              -1 -- failure
1215  *==========================================================================*/
mm_stream_request_buf(mm_stream_t * my_obj)1216 int32_t mm_stream_request_buf(mm_stream_t * my_obj)
1217 {
1218     int32_t rc = 0;
1219     struct v4l2_requestbuffers bufreq;
1220     uint8_t buf_num = my_obj->buf_num;
1221     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1222          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1223 
1224     CDBG_ERROR("%s: buf_num = %d, stream type = %d",
1225          __func__, buf_num, my_obj->stream_info->stream_type);
1226 
1227     if(buf_num > MM_CAMERA_MAX_NUM_FRAMES) {
1228         CDBG_ERROR("%s: buf num %d > max limit %d\n",
1229                    __func__, buf_num, MM_CAMERA_MAX_NUM_FRAMES);
1230         return -1;
1231     }
1232 
1233     memset(&bufreq, 0, sizeof(bufreq));
1234     bufreq.count = buf_num;
1235     bufreq.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1236     bufreq.memory = V4L2_MEMORY_USERPTR;
1237     rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
1238     if (rc < 0) {
1239       CDBG_ERROR("%s: fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d\n",
1240            __func__, my_obj->fd, rc);
1241     }
1242 
1243     CDBG("%s :X rc = %d",__func__,rc);
1244     return rc;
1245 }
1246 
1247 /*===========================================================================
1248  * FUNCTION   : mm_stream_map_buf
1249  *
1250  * DESCRIPTION: mapping stream buffer via domain socket to server
1251  *
1252  * PARAMETERS :
1253  *   @my_obj       : stream object
1254  *   @buf_type     : type of buffer to be mapped. could be following values:
1255  *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1256  *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1257  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1258  *   @frame_idx    : index of buffer within the stream buffers, only valid if
1259  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1260  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1261  *   @plane_idx    : plane index. If all planes share the same fd,
1262  *                   plane_idx = -1; otherwise, plean_idx is the
1263  *                   index to plane (0..num_of_planes)
1264  *   @fd           : file descriptor of the buffer
1265  *   @size         : size of the buffer
1266  *
1267  * RETURN     : int32_t type of status
1268  *              0  -- success
1269  *              -1 -- failure
1270  *==========================================================================*/
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)1271 int32_t mm_stream_map_buf(mm_stream_t * my_obj,
1272                           uint8_t buf_type,
1273                           uint32_t frame_idx,
1274                           int32_t plane_idx,
1275                           int fd,
1276                           uint32_t size)
1277 {
1278     if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
1279         CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__);
1280         return -1;
1281     }
1282 
1283     cam_sock_packet_t packet;
1284     memset(&packet, 0, sizeof(cam_sock_packet_t));
1285     packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;
1286     packet.payload.buf_map.type = buf_type;
1287     packet.payload.buf_map.fd = fd;
1288     packet.payload.buf_map.size = size;
1289     packet.payload.buf_map.stream_id = my_obj->server_stream_id;
1290     packet.payload.buf_map.frame_idx = frame_idx;
1291     packet.payload.buf_map.plane_idx = plane_idx;
1292     return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
1293                                   &packet,
1294                                   sizeof(cam_sock_packet_t),
1295                                   fd);
1296 }
1297 
1298 /*===========================================================================
1299  * FUNCTION   : mm_stream_unmap_buf
1300  *
1301  * DESCRIPTION: unmapping stream buffer via domain socket to server
1302  *
1303  * PARAMETERS :
1304  *   @my_obj       : stream object
1305  *   @buf_type     : type of buffer to be unmapped. could be following values:
1306  *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1307  *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1308  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1309  *   @frame_idx    : index of buffer within the stream buffers, only valid if
1310  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1311  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1312  *   @plane_idx    : plane index. If all planes share the same fd,
1313  *                   plane_idx = -1; otherwise, plean_idx is the
1314  *                   index to plane (0..num_of_planes)
1315  *
1316  * RETURN     : int32_t type of status
1317  *              0  -- success
1318  *              -1 -- failure
1319  *==========================================================================*/
mm_stream_unmap_buf(mm_stream_t * my_obj,uint8_t buf_type,uint32_t frame_idx,int32_t plane_idx)1320 int32_t mm_stream_unmap_buf(mm_stream_t * my_obj,
1321                             uint8_t buf_type,
1322                             uint32_t frame_idx,
1323                             int32_t plane_idx)
1324 {
1325     if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
1326         CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__);
1327         return -1;
1328     }
1329 
1330     cam_sock_packet_t packet;
1331     memset(&packet, 0, sizeof(cam_sock_packet_t));
1332     packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING;
1333     packet.payload.buf_unmap.type = buf_type;
1334     packet.payload.buf_unmap.stream_id = my_obj->server_stream_id;
1335     packet.payload.buf_unmap.frame_idx = frame_idx;
1336     packet.payload.buf_unmap.plane_idx = plane_idx;
1337     return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
1338                                   &packet,
1339                                   sizeof(cam_sock_packet_t),
1340                                   0);
1341 }
1342 
1343 /*===========================================================================
1344  * FUNCTION   : mm_stream_map_buf_ops
1345  *
1346  * DESCRIPTION: ops for mapping stream buffer via domain socket to server.
1347  *              This function will be passed to upper layer as part of ops table
1348  *              to be used by upper layer when allocating stream buffers and mapping
1349  *              buffers to server via domain socket.
1350  *
1351  * PARAMETERS :
1352  *   @frame_idx    : index of buffer within the stream buffers, only valid if
1353  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1354  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1355  *   @plane_idx    : plane index. If all planes share the same fd,
1356  *                   plane_idx = -1; otherwise, plean_idx is the
1357  *                   index to plane (0..num_of_planes)
1358  *   @fd           : file descriptor of the buffer
1359  *   @size         : size of the buffer
1360  *   @userdata     : user data ptr (stream object)
1361  *
1362  * RETURN     : int32_t type of status
1363  *              0  -- success
1364  *              -1 -- failure
1365  *==========================================================================*/
mm_stream_map_buf_ops(uint32_t frame_idx,int32_t plane_idx,int fd,uint32_t size,void * userdata)1366 static int32_t mm_stream_map_buf_ops(uint32_t frame_idx,
1367                                      int32_t plane_idx,
1368                                      int fd,
1369                                      uint32_t size,
1370                                      void *userdata)
1371 {
1372     mm_stream_t *my_obj = (mm_stream_t *)userdata;
1373     return mm_stream_map_buf(my_obj,
1374                              CAM_MAPPING_BUF_TYPE_STREAM_BUF,
1375                              frame_idx, plane_idx, fd, size);
1376 }
1377 
1378 /*===========================================================================
1379  * FUNCTION   : mm_stream_unmap_buf_ops
1380  *
1381  * DESCRIPTION: ops for unmapping stream buffer via domain socket to server.
1382  *              This function will be passed to upper layer as part of ops table
1383  *              to be used by upper layer when allocating stream buffers and unmapping
1384  *              buffers to server via domain socket.
1385  *
1386  * PARAMETERS :
1387  *   @frame_idx    : index of buffer within the stream buffers, only valid if
1388  *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1389  *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1390  *   @plane_idx    : plane index. If all planes share the same fd,
1391  *                   plane_idx = -1; otherwise, plean_idx is the
1392  *                   index to plane (0..num_of_planes)
1393  *   @userdata     : user data ptr (stream object)
1394  *
1395  * RETURN     : int32_t type of status
1396  *              0  -- success
1397  *              -1 -- failure
1398  *==========================================================================*/
mm_stream_unmap_buf_ops(uint32_t frame_idx,int32_t plane_idx,void * userdata)1399 static int32_t mm_stream_unmap_buf_ops(uint32_t frame_idx,
1400                                        int32_t plane_idx,
1401                                        void *userdata)
1402 {
1403     mm_stream_t *my_obj = (mm_stream_t *)userdata;
1404     return mm_stream_unmap_buf(my_obj,
1405                                CAM_MAPPING_BUF_TYPE_STREAM_BUF,
1406                                frame_idx,
1407                                plane_idx);
1408 }
1409 
1410 /*===========================================================================
1411  * FUNCTION   : mm_stream_init_bufs
1412  *
1413  * DESCRIPTION: initialize stream buffers needed. This function will request
1414  *              buffers needed from upper layer through the mem ops table passed
1415  *              during configuration stage.
1416  *
1417  * PARAMETERS :
1418  *   @my_obj  : stream object
1419  *
1420  * RETURN     : int32_t type of status
1421  *              0  -- success
1422  *              -1 -- failure
1423  *==========================================================================*/
mm_stream_init_bufs(mm_stream_t * my_obj)1424 int32_t mm_stream_init_bufs(mm_stream_t * my_obj)
1425 {
1426     int32_t i, rc = 0;
1427     uint8_t *reg_flags = NULL;
1428     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1429          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1430 
1431     /* deinit buf if it's not NULL*/
1432     if (NULL != my_obj->buf) {
1433         mm_stream_deinit_bufs(my_obj);
1434     }
1435 
1436     my_obj->map_ops.map_ops = mm_stream_map_buf_ops;
1437     my_obj->map_ops.unmap_ops = mm_stream_unmap_buf_ops;
1438     my_obj->map_ops.userdata = my_obj;
1439 
1440     rc = my_obj->mem_vtbl.get_bufs(&my_obj->frame_offset,
1441                                    &my_obj->buf_num,
1442                                    &reg_flags,
1443                                    &my_obj->buf,
1444                                    &my_obj->map_ops,
1445                                    my_obj->mem_vtbl.user_data);
1446 
1447     if (0 != rc) {
1448         CDBG_ERROR("%s: Error get buf, rc = %d\n", __func__, rc);
1449         return rc;
1450     }
1451 
1452     my_obj->buf_status =
1453         (mm_stream_buf_status_t *)malloc(sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
1454 
1455     if (NULL == my_obj->buf_status) {
1456         CDBG_ERROR("%s: No memory for buf_status", __func__);
1457         mm_stream_deinit_bufs(my_obj);
1458         free(reg_flags);
1459         return -1;
1460     }
1461 
1462     memset(my_obj->buf_status, 0, sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
1463     for (i = 0; i < my_obj->buf_num; i++) {
1464         my_obj->buf_status[i].initial_reg_flag = reg_flags[i];
1465         my_obj->buf[i].stream_id = my_obj->my_hdl;
1466         my_obj->buf[i].stream_type = my_obj->stream_info->stream_type;
1467     }
1468 
1469     free(reg_flags);
1470     reg_flags = NULL;
1471 
1472     /* update in stream info about number of stream buffers */
1473     my_obj->stream_info->num_bufs = my_obj->buf_num;
1474 
1475     return rc;
1476 }
1477 
1478 /*===========================================================================
1479  * FUNCTION   : mm_stream_deinit_bufs
1480  *
1481  * DESCRIPTION: return stream buffers to upper layer through the mem ops table
1482  *              passed during configuration stage.
1483  *
1484  * PARAMETERS :
1485  *   @my_obj  : stream object
1486  *
1487  * RETURN     : int32_t type of status
1488  *              0  -- success
1489  *              -1 -- failure
1490  *==========================================================================*/
mm_stream_deinit_bufs(mm_stream_t * my_obj)1491 int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj)
1492 {
1493     int32_t rc = 0;
1494     mm_camera_map_unmap_ops_tbl_t ops_tbl;
1495     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1496          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1497 
1498     if (NULL == my_obj->buf) {
1499         CDBG("%s: Buf is NULL, no need to deinit", __func__);
1500         return rc;
1501     }
1502 
1503     /* release bufs */
1504     ops_tbl.map_ops = mm_stream_map_buf_ops;
1505     ops_tbl.unmap_ops = mm_stream_unmap_buf_ops;
1506     ops_tbl.userdata = my_obj;
1507 
1508     rc = my_obj->mem_vtbl.put_bufs(&ops_tbl,
1509                                    my_obj->mem_vtbl.user_data);
1510 
1511     free(my_obj->buf);
1512     my_obj->buf = NULL;
1513     if (my_obj->buf_status != NULL) {
1514         free(my_obj->buf_status);
1515         my_obj->buf_status = NULL;
1516     }
1517 
1518     return rc;
1519 }
1520 
1521 /*===========================================================================
1522  * FUNCTION   : mm_stream_reg_buf
1523  *
1524  * DESCRIPTION: register buffers with kernel by calling v4l2 ioctl QBUF for
1525  *              each buffer in the stream
1526  *
1527  * PARAMETERS :
1528  *   @my_obj  : stream object
1529  *
1530  * RETURN     : int32_t type of status
1531  *              0  -- success
1532  *              -1 -- failure
1533  *==========================================================================*/
mm_stream_reg_buf(mm_stream_t * my_obj)1534 int32_t mm_stream_reg_buf(mm_stream_t * my_obj)
1535 {
1536     int32_t rc = 0;
1537     uint8_t i;
1538     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1539          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1540 
1541     rc = mm_stream_request_buf(my_obj);
1542     if (rc != 0) {
1543         return rc;
1544     }
1545 
1546     pthread_mutex_lock(&my_obj->buf_lock);
1547     my_obj->queued_buffer_count = 0;
1548     for(i = 0; i < my_obj->buf_num; i++){
1549         /* check if need to qbuf initially */
1550         if (my_obj->buf_status[i].initial_reg_flag) {
1551             rc = mm_stream_qbuf(my_obj, &my_obj->buf[i]);
1552             if (rc != 0) {
1553                 CDBG_ERROR("%s: VIDIOC_QBUF rc = %d\n", __func__, rc);
1554                 break;
1555             }
1556             my_obj->buf_status[i].buf_refcnt = 0;
1557             my_obj->buf_status[i].in_kernel = 1;
1558         } else {
1559             /* the buf is held by upper layer, will not queue into kernel.
1560              * add buf reference count */
1561             my_obj->buf_status[i].buf_refcnt = 1;
1562             my_obj->buf_status[i].in_kernel = 0;
1563         }
1564     }
1565     pthread_mutex_unlock(&my_obj->buf_lock);
1566 
1567     return rc;
1568 }
1569 
1570 /*===========================================================================
1571  * FUNCTION   : mm_stream_unreg buf
1572  *
1573  * DESCRIPTION: unregister all stream buffers from kernel
1574  *
1575  * PARAMETERS :
1576  *   @my_obj  : stream object
1577  *
1578  * RETURN     : int32_t type of status
1579  *              0  -- success
1580  *              -1 -- failure
1581  *==========================================================================*/
mm_stream_unreg_buf(mm_stream_t * my_obj)1582 int32_t mm_stream_unreg_buf(mm_stream_t * my_obj)
1583 {
1584     struct v4l2_requestbuffers bufreq;
1585     int32_t i, rc = 0;
1586     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1587          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1588 
1589     /* unreg buf to kernel */
1590     bufreq.count = 0;
1591     bufreq.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1592     bufreq.memory = V4L2_MEMORY_USERPTR;
1593     rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
1594     if (rc < 0) {
1595         CDBG_ERROR("%s: fd=%d, VIDIOC_REQBUFS failed, rc=%d\n",
1596               __func__, my_obj->fd, rc);
1597     }
1598 
1599     /* reset buf reference count */
1600     pthread_mutex_lock(&my_obj->buf_lock);
1601     if (NULL != my_obj->buf_status) {
1602         for(i = 0; i < my_obj->buf_num; i++){
1603             my_obj->buf_status[i].buf_refcnt = 0;
1604             my_obj->buf_status[i].in_kernel = 0;
1605         }
1606     }
1607     pthread_mutex_unlock(&my_obj->buf_lock);
1608 
1609     return rc;
1610 }
1611 
1612 /*===========================================================================
1613  * FUNCTION   : mm_stream_get_v4l2_fmt
1614  *
1615  * DESCRIPTION: translate camera image format into FOURCC code
1616  *
1617  * PARAMETERS :
1618  *   @fmt     : camera image format
1619  *
1620  * RETURN     : FOURCC code for image format
1621  *==========================================================================*/
mm_stream_get_v4l2_fmt(cam_format_t fmt)1622 uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt)
1623 {
1624     uint32_t val;
1625     switch(fmt) {
1626     case CAM_FORMAT_YUV_420_NV12:
1627     case CAM_FORMAT_YUV_420_NV12_VENUS:
1628         val = V4L2_PIX_FMT_NV12;
1629         break;
1630     case CAM_FORMAT_YUV_420_NV21:
1631         val = V4L2_PIX_FMT_NV21;
1632         break;
1633     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG:
1634     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG:
1635     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB:
1636     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR:
1637         val= V4L2_PIX_FMT_SBGGR10;
1638         break;
1639     case CAM_FORMAT_YUV_422_NV61:
1640         val= V4L2_PIX_FMT_NV61;
1641         break;
1642     case CAM_FORMAT_YUV_RAW_8BIT_YUYV:
1643         val= V4L2_PIX_FMT_YUYV;
1644         break;
1645     case CAM_FORMAT_YUV_RAW_8BIT_YVYU:
1646         val= V4L2_PIX_FMT_YVYU;
1647         break;
1648     case CAM_FORMAT_YUV_RAW_8BIT_UYVY:
1649         val= V4L2_PIX_FMT_UYVY;
1650         break;
1651     case CAM_FORMAT_YUV_RAW_8BIT_VYUY:
1652         val= V4L2_PIX_FMT_VYUY;
1653         break;
1654     case CAM_FORMAT_YUV_420_YV12:
1655         val= V4L2_PIX_FMT_NV12;
1656         break;
1657     case CAM_FORMAT_YUV_422_NV16:
1658         val= V4L2_PIX_FMT_NV16;
1659         break;
1660     default:
1661         val = 0;
1662         CDBG_ERROR("%s: Unknown fmt=%d", __func__, fmt);
1663         break;
1664     }
1665     CDBG("%s: fmt=%d, val =%d", __func__, fmt, val);
1666     return val;
1667 }
1668 
1669 /*===========================================================================
1670  * FUNCTION   : mm_stream_calc_offset_preview
1671  *
1672  * DESCRIPTION: calculate preview frame offset based on format and
1673  *              padding information
1674  *
1675  * PARAMETERS :
1676  *   @fmt     : image format
1677  *   @dim     : image dimension
1678  *   @buf_planes : [out] buffer plane information
1679  *
1680  * RETURN     : int32_t type of status
1681  *              0  -- success
1682  *              -1 -- failure
1683  *==========================================================================*/
mm_stream_calc_offset_preview(cam_format_t fmt,cam_dimension_t * dim,cam_stream_buf_plane_info_t * buf_planes)1684 int32_t mm_stream_calc_offset_preview(cam_format_t fmt,
1685                                       cam_dimension_t *dim,
1686                                       cam_stream_buf_plane_info_t *buf_planes)
1687 {
1688     int32_t rc = 0;
1689     int stride = 0, scanline = 0;
1690 
1691     switch (fmt) {
1692     case CAM_FORMAT_YUV_420_NV12:
1693     case CAM_FORMAT_YUV_420_NV21:
1694         /* 2 planes: Y + CbCr */
1695         buf_planes->plane_info.num_planes = 2;
1696 
1697         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
1698         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
1699 
1700         buf_planes->plane_info.mp[0].offset = 0;
1701         buf_planes->plane_info.mp[0].len = stride * scanline;
1702         buf_planes->plane_info.mp[0].offset_x = 0;
1703         buf_planes->plane_info.mp[0].offset_y = 0;
1704         buf_planes->plane_info.mp[0].stride = stride;
1705         buf_planes->plane_info.mp[0].scanline = scanline;
1706         buf_planes->plane_info.mp[0].width = dim->width;
1707         buf_planes->plane_info.mp[0].height = dim->height;
1708 
1709         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
1710         scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_2);
1711         buf_planes->plane_info.mp[1].offset = 0;
1712         buf_planes->plane_info.mp[1].len =
1713             stride * scanline;
1714         buf_planes->plane_info.mp[1].offset_x = 0;
1715         buf_planes->plane_info.mp[1].offset_y = 0;
1716         buf_planes->plane_info.mp[1].stride = stride;
1717         buf_planes->plane_info.mp[1].scanline = scanline;
1718         buf_planes->plane_info.mp[1].width = dim->width;
1719         buf_planes->plane_info.mp[1].height = dim->height / 2;
1720 
1721         buf_planes->plane_info.frame_len =
1722             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1723                         buf_planes->plane_info.mp[1].len,
1724                         CAM_PAD_TO_4K);
1725         break;
1726     case CAM_FORMAT_YUV_420_NV21_ADRENO:
1727         /* 2 planes: Y + CbCr */
1728         buf_planes->plane_info.num_planes = 2;
1729 
1730         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
1731         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32);
1732         buf_planes->plane_info.mp[0].offset = 0;
1733         buf_planes->plane_info.mp[0].len =
1734             PAD_TO_SIZE(stride * scanline,
1735                         CAM_PAD_TO_4K);
1736         buf_planes->plane_info.mp[0].offset_x = 0;
1737         buf_planes->plane_info.mp[0].offset_y = 0;
1738         buf_planes->plane_info.mp[0].stride = stride;
1739         buf_planes->plane_info.mp[0].scanline = scanline;
1740         buf_planes->plane_info.mp[0].width = dim->width;
1741         buf_planes->plane_info.mp[0].height = dim->height;
1742 
1743         stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2;
1744         scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32);
1745         buf_planes->plane_info.mp[1].offset = 0;
1746         buf_planes->plane_info.mp[1].len =
1747             PAD_TO_SIZE(stride * scanline,
1748                         CAM_PAD_TO_4K);
1749         buf_planes->plane_info.mp[1].offset_x = 0;
1750         buf_planes->plane_info.mp[1].offset_y = 0;
1751         buf_planes->plane_info.mp[1].stride = stride;
1752         buf_planes->plane_info.mp[1].scanline = scanline;
1753         buf_planes->plane_info.mp[1].width = dim->width;
1754         buf_planes->plane_info.mp[1].height = dim->height / 2;
1755 
1756         buf_planes->plane_info.frame_len =
1757             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1758                         buf_planes->plane_info.mp[1].len,
1759                         CAM_PAD_TO_4K);
1760         break;
1761     case CAM_FORMAT_YUV_420_YV12:
1762         /* 3 planes: Y + Cr + Cb */
1763         buf_planes->plane_info.num_planes = 3;
1764 
1765         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1766         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
1767         buf_planes->plane_info.mp[0].offset = 0;
1768         buf_planes->plane_info.mp[0].len = stride * scanline;
1769         buf_planes->plane_info.mp[0].offset_x = 0;
1770         buf_planes->plane_info.mp[0].offset_y = 0;
1771         buf_planes->plane_info.mp[0].stride = stride;
1772         buf_planes->plane_info.mp[0].scanline = scanline;
1773         buf_planes->plane_info.mp[0].width = dim->width;
1774         buf_planes->plane_info.mp[0].height = dim->height;
1775 
1776         stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
1777         scanline = scanline / 2;
1778         buf_planes->plane_info.mp[1].offset = 0;
1779         buf_planes->plane_info.mp[1].len =
1780             stride * scanline;
1781         buf_planes->plane_info.mp[1].offset_x = 0;
1782         buf_planes->plane_info.mp[1].offset_y = 0;
1783         buf_planes->plane_info.mp[1].stride = stride;
1784         buf_planes->plane_info.mp[1].scanline = scanline;
1785         buf_planes->plane_info.mp[1].width = dim->width / 2;
1786         buf_planes->plane_info.mp[1].height = dim->height / 2;
1787 
1788         buf_planes->plane_info.mp[2].offset = 0;
1789         buf_planes->plane_info.mp[2].len =
1790             stride * scanline;
1791         buf_planes->plane_info.mp[2].offset_x = 0;
1792         buf_planes->plane_info.mp[2].offset_y = 0;
1793         buf_planes->plane_info.mp[2].stride = stride;
1794         buf_planes->plane_info.mp[2].scanline = scanline;
1795         buf_planes->plane_info.mp[2].width = dim->width / 2;
1796         buf_planes->plane_info.mp[2].height = dim->height / 2;
1797 
1798         buf_planes->plane_info.frame_len =
1799             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1800                         buf_planes->plane_info.mp[1].len +
1801                         buf_planes->plane_info.mp[2].len,
1802                         CAM_PAD_TO_4K);
1803         break;
1804     case CAM_FORMAT_YUV_422_NV16:
1805     case CAM_FORMAT_YUV_422_NV61:
1806         /* 2 planes: Y + CbCr */
1807         buf_planes->plane_info.num_planes = 2;
1808 
1809         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1810         scanline = dim->height;
1811         buf_planes->plane_info.mp[0].offset = 0;
1812         buf_planes->plane_info.mp[0].len = stride * scanline;
1813         buf_planes->plane_info.mp[0].offset_x = 0;
1814         buf_planes->plane_info.mp[0].offset_y = 0;
1815         buf_planes->plane_info.mp[0].stride = stride;
1816         buf_planes->plane_info.mp[0].scanline = scanline;
1817         buf_planes->plane_info.mp[0].width = dim->width;
1818         buf_planes->plane_info.mp[0].height = dim->height;
1819 
1820         buf_planes->plane_info.mp[1].offset = 0;
1821         buf_planes->plane_info.mp[1].len = stride * scanline;
1822         buf_planes->plane_info.mp[1].offset_x = 0;
1823         buf_planes->plane_info.mp[1].offset_y = 0;
1824         buf_planes->plane_info.mp[1].stride = stride;
1825         buf_planes->plane_info.mp[1].scanline = scanline;
1826         buf_planes->plane_info.mp[1].width = dim->width;
1827         buf_planes->plane_info.mp[1].height = dim->height;
1828 
1829         buf_planes->plane_info.frame_len =
1830             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1831                         buf_planes->plane_info.mp[1].len,
1832                         CAM_PAD_TO_4K);
1833         break;
1834     case CAM_FORMAT_YUV_420_NV12_VENUS:
1835 #ifdef VENUS_PRESENT
1836         // using Venus
1837         stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
1838         scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
1839 
1840         buf_planes->plane_info.frame_len =
1841             VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height);
1842         buf_planes->plane_info.num_planes = 2;
1843         buf_planes->plane_info.mp[0].len = stride * scanline;
1844         buf_planes->plane_info.mp[0].offset = 0;
1845         buf_planes->plane_info.mp[0].offset_x =0;
1846         buf_planes->plane_info.mp[0].offset_y = 0;
1847         buf_planes->plane_info.mp[0].stride = stride;
1848         buf_planes->plane_info.mp[0].scanline = scanline;
1849         buf_planes->plane_info.mp[0].width = dim->width;
1850         buf_planes->plane_info.mp[0].height = dim->height;
1851         stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
1852         scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
1853         buf_planes->plane_info.mp[1].len =
1854             buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
1855         buf_planes->plane_info.mp[1].offset = 0;
1856         buf_planes->plane_info.mp[1].offset_x =0;
1857         buf_planes->plane_info.mp[1].offset_y = 0;
1858         buf_planes->plane_info.mp[1].stride = stride;
1859         buf_planes->plane_info.mp[1].scanline = scanline;
1860         buf_planes->plane_info.mp[1].width = dim->width;
1861         buf_planes->plane_info.mp[1].height = dim->height;
1862 #else
1863         CDBG_ERROR("%s: Venus hardware not avail, cannot use this format", __func__);
1864         rc = -1;
1865 #endif
1866         break;
1867     default:
1868         CDBG_ERROR("%s: Invalid cam_format for preview %d",
1869                    __func__, fmt);
1870         rc = -1;
1871         break;
1872     }
1873 
1874     return rc;
1875 }
1876 /*===========================================================================
1877  * FUNCTION   : mm_stream_calc_offset_post_view
1878  *
1879  * DESCRIPTION: calculate postview frame offset based on format and
1880  *              padding information
1881  *
1882  * PARAMETERS :
1883  *   @fmt     : image format
1884  *   @dim     : image dimension
1885  *   @buf_planes : [out] buffer plane information
1886  *
1887  * RETURN     : int32_t type of status
1888  *              0  -- success
1889  *              -1 -- failure
1890  *==========================================================================*/
mm_stream_calc_offset_post_view(cam_format_t fmt,cam_dimension_t * dim,cam_stream_buf_plane_info_t * buf_planes)1891 int32_t mm_stream_calc_offset_post_view(cam_format_t fmt,
1892                                       cam_dimension_t *dim,
1893                                       cam_stream_buf_plane_info_t *buf_planes)
1894 {
1895     int32_t rc = 0;
1896     int stride = 0, scanline = 0;
1897 
1898     switch (fmt) {
1899     case CAM_FORMAT_YUV_420_NV12:
1900     case CAM_FORMAT_YUV_420_NV21:
1901         /* 2 planes: Y + CbCr */
1902         buf_planes->plane_info.num_planes = 2;
1903 
1904         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_64);
1905         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_64);
1906         buf_planes->plane_info.mp[0].offset = 0;
1907         buf_planes->plane_info.mp[0].len = stride * scanline;
1908         buf_planes->plane_info.mp[0].offset_x = 0;
1909         buf_planes->plane_info.mp[0].offset_y = 0;
1910         buf_planes->plane_info.mp[0].stride = stride;
1911         buf_planes->plane_info.mp[0].scanline = scanline;
1912         buf_planes->plane_info.mp[0].width = dim->width;
1913         buf_planes->plane_info.mp[0].height = dim->height;
1914 
1915         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_64);
1916         scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_64);
1917         buf_planes->plane_info.mp[1].offset = 0;
1918         buf_planes->plane_info.mp[1].len =
1919             stride * scanline;
1920         buf_planes->plane_info.mp[1].offset_x = 0;
1921         buf_planes->plane_info.mp[1].offset_y = 0;
1922         buf_planes->plane_info.mp[1].stride = stride;
1923         buf_planes->plane_info.mp[1].scanline = scanline;
1924         buf_planes->plane_info.mp[1].width = dim->width;
1925         buf_planes->plane_info.mp[1].height = dim->height / 2;
1926 
1927         buf_planes->plane_info.frame_len =
1928             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1929                         buf_planes->plane_info.mp[1].len,
1930                         CAM_PAD_TO_4K);
1931         break;
1932     case CAM_FORMAT_YUV_420_NV21_ADRENO:
1933         /* 2 planes: Y + CbCr */
1934         buf_planes->plane_info.num_planes = 2;
1935 
1936         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
1937         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32);
1938         buf_planes->plane_info.mp[0].offset = 0;
1939         buf_planes->plane_info.mp[0].len =
1940             PAD_TO_SIZE(stride * scanline,
1941                         CAM_PAD_TO_4K);
1942         buf_planes->plane_info.mp[0].offset_x = 0;
1943         buf_planes->plane_info.mp[0].offset_y = 0;
1944         buf_planes->plane_info.mp[0].stride = stride;
1945         buf_planes->plane_info.mp[0].scanline = scanline;
1946         buf_planes->plane_info.mp[0].width = dim->width;
1947         buf_planes->plane_info.mp[0].height = dim->height;
1948 
1949         stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2;
1950         scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32);
1951         buf_planes->plane_info.mp[1].offset = 0;
1952         buf_planes->plane_info.mp[1].len =
1953             PAD_TO_SIZE(stride * scanline,
1954                         CAM_PAD_TO_4K);
1955         buf_planes->plane_info.mp[1].offset_x = 0;
1956         buf_planes->plane_info.mp[1].offset_y = 0;
1957         buf_planes->plane_info.mp[1].stride = stride;
1958         buf_planes->plane_info.mp[1].scanline = scanline;
1959         buf_planes->plane_info.mp[1].width = dim->width;
1960         buf_planes->plane_info.mp[1].height = dim->height / 2;
1961 
1962         buf_planes->plane_info.frame_len =
1963             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1964                         buf_planes->plane_info.mp[1].len,
1965                         CAM_PAD_TO_4K);
1966         break;
1967     case CAM_FORMAT_YUV_420_YV12:
1968         /* 3 planes: Y + Cr + Cb */
1969         buf_planes->plane_info.num_planes = 3;
1970 
1971         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1972         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
1973         buf_planes->plane_info.mp[0].offset = 0;
1974         buf_planes->plane_info.mp[0].len = stride * scanline;
1975         buf_planes->plane_info.mp[0].offset_x = 0;
1976         buf_planes->plane_info.mp[0].offset_y = 0;
1977         buf_planes->plane_info.mp[0].stride = stride;
1978         buf_planes->plane_info.mp[0].scanline = scanline;
1979         buf_planes->plane_info.mp[0].width = dim->width;
1980         buf_planes->plane_info.mp[0].height = dim->height;
1981 
1982         stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
1983         scanline = scanline / 2;
1984         buf_planes->plane_info.mp[1].offset = 0;
1985         buf_planes->plane_info.mp[1].len =
1986             stride * scanline;
1987         buf_planes->plane_info.mp[1].offset_x = 0;
1988         buf_planes->plane_info.mp[1].offset_y = 0;
1989         buf_planes->plane_info.mp[1].stride = stride;
1990         buf_planes->plane_info.mp[1].scanline = scanline;
1991         buf_planes->plane_info.mp[1].width = dim->width / 2;
1992         buf_planes->plane_info.mp[1].height = dim->height / 2;
1993 
1994         buf_planes->plane_info.mp[2].offset = 0;
1995         buf_planes->plane_info.mp[2].len =
1996             stride * scanline;
1997         buf_planes->plane_info.mp[2].offset_x = 0;
1998         buf_planes->plane_info.mp[2].offset_y = 0;
1999         buf_planes->plane_info.mp[2].stride = stride;
2000         buf_planes->plane_info.mp[2].scanline = scanline;
2001         buf_planes->plane_info.mp[2].width = dim->width / 2;
2002         buf_planes->plane_info.mp[2].height = dim->height / 2;
2003 
2004         buf_planes->plane_info.frame_len =
2005             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2006                         buf_planes->plane_info.mp[1].len +
2007                         buf_planes->plane_info.mp[2].len,
2008                         CAM_PAD_TO_4K);
2009         break;
2010     case CAM_FORMAT_YUV_422_NV16:
2011     case CAM_FORMAT_YUV_422_NV61:
2012         /* 2 planes: Y + CbCr */
2013         buf_planes->plane_info.num_planes = 2;
2014 
2015         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2016         scanline = dim->height;
2017         buf_planes->plane_info.mp[0].offset = 0;
2018         buf_planes->plane_info.mp[0].len = stride * scanline;
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         buf_planes->plane_info.mp[0].width = dim->width;
2024         buf_planes->plane_info.mp[0].height = dim->height;
2025 
2026         buf_planes->plane_info.mp[1].offset = 0;
2027         buf_planes->plane_info.mp[1].len = stride * scanline;
2028         buf_planes->plane_info.mp[1].offset_x = 0;
2029         buf_planes->plane_info.mp[1].offset_y = 0;
2030         buf_planes->plane_info.mp[1].stride = stride;
2031         buf_planes->plane_info.mp[1].scanline = scanline;
2032         buf_planes->plane_info.mp[1].width = dim->width;
2033         buf_planes->plane_info.mp[1].height = dim->height;
2034 
2035         buf_planes->plane_info.frame_len =
2036             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2037                         buf_planes->plane_info.mp[1].len,
2038                         CAM_PAD_TO_4K);
2039         break;
2040     case CAM_FORMAT_YUV_420_NV12_VENUS:
2041 #ifdef VENUS_PRESENT
2042         // using Venus
2043         stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
2044         scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
2045 
2046         buf_planes->plane_info.frame_len =
2047             VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height);
2048         buf_planes->plane_info.num_planes = 2;
2049         buf_planes->plane_info.mp[0].len = stride * scanline;
2050         buf_planes->plane_info.mp[0].offset = 0;
2051         buf_planes->plane_info.mp[0].offset_x =0;
2052         buf_planes->plane_info.mp[0].offset_y = 0;
2053         buf_planes->plane_info.mp[0].stride = stride;
2054         buf_planes->plane_info.mp[0].scanline = scanline;
2055         buf_planes->plane_info.mp[0].width = dim->width;
2056         buf_planes->plane_info.mp[0].height = dim->height;
2057         stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
2058         scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
2059         buf_planes->plane_info.mp[1].len =
2060             buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
2061         buf_planes->plane_info.mp[1].offset = 0;
2062         buf_planes->plane_info.mp[1].offset_x =0;
2063         buf_planes->plane_info.mp[1].offset_y = 0;
2064         buf_planes->plane_info.mp[1].stride = stride;
2065         buf_planes->plane_info.mp[1].scanline = scanline;
2066         buf_planes->plane_info.mp[1].width = dim->width;
2067         buf_planes->plane_info.mp[1].height = dim->height;
2068 #else
2069         CDBG_ERROR("%s: Venus hardware not avail, cannot use this format", __func__);
2070         rc = -1;
2071 #endif
2072         break;
2073     default:
2074         CDBG_ERROR("%s: Invalid cam_format for preview %d",
2075                    __func__, fmt);
2076         rc = -1;
2077         break;
2078     }
2079 
2080     return rc;
2081 }
2082 
2083 /*===========================================================================
2084  * FUNCTION   : mm_stream_calc_offset_snapshot
2085  *
2086  * DESCRIPTION: calculate snapshot/postproc frame offset based on format and
2087  *              padding information
2088  *
2089  * PARAMETERS :
2090  *   @fmt     : image format
2091  *   @dim     : image dimension
2092  *   @padding : padding information
2093  *   @buf_planes : [out] buffer plane information
2094  *
2095  * RETURN     : int32_t type of status
2096  *              0  -- success
2097  *              -1 -- failure
2098  *==========================================================================*/
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)2099 int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt,
2100                                        cam_dimension_t *dim,
2101                                        cam_padding_info_t *padding,
2102                                        cam_stream_buf_plane_info_t *buf_planes)
2103 {
2104     int32_t rc = 0;
2105     uint8_t isAFamily = mm_camera_util_chip_is_a_family();
2106     int offset_x = 0, offset_y = 0;
2107     int stride = 0, scanline = 0;
2108 
2109     if (isAFamily) {
2110         stride = dim->width;
2111         scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_16);
2112         offset_x = 0;
2113         offset_y = scanline - dim->height;
2114         scanline += offset_y; /* double padding */
2115     } else {
2116         stride = PAD_TO_SIZE(dim->width,
2117                              padding->width_padding);
2118         scanline = PAD_TO_SIZE(dim->height,
2119                                padding->height_padding);
2120         offset_x = 0;
2121         offset_y = 0;
2122     }
2123 
2124     switch (fmt) {
2125     case CAM_FORMAT_YUV_420_NV12:
2126     case CAM_FORMAT_YUV_420_NV21:
2127         /* 2 planes: Y + CbCr */
2128         buf_planes->plane_info.num_planes = 2;
2129 
2130         buf_planes->plane_info.mp[0].len =
2131             PAD_TO_SIZE(stride * scanline,
2132                         padding->plane_padding);
2133         buf_planes->plane_info.mp[0].offset =
2134             PAD_TO_SIZE(offset_x + stride * offset_y,
2135                         padding->plane_padding);
2136         buf_planes->plane_info.mp[0].offset_x = offset_x;
2137         buf_planes->plane_info.mp[0].offset_y = offset_y;
2138         buf_planes->plane_info.mp[0].stride = stride;
2139         buf_planes->plane_info.mp[0].scanline = scanline;
2140         buf_planes->plane_info.mp[0].width = dim->width;
2141         buf_planes->plane_info.mp[0].height = dim->height;
2142 
2143         scanline = scanline / 2;
2144         buf_planes->plane_info.mp[1].len =
2145             PAD_TO_SIZE(stride * scanline,
2146                         padding->plane_padding);
2147         buf_planes->plane_info.mp[1].offset =
2148             PAD_TO_SIZE(offset_x + stride * offset_y,
2149                         padding->plane_padding);
2150         buf_planes->plane_info.mp[1].offset_x = offset_x;
2151         buf_planes->plane_info.mp[1].offset_y = offset_y;
2152         buf_planes->plane_info.mp[1].stride = stride;
2153         buf_planes->plane_info.mp[1].scanline = scanline;
2154         buf_planes->plane_info.mp[1].width = dim->width;
2155         buf_planes->plane_info.mp[1].height = dim->height / 2;
2156 
2157         buf_planes->plane_info.frame_len =
2158             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2159                         buf_planes->plane_info.mp[1].len,
2160                         CAM_PAD_TO_4K);
2161         break;
2162     case CAM_FORMAT_YUV_420_YV12:
2163         /* 3 planes: Y + Cr + Cb */
2164         buf_planes->plane_info.num_planes = 3;
2165 
2166         buf_planes->plane_info.mp[0].offset =
2167             PAD_TO_SIZE(offset_x + stride * offset_y,
2168                         padding->plane_padding);
2169         buf_planes->plane_info.mp[0].len =
2170             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2171         buf_planes->plane_info.mp[0].offset_x = offset_x;
2172         buf_planes->plane_info.mp[0].offset_y = offset_y;
2173         buf_planes->plane_info.mp[0].stride = stride;
2174         buf_planes->plane_info.mp[0].scanline = scanline;
2175         buf_planes->plane_info.mp[0].width = dim->width;
2176         buf_planes->plane_info.mp[0].height = dim->height;
2177 
2178         stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
2179         scanline = scanline / 2;
2180         buf_planes->plane_info.mp[1].offset =
2181             PAD_TO_SIZE(offset_x + stride * offset_y,
2182                         padding->plane_padding);
2183         buf_planes->plane_info.mp[1].len =
2184             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2185         buf_planes->plane_info.mp[1].offset_x = offset_x;
2186         buf_planes->plane_info.mp[1].offset_y = offset_y;
2187         buf_planes->plane_info.mp[1].stride = stride;
2188         buf_planes->plane_info.mp[1].scanline = scanline;
2189         buf_planes->plane_info.mp[1].width = dim->width / 2;
2190         buf_planes->plane_info.mp[1].height = dim->height / 2;
2191 
2192         buf_planes->plane_info.mp[2].offset =
2193             PAD_TO_SIZE(offset_x + stride * offset_y,
2194                         padding->plane_padding);
2195         buf_planes->plane_info.mp[2].len =
2196             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2197         buf_planes->plane_info.mp[2].offset_x = offset_x;
2198         buf_planes->plane_info.mp[2].offset_y = offset_y;
2199         buf_planes->plane_info.mp[2].stride = stride;
2200         buf_planes->plane_info.mp[2].scanline = scanline;
2201         buf_planes->plane_info.mp[2].width = dim->width / 2;
2202         buf_planes->plane_info.mp[2].height = dim->height / 2;
2203 
2204         buf_planes->plane_info.frame_len =
2205             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2206                         buf_planes->plane_info.mp[1].len +
2207                         buf_planes->plane_info.mp[2].len,
2208                         CAM_PAD_TO_4K);
2209         break;
2210     case CAM_FORMAT_YUV_422_NV16:
2211     case CAM_FORMAT_YUV_422_NV61:
2212         /* 2 planes: Y + CbCr */
2213         buf_planes->plane_info.num_planes = 2;
2214         buf_planes->plane_info.mp[0].len =
2215             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2216         buf_planes->plane_info.mp[0].offset =
2217             PAD_TO_SIZE(offset_x + stride * offset_y,
2218                         padding->plane_padding);
2219         buf_planes->plane_info.mp[0].offset_x = offset_x;
2220         buf_planes->plane_info.mp[0].offset_y = offset_y;
2221         buf_planes->plane_info.mp[0].stride = stride;
2222         buf_planes->plane_info.mp[0].scanline = scanline;
2223         buf_planes->plane_info.mp[0].width = dim->width;
2224         buf_planes->plane_info.mp[0].height = dim->height;
2225 
2226         buf_planes->plane_info.mp[1].len =
2227             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2228         buf_planes->plane_info.mp[1].offset =
2229             PAD_TO_SIZE(offset_x + stride * offset_y,
2230                         padding->plane_padding);
2231         buf_planes->plane_info.mp[1].offset_x = offset_x;
2232         buf_planes->plane_info.mp[1].offset_y = offset_y;
2233         buf_planes->plane_info.mp[1].stride = stride;
2234         buf_planes->plane_info.mp[1].scanline = scanline;
2235         buf_planes->plane_info.mp[1].width = dim->width;
2236         buf_planes->plane_info.mp[1].height = dim->height;
2237 
2238         buf_planes->plane_info.frame_len = PAD_TO_SIZE(
2239             buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len,
2240             CAM_PAD_TO_4K);
2241         break;
2242     default:
2243         CDBG_ERROR("%s: Invalid cam_format for snapshot %d",
2244                    __func__, fmt);
2245         rc = -1;
2246         break;
2247     }
2248 
2249     return rc;
2250 }
2251 
2252 /*===========================================================================
2253  * FUNCTION   : mm_stream_calc_offset_raw
2254  *
2255  * DESCRIPTION: calculate raw frame offset based on format and padding information
2256  *
2257  * PARAMETERS :
2258  *   @fmt     : image format
2259  *   @dim     : image dimension
2260  *   @padding : padding information
2261  *   @buf_planes : [out] buffer plane information
2262  *
2263  * RETURN     : int32_t type of status
2264  *              0  -- success
2265  *              -1 -- failure
2266  *==========================================================================*/
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)2267 int32_t mm_stream_calc_offset_raw(cam_format_t fmt,
2268                                   cam_dimension_t *dim,
2269                                   cam_padding_info_t *padding,
2270                                   cam_stream_buf_plane_info_t *buf_planes)
2271 {
2272     int32_t rc = 0;
2273     int stride = 0;
2274     int scanline = dim->height;
2275 
2276     switch (fmt) {
2277     case CAM_FORMAT_YUV_RAW_8BIT_YUYV:
2278     case CAM_FORMAT_YUV_RAW_8BIT_YVYU:
2279     case CAM_FORMAT_YUV_RAW_8BIT_UYVY:
2280     case CAM_FORMAT_YUV_RAW_8BIT_VYUY:
2281     case CAM_FORMAT_JPEG_RAW_8BIT:
2282         /* 1 plane */
2283         /* Every 16 pixels occupy 16 bytes */
2284         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2285         buf_planes->plane_info.num_planes = 1;
2286         buf_planes->plane_info.mp[0].offset = 0;
2287         buf_planes->plane_info.mp[0].len =
2288             PAD_TO_SIZE(stride * scanline * 2, padding->plane_padding);
2289         buf_planes->plane_info.frame_len =
2290             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2291         buf_planes->plane_info.mp[0].offset_x =0;
2292         buf_planes->plane_info.mp[0].offset_y = 0;
2293         buf_planes->plane_info.mp[0].stride = stride;
2294         buf_planes->plane_info.mp[0].scanline = scanline;
2295         buf_planes->plane_info.mp[0].width = buf_planes->plane_info.mp[0].len;
2296         buf_planes->plane_info.mp[0].height = 1;
2297         break;
2298     case CAM_FORMAT_META_RAW_8BIT:
2299         // Every 16 pixels occupy 16 bytes
2300         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2301         buf_planes->plane_info.num_planes = 1;
2302         buf_planes->plane_info.mp[0].offset = 0;
2303         buf_planes->plane_info.mp[0].len =
2304             PAD_TO_SIZE(stride * scanline * 2, padding->plane_padding);
2305         buf_planes->plane_info.frame_len =
2306             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2307         buf_planes->plane_info.mp[0].offset_x =0;
2308         buf_planes->plane_info.mp[0].offset_y = 0;
2309         buf_planes->plane_info.mp[0].stride = stride;
2310         buf_planes->plane_info.mp[0].scanline = scanline;
2311         break;
2312 
2313     case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GBRG:
2314     case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GRBG:
2315     case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_RGGB:
2316     case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_BGGR:
2317     case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GBRG:
2318     case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GRBG:
2319     case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_RGGB:
2320     case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_BGGR:
2321     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GBRG:
2322     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GRBG:
2323     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_RGGB:
2324     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_BGGR:
2325     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GBRG:
2326     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GRBG:
2327     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_RGGB:
2328     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_BGGR:
2329     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GBRG:
2330     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GRBG:
2331     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_RGGB:
2332     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_BGGR:
2333         /* 1 plane */
2334         /* Every 16 pixels occupy 16 bytes */
2335         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2336         buf_planes->plane_info.num_planes = 1;
2337         buf_planes->plane_info.mp[0].offset = 0;
2338         buf_planes->plane_info.mp[0].len =
2339             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2340         buf_planes->plane_info.frame_len =
2341             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2342         buf_planes->plane_info.mp[0].offset_x =0;
2343         buf_planes->plane_info.mp[0].offset_y = 0;
2344         buf_planes->plane_info.mp[0].stride = stride;
2345         buf_planes->plane_info.mp[0].scanline = scanline;
2346         buf_planes->plane_info.mp[0].width = buf_planes->plane_info.mp[0].len;
2347         buf_planes->plane_info.mp[0].height = 1;
2348         break;
2349     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG:
2350     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG:
2351     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB:
2352     case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR:
2353     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GBRG:
2354     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GRBG:
2355     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_RGGB:
2356     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_BGGR:
2357         /* Every 12 pixels occupy 16 bytes */
2358         stride = (dim->width + 11)/12 * 16;
2359         buf_planes->plane_info.num_planes = 1;
2360         buf_planes->plane_info.mp[0].offset = 0;
2361         buf_planes->plane_info.mp[0].len =
2362             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2363         buf_planes->plane_info.frame_len =
2364             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2365         buf_planes->plane_info.mp[0].offset_x =0;
2366         buf_planes->plane_info.mp[0].offset_y = 0;
2367         buf_planes->plane_info.mp[0].stride = stride;
2368         buf_planes->plane_info.mp[0].scanline = scanline;
2369         buf_planes->plane_info.mp[0].width = buf_planes->plane_info.mp[0].len;
2370         buf_planes->plane_info.mp[0].height = 1;
2371         break;
2372     case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GBRG:
2373     case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GRBG:
2374     case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_RGGB:
2375     case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_BGGR:
2376     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GBRG:
2377     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GRBG:
2378     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_RGGB:
2379     case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_BGGR:
2380         /* Every 10 pixels occupy 16 bytes */
2381         stride = (dim->width + 9)/10 * 16;
2382         buf_planes->plane_info.num_planes = 1;
2383         buf_planes->plane_info.mp[0].offset = 0;
2384         buf_planes->plane_info.mp[0].len =
2385             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2386         buf_planes->plane_info.frame_len =
2387             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2388         buf_planes->plane_info.mp[0].offset_x =0;
2389         buf_planes->plane_info.mp[0].offset_y = 0;
2390         buf_planes->plane_info.mp[0].stride = stride;
2391         buf_planes->plane_info.mp[0].scanline = scanline;
2392         buf_planes->plane_info.mp[0].width = buf_planes->plane_info.mp[0].len;
2393         buf_planes->plane_info.mp[0].height = 1;
2394         break;
2395     case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG:
2396     case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GRBG:
2397     case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_RGGB:
2398     case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_BGGR:
2399     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GBRG:
2400     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GRBG:
2401     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_RGGB:
2402     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_BGGR:
2403         /* Every 64 pixels occupy 80 bytes */
2404         stride = PAD_TO_SIZE(
2405                 PAD_TO_SIZE(dim->width, CAM_PAD_TO_4)*5/4, CAM_PAD_TO_16);
2406         buf_planes->plane_info.num_planes = 1;
2407         buf_planes->plane_info.mp[0].offset = 0;
2408         buf_planes->plane_info.mp[0].len =
2409             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2410         buf_planes->plane_info.frame_len =
2411             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2412         buf_planes->plane_info.mp[0].offset_x =0;
2413         buf_planes->plane_info.mp[0].offset_y = 0;
2414         buf_planes->plane_info.mp[0].stride = stride;
2415         buf_planes->plane_info.mp[0].scanline = scanline;
2416         buf_planes->plane_info.mp[0].width = buf_planes->plane_info.mp[0].len;
2417         buf_planes->plane_info.mp[0].height = 1;
2418         break;
2419     case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GBRG:
2420     case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GRBG:
2421     case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_RGGB:
2422     case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_BGGR:
2423     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GBRG:
2424     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GRBG:
2425     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_RGGB:
2426     case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_BGGR:
2427         /* Every 32 pixels occupy 48 bytes */
2428         stride = PAD_TO_SIZE(PAD_TO_SIZE(dim->width, 2)*3/2, CAM_PAD_TO_16);
2429         buf_planes->plane_info.num_planes = 1;
2430         buf_planes->plane_info.mp[0].offset = 0;
2431         buf_planes->plane_info.mp[0].len =
2432             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2433         buf_planes->plane_info.frame_len =
2434             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2435         buf_planes->plane_info.mp[0].offset_x =0;
2436         buf_planes->plane_info.mp[0].offset_y = 0;
2437         buf_planes->plane_info.mp[0].stride = stride;
2438         buf_planes->plane_info.mp[0].scanline = scanline;
2439         buf_planes->plane_info.mp[0].width = buf_planes->plane_info.mp[0].len;
2440         buf_planes->plane_info.mp[0].height = 1;
2441         break;
2442     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GBRG:
2443     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GRBG:
2444     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_RGGB:
2445     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_BGGR:
2446     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GBRG:
2447     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GRBG:
2448     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_RGGB:
2449     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_BGGR:
2450     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GBRG:
2451     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GRBG:
2452     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_RGGB:
2453     case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_BGGR:
2454         /* Every 8 pixels occupy 16 bytes */
2455         stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_8) * 2;
2456         buf_planes->plane_info.num_planes = 1;
2457         buf_planes->plane_info.mp[0].offset = 0;
2458         buf_planes->plane_info.mp[0].len =
2459             PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2460         buf_planes->plane_info.frame_len =
2461             PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2462         buf_planes->plane_info.mp[0].offset_x =0;
2463         buf_planes->plane_info.mp[0].offset_y = 0;
2464         buf_planes->plane_info.mp[0].stride = stride;
2465         buf_planes->plane_info.mp[0].scanline = scanline;
2466         buf_planes->plane_info.mp[0].width = buf_planes->plane_info.mp[0].len;
2467         buf_planes->plane_info.mp[0].height = 1;
2468         break;
2469     default:
2470         CDBG_ERROR("%s: Invalid cam_format %d for raw stream",
2471                    __func__, fmt);
2472         rc = -1;
2473         break;
2474     }
2475 
2476     return rc;
2477 }
2478 
2479 /*===========================================================================
2480  * FUNCTION   : mm_stream_calc_offset_video
2481  *
2482  * DESCRIPTION: calculate video frame offset based on format and
2483  *              padding information
2484  *
2485  * PARAMETERS :
2486  *   @dim     : image dimension
2487  *   @buf_planes : [out] buffer plane information
2488  *
2489  * RETURN     : int32_t type of status
2490  *              0  -- success
2491  *              -1 -- failure
2492  *==========================================================================*/
2493 #ifdef VENUS_PRESENT
mm_stream_calc_offset_video(cam_dimension_t * dim,cam_stream_buf_plane_info_t * buf_planes)2494 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim,
2495                                     cam_stream_buf_plane_info_t *buf_planes)
2496 {
2497     int stride = 0, scanline = 0;
2498 
2499     // using Venus
2500     stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
2501     scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
2502 
2503     buf_planes->plane_info.frame_len =
2504         VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height);
2505     buf_planes->plane_info.num_planes = 2;
2506     buf_planes->plane_info.mp[0].len = stride * scanline;
2507     buf_planes->plane_info.mp[0].offset = 0;
2508     buf_planes->plane_info.mp[0].offset_x =0;
2509     buf_planes->plane_info.mp[0].offset_y = 0;
2510     buf_planes->plane_info.mp[0].stride = stride;
2511     buf_planes->plane_info.mp[0].scanline = scanline;
2512     buf_planes->plane_info.mp[0].width = dim->width;
2513     buf_planes->plane_info.mp[0].height = dim->height;
2514     stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
2515     scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
2516     buf_planes->plane_info.mp[1].len =
2517         buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
2518     buf_planes->plane_info.mp[1].offset = 0;
2519     buf_planes->plane_info.mp[1].offset_x =0;
2520     buf_planes->plane_info.mp[1].offset_y = 0;
2521     buf_planes->plane_info.mp[1].stride = stride;
2522     buf_planes->plane_info.mp[1].scanline = scanline;
2523     buf_planes->plane_info.mp[1].width = dim->width;
2524     buf_planes->plane_info.mp[1].height = dim->height;
2525 
2526     return 0;
2527 }
2528 #else
mm_stream_calc_offset_video(cam_dimension_t * dim,cam_stream_buf_plane_info_t * buf_planes)2529 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim,
2530                                     cam_stream_buf_plane_info_t *buf_planes)
2531 {
2532     int stride = 0, scanline = 0;
2533 
2534     buf_planes->plane_info.num_planes = 2;
2535 
2536     stride = dim->width;
2537     scanline = dim->height;
2538     buf_planes->plane_info.mp[0].len =
2539         PAD_TO_SIZE(stride * scanline, CAM_PAD_TO_2K);
2540     buf_planes->plane_info.mp[0].offset = 0;
2541     buf_planes->plane_info.mp[0].offset_x =0;
2542     buf_planes->plane_info.mp[0].offset_y = 0;
2543     buf_planes->plane_info.mp[0].stride = stride;
2544     buf_planes->plane_info.mp[0].scanline = scanline;
2545     buf_planes->plane_info.mp[0].width = dim->width;
2546     buf_planes->plane_info.mp[0].height = dim->height;
2547 
2548     stride = dim->width;
2549     scanline = dim->height / 2;
2550     buf_planes->plane_info.mp[1].len =
2551         PAD_TO_SIZE(stride * scanline, CAM_PAD_TO_2K);
2552     buf_planes->plane_info.mp[1].offset = 0;
2553     buf_planes->plane_info.mp[1].offset_x =0;
2554     buf_planes->plane_info.mp[1].offset_y = 0;
2555     buf_planes->plane_info.mp[1].stride = stride;
2556     buf_planes->plane_info.mp[1].scanline = scanline;
2557     buf_planes->plane_info.mp[0].width = dim->width;
2558     buf_planes->plane_info.mp[0].height = dim->height / 2;
2559 
2560     buf_planes->plane_info.frame_len =
2561         PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2562                     buf_planes->plane_info.mp[1].len,
2563                     CAM_PAD_TO_4K);
2564 
2565     return 0;
2566 }
2567 #endif
2568 
2569 /*===========================================================================
2570  * FUNCTION   : mm_stream_calc_offset_metadata
2571  *
2572  * DESCRIPTION: calculate metadata frame offset based on format and
2573  *              padding information
2574  *
2575  * PARAMETERS :
2576  *   @dim     : image dimension
2577  *   @padding : padding information
2578  *   @buf_planes : [out] buffer plane information
2579  *
2580  * RETURN     : int32_t type of status
2581  *              0  -- success
2582  *              -1 -- failure
2583  *==========================================================================*/
mm_stream_calc_offset_metadata(cam_dimension_t * dim,cam_padding_info_t * padding,cam_stream_buf_plane_info_t * buf_planes)2584 int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim,
2585                                        cam_padding_info_t *padding,
2586                                        cam_stream_buf_plane_info_t *buf_planes)
2587 {
2588     int32_t rc = 0;
2589     buf_planes->plane_info.num_planes = 1;
2590     buf_planes->plane_info.mp[0].offset = 0;
2591     buf_planes->plane_info.mp[0].len =
2592         PAD_TO_SIZE(dim->width * dim->height, padding->plane_padding);
2593     buf_planes->plane_info.frame_len =
2594         buf_planes->plane_info.mp[0].len;
2595 
2596     buf_planes->plane_info.mp[0].offset_x =0;
2597     buf_planes->plane_info.mp[0].offset_y = 0;
2598     buf_planes->plane_info.mp[0].stride = dim->width;
2599     buf_planes->plane_info.mp[0].scanline = dim->height;
2600     buf_planes->plane_info.mp[0].width = dim->width;
2601     buf_planes->plane_info.mp[0].height = dim->height;
2602     return rc;
2603 }
2604 
2605 /*===========================================================================
2606  * FUNCTION   : mm_stream_calc_offset_postproc
2607  *
2608  * DESCRIPTION: calculate postprocess frame offset
2609  *
2610  * PARAMETERS :
2611  *   @stream_info: ptr to stream info
2612  *   @padding : padding information
2613  *   @plns : [out] buffer plane information
2614  *
2615  * RETURN     : int32_t type of status
2616  *              0  -- success
2617  *              -1 -- failure
2618  *==========================================================================*/
mm_stream_calc_offset_postproc(cam_stream_info_t * stream_info,cam_padding_info_t * padding,cam_stream_buf_plane_info_t * plns)2619 int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info,
2620                                        cam_padding_info_t *padding,
2621                                        cam_stream_buf_plane_info_t *plns)
2622 {
2623     int32_t rc = 0;
2624     cam_stream_type_t type = CAM_STREAM_TYPE_DEFAULT;
2625     if (stream_info->reprocess_config.pp_type == CAM_OFFLINE_REPROCESS_TYPE) {
2626         type = stream_info->reprocess_config.offline.input_type;
2627         if (CAM_STREAM_TYPE_DEFAULT == type) {
2628             if (plns->plane_info.frame_len == 0) {
2629                 // take offset from input source
2630                 *plns = stream_info->reprocess_config.offline.input_buf_planes;
2631                 return rc;
2632             }
2633         } else {
2634             type = stream_info->reprocess_config.offline.input_type;
2635         }
2636     } else {
2637         type = stream_info->reprocess_config.online.input_stream_type;
2638     }
2639 
2640     switch (type) {
2641     case CAM_STREAM_TYPE_PREVIEW:
2642     case CAM_STREAM_TYPE_CALLBACK:
2643         rc = mm_stream_calc_offset_preview(stream_info->fmt,
2644                                            &stream_info->dim,
2645                                            plns);
2646         break;
2647     case CAM_STREAM_TYPE_POSTVIEW:
2648         rc = mm_stream_calc_offset_post_view(stream_info->fmt,
2649                                            &stream_info->dim,
2650                                            plns);
2651         break;
2652     case CAM_STREAM_TYPE_SNAPSHOT:
2653         rc = mm_stream_calc_offset_snapshot(stream_info->fmt,
2654                                             &stream_info->dim,
2655                                             padding,
2656                                             plns);
2657         break;
2658     case CAM_STREAM_TYPE_VIDEO:
2659         rc = mm_stream_calc_offset_video(&stream_info->dim,
2660                         plns);
2661         break;
2662     case CAM_STREAM_TYPE_RAW:
2663         rc = mm_stream_calc_offset_raw(stream_info->fmt,
2664                                        &stream_info->dim,
2665                                        padding,
2666                                        plns);
2667         break;
2668     case CAM_STREAM_TYPE_METADATA:
2669         rc = mm_stream_calc_offset_metadata(&stream_info->dim,
2670                                             padding,
2671                                             plns);
2672         break;
2673     default:
2674         CDBG_ERROR("%s: not supported for stream type %d",
2675                    __func__, type);
2676         rc = -1;
2677         break;
2678     }
2679     return rc;
2680 }
2681 
2682 /*===========================================================================
2683  * FUNCTION   : mm_stream_calc_offset
2684  *
2685  * DESCRIPTION: calculate frame offset based on format and padding information
2686  *
2687  * PARAMETERS :
2688  *   @my_obj  : stream object
2689  *
2690  * RETURN     : int32_t type of status
2691  *              0  -- success
2692  *              -1 -- failure
2693  *==========================================================================*/
mm_stream_calc_offset(mm_stream_t * my_obj)2694 int32_t mm_stream_calc_offset(mm_stream_t *my_obj)
2695 {
2696     int32_t rc = 0;
2697 
2698     cam_dimension_t dim = my_obj->stream_info->dim;
2699     if (my_obj->stream_info->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION &&
2700         my_obj->stream_info->stream_type != CAM_STREAM_TYPE_VIDEO) {
2701         if (my_obj->stream_info->pp_config.rotation == ROTATE_90 ||
2702             my_obj->stream_info->pp_config.rotation == ROTATE_270) {
2703             // rotated by 90 or 270, need to switch width and height
2704             dim.width = my_obj->stream_info->dim.height;
2705             dim.height = my_obj->stream_info->dim.width;
2706         }
2707     }
2708 
2709     switch (my_obj->stream_info->stream_type) {
2710     case CAM_STREAM_TYPE_PREVIEW:
2711     case CAM_STREAM_TYPE_CALLBACK:
2712         rc = mm_stream_calc_offset_preview(my_obj->stream_info->fmt,
2713                                            &dim,
2714                                            &my_obj->stream_info->buf_planes);
2715         break;
2716     case CAM_STREAM_TYPE_POSTVIEW:
2717       rc = mm_stream_calc_offset_post_view(my_obj->stream_info->fmt,
2718                                          &dim,
2719                                          &my_obj->stream_info->buf_planes);
2720       break;
2721     case CAM_STREAM_TYPE_SNAPSHOT:
2722         rc = mm_stream_calc_offset_snapshot(my_obj->stream_info->fmt,
2723                                             &dim,
2724                                             &my_obj->padding_info,
2725                                             &my_obj->stream_info->buf_planes);
2726         break;
2727     case CAM_STREAM_TYPE_OFFLINE_PROC:
2728         rc = mm_stream_calc_offset_postproc(my_obj->stream_info,
2729                                             &my_obj->padding_info,
2730                                             &my_obj->stream_info->buf_planes);
2731         break;
2732     case CAM_STREAM_TYPE_VIDEO:
2733         rc = mm_stream_calc_offset_video(&dim,
2734                                          &my_obj->stream_info->buf_planes);
2735         break;
2736     case CAM_STREAM_TYPE_RAW:
2737         rc = mm_stream_calc_offset_raw(my_obj->stream_info->fmt,
2738                                        &dim,
2739                                        &my_obj->padding_info,
2740                                        &my_obj->stream_info->buf_planes);
2741         break;
2742     case CAM_STREAM_TYPE_METADATA:
2743         rc = mm_stream_calc_offset_metadata(&dim,
2744                                             &my_obj->padding_info,
2745                                             &my_obj->stream_info->buf_planes);
2746         break;
2747     default:
2748         CDBG_ERROR("%s: not supported for stream type %d",
2749                    __func__, my_obj->stream_info->stream_type);
2750         rc = -1;
2751         break;
2752     }
2753 
2754     my_obj->frame_offset = my_obj->stream_info->buf_planes.plane_info;
2755     return rc;
2756 }
2757 
2758 /*===========================================================================
2759  * FUNCTION   : mm_stream_sync_info
2760  *
2761  * DESCRIPTION: synchronize stream information with server
2762  *
2763  * PARAMETERS :
2764  *   @my_obj  : stream object
2765  *
2766  * RETURN     : int32_t type of status
2767  *              0  -- success
2768  *              -1 -- failure
2769  * NOTE       : assume stream info buffer is mapped to server and filled in with
2770  *              stream information by upper layer. This call will let server to
2771  *              synchornize the stream information with HAL. If server find any
2772  *              fields that need to be changed accroding to hardware configuration,
2773  *              server will modify corresponding fields so that HAL could know
2774  *              about it.
2775  *==========================================================================*/
mm_stream_sync_info(mm_stream_t * my_obj)2776 int32_t mm_stream_sync_info(mm_stream_t *my_obj)
2777 {
2778     int32_t rc = 0;
2779     int32_t value = 0;
2780     my_obj->stream_info->stream_svr_id = my_obj->server_stream_id;
2781     rc = mm_stream_calc_offset(my_obj);
2782 
2783     if (rc == 0) {
2784         rc = mm_camera_util_s_ctrl(my_obj->fd,
2785                                    CAM_PRIV_STREAM_INFO_SYNC,
2786                                    &value);
2787     }
2788     return rc;
2789 }
2790 
2791 /*===========================================================================
2792  * FUNCTION   : mm_stream_set_fmt
2793  *
2794  * DESCRIPTION: set stream format to kernel via v4l2 ioctl
2795  *
2796  * PARAMETERS :
2797  *   @my_obj  : stream object
2798  *
2799  * RETURN     : int32_t type of status
2800  *              0  -- success
2801  *              -1 -- failure
2802  *==========================================================================*/
mm_stream_set_fmt(mm_stream_t * my_obj)2803 int32_t mm_stream_set_fmt(mm_stream_t *my_obj)
2804 {
2805     int32_t rc = 0;
2806     struct v4l2_format fmt;
2807     struct msm_v4l2_format_data msm_fmt;
2808     int i;
2809 
2810     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
2811          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
2812 
2813     if (my_obj->stream_info->dim.width == 0 ||
2814         my_obj->stream_info->dim.height == 0) {
2815         CDBG_ERROR("%s:invalid input[w=%d,h=%d,fmt=%d]\n",
2816                    __func__,
2817                    my_obj->stream_info->dim.width,
2818                    my_obj->stream_info->dim.height,
2819                    my_obj->stream_info->fmt);
2820         return -1;
2821     }
2822 
2823     memset(&fmt, 0, sizeof(fmt));
2824     memset(&msm_fmt, 0, sizeof(msm_fmt));
2825     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2826     msm_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2827     msm_fmt.width = my_obj->stream_info->dim.width;
2828     msm_fmt.height = my_obj->stream_info->dim.height;
2829     msm_fmt.pixelformat = mm_stream_get_v4l2_fmt(my_obj->stream_info->fmt);
2830     msm_fmt.num_planes = my_obj->frame_offset.num_planes;
2831     for (i = 0; i < msm_fmt.num_planes; i++) {
2832         msm_fmt.plane_sizes[i] = my_obj->frame_offset.mp[i].len;
2833     }
2834 
2835     memcpy(fmt.fmt.raw_data, &msm_fmt, sizeof(msm_fmt));
2836     rc = ioctl(my_obj->fd, VIDIOC_S_FMT, &fmt);
2837     return rc;
2838 }
2839 
2840 /*===========================================================================
2841  * FUNCTION   : mm_stream_buf_done
2842  *
2843  * DESCRIPTION: enqueue buffer back to kernel
2844  *
2845  * PARAMETERS :
2846  *   @my_obj       : stream object
2847  *   @frame        : frame to be enqueued back to kernel
2848  *
2849  * RETURN     : int32_t type of status
2850  *              0  -- success
2851  *              -1 -- failure
2852  *==========================================================================*/
mm_stream_buf_done(mm_stream_t * my_obj,mm_camera_buf_def_t * frame)2853 int32_t mm_stream_buf_done(mm_stream_t * my_obj,
2854                            mm_camera_buf_def_t *frame)
2855 {
2856     int32_t rc = 0;
2857     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
2858          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
2859 
2860     pthread_mutex_lock(&my_obj->buf_lock);
2861     if(my_obj->buf_status[frame->buf_idx].buf_refcnt == 0) {
2862         CDBG("%s: Error Trying to free second time?(idx=%d) count=%d\n",
2863                    __func__, frame->buf_idx,
2864                    my_obj->buf_status[frame->buf_idx].buf_refcnt);
2865         rc = -1;
2866     }else{
2867         my_obj->buf_status[frame->buf_idx].buf_refcnt--;
2868         if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) {
2869             CDBG("<DEBUG> : Buf done for buffer:%d, stream:%d", frame->buf_idx, frame->stream_type);
2870             rc = mm_stream_qbuf(my_obj, frame);
2871             if(rc < 0) {
2872                 CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n",
2873                            __func__, frame->buf_idx, rc);
2874             } else {
2875                 my_obj->buf_status[frame->buf_idx].in_kernel = 1;
2876             }
2877         }else{
2878             CDBG("<DEBUG> : Still ref count pending count :%d",
2879                  my_obj->buf_status[frame->buf_idx].buf_refcnt);
2880             CDBG("<DEBUG> : for buffer:%p:%d",
2881                  my_obj, frame->buf_idx);
2882         }
2883     }
2884     pthread_mutex_unlock(&my_obj->buf_lock);
2885     return rc;
2886 }
2887 
2888 /*===========================================================================
2889  * FUNCTION   : mm_stream_reg_buf_cb
2890  *
2891  * DESCRIPTION: Allow other stream to register dataCB at this stream.
2892  *
2893  * PARAMETERS :
2894  *   @my_obj       : stream object
2895  *   @val          : ptr to info about the callback to be registered
2896  *
2897  * RETURN     : int32_t type of status
2898  *              0  -- success
2899  *              -1 -- failure
2900  *==========================================================================*/
mm_stream_reg_buf_cb(mm_stream_t * my_obj,mm_stream_data_cb_t * val)2901 int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj,
2902                              mm_stream_data_cb_t *val)
2903 {
2904     int32_t rc = -1;
2905     uint8_t i;
2906     CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
2907          __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
2908 
2909     pthread_mutex_lock(&my_obj->cb_lock);
2910     for (i=0 ;i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
2911         if(NULL == my_obj->buf_cb[i].cb) {
2912             my_obj->buf_cb[i] = *val;
2913             rc = 0;
2914             break;
2915         }
2916     }
2917     pthread_mutex_unlock(&my_obj->cb_lock);
2918 
2919     return rc;
2920 }
2921