1
2
3
4
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
39static 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
53static const uint64_t format_modifiers_win_full[] = {
54 DRM_FORMAT_MOD_LINEAR,
55 DRM_FORMAT_MOD_INVALID,
56};
57
58static const uint64_t format_modifiers_win_full_afbc[] = {
59 ROCKCHIP_AFBC_MOD,
60 DRM_FORMAT_MOD_LINEAR,
61 DRM_FORMAT_MOD_INVALID,
62};
63
64static 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
75static const uint64_t format_modifiers_win_lite[] = {
76 DRM_FORMAT_MOD_LINEAR,
77 DRM_FORMAT_MOD_INVALID,
78};
79
80static 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
87static 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
104static 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
118static 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
125static const int rk3036_vop_intrs[] = {
126 DSP_HOLD_VALID_INTR,
127 FS_INTR,
128 LINE_FLAG_INTR,
129 BUS_ERROR_INTR,
130};
131
132static 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
141static 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
148static const struct vop_output rk3036_output = {
149 .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
150};
151
152static 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
162static 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
171static 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
184static 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
191static 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
200static 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
210static 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
219static 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
229static 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
236static 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
245static 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
252static 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};
268
269static const struct vop_win_phy px30_win1_data = {
270 .data_formats = formats_win_lite,
271 .nformats = ARRAY_SIZE(formats_win_lite),
272 .format_modifiers = format_modifiers_win_lite,
273 .enable = VOP_REG(PX30_WIN1_CTRL0, 0x1, 0),
274 .format = VOP_REG(PX30_WIN1_CTRL0, 0x7, 4),
275 .rb_swap = VOP_REG(PX30_WIN1_CTRL0, 0x1, 12),
276 .dsp_info = VOP_REG(PX30_WIN1_DSP_INFO, 0xffffffff, 0),
277 .dsp_st = VOP_REG(PX30_WIN1_DSP_ST, 0xffffffff, 0),
278 .yrgb_mst = VOP_REG(PX30_WIN1_MST, 0xffffffff, 0),
279 .yrgb_vir = VOP_REG(PX30_WIN1_VIR, 0x1fff, 0),
280};
281
282static const struct vop_win_phy px30_win2_data = {
283 .data_formats = formats_win_lite,
284 .nformats = ARRAY_SIZE(formats_win_lite),
285 .format_modifiers = format_modifiers_win_lite,
286 .gate = VOP_REG(PX30_WIN2_CTRL0, 0x1, 4),
287 .enable = VOP_REG(PX30_WIN2_CTRL0, 0x1, 0),
288 .format = VOP_REG(PX30_WIN2_CTRL0, 0x3, 5),
289 .rb_swap = VOP_REG(PX30_WIN2_CTRL0, 0x1, 20),
290 .dsp_info = VOP_REG(PX30_WIN2_DSP_INFO0, 0x0fff0fff, 0),
291 .dsp_st = VOP_REG(PX30_WIN2_DSP_ST0, 0x1fff1fff, 0),
292 .yrgb_mst = VOP_REG(PX30_WIN2_MST0, 0xffffffff, 0),
293 .yrgb_vir = VOP_REG(PX30_WIN2_VIR0_1, 0x1fff, 0),
294};
295
296static const struct vop_win_data px30_vop_big_win_data[] = {
297 { .base = 0x00, .phy = &px30_win0_data,
298 .type = DRM_PLANE_TYPE_PRIMARY },
299 { .base = 0x00, .phy = &px30_win1_data,
300 .type = DRM_PLANE_TYPE_OVERLAY },
301 { .base = 0x00, .phy = &px30_win2_data,
302 .type = DRM_PLANE_TYPE_CURSOR },
303};
304
305static const struct vop_data px30_vop_big = {
306 .intr = &px30_intr,
307 .feature = VOP_FEATURE_INTERNAL_RGB,
308 .common = &px30_common,
309 .modeset = &px30_modeset,
310 .output = &px30_output,
311 .win = px30_vop_big_win_data,
312 .win_size = ARRAY_SIZE(px30_vop_big_win_data),
313};
314
315static const struct vop_win_data px30_vop_lit_win_data[] = {
316 { .base = 0x00, .phy = &px30_win1_data,
317 .type = DRM_PLANE_TYPE_PRIMARY },
318};
319
320static const struct vop_data px30_vop_lit = {
321 .intr = &px30_intr,
322 .feature = VOP_FEATURE_INTERNAL_RGB,
323 .common = &px30_common,
324 .modeset = &px30_modeset,
325 .output = &px30_output,
326 .win = px30_vop_lit_win_data,
327 .win_size = ARRAY_SIZE(px30_vop_lit_win_data),
328};
329
330static const struct vop_scl_regs rk3066_win_scl = {
331 .scale_yrgb_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
332 .scale_yrgb_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
333 .scale_cbcr_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
334 .scale_cbcr_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
335};
336
337static const struct vop_win_phy rk3066_win0_data = {
338 .scl = &rk3066_win_scl,
339 .data_formats = formats_win_full,
340 .nformats = ARRAY_SIZE(formats_win_full),
341 .format_modifiers = format_modifiers_win_full,
342 .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0),
343 .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 4),
344 .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 19),
345 .act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0),
346 .dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0),
347 .dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0),
348 .yrgb_mst = VOP_REG(RK3066_WIN0_YRGB_MST0, 0xffffffff, 0),
349 .uv_mst = VOP_REG(RK3066_WIN0_CBR_MST0, 0xffffffff, 0),
350 .yrgb_vir = VOP_REG(RK3066_WIN0_VIR, 0xffff, 0),
351 .uv_vir = VOP_REG(RK3066_WIN0_VIR, 0x1fff, 16),
352};
353
354static const struct vop_win_phy rk3066_win1_data = {
355 .scl = &rk3066_win_scl,
356 .data_formats = formats_win_full,
357 .nformats = ARRAY_SIZE(formats_win_full),
358 .format_modifiers = format_modifiers_win_full,
359 .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1),
360 .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 7),
361 .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 23),
362 .act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0),
363 .dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0),
364 .dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0),
365 .yrgb_mst = VOP_REG(RK3066_WIN1_YRGB_MST, 0xffffffff, 0),
366 .uv_mst = VOP_REG(RK3066_WIN1_CBR_MST, 0xffffffff, 0),
367 .yrgb_vir = VOP_REG(RK3066_WIN1_VIR, 0xffff, 0),
368 .uv_vir = VOP_REG(RK3066_WIN1_VIR, 0x1fff, 16),
369};
370
371static const struct vop_win_phy rk3066_win2_data = {
372 .data_formats = formats_win_lite,
373 .nformats = ARRAY_SIZE(formats_win_lite),
374 .format_modifiers = format_modifiers_win_lite,
375 .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2),
376 .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 10),
377 .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 27),
378 .dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0),
379 .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0),
380 .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0),
381 .yrgb_vir = VOP_REG(RK3066_WIN2_VIR, 0xffff, 0),
382};
383
384static const struct vop_modeset rk3066_modeset = {
385 .htotal_pw = VOP_REG(RK3066_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
386 .hact_st_end = VOP_REG(RK3066_DSP_HACT_ST_END, 0x1fff1fff, 0),
387 .vtotal_pw = VOP_REG(RK3066_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
388 .vact_st_end = VOP_REG(RK3066_DSP_VACT_ST_END, 0x1fff1fff, 0),
389};
390
391static const struct vop_output rk3066_output = {
392 .pin_pol = VOP_REG(RK3066_DSP_CTRL0, 0x7, 4),
393};
394
395static const struct vop_common rk3066_common = {
396 .standby = VOP_REG(RK3066_SYS_CTRL0, 0x1, 1),
397 .out_mode = VOP_REG(RK3066_DSP_CTRL0, 0xf, 0),
398 .cfg_done = VOP_REG(RK3066_REG_CFG_DONE, 0x1, 0),
399 .dither_down_en = VOP_REG(RK3066_DSP_CTRL0, 0x1, 11),
400 .dither_down_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 10),
401 .dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24),
402};
403
404static const struct vop_win_data rk3066_vop_win_data[] = {
405 { .base = 0x00, .phy = &rk3066_win0_data,
406 .type = DRM_PLANE_TYPE_PRIMARY },
407 { .base = 0x00, .phy = &rk3066_win1_data,
408 .type = DRM_PLANE_TYPE_OVERLAY },
409 { .base = 0x00, .phy = &rk3066_win2_data,
410 .type = DRM_PLANE_TYPE_CURSOR },
411};
412
413static const int rk3066_vop_intrs[] = {
414
415
416
417
418 DSP_HOLD_VALID_INTR,
419 FS_INTR,
420 LINE_FLAG_INTR,
421 BUS_ERROR_INTR,
422};
423
424static const struct vop_intr rk3066_intr = {
425 .intrs = rk3066_vop_intrs,
426 .nintrs = ARRAY_SIZE(rk3066_vop_intrs),
427 .line_flag_num[0] = VOP_REG(RK3066_INT_STATUS, 0xfff, 12),
428 .status = VOP_REG(RK3066_INT_STATUS, 0xf, 0),
429 .enable = VOP_REG(RK3066_INT_STATUS, 0xf, 4),
430 .clear = VOP_REG(RK3066_INT_STATUS, 0xf, 8),
431};
432
433static const struct vop_data rk3066_vop = {
434 .version = VOP_VERSION(2, 1),
435 .intr = &rk3066_intr,
436 .common = &rk3066_common,
437 .modeset = &rk3066_modeset,
438 .output = &rk3066_output,
439 .win = rk3066_vop_win_data,
440 .win_size = ARRAY_SIZE(rk3066_vop_win_data),
441};
442
443static const struct vop_scl_regs rk3188_win_scl = {
444 .scale_yrgb_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
445 .scale_yrgb_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
446 .scale_cbcr_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
447 .scale_cbcr_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
448};
449
450static const struct vop_win_phy rk3188_win0_data = {
451 .scl = &rk3188_win_scl,
452 .data_formats = formats_win_full,
453 .nformats = ARRAY_SIZE(formats_win_full),
454 .format_modifiers = format_modifiers_win_full,
455 .enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 0),
456 .format = VOP_REG(RK3188_SYS_CTRL, 0x7, 3),
457 .rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 15),
458 .act_info = VOP_REG(RK3188_WIN0_ACT_INFO, 0x1fff1fff, 0),
459 .dsp_info = VOP_REG(RK3188_WIN0_DSP_INFO, 0x0fff0fff, 0),
460 .dsp_st = VOP_REG(RK3188_WIN0_DSP_ST, 0x1fff1fff, 0),
461 .yrgb_mst = VOP_REG(RK3188_WIN0_YRGB_MST0, 0xffffffff, 0),
462 .uv_mst = VOP_REG(RK3188_WIN0_CBR_MST0, 0xffffffff, 0),
463 .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 0),
464};
465
466static const struct vop_win_phy rk3188_win1_data = {
467 .data_formats = formats_win_lite,
468 .nformats = ARRAY_SIZE(formats_win_lite),
469 .format_modifiers = format_modifiers_win_lite,
470 .enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 1),
471 .format = VOP_REG(RK3188_SYS_CTRL, 0x7, 6),
472 .rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 19),
473
474 .dsp_info = VOP_REG(RK3188_WIN1_DSP_INFO, 0x07ff07ff, 0),
475 .dsp_st = VOP_REG(RK3188_WIN1_DSP_ST, 0x0fff0fff, 0),
476 .yrgb_mst = VOP_REG(RK3188_WIN1_MST, 0xffffffff, 0),
477 .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 16),
478};
479
480static const struct vop_modeset rk3188_modeset = {
481 .htotal_pw = VOP_REG(RK3188_DSP_HTOTAL_HS_END, 0x0fff0fff, 0),
482 .hact_st_end = VOP_REG(RK3188_DSP_HACT_ST_END, 0x0fff0fff, 0),
483 .vtotal_pw = VOP_REG(RK3188_DSP_VTOTAL_VS_END, 0x0fff0fff, 0),
484 .vact_st_end = VOP_REG(RK3188_DSP_VACT_ST_END, 0x0fff0fff, 0),
485};
486
487static const struct vop_output rk3188_output = {
488 .pin_pol = VOP_REG(RK3188_DSP_CTRL0, 0xf, 4),
489};
490
491static const struct vop_common rk3188_common = {
492 .gate_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 31),
493 .standby = VOP_REG(RK3188_SYS_CTRL, 0x1, 30),
494 .out_mode = VOP_REG(RK3188_DSP_CTRL0, 0xf, 0),
495 .cfg_done = VOP_REG(RK3188_REG_CFG_DONE, 0x1, 0),
496 .dither_down_sel = VOP_REG(RK3188_DSP_CTRL0, 0x1, 27),
497 .dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11),
498 .dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10),
499 .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x3, 24),
500};
501
502static const struct vop_win_data rk3188_vop_win_data[] = {
503 { .base = 0x00, .phy = &rk3188_win0_data,
504 .type = DRM_PLANE_TYPE_PRIMARY },
505 { .base = 0x00, .phy = &rk3188_win1_data,
506 .type = DRM_PLANE_TYPE_CURSOR },
507};
508
509static const int rk3188_vop_intrs[] = {
510
511
512
513
514 DSP_HOLD_VALID_INTR,
515 FS_INTR,
516 LINE_FLAG_INTR,
517 BUS_ERROR_INTR,
518};
519
520static const struct vop_intr rk3188_vop_intr = {
521 .intrs = rk3188_vop_intrs,
522 .nintrs = ARRAY_SIZE(rk3188_vop_intrs),
523 .line_flag_num[0] = VOP_REG(RK3188_INT_STATUS, 0xfff, 12),
524 .status = VOP_REG(RK3188_INT_STATUS, 0xf, 0),
525 .enable = VOP_REG(RK3188_INT_STATUS, 0xf, 4),
526 .clear = VOP_REG(RK3188_INT_STATUS, 0xf, 8),
527};
528
529static const struct vop_data rk3188_vop = {
530 .intr = &rk3188_vop_intr,
531 .common = &rk3188_common,
532 .modeset = &rk3188_modeset,
533 .output = &rk3188_output,
534 .win = rk3188_vop_win_data,
535 .win_size = ARRAY_SIZE(rk3188_vop_win_data),
536 .feature = VOP_FEATURE_INTERNAL_RGB,
537};
538
539static const struct vop_scl_extension rk3288_win_full_scl_ext = {
540 .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
541 .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
542 .cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28),
543 .cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26),
544 .cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24),
545 .yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23),
546 .yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22),
547 .yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20),
548 .yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18),
549 .yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16),
550 .line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15),
551 .cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12),
552 .yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8),
553 .vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7),
554 .vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6),
555 .vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5),
556 .vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4),
557 .bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2),
558 .cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1),
559 .yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0),
560 .lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5),
561};
562
563static const struct vop_scl_regs rk3288_win_full_scl = {
564 .ext = &rk3288_win_full_scl_ext,
565 .scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
566 .scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
567 .scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
568 .scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
569};
570
571static const struct vop_win_phy rk3288_win01_data = {
572 .scl = &rk3288_win_full_scl,
573 .data_formats = formats_win_full,
574 .nformats = ARRAY_SIZE(formats_win_full),
575 .format_modifiers = format_modifiers_win_full,
576 .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
577 .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
578 .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
579 .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
580 .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
581 .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
582 .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
583 .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
584 .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
585 .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
586 .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
587 .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
588 .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0),
589};
590
591static const struct vop_win_phy rk3288_win23_data = {
592 .data_formats = formats_win_lite,
593 .nformats = ARRAY_SIZE(formats_win_lite),
594 .format_modifiers = format_modifiers_win_lite,
595 .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4),
596 .gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
597 .format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
598 .rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
599 .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
600 .dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0),
601 .yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0),
602 .yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0),
603 .src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
604 .dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
605};
606
607static const struct vop_modeset rk3288_modeset = {
608 .htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
609 .hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0),
610 .vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
611 .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
612 .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
613 .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
614};
615
616static const struct vop_output rk3288_output = {
617 .pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4),
618 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
619 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
620 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
621 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
622};
623
624static const struct vop_common rk3288_common = {
625 .standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22),
626 .gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
627 .mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20),
628 .dither_down_sel = VOP_REG(RK3288_DSP_CTRL1, 0x1, 4),
629 .dither_down_mode = VOP_REG(RK3288_DSP_CTRL1, 0x1, 3),
630 .dither_down_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 2),
631 .pre_dither_down = VOP_REG(RK3288_DSP_CTRL1, 0x1, 1),
632 .dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6),
633 .dsp_lut_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 0),
634 .data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19),
635 .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18),
636 .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
637 .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0),
638};
639
640
641
642
643
644
645
646static const struct vop_win_data rk3288_vop_win_data[] = {
647 { .base = 0x00, .phy = &rk3288_win01_data,
648 .type = DRM_PLANE_TYPE_PRIMARY },
649 { .base = 0x40, .phy = &rk3288_win01_data,
650 .type = DRM_PLANE_TYPE_OVERLAY },
651 { .base = 0x00, .phy = &rk3288_win23_data,
652 .type = DRM_PLANE_TYPE_OVERLAY },
653 { .base = 0x50, .phy = &rk3288_win23_data,
654 .type = DRM_PLANE_TYPE_CURSOR },
655};
656
657static const int rk3288_vop_intrs[] = {
658 DSP_HOLD_VALID_INTR,
659 FS_INTR,
660 LINE_FLAG_INTR,
661 BUS_ERROR_INTR,
662};
663
664static const struct vop_intr rk3288_vop_intr = {
665 .intrs = rk3288_vop_intrs,
666 .nintrs = ARRAY_SIZE(rk3288_vop_intrs),
667 .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12),
668 .status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0),
669 .enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4),
670 .clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8),
671};
672
673static const struct vop_data rk3288_vop = {
674 .version = VOP_VERSION(3, 1),
675 .feature = VOP_FEATURE_OUTPUT_RGB10,
676 .intr = &rk3288_vop_intr,
677 .common = &rk3288_common,
678 .modeset = &rk3288_modeset,
679 .output = &rk3288_output,
680 .win = rk3288_vop_win_data,
681 .win_size = ARRAY_SIZE(rk3288_vop_win_data),
682 .lut_size = 1024,
683};
684
685static const int rk3368_vop_intrs[] = {
686 FS_INTR,
687 0, 0,
688 LINE_FLAG_INTR,
689 0,
690 BUS_ERROR_INTR,
691 0, 0, 0, 0, 0, 0, 0,
692 DSP_HOLD_VALID_INTR,
693};
694
695static const struct vop_intr rk3368_vop_intr = {
696 .intrs = rk3368_vop_intrs,
697 .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
698 .line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0),
699 .line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16),
700 .status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0),
701 .enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0),
702 .clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0),
703};
704
705static const struct vop_win_phy rk3368_win01_data = {
706 .scl = &rk3288_win_full_scl,
707 .data_formats = formats_win_full,
708 .nformats = ARRAY_SIZE(formats_win_full),
709 .format_modifiers = format_modifiers_win_full,
710 .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0),
711 .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1),
712 .rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12),
713 .x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21),
714 .y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22),
715 .act_info = VOP_REG(RK3368_WIN0_ACT_INFO, 0x1fff1fff, 0),
716 .dsp_info = VOP_REG(RK3368_WIN0_DSP_INFO, 0x0fff0fff, 0),
717 .dsp_st = VOP_REG(RK3368_WIN0_DSP_ST, 0x1fff1fff, 0),
718 .yrgb_mst = VOP_REG(RK3368_WIN0_YRGB_MST, 0xffffffff, 0),
719 .uv_mst = VOP_REG(RK3368_WIN0_CBR_MST, 0xffffffff, 0),
720 .yrgb_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 0),
721 .uv_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 16),
722 .src_alpha_ctl = VOP_REG(RK3368_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
723 .dst_alpha_ctl = VOP_REG(RK3368_WIN0_DST_ALPHA_CTRL, 0xff, 0),
724 .channel = VOP_REG(RK3368_WIN0_CTRL2, 0xff, 0),
725};
726
727static const struct vop_win_phy rk3368_win23_data = {
728 .data_formats = formats_win_lite,
729 .nformats = ARRAY_SIZE(formats_win_lite),
730 .format_modifiers = format_modifiers_win_lite,
731 .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0),
732 .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4),
733 .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5),
734 .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20),
735 .y_mir_en = VOP_REG(RK3368_WIN2_CTRL1, 0x1, 15),
736 .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0),
737 .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0),
738 .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0),
739 .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0),
740 .src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
741 .dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0),
742};
743
744static const struct vop_win_data rk3368_vop_win_data[] = {
745 { .base = 0x00, .phy = &rk3368_win01_data,
746 .type = DRM_PLANE_TYPE_PRIMARY },
747 { .base = 0x40, .phy = &rk3368_win01_data,
748 .type = DRM_PLANE_TYPE_OVERLAY },
749 { .base = 0x00, .phy = &rk3368_win23_data,
750 .type = DRM_PLANE_TYPE_OVERLAY },
751 { .base = 0x50, .phy = &rk3368_win23_data,
752 .type = DRM_PLANE_TYPE_CURSOR },
753};
754
755static const struct vop_output rk3368_output = {
756 .rgb_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 19),
757 .hdmi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 23),
758 .edp_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 27),
759 .mipi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 31),
760 .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 16),
761 .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 20),
762 .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 24),
763 .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 28),
764 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
765 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
766 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
767 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
768};
769
770static const struct vop_misc rk3368_misc = {
771 .global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11),
772};
773
774static const struct vop_data rk3368_vop = {
775 .version = VOP_VERSION(3, 2),
776 .intr = &rk3368_vop_intr,
777 .common = &rk3288_common,
778 .modeset = &rk3288_modeset,
779 .output = &rk3368_output,
780 .misc = &rk3368_misc,
781 .win = rk3368_vop_win_data,
782 .win_size = ARRAY_SIZE(rk3368_vop_win_data),
783};
784
785static const struct vop_intr rk3366_vop_intr = {
786 .intrs = rk3368_vop_intrs,
787 .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
788 .line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0),
789 .line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16),
790 .status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0),
791 .enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0),
792 .clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0),
793};
794
795static const struct vop_data rk3366_vop = {
796 .version = VOP_VERSION(3, 4),
797 .intr = &rk3366_vop_intr,
798 .common = &rk3288_common,
799 .modeset = &rk3288_modeset,
800 .output = &rk3368_output,
801 .misc = &rk3368_misc,
802 .win = rk3368_vop_win_data,
803 .win_size = ARRAY_SIZE(rk3368_vop_win_data),
804};
805
806static const struct vop_output rk3399_output = {
807 .dp_dclk_pol = VOP_REG(RK3399_DSP_CTRL1, 0x1, 19),
808 .rgb_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 19),
809 .hdmi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 23),
810 .edp_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 27),
811 .mipi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 31),
812 .dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0x7, 16),
813 .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 16),
814 .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 20),
815 .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 24),
816 .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 28),
817 .dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11),
818 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
819 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
820 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
821 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
822 .mipi_dual_channel_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 3),
823};
824
825static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win01_data = {
826 .y2r_coefficients = {
827 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 0),
828 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 16),
829 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 0),
830 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 16),
831 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 0),
832 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 16),
833 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 0),
834 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 16),
835 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 16, 0xffff, 0),
836 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 20, 0xffffffff, 0),
837 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 24, 0xffffffff, 0),
838 VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 28, 0xffffffff, 0),
839 },
840};
841
842static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win23_data = { };
843
844static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = {
845 { .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
846 .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1) },
847 { .base = 0x60, .phy = &rk3399_yuv2yuv_win01_data,
848 .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9) },
849 { .base = 0xC0, .phy = &rk3399_yuv2yuv_win23_data },
850 { .base = 0x120, .phy = &rk3399_yuv2yuv_win23_data },
851
852};
853
854static const struct vop_win_phy rk3399_win01_data = {
855 .scl = &rk3288_win_full_scl,
856 .data_formats = formats_win_full,
857 .nformats = ARRAY_SIZE(formats_win_full),
858 .format_modifiers = format_modifiers_win_full_afbc,
859 .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
860 .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
861 .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
862 .y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22),
863 .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
864 .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
865 .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
866 .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
867 .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
868 .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
869 .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
870 .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
871 .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
872};
873
874
875
876
877
878
879static const struct vop_win_data rk3399_vop_win_data[] = {
880 { .base = 0x00, .phy = &rk3399_win01_data,
881 .type = DRM_PLANE_TYPE_PRIMARY },
882 { .base = 0x40, .phy = &rk3288_win01_data,
883 .type = DRM_PLANE_TYPE_OVERLAY },
884 { .base = 0x00, .phy = &rk3288_win23_data,
885 .type = DRM_PLANE_TYPE_OVERLAY },
886 { .base = 0x50, .phy = &rk3288_win23_data,
887 .type = DRM_PLANE_TYPE_CURSOR },
888};
889
890static const struct vop_afbc rk3399_vop_afbc = {
891 .rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3),
892 .enable = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0),
893 .win_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1),
894 .format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16),
895 .hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21),
896 .hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0),
897 .pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0),
898};
899
900static const struct vop_data rk3399_vop_big = {
901 .version = VOP_VERSION(3, 5),
902 .feature = VOP_FEATURE_OUTPUT_RGB10,
903 .intr = &rk3366_vop_intr,
904 .common = &rk3288_common,
905 .modeset = &rk3288_modeset,
906 .output = &rk3399_output,
907 .afbc = &rk3399_vop_afbc,
908 .misc = &rk3368_misc,
909 .win = rk3399_vop_win_data,
910 .win_size = ARRAY_SIZE(rk3399_vop_win_data),
911 .win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data,
912};
913
914static const struct vop_win_data rk3399_vop_lit_win_data[] = {
915 { .base = 0x00, .phy = &rk3368_win01_data,
916 .type = DRM_PLANE_TYPE_PRIMARY },
917 { .base = 0x00, .phy = &rk3368_win23_data,
918 .type = DRM_PLANE_TYPE_CURSOR},
919};
920
921static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = {
922 { .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
923 .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1)},
924 { .base = 0x60, .phy = &rk3399_yuv2yuv_win23_data },
925};
926
927static const struct vop_data rk3399_vop_lit = {
928 .version = VOP_VERSION(3, 6),
929 .intr = &rk3366_vop_intr,
930 .common = &rk3288_common,
931 .modeset = &rk3288_modeset,
932 .output = &rk3399_output,
933 .misc = &rk3368_misc,
934 .win = rk3399_vop_lit_win_data,
935 .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data),
936 .win_yuv2yuv = rk3399_vop_lit_win_yuv2yuv_data,
937};
938
939static const struct vop_win_data rk3228_vop_win_data[] = {
940 { .base = 0x00, .phy = &rk3288_win01_data,
941 .type = DRM_PLANE_TYPE_PRIMARY },
942 { .base = 0x40, .phy = &rk3288_win01_data,
943 .type = DRM_PLANE_TYPE_CURSOR },
944};
945
946static const struct vop_data rk3228_vop = {
947 .version = VOP_VERSION(3, 7),
948 .feature = VOP_FEATURE_OUTPUT_RGB10,
949 .intr = &rk3366_vop_intr,
950 .common = &rk3288_common,
951 .modeset = &rk3288_modeset,
952 .output = &rk3399_output,
953 .misc = &rk3368_misc,
954 .win = rk3228_vop_win_data,
955 .win_size = ARRAY_SIZE(rk3228_vop_win_data),
956};
957
958static const struct vop_modeset rk3328_modeset = {
959 .htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
960 .hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0),
961 .vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
962 .vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0),
963 .hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
964 .vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
965};
966
967static const struct vop_output rk3328_output = {
968 .rgb_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 19),
969 .hdmi_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 23),
970 .edp_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 27),
971 .mipi_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 31),
972 .rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12),
973 .hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13),
974 .edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14),
975 .mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15),
976 .rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 16),
977 .hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 20),
978 .edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 24),
979 .mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 28),
980};
981
982static const struct vop_misc rk3328_misc = {
983 .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11),
984};
985
986static const struct vop_common rk3328_common = {
987 .standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22),
988 .dither_down_sel = VOP_REG(RK3328_DSP_CTRL1, 0x1, 4),
989 .dither_down_mode = VOP_REG(RK3328_DSP_CTRL1, 0x1, 3),
990 .dither_down_en = VOP_REG(RK3328_DSP_CTRL1, 0x1, 2),
991 .pre_dither_down = VOP_REG(RK3328_DSP_CTRL1, 0x1, 1),
992 .dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6),
993 .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18),
994 .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0),
995 .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0),
996};
997
998static const struct vop_intr rk3328_vop_intr = {
999 .intrs = rk3368_vop_intrs,
1000 .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
1001 .line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0),
1002 .line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16),
1003 .status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0),
1004 .enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0),
1005 .clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0),
1006};
1007
1008static const struct vop_win_data rk3328_vop_win_data[] = {
1009 { .base = 0xd0, .phy = &rk3368_win01_data,
1010 .type = DRM_PLANE_TYPE_PRIMARY },
1011 { .base = 0x1d0, .phy = &rk3368_win01_data,
1012 .type = DRM_PLANE_TYPE_OVERLAY },
1013 { .base = 0x2d0, .phy = &rk3368_win01_data,
1014 .type = DRM_PLANE_TYPE_CURSOR },
1015};
1016
1017static const struct vop_data rk3328_vop = {
1018 .version = VOP_VERSION(3, 8),
1019 .feature = VOP_FEATURE_OUTPUT_RGB10,
1020 .intr = &rk3328_vop_intr,
1021 .common = &rk3328_common,
1022 .modeset = &rk3328_modeset,
1023 .output = &rk3328_output,
1024 .misc = &rk3328_misc,
1025 .win = rk3328_vop_win_data,
1026 .win_size = ARRAY_SIZE(rk3328_vop_win_data),
1027};
1028
1029static const struct of_device_id vop_driver_dt_match[] = {
1030 { .compatible = "rockchip,rk3036-vop",
1031 .data = &rk3036_vop },
1032 { .compatible = "rockchip,rk3126-vop",
1033 .data = &rk3126_vop },
1034 { .compatible = "rockchip,px30-vop-big",
1035 .data = &px30_vop_big },
1036 { .compatible = "rockchip,px30-vop-lit",
1037 .data = &px30_vop_lit },
1038 { .compatible = "rockchip,rk3066-vop",
1039 .data = &rk3066_vop },
1040 { .compatible = "rockchip,rk3188-vop",
1041 .data = &rk3188_vop },
1042 { .compatible = "rockchip,rk3288-vop",
1043 .data = &rk3288_vop },
1044 { .compatible = "rockchip,rk3368-vop",
1045 .data = &rk3368_vop },
1046 { .compatible = "rockchip,rk3366-vop",
1047 .data = &rk3366_vop },
1048 { .compatible = "rockchip,rk3399-vop-big",
1049 .data = &rk3399_vop_big },
1050 { .compatible = "rockchip,rk3399-vop-lit",
1051 .data = &rk3399_vop_lit },
1052 { .compatible = "rockchip,rk3228-vop",
1053 .data = &rk3228_vop },
1054 { .compatible = "rockchip,rk3328-vop",
1055 .data = &rk3328_vop },
1056 {},
1057};
1058MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
1059
1060static int vop_probe(struct platform_device *pdev)
1061{
1062 struct device *dev = &pdev->dev;
1063
1064 if (!dev->of_node) {
1065 DRM_DEV_ERROR(dev, "can't find vop devices\n");
1066 return -ENODEV;
1067 }
1068
1069 return component_add(dev, &vop_component_ops);
1070}
1071
1072static int vop_remove(struct platform_device *pdev)
1073{
1074 component_del(&pdev->dev, &vop_component_ops);
1075
1076 return 0;
1077}
1078
1079struct platform_driver vop_platform_driver = {
1080 .probe = vop_probe,
1081 .remove = vop_remove,
1082 .driver = {
1083 .name = "rockchip-vop",
1084 .of_match_table = of_match_ptr(vop_driver_dt_match),
1085 },
1086};
1087