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