1/* 2Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. 3 4Redistribution and use in source and binary forms, with or without 5modification, are permitted provided that the following conditions are 6met: 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 Code Aurora Forum, Inc. 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 17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27IF 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 */ 47int32_t mm_stream_qbuf(mm_stream_t *my_obj, 48 mm_camera_buf_def_t *buf); 49int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj); 50int32_t mm_stream_set_fmt(mm_stream_t * my_obj); 51int32_t mm_stream_get_offset(mm_stream_t *my_obj); 52int32_t mm_stream_set_cid(mm_stream_t *my_obj,stream_cid_t *in_value); 53int32_t mm_stream_init_bufs(mm_stream_t * my_obj); 54int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj); 55int32_t mm_stream_request_buf(mm_stream_t * my_obj); 56int32_t mm_stream_unreg_buf(mm_stream_t * my_obj); 57int32_t mm_stream_release(mm_stream_t *my_obj); 58int32_t mm_stream_get_crop(mm_stream_t *my_obj, 59 mm_camera_rect_t *crop); 60int32_t mm_stream_get_cid(mm_stream_t *my_obj, 61 stream_cid_t *out_value); 62int32_t mm_stream_set_parm_acquire(mm_stream_t *my_obj, 63 void *value); 64int32_t mm_stream_get_parm_acquire(mm_stream_t *my_obj, 65 void *value); 66int32_t mm_stream_set_parm_config(mm_stream_t *my_obj, 67 void *value); 68int32_t mm_stream_get_parm_config(mm_stream_t *my_obj, 69 void *value); 70int32_t mm_stream_set_parm_start(mm_stream_t *my_obj, 71 void *value); 72int32_t mm_stream_get_parm_start(mm_stream_t *my_obj, 73 void *value); 74int32_t mm_stream_streamon(mm_stream_t *my_obj); 75int32_t mm_stream_streamoff(mm_stream_t *my_obj); 76int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj, 77 mm_camera_buf_info_t* buf_info); 78int32_t mm_stream_config(mm_stream_t *my_obj, 79 mm_camera_stream_config_t *config); 80uint8_t mm_stream_need_stream_on(mm_stream_t *my_obj); 81int32_t mm_stream_reg_buf(mm_stream_t * my_obj); 82int32_t mm_stream_buf_done(mm_stream_t * my_obj, 83 mm_camera_buf_def_t *frame); 84 85 86/* state machine function declare */ 87int32_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); 91int32_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); 95int32_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); 99int32_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); 103int32_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); 107int32_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); 111int32_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 116extern 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 121static 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 142void 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 196static 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 */ 247static 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 294static 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 */ 346int32_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 387int32_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 444int32_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 485int32_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 531int32_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 568int32_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 634int32_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 670int32_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 705int32_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 725int32_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 746uint8_t mm_stream_need_stream_on(mm_stream_t *my_obj) 747{ 748 return my_obj->need_stream_on; 749} 750 751int32_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 777int32_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 795static 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 825int32_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 876int32_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 895int32_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} 915int32_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 941int32_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} 957int32_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 984int32_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} 1000int32_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} 1026int32_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 1041int32_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 */ 1063int32_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 1101int32_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 1171int32_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 1249error_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 1267error_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 */ 1285int32_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 1330int32_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 1360int32_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 1388end: 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 1402int32_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 1428int32_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 1477int32_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 1498int32_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 1505int32_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 1546int32_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