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