1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) Rockchip Electronics Co., Ltd.
4 * Author: Andy Yan <andy.yan@rock-chips.com>
5 */
6
7 #include <linux/bitfield.h>
8 #include <linux/kernel.h>
9 #include <linux/component.h>
10 #include <linux/hw_bitfield.h>
11 #include <linux/mod_devicetable.h>
12 #include <linux/platform_device.h>
13 #include <linux/of.h>
14 #include <drm/drm_blend.h>
15 #include <drm/drm_fourcc.h>
16 #include <drm/drm_framebuffer.h>
17 #include <drm/drm_plane.h>
18 #include <drm/drm_print.h>
19
20 #include "rockchip_drm_vop2.h"
21
22 union vop2_alpha_ctrl {
23 u32 val;
24 struct {
25 /* [0:1] */
26 u32 color_mode:1;
27 u32 alpha_mode:1;
28 /* [2:3] */
29 u32 blend_mode:2;
30 u32 alpha_cal_mode:1;
31 /* [5:7] */
32 u32 factor_mode:3;
33 /* [8:9] */
34 u32 alpha_en:1;
35 u32 src_dst_swap:1;
36 u32 reserved:6;
37 /* [16:23] */
38 u32 glb_alpha:8;
39 } bits;
40 };
41
42 struct vop2_alpha {
43 union vop2_alpha_ctrl src_color_ctrl;
44 union vop2_alpha_ctrl dst_color_ctrl;
45 union vop2_alpha_ctrl src_alpha_ctrl;
46 union vop2_alpha_ctrl dst_alpha_ctrl;
47 };
48
49 struct vop2_alpha_config {
50 bool src_premulti_en;
51 bool dst_premulti_en;
52 bool src_pixel_alpha_en;
53 bool dst_pixel_alpha_en;
54 u16 src_glb_alpha_value;
55 u16 dst_glb_alpha_value;
56 };
57
58 static const uint32_t formats_cluster[] = {
59 DRM_FORMAT_XRGB2101010,
60 DRM_FORMAT_XBGR2101010,
61 DRM_FORMAT_XRGB8888,
62 DRM_FORMAT_ARGB8888,
63 DRM_FORMAT_XBGR8888,
64 DRM_FORMAT_ABGR8888,
65 DRM_FORMAT_RGB888,
66 DRM_FORMAT_BGR888,
67 DRM_FORMAT_RGB565,
68 DRM_FORMAT_BGR565,
69 DRM_FORMAT_YUV420_8BIT, /* yuv420_8bit non-Linear mode only */
70 DRM_FORMAT_YUV420_10BIT, /* yuv420_10bit non-Linear mode only */
71 DRM_FORMAT_YUYV, /* yuv422_8bit non-Linear mode only*/
72 DRM_FORMAT_Y210, /* yuv422_10bit non-Linear mode only */
73 };
74
75 /*
76 * The cluster windows on rk3576 support:
77 * RGB: linear mode and afbc
78 * YUV: linear mode and rfbc
79 * rfbc is a rockchip defined non-linear mode, produced by
80 * Video decoder
81 */
82 static const uint32_t formats_rk3576_cluster[] = {
83 DRM_FORMAT_XRGB2101010,
84 DRM_FORMAT_XBGR2101010,
85 DRM_FORMAT_ARGB2101010,
86 DRM_FORMAT_ABGR2101010,
87 DRM_FORMAT_XRGB8888,
88 DRM_FORMAT_ARGB8888,
89 DRM_FORMAT_XBGR8888,
90 DRM_FORMAT_ABGR8888,
91 DRM_FORMAT_RGB888,
92 DRM_FORMAT_BGR888,
93 DRM_FORMAT_RGB565,
94 DRM_FORMAT_BGR565,
95 DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
96 DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */
97 DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
98 DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */
99 DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
100 DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */
101 DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
102 DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
103 DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
104 };
105
106 static const uint32_t formats_esmart[] = {
107 DRM_FORMAT_XRGB8888,
108 DRM_FORMAT_ARGB8888,
109 DRM_FORMAT_XBGR8888,
110 DRM_FORMAT_ABGR8888,
111 DRM_FORMAT_RGB888,
112 DRM_FORMAT_BGR888,
113 DRM_FORMAT_RGB565,
114 DRM_FORMAT_BGR565,
115 DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
116 DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */
117 DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
118 DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */
119 DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
120 DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
121 DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */
122 DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
123 DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
124 DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */
125 DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */
126 DRM_FORMAT_YUYV, /* yuv422_8bit[YUYV] linear mode */
127 DRM_FORMAT_UYVY, /* yuv422_8bit[UYVY] linear mode */
128 };
129
130 static const uint32_t formats_rk356x_esmart[] = {
131 DRM_FORMAT_XRGB8888,
132 DRM_FORMAT_ARGB8888,
133 DRM_FORMAT_XBGR8888,
134 DRM_FORMAT_ABGR8888,
135 DRM_FORMAT_RGB888,
136 DRM_FORMAT_BGR888,
137 DRM_FORMAT_RGB565,
138 DRM_FORMAT_BGR565,
139 DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
140 DRM_FORMAT_NV21, /* yuv420_8bit linear mode, 2 plane */
141 DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
142 DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
143 DRM_FORMAT_NV61, /* yuv422_8bit linear mode, 2 plane */
144 DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
145 DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
146 DRM_FORMAT_NV42, /* yuv444_8bit linear mode, 2 plane */
147 DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
148 DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */
149 DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */
150 };
151
152 /*
153 * Add XRGB2101010/ARGB2101010ARGB1555/XRGB1555
154 */
155 static const uint32_t formats_rk3576_esmart[] = {
156 DRM_FORMAT_XRGB2101010,
157 DRM_FORMAT_XBGR2101010,
158 DRM_FORMAT_ARGB2101010,
159 DRM_FORMAT_ABGR2101010,
160 DRM_FORMAT_XRGB8888,
161 DRM_FORMAT_ARGB8888,
162 DRM_FORMAT_XBGR8888,
163 DRM_FORMAT_ABGR8888,
164 DRM_FORMAT_RGB888,
165 DRM_FORMAT_BGR888,
166 DRM_FORMAT_RGB565,
167 DRM_FORMAT_BGR565,
168 DRM_FORMAT_ARGB1555,
169 DRM_FORMAT_ABGR1555,
170 DRM_FORMAT_XRGB1555,
171 DRM_FORMAT_XBGR1555,
172 DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */
173 DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */
174 DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */
175 DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */
176 DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */
177 DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */
178 DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */
179 DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */
180 DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */
181 DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */
182 DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */
183 DRM_FORMAT_YUYV, /* yuv422_8bit[YUYV] linear mode */
184 DRM_FORMAT_UYVY, /* yuv422_8bit[UYVY] linear mode */
185 };
186
187 static const uint32_t formats_smart[] = {
188 DRM_FORMAT_XRGB8888,
189 DRM_FORMAT_ARGB8888,
190 DRM_FORMAT_XBGR8888,
191 DRM_FORMAT_ABGR8888,
192 DRM_FORMAT_RGB888,
193 DRM_FORMAT_BGR888,
194 DRM_FORMAT_RGB565,
195 DRM_FORMAT_BGR565,
196 };
197
198 static const uint64_t format_modifiers[] = {
199 DRM_FORMAT_MOD_LINEAR,
200 DRM_FORMAT_MOD_INVALID,
201 };
202
203 static const uint64_t format_modifiers_afbc[] = {
204 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16),
205
206 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
207 AFBC_FORMAT_MOD_SPARSE),
208
209 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
210 AFBC_FORMAT_MOD_YTR),
211
212 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
213 AFBC_FORMAT_MOD_CBR),
214
215 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
216 AFBC_FORMAT_MOD_YTR |
217 AFBC_FORMAT_MOD_SPARSE),
218
219 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
220 AFBC_FORMAT_MOD_CBR |
221 AFBC_FORMAT_MOD_SPARSE),
222
223 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
224 AFBC_FORMAT_MOD_YTR |
225 AFBC_FORMAT_MOD_CBR),
226
227 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
228 AFBC_FORMAT_MOD_YTR |
229 AFBC_FORMAT_MOD_CBR |
230 AFBC_FORMAT_MOD_SPARSE),
231
232 /* SPLIT mandates SPARSE, RGB modes mandates YTR */
233 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
234 AFBC_FORMAT_MOD_YTR |
235 AFBC_FORMAT_MOD_SPARSE |
236 AFBC_FORMAT_MOD_SPLIT),
237 DRM_FORMAT_MOD_INVALID,
238 };
239
240 /* used from rk3576, afbc 32*8 half mode */
241 static const uint64_t format_modifiers_rk3576_afbc[] = {
242 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
243 AFBC_FORMAT_MOD_SPLIT),
244
245 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
246 AFBC_FORMAT_MOD_SPARSE |
247 AFBC_FORMAT_MOD_SPLIT),
248
249 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
250 AFBC_FORMAT_MOD_YTR |
251 AFBC_FORMAT_MOD_SPLIT),
252
253 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
254 AFBC_FORMAT_MOD_CBR |
255 AFBC_FORMAT_MOD_SPLIT),
256
257 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
258 AFBC_FORMAT_MOD_CBR |
259 AFBC_FORMAT_MOD_SPARSE |
260 AFBC_FORMAT_MOD_SPLIT),
261
262 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
263 AFBC_FORMAT_MOD_YTR |
264 AFBC_FORMAT_MOD_CBR |
265 AFBC_FORMAT_MOD_SPLIT),
266
267 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
268 AFBC_FORMAT_MOD_YTR |
269 AFBC_FORMAT_MOD_CBR |
270 AFBC_FORMAT_MOD_SPARSE |
271 AFBC_FORMAT_MOD_SPLIT),
272
273 /* SPLIT mandates SPARSE, RGB modes mandates YTR */
274 DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
275 AFBC_FORMAT_MOD_YTR |
276 AFBC_FORMAT_MOD_SPARSE |
277 AFBC_FORMAT_MOD_SPLIT),
278 DRM_FORMAT_MOD_LINEAR,
279 DRM_FORMAT_MOD_INVALID,
280 };
281
282 static const struct reg_field rk3568_vop_cluster_regs[VOP2_WIN_MAX_REG] = {
283 [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0),
284 [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5),
285 [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14),
286 [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18),
287 [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31),
288 [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31),
289 [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31),
290 [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31),
291 [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31),
292 [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19),
293 [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15),
294 [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31),
295 [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8),
296 [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9),
297 [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11),
298 [VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 0, 3),
299 [VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 5, 8),
300 /* RK3588 only, reserved bit on rk3568*/
301 [VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3568_CLUSTER_CTRL, 13, 13),
302
303 /* Scale */
304 [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15),
305 [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31),
306 [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15),
307 [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 12, 13),
308 [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3),
309 [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28),
310 [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29),
311
312 /* cluster regs */
313 [VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1),
314 [VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0),
315 [VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7),
316
317 /* afbc regs */
318 [VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6),
319 [VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9),
320 [VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10),
321 [VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4),
322 [VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7),
323 [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8),
324 [VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31),
325 [VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31),
326 [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15),
327 [VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31),
328 [VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31),
329 [VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31),
330 [VOP2_WIN_TRANSFORM_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_TRANSFORM_OFFSET, 0, 31),
331 [VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0),
332 [VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1),
333 [VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2),
334 [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3),
335 [VOP2_WIN_UV_SWAP] = { .reg = 0xffffffff },
336 [VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff },
337 [VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff },
338 [VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff },
339 [VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff },
340 [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
341 [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
342 [VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff },
343 [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
344 [VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff },
345 [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
346 [VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff },
347 [VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff },
348 };
349
350 static const struct reg_field rk3568_vop_smart_regs[VOP2_WIN_MAX_REG] = {
351 [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0),
352 [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5),
353 [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12),
354 [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14),
355 [VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16),
356 [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31),
357 [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31),
358 [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28),
359 [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31),
360 [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31),
361 [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17),
362 [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15),
363 [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31),
364 [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0),
365 [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1),
366 [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3),
367 [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31),
368 [VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29),
369 [VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31),
370 [VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 4, 8),
371 [VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 12, 16),
372 /* RK3588 only, reserved register on rk3568 */
373 [VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3588_SMART_AXI_CTRL, 1, 1),
374
375 /* Scale */
376 [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15),
377 [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31),
378 [VOP2_WIN_SCALE_CBCR_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0, 15),
379 [VOP2_WIN_SCALE_CBCR_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 16, 31),
380 [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1),
381 [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3),
382 [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5),
383 [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7),
384 [VOP2_WIN_CBCR_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 8, 9),
385 [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 10, 11),
386 [VOP2_WIN_CBCR_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 12, 13),
387 [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 14, 15),
388 [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17),
389 [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8),
390 [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9),
391 [VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10),
392 [VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11),
393 [VOP2_WIN_XMIRROR] = { .reg = 0xffffffff },
394 [VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff },
395 [VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff },
396 [VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff },
397 [VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff },
398 [VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff },
399 [VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff },
400 [VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff },
401 [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff },
402 [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff },
403 [VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff },
404 [VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff },
405 [VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff },
406 [VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff },
407 [VOP2_WIN_TRANSFORM_OFFSET] = { .reg = 0xffffffff },
408 [VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff },
409 [VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff },
410 [VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff },
411 [VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff },
412 };
413
414 static const struct reg_field rk3576_vop_cluster_regs[VOP2_WIN_MAX_REG] = {
415 [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0),
416 [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5),
417 [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14),
418 [VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 17, 17),
419 [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18),
420 [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31),
421 [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31),
422 [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31),
423 [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31),
424 [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31),
425 [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19),
426 [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15),
427 [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31),
428 [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8),
429 [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9),
430 [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11),
431 [VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 0, 4),
432 [VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL2, 5, 9),
433 /* Read only bit on rk3576, writing on this bit have no effect.*/
434 [VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3568_CLUSTER_CTRL, 13, 13),
435
436 [VOP2_WIN_VP_SEL] = REG_FIELD(RK3576_CLUSTER_PORT_SEL_IMD, 0, 1),
437 [VOP2_WIN_DLY_NUM] = REG_FIELD(RK3576_CLUSTER_DLY_NUM, 0, 7),
438
439 /* Scale */
440 [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15),
441 [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31),
442 [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3),
443 [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15),
444 [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 22, 23),
445 [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28),
446 [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29),
447
448 /* cluster regs */
449 [VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1),
450 [VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0),
451 [VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7),
452
453 /* afbc regs */
454 [VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6),
455 [VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9),
456 [VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10),
457 [VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4),
458 [VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7),
459 [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8),
460 [VOP2_WIN_AFBC_PLD_OFFSET_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 16, 16),
461 [VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31),
462 [VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31),
463 [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15),
464 [VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31),
465 [VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31),
466 [VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31),
467 [VOP2_WIN_AFBC_PLD_OFFSET] = REG_FIELD(RK3576_CLUSTER_WIN_AFBCD_PLD_PTR_OFFSET, 0, 31),
468 [VOP2_WIN_TRANSFORM_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_TRANSFORM_OFFSET, 0, 31),
469 [VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0),
470 [VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1),
471 [VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2),
472 [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3),
473 [VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff },
474 [VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff },
475 [VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff },
476 [VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff },
477 [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
478 [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
479 [VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff },
480 [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff },
481 [VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff },
482 [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff },
483 [VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff },
484 [VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff },
485 };
486
487 static const struct reg_field rk3576_vop_smart_regs[VOP2_WIN_MAX_REG] = {
488 [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0),
489 [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5),
490 [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12),
491 [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14),
492 [VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16),
493 [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31),
494 [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31),
495 [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28),
496 [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31),
497 [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31),
498 [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17),
499 [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15),
500 [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31),
501 [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0),
502 [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1),
503 [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3),
504 [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31),
505 [VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29),
506 [VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31),
507 [VOP2_WIN_VP_SEL] = REG_FIELD(RK3576_SMART_PORT_SEL_IMD, 0, 1),
508 [VOP2_WIN_DLY_NUM] = REG_FIELD(RK3576_SMART_DLY_NUM, 0, 7),
509 [VOP2_WIN_AXI_YRGB_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 4, 8),
510 [VOP2_WIN_AXI_UV_R_ID] = REG_FIELD(RK3568_SMART_CTRL1, 12, 16),
511 [VOP2_WIN_AXI_BUS_ID] = REG_FIELD(RK3588_SMART_AXI_CTRL, 1, 1),
512
513 /* Scale */
514 [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15),
515 [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31),
516 [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1),
517 [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3),
518 [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5),
519 [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7),
520 [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17),
521 [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8),
522 [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9),
523 [VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10),
524 [VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11),
525 [VOP2_WIN_XMIRROR] = { .reg = 0xffffffff },
526
527 /* CBCR share the same scale factor as YRGB */
528 [VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff },
529 [VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff },
530 [VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff },
531 [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff},
532 [VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff},
533 [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff},
534
535 [VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff },
536 [VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff },
537 [VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff },
538 [VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff },
539 [VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff },
540 [VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff },
541 [VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff },
542 [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff },
543 [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff },
544 [VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff },
545 [VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff },
546 [VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff },
547 [VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff },
548 [VOP2_WIN_TRANSFORM_OFFSET] = { .reg = 0xffffffff },
549 [VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff },
550 [VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff },
551 [VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff },
552 [VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff },
553 };
554
555 static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
556 {
557 .id = 0,
558 .feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
559 .gamma_lut_len = 1024,
560 .cubic_lut_len = 9 * 9 * 9,
561 .max_output = { 4096, 2304 },
562 .pre_scan_max_dly = { 69, 53, 53, 42 },
563 .offset = 0xc00,
564 }, {
565 .id = 1,
566 .gamma_lut_len = 1024,
567 .max_output = { 2048, 1536 },
568 .pre_scan_max_dly = { 40, 40, 40, 40 },
569 .offset = 0xd00,
570 }, {
571 .id = 2,
572 .gamma_lut_len = 1024,
573 .max_output = { 1920, 1080 },
574 .pre_scan_max_dly = { 40, 40, 40, 40 },
575 .offset = 0xe00,
576 },
577 };
578
579 /*
580 * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win.
581 * Every cluster can work as 4K win or split into two win.
582 * All win in cluster support AFBCD.
583 *
584 * Every esmart win and smart win support 4 Multi-region.
585 *
586 * Scale filter mode:
587 *
588 * * Cluster: bicubic for horizontal scale up, others use bilinear
589 * * ESmart:
590 * * nearest-neighbor/bilinear/bicubic for scale up
591 * * nearest-neighbor/bilinear/average for scale down
592 *
593 *
594 * @TODO describe the wind like cpu-map dt nodes;
595 */
596 static const struct vop2_win_data rk3568_vop_win_data[] = {
597 {
598 .name = "Smart0-win0",
599 .phys_id = ROCKCHIP_VOP2_SMART0,
600 .base = 0x1c00,
601 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
602 .formats = formats_smart,
603 .nformats = ARRAY_SIZE(formats_smart),
604 .format_modifiers = format_modifiers,
605 /* 0xf means this layer can't attached to this VP */
606 .layer_sel_id = { 3, 3, 3, 0xf },
607 .supported_rotations = DRM_MODE_REFLECT_Y,
608 .type = DRM_PLANE_TYPE_PRIMARY,
609 .max_upscale_factor = 8,
610 .max_downscale_factor = 8,
611 .dly = { 20, 47, 41 },
612 }, {
613 .name = "Smart1-win0",
614 .phys_id = ROCKCHIP_VOP2_SMART1,
615 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
616 .formats = formats_smart,
617 .nformats = ARRAY_SIZE(formats_smart),
618 .format_modifiers = format_modifiers,
619 .base = 0x1e00,
620 .layer_sel_id = { 7, 7, 7, 0xf },
621 .supported_rotations = DRM_MODE_REFLECT_Y,
622 .type = DRM_PLANE_TYPE_PRIMARY,
623 .max_upscale_factor = 8,
624 .max_downscale_factor = 8,
625 .dly = { 20, 47, 41 },
626 }, {
627 .name = "Esmart1-win0",
628 .phys_id = ROCKCHIP_VOP2_ESMART1,
629 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
630 .formats = formats_rk356x_esmart,
631 .nformats = ARRAY_SIZE(formats_rk356x_esmart),
632 .format_modifiers = format_modifiers,
633 .base = 0x1a00,
634 .layer_sel_id = { 6, 6, 6, 0xf },
635 .supported_rotations = DRM_MODE_REFLECT_Y,
636 .type = DRM_PLANE_TYPE_PRIMARY,
637 .max_upscale_factor = 8,
638 .max_downscale_factor = 8,
639 .dly = { 20, 47, 41 },
640 }, {
641 .name = "Esmart0-win0",
642 .phys_id = ROCKCHIP_VOP2_ESMART0,
643 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
644 .formats = formats_rk356x_esmart,
645 .nformats = ARRAY_SIZE(formats_rk356x_esmart),
646 .format_modifiers = format_modifiers,
647 .base = 0x1800,
648 .layer_sel_id = { 2, 2, 2, 0xf },
649 .supported_rotations = DRM_MODE_REFLECT_Y,
650 .type = DRM_PLANE_TYPE_PRIMARY,
651 .max_upscale_factor = 8,
652 .max_downscale_factor = 8,
653 .dly = { 20, 47, 41 },
654 }, {
655 .name = "Cluster0-win0",
656 .phys_id = ROCKCHIP_VOP2_CLUSTER0,
657 .base = 0x1000,
658 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
659 .formats = formats_cluster,
660 .nformats = ARRAY_SIZE(formats_cluster),
661 .format_modifiers = format_modifiers_afbc,
662 .layer_sel_id = { 0, 0, 0, 0xf },
663 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
664 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
665 .max_upscale_factor = 4,
666 .max_downscale_factor = 4,
667 .dly = { 0, 27, 21 },
668 .type = DRM_PLANE_TYPE_OVERLAY,
669 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
670 }, {
671 .name = "Cluster1-win0",
672 .phys_id = ROCKCHIP_VOP2_CLUSTER1,
673 .base = 0x1200,
674 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2),
675 .formats = formats_cluster,
676 .nformats = ARRAY_SIZE(formats_cluster),
677 .format_modifiers = format_modifiers_afbc,
678 .layer_sel_id = { 1, 1, 1, 0xf },
679 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
680 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
681 .type = DRM_PLANE_TYPE_OVERLAY,
682 .max_upscale_factor = 4,
683 .max_downscale_factor = 4,
684 .dly = { 0, 27, 21 },
685 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
686 },
687 };
688
689 static const struct vop2_regs_dump rk3568_regs_dump[] = {
690 {
691 .name = "SYS",
692 .base = RK3568_REG_CFG_DONE,
693 .size = 0x100,
694 .en_reg = 0,
695 .en_val = 0,
696 .en_mask = 0
697 }, {
698 .name = "OVL",
699 .base = RK3568_OVL_CTRL,
700 .size = 0x100,
701 .en_reg = 0,
702 .en_val = 0,
703 .en_mask = 0,
704 }, {
705 .name = "VP0",
706 .base = RK3568_VP0_CTRL_BASE,
707 .size = 0x100,
708 .en_reg = RK3568_VP_DSP_CTRL,
709 .en_val = 0,
710 .en_mask = RK3568_VP_DSP_CTRL__STANDBY,
711 }, {
712 .name = "VP1",
713 .base = RK3568_VP1_CTRL_BASE,
714 .size = 0x100,
715 .en_reg = RK3568_VP_DSP_CTRL,
716 .en_val = 0,
717 .en_mask = RK3568_VP_DSP_CTRL__STANDBY,
718 }, {
719 .name = "VP2",
720 .base = RK3568_VP2_CTRL_BASE,
721 .size = 0x100,
722 .en_reg = RK3568_VP_DSP_CTRL,
723 .en_val = 0,
724 .en_mask = RK3568_VP_DSP_CTRL__STANDBY,
725
726 }, {
727 .name = "Cluster0",
728 .base = RK3568_CLUSTER0_CTRL_BASE,
729 .size = 0x110,
730 .en_reg = RK3568_CLUSTER_WIN_CTRL0,
731 .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
732 .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
733 }, {
734 .name = "Cluster1",
735 .base = RK3568_CLUSTER1_CTRL_BASE,
736 .size = 0x110,
737 .en_reg = RK3568_CLUSTER_WIN_CTRL0,
738 .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
739 .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
740 }, {
741 .name = "Esmart0",
742 .base = RK3568_ESMART0_CTRL_BASE,
743 .size = 0xf0,
744 .en_reg = RK3568_SMART_REGION0_CTRL,
745 .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
746 .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
747 }, {
748 .name = "Esmart1",
749 .base = RK3568_ESMART1_CTRL_BASE,
750 .size = 0xf0,
751 .en_reg = RK3568_SMART_REGION0_CTRL,
752 .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
753 .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
754 }, {
755 .name = "Smart0",
756 .base = RK3568_SMART0_CTRL_BASE,
757 .size = 0xf0,
758 .en_reg = RK3568_SMART_REGION0_CTRL,
759 .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
760 .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
761 }, {
762 .name = "Smart1",
763 .base = RK3568_SMART1_CTRL_BASE,
764 .size = 0xf0,
765 .en_reg = RK3568_SMART_REGION0_CTRL,
766 .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
767 .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
768 },
769 };
770
771 static const struct vop2_video_port_data rk3576_vop_video_ports[] = {
772 {
773 .id = 0,
774 .feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
775 .gamma_lut_len = 1024,
776 .cubic_lut_len = 9 * 9 * 9, /* 9x9x9 */
777 .max_output = { 4096, 2304 },
778 /* win layer_mix hdr */
779 .pre_scan_max_dly = { 10, 8, 2, 0 },
780 .offset = 0xc00,
781 .pixel_rate = 2,
782 }, {
783 .id = 1,
784 .feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
785 .gamma_lut_len = 1024,
786 .cubic_lut_len = 729, /* 9x9x9 */
787 .max_output = { 2560, 1600 },
788 /* win layer_mix hdr */
789 .pre_scan_max_dly = { 10, 6, 0, 0 },
790 .offset = 0xd00,
791 .pixel_rate = 1,
792 }, {
793 .id = 2,
794 .gamma_lut_len = 1024,
795 .max_output = { 1920, 1080 },
796 /* win layer_mix hdr */
797 .pre_scan_max_dly = { 10, 6, 0, 0 },
798 .offset = 0xe00,
799 .pixel_rate = 1,
800 },
801 };
802
803 /*
804 * rk3576 vop with 2 cluster, 4 esmart win.
805 * Every cluster can work as 4K win or split into two 2K win.
806 * All win in cluster support AFBCD.
807 *
808 * Every esmart win support 4 Multi-region.
809 *
810 * VP0 can use Cluster0/1 and Esmart0/2
811 * VP1 can use Cluster0/1 and Esmart1/3
812 * VP2 can use Esmart0/1/2/3
813 *
814 * Scale filter mode:
815 *
816 * * Cluster:
817 * * Support prescale down:
818 * * H/V: gt2/avg2 or gt4/avg4
819 * * After prescale down:
820 * * nearest-neighbor/bilinear/multi-phase filter for scale up
821 * * nearest-neighbor/bilinear/multi-phase filter for scale down
822 *
823 * * Esmart:
824 * * Support prescale down:
825 * * H: gt2/avg2 or gt4/avg4
826 * * V: gt2 or gt4
827 * * After prescale down:
828 * * nearest-neighbor/bilinear/bicubic for scale up
829 * * nearest-neighbor/bilinear for scale down
830 *
831 * AXI config::
832 *
833 * * Cluster0 win0: 0xa, 0xb [AXI0]
834 * * Cluster0 win1: 0xc, 0xd [AXI0]
835 * * Cluster1 win0: 0x6, 0x7 [AXI0]
836 * * Cluster1 win1: 0x8, 0x9 [AXI0]
837 * * Esmart0: 0x10, 0x11 [AXI0]
838 * * Esmart1: 0x12, 0x13 [AXI0]
839 * * Esmart2: 0xa, 0xb [AXI1]
840 * * Esmart3: 0xc, 0xd [AXI1]
841 * * Lut dma rid: 0x1, 0x2, 0x3 [AXI0]
842 * * DCI dma rid: 0x4 [AXI0]
843 * * Metadata rid: 0x5 [AXI0]
844 *
845 * * Limit:
846 * * (1) Cluster0/1 are fixed on AXI0 by IC design
847 * * (2) 0x0 and 0xf can't be used;
848 * * (3) 5 Bits ID for eache axi bus
849 * * (3) cluster and lut/dci/metadata rid must smaller than 0xf,
850 * * if Cluster rid is bigger than 0xf, VOP will dead at the
851 * * system bandwidth very terrible scene.
852 */
853 static const struct vop2_win_data rk3576_vop_win_data[] = {
854 {
855 .name = "Cluster0-win0",
856 .phys_id = ROCKCHIP_VOP2_CLUSTER0,
857 .base = 0x1000,
858 .possible_vp_mask = BIT(0) | BIT(1),
859 .formats = formats_rk3576_cluster,
860 .nformats = ARRAY_SIZE(formats_rk3576_cluster),
861 .format_modifiers = format_modifiers_rk3576_afbc,
862 .layer_sel_id = { 0, 0, 0xf, 0xf },
863 .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
864 .type = DRM_PLANE_TYPE_PRIMARY,
865 .axi_bus_id = 0,
866 .axi_yrgb_r_id = 0xa,
867 .axi_uv_r_id = 0xb,
868 .max_upscale_factor = 4,
869 .max_downscale_factor = 4,
870 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
871 }, {
872 .name = "Cluster1-win0",
873 .phys_id = ROCKCHIP_VOP2_CLUSTER1,
874 .base = 0x1200,
875 .possible_vp_mask = BIT(0) | BIT(1),
876 .formats = formats_rk3576_cluster,
877 .nformats = ARRAY_SIZE(formats_rk3576_cluster),
878 .format_modifiers = format_modifiers_rk3576_afbc,
879 .layer_sel_id = { 1, 1, 0xf, 0xf },
880 .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
881 .type = DRM_PLANE_TYPE_PRIMARY,
882 .axi_bus_id = 0,
883 .axi_yrgb_r_id = 6,
884 .axi_uv_r_id = 7,
885 .max_upscale_factor = 4,
886 .max_downscale_factor = 4,
887 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
888 }, {
889 .name = "Esmart0-win0",
890 .phys_id = ROCKCHIP_VOP2_ESMART0,
891 .base = 0x1800,
892 .possible_vp_mask = BIT(0) | BIT(2),
893 .formats = formats_rk3576_esmart,
894 .nformats = ARRAY_SIZE(formats_rk3576_esmart),
895 .format_modifiers = format_modifiers,
896 .layer_sel_id = { 2, 0xf, 0, 0xf },
897 .supported_rotations = DRM_MODE_REFLECT_Y,
898 .type = DRM_PLANE_TYPE_OVERLAY,
899 .axi_bus_id = 0,
900 .axi_yrgb_r_id = 0x10,
901 .axi_uv_r_id = 0x11,
902 .max_upscale_factor = 8,
903 .max_downscale_factor = 8,
904 }, {
905 .name = "Esmart1-win0",
906 .phys_id = ROCKCHIP_VOP2_ESMART1,
907 .base = 0x1a00,
908 .possible_vp_mask = BIT(1) | BIT(2),
909 .formats = formats_rk3576_esmart,
910 .nformats = ARRAY_SIZE(formats_rk3576_esmart),
911 .format_modifiers = format_modifiers,
912 .layer_sel_id = { 0xf, 2, 1, 0xf },
913 .supported_rotations = DRM_MODE_REFLECT_Y,
914 .type = DRM_PLANE_TYPE_OVERLAY,
915 .axi_bus_id = 0,
916 .axi_yrgb_r_id = 0x12,
917 .axi_uv_r_id = 0x13,
918 .max_upscale_factor = 8,
919 .max_downscale_factor = 8,
920 }, {
921 .name = "Esmart2-win0",
922 .phys_id = ROCKCHIP_VOP2_ESMART2,
923 .base = 0x1c00,
924 .possible_vp_mask = BIT(0) | BIT(2),
925 .formats = formats_rk3576_esmart,
926 .nformats = ARRAY_SIZE(formats_rk3576_esmart),
927 .format_modifiers = format_modifiers,
928 .layer_sel_id = { 3, 0xf, 2, 0xf },
929 .supported_rotations = DRM_MODE_REFLECT_Y,
930 .type = DRM_PLANE_TYPE_OVERLAY,
931 .axi_bus_id = 1,
932 .axi_yrgb_r_id = 0x0a,
933 .axi_uv_r_id = 0x0b,
934 .max_upscale_factor = 8,
935 .max_downscale_factor = 8,
936 }, {
937 .name = "Esmart3-win0",
938 .phys_id = ROCKCHIP_VOP2_ESMART3,
939 .base = 0x1e00,
940 .possible_vp_mask = BIT(1) | BIT(2),
941 .formats = formats_rk3576_esmart,
942 .nformats = ARRAY_SIZE(formats_rk3576_esmart),
943 .format_modifiers = format_modifiers,
944 .layer_sel_id = { 0xf, 3, 3, 0xf },
945 .supported_rotations = DRM_MODE_REFLECT_Y,
946 .type = DRM_PLANE_TYPE_OVERLAY,
947 .axi_bus_id = 1,
948 .axi_yrgb_r_id = 0x0c,
949 .axi_uv_r_id = 0x0d,
950 .max_upscale_factor = 8,
951 .max_downscale_factor = 8,
952 },
953 };
954
955 static const struct vop2_regs_dump rk3576_regs_dump[] = {
956 {
957 .name = "SYS",
958 .base = RK3568_REG_CFG_DONE,
959 .size = 0x200,
960 .en_reg = 0,
961 .en_val = 0,
962 .en_mask = 0
963 }, {
964 .name = "OVL_SYS",
965 .base = RK3576_SYS_EXTRA_ALPHA_CTRL,
966 .size = 0x50,
967 .en_reg = 0,
968 .en_val = 0,
969 .en_mask = 0,
970 }, {
971 .name = "OVL_VP0",
972 .base = RK3576_OVL_CTRL(0),
973 .size = 0x80,
974 .en_reg = 0,
975 .en_val = 0,
976 .en_mask = 0,
977 }, {
978 .name = "OVL_VP1",
979 .base = RK3576_OVL_CTRL(1),
980 .size = 0x80,
981 .en_reg = 0,
982 .en_val = 0,
983 .en_mask = 0,
984 }, {
985 .name = "OVL_VP2",
986 .base = RK3576_OVL_CTRL(2),
987 .size = 0x80,
988 .en_reg = 0,
989 .en_val = 0,
990 .en_mask = 0,
991 }, {
992 .name = "VP0",
993 .base = RK3568_VP0_CTRL_BASE,
994 .size = 0x100,
995 .en_reg = RK3568_VP_DSP_CTRL,
996 .en_val = 0,
997 .en_mask = RK3568_VP_DSP_CTRL__STANDBY,
998 }, {
999 .name = "VP1",
1000 .base = RK3568_VP1_CTRL_BASE,
1001 .size = 0x100,
1002 .en_reg = RK3568_VP_DSP_CTRL,
1003 .en_val = 0,
1004 .en_mask = RK3568_VP_DSP_CTRL__STANDBY,
1005 }, {
1006 .name = "VP2",
1007 .base = RK3568_VP2_CTRL_BASE,
1008 .size = 0x100,
1009 .en_reg = RK3568_VP_DSP_CTRL,
1010 .en_val = 0,
1011 .en_mask = RK3568_VP_DSP_CTRL__STANDBY,
1012 }, {
1013 .name = "Cluster0",
1014 .base = RK3568_CLUSTER0_CTRL_BASE,
1015 .size = 0x200,
1016 .en_reg = RK3568_CLUSTER_WIN_CTRL0,
1017 .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1018 .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1019 }, {
1020 .name = "Cluster1",
1021 .base = RK3568_CLUSTER1_CTRL_BASE,
1022 .size = 0x200,
1023 .en_reg = RK3568_CLUSTER_WIN_CTRL0,
1024 .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1025 .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1026 }, {
1027 .name = "Esmart0",
1028 .base = RK3568_ESMART0_CTRL_BASE,
1029 .size = 0xf0,
1030 .en_reg = RK3568_SMART_REGION0_CTRL,
1031 .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1032 .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1033 }, {
1034 .name = "Esmart1",
1035 .base = RK3568_ESMART1_CTRL_BASE,
1036 .size = 0xf0,
1037 .en_reg = RK3568_SMART_REGION0_CTRL,
1038 .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1039 .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1040 }, {
1041 .name = "Esmart2",
1042 .base = RK3588_ESMART2_CTRL_BASE,
1043 .size = 0xf0,
1044 .en_reg = RK3568_SMART_REGION0_CTRL,
1045 .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1046 .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1047 }, {
1048 .name = "Esmart3",
1049 .base = RK3588_ESMART3_CTRL_BASE,
1050 .size = 0xf0,
1051 .en_reg = RK3568_SMART_REGION0_CTRL,
1052 .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1053 .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1054 },
1055 };
1056
1057 static const struct vop2_video_port_data rk3588_vop_video_ports[] = {
1058 {
1059 .id = 0,
1060 .feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
1061 .gamma_lut_len = 1024,
1062 .cubic_lut_len = 9 * 9 * 9, /* 9x9x9 */
1063 .max_output = { 4096, 2304 },
1064 /* hdr2sdr sdr2hdr hdr2hdr sdr2sdr */
1065 .pre_scan_max_dly = { 76, 65, 65, 54 },
1066 .offset = 0xc00,
1067 }, {
1068 .id = 1,
1069 .feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
1070 .gamma_lut_len = 1024,
1071 .cubic_lut_len = 729, /* 9x9x9 */
1072 .max_output = { 4096, 2304 },
1073 .pre_scan_max_dly = { 76, 65, 65, 54 },
1074 .offset = 0xd00,
1075 }, {
1076 .id = 2,
1077 .feature = VOP2_VP_FEATURE_OUTPUT_10BIT,
1078 .gamma_lut_len = 1024,
1079 .cubic_lut_len = 17 * 17 * 17, /* 17x17x17 */
1080 .max_output = { 4096, 2304 },
1081 .pre_scan_max_dly = { 52, 52, 52, 52 },
1082 .offset = 0xe00,
1083 }, {
1084 .id = 3,
1085 .gamma_lut_len = 1024,
1086 .max_output = { 2048, 1536 },
1087 .pre_scan_max_dly = { 52, 52, 52, 52 },
1088 .offset = 0xf00,
1089 },
1090 };
1091
1092 /*
1093 * rk3588 vop with 4 cluster, 4 esmart win.
1094 * Every cluster can work as 4K win or split into two win.
1095 * All win in cluster support AFBCD.
1096 *
1097 * Every esmart win and smart win support 4 Multi-region.
1098 *
1099 * Scale filter mode:
1100 *
1101 * * Cluster: bicubic for horizontal scale up, others use bilinear
1102 * * ESmart:
1103 * * nearest-neighbor/bilinear/bicubic for scale up
1104 * * nearest-neighbor/bilinear/average for scale down
1105 *
1106 * AXI Read ID assignment:
1107 * Two AXI bus:
1108 * AXI0 is a read/write bus with a higher performance.
1109 * AXI1 is a read only bus.
1110 *
1111 * Every window on a AXI bus must assigned two unique
1112 * read id(yrgb_r_id/uv_r_id, valid id are 0x1~0xe).
1113 *
1114 * AXI0:
1115 * Cluster0/1, Esmart0/1, WriteBack
1116 *
1117 * AXI 1:
1118 * Cluster2/3, Esmart2/3
1119 *
1120 */
1121 static const struct vop2_win_data rk3588_vop_win_data[] = {
1122 {
1123 .name = "Cluster0-win0",
1124 .phys_id = ROCKCHIP_VOP2_CLUSTER0,
1125 .base = 0x1000,
1126 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1127 .formats = formats_cluster,
1128 .nformats = ARRAY_SIZE(formats_cluster),
1129 .format_modifiers = format_modifiers_afbc,
1130 .layer_sel_id = { 0, 0, 0, 0 },
1131 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
1132 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
1133 .axi_bus_id = 0,
1134 .axi_yrgb_r_id = 2,
1135 .axi_uv_r_id = 3,
1136 .max_upscale_factor = 4,
1137 .max_downscale_factor = 4,
1138 .dly = { 4, 26, 29 },
1139 .type = DRM_PLANE_TYPE_PRIMARY,
1140 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
1141 }, {
1142 .name = "Cluster1-win0",
1143 .phys_id = ROCKCHIP_VOP2_CLUSTER1,
1144 .base = 0x1200,
1145 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1146 .formats = formats_cluster,
1147 .nformats = ARRAY_SIZE(formats_cluster),
1148 .format_modifiers = format_modifiers_afbc,
1149 .layer_sel_id = { 1, 1, 1, 1 },
1150 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
1151 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
1152 .type = DRM_PLANE_TYPE_PRIMARY,
1153 .axi_bus_id = 0,
1154 .axi_yrgb_r_id = 6,
1155 .axi_uv_r_id = 7,
1156 .max_upscale_factor = 4,
1157 .max_downscale_factor = 4,
1158 .dly = { 4, 26, 29 },
1159 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
1160 }, {
1161 .name = "Cluster2-win0",
1162 .phys_id = ROCKCHIP_VOP2_CLUSTER2,
1163 .base = 0x1400,
1164 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1165 .formats = formats_cluster,
1166 .nformats = ARRAY_SIZE(formats_cluster),
1167 .format_modifiers = format_modifiers_afbc,
1168 .layer_sel_id = { 4, 4, 4, 4 },
1169 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
1170 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
1171 .type = DRM_PLANE_TYPE_PRIMARY,
1172 .axi_bus_id = 1,
1173 .axi_yrgb_r_id = 2,
1174 .axi_uv_r_id = 3,
1175 .max_upscale_factor = 4,
1176 .max_downscale_factor = 4,
1177 .dly = { 4, 26, 29 },
1178 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
1179 }, {
1180 .name = "Cluster3-win0",
1181 .phys_id = ROCKCHIP_VOP2_CLUSTER3,
1182 .base = 0x1600,
1183 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1184 .formats = formats_cluster,
1185 .nformats = ARRAY_SIZE(formats_cluster),
1186 .format_modifiers = format_modifiers_afbc,
1187 .layer_sel_id = { 5, 5, 5, 5 },
1188 .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
1189 DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
1190 .type = DRM_PLANE_TYPE_PRIMARY,
1191 .axi_bus_id = 1,
1192 .axi_yrgb_r_id = 6,
1193 .axi_uv_r_id = 7,
1194 .max_upscale_factor = 4,
1195 .max_downscale_factor = 4,
1196 .dly = { 4, 26, 29 },
1197 .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER,
1198 }, {
1199 .name = "Esmart0-win0",
1200 .phys_id = ROCKCHIP_VOP2_ESMART0,
1201 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1202 .formats = formats_esmart,
1203 .nformats = ARRAY_SIZE(formats_esmart),
1204 .format_modifiers = format_modifiers,
1205 .base = 0x1800,
1206 .layer_sel_id = { 2, 2, 2, 2 },
1207 .supported_rotations = DRM_MODE_REFLECT_Y,
1208 .type = DRM_PLANE_TYPE_OVERLAY,
1209 .axi_bus_id = 0,
1210 .axi_yrgb_r_id = 0x0a,
1211 .axi_uv_r_id = 0x0b,
1212 .max_upscale_factor = 8,
1213 .max_downscale_factor = 8,
1214 .dly = { 23, 45, 48 },
1215 }, {
1216 .name = "Esmart1-win0",
1217 .phys_id = ROCKCHIP_VOP2_ESMART1,
1218 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1219 .formats = formats_esmart,
1220 .nformats = ARRAY_SIZE(formats_esmart),
1221 .format_modifiers = format_modifiers,
1222 .base = 0x1a00,
1223 .layer_sel_id = { 3, 3, 3, 3 },
1224 .supported_rotations = DRM_MODE_REFLECT_Y,
1225 .type = DRM_PLANE_TYPE_OVERLAY,
1226 .axi_bus_id = 0,
1227 .axi_yrgb_r_id = 0x0c,
1228 .axi_uv_r_id = 0x01,
1229 .max_upscale_factor = 8,
1230 .max_downscale_factor = 8,
1231 .dly = { 23, 45, 48 },
1232 }, {
1233 .name = "Esmart2-win0",
1234 .phys_id = ROCKCHIP_VOP2_ESMART2,
1235 .base = 0x1c00,
1236 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1237 .formats = formats_esmart,
1238 .nformats = ARRAY_SIZE(formats_esmart),
1239 .format_modifiers = format_modifiers,
1240 .layer_sel_id = { 6, 6, 6, 6 },
1241 .supported_rotations = DRM_MODE_REFLECT_Y,
1242 .type = DRM_PLANE_TYPE_OVERLAY,
1243 .axi_bus_id = 1,
1244 .axi_yrgb_r_id = 0x0a,
1245 .axi_uv_r_id = 0x0b,
1246 .max_upscale_factor = 8,
1247 .max_downscale_factor = 8,
1248 .dly = { 23, 45, 48 },
1249 }, {
1250 .name = "Esmart3-win0",
1251 .phys_id = ROCKCHIP_VOP2_ESMART3,
1252 .possible_vp_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
1253 .formats = formats_esmart,
1254 .nformats = ARRAY_SIZE(formats_esmart),
1255 .format_modifiers = format_modifiers,
1256 .base = 0x1e00,
1257 .layer_sel_id = { 7, 7, 7, 7 },
1258 .supported_rotations = DRM_MODE_REFLECT_Y,
1259 .type = DRM_PLANE_TYPE_OVERLAY,
1260 .axi_bus_id = 1,
1261 .axi_yrgb_r_id = 0x0c,
1262 .axi_uv_r_id = 0x0d,
1263 .max_upscale_factor = 8,
1264 .max_downscale_factor = 8,
1265 .dly = { 23, 45, 48 },
1266 },
1267 };
1268
1269 static const struct vop2_regs_dump rk3588_regs_dump[] = {
1270 {
1271 .name = "SYS",
1272 .base = RK3568_REG_CFG_DONE,
1273 .size = 0x100,
1274 .en_reg = 0,
1275 .en_val = 0,
1276 .en_mask = 0
1277 }, {
1278 .name = "OVL",
1279 .base = RK3568_OVL_CTRL,
1280 .size = 0x100,
1281 .en_reg = 0,
1282 .en_val = 0,
1283 .en_mask = 0,
1284 }, {
1285 .name = "VP0",
1286 .base = RK3568_VP0_CTRL_BASE,
1287 .size = 0x100,
1288 .en_reg = RK3568_VP_DSP_CTRL,
1289 .en_val = 0,
1290 .en_mask = RK3568_VP_DSP_CTRL__STANDBY,
1291 }, {
1292 .name = "VP1",
1293 .base = RK3568_VP1_CTRL_BASE,
1294 .size = 0x100,
1295 .en_reg = RK3568_VP_DSP_CTRL,
1296 .en_val = 0,
1297 .en_mask = RK3568_VP_DSP_CTRL__STANDBY,
1298 }, {
1299 .name = "VP2",
1300 .base = RK3568_VP2_CTRL_BASE,
1301 .size = 0x100,
1302 .en_reg = RK3568_VP_DSP_CTRL,
1303 .en_val = 0,
1304 .en_mask = RK3568_VP_DSP_CTRL__STANDBY,
1305
1306 }, {
1307 .name = "VP3",
1308 .base = RK3588_VP3_CTRL_BASE,
1309 .size = 0x100,
1310 .en_reg = RK3568_VP_DSP_CTRL,
1311 .en_val = 0,
1312 .en_mask = RK3568_VP_DSP_CTRL__STANDBY,
1313 }, {
1314 .name = "Cluster0",
1315 .base = RK3568_CLUSTER0_CTRL_BASE,
1316 .size = 0x110,
1317 .en_reg = RK3568_CLUSTER_WIN_CTRL0,
1318 .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1319 .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1320 }, {
1321 .name = "Cluster1",
1322 .base = RK3568_CLUSTER1_CTRL_BASE,
1323 .size = 0x110,
1324 .en_reg = RK3568_CLUSTER_WIN_CTRL0,
1325 .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1326 .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1327 }, {
1328 .name = "Cluster2",
1329 .base = RK3588_CLUSTER2_CTRL_BASE,
1330 .size = 0x110,
1331 .en_reg = RK3568_CLUSTER_WIN_CTRL0,
1332 .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1333 .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1334 }, {
1335 .name = "Cluster3",
1336 .base = RK3588_CLUSTER3_CTRL_BASE,
1337 .size = 0x110,
1338 .en_reg = RK3568_CLUSTER_WIN_CTRL0,
1339 .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1340 .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN,
1341 }, {
1342 .name = "Esmart0",
1343 .base = RK3568_ESMART0_CTRL_BASE,
1344 .size = 0xf0,
1345 .en_reg = RK3568_SMART_REGION0_CTRL,
1346 .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1347 .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1348 }, {
1349 .name = "Esmart1",
1350 .base = RK3568_ESMART1_CTRL_BASE,
1351 .size = 0xf0,
1352 .en_reg = RK3568_SMART_REGION0_CTRL,
1353 .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1354 .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1355 }, {
1356 .name = "Esmart2",
1357 .base = RK3588_ESMART2_CTRL_BASE,
1358 .size = 0xf0,
1359 .en_reg = RK3568_SMART_REGION0_CTRL,
1360 .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1361 .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1362 }, {
1363 .name = "Esmart3",
1364 .base = RK3588_ESMART3_CTRL_BASE,
1365 .size = 0xf0,
1366 .en_reg = RK3568_SMART_REGION0_CTRL,
1367 .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1368 .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN,
1369 },
1370 };
1371
1372 /*
1373 * phys_id is used to identify a main window(Cluster Win/Smart Win, not
1374 * include the sub win of a cluster or the multi area) that can do overlay
1375 * in main overlay stage.
1376 */
vop2_find_win_by_phys_id(struct vop2 * vop2,uint8_t phys_id)1377 static struct vop2_win *vop2_find_win_by_phys_id(struct vop2 *vop2, uint8_t phys_id)
1378 {
1379 struct vop2_win *win;
1380 int i;
1381
1382 for (i = 0; i < vop2->data->win_size; i++) {
1383 win = &vop2->win[i];
1384 if (win->data->phys_id == phys_id)
1385 return win;
1386 }
1387
1388 return NULL;
1389 }
1390
rk3568_set_intf_mux(struct vop2_video_port * vp,int id,u32 polflags)1391 static unsigned long rk3568_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags)
1392 {
1393 struct vop2 *vop2 = vp->vop2;
1394 struct drm_crtc *crtc = &vp->crtc;
1395 u32 die, dip;
1396
1397 die = vop2_readl(vop2, RK3568_DSP_IF_EN);
1398 dip = vop2_readl(vop2, RK3568_DSP_IF_POL);
1399
1400 switch (id) {
1401 case ROCKCHIP_VOP2_EP_RGB0:
1402 die &= ~RK3568_SYS_DSP_INFACE_EN_RGB_MUX;
1403 die |= RK3568_SYS_DSP_INFACE_EN_RGB |
1404 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_RGB_MUX, vp->id);
1405 dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL;
1406 dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags);
1407 if (polflags & POLFLAG_DCLK_INV)
1408 regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3));
1409 else
1410 regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16));
1411 break;
1412 case ROCKCHIP_VOP2_EP_HDMI0:
1413 die &= ~RK3568_SYS_DSP_INFACE_EN_HDMI_MUX;
1414 die |= RK3568_SYS_DSP_INFACE_EN_HDMI |
1415 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id);
1416 dip &= ~RK3568_DSP_IF_POL__HDMI_PIN_POL;
1417 dip |= FIELD_PREP(RK3568_DSP_IF_POL__HDMI_PIN_POL, polflags);
1418 break;
1419 case ROCKCHIP_VOP2_EP_EDP0:
1420 die &= ~RK3568_SYS_DSP_INFACE_EN_EDP_MUX;
1421 die |= RK3568_SYS_DSP_INFACE_EN_EDP |
1422 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id);
1423 dip &= ~RK3568_DSP_IF_POL__EDP_PIN_POL;
1424 dip |= FIELD_PREP(RK3568_DSP_IF_POL__EDP_PIN_POL, polflags);
1425 break;
1426 case ROCKCHIP_VOP2_EP_MIPI0:
1427 die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX;
1428 die |= RK3568_SYS_DSP_INFACE_EN_MIPI0 |
1429 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX, vp->id);
1430 dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL;
1431 dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags);
1432 break;
1433 case ROCKCHIP_VOP2_EP_MIPI1:
1434 die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX;
1435 die |= RK3568_SYS_DSP_INFACE_EN_MIPI1 |
1436 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id);
1437 dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL;
1438 dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags);
1439 break;
1440 case ROCKCHIP_VOP2_EP_LVDS0:
1441 die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX;
1442 die |= RK3568_SYS_DSP_INFACE_EN_LVDS0 |
1443 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX, vp->id);
1444 dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL;
1445 dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags);
1446 break;
1447 case ROCKCHIP_VOP2_EP_LVDS1:
1448 die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX;
1449 die |= RK3568_SYS_DSP_INFACE_EN_LVDS1 |
1450 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX, vp->id);
1451 dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL;
1452 dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags);
1453 break;
1454 default:
1455 drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id);
1456 return 0;
1457 }
1458
1459 dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD;
1460
1461 vop2_writel(vop2, RK3568_DSP_IF_EN, die);
1462 vop2_writel(vop2, RK3568_DSP_IF_POL, dip);
1463
1464 return crtc->state->adjusted_mode.crtc_clock * 1000LL;
1465 }
1466
rk3576_set_intf_mux(struct vop2_video_port * vp,int id,u32 polflags)1467 static unsigned long rk3576_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags)
1468 {
1469 struct vop2 *vop2 = vp->vop2;
1470 struct drm_crtc *crtc = &vp->crtc;
1471 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
1472 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
1473 u8 port_pix_rate = vp->data->pixel_rate;
1474 int dclk_core_div, dclk_out_div, if_pixclk_div, if_dclk_sel;
1475 u32 ctrl, vp_clk_div, reg, dclk_div;
1476 unsigned long dclk_in_rate, dclk_core_rate;
1477
1478 if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420 || adjusted_mode->crtc_clock > 600000)
1479 dclk_div = 2;
1480 else
1481 dclk_div = 1;
1482
1483 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
1484 dclk_core_rate = adjusted_mode->crtc_clock / 2;
1485 else
1486 dclk_core_rate = adjusted_mode->crtc_clock / port_pix_rate;
1487
1488 dclk_in_rate = adjusted_mode->crtc_clock / dclk_div;
1489
1490 dclk_core_div = dclk_in_rate > dclk_core_rate ? 1 : 0;
1491
1492 if (vop2_output_if_is_edp(id))
1493 if_pixclk_div = port_pix_rate == 2 ? RK3576_DSP_IF_PCLK_DIV : 0;
1494 else
1495 if_pixclk_div = port_pix_rate == 1 ? RK3576_DSP_IF_PCLK_DIV : 0;
1496
1497 if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
1498 if_dclk_sel = RK3576_DSP_IF_DCLK_SEL_OUT;
1499 dclk_out_div = 1;
1500 } else {
1501 if_dclk_sel = 0;
1502 dclk_out_div = 0;
1503 }
1504
1505 switch (id) {
1506 case ROCKCHIP_VOP2_EP_HDMI0:
1507 reg = RK3576_HDMI0_IF_CTRL;
1508 break;
1509 case ROCKCHIP_VOP2_EP_EDP0:
1510 reg = RK3576_EDP0_IF_CTRL;
1511 break;
1512 case ROCKCHIP_VOP2_EP_MIPI0:
1513 reg = RK3576_MIPI0_IF_CTRL;
1514 break;
1515 case ROCKCHIP_VOP2_EP_DP0:
1516 reg = RK3576_DP0_IF_CTRL;
1517 break;
1518 case ROCKCHIP_VOP2_EP_DP1:
1519 reg = RK3576_DP1_IF_CTRL;
1520 break;
1521 default:
1522 drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id);
1523 return 0;
1524 }
1525
1526 ctrl = vop2_readl(vop2, reg);
1527 ctrl &= ~RK3576_DSP_IF_DCLK_SEL_OUT;
1528 ctrl &= ~RK3576_DSP_IF_PCLK_DIV;
1529 ctrl &= ~RK3576_DSP_IF_MUX;
1530 ctrl |= RK3576_DSP_IF_CFG_DONE_IMD;
1531 ctrl |= if_dclk_sel | if_pixclk_div;
1532 ctrl |= RK3576_DSP_IF_CLK_OUT_EN | RK3576_DSP_IF_EN;
1533 ctrl |= FIELD_PREP(RK3576_DSP_IF_MUX, vp->id);
1534 ctrl |= FIELD_PREP(RK3576_DSP_IF_PIN_POL, polflags);
1535 vop2_writel(vop2, reg, ctrl);
1536
1537 vp_clk_div = FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_CORE_DIV, dclk_core_div);
1538 vp_clk_div |= FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_OUT_DIV, dclk_out_div);
1539
1540 vop2_vp_write(vp, RK3588_VP_CLK_CTRL, vp_clk_div);
1541
1542 return dclk_in_rate * 1000LL;
1543 }
1544
1545 /*
1546 * calc the dclk on rk3588
1547 * the available div of dclk is 1, 2, 4
1548 */
rk3588_calc_dclk(unsigned long child_clk,unsigned long max_dclk)1549 static unsigned long rk3588_calc_dclk(unsigned long child_clk, unsigned long max_dclk)
1550 {
1551 if (child_clk * 4 <= max_dclk)
1552 return child_clk * 4;
1553 else if (child_clk * 2 <= max_dclk)
1554 return child_clk * 2;
1555 else if (child_clk <= max_dclk)
1556 return child_clk;
1557 else
1558 return 0;
1559 }
1560
1561 /*
1562 * 4 pixclk/cycle on rk3588
1563 * RGB/eDP/HDMI: if_pixclk >= dclk_core
1564 * DP: dp_pixclk = dclk_out <= dclk_core
1565 * DSI: mipi_pixclk <= dclk_out <= dclk_core
1566 */
rk3588_calc_cru_cfg(struct vop2_video_port * vp,int id,int * dclk_core_div,int * dclk_out_div,int * if_pixclk_div,int * if_dclk_div)1567 static unsigned long rk3588_calc_cru_cfg(struct vop2_video_port *vp, int id,
1568 int *dclk_core_div, int *dclk_out_div,
1569 int *if_pixclk_div, int *if_dclk_div)
1570 {
1571 struct vop2 *vop2 = vp->vop2;
1572 struct drm_crtc *crtc = &vp->crtc;
1573 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
1574 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
1575 int output_mode = vcstate->output_mode;
1576 unsigned long v_pixclk = adjusted_mode->crtc_clock * 1000LL; /* video timing pixclk */
1577 unsigned long dclk_core_rate = v_pixclk >> 2;
1578 unsigned long dclk_rate = v_pixclk;
1579 unsigned long dclk_out_rate;
1580 unsigned long if_pixclk_rate;
1581 int K = 1;
1582
1583 if (vop2_output_if_is_hdmi(id)) {
1584 /*
1585 * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate
1586 * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate
1587 */
1588 if (output_mode == ROCKCHIP_OUT_MODE_YUV420) {
1589 dclk_rate = dclk_rate >> 1;
1590 K = 2;
1591 }
1592
1593 /*
1594 * if_pixclk_rate = (dclk_core_rate << 1) / K;
1595 * if_dclk_rate = dclk_core_rate / K;
1596 * *if_pixclk_div = dclk_rate / if_pixclk_rate;
1597 * *if_dclk_div = dclk_rate / if_dclk_rate;
1598 */
1599 *if_pixclk_div = 2;
1600 *if_dclk_div = 4;
1601 } else if (vop2_output_if_is_edp(id)) {
1602 /*
1603 * edp_pixclk = edp_dclk > dclk_core
1604 */
1605 if_pixclk_rate = v_pixclk / K;
1606 dclk_rate = if_pixclk_rate * K;
1607 /*
1608 * *if_pixclk_div = dclk_rate / if_pixclk_rate;
1609 * *if_dclk_div = *if_pixclk_div;
1610 */
1611 *if_pixclk_div = K;
1612 *if_dclk_div = K;
1613 } else if (vop2_output_if_is_dp(id)) {
1614 if (output_mode == ROCKCHIP_OUT_MODE_YUV420)
1615 dclk_out_rate = v_pixclk >> 3;
1616 else
1617 dclk_out_rate = v_pixclk >> 2;
1618
1619 dclk_rate = rk3588_calc_dclk(dclk_out_rate, 600000000);
1620 if (!dclk_rate) {
1621 drm_err(vop2->drm, "DP dclk_out_rate out of range, dclk_out_rate: %ld Hz\n",
1622 dclk_out_rate);
1623 return 0;
1624 }
1625 *dclk_out_div = dclk_rate / dclk_out_rate;
1626 } else if (vop2_output_if_is_mipi(id)) {
1627 if_pixclk_rate = dclk_core_rate / K;
1628 /*
1629 * dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4
1630 */
1631 dclk_out_rate = if_pixclk_rate;
1632 /*
1633 * dclk_rate = N * dclk_core_rate N = (1,2,4 ),
1634 * we get a little factor here
1635 */
1636 dclk_rate = rk3588_calc_dclk(dclk_out_rate, 600000000);
1637 if (!dclk_rate) {
1638 drm_err(vop2->drm, "MIPI dclk out of range, dclk_out_rate: %ld Hz\n",
1639 dclk_out_rate);
1640 return 0;
1641 }
1642 *dclk_out_div = dclk_rate / dclk_out_rate;
1643 /*
1644 * mipi pixclk == dclk_out
1645 */
1646 *if_pixclk_div = 1;
1647 } else if (vop2_output_if_is_dpi(id)) {
1648 dclk_rate = v_pixclk;
1649 }
1650
1651 *dclk_core_div = dclk_rate / dclk_core_rate;
1652 *if_pixclk_div = ilog2(*if_pixclk_div);
1653 *if_dclk_div = ilog2(*if_dclk_div);
1654 *dclk_core_div = ilog2(*dclk_core_div);
1655 *dclk_out_div = ilog2(*dclk_out_div);
1656
1657 drm_dbg(vop2->drm, "dclk: %ld, pixclk_div: %d, dclk_div: %d\n",
1658 dclk_rate, *if_pixclk_div, *if_dclk_div);
1659
1660 return dclk_rate;
1661 }
1662
1663 /*
1664 * MIPI port mux on rk3588:
1665 * 0: Video Port2
1666 * 1: Video Port3
1667 * 3: Video Port 1(MIPI1 only)
1668 */
rk3588_get_mipi_port_mux(int vp_id)1669 static u32 rk3588_get_mipi_port_mux(int vp_id)
1670 {
1671 if (vp_id == 1)
1672 return 3;
1673 else if (vp_id == 3)
1674 return 1;
1675 else
1676 return 0;
1677 }
1678
rk3588_get_hdmi_pol(u32 flags)1679 static u32 rk3588_get_hdmi_pol(u32 flags)
1680 {
1681 u32 val;
1682
1683 val = (flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0;
1684 val |= (flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0;
1685
1686 return val;
1687 }
1688
rk3588_set_intf_mux(struct vop2_video_port * vp,int id,u32 polflags)1689 static unsigned long rk3588_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags)
1690 {
1691 struct vop2 *vop2 = vp->vop2;
1692 int dclk_core_div, dclk_out_div, if_pixclk_div, if_dclk_div;
1693 unsigned long clock;
1694 u32 die, dip, div, vp_clk_div, val;
1695
1696 clock = rk3588_calc_cru_cfg(vp, id, &dclk_core_div, &dclk_out_div,
1697 &if_pixclk_div, &if_dclk_div);
1698 if (!clock)
1699 return 0;
1700
1701 vp_clk_div = FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_CORE_DIV, dclk_core_div);
1702 vp_clk_div |= FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_OUT_DIV, dclk_out_div);
1703
1704 die = vop2_readl(vop2, RK3568_DSP_IF_EN);
1705 dip = vop2_readl(vop2, RK3568_DSP_IF_POL);
1706 div = vop2_readl(vop2, RK3568_DSP_IF_CTRL);
1707
1708 switch (id) {
1709 case ROCKCHIP_VOP2_EP_HDMI0:
1710 div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV;
1711 div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV;
1712 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div);
1713 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div);
1714 die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX;
1715 die |= RK3588_SYS_DSP_INFACE_EN_HDMI0 |
1716 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id);
1717 val = rk3588_get_hdmi_pol(polflags);
1718 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(1), 1));
1719 regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0,
1720 FIELD_PREP_WM16(GENMASK(6, 5), val));
1721 break;
1722 case ROCKCHIP_VOP2_EP_HDMI1:
1723 div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV;
1724 div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV;
1725 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV, if_dclk_div);
1726 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV, if_pixclk_div);
1727 die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX;
1728 die |= RK3588_SYS_DSP_INFACE_EN_HDMI1 |
1729 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id);
1730 val = rk3588_get_hdmi_pol(polflags);
1731 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(4), 1));
1732 regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0,
1733 FIELD_PREP_WM16(GENMASK(8, 7), val));
1734 break;
1735 case ROCKCHIP_VOP2_EP_EDP0:
1736 div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV;
1737 div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV;
1738 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div);
1739 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div);
1740 die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX;
1741 die |= RK3588_SYS_DSP_INFACE_EN_EDP0 |
1742 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id);
1743 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(0), 1));
1744 break;
1745 case ROCKCHIP_VOP2_EP_EDP1:
1746 div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV;
1747 div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV;
1748 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div);
1749 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div);
1750 die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX;
1751 die |= RK3588_SYS_DSP_INFACE_EN_EDP1 |
1752 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id);
1753 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(3), 1));
1754 break;
1755 case ROCKCHIP_VOP2_EP_MIPI0:
1756 div &= ~RK3588_DSP_IF_MIPI0_PCLK_DIV;
1757 div |= FIELD_PREP(RK3588_DSP_IF_MIPI0_PCLK_DIV, if_pixclk_div);
1758 die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX;
1759 val = rk3588_get_mipi_port_mux(vp->id);
1760 die |= RK3588_SYS_DSP_INFACE_EN_MIPI0 |
1761 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX, !!val);
1762 break;
1763 case ROCKCHIP_VOP2_EP_MIPI1:
1764 div &= ~RK3588_DSP_IF_MIPI1_PCLK_DIV;
1765 div |= FIELD_PREP(RK3588_DSP_IF_MIPI1_PCLK_DIV, if_pixclk_div);
1766 die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX;
1767 val = rk3588_get_mipi_port_mux(vp->id);
1768 die |= RK3588_SYS_DSP_INFACE_EN_MIPI1 |
1769 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, val);
1770 break;
1771 case ROCKCHIP_VOP2_EP_DP0:
1772 die &= ~RK3588_SYS_DSP_INFACE_EN_DP0_MUX;
1773 die |= RK3588_SYS_DSP_INFACE_EN_DP0 |
1774 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP0_MUX, vp->id);
1775 dip &= ~RK3588_DSP_IF_POL__DP0_PIN_POL;
1776 dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP0_PIN_POL, polflags);
1777 break;
1778 case ROCKCHIP_VOP2_EP_DP1:
1779 die &= ~RK3588_SYS_DSP_INFACE_EN_DP1_MUX;
1780 die |= RK3588_SYS_DSP_INFACE_EN_DP1 |
1781 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP1_MUX, vp->id);
1782 dip &= ~RK3588_DSP_IF_POL__DP1_PIN_POL;
1783 dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP1_PIN_POL, polflags);
1784 break;
1785 default:
1786 drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id);
1787 return 0;
1788 }
1789
1790 dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD;
1791
1792 vop2_vp_write(vp, RK3588_VP_CLK_CTRL, vp_clk_div);
1793 vop2_writel(vop2, RK3568_DSP_IF_EN, die);
1794 vop2_writel(vop2, RK3568_DSP_IF_CTRL, div);
1795 vop2_writel(vop2, RK3568_DSP_IF_POL, dip);
1796
1797 return clock;
1798 }
1799
is_opaque(u16 alpha)1800 static bool is_opaque(u16 alpha)
1801 {
1802 return (alpha >> 8) == 0xff;
1803 }
1804
vop2_parse_alpha(struct vop2_alpha_config * alpha_config,struct vop2_alpha * alpha)1805 static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config,
1806 struct vop2_alpha *alpha)
1807 {
1808 int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1;
1809 int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1;
1810 int src_color_mode = alpha_config->src_premulti_en ?
1811 ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
1812 int dst_color_mode = alpha_config->dst_premulti_en ?
1813 ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
1814
1815 alpha->src_color_ctrl.val = 0;
1816 alpha->dst_color_ctrl.val = 0;
1817 alpha->src_alpha_ctrl.val = 0;
1818 alpha->dst_alpha_ctrl.val = 0;
1819
1820 if (!alpha_config->src_pixel_alpha_en)
1821 alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
1822 else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en)
1823 alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX;
1824 else
1825 alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
1826
1827 alpha->src_color_ctrl.bits.alpha_en = 1;
1828
1829 if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) {
1830 alpha->src_color_ctrl.bits.color_mode = src_color_mode;
1831 alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
1832 } else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) {
1833 alpha->src_color_ctrl.bits.color_mode = src_color_mode;
1834 alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE;
1835 } else {
1836 alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL;
1837 alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
1838 }
1839 alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8;
1840 alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
1841 alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
1842
1843 alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
1844 alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
1845 alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
1846 alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8;
1847 alpha->dst_color_ctrl.bits.color_mode = dst_color_mode;
1848 alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
1849
1850 alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
1851 alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode;
1852 alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
1853 alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE;
1854
1855 alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
1856 if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en)
1857 alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX;
1858 else
1859 alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
1860 alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION;
1861 alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
1862 }
1863
vop2_find_start_mixer_id_for_vp(struct vop2_video_port * vp)1864 static int vop2_find_start_mixer_id_for_vp(struct vop2_video_port *vp)
1865 {
1866 struct vop2 *vop2 = vp->vop2;
1867 struct vop2_win *win;
1868 u32 layer_sel = vop2->old_layer_sel;
1869 u32 used_layer = 0;
1870 unsigned long win_mask = vp->win_mask;
1871 unsigned long phys_id;
1872 bool match;
1873 int i;
1874
1875 for (i = 0; i < 31; i += 4) {
1876 match = false;
1877 for_each_set_bit(phys_id, &win_mask, ROCKCHIP_VOP2_ESMART3) {
1878 win = vop2_find_win_by_phys_id(vop2, phys_id);
1879 if (win->data->layer_sel_id[vp->id] == ((layer_sel >> i) & 0xf)) {
1880 match = true;
1881 break;
1882 }
1883 }
1884
1885 if (!match)
1886 used_layer += 1;
1887 else
1888 break;
1889 }
1890
1891 return used_layer;
1892 }
1893
vop2_setup_cluster_alpha(struct vop2 * vop2,struct vop2_win * main_win)1894 static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_win)
1895 {
1896 struct vop2_alpha_config alpha_config;
1897 struct vop2_alpha alpha;
1898 struct drm_plane_state *bottom_win_pstate;
1899 bool src_pixel_alpha_en = false;
1900 u16 src_glb_alpha_val, dst_glb_alpha_val;
1901 u32 src_color_ctrl_reg, dst_color_ctrl_reg, src_alpha_ctrl_reg, dst_alpha_ctrl_reg;
1902 u32 offset = 0;
1903 bool premulti_en = false;
1904 bool swap = false;
1905
1906 /* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */
1907 bottom_win_pstate = main_win->base.state;
1908 src_glb_alpha_val = 0;
1909 dst_glb_alpha_val = main_win->base.state->alpha;
1910
1911 if (!bottom_win_pstate->fb)
1912 return;
1913
1914 alpha_config.src_premulti_en = premulti_en;
1915 alpha_config.dst_premulti_en = false;
1916 alpha_config.src_pixel_alpha_en = src_pixel_alpha_en;
1917 alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
1918 alpha_config.src_glb_alpha_value = src_glb_alpha_val;
1919 alpha_config.dst_glb_alpha_value = dst_glb_alpha_val;
1920 vop2_parse_alpha(&alpha_config, &alpha);
1921
1922 alpha.src_color_ctrl.bits.src_dst_swap = swap;
1923
1924 switch (main_win->data->phys_id) {
1925 case ROCKCHIP_VOP2_CLUSTER0:
1926 offset = 0x0;
1927 break;
1928 case ROCKCHIP_VOP2_CLUSTER1:
1929 offset = 0x10;
1930 break;
1931 case ROCKCHIP_VOP2_CLUSTER2:
1932 offset = 0x20;
1933 break;
1934 case ROCKCHIP_VOP2_CLUSTER3:
1935 offset = 0x30;
1936 break;
1937 }
1938
1939 if (vop2->version <= VOP_VERSION_RK3588) {
1940 src_color_ctrl_reg = RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL;
1941 dst_color_ctrl_reg = RK3568_CLUSTER0_MIX_DST_COLOR_CTRL;
1942 src_alpha_ctrl_reg = RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL;
1943 dst_alpha_ctrl_reg = RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL;
1944 } else {
1945 src_color_ctrl_reg = RK3576_CLUSTER0_MIX_SRC_COLOR_CTRL;
1946 dst_color_ctrl_reg = RK3576_CLUSTER0_MIX_DST_COLOR_CTRL;
1947 src_alpha_ctrl_reg = RK3576_CLUSTER0_MIX_SRC_ALPHA_CTRL;
1948 dst_alpha_ctrl_reg = RK3576_CLUSTER0_MIX_DST_ALPHA_CTRL;
1949 }
1950
1951 vop2_writel(vop2, src_color_ctrl_reg + offset, alpha.src_color_ctrl.val);
1952 vop2_writel(vop2, dst_color_ctrl_reg + offset, alpha.dst_color_ctrl.val);
1953 vop2_writel(vop2, src_alpha_ctrl_reg + offset, alpha.src_alpha_ctrl.val);
1954 vop2_writel(vop2, dst_alpha_ctrl_reg + offset, alpha.dst_alpha_ctrl.val);
1955 }
1956
vop2_setup_alpha(struct vop2_video_port * vp)1957 static void vop2_setup_alpha(struct vop2_video_port *vp)
1958 {
1959 struct vop2 *vop2 = vp->vop2;
1960 struct drm_framebuffer *fb;
1961 struct vop2_alpha_config alpha_config;
1962 struct vop2_alpha alpha;
1963 struct drm_plane *plane;
1964 int pixel_alpha_en;
1965 int premulti_en, gpremulti_en = 0;
1966 int mixer_id;
1967 u32 src_color_ctrl_reg, dst_color_ctrl_reg, src_alpha_ctrl_reg, dst_alpha_ctrl_reg;
1968 u32 offset;
1969 bool bottom_layer_alpha_en = false;
1970 u32 dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE;
1971
1972 if (vop2->version <= VOP_VERSION_RK3588)
1973 mixer_id = vop2_find_start_mixer_id_for_vp(vp);
1974 else
1975 mixer_id = 0;
1976
1977 alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
1978
1979 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
1980 struct vop2_win *win = to_vop2_win(plane);
1981
1982 if (plane->state->normalized_zpos == 0 &&
1983 !is_opaque(plane->state->alpha) &&
1984 !vop2_cluster_window(win)) {
1985 /*
1986 * If bottom layer have global alpha effect [except cluster layer,
1987 * because cluster have deal with bottom layer global alpha value
1988 * at cluster mix], bottom layer mix need deal with global alpha.
1989 */
1990 bottom_layer_alpha_en = true;
1991 dst_global_alpha = plane->state->alpha;
1992 }
1993 }
1994
1995 if (vop2->version <= VOP_VERSION_RK3588) {
1996 src_color_ctrl_reg = RK3568_MIX0_SRC_COLOR_CTRL;
1997 dst_color_ctrl_reg = RK3568_MIX0_DST_COLOR_CTRL;
1998 src_alpha_ctrl_reg = RK3568_MIX0_SRC_ALPHA_CTRL;
1999 dst_alpha_ctrl_reg = RK3568_MIX0_DST_ALPHA_CTRL;
2000 } else {
2001 src_color_ctrl_reg = RK3576_OVL_MIX0_SRC_COLOR_CTRL(vp->id);
2002 dst_color_ctrl_reg = RK3576_OVL_MIX0_DST_COLOR_CTRL(vp->id);
2003 src_alpha_ctrl_reg = RK3576_OVL_MIX0_SRC_ALPHA_CTRL(vp->id);
2004 dst_alpha_ctrl_reg = RK3576_OVL_MIX0_DST_ALPHA_CTRL(vp->id);
2005 }
2006
2007 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
2008 struct vop2_win *win = to_vop2_win(plane);
2009 int zpos = plane->state->normalized_zpos;
2010
2011 /*
2012 * Need to configure alpha from second layer.
2013 */
2014 if (zpos == 0)
2015 continue;
2016
2017 if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
2018 premulti_en = 1;
2019 else
2020 premulti_en = 0;
2021
2022 plane = &win->base;
2023 fb = plane->state->fb;
2024
2025 pixel_alpha_en = fb->format->has_alpha;
2026
2027 alpha_config.src_premulti_en = premulti_en;
2028
2029 if (bottom_layer_alpha_en && zpos == 1) {
2030 gpremulti_en = premulti_en;
2031 /* Cd = Cs + (1 - As) * Cd * Agd */
2032 alpha_config.dst_premulti_en = false;
2033 alpha_config.src_pixel_alpha_en = pixel_alpha_en;
2034 alpha_config.src_glb_alpha_value = plane->state->alpha;
2035 alpha_config.dst_glb_alpha_value = dst_global_alpha;
2036 } else if (vop2_cluster_window(win)) {
2037 /* Mix output data only have pixel alpha */
2038 alpha_config.dst_premulti_en = true;
2039 alpha_config.src_pixel_alpha_en = true;
2040 alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
2041 alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
2042 } else {
2043 /* Cd = Cs + (1 - As) * Cd */
2044 alpha_config.dst_premulti_en = true;
2045 alpha_config.src_pixel_alpha_en = pixel_alpha_en;
2046 alpha_config.src_glb_alpha_value = plane->state->alpha;
2047 alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
2048 }
2049
2050 vop2_parse_alpha(&alpha_config, &alpha);
2051
2052 offset = (mixer_id + zpos - 1) * 0x10;
2053
2054 vop2_writel(vop2, src_color_ctrl_reg + offset, alpha.src_color_ctrl.val);
2055 vop2_writel(vop2, dst_color_ctrl_reg + offset, alpha.dst_color_ctrl.val);
2056 vop2_writel(vop2, src_alpha_ctrl_reg + offset, alpha.src_alpha_ctrl.val);
2057 vop2_writel(vop2, dst_alpha_ctrl_reg + offset, alpha.dst_alpha_ctrl.val);
2058 }
2059
2060 if (vp->id == 0) {
2061 if (vop2->version <= VOP_VERSION_RK3588) {
2062 src_color_ctrl_reg = RK3568_HDR0_SRC_COLOR_CTRL;
2063 dst_color_ctrl_reg = RK3568_HDR0_DST_COLOR_CTRL;
2064 src_alpha_ctrl_reg = RK3568_HDR0_SRC_ALPHA_CTRL;
2065 dst_alpha_ctrl_reg = RK3568_HDR0_DST_ALPHA_CTRL;
2066 } else {
2067 src_color_ctrl_reg = RK3576_OVL_HDR_SRC_COLOR_CTRL(vp->id);
2068 dst_color_ctrl_reg = RK3576_OVL_HDR_DST_COLOR_CTRL(vp->id);
2069 src_alpha_ctrl_reg = RK3576_OVL_HDR_SRC_ALPHA_CTRL(vp->id);
2070 dst_alpha_ctrl_reg = RK3576_OVL_HDR_DST_ALPHA_CTRL(vp->id);
2071 }
2072
2073 if (bottom_layer_alpha_en) {
2074 /* Transfer pixel alpha to hdr mix */
2075 alpha_config.src_premulti_en = gpremulti_en;
2076 alpha_config.dst_premulti_en = true;
2077 alpha_config.src_pixel_alpha_en = true;
2078 alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
2079 alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE;
2080
2081 vop2_parse_alpha(&alpha_config, &alpha);
2082
2083 vop2_writel(vop2, src_color_ctrl_reg, alpha.src_color_ctrl.val);
2084 vop2_writel(vop2, dst_color_ctrl_reg, alpha.dst_color_ctrl.val);
2085 vop2_writel(vop2, src_alpha_ctrl_reg, alpha.src_alpha_ctrl.val);
2086 vop2_writel(vop2, dst_alpha_ctrl_reg, alpha.dst_alpha_ctrl.val);
2087 } else {
2088 vop2_writel(vop2, src_color_ctrl_reg, 0);
2089 }
2090 }
2091 }
2092
rk3568_vop2_read_port_mux(struct vop2 * vop2)2093 static u32 rk3568_vop2_read_port_mux(struct vop2 *vop2)
2094 {
2095 return vop2_readl(vop2, RK3568_OVL_PORT_SEL);
2096 }
2097
rk3568_vop2_wait_for_port_mux_done(struct vop2 * vop2)2098 static void rk3568_vop2_wait_for_port_mux_done(struct vop2 *vop2)
2099 {
2100 u32 port_mux_sel;
2101 int ret;
2102
2103 /*
2104 * Spin until the previous port_mux figuration is done.
2105 */
2106 ret = readx_poll_timeout_atomic(rk3568_vop2_read_port_mux, vop2, port_mux_sel,
2107 port_mux_sel == vop2->old_port_sel, 0, 50 * 1000);
2108 if (ret)
2109 DRM_DEV_ERROR(vop2->dev, "wait port_mux done timeout: 0x%x--0x%x\n",
2110 port_mux_sel, vop2->old_port_sel);
2111 }
2112
rk3568_vop2_read_layer_cfg(struct vop2 * vop2)2113 static u32 rk3568_vop2_read_layer_cfg(struct vop2 *vop2)
2114 {
2115 return vop2_readl(vop2, RK3568_OVL_LAYER_SEL);
2116 }
2117
rk3568_vop2_wait_for_layer_cfg_done(struct vop2 * vop2,u32 cfg)2118 static void rk3568_vop2_wait_for_layer_cfg_done(struct vop2 *vop2, u32 cfg)
2119 {
2120 u32 atv_layer_cfg;
2121 int ret;
2122
2123 /*
2124 * Spin until the previous layer configuration is done.
2125 */
2126 ret = readx_poll_timeout_atomic(rk3568_vop2_read_layer_cfg, vop2, atv_layer_cfg,
2127 atv_layer_cfg == cfg, 0, 50 * 1000);
2128 if (ret)
2129 DRM_DEV_ERROR(vop2->dev, "wait layer cfg done timeout: 0x%x--0x%x\n",
2130 atv_layer_cfg, cfg);
2131 }
2132
rk3568_vop2_setup_layer_mixer(struct vop2_video_port * vp)2133 static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp)
2134 {
2135 struct vop2 *vop2 = vp->vop2;
2136 struct drm_plane *plane;
2137 u32 layer_sel = 0;
2138 u32 port_sel;
2139 u32 old_layer_sel = 0;
2140 u32 atv_layer_sel = 0;
2141 u32 old_port_sel = 0;
2142 u8 layer_id;
2143 u8 old_layer_id;
2144 u8 layer_sel_id;
2145 unsigned int ofs;
2146 u32 ovl_ctrl;
2147 int i;
2148 struct vop2_video_port *vp0 = &vop2->vps[0];
2149 struct vop2_video_port *vp1 = &vop2->vps[1];
2150 struct vop2_video_port *vp2 = &vop2->vps[2];
2151 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
2152
2153 mutex_lock(&vop2->ovl_lock);
2154 ovl_ctrl = vop2_readl(vop2, RK3568_OVL_CTRL);
2155 ovl_ctrl &= ~RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD;
2156 ovl_ctrl &= ~RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL;
2157
2158 if (vcstate->yuv_overlay)
2159 ovl_ctrl |= RK3568_OVL_CTRL__YUV_MODE(vp->id);
2160 else
2161 ovl_ctrl &= ~RK3568_OVL_CTRL__YUV_MODE(vp->id);
2162
2163 old_port_sel = vop2->old_port_sel;
2164 port_sel = old_port_sel;
2165 port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT;
2166
2167 if (vp0->nlayers)
2168 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX,
2169 vp0->nlayers - 1);
2170 else
2171 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, 8);
2172
2173 if (vp1->nlayers)
2174 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX,
2175 (vp0->nlayers + vp1->nlayers - 1));
2176 else
2177 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8);
2178
2179 if (vp2->nlayers)
2180 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX,
2181 (vp2->nlayers + vp1->nlayers + vp0->nlayers - 1));
2182 else
2183 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, 8);
2184
2185 /* Fixed value for rk3588 */
2186 if (vop2->version == VOP_VERSION_RK3588)
2187 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SET__PORT3_MUX, 7);
2188
2189 atv_layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL);
2190 old_layer_sel = vop2->old_layer_sel;
2191 layer_sel = old_layer_sel;
2192
2193 ofs = 0;
2194 for (i = 0; i < vp->id; i++)
2195 ofs += vop2->vps[i].nlayers;
2196
2197 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
2198 struct vop2_win *win = to_vop2_win(plane);
2199 struct vop2_win *old_win;
2200
2201 layer_id = (u8)(plane->state->normalized_zpos + ofs);
2202 /*
2203 * Find the layer this win bind in old state.
2204 */
2205 for (old_layer_id = 0; old_layer_id < vop2->data->win_size; old_layer_id++) {
2206 layer_sel_id = (layer_sel >> (4 * old_layer_id)) & 0xf;
2207 if (layer_sel_id == win->data->layer_sel_id[vp->id])
2208 break;
2209 }
2210
2211 /*
2212 * Find the win bind to this layer in old state
2213 */
2214 for (i = 0; i < vop2->data->win_size; i++) {
2215 old_win = &vop2->win[i];
2216 layer_sel_id = (layer_sel >> (4 * layer_id)) & 0xf;
2217 if (layer_sel_id == old_win->data->layer_sel_id[vp->id])
2218 break;
2219 }
2220
2221 switch (win->data->phys_id) {
2222 case ROCKCHIP_VOP2_CLUSTER0:
2223 port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER0;
2224 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER0, vp->id);
2225 break;
2226 case ROCKCHIP_VOP2_CLUSTER1:
2227 port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER1;
2228 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id);
2229 break;
2230 case ROCKCHIP_VOP2_CLUSTER2:
2231 port_sel &= ~RK3588_OVL_PORT_SEL__CLUSTER2;
2232 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER2, vp->id);
2233 break;
2234 case ROCKCHIP_VOP2_CLUSTER3:
2235 port_sel &= ~RK3588_OVL_PORT_SEL__CLUSTER3;
2236 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER3, vp->id);
2237 break;
2238 case ROCKCHIP_VOP2_ESMART0:
2239 port_sel &= ~RK3568_OVL_PORT_SEL__ESMART0;
2240 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id);
2241 break;
2242 case ROCKCHIP_VOP2_ESMART1:
2243 port_sel &= ~RK3568_OVL_PORT_SEL__ESMART1;
2244 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id);
2245 break;
2246 case ROCKCHIP_VOP2_ESMART2:
2247 port_sel &= ~RK3588_OVL_PORT_SEL__ESMART2;
2248 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART2, vp->id);
2249 break;
2250 case ROCKCHIP_VOP2_ESMART3:
2251 port_sel &= ~RK3588_OVL_PORT_SEL__ESMART3;
2252 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART3, vp->id);
2253 break;
2254 case ROCKCHIP_VOP2_SMART0:
2255 port_sel &= ~RK3568_OVL_PORT_SEL__SMART0;
2256 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id);
2257 break;
2258 case ROCKCHIP_VOP2_SMART1:
2259 port_sel &= ~RK3568_OVL_PORT_SEL__SMART1;
2260 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART1, vp->id);
2261 break;
2262 }
2263
2264 layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(layer_id, 0x7);
2265 layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(layer_id, win->data->layer_sel_id[vp->id]);
2266 /*
2267 * When we bind a window from layerM to layerN, we also need to move the old
2268 * window on layerN to layerM to avoid one window selected by two or more layers.
2269 */
2270 layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(old_layer_id, 0x7);
2271 layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(old_layer_id,
2272 old_win->data->layer_sel_id[vp->id]);
2273 }
2274
2275 vop2->old_layer_sel = layer_sel;
2276 vop2->old_port_sel = port_sel;
2277 /*
2278 * As the RK3568_OVL_LAYER_SEL and RK3568_OVL_PORT_SEL are shared by all Video Ports,
2279 * and the configuration take effect by one Video Port's vsync.
2280 * When performing layer migration or change the zpos of layers, there are two things
2281 * to be observed and followed:
2282 * 1. When a layer is migrated from one VP to another, the configuration of the layer
2283 * can only take effect after the Port mux configuration is enabled.
2284 *
2285 * 2. When we change the zpos of layers, we must ensure that the change for the previous
2286 * VP takes effect before we proceed to change the next VP. Otherwise, the new
2287 * configuration might overwrite the previous one for the previous VP, or it could
2288 * lead to the configuration of the previous VP being take effect along with the VSYNC
2289 * of the new VP.
2290 */
2291 if (layer_sel != old_layer_sel || port_sel != old_port_sel)
2292 ovl_ctrl |= FIELD_PREP(RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL, vp->id);
2293 vop2_writel(vop2, RK3568_OVL_CTRL, ovl_ctrl);
2294
2295 if (port_sel != old_port_sel) {
2296 vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel);
2297 vop2_cfg_done(vp);
2298 rk3568_vop2_wait_for_port_mux_done(vop2);
2299 }
2300
2301 if (layer_sel != old_layer_sel && atv_layer_sel != old_layer_sel)
2302 rk3568_vop2_wait_for_layer_cfg_done(vop2, vop2->old_layer_sel);
2303
2304 vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel);
2305 mutex_unlock(&vop2->ovl_lock);
2306 }
2307
rk3568_vop2_setup_dly_for_windows(struct vop2_video_port * vp)2308 static void rk3568_vop2_setup_dly_for_windows(struct vop2_video_port *vp)
2309 {
2310 struct vop2 *vop2 = vp->vop2;
2311 struct vop2_win *win;
2312 int i = 0;
2313 u32 cdly = 0, sdly = 0;
2314
2315 for (i = 0; i < vop2->data->win_size; i++) {
2316 u32 dly;
2317
2318 win = &vop2->win[i];
2319 dly = win->delay;
2320
2321 switch (win->data->phys_id) {
2322 case ROCKCHIP_VOP2_CLUSTER0:
2323 cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_0, dly);
2324 cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_1, dly);
2325 break;
2326 case ROCKCHIP_VOP2_CLUSTER1:
2327 cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_0, dly);
2328 cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_1, dly);
2329 break;
2330 case ROCKCHIP_VOP2_ESMART0:
2331 sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART0, dly);
2332 break;
2333 case ROCKCHIP_VOP2_ESMART1:
2334 sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART1, dly);
2335 break;
2336 case ROCKCHIP_VOP2_SMART0:
2337 case ROCKCHIP_VOP2_ESMART2:
2338 sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART0, dly);
2339 break;
2340 case ROCKCHIP_VOP2_SMART1:
2341 case ROCKCHIP_VOP2_ESMART3:
2342 sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART1, dly);
2343 break;
2344 }
2345 }
2346
2347 vop2_writel(vop2, RK3568_CLUSTER_DLY_NUM, cdly);
2348 vop2_writel(vop2, RK3568_SMART_DLY_NUM, sdly);
2349 }
2350
rk3568_vop2_setup_overlay(struct vop2_video_port * vp)2351 static void rk3568_vop2_setup_overlay(struct vop2_video_port *vp)
2352 {
2353 struct vop2 *vop2 = vp->vop2;
2354 struct drm_crtc *crtc = &vp->crtc;
2355 struct drm_plane *plane;
2356
2357 vp->win_mask = 0;
2358
2359 drm_atomic_crtc_for_each_plane(plane, crtc) {
2360 struct vop2_win *win = to_vop2_win(plane);
2361
2362 win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT];
2363
2364 vp->win_mask |= BIT(win->data->phys_id);
2365
2366 if (vop2_cluster_window(win))
2367 vop2_setup_cluster_alpha(vop2, win);
2368 }
2369
2370 if (!vp->win_mask)
2371 return;
2372
2373 rk3568_vop2_setup_layer_mixer(vp);
2374 vop2_setup_alpha(vp);
2375 rk3568_vop2_setup_dly_for_windows(vp);
2376 }
2377
rk3576_vop2_setup_layer_mixer(struct vop2_video_port * vp)2378 static void rk3576_vop2_setup_layer_mixer(struct vop2_video_port *vp)
2379 {
2380 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
2381 struct vop2 *vop2 = vp->vop2;
2382 struct drm_plane *plane;
2383 u32 layer_sel = 0xffff; /* 0xf means this layer is disabled */
2384 u32 ovl_ctrl;
2385
2386 ovl_ctrl = vop2_readl(vop2, RK3576_OVL_CTRL(vp->id));
2387 if (vcstate->yuv_overlay)
2388 ovl_ctrl |= RK3576_OVL_CTRL__YUV_MODE;
2389 else
2390 ovl_ctrl &= ~RK3576_OVL_CTRL__YUV_MODE;
2391
2392 vop2_writel(vop2, RK3576_OVL_CTRL(vp->id), ovl_ctrl);
2393
2394 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
2395 struct vop2_win *win = to_vop2_win(plane);
2396
2397 layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos,
2398 0xf);
2399 layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos,
2400 win->data->layer_sel_id[vp->id]);
2401 }
2402
2403 vop2_writel(vop2, RK3576_OVL_LAYER_SEL(vp->id), layer_sel);
2404 }
2405
rk3576_vop2_setup_dly_for_windows(struct vop2_video_port * vp)2406 static void rk3576_vop2_setup_dly_for_windows(struct vop2_video_port *vp)
2407 {
2408 struct drm_plane *plane;
2409 struct vop2_win *win;
2410
2411 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
2412 win = to_vop2_win(plane);
2413 vop2_win_write(win, VOP2_WIN_DLY_NUM, 0);
2414 }
2415 }
2416
rk3576_vop2_setup_overlay(struct vop2_video_port * vp)2417 static void rk3576_vop2_setup_overlay(struct vop2_video_port *vp)
2418 {
2419 struct vop2 *vop2 = vp->vop2;
2420 struct drm_crtc *crtc = &vp->crtc;
2421 struct drm_plane *plane;
2422
2423 vp->win_mask = 0;
2424
2425 drm_atomic_crtc_for_each_plane(plane, crtc) {
2426 struct vop2_win *win = to_vop2_win(plane);
2427
2428 win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT];
2429 vp->win_mask |= BIT(win->data->phys_id);
2430
2431 if (vop2_cluster_window(win))
2432 vop2_setup_cluster_alpha(vop2, win);
2433 }
2434
2435 if (!vp->win_mask)
2436 return;
2437
2438 rk3576_vop2_setup_layer_mixer(vp);
2439 vop2_setup_alpha(vp);
2440 rk3576_vop2_setup_dly_for_windows(vp);
2441 }
2442
rk3568_vop2_setup_bg_dly(struct vop2_video_port * vp)2443 static void rk3568_vop2_setup_bg_dly(struct vop2_video_port *vp)
2444 {
2445 struct drm_crtc *crtc = &vp->crtc;
2446 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
2447 u16 hdisplay = mode->crtc_hdisplay;
2448 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2449 u32 bg_dly;
2450 u32 pre_scan_dly;
2451
2452 bg_dly = vp->data->pre_scan_max_dly[3];
2453 vop2_writel(vp->vop2, RK3568_VP_BG_MIX_CTRL(vp->id),
2454 FIELD_PREP(RK3568_VP_BG_MIX_CTRL__BG_DLY, bg_dly));
2455
2456 pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len;
2457 vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly);
2458 }
2459
rk3576_vop2_setup_bg_dly(struct vop2_video_port * vp)2460 static void rk3576_vop2_setup_bg_dly(struct vop2_video_port *vp)
2461 {
2462 struct drm_crtc *crtc = &vp->crtc;
2463 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
2464 u16 hdisplay = mode->crtc_hdisplay;
2465 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
2466 u32 bg_dly;
2467 u32 pre_scan_dly;
2468
2469 bg_dly = vp->data->pre_scan_max_dly[VOP2_DLY_WIN] +
2470 vp->data->pre_scan_max_dly[VOP2_DLY_LAYER_MIX] +
2471 vp->data->pre_scan_max_dly[VOP2_DLY_HDR_MIX];
2472
2473 vop2_writel(vp->vop2, RK3576_OVL_BG_MIX_CTRL(vp->id),
2474 FIELD_PREP(RK3576_OVL_BG_MIX_CTRL__BG_DLY, bg_dly));
2475
2476 pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len;
2477 vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly);
2478 }
2479
2480 static const struct vop2_ops rk3568_vop_ops = {
2481 .setup_intf_mux = rk3568_set_intf_mux,
2482 .setup_bg_dly = rk3568_vop2_setup_bg_dly,
2483 .setup_overlay = rk3568_vop2_setup_overlay,
2484 };
2485
2486 static const struct vop2_ops rk3576_vop_ops = {
2487 .setup_intf_mux = rk3576_set_intf_mux,
2488 .setup_bg_dly = rk3576_vop2_setup_bg_dly,
2489 .setup_overlay = rk3576_vop2_setup_overlay,
2490 };
2491
2492 static const struct vop2_ops rk3588_vop_ops = {
2493 .setup_intf_mux = rk3588_set_intf_mux,
2494 .setup_bg_dly = rk3568_vop2_setup_bg_dly,
2495 .setup_overlay = rk3568_vop2_setup_overlay,
2496 };
2497
2498 static const struct vop2_data rk3566_vop = {
2499 .version = VOP_VERSION_RK3568,
2500 .feature = VOP2_FEATURE_HAS_SYS_GRF,
2501 .nr_vps = 3,
2502 .max_input = { 4096, 2304 },
2503 .max_output = { 4096, 2304 },
2504 .vp = rk3568_vop_video_ports,
2505 .win = rk3568_vop_win_data,
2506 .win_size = ARRAY_SIZE(rk3568_vop_win_data),
2507 .cluster_reg = rk3568_vop_cluster_regs,
2508 .nr_cluster_regs = ARRAY_SIZE(rk3568_vop_cluster_regs),
2509 .smart_reg = rk3568_vop_smart_regs,
2510 .nr_smart_regs = ARRAY_SIZE(rk3568_vop_smart_regs),
2511 .regs_dump = rk3568_regs_dump,
2512 .regs_dump_size = ARRAY_SIZE(rk3568_regs_dump),
2513 .ops = &rk3568_vop_ops,
2514 .soc_id = 3566,
2515 };
2516
2517 static const struct vop2_data rk3568_vop = {
2518 .version = VOP_VERSION_RK3568,
2519 .feature = VOP2_FEATURE_HAS_SYS_GRF,
2520 .nr_vps = 3,
2521 .max_input = { 4096, 2304 },
2522 .max_output = { 4096, 2304 },
2523 .vp = rk3568_vop_video_ports,
2524 .win = rk3568_vop_win_data,
2525 .win_size = ARRAY_SIZE(rk3568_vop_win_data),
2526 .cluster_reg = rk3568_vop_cluster_regs,
2527 .nr_cluster_regs = ARRAY_SIZE(rk3568_vop_cluster_regs),
2528 .smart_reg = rk3568_vop_smart_regs,
2529 .nr_smart_regs = ARRAY_SIZE(rk3568_vop_smart_regs),
2530 .regs_dump = rk3568_regs_dump,
2531 .regs_dump_size = ARRAY_SIZE(rk3568_regs_dump),
2532 .ops = &rk3568_vop_ops,
2533 .soc_id = 3568,
2534 };
2535
2536 static const struct vop2_data rk3576_vop = {
2537 .version = VOP_VERSION_RK3576,
2538 .feature = VOP2_FEATURE_HAS_SYS_PMU,
2539 .nr_vps = 3,
2540 .max_input = { 4096, 4320 },
2541 .max_output = { 4096, 4320 },
2542 .vp = rk3576_vop_video_ports,
2543 .win = rk3576_vop_win_data,
2544 .win_size = ARRAY_SIZE(rk3576_vop_win_data),
2545 .cluster_reg = rk3576_vop_cluster_regs,
2546 .nr_cluster_regs = ARRAY_SIZE(rk3576_vop_cluster_regs),
2547 .smart_reg = rk3576_vop_smart_regs,
2548 .nr_smart_regs = ARRAY_SIZE(rk3576_vop_smart_regs),
2549 .regs_dump = rk3576_regs_dump,
2550 .regs_dump_size = ARRAY_SIZE(rk3576_regs_dump),
2551 .ops = &rk3576_vop_ops,
2552 .soc_id = 3576,
2553 };
2554
2555 static const struct vop2_data rk3588_vop = {
2556 .version = VOP_VERSION_RK3588,
2557 .feature = VOP2_FEATURE_HAS_SYS_GRF | VOP2_FEATURE_HAS_VO1_GRF |
2558 VOP2_FEATURE_HAS_VOP_GRF | VOP2_FEATURE_HAS_SYS_PMU,
2559 .nr_vps = 4,
2560 .max_input = { 4096, 4320 },
2561 .max_output = { 4096, 4320 },
2562 .vp = rk3588_vop_video_ports,
2563 .win = rk3588_vop_win_data,
2564 .win_size = ARRAY_SIZE(rk3588_vop_win_data),
2565 .cluster_reg = rk3568_vop_cluster_regs,
2566 .nr_cluster_regs = ARRAY_SIZE(rk3568_vop_cluster_regs),
2567 .smart_reg = rk3568_vop_smart_regs,
2568 .nr_smart_regs = ARRAY_SIZE(rk3568_vop_smart_regs),
2569 .regs_dump = rk3588_regs_dump,
2570 .regs_dump_size = ARRAY_SIZE(rk3588_regs_dump),
2571 .ops = &rk3588_vop_ops,
2572 .soc_id = 3588,
2573 };
2574
2575 static const struct of_device_id vop2_dt_match[] = {
2576 {
2577 .compatible = "rockchip,rk3566-vop",
2578 .data = &rk3566_vop,
2579 }, {
2580 .compatible = "rockchip,rk3568-vop",
2581 .data = &rk3568_vop,
2582 }, {
2583 .compatible = "rockchip,rk3576-vop",
2584 .data = &rk3576_vop,
2585 }, {
2586 .compatible = "rockchip,rk3588-vop",
2587 .data = &rk3588_vop
2588 }, {
2589 },
2590 };
2591 MODULE_DEVICE_TABLE(of, vop2_dt_match);
2592
vop2_probe(struct platform_device * pdev)2593 static int vop2_probe(struct platform_device *pdev)
2594 {
2595 struct device *dev = &pdev->dev;
2596
2597 return component_add(dev, &vop2_component_ops);
2598 }
2599
vop2_remove(struct platform_device * pdev)2600 static void vop2_remove(struct platform_device *pdev)
2601 {
2602 component_del(&pdev->dev, &vop2_component_ops);
2603 }
2604
2605 struct platform_driver vop2_platform_driver = {
2606 .probe = vop2_probe,
2607 .remove = vop2_remove,
2608 .driver = {
2609 .name = "rockchip-vop2",
2610 .of_match_table = vop2_dt_match,
2611 },
2612 };
2613