mm_camera_stream.c revision 7fde32d818742141a39fda194e66b84109182aff
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 */
48int32_t mm_stream_qbuf(mm_stream_t *my_obj,
49                       mm_camera_buf_def_t *buf);
50int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj);
51int32_t mm_stream_set_fmt(mm_stream_t * my_obj);
52int32_t mm_stream_sync_info(mm_stream_t *my_obj);
53int32_t mm_stream_init_bufs(mm_stream_t * my_obj);
54int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj);
55int32_t mm_stream_request_buf(mm_stream_t * my_obj);
56int32_t mm_stream_unreg_buf(mm_stream_t * my_obj);
57int32_t mm_stream_release(mm_stream_t *my_obj);
58int32_t mm_stream_set_parm(mm_stream_t *my_obj,
59                           cam_stream_parm_buffer_t *value);
60int32_t mm_stream_get_parm(mm_stream_t *my_obj,
61                           cam_stream_parm_buffer_t *value);
62int32_t mm_stream_do_action(mm_stream_t *my_obj,
63                            void *in_value);
64int32_t mm_stream_streamon(mm_stream_t *my_obj);
65int32_t mm_stream_streamoff(mm_stream_t *my_obj);
66int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
67                                 mm_camera_buf_info_t* buf_info,
68                                 uint8_t num_planes);
69int32_t mm_stream_config(mm_stream_t *my_obj,
70                         mm_camera_stream_config_t *config);
71int32_t mm_stream_reg_buf(mm_stream_t * my_obj);
72int32_t mm_stream_buf_done(mm_stream_t * my_obj,
73                           mm_camera_buf_def_t *frame);
74int32_t mm_stream_calc_offset(mm_stream_t *my_obj);
75int32_t mm_stream_calc_offset_preview(cam_format_t fmt,
76                                      cam_dimension_t *dim,
77                                      cam_stream_buf_plane_info_t *buf_planes);
78int32_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);
82int32_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);
86int32_t mm_stream_calc_offset_video(cam_dimension_t *dim,
87                                    cam_stream_buf_plane_info_t *buf_planes);
88int32_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);
91int32_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 */
97int32_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);
101int32_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);
105int32_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);
109int32_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);
113int32_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);
117int32_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);
121uint32_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 *==========================================================================*/
135void 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 *==========================================================================*/
194static 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 *==========================================================================*/
258static 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 *==========================================================================*/
336int32_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 *==========================================================================*/
391int32_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 *==========================================================================*/
454int32_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 *==========================================================================*/
519int32_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 *==========================================================================*/
589int32_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 *==========================================================================*/
650int32_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 *==========================================================================*/
736int32_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 *==========================================================================*/
807int32_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 *==========================================================================*/
841int32_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 *==========================================================================*/
874int32_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    /* Add fd to data poll thread */
882    rc = mm_camera_poll_thread_add_poll_fd(&my_obj->ch_obj->poll_thread[0],
883                                           my_obj->my_hdl,
884                                           my_obj->fd,
885                                           mm_stream_data_notify,
886                                           (void*)my_obj);
887    if (rc < 0) {
888        return rc;
889    }
890    rc = ioctl(my_obj->fd, VIDIOC_STREAMON, &buf_type);
891    if (rc < 0) {
892        CDBG_ERROR("%s: ioctl VIDIOC_STREAMON failed: rc=%d\n",
893                   __func__, rc);
894        /* remove fd from data poll thread in case of failure */
895        mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl);
896    }
897    CDBG("%s :X rc = %d",__func__,rc);
898    return rc;
899}
900
901/*===========================================================================
902 * FUNCTION   : mm_stream_streamoff
903 *
904 * DESCRIPTION: stream off a stream. sending v4l2 request to kernel
905 *
906 * PARAMETERS :
907 *   @my_obj       : stream object
908 *
909 * RETURN     : int32_t type of status
910 *              0  -- success
911 *              -1 -- failure
912 *==========================================================================*/
913int32_t mm_stream_streamoff(mm_stream_t *my_obj)
914{
915    int32_t rc;
916    enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
917    CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
918         __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
919
920    /* step1: remove fd from data poll thread */
921    mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl);
922
923    /* step2: stream off */
924    rc = ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type);
925    if (rc < 0) {
926        CDBG_ERROR("%s: STREAMOFF failed: %s\n",
927                __func__, strerror(errno));
928    }
929    CDBG("%s :X rc = %d",__func__,rc);
930    return rc;
931}
932
933/*===========================================================================
934 * FUNCTION   : mm_stream_read_msm_frame
935 *
936 * DESCRIPTION: dequeue a stream buffer from kernel queue
937 *
938 * PARAMETERS :
939 *   @my_obj       : stream object
940 *   @buf_info     : ptr to a struct storing buffer information
941 *   @num_planes   : number of planes in the buffer
942 *
943 * RETURN     : int32_t type of status
944 *              0  -- success
945 *              -1 -- failure
946 *==========================================================================*/
947int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
948                                 mm_camera_buf_info_t* buf_info,
949                                 uint8_t num_planes)
950{
951    int32_t rc = 0;
952    struct v4l2_buffer vb;
953    struct v4l2_plane planes[VIDEO_MAX_PLANES];
954    CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
955         __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
956
957    memset(&vb,  0,  sizeof(vb));
958    vb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
959    vb.memory = V4L2_MEMORY_USERPTR;
960    vb.m.planes = &planes[0];
961    vb.length = num_planes;
962
963    rc = ioctl(my_obj->fd, VIDIOC_DQBUF, &vb);
964    if (rc < 0) {
965        CDBG_ERROR("%s: VIDIOC_DQBUF ioctl call failed (rc=%d)\n",
966                   __func__, rc);
967    } else {
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_HIGH("%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        my_obj->mem_vtbl.clean_invalidate_buf(idx,
981                                my_obj->mem_vtbl.user_data);
982    }
983
984    CDBG("%s :X rc = %d",__func__,rc);
985    return rc;
986}
987
988/*===========================================================================
989 * FUNCTION   : mm_stream_set_parms
990 *
991 * DESCRIPTION: set parameters per stream
992 *
993 * PARAMETERS :
994 *   @my_obj       : stream object
995 *   @in_value     : ptr to a param struct to be set to server
996 *
997 * RETURN     : int32_t type of status
998 *              0  -- success
999 *              -1 -- failure
1000 * NOTE       : Assume the parms struct buf is already mapped to server via
1001 *              domain socket. Corresponding fields of parameters to be set
1002 *              are already filled in by upper layer caller.
1003 *==========================================================================*/
1004int32_t mm_stream_set_parm(mm_stream_t *my_obj,
1005                           cam_stream_parm_buffer_t *in_value)
1006{
1007    int32_t rc = -1;
1008    int32_t value = 0;
1009    if (in_value != NULL) {
1010        rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
1011    }
1012    return rc;
1013}
1014
1015/*===========================================================================
1016 * FUNCTION   : mm_stream_get_parms
1017 *
1018 * DESCRIPTION: get parameters per stream
1019 *
1020 * PARAMETERS :
1021 *   @my_obj       : stream object
1022 *   @in_value     : ptr to a param struct to be get from server
1023 *
1024 * RETURN     : int32_t type of status
1025 *              0  -- success
1026 *              -1 -- failure
1027 * NOTE       : Assume the parms struct buf is already mapped to server via
1028 *              domain socket. Corresponding fields of parameters to be get
1029 *              are already filled in by upper layer caller.
1030 *==========================================================================*/
1031int32_t mm_stream_get_parm(mm_stream_t *my_obj,
1032                           cam_stream_parm_buffer_t *in_value)
1033{
1034    int32_t rc = -1;
1035    int32_t value = 0;
1036    if (in_value != NULL) {
1037        rc = mm_camera_util_g_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
1038    }
1039    return rc;
1040}
1041
1042/*===========================================================================
1043 * FUNCTION   : mm_stream_do_actions
1044 *
1045 * DESCRIPTION: request server to perform stream based actions
1046 *
1047 * PARAMETERS :
1048 *   @my_obj       : stream object
1049 *   @in_value     : ptr to a struct of actions to be performed by the server
1050 *
1051 * RETURN     : int32_t type of status
1052 *              0  -- success
1053 *              -1 -- failure
1054 * NOTE       : Assume the action struct buf is already mapped to server via
1055 *              domain socket. Corresponding fields of actions to be performed
1056 *              are already filled in by upper layer caller.
1057 *==========================================================================*/
1058int32_t mm_stream_do_action(mm_stream_t *my_obj,
1059                            void *in_value)
1060{
1061    int32_t rc = -1;
1062    int32_t value = 0;
1063    if (in_value != NULL) {
1064        rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
1065    }
1066    return rc;
1067}
1068
1069/*===========================================================================
1070 * FUNCTION   : mm_stream_set_ext_mode
1071 *
1072 * DESCRIPTION: set stream extended mode to server via v4l2 ioctl
1073 *
1074 * PARAMETERS :
1075 *   @my_obj       : stream object
1076 *
1077 * RETURN     : int32_t type of status
1078 *              0  -- success
1079 *              -1 -- failure
1080 * NOTE       : Server will return a server stream id that uniquely identify
1081 *              this stream on server side. Later on communication to server
1082 *              per stream should use this server stream id.
1083 *==========================================================================*/
1084int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj)
1085{
1086    int32_t rc = 0;
1087    struct v4l2_streamparm s_parm;
1088    CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1089         __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1090
1091    memset(&s_parm, 0, sizeof(s_parm));
1092    s_parm.type =  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1093
1094    rc = ioctl(my_obj->fd, VIDIOC_S_PARM, &s_parm);
1095    CDBG("%s:stream fd=%d, rc=%d, extended_mode=%d\n",
1096         __func__, my_obj->fd, rc, s_parm.parm.capture.extendedmode);
1097    if (rc == 0) {
1098        /* get server stream id */
1099        my_obj->server_stream_id = s_parm.parm.capture.extendedmode;
1100    }
1101    return rc;
1102}
1103
1104/*===========================================================================
1105 * FUNCTION   : mm_stream_qbuf
1106 *
1107 * DESCRIPTION: enqueue buffer back to kernel queue for furture use
1108 *
1109 * PARAMETERS :
1110 *   @my_obj       : stream object
1111 *   @buf          : ptr to a struct storing buffer information
1112 *
1113 * RETURN     : int32_t type of status
1114 *              0  -- success
1115 *              -1 -- failure
1116 *==========================================================================*/
1117int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf)
1118{
1119    int32_t rc = 0;
1120    struct v4l2_buffer buffer;
1121	struct v4l2_plane planes[VIDEO_MAX_PLANES];
1122    CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1123         __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1124
1125	memcpy(planes, buf->planes, sizeof(planes));
1126    memset(&buffer, 0, sizeof(buffer));
1127    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1128    buffer.memory = V4L2_MEMORY_USERPTR;
1129    buffer.index = buf->buf_idx;
1130    buffer.m.planes = &planes[0];
1131    buffer.length = buf->num_planes;
1132
1133    CDBG("%s:plane 0: stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d, offset = %d, data_offset = %d\n", __func__,
1134         buf->stream_id, buf->fd, buffer.index, buffer.length, buf->planes[0].reserved[0], buf->planes[0].data_offset);
1135	CDBG("%s:plane 1: stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d, offset = %d, data_offset = %d\n", __func__,
1136         buf->stream_id, buf->fd, buffer.index, buffer.length, buf->planes[1].reserved[0], buf->planes[1].data_offset);
1137
1138    rc = ioctl(my_obj->fd, VIDIOC_QBUF, &buffer);
1139    CDBG("%s: qbuf idx:%d, rc:%d", __func__, buffer.index, rc);
1140    return rc;
1141}
1142
1143/*===========================================================================
1144 * FUNCTION   : mm_stream_request_buf
1145 *
1146 * DESCRIPTION: This function let kernel know the amount of buffers need to
1147 *              be registered via v4l2 ioctl.
1148 *
1149 * PARAMETERS :
1150 *   @my_obj       : stream object
1151 *
1152 * RETURN     : int32_t type of status
1153 *              0  -- success
1154 *              -1 -- failure
1155 *==========================================================================*/
1156int32_t mm_stream_request_buf(mm_stream_t * my_obj)
1157{
1158    int32_t rc = 0;
1159    uint8_t i,reg = 0;
1160    struct v4l2_requestbuffers bufreq;
1161    uint8_t buf_num = my_obj->buf_num;
1162    CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1163         __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1164
1165    if(buf_num > MM_CAMERA_MAX_NUM_FRAMES) {
1166        CDBG_ERROR("%s: buf num %d > max limit %d\n",
1167                   __func__, buf_num, MM_CAMERA_MAX_NUM_FRAMES);
1168        return -1;
1169    }
1170
1171    pthread_mutex_lock(&my_obj->buf_lock);
1172    for(i = 0; i < buf_num; i++){
1173        if (my_obj->buf_status[i].initial_reg_flag){
1174            reg = 1;
1175            break;
1176        }
1177    }
1178    pthread_mutex_unlock(&my_obj->buf_lock);
1179
1180    if(!reg) {
1181        /* No need to register a buffer */
1182        CDBG_ERROR("No Need to register this buffer");
1183        return rc;
1184    }
1185    memset(&bufreq, 0, sizeof(bufreq));
1186    bufreq.count = buf_num;
1187    bufreq.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1188    bufreq.memory = V4L2_MEMORY_USERPTR;
1189    rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
1190    if (rc < 0) {
1191      CDBG_ERROR("%s: fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d\n",
1192           __func__, my_obj->fd, rc);
1193    }
1194    CDBG("%s :X rc = %d",__func__,rc);
1195    return rc;
1196}
1197
1198/*===========================================================================
1199 * FUNCTION   : mm_stream_map_buf
1200 *
1201 * DESCRIPTION: mapping stream buffer via domain socket to server
1202 *
1203 * PARAMETERS :
1204 *   @my_obj       : stream object
1205 *   @buf_type     : type of buffer to be mapped. could be following values:
1206 *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1207 *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1208 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1209 *   @frame_idx    : index of buffer within the stream buffers, only valid if
1210 *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1211 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1212 *   @plane_idx    : plane index. If all planes share the same fd,
1213 *                   plane_idx = -1; otherwise, plean_idx is the
1214 *                   index to plane (0..num_of_planes)
1215 *   @fd           : file descriptor of the buffer
1216 *   @size         : size of the buffer
1217 *
1218 * RETURN     : int32_t type of status
1219 *              0  -- success
1220 *              -1 -- failure
1221 *==========================================================================*/
1222int32_t mm_stream_map_buf(mm_stream_t * my_obj,
1223                          uint8_t buf_type,
1224                          uint32_t frame_idx,
1225                          int32_t plane_idx,
1226                          int fd,
1227                          uint32_t size)
1228{
1229    if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
1230        CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__);
1231        return -1;
1232    }
1233
1234    cam_sock_packet_t packet;
1235    memset(&packet, 0, sizeof(cam_sock_packet_t));
1236    packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;
1237    packet.payload.buf_map.type = buf_type;
1238    packet.payload.buf_map.fd = fd;
1239    packet.payload.buf_map.size = size;
1240    packet.payload.buf_map.stream_id = my_obj->server_stream_id;
1241    packet.payload.buf_map.frame_idx = frame_idx;
1242    packet.payload.buf_map.plane_idx = plane_idx;
1243    return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
1244                                  &packet,
1245                                  sizeof(cam_sock_packet_t),
1246                                  fd);
1247}
1248
1249/*===========================================================================
1250 * FUNCTION   : mm_stream_unmap_buf
1251 *
1252 * DESCRIPTION: unmapping stream buffer via domain socket to server
1253 *
1254 * PARAMETERS :
1255 *   @my_obj       : stream object
1256 *   @buf_type     : type of buffer to be unmapped. could be following values:
1257 *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
1258 *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
1259 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1260 *   @frame_idx    : index of buffer within the stream buffers, only valid if
1261 *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1262 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1263 *   @plane_idx    : plane index. If all planes share the same fd,
1264 *                   plane_idx = -1; otherwise, plean_idx is the
1265 *                   index to plane (0..num_of_planes)
1266 *
1267 * RETURN     : int32_t type of status
1268 *              0  -- success
1269 *              -1 -- failure
1270 *==========================================================================*/
1271int32_t mm_stream_unmap_buf(mm_stream_t * my_obj,
1272                            uint8_t buf_type,
1273                            uint32_t frame_idx,
1274                            int32_t plane_idx)
1275{
1276    if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
1277        CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__);
1278        return -1;
1279    }
1280
1281    cam_sock_packet_t packet;
1282    memset(&packet, 0, sizeof(cam_sock_packet_t));
1283    packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING;
1284    packet.payload.buf_unmap.type = buf_type;
1285    packet.payload.buf_unmap.stream_id = my_obj->server_stream_id;
1286    packet.payload.buf_unmap.frame_idx = frame_idx;
1287    packet.payload.buf_unmap.plane_idx = plane_idx;
1288    return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
1289                                  &packet,
1290                                  sizeof(cam_sock_packet_t),
1291                                  0);
1292}
1293
1294/*===========================================================================
1295 * FUNCTION   : mm_stream_map_buf_ops
1296 *
1297 * DESCRIPTION: ops for mapping stream buffer via domain socket to server.
1298 *              This function will be passed to upper layer as part of ops table
1299 *              to be used by upper layer when allocating stream buffers and mapping
1300 *              buffers to server via domain socket.
1301 *
1302 * PARAMETERS :
1303 *   @frame_idx    : index of buffer within the stream buffers, only valid if
1304 *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1305 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1306 *   @plane_idx    : plane index. If all planes share the same fd,
1307 *                   plane_idx = -1; otherwise, plean_idx is the
1308 *                   index to plane (0..num_of_planes)
1309 *   @fd           : file descriptor of the buffer
1310 *   @size         : size of the buffer
1311 *   @userdata     : user data ptr (stream object)
1312 *
1313 * RETURN     : int32_t type of status
1314 *              0  -- success
1315 *              -1 -- failure
1316 *==========================================================================*/
1317static int32_t mm_stream_map_buf_ops(uint32_t frame_idx,
1318                                     int32_t plane_idx,
1319                                     int fd,
1320                                     uint32_t size,
1321                                     void *userdata)
1322{
1323    mm_stream_t *my_obj = (mm_stream_t *)userdata;
1324    return mm_stream_map_buf(my_obj,
1325                             CAM_MAPPING_BUF_TYPE_STREAM_BUF,
1326                             frame_idx, plane_idx, fd, size);
1327}
1328
1329/*===========================================================================
1330 * FUNCTION   : mm_stream_unmap_buf_ops
1331 *
1332 * DESCRIPTION: ops for unmapping stream buffer via domain socket to server.
1333 *              This function will be passed to upper layer as part of ops table
1334 *              to be used by upper layer when allocating stream buffers and unmapping
1335 *              buffers to server via domain socket.
1336 *
1337 * PARAMETERS :
1338 *   @frame_idx    : index of buffer within the stream buffers, only valid if
1339 *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1340 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1341 *   @plane_idx    : plane index. If all planes share the same fd,
1342 *                   plane_idx = -1; otherwise, plean_idx is the
1343 *                   index to plane (0..num_of_planes)
1344 *   @userdata     : user data ptr (stream object)
1345 *
1346 * RETURN     : int32_t type of status
1347 *              0  -- success
1348 *              -1 -- failure
1349 *==========================================================================*/
1350static int32_t mm_stream_unmap_buf_ops(uint32_t frame_idx,
1351                                       int32_t plane_idx,
1352                                       void *userdata)
1353{
1354    mm_stream_t *my_obj = (mm_stream_t *)userdata;
1355    return mm_stream_unmap_buf(my_obj,
1356                               CAM_MAPPING_BUF_TYPE_STREAM_BUF,
1357                               frame_idx,
1358                               plane_idx);
1359}
1360
1361/*===========================================================================
1362 * FUNCTION   : mm_stream_init_bufs
1363 *
1364 * DESCRIPTION: initialize stream buffers needed. This function will request
1365 *              buffers needed from upper layer through the mem ops table passed
1366 *              during configuration stage.
1367 *
1368 * PARAMETERS :
1369 *   @my_obj  : stream object
1370 *
1371 * RETURN     : int32_t type of status
1372 *              0  -- success
1373 *              -1 -- failure
1374 *==========================================================================*/
1375int32_t mm_stream_init_bufs(mm_stream_t * my_obj)
1376{
1377    int32_t i, rc = 0;
1378    uint8_t *reg_flags = NULL;
1379    mm_camera_map_unmap_ops_tbl_t ops_tbl;
1380    CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1381         __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1382
1383    /* deinit buf if it's not NULL*/
1384    if (NULL != my_obj->buf) {
1385        mm_stream_deinit_bufs(my_obj);
1386    }
1387
1388    ops_tbl.map_ops = mm_stream_map_buf_ops;
1389    ops_tbl.unmap_ops = mm_stream_unmap_buf_ops;
1390    ops_tbl.userdata = my_obj;
1391
1392    rc = my_obj->mem_vtbl.get_bufs(&my_obj->frame_offset,
1393                                   &my_obj->buf_num,
1394                                   &reg_flags,
1395                                   &my_obj->buf,
1396                                   &ops_tbl,
1397                                   my_obj->mem_vtbl.user_data);
1398
1399    if (0 != rc) {
1400        CDBG_ERROR("%s: Error get buf, rc = %d\n", __func__, rc);
1401        return rc;
1402    }
1403
1404    my_obj->buf_status =
1405        (mm_stream_buf_status_t *)malloc(sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
1406
1407    if (NULL == my_obj->buf_status) {
1408        CDBG_ERROR("%s: No memory for buf_status", __func__);
1409        mm_stream_deinit_bufs(my_obj);
1410        free(reg_flags);
1411        return -1;
1412    }
1413
1414    memset(my_obj->buf_status, 0, sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
1415    for (i = 0; i < my_obj->buf_num; i++) {
1416        my_obj->buf_status[i].initial_reg_flag = reg_flags[i];
1417        my_obj->buf[i].stream_id = my_obj->my_hdl;
1418        my_obj->buf[i].stream_type = my_obj->stream_info->stream_type;
1419    }
1420
1421    free(reg_flags);
1422    reg_flags = NULL;
1423
1424    return rc;
1425}
1426
1427/*===========================================================================
1428 * FUNCTION   : mm_stream_deinit_bufs
1429 *
1430 * DESCRIPTION: return stream buffers to upper layer through the mem ops table
1431 *              passed during configuration stage.
1432 *
1433 * PARAMETERS :
1434 *   @my_obj  : stream object
1435 *
1436 * RETURN     : int32_t type of status
1437 *              0  -- success
1438 *              -1 -- failure
1439 *==========================================================================*/
1440int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj)
1441{
1442    int32_t rc = 0;
1443    mm_camera_map_unmap_ops_tbl_t ops_tbl;
1444    CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1445         __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1446
1447    if (NULL == my_obj->buf) {
1448        CDBG("%s: Buf is NULL, no need to deinit", __func__);
1449        return rc;
1450    }
1451
1452    /* release bufs */
1453    ops_tbl.map_ops = mm_stream_map_buf_ops;
1454    ops_tbl.unmap_ops = mm_stream_unmap_buf_ops;
1455    ops_tbl.userdata = my_obj;
1456
1457    rc = my_obj->mem_vtbl.put_bufs(&ops_tbl,
1458                                   my_obj->mem_vtbl.user_data);
1459
1460    free(my_obj->buf);
1461    my_obj->buf = NULL;
1462    if (my_obj->buf_status != NULL) {
1463        free(my_obj->buf_status);
1464        my_obj->buf_status = NULL;
1465    }
1466
1467    return rc;
1468}
1469
1470/*===========================================================================
1471 * FUNCTION   : mm_stream_reg_buf
1472 *
1473 * DESCRIPTION: register buffers with kernel by calling v4l2 ioctl QBUF for
1474 *              each buffer in the stream
1475 *
1476 * PARAMETERS :
1477 *   @my_obj  : stream object
1478 *
1479 * RETURN     : int32_t type of status
1480 *              0  -- success
1481 *              -1 -- failure
1482 *==========================================================================*/
1483int32_t mm_stream_reg_buf(mm_stream_t * my_obj)
1484{
1485    int32_t rc = 0;
1486    uint8_t i;
1487    CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1488         __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1489
1490    rc = mm_stream_request_buf(my_obj);
1491    if (rc != 0) {
1492        return rc;
1493    }
1494
1495    pthread_mutex_lock(&my_obj->buf_lock);
1496    for(i = 0; i < my_obj->buf_num; i++){
1497        /* check if need to qbuf initially */
1498        if (my_obj->buf_status[i].initial_reg_flag) {
1499            rc = mm_stream_qbuf(my_obj, &my_obj->buf[i]);
1500            if (rc != 0) {
1501                CDBG_ERROR("%s: VIDIOC_QBUF rc = %d\n", __func__, rc);
1502                break;
1503            }
1504            my_obj->buf_status[i].buf_refcnt = 0;
1505            my_obj->buf_status[i].in_kernel = 1;
1506        } else {
1507            /* the buf is held by upper layer, will not queue into kernel.
1508             * add buf reference count */
1509            my_obj->buf_status[i].buf_refcnt = 1;
1510            my_obj->buf_status[i].in_kernel = 0;
1511        }
1512    }
1513    pthread_mutex_unlock(&my_obj->buf_lock);
1514
1515    return rc;
1516}
1517
1518/*===========================================================================
1519 * FUNCTION   : mm_stream_unreg buf
1520 *
1521 * DESCRIPTION: unregister all stream buffers from kernel
1522 *
1523 * PARAMETERS :
1524 *   @my_obj  : stream object
1525 *
1526 * RETURN     : int32_t type of status
1527 *              0  -- success
1528 *              -1 -- failure
1529 *==========================================================================*/
1530int32_t mm_stream_unreg_buf(mm_stream_t * my_obj)
1531{
1532    struct v4l2_requestbuffers bufreq;
1533    int32_t i, rc = 0;
1534    CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1535         __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1536
1537    /* unreg buf to kernel */
1538    bufreq.count = 0;
1539    bufreq.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1540    bufreq.memory = V4L2_MEMORY_USERPTR;
1541    rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
1542    if (rc < 0) {
1543        CDBG_ERROR("%s: fd=%d, VIDIOC_REQBUFS failed, rc=%d\n",
1544              __func__, my_obj->fd, rc);
1545    }
1546
1547    /* reset buf reference count */
1548    pthread_mutex_lock(&my_obj->buf_lock);
1549    if (NULL != my_obj->buf_status) {
1550        for(i = 0; i < my_obj->buf_num; i++){
1551            my_obj->buf_status[i].buf_refcnt = 0;
1552            my_obj->buf_status[i].in_kernel = 0;
1553        }
1554    }
1555    pthread_mutex_unlock(&my_obj->buf_lock);
1556
1557    return rc;
1558}
1559
1560/*===========================================================================
1561 * FUNCTION   : mm_stream_get_v4l2_fmt
1562 *
1563 * DESCRIPTION: translate camera image format into FOURCC code
1564 *
1565 * PARAMETERS :
1566 *   @fmt     : camera image format
1567 *
1568 * RETURN     : FOURCC code for image format
1569 *==========================================================================*/
1570uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt)
1571{
1572    uint32_t val;
1573    switch(fmt) {
1574    case CAM_FORMAT_YUV_420_NV12:
1575        val = V4L2_PIX_FMT_NV12;
1576        break;
1577    case CAM_FORMAT_YUV_420_NV21:
1578        val = V4L2_PIX_FMT_NV21;
1579        break;
1580    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG:
1581    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG:
1582    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB:
1583    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR:
1584        val= V4L2_PIX_FMT_SBGGR10;
1585        break;
1586    case CAM_FORMAT_YUV_422_NV61:
1587        val= V4L2_PIX_FMT_NV61;
1588        break;
1589    case CAM_FORMAT_YUV_RAW_8BIT_YUYV:
1590        val= V4L2_PIX_FMT_YUYV;
1591        break;
1592    case CAM_FORMAT_YUV_RAW_8BIT_YVYU:
1593        val= V4L2_PIX_FMT_YVYU;
1594        break;
1595    case CAM_FORMAT_YUV_RAW_8BIT_UYVY:
1596        val= V4L2_PIX_FMT_UYVY;
1597        break;
1598    case CAM_FORMAT_YUV_RAW_8BIT_VYUY:
1599        val= V4L2_PIX_FMT_VYUY;
1600        break;
1601    case CAM_FORMAT_YUV_420_YV12:
1602        val= V4L2_PIX_FMT_NV12;
1603        break;
1604    case CAM_FORMAT_YUV_422_NV16:
1605        val= V4L2_PIX_FMT_NV16;
1606        break;
1607    default:
1608        val = 0;
1609        CDBG_ERROR("%s: Unknown fmt=%d", __func__, fmt);
1610        break;
1611    }
1612    CDBG("%s: fmt=%d, val =%d", __func__, fmt, val);
1613    return val;
1614}
1615
1616/*===========================================================================
1617 * FUNCTION   : mm_stream_calc_offset_preview
1618 *
1619 * DESCRIPTION: calculate preview/postview frame offset based on format and
1620 *              padding information
1621 *
1622 * PARAMETERS :
1623 *   @fmt     : image format
1624 *   @dim     : image dimension
1625 *   @buf_planes : [out] buffer plane information
1626 *
1627 * RETURN     : int32_t type of status
1628 *              0  -- success
1629 *              -1 -- failure
1630 *==========================================================================*/
1631int32_t mm_stream_calc_offset_preview(cam_format_t fmt,
1632                                      cam_dimension_t *dim,
1633                                      cam_stream_buf_plane_info_t *buf_planes)
1634{
1635    int32_t rc = 0;
1636    int stride = 0, scanline = 0;
1637
1638    switch (fmt) {
1639    case CAM_FORMAT_YUV_420_NV12:
1640    case CAM_FORMAT_YUV_420_NV21:
1641        /* 2 planes: Y + CbCr */
1642        buf_planes->plane_info.num_planes = 2;
1643
1644        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1645        scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
1646        buf_planes->plane_info.mp[0].offset = 0;
1647        buf_planes->plane_info.mp[0].len = stride * scanline;
1648        buf_planes->plane_info.mp[0].offset_x = 0;
1649        buf_planes->plane_info.mp[0].offset_y = 0;
1650        buf_planes->plane_info.mp[0].stride = stride;
1651        buf_planes->plane_info.mp[0].scanline = scanline;
1652
1653        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1654        scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_2);
1655        buf_planes->plane_info.mp[1].offset = 0;
1656        buf_planes->plane_info.mp[1].len =
1657            stride * scanline;
1658        buf_planes->plane_info.mp[1].offset_x = 0;
1659        buf_planes->plane_info.mp[1].offset_y = 0;
1660        buf_planes->plane_info.mp[1].stride = stride;
1661        buf_planes->plane_info.mp[1].scanline = scanline;
1662
1663        buf_planes->plane_info.frame_len =
1664            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1665                        buf_planes->plane_info.mp[1].len,
1666                        CAM_PAD_TO_4K);
1667        break;
1668    case CAM_FORMAT_YUV_420_NV21_ADRENO:
1669        /* 2 planes: Y + CbCr */
1670        buf_planes->plane_info.num_planes = 2;
1671
1672        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
1673        scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32);
1674        buf_planes->plane_info.mp[0].offset = 0;
1675        buf_planes->plane_info.mp[0].len =
1676            PAD_TO_SIZE(stride * scanline,
1677                        CAM_PAD_TO_4K);
1678        buf_planes->plane_info.mp[0].offset_x = 0;
1679        buf_planes->plane_info.mp[0].offset_y = 0;
1680        buf_planes->plane_info.mp[0].stride = stride;
1681        buf_planes->plane_info.mp[0].scanline = scanline;
1682
1683        stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2;
1684        scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32);
1685        buf_planes->plane_info.mp[1].offset = 0;
1686        buf_planes->plane_info.mp[1].len =
1687            PAD_TO_SIZE(stride * scanline,
1688                        CAM_PAD_TO_4K);
1689        buf_planes->plane_info.mp[1].offset_x = 0;
1690        buf_planes->plane_info.mp[1].offset_y = 0;
1691        buf_planes->plane_info.mp[1].stride = stride;
1692        buf_planes->plane_info.mp[1].scanline = scanline;
1693
1694        buf_planes->plane_info.frame_len =
1695            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1696                        buf_planes->plane_info.mp[1].len,
1697                        CAM_PAD_TO_4K);
1698        break;
1699    case CAM_FORMAT_YUV_420_YV12:
1700        /* 3 planes: Y + Cr + Cb */
1701        buf_planes->plane_info.num_planes = 3;
1702
1703        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1704        scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
1705        buf_planes->plane_info.mp[0].offset = 0;
1706        buf_planes->plane_info.mp[0].len = stride * scanline;
1707        buf_planes->plane_info.mp[0].offset_x = 0;
1708        buf_planes->plane_info.mp[0].offset_y = 0;
1709        buf_planes->plane_info.mp[0].stride = stride;
1710        buf_planes->plane_info.mp[0].scanline = scanline;
1711
1712        stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
1713        scanline = scanline / 2;
1714        buf_planes->plane_info.mp[1].offset = 0;
1715        buf_planes->plane_info.mp[1].len =
1716            stride * scanline;
1717        buf_planes->plane_info.mp[1].offset_x = 0;
1718        buf_planes->plane_info.mp[1].offset_y = 0;
1719        buf_planes->plane_info.mp[1].stride = stride;
1720        buf_planes->plane_info.mp[1].scanline = scanline;
1721
1722        buf_planes->plane_info.mp[2].offset = 0;
1723        buf_planes->plane_info.mp[2].len =
1724            stride * scanline;
1725        buf_planes->plane_info.mp[2].offset_x = 0;
1726        buf_planes->plane_info.mp[2].offset_y = 0;
1727        buf_planes->plane_info.mp[2].stride = stride;
1728        buf_planes->plane_info.mp[2].scanline = scanline;
1729
1730        buf_planes->plane_info.frame_len =
1731            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1732                        buf_planes->plane_info.mp[1].len +
1733                        buf_planes->plane_info.mp[2].len,
1734                        CAM_PAD_TO_4K);
1735        break;
1736    case CAM_FORMAT_YUV_422_NV16:
1737    case CAM_FORMAT_YUV_422_NV61:
1738        /* 2 planes: Y + CbCr */
1739        buf_planes->plane_info.num_planes = 2;
1740
1741        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1742        scanline = dim->height;
1743        buf_planes->plane_info.mp[0].offset = 0;
1744        buf_planes->plane_info.mp[0].len = stride * scanline;
1745        buf_planes->plane_info.mp[0].offset_x = 0;
1746        buf_planes->plane_info.mp[0].offset_y = 0;
1747        buf_planes->plane_info.mp[0].stride = stride;
1748        buf_planes->plane_info.mp[0].scanline = scanline;
1749
1750        buf_planes->plane_info.mp[1].offset = 0;
1751        buf_planes->plane_info.mp[1].len = stride * scanline;
1752        buf_planes->plane_info.mp[1].offset_x = 0;
1753        buf_planes->plane_info.mp[1].offset_y = 0;
1754        buf_planes->plane_info.mp[1].stride = stride;
1755        buf_planes->plane_info.mp[1].scanline = scanline;
1756
1757        buf_planes->plane_info.frame_len =
1758            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1759                        buf_planes->plane_info.mp[1].len,
1760                        CAM_PAD_TO_4K);
1761        break;
1762    default:
1763        CDBG_ERROR("%s: Invalid cam_format for preview %d",
1764                   __func__, fmt);
1765        rc = -1;
1766        break;
1767    }
1768
1769    return rc;
1770}
1771
1772/*===========================================================================
1773 * FUNCTION   : mm_stream_calc_offset_snapshot
1774 *
1775 * DESCRIPTION: calculate snapshot/postproc frame offset based on format and
1776 *              padding information
1777 *
1778 * PARAMETERS :
1779 *   @fmt     : image format
1780 *   @dim     : image dimension
1781 *   @padding : padding information
1782 *   @buf_planes : [out] buffer plane information
1783 *
1784 * RETURN     : int32_t type of status
1785 *              0  -- success
1786 *              -1 -- failure
1787 *==========================================================================*/
1788int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt,
1789                                       cam_dimension_t *dim,
1790                                       cam_padding_info_t *padding,
1791                                       cam_stream_buf_plane_info_t *buf_planes)
1792{
1793    int32_t rc = 0;
1794    uint8_t isAFamily = mm_camera_util_chip_is_a_family();
1795    int offset_x = 0, offset_y = 0;
1796    int stride = 0, scanline = 0;
1797
1798    if (isAFamily) {
1799        stride = dim->width;
1800        scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_16);
1801        offset_x = 0;
1802        offset_y = scanline - dim->height;
1803        scanline += offset_y; /* double padding */
1804    } else {
1805        stride = PAD_TO_SIZE(dim->width,
1806                             padding->width_padding);
1807        scanline = PAD_TO_SIZE(dim->height,
1808                               padding->height_padding);
1809        offset_x = 0;
1810        offset_y = 0;
1811    }
1812
1813    switch (fmt) {
1814    case CAM_FORMAT_YUV_420_NV12:
1815    case CAM_FORMAT_YUV_420_NV21:
1816        /* 2 planes: Y + CbCr */
1817        buf_planes->plane_info.num_planes = 2;
1818
1819        buf_planes->plane_info.mp[0].len =
1820            PAD_TO_SIZE(stride * scanline,
1821                        padding->plane_padding);
1822        buf_planes->plane_info.mp[0].offset =
1823            PAD_TO_SIZE(offset_x + stride * offset_y,
1824                        padding->plane_padding);
1825        buf_planes->plane_info.mp[0].offset_x = offset_x;
1826        buf_planes->plane_info.mp[0].offset_y = offset_y;
1827        buf_planes->plane_info.mp[0].stride = stride;
1828        buf_planes->plane_info.mp[0].scanline = scanline;
1829
1830        scanline = scanline / 2;
1831        buf_planes->plane_info.mp[1].len =
1832            PAD_TO_SIZE(stride * scanline,
1833                        padding->plane_padding);
1834        buf_planes->plane_info.mp[1].offset =
1835            PAD_TO_SIZE(offset_x + stride * offset_y,
1836                        padding->plane_padding);
1837        buf_planes->plane_info.mp[1].offset_x = offset_x;
1838        buf_planes->plane_info.mp[1].offset_y = offset_y;
1839        buf_planes->plane_info.mp[1].stride = stride;
1840        buf_planes->plane_info.mp[1].scanline = scanline;
1841
1842        buf_planes->plane_info.frame_len =
1843            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1844                        buf_planes->plane_info.mp[1].len,
1845                        CAM_PAD_TO_4K);
1846        break;
1847    case CAM_FORMAT_YUV_420_YV12:
1848        /* 3 planes: Y + Cr + Cb */
1849        buf_planes->plane_info.num_planes = 3;
1850
1851        buf_planes->plane_info.mp[0].offset =
1852            PAD_TO_SIZE(offset_x + stride * offset_y,
1853                        padding->plane_padding);
1854        buf_planes->plane_info.mp[0].len =
1855            PAD_TO_SIZE(stride * scanline, padding->plane_padding);
1856        buf_planes->plane_info.mp[0].offset_x = offset_x;
1857        buf_planes->plane_info.mp[0].offset_y = offset_y;
1858        buf_planes->plane_info.mp[0].stride = stride;
1859        buf_planes->plane_info.mp[0].scanline = scanline;
1860
1861        stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
1862        scanline = scanline / 2;
1863        buf_planes->plane_info.mp[1].offset =
1864            PAD_TO_SIZE(offset_x + stride * offset_y,
1865                        padding->plane_padding);
1866        buf_planes->plane_info.mp[1].len =
1867            PAD_TO_SIZE(stride * scanline, padding->plane_padding);
1868        buf_planes->plane_info.mp[1].offset_x = offset_x;
1869        buf_planes->plane_info.mp[1].offset_y = offset_y;
1870        buf_planes->plane_info.mp[1].stride = stride;
1871        buf_planes->plane_info.mp[1].scanline = scanline;
1872
1873        buf_planes->plane_info.mp[2].offset =
1874            PAD_TO_SIZE(offset_x + stride * offset_y,
1875                        padding->plane_padding);
1876        buf_planes->plane_info.mp[2].len =
1877            PAD_TO_SIZE(stride * scanline, padding->plane_padding);
1878        buf_planes->plane_info.mp[2].offset_x = offset_x;
1879        buf_planes->plane_info.mp[2].offset_y = offset_y;
1880        buf_planes->plane_info.mp[2].stride = stride;
1881        buf_planes->plane_info.mp[2].scanline = scanline;
1882
1883        buf_planes->plane_info.frame_len =
1884            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
1885                        buf_planes->plane_info.mp[1].len +
1886                        buf_planes->plane_info.mp[2].len,
1887                        CAM_PAD_TO_4K);
1888        break;
1889    case CAM_FORMAT_YUV_422_NV16:
1890    case CAM_FORMAT_YUV_422_NV61:
1891        /* 2 planes: Y + CbCr */
1892        buf_planes->plane_info.num_planes = 2;
1893        buf_planes->plane_info.mp[0].len =
1894            PAD_TO_SIZE(stride * scanline, padding->plane_padding);
1895        buf_planes->plane_info.mp[0].offset =
1896            PAD_TO_SIZE(offset_x + stride * offset_y,
1897                        padding->plane_padding);
1898        buf_planes->plane_info.mp[0].offset_x = offset_x;
1899        buf_planes->plane_info.mp[0].offset_y = offset_y;
1900        buf_planes->plane_info.mp[0].stride = stride;
1901        buf_planes->plane_info.mp[0].scanline = scanline;
1902
1903        buf_planes->plane_info.mp[1].len =
1904            PAD_TO_SIZE(stride * scanline, padding->plane_padding);
1905        buf_planes->plane_info.mp[1].offset =
1906            PAD_TO_SIZE(offset_x + stride * offset_y,
1907                        padding->plane_padding);
1908        buf_planes->plane_info.mp[1].offset_x = offset_x;
1909        buf_planes->plane_info.mp[1].offset_y = offset_y;
1910        buf_planes->plane_info.mp[1].stride = stride;
1911        buf_planes->plane_info.mp[1].scanline = scanline;
1912
1913        buf_planes->plane_info.frame_len = PAD_TO_SIZE(
1914            buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len,
1915            CAM_PAD_TO_4K);
1916        break;
1917    default:
1918        CDBG_ERROR("%s: Invalid cam_format for snapshot %d",
1919                   __func__, fmt);
1920        rc = -1;
1921        break;
1922    }
1923
1924    return rc;
1925}
1926
1927/*===========================================================================
1928 * FUNCTION   : mm_stream_calc_offset_raw
1929 *
1930 * DESCRIPTION: calculate raw frame offset based on format and padding information
1931 *
1932 * PARAMETERS :
1933 *   @fmt     : image format
1934 *   @dim     : image dimension
1935 *   @padding : padding information
1936 *   @buf_planes : [out] buffer plane information
1937 *
1938 * RETURN     : int32_t type of status
1939 *              0  -- success
1940 *              -1 -- failure
1941 *==========================================================================*/
1942int32_t mm_stream_calc_offset_raw(cam_format_t fmt,
1943                                  cam_dimension_t *dim,
1944                                  cam_padding_info_t *padding,
1945                                  cam_stream_buf_plane_info_t *buf_planes)
1946{
1947    int32_t rc = 0;
1948    int stride = 0;
1949    int scanline = dim->height;
1950
1951    switch (fmt) {
1952    case CAM_FORMAT_YUV_RAW_8BIT_YUYV:
1953    case CAM_FORMAT_YUV_RAW_8BIT_YVYU:
1954    case CAM_FORMAT_YUV_RAW_8BIT_UYVY:
1955    case CAM_FORMAT_YUV_RAW_8BIT_VYUY:
1956        /* 1 plane */
1957        /* Every 16 pixels occupy 16 bytes */
1958        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1959        buf_planes->plane_info.num_planes = 1;
1960        buf_planes->plane_info.mp[0].offset = 0;
1961        buf_planes->plane_info.mp[0].len =
1962            PAD_TO_SIZE(stride * scanline * 2, padding->plane_padding);
1963        buf_planes->plane_info.frame_len =
1964            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
1965        buf_planes->plane_info.mp[0].offset_x =0;
1966        buf_planes->plane_info.mp[0].offset_y = 0;
1967        buf_planes->plane_info.mp[0].stride = stride;
1968        buf_planes->plane_info.mp[0].scanline = scanline;
1969        break;
1970    case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GBRG:
1971    case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GRBG:
1972    case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_RGGB:
1973    case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_BGGR:
1974    case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GBRG:
1975    case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GRBG:
1976    case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_RGGB:
1977    case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_BGGR:
1978    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GBRG:
1979    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GRBG:
1980    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_RGGB:
1981    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_BGGR:
1982    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GBRG:
1983    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GRBG:
1984    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_RGGB:
1985    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_BGGR:
1986    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GBRG:
1987    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GRBG:
1988    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_RGGB:
1989    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_BGGR:
1990        /* 1 plane */
1991        /* Every 16 pixels occupy 16 bytes */
1992        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
1993        buf_planes->plane_info.num_planes = 1;
1994        buf_planes->plane_info.mp[0].offset = 0;
1995        buf_planes->plane_info.mp[0].len =
1996            PAD_TO_SIZE(stride * scanline, padding->plane_padding);
1997        buf_planes->plane_info.frame_len =
1998            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
1999        buf_planes->plane_info.mp[0].offset_x =0;
2000        buf_planes->plane_info.mp[0].offset_y = 0;
2001        buf_planes->plane_info.mp[0].stride = stride;
2002        buf_planes->plane_info.mp[0].scanline = scanline;
2003        break;
2004    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG:
2005    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG:
2006    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB:
2007    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR:
2008    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GBRG:
2009    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GRBG:
2010    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_RGGB:
2011    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_BGGR:
2012        /* Every 12 pixels occupy 16 bytes */
2013        stride = (dim->width + 11)/12 * 12;
2014        buf_planes->plane_info.num_planes = 1;
2015        buf_planes->plane_info.mp[0].offset = 0;
2016        buf_planes->plane_info.mp[0].len =
2017            PAD_TO_SIZE(stride * scanline * 8 / 6, padding->plane_padding);
2018        buf_planes->plane_info.frame_len =
2019            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2020        buf_planes->plane_info.mp[0].offset_x =0;
2021        buf_planes->plane_info.mp[0].offset_y = 0;
2022        buf_planes->plane_info.mp[0].stride = stride;
2023        buf_planes->plane_info.mp[0].scanline = scanline;
2024        break;
2025    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GBRG:
2026    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GRBG:
2027    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_RGGB:
2028    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_BGGR:
2029    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GBRG:
2030    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GRBG:
2031    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_RGGB:
2032    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_BGGR:
2033        /* Every 10 pixels occupy 16 bytes */
2034        stride = (dim->width + 9)/10 * 10;
2035        buf_planes->plane_info.num_planes = 1;
2036        buf_planes->plane_info.mp[0].offset = 0;
2037        buf_planes->plane_info.mp[0].len =
2038            PAD_TO_SIZE(stride * scanline * 8 / 5, padding->plane_padding);
2039        buf_planes->plane_info.frame_len =
2040            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2041        buf_planes->plane_info.mp[0].offset_x =0;
2042        buf_planes->plane_info.mp[0].offset_y = 0;
2043        buf_planes->plane_info.mp[0].stride = stride;
2044        buf_planes->plane_info.mp[0].scanline = scanline;
2045        break;
2046    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG:
2047    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GRBG:
2048    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_RGGB:
2049    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_BGGR:
2050    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GBRG:
2051    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GRBG:
2052    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_RGGB:
2053    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_BGGR:
2054        /* Every 64 pixels occupy 80 bytes */
2055        stride = PAD_TO_SIZE(dim->width * 5 / 4, CAM_PAD_TO_8);
2056        buf_planes->plane_info.num_planes = 1;
2057        buf_planes->plane_info.mp[0].offset = 0;
2058        buf_planes->plane_info.mp[0].len =
2059            PAD_TO_SIZE(stride * scanline, padding->plane_padding);
2060        buf_planes->plane_info.frame_len =
2061            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2062        buf_planes->plane_info.mp[0].offset_x =0;
2063        buf_planes->plane_info.mp[0].offset_y = 0;
2064        buf_planes->plane_info.mp[0].stride = stride;
2065        buf_planes->plane_info.mp[0].scanline = scanline;
2066        break;
2067    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GBRG:
2068    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GRBG:
2069    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_RGGB:
2070    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_BGGR:
2071    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GBRG:
2072    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GRBG:
2073    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_RGGB:
2074    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_BGGR:
2075        /* Every 32 pixels occupy 48 bytes */
2076        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
2077        buf_planes->plane_info.num_planes = 1;
2078        buf_planes->plane_info.mp[0].offset = 0;
2079        buf_planes->plane_info.mp[0].len =
2080            PAD_TO_SIZE(stride * scanline * 3 / 2, padding->plane_padding);
2081        buf_planes->plane_info.frame_len =
2082            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2083        buf_planes->plane_info.mp[0].offset_x =0;
2084        buf_planes->plane_info.mp[0].offset_y = 0;
2085        buf_planes->plane_info.mp[0].stride = stride;
2086        buf_planes->plane_info.mp[0].scanline = scanline;
2087        break;
2088    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GBRG:
2089    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GRBG:
2090    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_RGGB:
2091    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_BGGR:
2092    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GBRG:
2093    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GRBG:
2094    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_RGGB:
2095    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_BGGR:
2096    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GBRG:
2097    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GRBG:
2098    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_RGGB:
2099    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_BGGR:
2100        /* Every 8 pixels occupy 16 bytes */
2101        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_8);
2102        buf_planes->plane_info.num_planes = 1;
2103        buf_planes->plane_info.mp[0].offset = 0;
2104        buf_planes->plane_info.mp[0].len =
2105            PAD_TO_SIZE(stride * scanline * 2, padding->plane_padding);
2106        buf_planes->plane_info.frame_len =
2107            PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2108        buf_planes->plane_info.mp[0].offset_x =0;
2109        buf_planes->plane_info.mp[0].offset_y = 0;
2110        buf_planes->plane_info.mp[0].stride = stride;
2111        buf_planes->plane_info.mp[0].scanline = scanline;
2112        break;
2113    default:
2114        CDBG_ERROR("%s: Invalid cam_format %d for raw stream",
2115                   __func__, fmt);
2116        rc = -1;
2117        break;
2118    }
2119
2120    return rc;
2121}
2122
2123/*===========================================================================
2124 * FUNCTION   : mm_stream_calc_offset_video
2125 *
2126 * DESCRIPTION: calculate video frame offset based on format and
2127 *              padding information
2128 *
2129 * PARAMETERS :
2130 *   @dim     : image dimension
2131 *   @buf_planes : [out] buffer plane information
2132 *
2133 * RETURN     : int32_t type of status
2134 *              0  -- success
2135 *              -1 -- failure
2136 *==========================================================================*/
2137#ifdef VENUS_PRESENT
2138int32_t mm_stream_calc_offset_video(cam_dimension_t *dim,
2139                                    cam_stream_buf_plane_info_t *buf_planes)
2140{
2141    int stride = 0, scanline = 0;
2142
2143    // using Venus
2144    stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
2145    scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
2146
2147    buf_planes->plane_info.frame_len =
2148        VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height);
2149    buf_planes->plane_info.num_planes = 2;
2150    buf_planes->plane_info.mp[0].len = stride * scanline;
2151    buf_planes->plane_info.mp[0].offset = 0;
2152    buf_planes->plane_info.mp[0].offset_x =0;
2153    buf_planes->plane_info.mp[0].offset_y = 0;
2154    buf_planes->plane_info.mp[0].stride = stride;
2155    buf_planes->plane_info.mp[0].scanline = scanline;
2156    stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
2157    scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
2158    buf_planes->plane_info.mp[1].len =
2159        buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
2160    buf_planes->plane_info.mp[1].offset = 0;
2161    buf_planes->plane_info.mp[1].offset_x =0;
2162    buf_planes->plane_info.mp[1].offset_y = 0;
2163    buf_planes->plane_info.mp[1].stride = stride;
2164    buf_planes->plane_info.mp[1].scanline = scanline;
2165
2166    return 0;
2167}
2168#else
2169int32_t mm_stream_calc_offset_video(cam_dimension_t *dim,
2170                                    cam_stream_buf_plane_info_t *buf_planes)
2171{
2172    int stride = 0, scanline = 0;
2173
2174    buf_planes->plane_info.num_planes = 2;
2175
2176    stride = dim->width;
2177    scanline = dim->height;
2178    buf_planes->plane_info.mp[0].len =
2179        PAD_TO_SIZE(stride * scanline, CAM_PAD_TO_2K);
2180    buf_planes->plane_info.mp[0].offset = 0;
2181    buf_planes->plane_info.mp[0].offset_x =0;
2182    buf_planes->plane_info.mp[0].offset_y = 0;
2183    buf_planes->plane_info.mp[0].stride = stride;
2184    buf_planes->plane_info.mp[0].scanline = scanline;
2185
2186    stride = dim->width;
2187    scanline = dim->height / 2;
2188    buf_planes->plane_info.mp[1].len =
2189        PAD_TO_SIZE(stride * scanline, CAM_PAD_TO_2K);
2190    buf_planes->plane_info.mp[1].offset = 0;
2191    buf_planes->plane_info.mp[1].offset_x =0;
2192    buf_planes->plane_info.mp[1].offset_y = 0;
2193    buf_planes->plane_info.mp[1].stride = stride;
2194    buf_planes->plane_info.mp[1].scanline = scanline;
2195
2196    buf_planes->plane_info.frame_len =
2197        PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2198                    buf_planes->plane_info.mp[1].len,
2199                    CAM_PAD_TO_4K);
2200
2201    return 0;
2202}
2203#endif
2204
2205/*===========================================================================
2206 * FUNCTION   : mm_stream_calc_offset_metadata
2207 *
2208 * DESCRIPTION: calculate metadata frame offset based on format and
2209 *              padding information
2210 *
2211 * PARAMETERS :
2212 *   @dim     : image dimension
2213 *   @padding : padding information
2214 *   @buf_planes : [out] buffer plane information
2215 *
2216 * RETURN     : int32_t type of status
2217 *              0  -- success
2218 *              -1 -- failure
2219 *==========================================================================*/
2220int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim,
2221                                       cam_padding_info_t *padding,
2222                                       cam_stream_buf_plane_info_t *buf_planes)
2223{
2224    int32_t rc = 0;
2225    buf_planes->plane_info.num_planes = 1;
2226    buf_planes->plane_info.mp[0].offset = 0;
2227    buf_planes->plane_info.mp[0].len =
2228        PAD_TO_SIZE(dim->width * dim->height, padding->plane_padding);
2229    buf_planes->plane_info.frame_len =
2230        buf_planes->plane_info.mp[0].len;
2231
2232    buf_planes->plane_info.mp[0].offset_x =0;
2233    buf_planes->plane_info.mp[0].offset_y = 0;
2234    buf_planes->plane_info.mp[0].stride = dim->width;
2235    buf_planes->plane_info.mp[0].scanline = dim->height;
2236    return rc;
2237}
2238
2239/*===========================================================================
2240 * FUNCTION   : mm_stream_calc_offset_postproc
2241 *
2242 * DESCRIPTION: calculate postprocess frame offset
2243 *
2244 * PARAMETERS :
2245 *   @stream_info: ptr to stream info
2246 *   @padding : padding information
2247 *   @buf_planes : [out] buffer plane information
2248 *
2249 * RETURN     : int32_t type of status
2250 *              0  -- success
2251 *              -1 -- failure
2252 *==========================================================================*/
2253int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info,
2254                                       cam_padding_info_t *padding,
2255                                       cam_stream_buf_plane_info_t *buf_planes)
2256{
2257    int32_t rc = 0;
2258    if (stream_info->reprocess_config.pp_type == CAM_OFFLINE_REPROCESS_TYPE) {
2259        // take offset from input source
2260        *buf_planes = stream_info->reprocess_config.offline.input_buf_planes;
2261        return rc;
2262    }
2263
2264    cam_dimension_t dim = stream_info->dim;
2265    if (stream_info->reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
2266        if (stream_info->reprocess_config.pp_feature_config.rotation == ROTATE_90 ||
2267            stream_info->reprocess_config.pp_feature_config.rotation == ROTATE_270) {
2268            // rotated by 90 or 270, need to switch width and height
2269            dim.width = stream_info->dim.height;
2270            dim.height = stream_info->dim.width;
2271        }
2272    }
2273
2274    switch (stream_info->reprocess_config.online.input_stream_type) {
2275    case CAM_STREAM_TYPE_PREVIEW:
2276    case CAM_STREAM_TYPE_POSTVIEW:
2277        rc = mm_stream_calc_offset_preview(stream_info->fmt,
2278                                           &dim,
2279                                           buf_planes);
2280        break;
2281    case CAM_STREAM_TYPE_SNAPSHOT:
2282        rc = mm_stream_calc_offset_snapshot(stream_info->fmt,
2283                                            &dim,
2284                                            padding,
2285                                            buf_planes);
2286        break;
2287    case CAM_STREAM_TYPE_VIDEO:
2288        rc = mm_stream_calc_offset_video(&dim,
2289                                         buf_planes);
2290        break;
2291    case CAM_STREAM_TYPE_RAW:
2292        rc = mm_stream_calc_offset_raw(stream_info->fmt,
2293                                       &dim,
2294                                       padding,
2295                                       buf_planes);
2296        break;
2297    case CAM_STREAM_TYPE_METADATA:
2298        rc = mm_stream_calc_offset_metadata(&dim,
2299                                            padding,
2300                                            buf_planes);
2301        break;
2302    default:
2303        CDBG_ERROR("%s: not supported for stream type %d",
2304                   __func__, stream_info->reprocess_config.online.input_stream_type);
2305        rc = -1;
2306        break;
2307    }
2308    return rc;
2309}
2310
2311/*===========================================================================
2312 * FUNCTION   : mm_stream_calc_offset
2313 *
2314 * DESCRIPTION: calculate frame offset based on format and padding information
2315 *
2316 * PARAMETERS :
2317 *   @my_obj  : stream object
2318 *
2319 * RETURN     : int32_t type of status
2320 *              0  -- success
2321 *              -1 -- failure
2322 *==========================================================================*/
2323int32_t mm_stream_calc_offset(mm_stream_t *my_obj)
2324{
2325    int32_t rc = 0;
2326
2327    cam_dimension_t dim = my_obj->stream_info->dim;
2328    if (my_obj->stream_info->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
2329        if (my_obj->stream_info->pp_config.rotation == ROTATE_90 ||
2330            my_obj->stream_info->pp_config.rotation == ROTATE_270) {
2331            // rotated by 90 or 270, need to switch width and height
2332            dim.width = my_obj->stream_info->dim.height;
2333            dim.height = my_obj->stream_info->dim.width;
2334        }
2335    }
2336
2337    switch (my_obj->stream_info->stream_type) {
2338    case CAM_STREAM_TYPE_PREVIEW:
2339    case CAM_STREAM_TYPE_POSTVIEW:
2340        rc = mm_stream_calc_offset_preview(my_obj->stream_info->fmt,
2341                                           &dim,
2342                                           &my_obj->stream_info->buf_planes);
2343        break;
2344    case CAM_STREAM_TYPE_SNAPSHOT:
2345        rc = mm_stream_calc_offset_snapshot(my_obj->stream_info->fmt,
2346                                            &dim,
2347                                            &my_obj->padding_info,
2348                                            &my_obj->stream_info->buf_planes);
2349        break;
2350    case CAM_STREAM_TYPE_OFFLINE_PROC:
2351        rc = mm_stream_calc_offset_postproc(my_obj->stream_info,
2352                                            &my_obj->padding_info,
2353                                            &my_obj->stream_info->buf_planes);
2354        break;
2355    case CAM_STREAM_TYPE_VIDEO:
2356        rc = mm_stream_calc_offset_video(&dim,
2357                                         &my_obj->stream_info->buf_planes);
2358        break;
2359    case CAM_STREAM_TYPE_RAW:
2360        rc = mm_stream_calc_offset_raw(my_obj->stream_info->fmt,
2361                                       &dim,
2362                                       &my_obj->padding_info,
2363                                       &my_obj->stream_info->buf_planes);
2364        break;
2365    case CAM_STREAM_TYPE_METADATA:
2366        rc = mm_stream_calc_offset_metadata(&dim,
2367                                            &my_obj->padding_info,
2368                                            &my_obj->stream_info->buf_planes);
2369        break;
2370    default:
2371        CDBG_ERROR("%s: not supported for stream type %d",
2372                   __func__, my_obj->stream_info->stream_type);
2373        rc = -1;
2374        break;
2375    }
2376
2377    my_obj->frame_offset = my_obj->stream_info->buf_planes.plane_info;
2378    return rc;
2379}
2380
2381/*===========================================================================
2382 * FUNCTION   : mm_stream_sync_info
2383 *
2384 * DESCRIPTION: synchronize stream information with server
2385 *
2386 * PARAMETERS :
2387 *   @my_obj  : stream object
2388 *
2389 * RETURN     : int32_t type of status
2390 *              0  -- success
2391 *              -1 -- failure
2392 * NOTE       : assume stream info buffer is mapped to server and filled in with
2393 *              stream information by upper layer. This call will let server to
2394 *              synchornize the stream information with HAL. If server find any
2395 *              fields that need to be changed accroding to hardware configuration,
2396 *              server will modify corresponding fields so that HAL could know
2397 *              about it.
2398 *==========================================================================*/
2399int32_t mm_stream_sync_info(mm_stream_t *my_obj)
2400{
2401    int32_t rc = 0;
2402    int32_t value = 0;
2403    my_obj->stream_info->stream_svr_id = my_obj->server_stream_id;
2404    rc = mm_stream_calc_offset(my_obj);
2405
2406    if (rc == 0) {
2407        rc = mm_camera_util_s_ctrl(my_obj->fd,
2408                                   CAM_PRIV_STREAM_INFO_SYNC,
2409                                   &value);
2410    }
2411    return rc;
2412}
2413
2414/*===========================================================================
2415 * FUNCTION   : mm_stream_set_fmt
2416 *
2417 * DESCRIPTION: set stream format to kernel via v4l2 ioctl
2418 *
2419 * PARAMETERS :
2420 *   @my_obj  : stream object
2421 *
2422 * RETURN     : int32_t type of status
2423 *              0  -- success
2424 *              -1 -- failure
2425 *==========================================================================*/
2426int32_t mm_stream_set_fmt(mm_stream_t *my_obj)
2427{
2428    int32_t rc = 0;
2429    struct v4l2_format fmt;
2430    struct msm_v4l2_format_data msm_fmt;
2431    int i;
2432
2433    CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
2434         __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
2435
2436    if (my_obj->stream_info->dim.width == 0 ||
2437        my_obj->stream_info->dim.height == 0) {
2438        CDBG_ERROR("%s:invalid input[w=%d,h=%d,fmt=%d]\n",
2439                   __func__,
2440                   my_obj->stream_info->dim.width,
2441                   my_obj->stream_info->dim.height,
2442                   my_obj->stream_info->fmt);
2443        return -1;
2444    }
2445
2446    memset(&fmt, 0, sizeof(fmt));
2447    memset(&msm_fmt, 0, sizeof(msm_fmt));
2448    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2449    msm_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2450    msm_fmt.width = my_obj->stream_info->dim.width;
2451    msm_fmt.height = my_obj->stream_info->dim.height;
2452    msm_fmt.pixelformat = mm_stream_get_v4l2_fmt(my_obj->stream_info->fmt);
2453    msm_fmt.num_planes = my_obj->frame_offset.num_planes;
2454    for (i = 0; i < msm_fmt.num_planes; i++) {
2455        msm_fmt.plane_sizes[i] = my_obj->frame_offset.mp[i].len;
2456    }
2457
2458    memcpy(fmt.fmt.raw_data, &msm_fmt, sizeof(msm_fmt));
2459    rc = ioctl(my_obj->fd, VIDIOC_S_FMT, &fmt);
2460    return rc;
2461}
2462
2463/*===========================================================================
2464 * FUNCTION   : mm_stream_buf_done
2465 *
2466 * DESCRIPTION: enqueue buffer back to kernel
2467 *
2468 * PARAMETERS :
2469 *   @my_obj       : stream object
2470 *   @frame        : frame to be enqueued back to kernel
2471 *
2472 * RETURN     : int32_t type of status
2473 *              0  -- success
2474 *              -1 -- failure
2475 *==========================================================================*/
2476int32_t mm_stream_buf_done(mm_stream_t * my_obj,
2477                           mm_camera_buf_def_t *frame)
2478{
2479    int32_t rc = 0;
2480    CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
2481         __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
2482
2483    pthread_mutex_lock(&my_obj->buf_lock);
2484    if(my_obj->buf_status[frame->buf_idx].buf_refcnt == 0) {
2485        CDBG("%s: Error Trying to free second time?(idx=%d) count=%d\n",
2486                   __func__, frame->buf_idx,
2487                   my_obj->buf_status[frame->buf_idx].buf_refcnt);
2488        rc = -1;
2489    }else{
2490        my_obj->buf_status[frame->buf_idx].buf_refcnt--;
2491        if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) {
2492            CDBG("<DEBUG> : Buf done for buffer:%d", frame->buf_idx);
2493            my_obj->mem_vtbl.invalidate_buf(frame->buf_idx,
2494                                            my_obj->mem_vtbl.user_data);
2495            rc = mm_stream_qbuf(my_obj, frame);
2496            if(rc < 0) {
2497                CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n",
2498                           __func__, frame->buf_idx, rc);
2499            } else {
2500                my_obj->buf_status[frame->buf_idx].in_kernel = 1;
2501            }
2502        }else{
2503            CDBG("<DEBUG> : Still ref count pending count :%d",
2504                 my_obj->buf_status[frame->buf_idx].buf_refcnt);
2505            CDBG("<DEBUG> : for buffer:%p:%d",
2506                 my_obj, frame->buf_idx);
2507        }
2508    }
2509    pthread_mutex_unlock(&my_obj->buf_lock);
2510    return rc;
2511}
2512
2513/*===========================================================================
2514 * FUNCTION   : mm_stream_reg_buf_cb
2515 *
2516 * DESCRIPTION: Allow other stream to register dataCB at this stream.
2517 *
2518 * PARAMETERS :
2519 *   @my_obj       : stream object
2520 *   @val          : ptr to info about the callback to be registered
2521 *
2522 * RETURN     : int32_t type of status
2523 *              0  -- success
2524 *              -1 -- failure
2525 *==========================================================================*/
2526int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj,
2527                             mm_stream_data_cb_t *val)
2528{
2529    int32_t rc = -1;
2530    uint8_t i;
2531    CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
2532         __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
2533
2534    pthread_mutex_lock(&my_obj->cb_lock);
2535    for (i=0 ;i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
2536        if(NULL == my_obj->buf_cb[i].cb) {
2537            my_obj->buf_cb[i] = *val;
2538            rc = 0;
2539            break;
2540        }
2541    }
2542    pthread_mutex_unlock(&my_obj->cb_lock);
2543
2544    return rc;
2545}
2546