1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Support for Intel Camera Imaging ISP subsystem.
4 * Copyright (c) 2010 - 2015, Intel Corporation.
5 *
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.
9 *
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
13 * more details.
14 */
15
16#define __INLINE_INPUT_SYSTEM__
17#include "input_system.h"
18#include "assert_support.h"
19#include "ia_css_isys.h"
20#include "ia_css_irq.h"
21#include "sh_css_internal.h"
22
23void ia_css_isys_rx_enable_all_interrupts(enum mipi_port_id port)
24{
25	hrt_data bits = receiver_port_reg_load(RX0_ID,
26					       port,
27					       _HRT_CSS_RECEIVER_IRQ_ENABLE_REG_IDX);
28
29	bits |= (1U << _HRT_CSS_RECEIVER_IRQ_OVERRUN_BIT) |
30		(1U << _HRT_CSS_RECEIVER_IRQ_INIT_TIMEOUT_BIT) |
31		(1U << _HRT_CSS_RECEIVER_IRQ_SLEEP_MODE_ENTRY_BIT) |
32		(1U << _HRT_CSS_RECEIVER_IRQ_SLEEP_MODE_EXIT_BIT) |
33		(1U << _HRT_CSS_RECEIVER_IRQ_ERR_SOT_HS_BIT) |
34		(1U << _HRT_CSS_RECEIVER_IRQ_ERR_SOT_SYNC_HS_BIT) |
35		(1U << _HRT_CSS_RECEIVER_IRQ_ERR_CONTROL_BIT) |
36		(1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_DOUBLE_BIT) |
37		(1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_CORRECTED_BIT) |
38		/*(1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_NO_CORRECTION_BIT) | */
39		(1U << _HRT_CSS_RECEIVER_IRQ_ERR_CRC_BIT) |
40		(1U << _HRT_CSS_RECEIVER_IRQ_ERR_ID_BIT) |
41		(1U << _HRT_CSS_RECEIVER_IRQ_ERR_FRAME_SYNC_BIT) |
42		(1U << _HRT_CSS_RECEIVER_IRQ_ERR_FRAME_DATA_BIT) |
43		(1U << _HRT_CSS_RECEIVER_IRQ_DATA_TIMEOUT_BIT) |
44		(1U << _HRT_CSS_RECEIVER_IRQ_ERR_ESCAPE_BIT);
45	/*(1U << _HRT_CSS_RECEIVER_IRQ_ERR_LINE_SYNC_BIT); */
46
47	receiver_port_reg_store(RX0_ID,
48				port,
49				_HRT_CSS_RECEIVER_IRQ_ENABLE_REG_IDX, bits);
50
51	/*
52	 * The CSI is nested into the Iunit IRQ's
53	 */
54	ia_css_irq_enable(IA_CSS_IRQ_INFO_CSS_RECEIVER_ERROR, true);
55
56	return;
57}
58
59/* This function converts between the enum used on the CSS API and the
60 * internal DLI enum type.
61 * We do not use an array for this since we cannot use named array
62 * initializers in Windows. Without that there is no easy way to guarantee
63 * that the array values would be in the correct order.
64 * */
65enum mipi_port_id ia_css_isys_port_to_mipi_port(enum mipi_port_id api_port)
66{
67	/* In this module the validity of the inptu variable should
68	 * have been checked already, so we do not check for erroneous
69	 * values. */
70	enum mipi_port_id port = MIPI_PORT0_ID;
71
72	if (api_port == MIPI_PORT1_ID)
73		port = MIPI_PORT1_ID;
74	else if (api_port == MIPI_PORT2_ID)
75		port = MIPI_PORT2_ID;
76
77	return port;
78}
79
80unsigned int ia_css_isys_rx_get_interrupt_reg(enum mipi_port_id port)
81{
82	return receiver_port_reg_load(RX0_ID,
83				      port,
84				      _HRT_CSS_RECEIVER_IRQ_STATUS_REG_IDX);
85}
86
87void ia_css_rx_get_irq_info(unsigned int *irq_infos)
88{
89	ia_css_rx_port_get_irq_info(MIPI_PORT1_ID, irq_infos);
90}
91
92void ia_css_rx_port_get_irq_info(enum mipi_port_id api_port,
93				 unsigned int *irq_infos)
94{
95	enum mipi_port_id port = ia_css_isys_port_to_mipi_port(api_port);
96
97	ia_css_isys_rx_get_irq_info(port, irq_infos);
98}
99
100void ia_css_isys_rx_get_irq_info(enum mipi_port_id port,
101				 unsigned int *irq_infos)
102{
103	unsigned int bits;
104
105	assert(irq_infos);
106	bits = ia_css_isys_rx_get_interrupt_reg(port);
107	*irq_infos = ia_css_isys_rx_translate_irq_infos(bits);
108}
109
110/* Translate register bits to CSS API enum mask */
111unsigned int ia_css_isys_rx_translate_irq_infos(unsigned int bits)
112{
113	unsigned int infos = 0;
114
115	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_OVERRUN_BIT))
116		infos |= IA_CSS_RX_IRQ_INFO_BUFFER_OVERRUN;
117	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_INIT_TIMEOUT_BIT))
118		infos |= IA_CSS_RX_IRQ_INFO_INIT_TIMEOUT;
119	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_SLEEP_MODE_ENTRY_BIT))
120		infos |= IA_CSS_RX_IRQ_INFO_ENTER_SLEEP_MODE;
121	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_SLEEP_MODE_EXIT_BIT))
122		infos |= IA_CSS_RX_IRQ_INFO_EXIT_SLEEP_MODE;
123	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_CORRECTED_BIT))
124		infos |= IA_CSS_RX_IRQ_INFO_ECC_CORRECTED;
125	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_SOT_HS_BIT))
126		infos |= IA_CSS_RX_IRQ_INFO_ERR_SOT;
127	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_SOT_SYNC_HS_BIT))
128		infos |= IA_CSS_RX_IRQ_INFO_ERR_SOT_SYNC;
129	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_CONTROL_BIT))
130		infos |= IA_CSS_RX_IRQ_INFO_ERR_CONTROL;
131	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_DOUBLE_BIT))
132		infos |= IA_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE;
133	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_CRC_BIT))
134		infos |= IA_CSS_RX_IRQ_INFO_ERR_CRC;
135	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_ID_BIT))
136		infos |= IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID;
137	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_FRAME_SYNC_BIT))
138		infos |= IA_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC;
139	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_FRAME_DATA_BIT))
140		infos |= IA_CSS_RX_IRQ_INFO_ERR_FRAME_DATA;
141	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_DATA_TIMEOUT_BIT))
142		infos |= IA_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT;
143	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_ESCAPE_BIT))
144		infos |= IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC;
145	if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_LINE_SYNC_BIT))
146		infos |= IA_CSS_RX_IRQ_INFO_ERR_LINE_SYNC;
147
148	return infos;
149}
150
151void ia_css_rx_clear_irq_info(unsigned int irq_infos)
152{
153	ia_css_rx_port_clear_irq_info(MIPI_PORT1_ID, irq_infos);
154}
155
156void ia_css_rx_port_clear_irq_info(enum mipi_port_id api_port,
157				   unsigned int irq_infos)
158{
159	enum mipi_port_id port = ia_css_isys_port_to_mipi_port(api_port);
160
161	ia_css_isys_rx_clear_irq_info(port, irq_infos);
162}
163
164void ia_css_isys_rx_clear_irq_info(enum mipi_port_id port,
165				   unsigned int irq_infos)
166{
167	hrt_data bits = receiver_port_reg_load(RX0_ID,
168					       port,
169					       _HRT_CSS_RECEIVER_IRQ_ENABLE_REG_IDX);
170
171	/* MW: Why do we remap the receiver bitmap */
172	if (irq_infos & IA_CSS_RX_IRQ_INFO_BUFFER_OVERRUN)
173		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_OVERRUN_BIT;
174	if (irq_infos & IA_CSS_RX_IRQ_INFO_INIT_TIMEOUT)
175		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_INIT_TIMEOUT_BIT;
176	if (irq_infos & IA_CSS_RX_IRQ_INFO_ENTER_SLEEP_MODE)
177		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_SLEEP_MODE_ENTRY_BIT;
178	if (irq_infos & IA_CSS_RX_IRQ_INFO_EXIT_SLEEP_MODE)
179		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_SLEEP_MODE_EXIT_BIT;
180	if (irq_infos & IA_CSS_RX_IRQ_INFO_ECC_CORRECTED)
181		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_CORRECTED_BIT;
182	if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_SOT)
183		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_SOT_HS_BIT;
184	if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_SOT_SYNC)
185		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_SOT_SYNC_HS_BIT;
186	if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_CONTROL)
187		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_CONTROL_BIT;
188	if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE)
189		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_DOUBLE_BIT;
190	if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_CRC)
191		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_CRC_BIT;
192	if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID)
193		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_ID_BIT;
194	if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC)
195		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_FRAME_SYNC_BIT;
196	if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_FRAME_DATA)
197		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_FRAME_DATA_BIT;
198	if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT)
199		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_DATA_TIMEOUT_BIT;
200	if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC)
201		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_ESCAPE_BIT;
202	if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_LINE_SYNC)
203		bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_LINE_SYNC_BIT;
204
205	receiver_port_reg_store(RX0_ID,
206				port,
207				_HRT_CSS_RECEIVER_IRQ_ENABLE_REG_IDX, bits);
208
209	return;
210}
211
212static int ia_css_isys_2400_set_fmt_type(enum atomisp_input_format input_format,
213					 unsigned int *fmt_type)
214{
215	switch (input_format) {
216	case ATOMISP_INPUT_FORMAT_RGB_888:
217		*fmt_type = MIPI_FORMAT_2400_RGB888;
218		break;
219	case ATOMISP_INPUT_FORMAT_RGB_555:
220		*fmt_type = MIPI_FORMAT_2400_RGB555;
221		break;
222	case ATOMISP_INPUT_FORMAT_RGB_444:
223		*fmt_type = MIPI_FORMAT_2400_RGB444;
224		break;
225	case ATOMISP_INPUT_FORMAT_RGB_565:
226		*fmt_type = MIPI_FORMAT_2400_RGB565;
227		break;
228	case ATOMISP_INPUT_FORMAT_RGB_666:
229		*fmt_type = MIPI_FORMAT_2400_RGB666;
230		break;
231	case ATOMISP_INPUT_FORMAT_RAW_8:
232		*fmt_type = MIPI_FORMAT_2400_RAW8;
233		break;
234	case ATOMISP_INPUT_FORMAT_RAW_10:
235		*fmt_type = MIPI_FORMAT_2400_RAW10;
236		break;
237	case ATOMISP_INPUT_FORMAT_RAW_6:
238		*fmt_type = MIPI_FORMAT_2400_RAW6;
239		break;
240	case ATOMISP_INPUT_FORMAT_RAW_7:
241		*fmt_type = MIPI_FORMAT_2400_RAW7;
242		break;
243	case ATOMISP_INPUT_FORMAT_RAW_12:
244		*fmt_type = MIPI_FORMAT_2400_RAW12;
245		break;
246	case ATOMISP_INPUT_FORMAT_RAW_14:
247		*fmt_type = MIPI_FORMAT_2400_RAW14;
248		break;
249	case ATOMISP_INPUT_FORMAT_YUV420_8:
250		*fmt_type = MIPI_FORMAT_2400_YUV420_8;
251		break;
252	case ATOMISP_INPUT_FORMAT_YUV420_10:
253		*fmt_type = MIPI_FORMAT_2400_YUV420_10;
254		break;
255	case ATOMISP_INPUT_FORMAT_YUV422_8:
256		*fmt_type = MIPI_FORMAT_2400_YUV422_8;
257		break;
258	case ATOMISP_INPUT_FORMAT_YUV422_10:
259		*fmt_type = MIPI_FORMAT_2400_YUV422_10;
260		break;
261	case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
262		*fmt_type = MIPI_FORMAT_2400_YUV420_8_LEGACY;
263		break;
264	case ATOMISP_INPUT_FORMAT_EMBEDDED:
265		*fmt_type = MIPI_FORMAT_2400_EMBEDDED;
266		break;
267	case ATOMISP_INPUT_FORMAT_RAW_16:
268		/* This is not specified by Arasan, so we use
269		 * 17 for now.
270		 */
271		*fmt_type = MIPI_FORMAT_2400_RAW16;
272		break;
273	case ATOMISP_INPUT_FORMAT_BINARY_8:
274		*fmt_type = MIPI_FORMAT_2400_CUSTOM0;
275		break;
276	case ATOMISP_INPUT_FORMAT_YUV420_16:
277	case ATOMISP_INPUT_FORMAT_YUV422_16:
278	default:
279		return -EINVAL;
280	}
281	return 0;
282}
283
284static int ia_css_isys_2401_set_fmt_type(enum atomisp_input_format input_format,
285					 unsigned int *fmt_type)
286{
287	switch (input_format) {
288	case ATOMISP_INPUT_FORMAT_RGB_888:
289		*fmt_type = MIPI_FORMAT_2401_RGB888;
290		break;
291	case ATOMISP_INPUT_FORMAT_RGB_555:
292		*fmt_type = MIPI_FORMAT_2401_RGB555;
293		break;
294	case ATOMISP_INPUT_FORMAT_RGB_444:
295		*fmt_type = MIPI_FORMAT_2401_RGB444;
296		break;
297	case ATOMISP_INPUT_FORMAT_RGB_565:
298		*fmt_type = MIPI_FORMAT_2401_RGB565;
299		break;
300	case ATOMISP_INPUT_FORMAT_RGB_666:
301		*fmt_type = MIPI_FORMAT_2401_RGB666;
302		break;
303	case ATOMISP_INPUT_FORMAT_RAW_8:
304		*fmt_type = MIPI_FORMAT_2401_RAW8;
305		break;
306	case ATOMISP_INPUT_FORMAT_RAW_10:
307		*fmt_type = MIPI_FORMAT_2401_RAW10;
308		break;
309	case ATOMISP_INPUT_FORMAT_RAW_6:
310		*fmt_type = MIPI_FORMAT_2401_RAW6;
311		break;
312	case ATOMISP_INPUT_FORMAT_RAW_7:
313		*fmt_type = MIPI_FORMAT_2401_RAW7;
314		break;
315	case ATOMISP_INPUT_FORMAT_RAW_12:
316		*fmt_type = MIPI_FORMAT_2401_RAW12;
317		break;
318	case ATOMISP_INPUT_FORMAT_RAW_14:
319		*fmt_type = MIPI_FORMAT_2401_RAW14;
320		break;
321	case ATOMISP_INPUT_FORMAT_YUV420_8:
322		*fmt_type = MIPI_FORMAT_2401_YUV420_8;
323		break;
324	case ATOMISP_INPUT_FORMAT_YUV420_10:
325		*fmt_type = MIPI_FORMAT_2401_YUV420_10;
326		break;
327	case ATOMISP_INPUT_FORMAT_YUV422_8:
328		*fmt_type = MIPI_FORMAT_2401_YUV422_8;
329		break;
330	case ATOMISP_INPUT_FORMAT_YUV422_10:
331		*fmt_type = MIPI_FORMAT_2401_YUV422_10;
332		break;
333	case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
334		*fmt_type = MIPI_FORMAT_2401_YUV420_8_LEGACY;
335		break;
336	case ATOMISP_INPUT_FORMAT_EMBEDDED:
337		*fmt_type = MIPI_FORMAT_2401_EMBEDDED;
338		break;
339	case ATOMISP_INPUT_FORMAT_USER_DEF1:
340		*fmt_type = MIPI_FORMAT_2401_CUSTOM0;
341		break;
342	case ATOMISP_INPUT_FORMAT_USER_DEF2:
343		*fmt_type = MIPI_FORMAT_2401_CUSTOM1;
344		break;
345	case ATOMISP_INPUT_FORMAT_USER_DEF3:
346		*fmt_type = MIPI_FORMAT_2401_CUSTOM2;
347		break;
348	case ATOMISP_INPUT_FORMAT_USER_DEF4:
349		*fmt_type = MIPI_FORMAT_2401_CUSTOM3;
350		break;
351	case ATOMISP_INPUT_FORMAT_USER_DEF5:
352		*fmt_type = MIPI_FORMAT_2401_CUSTOM4;
353		break;
354	case ATOMISP_INPUT_FORMAT_USER_DEF6:
355		*fmt_type = MIPI_FORMAT_2401_CUSTOM5;
356		break;
357	case ATOMISP_INPUT_FORMAT_USER_DEF7:
358		*fmt_type = MIPI_FORMAT_2401_CUSTOM6;
359		break;
360	case ATOMISP_INPUT_FORMAT_USER_DEF8:
361		*fmt_type = MIPI_FORMAT_2401_CUSTOM7;
362		break;
363
364	case ATOMISP_INPUT_FORMAT_YUV420_16:
365	case ATOMISP_INPUT_FORMAT_YUV422_16:
366	default:
367		return -EINVAL;
368	}
369	return 0;
370}
371
372int ia_css_isys_convert_stream_format_to_mipi_format(
373    enum atomisp_input_format input_format,
374    mipi_predictor_t compression,
375    unsigned int *fmt_type)
376{
377	assert(fmt_type);
378	/*
379	 * Custom (user defined) modes. Used for compressed
380	 * MIPI transfers
381	 *
382	 * Checkpatch thinks the indent before "if" is suspect
383	 * I think the only suspect part is the missing "else"
384	 * because of the return.
385	 */
386	if (compression != MIPI_PREDICTOR_NONE) {
387		switch (input_format) {
388		case ATOMISP_INPUT_FORMAT_RAW_6:
389			*fmt_type = 6;
390			break;
391		case ATOMISP_INPUT_FORMAT_RAW_7:
392			*fmt_type = 7;
393			break;
394		case ATOMISP_INPUT_FORMAT_RAW_8:
395			*fmt_type = 8;
396			break;
397		case ATOMISP_INPUT_FORMAT_RAW_10:
398			*fmt_type = 10;
399			break;
400		case ATOMISP_INPUT_FORMAT_RAW_12:
401			*fmt_type = 12;
402			break;
403		case ATOMISP_INPUT_FORMAT_RAW_14:
404			*fmt_type = 14;
405			break;
406		case ATOMISP_INPUT_FORMAT_RAW_16:
407			*fmt_type = 16;
408			break;
409		default:
410			return -EINVAL;
411		}
412		return 0;
413	}
414	/*
415	 * This mapping comes from the Arasan CSS function spec
416	 * (CSS_func_spec1.08_ahb_sep29_08.pdf).
417	 *
418	 * MW: For some reason the mapping is not 1-to-1
419	 */
420	if (IS_ISP2401)
421		return ia_css_isys_2401_set_fmt_type(input_format, fmt_type);
422	else
423		return ia_css_isys_2400_set_fmt_type(input_format, fmt_type);
424}
425
426static mipi_predictor_t sh_css_csi2_compression_type_2_mipi_predictor(
427    enum ia_css_csi2_compression_type type)
428{
429	mipi_predictor_t predictor = MIPI_PREDICTOR_NONE;
430
431	switch (type) {
432	case IA_CSS_CSI2_COMPRESSION_TYPE_1:
433		predictor = MIPI_PREDICTOR_TYPE1 - 1;
434		break;
435	case IA_CSS_CSI2_COMPRESSION_TYPE_2:
436		predictor = MIPI_PREDICTOR_TYPE2 - 1;
437		break;
438	default:
439		break;
440	}
441	return predictor;
442}
443
444int ia_css_isys_convert_compressed_format(
445    struct ia_css_csi2_compression *comp,
446    struct isp2401_input_system_cfg_s *cfg)
447{
448	int err = 0;
449
450	assert(comp);
451	assert(cfg);
452
453	if (comp->type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) {
454		/* compression register bit slicing
455		4 bit for each user defined data type
456			3 bit indicate compression scheme
457				000 No compression
458				001 10-6-10
459				010 10-7-10
460				011 10-8-10
461				100 12-6-12
462				101 12-6-12
463				100 12-7-12
464				110 12-8-12
465			1 bit indicate predictor
466		*/
467		if (comp->uncompressed_bits_per_pixel == UNCOMPRESSED_BITS_PER_PIXEL_10) {
468			switch (comp->compressed_bits_per_pixel) {
469			case COMPRESSED_BITS_PER_PIXEL_6:
470				cfg->csi_port_attr.comp_scheme = MIPI_COMPRESSOR_10_6_10;
471				break;
472			case COMPRESSED_BITS_PER_PIXEL_7:
473				cfg->csi_port_attr.comp_scheme = MIPI_COMPRESSOR_10_7_10;
474				break;
475			case COMPRESSED_BITS_PER_PIXEL_8:
476				cfg->csi_port_attr.comp_scheme = MIPI_COMPRESSOR_10_8_10;
477				break;
478			default:
479				err = -EINVAL;
480			}
481		} else if (comp->uncompressed_bits_per_pixel ==
482			   UNCOMPRESSED_BITS_PER_PIXEL_12) {
483			switch (comp->compressed_bits_per_pixel) {
484			case COMPRESSED_BITS_PER_PIXEL_6:
485				cfg->csi_port_attr.comp_scheme = MIPI_COMPRESSOR_12_6_12;
486				break;
487			case COMPRESSED_BITS_PER_PIXEL_7:
488				cfg->csi_port_attr.comp_scheme = MIPI_COMPRESSOR_12_7_12;
489				break;
490			case COMPRESSED_BITS_PER_PIXEL_8:
491				cfg->csi_port_attr.comp_scheme = MIPI_COMPRESSOR_12_8_12;
492				break;
493			default:
494				err = -EINVAL;
495			}
496		} else
497			err = -EINVAL;
498		cfg->csi_port_attr.comp_predictor =
499		    sh_css_csi2_compression_type_2_mipi_predictor(comp->type);
500		cfg->csi_port_attr.comp_enable = true;
501	} else /* No compression */
502		cfg->csi_port_attr.comp_enable = false;
503	return err;
504}
505
506unsigned int ia_css_csi2_calculate_input_system_alignment(
507    enum atomisp_input_format fmt_type)
508{
509	unsigned int memory_alignment_in_bytes = HIVE_ISP_DDR_WORD_BYTES;
510
511	switch (fmt_type) {
512	case ATOMISP_INPUT_FORMAT_RAW_6:
513	case ATOMISP_INPUT_FORMAT_RAW_7:
514	case ATOMISP_INPUT_FORMAT_RAW_8:
515	case ATOMISP_INPUT_FORMAT_RAW_10:
516	case ATOMISP_INPUT_FORMAT_RAW_12:
517	case ATOMISP_INPUT_FORMAT_RAW_14:
518		memory_alignment_in_bytes = 2 * ISP_VEC_NELEMS;
519		break;
520	case ATOMISP_INPUT_FORMAT_YUV420_8:
521	case ATOMISP_INPUT_FORMAT_YUV422_8:
522	case ATOMISP_INPUT_FORMAT_USER_DEF1:
523	case ATOMISP_INPUT_FORMAT_USER_DEF2:
524	case ATOMISP_INPUT_FORMAT_USER_DEF3:
525	case ATOMISP_INPUT_FORMAT_USER_DEF4:
526	case ATOMISP_INPUT_FORMAT_USER_DEF5:
527	case ATOMISP_INPUT_FORMAT_USER_DEF6:
528	case ATOMISP_INPUT_FORMAT_USER_DEF7:
529	case ATOMISP_INPUT_FORMAT_USER_DEF8:
530		/* Planar YUV formats need to have all planes aligned, this means
531		 * double the alignment for the Y plane if the horizontal decimation is 2. */
532		memory_alignment_in_bytes = 2 * HIVE_ISP_DDR_WORD_BYTES;
533		break;
534	case ATOMISP_INPUT_FORMAT_EMBEDDED:
535	default:
536		memory_alignment_in_bytes = HIVE_ISP_DDR_WORD_BYTES;
537		break;
538	}
539	return memory_alignment_in_bytes;
540}
541
542
543static const mipi_lane_cfg_t MIPI_PORT_LANES[N_RX_MODE][N_MIPI_PORT_ID] = {
544	{MIPI_4LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG},
545	{MIPI_3LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG},
546	{MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG},
547	{MIPI_1LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG},
548	{MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_2LANE_CFG},
549	{MIPI_3LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG},
550	{MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG},
551	{MIPI_1LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG}
552};
553
554void ia_css_isys_rx_configure(const rx_cfg_t *config,
555			      const enum ia_css_input_mode input_mode)
556{
557	bool any_port_enabled = false;
558	enum mipi_port_id port;
559
560	if ((!config)
561	    || (config->mode >= N_RX_MODE)
562	    || (config->port >= N_MIPI_PORT_ID)) {
563		assert(0);
564		return;
565	}
566	for (port = (enum mipi_port_id)0; port < N_MIPI_PORT_ID; port++) {
567		if (is_receiver_port_enabled(RX0_ID, port))
568			any_port_enabled = true;
569	}
570	/* AM: Check whether this is a problem with multiple
571	 * streams. MS: This is the case. */
572
573	port = config->port;
574	receiver_port_enable(RX0_ID, port, false);
575
576	port = config->port;
577
578	/* AM: Check whether this is a problem with multiple streams. */
579	if (MIPI_PORT_LANES[config->mode][port] != MIPI_0LANE_CFG) {
580		receiver_port_reg_store(RX0_ID, port,
581					_HRT_CSS_RECEIVER_FUNC_PROG_REG_IDX,
582					config->timeout);
583		receiver_port_reg_store(RX0_ID, port,
584					_HRT_CSS_RECEIVER_2400_INIT_COUNT_REG_IDX,
585					config->initcount);
586		receiver_port_reg_store(RX0_ID, port,
587					_HRT_CSS_RECEIVER_2400_SYNC_COUNT_REG_IDX,
588					config->synccount);
589		receiver_port_reg_store(RX0_ID, port,
590					_HRT_CSS_RECEIVER_2400_RX_COUNT_REG_IDX,
591					config->rxcount);
592
593		if (input_mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
594			/* MW: A bit of a hack, straight wiring of the capture
595			 * units,assuming they are linearly enumerated. */
596			input_system_sub_system_reg_store(INPUT_SYSTEM0_ID,
597							  GPREGS_UNIT0_ID,
598							  HIVE_ISYS_GPREG_MULTICAST_A_IDX
599							  + (unsigned int)port,
600							  INPUT_SYSTEM_CSI_BACKEND);
601			/* MW: Like the integration test example we overwite,
602			 * the GPREG_MUX register */
603			input_system_sub_system_reg_store(INPUT_SYSTEM0_ID,
604							  GPREGS_UNIT0_ID,
605							  HIVE_ISYS_GPREG_MUX_IDX,
606							  (input_system_multiplex_t)port);
607		} else {
608			/*
609			 * AM: A bit of a hack, wiring the input system.
610			 */
611			input_system_sub_system_reg_store(INPUT_SYSTEM0_ID,
612							  GPREGS_UNIT0_ID,
613							  HIVE_ISYS_GPREG_MULTICAST_A_IDX
614							  + (unsigned int)port,
615							  INPUT_SYSTEM_INPUT_BUFFER);
616			input_system_sub_system_reg_store(INPUT_SYSTEM0_ID,
617							  GPREGS_UNIT0_ID,
618							  HIVE_ISYS_GPREG_MUX_IDX,
619							  INPUT_SYSTEM_ACQUISITION_UNIT);
620		}
621	}
622	/*
623	 * The 2ppc is shared for all ports, so we cannot
624	 * disable->configure->enable individual ports
625	 */
626	/* AM: Check whether this is a problem with multiple streams. */
627	/* MS: 2ppc should be a property per binary and should be
628	 * enabled/disabled per binary.
629	 * Currently it is implemented as a system wide setting due
630	 * to effort and risks. */
631	if (!any_port_enabled) {
632		receiver_reg_store(RX0_ID,
633				   _HRT_CSS_RECEIVER_TWO_PIXEL_EN_REG_IDX,
634				   config->is_two_ppc);
635		receiver_reg_store(RX0_ID, _HRT_CSS_RECEIVER_BE_TWO_PPC_REG_IDX,
636				   config->is_two_ppc);
637	}
638	receiver_port_enable(RX0_ID, port, true);
639	/* TODO: JB: need to add the beneath used define to mizuchi */
640	/* sh_css_sw_hive_isp_css_2400_system_20121224_0125\css
641	 *                      \hrt\input_system_defs.h
642	 * #define INPUT_SYSTEM_CSI_RECEIVER_SELECT_BACKENG 0X207
643	 */
644	/* TODO: need better name for define
645	 * input_system_reg_store(INPUT_SYSTEM0_ID,
646	 *                INPUT_SYSTEM_CSI_RECEIVER_SELECT_BACKENG, 1);
647	 */
648	input_system_reg_store(INPUT_SYSTEM0_ID, 0x207, 1);
649
650	return;
651}
652
653void ia_css_isys_rx_disable(void)
654{
655	enum mipi_port_id port;
656
657	for (port = (enum mipi_port_id)0; port < N_MIPI_PORT_ID; port++) {
658		receiver_port_reg_store(RX0_ID, port,
659					_HRT_CSS_RECEIVER_DEVICE_READY_REG_IDX,
660					false);
661	}
662	return;
663}
664