xref: /linux/drivers/media/platform/qcom/camss/camss-vfe-4-7.c (revision 4f9786035f9e519db41375818e1d0b5f20da2f10)
14e1abf66STodor Tomov // SPDX-License-Identifier: GPL-2.0
24e1abf66STodor Tomov /*
34e1abf66STodor Tomov  * camss-vfe-4-7.c
44e1abf66STodor Tomov  *
54e1abf66STodor Tomov  * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v4.7
64e1abf66STodor Tomov  *
74e1abf66STodor Tomov  * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
84e1abf66STodor Tomov  * Copyright (C) 2015-2018 Linaro Ltd.
94e1abf66STodor Tomov  */
104e1abf66STodor Tomov 
112f6f8af6SRobert Foss #include <linux/device.h>
124e1abf66STodor Tomov #include <linux/interrupt.h>
133799eca5SArnd Bergmann #include <linux/io.h>
144e1abf66STodor Tomov #include <linux/iopoll.h>
154e1abf66STodor Tomov 
16c3177cb0SRobert Foss #include "camss.h"
174e1abf66STodor Tomov #include "camss-vfe.h"
18633b388fSRobert Foss #include "camss-vfe-gen1.h"
19633b388fSRobert Foss 
204e1abf66STodor Tomov 
214e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD		0x018
224e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_CORE	BIT(0)
234e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_CAMIF	BIT(1)
244e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_BUS	BIT(2)
254e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_BUS_BDG	BIT(3)
264e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_REGISTER	BIT(4)
274e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_PM	BIT(5)
284e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_BUS_MISR	BIT(6)
294e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_TESTGEN	BIT(7)
304e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_DSP	BIT(8)
314e1abf66STodor Tomov #define VFE_0_GLOBAL_RESET_CMD_IDLE_CGC	BIT(9)
324e1abf66STodor Tomov 
334e1abf66STodor Tomov #define VFE_0_MODULE_LENS_EN		0x040
344e1abf66STodor Tomov #define VFE_0_MODULE_LENS_EN_DEMUX		BIT(2)
354e1abf66STodor Tomov #define VFE_0_MODULE_LENS_EN_CHROMA_UPSAMPLE	BIT(3)
364e1abf66STodor Tomov 
374e1abf66STodor Tomov #define VFE_0_MODULE_ZOOM_EN		0x04c
384e1abf66STodor Tomov #define VFE_0_MODULE_ZOOM_EN_SCALE_ENC		BIT(1)
394e1abf66STodor Tomov #define VFE_0_MODULE_ZOOM_EN_CROP_ENC		BIT(2)
40312e1c85STodor Tomov #define VFE_0_MODULE_ZOOM_EN_REALIGN_BUF	BIT(9)
414e1abf66STodor Tomov 
424e1abf66STodor Tomov #define VFE_0_CORE_CFG			0x050
434e1abf66STodor Tomov #define VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR	0x4
444e1abf66STodor Tomov #define VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB	0x5
454e1abf66STodor Tomov #define VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY	0x6
464e1abf66STodor Tomov #define VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY	0x7
474e1abf66STodor Tomov #define VFE_0_CORE_CFG_COMPOSITE_REG_UPDATE_EN	BIT(4)
484e1abf66STodor Tomov 
494e1abf66STodor Tomov #define VFE_0_IRQ_CMD			0x058
504e1abf66STodor Tomov #define VFE_0_IRQ_CMD_GLOBAL_CLEAR	BIT(0)
514e1abf66STodor Tomov 
524e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0		0x05c
534e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_CAMIF_SOF			BIT(0)
544e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_CAMIF_EOF			BIT(1)
554e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n)		BIT((n) + 5)
564e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(n)		\
574e1abf66STodor Tomov 	((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n))
584e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(n)	BIT((n) + 8)
594e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(n)	BIT((n) + 25)
604e1abf66STodor Tomov #define VFE_0_IRQ_MASK_0_RESET_ACK			BIT(31)
614e1abf66STodor Tomov #define VFE_0_IRQ_MASK_1		0x060
624e1abf66STodor Tomov #define VFE_0_IRQ_MASK_1_CAMIF_ERROR			BIT(0)
634e1abf66STodor Tomov #define VFE_0_IRQ_MASK_1_VIOLATION			BIT(7)
644e1abf66STodor Tomov #define VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK		BIT(8)
654e1abf66STodor Tomov #define VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(n)	BIT((n) + 9)
664e1abf66STodor Tomov #define VFE_0_IRQ_MASK_1_RDIn_SOF(n)			BIT((n) + 29)
674e1abf66STodor Tomov 
684e1abf66STodor Tomov #define VFE_0_IRQ_CLEAR_0		0x064
694e1abf66STodor Tomov #define VFE_0_IRQ_CLEAR_1		0x068
704e1abf66STodor Tomov 
714e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0		0x06c
724e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0_CAMIF_SOF			BIT(0)
734e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n)		BIT((n) + 5)
744e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(n)		\
754e1abf66STodor Tomov 	((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n))
764e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(n)	BIT((n) + 8)
774e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(n)	BIT((n) + 25)
784e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_0_RESET_ACK			BIT(31)
794e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_1		0x070
804e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_1_VIOLATION			BIT(7)
814e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK		BIT(8)
824e1abf66STodor Tomov #define VFE_0_IRQ_STATUS_1_RDIn_SOF(n)			BIT((n) + 29)
834e1abf66STodor Tomov 
844e1abf66STodor Tomov #define VFE_0_IRQ_COMPOSITE_MASK_0	0x074
854e1abf66STodor Tomov #define VFE_0_VIOLATION_STATUS		0x07c
864e1abf66STodor Tomov 
874e1abf66STodor Tomov #define VFE_0_BUS_CMD			0x80
884e1abf66STodor Tomov #define VFE_0_BUS_CMD_Mx_RLD_CMD(x)	BIT(x)
894e1abf66STodor Tomov 
904e1abf66STodor Tomov #define VFE_0_BUS_CFG			0x084
914e1abf66STodor Tomov 
924e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x(x)		(0x90 + 0x4 * ((x) / 2))
934e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN			BIT(2)
94312e1c85STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN			BIT(3)
95312e1c85STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTRA		(0x1 << 4)
96312e1c85STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER		(0x2 << 4)
974e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA	(0x3 << 4)
984e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT		8
994e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA		0x0
1004e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0	0xc
1014e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1	0xd
1024e1abf66STodor Tomov #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2	0xe
1034e1abf66STodor Tomov 
1044e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(n)		(0x0a0 + 0x2c * (n))
1054e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT	0
1064e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(n)	(0x0a4 + 0x2c * (n))
1074e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(n)	(0x0ac + 0x2c * (n))
1084e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(n)		(0x0b4 + 0x2c * (n))
1094e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT	1
1104e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT	2
1114e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK	(0x1f << 2)
1124e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(n)		(0x0b8 + 0x2c * (n))
1134e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT	16
1144e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(n)	(0x0bc + 0x2c * (n))
1154e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(n)	(0x0c0 + 0x2c * (n))
1164e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(n)	\
1174e1abf66STodor Tomov 							(0x0c4 + 0x2c * (n))
1184e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(n)	\
1194e1abf66STodor Tomov 							(0x0c8 + 0x2c * (n))
1204e1abf66STodor Tomov #define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF	0xffffffff
1214e1abf66STodor Tomov 
1224e1abf66STodor Tomov #define VFE_0_BUS_PING_PONG_STATUS	0x338
1234e1abf66STodor Tomov 
1244e1abf66STodor Tomov #define VFE_0_BUS_BDG_CMD		0x400
1254e1abf66STodor Tomov #define VFE_0_BUS_BDG_CMD_HALT_REQ	1
1264e1abf66STodor Tomov 
1274e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_0		0x404
1284e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_0_CFG	0xaaa9aaa9
1294e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_1		0x408
1304e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_2		0x40c
1314e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_3		0x410
1324e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_4		0x414
1334e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_5		0x418
1344e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_6		0x41c
1354e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_7		0x420
1364e1abf66STodor Tomov #define VFE_0_BUS_BDG_QOS_CFG_7_CFG	0x0001aaa9
1374e1abf66STodor Tomov 
13840296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_BDG_QOS_CFG_0_CFG	0xaaa5aaa5
13940296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_BDG_QOS_CFG_3_CFG	0xaa55aaa5
14040296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_BDG_QOS_CFG_4_CFG	0xaa55aa55
14140296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_BDG_QOS_CFG_7_CFG	0x0005aa55
14240296e71SAngeloGioacchino Del Regno 
1434e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_0		0x424
1444e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_0_CFG	0xcccc0011
1454e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_1		0x428
1464e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_2		0x42c
1474e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_3		0x430
1484e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_4		0x434
1494e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_5		0x438
1504e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_6		0x43c
1514e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_7		0x440
1524e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_8		0x444
1534e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_9		0x448
1544e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_10		0x44c
1554e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_11		0x450
1564e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_12		0x454
1574e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_13		0x458
1584e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_14		0x45c
1594e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_15		0x460
1604e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_16		0x464
1614e1abf66STodor Tomov #define VFE_0_BUS_BDG_DS_CFG_16_CFG	0x40000103
1624e1abf66STodor Tomov 
16340296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_BDG_DS_CFG_0_CFG	0xcccc1111
16440296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_BDG_DS_CFG_16_CFG	0x00000110
16540296e71SAngeloGioacchino Del Regno 
1664e1abf66STodor Tomov #define VFE_0_RDI_CFG_x(x)		(0x46c + (0x4 * (x)))
1674e1abf66STodor Tomov #define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT	28
1684e1abf66STodor Tomov #define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK	(0xf << 28)
1694e1abf66STodor Tomov #define VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT	4
1704e1abf66STodor Tomov #define VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK		(0xf << 4)
1714e1abf66STodor Tomov #define VFE_0_RDI_CFG_x_RDI_EN_BIT		BIT(2)
1724e1abf66STodor Tomov #define VFE_0_RDI_CFG_x_MIPI_EN_BITS		0x3
1734e1abf66STodor Tomov 
1744e1abf66STodor Tomov #define VFE_0_CAMIF_CMD				0x478
1754e1abf66STodor Tomov #define VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY	0
1764e1abf66STodor Tomov #define VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY	1
1774e1abf66STodor Tomov #define VFE_0_CAMIF_CMD_NO_CHANGE		3
1784e1abf66STodor Tomov #define VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS	BIT(2)
1794e1abf66STodor Tomov #define VFE_0_CAMIF_CFG				0x47c
1804e1abf66STodor Tomov #define VFE_0_CAMIF_CFG_VFE_OUTPUT_EN		BIT(6)
1814e1abf66STodor Tomov #define VFE_0_CAMIF_FRAME_CFG			0x484
1824e1abf66STodor Tomov #define VFE_0_CAMIF_WINDOW_WIDTH_CFG		0x488
1834e1abf66STodor Tomov #define VFE_0_CAMIF_WINDOW_HEIGHT_CFG		0x48c
1844e1abf66STodor Tomov #define VFE_0_CAMIF_SUBSAMPLE_CFG		0x490
1854e1abf66STodor Tomov #define VFE_0_CAMIF_IRQ_FRAMEDROP_PATTERN	0x498
1864e1abf66STodor Tomov #define VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN	0x49c
1874e1abf66STodor Tomov #define VFE_0_CAMIF_STATUS			0x4a4
1884e1abf66STodor Tomov #define VFE_0_CAMIF_STATUS_HALT			BIT(31)
1894e1abf66STodor Tomov 
1904e1abf66STodor Tomov #define VFE_0_REG_UPDATE		0x4ac
1914e1abf66STodor Tomov #define VFE_0_REG_UPDATE_RDIn(n)		BIT(1 + (n))
1924e1abf66STodor Tomov #define VFE_0_REG_UPDATE_line_n(n)		\
1934e1abf66STodor Tomov 			((n) == VFE_LINE_PIX ? 1 : VFE_0_REG_UPDATE_RDIn(n))
1944e1abf66STodor Tomov 
1954e1abf66STodor Tomov #define VFE_0_DEMUX_CFG				0x560
1964e1abf66STodor Tomov #define VFE_0_DEMUX_CFG_PERIOD			0x3
1974e1abf66STodor Tomov #define VFE_0_DEMUX_GAIN_0			0x564
1984e1abf66STodor Tomov #define VFE_0_DEMUX_GAIN_0_CH0_EVEN		(0x80 << 0)
1994e1abf66STodor Tomov #define VFE_0_DEMUX_GAIN_0_CH0_ODD		(0x80 << 16)
2004e1abf66STodor Tomov #define VFE_0_DEMUX_GAIN_1			0x568
2014e1abf66STodor Tomov #define VFE_0_DEMUX_GAIN_1_CH1			(0x80 << 0)
2024e1abf66STodor Tomov #define VFE_0_DEMUX_GAIN_1_CH2			(0x80 << 16)
2034e1abf66STodor Tomov #define VFE_0_DEMUX_EVEN_CFG			0x574
2044e1abf66STodor Tomov #define VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV	0x9cac
2054e1abf66STodor Tomov #define VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU	0xac9c
2064e1abf66STodor Tomov #define VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY	0xc9ca
2074e1abf66STodor Tomov #define VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY	0xcac9
2084e1abf66STodor Tomov #define VFE_0_DEMUX_ODD_CFG			0x578
2094e1abf66STodor Tomov #define VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV	0x9cac
2104e1abf66STodor Tomov #define VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU	0xac9c
2114e1abf66STodor Tomov #define VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY	0xc9ca
2124e1abf66STodor Tomov #define VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY	0xcac9
2134e1abf66STodor Tomov 
2144e1abf66STodor Tomov #define VFE_0_SCALE_ENC_Y_CFG			0x91c
2154e1abf66STodor Tomov #define VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE		0x920
2164e1abf66STodor Tomov #define VFE_0_SCALE_ENC_Y_H_PHASE		0x924
2174e1abf66STodor Tomov #define VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE		0x934
2184e1abf66STodor Tomov #define VFE_0_SCALE_ENC_Y_V_PHASE		0x938
2194e1abf66STodor Tomov #define VFE_0_SCALE_ENC_CBCR_CFG		0x948
2204e1abf66STodor Tomov #define VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE	0x94c
2214e1abf66STodor Tomov #define VFE_0_SCALE_ENC_CBCR_H_PHASE		0x950
2224e1abf66STodor Tomov #define VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE	0x960
2234e1abf66STodor Tomov #define VFE_0_SCALE_ENC_CBCR_V_PHASE		0x964
2244e1abf66STodor Tomov 
2254e1abf66STodor Tomov #define VFE_0_CROP_ENC_Y_WIDTH			0x974
2264e1abf66STodor Tomov #define VFE_0_CROP_ENC_Y_HEIGHT			0x978
2274e1abf66STodor Tomov #define VFE_0_CROP_ENC_CBCR_WIDTH		0x97c
2284e1abf66STodor Tomov #define VFE_0_CROP_ENC_CBCR_HEIGHT		0x980
2294e1abf66STodor Tomov 
2304e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MAX_CFG			0x984
2314e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MAX_CFG_CH0		(0xff << 0)
2324e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MAX_CFG_CH1		(0xff << 8)
2334e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MAX_CFG_CH2		(0xff << 16)
2344e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MIN_CFG			0x988
2354e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MIN_CFG_CH0		(0x0 << 0)
2364e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MIN_CFG_CH1		(0x0 << 8)
2374e1abf66STodor Tomov #define VFE_0_CLAMP_ENC_MIN_CFG_CH2		(0x0 << 16)
2384e1abf66STodor Tomov 
239312e1c85STodor Tomov #define VFE_0_REALIGN_BUF_CFG			0xaac
240312e1c85STodor Tomov #define VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL     BIT(2)
241312e1c85STodor Tomov #define VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL     BIT(3)
242312e1c85STodor Tomov #define VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE      BIT(4)
243312e1c85STodor Tomov 
24440296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_IMAGE_MASTER_CMD		0xcec
24540296e71SAngeloGioacchino Del Regno #define VFE48_0_BUS_IMAGE_MASTER_n_SHIFT(x)	(2 * (x))
24640296e71SAngeloGioacchino Del Regno 
2474e1abf66STodor Tomov #define CAMIF_TIMEOUT_SLEEP_US 1000
2484e1abf66STodor Tomov #define CAMIF_TIMEOUT_ALL_US 1000000
2494e1abf66STodor Tomov 
2504e1abf66STodor Tomov #define MSM_VFE_VFE0_UB_SIZE 2047
2514e1abf66STodor Tomov #define MSM_VFE_VFE0_UB_SIZE_RDI (MSM_VFE_VFE0_UB_SIZE / 3)
2524e1abf66STodor Tomov #define MSM_VFE_VFE1_UB_SIZE 1535
2534e1abf66STodor Tomov #define MSM_VFE_VFE1_UB_SIZE_RDI (MSM_VFE_VFE1_UB_SIZE / 3)
2544e1abf66STodor Tomov 
vfe_get_ub_size(u8 vfe_id)255633b388fSRobert Foss static u16 vfe_get_ub_size(u8 vfe_id)
2564e1abf66STodor Tomov {
2574e1abf66STodor Tomov 	if (vfe_id == 0)
2584e1abf66STodor Tomov 		return MSM_VFE_VFE0_UB_SIZE_RDI;
2594e1abf66STodor Tomov 	else if (vfe_id == 1)
2604e1abf66STodor Tomov 		return MSM_VFE_VFE1_UB_SIZE_RDI;
2614e1abf66STodor Tomov 
2624e1abf66STodor Tomov 	return 0;
2634e1abf66STodor Tomov }
2644e1abf66STodor Tomov 
vfe_reg_clr(struct vfe_device * vfe,u32 reg,u32 clr_bits)2654e1abf66STodor Tomov static inline void vfe_reg_clr(struct vfe_device *vfe, u32 reg, u32 clr_bits)
2664e1abf66STodor Tomov {
2674e1abf66STodor Tomov 	u32 bits = readl_relaxed(vfe->base + reg);
2684e1abf66STodor Tomov 
2694e1abf66STodor Tomov 	writel_relaxed(bits & ~clr_bits, vfe->base + reg);
2704e1abf66STodor Tomov }
2714e1abf66STodor Tomov 
vfe_reg_set(struct vfe_device * vfe,u32 reg,u32 set_bits)2724e1abf66STodor Tomov static inline void vfe_reg_set(struct vfe_device *vfe, u32 reg, u32 set_bits)
2734e1abf66STodor Tomov {
2744e1abf66STodor Tomov 	u32 bits = readl_relaxed(vfe->base + reg);
2754e1abf66STodor Tomov 
2764e1abf66STodor Tomov 	writel_relaxed(bits | set_bits, vfe->base + reg);
2774e1abf66STodor Tomov }
2784e1abf66STodor Tomov 
vfe_global_reset(struct vfe_device * vfe)2794e1abf66STodor Tomov static void vfe_global_reset(struct vfe_device *vfe)
2804e1abf66STodor Tomov {
2814e1abf66STodor Tomov 	u32 reset_bits = VFE_0_GLOBAL_RESET_CMD_IDLE_CGC	|
2824e1abf66STodor Tomov 			 VFE_0_GLOBAL_RESET_CMD_DSP		|
2834e1abf66STodor Tomov 			 VFE_0_GLOBAL_RESET_CMD_TESTGEN		|
2844e1abf66STodor Tomov 			 VFE_0_GLOBAL_RESET_CMD_BUS_MISR	|
2854e1abf66STodor Tomov 			 VFE_0_GLOBAL_RESET_CMD_PM		|
2864e1abf66STodor Tomov 			 VFE_0_GLOBAL_RESET_CMD_REGISTER	|
2874e1abf66STodor Tomov 			 VFE_0_GLOBAL_RESET_CMD_BUS_BDG		|
2884e1abf66STodor Tomov 			 VFE_0_GLOBAL_RESET_CMD_BUS		|
2894e1abf66STodor Tomov 			 VFE_0_GLOBAL_RESET_CMD_CAMIF		|
2904e1abf66STodor Tomov 			 VFE_0_GLOBAL_RESET_CMD_CORE;
2914e1abf66STodor Tomov 
2924e1abf66STodor Tomov 	writel_relaxed(BIT(31), vfe->base + VFE_0_IRQ_MASK_0);
293633b388fSRobert Foss 
294633b388fSRobert Foss 	/* Enforce barrier between IRQ mask setup and global reset */
2954e1abf66STodor Tomov 	wmb();
2964e1abf66STodor Tomov 	writel_relaxed(reset_bits, vfe->base + VFE_0_GLOBAL_RESET_CMD);
2974e1abf66STodor Tomov }
2984e1abf66STodor Tomov 
vfe_halt_request(struct vfe_device * vfe)2994e1abf66STodor Tomov static void vfe_halt_request(struct vfe_device *vfe)
3004e1abf66STodor Tomov {
3014e1abf66STodor Tomov 	writel_relaxed(VFE_0_BUS_BDG_CMD_HALT_REQ,
3024e1abf66STodor Tomov 		       vfe->base + VFE_0_BUS_BDG_CMD);
3034e1abf66STodor Tomov }
3044e1abf66STodor Tomov 
vfe_halt_clear(struct vfe_device * vfe)3054e1abf66STodor Tomov static void vfe_halt_clear(struct vfe_device *vfe)
3064e1abf66STodor Tomov {
3074e1abf66STodor Tomov 	writel_relaxed(0x0, vfe->base + VFE_0_BUS_BDG_CMD);
3084e1abf66STodor Tomov }
3094e1abf66STodor Tomov 
vfe_wm_enable(struct vfe_device * vfe,u8 wm,u8 enable)310633b388fSRobert Foss static void vfe_wm_enable(struct vfe_device *vfe, u8 wm, u8 enable)
3114e1abf66STodor Tomov {
3124e1abf66STodor Tomov 	if (enable)
3134e1abf66STodor Tomov 		vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm),
3144e1abf66STodor Tomov 			    1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT);
3154e1abf66STodor Tomov 	else
3164e1abf66STodor Tomov 		vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm),
3174e1abf66STodor Tomov 			    1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT);
3184e1abf66STodor Tomov }
3194e1abf66STodor Tomov 
vfe_wm_frame_based(struct vfe_device * vfe,u8 wm,u8 enable)3204e1abf66STodor Tomov static void vfe_wm_frame_based(struct vfe_device *vfe, u8 wm, u8 enable)
3214e1abf66STodor Tomov {
3224e1abf66STodor Tomov 	if (enable)
3234e1abf66STodor Tomov 		vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm),
3244e1abf66STodor Tomov 			1 << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT);
3254e1abf66STodor Tomov 	else
3264e1abf66STodor Tomov 		vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm),
3274e1abf66STodor Tomov 			1 << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_BASED_SHIFT);
3284e1abf66STodor Tomov }
3294e1abf66STodor Tomov 
3304e1abf66STodor Tomov #define CALC_WORD(width, M, N) (((width) * (M) + (N) - 1) / (N))
3314e1abf66STodor Tomov 
vfe_word_per_line_by_pixel(u32 format,u32 pixel_per_line)332312e1c85STodor Tomov static int vfe_word_per_line_by_pixel(u32 format, u32 pixel_per_line)
3334e1abf66STodor Tomov {
3344e1abf66STodor Tomov 	int val = 0;
3354e1abf66STodor Tomov 
3364e1abf66STodor Tomov 	switch (format) {
3374e1abf66STodor Tomov 	case V4L2_PIX_FMT_NV12:
3384e1abf66STodor Tomov 	case V4L2_PIX_FMT_NV21:
3394e1abf66STodor Tomov 	case V4L2_PIX_FMT_NV16:
3404e1abf66STodor Tomov 	case V4L2_PIX_FMT_NV61:
3414e1abf66STodor Tomov 		val = CALC_WORD(pixel_per_line, 1, 8);
3424e1abf66STodor Tomov 		break;
3434e1abf66STodor Tomov 	case V4L2_PIX_FMT_YUYV:
3444e1abf66STodor Tomov 	case V4L2_PIX_FMT_YVYU:
3454e1abf66STodor Tomov 	case V4L2_PIX_FMT_UYVY:
3464e1abf66STodor Tomov 	case V4L2_PIX_FMT_VYUY:
3474e1abf66STodor Tomov 		val = CALC_WORD(pixel_per_line, 2, 8);
3484e1abf66STodor Tomov 		break;
3494e1abf66STodor Tomov 	}
3504e1abf66STodor Tomov 
3514e1abf66STodor Tomov 	return val;
3524e1abf66STodor Tomov }
3534e1abf66STodor Tomov 
vfe_word_per_line_by_bytes(u32 bytes_per_line)354312e1c85STodor Tomov static int vfe_word_per_line_by_bytes(u32 bytes_per_line)
355312e1c85STodor Tomov {
356312e1c85STodor Tomov 	return CALC_WORD(bytes_per_line, 1, 8);
357312e1c85STodor Tomov }
358312e1c85STodor Tomov 
vfe_get_wm_sizes(struct v4l2_pix_format_mplane * pix,u8 plane,u16 * width,u16 * height,u16 * bytesperline)3594e1abf66STodor Tomov static void vfe_get_wm_sizes(struct v4l2_pix_format_mplane *pix, u8 plane,
3604e1abf66STodor Tomov 			     u16 *width, u16 *height, u16 *bytesperline)
3614e1abf66STodor Tomov {
362749d8965STom Rix 	*width = pix->width;
363749d8965STom Rix 	*height = pix->height;
364749d8965STom Rix 
3654e1abf66STodor Tomov 	switch (pix->pixelformat) {
3664e1abf66STodor Tomov 	case V4L2_PIX_FMT_NV12:
3674e1abf66STodor Tomov 	case V4L2_PIX_FMT_NV21:
3684e1abf66STodor Tomov 		*bytesperline = pix->plane_fmt[0].bytesperline;
3694e1abf66STodor Tomov 		if (plane == 1)
3704e1abf66STodor Tomov 			*height /= 2;
3714e1abf66STodor Tomov 		break;
3724e1abf66STodor Tomov 	case V4L2_PIX_FMT_NV16:
3734e1abf66STodor Tomov 	case V4L2_PIX_FMT_NV61:
3744e1abf66STodor Tomov 		*bytesperline = pix->plane_fmt[0].bytesperline;
3754e1abf66STodor Tomov 		break;
376312e1c85STodor Tomov 	case V4L2_PIX_FMT_YUYV:
377312e1c85STodor Tomov 	case V4L2_PIX_FMT_YVYU:
378312e1c85STodor Tomov 	case V4L2_PIX_FMT_VYUY:
379312e1c85STodor Tomov 	case V4L2_PIX_FMT_UYVY:
380312e1c85STodor Tomov 		*bytesperline = pix->plane_fmt[plane].bytesperline;
381312e1c85STodor Tomov 		break;
3824e1abf66STodor Tomov 	}
3834e1abf66STodor Tomov }
3844e1abf66STodor Tomov 
vfe_wm_line_based(struct vfe_device * vfe,u32 wm,struct v4l2_pix_format_mplane * pix,u8 plane,u32 enable)3854e1abf66STodor Tomov static void vfe_wm_line_based(struct vfe_device *vfe, u32 wm,
3864e1abf66STodor Tomov 			      struct v4l2_pix_format_mplane *pix,
3874e1abf66STodor Tomov 			      u8 plane, u32 enable)
3884e1abf66STodor Tomov {
3894e1abf66STodor Tomov 	u32 reg;
3904e1abf66STodor Tomov 
3914e1abf66STodor Tomov 	if (enable) {
3924e1abf66STodor Tomov 		u16 width = 0, height = 0, bytesperline = 0, wpl;
3934e1abf66STodor Tomov 
3944e1abf66STodor Tomov 		vfe_get_wm_sizes(pix, plane, &width, &height, &bytesperline);
3954e1abf66STodor Tomov 
396312e1c85STodor Tomov 		wpl = vfe_word_per_line_by_pixel(pix->pixelformat, width);
3974e1abf66STodor Tomov 
3984e1abf66STodor Tomov 		reg = height - 1;
3994e1abf66STodor Tomov 		reg |= ((wpl + 3) / 4 - 1) << 16;
4004e1abf66STodor Tomov 
4014e1abf66STodor Tomov 		writel_relaxed(reg, vfe->base +
4024e1abf66STodor Tomov 			       VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));
4034e1abf66STodor Tomov 
404312e1c85STodor Tomov 		wpl = vfe_word_per_line_by_bytes(bytesperline);
4054e1abf66STodor Tomov 
4064e1abf66STodor Tomov 		reg = 0x3;
4074e1abf66STodor Tomov 		reg |= (height - 1) << 2;
4084e1abf66STodor Tomov 		reg |= ((wpl + 1) / 2) << 16;
4094e1abf66STodor Tomov 
4104e1abf66STodor Tomov 		writel_relaxed(reg, vfe->base +
4114e1abf66STodor Tomov 			       VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm));
4124e1abf66STodor Tomov 	} else {
4134e1abf66STodor Tomov 		writel_relaxed(0, vfe->base +
4144e1abf66STodor Tomov 			       VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));
4154e1abf66STodor Tomov 		writel_relaxed(0, vfe->base +
4164e1abf66STodor Tomov 			       VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm));
4174e1abf66STodor Tomov 	}
4184e1abf66STodor Tomov }
4194e1abf66STodor Tomov 
vfe_wm_set_framedrop_period(struct vfe_device * vfe,u8 wm,u8 per)4204e1abf66STodor Tomov static void vfe_wm_set_framedrop_period(struct vfe_device *vfe, u8 wm, u8 per)
4214e1abf66STodor Tomov {
4224e1abf66STodor Tomov 	u32 reg;
4234e1abf66STodor Tomov 
4244e1abf66STodor Tomov 	reg = readl_relaxed(vfe->base +
4254e1abf66STodor Tomov 			    VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm));
4264e1abf66STodor Tomov 
4274e1abf66STodor Tomov 	reg &= ~(VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK);
4284e1abf66STodor Tomov 
4294e1abf66STodor Tomov 	reg |= (per << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT)
4304e1abf66STodor Tomov 		& VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK;
4314e1abf66STodor Tomov 
4324e1abf66STodor Tomov 	writel_relaxed(reg,
4334e1abf66STodor Tomov 		       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm));
4344e1abf66STodor Tomov }
4354e1abf66STodor Tomov 
vfe_wm_set_framedrop_pattern(struct vfe_device * vfe,u8 wm,u32 pattern)4364e1abf66STodor Tomov static void vfe_wm_set_framedrop_pattern(struct vfe_device *vfe, u8 wm,
4374e1abf66STodor Tomov 					 u32 pattern)
4384e1abf66STodor Tomov {
4394e1abf66STodor Tomov 	writel_relaxed(pattern,
4404e1abf66STodor Tomov 	       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(wm));
4414e1abf66STodor Tomov }
4424e1abf66STodor Tomov 
vfe_wm_set_ub_cfg(struct vfe_device * vfe,u8 wm,u16 offset,u16 depth)4434e1abf66STodor Tomov static void vfe_wm_set_ub_cfg(struct vfe_device *vfe, u8 wm,
4444e1abf66STodor Tomov 			      u16 offset, u16 depth)
4454e1abf66STodor Tomov {
4464e1abf66STodor Tomov 	u32 reg;
4474e1abf66STodor Tomov 
4484e1abf66STodor Tomov 	reg = (offset << VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT) |
4494e1abf66STodor Tomov 		depth;
4504e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(wm));
4514e1abf66STodor Tomov }
4524e1abf66STodor Tomov 
vfe_bus_reload_wm(struct vfe_device * vfe,u8 wm)4534e1abf66STodor Tomov static void vfe_bus_reload_wm(struct vfe_device *vfe, u8 wm)
4544e1abf66STodor Tomov {
455633b388fSRobert Foss 	/* Enforce barrier between any outstanding register write */
4564e1abf66STodor Tomov 	wmb();
457633b388fSRobert Foss 
4584e1abf66STodor Tomov 	writel_relaxed(VFE_0_BUS_CMD_Mx_RLD_CMD(wm), vfe->base + VFE_0_BUS_CMD);
459633b388fSRobert Foss 
460633b388fSRobert Foss 	/* Use barrier to make sure bus reload is issued before anything else */
4614e1abf66STodor Tomov 	wmb();
4624e1abf66STodor Tomov }
4634e1abf66STodor Tomov 
vfe_wm_set_ping_addr(struct vfe_device * vfe,u8 wm,u32 addr)4644e1abf66STodor Tomov static void vfe_wm_set_ping_addr(struct vfe_device *vfe, u8 wm, u32 addr)
4654e1abf66STodor Tomov {
4664e1abf66STodor Tomov 	writel_relaxed(addr,
4674e1abf66STodor Tomov 		       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(wm));
4684e1abf66STodor Tomov }
4694e1abf66STodor Tomov 
vfe_wm_set_pong_addr(struct vfe_device * vfe,u8 wm,u32 addr)4704e1abf66STodor Tomov static void vfe_wm_set_pong_addr(struct vfe_device *vfe, u8 wm, u32 addr)
4714e1abf66STodor Tomov {
4724e1abf66STodor Tomov 	writel_relaxed(addr,
4734e1abf66STodor Tomov 		       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(wm));
4744e1abf66STodor Tomov }
4754e1abf66STodor Tomov 
vfe_wm_get_ping_pong_status(struct vfe_device * vfe,u8 wm)4764e1abf66STodor Tomov static int vfe_wm_get_ping_pong_status(struct vfe_device *vfe, u8 wm)
4774e1abf66STodor Tomov {
4784e1abf66STodor Tomov 	u32 reg;
4794e1abf66STodor Tomov 
4804e1abf66STodor Tomov 	reg = readl_relaxed(vfe->base + VFE_0_BUS_PING_PONG_STATUS);
4814e1abf66STodor Tomov 
4824e1abf66STodor Tomov 	return (reg >> wm) & 0x1;
4834e1abf66STodor Tomov }
4844e1abf66STodor Tomov 
vfe_bus_enable_wr_if(struct vfe_device * vfe,u8 enable)4854e1abf66STodor Tomov static void vfe_bus_enable_wr_if(struct vfe_device *vfe, u8 enable)
4864e1abf66STodor Tomov {
4874e1abf66STodor Tomov 	if (enable)
4884e1abf66STodor Tomov 		writel_relaxed(0x101, vfe->base + VFE_0_BUS_CFG);
4894e1abf66STodor Tomov 	else
4904e1abf66STodor Tomov 		writel_relaxed(0, vfe->base + VFE_0_BUS_CFG);
4914e1abf66STodor Tomov }
4924e1abf66STodor Tomov 
vfe_bus_connect_wm_to_rdi(struct vfe_device * vfe,u8 wm,enum vfe_line_id id)4934e1abf66STodor Tomov static void vfe_bus_connect_wm_to_rdi(struct vfe_device *vfe, u8 wm,
4944e1abf66STodor Tomov 				      enum vfe_line_id id)
4954e1abf66STodor Tomov {
4964e1abf66STodor Tomov 	u32 reg;
4974e1abf66STodor Tomov 
4984e1abf66STodor Tomov 	reg = VFE_0_RDI_CFG_x_MIPI_EN_BITS;
4994e1abf66STodor Tomov 	vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), reg);
5004e1abf66STodor Tomov 
5014e1abf66STodor Tomov 	reg = VFE_0_RDI_CFG_x_RDI_EN_BIT;
5024e1abf66STodor Tomov 	reg |= ((3 * id) << VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT) &
5034e1abf66STodor Tomov 		VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK;
5044e1abf66STodor Tomov 	vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id), reg);
5054e1abf66STodor Tomov 
5064e1abf66STodor Tomov 	switch (id) {
5074e1abf66STodor Tomov 	case VFE_LINE_RDI0:
5084e1abf66STodor Tomov 	default:
5094e1abf66STodor Tomov 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 <<
5104e1abf66STodor Tomov 		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5114e1abf66STodor Tomov 		break;
5124e1abf66STodor Tomov 	case VFE_LINE_RDI1:
5134e1abf66STodor Tomov 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 <<
5144e1abf66STodor Tomov 		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5154e1abf66STodor Tomov 		break;
5164e1abf66STodor Tomov 	case VFE_LINE_RDI2:
5174e1abf66STodor Tomov 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 <<
5184e1abf66STodor Tomov 		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5194e1abf66STodor Tomov 		break;
5204e1abf66STodor Tomov 	}
5214e1abf66STodor Tomov 
5224e1abf66STodor Tomov 	if (wm % 2 == 1)
5234e1abf66STodor Tomov 		reg <<= 16;
5244e1abf66STodor Tomov 
5254e1abf66STodor Tomov 	vfe_reg_set(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg);
5264e1abf66STodor Tomov }
5274e1abf66STodor Tomov 
vfe_wm_set_subsample(struct vfe_device * vfe,u8 wm)5284e1abf66STodor Tomov static void vfe_wm_set_subsample(struct vfe_device *vfe, u8 wm)
5294e1abf66STodor Tomov {
5304e1abf66STodor Tomov 	writel_relaxed(VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF,
5314e1abf66STodor Tomov 	       vfe->base +
5324e1abf66STodor Tomov 	       VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(wm));
5334e1abf66STodor Tomov }
5344e1abf66STodor Tomov 
vfe_bus_disconnect_wm_from_rdi(struct vfe_device * vfe,u8 wm,enum vfe_line_id id)5354e1abf66STodor Tomov static void vfe_bus_disconnect_wm_from_rdi(struct vfe_device *vfe, u8 wm,
5364e1abf66STodor Tomov 					   enum vfe_line_id id)
5374e1abf66STodor Tomov {
5384e1abf66STodor Tomov 	u32 reg;
5394e1abf66STodor Tomov 
5404e1abf66STodor Tomov 	reg = VFE_0_RDI_CFG_x_RDI_EN_BIT;
5414e1abf66STodor Tomov 	vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id), reg);
5424e1abf66STodor Tomov 
5434e1abf66STodor Tomov 	switch (id) {
5444e1abf66STodor Tomov 	case VFE_LINE_RDI0:
5454e1abf66STodor Tomov 	default:
5464e1abf66STodor Tomov 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 <<
5474e1abf66STodor Tomov 		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5484e1abf66STodor Tomov 		break;
5494e1abf66STodor Tomov 	case VFE_LINE_RDI1:
5504e1abf66STodor Tomov 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 <<
5514e1abf66STodor Tomov 		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5524e1abf66STodor Tomov 		break;
5534e1abf66STodor Tomov 	case VFE_LINE_RDI2:
5544e1abf66STodor Tomov 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 <<
5554e1abf66STodor Tomov 		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5564e1abf66STodor Tomov 		break;
5574e1abf66STodor Tomov 	}
5584e1abf66STodor Tomov 
5594e1abf66STodor Tomov 	if (wm % 2 == 1)
5604e1abf66STodor Tomov 		reg <<= 16;
5614e1abf66STodor Tomov 
5624e1abf66STodor Tomov 	vfe_reg_clr(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg);
5634e1abf66STodor Tomov }
5644e1abf66STodor Tomov 
vfe_set_xbar_cfg(struct vfe_device * vfe,struct vfe_output * output,u8 enable)5654e1abf66STodor Tomov static void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output,
5664e1abf66STodor Tomov 			     u8 enable)
5674e1abf66STodor Tomov {
5684e1abf66STodor Tomov 	struct vfe_line *line = container_of(output, struct vfe_line, output);
5694e1abf66STodor Tomov 	u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
5704e1abf66STodor Tomov 	u32 reg;
5714e1abf66STodor Tomov 
572312e1c85STodor Tomov 	switch (p) {
573312e1c85STodor Tomov 	case V4L2_PIX_FMT_NV12:
574312e1c85STodor Tomov 	case V4L2_PIX_FMT_NV21:
575312e1c85STodor Tomov 	case V4L2_PIX_FMT_NV16:
576312e1c85STodor Tomov 	case V4L2_PIX_FMT_NV61:
5774e1abf66STodor Tomov 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA <<
5784e1abf66STodor Tomov 			VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
5794e1abf66STodor Tomov 
580312e1c85STodor Tomov 		if (output->wm_idx[0] % 2 == 1)
5814e1abf66STodor Tomov 			reg <<= 16;
5824e1abf66STodor Tomov 
5834e1abf66STodor Tomov 		if (enable)
5844e1abf66STodor Tomov 			vfe_reg_set(vfe,
585312e1c85STodor Tomov 				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
5864e1abf66STodor Tomov 				    reg);
5874e1abf66STodor Tomov 		else
5884e1abf66STodor Tomov 			vfe_reg_clr(vfe,
589312e1c85STodor Tomov 				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
5904e1abf66STodor Tomov 				    reg);
591312e1c85STodor Tomov 
592312e1c85STodor Tomov 		reg = VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;
593312e1c85STodor Tomov 		if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV16)
594312e1c85STodor Tomov 			reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;
595312e1c85STodor Tomov 
596312e1c85STodor Tomov 		if (output->wm_idx[1] % 2 == 1)
597312e1c85STodor Tomov 			reg <<= 16;
598312e1c85STodor Tomov 
599312e1c85STodor Tomov 		if (enable)
600312e1c85STodor Tomov 			vfe_reg_set(vfe,
601312e1c85STodor Tomov 				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]),
602312e1c85STodor Tomov 				    reg);
603312e1c85STodor Tomov 		else
604312e1c85STodor Tomov 			vfe_reg_clr(vfe,
605312e1c85STodor Tomov 				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]),
606312e1c85STodor Tomov 				    reg);
607312e1c85STodor Tomov 		break;
608312e1c85STodor Tomov 	case V4L2_PIX_FMT_YUYV:
609312e1c85STodor Tomov 	case V4L2_PIX_FMT_YVYU:
610312e1c85STodor Tomov 	case V4L2_PIX_FMT_VYUY:
611312e1c85STodor Tomov 	case V4L2_PIX_FMT_UYVY:
612312e1c85STodor Tomov 		reg = VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN;
613312e1c85STodor Tomov 		reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;
614312e1c85STodor Tomov 
615312e1c85STodor Tomov 		if (p == V4L2_PIX_FMT_YUYV || p == V4L2_PIX_FMT_YVYU)
616312e1c85STodor Tomov 			reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;
617312e1c85STodor Tomov 
618312e1c85STodor Tomov 		if (output->wm_idx[0] % 2 == 1)
619312e1c85STodor Tomov 			reg <<= 16;
620312e1c85STodor Tomov 
621312e1c85STodor Tomov 		if (enable)
622312e1c85STodor Tomov 			vfe_reg_set(vfe,
623312e1c85STodor Tomov 				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
624312e1c85STodor Tomov 				    reg);
625312e1c85STodor Tomov 		else
626312e1c85STodor Tomov 			vfe_reg_clr(vfe,
627312e1c85STodor Tomov 				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
628312e1c85STodor Tomov 				    reg);
629312e1c85STodor Tomov 		break;
630312e1c85STodor Tomov 	default:
631312e1c85STodor Tomov 		break;
6324e1abf66STodor Tomov 	}
6334e1abf66STodor Tomov }
6344e1abf66STodor Tomov 
vfe_set_realign_cfg(struct vfe_device * vfe,struct vfe_line * line,u8 enable)635312e1c85STodor Tomov static void vfe_set_realign_cfg(struct vfe_device *vfe, struct vfe_line *line,
636312e1c85STodor Tomov 				u8 enable)
637312e1c85STodor Tomov {
638312e1c85STodor Tomov 	u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
639312e1c85STodor Tomov 	u32 val = VFE_0_MODULE_ZOOM_EN_REALIGN_BUF;
640312e1c85STodor Tomov 
641312e1c85STodor Tomov 	if (p != V4L2_PIX_FMT_YUYV && p != V4L2_PIX_FMT_YVYU &&
642312e1c85STodor Tomov 			p != V4L2_PIX_FMT_VYUY && p != V4L2_PIX_FMT_UYVY)
643312e1c85STodor Tomov 		return;
644312e1c85STodor Tomov 
645312e1c85STodor Tomov 	if (enable) {
646312e1c85STodor Tomov 		vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val);
647312e1c85STodor Tomov 	} else {
648312e1c85STodor Tomov 		vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val);
649312e1c85STodor Tomov 		return;
650312e1c85STodor Tomov 	}
651312e1c85STodor Tomov 
652312e1c85STodor Tomov 	val = VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE;
653312e1c85STodor Tomov 
654312e1c85STodor Tomov 	if (p == V4L2_PIX_FMT_UYVY || p == V4L2_PIX_FMT_YUYV)
655312e1c85STodor Tomov 		val |= VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL;
656312e1c85STodor Tomov 	else
657312e1c85STodor Tomov 		val |= VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL;
658312e1c85STodor Tomov 
659312e1c85STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_REALIGN_BUF_CFG);
660312e1c85STodor Tomov }
661312e1c85STodor Tomov 
vfe_set_rdi_cid(struct vfe_device * vfe,enum vfe_line_id id,u8 cid)6624e1abf66STodor Tomov static void vfe_set_rdi_cid(struct vfe_device *vfe, enum vfe_line_id id, u8 cid)
6634e1abf66STodor Tomov {
6644e1abf66STodor Tomov 	vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id),
6654e1abf66STodor Tomov 		    VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK);
6664e1abf66STodor Tomov 
6674e1abf66STodor Tomov 	vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id),
6684e1abf66STodor Tomov 		    cid << VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT);
6694e1abf66STodor Tomov }
6704e1abf66STodor Tomov 
vfe_reg_update(struct vfe_device * vfe,enum vfe_line_id line_id)6714e1abf66STodor Tomov static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id)
6724e1abf66STodor Tomov {
6734e1abf66STodor Tomov 	vfe->reg_update |= VFE_0_REG_UPDATE_line_n(line_id);
674633b388fSRobert Foss 
675633b388fSRobert Foss 	/* Enforce barrier between line update and commit */
6764e1abf66STodor Tomov 	wmb();
6774e1abf66STodor Tomov 	writel_relaxed(vfe->reg_update, vfe->base + VFE_0_REG_UPDATE);
678633b388fSRobert Foss 
679633b388fSRobert Foss 	/* Make sure register update is issued before further reg writes */
6804e1abf66STodor Tomov 	wmb();
6814e1abf66STodor Tomov }
6824e1abf66STodor Tomov 
vfe_reg_update_clear(struct vfe_device * vfe,enum vfe_line_id line_id)6834e1abf66STodor Tomov static inline void vfe_reg_update_clear(struct vfe_device *vfe,
6844e1abf66STodor Tomov 					enum vfe_line_id line_id)
6854e1abf66STodor Tomov {
6864e1abf66STodor Tomov 	vfe->reg_update &= ~VFE_0_REG_UPDATE_line_n(line_id);
6874e1abf66STodor Tomov }
6884e1abf66STodor Tomov 
vfe_enable_irq_wm_line(struct vfe_device * vfe,u8 wm,enum vfe_line_id line_id,u8 enable)6894e1abf66STodor Tomov static void vfe_enable_irq_wm_line(struct vfe_device *vfe, u8 wm,
6904e1abf66STodor Tomov 				   enum vfe_line_id line_id, u8 enable)
6914e1abf66STodor Tomov {
6924e1abf66STodor Tomov 	u32 irq_en0 = VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(wm) |
6934e1abf66STodor Tomov 		      VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id);
6944e1abf66STodor Tomov 	u32 irq_en1 = VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(wm) |
6954e1abf66STodor Tomov 		      VFE_0_IRQ_MASK_1_RDIn_SOF(line_id);
6964e1abf66STodor Tomov 
6974e1abf66STodor Tomov 	if (enable) {
6984e1abf66STodor Tomov 		vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
6994e1abf66STodor Tomov 		vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
7004e1abf66STodor Tomov 	} else {
7014e1abf66STodor Tomov 		vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0);
7024e1abf66STodor Tomov 		vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1);
7034e1abf66STodor Tomov 	}
7044e1abf66STodor Tomov }
7054e1abf66STodor Tomov 
vfe_enable_irq_pix_line(struct vfe_device * vfe,u8 comp,enum vfe_line_id line_id,u8 enable)7064e1abf66STodor Tomov static void vfe_enable_irq_pix_line(struct vfe_device *vfe, u8 comp,
7074e1abf66STodor Tomov 				    enum vfe_line_id line_id, u8 enable)
7084e1abf66STodor Tomov {
7094e1abf66STodor Tomov 	struct vfe_output *output = &vfe->line[line_id].output;
7104e1abf66STodor Tomov 	unsigned int i;
7114e1abf66STodor Tomov 	u32 irq_en0;
7124e1abf66STodor Tomov 	u32 irq_en1;
7134e1abf66STodor Tomov 	u32 comp_mask = 0;
7144e1abf66STodor Tomov 
7154e1abf66STodor Tomov 	irq_en0 = VFE_0_IRQ_MASK_0_CAMIF_SOF;
7164e1abf66STodor Tomov 	irq_en0 |= VFE_0_IRQ_MASK_0_CAMIF_EOF;
7174e1abf66STodor Tomov 	irq_en0 |= VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(comp);
7184e1abf66STodor Tomov 	irq_en0 |= VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id);
7194e1abf66STodor Tomov 	irq_en1 = VFE_0_IRQ_MASK_1_CAMIF_ERROR;
7204e1abf66STodor Tomov 	for (i = 0; i < output->wm_num; i++) {
7214e1abf66STodor Tomov 		irq_en1 |= VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(
7224e1abf66STodor Tomov 							output->wm_idx[i]);
7234e1abf66STodor Tomov 		comp_mask |= (1 << output->wm_idx[i]) << comp * 8;
7244e1abf66STodor Tomov 	}
7254e1abf66STodor Tomov 
7264e1abf66STodor Tomov 	if (enable) {
7274e1abf66STodor Tomov 		vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
7284e1abf66STodor Tomov 		vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
7294e1abf66STodor Tomov 		vfe_reg_set(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask);
7304e1abf66STodor Tomov 	} else {
7314e1abf66STodor Tomov 		vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0);
7324e1abf66STodor Tomov 		vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1);
7334e1abf66STodor Tomov 		vfe_reg_clr(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask);
7344e1abf66STodor Tomov 	}
7354e1abf66STodor Tomov }
7364e1abf66STodor Tomov 
vfe_enable_irq_common(struct vfe_device * vfe)7374e1abf66STodor Tomov static void vfe_enable_irq_common(struct vfe_device *vfe)
7384e1abf66STodor Tomov {
7394e1abf66STodor Tomov 	u32 irq_en0 = VFE_0_IRQ_MASK_0_RESET_ACK;
7404e1abf66STodor Tomov 	u32 irq_en1 = VFE_0_IRQ_MASK_1_VIOLATION |
7414e1abf66STodor Tomov 		      VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK;
7424e1abf66STodor Tomov 
7434e1abf66STodor Tomov 	vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
7444e1abf66STodor Tomov 	vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
7454e1abf66STodor Tomov }
7464e1abf66STodor Tomov 
vfe_set_demux_cfg(struct vfe_device * vfe,struct vfe_line * line)7474e1abf66STodor Tomov static void vfe_set_demux_cfg(struct vfe_device *vfe, struct vfe_line *line)
7484e1abf66STodor Tomov {
7494e1abf66STodor Tomov 	u32 val, even_cfg, odd_cfg;
7504e1abf66STodor Tomov 
7514e1abf66STodor Tomov 	writel_relaxed(VFE_0_DEMUX_CFG_PERIOD, vfe->base + VFE_0_DEMUX_CFG);
7524e1abf66STodor Tomov 
7534e1abf66STodor Tomov 	val = VFE_0_DEMUX_GAIN_0_CH0_EVEN | VFE_0_DEMUX_GAIN_0_CH0_ODD;
7544e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_0);
7554e1abf66STodor Tomov 
7564e1abf66STodor Tomov 	val = VFE_0_DEMUX_GAIN_1_CH1 | VFE_0_DEMUX_GAIN_1_CH2;
7574e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_1);
7584e1abf66STodor Tomov 
7594e1abf66STodor Tomov 	switch (line->fmt[MSM_VFE_PAD_SINK].code) {
76089936bfbSMartin Dørum 	case MEDIA_BUS_FMT_YUYV8_1X16:
7614e1abf66STodor Tomov 		even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV;
7624e1abf66STodor Tomov 		odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV;
7634e1abf66STodor Tomov 		break;
76489936bfbSMartin Dørum 	case MEDIA_BUS_FMT_YVYU8_1X16:
7654e1abf66STodor Tomov 		even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU;
7664e1abf66STodor Tomov 		odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU;
7674e1abf66STodor Tomov 		break;
76889936bfbSMartin Dørum 	case MEDIA_BUS_FMT_UYVY8_1X16:
7694e1abf66STodor Tomov 	default:
7704e1abf66STodor Tomov 		even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY;
7714e1abf66STodor Tomov 		odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY;
7724e1abf66STodor Tomov 		break;
77389936bfbSMartin Dørum 	case MEDIA_BUS_FMT_VYUY8_1X16:
7744e1abf66STodor Tomov 		even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY;
7754e1abf66STodor Tomov 		odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY;
7764e1abf66STodor Tomov 		break;
7774e1abf66STodor Tomov 	}
7784e1abf66STodor Tomov 
7794e1abf66STodor Tomov 	writel_relaxed(even_cfg, vfe->base + VFE_0_DEMUX_EVEN_CFG);
7804e1abf66STodor Tomov 	writel_relaxed(odd_cfg, vfe->base + VFE_0_DEMUX_ODD_CFG);
7814e1abf66STodor Tomov }
7824e1abf66STodor Tomov 
vfe_set_scale_cfg(struct vfe_device * vfe,struct vfe_line * line)7834e1abf66STodor Tomov static void vfe_set_scale_cfg(struct vfe_device *vfe, struct vfe_line *line)
7844e1abf66STodor Tomov {
7854e1abf66STodor Tomov 	u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
7864e1abf66STodor Tomov 	u32 reg;
7874e1abf66STodor Tomov 	u16 input, output;
7884e1abf66STodor Tomov 	u8 interp_reso;
7894e1abf66STodor Tomov 	u32 phase_mult;
7904e1abf66STodor Tomov 
7914e1abf66STodor Tomov 	writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_Y_CFG);
7924e1abf66STodor Tomov 
7934e1abf66STodor Tomov 	input = line->fmt[MSM_VFE_PAD_SINK].width - 1;
7944e1abf66STodor Tomov 	output = line->compose.width - 1;
7954e1abf66STodor Tomov 	reg = (output << 16) | input;
7964e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE);
7974e1abf66STodor Tomov 
7984e1abf66STodor Tomov 	interp_reso = vfe_calc_interp_reso(input, output);
7994e1abf66STodor Tomov 	phase_mult = input * (1 << (14 + interp_reso)) / output;
8004e1abf66STodor Tomov 	reg = (interp_reso << 28) | phase_mult;
8014e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_PHASE);
8024e1abf66STodor Tomov 
8034e1abf66STodor Tomov 	input = line->fmt[MSM_VFE_PAD_SINK].height - 1;
8044e1abf66STodor Tomov 	output = line->compose.height - 1;
8054e1abf66STodor Tomov 	reg = (output << 16) | input;
8064e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE);
8074e1abf66STodor Tomov 
8084e1abf66STodor Tomov 	interp_reso = vfe_calc_interp_reso(input, output);
8094e1abf66STodor Tomov 	phase_mult = input * (1 << (14 + interp_reso)) / output;
8104e1abf66STodor Tomov 	reg = (interp_reso << 28) | phase_mult;
8114e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_PHASE);
8124e1abf66STodor Tomov 
8134e1abf66STodor Tomov 	writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_CBCR_CFG);
8144e1abf66STodor Tomov 
8154e1abf66STodor Tomov 	input = line->fmt[MSM_VFE_PAD_SINK].width - 1;
8164e1abf66STodor Tomov 	output = line->compose.width / 2 - 1;
8174e1abf66STodor Tomov 	reg = (output << 16) | input;
8184e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE);
8194e1abf66STodor Tomov 
8204e1abf66STodor Tomov 	interp_reso = vfe_calc_interp_reso(input, output);
8214e1abf66STodor Tomov 	phase_mult = input * (1 << (14 + interp_reso)) / output;
8224e1abf66STodor Tomov 	reg = (interp_reso << 28) | phase_mult;
8234e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_PHASE);
8244e1abf66STodor Tomov 
8254e1abf66STodor Tomov 	input = line->fmt[MSM_VFE_PAD_SINK].height - 1;
8264e1abf66STodor Tomov 	output = line->compose.height - 1;
8274e1abf66STodor Tomov 	if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21)
8284e1abf66STodor Tomov 		output = line->compose.height / 2 - 1;
8294e1abf66STodor Tomov 	reg = (output << 16) | input;
8304e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE);
8314e1abf66STodor Tomov 
8324e1abf66STodor Tomov 	interp_reso = vfe_calc_interp_reso(input, output);
8334e1abf66STodor Tomov 	phase_mult = input * (1 << (14 + interp_reso)) / output;
8344e1abf66STodor Tomov 	reg = (interp_reso << 28) | phase_mult;
8354e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_PHASE);
8364e1abf66STodor Tomov }
8374e1abf66STodor Tomov 
vfe_set_crop_cfg(struct vfe_device * vfe,struct vfe_line * line)8384e1abf66STodor Tomov static void vfe_set_crop_cfg(struct vfe_device *vfe, struct vfe_line *line)
8394e1abf66STodor Tomov {
8404e1abf66STodor Tomov 	u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
8414e1abf66STodor Tomov 	u32 reg;
8424e1abf66STodor Tomov 	u16 first, last;
8434e1abf66STodor Tomov 
8444e1abf66STodor Tomov 	first = line->crop.left;
8454e1abf66STodor Tomov 	last = line->crop.left + line->crop.width - 1;
8464e1abf66STodor Tomov 	reg = (first << 16) | last;
8474e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_WIDTH);
8484e1abf66STodor Tomov 
8494e1abf66STodor Tomov 	first = line->crop.top;
8504e1abf66STodor Tomov 	last = line->crop.top + line->crop.height - 1;
8514e1abf66STodor Tomov 	reg = (first << 16) | last;
8524e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_HEIGHT);
8534e1abf66STodor Tomov 
8544e1abf66STodor Tomov 	first = line->crop.left / 2;
8554e1abf66STodor Tomov 	last = line->crop.left / 2 + line->crop.width / 2 - 1;
8564e1abf66STodor Tomov 	reg = (first << 16) | last;
8574e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_WIDTH);
8584e1abf66STodor Tomov 
8594e1abf66STodor Tomov 	first = line->crop.top;
8604e1abf66STodor Tomov 	last = line->crop.top + line->crop.height - 1;
8614e1abf66STodor Tomov 	if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21) {
8624e1abf66STodor Tomov 		first = line->crop.top / 2;
8634e1abf66STodor Tomov 		last = line->crop.top / 2 + line->crop.height / 2 - 1;
8644e1abf66STodor Tomov 	}
8654e1abf66STodor Tomov 	reg = (first << 16) | last;
8664e1abf66STodor Tomov 	writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_HEIGHT);
8674e1abf66STodor Tomov }
8684e1abf66STodor Tomov 
vfe_set_clamp_cfg(struct vfe_device * vfe)8694e1abf66STodor Tomov static void vfe_set_clamp_cfg(struct vfe_device *vfe)
8704e1abf66STodor Tomov {
8714e1abf66STodor Tomov 	u32 val = VFE_0_CLAMP_ENC_MAX_CFG_CH0 |
8724e1abf66STodor Tomov 		VFE_0_CLAMP_ENC_MAX_CFG_CH1 |
8734e1abf66STodor Tomov 		VFE_0_CLAMP_ENC_MAX_CFG_CH2;
8744e1abf66STodor Tomov 
8754e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MAX_CFG);
8764e1abf66STodor Tomov 
8774e1abf66STodor Tomov 	val = VFE_0_CLAMP_ENC_MIN_CFG_CH0 |
8784e1abf66STodor Tomov 		VFE_0_CLAMP_ENC_MIN_CFG_CH1 |
8794e1abf66STodor Tomov 		VFE_0_CLAMP_ENC_MIN_CFG_CH2;
8804e1abf66STodor Tomov 
8814e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MIN_CFG);
8824e1abf66STodor Tomov }
8834e1abf66STodor Tomov 
vfe_set_qos(struct vfe_device * vfe)884633b388fSRobert Foss static void vfe_set_qos(struct vfe_device *vfe)
8854e1abf66STodor Tomov {
8864e1abf66STodor Tomov 	u32 val = VFE_0_BUS_BDG_QOS_CFG_0_CFG;
8874e1abf66STodor Tomov 	u32 val7 = VFE_0_BUS_BDG_QOS_CFG_7_CFG;
8884e1abf66STodor Tomov 
8894e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_0);
8904e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_1);
8914e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_2);
8924e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_3);
8934e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_4);
8944e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_5);
8954e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_6);
8964e1abf66STodor Tomov 	writel_relaxed(val7, vfe->base + VFE_0_BUS_BDG_QOS_CFG_7);
8974e1abf66STodor Tomov }
8984e1abf66STodor Tomov 
vfe_set_ds(struct vfe_device * vfe)899633b388fSRobert Foss static void vfe_set_ds(struct vfe_device *vfe)
9004e1abf66STodor Tomov {
9014e1abf66STodor Tomov 	u32 val = VFE_0_BUS_BDG_DS_CFG_0_CFG;
9024e1abf66STodor Tomov 	u32 val16 = VFE_0_BUS_BDG_DS_CFG_16_CFG;
9034e1abf66STodor Tomov 
9044e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_0);
9054e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_1);
9064e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_2);
9074e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_3);
9084e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_4);
9094e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_5);
9104e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_6);
9114e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_7);
9124e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_8);
9134e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_9);
9144e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_10);
9154e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_11);
9164e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_12);
9174e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_13);
9184e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_14);
9194e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_DS_CFG_15);
9204e1abf66STodor Tomov 	writel_relaxed(val16, vfe->base + VFE_0_BUS_BDG_DS_CFG_16);
9214e1abf66STodor Tomov }
9224e1abf66STodor Tomov 
vfe_set_cgc_override(struct vfe_device * vfe,u8 wm,u8 enable)9234e1abf66STodor Tomov static void vfe_set_cgc_override(struct vfe_device *vfe, u8 wm, u8 enable)
9244e1abf66STodor Tomov {
9254e1abf66STodor Tomov 	/* empty */
9264e1abf66STodor Tomov }
9274e1abf66STodor Tomov 
vfe_set_camif_cfg(struct vfe_device * vfe,struct vfe_line * line)9284e1abf66STodor Tomov static void vfe_set_camif_cfg(struct vfe_device *vfe, struct vfe_line *line)
9294e1abf66STodor Tomov {
9304e1abf66STodor Tomov 	u32 val;
9314e1abf66STodor Tomov 
9324e1abf66STodor Tomov 	switch (line->fmt[MSM_VFE_PAD_SINK].code) {
93389936bfbSMartin Dørum 	case MEDIA_BUS_FMT_YUYV8_1X16:
9344e1abf66STodor Tomov 		val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR;
9354e1abf66STodor Tomov 		break;
93689936bfbSMartin Dørum 	case MEDIA_BUS_FMT_YVYU8_1X16:
9374e1abf66STodor Tomov 		val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB;
9384e1abf66STodor Tomov 		break;
93989936bfbSMartin Dørum 	case MEDIA_BUS_FMT_UYVY8_1X16:
9404e1abf66STodor Tomov 	default:
9414e1abf66STodor Tomov 		val = VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY;
9424e1abf66STodor Tomov 		break;
94389936bfbSMartin Dørum 	case MEDIA_BUS_FMT_VYUY8_1X16:
9444e1abf66STodor Tomov 		val = VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY;
9454e1abf66STodor Tomov 		break;
9464e1abf66STodor Tomov 	}
9474e1abf66STodor Tomov 
9484e1abf66STodor Tomov 	val |= VFE_0_CORE_CFG_COMPOSITE_REG_UPDATE_EN;
9494e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_CORE_CFG);
9504e1abf66STodor Tomov 
9514e1abf66STodor Tomov 	val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1;
9524e1abf66STodor Tomov 	val |= (line->fmt[MSM_VFE_PAD_SINK].height - 1) << 16;
9534e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_FRAME_CFG);
9544e1abf66STodor Tomov 
9554e1abf66STodor Tomov 	val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1;
9564e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_WIDTH_CFG);
9574e1abf66STodor Tomov 
9584e1abf66STodor Tomov 	val = line->fmt[MSM_VFE_PAD_SINK].height - 1;
9594e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_HEIGHT_CFG);
9604e1abf66STodor Tomov 
9614e1abf66STodor Tomov 	val = 0xffffffff;
9624e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_SUBSAMPLE_CFG);
9634e1abf66STodor Tomov 
9644e1abf66STodor Tomov 	val = 0xffffffff;
9654e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_FRAMEDROP_PATTERN);
9664e1abf66STodor Tomov 
9674e1abf66STodor Tomov 	val = 0xffffffff;
9684e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN);
9694e1abf66STodor Tomov 
9704e1abf66STodor Tomov 	val = VFE_0_RDI_CFG_x_MIPI_EN_BITS;
9714e1abf66STodor Tomov 	vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), val);
9724e1abf66STodor Tomov 
9734e1abf66STodor Tomov 	val = VFE_0_CAMIF_CFG_VFE_OUTPUT_EN;
9744e1abf66STodor Tomov 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_CFG);
9754e1abf66STodor Tomov }
9764e1abf66STodor Tomov 
vfe_set_camif_cmd(struct vfe_device * vfe,u8 enable)9774e1abf66STodor Tomov static void vfe_set_camif_cmd(struct vfe_device *vfe, u8 enable)
9784e1abf66STodor Tomov {
9794e1abf66STodor Tomov 	u32 cmd;
9804e1abf66STodor Tomov 
9814e1abf66STodor Tomov 	cmd = VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS | VFE_0_CAMIF_CMD_NO_CHANGE;
9824e1abf66STodor Tomov 	writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD);
983633b388fSRobert Foss 
984633b388fSRobert Foss 	/* Make sure camif command is issued written before it is changed again */
9854e1abf66STodor Tomov 	wmb();
9864e1abf66STodor Tomov 
9874e1abf66STodor Tomov 	if (enable)
9884e1abf66STodor Tomov 		cmd = VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY;
9894e1abf66STodor Tomov 	else
9904e1abf66STodor Tomov 		cmd = VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY;
9914e1abf66STodor Tomov 
9924e1abf66STodor Tomov 	writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD);
9934e1abf66STodor Tomov }
9944e1abf66STodor Tomov 
vfe_set_module_cfg(struct vfe_device * vfe,u8 enable)9954e1abf66STodor Tomov static void vfe_set_module_cfg(struct vfe_device *vfe, u8 enable)
9964e1abf66STodor Tomov {
9974e1abf66STodor Tomov 	u32 val_lens = VFE_0_MODULE_LENS_EN_DEMUX |
9984e1abf66STodor Tomov 		       VFE_0_MODULE_LENS_EN_CHROMA_UPSAMPLE;
9994e1abf66STodor Tomov 	u32 val_zoom = VFE_0_MODULE_ZOOM_EN_SCALE_ENC |
10004e1abf66STodor Tomov 		       VFE_0_MODULE_ZOOM_EN_CROP_ENC;
10014e1abf66STodor Tomov 
10024e1abf66STodor Tomov 	if (enable) {
1003312e1c85STodor Tomov 		vfe_reg_set(vfe, VFE_0_MODULE_LENS_EN, val_lens);
1004312e1c85STodor Tomov 		vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom);
10054e1abf66STodor Tomov 	} else {
1006312e1c85STodor Tomov 		vfe_reg_clr(vfe, VFE_0_MODULE_LENS_EN, val_lens);
1007312e1c85STodor Tomov 		vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom);
10084e1abf66STodor Tomov 	}
10094e1abf66STodor Tomov }
10104e1abf66STodor Tomov 
vfe_camif_wait_for_stop(struct vfe_device * vfe,struct device * dev)10114e1abf66STodor Tomov static int vfe_camif_wait_for_stop(struct vfe_device *vfe, struct device *dev)
10124e1abf66STodor Tomov {
10134e1abf66STodor Tomov 	u32 val;
10144e1abf66STodor Tomov 	int ret;
10154e1abf66STodor Tomov 
10164e1abf66STodor Tomov 	ret = readl_poll_timeout(vfe->base + VFE_0_CAMIF_STATUS,
10174e1abf66STodor Tomov 				 val,
10184e1abf66STodor Tomov 				 (val & VFE_0_CAMIF_STATUS_HALT),
10194e1abf66STodor Tomov 				 CAMIF_TIMEOUT_SLEEP_US,
10204e1abf66STodor Tomov 				 CAMIF_TIMEOUT_ALL_US);
10214e1abf66STodor Tomov 	if (ret < 0)
10224e1abf66STodor Tomov 		dev_err(dev, "%s: camif stop timeout\n", __func__);
10234e1abf66STodor Tomov 
10244e1abf66STodor Tomov 	return ret;
10254e1abf66STodor Tomov }
10264e1abf66STodor Tomov 
10274e1abf66STodor Tomov 
10284e1abf66STodor Tomov 
10294e1abf66STodor Tomov /*
1030ad46e1a8SRobert Foss  * vfe_isr - VFE module interrupt handler
10314e1abf66STodor Tomov  * @irq: Interrupt line
10324e1abf66STodor Tomov  * @dev: VFE device
10334e1abf66STodor Tomov  *
10344e1abf66STodor Tomov  * Return IRQ_HANDLED on success
10354e1abf66STodor Tomov  */
vfe_isr(int irq,void * dev)10364e1abf66STodor Tomov static irqreturn_t vfe_isr(int irq, void *dev)
10374e1abf66STodor Tomov {
10384e1abf66STodor Tomov 	struct vfe_device *vfe = dev;
10394e1abf66STodor Tomov 	u32 value0, value1;
10404e1abf66STodor Tomov 	int i, j;
10414e1abf66STodor Tomov 
1042ae44829aSRadoslav Tsvetkov 	vfe->res->hw_ops->isr_read(vfe, &value0, &value1);
10434e1abf66STodor Tomov 
1044c3177cb0SRobert Foss 	dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n",
10454e1abf66STodor Tomov 		value0, value1);
10464e1abf66STodor Tomov 
10474e1abf66STodor Tomov 	if (value0 & VFE_0_IRQ_STATUS_0_RESET_ACK)
10484e1abf66STodor Tomov 		vfe->isr_ops.reset_ack(vfe);
10494e1abf66STodor Tomov 
10504e1abf66STodor Tomov 	if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION)
1051ae44829aSRadoslav Tsvetkov 		vfe->res->hw_ops->violation_read(vfe);
10524e1abf66STodor Tomov 
10534e1abf66STodor Tomov 	if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK)
10544e1abf66STodor Tomov 		vfe->isr_ops.halt_ack(vfe);
10554e1abf66STodor Tomov 
1056ae44829aSRadoslav Tsvetkov 	for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++)
10574e1abf66STodor Tomov 		if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i))
10584e1abf66STodor Tomov 			vfe->isr_ops.reg_update(vfe, i);
10594e1abf66STodor Tomov 
10604e1abf66STodor Tomov 	if (value0 & VFE_0_IRQ_STATUS_0_CAMIF_SOF)
10614e1abf66STodor Tomov 		vfe->isr_ops.sof(vfe, VFE_LINE_PIX);
10624e1abf66STodor Tomov 
10634e1abf66STodor Tomov 	for (i = VFE_LINE_RDI0; i <= VFE_LINE_RDI2; i++)
10644e1abf66STodor Tomov 		if (value1 & VFE_0_IRQ_STATUS_1_RDIn_SOF(i))
10654e1abf66STodor Tomov 			vfe->isr_ops.sof(vfe, i);
10664e1abf66STodor Tomov 
10674e1abf66STodor Tomov 	for (i = 0; i < MSM_VFE_COMPOSITE_IRQ_NUM; i++)
10684e1abf66STodor Tomov 		if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(i)) {
10694e1abf66STodor Tomov 			vfe->isr_ops.comp_done(vfe, i);
10704e1abf66STodor Tomov 			for (j = 0; j < ARRAY_SIZE(vfe->wm_output_map); j++)
10714e1abf66STodor Tomov 				if (vfe->wm_output_map[j] == VFE_LINE_PIX)
10724e1abf66STodor Tomov 					value0 &= ~VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(j);
10734e1abf66STodor Tomov 		}
10744e1abf66STodor Tomov 
10754e1abf66STodor Tomov 	for (i = 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++)
10764e1abf66STodor Tomov 		if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(i))
10774e1abf66STodor Tomov 			vfe->isr_ops.wm_done(vfe, i);
10784e1abf66STodor Tomov 
10794e1abf66STodor Tomov 	return IRQ_HANDLED;
10804e1abf66STodor Tomov }
10814e1abf66STodor Tomov 
vfe_isr_read(struct vfe_device * vfe,u32 * value0,u32 * value1)1082633b388fSRobert Foss static void vfe_isr_read(struct vfe_device *vfe, u32 *value0, u32 *value1)
1083633b388fSRobert Foss {
1084633b388fSRobert Foss 	*value0 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_0);
1085633b388fSRobert Foss 	*value1 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_1);
1086633b388fSRobert Foss 
1087633b388fSRobert Foss 	writel_relaxed(*value0, vfe->base + VFE_0_IRQ_CLEAR_0);
1088633b388fSRobert Foss 	writel_relaxed(*value1, vfe->base + VFE_0_IRQ_CLEAR_1);
1089633b388fSRobert Foss 
1090633b388fSRobert Foss 	/* Enforce barrier between local & global IRQ clear */
1091633b388fSRobert Foss 	wmb();
1092633b388fSRobert Foss 	writel_relaxed(VFE_0_IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_0_IRQ_CMD);
1093633b388fSRobert Foss }
1094633b388fSRobert Foss 
vfe_violation_read(struct vfe_device * vfe)1095633b388fSRobert Foss static void vfe_violation_read(struct vfe_device *vfe)
1096633b388fSRobert Foss {
1097633b388fSRobert Foss 	u32 violation = readl_relaxed(vfe->base + VFE_0_VIOLATION_STATUS);
1098633b388fSRobert Foss 
1099633b388fSRobert Foss 	pr_err_ratelimited("VFE: violation = 0x%08x\n", violation);
1100633b388fSRobert Foss }
1101633b388fSRobert Foss 
1102633b388fSRobert Foss static const struct vfe_hw_ops_gen1 vfe_ops_gen1_4_7 = {
11034e1abf66STodor Tomov 	.bus_connect_wm_to_rdi = vfe_bus_connect_wm_to_rdi,
11044e1abf66STodor Tomov 	.bus_disconnect_wm_from_rdi = vfe_bus_disconnect_wm_from_rdi,
1105633b388fSRobert Foss 	.bus_enable_wr_if = vfe_bus_enable_wr_if,
1106633b388fSRobert Foss 	.bus_reload_wm = vfe_bus_reload_wm,
1107633b388fSRobert Foss 	.camif_wait_for_stop = vfe_camif_wait_for_stop,
11084e1abf66STodor Tomov 	.enable_irq_common = vfe_enable_irq_common,
1109633b388fSRobert Foss 	.enable_irq_pix_line = vfe_enable_irq_pix_line,
1110633b388fSRobert Foss 	.enable_irq_wm_line = vfe_enable_irq_wm_line,
1111633b388fSRobert Foss 	.get_ub_size = vfe_get_ub_size,
1112633b388fSRobert Foss 	.halt_clear = vfe_halt_clear,
1113633b388fSRobert Foss 	.halt_request = vfe_halt_request,
11144e1abf66STodor Tomov 	.set_camif_cfg = vfe_set_camif_cfg,
11154e1abf66STodor Tomov 	.set_camif_cmd = vfe_set_camif_cmd,
1116633b388fSRobert Foss 	.set_cgc_override = vfe_set_cgc_override,
1117633b388fSRobert Foss 	.set_clamp_cfg = vfe_set_clamp_cfg,
1118633b388fSRobert Foss 	.set_crop_cfg = vfe_set_crop_cfg,
1119633b388fSRobert Foss 	.set_demux_cfg = vfe_set_demux_cfg,
1120633b388fSRobert Foss 	.set_ds = vfe_set_ds,
11214e1abf66STodor Tomov 	.set_module_cfg = vfe_set_module_cfg,
1122633b388fSRobert Foss 	.set_qos = vfe_set_qos,
1123633b388fSRobert Foss 	.set_rdi_cid = vfe_set_rdi_cid,
1124633b388fSRobert Foss 	.set_realign_cfg = vfe_set_realign_cfg,
1125633b388fSRobert Foss 	.set_scale_cfg = vfe_set_scale_cfg,
1126633b388fSRobert Foss 	.set_xbar_cfg = vfe_set_xbar_cfg,
1127633b388fSRobert Foss 	.wm_enable = vfe_wm_enable,
1128633b388fSRobert Foss 	.wm_frame_based = vfe_wm_frame_based,
1129633b388fSRobert Foss 	.wm_get_ping_pong_status = vfe_wm_get_ping_pong_status,
1130633b388fSRobert Foss 	.wm_line_based = vfe_wm_line_based,
1131633b388fSRobert Foss 	.wm_set_framedrop_pattern = vfe_wm_set_framedrop_pattern,
1132633b388fSRobert Foss 	.wm_set_framedrop_period = vfe_wm_set_framedrop_period,
1133633b388fSRobert Foss 	.wm_set_ping_addr = vfe_wm_set_ping_addr,
1134633b388fSRobert Foss 	.wm_set_pong_addr = vfe_wm_set_pong_addr,
1135633b388fSRobert Foss 	.wm_set_subsample = vfe_wm_set_subsample,
1136633b388fSRobert Foss 	.wm_set_ub_cfg = vfe_wm_set_ub_cfg,
11374e1abf66STodor Tomov };
113840296e71SAngeloGioacchino Del Regno 
vfe_subdev_init(struct device * dev,struct vfe_device * vfe)1139633b388fSRobert Foss static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe)
114040296e71SAngeloGioacchino Del Regno {
1141633b388fSRobert Foss 	vfe->isr_ops = vfe_isr_ops_gen1;
1142633b388fSRobert Foss 	vfe->ops_gen1 = &vfe_ops_gen1_4_7;
1143633b388fSRobert Foss 	vfe->video_ops = vfe_video_ops_gen1;
114440296e71SAngeloGioacchino Del Regno }
114540296e71SAngeloGioacchino Del Regno 
1146633b388fSRobert Foss const struct vfe_hw_ops vfe_ops_4_7 = {
114740296e71SAngeloGioacchino Del Regno 	.global_reset = vfe_global_reset,
1148d2e86540SRobert Foss 	.hw_version = vfe_hw_version,
114940296e71SAngeloGioacchino Del Regno 	.isr_read = vfe_isr_read,
115040296e71SAngeloGioacchino Del Regno 	.isr = vfe_isr,
11512f6f8af6SRobert Foss 	.pm_domain_off = vfe_pm_domain_off,
11522f6f8af6SRobert Foss 	.pm_domain_on = vfe_pm_domain_on,
1153633b388fSRobert Foss 	.reg_update_clear = vfe_reg_update_clear,
1154633b388fSRobert Foss 	.reg_update = vfe_reg_update,
1155633b388fSRobert Foss 	.subdev_init = vfe_subdev_init,
1156633b388fSRobert Foss 	.vfe_disable = vfe_gen1_disable,
1157633b388fSRobert Foss 	.vfe_enable = vfe_gen1_enable,
1158633b388fSRobert Foss 	.vfe_halt = vfe_gen1_halt,
1159633b388fSRobert Foss 	.violation_read = vfe_violation_read,
116040296e71SAngeloGioacchino Del Regno };
1161