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