xref: /OK3568_Linux_fs/kernel/drivers/media/platform/qcom/camss/camss-vfe-4-1.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * camss-vfe-4-1.c
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v4.1
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
8*4882a593Smuzhiyun  * Copyright (C) 2015-2018 Linaro Ltd.
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/interrupt.h>
12*4882a593Smuzhiyun #include <linux/io.h>
13*4882a593Smuzhiyun #include <linux/iopoll.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include "camss-vfe.h"
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define VFE_0_HW_VERSION		0x000
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define VFE_0_GLOBAL_RESET_CMD		0x00c
20*4882a593Smuzhiyun #define VFE_0_GLOBAL_RESET_CMD_CORE	BIT(0)
21*4882a593Smuzhiyun #define VFE_0_GLOBAL_RESET_CMD_CAMIF	BIT(1)
22*4882a593Smuzhiyun #define VFE_0_GLOBAL_RESET_CMD_BUS	BIT(2)
23*4882a593Smuzhiyun #define VFE_0_GLOBAL_RESET_CMD_BUS_BDG	BIT(3)
24*4882a593Smuzhiyun #define VFE_0_GLOBAL_RESET_CMD_REGISTER	BIT(4)
25*4882a593Smuzhiyun #define VFE_0_GLOBAL_RESET_CMD_TIMER	BIT(5)
26*4882a593Smuzhiyun #define VFE_0_GLOBAL_RESET_CMD_PM	BIT(6)
27*4882a593Smuzhiyun #define VFE_0_GLOBAL_RESET_CMD_BUS_MISR	BIT(7)
28*4882a593Smuzhiyun #define VFE_0_GLOBAL_RESET_CMD_TESTGEN	BIT(8)
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #define VFE_0_MODULE_CFG		0x018
31*4882a593Smuzhiyun #define VFE_0_MODULE_CFG_DEMUX			BIT(2)
32*4882a593Smuzhiyun #define VFE_0_MODULE_CFG_CHROMA_UPSAMPLE	BIT(3)
33*4882a593Smuzhiyun #define VFE_0_MODULE_CFG_SCALE_ENC		BIT(23)
34*4882a593Smuzhiyun #define VFE_0_MODULE_CFG_CROP_ENC		BIT(27)
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define VFE_0_CORE_CFG			0x01c
37*4882a593Smuzhiyun #define VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR	0x4
38*4882a593Smuzhiyun #define VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB	0x5
39*4882a593Smuzhiyun #define VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY	0x6
40*4882a593Smuzhiyun #define VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY	0x7
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #define VFE_0_IRQ_CMD			0x024
43*4882a593Smuzhiyun #define VFE_0_IRQ_CMD_GLOBAL_CLEAR	BIT(0)
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_0		0x028
46*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_0_CAMIF_SOF			BIT(0)
47*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_0_CAMIF_EOF			BIT(1)
48*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n)		BIT((n) + 5)
49*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(n)		\
50*4882a593Smuzhiyun 	((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_MASK_0_RDIn_REG_UPDATE(n))
51*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(n)	BIT((n) + 8)
52*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(n)	BIT((n) + 25)
53*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_0_RESET_ACK			BIT(31)
54*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_1		0x02c
55*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_1_CAMIF_ERROR			BIT(0)
56*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_1_VIOLATION			BIT(7)
57*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK		BIT(8)
58*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(n)	BIT((n) + 9)
59*4882a593Smuzhiyun #define VFE_0_IRQ_MASK_1_RDIn_SOF(n)			BIT((n) + 29)
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #define VFE_0_IRQ_CLEAR_0		0x030
62*4882a593Smuzhiyun #define VFE_0_IRQ_CLEAR_1		0x034
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun #define VFE_0_IRQ_STATUS_0		0x038
65*4882a593Smuzhiyun #define VFE_0_IRQ_STATUS_0_CAMIF_SOF			BIT(0)
66*4882a593Smuzhiyun #define VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n)		BIT((n) + 5)
67*4882a593Smuzhiyun #define VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(n)		\
68*4882a593Smuzhiyun 	((n) == VFE_LINE_PIX ? BIT(4) : VFE_0_IRQ_STATUS_0_RDIn_REG_UPDATE(n))
69*4882a593Smuzhiyun #define VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(n)	BIT((n) + 8)
70*4882a593Smuzhiyun #define VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(n)	BIT((n) + 25)
71*4882a593Smuzhiyun #define VFE_0_IRQ_STATUS_0_RESET_ACK			BIT(31)
72*4882a593Smuzhiyun #define VFE_0_IRQ_STATUS_1		0x03c
73*4882a593Smuzhiyun #define VFE_0_IRQ_STATUS_1_VIOLATION			BIT(7)
74*4882a593Smuzhiyun #define VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK		BIT(8)
75*4882a593Smuzhiyun #define VFE_0_IRQ_STATUS_1_RDIn_SOF(n)			BIT((n) + 29)
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun #define VFE_0_IRQ_COMPOSITE_MASK_0	0x40
78*4882a593Smuzhiyun #define VFE_0_VIOLATION_STATUS		0x48
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun #define VFE_0_BUS_CMD			0x4c
81*4882a593Smuzhiyun #define VFE_0_BUS_CMD_Mx_RLD_CMD(x)	BIT(x)
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun #define VFE_0_BUS_CFG			0x050
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun #define VFE_0_BUS_XBAR_CFG_x(x)		(0x58 + 0x4 * ((x) / 2))
86*4882a593Smuzhiyun #define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN			BIT(1)
87*4882a593Smuzhiyun #define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA	(0x3 << 4)
88*4882a593Smuzhiyun #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT		8
89*4882a593Smuzhiyun #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA		0
90*4882a593Smuzhiyun #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0	5
91*4882a593Smuzhiyun #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1	6
92*4882a593Smuzhiyun #define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2	7
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(n)		(0x06c + 0x24 * (n))
95*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT	0
96*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_FRM_BASED_SHIFT	1
97*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(n)	(0x070 + 0x24 * (n))
98*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(n)	(0x074 + 0x24 * (n))
99*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(n)		(0x078 + 0x24 * (n))
100*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT	2
101*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK	(0x1f << 2)
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(n)		(0x07c + 0x24 * (n))
104*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT	16
105*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(n)	(0x080 + 0x24 * (n))
106*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(n)	(0x084 + 0x24 * (n))
107*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(n)	\
108*4882a593Smuzhiyun 							(0x088 + 0x24 * (n))
109*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(n)	\
110*4882a593Smuzhiyun 							(0x08c + 0x24 * (n))
111*4882a593Smuzhiyun #define VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF	0xffffffff
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun #define VFE_0_BUS_PING_PONG_STATUS	0x268
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun #define VFE_0_BUS_BDG_CMD		0x2c0
116*4882a593Smuzhiyun #define VFE_0_BUS_BDG_CMD_HALT_REQ	1
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun #define VFE_0_BUS_BDG_QOS_CFG_0		0x2c4
119*4882a593Smuzhiyun #define VFE_0_BUS_BDG_QOS_CFG_0_CFG	0xaaa5aaa5
120*4882a593Smuzhiyun #define VFE_0_BUS_BDG_QOS_CFG_1		0x2c8
121*4882a593Smuzhiyun #define VFE_0_BUS_BDG_QOS_CFG_2		0x2cc
122*4882a593Smuzhiyun #define VFE_0_BUS_BDG_QOS_CFG_3		0x2d0
123*4882a593Smuzhiyun #define VFE_0_BUS_BDG_QOS_CFG_4		0x2d4
124*4882a593Smuzhiyun #define VFE_0_BUS_BDG_QOS_CFG_5		0x2d8
125*4882a593Smuzhiyun #define VFE_0_BUS_BDG_QOS_CFG_6		0x2dc
126*4882a593Smuzhiyun #define VFE_0_BUS_BDG_QOS_CFG_7		0x2e0
127*4882a593Smuzhiyun #define VFE_0_BUS_BDG_QOS_CFG_7_CFG	0x0001aaa5
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun #define VFE_0_RDI_CFG_x(x)		(0x2e8 + (0x4 * (x)))
130*4882a593Smuzhiyun #define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT	28
131*4882a593Smuzhiyun #define VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK	(0xf << 28)
132*4882a593Smuzhiyun #define VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT	4
133*4882a593Smuzhiyun #define VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK		(0xf << 4)
134*4882a593Smuzhiyun #define VFE_0_RDI_CFG_x_RDI_EN_BIT		BIT(2)
135*4882a593Smuzhiyun #define VFE_0_RDI_CFG_x_MIPI_EN_BITS		0x3
136*4882a593Smuzhiyun #define VFE_0_RDI_CFG_x_RDI_Mr_FRAME_BASED_EN(r)	BIT(16 + (r))
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun #define VFE_0_CAMIF_CMD				0x2f4
139*4882a593Smuzhiyun #define VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY	0
140*4882a593Smuzhiyun #define VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY	1
141*4882a593Smuzhiyun #define VFE_0_CAMIF_CMD_NO_CHANGE		3
142*4882a593Smuzhiyun #define VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS	BIT(2)
143*4882a593Smuzhiyun #define VFE_0_CAMIF_CFG				0x2f8
144*4882a593Smuzhiyun #define VFE_0_CAMIF_CFG_VFE_OUTPUT_EN		BIT(6)
145*4882a593Smuzhiyun #define VFE_0_CAMIF_FRAME_CFG			0x300
146*4882a593Smuzhiyun #define VFE_0_CAMIF_WINDOW_WIDTH_CFG		0x304
147*4882a593Smuzhiyun #define VFE_0_CAMIF_WINDOW_HEIGHT_CFG		0x308
148*4882a593Smuzhiyun #define VFE_0_CAMIF_SUBSAMPLE_CFG_0		0x30c
149*4882a593Smuzhiyun #define VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN	0x314
150*4882a593Smuzhiyun #define VFE_0_CAMIF_STATUS			0x31c
151*4882a593Smuzhiyun #define VFE_0_CAMIF_STATUS_HALT			BIT(31)
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun #define VFE_0_REG_UPDATE			0x378
154*4882a593Smuzhiyun #define VFE_0_REG_UPDATE_RDIn(n)		BIT(1 + (n))
155*4882a593Smuzhiyun #define VFE_0_REG_UPDATE_line_n(n)		\
156*4882a593Smuzhiyun 			((n) == VFE_LINE_PIX ? 1 : VFE_0_REG_UPDATE_RDIn(n))
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun #define VFE_0_DEMUX_CFG				0x424
159*4882a593Smuzhiyun #define VFE_0_DEMUX_CFG_PERIOD			0x3
160*4882a593Smuzhiyun #define VFE_0_DEMUX_GAIN_0			0x428
161*4882a593Smuzhiyun #define VFE_0_DEMUX_GAIN_0_CH0_EVEN		(0x80 << 0)
162*4882a593Smuzhiyun #define VFE_0_DEMUX_GAIN_0_CH0_ODD		(0x80 << 16)
163*4882a593Smuzhiyun #define VFE_0_DEMUX_GAIN_1			0x42c
164*4882a593Smuzhiyun #define VFE_0_DEMUX_GAIN_1_CH1			(0x80 << 0)
165*4882a593Smuzhiyun #define VFE_0_DEMUX_GAIN_1_CH2			(0x80 << 16)
166*4882a593Smuzhiyun #define VFE_0_DEMUX_EVEN_CFG			0x438
167*4882a593Smuzhiyun #define VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV	0x9cac
168*4882a593Smuzhiyun #define VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU	0xac9c
169*4882a593Smuzhiyun #define VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY	0xc9ca
170*4882a593Smuzhiyun #define VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY	0xcac9
171*4882a593Smuzhiyun #define VFE_0_DEMUX_ODD_CFG			0x43c
172*4882a593Smuzhiyun #define VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV	0x9cac
173*4882a593Smuzhiyun #define VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU	0xac9c
174*4882a593Smuzhiyun #define VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY	0xc9ca
175*4882a593Smuzhiyun #define VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY	0xcac9
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun #define VFE_0_SCALE_ENC_Y_CFG			0x75c
178*4882a593Smuzhiyun #define VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE		0x760
179*4882a593Smuzhiyun #define VFE_0_SCALE_ENC_Y_H_PHASE		0x764
180*4882a593Smuzhiyun #define VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE		0x76c
181*4882a593Smuzhiyun #define VFE_0_SCALE_ENC_Y_V_PHASE		0x770
182*4882a593Smuzhiyun #define VFE_0_SCALE_ENC_CBCR_CFG		0x778
183*4882a593Smuzhiyun #define VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE	0x77c
184*4882a593Smuzhiyun #define VFE_0_SCALE_ENC_CBCR_H_PHASE		0x780
185*4882a593Smuzhiyun #define VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE	0x790
186*4882a593Smuzhiyun #define VFE_0_SCALE_ENC_CBCR_V_PHASE		0x794
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun #define VFE_0_CROP_ENC_Y_WIDTH			0x854
189*4882a593Smuzhiyun #define VFE_0_CROP_ENC_Y_HEIGHT			0x858
190*4882a593Smuzhiyun #define VFE_0_CROP_ENC_CBCR_WIDTH		0x85c
191*4882a593Smuzhiyun #define VFE_0_CROP_ENC_CBCR_HEIGHT		0x860
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun #define VFE_0_CLAMP_ENC_MAX_CFG			0x874
194*4882a593Smuzhiyun #define VFE_0_CLAMP_ENC_MAX_CFG_CH0		(0xff << 0)
195*4882a593Smuzhiyun #define VFE_0_CLAMP_ENC_MAX_CFG_CH1		(0xff << 8)
196*4882a593Smuzhiyun #define VFE_0_CLAMP_ENC_MAX_CFG_CH2		(0xff << 16)
197*4882a593Smuzhiyun #define VFE_0_CLAMP_ENC_MIN_CFG			0x878
198*4882a593Smuzhiyun #define VFE_0_CLAMP_ENC_MIN_CFG_CH0		(0x0 << 0)
199*4882a593Smuzhiyun #define VFE_0_CLAMP_ENC_MIN_CFG_CH1		(0x0 << 8)
200*4882a593Smuzhiyun #define VFE_0_CLAMP_ENC_MIN_CFG_CH2		(0x0 << 16)
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun #define VFE_0_CGC_OVERRIDE_1			0x974
203*4882a593Smuzhiyun #define VFE_0_CGC_OVERRIDE_1_IMAGE_Mx_CGC_OVERRIDE(x)	BIT(x)
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun #define CAMIF_TIMEOUT_SLEEP_US 1000
206*4882a593Smuzhiyun #define CAMIF_TIMEOUT_ALL_US 1000000
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun #define MSM_VFE_VFE0_UB_SIZE 1023
209*4882a593Smuzhiyun #define MSM_VFE_VFE0_UB_SIZE_RDI (MSM_VFE_VFE0_UB_SIZE / 3)
210*4882a593Smuzhiyun 
vfe_hw_version_read(struct vfe_device * vfe,struct device * dev)211*4882a593Smuzhiyun static void vfe_hw_version_read(struct vfe_device *vfe, struct device *dev)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun 	u32 hw_version = readl_relaxed(vfe->base + VFE_0_HW_VERSION);
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	dev_dbg(dev, "VFE HW Version = 0x%08x\n", hw_version);
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun 
vfe_get_ub_size(u8 vfe_id)218*4882a593Smuzhiyun static u16 vfe_get_ub_size(u8 vfe_id)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun 	if (vfe_id == 0)
221*4882a593Smuzhiyun 		return MSM_VFE_VFE0_UB_SIZE_RDI;
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	return 0;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun 
vfe_reg_clr(struct vfe_device * vfe,u32 reg,u32 clr_bits)226*4882a593Smuzhiyun static inline void vfe_reg_clr(struct vfe_device *vfe, u32 reg, u32 clr_bits)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun 	u32 bits = readl_relaxed(vfe->base + reg);
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	writel_relaxed(bits & ~clr_bits, vfe->base + reg);
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun 
vfe_reg_set(struct vfe_device * vfe,u32 reg,u32 set_bits)233*4882a593Smuzhiyun static inline void vfe_reg_set(struct vfe_device *vfe, u32 reg, u32 set_bits)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun 	u32 bits = readl_relaxed(vfe->base + reg);
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	writel_relaxed(bits | set_bits, vfe->base + reg);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
vfe_global_reset(struct vfe_device * vfe)240*4882a593Smuzhiyun static void vfe_global_reset(struct vfe_device *vfe)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	u32 reset_bits = VFE_0_GLOBAL_RESET_CMD_TESTGEN		|
243*4882a593Smuzhiyun 			 VFE_0_GLOBAL_RESET_CMD_BUS_MISR	|
244*4882a593Smuzhiyun 			 VFE_0_GLOBAL_RESET_CMD_PM		|
245*4882a593Smuzhiyun 			 VFE_0_GLOBAL_RESET_CMD_TIMER		|
246*4882a593Smuzhiyun 			 VFE_0_GLOBAL_RESET_CMD_REGISTER	|
247*4882a593Smuzhiyun 			 VFE_0_GLOBAL_RESET_CMD_BUS_BDG		|
248*4882a593Smuzhiyun 			 VFE_0_GLOBAL_RESET_CMD_BUS		|
249*4882a593Smuzhiyun 			 VFE_0_GLOBAL_RESET_CMD_CAMIF		|
250*4882a593Smuzhiyun 			 VFE_0_GLOBAL_RESET_CMD_CORE;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	writel_relaxed(reset_bits, vfe->base + VFE_0_GLOBAL_RESET_CMD);
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
vfe_halt_request(struct vfe_device * vfe)255*4882a593Smuzhiyun static void vfe_halt_request(struct vfe_device *vfe)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	writel_relaxed(VFE_0_BUS_BDG_CMD_HALT_REQ,
258*4882a593Smuzhiyun 		       vfe->base + VFE_0_BUS_BDG_CMD);
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun 
vfe_halt_clear(struct vfe_device * vfe)261*4882a593Smuzhiyun static void vfe_halt_clear(struct vfe_device *vfe)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun 	writel_relaxed(0x0, vfe->base + VFE_0_BUS_BDG_CMD);
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun 
vfe_wm_enable(struct vfe_device * vfe,u8 wm,u8 enable)266*4882a593Smuzhiyun static void vfe_wm_enable(struct vfe_device *vfe, u8 wm, u8 enable)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	if (enable)
269*4882a593Smuzhiyun 		vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm),
270*4882a593Smuzhiyun 			    1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT);
271*4882a593Smuzhiyun 	else
272*4882a593Smuzhiyun 		vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm),
273*4882a593Smuzhiyun 			    1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_WR_PATH_SHIFT);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
vfe_wm_frame_based(struct vfe_device * vfe,u8 wm,u8 enable)276*4882a593Smuzhiyun static void vfe_wm_frame_based(struct vfe_device *vfe, u8 wm, u8 enable)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun 	if (enable)
279*4882a593Smuzhiyun 		vfe_reg_set(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm),
280*4882a593Smuzhiyun 			1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_FRM_BASED_SHIFT);
281*4882a593Smuzhiyun 	else
282*4882a593Smuzhiyun 		vfe_reg_clr(vfe, VFE_0_BUS_IMAGE_MASTER_n_WR_CFG(wm),
283*4882a593Smuzhiyun 			1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_FRM_BASED_SHIFT);
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun #define CALC_WORD(width, M, N) (((width) * (M) + (N) - 1) / (N))
287*4882a593Smuzhiyun 
vfe_word_per_line(u32 format,u32 pixel_per_line)288*4882a593Smuzhiyun static int vfe_word_per_line(u32 format, u32 pixel_per_line)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun 	int val = 0;
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	switch (format) {
293*4882a593Smuzhiyun 	case V4L2_PIX_FMT_NV12:
294*4882a593Smuzhiyun 	case V4L2_PIX_FMT_NV21:
295*4882a593Smuzhiyun 	case V4L2_PIX_FMT_NV16:
296*4882a593Smuzhiyun 	case V4L2_PIX_FMT_NV61:
297*4882a593Smuzhiyun 		val = CALC_WORD(pixel_per_line, 1, 8);
298*4882a593Smuzhiyun 		break;
299*4882a593Smuzhiyun 	case V4L2_PIX_FMT_YUYV:
300*4882a593Smuzhiyun 	case V4L2_PIX_FMT_YVYU:
301*4882a593Smuzhiyun 	case V4L2_PIX_FMT_UYVY:
302*4882a593Smuzhiyun 	case V4L2_PIX_FMT_VYUY:
303*4882a593Smuzhiyun 		val = CALC_WORD(pixel_per_line, 2, 8);
304*4882a593Smuzhiyun 		break;
305*4882a593Smuzhiyun 	}
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	return val;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun 
vfe_get_wm_sizes(struct v4l2_pix_format_mplane * pix,u8 plane,u16 * width,u16 * height,u16 * bytesperline)310*4882a593Smuzhiyun static void vfe_get_wm_sizes(struct v4l2_pix_format_mplane *pix, u8 plane,
311*4882a593Smuzhiyun 			     u16 *width, u16 *height, u16 *bytesperline)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun 	switch (pix->pixelformat) {
314*4882a593Smuzhiyun 	case V4L2_PIX_FMT_NV12:
315*4882a593Smuzhiyun 	case V4L2_PIX_FMT_NV21:
316*4882a593Smuzhiyun 		*width = pix->width;
317*4882a593Smuzhiyun 		*height = pix->height;
318*4882a593Smuzhiyun 		*bytesperline = pix->plane_fmt[0].bytesperline;
319*4882a593Smuzhiyun 		if (plane == 1)
320*4882a593Smuzhiyun 			*height /= 2;
321*4882a593Smuzhiyun 		break;
322*4882a593Smuzhiyun 	case V4L2_PIX_FMT_NV16:
323*4882a593Smuzhiyun 	case V4L2_PIX_FMT_NV61:
324*4882a593Smuzhiyun 		*width = pix->width;
325*4882a593Smuzhiyun 		*height = pix->height;
326*4882a593Smuzhiyun 		*bytesperline = pix->plane_fmt[0].bytesperline;
327*4882a593Smuzhiyun 		break;
328*4882a593Smuzhiyun 	}
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun 
vfe_wm_line_based(struct vfe_device * vfe,u32 wm,struct v4l2_pix_format_mplane * pix,u8 plane,u32 enable)331*4882a593Smuzhiyun static void vfe_wm_line_based(struct vfe_device *vfe, u32 wm,
332*4882a593Smuzhiyun 			      struct v4l2_pix_format_mplane *pix,
333*4882a593Smuzhiyun 			      u8 plane, u32 enable)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun 	u32 reg;
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	if (enable) {
338*4882a593Smuzhiyun 		u16 width = 0, height = 0, bytesperline = 0, wpl;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 		vfe_get_wm_sizes(pix, plane, &width, &height, &bytesperline);
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 		wpl = vfe_word_per_line(pix->pixelformat, width);
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 		reg = height - 1;
345*4882a593Smuzhiyun 		reg |= ((wpl + 1) / 2 - 1) << 16;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 		writel_relaxed(reg, vfe->base +
348*4882a593Smuzhiyun 			       VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 		wpl = vfe_word_per_line(pix->pixelformat, bytesperline);
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 		reg = 0x3;
353*4882a593Smuzhiyun 		reg |= (height - 1) << 4;
354*4882a593Smuzhiyun 		reg |= wpl << 16;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 		writel_relaxed(reg, vfe->base +
357*4882a593Smuzhiyun 			       VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm));
358*4882a593Smuzhiyun 	} else {
359*4882a593Smuzhiyun 		writel_relaxed(0, vfe->base +
360*4882a593Smuzhiyun 			       VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));
361*4882a593Smuzhiyun 		writel_relaxed(0, vfe->base +
362*4882a593Smuzhiyun 			       VFE_0_BUS_IMAGE_MASTER_n_WR_BUFFER_CFG(wm));
363*4882a593Smuzhiyun 	}
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun 
vfe_wm_set_framedrop_period(struct vfe_device * vfe,u8 wm,u8 per)366*4882a593Smuzhiyun static void vfe_wm_set_framedrop_period(struct vfe_device *vfe, u8 wm, u8 per)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun 	u32 reg;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	reg = readl_relaxed(vfe->base +
371*4882a593Smuzhiyun 			    VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm));
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	reg &= ~(VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK);
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	reg |= (per << VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_SHIFT)
376*4882a593Smuzhiyun 		& VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG_FRM_DROP_PER_MASK;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	writel_relaxed(reg,
379*4882a593Smuzhiyun 		       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_ADDR_CFG(wm));
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun 
vfe_wm_set_framedrop_pattern(struct vfe_device * vfe,u8 wm,u32 pattern)382*4882a593Smuzhiyun static void vfe_wm_set_framedrop_pattern(struct vfe_device *vfe, u8 wm,
383*4882a593Smuzhiyun 					 u32 pattern)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun 	writel_relaxed(pattern,
386*4882a593Smuzhiyun 	       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_FRAMEDROP_PATTERN(wm));
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun 
vfe_wm_set_ub_cfg(struct vfe_device * vfe,u8 wm,u16 offset,u16 depth)389*4882a593Smuzhiyun static void vfe_wm_set_ub_cfg(struct vfe_device *vfe, u8 wm,
390*4882a593Smuzhiyun 			      u16 offset, u16 depth)
391*4882a593Smuzhiyun {
392*4882a593Smuzhiyun 	u32 reg;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	reg = (offset << VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG_OFFSET_SHIFT) |
395*4882a593Smuzhiyun 		depth;
396*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_UB_CFG(wm));
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun 
vfe_bus_reload_wm(struct vfe_device * vfe,u8 wm)399*4882a593Smuzhiyun static void vfe_bus_reload_wm(struct vfe_device *vfe, u8 wm)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun 	wmb();
402*4882a593Smuzhiyun 	writel_relaxed(VFE_0_BUS_CMD_Mx_RLD_CMD(wm), vfe->base + VFE_0_BUS_CMD);
403*4882a593Smuzhiyun 	wmb();
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun 
vfe_wm_set_ping_addr(struct vfe_device * vfe,u8 wm,u32 addr)406*4882a593Smuzhiyun static void vfe_wm_set_ping_addr(struct vfe_device *vfe, u8 wm, u32 addr)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun 	writel_relaxed(addr,
409*4882a593Smuzhiyun 		       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PING_ADDR(wm));
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun 
vfe_wm_set_pong_addr(struct vfe_device * vfe,u8 wm,u32 addr)412*4882a593Smuzhiyun static void vfe_wm_set_pong_addr(struct vfe_device *vfe, u8 wm, u32 addr)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun 	writel_relaxed(addr,
415*4882a593Smuzhiyun 		       vfe->base + VFE_0_BUS_IMAGE_MASTER_n_WR_PONG_ADDR(wm));
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun 
vfe_wm_get_ping_pong_status(struct vfe_device * vfe,u8 wm)418*4882a593Smuzhiyun static int vfe_wm_get_ping_pong_status(struct vfe_device *vfe, u8 wm)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun 	u32 reg;
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	reg = readl_relaxed(vfe->base + VFE_0_BUS_PING_PONG_STATUS);
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	return (reg >> wm) & 0x1;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun 
vfe_bus_enable_wr_if(struct vfe_device * vfe,u8 enable)427*4882a593Smuzhiyun static void vfe_bus_enable_wr_if(struct vfe_device *vfe, u8 enable)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun 	if (enable)
430*4882a593Smuzhiyun 		writel_relaxed(0x10000009, vfe->base + VFE_0_BUS_CFG);
431*4882a593Smuzhiyun 	else
432*4882a593Smuzhiyun 		writel_relaxed(0, vfe->base + VFE_0_BUS_CFG);
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun 
vfe_bus_connect_wm_to_rdi(struct vfe_device * vfe,u8 wm,enum vfe_line_id id)435*4882a593Smuzhiyun static void vfe_bus_connect_wm_to_rdi(struct vfe_device *vfe, u8 wm,
436*4882a593Smuzhiyun 				      enum vfe_line_id id)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun 	u32 reg;
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	reg = VFE_0_RDI_CFG_x_MIPI_EN_BITS;
441*4882a593Smuzhiyun 	reg |= VFE_0_RDI_CFG_x_RDI_Mr_FRAME_BASED_EN(id);
442*4882a593Smuzhiyun 	vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), reg);
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	reg = VFE_0_RDI_CFG_x_RDI_EN_BIT;
445*4882a593Smuzhiyun 	reg |= ((3 * id) << VFE_0_RDI_CFG_x_RDI_STREAM_SEL_SHIFT) &
446*4882a593Smuzhiyun 		VFE_0_RDI_CFG_x_RDI_STREAM_SEL_MASK;
447*4882a593Smuzhiyun 	vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id), reg);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	switch (id) {
450*4882a593Smuzhiyun 	case VFE_LINE_RDI0:
451*4882a593Smuzhiyun 	default:
452*4882a593Smuzhiyun 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 <<
453*4882a593Smuzhiyun 		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
454*4882a593Smuzhiyun 		break;
455*4882a593Smuzhiyun 	case VFE_LINE_RDI1:
456*4882a593Smuzhiyun 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 <<
457*4882a593Smuzhiyun 		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
458*4882a593Smuzhiyun 		break;
459*4882a593Smuzhiyun 	case VFE_LINE_RDI2:
460*4882a593Smuzhiyun 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 <<
461*4882a593Smuzhiyun 		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
462*4882a593Smuzhiyun 		break;
463*4882a593Smuzhiyun 	}
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	if (wm % 2 == 1)
466*4882a593Smuzhiyun 		reg <<= 16;
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	vfe_reg_set(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg);
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun 
vfe_wm_set_subsample(struct vfe_device * vfe,u8 wm)471*4882a593Smuzhiyun static void vfe_wm_set_subsample(struct vfe_device *vfe, u8 wm)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	writel_relaxed(VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN_DEF,
474*4882a593Smuzhiyun 		       vfe->base +
475*4882a593Smuzhiyun 		       VFE_0_BUS_IMAGE_MASTER_n_WR_IRQ_SUBSAMPLE_PATTERN(wm));
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun 
vfe_bus_disconnect_wm_from_rdi(struct vfe_device * vfe,u8 wm,enum vfe_line_id id)478*4882a593Smuzhiyun static void vfe_bus_disconnect_wm_from_rdi(struct vfe_device *vfe, u8 wm,
479*4882a593Smuzhiyun 					   enum vfe_line_id id)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun 	u32 reg;
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	reg = VFE_0_RDI_CFG_x_RDI_Mr_FRAME_BASED_EN(id);
484*4882a593Smuzhiyun 	vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(0), reg);
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	reg = VFE_0_RDI_CFG_x_RDI_EN_BIT;
487*4882a593Smuzhiyun 	vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id), reg);
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 	switch (id) {
490*4882a593Smuzhiyun 	case VFE_LINE_RDI0:
491*4882a593Smuzhiyun 	default:
492*4882a593Smuzhiyun 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI0 <<
493*4882a593Smuzhiyun 		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
494*4882a593Smuzhiyun 		break;
495*4882a593Smuzhiyun 	case VFE_LINE_RDI1:
496*4882a593Smuzhiyun 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI1 <<
497*4882a593Smuzhiyun 		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
498*4882a593Smuzhiyun 		break;
499*4882a593Smuzhiyun 	case VFE_LINE_RDI2:
500*4882a593Smuzhiyun 		reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_VAL_RDI2 <<
501*4882a593Smuzhiyun 		      VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
502*4882a593Smuzhiyun 		break;
503*4882a593Smuzhiyun 	}
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	if (wm % 2 == 1)
506*4882a593Smuzhiyun 		reg <<= 16;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	vfe_reg_clr(vfe, VFE_0_BUS_XBAR_CFG_x(wm), reg);
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun 
vfe_set_xbar_cfg(struct vfe_device * vfe,struct vfe_output * output,u8 enable)511*4882a593Smuzhiyun static void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output,
512*4882a593Smuzhiyun 			     u8 enable)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun 	struct vfe_line *line = container_of(output, struct vfe_line, output);
515*4882a593Smuzhiyun 	u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
516*4882a593Smuzhiyun 	u32 reg;
517*4882a593Smuzhiyun 	unsigned int i;
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 	for (i = 0; i < output->wm_num; i++) {
520*4882a593Smuzhiyun 		if (i == 0) {
521*4882a593Smuzhiyun 			reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA <<
522*4882a593Smuzhiyun 				VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
523*4882a593Smuzhiyun 		} else if (i == 1) {
524*4882a593Smuzhiyun 			reg = VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;
525*4882a593Smuzhiyun 			if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV16)
526*4882a593Smuzhiyun 				reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;
527*4882a593Smuzhiyun 		} else {
528*4882a593Smuzhiyun 			/* On current devices output->wm_num is always <= 2 */
529*4882a593Smuzhiyun 			break;
530*4882a593Smuzhiyun 		}
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 		if (output->wm_idx[i] % 2 == 1)
533*4882a593Smuzhiyun 			reg <<= 16;
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 		if (enable)
536*4882a593Smuzhiyun 			vfe_reg_set(vfe,
537*4882a593Smuzhiyun 				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[i]),
538*4882a593Smuzhiyun 				    reg);
539*4882a593Smuzhiyun 		else
540*4882a593Smuzhiyun 			vfe_reg_clr(vfe,
541*4882a593Smuzhiyun 				    VFE_0_BUS_XBAR_CFG_x(output->wm_idx[i]),
542*4882a593Smuzhiyun 				    reg);
543*4882a593Smuzhiyun 	}
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
vfe_set_realign_cfg(struct vfe_device * vfe,struct vfe_line * line,u8 enable)546*4882a593Smuzhiyun static void vfe_set_realign_cfg(struct vfe_device *vfe, struct vfe_line *line,
547*4882a593Smuzhiyun 				u8 enable)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun 	/* empty */
550*4882a593Smuzhiyun }
vfe_set_rdi_cid(struct vfe_device * vfe,enum vfe_line_id id,u8 cid)551*4882a593Smuzhiyun static void vfe_set_rdi_cid(struct vfe_device *vfe, enum vfe_line_id id, u8 cid)
552*4882a593Smuzhiyun {
553*4882a593Smuzhiyun 	vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id),
554*4882a593Smuzhiyun 		    VFE_0_RDI_CFG_x_RDI_M0_SEL_MASK);
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 	vfe_reg_set(vfe, VFE_0_RDI_CFG_x(id),
557*4882a593Smuzhiyun 		    cid << VFE_0_RDI_CFG_x_RDI_M0_SEL_SHIFT);
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun 
vfe_reg_update(struct vfe_device * vfe,enum vfe_line_id line_id)560*4882a593Smuzhiyun static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun 	vfe->reg_update |= VFE_0_REG_UPDATE_line_n(line_id);
563*4882a593Smuzhiyun 	wmb();
564*4882a593Smuzhiyun 	writel_relaxed(vfe->reg_update, vfe->base + VFE_0_REG_UPDATE);
565*4882a593Smuzhiyun 	wmb();
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun 
vfe_reg_update_clear(struct vfe_device * vfe,enum vfe_line_id line_id)568*4882a593Smuzhiyun static inline void vfe_reg_update_clear(struct vfe_device *vfe,
569*4882a593Smuzhiyun 					enum vfe_line_id line_id)
570*4882a593Smuzhiyun {
571*4882a593Smuzhiyun 	vfe->reg_update &= ~VFE_0_REG_UPDATE_line_n(line_id);
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun 
vfe_enable_irq_wm_line(struct vfe_device * vfe,u8 wm,enum vfe_line_id line_id,u8 enable)574*4882a593Smuzhiyun static void vfe_enable_irq_wm_line(struct vfe_device *vfe, u8 wm,
575*4882a593Smuzhiyun 				   enum vfe_line_id line_id, u8 enable)
576*4882a593Smuzhiyun {
577*4882a593Smuzhiyun 	u32 irq_en0 = VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(wm) |
578*4882a593Smuzhiyun 		      VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id);
579*4882a593Smuzhiyun 	u32 irq_en1 = VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(wm) |
580*4882a593Smuzhiyun 		      VFE_0_IRQ_MASK_1_RDIn_SOF(line_id);
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	if (enable) {
583*4882a593Smuzhiyun 		vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
584*4882a593Smuzhiyun 		vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
585*4882a593Smuzhiyun 	} else {
586*4882a593Smuzhiyun 		vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0);
587*4882a593Smuzhiyun 		vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1);
588*4882a593Smuzhiyun 	}
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun 
vfe_enable_irq_pix_line(struct vfe_device * vfe,u8 comp,enum vfe_line_id line_id,u8 enable)591*4882a593Smuzhiyun static void vfe_enable_irq_pix_line(struct vfe_device *vfe, u8 comp,
592*4882a593Smuzhiyun 				    enum vfe_line_id line_id, u8 enable)
593*4882a593Smuzhiyun {
594*4882a593Smuzhiyun 	struct vfe_output *output = &vfe->line[line_id].output;
595*4882a593Smuzhiyun 	unsigned int i;
596*4882a593Smuzhiyun 	u32 irq_en0;
597*4882a593Smuzhiyun 	u32 irq_en1;
598*4882a593Smuzhiyun 	u32 comp_mask = 0;
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun 	irq_en0 = VFE_0_IRQ_MASK_0_CAMIF_SOF;
601*4882a593Smuzhiyun 	irq_en0 |= VFE_0_IRQ_MASK_0_CAMIF_EOF;
602*4882a593Smuzhiyun 	irq_en0 |= VFE_0_IRQ_MASK_0_IMAGE_COMPOSITE_DONE_n(comp);
603*4882a593Smuzhiyun 	irq_en0 |= VFE_0_IRQ_MASK_0_line_n_REG_UPDATE(line_id);
604*4882a593Smuzhiyun 	irq_en1 = VFE_0_IRQ_MASK_1_CAMIF_ERROR;
605*4882a593Smuzhiyun 	for (i = 0; i < output->wm_num; i++) {
606*4882a593Smuzhiyun 		irq_en1 |= VFE_0_IRQ_MASK_1_IMAGE_MASTER_n_BUS_OVERFLOW(
607*4882a593Smuzhiyun 							output->wm_idx[i]);
608*4882a593Smuzhiyun 		comp_mask |= (1 << output->wm_idx[i]) << comp * 8;
609*4882a593Smuzhiyun 	}
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	if (enable) {
612*4882a593Smuzhiyun 		vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
613*4882a593Smuzhiyun 		vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
614*4882a593Smuzhiyun 		vfe_reg_set(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask);
615*4882a593Smuzhiyun 	} else {
616*4882a593Smuzhiyun 		vfe_reg_clr(vfe, VFE_0_IRQ_MASK_0, irq_en0);
617*4882a593Smuzhiyun 		vfe_reg_clr(vfe, VFE_0_IRQ_MASK_1, irq_en1);
618*4882a593Smuzhiyun 		vfe_reg_clr(vfe, VFE_0_IRQ_COMPOSITE_MASK_0, comp_mask);
619*4882a593Smuzhiyun 	}
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun 
vfe_enable_irq_common(struct vfe_device * vfe)622*4882a593Smuzhiyun static void vfe_enable_irq_common(struct vfe_device *vfe)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun 	u32 irq_en0 = VFE_0_IRQ_MASK_0_RESET_ACK;
625*4882a593Smuzhiyun 	u32 irq_en1 = VFE_0_IRQ_MASK_1_VIOLATION |
626*4882a593Smuzhiyun 		      VFE_0_IRQ_MASK_1_BUS_BDG_HALT_ACK;
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	vfe_reg_set(vfe, VFE_0_IRQ_MASK_0, irq_en0);
629*4882a593Smuzhiyun 	vfe_reg_set(vfe, VFE_0_IRQ_MASK_1, irq_en1);
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun 
vfe_set_demux_cfg(struct vfe_device * vfe,struct vfe_line * line)632*4882a593Smuzhiyun static void vfe_set_demux_cfg(struct vfe_device *vfe, struct vfe_line *line)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun 	u32 val, even_cfg, odd_cfg;
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	writel_relaxed(VFE_0_DEMUX_CFG_PERIOD, vfe->base + VFE_0_DEMUX_CFG);
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	val = VFE_0_DEMUX_GAIN_0_CH0_EVEN | VFE_0_DEMUX_GAIN_0_CH0_ODD;
639*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_0);
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	val = VFE_0_DEMUX_GAIN_1_CH1 | VFE_0_DEMUX_GAIN_1_CH2;
642*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_DEMUX_GAIN_1);
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun 	switch (line->fmt[MSM_VFE_PAD_SINK].code) {
645*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV8_2X8:
646*4882a593Smuzhiyun 		even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YUYV;
647*4882a593Smuzhiyun 		odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YUYV;
648*4882a593Smuzhiyun 		break;
649*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YVYU8_2X8:
650*4882a593Smuzhiyun 		even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_YVYU;
651*4882a593Smuzhiyun 		odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_YVYU;
652*4882a593Smuzhiyun 		break;
653*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYVY8_2X8:
654*4882a593Smuzhiyun 	default:
655*4882a593Smuzhiyun 		even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_UYVY;
656*4882a593Smuzhiyun 		odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_UYVY;
657*4882a593Smuzhiyun 		break;
658*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_VYUY8_2X8:
659*4882a593Smuzhiyun 		even_cfg = VFE_0_DEMUX_EVEN_CFG_PATTERN_VYUY;
660*4882a593Smuzhiyun 		odd_cfg = VFE_0_DEMUX_ODD_CFG_PATTERN_VYUY;
661*4882a593Smuzhiyun 		break;
662*4882a593Smuzhiyun 	}
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	writel_relaxed(even_cfg, vfe->base + VFE_0_DEMUX_EVEN_CFG);
665*4882a593Smuzhiyun 	writel_relaxed(odd_cfg, vfe->base + VFE_0_DEMUX_ODD_CFG);
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun 
vfe_calc_interp_reso(u16 input,u16 output)668*4882a593Smuzhiyun static inline u8 vfe_calc_interp_reso(u16 input, u16 output)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun 	if (input / output >= 16)
671*4882a593Smuzhiyun 		return 0;
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	if (input / output >= 8)
674*4882a593Smuzhiyun 		return 1;
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 	if (input / output >= 4)
677*4882a593Smuzhiyun 		return 2;
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 	return 3;
680*4882a593Smuzhiyun }
681*4882a593Smuzhiyun 
vfe_set_scale_cfg(struct vfe_device * vfe,struct vfe_line * line)682*4882a593Smuzhiyun static void vfe_set_scale_cfg(struct vfe_device *vfe, struct vfe_line *line)
683*4882a593Smuzhiyun {
684*4882a593Smuzhiyun 	u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
685*4882a593Smuzhiyun 	u32 reg;
686*4882a593Smuzhiyun 	u16 input, output;
687*4882a593Smuzhiyun 	u8 interp_reso;
688*4882a593Smuzhiyun 	u32 phase_mult;
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun 	writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_Y_CFG);
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	input = line->fmt[MSM_VFE_PAD_SINK].width;
693*4882a593Smuzhiyun 	output = line->compose.width;
694*4882a593Smuzhiyun 	reg = (output << 16) | input;
695*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_IMAGE_SIZE);
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun 	interp_reso = vfe_calc_interp_reso(input, output);
698*4882a593Smuzhiyun 	phase_mult = input * (1 << (13 + interp_reso)) / output;
699*4882a593Smuzhiyun 	reg = (interp_reso << 20) | phase_mult;
700*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_H_PHASE);
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun 	input = line->fmt[MSM_VFE_PAD_SINK].height;
703*4882a593Smuzhiyun 	output = line->compose.height;
704*4882a593Smuzhiyun 	reg = (output << 16) | input;
705*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_IMAGE_SIZE);
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	interp_reso = vfe_calc_interp_reso(input, output);
708*4882a593Smuzhiyun 	phase_mult = input * (1 << (13 + interp_reso)) / output;
709*4882a593Smuzhiyun 	reg = (interp_reso << 20) | phase_mult;
710*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_Y_V_PHASE);
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 	writel_relaxed(0x3, vfe->base + VFE_0_SCALE_ENC_CBCR_CFG);
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	input = line->fmt[MSM_VFE_PAD_SINK].width;
715*4882a593Smuzhiyun 	output = line->compose.width / 2;
716*4882a593Smuzhiyun 	reg = (output << 16) | input;
717*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_IMAGE_SIZE);
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	interp_reso = vfe_calc_interp_reso(input, output);
720*4882a593Smuzhiyun 	phase_mult = input * (1 << (13 + interp_reso)) / output;
721*4882a593Smuzhiyun 	reg = (interp_reso << 20) | phase_mult;
722*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_H_PHASE);
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	input = line->fmt[MSM_VFE_PAD_SINK].height;
725*4882a593Smuzhiyun 	output = line->compose.height;
726*4882a593Smuzhiyun 	if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21)
727*4882a593Smuzhiyun 		output = line->compose.height / 2;
728*4882a593Smuzhiyun 	reg = (output << 16) | input;
729*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_IMAGE_SIZE);
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 	interp_reso = vfe_calc_interp_reso(input, output);
732*4882a593Smuzhiyun 	phase_mult = input * (1 << (13 + interp_reso)) / output;
733*4882a593Smuzhiyun 	reg = (interp_reso << 20) | phase_mult;
734*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_SCALE_ENC_CBCR_V_PHASE);
735*4882a593Smuzhiyun }
736*4882a593Smuzhiyun 
vfe_set_crop_cfg(struct vfe_device * vfe,struct vfe_line * line)737*4882a593Smuzhiyun static void vfe_set_crop_cfg(struct vfe_device *vfe, struct vfe_line *line)
738*4882a593Smuzhiyun {
739*4882a593Smuzhiyun 	u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
740*4882a593Smuzhiyun 	u32 reg;
741*4882a593Smuzhiyun 	u16 first, last;
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun 	first = line->crop.left;
744*4882a593Smuzhiyun 	last = line->crop.left + line->crop.width - 1;
745*4882a593Smuzhiyun 	reg = (first << 16) | last;
746*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_WIDTH);
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun 	first = line->crop.top;
749*4882a593Smuzhiyun 	last = line->crop.top + line->crop.height - 1;
750*4882a593Smuzhiyun 	reg = (first << 16) | last;
751*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_Y_HEIGHT);
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	first = line->crop.left / 2;
754*4882a593Smuzhiyun 	last = line->crop.left / 2 + line->crop.width / 2 - 1;
755*4882a593Smuzhiyun 	reg = (first << 16) | last;
756*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_WIDTH);
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 	first = line->crop.top;
759*4882a593Smuzhiyun 	last = line->crop.top + line->crop.height - 1;
760*4882a593Smuzhiyun 	if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV21) {
761*4882a593Smuzhiyun 		first = line->crop.top / 2;
762*4882a593Smuzhiyun 		last = line->crop.top / 2 + line->crop.height / 2 - 1;
763*4882a593Smuzhiyun 	}
764*4882a593Smuzhiyun 	reg = (first << 16) | last;
765*4882a593Smuzhiyun 	writel_relaxed(reg, vfe->base + VFE_0_CROP_ENC_CBCR_HEIGHT);
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun 
vfe_set_clamp_cfg(struct vfe_device * vfe)768*4882a593Smuzhiyun static void vfe_set_clamp_cfg(struct vfe_device *vfe)
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun 	u32 val = VFE_0_CLAMP_ENC_MAX_CFG_CH0 |
771*4882a593Smuzhiyun 		VFE_0_CLAMP_ENC_MAX_CFG_CH1 |
772*4882a593Smuzhiyun 		VFE_0_CLAMP_ENC_MAX_CFG_CH2;
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MAX_CFG);
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 	val = VFE_0_CLAMP_ENC_MIN_CFG_CH0 |
777*4882a593Smuzhiyun 		VFE_0_CLAMP_ENC_MIN_CFG_CH1 |
778*4882a593Smuzhiyun 		VFE_0_CLAMP_ENC_MIN_CFG_CH2;
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_CLAMP_ENC_MIN_CFG);
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun 
vfe_set_qos(struct vfe_device * vfe)783*4882a593Smuzhiyun static void vfe_set_qos(struct vfe_device *vfe)
784*4882a593Smuzhiyun {
785*4882a593Smuzhiyun 	u32 val = VFE_0_BUS_BDG_QOS_CFG_0_CFG;
786*4882a593Smuzhiyun 	u32 val7 = VFE_0_BUS_BDG_QOS_CFG_7_CFG;
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_0);
789*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_1);
790*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_2);
791*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_3);
792*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_4);
793*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_5);
794*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_BUS_BDG_QOS_CFG_6);
795*4882a593Smuzhiyun 	writel_relaxed(val7, vfe->base + VFE_0_BUS_BDG_QOS_CFG_7);
796*4882a593Smuzhiyun }
797*4882a593Smuzhiyun 
vfe_set_ds(struct vfe_device * vfe)798*4882a593Smuzhiyun static void vfe_set_ds(struct vfe_device *vfe)
799*4882a593Smuzhiyun {
800*4882a593Smuzhiyun 	/* empty */
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun 
vfe_set_cgc_override(struct vfe_device * vfe,u8 wm,u8 enable)803*4882a593Smuzhiyun static void vfe_set_cgc_override(struct vfe_device *vfe, u8 wm, u8 enable)
804*4882a593Smuzhiyun {
805*4882a593Smuzhiyun 	u32 val = VFE_0_CGC_OVERRIDE_1_IMAGE_Mx_CGC_OVERRIDE(wm);
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 	if (enable)
808*4882a593Smuzhiyun 		vfe_reg_set(vfe, VFE_0_CGC_OVERRIDE_1, val);
809*4882a593Smuzhiyun 	else
810*4882a593Smuzhiyun 		vfe_reg_clr(vfe, VFE_0_CGC_OVERRIDE_1, val);
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 	wmb();
813*4882a593Smuzhiyun }
814*4882a593Smuzhiyun 
vfe_set_camif_cfg(struct vfe_device * vfe,struct vfe_line * line)815*4882a593Smuzhiyun static void vfe_set_camif_cfg(struct vfe_device *vfe, struct vfe_line *line)
816*4882a593Smuzhiyun {
817*4882a593Smuzhiyun 	u32 val;
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 	switch (line->fmt[MSM_VFE_PAD_SINK].code) {
820*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV8_2X8:
821*4882a593Smuzhiyun 		val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR;
822*4882a593Smuzhiyun 		break;
823*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YVYU8_2X8:
824*4882a593Smuzhiyun 		val = VFE_0_CORE_CFG_PIXEL_PATTERN_YCRYCB;
825*4882a593Smuzhiyun 		break;
826*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_UYVY8_2X8:
827*4882a593Smuzhiyun 	default:
828*4882a593Smuzhiyun 		val = VFE_0_CORE_CFG_PIXEL_PATTERN_CBYCRY;
829*4882a593Smuzhiyun 		break;
830*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_VYUY8_2X8:
831*4882a593Smuzhiyun 		val = VFE_0_CORE_CFG_PIXEL_PATTERN_CRYCBY;
832*4882a593Smuzhiyun 		break;
833*4882a593Smuzhiyun 	}
834*4882a593Smuzhiyun 
835*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_CORE_CFG);
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun 	val = line->fmt[MSM_VFE_PAD_SINK].width * 2;
838*4882a593Smuzhiyun 	val |= line->fmt[MSM_VFE_PAD_SINK].height << 16;
839*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_FRAME_CFG);
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 	val = line->fmt[MSM_VFE_PAD_SINK].width * 2 - 1;
842*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_WIDTH_CFG);
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun 	val = line->fmt[MSM_VFE_PAD_SINK].height - 1;
845*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_WINDOW_HEIGHT_CFG);
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 	val = 0xffffffff;
848*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_SUBSAMPLE_CFG_0);
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun 	val = 0xffffffff;
851*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_IRQ_SUBSAMPLE_PATTERN);
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	val = VFE_0_RDI_CFG_x_MIPI_EN_BITS;
854*4882a593Smuzhiyun 	vfe_reg_set(vfe, VFE_0_RDI_CFG_x(0), val);
855*4882a593Smuzhiyun 
856*4882a593Smuzhiyun 	val = VFE_0_CAMIF_CFG_VFE_OUTPUT_EN;
857*4882a593Smuzhiyun 	writel_relaxed(val, vfe->base + VFE_0_CAMIF_CFG);
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun 
vfe_set_camif_cmd(struct vfe_device * vfe,u8 enable)860*4882a593Smuzhiyun static void vfe_set_camif_cmd(struct vfe_device *vfe, u8 enable)
861*4882a593Smuzhiyun {
862*4882a593Smuzhiyun 	u32 cmd;
863*4882a593Smuzhiyun 
864*4882a593Smuzhiyun 	cmd = VFE_0_CAMIF_CMD_CLEAR_CAMIF_STATUS | VFE_0_CAMIF_CMD_NO_CHANGE;
865*4882a593Smuzhiyun 	writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD);
866*4882a593Smuzhiyun 	wmb();
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun 	if (enable)
869*4882a593Smuzhiyun 		cmd = VFE_0_CAMIF_CMD_ENABLE_FRAME_BOUNDARY;
870*4882a593Smuzhiyun 	else
871*4882a593Smuzhiyun 		cmd = VFE_0_CAMIF_CMD_DISABLE_FRAME_BOUNDARY;
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 	writel_relaxed(cmd, vfe->base + VFE_0_CAMIF_CMD);
874*4882a593Smuzhiyun }
875*4882a593Smuzhiyun 
vfe_set_module_cfg(struct vfe_device * vfe,u8 enable)876*4882a593Smuzhiyun static void vfe_set_module_cfg(struct vfe_device *vfe, u8 enable)
877*4882a593Smuzhiyun {
878*4882a593Smuzhiyun 	u32 val = VFE_0_MODULE_CFG_DEMUX |
879*4882a593Smuzhiyun 		  VFE_0_MODULE_CFG_CHROMA_UPSAMPLE |
880*4882a593Smuzhiyun 		  VFE_0_MODULE_CFG_SCALE_ENC |
881*4882a593Smuzhiyun 		  VFE_0_MODULE_CFG_CROP_ENC;
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun 	if (enable)
884*4882a593Smuzhiyun 		writel_relaxed(val, vfe->base + VFE_0_MODULE_CFG);
885*4882a593Smuzhiyun 	else
886*4882a593Smuzhiyun 		writel_relaxed(0x0, vfe->base + VFE_0_MODULE_CFG);
887*4882a593Smuzhiyun }
888*4882a593Smuzhiyun 
vfe_camif_wait_for_stop(struct vfe_device * vfe,struct device * dev)889*4882a593Smuzhiyun static int vfe_camif_wait_for_stop(struct vfe_device *vfe, struct device *dev)
890*4882a593Smuzhiyun {
891*4882a593Smuzhiyun 	u32 val;
892*4882a593Smuzhiyun 	int ret;
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun 	ret = readl_poll_timeout(vfe->base + VFE_0_CAMIF_STATUS,
895*4882a593Smuzhiyun 				 val,
896*4882a593Smuzhiyun 				 (val & VFE_0_CAMIF_STATUS_HALT),
897*4882a593Smuzhiyun 				 CAMIF_TIMEOUT_SLEEP_US,
898*4882a593Smuzhiyun 				 CAMIF_TIMEOUT_ALL_US);
899*4882a593Smuzhiyun 	if (ret < 0)
900*4882a593Smuzhiyun 		dev_err(dev, "%s: camif stop timeout\n", __func__);
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 	return ret;
903*4882a593Smuzhiyun }
904*4882a593Smuzhiyun 
vfe_isr_read(struct vfe_device * vfe,u32 * value0,u32 * value1)905*4882a593Smuzhiyun static void vfe_isr_read(struct vfe_device *vfe, u32 *value0, u32 *value1)
906*4882a593Smuzhiyun {
907*4882a593Smuzhiyun 	*value0 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_0);
908*4882a593Smuzhiyun 	*value1 = readl_relaxed(vfe->base + VFE_0_IRQ_STATUS_1);
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun 	writel_relaxed(*value0, vfe->base + VFE_0_IRQ_CLEAR_0);
911*4882a593Smuzhiyun 	writel_relaxed(*value1, vfe->base + VFE_0_IRQ_CLEAR_1);
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun 	wmb();
914*4882a593Smuzhiyun 	writel_relaxed(VFE_0_IRQ_CMD_GLOBAL_CLEAR, vfe->base + VFE_0_IRQ_CMD);
915*4882a593Smuzhiyun }
916*4882a593Smuzhiyun 
vfe_violation_read(struct vfe_device * vfe)917*4882a593Smuzhiyun static void vfe_violation_read(struct vfe_device *vfe)
918*4882a593Smuzhiyun {
919*4882a593Smuzhiyun 	u32 violation = readl_relaxed(vfe->base + VFE_0_VIOLATION_STATUS);
920*4882a593Smuzhiyun 
921*4882a593Smuzhiyun 	pr_err_ratelimited("VFE: violation = 0x%08x\n", violation);
922*4882a593Smuzhiyun }
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun /*
925*4882a593Smuzhiyun  * vfe_isr - ISPIF module interrupt handler
926*4882a593Smuzhiyun  * @irq: Interrupt line
927*4882a593Smuzhiyun  * @dev: VFE device
928*4882a593Smuzhiyun  *
929*4882a593Smuzhiyun  * Return IRQ_HANDLED on success
930*4882a593Smuzhiyun  */
vfe_isr(int irq,void * dev)931*4882a593Smuzhiyun static irqreturn_t vfe_isr(int irq, void *dev)
932*4882a593Smuzhiyun {
933*4882a593Smuzhiyun 	struct vfe_device *vfe = dev;
934*4882a593Smuzhiyun 	u32 value0, value1;
935*4882a593Smuzhiyun 	int i, j;
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 	vfe->ops->isr_read(vfe, &value0, &value1);
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun 	trace_printk("VFE: status0 = 0x%08x, status1 = 0x%08x\n",
940*4882a593Smuzhiyun 		     value0, value1);
941*4882a593Smuzhiyun 
942*4882a593Smuzhiyun 	if (value0 & VFE_0_IRQ_STATUS_0_RESET_ACK)
943*4882a593Smuzhiyun 		vfe->isr_ops.reset_ack(vfe);
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun 	if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION)
946*4882a593Smuzhiyun 		vfe->ops->violation_read(vfe);
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun 	if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK)
949*4882a593Smuzhiyun 		vfe->isr_ops.halt_ack(vfe);
950*4882a593Smuzhiyun 
951*4882a593Smuzhiyun 	for (i = VFE_LINE_RDI0; i <= VFE_LINE_PIX; i++)
952*4882a593Smuzhiyun 		if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i))
953*4882a593Smuzhiyun 			vfe->isr_ops.reg_update(vfe, i);
954*4882a593Smuzhiyun 
955*4882a593Smuzhiyun 	if (value0 & VFE_0_IRQ_STATUS_0_CAMIF_SOF)
956*4882a593Smuzhiyun 		vfe->isr_ops.sof(vfe, VFE_LINE_PIX);
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	for (i = VFE_LINE_RDI0; i <= VFE_LINE_RDI2; i++)
959*4882a593Smuzhiyun 		if (value1 & VFE_0_IRQ_STATUS_1_RDIn_SOF(i))
960*4882a593Smuzhiyun 			vfe->isr_ops.sof(vfe, i);
961*4882a593Smuzhiyun 
962*4882a593Smuzhiyun 	for (i = 0; i < MSM_VFE_COMPOSITE_IRQ_NUM; i++)
963*4882a593Smuzhiyun 		if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_COMPOSITE_DONE_n(i)) {
964*4882a593Smuzhiyun 			vfe->isr_ops.comp_done(vfe, i);
965*4882a593Smuzhiyun 			for (j = 0; j < ARRAY_SIZE(vfe->wm_output_map); j++)
966*4882a593Smuzhiyun 				if (vfe->wm_output_map[j] == VFE_LINE_PIX)
967*4882a593Smuzhiyun 					value0 &= ~VFE_0_IRQ_MASK_0_IMAGE_MASTER_n_PING_PONG(j);
968*4882a593Smuzhiyun 		}
969*4882a593Smuzhiyun 
970*4882a593Smuzhiyun 	for (i = 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++)
971*4882a593Smuzhiyun 		if (value0 & VFE_0_IRQ_STATUS_0_IMAGE_MASTER_n_PING_PONG(i))
972*4882a593Smuzhiyun 			vfe->isr_ops.wm_done(vfe, i);
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 	return IRQ_HANDLED;
975*4882a593Smuzhiyun }
976*4882a593Smuzhiyun 
977*4882a593Smuzhiyun const struct vfe_hw_ops vfe_ops_4_1 = {
978*4882a593Smuzhiyun 	.hw_version_read = vfe_hw_version_read,
979*4882a593Smuzhiyun 	.get_ub_size = vfe_get_ub_size,
980*4882a593Smuzhiyun 	.global_reset = vfe_global_reset,
981*4882a593Smuzhiyun 	.halt_request = vfe_halt_request,
982*4882a593Smuzhiyun 	.halt_clear = vfe_halt_clear,
983*4882a593Smuzhiyun 	.wm_enable = vfe_wm_enable,
984*4882a593Smuzhiyun 	.wm_frame_based = vfe_wm_frame_based,
985*4882a593Smuzhiyun 	.wm_line_based = vfe_wm_line_based,
986*4882a593Smuzhiyun 	.wm_set_framedrop_period = vfe_wm_set_framedrop_period,
987*4882a593Smuzhiyun 	.wm_set_framedrop_pattern = vfe_wm_set_framedrop_pattern,
988*4882a593Smuzhiyun 	.wm_set_ub_cfg = vfe_wm_set_ub_cfg,
989*4882a593Smuzhiyun 	.bus_reload_wm = vfe_bus_reload_wm,
990*4882a593Smuzhiyun 	.wm_set_ping_addr = vfe_wm_set_ping_addr,
991*4882a593Smuzhiyun 	.wm_set_pong_addr = vfe_wm_set_pong_addr,
992*4882a593Smuzhiyun 	.wm_get_ping_pong_status = vfe_wm_get_ping_pong_status,
993*4882a593Smuzhiyun 	.bus_enable_wr_if = vfe_bus_enable_wr_if,
994*4882a593Smuzhiyun 	.bus_connect_wm_to_rdi = vfe_bus_connect_wm_to_rdi,
995*4882a593Smuzhiyun 	.wm_set_subsample = vfe_wm_set_subsample,
996*4882a593Smuzhiyun 	.bus_disconnect_wm_from_rdi = vfe_bus_disconnect_wm_from_rdi,
997*4882a593Smuzhiyun 	.set_xbar_cfg = vfe_set_xbar_cfg,
998*4882a593Smuzhiyun 	.set_realign_cfg = vfe_set_realign_cfg,
999*4882a593Smuzhiyun 	.set_rdi_cid = vfe_set_rdi_cid,
1000*4882a593Smuzhiyun 	.reg_update = vfe_reg_update,
1001*4882a593Smuzhiyun 	.reg_update_clear = vfe_reg_update_clear,
1002*4882a593Smuzhiyun 	.enable_irq_wm_line = vfe_enable_irq_wm_line,
1003*4882a593Smuzhiyun 	.enable_irq_pix_line = vfe_enable_irq_pix_line,
1004*4882a593Smuzhiyun 	.enable_irq_common = vfe_enable_irq_common,
1005*4882a593Smuzhiyun 	.set_demux_cfg = vfe_set_demux_cfg,
1006*4882a593Smuzhiyun 	.set_scale_cfg = vfe_set_scale_cfg,
1007*4882a593Smuzhiyun 	.set_crop_cfg = vfe_set_crop_cfg,
1008*4882a593Smuzhiyun 	.set_clamp_cfg = vfe_set_clamp_cfg,
1009*4882a593Smuzhiyun 	.set_qos = vfe_set_qos,
1010*4882a593Smuzhiyun 	.set_ds = vfe_set_ds,
1011*4882a593Smuzhiyun 	.set_cgc_override = vfe_set_cgc_override,
1012*4882a593Smuzhiyun 	.set_camif_cfg = vfe_set_camif_cfg,
1013*4882a593Smuzhiyun 	.set_camif_cmd = vfe_set_camif_cmd,
1014*4882a593Smuzhiyun 	.set_module_cfg = vfe_set_module_cfg,
1015*4882a593Smuzhiyun 	.camif_wait_for_stop = vfe_camif_wait_for_stop,
1016*4882a593Smuzhiyun 	.isr_read = vfe_isr_read,
1017*4882a593Smuzhiyun 	.violation_read = vfe_violation_read,
1018*4882a593Smuzhiyun 	.isr = vfe_isr,
1019*4882a593Smuzhiyun };
1020