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