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