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