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