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