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