1 /* 2 * Support for Intel Camera Imaging ISP subsystem. 3 * Copyright (c) 2015, Intel Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 */ 14 15 #include "ia_css_mipi.h" 16 #include "sh_css_mipi.h" 17 #include <type_support.h> 18 #include "system_global.h" 19 #include "ia_css_err.h" 20 #include "ia_css_pipe.h" 21 #include "ia_css_stream_format.h" 22 #include "sh_css_stream_format.h" 23 #include "ia_css_stream_public.h" 24 #include "ia_css_frame_public.h" 25 #include "ia_css_input_port.h" 26 #include "ia_css_debug.h" 27 #include "sh_css_struct.h" 28 #include "sh_css_defs.h" 29 #include "sh_css_sp.h" /* sh_css_update_host2sp_mipi_frame sh_css_update_host2sp_num_mipi_frames ... */ 30 #include "sw_event_global.h" /* IA_CSS_PSYS_SW_EVENT_MIPI_BUFFERS_READY */ 31 32 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 33 static u32 34 ref_count_mipi_allocation[N_CSI_PORTS]; /* Initialized in mipi_init */ 35 #endif 36 37 int 38 ia_css_mipi_frame_specify(const unsigned int size_mem_words, 39 const bool contiguous) { 40 int err = 0; 41 42 my_css.size_mem_words = size_mem_words; 43 (void)contiguous; 44 45 return err; 46 } 47 48 /* 49 * Check if a source port or TPG/PRBS ID is valid 50 */ 51 static bool ia_css_mipi_is_source_port_valid(struct ia_css_pipe *pipe, 52 unsigned int *pport) 53 { 54 bool ret = true; 55 unsigned int port = 0; 56 unsigned int max_ports = 0; 57 58 switch (pipe->stream->config.mode) { 59 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: 60 port = (unsigned int)pipe->stream->config.source.port.port; 61 max_ports = N_CSI_PORTS; 62 break; 63 case IA_CSS_INPUT_MODE_TPG: 64 port = (unsigned int)pipe->stream->config.source.tpg.id; 65 max_ports = N_CSS_TPG_IDS; 66 break; 67 case IA_CSS_INPUT_MODE_PRBS: 68 port = (unsigned int)pipe->stream->config.source.prbs.id; 69 max_ports = N_CSS_PRBS_IDS; 70 break; 71 default: 72 assert(false); 73 ret = false; 74 break; 75 } 76 77 if (ret) { 78 assert(port < max_ports); 79 80 if (port >= max_ports) 81 ret = false; 82 } 83 84 *pport = port; 85 86 return ret; 87 } 88 89 /* Assumptions: 90 * - A line is multiple of 4 bytes = 1 word. 91 * - Each frame has SOF and EOF (each 1 word). 92 * - Each line has format header and optionally SOL and EOL (each 1 word). 93 * - Odd and even lines of YUV420 format are different in bites per pixel size. 94 * - Custom size of embedded data. 95 * -- Interleaved frames are not taken into account. 96 * -- Lines are multiples of 8B, and not necessary of (custom 3B, or 7B 97 * etc.). 98 * Result is given in DDR mem words, 32B or 256 bits 99 */ 100 int 101 ia_css_mipi_frame_calculate_size(const unsigned int width, 102 const unsigned int height, 103 const enum atomisp_input_format format, 104 const bool hasSOLandEOL, 105 const unsigned int embedded_data_size_words, 106 unsigned int *size_mem_words) { 107 int err = 0; 108 109 unsigned int bits_per_pixel = 0; 110 unsigned int even_line_bytes = 0; 111 unsigned int odd_line_bytes = 0; 112 unsigned int words_per_odd_line = 0; 113 unsigned int words_for_first_line = 0; 114 unsigned int words_per_even_line = 0; 115 unsigned int mem_words_per_even_line = 0; 116 unsigned int mem_words_per_odd_line = 0; 117 unsigned int mem_words_for_first_line = 0; 118 unsigned int mem_words_for_EOF = 0; 119 unsigned int mem_words = 0; 120 unsigned int width_padded = width; 121 122 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 123 /* The changes will be reverted as soon as RAW 124 * Buffers are deployed by the 2401 Input System 125 * in the non-continuous use scenario. 126 */ 127 width_padded += (2 * ISP_VEC_NELEMS); 128 #endif 129 130 IA_CSS_ENTER("padded_width=%d, height=%d, format=%d, hasSOLandEOL=%d, embedded_data_size_words=%d\n", 131 width_padded, height, format, hasSOLandEOL, embedded_data_size_words); 132 133 switch (format) 134 { 135 case ATOMISP_INPUT_FORMAT_RAW_6: /* 4p, 3B, 24bits */ 136 bits_per_pixel = 6; 137 break; 138 case ATOMISP_INPUT_FORMAT_RAW_7: /* 8p, 7B, 56bits */ 139 bits_per_pixel = 7; 140 break; 141 case ATOMISP_INPUT_FORMAT_RAW_8: /* 1p, 1B, 8bits */ 142 case ATOMISP_INPUT_FORMAT_BINARY_8: /* 8bits, TODO: check. */ 143 case ATOMISP_INPUT_FORMAT_YUV420_8: /* odd 2p, 2B, 16bits, even 2p, 4B, 32bits */ 144 bits_per_pixel = 8; 145 break; 146 case ATOMISP_INPUT_FORMAT_YUV420_10: /* odd 4p, 5B, 40bits, even 4p, 10B, 80bits */ 147 case ATOMISP_INPUT_FORMAT_RAW_10: /* 4p, 5B, 40bits */ 148 #if !defined(HAS_NO_PACKED_RAW_PIXELS) 149 /* The changes will be reverted as soon as RAW 150 * Buffers are deployed by the 2401 Input System 151 * in the non-continuous use scenario. 152 */ 153 bits_per_pixel = 10; 154 #else 155 bits_per_pixel = 16; 156 #endif 157 break; 158 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY: /* 2p, 3B, 24bits */ 159 case ATOMISP_INPUT_FORMAT_RAW_12: /* 2p, 3B, 24bits */ 160 bits_per_pixel = 12; 161 break; 162 case ATOMISP_INPUT_FORMAT_RAW_14: /* 4p, 7B, 56bits */ 163 bits_per_pixel = 14; 164 break; 165 case ATOMISP_INPUT_FORMAT_RGB_444: /* 1p, 2B, 16bits */ 166 case ATOMISP_INPUT_FORMAT_RGB_555: /* 1p, 2B, 16bits */ 167 case ATOMISP_INPUT_FORMAT_RGB_565: /* 1p, 2B, 16bits */ 168 case ATOMISP_INPUT_FORMAT_YUV422_8: /* 2p, 4B, 32bits */ 169 bits_per_pixel = 16; 170 break; 171 case ATOMISP_INPUT_FORMAT_RGB_666: /* 4p, 9B, 72bits */ 172 bits_per_pixel = 18; 173 break; 174 case ATOMISP_INPUT_FORMAT_YUV422_10: /* 2p, 5B, 40bits */ 175 bits_per_pixel = 20; 176 break; 177 case ATOMISP_INPUT_FORMAT_RGB_888: /* 1p, 3B, 24bits */ 178 bits_per_pixel = 24; 179 break; 180 181 case ATOMISP_INPUT_FORMAT_YUV420_16: /* Not supported */ 182 case ATOMISP_INPUT_FORMAT_YUV422_16: /* Not supported */ 183 case ATOMISP_INPUT_FORMAT_RAW_16: /* TODO: not specified in MIPI SPEC, check */ 184 default: 185 return -EINVAL; 186 } 187 188 odd_line_bytes = (width_padded * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */ 189 190 /* Even lines for YUV420 formats are double in bits_per_pixel. */ 191 if (format == ATOMISP_INPUT_FORMAT_YUV420_8 192 || format == ATOMISP_INPUT_FORMAT_YUV420_10 193 || format == ATOMISP_INPUT_FORMAT_YUV420_16) 194 { 195 even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >> 196 3; /* ceil ( bits per line / 8) */ 197 } else 198 { 199 even_line_bytes = odd_line_bytes; 200 } 201 202 /* a frame represented in memory: ()- optional; data - payload words. 203 * addr 0 1 2 3 4 5 6 7: 204 * first SOF (SOL) PACK_H data data data data data 205 * data data data data data data data data 206 * ... 207 * data data 0 0 0 0 0 0 208 * second (EOL) (SOL) PACK_H data data data data data 209 * data data data data data data data data 210 * ... 211 * data data 0 0 0 0 0 0 212 * ... 213 * last (EOL) EOF 0 0 0 0 0 0 214 * 215 * Embedded lines are regular lines stored before the first and after 216 * payload lines. 217 */ 218 219 words_per_odd_line = (odd_line_bytes + 3) >> 2; 220 /* ceil(odd_line_bytes/4); word = 4 bytes */ 221 words_per_even_line = (even_line_bytes + 3) >> 2; 222 words_for_first_line = words_per_odd_line + 2 + (hasSOLandEOL ? 1 : 0); 223 /* + SOF +packet header + optionally (SOL), but (EOL) is not in the first line */ 224 words_per_odd_line += (1 + (hasSOLandEOL ? 2 : 0)); 225 /* each non-first line has format header, and optionally (SOL) and (EOL). */ 226 words_per_even_line += (1 + (hasSOLandEOL ? 2 : 0)); 227 228 mem_words_per_odd_line = (words_per_odd_line + 7) >> 3; 229 /* ceil(words_per_odd_line/8); mem_word = 32 bytes, 8 words */ 230 mem_words_for_first_line = (words_for_first_line + 7) >> 3; 231 mem_words_per_even_line = (words_per_even_line + 7) >> 3; 232 mem_words_for_EOF = 1; /* last line consisit of the optional (EOL) and EOF */ 233 234 mem_words = ((embedded_data_size_words + 7) >> 3) + 235 mem_words_for_first_line + 236 (((height + 1) >> 1) - 1) * mem_words_per_odd_line + 237 /* ceil (height/2) - 1 (first line is calculated separatelly) */ 238 (height >> 1) * mem_words_per_even_line + /* floor(height/2) */ 239 mem_words_for_EOF; 240 241 *size_mem_words = mem_words; /* ceil(words/8); mem word is 32B = 8words. */ 242 /* Check if the above is still needed. */ 243 244 IA_CSS_LEAVE_ERR(err); 245 return err; 246 } 247 248 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) 249 int 250 ia_css_mipi_frame_enable_check_on_size(const enum mipi_port_id port, 251 const unsigned int size_mem_words) { 252 u32 idx; 253 254 int err = -EBUSY; 255 256 OP___assert(port < N_CSI_PORTS); 257 OP___assert(size_mem_words != 0); 258 259 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT && 260 my_css.mipi_sizes_for_check[port][idx] != 0; 261 idx++) /* do nothing */ 262 { 263 } 264 if (idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT) 265 { 266 my_css.mipi_sizes_for_check[port][idx] = size_mem_words; 267 err = 0; 268 } 269 270 return err; 271 } 272 #endif 273 274 void 275 mipi_init(void) 276 { 277 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 278 unsigned int i; 279 280 for (i = 0; i < N_CSI_PORTS; i++) 281 ref_count_mipi_allocation[i] = 0; 282 #endif 283 } 284 285 int 286 calculate_mipi_buff_size( 287 struct ia_css_stream_config *stream_cfg, 288 unsigned int *size_mem_words) { 289 #if !defined(USE_INPUT_SYSTEM_VERSION_2401) 290 int err = -EINVAL; 291 (void)stream_cfg; 292 (void)size_mem_words; 293 #else 294 unsigned int width; 295 unsigned int height; 296 enum atomisp_input_format format; 297 bool pack_raw_pixels; 298 299 unsigned int width_padded; 300 unsigned int bits_per_pixel = 0; 301 302 unsigned int even_line_bytes = 0; 303 unsigned int odd_line_bytes = 0; 304 305 unsigned int words_per_odd_line = 0; 306 unsigned int words_per_even_line = 0; 307 308 unsigned int mem_words_per_even_line = 0; 309 unsigned int mem_words_per_odd_line = 0; 310 311 unsigned int mem_words_per_buff_line = 0; 312 unsigned int mem_words_per_buff = 0; 313 int err = 0; 314 315 /** 316 * zhengjie.lu@intel.com 317 * 318 * NOTE 319 * - In the struct "ia_css_stream_config", there 320 * are two members: "input_config" and "isys_config". 321 * Both of them provide the same information, e.g. 322 * input_res and format. 323 * 324 * Question here is that: which one shall be used? 325 */ 326 width = stream_cfg->input_config.input_res.width; 327 height = stream_cfg->input_config.input_res.height; 328 format = stream_cfg->input_config.format; 329 pack_raw_pixels = stream_cfg->pack_raw_pixels; 330 /* end of NOTE */ 331 332 /** 333 * zhengjie.lu@intel.com 334 * 335 * NOTE 336 * - The following code is derived from the 337 * existing code "ia_css_mipi_frame_calculate_size()". 338 * 339 * Question here is: why adding "2 * ISP_VEC_NELEMS" 340 * to "width_padded", but not making "width_padded" 341 * aligned with "2 * ISP_VEC_NELEMS"? 342 */ 343 /* The changes will be reverted as soon as RAW 344 * Buffers are deployed by the 2401 Input System 345 * in the non-continuous use scenario. 346 */ 347 width_padded = width + (2 * ISP_VEC_NELEMS); 348 /* end of NOTE */ 349 350 IA_CSS_ENTER("padded_width=%d, height=%d, format=%d\n", 351 width_padded, height, format); 352 353 bits_per_pixel = sh_css_stream_format_2_bits_per_subpixel(format); 354 bits_per_pixel = 355 (format == ATOMISP_INPUT_FORMAT_RAW_10 && pack_raw_pixels) ? bits_per_pixel : 16; 356 if (bits_per_pixel == 0) 357 return -EINVAL; 358 359 odd_line_bytes = (width_padded * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */ 360 361 /* Even lines for YUV420 formats are double in bits_per_pixel. */ 362 if (format == ATOMISP_INPUT_FORMAT_YUV420_8 363 || format == ATOMISP_INPUT_FORMAT_YUV420_10) 364 { 365 even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >> 366 3; /* ceil ( bits per line / 8) */ 367 } else 368 { 369 even_line_bytes = odd_line_bytes; 370 } 371 372 words_per_odd_line = (odd_line_bytes + 3) >> 2; 373 /* ceil(odd_line_bytes/4); word = 4 bytes */ 374 words_per_even_line = (even_line_bytes + 3) >> 2; 375 376 mem_words_per_odd_line = (words_per_odd_line + 7) >> 3; 377 /* ceil(words_per_odd_line/8); mem_word = 32 bytes, 8 words */ 378 mem_words_per_even_line = (words_per_even_line + 7) >> 3; 379 380 mem_words_per_buff_line = 381 (mem_words_per_odd_line > mem_words_per_even_line) ? mem_words_per_odd_line : mem_words_per_even_line; 382 mem_words_per_buff = mem_words_per_buff_line * height; 383 384 *size_mem_words = mem_words_per_buff; 385 386 IA_CSS_LEAVE_ERR(err); 387 #endif 388 return err; 389 } 390 391 static bool buffers_needed(struct ia_css_pipe *pipe) 392 { 393 if (!atomisp_hw_is_isp2401) { 394 if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 395 return false; 396 else 397 return true; 398 } 399 400 if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR || 401 pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG || 402 pipe->stream->config.mode == IA_CSS_INPUT_MODE_PRBS) 403 return false; 404 405 return true; 406 } 407 408 int 409 allocate_mipi_frames(struct ia_css_pipe *pipe, 410 struct ia_css_stream_info *info) { 411 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 412 int err = -EINVAL; 413 unsigned int port; 414 struct ia_css_frame_info mipi_intermediate_info; 415 416 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 417 "allocate_mipi_frames(%p) enter:\n", pipe); 418 419 assert(pipe); 420 assert(pipe->stream); 421 if ((!pipe) || (!pipe->stream)) 422 { 423 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 424 "allocate_mipi_frames(%p) exit: pipe or stream is null.\n", 425 pipe); 426 return -EINVAL; 427 } 428 429 #ifdef USE_INPUT_SYSTEM_VERSION_2401 430 if (pipe->stream->config.online) 431 { 432 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 433 "allocate_mipi_frames(%p) exit: no buffers needed for 2401 pipe mode.\n", 434 pipe); 435 return 0; 436 } 437 438 #endif 439 440 if (!buffers_needed(pipe)) { 441 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 442 "allocate_mipi_frames(%p) exit: no buffers needed for pipe mode.\n", 443 pipe); 444 return 0; /* AM TODO: Check */ 445 } 446 447 if (!atomisp_hw_is_isp2401) 448 port = (unsigned int)pipe->stream->config.source.port.port; 449 else 450 err = ia_css_mipi_is_source_port_valid(pipe, &port); 451 452 assert(port < N_CSI_PORTS); 453 454 if (port >= N_CSI_PORTS || err) { 455 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 456 "allocate_mipi_frames(%p) exit: error: port is not correct (port=%d).\n", 457 pipe, port); 458 return -EINVAL; 459 } 460 461 #ifdef USE_INPUT_SYSTEM_VERSION_2401 462 err = calculate_mipi_buff_size( 463 &pipe->stream->config, 464 &my_css.mipi_frame_size[port]); 465 #endif 466 467 #if defined(USE_INPUT_SYSTEM_VERSION_2) 468 if (ref_count_mipi_allocation[port] != 0) 469 { 470 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 471 "allocate_mipi_frames(%p) exit: already allocated for this port (port=%d).\n", 472 pipe, port); 473 return 0; 474 } 475 #else 476 /* 2401 system allows multiple streams to use same physical port. This is not 477 * true for 2400 system. Currently 2401 uses MIPI buffers as a temporary solution. 478 * TODO AM: Once that is changed (removed) this code should be removed as well. 479 * In that case only 2400 related code should remain. 480 */ 481 if (ref_count_mipi_allocation[port] != 0) 482 { 483 ref_count_mipi_allocation[port]++; 484 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 485 "allocate_mipi_frames(%p) leave: nothing to do, already allocated for this port (port=%d).\n", 486 pipe, port); 487 return 0; 488 } 489 #endif 490 491 ref_count_mipi_allocation[port]++; 492 493 /* TODO: Cleaning needed. */ 494 /* This code needs to modified to allocate the MIPI frames in the correct normal way 495 with an allocate from info, by justin */ 496 mipi_intermediate_info = pipe->pipe_settings.video.video_binary.internal_frame_info; 497 mipi_intermediate_info.res.width = 0; 498 mipi_intermediate_info.res.height = 0; 499 /* To indicate it is not (yet) valid format. */ 500 mipi_intermediate_info.format = IA_CSS_FRAME_FORMAT_NUM; 501 mipi_intermediate_info.padded_width = 0; 502 mipi_intermediate_info.raw_bit_depth = 0; 503 504 /* AM TODO: mipi frames number should come from stream struct. */ 505 my_css.num_mipi_frames[port] = NUM_MIPI_FRAMES_PER_STREAM; 506 507 /* Incremental allocation (per stream), not for all streams at once. */ 508 { /* limit the scope of i,j */ 509 unsigned int i, j; 510 511 for (i = 0; i < my_css.num_mipi_frames[port]; i++) 512 { 513 /* free previous frame */ 514 if (my_css.mipi_frames[port][i]) { 515 ia_css_frame_free(my_css.mipi_frames[port][i]); 516 my_css.mipi_frames[port][i] = NULL; 517 } 518 /* check if new frame is needed */ 519 if (i < my_css.num_mipi_frames[port]) { 520 /* allocate new frame */ 521 err = ia_css_frame_allocate_with_buffer_size( 522 &my_css.mipi_frames[port][i], 523 my_css.mipi_frame_size[port] * HIVE_ISP_DDR_WORD_BYTES, 524 false); 525 if (err) { 526 for (j = 0; j < i; j++) { 527 if (my_css.mipi_frames[port][j]) { 528 ia_css_frame_free(my_css.mipi_frames[port][j]); 529 my_css.mipi_frames[port][j] = NULL; 530 } 531 } 532 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 533 "allocate_mipi_frames(%p, %d) exit: error: allocation failed.\n", 534 pipe, port); 535 return err; 536 } 537 } 538 if (info->metadata_info.size > 0) { 539 /* free previous metadata buffer */ 540 if (my_css.mipi_metadata[port][i]) { 541 ia_css_metadata_free(my_css.mipi_metadata[port][i]); 542 my_css.mipi_metadata[port][i] = NULL; 543 } 544 /* check if need to allocate a new metadata buffer */ 545 if (i < my_css.num_mipi_frames[port]) { 546 /* allocate new metadata buffer */ 547 my_css.mipi_metadata[port][i] = ia_css_metadata_allocate(&info->metadata_info); 548 if (!my_css.mipi_metadata[port][i]) { 549 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 550 "allocate_mipi_metadata(%p, %d) failed.\n", 551 pipe, port); 552 return err; 553 } 554 } 555 } 556 } 557 } 558 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 559 "allocate_mipi_frames(%p) exit:\n", pipe); 560 561 return err; 562 #else 563 (void)pipe; 564 (void)info; 565 return 0; 566 #endif 567 } 568 569 int 570 free_mipi_frames(struct ia_css_pipe *pipe) { 571 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 572 int err = -EINVAL; 573 unsigned int port; 574 575 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 576 "free_mipi_frames(%p) enter:\n", pipe); 577 578 /* assert(pipe != NULL); TEMP: TODO: Should be assert only. */ 579 if (pipe) 580 { 581 assert(pipe->stream); 582 if ((!pipe) || (!pipe->stream)) { 583 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 584 "free_mipi_frames(%p) exit: error: pipe or stream is null.\n", 585 pipe); 586 return -EINVAL; 587 } 588 589 if (!buffers_needed(pipe)) { 590 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 591 "free_mipi_frames(%p) exit: error: wrong mode.\n", 592 pipe); 593 return err; 594 } 595 596 if (!atomisp_hw_is_isp2401) 597 port = (unsigned int)pipe->stream->config.source.port.port; 598 else 599 err = ia_css_mipi_is_source_port_valid(pipe, &port); 600 601 assert(port < N_CSI_PORTS); 602 603 if (port >= N_CSI_PORTS || err) { 604 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 605 "free_mipi_frames(%p, %d) exit: error: pipe port is not correct.\n", 606 pipe, port); 607 return err; 608 } 609 610 if (ref_count_mipi_allocation[port] > 0) { 611 #if defined(USE_INPUT_SYSTEM_VERSION_2) 612 assert(ref_count_mipi_allocation[port] == 1); 613 if (ref_count_mipi_allocation[port] != 1) { 614 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 615 "free_mipi_frames(%p) exit: error: wrong ref_count (ref_count=%d).\n", 616 pipe, ref_count_mipi_allocation[port]); 617 return err; 618 } 619 #endif 620 621 ref_count_mipi_allocation[port]--; 622 623 if (ref_count_mipi_allocation[port] == 0) { 624 /* no streams are using this buffer, so free it */ 625 unsigned int i; 626 627 for (i = 0; i < my_css.num_mipi_frames[port]; i++) { 628 if (my_css.mipi_frames[port][i]) { 629 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 630 "free_mipi_frames(port=%d, num=%d).\n", port, i); 631 ia_css_frame_free(my_css.mipi_frames[port][i]); 632 my_css.mipi_frames[port][i] = NULL; 633 } 634 if (my_css.mipi_metadata[port][i]) { 635 ia_css_metadata_free(my_css.mipi_metadata[port][i]); 636 my_css.mipi_metadata[port][i] = NULL; 637 } 638 } 639 640 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 641 "free_mipi_frames(%p) exit (deallocated).\n", pipe); 642 } 643 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 644 else { 645 /* 2401 system allows multiple streams to use same physical port. This is not 646 * true for 2400 system. Currently 2401 uses MIPI buffers as a temporary solution. 647 * TODO AM: Once that is changed (removed) this code should be removed as well. 648 * In that case only 2400 related code should remain. 649 */ 650 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 651 "free_mipi_frames(%p) leave: nothing to do, other streams still use this port (port=%d).\n", 652 pipe, port); 653 } 654 #endif 655 } 656 } else /* pipe ==NULL */ 657 { 658 /* AM TEMP: free-ing all mipi buffers just like a legacy code. */ 659 for (port = CSI_PORT0_ID; port < N_CSI_PORTS; port++) { 660 unsigned int i; 661 662 for (i = 0; i < my_css.num_mipi_frames[port]; i++) { 663 if (my_css.mipi_frames[port][i]) { 664 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 665 "free_mipi_frames(port=%d, num=%d).\n", port, i); 666 ia_css_frame_free(my_css.mipi_frames[port][i]); 667 my_css.mipi_frames[port][i] = NULL; 668 } 669 if (my_css.mipi_metadata[port][i]) { 670 ia_css_metadata_free(my_css.mipi_metadata[port][i]); 671 my_css.mipi_metadata[port][i] = NULL; 672 } 673 } 674 ref_count_mipi_allocation[port] = 0; 675 } 676 } 677 #else 678 (void)pipe; 679 #endif 680 return 0; 681 } 682 683 int 684 send_mipi_frames(struct ia_css_pipe *pipe) { 685 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 686 int err = -EINVAL; 687 unsigned int i; 688 #ifndef ISP2401 689 unsigned int port; 690 #else 691 unsigned int port = 0; 692 #endif 693 694 IA_CSS_ENTER_PRIVATE("pipe=%p", pipe); 695 696 assert(pipe); 697 assert(pipe->stream); 698 if (!pipe || !pipe->stream) 699 { 700 IA_CSS_ERROR("pipe or stream is null"); 701 return -EINVAL; 702 } 703 704 /* multi stream video needs mipi buffers */ 705 /* nothing to be done in other cases. */ 706 if (!buffers_needed(pipe)) { 707 IA_CSS_LOG("nothing to be done for this mode"); 708 return 0; 709 /* TODO: AM: maybe this should be returning an error. */ 710 } 711 712 if (!atomisp_hw_is_isp2401) 713 port = (unsigned int)pipe->stream->config.source.port.port; 714 else 715 err = ia_css_mipi_is_source_port_valid(pipe, &port); 716 717 assert(port < N_CSI_PORTS); 718 719 if (port >= N_CSI_PORTS || err) { 720 IA_CSS_ERROR("send_mipi_frames(%p) exit: invalid port specified (port=%d).\n", 721 pipe, port); 722 return err; 723 } 724 725 /* Hand-over the SP-internal mipi buffers */ 726 for (i = 0; i < my_css.num_mipi_frames[port]; i++) 727 { 728 /* Need to include the ofset for port. */ 729 sh_css_update_host2sp_mipi_frame(port * NUM_MIPI_FRAMES_PER_STREAM + i, 730 my_css.mipi_frames[port][i]); 731 sh_css_update_host2sp_mipi_metadata(port * NUM_MIPI_FRAMES_PER_STREAM + i, 732 my_css.mipi_metadata[port][i]); 733 } 734 sh_css_update_host2sp_num_mipi_frames(my_css.num_mipi_frames[port]); 735 736 /********************************** 737 * Send an event to inform the SP 738 * that all MIPI frames are passed. 739 **********************************/ 740 if (!sh_css_sp_is_running()) 741 { 742 /* SP is not running. The queues are not valid */ 743 IA_CSS_ERROR("sp is not running"); 744 return err; 745 } 746 747 ia_css_bufq_enqueue_psys_event( 748 IA_CSS_PSYS_SW_EVENT_MIPI_BUFFERS_READY, 749 (uint8_t)port, 750 (uint8_t)my_css.num_mipi_frames[port], 751 0 /* not used */); 752 IA_CSS_LEAVE_ERR_PRIVATE(0); 753 #else 754 (void)pipe; 755 #endif 756 return 0; 757 } 758