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