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