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