2 * Support for Intel Camera Imaging ISP subsystem.
3 * Copyright (c) 2015, Intel Corporation.
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.
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
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 */
32 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
33 static uint32_t ref_count_mipi_allocation[N_CSI_PORTS]; /* Initialized in mipi_init */
37 ia_css_mipi_frame_specify(const unsigned int size_mem_words,
38 const bool contiguous)
40 enum ia_css_err err = IA_CSS_SUCCESS;
42 my_css.size_mem_words = size_mem_words;
49 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
51 * Check if a source port or TPG/PRBS ID is valid
53 static bool ia_css_mipi_is_source_port_valid(struct ia_css_pipe *pipe,
57 unsigned int port = 0;
58 unsigned int max_ports = 0;
60 switch (pipe->stream->config.mode) {
61 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
62 port = (unsigned int) pipe->stream->config.source.port.port;
63 max_ports = N_CSI_PORTS;
65 case IA_CSS_INPUT_MODE_TPG:
66 port = (unsigned int) pipe->stream->config.source.tpg.id;
67 max_ports = N_CSS_TPG_IDS;
69 case IA_CSS_INPUT_MODE_PRBS:
70 port = (unsigned int) pipe->stream->config.source.prbs.id;
71 max_ports = N_CSS_PRBS_IDS;
80 assert(port < max_ports);
82 if (port >= max_ports)
94 * - A line is multiple of 4 bytes = 1 word.
95 * - Each frame has SOF and EOF (each 1 word).
96 * - Each line has format header and optionally SOL and EOL (each 1 word).
97 * - Odd and even lines of YUV420 format are different in bites per pixel size.
98 * - Custom size of embedded data.
99 * -- Interleaved frames are not taken into account.
100 * -- Lines are multiples of 8B, and not necessary of (custom 3B, or 7B
102 * Result is given in DDR mem words, 32B or 256 bits
105 ia_css_mipi_frame_calculate_size(const unsigned int width,
106 const unsigned int height,
107 const enum ia_css_stream_format format,
108 const bool hasSOLandEOL,
109 const unsigned int embedded_data_size_words,
110 unsigned int *size_mem_words)
112 enum ia_css_err err = IA_CSS_SUCCESS;
114 unsigned int bits_per_pixel = 0;
115 unsigned int even_line_bytes = 0;
116 unsigned int odd_line_bytes = 0;
117 unsigned int words_per_odd_line = 0;
118 unsigned int words_for_first_line = 0;
119 unsigned int words_per_even_line = 0;
120 unsigned int mem_words_per_even_line = 0;
121 unsigned int mem_words_per_odd_line = 0;
122 unsigned int mem_words_for_first_line = 0;
123 unsigned int mem_words_for_EOF = 0;
124 unsigned int mem_words = 0;
125 unsigned int width_padded = width;
127 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
128 /* The changes will be reverted as soon as RAW
129 * Buffers are deployed by the 2401 Input System
130 * in the non-continuous use scenario.
132 width_padded += (2 * ISP_VEC_NELEMS);
135 IA_CSS_ENTER("padded_width=%d, height=%d, format=%d, hasSOLandEOL=%d, embedded_data_size_words=%d\n",
136 width_padded, height, format, hasSOLandEOL, embedded_data_size_words);
139 case IA_CSS_STREAM_FORMAT_RAW_6: /* 4p, 3B, 24bits */
140 bits_per_pixel = 6; break;
141 case IA_CSS_STREAM_FORMAT_RAW_7: /* 8p, 7B, 56bits */
142 bits_per_pixel = 7; break;
143 case IA_CSS_STREAM_FORMAT_RAW_8: /* 1p, 1B, 8bits */
144 case IA_CSS_STREAM_FORMAT_BINARY_8: /* 8bits, TODO: check. */
145 case IA_CSS_STREAM_FORMAT_YUV420_8: /* odd 2p, 2B, 16bits, even 2p, 4B, 32bits */
146 bits_per_pixel = 8; break;
147 case IA_CSS_STREAM_FORMAT_YUV420_10: /* odd 4p, 5B, 40bits, even 4p, 10B, 80bits */
148 case IA_CSS_STREAM_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 IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY: /* 2p, 3B, 24bits */
160 case IA_CSS_STREAM_FORMAT_RAW_12: /* 2p, 3B, 24bits */
161 bits_per_pixel = 12; break;
162 case IA_CSS_STREAM_FORMAT_RAW_14: /* 4p, 7B, 56bits */
163 bits_per_pixel = 14; break;
164 case IA_CSS_STREAM_FORMAT_RGB_444: /* 1p, 2B, 16bits */
165 case IA_CSS_STREAM_FORMAT_RGB_555: /* 1p, 2B, 16bits */
166 case IA_CSS_STREAM_FORMAT_RGB_565: /* 1p, 2B, 16bits */
167 case IA_CSS_STREAM_FORMAT_YUV422_8: /* 2p, 4B, 32bits */
168 bits_per_pixel = 16; break;
169 case IA_CSS_STREAM_FORMAT_RGB_666: /* 4p, 9B, 72bits */
170 bits_per_pixel = 18; break;
171 case IA_CSS_STREAM_FORMAT_YUV422_10: /* 2p, 5B, 40bits */
172 bits_per_pixel = 20; break;
173 case IA_CSS_STREAM_FORMAT_RGB_888: /* 1p, 3B, 24bits */
174 bits_per_pixel = 24; break;
176 case IA_CSS_STREAM_FORMAT_YUV420_16: /* Not supported */
177 case IA_CSS_STREAM_FORMAT_YUV422_16: /* Not supported */
178 case IA_CSS_STREAM_FORMAT_RAW_16: /* TODO: not specified in MIPI SPEC, check */
180 return IA_CSS_ERR_INVALID_ARGUMENTS;
183 odd_line_bytes = (width_padded * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */
185 /* Even lines for YUV420 formats are double in bits_per_pixel. */
186 if (format == IA_CSS_STREAM_FORMAT_YUV420_8
187 || format == IA_CSS_STREAM_FORMAT_YUV420_10
188 || format == IA_CSS_STREAM_FORMAT_YUV420_16) {
189 even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */
191 even_line_bytes = odd_line_bytes;
194 /* a frame represented in memory: ()- optional; data - payload words.
195 * addr 0 1 2 3 4 5 6 7:
196 * first SOF (SOL) PACK_H data data data data data
197 * data data data data data data data data
199 * data data 0 0 0 0 0 0
200 * second (EOL) (SOL) PACK_H data data data data data
201 * data data data data data data data data
203 * data data 0 0 0 0 0 0
205 * last (EOL) EOF 0 0 0 0 0 0
207 * Embedded lines are regular lines stored before the first and after
211 words_per_odd_line = (odd_line_bytes + 3) >> 2;
212 /* ceil(odd_line_bytes/4); word = 4 bytes */
213 words_per_even_line = (even_line_bytes + 3) >> 2;
214 words_for_first_line = words_per_odd_line + 2 + (hasSOLandEOL ? 1 : 0);
215 /* + SOF +packet header + optionally (SOL), but (EOL) is not in the first line */
216 words_per_odd_line += (1 + (hasSOLandEOL ? 2 : 0));
217 /* each non-first line has format header, and optionally (SOL) and (EOL). */
218 words_per_even_line += (1 + (hasSOLandEOL ? 2 : 0));
220 mem_words_per_odd_line = (words_per_odd_line + 7) >> 3;
221 /* ceil(words_per_odd_line/8); mem_word = 32 bytes, 8 words */
222 mem_words_for_first_line = (words_for_first_line + 7) >> 3;
223 mem_words_per_even_line = (words_per_even_line + 7) >> 3;
224 mem_words_for_EOF = 1; /* last line consisit of the optional (EOL) and EOF */
226 mem_words = ((embedded_data_size_words + 7) >> 3) +
227 mem_words_for_first_line +
228 (((height + 1) >> 1) - 1) * mem_words_per_odd_line +
229 /* ceil (height/2) - 1 (first line is calculated separatelly) */
230 (height >> 1) * mem_words_per_even_line + /* floor(height/2) */
233 *size_mem_words = mem_words; /* ceil(words/8); mem word is 32B = 8words. */
234 /* Check if the above is still needed. */
236 IA_CSS_LEAVE_ERR(err);
240 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
242 ia_css_mipi_frame_enable_check_on_size(const enum ia_css_csi2_port port,
243 const unsigned int size_mem_words)
247 enum ia_css_err err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
249 OP___assert(port < N_CSI_PORTS);
250 OP___assert(size_mem_words != 0);
252 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT &&
253 my_css.mipi_sizes_for_check[port][idx] != 0;
254 idx++) { /* do nothing */
256 if (idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT) {
257 my_css.mipi_sizes_for_check[port][idx] = size_mem_words;
258 err = IA_CSS_SUCCESS;
268 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
271 for (i = 0; i < N_CSI_PORTS; i++)
272 ref_count_mipi_allocation[i] = 0;
277 calculate_mipi_buff_size(
278 struct ia_css_stream_config *stream_cfg,
279 unsigned int *size_mem_words)
281 #if !defined(USE_INPUT_SYSTEM_VERSION_2401)
282 enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
284 (void)size_mem_words;
288 enum ia_css_stream_format format;
289 bool pack_raw_pixels;
291 unsigned int width_padded;
292 unsigned int bits_per_pixel = 0;
294 unsigned int even_line_bytes = 0;
295 unsigned int odd_line_bytes = 0;
297 unsigned int words_per_odd_line = 0;
298 unsigned int words_per_even_line = 0;
300 unsigned int mem_words_per_even_line = 0;
301 unsigned int mem_words_per_odd_line = 0;
303 unsigned int mem_words_per_buff_line = 0;
304 unsigned int mem_words_per_buff = 0;
305 enum ia_css_err err = IA_CSS_SUCCESS;
309 * zhengjie.lu@intel.com
313 * - In the struct "ia_css_stream_config", there
314 * are two members: "input_config" and "isys_config".
315 * Both of them provide the same information, e.g.
316 * input_res and format.
318 * Question here is that: which one shall be used?
320 width = stream_cfg->input_config.input_res.width;
321 height = stream_cfg->input_config.input_res.height;
322 format = stream_cfg->input_config.format;
323 pack_raw_pixels = stream_cfg->pack_raw_pixels;
328 * zhengjie.lu@intel.com
332 * - The following code is derived from the
333 * existing code "ia_css_mipi_frame_calculate_size()".
335 * Question here is: why adding "2 * ISP_VEC_NELEMS"
336 * to "width_padded", but not making "width_padded"
337 * aligned with "2 * ISP_VEC_NELEMS"?
339 /* The changes will be reverted as soon as RAW
340 * Buffers are deployed by the 2401 Input System
341 * in the non-continuous use scenario.
343 width_padded = width + (2 * ISP_VEC_NELEMS);
346 IA_CSS_ENTER("padded_width=%d, height=%d, format=%d\n",
347 width_padded, height, format);
349 bits_per_pixel = sh_css_stream_format_2_bits_per_subpixel(format);
351 (format == IA_CSS_STREAM_FORMAT_RAW_10 && pack_raw_pixels) ? bits_per_pixel : 16;
352 if (bits_per_pixel == 0)
353 return IA_CSS_ERR_INTERNAL_ERROR;
355 odd_line_bytes = (width_padded * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */
357 /* Even lines for YUV420 formats are double in bits_per_pixel. */
358 if (format == IA_CSS_STREAM_FORMAT_YUV420_8
359 || format == IA_CSS_STREAM_FORMAT_YUV420_10) {
360 even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */
362 even_line_bytes = odd_line_bytes;
365 words_per_odd_line = (odd_line_bytes + 3) >> 2;
366 /* ceil(odd_line_bytes/4); word = 4 bytes */
367 words_per_even_line = (even_line_bytes + 3) >> 2;
369 mem_words_per_odd_line = (words_per_odd_line + 7) >> 3;
370 /* ceil(words_per_odd_line/8); mem_word = 32 bytes, 8 words */
371 mem_words_per_even_line = (words_per_even_line + 7) >> 3;
373 mem_words_per_buff_line =
374 (mem_words_per_odd_line > mem_words_per_even_line) ? mem_words_per_odd_line : mem_words_per_even_line;
375 mem_words_per_buff = mem_words_per_buff_line * height;
377 *size_mem_words = mem_words_per_buff;
379 IA_CSS_LEAVE_ERR(err);
385 allocate_mipi_frames(struct ia_css_pipe *pipe, struct ia_css_stream_info *info)
387 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
388 enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
392 unsigned int port = 0;
394 struct ia_css_frame_info mipi_intermediate_info;
396 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
397 "allocate_mipi_frames(%p) enter:\n", pipe);
399 assert(pipe != NULL);
400 assert(pipe->stream != NULL);
401 if ((pipe == NULL) || (pipe->stream == NULL)) {
402 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
403 "allocate_mipi_frames(%p) exit: pipe or stream is null.\n",
405 return IA_CSS_ERR_INVALID_ARGUMENTS;
408 #ifdef USE_INPUT_SYSTEM_VERSION_2401
409 if (pipe->stream->config.online) {
410 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
411 "allocate_mipi_frames(%p) exit: no buffers needed for 2401 pipe mode.\n",
413 return IA_CSS_SUCCESS;
418 if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
420 if (!(pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR ||
421 pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
422 pipe->stream->config.mode == IA_CSS_INPUT_MODE_PRBS)) {
424 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
425 "allocate_mipi_frames(%p) exit: no buffers needed for pipe mode.\n",
427 return IA_CSS_SUCCESS; /* AM TODO: Check */
431 port = (unsigned int) pipe->stream->config.source.port.port;
432 assert(port < N_CSI_PORTS);
433 if (port >= N_CSI_PORTS) {
435 if (!ia_css_mipi_is_source_port_valid(pipe, &port)) {
437 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
438 "allocate_mipi_frames(%p) exit: error: port is not correct (port=%d).\n",
440 return IA_CSS_ERR_INTERNAL_ERROR;
443 #ifdef USE_INPUT_SYSTEM_VERSION_2401
444 err = calculate_mipi_buff_size(
445 &(pipe->stream->config),
446 &(my_css.mipi_frame_size[port]));
449 #if defined(USE_INPUT_SYSTEM_VERSION_2)
450 if (ref_count_mipi_allocation[port] != 0) {
451 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
452 "allocate_mipi_frames(%p) exit: already allocated for this port (port=%d).\n",
454 return IA_CSS_SUCCESS;
457 /* 2401 system allows multiple streams to use same physical port. This is not
458 * true for 2400 system. Currently 2401 uses MIPI buffers as a temporary solution.
459 * TODO AM: Once that is changed (removed) this code should be removed as well.
460 * In that case only 2400 related code should remain.
462 if (ref_count_mipi_allocation[port] != 0) {
463 ref_count_mipi_allocation[port]++;
464 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
465 "allocate_mipi_frames(%p) leave: nothing to do, already allocated for this port (port=%d).\n",
467 return IA_CSS_SUCCESS;
471 ref_count_mipi_allocation[port]++;
473 /* TODO: Cleaning needed. */
474 /* This code needs to modified to allocate the MIPI frames in the correct normal way
475 with an allocate from info, by justin */
476 mipi_intermediate_info = pipe->pipe_settings.video.video_binary.internal_frame_info;
477 mipi_intermediate_info.res.width = 0;
478 mipi_intermediate_info.res.height = 0;
479 /* To indicate it is not (yet) valid format. */
480 mipi_intermediate_info.format = IA_CSS_FRAME_FORMAT_NUM;
481 mipi_intermediate_info.padded_width = 0;
482 mipi_intermediate_info.raw_bit_depth = 0;
484 /* AM TODO: mipi frames number should come from stream struct. */
485 my_css.num_mipi_frames[port] = NUM_MIPI_FRAMES_PER_STREAM;
487 /* Incremental allocation (per stream), not for all streams at once. */
488 { /* limit the scope of i,j */
490 for (i = 0; i < my_css.num_mipi_frames[port]; i++) {
491 /* free previous frame */
492 if (my_css.mipi_frames[port][i]) {
493 ia_css_frame_free(my_css.mipi_frames[port][i]);
494 my_css.mipi_frames[port][i] = NULL;
496 /* check if new frame is needed */
497 if (i < my_css.num_mipi_frames[port]) {
498 /* allocate new frame */
499 err = ia_css_frame_allocate_with_buffer_size(
500 &my_css.mipi_frames[port][i],
501 my_css.mipi_frame_size[port] * HIVE_ISP_DDR_WORD_BYTES,
503 if (err != IA_CSS_SUCCESS) {
504 for (j = 0; j < i; j++) {
505 if (my_css.mipi_frames[port][j]) {
506 ia_css_frame_free(my_css.mipi_frames[port][j]);
507 my_css.mipi_frames[port][j] = NULL;
510 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
511 "allocate_mipi_frames(%p, %d) exit: error: allocation failed.\n",
516 if (info->metadata_info.size > 0) {
517 /* free previous metadata buffer */
518 if (my_css.mipi_metadata[port][i] != NULL) {
519 ia_css_metadata_free(my_css.mipi_metadata[port][i]);
520 my_css.mipi_metadata[port][i] = NULL;
522 /* check if need to allocate a new metadata buffer */
523 if (i < my_css.num_mipi_frames[port]) {
524 /* allocate new metadata buffer */
525 my_css.mipi_metadata[port][i] = ia_css_metadata_allocate(&info->metadata_info);
526 if (my_css.mipi_metadata[port][i] == NULL) {
527 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
528 "allocate_mipi_metadata(%p, %d) failed.\n",
536 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
537 "allocate_mipi_frames(%p) exit:\n", pipe);
543 return IA_CSS_SUCCESS;
548 free_mipi_frames(struct ia_css_pipe *pipe)
550 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
551 enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
555 unsigned int port = 0;
557 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
558 "free_mipi_frames(%p) enter:\n", pipe);
560 /* assert(pipe != NULL); TEMP: TODO: Should be assert only. */
562 assert(pipe->stream != NULL);
563 if ((pipe == NULL) || (pipe->stream == NULL)) {
564 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
565 "free_mipi_frames(%p) exit: error: pipe or stream is null.\n",
567 return IA_CSS_ERR_INVALID_ARGUMENTS;
571 if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
573 if (!(pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR ||
574 pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
575 pipe->stream->config.mode == IA_CSS_INPUT_MODE_PRBS)) {
577 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
578 "free_mipi_frames(%p) exit: error: wrong mode.\n",
584 port = (unsigned int) pipe->stream->config.source.port.port;
585 assert(port < N_CSI_PORTS);
586 if (port >= N_CSI_PORTS) {
588 if (!ia_css_mipi_is_source_port_valid(pipe, &port)) {
590 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
592 "free_mipi_frames(%p, %d) exit: error: pipe port is not correct.\n",
594 "free_mipi_frames(%p) exit: error: pipe port is not correct (port=%d).\n",
602 if (ref_count_mipi_allocation[port] > 0) {
603 #if defined(USE_INPUT_SYSTEM_VERSION_2)
604 assert(ref_count_mipi_allocation[port] == 1);
605 if (ref_count_mipi_allocation[port] != 1) {
606 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
607 "free_mipi_frames(%p) exit: error: wrong ref_count (ref_count=%d).\n",
608 pipe, ref_count_mipi_allocation[port]);
613 ref_count_mipi_allocation[port]--;
615 if (ref_count_mipi_allocation[port] == 0) {
616 /* no streams are using this buffer, so free it */
618 for (i = 0; i < my_css.num_mipi_frames[port]; i++) {
619 if (my_css.mipi_frames[port][i] != NULL) {
620 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
621 "free_mipi_frames(port=%d, num=%d).\n", port, i);
622 ia_css_frame_free(my_css.mipi_frames[port][i]);
623 my_css.mipi_frames[port][i] = NULL;
625 if (my_css.mipi_metadata[port][i] != NULL) {
626 ia_css_metadata_free(my_css.mipi_metadata[port][i]);
627 my_css.mipi_metadata[port][i] = NULL;
631 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
632 "free_mipi_frames(%p) exit (deallocated).\n", pipe);
634 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
636 /* 2401 system allows multiple streams to use same physical port. This is not
637 * true for 2400 system. Currently 2401 uses MIPI buffers as a temporary solution.
638 * TODO AM: Once that is changed (removed) this code should be removed as well.
639 * In that case only 2400 related code should remain.
641 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
642 "free_mipi_frames(%p) leave: nothing to do, other streams still use this port (port=%d).\n",
647 } else { /* pipe ==NULL */
648 /* AM TEMP: free-ing all mipi buffers just like a legacy code. */
649 for (port = CSI_PORT0_ID; port < N_CSI_PORTS; port++) {
651 for (i = 0; i < my_css.num_mipi_frames[port]; i++) {
652 if (my_css.mipi_frames[port][i] != NULL) {
653 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
654 "free_mipi_frames(port=%d, num=%d).\n", port, i);
655 ia_css_frame_free(my_css.mipi_frames[port][i]);
656 my_css.mipi_frames[port][i] = NULL;
658 if (my_css.mipi_metadata[port][i] != NULL) {
659 ia_css_metadata_free(my_css.mipi_metadata[port][i]);
660 my_css.mipi_metadata[port][i] = NULL;
663 ref_count_mipi_allocation[port] = 0;
669 return IA_CSS_SUCCESS;
673 send_mipi_frames(struct ia_css_pipe *pipe)
675 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
676 enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
681 unsigned int port = 0;
684 IA_CSS_ENTER_PRIVATE("pipe=%p", pipe);
686 assert(pipe != NULL);
687 assert(pipe->stream != NULL);
688 if (pipe == NULL || pipe->stream == NULL) {
689 IA_CSS_ERROR("pipe or stream is null");
690 return IA_CSS_ERR_INVALID_ARGUMENTS;
693 /* multi stream video needs mipi buffers */
694 /* nothing to be done in other cases. */
696 if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
698 if (!(pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR ||
699 pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
700 pipe->stream->config.mode == IA_CSS_INPUT_MODE_PRBS)) {
702 IA_CSS_LOG("nothing to be done for this mode");
703 return IA_CSS_SUCCESS;
704 /* TODO: AM: maybe this should be returning an error. */
708 port = (unsigned int) pipe->stream->config.source.port.port;
709 assert(port < N_CSI_PORTS);
710 if (port >= N_CSI_PORTS) {
711 IA_CSS_ERROR("invalid port specified (%d)", port);
713 if (!ia_css_mipi_is_source_port_valid(pipe, &port)) {
714 IA_CSS_ERROR("send_mipi_frames(%p) exit: invalid port specified (port=%d).\n", pipe, port);
719 /* Hand-over the SP-internal mipi buffers */
720 for (i = 0; i < my_css.num_mipi_frames[port]; i++) {
721 /* Need to include the ofset for port. */
722 sh_css_update_host2sp_mipi_frame(port * NUM_MIPI_FRAMES_PER_STREAM + i,
723 my_css.mipi_frames[port][i]);
724 sh_css_update_host2sp_mipi_metadata(port * NUM_MIPI_FRAMES_PER_STREAM + i,
725 my_css.mipi_metadata[port][i]);
727 sh_css_update_host2sp_num_mipi_frames(my_css.num_mipi_frames[port]);
729 /**********************************
730 * Send an event to inform the SP
731 * that all MIPI frames are passed.
732 **********************************/
733 if (!sh_css_sp_is_running()) {
734 /* SP is not running. The queues are not valid */
735 IA_CSS_ERROR("sp is not running");
739 ia_css_bufq_enqueue_psys_event(
740 IA_CSS_PSYS_SW_EVENT_MIPI_BUFFERS_READY,
742 (uint8_t)my_css.num_mipi_frames[port],
744 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
748 return IA_CSS_SUCCESS;