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