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