19c92ab61SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a67719d1SMark Yao /*
3a67719d1SMark Yao  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4a67719d1SMark Yao  * Author:Mark Yao <mark.yao@rock-chips.com>
5a67719d1SMark Yao  */
6a67719d1SMark Yao 
7a67719d1SMark Yao #include <linux/component.h>
8c2156ccdSSam Ravnborg #include <linux/mod_devicetable.h>
9c2156ccdSSam Ravnborg #include <linux/module.h>
10c2156ccdSSam Ravnborg #include <linux/of.h>
11c2156ccdSSam Ravnborg #include <linux/platform_device.h>
12c2156ccdSSam Ravnborg 
13c2156ccdSSam Ravnborg #include <drm/drm_fourcc.h>
14c2156ccdSSam Ravnborg #include <drm/drm_plane.h>
15c2156ccdSSam Ravnborg #include <drm/drm_print.h>
16a67719d1SMark Yao 
17a67719d1SMark Yao #include "rockchip_drm_vop.h"
18a67719d1SMark Yao #include "rockchip_vop_reg.h"
19b02516b6SBen Dooks #include "rockchip_drm_drv.h"
20a67719d1SMark Yao 
219548e1b4SMark yao #define _VOP_REG(off, _mask, _shift, _write_mask, _relaxed) \
229548e1b4SMark yao 		{ \
239548e1b4SMark yao 		 .offset = off, \
24a67719d1SMark Yao 		 .mask = _mask, \
259548e1b4SMark yao 		 .shift = _shift, \
269548e1b4SMark yao 		 .write_mask = _write_mask, \
279548e1b4SMark yao 		 .relaxed = _relaxed, \
289548e1b4SMark yao 		}
29d49463ecSMark Yao 
309548e1b4SMark yao #define VOP_REG(off, _mask, _shift) \
319548e1b4SMark yao 		_VOP_REG(off, _mask, _shift, false, true)
329548e1b4SMark yao 
339548e1b4SMark yao #define VOP_REG_SYNC(off, _mask, _shift) \
349548e1b4SMark yao 		_VOP_REG(off, _mask, _shift, false, false)
359548e1b4SMark yao 
369548e1b4SMark yao #define VOP_REG_MASK_SYNC(off, _mask, _shift) \
379548e1b4SMark yao 		_VOP_REG(off, _mask, _shift, true, false)
38a67719d1SMark Yao 
39f7673453SMark Yao static const uint32_t formats_win_full[] = {
40a67719d1SMark Yao 	DRM_FORMAT_XRGB8888,
41a67719d1SMark Yao 	DRM_FORMAT_ARGB8888,
42a67719d1SMark Yao 	DRM_FORMAT_XBGR8888,
43a67719d1SMark Yao 	DRM_FORMAT_ABGR8888,
44a67719d1SMark Yao 	DRM_FORMAT_RGB888,
45a67719d1SMark Yao 	DRM_FORMAT_BGR888,
46a67719d1SMark Yao 	DRM_FORMAT_RGB565,
47a67719d1SMark Yao 	DRM_FORMAT_BGR565,
48a67719d1SMark Yao 	DRM_FORMAT_NV12,
49a67719d1SMark Yao 	DRM_FORMAT_NV16,
50a67719d1SMark Yao 	DRM_FORMAT_NV24,
51a67719d1SMark Yao };
52a67719d1SMark Yao 
53f7673453SMark Yao static const uint32_t formats_win_lite[] = {
54a67719d1SMark Yao 	DRM_FORMAT_XRGB8888,
55a67719d1SMark Yao 	DRM_FORMAT_ARGB8888,
56a67719d1SMark Yao 	DRM_FORMAT_XBGR8888,
57a67719d1SMark Yao 	DRM_FORMAT_ABGR8888,
58a67719d1SMark Yao 	DRM_FORMAT_RGB888,
59a67719d1SMark Yao 	DRM_FORMAT_BGR888,
60a67719d1SMark Yao 	DRM_FORMAT_RGB565,
61a67719d1SMark Yao 	DRM_FORMAT_BGR565,
62a67719d1SMark Yao };
63a67719d1SMark Yao 
64b51502adSMark Yao static const struct vop_scl_regs rk3036_win_scl = {
65b51502adSMark Yao 	.scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
66b51502adSMark Yao 	.scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
67b51502adSMark Yao 	.scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
68b51502adSMark Yao 	.scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
69b51502adSMark Yao };
70b51502adSMark Yao 
71b51502adSMark Yao static const struct vop_win_phy rk3036_win0_data = {
72b51502adSMark Yao 	.scl = &rk3036_win_scl,
73b51502adSMark Yao 	.data_formats = formats_win_full,
74b51502adSMark Yao 	.nformats = ARRAY_SIZE(formats_win_full),
75b51502adSMark Yao 	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
76b51502adSMark Yao 	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
77b51502adSMark Yao 	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
78b51502adSMark Yao 	.act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
79b51502adSMark Yao 	.dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
80b51502adSMark Yao 	.dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
81b51502adSMark Yao 	.yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
82b51502adSMark Yao 	.uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
83b51502adSMark Yao 	.yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
84b51502adSMark Yao 	.uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16),
85b51502adSMark Yao };
86b51502adSMark Yao 
87b51502adSMark Yao static const struct vop_win_phy rk3036_win1_data = {
88b51502adSMark Yao 	.data_formats = formats_win_lite,
89b51502adSMark Yao 	.nformats = ARRAY_SIZE(formats_win_lite),
90b51502adSMark Yao 	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
91b51502adSMark Yao 	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
92b51502adSMark Yao 	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
93b51502adSMark Yao 	.act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
94b51502adSMark Yao 	.dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
95b51502adSMark Yao 	.dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
96b51502adSMark Yao 	.yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
97b51502adSMark Yao 	.yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
98b51502adSMark Yao };
99b51502adSMark Yao 
100b51502adSMark Yao static const struct vop_win_data rk3036_vop_win_data[] = {
101b51502adSMark Yao 	{ .base = 0x00, .phy = &rk3036_win0_data,
102b51502adSMark Yao 	  .type = DRM_PLANE_TYPE_PRIMARY },
103b51502adSMark Yao 	{ .base = 0x00, .phy = &rk3036_win1_data,
104b51502adSMark Yao 	  .type = DRM_PLANE_TYPE_CURSOR },
105b51502adSMark Yao };
106b51502adSMark Yao 
107b51502adSMark Yao static const int rk3036_vop_intrs[] = {
108b51502adSMark Yao 	DSP_HOLD_VALID_INTR,
109b51502adSMark Yao 	FS_INTR,
110b51502adSMark Yao 	LINE_FLAG_INTR,
111b51502adSMark Yao 	BUS_ERROR_INTR,
112b51502adSMark Yao };
113b51502adSMark Yao 
114b51502adSMark Yao static const struct vop_intr rk3036_intr = {
115b51502adSMark Yao 	.intrs = rk3036_vop_intrs,
116b51502adSMark Yao 	.nintrs = ARRAY_SIZE(rk3036_vop_intrs),
117ac6560dfSMark yao 	.line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12),
1189a61c54bSMark yao 	.status = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 0),
1199a61c54bSMark yao 	.enable = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 4),
1209a61c54bSMark yao 	.clear = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 8),
121b51502adSMark Yao };
122b51502adSMark Yao 
1239a61c54bSMark yao static const struct vop_modeset rk3036_modeset = {
124b51502adSMark Yao 	.htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
125b51502adSMark Yao 	.hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
126b51502adSMark Yao 	.vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
127b51502adSMark Yao 	.vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
1289a61c54bSMark yao };
1299a61c54bSMark yao 
1309a61c54bSMark yao static const struct vop_output rk3036_output = {
1319a61c54bSMark yao 	.pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
1329a61c54bSMark yao };
1339a61c54bSMark yao 
1349a61c54bSMark yao static const struct vop_common rk3036_common = {
1359a61c54bSMark yao 	.standby = VOP_REG_SYNC(RK3036_SYS_CTRL, 0x1, 30),
1369a61c54bSMark yao 	.out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
1379a61c54bSMark yao 	.dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24),
138a5c0fa44SUrja Rannikko 	.dither_down_sel = VOP_REG(RK3036_DSP_CTRL0, 0x1, 27),
139a5c0fa44SUrja Rannikko 	.dither_down_en = VOP_REG(RK3036_DSP_CTRL0, 0x1, 11),
140a5c0fa44SUrja Rannikko 	.dither_down_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 10),
1419548e1b4SMark yao 	.cfg_done = VOP_REG_SYNC(RK3036_REG_CFG_DONE, 0x1, 0),
142b51502adSMark Yao };
143b51502adSMark Yao 
144b51502adSMark Yao static const struct vop_data rk3036_vop = {
145b51502adSMark Yao 	.intr = &rk3036_intr,
1469a61c54bSMark yao 	.common = &rk3036_common,
1479a61c54bSMark yao 	.modeset = &rk3036_modeset,
1489a61c54bSMark yao 	.output = &rk3036_output,
149b51502adSMark Yao 	.win = rk3036_vop_win_data,
150b51502adSMark Yao 	.win_size = ARRAY_SIZE(rk3036_vop_win_data),
151b51502adSMark Yao };
152b51502adSMark Yao 
153460c3b00SSandy Huang static const struct vop_win_phy rk3126_win1_data = {
154460c3b00SSandy Huang 	.data_formats = formats_win_lite,
155460c3b00SSandy Huang 	.nformats = ARRAY_SIZE(formats_win_lite),
156460c3b00SSandy Huang 	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
157460c3b00SSandy Huang 	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
158460c3b00SSandy Huang 	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
159460c3b00SSandy Huang 	.dsp_info = VOP_REG(RK3126_WIN1_DSP_INFO, 0x0fff0fff, 0),
160460c3b00SSandy Huang 	.dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0),
161460c3b00SSandy Huang 	.yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0),
162460c3b00SSandy Huang 	.yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
163460c3b00SSandy Huang };
164460c3b00SSandy Huang 
165460c3b00SSandy Huang static const struct vop_win_data rk3126_vop_win_data[] = {
166460c3b00SSandy Huang 	{ .base = 0x00, .phy = &rk3036_win0_data,
167460c3b00SSandy Huang 	  .type = DRM_PLANE_TYPE_PRIMARY },
168460c3b00SSandy Huang 	{ .base = 0x00, .phy = &rk3126_win1_data,
169460c3b00SSandy Huang 	  .type = DRM_PLANE_TYPE_CURSOR },
170460c3b00SSandy Huang };
171460c3b00SSandy Huang 
172460c3b00SSandy Huang static const struct vop_data rk3126_vop = {
173460c3b00SSandy Huang 	.intr = &rk3036_intr,
174460c3b00SSandy Huang 	.common = &rk3036_common,
175460c3b00SSandy Huang 	.modeset = &rk3036_modeset,
176460c3b00SSandy Huang 	.output = &rk3036_output,
177460c3b00SSandy Huang 	.win = rk3126_vop_win_data,
178460c3b00SSandy Huang 	.win_size = ARRAY_SIZE(rk3126_vop_win_data),
179460c3b00SSandy Huang };
180460c3b00SSandy Huang 
181570913e0SSandy Huang static const int px30_vop_intrs[] = {
182570913e0SSandy Huang 	FS_INTR,
183570913e0SSandy Huang 	0, 0,
184570913e0SSandy Huang 	LINE_FLAG_INTR,
185570913e0SSandy Huang 	0,
186570913e0SSandy Huang 	BUS_ERROR_INTR,
187570913e0SSandy Huang 	0, 0,
188570913e0SSandy Huang 	DSP_HOLD_VALID_INTR,
189570913e0SSandy Huang };
190570913e0SSandy Huang 
191570913e0SSandy Huang static const struct vop_intr px30_intr = {
192570913e0SSandy Huang 	.intrs = px30_vop_intrs,
193570913e0SSandy Huang 	.nintrs = ARRAY_SIZE(px30_vop_intrs),
194a6edf839SSandy Huang 	.line_flag_num[0] = VOP_REG(PX30_LINE_FLAG, 0xfff, 0),
195a6edf839SSandy Huang 	.status = VOP_REG_MASK_SYNC(PX30_INTR_STATUS, 0xffff, 0),
196a6edf839SSandy Huang 	.enable = VOP_REG_MASK_SYNC(PX30_INTR_EN, 0xffff, 0),
197a6edf839SSandy Huang 	.clear = VOP_REG_MASK_SYNC(PX30_INTR_CLEAR, 0xffff, 0),
198570913e0SSandy Huang };
199570913e0SSandy Huang 
200570913e0SSandy Huang static const struct vop_common px30_common = {
201570913e0SSandy Huang 	.standby = VOP_REG_SYNC(PX30_SYS_CTRL2, 0x1, 1),
202570913e0SSandy Huang 	.out_mode = VOP_REG(PX30_DSP_CTRL2, 0xf, 16),
203570913e0SSandy Huang 	.dsp_blank = VOP_REG(PX30_DSP_CTRL2, 0x1, 14),
204a5c0fa44SUrja Rannikko 	.dither_down_en = VOP_REG(PX30_DSP_CTRL2, 0x1, 8),
205a5c0fa44SUrja Rannikko 	.dither_down_sel = VOP_REG(PX30_DSP_CTRL2, 0x1, 7),
206a5c0fa44SUrja Rannikko 	.dither_down_mode = VOP_REG(PX30_DSP_CTRL2, 0x1, 6),
207570913e0SSandy Huang 	.cfg_done = VOP_REG_SYNC(PX30_REG_CFG_DONE, 0x1, 0),
208570913e0SSandy Huang };
209570913e0SSandy Huang 
210570913e0SSandy Huang static const struct vop_modeset px30_modeset = {
211570913e0SSandy Huang 	.htotal_pw = VOP_REG(PX30_DSP_HTOTAL_HS_END, 0x0fff0fff, 0),
212570913e0SSandy Huang 	.hact_st_end = VOP_REG(PX30_DSP_HACT_ST_END, 0x0fff0fff, 0),
213570913e0SSandy Huang 	.vtotal_pw = VOP_REG(PX30_DSP_VTOTAL_VS_END, 0x0fff0fff, 0),
214570913e0SSandy Huang 	.vact_st_end = VOP_REG(PX30_DSP_VACT_ST_END, 0x0fff0fff, 0),
215570913e0SSandy Huang };
216570913e0SSandy Huang 
217570913e0SSandy Huang static const struct vop_output px30_output = {
218570913e0SSandy Huang 	.rgb_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0xf, 1),
219570913e0SSandy Huang 	.mipi_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0xf, 25),
220570913e0SSandy Huang 	.rgb_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 0),
221570913e0SSandy Huang 	.mipi_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 24),
222570913e0SSandy Huang };
223570913e0SSandy Huang 
224570913e0SSandy Huang static const struct vop_scl_regs px30_win_scl = {
225570913e0SSandy Huang 	.scale_yrgb_x = VOP_REG(PX30_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
226570913e0SSandy Huang 	.scale_yrgb_y = VOP_REG(PX30_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
227570913e0SSandy Huang 	.scale_cbcr_x = VOP_REG(PX30_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
228570913e0SSandy Huang 	.scale_cbcr_y = VOP_REG(PX30_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
229570913e0SSandy Huang };
230570913e0SSandy Huang 
231570913e0SSandy Huang static const struct vop_win_phy px30_win0_data = {
232570913e0SSandy Huang 	.scl = &px30_win_scl,
233570913e0SSandy Huang 	.data_formats = formats_win_full,
234570913e0SSandy Huang 	.nformats = ARRAY_SIZE(formats_win_full),
235570913e0SSandy Huang 	.enable = VOP_REG(PX30_WIN0_CTRL0, 0x1, 0),
236570913e0SSandy Huang 	.format = VOP_REG(PX30_WIN0_CTRL0, 0x7, 1),
237570913e0SSandy Huang 	.rb_swap = VOP_REG(PX30_WIN0_CTRL0, 0x1, 12),
238570913e0SSandy Huang 	.act_info = VOP_REG(PX30_WIN0_ACT_INFO, 0xffffffff, 0),
239570913e0SSandy Huang 	.dsp_info = VOP_REG(PX30_WIN0_DSP_INFO, 0xffffffff, 0),
240570913e0SSandy Huang 	.dsp_st = VOP_REG(PX30_WIN0_DSP_ST, 0xffffffff, 0),
241570913e0SSandy Huang 	.yrgb_mst = VOP_REG(PX30_WIN0_YRGB_MST0, 0xffffffff, 0),
242570913e0SSandy Huang 	.uv_mst = VOP_REG(PX30_WIN0_CBR_MST0, 0xffffffff, 0),
243570913e0SSandy Huang 	.yrgb_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 0),
244570913e0SSandy Huang 	.uv_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 16),
245570913e0SSandy Huang };
246570913e0SSandy Huang 
247570913e0SSandy Huang static const struct vop_win_phy px30_win1_data = {
248570913e0SSandy Huang 	.data_formats = formats_win_lite,
249570913e0SSandy Huang 	.nformats = ARRAY_SIZE(formats_win_lite),
250570913e0SSandy Huang 	.enable = VOP_REG(PX30_WIN1_CTRL0, 0x1, 0),
251570913e0SSandy Huang 	.format = VOP_REG(PX30_WIN1_CTRL0, 0x7, 4),
252570913e0SSandy Huang 	.rb_swap = VOP_REG(PX30_WIN1_CTRL0, 0x1, 12),
253570913e0SSandy Huang 	.dsp_info = VOP_REG(PX30_WIN1_DSP_INFO, 0xffffffff, 0),
254570913e0SSandy Huang 	.dsp_st = VOP_REG(PX30_WIN1_DSP_ST, 0xffffffff, 0),
255570913e0SSandy Huang 	.yrgb_mst = VOP_REG(PX30_WIN1_MST, 0xffffffff, 0),
256570913e0SSandy Huang 	.yrgb_vir = VOP_REG(PX30_WIN1_VIR, 0x1fff, 0),
257570913e0SSandy Huang };
258570913e0SSandy Huang 
259570913e0SSandy Huang static const struct vop_win_phy px30_win2_data = {
260570913e0SSandy Huang 	.data_formats = formats_win_lite,
261570913e0SSandy Huang 	.nformats = ARRAY_SIZE(formats_win_lite),
262a6edf839SSandy Huang 	.gate = VOP_REG(PX30_WIN2_CTRL0, 0x1, 4),
263a6edf839SSandy Huang 	.enable = VOP_REG(PX30_WIN2_CTRL0, 0x1, 0),
264570913e0SSandy Huang 	.format = VOP_REG(PX30_WIN2_CTRL0, 0x3, 5),
265570913e0SSandy Huang 	.rb_swap = VOP_REG(PX30_WIN2_CTRL0, 0x1, 20),
266570913e0SSandy Huang 	.dsp_info = VOP_REG(PX30_WIN2_DSP_INFO0, 0x0fff0fff, 0),
267570913e0SSandy Huang 	.dsp_st = VOP_REG(PX30_WIN2_DSP_ST0, 0x1fff1fff, 0),
268570913e0SSandy Huang 	.yrgb_mst = VOP_REG(PX30_WIN2_MST0, 0xffffffff, 0),
269570913e0SSandy Huang 	.yrgb_vir = VOP_REG(PX30_WIN2_VIR0_1, 0x1fff, 0),
270570913e0SSandy Huang };
271570913e0SSandy Huang 
272570913e0SSandy Huang static const struct vop_win_data px30_vop_big_win_data[] = {
273570913e0SSandy Huang 	{ .base = 0x00, .phy = &px30_win0_data,
274570913e0SSandy Huang 	  .type = DRM_PLANE_TYPE_PRIMARY },
275570913e0SSandy Huang 	{ .base = 0x00, .phy = &px30_win1_data,
276570913e0SSandy Huang 	  .type = DRM_PLANE_TYPE_OVERLAY },
277570913e0SSandy Huang 	{ .base = 0x00, .phy = &px30_win2_data,
278570913e0SSandy Huang 	  .type = DRM_PLANE_TYPE_CURSOR },
279570913e0SSandy Huang };
280570913e0SSandy Huang 
281570913e0SSandy Huang static const struct vop_data px30_vop_big = {
282570913e0SSandy Huang 	.intr = &px30_intr,
2838d544233SSandy Huang 	.feature = VOP_FEATURE_INTERNAL_RGB,
284570913e0SSandy Huang 	.common = &px30_common,
285570913e0SSandy Huang 	.modeset = &px30_modeset,
286570913e0SSandy Huang 	.output = &px30_output,
287570913e0SSandy Huang 	.win = px30_vop_big_win_data,
288570913e0SSandy Huang 	.win_size = ARRAY_SIZE(px30_vop_big_win_data),
289570913e0SSandy Huang };
290570913e0SSandy Huang 
291570913e0SSandy Huang static const struct vop_win_data px30_vop_lit_win_data[] = {
292570913e0SSandy Huang 	{ .base = 0x00, .phy = &px30_win1_data,
293570913e0SSandy Huang 	  .type = DRM_PLANE_TYPE_PRIMARY },
294570913e0SSandy Huang };
295570913e0SSandy Huang 
296570913e0SSandy Huang static const struct vop_data px30_vop_lit = {
297570913e0SSandy Huang 	.intr = &px30_intr,
2988d544233SSandy Huang 	.feature = VOP_FEATURE_INTERNAL_RGB,
299570913e0SSandy Huang 	.common = &px30_common,
300570913e0SSandy Huang 	.modeset = &px30_modeset,
301570913e0SSandy Huang 	.output = &px30_output,
302570913e0SSandy Huang 	.win = px30_vop_lit_win_data,
303570913e0SSandy Huang 	.win_size = ARRAY_SIZE(px30_vop_lit_win_data),
304570913e0SSandy Huang };
305570913e0SSandy Huang 
306f4a6de85SMark Yao static const struct vop_scl_regs rk3066_win_scl = {
307f4a6de85SMark Yao 	.scale_yrgb_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
308f4a6de85SMark Yao 	.scale_yrgb_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
309f4a6de85SMark Yao 	.scale_cbcr_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
310f4a6de85SMark Yao 	.scale_cbcr_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
311f4a6de85SMark Yao };
312f4a6de85SMark Yao 
313f4a6de85SMark Yao static const struct vop_win_phy rk3066_win0_data = {
314f4a6de85SMark Yao 	.scl = &rk3066_win_scl,
315f4a6de85SMark Yao 	.data_formats = formats_win_full,
316f4a6de85SMark Yao 	.nformats = ARRAY_SIZE(formats_win_full),
317f4a6de85SMark Yao 	.enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0),
318f4a6de85SMark Yao 	.format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 4),
319f4a6de85SMark Yao 	.rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 19),
320f4a6de85SMark Yao 	.act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0),
321f4a6de85SMark Yao 	.dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0),
322f4a6de85SMark Yao 	.dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0),
323f4a6de85SMark Yao 	.yrgb_mst = VOP_REG(RK3066_WIN0_YRGB_MST0, 0xffffffff, 0),
324f4a6de85SMark Yao 	.uv_mst = VOP_REG(RK3066_WIN0_CBR_MST0, 0xffffffff, 0),
325f4a6de85SMark Yao 	.yrgb_vir = VOP_REG(RK3066_WIN0_VIR, 0xffff, 0),
326f4a6de85SMark Yao 	.uv_vir = VOP_REG(RK3066_WIN0_VIR, 0x1fff, 16),
327f4a6de85SMark Yao };
328f4a6de85SMark Yao 
329f4a6de85SMark Yao static const struct vop_win_phy rk3066_win1_data = {
330f4a6de85SMark Yao 	.scl = &rk3066_win_scl,
331f4a6de85SMark Yao 	.data_formats = formats_win_full,
332f4a6de85SMark Yao 	.nformats = ARRAY_SIZE(formats_win_full),
333f4a6de85SMark Yao 	.enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1),
334f4a6de85SMark Yao 	.format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 7),
335f4a6de85SMark Yao 	.rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 23),
336f4a6de85SMark Yao 	.act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0),
337f4a6de85SMark Yao 	.dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0),
338f4a6de85SMark Yao 	.dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0),
339f4a6de85SMark Yao 	.yrgb_mst = VOP_REG(RK3066_WIN1_YRGB_MST, 0xffffffff, 0),
340f4a6de85SMark Yao 	.uv_mst = VOP_REG(RK3066_WIN1_CBR_MST, 0xffffffff, 0),
341f4a6de85SMark Yao 	.yrgb_vir = VOP_REG(RK3066_WIN1_VIR, 0xffff, 0),
342f4a6de85SMark Yao 	.uv_vir = VOP_REG(RK3066_WIN1_VIR, 0x1fff, 16),
343f4a6de85SMark Yao };
344f4a6de85SMark Yao 
345f4a6de85SMark Yao static const struct vop_win_phy rk3066_win2_data = {
346f4a6de85SMark Yao 	.data_formats = formats_win_lite,
347f4a6de85SMark Yao 	.nformats = ARRAY_SIZE(formats_win_lite),
348f4a6de85SMark Yao 	.enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2),
349f4a6de85SMark Yao 	.format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 10),
350f4a6de85SMark Yao 	.rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 27),
351f4a6de85SMark Yao 	.dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0),
352f4a6de85SMark Yao 	.dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0),
353f4a6de85SMark Yao 	.yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0),
354f4a6de85SMark Yao 	.yrgb_vir = VOP_REG(RK3066_WIN2_VIR, 0xffff, 0),
355f4a6de85SMark Yao };
356f4a6de85SMark Yao 
357f4a6de85SMark Yao static const struct vop_modeset rk3066_modeset = {
358f4a6de85SMark Yao 	.htotal_pw = VOP_REG(RK3066_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
359f4a6de85SMark Yao 	.hact_st_end = VOP_REG(RK3066_DSP_HACT_ST_END, 0x1fff1fff, 0),
360f4a6de85SMark Yao 	.vtotal_pw = VOP_REG(RK3066_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
361f4a6de85SMark Yao 	.vact_st_end = VOP_REG(RK3066_DSP_VACT_ST_END, 0x1fff1fff, 0),
362f4a6de85SMark Yao };
363f4a6de85SMark Yao 
364f4a6de85SMark Yao static const struct vop_output rk3066_output = {
365f4a6de85SMark Yao 	.pin_pol = VOP_REG(RK3066_DSP_CTRL0, 0x7, 4),
366f4a6de85SMark Yao };
367f4a6de85SMark Yao 
368f4a6de85SMark Yao static const struct vop_common rk3066_common = {
369f4a6de85SMark Yao 	.standby = VOP_REG(RK3066_SYS_CTRL0, 0x1, 1),
370f4a6de85SMark Yao 	.out_mode = VOP_REG(RK3066_DSP_CTRL0, 0xf, 0),
371f4a6de85SMark Yao 	.cfg_done = VOP_REG(RK3066_REG_CFG_DONE, 0x1, 0),
372a5c0fa44SUrja Rannikko 	.dither_down_en = VOP_REG(RK3066_DSP_CTRL0, 0x1, 11),
373a5c0fa44SUrja Rannikko 	.dither_down_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 10),
374f4a6de85SMark Yao 	.dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24),
375f4a6de85SMark Yao };
376f4a6de85SMark Yao 
377f4a6de85SMark Yao static const struct vop_win_data rk3066_vop_win_data[] = {
378f4a6de85SMark Yao 	{ .base = 0x00, .phy = &rk3066_win0_data,
379f4a6de85SMark Yao 	  .type = DRM_PLANE_TYPE_PRIMARY },
380f4a6de85SMark Yao 	{ .base = 0x00, .phy = &rk3066_win1_data,
381f4a6de85SMark Yao 	  .type = DRM_PLANE_TYPE_OVERLAY },
382f4a6de85SMark Yao 	{ .base = 0x00, .phy = &rk3066_win2_data,
383f4a6de85SMark Yao 	  .type = DRM_PLANE_TYPE_CURSOR },
384f4a6de85SMark Yao };
385f4a6de85SMark Yao 
386f4a6de85SMark Yao static const int rk3066_vop_intrs[] = {
387f4a6de85SMark Yao 	/*
388f4a6de85SMark Yao 	 * hs_start interrupt fires at frame-start, so serves
389f4a6de85SMark Yao 	 * the same purpose as dsp_hold in the driver.
390f4a6de85SMark Yao 	 */
391f4a6de85SMark Yao 	DSP_HOLD_VALID_INTR,
392f4a6de85SMark Yao 	FS_INTR,
393f4a6de85SMark Yao 	LINE_FLAG_INTR,
394f4a6de85SMark Yao 	BUS_ERROR_INTR,
395f4a6de85SMark Yao };
396f4a6de85SMark Yao 
397f4a6de85SMark Yao static const struct vop_intr rk3066_intr = {
398f4a6de85SMark Yao 	.intrs = rk3066_vop_intrs,
399f4a6de85SMark Yao 	.nintrs = ARRAY_SIZE(rk3066_vop_intrs),
400f4a6de85SMark Yao 	.line_flag_num[0] = VOP_REG(RK3066_INT_STATUS, 0xfff, 12),
401f4a6de85SMark Yao 	.status = VOP_REG(RK3066_INT_STATUS, 0xf, 0),
402f4a6de85SMark Yao 	.enable = VOP_REG(RK3066_INT_STATUS, 0xf, 4),
403f4a6de85SMark Yao 	.clear = VOP_REG(RK3066_INT_STATUS, 0xf, 8),
404f4a6de85SMark Yao };
405f4a6de85SMark Yao 
406f4a6de85SMark Yao static const struct vop_data rk3066_vop = {
407f4a6de85SMark Yao 	.version = VOP_VERSION(2, 1),
408f4a6de85SMark Yao 	.intr = &rk3066_intr,
409f4a6de85SMark Yao 	.common = &rk3066_common,
410f4a6de85SMark Yao 	.modeset = &rk3066_modeset,
411f4a6de85SMark Yao 	.output = &rk3066_output,
412f4a6de85SMark Yao 	.win = rk3066_vop_win_data,
413f4a6de85SMark Yao 	.win_size = ARRAY_SIZE(rk3066_vop_win_data),
414f4a6de85SMark Yao };
415f4a6de85SMark Yao 
416428e15ccSHeiko Stuebner static const struct vop_scl_regs rk3188_win_scl = {
417428e15ccSHeiko Stuebner 	.scale_yrgb_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
418428e15ccSHeiko Stuebner 	.scale_yrgb_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
419428e15ccSHeiko Stuebner 	.scale_cbcr_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
420428e15ccSHeiko Stuebner 	.scale_cbcr_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
421428e15ccSHeiko Stuebner };
422428e15ccSHeiko Stuebner 
423428e15ccSHeiko Stuebner static const struct vop_win_phy rk3188_win0_data = {
424428e15ccSHeiko Stuebner 	.scl = &rk3188_win_scl,
425428e15ccSHeiko Stuebner 	.data_formats = formats_win_full,
426428e15ccSHeiko Stuebner 	.nformats = ARRAY_SIZE(formats_win_full),
427428e15ccSHeiko Stuebner 	.enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 0),
428428e15ccSHeiko Stuebner 	.format = VOP_REG(RK3188_SYS_CTRL, 0x7, 3),
429428e15ccSHeiko Stuebner 	.rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 15),
430428e15ccSHeiko Stuebner 	.act_info = VOP_REG(RK3188_WIN0_ACT_INFO, 0x1fff1fff, 0),
431428e15ccSHeiko Stuebner 	.dsp_info = VOP_REG(RK3188_WIN0_DSP_INFO, 0x0fff0fff, 0),
432428e15ccSHeiko Stuebner 	.dsp_st = VOP_REG(RK3188_WIN0_DSP_ST, 0x1fff1fff, 0),
433428e15ccSHeiko Stuebner 	.yrgb_mst = VOP_REG(RK3188_WIN0_YRGB_MST0, 0xffffffff, 0),
434428e15ccSHeiko Stuebner 	.uv_mst = VOP_REG(RK3188_WIN0_CBR_MST0, 0xffffffff, 0),
435428e15ccSHeiko Stuebner 	.yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 0),
436428e15ccSHeiko Stuebner };
437428e15ccSHeiko Stuebner 
438428e15ccSHeiko Stuebner static const struct vop_win_phy rk3188_win1_data = {
439428e15ccSHeiko Stuebner 	.data_formats = formats_win_lite,
440428e15ccSHeiko Stuebner 	.nformats = ARRAY_SIZE(formats_win_lite),
441428e15ccSHeiko Stuebner 	.enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 1),
442428e15ccSHeiko Stuebner 	.format = VOP_REG(RK3188_SYS_CTRL, 0x7, 6),
443428e15ccSHeiko Stuebner 	.rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 19),
444428e15ccSHeiko Stuebner 	/* no act_info on window1 */
445428e15ccSHeiko Stuebner 	.dsp_info = VOP_REG(RK3188_WIN1_DSP_INFO, 0x07ff07ff, 0),
446428e15ccSHeiko Stuebner 	.dsp_st = VOP_REG(RK3188_WIN1_DSP_ST, 0x0fff0fff, 0),
447428e15ccSHeiko Stuebner 	.yrgb_mst = VOP_REG(RK3188_WIN1_MST, 0xffffffff, 0),
448428e15ccSHeiko Stuebner 	.yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 16),
449428e15ccSHeiko Stuebner };
450428e15ccSHeiko Stuebner 
451428e15ccSHeiko Stuebner static const struct vop_modeset rk3188_modeset = {
452428e15ccSHeiko Stuebner 	.htotal_pw = VOP_REG(RK3188_DSP_HTOTAL_HS_END, 0x0fff0fff, 0),
453428e15ccSHeiko Stuebner 	.hact_st_end = VOP_REG(RK3188_DSP_HACT_ST_END, 0x0fff0fff, 0),
454428e15ccSHeiko Stuebner 	.vtotal_pw = VOP_REG(RK3188_DSP_VTOTAL_VS_END, 0x0fff0fff, 0),
455428e15ccSHeiko Stuebner 	.vact_st_end = VOP_REG(RK3188_DSP_VACT_ST_END, 0x0fff0fff, 0),
456428e15ccSHeiko Stuebner };
457428e15ccSHeiko Stuebner 
458428e15ccSHeiko Stuebner static const struct vop_output rk3188_output = {
459428e15ccSHeiko Stuebner 	.pin_pol = VOP_REG(RK3188_DSP_CTRL0, 0xf, 4),
460428e15ccSHeiko Stuebner };
461428e15ccSHeiko Stuebner 
462428e15ccSHeiko Stuebner static const struct vop_common rk3188_common = {
463428e15ccSHeiko Stuebner 	.gate_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 31),
464428e15ccSHeiko Stuebner 	.standby = VOP_REG(RK3188_SYS_CTRL, 0x1, 30),
465428e15ccSHeiko Stuebner 	.out_mode = VOP_REG(RK3188_DSP_CTRL0, 0xf, 0),
466428e15ccSHeiko Stuebner 	.cfg_done = VOP_REG(RK3188_REG_CFG_DONE, 0x1, 0),
467a5c0fa44SUrja Rannikko 	.dither_down_sel = VOP_REG(RK3188_DSP_CTRL0, 0x1, 27),
468a5c0fa44SUrja Rannikko 	.dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11),
469a5c0fa44SUrja Rannikko 	.dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10),
470428e15ccSHeiko Stuebner 	.dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x3, 24),
471428e15ccSHeiko Stuebner };
472428e15ccSHeiko Stuebner 
473428e15ccSHeiko Stuebner static const struct vop_win_data rk3188_vop_win_data[] = {
474428e15ccSHeiko Stuebner 	{ .base = 0x00, .phy = &rk3188_win0_data,
475428e15ccSHeiko Stuebner 	  .type = DRM_PLANE_TYPE_PRIMARY },
476428e15ccSHeiko Stuebner 	{ .base = 0x00, .phy = &rk3188_win1_data,
477428e15ccSHeiko Stuebner 	  .type = DRM_PLANE_TYPE_CURSOR },
478428e15ccSHeiko Stuebner };
479428e15ccSHeiko Stuebner 
480428e15ccSHeiko Stuebner static const int rk3188_vop_intrs[] = {
4814f297df8SHeiko Stuebner 	/*
4824f297df8SHeiko Stuebner 	 * hs_start interrupt fires at frame-start, so serves
4834f297df8SHeiko Stuebner 	 * the same purpose as dsp_hold in the driver.
4844f297df8SHeiko Stuebner 	 */
4854f297df8SHeiko Stuebner 	DSP_HOLD_VALID_INTR,
486428e15ccSHeiko Stuebner 	FS_INTR,
487428e15ccSHeiko Stuebner 	LINE_FLAG_INTR,
488428e15ccSHeiko Stuebner 	BUS_ERROR_INTR,
489428e15ccSHeiko Stuebner };
490428e15ccSHeiko Stuebner 
491428e15ccSHeiko Stuebner static const struct vop_intr rk3188_vop_intr = {
492428e15ccSHeiko Stuebner 	.intrs = rk3188_vop_intrs,
493428e15ccSHeiko Stuebner 	.nintrs = ARRAY_SIZE(rk3188_vop_intrs),
494428e15ccSHeiko Stuebner 	.line_flag_num[0] = VOP_REG(RK3188_INT_STATUS, 0xfff, 12),
495428e15ccSHeiko Stuebner 	.status = VOP_REG(RK3188_INT_STATUS, 0xf, 0),
496428e15ccSHeiko Stuebner 	.enable = VOP_REG(RK3188_INT_STATUS, 0xf, 4),
497428e15ccSHeiko Stuebner 	.clear = VOP_REG(RK3188_INT_STATUS, 0xf, 8),
498428e15ccSHeiko Stuebner };
499428e15ccSHeiko Stuebner 
500428e15ccSHeiko Stuebner static const struct vop_data rk3188_vop = {
501428e15ccSHeiko Stuebner 	.intr = &rk3188_vop_intr,
502428e15ccSHeiko Stuebner 	.common = &rk3188_common,
503428e15ccSHeiko Stuebner 	.modeset = &rk3188_modeset,
504428e15ccSHeiko Stuebner 	.output = &rk3188_output,
505428e15ccSHeiko Stuebner 	.win = rk3188_vop_win_data,
506428e15ccSHeiko Stuebner 	.win_size = ARRAY_SIZE(rk3188_vop_win_data),
507428e15ccSHeiko Stuebner 	.feature = VOP_FEATURE_INTERNAL_RGB,
508428e15ccSHeiko Stuebner };
509428e15ccSHeiko Stuebner 
510f7673453SMark Yao static const struct vop_scl_extension rk3288_win_full_scl_ext = {
511f7673453SMark Yao 	.cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
512f7673453SMark Yao 	.cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
513f7673453SMark Yao 	.cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28),
514f7673453SMark Yao 	.cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26),
515f7673453SMark Yao 	.cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24),
516f7673453SMark Yao 	.yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23),
517f7673453SMark Yao 	.yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22),
518f7673453SMark Yao 	.yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20),
519f7673453SMark Yao 	.yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18),
520f7673453SMark Yao 	.yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16),
521f7673453SMark Yao 	.line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15),
522f7673453SMark Yao 	.cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12),
523f7673453SMark Yao 	.yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8),
524f7673453SMark Yao 	.vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7),
525f7673453SMark Yao 	.vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6),
526f7673453SMark Yao 	.vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5),
527f7673453SMark Yao 	.vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4),
528f7673453SMark Yao 	.bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2),
529f7673453SMark Yao 	.cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1),
530f7673453SMark Yao 	.yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0),
531f7673453SMark Yao 	.lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5),
5321194fffbSMark Yao };
5331194fffbSMark Yao 
534f7673453SMark Yao static const struct vop_scl_regs rk3288_win_full_scl = {
535f7673453SMark Yao 	.ext = &rk3288_win_full_scl_ext,
536f7673453SMark Yao 	.scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
537f7673453SMark Yao 	.scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
538f7673453SMark Yao 	.scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
539f7673453SMark Yao 	.scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
540a67719d1SMark Yao };
541a67719d1SMark Yao 
542f7673453SMark Yao static const struct vop_win_phy rk3288_win01_data = {
543f7673453SMark Yao 	.scl = &rk3288_win_full_scl,
544f7673453SMark Yao 	.data_formats = formats_win_full,
545f7673453SMark Yao 	.nformats = ARRAY_SIZE(formats_win_full),
546f7673453SMark Yao 	.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
547f7673453SMark Yao 	.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
548f7673453SMark Yao 	.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
549f7673453SMark Yao 	.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
550f7673453SMark Yao 	.dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
551f7673453SMark Yao 	.dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
552f7673453SMark Yao 	.yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
553f7673453SMark Yao 	.uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
554f7673453SMark Yao 	.yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
555f7673453SMark Yao 	.uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
556f7673453SMark Yao 	.src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
557f7673453SMark Yao 	.dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
5589dd2aca4SMark yao 	.channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0),
559a67719d1SMark Yao };
560a67719d1SMark Yao 
561f7673453SMark Yao static const struct vop_win_phy rk3288_win23_data = {
562f7673453SMark Yao 	.data_formats = formats_win_lite,
563f7673453SMark Yao 	.nformats = ARRAY_SIZE(formats_win_lite),
56460b7ae7fSMark yao 	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4),
56560b7ae7fSMark yao 	.gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
566f7673453SMark Yao 	.format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
567f7673453SMark Yao 	.rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
568f7673453SMark Yao 	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
569f7673453SMark Yao 	.dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0),
570f7673453SMark Yao 	.yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0),
571f7673453SMark Yao 	.yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0),
572f7673453SMark Yao 	.src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
573f7673453SMark Yao 	.dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
574a67719d1SMark Yao };
575a67719d1SMark Yao 
5769a61c54bSMark yao static const struct vop_modeset rk3288_modeset = {
577f7673453SMark Yao 	.htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
578f7673453SMark Yao 	.hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0),
579f7673453SMark Yao 	.vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
580f7673453SMark Yao 	.vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
581f7673453SMark Yao 	.hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
582f7673453SMark Yao 	.vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
5839a61c54bSMark yao };
5849a61c54bSMark yao 
5859a61c54bSMark yao static const struct vop_output rk3288_output = {
5869a61c54bSMark yao 	.pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4),
5879a61c54bSMark yao 	.rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
5889a61c54bSMark yao 	.hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
5899a61c54bSMark yao 	.edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
5909a61c54bSMark yao 	.mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
5919a61c54bSMark yao };
5929a61c54bSMark yao 
5939a61c54bSMark yao static const struct vop_common rk3288_common = {
5949a61c54bSMark yao 	.standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22),
5959a61c54bSMark yao 	.gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
5969a61c54bSMark yao 	.mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20),
597a5c0fa44SUrja Rannikko 	.dither_down_sel = VOP_REG(RK3288_DSP_CTRL1, 0x1, 4),
598a5c0fa44SUrja Rannikko 	.dither_down_mode = VOP_REG(RK3288_DSP_CTRL1, 0x1, 3),
599a5c0fa44SUrja Rannikko 	.dither_down_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 2),
6006bda8112SMark Yao 	.pre_dither_down = VOP_REG(RK3288_DSP_CTRL1, 0x1, 1),
6019a61c54bSMark yao 	.dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6),
602b23ab6acSEzequiel Garcia 	.dsp_lut_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 0),
6039a61c54bSMark yao 	.data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19),
6049a61c54bSMark yao 	.dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18),
6059a61c54bSMark yao 	.out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
6069548e1b4SMark yao 	.cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0),
607a67719d1SMark Yao };
608a67719d1SMark Yao 
609a67719d1SMark Yao /*
610a67719d1SMark Yao  * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
611a67719d1SMark Yao  * special support to get alpha blending working.  For now, just use overlay
612a67719d1SMark Yao  * window 3 for the drm cursor.
613a67719d1SMark Yao  *
614a67719d1SMark Yao  */
615a67719d1SMark Yao static const struct vop_win_data rk3288_vop_win_data[] = {
616f7673453SMark Yao 	{ .base = 0x00, .phy = &rk3288_win01_data,
617f7673453SMark Yao 	  .type = DRM_PLANE_TYPE_PRIMARY },
618f7673453SMark Yao 	{ .base = 0x40, .phy = &rk3288_win01_data,
619f7673453SMark Yao 	  .type = DRM_PLANE_TYPE_OVERLAY },
620f7673453SMark Yao 	{ .base = 0x00, .phy = &rk3288_win23_data,
621f7673453SMark Yao 	  .type = DRM_PLANE_TYPE_OVERLAY },
622f7673453SMark Yao 	{ .base = 0x50, .phy = &rk3288_win23_data,
623f7673453SMark Yao 	  .type = DRM_PLANE_TYPE_CURSOR },
624a67719d1SMark Yao };
625a67719d1SMark Yao 
626a67719d1SMark Yao static const int rk3288_vop_intrs[] = {
627a67719d1SMark Yao 	DSP_HOLD_VALID_INTR,
628a67719d1SMark Yao 	FS_INTR,
629a67719d1SMark Yao 	LINE_FLAG_INTR,
630a67719d1SMark Yao 	BUS_ERROR_INTR,
631a67719d1SMark Yao };
632a67719d1SMark Yao 
633a67719d1SMark Yao static const struct vop_intr rk3288_vop_intr = {
634a67719d1SMark Yao 	.intrs = rk3288_vop_intrs,
635a67719d1SMark Yao 	.nintrs = ARRAY_SIZE(rk3288_vop_intrs),
636ac6560dfSMark yao 	.line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12),
637f7673453SMark Yao 	.status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0),
638f7673453SMark Yao 	.enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4),
639f7673453SMark Yao 	.clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8),
640a67719d1SMark Yao };
641a67719d1SMark Yao 
642a67719d1SMark Yao static const struct vop_data rk3288_vop = {
643eb5cb6aaSMark yao 	.version = VOP_VERSION(3, 1),
644efd11cc8SMark yao 	.feature = VOP_FEATURE_OUTPUT_RGB10,
645a67719d1SMark Yao 	.intr = &rk3288_vop_intr,
6469a61c54bSMark yao 	.common = &rk3288_common,
6479a61c54bSMark yao 	.modeset = &rk3288_modeset,
6489a61c54bSMark yao 	.output = &rk3288_output,
649a67719d1SMark Yao 	.win = rk3288_vop_win_data,
650a67719d1SMark Yao 	.win_size = ARRAY_SIZE(rk3288_vop_win_data),
651b23ab6acSEzequiel Garcia 	.lut_size = 1024,
652a67719d1SMark Yao };
653a67719d1SMark Yao 
654eb5cb6aaSMark yao static const int rk3368_vop_intrs[] = {
6550a63bfd0SMark Yao 	FS_INTR,
6560a63bfd0SMark Yao 	0, 0,
6570a63bfd0SMark Yao 	LINE_FLAG_INTR,
6580a63bfd0SMark Yao 	0,
6590a63bfd0SMark Yao 	BUS_ERROR_INTR,
6600a63bfd0SMark Yao 	0, 0, 0, 0, 0, 0, 0,
6610a63bfd0SMark Yao 	DSP_HOLD_VALID_INTR,
662f7673453SMark Yao };
663f7673453SMark Yao 
664eb5cb6aaSMark yao static const struct vop_intr rk3368_vop_intr = {
665eb5cb6aaSMark yao 	.intrs = rk3368_vop_intrs,
666eb5cb6aaSMark yao 	.nintrs = ARRAY_SIZE(rk3368_vop_intrs),
667eb5cb6aaSMark yao 	.line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0),
668eb5cb6aaSMark yao 	.line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16),
669eb5cb6aaSMark yao 	.status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0),
670eb5cb6aaSMark yao 	.enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0),
671eb5cb6aaSMark yao 	.clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0),
672eb5cb6aaSMark yao };
673eb5cb6aaSMark yao 
674fbb1c738SEzequiel Garcia static const struct vop_win_phy rk3368_win01_data = {
675fbb1c738SEzequiel Garcia 	.scl = &rk3288_win_full_scl,
676fbb1c738SEzequiel Garcia 	.data_formats = formats_win_full,
677fbb1c738SEzequiel Garcia 	.nformats = ARRAY_SIZE(formats_win_full),
678fbb1c738SEzequiel Garcia 	.enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0),
679fbb1c738SEzequiel Garcia 	.format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1),
680fbb1c738SEzequiel Garcia 	.rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12),
681677e8bbcSDaniele Castagna 	.x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21),
682677e8bbcSDaniele Castagna 	.y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22),
683fbb1c738SEzequiel Garcia 	.act_info = VOP_REG(RK3368_WIN0_ACT_INFO, 0x1fff1fff, 0),
684fbb1c738SEzequiel Garcia 	.dsp_info = VOP_REG(RK3368_WIN0_DSP_INFO, 0x0fff0fff, 0),
685fbb1c738SEzequiel Garcia 	.dsp_st = VOP_REG(RK3368_WIN0_DSP_ST, 0x1fff1fff, 0),
686fbb1c738SEzequiel Garcia 	.yrgb_mst = VOP_REG(RK3368_WIN0_YRGB_MST, 0xffffffff, 0),
687fbb1c738SEzequiel Garcia 	.uv_mst = VOP_REG(RK3368_WIN0_CBR_MST, 0xffffffff, 0),
688fbb1c738SEzequiel Garcia 	.yrgb_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 0),
689fbb1c738SEzequiel Garcia 	.uv_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 16),
690fbb1c738SEzequiel Garcia 	.src_alpha_ctl = VOP_REG(RK3368_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
691fbb1c738SEzequiel Garcia 	.dst_alpha_ctl = VOP_REG(RK3368_WIN0_DST_ALPHA_CTRL, 0xff, 0),
692fbb1c738SEzequiel Garcia 	.channel = VOP_REG(RK3368_WIN0_CTRL2, 0xff, 0),
693fbb1c738SEzequiel Garcia };
694fbb1c738SEzequiel Garcia 
695eb5cb6aaSMark yao static const struct vop_win_phy rk3368_win23_data = {
696eb5cb6aaSMark yao 	.data_formats = formats_win_lite,
697eb5cb6aaSMark yao 	.nformats = ARRAY_SIZE(formats_win_lite),
698eb5cb6aaSMark yao 	.gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0),
699eb5cb6aaSMark yao 	.enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4),
700eb5cb6aaSMark yao 	.format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5),
701eb5cb6aaSMark yao 	.rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20),
702677e8bbcSDaniele Castagna 	.y_mir_en = VOP_REG(RK3368_WIN2_CTRL1, 0x1, 15),
703eb5cb6aaSMark yao 	.dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0),
704eb5cb6aaSMark yao 	.dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0),
705eb5cb6aaSMark yao 	.yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0),
706eb5cb6aaSMark yao 	.yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0),
707eb5cb6aaSMark yao 	.src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
708eb5cb6aaSMark yao 	.dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0),
709eb5cb6aaSMark yao };
710eb5cb6aaSMark yao 
711eb5cb6aaSMark yao static const struct vop_win_data rk3368_vop_win_data[] = {
712fbb1c738SEzequiel Garcia 	{ .base = 0x00, .phy = &rk3368_win01_data,
713eb5cb6aaSMark yao 	  .type = DRM_PLANE_TYPE_PRIMARY },
714fbb1c738SEzequiel Garcia 	{ .base = 0x40, .phy = &rk3368_win01_data,
715eb5cb6aaSMark yao 	  .type = DRM_PLANE_TYPE_OVERLAY },
716eb5cb6aaSMark yao 	{ .base = 0x00, .phy = &rk3368_win23_data,
717eb5cb6aaSMark yao 	  .type = DRM_PLANE_TYPE_OVERLAY },
718eb5cb6aaSMark yao 	{ .base = 0x50, .phy = &rk3368_win23_data,
719eb5cb6aaSMark yao 	  .type = DRM_PLANE_TYPE_CURSOR },
720eb5cb6aaSMark yao };
721eb5cb6aaSMark yao 
722eb5cb6aaSMark yao static const struct vop_output rk3368_output = {
723eb5cb6aaSMark yao 	.rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16),
724eb5cb6aaSMark yao 	.hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20),
725eb5cb6aaSMark yao 	.edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24),
726eb5cb6aaSMark yao 	.mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28),
727eb5cb6aaSMark yao 	.rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
728eb5cb6aaSMark yao 	.hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
729eb5cb6aaSMark yao 	.edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
730eb5cb6aaSMark yao 	.mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
731eb5cb6aaSMark yao };
732eb5cb6aaSMark yao 
733eb5cb6aaSMark yao static const struct vop_misc rk3368_misc = {
734eb5cb6aaSMark yao 	.global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11),
735eb5cb6aaSMark yao };
736eb5cb6aaSMark yao 
737eb5cb6aaSMark yao static const struct vop_data rk3368_vop = {
738eb5cb6aaSMark yao 	.version = VOP_VERSION(3, 2),
739eb5cb6aaSMark yao 	.intr = &rk3368_vop_intr,
740eb5cb6aaSMark yao 	.common = &rk3288_common,
741eb5cb6aaSMark yao 	.modeset = &rk3288_modeset,
742eb5cb6aaSMark yao 	.output = &rk3368_output,
743eb5cb6aaSMark yao 	.misc = &rk3368_misc,
744eb5cb6aaSMark yao 	.win = rk3368_vop_win_data,
745eb5cb6aaSMark yao 	.win_size = ARRAY_SIZE(rk3368_vop_win_data),
746eb5cb6aaSMark yao };
747eb5cb6aaSMark yao 
748eb5cb6aaSMark yao static const struct vop_intr rk3366_vop_intr = {
749eb5cb6aaSMark yao 	.intrs = rk3368_vop_intrs,
750eb5cb6aaSMark yao 	.nintrs = ARRAY_SIZE(rk3368_vop_intrs),
751eb5cb6aaSMark yao 	.line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0),
752eb5cb6aaSMark yao 	.line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16),
753eb5cb6aaSMark yao 	.status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0),
754eb5cb6aaSMark yao 	.enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0),
755eb5cb6aaSMark yao 	.clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0),
756eb5cb6aaSMark yao };
757eb5cb6aaSMark yao 
758eb5cb6aaSMark yao static const struct vop_data rk3366_vop = {
759eb5cb6aaSMark yao 	.version = VOP_VERSION(3, 4),
760eb5cb6aaSMark yao 	.intr = &rk3366_vop_intr,
761eb5cb6aaSMark yao 	.common = &rk3288_common,
762eb5cb6aaSMark yao 	.modeset = &rk3288_modeset,
763eb5cb6aaSMark yao 	.output = &rk3368_output,
764eb5cb6aaSMark yao 	.misc = &rk3368_misc,
765eb5cb6aaSMark yao 	.win = rk3368_vop_win_data,
766eb5cb6aaSMark yao 	.win_size = ARRAY_SIZE(rk3368_vop_win_data),
767f7673453SMark Yao };
768f7673453SMark Yao 
7699a61c54bSMark yao static const struct vop_output rk3399_output = {
7709a61c54bSMark yao 	.dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16),
771eb5cb6aaSMark yao 	.rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16),
772eb5cb6aaSMark yao 	.hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20),
773eb5cb6aaSMark yao 	.edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24),
774eb5cb6aaSMark yao 	.mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28),
7759a61c54bSMark yao 	.dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11),
7769a61c54bSMark yao 	.rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
7779a61c54bSMark yao 	.hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
7789a61c54bSMark yao 	.edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
7799a61c54bSMark yao 	.mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
780cf6d100dSHeiko Stuebner 	.mipi_dual_channel_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 3),
7819a61c54bSMark yao };
7829a61c54bSMark yao 
7831c21aa8fSDaniele Castagna static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win01_data = {
7841c21aa8fSDaniele Castagna 	.y2r_coefficients = {
7851c21aa8fSDaniele Castagna 		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 0),
7861c21aa8fSDaniele Castagna 		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 16),
7871c21aa8fSDaniele Castagna 		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 0),
7881c21aa8fSDaniele Castagna 		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 16),
7891c21aa8fSDaniele Castagna 		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 0),
7901c21aa8fSDaniele Castagna 		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 16),
7911c21aa8fSDaniele Castagna 		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 0),
7921c21aa8fSDaniele Castagna 		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 16),
7931c21aa8fSDaniele Castagna 		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 16, 0xffff, 0),
7941c21aa8fSDaniele Castagna 		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 20, 0xffffffff, 0),
7951c21aa8fSDaniele Castagna 		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 24, 0xffffffff, 0),
7961c21aa8fSDaniele Castagna 		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 28, 0xffffffff, 0),
7971c21aa8fSDaniele Castagna 	},
7981c21aa8fSDaniele Castagna };
7991c21aa8fSDaniele Castagna 
8001c21aa8fSDaniele Castagna static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win23_data = { };
8011c21aa8fSDaniele Castagna 
8021c21aa8fSDaniele Castagna static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = {
8031c21aa8fSDaniele Castagna 	{ .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
8041c21aa8fSDaniele Castagna 	  .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1) },
8051c21aa8fSDaniele Castagna 	{ .base = 0x60, .phy = &rk3399_yuv2yuv_win01_data,
8061c21aa8fSDaniele Castagna 	  .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9) },
8071c21aa8fSDaniele Castagna 	{ .base = 0xC0, .phy = &rk3399_yuv2yuv_win23_data },
8081c21aa8fSDaniele Castagna 	{ .base = 0x120, .phy = &rk3399_yuv2yuv_win23_data },
8091c21aa8fSDaniele Castagna };
8101c21aa8fSDaniele Castagna 
8110a63bfd0SMark Yao static const struct vop_data rk3399_vop_big = {
812eb5cb6aaSMark yao 	.version = VOP_VERSION(3, 5),
813efd11cc8SMark yao 	.feature = VOP_FEATURE_OUTPUT_RGB10,
814eb5cb6aaSMark yao 	.intr = &rk3366_vop_intr,
8159a61c54bSMark yao 	.common = &rk3288_common,
8169a61c54bSMark yao 	.modeset = &rk3288_modeset,
8179a61c54bSMark yao 	.output = &rk3399_output,
818eb5cb6aaSMark yao 	.misc = &rk3368_misc,
819eb5cb6aaSMark yao 	.win = rk3368_vop_win_data,
820eb5cb6aaSMark yao 	.win_size = ARRAY_SIZE(rk3368_vop_win_data),
8211c21aa8fSDaniele Castagna 	.win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data,
8220a63bfd0SMark Yao };
8230a63bfd0SMark Yao 
8240a63bfd0SMark Yao static const struct vop_win_data rk3399_vop_lit_win_data[] = {
825fbb1c738SEzequiel Garcia 	{ .base = 0x00, .phy = &rk3368_win01_data,
826f7673453SMark Yao 	  .type = DRM_PLANE_TYPE_PRIMARY },
827eb5cb6aaSMark yao 	{ .base = 0x00, .phy = &rk3368_win23_data,
828f7673453SMark Yao 	  .type = DRM_PLANE_TYPE_CURSOR},
829f7673453SMark Yao };
830f7673453SMark Yao 
8311c21aa8fSDaniele Castagna static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = {
8321c21aa8fSDaniele Castagna 	{ .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
8331c21aa8fSDaniele Castagna 	  .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1)},
8341c21aa8fSDaniele Castagna 	{ .base = 0x60, .phy = &rk3399_yuv2yuv_win23_data },
8351c21aa8fSDaniele Castagna };
8361c21aa8fSDaniele Castagna 
8370a63bfd0SMark Yao static const struct vop_data rk3399_vop_lit = {
838eb5cb6aaSMark yao 	.version = VOP_VERSION(3, 6),
839eb5cb6aaSMark yao 	.intr = &rk3366_vop_intr,
8409a61c54bSMark yao 	.common = &rk3288_common,
8419a61c54bSMark yao 	.modeset = &rk3288_modeset,
8429a61c54bSMark yao 	.output = &rk3399_output,
843eb5cb6aaSMark yao 	.misc = &rk3368_misc,
8440a63bfd0SMark Yao 	.win = rk3399_vop_lit_win_data,
8450a63bfd0SMark Yao 	.win_size = ARRAY_SIZE(rk3399_vop_lit_win_data),
8461c21aa8fSDaniele Castagna 	.win_yuv2yuv = rk3399_vop_lit_win_yuv2yuv_data,
847f7673453SMark Yao };
848f7673453SMark Yao 
849eb5cb6aaSMark yao static const struct vop_win_data rk3228_vop_win_data[] = {
850eb5cb6aaSMark yao 	{ .base = 0x00, .phy = &rk3288_win01_data,
851eb5cb6aaSMark yao 	  .type = DRM_PLANE_TYPE_PRIMARY },
852eb5cb6aaSMark yao 	{ .base = 0x40, .phy = &rk3288_win01_data,
853eb5cb6aaSMark yao 	  .type = DRM_PLANE_TYPE_CURSOR },
854eb5cb6aaSMark yao };
855eb5cb6aaSMark yao 
856eb5cb6aaSMark yao static const struct vop_data rk3228_vop = {
857eb5cb6aaSMark yao 	.version = VOP_VERSION(3, 7),
858eb5cb6aaSMark yao 	.feature = VOP_FEATURE_OUTPUT_RGB10,
859eb5cb6aaSMark yao 	.intr = &rk3366_vop_intr,
860eb5cb6aaSMark yao 	.common = &rk3288_common,
861eb5cb6aaSMark yao 	.modeset = &rk3288_modeset,
862eb5cb6aaSMark yao 	.output = &rk3399_output,
863eb5cb6aaSMark yao 	.misc = &rk3368_misc,
864eb5cb6aaSMark yao 	.win = rk3228_vop_win_data,
865eb5cb6aaSMark yao 	.win_size = ARRAY_SIZE(rk3228_vop_win_data),
866eb5cb6aaSMark yao };
867eb5cb6aaSMark yao 
868eb5cb6aaSMark yao static const struct vop_modeset rk3328_modeset = {
869eb5cb6aaSMark yao 	.htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
870eb5cb6aaSMark yao 	.hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0),
871eb5cb6aaSMark yao 	.vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
872eb5cb6aaSMark yao 	.vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0),
873eb5cb6aaSMark yao 	.hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
874eb5cb6aaSMark yao 	.vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
875eb5cb6aaSMark yao };
876eb5cb6aaSMark yao 
877eb5cb6aaSMark yao static const struct vop_output rk3328_output = {
878eb5cb6aaSMark yao 	.rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12),
879eb5cb6aaSMark yao 	.hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13),
880eb5cb6aaSMark yao 	.edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14),
881eb5cb6aaSMark yao 	.mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15),
882eb5cb6aaSMark yao 	.rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 16),
883eb5cb6aaSMark yao 	.hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 20),
884eb5cb6aaSMark yao 	.edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 24),
885eb5cb6aaSMark yao 	.mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 28),
886eb5cb6aaSMark yao };
887eb5cb6aaSMark yao 
888eb5cb6aaSMark yao static const struct vop_misc rk3328_misc = {
889eb5cb6aaSMark yao 	.global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11),
890eb5cb6aaSMark yao };
891eb5cb6aaSMark yao 
892eb5cb6aaSMark yao static const struct vop_common rk3328_common = {
893eb5cb6aaSMark yao 	.standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22),
894a5c0fa44SUrja Rannikko 	.dither_down_sel = VOP_REG(RK3328_DSP_CTRL1, 0x1, 4),
895a5c0fa44SUrja Rannikko 	.dither_down_mode = VOP_REG(RK3328_DSP_CTRL1, 0x1, 3),
896a5c0fa44SUrja Rannikko 	.dither_down_en = VOP_REG(RK3328_DSP_CTRL1, 0x1, 2),
897a5c0fa44SUrja Rannikko 	.pre_dither_down = VOP_REG(RK3328_DSP_CTRL1, 0x1, 1),
898eb5cb6aaSMark yao 	.dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6),
899eb5cb6aaSMark yao 	.dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18),
900eb5cb6aaSMark yao 	.out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0),
901eb5cb6aaSMark yao 	.cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0),
902eb5cb6aaSMark yao };
903eb5cb6aaSMark yao 
904eb5cb6aaSMark yao static const struct vop_intr rk3328_vop_intr = {
905eb5cb6aaSMark yao 	.intrs = rk3368_vop_intrs,
906eb5cb6aaSMark yao 	.nintrs = ARRAY_SIZE(rk3368_vop_intrs),
907eb5cb6aaSMark yao 	.line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0),
908eb5cb6aaSMark yao 	.line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16),
909eb5cb6aaSMark yao 	.status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0),
910eb5cb6aaSMark yao 	.enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0),
911eb5cb6aaSMark yao 	.clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0),
912eb5cb6aaSMark yao };
913eb5cb6aaSMark yao 
914eb5cb6aaSMark yao static const struct vop_win_data rk3328_vop_win_data[] = {
915fbb1c738SEzequiel Garcia 	{ .base = 0xd0, .phy = &rk3368_win01_data,
916eb5cb6aaSMark yao 	  .type = DRM_PLANE_TYPE_PRIMARY },
917fbb1c738SEzequiel Garcia 	{ .base = 0x1d0, .phy = &rk3368_win01_data,
918eb5cb6aaSMark yao 	  .type = DRM_PLANE_TYPE_OVERLAY },
919fbb1c738SEzequiel Garcia 	{ .base = 0x2d0, .phy = &rk3368_win01_data,
920eb5cb6aaSMark yao 	  .type = DRM_PLANE_TYPE_CURSOR },
921eb5cb6aaSMark yao };
922eb5cb6aaSMark yao 
923eb5cb6aaSMark yao static const struct vop_data rk3328_vop = {
924eb5cb6aaSMark yao 	.version = VOP_VERSION(3, 8),
925eb5cb6aaSMark yao 	.feature = VOP_FEATURE_OUTPUT_RGB10,
926eb5cb6aaSMark yao 	.intr = &rk3328_vop_intr,
927eb5cb6aaSMark yao 	.common = &rk3328_common,
928eb5cb6aaSMark yao 	.modeset = &rk3328_modeset,
929eb5cb6aaSMark yao 	.output = &rk3328_output,
930eb5cb6aaSMark yao 	.misc = &rk3328_misc,
931eb5cb6aaSMark yao 	.win = rk3328_vop_win_data,
932eb5cb6aaSMark yao 	.win_size = ARRAY_SIZE(rk3328_vop_win_data),
933eb5cb6aaSMark yao };
934eb5cb6aaSMark yao 
935a67719d1SMark Yao static const struct of_device_id vop_driver_dt_match[] = {
936f7673453SMark Yao 	{ .compatible = "rockchip,rk3036-vop",
937f7673453SMark Yao 	  .data = &rk3036_vop },
938460c3b00SSandy Huang 	{ .compatible = "rockchip,rk3126-vop",
939460c3b00SSandy Huang 	  .data = &rk3126_vop },
940570913e0SSandy Huang 	{ .compatible = "rockchip,px30-vop-big",
941570913e0SSandy Huang 	  .data = &px30_vop_big },
942570913e0SSandy Huang 	{ .compatible = "rockchip,px30-vop-lit",
943570913e0SSandy Huang 	  .data = &px30_vop_lit },
944f4a6de85SMark Yao 	{ .compatible = "rockchip,rk3066-vop",
945f4a6de85SMark Yao 	  .data = &rk3066_vop },
946428e15ccSHeiko Stuebner 	{ .compatible = "rockchip,rk3188-vop",
947428e15ccSHeiko Stuebner 	  .data = &rk3188_vop },
948b51502adSMark Yao 	{ .compatible = "rockchip,rk3288-vop",
949b51502adSMark Yao 	  .data = &rk3288_vop },
950eb5cb6aaSMark yao 	{ .compatible = "rockchip,rk3368-vop",
951eb5cb6aaSMark yao 	  .data = &rk3368_vop },
952eb5cb6aaSMark yao 	{ .compatible = "rockchip,rk3366-vop",
953eb5cb6aaSMark yao 	  .data = &rk3366_vop },
9540a63bfd0SMark Yao 	{ .compatible = "rockchip,rk3399-vop-big",
9550a63bfd0SMark Yao 	  .data = &rk3399_vop_big },
9560a63bfd0SMark Yao 	{ .compatible = "rockchip,rk3399-vop-lit",
9570a63bfd0SMark Yao 	  .data = &rk3399_vop_lit },
958eb5cb6aaSMark yao 	{ .compatible = "rockchip,rk3228-vop",
959eb5cb6aaSMark yao 	  .data = &rk3228_vop },
960eb5cb6aaSMark yao 	{ .compatible = "rockchip,rk3328-vop",
961eb5cb6aaSMark yao 	  .data = &rk3328_vop },
962a67719d1SMark Yao 	{},
963a67719d1SMark Yao };
964a67719d1SMark Yao MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
965a67719d1SMark Yao 
966a67719d1SMark Yao static int vop_probe(struct platform_device *pdev)
967a67719d1SMark Yao {
968a67719d1SMark Yao 	struct device *dev = &pdev->dev;
969a67719d1SMark Yao 
970a67719d1SMark Yao 	if (!dev->of_node) {
971d8dd6804SHaneen Mohammed 		DRM_DEV_ERROR(dev, "can't find vop devices\n");
972a67719d1SMark Yao 		return -ENODEV;
973a67719d1SMark Yao 	}
974a67719d1SMark Yao 
975a67719d1SMark Yao 	return component_add(dev, &vop_component_ops);
976a67719d1SMark Yao }
977a67719d1SMark Yao 
978a67719d1SMark Yao static int vop_remove(struct platform_device *pdev)
979a67719d1SMark Yao {
980a67719d1SMark Yao 	component_del(&pdev->dev, &vop_component_ops);
981a67719d1SMark Yao 
982a67719d1SMark Yao 	return 0;
983a67719d1SMark Yao }
984a67719d1SMark Yao 
9858820b68bSJeffy Chen struct platform_driver vop_platform_driver = {
986a67719d1SMark Yao 	.probe = vop_probe,
987a67719d1SMark Yao 	.remove = vop_remove,
988a67719d1SMark Yao 	.driver = {
989a67719d1SMark Yao 		.name = "rockchip-vop",
990a67719d1SMark Yao 		.of_match_table = of_match_ptr(vop_driver_dt_match),
991a67719d1SMark Yao 	},
992a67719d1SMark Yao };
993