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