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