GNU Linux-libre 5.10.153-gnu1
[releases.git] / drivers / gpu / drm / rockchip / rockchip_vop_reg.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4  * Author:Mark Yao <mark.yao@rock-chips.com>
5  */
6
7 #include <linux/component.h>
8 #include <linux/mod_devicetable.h>
9 #include <linux/module.h>
10 #include <linux/of.h>
11 #include <linux/platform_device.h>
12
13 #include <drm/drm_fourcc.h>
14 #include <drm/drm_plane.h>
15 #include <drm/drm_print.h>
16
17 #include "rockchip_drm_vop.h"
18 #include "rockchip_vop_reg.h"
19 #include "rockchip_drm_drv.h"
20
21 #define _VOP_REG(off, _mask, _shift, _write_mask, _relaxed) \
22                 { \
23                  .offset = off, \
24                  .mask = _mask, \
25                  .shift = _shift, \
26                  .write_mask = _write_mask, \
27                  .relaxed = _relaxed, \
28                 }
29
30 #define VOP_REG(off, _mask, _shift) \
31                 _VOP_REG(off, _mask, _shift, false, true)
32
33 #define VOP_REG_SYNC(off, _mask, _shift) \
34                 _VOP_REG(off, _mask, _shift, false, false)
35
36 #define VOP_REG_MASK_SYNC(off, _mask, _shift) \
37                 _VOP_REG(off, _mask, _shift, true, false)
38
39 static const uint32_t formats_win_full[] = {
40         DRM_FORMAT_XRGB8888,
41         DRM_FORMAT_ARGB8888,
42         DRM_FORMAT_XBGR8888,
43         DRM_FORMAT_ABGR8888,
44         DRM_FORMAT_RGB888,
45         DRM_FORMAT_BGR888,
46         DRM_FORMAT_RGB565,
47         DRM_FORMAT_BGR565,
48         DRM_FORMAT_NV12,
49         DRM_FORMAT_NV16,
50         DRM_FORMAT_NV24,
51 };
52
53 static const uint64_t format_modifiers_win_full[] = {
54         DRM_FORMAT_MOD_LINEAR,
55         DRM_FORMAT_MOD_INVALID,
56 };
57
58 static const uint64_t format_modifiers_win_full_afbc[] = {
59         ROCKCHIP_AFBC_MOD,
60         DRM_FORMAT_MOD_LINEAR,
61         DRM_FORMAT_MOD_INVALID,
62 };
63
64 static const uint32_t formats_win_lite[] = {
65         DRM_FORMAT_XRGB8888,
66         DRM_FORMAT_ARGB8888,
67         DRM_FORMAT_XBGR8888,
68         DRM_FORMAT_ABGR8888,
69         DRM_FORMAT_RGB888,
70         DRM_FORMAT_BGR888,
71         DRM_FORMAT_RGB565,
72         DRM_FORMAT_BGR565,
73 };
74
75 static const uint64_t format_modifiers_win_lite[] = {
76         DRM_FORMAT_MOD_LINEAR,
77         DRM_FORMAT_MOD_INVALID,
78 };
79
80 static const struct vop_scl_regs rk3036_win_scl = {
81         .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
82         .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
83         .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
84         .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
85 };
86
87 static const struct vop_win_phy rk3036_win0_data = {
88         .scl = &rk3036_win_scl,
89         .data_formats = formats_win_full,
90         .nformats = ARRAY_SIZE(formats_win_full),
91         .format_modifiers = format_modifiers_win_full,
92         .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
93         .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
94         .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
95         .act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
96         .dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
97         .dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
98         .yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
99         .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
100         .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
101         .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16),
102 };
103
104 static const struct vop_win_phy rk3036_win1_data = {
105         .data_formats = formats_win_lite,
106         .nformats = ARRAY_SIZE(formats_win_lite),
107         .format_modifiers = format_modifiers_win_lite,
108         .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
109         .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
110         .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
111         .act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
112         .dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
113         .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
114         .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
115         .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
116 };
117
118 static const struct vop_win_data rk3036_vop_win_data[] = {
119         { .base = 0x00, .phy = &rk3036_win0_data,
120           .type = DRM_PLANE_TYPE_PRIMARY },
121         { .base = 0x00, .phy = &rk3036_win1_data,
122           .type = DRM_PLANE_TYPE_CURSOR },
123 };
124
125 static const int rk3036_vop_intrs[] = {
126         DSP_HOLD_VALID_INTR,
127         FS_INTR,
128         LINE_FLAG_INTR,
129         BUS_ERROR_INTR,
130 };
131
132 static const struct vop_intr rk3036_intr = {
133         .intrs = rk3036_vop_intrs,
134         .nintrs = ARRAY_SIZE(rk3036_vop_intrs),
135         .line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12),
136         .status = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 0),
137         .enable = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 4),
138         .clear = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 8),
139 };
140
141 static const struct vop_modeset rk3036_modeset = {
142         .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
143         .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
144         .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
145         .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
146 };
147
148 static const struct vop_output rk3036_output = {
149         .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
150 };
151
152 static const struct vop_common rk3036_common = {
153         .standby = VOP_REG_SYNC(RK3036_SYS_CTRL, 0x1, 30),
154         .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
155         .dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24),
156         .dither_down_sel = VOP_REG(RK3036_DSP_CTRL0, 0x1, 27),
157         .dither_down_en = VOP_REG(RK3036_DSP_CTRL0, 0x1, 11),
158         .dither_down_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 10),
159         .cfg_done = VOP_REG_SYNC(RK3036_REG_CFG_DONE, 0x1, 0),
160 };
161
162 static const struct vop_data rk3036_vop = {
163         .intr = &rk3036_intr,
164         .common = &rk3036_common,
165         .modeset = &rk3036_modeset,
166         .output = &rk3036_output,
167         .win = rk3036_vop_win_data,
168         .win_size = ARRAY_SIZE(rk3036_vop_win_data),
169 };
170
171 static const struct vop_win_phy rk3126_win1_data = {
172         .data_formats = formats_win_lite,
173         .nformats = ARRAY_SIZE(formats_win_lite),
174         .format_modifiers = format_modifiers_win_lite,
175         .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
176         .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
177         .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
178         .dsp_info = VOP_REG(RK3126_WIN1_DSP_INFO, 0x0fff0fff, 0),
179         .dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0),
180         .yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0),
181         .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
182 };
183
184 static const struct vop_win_data rk3126_vop_win_data[] = {
185         { .base = 0x00, .phy = &rk3036_win0_data,
186           .type = DRM_PLANE_TYPE_PRIMARY },
187         { .base = 0x00, .phy = &rk3126_win1_data,
188           .type = DRM_PLANE_TYPE_CURSOR },
189 };
190
191 static const struct vop_data rk3126_vop = {
192         .intr = &rk3036_intr,
193         .common = &rk3036_common,
194         .modeset = &rk3036_modeset,
195         .output = &rk3036_output,
196         .win = rk3126_vop_win_data,
197         .win_size = ARRAY_SIZE(rk3126_vop_win_data),
198 };
199
200 static const int px30_vop_intrs[] = {
201         FS_INTR,
202         0, 0,
203         LINE_FLAG_INTR,
204         0,
205         BUS_ERROR_INTR,
206         0, 0,
207         DSP_HOLD_VALID_INTR,
208 };
209
210 static const struct vop_intr px30_intr = {
211         .intrs = px30_vop_intrs,
212         .nintrs = ARRAY_SIZE(px30_vop_intrs),
213         .line_flag_num[0] = VOP_REG(PX30_LINE_FLAG, 0xfff, 0),
214         .status = VOP_REG_MASK_SYNC(PX30_INTR_STATUS, 0xffff, 0),
215         .enable = VOP_REG_MASK_SYNC(PX30_INTR_EN, 0xffff, 0),
216         .clear = VOP_REG_MASK_SYNC(PX30_INTR_CLEAR, 0xffff, 0),
217 };
218
219 static const struct vop_common px30_common = {
220         .standby = VOP_REG_SYNC(PX30_SYS_CTRL2, 0x1, 1),
221         .out_mode = VOP_REG(PX30_DSP_CTRL2, 0xf, 16),
222         .dsp_blank = VOP_REG(PX30_DSP_CTRL2, 0x1, 14),
223         .dither_down_en = VOP_REG(PX30_DSP_CTRL2, 0x1, 8),
224         .dither_down_sel = VOP_REG(PX30_DSP_CTRL2, 0x1, 7),
225         .dither_down_mode = VOP_REG(PX30_DSP_CTRL2, 0x1, 6),
226         .cfg_done = VOP_REG_SYNC(PX30_REG_CFG_DONE, 0x1, 0),
227 };
228
229 static const struct vop_modeset px30_modeset = {
230         .htotal_pw = VOP_REG(PX30_DSP_HTOTAL_HS_END, 0x0fff0fff, 0),
231         .hact_st_end = VOP_REG(PX30_DSP_HACT_ST_END, 0x0fff0fff, 0),
232         .vtotal_pw = VOP_REG(PX30_DSP_VTOTAL_VS_END, 0x0fff0fff, 0),
233         .vact_st_end = VOP_REG(PX30_DSP_VACT_ST_END, 0x0fff0fff, 0),
234 };
235
236 static const struct vop_output px30_output = {
237         .rgb_dclk_pol = VOP_REG(PX30_DSP_CTRL0, 0x1, 1),
238         .rgb_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0x7, 2),
239         .rgb_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 0),
240         .mipi_dclk_pol = VOP_REG(PX30_DSP_CTRL0, 0x1, 25),
241         .mipi_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0x7, 26),
242         .mipi_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 24),
243 };
244
245 static const struct vop_scl_regs px30_win_scl = {
246         .scale_yrgb_x = VOP_REG(PX30_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
247         .scale_yrgb_y = VOP_REG(PX30_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
248         .scale_cbcr_x = VOP_REG(PX30_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
249         .scale_cbcr_y = VOP_REG(PX30_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
250 };
251
252 static const struct vop_win_phy px30_win0_data = {
253         .scl = &px30_win_scl,
254         .data_formats = formats_win_full,
255         .nformats = ARRAY_SIZE(formats_win_full),
256         .format_modifiers = format_modifiers_win_full,
257         .enable = VOP_REG(PX30_WIN0_CTRL0, 0x1, 0),
258         .format = VOP_REG(PX30_WIN0_CTRL0, 0x7, 1),
259         .rb_swap = VOP_REG(PX30_WIN0_CTRL0, 0x1, 12),
260         .act_info = VOP_REG(PX30_WIN0_ACT_INFO, 0xffffffff, 0),
261         .dsp_info = VOP_REG(PX30_WIN0_DSP_INFO, 0xffffffff, 0),
262         .dsp_st = VOP_REG(PX30_WIN0_DSP_ST, 0xffffffff, 0),
263         .yrgb_mst = VOP_REG(PX30_WIN0_YRGB_MST0, 0xffffffff, 0),
264         .uv_mst = VOP_REG(PX30_WIN0_CBR_MST0, 0xffffffff, 0),
265         .yrgb_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 0),
266         .uv_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 16),
267         .alpha_pre_mul = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 2),
268         .alpha_mode = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 1),
269         .alpha_en = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 0),
270 };
271
272 static const struct vop_win_phy px30_win1_data = {
273         .data_formats = formats_win_lite,
274         .nformats = ARRAY_SIZE(formats_win_lite),
275         .format_modifiers = format_modifiers_win_lite,
276         .enable = VOP_REG(PX30_WIN1_CTRL0, 0x1, 0),
277         .format = VOP_REG(PX30_WIN1_CTRL0, 0x7, 4),
278         .rb_swap = VOP_REG(PX30_WIN1_CTRL0, 0x1, 12),
279         .dsp_info = VOP_REG(PX30_WIN1_DSP_INFO, 0xffffffff, 0),
280         .dsp_st = VOP_REG(PX30_WIN1_DSP_ST, 0xffffffff, 0),
281         .yrgb_mst = VOP_REG(PX30_WIN1_MST, 0xffffffff, 0),
282         .yrgb_vir = VOP_REG(PX30_WIN1_VIR, 0x1fff, 0),
283         .alpha_pre_mul = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 2),
284         .alpha_mode = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 1),
285         .alpha_en = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 0),
286 };
287
288 static const struct vop_win_phy px30_win2_data = {
289         .data_formats = formats_win_lite,
290         .nformats = ARRAY_SIZE(formats_win_lite),
291         .format_modifiers = format_modifiers_win_lite,
292         .gate = VOP_REG(PX30_WIN2_CTRL0, 0x1, 4),
293         .enable = VOP_REG(PX30_WIN2_CTRL0, 0x1, 0),
294         .format = VOP_REG(PX30_WIN2_CTRL0, 0x3, 5),
295         .rb_swap = VOP_REG(PX30_WIN2_CTRL0, 0x1, 20),
296         .dsp_info = VOP_REG(PX30_WIN2_DSP_INFO0, 0x0fff0fff, 0),
297         .dsp_st = VOP_REG(PX30_WIN2_DSP_ST0, 0x1fff1fff, 0),
298         .yrgb_mst = VOP_REG(PX30_WIN2_MST0, 0xffffffff, 0),
299         .yrgb_vir = VOP_REG(PX30_WIN2_VIR0_1, 0x1fff, 0),
300         .alpha_pre_mul = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 2),
301         .alpha_mode = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 1),
302         .alpha_en = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 0),
303 };
304
305 static const struct vop_win_data px30_vop_big_win_data[] = {
306         { .base = 0x00, .phy = &px30_win0_data,
307           .type = DRM_PLANE_TYPE_PRIMARY },
308         { .base = 0x00, .phy = &px30_win1_data,
309           .type = DRM_PLANE_TYPE_OVERLAY },
310         { .base = 0x00, .phy = &px30_win2_data,
311           .type = DRM_PLANE_TYPE_CURSOR },
312 };
313
314 static const struct vop_data px30_vop_big = {
315         .intr = &px30_intr,
316         .feature = VOP_FEATURE_INTERNAL_RGB,
317         .common = &px30_common,
318         .modeset = &px30_modeset,
319         .output = &px30_output,
320         .win = px30_vop_big_win_data,
321         .win_size = ARRAY_SIZE(px30_vop_big_win_data),
322 };
323
324 static const struct vop_win_data px30_vop_lit_win_data[] = {
325         { .base = 0x00, .phy = &px30_win1_data,
326           .type = DRM_PLANE_TYPE_PRIMARY },
327 };
328
329 static const struct vop_data px30_vop_lit = {
330         .intr = &px30_intr,
331         .feature = VOP_FEATURE_INTERNAL_RGB,
332         .common = &px30_common,
333         .modeset = &px30_modeset,
334         .output = &px30_output,
335         .win = px30_vop_lit_win_data,
336         .win_size = ARRAY_SIZE(px30_vop_lit_win_data),
337 };
338
339 static const struct vop_scl_regs rk3066_win_scl = {
340         .scale_yrgb_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
341         .scale_yrgb_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
342         .scale_cbcr_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
343         .scale_cbcr_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
344 };
345
346 static const struct vop_win_phy rk3066_win0_data = {
347         .scl = &rk3066_win_scl,
348         .data_formats = formats_win_full,
349         .nformats = ARRAY_SIZE(formats_win_full),
350         .format_modifiers = format_modifiers_win_full,
351         .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0),
352         .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 4),
353         .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 19),
354         .act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0),
355         .dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0),
356         .dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0),
357         .yrgb_mst = VOP_REG(RK3066_WIN0_YRGB_MST0, 0xffffffff, 0),
358         .uv_mst = VOP_REG(RK3066_WIN0_CBR_MST0, 0xffffffff, 0),
359         .yrgb_vir = VOP_REG(RK3066_WIN0_VIR, 0xffff, 0),
360         .uv_vir = VOP_REG(RK3066_WIN0_VIR, 0x1fff, 16),
361 };
362
363 static const struct vop_win_phy rk3066_win1_data = {
364         .data_formats = formats_win_full,
365         .nformats = ARRAY_SIZE(formats_win_full),
366         .format_modifiers = format_modifiers_win_full,
367         .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1),
368         .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 7),
369         .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 23),
370         .act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0),
371         .dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0),
372         .dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0),
373         .yrgb_mst = VOP_REG(RK3066_WIN1_YRGB_MST, 0xffffffff, 0),
374         .uv_mst = VOP_REG(RK3066_WIN1_CBR_MST, 0xffffffff, 0),
375         .yrgb_vir = VOP_REG(RK3066_WIN1_VIR, 0xffff, 0),
376         .uv_vir = VOP_REG(RK3066_WIN1_VIR, 0x1fff, 16),
377 };
378
379 static const struct vop_win_phy rk3066_win2_data = {
380         .data_formats = formats_win_lite,
381         .nformats = ARRAY_SIZE(formats_win_lite),
382         .format_modifiers = format_modifiers_win_lite,
383         .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2),
384         .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 10),
385         .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 27),
386         .dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0),
387         .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0),
388         .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0),
389         .yrgb_vir = VOP_REG(RK3066_WIN2_VIR, 0xffff, 0),
390 };
391
392 static const struct vop_modeset rk3066_modeset = {
393         .htotal_pw = VOP_REG(RK3066_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
394         .hact_st_end = VOP_REG(RK3066_DSP_HACT_ST_END, 0x1fff1fff, 0),
395         .vtotal_pw = VOP_REG(RK3066_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
396         .vact_st_end = VOP_REG(RK3066_DSP_VACT_ST_END, 0x1fff1fff, 0),
397 };
398
399 static const struct vop_output rk3066_output = {
400         .pin_pol = VOP_REG(RK3066_DSP_CTRL0, 0x7, 4),
401 };
402
403 static const struct vop_common rk3066_common = {
404         .standby = VOP_REG(RK3066_SYS_CTRL0, 0x1, 1),
405         .out_mode = VOP_REG(RK3066_DSP_CTRL0, 0xf, 0),
406         .cfg_done = VOP_REG(RK3066_REG_CFG_DONE, 0x1, 0),
407         .dither_down_en = VOP_REG(RK3066_DSP_CTRL0, 0x1, 11),
408         .dither_down_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 10),
409         .dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24),
410         .dither_up = VOP_REG(RK3066_DSP_CTRL0, 0x1, 9),
411         .dsp_lut_en = VOP_REG(RK3066_SYS_CTRL1, 0x1, 31),
412         .data_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 25),
413 };
414
415 static const struct vop_win_data rk3066_vop_win_data[] = {
416         { .base = 0x00, .phy = &rk3066_win0_data,
417           .type = DRM_PLANE_TYPE_PRIMARY },
418         { .base = 0x00, .phy = &rk3066_win1_data,
419           .type = DRM_PLANE_TYPE_OVERLAY },
420         { .base = 0x00, .phy = &rk3066_win2_data,
421           .type = DRM_PLANE_TYPE_CURSOR },
422 };
423
424 static const int rk3066_vop_intrs[] = {
425         /*
426          * hs_start interrupt fires at frame-start, so serves
427          * the same purpose as dsp_hold in the driver.
428          */
429         DSP_HOLD_VALID_INTR,
430         FS_INTR,
431         LINE_FLAG_INTR,
432         BUS_ERROR_INTR,
433 };
434
435 static const struct vop_intr rk3066_intr = {
436         .intrs = rk3066_vop_intrs,
437         .nintrs = ARRAY_SIZE(rk3066_vop_intrs),
438         .line_flag_num[0] = VOP_REG(RK3066_INT_STATUS, 0xfff, 12),
439         .status = VOP_REG(RK3066_INT_STATUS, 0xf, 0),
440         .enable = VOP_REG(RK3066_INT_STATUS, 0xf, 4),
441         .clear = VOP_REG(RK3066_INT_STATUS, 0xf, 8),
442 };
443
444 static const struct vop_data rk3066_vop = {
445         .version = VOP_VERSION(2, 1),
446         .intr = &rk3066_intr,
447         .common = &rk3066_common,
448         .modeset = &rk3066_modeset,
449         .output = &rk3066_output,
450         .win = rk3066_vop_win_data,
451         .win_size = ARRAY_SIZE(rk3066_vop_win_data),
452 };
453
454 static const struct vop_scl_regs rk3188_win_scl = {
455         .scale_yrgb_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
456         .scale_yrgb_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
457         .scale_cbcr_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
458         .scale_cbcr_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
459 };
460
461 static const struct vop_win_phy rk3188_win0_data = {
462         .scl = &rk3188_win_scl,
463         .data_formats = formats_win_full,
464         .nformats = ARRAY_SIZE(formats_win_full),
465         .format_modifiers = format_modifiers_win_full,
466         .enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 0),
467         .format = VOP_REG(RK3188_SYS_CTRL, 0x7, 3),
468         .rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 15),
469         .act_info = VOP_REG(RK3188_WIN0_ACT_INFO, 0x1fff1fff, 0),
470         .dsp_info = VOP_REG(RK3188_WIN0_DSP_INFO, 0x0fff0fff, 0),
471         .dsp_st = VOP_REG(RK3188_WIN0_DSP_ST, 0x1fff1fff, 0),
472         .yrgb_mst = VOP_REG(RK3188_WIN0_YRGB_MST0, 0xffffffff, 0),
473         .uv_mst = VOP_REG(RK3188_WIN0_CBR_MST0, 0xffffffff, 0),
474         .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 0),
475 };
476
477 static const struct vop_win_phy rk3188_win1_data = {
478         .data_formats = formats_win_lite,
479         .nformats = ARRAY_SIZE(formats_win_lite),
480         .format_modifiers = format_modifiers_win_lite,
481         .enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 1),
482         .format = VOP_REG(RK3188_SYS_CTRL, 0x7, 6),
483         .rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 19),
484         /* no act_info on window1 */
485         .dsp_info = VOP_REG(RK3188_WIN1_DSP_INFO, 0x07ff07ff, 0),
486         .dsp_st = VOP_REG(RK3188_WIN1_DSP_ST, 0x0fff0fff, 0),
487         .yrgb_mst = VOP_REG(RK3188_WIN1_MST, 0xffffffff, 0),
488         .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 16),
489 };
490
491 static const struct vop_modeset rk3188_modeset = {
492         .htotal_pw = VOP_REG(RK3188_DSP_HTOTAL_HS_END, 0x0fff0fff, 0),
493         .hact_st_end = VOP_REG(RK3188_DSP_HACT_ST_END, 0x0fff0fff, 0),
494         .vtotal_pw = VOP_REG(RK3188_DSP_VTOTAL_VS_END, 0x0fff0fff, 0),
495         .vact_st_end = VOP_REG(RK3188_DSP_VACT_ST_END, 0x0fff0fff, 0),
496 };
497
498 static const struct vop_output rk3188_output = {
499         .pin_pol = VOP_REG(RK3188_DSP_CTRL0, 0xf, 4),
500 };
501
502 static const struct vop_common rk3188_common = {
503         .gate_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 31),
504         .standby = VOP_REG(RK3188_SYS_CTRL, 0x1, 30),
505         .out_mode = VOP_REG(RK3188_DSP_CTRL0, 0xf, 0),
506         .cfg_done = VOP_REG(RK3188_REG_CFG_DONE, 0x1, 0),
507         .dither_down_sel = VOP_REG(RK3188_DSP_CTRL0, 0x1, 27),
508         .dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11),
509         .dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10),
510         .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 24),
511         .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9),
512         .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28),
513         .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25),
514 };
515
516 static const struct vop_win_data rk3188_vop_win_data[] = {
517         { .base = 0x00, .phy = &rk3188_win0_data,
518           .type = DRM_PLANE_TYPE_PRIMARY },
519         { .base = 0x00, .phy = &rk3188_win1_data,
520           .type = DRM_PLANE_TYPE_CURSOR },
521 };
522
523 static const int rk3188_vop_intrs[] = {
524         /*
525          * hs_start interrupt fires at frame-start, so serves
526          * the same purpose as dsp_hold in the driver.
527          */
528         DSP_HOLD_VALID_INTR,
529         FS_INTR,
530         LINE_FLAG_INTR,
531         BUS_ERROR_INTR,
532 };
533
534 static const struct vop_intr rk3188_vop_intr = {
535         .intrs = rk3188_vop_intrs,
536         .nintrs = ARRAY_SIZE(rk3188_vop_intrs),
537         .line_flag_num[0] = VOP_REG(RK3188_INT_STATUS, 0xfff, 12),
538         .status = VOP_REG(RK3188_INT_STATUS, 0xf, 0),
539         .enable = VOP_REG(RK3188_INT_STATUS, 0xf, 4),
540         .clear = VOP_REG(RK3188_INT_STATUS, 0xf, 8),
541 };
542
543 static const struct vop_data rk3188_vop = {
544         .intr = &rk3188_vop_intr,
545         .common = &rk3188_common,
546         .modeset = &rk3188_modeset,
547         .output = &rk3188_output,
548         .win = rk3188_vop_win_data,
549         .win_size = ARRAY_SIZE(rk3188_vop_win_data),
550         .feature = VOP_FEATURE_INTERNAL_RGB,
551 };
552
553 static const struct vop_scl_extension rk3288_win_full_scl_ext = {
554         .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
555         .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
556         .cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28),
557         .cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26),
558         .cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24),
559         .yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23),
560         .yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22),
561         .yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20),
562         .yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18),
563         .yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16),
564         .line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15),
565         .cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12),
566         .yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8),
567         .vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7),
568         .vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6),
569         .vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5),
570         .vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4),
571         .bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2),
572         .cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1),
573         .yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0),
574         .lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5),
575 };
576
577 static const struct vop_scl_regs rk3288_win_full_scl = {
578         .ext = &rk3288_win_full_scl_ext,
579         .scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
580         .scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
581         .scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
582         .scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
583 };
584
585 static const struct vop_win_phy rk3288_win01_data = {
586         .scl = &rk3288_win_full_scl,
587         .data_formats = formats_win_full,
588         .nformats = ARRAY_SIZE(formats_win_full),
589         .format_modifiers = format_modifiers_win_full,
590         .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
591         .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
592         .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
593         .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
594         .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
595         .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
596         .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
597         .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
598         .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
599         .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
600         .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
601         .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
602         .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0),
603 };
604
605 static const struct vop_win_phy rk3288_win23_data = {
606         .data_formats = formats_win_lite,
607         .nformats = ARRAY_SIZE(formats_win_lite),
608         .format_modifiers = format_modifiers_win_lite,
609         .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4),
610         .gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
611         .format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
612         .rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
613         .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
614         .dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0),
615         .yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0),
616         .yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0),
617         .src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
618         .dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
619 };
620
621 static const struct vop_modeset rk3288_modeset = {
622         .htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
623         .hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0),
624         .vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
625         .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
626         .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
627         .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
628 };
629
630 static const struct vop_output rk3288_output = {
631         .pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4),
632         .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
633         .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
634         .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
635         .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
636 };
637
638 static const struct vop_common rk3288_common = {
639         .standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22),
640         .gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
641         .mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20),
642         .dither_down_sel = VOP_REG(RK3288_DSP_CTRL1, 0x1, 4),
643         .dither_down_mode = VOP_REG(RK3288_DSP_CTRL1, 0x1, 3),
644         .dither_down_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 2),
645         .pre_dither_down = VOP_REG(RK3288_DSP_CTRL1, 0x1, 1),
646         .dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6),
647         .dsp_lut_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 0),
648         .data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19),
649         .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18),
650         .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
651         .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0),
652 };
653
654 /*
655  * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
656  * special support to get alpha blending working.  For now, just use overlay
657  * window 3 for the drm cursor.
658  *
659  */
660 static const struct vop_win_data rk3288_vop_win_data[] = {
661         { .base = 0x00, .phy = &rk3288_win01_data,
662           .type = DRM_PLANE_TYPE_PRIMARY },
663         { .base = 0x40, .phy = &rk3288_win01_data,
664           .type = DRM_PLANE_TYPE_OVERLAY },
665         { .base = 0x00, .phy = &rk3288_win23_data,
666           .type = DRM_PLANE_TYPE_OVERLAY },
667         { .base = 0x50, .phy = &rk3288_win23_data,
668           .type = DRM_PLANE_TYPE_CURSOR },
669 };
670
671 static const int rk3288_vop_intrs[] = {
672         DSP_HOLD_VALID_INTR,
673         FS_INTR,
674         LINE_FLAG_INTR,
675         BUS_ERROR_INTR,
676 };
677
678 static const struct vop_intr rk3288_vop_intr = {
679         .intrs = rk3288_vop_intrs,
680         .nintrs = ARRAY_SIZE(rk3288_vop_intrs),
681         .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12),
682         .status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0),
683         .enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4),
684         .clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8),
685 };
686
687 static const struct vop_data rk3288_vop = {
688         .version = VOP_VERSION(3, 1),
689         .feature = VOP_FEATURE_OUTPUT_RGB10,
690         .intr = &rk3288_vop_intr,
691         .common = &rk3288_common,
692         .modeset = &rk3288_modeset,
693         .output = &rk3288_output,
694         .win = rk3288_vop_win_data,
695         .win_size = ARRAY_SIZE(rk3288_vop_win_data),
696         .lut_size = 1024,
697 };
698
699 static const int rk3368_vop_intrs[] = {
700         FS_INTR,
701         0, 0,
702         LINE_FLAG_INTR,
703         0,
704         BUS_ERROR_INTR,
705         0, 0, 0, 0, 0, 0, 0,
706         DSP_HOLD_VALID_INTR,
707 };
708
709 static const struct vop_intr rk3368_vop_intr = {
710         .intrs = rk3368_vop_intrs,
711         .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
712         .line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0),
713         .line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16),
714         .status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0),
715         .enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0),
716         .clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0),
717 };
718
719 static const struct vop_win_phy rk3368_win01_data = {
720         .scl = &rk3288_win_full_scl,
721         .data_formats = formats_win_full,
722         .nformats = ARRAY_SIZE(formats_win_full),
723         .format_modifiers = format_modifiers_win_full,
724         .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0),
725         .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1),
726         .rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12),
727         .x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21),
728         .y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22),
729         .act_info = VOP_REG(RK3368_WIN0_ACT_INFO, 0x1fff1fff, 0),
730         .dsp_info = VOP_REG(RK3368_WIN0_DSP_INFO, 0x0fff0fff, 0),
731         .dsp_st = VOP_REG(RK3368_WIN0_DSP_ST, 0x1fff1fff, 0),
732         .yrgb_mst = VOP_REG(RK3368_WIN0_YRGB_MST, 0xffffffff, 0),
733         .uv_mst = VOP_REG(RK3368_WIN0_CBR_MST, 0xffffffff, 0),
734         .yrgb_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 0),
735         .uv_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 16),
736         .src_alpha_ctl = VOP_REG(RK3368_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
737         .dst_alpha_ctl = VOP_REG(RK3368_WIN0_DST_ALPHA_CTRL, 0xff, 0),
738         .channel = VOP_REG(RK3368_WIN0_CTRL2, 0xff, 0),
739 };
740
741 static const struct vop_win_phy rk3368_win23_data = {
742         .data_formats = formats_win_lite,
743         .nformats = ARRAY_SIZE(formats_win_lite),
744         .format_modifiers = format_modifiers_win_lite,
745         .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0),
746         .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4),
747         .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5),
748         .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20),
749         .y_mir_en = VOP_REG(RK3368_WIN2_CTRL1, 0x1, 15),
750         .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0),
751         .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0),
752         .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0),
753         .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0),
754         .src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
755         .dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0),
756 };
757
758 static const struct vop_win_data rk3368_vop_win_data[] = {
759         { .base = 0x00, .phy = &rk3368_win01_data,
760           .type = DRM_PLANE_TYPE_PRIMARY },
761         { .base = 0x40, .phy = &rk3368_win01_data,
762           .type = DRM_PLANE_TYPE_OVERLAY },
763         { .base = 0x00, .phy = &rk3368_win23_data,
764           .type = DRM_PLANE_TYPE_OVERLAY },
765         { .base = 0x50, .phy = &rk3368_win23_data,
766           .type = DRM_PLANE_TYPE_CURSOR },
767 };
768
769 static const struct vop_output rk3368_output = {
770         .rgb_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 19),
771         .hdmi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 23),
772         .edp_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 27),
773         .mipi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 31),
774         .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 16),
775         .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 20),
776         .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 24),
777         .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 28),
778         .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
779         .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
780         .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
781         .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
782 };
783
784 static const struct vop_misc rk3368_misc = {
785         .global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11),
786 };
787
788 static const struct vop_data rk3368_vop = {
789         .version = VOP_VERSION(3, 2),
790         .intr = &rk3368_vop_intr,
791         .common = &rk3288_common,
792         .modeset = &rk3288_modeset,
793         .output = &rk3368_output,
794         .misc = &rk3368_misc,
795         .win = rk3368_vop_win_data,
796         .win_size = ARRAY_SIZE(rk3368_vop_win_data),
797 };
798
799 static const struct vop_intr rk3366_vop_intr = {
800         .intrs = rk3368_vop_intrs,
801         .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
802         .line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0),
803         .line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16),
804         .status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0),
805         .enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0),
806         .clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0),
807 };
808
809 static const struct vop_data rk3366_vop = {
810         .version = VOP_VERSION(3, 4),
811         .intr = &rk3366_vop_intr,
812         .common = &rk3288_common,
813         .modeset = &rk3288_modeset,
814         .output = &rk3368_output,
815         .misc = &rk3368_misc,
816         .win = rk3368_vop_win_data,
817         .win_size = ARRAY_SIZE(rk3368_vop_win_data),
818 };
819
820 static const struct vop_output rk3399_output = {
821         .dp_dclk_pol = VOP_REG(RK3399_DSP_CTRL1, 0x1, 19),
822         .rgb_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 19),
823         .hdmi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 23),
824         .edp_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 27),
825         .mipi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 31),
826         .dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0x7, 16),
827         .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 16),
828         .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 20),
829         .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 24),
830         .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 28),
831         .dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11),
832         .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
833         .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
834         .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
835         .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
836         .mipi_dual_channel_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 3),
837 };
838
839 static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win01_data = {
840         .y2r_coefficients = {
841                 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 0),
842                 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 16),
843                 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 0),
844                 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 16),
845                 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 0),
846                 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 16),
847                 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 0),
848                 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 16),
849                 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 16, 0xffff, 0),
850                 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 20, 0xffffffff, 0),
851                 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 24, 0xffffffff, 0),
852                 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 28, 0xffffffff, 0),
853         },
854 };
855
856 static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win23_data = { };
857
858 static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = {
859         { .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
860           .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1) },
861         { .base = 0x60, .phy = &rk3399_yuv2yuv_win01_data,
862           .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9) },
863         { .base = 0xC0, .phy = &rk3399_yuv2yuv_win23_data },
864         { .base = 0x120, .phy = &rk3399_yuv2yuv_win23_data },
865
866 };
867
868 static const struct vop_win_phy rk3399_win01_data = {
869         .scl = &rk3288_win_full_scl,
870         .data_formats = formats_win_full,
871         .nformats = ARRAY_SIZE(formats_win_full),
872         .format_modifiers = format_modifiers_win_full_afbc,
873         .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
874         .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
875         .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
876         .x_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 21),
877         .y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22),
878         .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
879         .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
880         .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
881         .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
882         .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
883         .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
884         .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
885         .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
886         .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
887         .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0),
888 };
889
890 /*
891  * rk3399 vop big windows register layout is same as rk3288, but we
892  * have a separate rk3399 win data array here so that we can advertise
893  * AFBC on the primary plane.
894  */
895 static const struct vop_win_data rk3399_vop_win_data[] = {
896         { .base = 0x00, .phy = &rk3399_win01_data,
897           .type = DRM_PLANE_TYPE_PRIMARY },
898         { .base = 0x40, .phy = &rk3368_win01_data,
899           .type = DRM_PLANE_TYPE_OVERLAY },
900         { .base = 0x00, .phy = &rk3368_win23_data,
901           .type = DRM_PLANE_TYPE_OVERLAY },
902         { .base = 0x50, .phy = &rk3368_win23_data,
903           .type = DRM_PLANE_TYPE_CURSOR },
904 };
905
906 static const struct vop_afbc rk3399_vop_afbc = {
907         .rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3),
908         .enable = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0),
909         .win_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1),
910         .format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16),
911         .hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21),
912         .hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0),
913         .pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0),
914 };
915
916 static const struct vop_data rk3399_vop_big = {
917         .version = VOP_VERSION(3, 5),
918         .feature = VOP_FEATURE_OUTPUT_RGB10,
919         .intr = &rk3366_vop_intr,
920         .common = &rk3288_common,
921         .modeset = &rk3288_modeset,
922         .output = &rk3399_output,
923         .afbc = &rk3399_vop_afbc,
924         .misc = &rk3368_misc,
925         .win = rk3399_vop_win_data,
926         .win_size = ARRAY_SIZE(rk3399_vop_win_data),
927         .win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data,
928 };
929
930 static const struct vop_win_data rk3399_vop_lit_win_data[] = {
931         { .base = 0x00, .phy = &rk3368_win01_data,
932           .type = DRM_PLANE_TYPE_PRIMARY },
933         { .base = 0x00, .phy = &rk3368_win23_data,
934           .type = DRM_PLANE_TYPE_CURSOR},
935 };
936
937 static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = {
938         { .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
939           .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1)},
940         { .base = 0x60, .phy = &rk3399_yuv2yuv_win23_data },
941 };
942
943 static const struct vop_data rk3399_vop_lit = {
944         .version = VOP_VERSION(3, 6),
945         .intr = &rk3366_vop_intr,
946         .common = &rk3288_common,
947         .modeset = &rk3288_modeset,
948         .output = &rk3399_output,
949         .misc = &rk3368_misc,
950         .win = rk3399_vop_lit_win_data,
951         .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data),
952         .win_yuv2yuv = rk3399_vop_lit_win_yuv2yuv_data,
953 };
954
955 static const struct vop_win_data rk3228_vop_win_data[] = {
956         { .base = 0x00, .phy = &rk3288_win01_data,
957           .type = DRM_PLANE_TYPE_PRIMARY },
958         { .base = 0x40, .phy = &rk3288_win01_data,
959           .type = DRM_PLANE_TYPE_CURSOR },
960 };
961
962 static const struct vop_data rk3228_vop = {
963         .version = VOP_VERSION(3, 7),
964         .feature = VOP_FEATURE_OUTPUT_RGB10,
965         .intr = &rk3366_vop_intr,
966         .common = &rk3288_common,
967         .modeset = &rk3288_modeset,
968         .output = &rk3399_output,
969         .misc = &rk3368_misc,
970         .win = rk3228_vop_win_data,
971         .win_size = ARRAY_SIZE(rk3228_vop_win_data),
972 };
973
974 static const struct vop_modeset rk3328_modeset = {
975         .htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
976         .hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0),
977         .vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
978         .vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0),
979         .hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
980         .vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
981 };
982
983 static const struct vop_output rk3328_output = {
984         .rgb_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 19),
985         .hdmi_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 23),
986         .edp_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 27),
987         .mipi_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 31),
988         .rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12),
989         .hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13),
990         .edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14),
991         .mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15),
992         .rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 16),
993         .hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 20),
994         .edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 24),
995         .mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 28),
996 };
997
998 static const struct vop_misc rk3328_misc = {
999         .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11),
1000 };
1001
1002 static const struct vop_common rk3328_common = {
1003         .standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22),
1004         .dither_down_sel = VOP_REG(RK3328_DSP_CTRL1, 0x1, 4),
1005         .dither_down_mode = VOP_REG(RK3328_DSP_CTRL1, 0x1, 3),
1006         .dither_down_en = VOP_REG(RK3328_DSP_CTRL1, 0x1, 2),
1007         .pre_dither_down = VOP_REG(RK3328_DSP_CTRL1, 0x1, 1),
1008         .dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6),
1009         .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18),
1010         .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0),
1011         .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0),
1012 };
1013
1014 static const struct vop_intr rk3328_vop_intr = {
1015         .intrs = rk3368_vop_intrs,
1016         .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
1017         .line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0),
1018         .line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16),
1019         .status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0),
1020         .enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0),
1021         .clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0),
1022 };
1023
1024 static const struct vop_win_data rk3328_vop_win_data[] = {
1025         { .base = 0xd0, .phy = &rk3368_win01_data,
1026           .type = DRM_PLANE_TYPE_PRIMARY },
1027         { .base = 0x1d0, .phy = &rk3368_win01_data,
1028           .type = DRM_PLANE_TYPE_OVERLAY },
1029         { .base = 0x2d0, .phy = &rk3368_win01_data,
1030           .type = DRM_PLANE_TYPE_CURSOR },
1031 };
1032
1033 static const struct vop_data rk3328_vop = {
1034         .version = VOP_VERSION(3, 8),
1035         .feature = VOP_FEATURE_OUTPUT_RGB10,
1036         .intr = &rk3328_vop_intr,
1037         .common = &rk3328_common,
1038         .modeset = &rk3328_modeset,
1039         .output = &rk3328_output,
1040         .misc = &rk3328_misc,
1041         .win = rk3328_vop_win_data,
1042         .win_size = ARRAY_SIZE(rk3328_vop_win_data),
1043 };
1044
1045 static const struct of_device_id vop_driver_dt_match[] = {
1046         { .compatible = "rockchip,rk3036-vop",
1047           .data = &rk3036_vop },
1048         { .compatible = "rockchip,rk3126-vop",
1049           .data = &rk3126_vop },
1050         { .compatible = "rockchip,px30-vop-big",
1051           .data = &px30_vop_big },
1052         { .compatible = "rockchip,px30-vop-lit",
1053           .data = &px30_vop_lit },
1054         { .compatible = "rockchip,rk3066-vop",
1055           .data = &rk3066_vop },
1056         { .compatible = "rockchip,rk3188-vop",
1057           .data = &rk3188_vop },
1058         { .compatible = "rockchip,rk3288-vop",
1059           .data = &rk3288_vop },
1060         { .compatible = "rockchip,rk3368-vop",
1061           .data = &rk3368_vop },
1062         { .compatible = "rockchip,rk3366-vop",
1063           .data = &rk3366_vop },
1064         { .compatible = "rockchip,rk3399-vop-big",
1065           .data = &rk3399_vop_big },
1066         { .compatible = "rockchip,rk3399-vop-lit",
1067           .data = &rk3399_vop_lit },
1068         { .compatible = "rockchip,rk3228-vop",
1069           .data = &rk3228_vop },
1070         { .compatible = "rockchip,rk3328-vop",
1071           .data = &rk3328_vop },
1072         {},
1073 };
1074 MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
1075
1076 static int vop_probe(struct platform_device *pdev)
1077 {
1078         struct device *dev = &pdev->dev;
1079
1080         if (!dev->of_node) {
1081                 DRM_DEV_ERROR(dev, "can't find vop devices\n");
1082                 return -ENODEV;
1083         }
1084
1085         return component_add(dev, &vop_component_ops);
1086 }
1087
1088 static int vop_remove(struct platform_device *pdev)
1089 {
1090         component_del(&pdev->dev, &vop_component_ops);
1091
1092         return 0;
1093 }
1094
1095 struct platform_driver vop_platform_driver = {
1096         .probe = vop_probe,
1097         .remove = vop_remove,
1098         .driver = {
1099                 .name = "rockchip-vop",
1100                 .of_match_table = of_match_ptr(vop_driver_dt_match),
1101         },
1102 };