Linux-libre 4.14.69-gnu
[librecmc/linux-libre.git] / drivers / staging / media / atomisp / pci / atomisp2 / css2400 / sh_css_mipi.c
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 uint32_t ref_count_mipi_allocation[N_CSI_PORTS]; /* Initialized in mipi_init */
34 #endif
35
36 enum ia_css_err
37 ia_css_mipi_frame_specify(const unsigned int size_mem_words,
38                                 const bool contiguous)
39 {
40         enum ia_css_err err = IA_CSS_SUCCESS;
41
42         my_css.size_mem_words = size_mem_words;
43         (void)contiguous;
44
45         return err;
46 }
47
48 #ifdef ISP2401
49 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
50 /*
51  * Check if a source port or TPG/PRBS ID is valid
52  */
53 static bool ia_css_mipi_is_source_port_valid(struct ia_css_pipe *pipe,
54                                                 unsigned int *pport)
55 {
56         bool ret = true;
57         unsigned int port = 0;
58         unsigned int max_ports = 0;
59
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;
64                 break;
65         case IA_CSS_INPUT_MODE_TPG:
66                 port = (unsigned int) pipe->stream->config.source.tpg.id;
67                 max_ports = N_CSS_TPG_IDS;
68                 break;
69         case IA_CSS_INPUT_MODE_PRBS:
70                 port = (unsigned int) pipe->stream->config.source.prbs.id;
71                 max_ports = N_CSS_PRBS_IDS;
72                 break;
73         default:
74                 assert(false);
75                 ret = false;
76                 break;
77         }
78
79         if (ret) {
80                 assert(port < max_ports);
81
82                 if (port >= max_ports)
83                         ret = false;
84         }
85
86         *pport = port;
87
88         return ret;
89 }
90 #endif
91
92 #endif
93 /* Assumptions:
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
101  *  etc.).
102  * Result is given in DDR mem words, 32B or 256 bits
103  */
104 enum ia_css_err
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)
111 {
112         enum ia_css_err err = IA_CSS_SUCCESS;
113
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;
126
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.
131          */
132         width_padded += (2 * ISP_VEC_NELEMS);
133 #endif
134
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);
137
138         switch (format) {
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.
153                  */
154                 bits_per_pixel = 10;
155 #else
156                 bits_per_pixel = 16;
157 #endif
158                 break;
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;
175
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 */
179         default:
180                 return IA_CSS_ERR_INVALID_ARGUMENTS;
181         }
182
183         odd_line_bytes = (width_padded * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */
184
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) */
190         } else {
191                 even_line_bytes = odd_line_bytes;
192         }
193
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
198         *               ...
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
202         *               ...
203         *               data    data    0       0       0       0       0       0
204         *  ...
205         *  last         (EOL)   EOF     0       0       0       0       0       0
206         *
207         *  Embedded lines are regular lines stored before the first and after
208         *  payload lines.
209         */
210
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));
219
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 */
225
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) */
231                                 mem_words_for_EOF;
232
233         *size_mem_words = mem_words; /* ceil(words/8); mem word is 32B = 8words. */
234         /* Check if the above is still needed. */
235
236         IA_CSS_LEAVE_ERR(err);
237         return err;
238 }
239
240 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
241 enum ia_css_err
242 ia_css_mipi_frame_enable_check_on_size(const enum ia_css_csi2_port port,
243                                 const unsigned int      size_mem_words)
244 {
245         uint32_t idx;
246
247         enum ia_css_err err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
248
249         OP___assert(port < N_CSI_PORTS);
250         OP___assert(size_mem_words != 0);
251
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 */
255         }
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;
259         }
260
261         return err;
262 }
263 #endif
264
265 void
266 mipi_init(void)
267 {
268 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
269         unsigned int i;
270
271         for (i = 0; i < N_CSI_PORTS; i++)
272                 ref_count_mipi_allocation[i] = 0;
273 #endif
274 }
275
276 enum ia_css_err
277 calculate_mipi_buff_size(
278                 struct ia_css_stream_config *stream_cfg,
279                 unsigned int *size_mem_words)
280 {
281 #if !defined(USE_INPUT_SYSTEM_VERSION_2401)
282         enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
283         (void)stream_cfg;
284         (void)size_mem_words;
285 #else
286         unsigned int width;
287         unsigned int height;
288         enum ia_css_stream_format format;
289         bool pack_raw_pixels;
290
291         unsigned int width_padded;
292         unsigned int bits_per_pixel = 0;
293
294         unsigned int even_line_bytes = 0;
295         unsigned int odd_line_bytes = 0;
296
297         unsigned int words_per_odd_line = 0;
298         unsigned int words_per_even_line = 0;
299
300         unsigned int mem_words_per_even_line = 0;
301         unsigned int mem_words_per_odd_line = 0;
302
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;
306
307         /**
308 #ifndef ISP2401
309          * zhengjie.lu@intel.com
310          *
311 #endif
312          * NOTE
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.
317          *
318          *   Question here is that: which one shall be used?
319          */
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;
324         /** end of NOTE */
325
326         /**
327 #ifndef ISP2401
328          * zhengjie.lu@intel.com
329          *
330 #endif
331          * NOTE
332          * - The following code is derived from the
333          *   existing code "ia_css_mipi_frame_calculate_size()".
334          *
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"?
338          */
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.
342          */
343         width_padded = width + (2 * ISP_VEC_NELEMS);
344         /** end of NOTE */
345
346         IA_CSS_ENTER("padded_width=%d, height=%d, format=%d\n",
347                      width_padded, height, format);
348
349         bits_per_pixel = sh_css_stream_format_2_bits_per_subpixel(format);
350         bits_per_pixel =
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;
354
355         odd_line_bytes = (width_padded * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */
356
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) */
361         } else {
362                 even_line_bytes = odd_line_bytes;
363         }
364
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;
368
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;
372
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;
376
377         *size_mem_words = mem_words_per_buff;
378
379         IA_CSS_LEAVE_ERR(err);
380 #endif
381         return err;
382 }
383
384 enum ia_css_err
385 allocate_mipi_frames(struct ia_css_pipe *pipe, struct ia_css_stream_info *info)
386 {
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;
389 #ifndef ISP2401
390         unsigned int port;
391 #else
392         unsigned int port = 0;
393 #endif
394         struct ia_css_frame_info mipi_intermediate_info;
395
396         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
397                 "allocate_mipi_frames(%p) enter:\n", pipe);
398
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",
404                         pipe);
405                 return IA_CSS_ERR_INVALID_ARGUMENTS;
406         }
407
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",
412                         pipe);
413                 return IA_CSS_SUCCESS;
414         }
415
416 #endif
417 #ifndef ISP2401
418         if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
419 #else
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)) {
423 #endif
424                 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
425                         "allocate_mipi_frames(%p) exit: no buffers needed for pipe mode.\n",
426                         pipe);
427                 return IA_CSS_SUCCESS; /* AM TODO: Check  */
428         }
429
430 #ifndef ISP2401
431         port = (unsigned int) pipe->stream->config.source.port.port;
432         assert(port < N_CSI_PORTS);
433         if (port >= N_CSI_PORTS) {
434 #else
435         if (!ia_css_mipi_is_source_port_valid(pipe, &port)) {
436 #endif
437                 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
438                         "allocate_mipi_frames(%p) exit: error: port is not correct (port=%d).\n",
439                         pipe, port);
440                 return IA_CSS_ERR_INTERNAL_ERROR;
441         }
442
443 #ifdef USE_INPUT_SYSTEM_VERSION_2401
444         err = calculate_mipi_buff_size(
445                         &(pipe->stream->config),
446                         &(my_css.mipi_frame_size[port]));
447 #endif
448
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",
453                         pipe, port);
454                 return IA_CSS_SUCCESS;
455         }
456 #else
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.
461          */
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",
466                         pipe, port);
467                 return IA_CSS_SUCCESS;
468         }
469 #endif
470
471         ref_count_mipi_allocation[port]++;
472
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;
483
484         /* AM TODO: mipi frames number should come from stream struct. */
485         my_css.num_mipi_frames[port] = NUM_MIPI_FRAMES_PER_STREAM;
486
487         /* Incremental allocation (per stream), not for all streams at once. */
488         { /* limit the scope of i,j */
489                 unsigned 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;
495                         }
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,
502                                         false);
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;
508                                                 }
509                                         }
510                                         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
511                                                 "allocate_mipi_frames(%p, %d) exit: error: allocation failed.\n",
512                                                 pipe, port);
513                                         return err;
514                                 }
515                         }
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;
521                                 }
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",
529                                                         pipe, port);
530                                                 return err;
531                                         }
532                                 }
533                         }
534                 }
535         }
536         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
537                 "allocate_mipi_frames(%p) exit:\n", pipe);
538
539         return err;
540 #else
541         (void)pipe;
542         (void)info;
543         return IA_CSS_SUCCESS;
544 #endif
545 }
546
547 enum ia_css_err
548 free_mipi_frames(struct ia_css_pipe *pipe)
549 {
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;
552 #ifndef ISP2401
553         unsigned int port;
554 #else
555         unsigned int port = 0;
556 #endif
557         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
558                 "free_mipi_frames(%p) enter:\n", pipe);
559
560         /* assert(pipe != NULL); TEMP: TODO: Should be assert only. */
561         if (pipe != NULL) {
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",
566                                 pipe);
567                         return IA_CSS_ERR_INVALID_ARGUMENTS;
568                 }
569
570 #ifndef ISP2401
571                 if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
572 #else
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)) {
576 #endif
577                         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
578                                 "free_mipi_frames(%p) exit: error: wrong mode.\n",
579                                 pipe);
580                         return err;
581                 }
582
583 #ifndef ISP2401
584                 port = (unsigned int) pipe->stream->config.source.port.port;
585                 assert(port < N_CSI_PORTS);
586                 if (port >= N_CSI_PORTS) {
587 #else
588                 if (!ia_css_mipi_is_source_port_valid(pipe, &port)) {
589 #endif
590                         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
591 #ifndef ISP2401
592                                 "free_mipi_frames(%p, %d) exit: error: pipe port is not correct.\n",
593 #else
594                                 "free_mipi_frames(%p) exit: error: pipe port is not correct (port=%d).\n",
595 #endif
596                                 pipe, port);
597                         return err;
598                 }
599 #ifdef ISP2401
600
601 #endif
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]);
609                                 return err;
610                         }
611 #endif
612
613                         ref_count_mipi_allocation[port]--;
614
615                         if (ref_count_mipi_allocation[port] == 0) {
616                                 /* no streams are using this buffer, so free it */
617                                 unsigned int i;
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;
624                                         }
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;
628                                         }
629                                 }
630
631                                 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
632                                         "free_mipi_frames(%p) exit (deallocated).\n", pipe);
633                         }
634 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
635                         else {
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.
640                                  */
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",
643                                         pipe, port);
644                         }
645 #endif
646                 }
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++) {
650                         unsigned int i;
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;
657                                 }
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;
661                                 }
662                         }
663                         ref_count_mipi_allocation[port] = 0;
664                 }
665         }
666 #else
667         (void)pipe;
668 #endif
669         return IA_CSS_SUCCESS;
670 }
671
672 enum ia_css_err
673 send_mipi_frames(struct ia_css_pipe *pipe)
674 {
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;
677         unsigned int i;
678 #ifndef ISP2401
679         unsigned int port;
680 #else
681         unsigned int port = 0;
682 #endif
683
684         IA_CSS_ENTER_PRIVATE("pipe=%p", pipe);
685
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;
691         }
692
693         /* multi stream video needs mipi buffers */
694         /* nothing to be done in other cases. */
695 #ifndef ISP2401
696         if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
697 #else
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)) {
701 #endif
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. */
705         }
706
707 #ifndef ISP2401
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);
712 #else
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);
715 #endif
716                 return err;
717         }
718
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]);
726         }
727         sh_css_update_host2sp_num_mipi_frames(my_css.num_mipi_frames[port]);
728
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");
736                 return err;
737         }
738
739         ia_css_bufq_enqueue_psys_event(
740                         IA_CSS_PSYS_SW_EVENT_MIPI_BUFFERS_READY,
741                         (uint8_t)port,
742                         (uint8_t)my_css.num_mipi_frames[port],
743                         0 /* not used */);
744         IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
745 #else
746         (void)pipe;
747 #endif
748         return IA_CSS_SUCCESS;
749 }