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