1
2
3
4
5
6
7
8
9
10
11
12
13
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"
31#include "sw_event_global.h"
32
33static u32
34ref_count_mipi_allocation[N_CSI_PORTS];
35
36
37
38
39static bool ia_css_mipi_is_source_port_valid(struct ia_css_pipe *pipe,
40 unsigned int *pport)
41{
42 bool ret = true;
43 unsigned int port = 0;
44 unsigned int max_ports = 0;
45
46 switch (pipe->stream->config.mode) {
47 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
48 port = (unsigned int)pipe->stream->config.source.port.port;
49 max_ports = N_CSI_PORTS;
50 break;
51 case IA_CSS_INPUT_MODE_TPG:
52 port = (unsigned int)pipe->stream->config.source.tpg.id;
53 max_ports = N_CSS_TPG_IDS;
54 break;
55 case IA_CSS_INPUT_MODE_PRBS:
56 port = (unsigned int)pipe->stream->config.source.prbs.id;
57 max_ports = N_CSS_PRBS_IDS;
58 break;
59 default:
60 assert(false);
61 ret = false;
62 break;
63 }
64
65 if (ret) {
66 assert(port < max_ports);
67
68 if (port >= max_ports)
69 ret = false;
70 }
71
72 *pport = port;
73
74 return ret;
75}
76
77
78
79
80
81
82
83
84
85
86
87
88int
89ia_css_mipi_frame_calculate_size(const unsigned int width,
90 const unsigned int height,
91 const enum atomisp_input_format format,
92 const bool hasSOLandEOL,
93 const unsigned int embedded_data_size_words,
94 unsigned int *size_mem_words)
95{
96 int err = 0;
97
98 unsigned int bits_per_pixel = 0;
99 unsigned int even_line_bytes = 0;
100 unsigned int odd_line_bytes = 0;
101 unsigned int words_per_odd_line = 0;
102 unsigned int words_for_first_line = 0;
103 unsigned int words_per_even_line = 0;
104 unsigned int mem_words_per_even_line = 0;
105 unsigned int mem_words_per_odd_line = 0;
106 unsigned int mem_words_for_first_line = 0;
107 unsigned int mem_words_for_EOF = 0;
108 unsigned int mem_words = 0;
109 unsigned int width_padded = width;
110
111#if defined(ISP2401)
112
113
114
115
116 width_padded += (2 * ISP_VEC_NELEMS);
117#endif
118
119 IA_CSS_ENTER("padded_width=%d, height=%d, format=%d, hasSOLandEOL=%d, embedded_data_size_words=%d\n",
120 width_padded, height, format, hasSOLandEOL, embedded_data_size_words);
121
122 switch (format) {
123 case ATOMISP_INPUT_FORMAT_RAW_6:
124 bits_per_pixel = 6;
125 break;
126 case ATOMISP_INPUT_FORMAT_RAW_7:
127 bits_per_pixel = 7;
128 break;
129 case ATOMISP_INPUT_FORMAT_RAW_8:
130 case ATOMISP_INPUT_FORMAT_BINARY_8:
131 case ATOMISP_INPUT_FORMAT_YUV420_8:
132 bits_per_pixel = 8;
133 break;
134 case ATOMISP_INPUT_FORMAT_YUV420_10:
135 case ATOMISP_INPUT_FORMAT_RAW_10:
136#if !defined(HAS_NO_PACKED_RAW_PIXELS)
137
138
139
140
141 bits_per_pixel = 10;
142#else
143 bits_per_pixel = 16;
144#endif
145 break;
146 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
147 case ATOMISP_INPUT_FORMAT_RAW_12:
148 bits_per_pixel = 12;
149 break;
150 case ATOMISP_INPUT_FORMAT_RAW_14:
151 bits_per_pixel = 14;
152 break;
153 case ATOMISP_INPUT_FORMAT_RGB_444:
154 case ATOMISP_INPUT_FORMAT_RGB_555:
155 case ATOMISP_INPUT_FORMAT_RGB_565:
156 case ATOMISP_INPUT_FORMAT_YUV422_8:
157 bits_per_pixel = 16;
158 break;
159 case ATOMISP_INPUT_FORMAT_RGB_666:
160 bits_per_pixel = 18;
161 break;
162 case ATOMISP_INPUT_FORMAT_YUV422_10:
163 bits_per_pixel = 20;
164 break;
165 case ATOMISP_INPUT_FORMAT_RGB_888:
166 bits_per_pixel = 24;
167 break;
168
169 case ATOMISP_INPUT_FORMAT_YUV420_16:
170 case ATOMISP_INPUT_FORMAT_YUV422_16:
171 case ATOMISP_INPUT_FORMAT_RAW_16:
172 default:
173 return -EINVAL;
174 }
175
176 odd_line_bytes = (width_padded * bits_per_pixel + 7) >> 3;
177
178
179 if (format == ATOMISP_INPUT_FORMAT_YUV420_8
180 || format == ATOMISP_INPUT_FORMAT_YUV420_10
181 || format == ATOMISP_INPUT_FORMAT_YUV420_16) {
182 even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >>
183 3;
184 } else {
185 even_line_bytes = odd_line_bytes;
186 }
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205 words_per_odd_line = (odd_line_bytes + 3) >> 2;
206
207 words_per_even_line = (even_line_bytes + 3) >> 2;
208 words_for_first_line = words_per_odd_line + 2 + (hasSOLandEOL ? 1 : 0);
209
210 words_per_odd_line += (1 + (hasSOLandEOL ? 2 : 0));
211
212 words_per_even_line += (1 + (hasSOLandEOL ? 2 : 0));
213
214 mem_words_per_odd_line = (words_per_odd_line + 7) >> 3;
215
216 mem_words_for_first_line = (words_for_first_line + 7) >> 3;
217 mem_words_per_even_line = (words_per_even_line + 7) >> 3;
218 mem_words_for_EOF = 1;
219
220 mem_words = ((embedded_data_size_words + 7) >> 3) +
221 mem_words_for_first_line +
222 (((height + 1) >> 1) - 1) * mem_words_per_odd_line +
223
224 (height >> 1) * mem_words_per_even_line +
225 mem_words_for_EOF;
226
227 *size_mem_words = mem_words;
228
229
230 IA_CSS_LEAVE_ERR(err);
231 return err;
232}
233
234#if !defined(ISP2401)
235int
236ia_css_mipi_frame_enable_check_on_size(const enum mipi_port_id port,
237 const unsigned int size_mem_words)
238{
239 u32 idx;
240
241 int err = -EBUSY;
242
243 OP___assert(port < N_CSI_PORTS);
244 OP___assert(size_mem_words != 0);
245
246 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT &&
247 my_css.mipi_sizes_for_check[port][idx] != 0;
248 idx++) {
249 }
250 if (idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT) {
251 my_css.mipi_sizes_for_check[port][idx] = size_mem_words;
252 err = 0;
253 }
254
255 return err;
256}
257#endif
258
259void
260mipi_init(void)
261{
262 unsigned int i;
263
264 for (i = 0; i < N_CSI_PORTS; i++)
265 ref_count_mipi_allocation[i] = 0;
266}
267
268int
269calculate_mipi_buff_size(
270 struct ia_css_stream_config *stream_cfg,
271 unsigned int *size_mem_words)
272{
273#if !defined(ISP2401)
274 int err = -EINVAL;
275 (void)stream_cfg;
276 (void)size_mem_words;
277#else
278 unsigned int width;
279 unsigned int height;
280 enum atomisp_input_format format;
281 bool pack_raw_pixels;
282
283 unsigned int width_padded;
284 unsigned int bits_per_pixel = 0;
285
286 unsigned int even_line_bytes = 0;
287 unsigned int odd_line_bytes = 0;
288
289 unsigned int words_per_odd_line = 0;
290 unsigned int words_per_even_line = 0;
291
292 unsigned int mem_words_per_even_line = 0;
293 unsigned int mem_words_per_odd_line = 0;
294
295 unsigned int mem_words_per_buff_line = 0;
296 unsigned int mem_words_per_buff = 0;
297 int err = 0;
298
299
300
301
302
303
304
305
306
307
308
309
310 width = stream_cfg->input_config.input_res.width;
311 height = stream_cfg->input_config.input_res.height;
312 format = stream_cfg->input_config.format;
313 pack_raw_pixels = stream_cfg->pack_raw_pixels;
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331 width_padded = width + (2 * ISP_VEC_NELEMS);
332
333
334 IA_CSS_ENTER("padded_width=%d, height=%d, format=%d\n",
335 width_padded, height, format);
336
337 bits_per_pixel = sh_css_stream_format_2_bits_per_subpixel(format);
338 bits_per_pixel =
339 (format == ATOMISP_INPUT_FORMAT_RAW_10 && pack_raw_pixels) ? bits_per_pixel : 16;
340 if (bits_per_pixel == 0)
341 return -EINVAL;
342
343 odd_line_bytes = (width_padded * bits_per_pixel + 7) >> 3;
344
345
346 if (format == ATOMISP_INPUT_FORMAT_YUV420_8
347 || format == ATOMISP_INPUT_FORMAT_YUV420_10) {
348 even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >>
349 3;
350 } else {
351 even_line_bytes = odd_line_bytes;
352 }
353
354 words_per_odd_line = (odd_line_bytes + 3) >> 2;
355
356 words_per_even_line = (even_line_bytes + 3) >> 2;
357
358 mem_words_per_odd_line = (words_per_odd_line + 7) >> 3;
359
360 mem_words_per_even_line = (words_per_even_line + 7) >> 3;
361
362 mem_words_per_buff_line =
363 (mem_words_per_odd_line > mem_words_per_even_line) ? mem_words_per_odd_line : mem_words_per_even_line;
364 mem_words_per_buff = mem_words_per_buff_line * height;
365
366 *size_mem_words = mem_words_per_buff;
367
368 IA_CSS_LEAVE_ERR(err);
369#endif
370 return err;
371}
372
373static bool buffers_needed(struct ia_css_pipe *pipe)
374{
375 if (!IS_ISP2401) {
376 if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
377 return false;
378 else
379 return true;
380 }
381
382 if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR ||
383 pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
384 pipe->stream->config.mode == IA_CSS_INPUT_MODE_PRBS)
385 return false;
386
387 return true;
388}
389
390int
391allocate_mipi_frames(struct ia_css_pipe *pipe,
392 struct ia_css_stream_info *info)
393{
394 int err = -EINVAL;
395 unsigned int port;
396
397 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
398 "allocate_mipi_frames(%p) enter:\n", pipe);
399
400 assert(pipe);
401 assert(pipe->stream);
402 if ((!pipe) || (!pipe->stream)) {
403 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
404 "allocate_mipi_frames(%p) exit: pipe or stream is null.\n",
405 pipe);
406 return -EINVAL;
407 }
408
409#ifdef ISP2401
410 if (pipe->stream->config.online) {
411 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
412 "allocate_mipi_frames(%p) exit: no buffers needed for 2401 pipe mode.\n",
413 pipe);
414 return 0;
415 }
416
417#endif
418
419 if (!buffers_needed(pipe)) {
420 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
421 "allocate_mipi_frames(%p) exit: no buffers needed for pipe mode.\n",
422 pipe);
423 return 0;
424 }
425
426 if (!IS_ISP2401)
427 port = (unsigned int)pipe->stream->config.source.port.port;
428 else
429 err = ia_css_mipi_is_source_port_valid(pipe, &port);
430
431 assert(port < N_CSI_PORTS);
432
433 if (port >= N_CSI_PORTS || err) {
434 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
435 "allocate_mipi_frames(%p) exit: error: port is not correct (port=%d).\n",
436 pipe, port);
437 return -EINVAL;
438 }
439
440#ifdef ISP2401
441 err = calculate_mipi_buff_size(
442 &pipe->stream->config,
443 &my_css.mipi_frame_size[port]);
444#endif
445
446#if !defined(ISP2401)
447 if (ref_count_mipi_allocation[port] != 0) {
448 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
449 "allocate_mipi_frames(%p) exit: already allocated for this port (port=%d).\n",
450 pipe, port);
451 return 0;
452 }
453#else
454
455
456
457
458
459 if (ref_count_mipi_allocation[port] != 0) {
460 ref_count_mipi_allocation[port]++;
461 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
462 "allocate_mipi_frames(%p) leave: nothing to do, already allocated for this port (port=%d).\n",
463 pipe, port);
464 return 0;
465 }
466#endif
467
468 ref_count_mipi_allocation[port]++;
469
470
471 my_css.num_mipi_frames[port] = NUM_MIPI_FRAMES_PER_STREAM;
472
473
474 {
475 unsigned int i, j;
476
477 for (i = 0; i < my_css.num_mipi_frames[port]; i++) {
478
479 if (my_css.mipi_frames[port][i]) {
480 ia_css_frame_free(my_css.mipi_frames[port][i]);
481 my_css.mipi_frames[port][i] = NULL;
482 }
483
484 if (i < my_css.num_mipi_frames[port]) {
485
486 err = ia_css_frame_allocate_with_buffer_size(
487 &my_css.mipi_frames[port][i],
488 my_css.mipi_frame_size[port] * HIVE_ISP_DDR_WORD_BYTES,
489 false);
490 if (err) {
491 for (j = 0; j < i; j++) {
492 if (my_css.mipi_frames[port][j]) {
493 ia_css_frame_free(my_css.mipi_frames[port][j]);
494 my_css.mipi_frames[port][j] = NULL;
495 }
496 }
497 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
498 "allocate_mipi_frames(%p, %d) exit: error: allocation failed.\n",
499 pipe, port);
500 return err;
501 }
502 }
503 if (info->metadata_info.size > 0) {
504
505 if (my_css.mipi_metadata[port][i]) {
506 ia_css_metadata_free(my_css.mipi_metadata[port][i]);
507 my_css.mipi_metadata[port][i] = NULL;
508 }
509
510 if (i < my_css.num_mipi_frames[port]) {
511
512 my_css.mipi_metadata[port][i] = ia_css_metadata_allocate(&info->metadata_info);
513 if (!my_css.mipi_metadata[port][i]) {
514 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
515 "allocate_mipi_metadata(%p, %d) failed.\n",
516 pipe, port);
517 return err;
518 }
519 }
520 }
521 }
522 }
523 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
524 "allocate_mipi_frames(%p) exit:\n", pipe);
525
526 return err;
527}
528
529int
530free_mipi_frames(struct ia_css_pipe *pipe)
531{
532 int err = -EINVAL;
533 unsigned int port;
534
535 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
536 "free_mipi_frames(%p) enter:\n", pipe);
537
538
539 if (pipe) {
540 assert(pipe->stream);
541 if ((!pipe) || (!pipe->stream)) {
542 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
543 "free_mipi_frames(%p) exit: error: pipe or stream is null.\n",
544 pipe);
545 return -EINVAL;
546 }
547
548 if (!buffers_needed(pipe)) {
549 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
550 "free_mipi_frames(%p) exit: error: wrong mode.\n",
551 pipe);
552 return err;
553 }
554
555 if (!IS_ISP2401)
556 port = (unsigned int)pipe->stream->config.source.port.port;
557 else
558 err = ia_css_mipi_is_source_port_valid(pipe, &port);
559
560 assert(port < N_CSI_PORTS);
561
562 if (port >= N_CSI_PORTS || err) {
563 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
564 "free_mipi_frames(%p, %d) exit: error: pipe port is not correct.\n",
565 pipe, port);
566 return err;
567 }
568
569 if (ref_count_mipi_allocation[port] > 0) {
570#if !defined(ISP2401)
571 assert(ref_count_mipi_allocation[port] == 1);
572 if (ref_count_mipi_allocation[port] != 1) {
573 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
574 "free_mipi_frames(%p) exit: error: wrong ref_count (ref_count=%d).\n",
575 pipe, ref_count_mipi_allocation[port]);
576 return err;
577 }
578#endif
579
580 ref_count_mipi_allocation[port]--;
581
582 if (ref_count_mipi_allocation[port] == 0) {
583
584 unsigned int i;
585
586 for (i = 0; i < my_css.num_mipi_frames[port]; i++) {
587 if (my_css.mipi_frames[port][i]) {
588 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
589 "free_mipi_frames(port=%d, num=%d).\n", port, i);
590 ia_css_frame_free(my_css.mipi_frames[port][i]);
591 my_css.mipi_frames[port][i] = NULL;
592 }
593 if (my_css.mipi_metadata[port][i]) {
594 ia_css_metadata_free(my_css.mipi_metadata[port][i]);
595 my_css.mipi_metadata[port][i] = NULL;
596 }
597 }
598
599 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
600 "free_mipi_frames(%p) exit (deallocated).\n", pipe);
601 }
602#if defined(ISP2401)
603 else {
604
605
606
607
608
609 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
610 "free_mipi_frames(%p) leave: nothing to do, other streams still use this port (port=%d).\n",
611 pipe, port);
612 }
613#endif
614 }
615 } else {
616
617 for (port = CSI_PORT0_ID; port < N_CSI_PORTS; port++) {
618 unsigned int i;
619
620 for (i = 0; i < my_css.num_mipi_frames[port]; i++) {
621 if (my_css.mipi_frames[port][i]) {
622 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
623 "free_mipi_frames(port=%d, num=%d).\n", port, i);
624 ia_css_frame_free(my_css.mipi_frames[port][i]);
625 my_css.mipi_frames[port][i] = NULL;
626 }
627 if (my_css.mipi_metadata[port][i]) {
628 ia_css_metadata_free(my_css.mipi_metadata[port][i]);
629 my_css.mipi_metadata[port][i] = NULL;
630 }
631 }
632 ref_count_mipi_allocation[port] = 0;
633 }
634 }
635 return 0;
636}
637
638int
639send_mipi_frames(struct ia_css_pipe *pipe)
640{
641 int err = -EINVAL;
642 unsigned int i;
643#ifndef ISP2401
644 unsigned int port;
645#else
646 unsigned int port = 0;
647#endif
648
649 IA_CSS_ENTER_PRIVATE("pipe=%p", pipe);
650
651 assert(pipe);
652 assert(pipe->stream);
653 if (!pipe || !pipe->stream) {
654 IA_CSS_ERROR("pipe or stream is null");
655 return -EINVAL;
656 }
657
658
659
660 if (!buffers_needed(pipe)) {
661 IA_CSS_LOG("nothing to be done for this mode");
662 return 0;
663
664 }
665
666 if (!IS_ISP2401)
667 port = (unsigned int)pipe->stream->config.source.port.port;
668 else
669 err = ia_css_mipi_is_source_port_valid(pipe, &port);
670
671 assert(port < N_CSI_PORTS);
672
673 if (port >= N_CSI_PORTS || err) {
674 IA_CSS_ERROR("send_mipi_frames(%p) exit: invalid port specified (port=%d).\n",
675 pipe, port);
676 return err;
677 }
678
679
680 for (i = 0; i < my_css.num_mipi_frames[port]; i++) {
681
682 sh_css_update_host2sp_mipi_frame(port * NUM_MIPI_FRAMES_PER_STREAM + i,
683 my_css.mipi_frames[port][i]);
684 sh_css_update_host2sp_mipi_metadata(port * NUM_MIPI_FRAMES_PER_STREAM + i,
685 my_css.mipi_metadata[port][i]);
686 }
687 sh_css_update_host2sp_num_mipi_frames(my_css.num_mipi_frames[port]);
688
689
690
691
692
693 if (!sh_css_sp_is_running()) {
694
695 IA_CSS_ERROR("sp is not running");
696 return err;
697 }
698
699 ia_css_bufq_enqueue_psys_event(
700 IA_CSS_PSYS_SW_EVENT_MIPI_BUFFERS_READY,
701 (uint8_t)port,
702 (uint8_t)my_css.num_mipi_frames[port],
703 0 );
704 IA_CSS_LEAVE_ERR_PRIVATE(0);
705 return 0;
706}
707