1 /*
2 Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 <semaphore.h>
39
40 #include "mm_camera_dbg.h"
41 #include "mm_camera_interface.h"
42 #include "mm_camera.h"
43
44 #define MM_CAMERA_MAX_NUM_FRAMES 16
45
46 /* internal function decalre */
47 int32_t mm_stream_qbuf(mm_stream_t *my_obj,
48 mm_camera_buf_def_t *buf);
49 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj);
50 int32_t mm_stream_set_fmt(mm_stream_t * my_obj);
51 int32_t mm_stream_get_offset(mm_stream_t *my_obj);
52 int32_t mm_stream_set_cid(mm_stream_t *my_obj,stream_cid_t *in_value);
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_get_crop(mm_stream_t *my_obj,
59 mm_camera_rect_t *crop);
60 int32_t mm_stream_get_cid(mm_stream_t *my_obj,
61 stream_cid_t *out_value);
62 int32_t mm_stream_set_parm_acquire(mm_stream_t *my_obj,
63 void *value);
64 int32_t mm_stream_get_parm_acquire(mm_stream_t *my_obj,
65 void *value);
66 int32_t mm_stream_set_parm_config(mm_stream_t *my_obj,
67 void *value);
68 int32_t mm_stream_get_parm_config(mm_stream_t *my_obj,
69 void *value);
70 int32_t mm_stream_set_parm_start(mm_stream_t *my_obj,
71 void *value);
72 int32_t mm_stream_get_parm_start(mm_stream_t *my_obj,
73 void *value);
74 int32_t mm_stream_streamon(mm_stream_t *my_obj);
75 int32_t mm_stream_streamoff(mm_stream_t *my_obj);
76 int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
77 mm_camera_buf_info_t* buf_info);
78 int32_t mm_stream_config(mm_stream_t *my_obj,
79 mm_camera_stream_config_t *config);
80 uint8_t mm_stream_need_stream_on(mm_stream_t *my_obj);
81 int32_t mm_stream_reg_buf(mm_stream_t * my_obj);
82 int32_t mm_stream_buf_done(mm_stream_t * my_obj,
83 mm_camera_buf_def_t *frame);
84
85
86 /* state machine function declare */
87 int32_t mm_stream_fsm_inited(mm_stream_t * my_obj,
88 mm_stream_evt_type_t evt,
89 void * in_val,
90 void * out_val);
91 int32_t mm_stream_fsm_acquired(mm_stream_t * my_obj,
92 mm_stream_evt_type_t evt,
93 void * in_val,
94 void * out_val);
95 int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
96 mm_stream_evt_type_t evt,
97 void * in_val,
98 void * out_val);
99 int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
100 mm_stream_evt_type_t evt,
101 void * in_val,
102 void * out_val);
103 int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
104 mm_stream_evt_type_t evt,
105 void * in_val,
106 void * out_val);
107 int32_t mm_stream_fsm_active_stream_on(mm_stream_t * my_obj,
108 mm_stream_evt_type_t evt,
109 void * in_val,
110 void * out_val);
111 int32_t mm_stream_fsm_active_stream_off(mm_stream_t * my_obj,
112 mm_stream_evt_type_t evt,
113 void * in_val,
114 void * out_val);
115
116 extern int32_t mm_camera_send_native_ctrl_cmd(mm_camera_obj_t * my_obj,
117 cam_ctrl_type type,
118 uint32_t length,
119 void *value);
120
get_stream_inst_handle(mm_stream_t * my_obj)121 static int get_stream_inst_handle(mm_stream_t *my_obj)
122 {
123 int rc = 0;
124 uint32_t inst_handle;
125 struct msm_camera_v4l2_ioctl_t v4l2_ioctl;
126
127 v4l2_ioctl.id = MSM_V4L2_PID_INST_HANDLE;
128 v4l2_ioctl.ioctl_ptr = &inst_handle;
129 v4l2_ioctl.len = sizeof(inst_handle);
130 rc = ioctl(my_obj->fd, MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL, &v4l2_ioctl);
131 if (rc) {
132 CDBG_ERROR("%s Error getting mctl pp inst handle", __func__);
133 return rc;
134 }
135
136 my_obj->inst_hdl = inst_handle;
137 CDBG("%s: inst handle = %x rc = %d\n", __func__,
138 my_obj->inst_hdl, rc);
139 return rc;
140 }
141
mm_stream_handle_rcvd_buf(mm_stream_t * my_obj,mm_camera_buf_info_t * buf_info)142 void mm_stream_handle_rcvd_buf(mm_stream_t *my_obj,
143 mm_camera_buf_info_t *buf_info)
144 {
145 int32_t i;
146 uint8_t has_cb = 0;
147
148 /* enqueue to super buf thread */
149 if (my_obj->is_bundled) {
150 mm_camera_cmdcb_t* node = NULL;
151
152 /* send sem_post to wake up channel cmd thread to enqueue to super buffer */
153 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
154 if (NULL != node) {
155 memset(node, 0, sizeof(mm_camera_cmdcb_t));
156 node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
157 memcpy(&node->u.buf, buf_info, sizeof(mm_camera_buf_info_t));
158
159 /* enqueue to cmd thread */
160 mm_camera_queue_enq(&(my_obj->ch_obj->cmd_thread.cmd_queue), node);
161
162 /* wake up cmd thread */
163 sem_post(&(my_obj->ch_obj->cmd_thread.cmd_sem));
164 } else {
165 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
166 }
167 }
168
169 /* check if has CB */
170 for (i=0 ; i< MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
171 if(NULL != my_obj->buf_cb[i].cb) {
172 has_cb = 1;
173 }
174 }
175 if(has_cb) {
176 mm_camera_cmdcb_t* node = NULL;
177
178 /* send sem_post to wake up cmd thread to dispatch dataCB */
179 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
180 if (NULL != node) {
181 memset(node, 0, sizeof(mm_camera_cmdcb_t));
182 node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
183 memcpy(&node->u.buf, buf_info, sizeof(mm_camera_buf_info_t));
184
185 /* enqueue to cmd thread */
186 mm_camera_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
187
188 /* wake up cmd thread */
189 sem_post(&(my_obj->cmd_thread.cmd_sem));
190 } else {
191 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
192 }
193 }
194 }
195
mm_stream_data_notify(void * user_data)196 static void mm_stream_data_notify(void* user_data)
197 {
198 mm_stream_t *my_obj = (mm_stream_t*)user_data;
199 int32_t idx = -1, i, rc;
200 uint8_t has_cb = 0;
201 mm_camera_buf_info_t buf_info;
202
203 if (NULL == my_obj) {
204 return;
205 }
206
207 if (MM_STREAM_STATE_ACTIVE_STREAM_ON != 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
217 pthread_mutex_lock(&my_obj->buf_lock);
218 rc = mm_stream_read_msm_frame(my_obj, &buf_info);
219 if (rc != 0) {
220 pthread_mutex_unlock(&my_obj->buf_lock);
221 return;
222 }
223 idx = buf_info.buf->buf_idx;
224
225 /* update buffer location */
226 my_obj->buf_status[idx].in_kernel = 0;
227
228 /* update buf ref count */
229 if (my_obj->is_bundled) {
230 /* need to add into super buf since bundled, add ref count */
231 my_obj->buf_status[idx].buf_refcnt++;
232 }
233
234 for (i=0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
235 if(NULL != my_obj->buf_cb[i].cb) {
236 /* for every CB, add ref count */
237 my_obj->buf_status[idx].buf_refcnt++;
238 has_cb = 1;
239 }
240 }
241 pthread_mutex_unlock(&my_obj->buf_lock);
242
243 mm_stream_handle_rcvd_buf(my_obj, &buf_info);
244 }
245
246 /* special function for dataCB registered at other stream */
mm_stream_buf_notify(mm_camera_super_buf_t * super_buf,void * user_data)247 static void mm_stream_buf_notify(mm_camera_super_buf_t *super_buf,
248 void *user_data)
249 {
250 mm_stream_t * my_obj = (mm_stream_t*)user_data;
251 mm_camera_buf_info_t buf_info;
252 int8_t i;
253 mm_camera_buf_def_t *buf = super_buf->bufs[0];
254
255 CDBG("%s : E",__func__);
256 if (my_obj == NULL) {
257 return;
258 }
259
260 if (MM_STREAM_STATE_ACTIVE_STREAM_OFF != my_obj->state) {
261 /* this CB will only received in active_stream_off state
262 * if not so, return here */
263 return;
264 }
265
266 /* 1) copy buf into local buf */
267 if (my_obj->buf_num <= 0) {
268 CDBG_ERROR("%s: Local buf is not allocated yet", __func__);
269 return;
270 }
271
272 my_obj->buf[0].buf_idx = 0;
273 my_obj->buf[0].stream_id = my_obj->my_hdl;
274 my_obj->buf[0].frame_idx = buf->frame_idx;
275
276 memcpy(&my_obj->buf[0].ts, &buf->ts, sizeof(buf->ts));
277
278 memcpy(&my_obj->buf[0].planes,&buf->planes,buf->num_planes * sizeof(struct v4l2_plane));
279
280 /* set flag to indicate buf be to sent out is from local */
281 my_obj->is_local_buf = 1;
282
283 /* 2) buf_done the buf from other stream */
284 mm_channel_qbuf(my_obj->ch_obj, buf);
285
286 /* 3) handle received buf */
287 memset(&buf_info, 0, sizeof(mm_camera_buf_info_t));
288 buf_info.frame_idx =my_obj->buf[0].frame_idx;
289 buf_info.buf = &my_obj->buf[0];
290 buf_info.stream_id = my_obj->my_hdl;
291 mm_stream_handle_rcvd_buf(my_obj, &buf_info);
292 }
293
mm_stream_dispatch_app_data(mm_camera_cmdcb_t * cmd_cb,void * user_data)294 static void mm_stream_dispatch_app_data(mm_camera_cmdcb_t *cmd_cb,
295 void* user_data)
296 {
297 int i;
298 mm_stream_t * my_obj = (mm_stream_t *)user_data;
299 mm_camera_buf_info_t* buf_info = NULL;
300 mm_camera_super_buf_t super_buf;
301
302 if (NULL == my_obj) {
303 return;
304 }
305
306 if (MM_CAMERA_CMD_TYPE_DATA_CB != cmd_cb->cmd_type) {
307 CDBG_ERROR("%s: Wrong cmd_type (%d) for dataCB",
308 __func__, cmd_cb->cmd_type);
309 return;
310 }
311
312 buf_info = &cmd_cb->u.buf;
313 memset(&super_buf, 0, sizeof(mm_camera_super_buf_t));
314 super_buf.num_bufs = 1;
315 super_buf.bufs[0] = buf_info->buf;
316 super_buf.camera_handle = my_obj->ch_obj->cam_obj->my_hdl;
317 super_buf.ch_id = my_obj->ch_obj->my_hdl;
318
319
320 pthread_mutex_lock(&my_obj->cb_lock);
321 for(i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
322 if(NULL != my_obj->buf_cb[i].cb) {
323 if (my_obj->buf_cb[i].cb_count != 0) {
324 /* if <0, means infinite CB
325 * if >0, means CB for certain times
326 * both case we need to call CB */
327 my_obj->buf_cb[i].cb(&super_buf,
328 my_obj->buf_cb[i].user_data);
329 }
330
331 /* if >0, reduce count by 1 every time we called CB until reaches 0
332 * when count reach 0, reset the buf_cb to have no CB */
333 if (my_obj->buf_cb[i].cb_count > 0) {
334 my_obj->buf_cb[i].cb_count--;
335 if (0 == my_obj->buf_cb[i].cb_count) {
336 my_obj->buf_cb[i].cb = NULL;
337 my_obj->buf_cb[i].user_data = NULL;
338 }
339 }
340 }
341 }
342 pthread_mutex_unlock(&my_obj->cb_lock);
343 }
344
345 /* state machine entry */
mm_stream_fsm_fn(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)346 int32_t mm_stream_fsm_fn(mm_stream_t *my_obj,
347 mm_stream_evt_type_t evt,
348 void * in_val,
349 void * out_val)
350 {
351 int32_t rc = -1;
352
353 CDBG("%s : E - evt = %d, my_obj->state = %d",__func__,evt,my_obj->state);
354 switch (my_obj->state) {
355 case MM_STREAM_STATE_NOTUSED:
356 CDBG("%s: Not handling evt in unused state", __func__);
357 break;
358 case MM_STREAM_STATE_INITED:
359 rc = mm_stream_fsm_inited(my_obj, evt, in_val, out_val);
360 break;
361 case MM_STREAM_STATE_ACQUIRED:
362 rc = mm_stream_fsm_acquired(my_obj, evt, in_val, out_val);
363 break;
364 case MM_STREAM_STATE_CFG:
365 rc = mm_stream_fsm_cfg(my_obj, evt, in_val, out_val);
366 break;
367 case MM_STREAM_STATE_BUFFED:
368 rc = mm_stream_fsm_buffed(my_obj, evt, in_val, out_val);
369 break;
370 case MM_STREAM_STATE_REG:
371 rc = mm_stream_fsm_reg(my_obj, evt, in_val, out_val);
372 break;
373 case MM_STREAM_STATE_ACTIVE_STREAM_ON:
374 rc = mm_stream_fsm_active_stream_on(my_obj, evt, in_val, out_val);
375 break;
376 case MM_STREAM_STATE_ACTIVE_STREAM_OFF:
377 rc = mm_stream_fsm_active_stream_off(my_obj, evt, in_val, out_val);
378 break;
379 default:
380 CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
381 break;
382 }
383 CDBG("%s : X rc =%d",__func__,rc);
384 return rc;
385 }
386
mm_stream_fsm_inited(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)387 int32_t mm_stream_fsm_inited(mm_stream_t *my_obj,
388 mm_stream_evt_type_t evt,
389 void * in_val,
390 void * out_val)
391 {
392 int32_t rc = 0;
393 char dev_name[MM_CAMERA_DEV_NAME_LEN];
394
395 CDBG("%s :E evt = %d",__func__,evt);
396 switch(evt) {
397 case MM_STREAM_EVT_ACQUIRE:
398 if ((NULL == my_obj->ch_obj) || (NULL == my_obj->ch_obj->cam_obj)) {
399 CDBG_ERROR("%s: NULL channel or camera obj\n", __func__);
400 rc = -1;
401 break;
402 }
403
404 snprintf(dev_name, sizeof(dev_name), "/dev/%s",
405 mm_camera_util_get_dev_name(my_obj->ch_obj->cam_obj->my_hdl));
406
407 my_obj->fd = open(dev_name, O_RDWR | O_NONBLOCK);
408 if (my_obj->fd <= 0) {
409 CDBG_ERROR("%s: open dev returned %d\n", __func__, my_obj->fd);
410 rc = -1;
411 break;
412 }
413 CDBG("%s: open dev fd = %d, ext_image_mode = %d, sensor_idx = %d\n",
414 __func__, my_obj->fd, my_obj->ext_image_mode, my_obj->sensor_idx);
415 rc = mm_stream_set_ext_mode(my_obj);
416 if (0 == rc) {
417 my_obj->state = MM_STREAM_STATE_ACQUIRED;
418 } else {
419 /* failed setting ext_mode
420 * close fd */
421 if(my_obj->fd > 0) {
422 close(my_obj->fd);
423 my_obj->fd = -1;
424 }
425 break;
426 }
427 rc = get_stream_inst_handle(my_obj);
428 if(rc) {
429 if(my_obj->fd > 0) {
430 close(my_obj->fd);
431 my_obj->fd = -1;
432 }
433 }
434 break;
435 default:
436 CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
437 __func__,evt,my_obj->state);
438 rc = -1;
439 break;
440 }
441 return rc;
442 }
443
mm_stream_fsm_acquired(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)444 int32_t mm_stream_fsm_acquired(mm_stream_t *my_obj,
445 mm_stream_evt_type_t evt,
446 void * in_val,
447 void * out_val)
448 {
449 int32_t rc = 0;
450
451 CDBG("%s :E evt = %d",__func__,evt);
452 switch(evt) {
453 case MM_STREAM_EVT_SET_FMT:
454 {
455 mm_camera_stream_config_t *config =
456 (mm_camera_stream_config_t *)in_val;
457
458 rc = mm_stream_config(my_obj, config);
459
460 /* change state to configed */
461 my_obj->state = MM_STREAM_STATE_CFG;
462
463 break;
464 }
465 case MM_STREAM_EVT_RELEASE:
466 rc = mm_stream_release(my_obj);
467 /* change state to not used */
468 my_obj->state = MM_STREAM_STATE_NOTUSED;
469 break;
470 case MM_STREAM_EVT_SET_PARM:
471 rc = mm_stream_set_parm_acquire(my_obj, in_val);
472 break;
473 case MM_STREAM_EVT_GET_PARM:
474 rc = mm_stream_get_parm_acquire(my_obj,out_val);
475 break;
476 default:
477 CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
478 __func__, evt, my_obj->state);
479 rc = -1;
480 }
481 CDBG("%s :X rc = %d",__func__,rc);
482 return rc;
483 }
484
mm_stream_fsm_cfg(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)485 int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
486 mm_stream_evt_type_t evt,
487 void * in_val,
488 void * out_val)
489 {
490 int32_t rc = 0;
491 CDBG("%s :E evt = %d",__func__,evt);
492 switch(evt) {
493 case MM_STREAM_EVT_SET_FMT:
494 {
495 mm_camera_stream_config_t *config =
496 (mm_camera_stream_config_t *)in_val;
497
498 rc = mm_stream_config(my_obj, config);
499
500 /* change state to configed */
501 my_obj->state = MM_STREAM_STATE_CFG;
502
503 break;
504 }
505 case MM_STREAM_EVT_RELEASE:
506 rc = mm_stream_release(my_obj);
507 my_obj->state = MM_STREAM_STATE_NOTUSED;
508 break;
509 case MM_STREAM_EVT_SET_PARM:
510 rc = mm_stream_set_parm_config(my_obj, in_val);
511 break;
512 case MM_STREAM_EVT_GET_PARM:
513 rc = mm_stream_get_parm_config(my_obj, out_val);
514 break;
515 case MM_STREAM_EVT_GET_BUF:
516 rc = mm_stream_init_bufs(my_obj);
517 /* change state to buff allocated */
518 if(0 == rc) {
519 my_obj->state = MM_STREAM_STATE_BUFFED;
520 }
521 break;
522 default:
523 CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
524 __func__, evt, my_obj->state);
525 rc = -1;
526 }
527 CDBG("%s :X rc = %d",__func__,rc);
528 return rc;
529 }
530
mm_stream_fsm_buffed(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)531 int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
532 mm_stream_evt_type_t evt,
533 void * in_val,
534 void * out_val)
535 {
536 int32_t rc = 0;
537 CDBG("%s :E evt = %d",__func__,evt);
538 switch(evt) {
539 case MM_STREAM_EVT_PUT_BUF:
540 rc = mm_stream_deinit_bufs(my_obj);
541 /* change state to configed */
542 if(0 == rc) {
543 my_obj->state = MM_STREAM_STATE_CFG;
544 }
545 break;
546 case MM_STREAM_EVT_REG_BUF:
547 rc = mm_stream_reg_buf(my_obj);
548 /* change state to regged */
549 if(0 == rc) {
550 my_obj->state = MM_STREAM_STATE_REG;
551 }
552 break;
553 case MM_STREAM_EVT_SET_PARM:
554 rc = mm_stream_set_parm_config(my_obj, in_val);
555 break;
556 case MM_STREAM_EVT_GET_PARM:
557 rc = mm_stream_get_parm_config(my_obj, out_val);
558 break;
559 default:
560 CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
561 __func__, evt, my_obj->state);
562 rc = -1;
563 }
564 CDBG("%s :X rc = %d",__func__,rc);
565 return rc;
566 }
567
mm_stream_fsm_reg(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)568 int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
569 mm_stream_evt_type_t evt,
570 void * in_val,
571 void * out_val)
572 {
573 int32_t rc = 0;
574 CDBG("%s :E evt = %d",__func__,evt);
575
576 switch(evt) {
577 case MM_STREAM_EVT_UNREG_BUF:
578 rc = mm_stream_unreg_buf(my_obj);
579
580 /* change state to buffed */
581 my_obj->state = MM_STREAM_STATE_BUFFED;
582 break;
583 case MM_STREAM_EVT_START:
584 {
585 /* launch cmd thread if CB is not null */
586 if (NULL != my_obj->buf_cb) {
587 mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
588 mm_stream_dispatch_app_data,
589 (void *)my_obj);
590
591 }
592
593 if(mm_stream_need_stream_on(my_obj)) {
594 rc = mm_stream_streamon(my_obj);
595 if (0 != rc) {
596 /* failed stream on, need to release cmd thread if it's launched */
597 if (NULL != my_obj->buf_cb) {
598 mm_camera_cmd_thread_release(&my_obj->cmd_thread);
599
600 }
601 break;
602 }
603 my_obj->state = MM_STREAM_STATE_ACTIVE_STREAM_ON;
604 } else {
605 /* register one time CB at video fd */
606 CDBG("%s : Video Size snapshot Enabled",__func__);
607 mm_stream_data_cb_t cb;
608 memset(&cb, 0, sizeof(mm_stream_data_cb_t));
609 cb.cb_count = 1; /* one time reigstration */
610 cb.user_data = (void*)my_obj;
611 cb.cb = mm_stream_buf_notify;
612 rc = mm_channel_reg_stream_cb(my_obj->ch_obj, &cb,
613 MSM_V4L2_EXT_CAPTURE_MODE_VIDEO,
614 my_obj->sensor_idx);
615 my_obj->state = MM_STREAM_STATE_ACTIVE_STREAM_OFF;
616 }
617 }
618 break;
619 case MM_STREAM_EVT_SET_PARM:
620 rc = mm_stream_set_parm_config(my_obj, in_val);
621 break;
622 case MM_STREAM_EVT_GET_PARM:
623 rc = mm_stream_get_parm_config(my_obj, out_val);
624 break;
625 default:
626 CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
627 __func__, evt, my_obj->state);
628 rc = -1;
629 }
630 CDBG("%s :X rc = %d",__func__,rc);
631 return rc;
632 }
633
mm_stream_fsm_active_stream_on(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)634 int32_t mm_stream_fsm_active_stream_on(mm_stream_t * my_obj,
635 mm_stream_evt_type_t evt,
636 void * in_val,
637 void * out_val)
638 {
639 int32_t rc = 0;
640 CDBG("%s :E evt = %d",__func__,evt);
641 switch(evt) {
642 case MM_STREAM_EVT_QBUF:
643 rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val);
644 break;
645 case MM_STREAM_EVT_STOP:
646 {
647 rc = mm_stream_streamoff(my_obj);
648 if (NULL != my_obj->buf_cb) {
649 mm_camera_cmd_thread_release(&my_obj->cmd_thread);
650
651 }
652 my_obj->state = MM_STREAM_STATE_REG;
653 }
654 break;
655 case MM_STREAM_EVT_SET_PARM:
656 rc = mm_stream_set_parm_start(my_obj, in_val);
657 break;
658 case MM_STREAM_EVT_GET_PARM:
659 rc = mm_stream_get_parm_start(my_obj, out_val);
660 break;
661 default:
662 CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
663 __func__, evt, my_obj->state);
664 return -1;
665 }
666 CDBG("%s :X rc = %d",__func__,rc);
667 return rc;
668 }
669
mm_stream_fsm_active_stream_off(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)670 int32_t mm_stream_fsm_active_stream_off(mm_stream_t * my_obj,
671 mm_stream_evt_type_t evt,
672 void * in_val,
673 void * out_val)
674 {
675 int32_t rc = 0;
676 CDBG("%s :E evt = %d",__func__,evt);
677 switch(evt) {
678 case MM_STREAM_EVT_QBUF:
679 rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val);
680 break;
681 case MM_STREAM_EVT_STOP:
682 {
683 if (NULL != my_obj->buf_cb) {
684 rc = mm_camera_cmd_thread_release(&my_obj->cmd_thread);
685
686 }
687 my_obj->state = MM_STREAM_STATE_REG;
688 }
689 break;
690 case MM_STREAM_EVT_SET_PARM:
691 rc = mm_stream_set_parm_config(my_obj, in_val);
692 break;
693 case MM_STREAM_EVT_GET_PARM:
694 rc = mm_stream_get_parm_config(my_obj, out_val);
695 break;
696 default:
697 CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
698 __func__, evt, my_obj->state);
699 return -1;
700 }
701 CDBG("%s :X rc = %d",__func__,rc);
702 return rc;
703 }
704
mm_stream_config(mm_stream_t * my_obj,mm_camera_stream_config_t * config)705 int32_t mm_stream_config(mm_stream_t *my_obj,
706 mm_camera_stream_config_t *config)
707 {
708 int32_t rc = 0;
709 memcpy(&my_obj->fmt, &config->fmt, sizeof(mm_camera_image_fmt_t));
710 my_obj->hal_requested_num_bufs = config->num_of_bufs;
711 my_obj->need_stream_on = config->need_stream_on;
712
713 rc = mm_stream_get_offset(my_obj);
714 if(rc != 0) {
715 CDBG_ERROR("%s: Error in offset query",__func__);
716 return rc;
717 }
718 if(mm_stream_need_stream_on(my_obj)) {
719 /* only send fmt to backend if we need streamon */
720 rc = mm_stream_set_fmt(my_obj);
721 }
722 return rc;
723 }
724
mm_stream_release(mm_stream_t * my_obj)725 int32_t mm_stream_release(mm_stream_t *my_obj)
726 {
727 int32_t rc;
728
729 /* close fd */
730 if(my_obj->fd > 0)
731 {
732 close(my_obj->fd);
733 }
734
735 /* destroy mutex */
736 pthread_mutex_destroy(&my_obj->buf_lock);
737 pthread_mutex_destroy(&my_obj->cb_lock);
738
739 /* reset stream obj */
740 memset(my_obj, 0, sizeof(mm_stream_t));
741 my_obj->fd = -1;
742
743 return 0;
744 }
745
mm_stream_need_stream_on(mm_stream_t * my_obj)746 uint8_t mm_stream_need_stream_on(mm_stream_t *my_obj)
747 {
748 return my_obj->need_stream_on;
749 }
750
mm_stream_streamon(mm_stream_t * my_obj)751 int32_t mm_stream_streamon(mm_stream_t *my_obj)
752 {
753 int32_t rc;
754 enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
755
756 CDBG("%s :E",__func__);
757 /* Add fd to data poll thread */
758 rc = mm_camera_poll_thread_add_poll_fd(&my_obj->ch_obj->poll_thread[0],
759 my_obj->my_hdl,
760 my_obj->fd,
761 mm_stream_data_notify,
762 (void*)my_obj);
763 if (rc < 0) {
764 return rc;
765 }
766 rc = ioctl(my_obj->fd, VIDIOC_STREAMON, &buf_type);
767 if (rc < 0) {
768 CDBG_ERROR("%s: ioctl VIDIOC_STREAMON failed: rc=%d\n",
769 __func__, rc);
770 /* remove fd from data poll thread in case of failure */
771 mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl);
772 }
773 CDBG("%s :X rc = %d",__func__,rc);
774 return rc;
775 }
776
mm_stream_streamoff(mm_stream_t * my_obj)777 int32_t mm_stream_streamoff(mm_stream_t *my_obj)
778 {
779 int32_t rc;
780 enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
781
782 /* step1: remove fd from data poll thread */
783 mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl);
784
785 /* step2: stream off */
786 rc = ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type);
787 if (rc < 0) {
788 CDBG_ERROR("%s: STREAMOFF failed: %s\n",
789 __func__, strerror(errno));
790 }
791 CDBG("%s :X rc = %d",__func__,rc);
792 return rc;
793 }
794
mm_stream_util_get_v4l2_fmt(cam_format_t fmt,uint8_t * num_planes)795 static uint32_t mm_stream_util_get_v4l2_fmt(cam_format_t fmt,
796 uint8_t *num_planes)
797 {
798 uint32_t val;
799 switch(fmt) {
800 case CAMERA_YUV_420_NV12:
801 val = V4L2_PIX_FMT_NV12;
802 *num_planes = 2;
803 break;
804 case CAMERA_YUV_420_NV21:
805 val = V4L2_PIX_FMT_NV21;
806 *num_planes = 2;
807 break;
808 case CAMERA_BAYER_SBGGR10:
809 case CAMERA_RDI:
810 val= V4L2_PIX_FMT_SBGGR10;
811 *num_planes = 1;
812 break;
813 case CAMERA_YUV_422_NV61:
814 val= V4L2_PIX_FMT_NV61;
815 *num_planes = 2;
816 break;
817 default:
818 val = 0;
819 *num_planes = 0;
820 break;
821 }
822 return val;
823 }
824
mm_stream_read_msm_frame(mm_stream_t * my_obj,mm_camera_buf_info_t * buf_info)825 int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
826 mm_camera_buf_info_t* buf_info)
827 {
828 int32_t idx = -1, rc = 0;
829 struct v4l2_buffer vb;
830 struct v4l2_plane planes[VIDEO_MAX_PLANES];
831 uint32_t i = 0;
832 uint8_t num_planes = 0;
833
834 mm_stream_util_get_v4l2_fmt(my_obj->fmt.fmt,
835 &num_planes);
836
837 memset(&vb, 0, sizeof(vb));
838 vb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
839 vb.memory = V4L2_MEMORY_USERPTR;
840 vb.m.planes = &planes[0];
841 vb.length = num_planes;
842
843 rc = ioctl(my_obj->fd, VIDIOC_DQBUF, &vb);
844 if (rc < 0) {
845 CDBG_ERROR("%s: VIDIOC_DQBUF ioctl call failed (rc=%d)\n",
846 __func__, rc);
847 } else {
848 int8_t idx = vb.index;
849 buf_info->buf = &my_obj->buf[idx];
850 buf_info->frame_idx = vb.sequence;
851 buf_info->stream_id = my_obj->my_hdl;
852 buf_info->need_pp = my_obj->is_pp_needed;
853
854 buf_info->buf->stream_id = my_obj->my_hdl;
855 buf_info->buf->buf_idx = idx;
856 buf_info->buf->frame_idx = vb.sequence;
857 buf_info->buf->ts.tv_sec = vb.timestamp.tv_sec;
858 buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000;
859
860 for(i = 0; i < vb.length; i++) {
861 CDBG("%s plane %d addr offset: %d data offset:%d\n",
862 __func__, i, vb.m.planes[i].reserved[0],
863 vb.m.planes[i].data_offset);
864 buf_info->buf->planes[i].reserved[0] =
865 vb.m.planes[i].reserved[0];
866 buf_info->buf->planes[i].data_offset =
867 vb.m.planes[i].data_offset;
868 }
869
870
871 }
872 CDBG("%s :X rc = %d",__func__,rc);
873 return rc;
874 }
875
mm_stream_get_crop(mm_stream_t * my_obj,mm_camera_rect_t * crop)876 int32_t mm_stream_get_crop(mm_stream_t *my_obj,
877 mm_camera_rect_t *crop)
878 {
879 struct v4l2_crop crop_info;
880 int32_t rc = 0;
881
882 memset(&crop_info, 0, sizeof(crop_info));
883 crop_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
884 rc = ioctl(my_obj->fd, VIDIOC_G_CROP, &crop_info);
885 if (0 == rc) {
886 crop->left = crop_info.c.left;
887 crop->top = crop_info.c.top;
888 crop->width = crop_info.c.width;
889 crop->height = crop_info.c.height;
890 }
891 CDBG("%s :X rc = %d",__func__,rc);
892 return rc;
893 }
894
mm_stream_set_parm_acquire(mm_stream_t * my_obj,void * in_value)895 int32_t mm_stream_set_parm_acquire(mm_stream_t *my_obj,
896 void *in_value)
897 {
898 int32_t rc = 0;
899 mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)in_value;
900 mm_camera_stream_parm_t parm_type = payload->parm_type;
901
902 CDBG("%s: parm_type = %d",__func__,(int)parm_type);
903 switch(parm_type) {
904 case MM_CAMERA_STREAM_CID:{
905 stream_cid_t *value = (stream_cid_t *)in_value;
906 mm_stream_set_cid(my_obj,value);
907 break;
908 }
909 default:
910 CDBG_ERROR("%s : Parm -%d set is not supported here",__func__,(int)parm_type);
911 break;
912 }
913 return rc;
914 }
mm_stream_get_parm_acquire(mm_stream_t * my_obj,void * out_value)915 int32_t mm_stream_get_parm_acquire(mm_stream_t *my_obj,
916 void *out_value)
917 {
918 int32_t rc = 0;
919 mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)out_value;
920 mm_camera_stream_parm_t parm_type = payload->parm_type;
921
922 CDBG("%s: parm_type = %d",__func__,(int)parm_type);
923 switch(parm_type) {
924 case MM_CAMERA_STREAM_CID:{
925 stream_cid_t *value = (stream_cid_t *)out_value;
926 rc = mm_stream_get_cid(my_obj,value);
927 break;
928 }
929 case MM_CAMERA_STREAM_CROP:{
930 mm_camera_rect_t *crop = (mm_camera_rect_t *)out_value;
931 rc = mm_stream_get_crop(my_obj, crop);
932 break;
933 }
934 default:
935 CDBG_ERROR("%s : Parm -%d get is not supported here",__func__,(int)parm_type);
936 break;
937 }
938 return rc;
939 }
940
mm_stream_set_parm_config(mm_stream_t * my_obj,void * in_value)941 int32_t mm_stream_set_parm_config(mm_stream_t *my_obj,
942 void *in_value)
943 {
944 int32_t rc = 0;
945 mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)in_value;
946 mm_camera_stream_parm_t parm_type = payload->parm_type;
947 void *value = payload->value;
948
949 CDBG("%s: parm_type = %d",__func__,(int)parm_type);
950 switch(parm_type) {
951 default:
952 CDBG_ERROR("%s : Parm -%d set is not supported here",__func__,(int)parm_type);
953 break;
954 }
955 return rc;
956 }
mm_stream_get_parm_config(mm_stream_t * my_obj,void * out_value)957 int32_t mm_stream_get_parm_config(mm_stream_t *my_obj,
958 void *out_value)
959 {
960 int32_t rc = 0;
961 mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)out_value;
962
963 if(payload == NULL) {
964 CDBG_ERROR("%s : Invalid Argument",__func__);
965 return -1;
966 }
967 CDBG("%s: parm_type = %d",__func__,(int)payload->parm_type);
968 switch(payload->parm_type) {
969 case MM_CAMERA_STREAM_OFFSET:
970 memcpy(payload->value,(void *)&my_obj->frame_offset,sizeof(mm_camera_frame_len_offset));
971 break;
972 case MM_CAMERA_STREAM_CROP:{
973 mm_camera_rect_t *crop = (mm_camera_rect_t *)payload->value;
974 rc = mm_stream_get_crop(my_obj, crop);
975 break;
976 }
977 default:
978 CDBG_ERROR("%s : Parm -%d get is not supported here",__func__,(int)payload->parm_type);
979 break;
980 }
981 return rc;
982 }
983
mm_stream_set_parm_start(mm_stream_t * my_obj,void * in_value)984 int32_t mm_stream_set_parm_start(mm_stream_t *my_obj,
985 void *in_value)
986 {
987 int32_t rc = 0;
988 mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)in_value;
989 mm_camera_stream_parm_t parm_type = payload->parm_type;
990 void *value = payload->value;
991
992 CDBG("%s: parm_type = %d",__func__,(int)parm_type);
993 switch(parm_type) {
994 default:
995 CDBG_ERROR("%s : Parm -%d set is not supported here",__func__,(int)parm_type);
996 break;
997 }
998 return rc;
999 }
mm_stream_get_parm_start(mm_stream_t * my_obj,void * out_value)1000 int32_t mm_stream_get_parm_start(mm_stream_t *my_obj,
1001 void *out_value)
1002 {
1003 int32_t rc = 0;
1004 mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)out_value;
1005
1006 if(payload == NULL) {
1007 CDBG_ERROR("%s : Invalid Argument",__func__);
1008 return -1;
1009 }
1010 CDBG("%s: parm_type = %d",__func__,(int)payload->parm_type);
1011 switch(payload->parm_type) {
1012 case MM_CAMERA_STREAM_OFFSET:
1013 memcpy(payload->value,(void *)&my_obj->frame_offset,sizeof(mm_camera_frame_len_offset));
1014 break;
1015 case MM_CAMERA_STREAM_CROP:{
1016 mm_camera_rect_t *crop = (mm_camera_rect_t *)payload->value;
1017 rc = mm_stream_get_crop(my_obj, crop);
1018 break;
1019 }
1020 default:
1021 CDBG_ERROR("%s : Parm -%d get is not supported here",__func__,(int)payload->parm_type);
1022 break;
1023 }
1024 return rc;
1025 }
mm_stream_set_ext_mode(mm_stream_t * my_obj)1026 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj)
1027 {
1028 int32_t rc = 0;
1029 struct v4l2_streamparm s_parm;
1030
1031 s_parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1032 s_parm.parm.capture.extendedmode = my_obj->ext_image_mode;
1033
1034 rc = ioctl(my_obj->fd, VIDIOC_S_PARM, &s_parm);
1035 CDBG("%s:stream fd=%d, rc=%d, extended_mode=%d\n",
1036 __func__, my_obj->fd, rc,
1037 s_parm.parm.capture.extendedmode);
1038 return rc;
1039 }
1040
mm_stream_qbuf(mm_stream_t * my_obj,mm_camera_buf_def_t * buf)1041 int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf)
1042 {
1043 int32_t i, rc = 0;
1044 int *ret;
1045 struct v4l2_buffer buffer;
1046
1047 memset(&buffer, 0, sizeof(buffer));
1048 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1049 buffer.memory = V4L2_MEMORY_USERPTR;
1050 buffer.index = buf->buf_idx;
1051 buffer.m.planes = &buf->planes[0];
1052 buffer.length = buf->num_planes;
1053
1054 CDBG("%s:stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d\n", __func__,
1055 buf->stream_id, buf->fd, buffer.index, buffer.length);
1056
1057 rc = ioctl(my_obj->fd, VIDIOC_QBUF, &buffer);
1058 CDBG("%s: qbuf idx:%d, rc:%d", __func__, buffer.index, rc);
1059 return rc;
1060 }
1061
1062 /* This function let kernel know amount of buffers will be registered */
mm_stream_request_buf(mm_stream_t * my_obj)1063 int32_t mm_stream_request_buf(mm_stream_t * my_obj)
1064 {
1065 int32_t rc = 0;
1066 uint8_t i,reg = 0;
1067 struct v4l2_requestbuffers bufreq;
1068 uint8_t buf_num = my_obj->buf_num;
1069
1070 if(buf_num > MM_CAMERA_MAX_NUM_FRAMES) {
1071 CDBG_ERROR("%s: buf num %d > max limit %d\n",
1072 __func__, buf_num, MM_CAMERA_MAX_NUM_FRAMES);
1073 return -1;
1074 }
1075 pthread_mutex_lock(&my_obj->buf_lock);
1076 for(i = 0; i < buf_num; i++){
1077 if (my_obj->buf_status[i].initial_reg_flag){
1078 reg = 1;
1079 break;
1080 }
1081 }
1082 pthread_mutex_unlock(&my_obj->buf_lock);
1083 if(!reg) {
1084 //No need to register a buffer
1085 CDBG_ERROR("No Need to register this buffer");
1086 return rc;
1087 }
1088 memset(&bufreq, 0, sizeof(bufreq));
1089 bufreq.count = buf_num;
1090 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1091 bufreq.memory = V4L2_MEMORY_USERPTR;
1092 rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
1093 if (rc < 0) {
1094 CDBG_ERROR("%s: fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d\n",
1095 __func__, my_obj->fd, rc);
1096 }
1097 CDBG("%s :X rc = %d",__func__,rc);
1098 return rc;
1099 }
1100
mm_stream_get_frame_len_offset(mm_camera_image_fmt_t * img_fmt,camera_mode_t mode,int image_type,mm_camera_frame_len_offset * frame_offset)1101 int32_t mm_stream_get_frame_len_offset(mm_camera_image_fmt_t* img_fmt,
1102 camera_mode_t mode,
1103 int image_type,
1104 mm_camera_frame_len_offset * frame_offset)
1105 {
1106 /* TODO : this function should query the frame len from backend using cmd */
1107 /* for now, it's still use hardcoded value */
1108 uint32_t width, height;
1109 int local_height;
1110
1111 width = img_fmt->width;
1112 height = img_fmt->height;
1113
1114 switch (img_fmt->fmt) {
1115 case CAMERA_YUV_420_NV12:
1116 case CAMERA_YUV_420_NV21:
1117 frame_offset->num_planes = 2;
1118 if (image_type == OUTPUT_TYPE_V) {
1119 frame_offset->mp[0].len = PAD_TO_2K(width * height);
1120 frame_offset->mp[1].len = PAD_TO_2K(width * height/2);
1121 /* TODO: offset to count in meta header*/
1122 frame_offset->mp[0].offset = 0;
1123 frame_offset->mp[1].offset = 0;
1124 } else if (image_type == OUTPUT_TYPE_P) {
1125 frame_offset->mp[0].len = PAD_TO_WORD(width * height);
1126 frame_offset->mp[1].len = PAD_TO_WORD(width * height/2);
1127 /* TODO: offset to count in meta header*/
1128 frame_offset->mp[0].offset = 0;
1129 frame_offset->mp[1].offset = 0;
1130 } else {
1131 frame_offset->mp[0].len = PAD_TO_WORD(width * CEILING16(height));
1132 frame_offset->mp[1].len = PAD_TO_WORD(width * CEILING16(height)/2);
1133 /* TODO: offset to count in meta header*/
1134 frame_offset->mp[0].offset = 0;
1135 frame_offset->mp[1].offset = 0;
1136 }
1137 frame_offset->frame_len =
1138 PAD_TO_4K(frame_offset->mp[0].len + frame_offset->mp[1].len);
1139 break;
1140 case CAMERA_BAYER_SBGGR10:
1141 frame_offset->num_planes = 1;
1142 frame_offset->mp[0].len = PAD_TO_WORD(width * height);
1143 frame_offset->frame_len = frame_offset->mp[0].len;
1144 break;
1145 case CAMERA_YUV_422_NV16:
1146 case CAMERA_YUV_422_NV61:
1147 if( image_type == OUTPUT_TYPE_S || image_type == OUTPUT_TYPE_V) {
1148 local_height = CEILING16(height);
1149 } else {
1150 local_height = height;
1151 }
1152 frame_offset->num_planes = 2;
1153 frame_offset->mp[0].len = PAD_TO_WORD(width * height);
1154 frame_offset->mp[1].len = PAD_TO_WORD(width * height);
1155 /* TODO: offset to count in meta header*/
1156 frame_offset->mp[0].offset = 0;
1157 frame_offset->mp[1].offset = 0;
1158 frame_offset->frame_len =
1159 frame_offset->mp[0].len + frame_offset->mp[1].len;
1160 break;
1161 default:
1162 CDBG("%s: format %d not supported.\n",
1163 __func__, img_fmt->fmt);
1164 frame_offset->frame_len = 0;
1165 }
1166 CDBG("%s:fmt=%d,image_type=%d,width=%d,height=%d,frame_len=%d\n",
1167 __func__, img_fmt->fmt, image_type, width, height, frame_offset->frame_len);
1168 return 0;
1169 }
1170
mm_stream_init_bufs(mm_stream_t * my_obj)1171 int32_t mm_stream_init_bufs(mm_stream_t * my_obj)
1172 {
1173 int32_t i, rc = 0, j;
1174 int image_type;
1175 mm_camear_mem_vtbl_t *mem_vtbl = NULL;
1176 mm_camera_frame_len_offset frame_offset;
1177 uint8_t *reg_flags = NULL;
1178
1179 /* deinit buf if it's not NULL*/
1180 if (NULL != my_obj->buf) {
1181 mm_stream_deinit_bufs(my_obj);
1182 }
1183
1184 my_obj->buf_num = my_obj->hal_requested_num_bufs;
1185 /* if stream needs do pp, allocate extra one buf for pp*/
1186 if (my_obj->is_pp_needed) {
1187 my_obj->buf_num++;
1188 }
1189
1190 my_obj->buf =
1191 (mm_camera_buf_def_t*)malloc(sizeof(mm_camera_buf_def_t) * my_obj->buf_num);
1192 my_obj->buf_status =
1193 (mm_stream_buf_status_t*)malloc(sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
1194 reg_flags = (uint8_t *)malloc(sizeof(uint8_t) * my_obj->buf_num);
1195
1196 if (NULL == my_obj->buf ||
1197 NULL == my_obj->buf_status ||
1198 NULL == reg_flags) {
1199 CDBG_ERROR("%s: No memory for buf", __func__);
1200 rc = -1;
1201 goto error_malloc;
1202 }
1203
1204 memset(my_obj->buf, 0, sizeof(mm_camera_buf_def_t) * my_obj->buf_num);
1205 memset(my_obj->buf_status, 0, sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
1206 memset(reg_flags, 0, sizeof(uint8_t) * my_obj->buf_num);
1207
1208 mem_vtbl = my_obj->ch_obj->cam_obj->mem_vtbl;
1209 rc = mem_vtbl->get_buf(my_obj->ch_obj->cam_obj->my_hdl,
1210 my_obj->ch_obj->my_hdl,
1211 my_obj->my_hdl,
1212 mem_vtbl->user_data,
1213 &my_obj->frame_offset,
1214 my_obj->buf_num,
1215 reg_flags,
1216 my_obj->buf);
1217
1218 if (0 != rc) {
1219 CDBG_ERROR("%s: Error get buf, rc = %d\n", __func__, rc);
1220 goto error_malloc;
1221 }
1222
1223 for (i=0; i < my_obj->buf_num; i++) {
1224 my_obj->buf_status[i].initial_reg_flag = reg_flags[i];
1225 my_obj->buf[i].stream_id = my_obj->my_hdl;
1226 }
1227
1228 free(reg_flags);
1229 reg_flags = NULL;
1230
1231 for (i=0; i < my_obj->buf_num; i++) {
1232 if (my_obj->buf[i].fd > 0) {
1233 if(0 >= (rc = mm_camera_map_buf(my_obj->ch_obj->cam_obj,
1234 my_obj->ext_image_mode,
1235 i,
1236 my_obj->buf[i].fd,
1237 my_obj->buf[i].frame_len)))
1238 {
1239 CDBG_ERROR("%s: Error mapping buf (rc = %d)", __func__, rc);
1240 goto error_map;
1241 }
1242 } else {
1243 CDBG_ERROR("%s: Invalid fd for buf idx (%d)", __func__, i);
1244 }
1245 }
1246
1247 return 0;
1248
1249 error_map:
1250 /* error, unmapping previously mapped bufs */
1251 for (j=0; j<i; j++) {
1252 if (my_obj->buf[j].fd > 0) {
1253 mm_camera_unmap_buf(my_obj->ch_obj->cam_obj,
1254 my_obj->ext_image_mode,
1255 j);
1256 }
1257 }
1258
1259 /* put buf back */
1260 mem_vtbl->put_buf(my_obj->ch_obj->cam_obj->my_hdl,
1261 my_obj->ch_obj->my_hdl,
1262 my_obj->my_hdl,
1263 mem_vtbl->user_data,
1264 my_obj->buf_num,
1265 my_obj->buf);
1266
1267 error_malloc:
1268 if (NULL != my_obj->buf) {
1269 free(my_obj->buf);
1270 my_obj->buf = NULL;
1271 }
1272 if (NULL != my_obj->buf_status) {
1273 free(my_obj->buf_status);
1274 my_obj->buf_status = NULL;
1275 }
1276 if (NULL != reg_flags) {
1277 free(reg_flags);
1278 reg_flags = NULL;
1279 }
1280
1281 return rc;
1282 }
1283
1284 /* return buffers to surface or release buffers allocated */
mm_stream_deinit_bufs(mm_stream_t * my_obj)1285 int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj)
1286 {
1287 int32_t rc = 0, i;
1288 mm_camear_mem_vtbl_t *mem_vtbl = NULL;
1289
1290 if (NULL == my_obj->buf) {
1291 CDBG("%s: Buf is NULL, no need to deinit", __func__);
1292 return rc;
1293 }
1294
1295 /* IOMMU unmapping */
1296 for (i=0; i<my_obj->buf_num; i++) {
1297 if (my_obj->buf[i].fd > 0) {
1298 rc = mm_camera_unmap_buf(my_obj->ch_obj->cam_obj,
1299 my_obj->ext_image_mode,
1300 i);
1301 if (rc < 0 ) {
1302 CDBG_ERROR("%s: Error unmapping bufs at idx(%d) rc=%d",
1303 __func__, i, rc);
1304 }
1305 }
1306 }
1307
1308 /* release bufs */
1309 mem_vtbl = my_obj->ch_obj->cam_obj->mem_vtbl;
1310 if (NULL != mem_vtbl) {
1311 rc = mem_vtbl->put_buf(my_obj->ch_obj->cam_obj->my_hdl,
1312 my_obj->ch_obj->my_hdl,
1313 my_obj->my_hdl,
1314 mem_vtbl->user_data,
1315 my_obj->buf_num,
1316 my_obj->buf);
1317 } else {
1318 CDBG_ERROR("%s: mem table is NULL, cannot release buf", __func__);
1319 rc = -1;
1320 }
1321
1322 free(my_obj->buf);
1323 my_obj->buf = NULL;
1324 free(my_obj->buf_status);
1325 my_obj->buf_status = NULL;
1326
1327 return rc;
1328 }
1329
mm_stream_reg_buf(mm_stream_t * my_obj)1330 int32_t mm_stream_reg_buf(mm_stream_t * my_obj)
1331 {
1332 int32_t rc = 0;
1333 uint8_t i;
1334
1335 rc = mm_stream_request_buf(my_obj);
1336 if (rc != 0) {
1337 return rc;
1338 }
1339
1340 pthread_mutex_lock(&my_obj->buf_lock);
1341 for(i = 0; i < my_obj->buf_num; i++){
1342 my_obj->buf[i].buf_idx = i;
1343
1344 /* check if need to qbuf initially */
1345 if (my_obj->buf_status[i].initial_reg_flag) {
1346 rc = mm_stream_qbuf(my_obj, &my_obj->buf[i]);
1347 if (rc != 0) {
1348 CDBG_ERROR("%s: VIDIOC_QBUF rc = %d\n", __func__, rc);
1349 return rc;
1350 }
1351 }
1352
1353 my_obj->buf_status[i].buf_refcnt = 0;
1354 my_obj->buf_status[i].in_kernel = 1;
1355 }
1356 pthread_mutex_unlock(&my_obj->buf_lock);
1357 return rc;
1358 }
1359
mm_stream_unreg_buf(mm_stream_t * my_obj)1360 int32_t mm_stream_unreg_buf(mm_stream_t * my_obj)
1361 {
1362 struct v4l2_requestbuffers bufreq;
1363 int32_t i, rc = 0,reg = 0;
1364
1365 pthread_mutex_lock(&my_obj->buf_lock);
1366 if (NULL != my_obj->buf_status) {
1367 for(i = 0; i < my_obj->buf_num; i++){
1368 if (my_obj->buf_status[i].initial_reg_flag){
1369 reg = 1;
1370 break;
1371 }
1372 }
1373 }
1374 pthread_mutex_unlock(&my_obj->buf_lock);
1375 if(!reg) {
1376 //No need to unregister a buffer
1377 goto end;
1378 }
1379 bufreq.count = 0;
1380 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1381 bufreq.memory = V4L2_MEMORY_USERPTR;
1382 rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
1383 if (rc < 0) {
1384 CDBG_ERROR("%s: fd=%d, VIDIOC_REQBUFS failed, rc=%d\n",
1385 __func__, my_obj->fd, rc);
1386 }
1387
1388 end:
1389 /* reset buf reference count */
1390 pthread_mutex_lock(&my_obj->buf_lock);
1391 if (NULL != my_obj->buf_status) {
1392 for(i = 0; i < my_obj->buf_num; i++){
1393 my_obj->buf_status[i].buf_refcnt = 0;
1394 my_obj->buf_status[i].in_kernel = 0;
1395 }
1396 }
1397 pthread_mutex_unlock(&my_obj->buf_lock);
1398
1399 return rc;
1400 }
1401
mm_stream_set_fmt(mm_stream_t * my_obj)1402 int32_t mm_stream_set_fmt(mm_stream_t *my_obj)
1403 {
1404 int32_t rc = 0;
1405 struct v4l2_format fmt;
1406
1407 if(my_obj->fmt.width == 0 || my_obj->fmt.height == 0) {
1408 CDBG_ERROR("%s:invalid input[w=%d,h=%d,fmt=%d]\n",
1409 __func__, my_obj->fmt.width, my_obj->fmt.height, my_obj->fmt.fmt);
1410 return -1;
1411 }
1412
1413 memset(&fmt, 0, sizeof(fmt));
1414 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1415 fmt.fmt.pix_mp.width = my_obj->fmt.width;
1416 fmt.fmt.pix_mp.height= my_obj->fmt.height;
1417 fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
1418 fmt.fmt.pix_mp.pixelformat =
1419 mm_stream_util_get_v4l2_fmt(my_obj->fmt.fmt,
1420 &(fmt.fmt.pix_mp.num_planes));
1421 rc = ioctl(my_obj->fd, VIDIOC_S_FMT, &fmt);
1422 CDBG("%s:fd=%d, ext_image_mode=%d, rc=%d\n",
1423 __func__, my_obj->fd, my_obj->ext_image_mode, rc);
1424
1425 return rc;
1426 }
1427
mm_stream_get_offset(mm_stream_t * my_obj)1428 int32_t mm_stream_get_offset(mm_stream_t *my_obj)
1429 {
1430 int32_t rc = 0;
1431 cam_frame_resolution_t frame_offset;
1432
1433 memset(&my_obj->frame_offset,0,sizeof(mm_camera_frame_len_offset));
1434
1435 frame_offset.format = my_obj->fmt.fmt;
1436 frame_offset.image_mode = my_obj->ext_image_mode;
1437 frame_offset.rotation = my_obj->fmt.rotation;
1438 frame_offset.width = my_obj->fmt.width;
1439 frame_offset.height = my_obj->fmt.height;
1440
1441 switch (my_obj->ext_image_mode) {
1442 case MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW:
1443 case MSM_V4L2_EXT_CAPTURE_MODE_MAIN:
1444 case MSM_V4L2_EXT_CAPTURE_MODE_RAW:
1445 case MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL:
1446 case MSM_V4L2_EXT_CAPTURE_MODE_RDI:
1447 frame_offset.padding_format = CAMERA_PAD_TO_WORD;
1448 break;
1449 case MSM_V4L2_EXT_CAPTURE_MODE_VIDEO:
1450 default:
1451 frame_offset.padding_format = CAMERA_PAD_TO_2K;
1452 break;
1453 }
1454
1455 CDBG("%s: format = %d, image_mode = %d, padding_format = %d, rotation = %d,"
1456 "width = %d height = %d",
1457 __func__,frame_offset.format,frame_offset.image_mode,frame_offset.padding_format,
1458 frame_offset.rotation,frame_offset.width,frame_offset.height);
1459
1460 rc = mm_camera_send_native_ctrl_cmd(my_obj->ch_obj->cam_obj,
1461 CAMERA_GET_PARM_FRAME_RESOLUTION,
1462 sizeof(cam_frame_resolution_t),
1463 &frame_offset);
1464 if(rc != 0) {
1465 CDBG_ERROR("%s: Failed to get the stream offset and frame length",__func__);
1466 return rc;
1467 }
1468 my_obj->fmt.width = frame_offset.width;
1469 my_obj->fmt.height = frame_offset.height;
1470 memcpy(&my_obj->frame_offset,&frame_offset.frame_offset,sizeof(mm_camera_frame_len_offset));
1471 CDBG("%s: Frame length = %d width = %d, height = %d, rc = %d",
1472 __func__,my_obj->frame_offset.frame_len,my_obj->fmt.width,my_obj->fmt.height,rc);
1473 return rc;
1474 }
1475
1476
mm_stream_set_cid(mm_stream_t * my_obj,stream_cid_t * value)1477 int32_t mm_stream_set_cid(mm_stream_t *my_obj,stream_cid_t *value)
1478 {
1479 int32_t rc = 0;
1480 cam_cid_info_t cam_cid_info;
1481
1482 cam_cid_info.num_cids = 1;
1483 cam_cid_info.cid_entries[0].cid = value->cid;
1484 cam_cid_info.cid_entries[0].dt = value->dt;
1485 cam_cid_info.cid_entries[0].inst_handle = my_obj->inst_hdl;
1486
1487 rc = mm_camera_send_native_ctrl_cmd(my_obj->ch_obj->cam_obj,
1488 CAMERA_SET_PARM_CID,
1489 sizeof(cam_cid_info_t),
1490 &cam_cid_info);
1491 if(rc != 0) {
1492 CDBG_ERROR("%s: Failed to set the CID",__func__);
1493 return rc;
1494 }
1495 return rc;
1496 }
1497
mm_stream_get_cid(mm_stream_t * my_obj,stream_cid_t * out_value)1498 int32_t mm_stream_get_cid(mm_stream_t *my_obj,stream_cid_t *out_value)
1499 {
1500 //TODO: Need to use sensor structure init in camera query
1501 int32_t rc = 0;
1502 return rc;
1503 }
1504
mm_stream_buf_done(mm_stream_t * my_obj,mm_camera_buf_def_t * frame)1505 int32_t mm_stream_buf_done(mm_stream_t * my_obj,
1506 mm_camera_buf_def_t *frame)
1507 {
1508 int32_t rc = 0;
1509
1510 if (my_obj->is_local_buf) {
1511 /* special case for video-sized live snapshot
1512 * buf is local, no need to qbuf to kernel */
1513 return 0;
1514 }
1515
1516 pthread_mutex_lock(&my_obj->buf_lock);
1517
1518 if(my_obj->buf_status[frame->buf_idx].buf_refcnt == 0) {
1519 CDBG("%s: Error Trying to free second time?(idx=%d) count=%d, ext_image_mode=%d\n",
1520 __func__, frame->buf_idx,
1521 my_obj->buf_status[frame->buf_idx].buf_refcnt,
1522 my_obj->ext_image_mode);
1523 rc = -1;
1524 }else{
1525 my_obj->buf_status[frame->buf_idx].buf_refcnt--;
1526 if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) {
1527 CDBG("<DEBUG> : Buf done for buffer:%d:%d", my_obj->ext_image_mode, frame->buf_idx);
1528 rc = mm_stream_qbuf(my_obj, frame);
1529 if(rc < 0) {
1530 CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n",
1531 __func__, frame->buf_idx, rc);
1532 } else {
1533 my_obj->buf_status[frame->buf_idx].in_kernel = 1;
1534 }
1535 }else{
1536 CDBG("<DEBUG> : Still ref count pending count :%d",
1537 my_obj->buf_status[frame->buf_idx].buf_refcnt);
1538 CDBG("<DEBUG> : for buffer:%p:%d, ext_image_mode=%d",
1539 my_obj, frame->buf_idx, my_obj->ext_image_mode);
1540 }
1541 }
1542 pthread_mutex_unlock(&my_obj->buf_lock);
1543 return rc;
1544 }
1545
mm_stream_reg_buf_cb(mm_stream_t * my_obj,mm_stream_data_cb_t * val)1546 int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj,
1547 mm_stream_data_cb_t *val)
1548 {
1549 int32_t rc = -1;
1550 uint8_t i;
1551
1552 pthread_mutex_lock(&my_obj->cb_lock);
1553 for (i=0 ;i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
1554 if(NULL == my_obj->buf_cb[i].cb) {
1555 memcpy(&my_obj->buf_cb[i], val, sizeof(mm_stream_data_cb_t));
1556 rc = 0;
1557 break;
1558 }
1559 }
1560 pthread_mutex_unlock(&my_obj->cb_lock);
1561
1562 return rc;
1563 }
1564