1f5fbb83fSMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0
29d4fa1a1SMauro Carvalho Chehab /*
39d4fa1a1SMauro Carvalho Chehab  * Support for Intel Camera Imaging ISP subsystem.
43c0538fbSMauro Carvalho Chehab  * Copyright (c) 2010 - 2015, Intel Corporation.
59d4fa1a1SMauro Carvalho Chehab  *
69d4fa1a1SMauro Carvalho Chehab  * This program is free software; you can redistribute it and/or modify it
79d4fa1a1SMauro Carvalho Chehab  * under the terms and conditions of the GNU General Public License,
89d4fa1a1SMauro Carvalho Chehab  * version 2, as published by the Free Software Foundation.
99d4fa1a1SMauro Carvalho Chehab  *
109d4fa1a1SMauro Carvalho Chehab  * This program is distributed in the hope it will be useful, but WITHOUT
119d4fa1a1SMauro Carvalho Chehab  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
129d4fa1a1SMauro Carvalho Chehab  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
139d4fa1a1SMauro Carvalho Chehab  * more details.
149d4fa1a1SMauro Carvalho Chehab  */
159d4fa1a1SMauro Carvalho Chehab 
169d4fa1a1SMauro Carvalho Chehab #include "platform_support.h"
179d4fa1a1SMauro Carvalho Chehab 
189d4fa1a1SMauro Carvalho Chehab #include "ia_css_inputfifo.h"
199d4fa1a1SMauro Carvalho Chehab 
209d4fa1a1SMauro Carvalho Chehab #include "device_access.h"
219d4fa1a1SMauro Carvalho Chehab 
229d4fa1a1SMauro Carvalho Chehab #define __INLINE_SP__
239d4fa1a1SMauro Carvalho Chehab #include "sp.h"
249d4fa1a1SMauro Carvalho Chehab #define __INLINE_ISP__
259d4fa1a1SMauro Carvalho Chehab #include "isp.h"
269d4fa1a1SMauro Carvalho Chehab #define __INLINE_IRQ__
279d4fa1a1SMauro Carvalho Chehab #include "irq.h"
289d4fa1a1SMauro Carvalho Chehab #define __INLINE_FIFO_MONITOR__
299d4fa1a1SMauro Carvalho Chehab #include "fifo_monitor.h"
309d4fa1a1SMauro Carvalho Chehab 
319d4fa1a1SMauro Carvalho Chehab #define __INLINE_EVENT__
329d4fa1a1SMauro Carvalho Chehab #include "event_fifo.h"
339d4fa1a1SMauro Carvalho Chehab #define __INLINE_SP__
349d4fa1a1SMauro Carvalho Chehab 
359d4fa1a1SMauro Carvalho Chehab #include "input_system.h"	/* MIPI_PREDICTOR_NONE,... */
369d4fa1a1SMauro Carvalho Chehab 
379d4fa1a1SMauro Carvalho Chehab #include "assert_support.h"
389d4fa1a1SMauro Carvalho Chehab 
399d4fa1a1SMauro Carvalho Chehab /* System independent */
409d4fa1a1SMauro Carvalho Chehab #include "sh_css_internal.h"
419d4fa1a1SMauro Carvalho Chehab #include "ia_css_isys.h"
429d4fa1a1SMauro Carvalho Chehab 
439d4fa1a1SMauro Carvalho Chehab #define HBLANK_CYCLES (187)
449d4fa1a1SMauro Carvalho Chehab #define MARKER_CYCLES (6)
459d4fa1a1SMauro Carvalho Chehab 
469d4fa1a1SMauro Carvalho Chehab #include <hive_isp_css_streaming_to_mipi_types_hrt.h>
479d4fa1a1SMauro Carvalho Chehab 
489d4fa1a1SMauro Carvalho Chehab /* The data type is used to send special cases:
499d4fa1a1SMauro Carvalho Chehab  * yuv420: odd lines (1, 3 etc) are twice as wide as even
509d4fa1a1SMauro Carvalho Chehab  *         lines (0, 2, 4 etc).
519d4fa1a1SMauro Carvalho Chehab  * rgb: for two pixels per clock, the R and B values are sent
529d4fa1a1SMauro Carvalho Chehab  *      to output_0 while only G is sent to output_1. This means
539d4fa1a1SMauro Carvalho Chehab  *      that output_1 only gets half the number of values of output_0.
549d4fa1a1SMauro Carvalho Chehab  *      WARNING: This type should also be used for Legacy YUV420.
559d4fa1a1SMauro Carvalho Chehab  * regular: used for all other data types (RAW, YUV422, etc)
569d4fa1a1SMauro Carvalho Chehab  */
579d4fa1a1SMauro Carvalho Chehab enum inputfifo_mipi_data_type {
589d4fa1a1SMauro Carvalho Chehab 	inputfifo_mipi_data_type_regular,
599d4fa1a1SMauro Carvalho Chehab 	inputfifo_mipi_data_type_yuv420,
609d4fa1a1SMauro Carvalho Chehab 	inputfifo_mipi_data_type_yuv420_legacy,
619d4fa1a1SMauro Carvalho Chehab 	inputfifo_mipi_data_type_rgb,
629d4fa1a1SMauro Carvalho Chehab };
639d4fa1a1SMauro Carvalho Chehab 
649d4fa1a1SMauro Carvalho Chehab static unsigned int inputfifo_curr_ch_id, inputfifo_curr_fmt_type;
659d4fa1a1SMauro Carvalho Chehab struct inputfifo_instance {
669d4fa1a1SMauro Carvalho Chehab 	unsigned int				ch_id;
679d4fa1a1SMauro Carvalho Chehab 	enum atomisp_input_format	input_format;
689d4fa1a1SMauro Carvalho Chehab 	bool						two_ppc;
699d4fa1a1SMauro Carvalho Chehab 	bool						streaming;
709d4fa1a1SMauro Carvalho Chehab 	unsigned int				hblank_cycles;
719d4fa1a1SMauro Carvalho Chehab 	unsigned int				marker_cycles;
729d4fa1a1SMauro Carvalho Chehab 	unsigned int				fmt_type;
739d4fa1a1SMauro Carvalho Chehab 	enum inputfifo_mipi_data_type	type;
749d4fa1a1SMauro Carvalho Chehab };
759d4fa1a1SMauro Carvalho Chehab 
769d4fa1a1SMauro Carvalho Chehab /*
779d4fa1a1SMauro Carvalho Chehab  * Maintain a basic streaming to Mipi administration with ch_id as index
789d4fa1a1SMauro Carvalho Chehab  * ch_id maps on the "Mipi virtual channel ID" and can have value 0..3
799d4fa1a1SMauro Carvalho Chehab  */
809d4fa1a1SMauro Carvalho Chehab #define INPUTFIFO_NR_OF_S2M_CHANNELS	(4)
819d4fa1a1SMauro Carvalho Chehab static struct inputfifo_instance
829d4fa1a1SMauro Carvalho Chehab 	inputfifo_inst_admin[INPUTFIFO_NR_OF_S2M_CHANNELS];
839d4fa1a1SMauro Carvalho Chehab 
849d4fa1a1SMauro Carvalho Chehab /* Streaming to MIPI */
inputfifo_wrap_marker(unsigned int marker)859d4fa1a1SMauro Carvalho Chehab static unsigned int inputfifo_wrap_marker(
869d4fa1a1SMauro Carvalho Chehab     /* static inline unsigned inputfifo_wrap_marker( */
879d4fa1a1SMauro Carvalho Chehab     unsigned int marker)
889d4fa1a1SMauro Carvalho Chehab {
899d4fa1a1SMauro Carvalho Chehab 	return marker |
909d4fa1a1SMauro Carvalho Chehab 	       (inputfifo_curr_ch_id << HIVE_STR_TO_MIPI_CH_ID_LSB) |
919d4fa1a1SMauro Carvalho Chehab 	       (inputfifo_curr_fmt_type << _HIVE_STR_TO_MIPI_FMT_TYPE_LSB);
929d4fa1a1SMauro Carvalho Chehab }
939d4fa1a1SMauro Carvalho Chehab 
949d4fa1a1SMauro Carvalho Chehab static inline void
_sh_css_fifo_snd(unsigned int token)959d4fa1a1SMauro Carvalho Chehab _sh_css_fifo_snd(unsigned int token)
969d4fa1a1SMauro Carvalho Chehab {
979d4fa1a1SMauro Carvalho Chehab 	while (!can_event_send_token(STR2MIPI_EVENT_ID))
9869a03e36SMauro Carvalho Chehab 		udelay(1);
999d4fa1a1SMauro Carvalho Chehab 	event_send_token(STR2MIPI_EVENT_ID, token);
1009d4fa1a1SMauro Carvalho Chehab 	return;
1019d4fa1a1SMauro Carvalho Chehab }
1029d4fa1a1SMauro Carvalho Chehab 
inputfifo_send_data_a(unsigned int data)1039d4fa1a1SMauro Carvalho Chehab static void inputfifo_send_data_a(
1049d4fa1a1SMauro Carvalho Chehab     /* static inline void inputfifo_send_data_a( */
1059d4fa1a1SMauro Carvalho Chehab     unsigned int data)
1069d4fa1a1SMauro Carvalho Chehab {
1079d4fa1a1SMauro Carvalho Chehab 	unsigned int token = (1 << HIVE_STR_TO_MIPI_VALID_A_BIT) |
1089d4fa1a1SMauro Carvalho Chehab 			     (data << HIVE_STR_TO_MIPI_DATA_A_LSB);
1099d4fa1a1SMauro Carvalho Chehab 	_sh_css_fifo_snd(token);
1109d4fa1a1SMauro Carvalho Chehab 	return;
1119d4fa1a1SMauro Carvalho Chehab }
1129d4fa1a1SMauro Carvalho Chehab 
inputfifo_send_data_b(unsigned int data)1139d4fa1a1SMauro Carvalho Chehab static void inputfifo_send_data_b(
1149d4fa1a1SMauro Carvalho Chehab     /* static inline void inputfifo_send_data_b( */
1159d4fa1a1SMauro Carvalho Chehab     unsigned int data)
1169d4fa1a1SMauro Carvalho Chehab {
1179d4fa1a1SMauro Carvalho Chehab 	unsigned int token = (1 << HIVE_STR_TO_MIPI_VALID_B_BIT) |
1189d4fa1a1SMauro Carvalho Chehab 			     (data << _HIVE_STR_TO_MIPI_DATA_B_LSB);
1199d4fa1a1SMauro Carvalho Chehab 	_sh_css_fifo_snd(token);
1209d4fa1a1SMauro Carvalho Chehab 	return;
1219d4fa1a1SMauro Carvalho Chehab }
1229d4fa1a1SMauro Carvalho Chehab 
inputfifo_send_data(unsigned int a,unsigned int b)1239d4fa1a1SMauro Carvalho Chehab static void inputfifo_send_data(
1249d4fa1a1SMauro Carvalho Chehab     /* static inline void inputfifo_send_data( */
1259d4fa1a1SMauro Carvalho Chehab     unsigned int a,
1269d4fa1a1SMauro Carvalho Chehab     unsigned int b)
1279d4fa1a1SMauro Carvalho Chehab {
1289d4fa1a1SMauro Carvalho Chehab 	unsigned int token = ((1 << HIVE_STR_TO_MIPI_VALID_A_BIT) |
1299d4fa1a1SMauro Carvalho Chehab 			      (1 << HIVE_STR_TO_MIPI_VALID_B_BIT) |
1309d4fa1a1SMauro Carvalho Chehab 			      (a << HIVE_STR_TO_MIPI_DATA_A_LSB) |
1319d4fa1a1SMauro Carvalho Chehab 			      (b << _HIVE_STR_TO_MIPI_DATA_B_LSB));
1329d4fa1a1SMauro Carvalho Chehab 	_sh_css_fifo_snd(token);
1339d4fa1a1SMauro Carvalho Chehab 	return;
1349d4fa1a1SMauro Carvalho Chehab }
1359d4fa1a1SMauro Carvalho Chehab 
inputfifo_send_sol(void)1369d4fa1a1SMauro Carvalho Chehab static void inputfifo_send_sol(void)
1379d4fa1a1SMauro Carvalho Chehab /* static inline void inputfifo_send_sol(void) */
1389d4fa1a1SMauro Carvalho Chehab {
1399d4fa1a1SMauro Carvalho Chehab 	hrt_data	token = inputfifo_wrap_marker(
1409d4fa1a1SMauro Carvalho Chehab 				1 << HIVE_STR_TO_MIPI_SOL_BIT);
1419d4fa1a1SMauro Carvalho Chehab 
1429d4fa1a1SMauro Carvalho Chehab 	_sh_css_fifo_snd(token);
1439d4fa1a1SMauro Carvalho Chehab 	return;
1449d4fa1a1SMauro Carvalho Chehab }
1459d4fa1a1SMauro Carvalho Chehab 
inputfifo_send_eol(void)1469d4fa1a1SMauro Carvalho Chehab static void inputfifo_send_eol(void)
1479d4fa1a1SMauro Carvalho Chehab /* static inline void inputfifo_send_eol(void) */
1489d4fa1a1SMauro Carvalho Chehab {
1499d4fa1a1SMauro Carvalho Chehab 	hrt_data	token = inputfifo_wrap_marker(
1509d4fa1a1SMauro Carvalho Chehab 				1 << HIVE_STR_TO_MIPI_EOL_BIT);
1519d4fa1a1SMauro Carvalho Chehab 	_sh_css_fifo_snd(token);
1529d4fa1a1SMauro Carvalho Chehab 	return;
1539d4fa1a1SMauro Carvalho Chehab }
1549d4fa1a1SMauro Carvalho Chehab 
inputfifo_send_sof(void)1559d4fa1a1SMauro Carvalho Chehab static void inputfifo_send_sof(void)
1569d4fa1a1SMauro Carvalho Chehab /* static inline void inputfifo_send_sof(void) */
1579d4fa1a1SMauro Carvalho Chehab {
1589d4fa1a1SMauro Carvalho Chehab 	hrt_data	token = inputfifo_wrap_marker(
1599d4fa1a1SMauro Carvalho Chehab 				1 << HIVE_STR_TO_MIPI_SOF_BIT);
1609d4fa1a1SMauro Carvalho Chehab 
1619d4fa1a1SMauro Carvalho Chehab 	_sh_css_fifo_snd(token);
1629d4fa1a1SMauro Carvalho Chehab 	return;
1639d4fa1a1SMauro Carvalho Chehab }
1649d4fa1a1SMauro Carvalho Chehab 
inputfifo_send_eof(void)1659d4fa1a1SMauro Carvalho Chehab static void inputfifo_send_eof(void)
1669d4fa1a1SMauro Carvalho Chehab /* static inline void inputfifo_send_eof(void) */
1679d4fa1a1SMauro Carvalho Chehab {
1689d4fa1a1SMauro Carvalho Chehab 	hrt_data	token = inputfifo_wrap_marker(
1699d4fa1a1SMauro Carvalho Chehab 				1 << HIVE_STR_TO_MIPI_EOF_BIT);
1709d4fa1a1SMauro Carvalho Chehab 	_sh_css_fifo_snd(token);
1719d4fa1a1SMauro Carvalho Chehab 	return;
1729d4fa1a1SMauro Carvalho Chehab }
1739d4fa1a1SMauro Carvalho Chehab 
inputfifo_send_ch_id_and_fmt_type(unsigned int ch_id,unsigned int fmt_type)1749d4fa1a1SMauro Carvalho Chehab static void inputfifo_send_ch_id_and_fmt_type(
1759d4fa1a1SMauro Carvalho Chehab     /* static inline
1769d4fa1a1SMauro Carvalho Chehab     void inputfifo_send_ch_id_and_fmt_type( */
1779d4fa1a1SMauro Carvalho Chehab     unsigned int ch_id,
1789d4fa1a1SMauro Carvalho Chehab     unsigned int fmt_type)
1799d4fa1a1SMauro Carvalho Chehab {
1809d4fa1a1SMauro Carvalho Chehab 	hrt_data	token;
1819d4fa1a1SMauro Carvalho Chehab 
1829d4fa1a1SMauro Carvalho Chehab 	inputfifo_curr_ch_id = ch_id & _HIVE_ISP_CH_ID_MASK;
1839d4fa1a1SMauro Carvalho Chehab 	inputfifo_curr_fmt_type = fmt_type & _HIVE_ISP_FMT_TYPE_MASK;
1849d4fa1a1SMauro Carvalho Chehab 	/* we send an zero marker, this will wrap the ch_id and
1859d4fa1a1SMauro Carvalho Chehab 	 * fmt_type automatically.
1869d4fa1a1SMauro Carvalho Chehab 	 */
1879d4fa1a1SMauro Carvalho Chehab 	token = inputfifo_wrap_marker(0);
1889d4fa1a1SMauro Carvalho Chehab 	_sh_css_fifo_snd(token);
1899d4fa1a1SMauro Carvalho Chehab 	return;
1909d4fa1a1SMauro Carvalho Chehab }
1919d4fa1a1SMauro Carvalho Chehab 
inputfifo_send_empty_token(void)1929d4fa1a1SMauro Carvalho Chehab static void inputfifo_send_empty_token(void)
1939d4fa1a1SMauro Carvalho Chehab /* static inline void inputfifo_send_empty_token(void) */
1949d4fa1a1SMauro Carvalho Chehab {
1959d4fa1a1SMauro Carvalho Chehab 	hrt_data	token = inputfifo_wrap_marker(0);
1969d4fa1a1SMauro Carvalho Chehab 
1979d4fa1a1SMauro Carvalho Chehab 	_sh_css_fifo_snd(token);
1989d4fa1a1SMauro Carvalho Chehab 	return;
1999d4fa1a1SMauro Carvalho Chehab }
2009d4fa1a1SMauro Carvalho Chehab 
inputfifo_start_frame(unsigned int ch_id,unsigned int fmt_type)2019d4fa1a1SMauro Carvalho Chehab static void inputfifo_start_frame(
2029d4fa1a1SMauro Carvalho Chehab     /* static inline void inputfifo_start_frame( */
2039d4fa1a1SMauro Carvalho Chehab     unsigned int ch_id,
2049d4fa1a1SMauro Carvalho Chehab     unsigned int fmt_type)
2059d4fa1a1SMauro Carvalho Chehab {
2069d4fa1a1SMauro Carvalho Chehab 	inputfifo_send_ch_id_and_fmt_type(ch_id, fmt_type);
2079d4fa1a1SMauro Carvalho Chehab 	inputfifo_send_sof();
2089d4fa1a1SMauro Carvalho Chehab 	return;
2099d4fa1a1SMauro Carvalho Chehab }
2109d4fa1a1SMauro Carvalho Chehab 
inputfifo_end_frame(unsigned int marker_cycles)2119d4fa1a1SMauro Carvalho Chehab static void inputfifo_end_frame(
2129d4fa1a1SMauro Carvalho Chehab     unsigned int marker_cycles)
2139d4fa1a1SMauro Carvalho Chehab {
2149d4fa1a1SMauro Carvalho Chehab 	unsigned int i;
2159d4fa1a1SMauro Carvalho Chehab 
2169d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < marker_cycles; i++)
2179d4fa1a1SMauro Carvalho Chehab 		inputfifo_send_empty_token();
2189d4fa1a1SMauro Carvalho Chehab 	inputfifo_send_eof();
2199d4fa1a1SMauro Carvalho Chehab 	return;
2209d4fa1a1SMauro Carvalho Chehab }
2219d4fa1a1SMauro Carvalho Chehab 
inputfifo_send_line2(const unsigned short * data,unsigned int width,const unsigned short * data2,unsigned int width2,unsigned int hblank_cycles,unsigned int marker_cycles,unsigned int two_ppc,enum inputfifo_mipi_data_type type)2229d4fa1a1SMauro Carvalho Chehab static void inputfifo_send_line2(
2239d4fa1a1SMauro Carvalho Chehab     const unsigned short *data,
2249d4fa1a1SMauro Carvalho Chehab     unsigned int width,
2259d4fa1a1SMauro Carvalho Chehab     const unsigned short *data2,
2269d4fa1a1SMauro Carvalho Chehab     unsigned int width2,
2279d4fa1a1SMauro Carvalho Chehab     unsigned int hblank_cycles,
2289d4fa1a1SMauro Carvalho Chehab     unsigned int marker_cycles,
2299d4fa1a1SMauro Carvalho Chehab     unsigned int two_ppc,
2309d4fa1a1SMauro Carvalho Chehab     enum inputfifo_mipi_data_type type)
2319d4fa1a1SMauro Carvalho Chehab {
2329d4fa1a1SMauro Carvalho Chehab 	unsigned int i, is_rgb = 0, is_legacy = 0;
2339d4fa1a1SMauro Carvalho Chehab 
2349d4fa1a1SMauro Carvalho Chehab 	assert(data);
2359d4fa1a1SMauro Carvalho Chehab 	assert((data2) || (width2 == 0));
2369d4fa1a1SMauro Carvalho Chehab 	if (type == inputfifo_mipi_data_type_rgb)
2379d4fa1a1SMauro Carvalho Chehab 		is_rgb = 1;
2389d4fa1a1SMauro Carvalho Chehab 
2399d4fa1a1SMauro Carvalho Chehab 	if (type == inputfifo_mipi_data_type_yuv420_legacy)
2409d4fa1a1SMauro Carvalho Chehab 		is_legacy = 1;
2419d4fa1a1SMauro Carvalho Chehab 
2429d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < hblank_cycles; i++)
2439d4fa1a1SMauro Carvalho Chehab 		inputfifo_send_empty_token();
2449d4fa1a1SMauro Carvalho Chehab 	inputfifo_send_sol();
2459d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < marker_cycles; i++)
2469d4fa1a1SMauro Carvalho Chehab 		inputfifo_send_empty_token();
2479d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < width; i++, data++) {
2489d4fa1a1SMauro Carvalho Chehab 		/* for RGB in two_ppc, we only actually send 2 pixels per
2499d4fa1a1SMauro Carvalho Chehab 		 * clock in the even pixels (0, 2 etc). In the other cycles,
2509d4fa1a1SMauro Carvalho Chehab 		 * we only send 1 pixel, to data[0].
2519d4fa1a1SMauro Carvalho Chehab 		 */
2529d4fa1a1SMauro Carvalho Chehab 		unsigned int send_two_pixels = two_ppc;
2539d4fa1a1SMauro Carvalho Chehab 
2549d4fa1a1SMauro Carvalho Chehab 		if ((is_rgb || is_legacy) && (i % 3 == 2))
2559d4fa1a1SMauro Carvalho Chehab 			send_two_pixels = 0;
2569d4fa1a1SMauro Carvalho Chehab 		if (send_two_pixels) {
2579d4fa1a1SMauro Carvalho Chehab 			if (i + 1 == width) {
2589d4fa1a1SMauro Carvalho Chehab 				/* for jpg (binary) copy, this can occur
2599d4fa1a1SMauro Carvalho Chehab 				 * if the file contains an odd number of bytes.
2609d4fa1a1SMauro Carvalho Chehab 				 */
2619d4fa1a1SMauro Carvalho Chehab 				inputfifo_send_data(
2629d4fa1a1SMauro Carvalho Chehab 				    data[0], 0);
2639d4fa1a1SMauro Carvalho Chehab 			} else {
2649d4fa1a1SMauro Carvalho Chehab 				inputfifo_send_data(
2659d4fa1a1SMauro Carvalho Chehab 				    data[0], data[1]);
2669d4fa1a1SMauro Carvalho Chehab 			}
2679d4fa1a1SMauro Carvalho Chehab 			/* Additional increment because we send 2 pixels */
2689d4fa1a1SMauro Carvalho Chehab 			data++;
2699d4fa1a1SMauro Carvalho Chehab 			i++;
2709d4fa1a1SMauro Carvalho Chehab 		} else if (two_ppc && is_legacy) {
2719d4fa1a1SMauro Carvalho Chehab 			inputfifo_send_data_b(data[0]);
2729d4fa1a1SMauro Carvalho Chehab 		} else {
2739d4fa1a1SMauro Carvalho Chehab 			inputfifo_send_data_a(data[0]);
2749d4fa1a1SMauro Carvalho Chehab 		}
2759d4fa1a1SMauro Carvalho Chehab 	}
2769d4fa1a1SMauro Carvalho Chehab 
2779d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < width2; i++, data2++) {
2789d4fa1a1SMauro Carvalho Chehab 		/* for RGB in two_ppc, we only actually send 2 pixels per
2799d4fa1a1SMauro Carvalho Chehab 		 * clock in the even pixels (0, 2 etc). In the other cycles,
2809d4fa1a1SMauro Carvalho Chehab 		 * we only send 1 pixel, to data2[0].
2819d4fa1a1SMauro Carvalho Chehab 		 */
2829d4fa1a1SMauro Carvalho Chehab 		unsigned int send_two_pixels = two_ppc;
2839d4fa1a1SMauro Carvalho Chehab 
2849d4fa1a1SMauro Carvalho Chehab 		if ((is_rgb || is_legacy) && (i % 3 == 2))
2859d4fa1a1SMauro Carvalho Chehab 			send_two_pixels = 0;
2869d4fa1a1SMauro Carvalho Chehab 		if (send_two_pixels) {
2879d4fa1a1SMauro Carvalho Chehab 			if (i + 1 == width2) {
2889d4fa1a1SMauro Carvalho Chehab 				/* for jpg (binary) copy, this can occur
2899d4fa1a1SMauro Carvalho Chehab 				 * if the file contains an odd number of bytes.
2909d4fa1a1SMauro Carvalho Chehab 				 */
2919d4fa1a1SMauro Carvalho Chehab 				inputfifo_send_data(
2929d4fa1a1SMauro Carvalho Chehab 				    data2[0], 0);
2939d4fa1a1SMauro Carvalho Chehab 			} else {
2949d4fa1a1SMauro Carvalho Chehab 				inputfifo_send_data(
2959d4fa1a1SMauro Carvalho Chehab 				    data2[0], data2[1]);
2969d4fa1a1SMauro Carvalho Chehab 			}
2979d4fa1a1SMauro Carvalho Chehab 			/* Additional increment because we send 2 pixels */
2989d4fa1a1SMauro Carvalho Chehab 			data2++;
2999d4fa1a1SMauro Carvalho Chehab 			i++;
3009d4fa1a1SMauro Carvalho Chehab 		} else if (two_ppc && is_legacy) {
3019d4fa1a1SMauro Carvalho Chehab 			inputfifo_send_data_b(data2[0]);
3029d4fa1a1SMauro Carvalho Chehab 		} else {
3039d4fa1a1SMauro Carvalho Chehab 			inputfifo_send_data_a(data2[0]);
3049d4fa1a1SMauro Carvalho Chehab 		}
3059d4fa1a1SMauro Carvalho Chehab 	}
3069d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < hblank_cycles; i++)
3079d4fa1a1SMauro Carvalho Chehab 		inputfifo_send_empty_token();
3089d4fa1a1SMauro Carvalho Chehab 	inputfifo_send_eol();
3099d4fa1a1SMauro Carvalho Chehab 	return;
3109d4fa1a1SMauro Carvalho Chehab }
3119d4fa1a1SMauro Carvalho Chehab 
3129d4fa1a1SMauro Carvalho Chehab static void
inputfifo_send_line(const unsigned short * data,unsigned int width,unsigned int hblank_cycles,unsigned int marker_cycles,unsigned int two_ppc,enum inputfifo_mipi_data_type type)3139d4fa1a1SMauro Carvalho Chehab inputfifo_send_line(const unsigned short *data,
3149d4fa1a1SMauro Carvalho Chehab 		    unsigned int width,
3159d4fa1a1SMauro Carvalho Chehab 		    unsigned int hblank_cycles,
3169d4fa1a1SMauro Carvalho Chehab 		    unsigned int marker_cycles,
3179d4fa1a1SMauro Carvalho Chehab 		    unsigned int two_ppc,
3189d4fa1a1SMauro Carvalho Chehab 		    enum inputfifo_mipi_data_type type)
3199d4fa1a1SMauro Carvalho Chehab {
3209d4fa1a1SMauro Carvalho Chehab 	assert(data);
3219d4fa1a1SMauro Carvalho Chehab 	inputfifo_send_line2(data, width, NULL, 0,
3229d4fa1a1SMauro Carvalho Chehab 			     hblank_cycles,
3239d4fa1a1SMauro Carvalho Chehab 			     marker_cycles,
3249d4fa1a1SMauro Carvalho Chehab 			     two_ppc,
3259d4fa1a1SMauro Carvalho Chehab 			     type);
3269d4fa1a1SMauro Carvalho Chehab }
3279d4fa1a1SMauro Carvalho Chehab 
3289d4fa1a1SMauro Carvalho Chehab /* Send a frame of data into the input network via the GP FIFO.
3299d4fa1a1SMauro Carvalho Chehab  *  Parameters:
3309d4fa1a1SMauro Carvalho Chehab  *   - data: array of 16 bit values that contains all data for the frame.
3319d4fa1a1SMauro Carvalho Chehab  *   - width: width of a line in number of subpixels, for yuv420 it is the
3329d4fa1a1SMauro Carvalho Chehab  *            number of Y components per line.
3339d4fa1a1SMauro Carvalho Chehab  *   - height: height of the frame in number of lines.
3349d4fa1a1SMauro Carvalho Chehab  *   - ch_id: channel ID.
3359d4fa1a1SMauro Carvalho Chehab  *   - fmt_type: format type.
3369d4fa1a1SMauro Carvalho Chehab  *   - hblank_cycles: length of horizontal blanking in cycles.
3379d4fa1a1SMauro Carvalho Chehab  *   - marker_cycles: number of empty cycles after start-of-line and before
3389d4fa1a1SMauro Carvalho Chehab  *                    end-of-frame.
3399d4fa1a1SMauro Carvalho Chehab  *   - two_ppc: boolean, describes whether to send one or two pixels per clock
3409d4fa1a1SMauro Carvalho Chehab  *              cycle. In this mode, we sent pixels N and N+1 in the same cycle,
3419d4fa1a1SMauro Carvalho Chehab  *              to IF_PRIM_A and IF_PRIM_B respectively. The caller must make
3429d4fa1a1SMauro Carvalho Chehab  *              sure the input data has been formatted correctly for this.
3439d4fa1a1SMauro Carvalho Chehab  *              For example, for RGB formats this means that unused values
3449d4fa1a1SMauro Carvalho Chehab  *              must be inserted.
3459d4fa1a1SMauro Carvalho Chehab  *   - yuv420: boolean, describes whether (non-legacy) yuv420 data is used. In
3469d4fa1a1SMauro Carvalho Chehab  *             this mode, the odd lines (1,3,5 etc) are half as long as the
3479d4fa1a1SMauro Carvalho Chehab  *             even lines (2,4,6 etc).
3489d4fa1a1SMauro Carvalho Chehab  *             Note that the first line is odd (1) and the second line is even
3499d4fa1a1SMauro Carvalho Chehab  *             (2).
3509d4fa1a1SMauro Carvalho Chehab  *
3519d4fa1a1SMauro Carvalho Chehab  * This function does not do any reordering of pixels, the caller must make
3529d4fa1a1SMauro Carvalho Chehab  * sure the data is in the righ format. Please refer to the CSS receiver
3539d4fa1a1SMauro Carvalho Chehab  * documentation for details on the data formats.
3549d4fa1a1SMauro Carvalho Chehab  */
3559d4fa1a1SMauro Carvalho Chehab 
inputfifo_send_frame(const unsigned short * data,unsigned int width,unsigned int height,unsigned int ch_id,unsigned int fmt_type,unsigned int hblank_cycles,unsigned int marker_cycles,unsigned int two_ppc,enum inputfifo_mipi_data_type type)3569d4fa1a1SMauro Carvalho Chehab static void inputfifo_send_frame(
3579d4fa1a1SMauro Carvalho Chehab     const unsigned short *data,
3589d4fa1a1SMauro Carvalho Chehab     unsigned int width,
3599d4fa1a1SMauro Carvalho Chehab     unsigned int height,
3609d4fa1a1SMauro Carvalho Chehab     unsigned int ch_id,
3619d4fa1a1SMauro Carvalho Chehab     unsigned int fmt_type,
3629d4fa1a1SMauro Carvalho Chehab     unsigned int hblank_cycles,
3639d4fa1a1SMauro Carvalho Chehab     unsigned int marker_cycles,
3649d4fa1a1SMauro Carvalho Chehab     unsigned int two_ppc,
3659d4fa1a1SMauro Carvalho Chehab     enum inputfifo_mipi_data_type type)
3669d4fa1a1SMauro Carvalho Chehab {
3679d4fa1a1SMauro Carvalho Chehab 	unsigned int i;
3689d4fa1a1SMauro Carvalho Chehab 
3699d4fa1a1SMauro Carvalho Chehab 	assert(data);
3709d4fa1a1SMauro Carvalho Chehab 	inputfifo_start_frame(ch_id, fmt_type);
3719d4fa1a1SMauro Carvalho Chehab 
3729d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < height; i++) {
3739d4fa1a1SMauro Carvalho Chehab 		if ((type == inputfifo_mipi_data_type_yuv420) &&
3749d4fa1a1SMauro Carvalho Chehab 		    (i & 1) == 1) {
3759d4fa1a1SMauro Carvalho Chehab 			inputfifo_send_line(data, 2 * width,
3769d4fa1a1SMauro Carvalho Chehab 					    hblank_cycles,
3779d4fa1a1SMauro Carvalho Chehab 					    marker_cycles,
3789d4fa1a1SMauro Carvalho Chehab 					    two_ppc, type);
3799d4fa1a1SMauro Carvalho Chehab 			data += 2 * width;
3809d4fa1a1SMauro Carvalho Chehab 		} else {
3819d4fa1a1SMauro Carvalho Chehab 			inputfifo_send_line(data, width,
3829d4fa1a1SMauro Carvalho Chehab 					    hblank_cycles,
3839d4fa1a1SMauro Carvalho Chehab 					    marker_cycles,
3849d4fa1a1SMauro Carvalho Chehab 					    two_ppc, type);
3859d4fa1a1SMauro Carvalho Chehab 			data += width;
3869d4fa1a1SMauro Carvalho Chehab 		}
3879d4fa1a1SMauro Carvalho Chehab 	}
3889d4fa1a1SMauro Carvalho Chehab 	inputfifo_end_frame(marker_cycles);
3899d4fa1a1SMauro Carvalho Chehab 	return;
3909d4fa1a1SMauro Carvalho Chehab }
3919d4fa1a1SMauro Carvalho Chehab 
inputfifo_determine_type(enum atomisp_input_format input_format)3929d4fa1a1SMauro Carvalho Chehab static enum inputfifo_mipi_data_type inputfifo_determine_type(
3939d4fa1a1SMauro Carvalho Chehab     enum atomisp_input_format input_format)
3949d4fa1a1SMauro Carvalho Chehab {
3959d4fa1a1SMauro Carvalho Chehab 	enum inputfifo_mipi_data_type type;
3969d4fa1a1SMauro Carvalho Chehab 
3979d4fa1a1SMauro Carvalho Chehab 	type = inputfifo_mipi_data_type_regular;
3989d4fa1a1SMauro Carvalho Chehab 	if (input_format == ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) {
3999d4fa1a1SMauro Carvalho Chehab 		type =
4009d4fa1a1SMauro Carvalho Chehab 		    inputfifo_mipi_data_type_yuv420_legacy;
4019d4fa1a1SMauro Carvalho Chehab 	} else if (input_format == ATOMISP_INPUT_FORMAT_YUV420_8  ||
4029d4fa1a1SMauro Carvalho Chehab 		   input_format == ATOMISP_INPUT_FORMAT_YUV420_10 ||
4039d4fa1a1SMauro Carvalho Chehab 		   input_format == ATOMISP_INPUT_FORMAT_YUV420_16) {
4049d4fa1a1SMauro Carvalho Chehab 		type =
4059d4fa1a1SMauro Carvalho Chehab 		    inputfifo_mipi_data_type_yuv420;
4069d4fa1a1SMauro Carvalho Chehab 	} else if (input_format >= ATOMISP_INPUT_FORMAT_RGB_444 &&
4079d4fa1a1SMauro Carvalho Chehab 		   input_format <= ATOMISP_INPUT_FORMAT_RGB_888) {
4089d4fa1a1SMauro Carvalho Chehab 		type =
4099d4fa1a1SMauro Carvalho Chehab 		    inputfifo_mipi_data_type_rgb;
4109d4fa1a1SMauro Carvalho Chehab 	}
4119d4fa1a1SMauro Carvalho Chehab 	return type;
4129d4fa1a1SMauro Carvalho Chehab }
4139d4fa1a1SMauro Carvalho Chehab 
inputfifo_get_inst(unsigned int ch_id)4149d4fa1a1SMauro Carvalho Chehab static struct inputfifo_instance *inputfifo_get_inst(
4159d4fa1a1SMauro Carvalho Chehab     unsigned int ch_id)
4169d4fa1a1SMauro Carvalho Chehab {
4179d4fa1a1SMauro Carvalho Chehab 	return &inputfifo_inst_admin[ch_id];
4189d4fa1a1SMauro Carvalho Chehab }
4199d4fa1a1SMauro Carvalho Chehab 
ia_css_inputfifo_send_input_frame(const unsigned short * data,unsigned int width,unsigned int height,unsigned int ch_id,enum atomisp_input_format input_format,bool two_ppc)4209d4fa1a1SMauro Carvalho Chehab void ia_css_inputfifo_send_input_frame(
4219d4fa1a1SMauro Carvalho Chehab     const unsigned short *data,
4229d4fa1a1SMauro Carvalho Chehab     unsigned int width,
4239d4fa1a1SMauro Carvalho Chehab     unsigned int height,
4249d4fa1a1SMauro Carvalho Chehab     unsigned int ch_id,
4259d4fa1a1SMauro Carvalho Chehab     enum atomisp_input_format input_format,
4269d4fa1a1SMauro Carvalho Chehab     bool two_ppc)
4279d4fa1a1SMauro Carvalho Chehab {
4289d4fa1a1SMauro Carvalho Chehab 	unsigned int fmt_type, hblank_cycles, marker_cycles;
4299d4fa1a1SMauro Carvalho Chehab 	enum inputfifo_mipi_data_type type;
4309d4fa1a1SMauro Carvalho Chehab 
4319d4fa1a1SMauro Carvalho Chehab 	assert(data);
4329d4fa1a1SMauro Carvalho Chehab 	hblank_cycles = HBLANK_CYCLES;
4339d4fa1a1SMauro Carvalho Chehab 	marker_cycles = MARKER_CYCLES;
4349d4fa1a1SMauro Carvalho Chehab 	ia_css_isys_convert_stream_format_to_mipi_format(input_format,
4359d4fa1a1SMauro Carvalho Chehab 		MIPI_PREDICTOR_NONE,
4369d4fa1a1SMauro Carvalho Chehab 		&fmt_type);
4379d4fa1a1SMauro Carvalho Chehab 
4389d4fa1a1SMauro Carvalho Chehab 	type = inputfifo_determine_type(input_format);
4399d4fa1a1SMauro Carvalho Chehab 
4409d4fa1a1SMauro Carvalho Chehab 	inputfifo_send_frame(data, width, height,
4419d4fa1a1SMauro Carvalho Chehab 			     ch_id, fmt_type, hblank_cycles, marker_cycles,
4429d4fa1a1SMauro Carvalho Chehab 			     two_ppc, type);
4439d4fa1a1SMauro Carvalho Chehab }
4449d4fa1a1SMauro Carvalho Chehab 
ia_css_inputfifo_start_frame(unsigned int ch_id,enum atomisp_input_format input_format,bool two_ppc)4459d4fa1a1SMauro Carvalho Chehab void ia_css_inputfifo_start_frame(
4469d4fa1a1SMauro Carvalho Chehab     unsigned int ch_id,
4479d4fa1a1SMauro Carvalho Chehab     enum atomisp_input_format input_format,
4489d4fa1a1SMauro Carvalho Chehab     bool two_ppc)
4499d4fa1a1SMauro Carvalho Chehab {
4509d4fa1a1SMauro Carvalho Chehab 	struct inputfifo_instance *s2mi;
4519d4fa1a1SMauro Carvalho Chehab 
4529d4fa1a1SMauro Carvalho Chehab 	s2mi = inputfifo_get_inst(ch_id);
4539d4fa1a1SMauro Carvalho Chehab 
4549d4fa1a1SMauro Carvalho Chehab 	s2mi->ch_id = ch_id;
4559d4fa1a1SMauro Carvalho Chehab 	ia_css_isys_convert_stream_format_to_mipi_format(input_format,
4569d4fa1a1SMauro Carvalho Chehab 		MIPI_PREDICTOR_NONE,
4579d4fa1a1SMauro Carvalho Chehab 		&s2mi->fmt_type);
4589d4fa1a1SMauro Carvalho Chehab 	s2mi->two_ppc = two_ppc;
4599d4fa1a1SMauro Carvalho Chehab 	s2mi->type = inputfifo_determine_type(input_format);
4609d4fa1a1SMauro Carvalho Chehab 	s2mi->hblank_cycles = HBLANK_CYCLES;
4619d4fa1a1SMauro Carvalho Chehab 	s2mi->marker_cycles = MARKER_CYCLES;
4629d4fa1a1SMauro Carvalho Chehab 	s2mi->streaming = true;
4639d4fa1a1SMauro Carvalho Chehab 
4649d4fa1a1SMauro Carvalho Chehab 	inputfifo_start_frame(ch_id, s2mi->fmt_type);
4659d4fa1a1SMauro Carvalho Chehab 	return;
4669d4fa1a1SMauro Carvalho Chehab }
4679d4fa1a1SMauro Carvalho Chehab 
ia_css_inputfifo_send_line(unsigned int ch_id,const unsigned short * data,unsigned int width,const unsigned short * data2,unsigned int width2)4689d4fa1a1SMauro Carvalho Chehab void ia_css_inputfifo_send_line(
4699d4fa1a1SMauro Carvalho Chehab     unsigned int ch_id,
4709d4fa1a1SMauro Carvalho Chehab     const unsigned short *data,
4719d4fa1a1SMauro Carvalho Chehab     unsigned int width,
4729d4fa1a1SMauro Carvalho Chehab     const unsigned short *data2,
4739d4fa1a1SMauro Carvalho Chehab     unsigned int width2)
4749d4fa1a1SMauro Carvalho Chehab {
4759d4fa1a1SMauro Carvalho Chehab 	struct inputfifo_instance *s2mi;
4769d4fa1a1SMauro Carvalho Chehab 
4779d4fa1a1SMauro Carvalho Chehab 	assert(data);
4789d4fa1a1SMauro Carvalho Chehab 	assert((data2) || (width2 == 0));
4799d4fa1a1SMauro Carvalho Chehab 	s2mi = inputfifo_get_inst(ch_id);
4809d4fa1a1SMauro Carvalho Chehab 
4819d4fa1a1SMauro Carvalho Chehab 	/* Set global variables that indicate channel_id and format_type */
4829d4fa1a1SMauro Carvalho Chehab 	inputfifo_curr_ch_id = (s2mi->ch_id) & _HIVE_ISP_CH_ID_MASK;
4839d4fa1a1SMauro Carvalho Chehab 	inputfifo_curr_fmt_type = (s2mi->fmt_type) & _HIVE_ISP_FMT_TYPE_MASK;
4849d4fa1a1SMauro Carvalho Chehab 
4859d4fa1a1SMauro Carvalho Chehab 	inputfifo_send_line2(data, width, data2, width2,
4869d4fa1a1SMauro Carvalho Chehab 			     s2mi->hblank_cycles,
4879d4fa1a1SMauro Carvalho Chehab 			     s2mi->marker_cycles,
4889d4fa1a1SMauro Carvalho Chehab 			     s2mi->two_ppc,
4899d4fa1a1SMauro Carvalho Chehab 			     s2mi->type);
4909d4fa1a1SMauro Carvalho Chehab }
4919d4fa1a1SMauro Carvalho Chehab 
ia_css_inputfifo_send_embedded_line(unsigned int ch_id,enum atomisp_input_format data_type,const unsigned short * data,unsigned int width)4929d4fa1a1SMauro Carvalho Chehab void ia_css_inputfifo_send_embedded_line(
4939d4fa1a1SMauro Carvalho Chehab     unsigned int	ch_id,
4949d4fa1a1SMauro Carvalho Chehab     enum atomisp_input_format	data_type,
4959d4fa1a1SMauro Carvalho Chehab     const unsigned short	*data,
4969d4fa1a1SMauro Carvalho Chehab     unsigned int	width)
4979d4fa1a1SMauro Carvalho Chehab {
4989d4fa1a1SMauro Carvalho Chehab 	struct inputfifo_instance *s2mi;
4999d4fa1a1SMauro Carvalho Chehab 	unsigned int fmt_type;
5009d4fa1a1SMauro Carvalho Chehab 
5019d4fa1a1SMauro Carvalho Chehab 	assert(data);
5029d4fa1a1SMauro Carvalho Chehab 	s2mi = inputfifo_get_inst(ch_id);
5039d4fa1a1SMauro Carvalho Chehab 	ia_css_isys_convert_stream_format_to_mipi_format(data_type,
5049d4fa1a1SMauro Carvalho Chehab 		MIPI_PREDICTOR_NONE, &fmt_type);
5059d4fa1a1SMauro Carvalho Chehab 
5069d4fa1a1SMauro Carvalho Chehab 	/* Set format_type for metadata line. */
5079d4fa1a1SMauro Carvalho Chehab 	inputfifo_curr_fmt_type = fmt_type & _HIVE_ISP_FMT_TYPE_MASK;
5089d4fa1a1SMauro Carvalho Chehab 
5099d4fa1a1SMauro Carvalho Chehab 	inputfifo_send_line(data, width, s2mi->hblank_cycles, s2mi->marker_cycles,
5109d4fa1a1SMauro Carvalho Chehab 			    s2mi->two_ppc, inputfifo_mipi_data_type_regular);
5119d4fa1a1SMauro Carvalho Chehab }
5129d4fa1a1SMauro Carvalho Chehab 
ia_css_inputfifo_end_frame(unsigned int ch_id)5139d4fa1a1SMauro Carvalho Chehab void ia_css_inputfifo_end_frame(
5149d4fa1a1SMauro Carvalho Chehab     unsigned int	ch_id)
5159d4fa1a1SMauro Carvalho Chehab {
5169d4fa1a1SMauro Carvalho Chehab 	struct inputfifo_instance *s2mi;
5179d4fa1a1SMauro Carvalho Chehab 
5189d4fa1a1SMauro Carvalho Chehab 	s2mi = inputfifo_get_inst(ch_id);
5199d4fa1a1SMauro Carvalho Chehab 
5209d4fa1a1SMauro Carvalho Chehab 	/* Set global variables that indicate channel_id and format_type */
5219d4fa1a1SMauro Carvalho Chehab 	inputfifo_curr_ch_id = (s2mi->ch_id) & _HIVE_ISP_CH_ID_MASK;
5229d4fa1a1SMauro Carvalho Chehab 	inputfifo_curr_fmt_type = (s2mi->fmt_type) & _HIVE_ISP_FMT_TYPE_MASK;
5239d4fa1a1SMauro Carvalho Chehab 
5249d4fa1a1SMauro Carvalho Chehab 	/* Call existing HRT function */
5259d4fa1a1SMauro Carvalho Chehab 	inputfifo_end_frame(s2mi->marker_cycles);
5269d4fa1a1SMauro Carvalho Chehab 
5279d4fa1a1SMauro Carvalho Chehab 	s2mi->streaming = false;
5289d4fa1a1SMauro Carvalho Chehab 	return;
5299d4fa1a1SMauro Carvalho Chehab }
530