drm/msm/hdmi: Enable HPD after HDMI IRQ is set up
[linux/fpc-iii.git] / drivers / gpu / drm / rockchip / rockchip_vop_reg.c
blob08023d3ecb76c07a5c5976acf53e2d5375093529
1 /*
2 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
3 * Author:Mark Yao <mark.yao@rock-chips.com>
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <drm/drmP.h>
17 #include <linux/kernel.h>
18 #include <linux/component.h>
20 #include "rockchip_drm_vop.h"
21 #include "rockchip_vop_reg.h"
23 #define _VOP_REG(off, _mask, _shift, _write_mask, _relaxed) \
24 { \
25 .offset = off, \
26 .mask = _mask, \
27 .shift = _shift, \
28 .write_mask = _write_mask, \
29 .relaxed = _relaxed, \
32 #define VOP_REG(off, _mask, _shift) \
33 _VOP_REG(off, _mask, _shift, false, true)
35 #define VOP_REG_SYNC(off, _mask, _shift) \
36 _VOP_REG(off, _mask, _shift, false, false)
38 #define VOP_REG_MASK_SYNC(off, _mask, _shift) \
39 _VOP_REG(off, _mask, _shift, true, false)
41 static const uint32_t formats_win_full[] = {
42 DRM_FORMAT_XRGB8888,
43 DRM_FORMAT_ARGB8888,
44 DRM_FORMAT_XBGR8888,
45 DRM_FORMAT_ABGR8888,
46 DRM_FORMAT_RGB888,
47 DRM_FORMAT_BGR888,
48 DRM_FORMAT_RGB565,
49 DRM_FORMAT_BGR565,
50 DRM_FORMAT_NV12,
51 DRM_FORMAT_NV16,
52 DRM_FORMAT_NV24,
55 static const uint32_t formats_win_lite[] = {
56 DRM_FORMAT_XRGB8888,
57 DRM_FORMAT_ARGB8888,
58 DRM_FORMAT_XBGR8888,
59 DRM_FORMAT_ABGR8888,
60 DRM_FORMAT_RGB888,
61 DRM_FORMAT_BGR888,
62 DRM_FORMAT_RGB565,
63 DRM_FORMAT_BGR565,
66 static const struct vop_scl_regs rk3036_win_scl = {
67 .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
68 .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
69 .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
70 .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
73 static const struct vop_win_phy rk3036_win0_data = {
74 .scl = &rk3036_win_scl,
75 .data_formats = formats_win_full,
76 .nformats = ARRAY_SIZE(formats_win_full),
77 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
78 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
79 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
80 .act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
81 .dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
82 .dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
83 .yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
84 .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
85 .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
86 .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16),
89 static const struct vop_win_phy rk3036_win1_data = {
90 .data_formats = formats_win_lite,
91 .nformats = ARRAY_SIZE(formats_win_lite),
92 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
93 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
94 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
95 .act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
96 .dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
97 .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
98 .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
99 .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
102 static const struct vop_win_data rk3036_vop_win_data[] = {
103 { .base = 0x00, .phy = &rk3036_win0_data,
104 .type = DRM_PLANE_TYPE_PRIMARY },
105 { .base = 0x00, .phy = &rk3036_win1_data,
106 .type = DRM_PLANE_TYPE_CURSOR },
109 static const int rk3036_vop_intrs[] = {
110 DSP_HOLD_VALID_INTR,
111 FS_INTR,
112 LINE_FLAG_INTR,
113 BUS_ERROR_INTR,
116 static const struct vop_intr rk3036_intr = {
117 .intrs = rk3036_vop_intrs,
118 .nintrs = ARRAY_SIZE(rk3036_vop_intrs),
119 .line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12),
120 .status = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 0),
121 .enable = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 4),
122 .clear = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 8),
125 static const struct vop_modeset rk3036_modeset = {
126 .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
127 .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
128 .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
129 .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
132 static const struct vop_output rk3036_output = {
133 .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
136 static const struct vop_common rk3036_common = {
137 .standby = VOP_REG_SYNC(RK3036_SYS_CTRL, 0x1, 30),
138 .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
139 .dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24),
140 .cfg_done = VOP_REG_SYNC(RK3036_REG_CFG_DONE, 0x1, 0),
143 static const struct vop_data rk3036_vop = {
144 .intr = &rk3036_intr,
145 .common = &rk3036_common,
146 .modeset = &rk3036_modeset,
147 .output = &rk3036_output,
148 .win = rk3036_vop_win_data,
149 .win_size = ARRAY_SIZE(rk3036_vop_win_data),
152 static const struct vop_win_phy rk3126_win1_data = {
153 .data_formats = formats_win_lite,
154 .nformats = ARRAY_SIZE(formats_win_lite),
155 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
156 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
157 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
158 .dsp_info = VOP_REG(RK3126_WIN1_DSP_INFO, 0x0fff0fff, 0),
159 .dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0),
160 .yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0),
161 .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
164 static const struct vop_win_data rk3126_vop_win_data[] = {
165 { .base = 0x00, .phy = &rk3036_win0_data,
166 .type = DRM_PLANE_TYPE_PRIMARY },
167 { .base = 0x00, .phy = &rk3126_win1_data,
168 .type = DRM_PLANE_TYPE_CURSOR },
171 static const struct vop_data rk3126_vop = {
172 .intr = &rk3036_intr,
173 .common = &rk3036_common,
174 .modeset = &rk3036_modeset,
175 .output = &rk3036_output,
176 .win = rk3126_vop_win_data,
177 .win_size = ARRAY_SIZE(rk3126_vop_win_data),
180 static const struct vop_scl_extension rk3288_win_full_scl_ext = {
181 .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
182 .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
183 .cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28),
184 .cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26),
185 .cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24),
186 .yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23),
187 .yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22),
188 .yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20),
189 .yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18),
190 .yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16),
191 .line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15),
192 .cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12),
193 .yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8),
194 .vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7),
195 .vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6),
196 .vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5),
197 .vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4),
198 .bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2),
199 .cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1),
200 .yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0),
201 .lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5),
204 static const struct vop_scl_regs rk3288_win_full_scl = {
205 .ext = &rk3288_win_full_scl_ext,
206 .scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
207 .scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
208 .scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
209 .scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
212 static const struct vop_win_phy rk3288_win01_data = {
213 .scl = &rk3288_win_full_scl,
214 .data_formats = formats_win_full,
215 .nformats = ARRAY_SIZE(formats_win_full),
216 .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
217 .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
218 .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
219 .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
220 .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
221 .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
222 .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
223 .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
224 .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
225 .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
226 .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
227 .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
228 .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0),
231 static const struct vop_win_phy rk3288_win23_data = {
232 .data_formats = formats_win_lite,
233 .nformats = ARRAY_SIZE(formats_win_lite),
234 .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4),
235 .gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
236 .format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
237 .rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
238 .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
239 .dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0),
240 .yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0),
241 .yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0),
242 .src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
243 .dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
246 static const struct vop_modeset rk3288_modeset = {
247 .htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
248 .hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0),
249 .vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
250 .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
251 .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
252 .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
255 static const struct vop_output rk3288_output = {
256 .pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4),
257 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
258 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
259 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
260 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
263 static const struct vop_common rk3288_common = {
264 .standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22),
265 .gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
266 .mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20),
267 .pre_dither_down = VOP_REG(RK3288_DSP_CTRL1, 0x1, 1),
268 .dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1),
269 .dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6),
270 .data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19),
271 .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18),
272 .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
273 .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0),
277 * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
278 * special support to get alpha blending working. For now, just use overlay
279 * window 3 for the drm cursor.
282 static const struct vop_win_data rk3288_vop_win_data[] = {
283 { .base = 0x00, .phy = &rk3288_win01_data,
284 .type = DRM_PLANE_TYPE_PRIMARY },
285 { .base = 0x40, .phy = &rk3288_win01_data,
286 .type = DRM_PLANE_TYPE_OVERLAY },
287 { .base = 0x00, .phy = &rk3288_win23_data,
288 .type = DRM_PLANE_TYPE_OVERLAY },
289 { .base = 0x50, .phy = &rk3288_win23_data,
290 .type = DRM_PLANE_TYPE_CURSOR },
293 static const int rk3288_vop_intrs[] = {
294 DSP_HOLD_VALID_INTR,
295 FS_INTR,
296 LINE_FLAG_INTR,
297 BUS_ERROR_INTR,
300 static const struct vop_intr rk3288_vop_intr = {
301 .intrs = rk3288_vop_intrs,
302 .nintrs = ARRAY_SIZE(rk3288_vop_intrs),
303 .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12),
304 .status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0),
305 .enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4),
306 .clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8),
309 static const struct vop_data rk3288_vop = {
310 .version = VOP_VERSION(3, 1),
311 .feature = VOP_FEATURE_OUTPUT_RGB10,
312 .intr = &rk3288_vop_intr,
313 .common = &rk3288_common,
314 .modeset = &rk3288_modeset,
315 .output = &rk3288_output,
316 .win = rk3288_vop_win_data,
317 .win_size = ARRAY_SIZE(rk3288_vop_win_data),
320 static const int rk3368_vop_intrs[] = {
321 FS_INTR,
322 0, 0,
323 LINE_FLAG_INTR,
325 BUS_ERROR_INTR,
326 0, 0, 0, 0, 0, 0, 0,
327 DSP_HOLD_VALID_INTR,
330 static const struct vop_intr rk3368_vop_intr = {
331 .intrs = rk3368_vop_intrs,
332 .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
333 .line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0),
334 .line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16),
335 .status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0),
336 .enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0),
337 .clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0),
340 static const struct vop_win_phy rk3368_win23_data = {
341 .data_formats = formats_win_lite,
342 .nformats = ARRAY_SIZE(formats_win_lite),
343 .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0),
344 .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4),
345 .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5),
346 .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20),
347 .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0),
348 .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0),
349 .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0),
350 .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0),
351 .src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
352 .dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0),
355 static const struct vop_win_data rk3368_vop_win_data[] = {
356 { .base = 0x00, .phy = &rk3288_win01_data,
357 .type = DRM_PLANE_TYPE_PRIMARY },
358 { .base = 0x40, .phy = &rk3288_win01_data,
359 .type = DRM_PLANE_TYPE_OVERLAY },
360 { .base = 0x00, .phy = &rk3368_win23_data,
361 .type = DRM_PLANE_TYPE_OVERLAY },
362 { .base = 0x50, .phy = &rk3368_win23_data,
363 .type = DRM_PLANE_TYPE_CURSOR },
366 static const struct vop_output rk3368_output = {
367 .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16),
368 .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20),
369 .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24),
370 .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28),
371 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
372 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
373 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
374 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
377 static const struct vop_misc rk3368_misc = {
378 .global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11),
381 static const struct vop_data rk3368_vop = {
382 .version = VOP_VERSION(3, 2),
383 .intr = &rk3368_vop_intr,
384 .common = &rk3288_common,
385 .modeset = &rk3288_modeset,
386 .output = &rk3368_output,
387 .misc = &rk3368_misc,
388 .win = rk3368_vop_win_data,
389 .win_size = ARRAY_SIZE(rk3368_vop_win_data),
392 static const struct vop_intr rk3366_vop_intr = {
393 .intrs = rk3368_vop_intrs,
394 .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
395 .line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0),
396 .line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16),
397 .status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0),
398 .enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0),
399 .clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0),
402 static const struct vop_data rk3366_vop = {
403 .version = VOP_VERSION(3, 4),
404 .intr = &rk3366_vop_intr,
405 .common = &rk3288_common,
406 .modeset = &rk3288_modeset,
407 .output = &rk3368_output,
408 .misc = &rk3368_misc,
409 .win = rk3368_vop_win_data,
410 .win_size = ARRAY_SIZE(rk3368_vop_win_data),
413 static const struct vop_output rk3399_output = {
414 .dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16),
415 .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16),
416 .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20),
417 .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24),
418 .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28),
419 .dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11),
420 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
421 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
422 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
423 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
426 static const struct vop_data rk3399_vop_big = {
427 .version = VOP_VERSION(3, 5),
428 .feature = VOP_FEATURE_OUTPUT_RGB10,
429 .intr = &rk3366_vop_intr,
430 .common = &rk3288_common,
431 .modeset = &rk3288_modeset,
432 .output = &rk3399_output,
433 .misc = &rk3368_misc,
434 .win = rk3368_vop_win_data,
435 .win_size = ARRAY_SIZE(rk3368_vop_win_data),
438 static const struct vop_win_data rk3399_vop_lit_win_data[] = {
439 { .base = 0x00, .phy = &rk3288_win01_data,
440 .type = DRM_PLANE_TYPE_PRIMARY },
441 { .base = 0x00, .phy = &rk3368_win23_data,
442 .type = DRM_PLANE_TYPE_CURSOR},
445 static const struct vop_data rk3399_vop_lit = {
446 .version = VOP_VERSION(3, 6),
447 .intr = &rk3366_vop_intr,
448 .common = &rk3288_common,
449 .modeset = &rk3288_modeset,
450 .output = &rk3399_output,
451 .misc = &rk3368_misc,
452 .win = rk3399_vop_lit_win_data,
453 .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data),
456 static const struct vop_win_data rk3228_vop_win_data[] = {
457 { .base = 0x00, .phy = &rk3288_win01_data,
458 .type = DRM_PLANE_TYPE_PRIMARY },
459 { .base = 0x40, .phy = &rk3288_win01_data,
460 .type = DRM_PLANE_TYPE_CURSOR },
463 static const struct vop_data rk3228_vop = {
464 .version = VOP_VERSION(3, 7),
465 .feature = VOP_FEATURE_OUTPUT_RGB10,
466 .intr = &rk3366_vop_intr,
467 .common = &rk3288_common,
468 .modeset = &rk3288_modeset,
469 .output = &rk3399_output,
470 .misc = &rk3368_misc,
471 .win = rk3228_vop_win_data,
472 .win_size = ARRAY_SIZE(rk3228_vop_win_data),
475 static const struct vop_modeset rk3328_modeset = {
476 .htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
477 .hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0),
478 .vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
479 .vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0),
480 .hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
481 .vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
484 static const struct vop_output rk3328_output = {
485 .rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12),
486 .hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13),
487 .edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14),
488 .mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15),
489 .rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 16),
490 .hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 20),
491 .edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 24),
492 .mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 28),
495 static const struct vop_misc rk3328_misc = {
496 .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11),
499 static const struct vop_common rk3328_common = {
500 .standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22),
501 .dither_down = VOP_REG(RK3328_DSP_CTRL1, 0xf, 1),
502 .dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6),
503 .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18),
504 .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0),
505 .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0),
508 static const struct vop_intr rk3328_vop_intr = {
509 .intrs = rk3368_vop_intrs,
510 .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
511 .line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0),
512 .line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16),
513 .status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0),
514 .enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0),
515 .clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0),
518 static const struct vop_win_data rk3328_vop_win_data[] = {
519 { .base = 0xd0, .phy = &rk3288_win01_data,
520 .type = DRM_PLANE_TYPE_PRIMARY },
521 { .base = 0x1d0, .phy = &rk3288_win01_data,
522 .type = DRM_PLANE_TYPE_OVERLAY },
523 { .base = 0x2d0, .phy = &rk3288_win01_data,
524 .type = DRM_PLANE_TYPE_CURSOR },
527 static const struct vop_data rk3328_vop = {
528 .version = VOP_VERSION(3, 8),
529 .feature = VOP_FEATURE_OUTPUT_RGB10,
530 .intr = &rk3328_vop_intr,
531 .common = &rk3328_common,
532 .modeset = &rk3328_modeset,
533 .output = &rk3328_output,
534 .misc = &rk3328_misc,
535 .win = rk3328_vop_win_data,
536 .win_size = ARRAY_SIZE(rk3328_vop_win_data),
539 static const struct of_device_id vop_driver_dt_match[] = {
540 { .compatible = "rockchip,rk3036-vop",
541 .data = &rk3036_vop },
542 { .compatible = "rockchip,rk3126-vop",
543 .data = &rk3126_vop },
544 { .compatible = "rockchip,rk3288-vop",
545 .data = &rk3288_vop },
546 { .compatible = "rockchip,rk3368-vop",
547 .data = &rk3368_vop },
548 { .compatible = "rockchip,rk3366-vop",
549 .data = &rk3366_vop },
550 { .compatible = "rockchip,rk3399-vop-big",
551 .data = &rk3399_vop_big },
552 { .compatible = "rockchip,rk3399-vop-lit",
553 .data = &rk3399_vop_lit },
554 { .compatible = "rockchip,rk3228-vop",
555 .data = &rk3228_vop },
556 { .compatible = "rockchip,rk3328-vop",
557 .data = &rk3328_vop },
560 MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
562 static int vop_probe(struct platform_device *pdev)
564 struct device *dev = &pdev->dev;
566 if (!dev->of_node) {
567 DRM_DEV_ERROR(dev, "can't find vop devices\n");
568 return -ENODEV;
571 return component_add(dev, &vop_component_ops);
574 static int vop_remove(struct platform_device *pdev)
576 component_del(&pdev->dev, &vop_component_ops);
578 return 0;
581 struct platform_driver vop_platform_driver = {
582 .probe = vop_probe,
583 .remove = vop_remove,
584 .driver = {
585 .name = "rockchip-vop",
586 .of_match_table = of_match_ptr(vop_driver_dt_match),