1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4 * Author:Mark Yao <mark.yao@rock-chips.com>
7 #include <linux/component.h>
8 #include <linux/mod_devicetable.h>
9 #include <linux/module.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) \
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
[] = {
53 static const uint32_t formats_win_lite
[] = {
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
[] = {
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
[] = {
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
= {
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
= {
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.
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.
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
[] = {
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
),
656 static const int rk3368_vop_intrs
[] = {
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
;
986 DRM_DEV_ERROR(dev
, "can't find vop devices\n");
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
);
1000 struct platform_driver vop_platform_driver
= {
1002 .remove
= vop_remove
,
1004 .name
= "rockchip-vop",
1005 .of_match_table
= of_match_ptr(vop_driver_dt_match
),