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