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