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