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
17 Support for Intel Camera Imaging ISP subsystem.
18 Copyright (c) 2010 - 2015, Intel Corporation.
20 This program is free software; you can redistribute it and/or modify it
21 under the terms and conditions of the GNU General Public License,
22 version 2, as published by the Free Software Foundation.
24 This program is distributed in the hope it will be useful, but WITHOUT
25 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
31 #include "platform_support.h"
33 #include "ia_css_inputfifo.h"
35 #include "device_access.h"
39 #define __INLINE_ISP__
41 #define __INLINE_IRQ__
43 #define __INLINE_FIFO_MONITOR__
44 #include "fifo_monitor.h"
46 #define __INLINE_EVENT__
47 #include "event_fifo.h"
50 #if !defined(HAS_NO_INPUT_SYSTEM)
51 #include "input_system.h" /* MIPI_PREDICTOR_NONE,... */
54 #include "assert_support.h"
56 /* System independent */
57 #include "sh_css_internal.h"
58 #if !defined(HAS_NO_INPUT_SYSTEM)
59 #include "ia_css_isys.h"
62 #define HBLANK_CYCLES (187)
63 #define MARKER_CYCLES (6)
65 #if !defined(HAS_NO_INPUT_SYSTEM)
66 #include <hive_isp_css_streaming_to_mipi_types_hrt.h>
69 /* The data type is used to send special cases:
70 * yuv420: odd lines (1, 3 etc) are twice as wide as even
71 * lines (0, 2, 4 etc).
72 * rgb: for two pixels per clock, the R and B values are sent
73 * to output_0 while only G is sent to output_1. This means
74 * that output_1 only gets half the number of values of output_0.
75 * WARNING: This type should also be used for Legacy YUV420.
76 * regular: used for all other data types (RAW, YUV422, etc)
78 enum inputfifo_mipi_data_type {
79 inputfifo_mipi_data_type_regular,
80 inputfifo_mipi_data_type_yuv420,
81 inputfifo_mipi_data_type_yuv420_legacy,
82 inputfifo_mipi_data_type_rgb,
84 #if !defined(HAS_NO_INPUT_SYSTEM)
85 static unsigned int inputfifo_curr_ch_id, inputfifo_curr_fmt_type;
87 struct inputfifo_instance {
89 enum ia_css_stream_format input_format;
92 unsigned int hblank_cycles;
93 unsigned int marker_cycles;
94 unsigned int fmt_type;
95 enum inputfifo_mipi_data_type type;
97 #if !defined(HAS_NO_INPUT_SYSTEM)
99 * Maintain a basic streaming to Mipi administration with ch_id as index
100 * ch_id maps on the "Mipi virtual channel ID" and can have value 0..3
102 #define INPUTFIFO_NR_OF_S2M_CHANNELS (4)
103 static struct inputfifo_instance
104 inputfifo_inst_admin[INPUTFIFO_NR_OF_S2M_CHANNELS];
106 /* Streaming to MIPI */
107 static unsigned inputfifo_wrap_marker(
108 /* STORAGE_CLASS_INLINE unsigned inputfifo_wrap_marker( */
112 (inputfifo_curr_ch_id << HIVE_STR_TO_MIPI_CH_ID_LSB) |
113 (inputfifo_curr_fmt_type << _HIVE_STR_TO_MIPI_FMT_TYPE_LSB);
116 STORAGE_CLASS_INLINE void
117 _sh_css_fifo_snd(unsigned token)
119 while (!can_event_send_token(STR2MIPI_EVENT_ID))
121 event_send_token(STR2MIPI_EVENT_ID, token);
125 static void inputfifo_send_data_a(
126 /* STORAGE_CLASS_INLINE void inputfifo_send_data_a( */
129 unsigned int token = (1 << HIVE_STR_TO_MIPI_VALID_A_BIT) |
130 (data << HIVE_STR_TO_MIPI_DATA_A_LSB);
131 _sh_css_fifo_snd(token);
137 static void inputfifo_send_data_b(
138 /* STORAGE_CLASS_INLINE void inputfifo_send_data_b( */
141 unsigned int token = (1 << HIVE_STR_TO_MIPI_VALID_B_BIT) |
142 (data << _HIVE_STR_TO_MIPI_DATA_B_LSB);
143 _sh_css_fifo_snd(token);
149 static void inputfifo_send_data(
150 /* STORAGE_CLASS_INLINE void inputfifo_send_data( */
154 unsigned int token = ((1 << HIVE_STR_TO_MIPI_VALID_A_BIT) |
155 (1 << HIVE_STR_TO_MIPI_VALID_B_BIT) |
156 (a << HIVE_STR_TO_MIPI_DATA_A_LSB) |
157 (b << _HIVE_STR_TO_MIPI_DATA_B_LSB));
158 _sh_css_fifo_snd(token);
164 static void inputfifo_send_sol(void)
165 /* STORAGE_CLASS_INLINE void inputfifo_send_sol(void) */
167 hrt_data token = inputfifo_wrap_marker(
168 1 << HIVE_STR_TO_MIPI_SOL_BIT);
170 _sh_css_fifo_snd(token);
176 static void inputfifo_send_eol(void)
177 /* STORAGE_CLASS_INLINE void inputfifo_send_eol(void) */
179 hrt_data token = inputfifo_wrap_marker(
180 1 << HIVE_STR_TO_MIPI_EOL_BIT);
181 _sh_css_fifo_snd(token);
187 static void inputfifo_send_sof(void)
188 /* STORAGE_CLASS_INLINE void inputfifo_send_sof(void) */
190 hrt_data token = inputfifo_wrap_marker(
191 1 << HIVE_STR_TO_MIPI_SOF_BIT);
193 _sh_css_fifo_snd(token);
199 static void inputfifo_send_eof(void)
200 /* STORAGE_CLASS_INLINE void inputfifo_send_eof(void) */
202 hrt_data token = inputfifo_wrap_marker(
203 1 << HIVE_STR_TO_MIPI_EOF_BIT);
204 _sh_css_fifo_snd(token);
211 static void inputfifo_send_ch_id(
212 /* STORAGE_CLASS_INLINE void inputfifo_send_ch_id( */
216 inputfifo_curr_ch_id = ch_id & _HIVE_ISP_CH_ID_MASK;
217 /* we send an zero marker, this will wrap the ch_id and
218 * fmt_type automatically.
220 token = inputfifo_wrap_marker(0);
221 _sh_css_fifo_snd(token);
225 static void inputfifo_send_fmt_type(
226 /* STORAGE_CLASS_INLINE void inputfifo_send_fmt_type( */
227 unsigned int fmt_type)
230 inputfifo_curr_fmt_type = fmt_type & _HIVE_ISP_FMT_TYPE_MASK;
231 /* we send an zero marker, this will wrap the ch_id and
232 * fmt_type automatically.
234 token = inputfifo_wrap_marker(0);
235 _sh_css_fifo_snd(token);
242 static void inputfifo_send_ch_id_and_fmt_type(
243 /* STORAGE_CLASS_INLINE
244 void inputfifo_send_ch_id_and_fmt_type( */
246 unsigned int fmt_type)
249 inputfifo_curr_ch_id = ch_id & _HIVE_ISP_CH_ID_MASK;
250 inputfifo_curr_fmt_type = fmt_type & _HIVE_ISP_FMT_TYPE_MASK;
251 /* we send an zero marker, this will wrap the ch_id and
252 * fmt_type automatically.
254 token = inputfifo_wrap_marker(0);
255 _sh_css_fifo_snd(token);
261 static void inputfifo_send_empty_token(void)
262 /* STORAGE_CLASS_INLINE void inputfifo_send_empty_token(void) */
264 hrt_data token = inputfifo_wrap_marker(0);
265 _sh_css_fifo_snd(token);
271 static void inputfifo_start_frame(
272 /* STORAGE_CLASS_INLINE void inputfifo_start_frame( */
274 unsigned int fmt_type)
276 inputfifo_send_ch_id_and_fmt_type(ch_id, fmt_type);
277 inputfifo_send_sof();
283 static void inputfifo_end_frame(
284 unsigned int marker_cycles)
287 for (i = 0; i < marker_cycles; i++)
288 inputfifo_send_empty_token();
289 inputfifo_send_eof();
295 static void inputfifo_send_line2(
296 const unsigned short *data,
298 const unsigned short *data2,
300 unsigned int hblank_cycles,
301 unsigned int marker_cycles,
302 unsigned int two_ppc,
303 enum inputfifo_mipi_data_type type)
305 unsigned int i, is_rgb = 0, is_legacy = 0;
307 assert(data != NULL);
308 assert((data2 != NULL) || (width2 == 0));
309 if (type == inputfifo_mipi_data_type_rgb)
312 if (type == inputfifo_mipi_data_type_yuv420_legacy)
315 for (i = 0; i < hblank_cycles; i++)
316 inputfifo_send_empty_token();
317 inputfifo_send_sol();
318 for (i = 0; i < marker_cycles; i++)
319 inputfifo_send_empty_token();
320 for (i = 0; i < width; i++, data++) {
321 /* for RGB in two_ppc, we only actually send 2 pixels per
322 * clock in the even pixels (0, 2 etc). In the other cycles,
323 * we only send 1 pixel, to data[0].
325 unsigned int send_two_pixels = two_ppc;
326 if ((is_rgb || is_legacy) && (i % 3 == 2))
328 if (send_two_pixels) {
329 if (i + 1 == width) {
330 /* for jpg (binary) copy, this can occur
331 * if the file contains an odd number of bytes.
339 /* Additional increment because we send 2 pixels */
342 } else if (two_ppc && is_legacy) {
343 inputfifo_send_data_b(data[0]);
345 inputfifo_send_data_a(data[0]);
349 for (i = 0; i < width2; i++, data2++) {
350 /* for RGB in two_ppc, we only actually send 2 pixels per
351 * clock in the even pixels (0, 2 etc). In the other cycles,
352 * we only send 1 pixel, to data2[0].
354 unsigned int send_two_pixels = two_ppc;
355 if ((is_rgb || is_legacy) && (i % 3 == 2))
357 if (send_two_pixels) {
358 if (i + 1 == width2) {
359 /* for jpg (binary) copy, this can occur
360 * if the file contains an odd number of bytes.
368 /* Additional increment because we send 2 pixels */
371 } else if (two_ppc && is_legacy) {
372 inputfifo_send_data_b(data2[0]);
374 inputfifo_send_data_a(data2[0]);
377 for (i = 0; i < hblank_cycles; i++)
378 inputfifo_send_empty_token();
379 inputfifo_send_eol();
386 inputfifo_send_line(const unsigned short *data,
388 unsigned int hblank_cycles,
389 unsigned int marker_cycles,
390 unsigned int two_ppc,
391 enum inputfifo_mipi_data_type type)
393 assert(data != NULL);
394 inputfifo_send_line2(data, width, NULL, 0,
402 /* Send a frame of data into the input network via the GP FIFO.
404 * - data: array of 16 bit values that contains all data for the frame.
405 * - width: width of a line in number of subpixels, for yuv420 it is the
406 * number of Y components per line.
407 * - height: height of the frame in number of lines.
408 * - ch_id: channel ID.
409 * - fmt_type: format type.
410 * - hblank_cycles: length of horizontal blanking in cycles.
411 * - marker_cycles: number of empty cycles after start-of-line and before
413 * - two_ppc: boolean, describes whether to send one or two pixels per clock
414 * cycle. In this mode, we sent pixels N and N+1 in the same cycle,
415 * to IF_PRIM_A and IF_PRIM_B respectively. The caller must make
416 * sure the input data has been formatted correctly for this.
417 * For example, for RGB formats this means that unused values
419 * - yuv420: boolean, describes whether (non-legacy) yuv420 data is used. In
420 * this mode, the odd lines (1,3,5 etc) are half as long as the
421 * even lines (2,4,6 etc).
422 * Note that the first line is odd (1) and the second line is even
425 * This function does not do any reordering of pixels, the caller must make
426 * sure the data is in the righ format. Please refer to the CSS receiver
427 * documentation for details on the data formats.
430 static void inputfifo_send_frame(
431 const unsigned short *data,
435 unsigned int fmt_type,
436 unsigned int hblank_cycles,
437 unsigned int marker_cycles,
438 unsigned int two_ppc,
439 enum inputfifo_mipi_data_type type)
443 assert(data != NULL);
444 inputfifo_start_frame(ch_id, fmt_type);
446 for (i = 0; i < height; i++) {
447 if ((type == inputfifo_mipi_data_type_yuv420) &&
449 inputfifo_send_line(data, 2 * width,
455 inputfifo_send_line(data, width,
462 inputfifo_end_frame(marker_cycles);
468 static enum inputfifo_mipi_data_type inputfifo_determine_type(
469 enum ia_css_stream_format input_format)
471 enum inputfifo_mipi_data_type type;
473 type = inputfifo_mipi_data_type_regular;
474 if (input_format == IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY) {
476 inputfifo_mipi_data_type_yuv420_legacy;
477 } else if (input_format == IA_CSS_STREAM_FORMAT_YUV420_8 ||
478 input_format == IA_CSS_STREAM_FORMAT_YUV420_10 ||
479 input_format == IA_CSS_STREAM_FORMAT_YUV420_16) {
481 inputfifo_mipi_data_type_yuv420;
482 } else if (input_format >= IA_CSS_STREAM_FORMAT_RGB_444 &&
483 input_format <= IA_CSS_STREAM_FORMAT_RGB_888) {
485 inputfifo_mipi_data_type_rgb;
492 static struct inputfifo_instance *inputfifo_get_inst(
495 return &inputfifo_inst_admin[ch_id];
498 void ia_css_inputfifo_send_input_frame(
499 const unsigned short *data,
503 enum ia_css_stream_format input_format,
506 unsigned int fmt_type, hblank_cycles, marker_cycles;
507 enum inputfifo_mipi_data_type type;
509 assert(data != NULL);
510 hblank_cycles = HBLANK_CYCLES;
511 marker_cycles = MARKER_CYCLES;
512 ia_css_isys_convert_stream_format_to_mipi_format(input_format,
516 type = inputfifo_determine_type(input_format);
518 inputfifo_send_frame(data, width, height,
519 ch_id, fmt_type, hblank_cycles, marker_cycles,
525 void ia_css_inputfifo_start_frame(
527 enum ia_css_stream_format input_format,
530 struct inputfifo_instance *s2mi;
531 s2mi = inputfifo_get_inst(ch_id);
534 ia_css_isys_convert_stream_format_to_mipi_format(input_format,
537 s2mi->two_ppc = two_ppc;
538 s2mi->type = inputfifo_determine_type(input_format);
539 s2mi->hblank_cycles = HBLANK_CYCLES;
540 s2mi->marker_cycles = MARKER_CYCLES;
541 s2mi->streaming = true;
543 inputfifo_start_frame(ch_id, s2mi->fmt_type);
549 void ia_css_inputfifo_send_line(
551 const unsigned short *data,
553 const unsigned short *data2,
556 struct inputfifo_instance *s2mi;
558 assert(data != NULL);
559 assert((data2 != NULL) || (width2 == 0));
560 s2mi = inputfifo_get_inst(ch_id);
563 /* Set global variables that indicate channel_id and format_type */
564 inputfifo_curr_ch_id = (s2mi->ch_id) & _HIVE_ISP_CH_ID_MASK;
565 inputfifo_curr_fmt_type = (s2mi->fmt_type) & _HIVE_ISP_FMT_TYPE_MASK;
567 inputfifo_send_line2(data, width, data2, width2,
575 void ia_css_inputfifo_send_embedded_line(
577 enum ia_css_stream_format data_type,
578 const unsigned short *data,
581 struct inputfifo_instance *s2mi;
582 unsigned int fmt_type;
584 assert(data != NULL);
585 s2mi = inputfifo_get_inst(ch_id);
586 ia_css_isys_convert_stream_format_to_mipi_format(data_type,
587 MIPI_PREDICTOR_NONE, &fmt_type);
589 /* Set format_type for metadata line. */
590 inputfifo_curr_fmt_type = fmt_type & _HIVE_ISP_FMT_TYPE_MASK;
592 inputfifo_send_line(data, width, s2mi->hblank_cycles, s2mi->marker_cycles,
593 s2mi->two_ppc, inputfifo_mipi_data_type_regular);
597 void ia_css_inputfifo_end_frame(
600 struct inputfifo_instance *s2mi;
601 s2mi = inputfifo_get_inst(ch_id);
603 /* Set global variables that indicate channel_id and format_type */
604 inputfifo_curr_ch_id = (s2mi->ch_id) & _HIVE_ISP_CH_ID_MASK;
605 inputfifo_curr_fmt_type = (s2mi->fmt_type) & _HIVE_ISP_FMT_TYPE_MASK;
607 /* Call existing HRT function */
608 inputfifo_end_frame(s2mi->marker_cycles);
610 s2mi->streaming = false;
613 #endif /* #if !defined(HAS_NO_INPUT_SYSTEM) */