1 // SPDX-License-Identifier: GPL-2.0
3 * Support for Intel Camera Imaging ISP subsystem.
4 * Copyright (c) 2015, Intel Corporation.
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.
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
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 */
33 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
35 ref_count_mipi_allocation[N_CSI_PORTS]; /* Initialized in mipi_init */
39 ia_css_mipi_frame_specify(const unsigned int size_mem_words,
40 const bool contiguous) {
43 my_css.size_mem_words = size_mem_words;
50 * Check if a source port or TPG/PRBS ID is valid
52 static bool ia_css_mipi_is_source_port_valid(struct ia_css_pipe *pipe,
56 unsigned int port = 0;
57 unsigned int max_ports = 0;
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;
64 case IA_CSS_INPUT_MODE_TPG:
65 port = (unsigned int)pipe->stream->config.source.tpg.id;
66 max_ports = N_CSS_TPG_IDS;
68 case IA_CSS_INPUT_MODE_PRBS:
69 port = (unsigned int)pipe->stream->config.source.prbs.id;
70 max_ports = N_CSS_PRBS_IDS;
79 assert(port < max_ports);
81 if (port >= max_ports)
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
99 * Result is given in DDR mem words, 32B or 256 bits
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) {
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;
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.
128 width_padded += (2 * ISP_VEC_NELEMS);
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);
136 case ATOMISP_INPUT_FORMAT_RAW_6: /* 4p, 3B, 24bits */
139 case ATOMISP_INPUT_FORMAT_RAW_7: /* 8p, 7B, 56bits */
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 */
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.
159 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY: /* 2p, 3B, 24bits */
160 case ATOMISP_INPUT_FORMAT_RAW_12: /* 2p, 3B, 24bits */
163 case ATOMISP_INPUT_FORMAT_RAW_14: /* 4p, 7B, 56bits */
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 */
172 case ATOMISP_INPUT_FORMAT_RGB_666: /* 4p, 9B, 72bits */
175 case ATOMISP_INPUT_FORMAT_YUV422_10: /* 2p, 5B, 40bits */
178 case ATOMISP_INPUT_FORMAT_RGB_888: /* 1p, 3B, 24bits */
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 */
189 odd_line_bytes = (width_padded * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */
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)
196 even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >>
197 3; /* ceil ( bits per line / 8) */
200 even_line_bytes = odd_line_bytes;
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
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
212 * data data 0 0 0 0 0 0
214 * last (EOL) EOF 0 0 0 0 0 0
216 * Embedded lines are regular lines stored before the first and after
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));
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 */
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) */
242 *size_mem_words = mem_words; /* ceil(words/8); mem word is 32B = 8words. */
243 /* Check if the above is still needed. */
245 IA_CSS_LEAVE_ERR(err);
249 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
251 ia_css_mipi_frame_enable_check_on_size(const enum mipi_port_id port,
252 const unsigned int size_mem_words) {
257 OP___assert(port < N_CSI_PORTS);
258 OP___assert(size_mem_words != 0);
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 */
265 if (idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT)
267 my_css.mipi_sizes_for_check[port][idx] = size_mem_words;
278 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
281 for (i = 0; i < N_CSI_PORTS; i++)
282 ref_count_mipi_allocation[i] = 0;
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)
293 (void)size_mem_words;
297 enum atomisp_input_format format;
298 bool pack_raw_pixels;
300 unsigned int width_padded;
301 unsigned int bits_per_pixel = 0;
303 unsigned int even_line_bytes = 0;
304 unsigned int odd_line_bytes = 0;
306 unsigned int words_per_odd_line = 0;
307 unsigned int words_per_even_line = 0;
309 unsigned int mem_words_per_even_line = 0;
310 unsigned int mem_words_per_odd_line = 0;
312 unsigned int mem_words_per_buff_line = 0;
313 unsigned int mem_words_per_buff = 0;
317 * zhengjie.lu@intel.com
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.
325 * Question here is that: which one shall be used?
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;
334 * zhengjie.lu@intel.com
337 * - The following code is derived from the
338 * existing code "ia_css_mipi_frame_calculate_size()".
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"?
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.
348 width_padded = width + (2 * ISP_VEC_NELEMS);
351 IA_CSS_ENTER("padded_width=%d, height=%d, format=%d\n",
352 width_padded, height, format);
354 bits_per_pixel = sh_css_stream_format_2_bits_per_subpixel(format);
356 (format == ATOMISP_INPUT_FORMAT_RAW_10 && pack_raw_pixels) ? bits_per_pixel : 16;
357 if (bits_per_pixel == 0)
360 odd_line_bytes = (width_padded * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */
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)
366 even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >>
367 3; /* ceil ( bits per line / 8) */
370 even_line_bytes = odd_line_bytes;
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;
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;
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;
385 *size_mem_words = mem_words_per_buff;
387 IA_CSS_LEAVE_ERR(err);
392 static bool buffers_needed(struct ia_css_pipe *pipe)
395 if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
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)
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)
415 struct ia_css_frame_info mipi_intermediate_info;
417 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
418 "allocate_mipi_frames(%p) enter:\n", pipe);
421 assert(pipe->stream);
422 if ((!pipe) || (!pipe->stream))
424 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
425 "allocate_mipi_frames(%p) exit: pipe or stream is null.\n",
430 #ifdef USE_INPUT_SYSTEM_VERSION_2401
431 if (pipe->stream->config.online)
433 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
434 "allocate_mipi_frames(%p) exit: no buffers needed for 2401 pipe mode.\n",
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",
445 return 0; /* AM TODO: Check */
449 port = (unsigned int)pipe->stream->config.source.port.port;
451 err = ia_css_mipi_is_source_port_valid(pipe, &port);
453 assert(port < N_CSI_PORTS);
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",
462 #ifdef USE_INPUT_SYSTEM_VERSION_2401
463 err = calculate_mipi_buff_size(
464 &pipe->stream->config,
465 &my_css.mipi_frame_size[port]);
468 #if defined(USE_INPUT_SYSTEM_VERSION_2)
469 if (ref_count_mipi_allocation[port] != 0)
471 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
472 "allocate_mipi_frames(%p) exit: already allocated for this port (port=%d).\n",
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.
482 if (ref_count_mipi_allocation[port] != 0)
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",
492 ref_count_mipi_allocation[port]++;
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;
505 /* AM TODO: mipi frames number should come from stream struct. */
506 my_css.num_mipi_frames[port] = NUM_MIPI_FRAMES_PER_STREAM;
508 /* Incremental allocation (per stream), not for all streams at once. */
509 { /* limit the scope of i,j */
512 for (i = 0; i < my_css.num_mipi_frames[port]; i++)
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;
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,
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;
533 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
534 "allocate_mipi_frames(%p, %d) exit: error: allocation failed.\n",
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;
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",
559 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
560 "allocate_mipi_frames(%p) exit:\n", pipe);
571 free_mipi_frames(struct ia_css_pipe *pipe) {
572 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
576 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
577 "free_mipi_frames(%p) enter:\n", pipe);
579 /* assert(pipe != NULL); TEMP: TODO: Should be assert only. */
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",
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",
598 port = (unsigned int)pipe->stream->config.source.port.port;
600 err = ia_css_mipi_is_source_port_valid(pipe, &port);
602 assert(port < N_CSI_PORTS);
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",
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]);
622 ref_count_mipi_allocation[port]--;
624 if (ref_count_mipi_allocation[port] == 0) {
625 /* no streams are using this buffer, so free it */
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;
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;
641 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
642 "free_mipi_frames(%p) exit (deallocated).\n", pipe);
644 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
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.
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",
657 } else /* pipe ==NULL */
659 /* AM TEMP: free-ing all mipi buffers just like a legacy code. */
660 for (port = CSI_PORT0_ID; port < N_CSI_PORTS; port++) {
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;
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;
675 ref_count_mipi_allocation[port] = 0;
685 send_mipi_frames(struct ia_css_pipe *pipe) {
686 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
692 unsigned int port = 0;
695 IA_CSS_ENTER_PRIVATE("pipe=%p", pipe);
698 assert(pipe->stream);
699 if (!pipe || !pipe->stream)
701 IA_CSS_ERROR("pipe or stream is null");
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");
710 /* TODO: AM: maybe this should be returning an error. */
714 port = (unsigned int)pipe->stream->config.source.port.port;
716 err = ia_css_mipi_is_source_port_valid(pipe, &port);
718 assert(port < N_CSI_PORTS);
720 if (port >= N_CSI_PORTS || err) {
721 IA_CSS_ERROR("send_mipi_frames(%p) exit: invalid port specified (port=%d).\n",
726 /* Hand-over the SP-internal mipi buffers */
727 for (i = 0; i < my_css.num_mipi_frames[port]; i++)
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]);
735 sh_css_update_host2sp_num_mipi_frames(my_css.num_mipi_frames[port]);
737 /**********************************
738 * Send an event to inform the SP
739 * that all MIPI frames are passed.
740 **********************************/
741 if (!sh_css_sp_is_running())
743 /* SP is not running. The queues are not valid */
744 IA_CSS_ERROR("sp is not running");
748 ia_css_bufq_enqueue_psys_event(
749 IA_CSS_PSYS_SW_EVENT_MIPI_BUFFERS_READY,
751 (uint8_t)my_css.num_mipi_frames[port],
753 IA_CSS_LEAVE_ERR_PRIVATE(0);