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 static unsigned long rk3568_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags) 1373 { 1374 struct vop2 *vop2 = vp->vop2; 1375 struct drm_crtc *crtc = &vp->crtc; 1376 u32 die, dip; 1377 1378 die = vop2_readl(vop2, RK3568_DSP_IF_EN); 1379 dip = vop2_readl(vop2, RK3568_DSP_IF_POL); 1380 1381 switch (id) { 1382 case ROCKCHIP_VOP2_EP_RGB0: 1383 die &= ~RK3568_SYS_DSP_INFACE_EN_RGB_MUX; 1384 die |= RK3568_SYS_DSP_INFACE_EN_RGB | 1385 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_RGB_MUX, vp->id); 1386 dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; 1387 dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); 1388 if (polflags & POLFLAG_DCLK_INV) 1389 regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3)); 1390 else 1391 regmap_write(vop2->sys_grf, RK3568_GRF_VO_CON1, BIT(3 + 16)); 1392 break; 1393 case ROCKCHIP_VOP2_EP_HDMI0: 1394 die &= ~RK3568_SYS_DSP_INFACE_EN_HDMI_MUX; 1395 die |= RK3568_SYS_DSP_INFACE_EN_HDMI | 1396 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id); 1397 dip &= ~RK3568_DSP_IF_POL__HDMI_PIN_POL; 1398 dip |= FIELD_PREP(RK3568_DSP_IF_POL__HDMI_PIN_POL, polflags); 1399 break; 1400 case ROCKCHIP_VOP2_EP_EDP0: 1401 die &= ~RK3568_SYS_DSP_INFACE_EN_EDP_MUX; 1402 die |= RK3568_SYS_DSP_INFACE_EN_EDP | 1403 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id); 1404 dip &= ~RK3568_DSP_IF_POL__EDP_PIN_POL; 1405 dip |= FIELD_PREP(RK3568_DSP_IF_POL__EDP_PIN_POL, polflags); 1406 break; 1407 case ROCKCHIP_VOP2_EP_MIPI0: 1408 die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX; 1409 die |= RK3568_SYS_DSP_INFACE_EN_MIPI0 | 1410 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX, vp->id); 1411 dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL; 1412 dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags); 1413 break; 1414 case ROCKCHIP_VOP2_EP_MIPI1: 1415 die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX; 1416 die |= RK3568_SYS_DSP_INFACE_EN_MIPI1 | 1417 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id); 1418 dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL; 1419 dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags); 1420 break; 1421 case ROCKCHIP_VOP2_EP_LVDS0: 1422 die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX; 1423 die |= RK3568_SYS_DSP_INFACE_EN_LVDS0 | 1424 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX, vp->id); 1425 dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; 1426 dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); 1427 break; 1428 case ROCKCHIP_VOP2_EP_LVDS1: 1429 die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX; 1430 die |= RK3568_SYS_DSP_INFACE_EN_LVDS1 | 1431 FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX, vp->id); 1432 dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; 1433 dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); 1434 break; 1435 default: 1436 drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); 1437 return 0; 1438 } 1439 1440 dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD; 1441 1442 vop2_writel(vop2, RK3568_DSP_IF_EN, die); 1443 vop2_writel(vop2, RK3568_DSP_IF_POL, dip); 1444 1445 return crtc->state->adjusted_mode.crtc_clock * 1000LL; 1446 } 1447 1448 static unsigned long rk3576_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags) 1449 { 1450 struct vop2 *vop2 = vp->vop2; 1451 struct drm_crtc *crtc = &vp->crtc; 1452 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; 1453 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); 1454 u8 port_pix_rate = vp->data->pixel_rate; 1455 int dclk_core_div, dclk_out_div, if_pixclk_div, if_dclk_sel; 1456 u32 ctrl, vp_clk_div, reg, dclk_div; 1457 unsigned long dclk_in_rate, dclk_core_rate; 1458 1459 if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420 || adjusted_mode->crtc_clock > 600000) 1460 dclk_div = 2; 1461 else 1462 dclk_div = 1; 1463 1464 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) 1465 dclk_core_rate = adjusted_mode->crtc_clock / 2; 1466 else 1467 dclk_core_rate = adjusted_mode->crtc_clock / port_pix_rate; 1468 1469 dclk_in_rate = adjusted_mode->crtc_clock / dclk_div; 1470 1471 dclk_core_div = dclk_in_rate > dclk_core_rate ? 1 : 0; 1472 1473 if (vop2_output_if_is_edp(id)) 1474 if_pixclk_div = port_pix_rate == 2 ? RK3576_DSP_IF_PCLK_DIV : 0; 1475 else 1476 if_pixclk_div = port_pix_rate == 1 ? RK3576_DSP_IF_PCLK_DIV : 0; 1477 1478 if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420) { 1479 if_dclk_sel = RK3576_DSP_IF_DCLK_SEL_OUT; 1480 dclk_out_div = 1; 1481 } else { 1482 if_dclk_sel = 0; 1483 dclk_out_div = 0; 1484 } 1485 1486 switch (id) { 1487 case ROCKCHIP_VOP2_EP_HDMI0: 1488 reg = RK3576_HDMI0_IF_CTRL; 1489 break; 1490 case ROCKCHIP_VOP2_EP_EDP0: 1491 reg = RK3576_EDP0_IF_CTRL; 1492 break; 1493 case ROCKCHIP_VOP2_EP_MIPI0: 1494 reg = RK3576_MIPI0_IF_CTRL; 1495 break; 1496 case ROCKCHIP_VOP2_EP_DP0: 1497 reg = RK3576_DP0_IF_CTRL; 1498 break; 1499 case ROCKCHIP_VOP2_EP_DP1: 1500 reg = RK3576_DP1_IF_CTRL; 1501 break; 1502 default: 1503 drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); 1504 return 0; 1505 } 1506 1507 ctrl = vop2_readl(vop2, reg); 1508 ctrl &= ~RK3576_DSP_IF_DCLK_SEL_OUT; 1509 ctrl &= ~RK3576_DSP_IF_PCLK_DIV; 1510 ctrl &= ~RK3576_DSP_IF_MUX; 1511 ctrl |= RK3576_DSP_IF_CFG_DONE_IMD; 1512 ctrl |= if_dclk_sel | if_pixclk_div; 1513 ctrl |= RK3576_DSP_IF_CLK_OUT_EN | RK3576_DSP_IF_EN; 1514 ctrl |= FIELD_PREP(RK3576_DSP_IF_MUX, vp->id); 1515 ctrl |= FIELD_PREP(RK3576_DSP_IF_PIN_POL, polflags); 1516 vop2_writel(vop2, reg, ctrl); 1517 1518 vp_clk_div = FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_CORE_DIV, dclk_core_div); 1519 vp_clk_div |= FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_OUT_DIV, dclk_out_div); 1520 1521 vop2_vp_write(vp, RK3588_VP_CLK_CTRL, vp_clk_div); 1522 1523 return dclk_in_rate * 1000LL; 1524 } 1525 1526 /* 1527 * calc the dclk on rk3588 1528 * the available div of dclk is 1, 2, 4 1529 */ 1530 static unsigned long rk3588_calc_dclk(unsigned long child_clk, unsigned long max_dclk) 1531 { 1532 if (child_clk * 4 <= max_dclk) 1533 return child_clk * 4; 1534 else if (child_clk * 2 <= max_dclk) 1535 return child_clk * 2; 1536 else if (child_clk <= max_dclk) 1537 return child_clk; 1538 else 1539 return 0; 1540 } 1541 1542 /* 1543 * 4 pixclk/cycle on rk3588 1544 * RGB/eDP/HDMI: if_pixclk >= dclk_core 1545 * DP: dp_pixclk = dclk_out <= dclk_core 1546 * DSI: mipi_pixclk <= dclk_out <= dclk_core 1547 */ 1548 static unsigned long rk3588_calc_cru_cfg(struct vop2_video_port *vp, int id, 1549 int *dclk_core_div, int *dclk_out_div, 1550 int *if_pixclk_div, int *if_dclk_div) 1551 { 1552 struct vop2 *vop2 = vp->vop2; 1553 struct drm_crtc *crtc = &vp->crtc; 1554 struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; 1555 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); 1556 int output_mode = vcstate->output_mode; 1557 unsigned long v_pixclk = adjusted_mode->crtc_clock * 1000LL; /* video timing pixclk */ 1558 unsigned long dclk_core_rate = v_pixclk >> 2; 1559 unsigned long dclk_rate = v_pixclk; 1560 unsigned long dclk_out_rate; 1561 unsigned long if_pixclk_rate; 1562 int K = 1; 1563 1564 if (vop2_output_if_is_hdmi(id)) { 1565 /* 1566 * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate 1567 * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate 1568 */ 1569 if (output_mode == ROCKCHIP_OUT_MODE_YUV420) { 1570 dclk_rate = dclk_rate >> 1; 1571 K = 2; 1572 } 1573 1574 /* 1575 * if_pixclk_rate = (dclk_core_rate << 1) / K; 1576 * if_dclk_rate = dclk_core_rate / K; 1577 * *if_pixclk_div = dclk_rate / if_pixclk_rate; 1578 * *if_dclk_div = dclk_rate / if_dclk_rate; 1579 */ 1580 *if_pixclk_div = 2; 1581 *if_dclk_div = 4; 1582 } else if (vop2_output_if_is_edp(id)) { 1583 /* 1584 * edp_pixclk = edp_dclk > dclk_core 1585 */ 1586 if_pixclk_rate = v_pixclk / K; 1587 dclk_rate = if_pixclk_rate * K; 1588 /* 1589 * *if_pixclk_div = dclk_rate / if_pixclk_rate; 1590 * *if_dclk_div = *if_pixclk_div; 1591 */ 1592 *if_pixclk_div = K; 1593 *if_dclk_div = K; 1594 } else if (vop2_output_if_is_dp(id)) { 1595 if (output_mode == ROCKCHIP_OUT_MODE_YUV420) 1596 dclk_out_rate = v_pixclk >> 3; 1597 else 1598 dclk_out_rate = v_pixclk >> 2; 1599 1600 dclk_rate = rk3588_calc_dclk(dclk_out_rate, 600000000); 1601 if (!dclk_rate) { 1602 drm_err(vop2->drm, "DP dclk_out_rate out of range, dclk_out_rate: %ld Hz\n", 1603 dclk_out_rate); 1604 return 0; 1605 } 1606 *dclk_out_div = dclk_rate / dclk_out_rate; 1607 } else if (vop2_output_if_is_mipi(id)) { 1608 if_pixclk_rate = dclk_core_rate / K; 1609 /* 1610 * dclk_core = dclk_out * K = if_pixclk * K = v_pixclk / 4 1611 */ 1612 dclk_out_rate = if_pixclk_rate; 1613 /* 1614 * dclk_rate = N * dclk_core_rate N = (1,2,4 ), 1615 * we get a little factor here 1616 */ 1617 dclk_rate = rk3588_calc_dclk(dclk_out_rate, 600000000); 1618 if (!dclk_rate) { 1619 drm_err(vop2->drm, "MIPI dclk out of range, dclk_out_rate: %ld Hz\n", 1620 dclk_out_rate); 1621 return 0; 1622 } 1623 *dclk_out_div = dclk_rate / dclk_out_rate; 1624 /* 1625 * mipi pixclk == dclk_out 1626 */ 1627 *if_pixclk_div = 1; 1628 } else if (vop2_output_if_is_dpi(id)) { 1629 dclk_rate = v_pixclk; 1630 } 1631 1632 *dclk_core_div = dclk_rate / dclk_core_rate; 1633 *if_pixclk_div = ilog2(*if_pixclk_div); 1634 *if_dclk_div = ilog2(*if_dclk_div); 1635 *dclk_core_div = ilog2(*dclk_core_div); 1636 *dclk_out_div = ilog2(*dclk_out_div); 1637 1638 drm_dbg(vop2->drm, "dclk: %ld, pixclk_div: %d, dclk_div: %d\n", 1639 dclk_rate, *if_pixclk_div, *if_dclk_div); 1640 1641 return dclk_rate; 1642 } 1643 1644 /* 1645 * MIPI port mux on rk3588: 1646 * 0: Video Port2 1647 * 1: Video Port3 1648 * 3: Video Port 1(MIPI1 only) 1649 */ 1650 static u32 rk3588_get_mipi_port_mux(int vp_id) 1651 { 1652 if (vp_id == 1) 1653 return 3; 1654 else if (vp_id == 3) 1655 return 1; 1656 else 1657 return 0; 1658 } 1659 1660 static u32 rk3588_get_hdmi_pol(u32 flags) 1661 { 1662 u32 val; 1663 1664 val = (flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0; 1665 val |= (flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0; 1666 1667 return val; 1668 } 1669 1670 static unsigned long rk3588_set_intf_mux(struct vop2_video_port *vp, int id, u32 polflags) 1671 { 1672 struct vop2 *vop2 = vp->vop2; 1673 int dclk_core_div, dclk_out_div, if_pixclk_div, if_dclk_div; 1674 unsigned long clock; 1675 u32 die, dip, div, vp_clk_div, val; 1676 1677 clock = rk3588_calc_cru_cfg(vp, id, &dclk_core_div, &dclk_out_div, 1678 &if_pixclk_div, &if_dclk_div); 1679 if (!clock) 1680 return 0; 1681 1682 vp_clk_div = FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_CORE_DIV, dclk_core_div); 1683 vp_clk_div |= FIELD_PREP(RK3588_VP_CLK_CTRL__DCLK_OUT_DIV, dclk_out_div); 1684 1685 die = vop2_readl(vop2, RK3568_DSP_IF_EN); 1686 dip = vop2_readl(vop2, RK3568_DSP_IF_POL); 1687 div = vop2_readl(vop2, RK3568_DSP_IF_CTRL); 1688 1689 switch (id) { 1690 case ROCKCHIP_VOP2_EP_HDMI0: 1691 div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV; 1692 div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV; 1693 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div); 1694 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div); 1695 die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX; 1696 die |= RK3588_SYS_DSP_INFACE_EN_HDMI0 | 1697 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id); 1698 val = rk3588_get_hdmi_pol(polflags); 1699 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(1), 1)); 1700 regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, 1701 FIELD_PREP_WM16(GENMASK(6, 5), val)); 1702 break; 1703 case ROCKCHIP_VOP2_EP_HDMI1: 1704 div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV; 1705 div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV; 1706 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV, if_dclk_div); 1707 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV, if_pixclk_div); 1708 die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX; 1709 die |= RK3588_SYS_DSP_INFACE_EN_HDMI1 | 1710 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id); 1711 val = rk3588_get_hdmi_pol(polflags); 1712 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(4), 1)); 1713 regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, 1714 FIELD_PREP_WM16(GENMASK(8, 7), val)); 1715 break; 1716 case ROCKCHIP_VOP2_EP_EDP0: 1717 div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV; 1718 div &= ~RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV; 1719 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div); 1720 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div); 1721 die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX; 1722 die |= RK3588_SYS_DSP_INFACE_EN_EDP0 | 1723 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id); 1724 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(0), 1)); 1725 break; 1726 case ROCKCHIP_VOP2_EP_EDP1: 1727 div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV; 1728 div &= ~RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV; 1729 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV, if_dclk_div); 1730 div |= FIELD_PREP(RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV, if_pixclk_div); 1731 die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX; 1732 die |= RK3588_SYS_DSP_INFACE_EN_EDP1 | 1733 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id); 1734 regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(3), 1)); 1735 break; 1736 case ROCKCHIP_VOP2_EP_MIPI0: 1737 div &= ~RK3588_DSP_IF_MIPI0_PCLK_DIV; 1738 div |= FIELD_PREP(RK3588_DSP_IF_MIPI0_PCLK_DIV, if_pixclk_div); 1739 die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX; 1740 val = rk3588_get_mipi_port_mux(vp->id); 1741 die |= RK3588_SYS_DSP_INFACE_EN_MIPI0 | 1742 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX, !!val); 1743 break; 1744 case ROCKCHIP_VOP2_EP_MIPI1: 1745 div &= ~RK3588_DSP_IF_MIPI1_PCLK_DIV; 1746 div |= FIELD_PREP(RK3588_DSP_IF_MIPI1_PCLK_DIV, if_pixclk_div); 1747 die &= ~RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX; 1748 val = rk3588_get_mipi_port_mux(vp->id); 1749 die |= RK3588_SYS_DSP_INFACE_EN_MIPI1 | 1750 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX, val); 1751 break; 1752 case ROCKCHIP_VOP2_EP_DP0: 1753 die &= ~RK3588_SYS_DSP_INFACE_EN_DP0_MUX; 1754 die |= RK3588_SYS_DSP_INFACE_EN_DP0 | 1755 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP0_MUX, vp->id); 1756 dip &= ~RK3588_DSP_IF_POL__DP0_PIN_POL; 1757 dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP0_PIN_POL, polflags); 1758 break; 1759 case ROCKCHIP_VOP2_EP_DP1: 1760 die &= ~RK3588_SYS_DSP_INFACE_EN_DP1_MUX; 1761 die |= RK3588_SYS_DSP_INFACE_EN_DP1 | 1762 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_DP1_MUX, vp->id); 1763 dip &= ~RK3588_DSP_IF_POL__DP1_PIN_POL; 1764 dip |= FIELD_PREP(RK3588_DSP_IF_POL__DP1_PIN_POL, polflags); 1765 break; 1766 default: 1767 drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); 1768 return 0; 1769 } 1770 1771 dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD; 1772 1773 vop2_vp_write(vp, RK3588_VP_CLK_CTRL, vp_clk_div); 1774 vop2_writel(vop2, RK3568_DSP_IF_EN, die); 1775 vop2_writel(vop2, RK3568_DSP_IF_CTRL, div); 1776 vop2_writel(vop2, RK3568_DSP_IF_POL, dip); 1777 1778 return clock; 1779 } 1780 1781 static bool is_opaque(u16 alpha) 1782 { 1783 return (alpha >> 8) == 0xff; 1784 } 1785 1786 static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config, 1787 struct vop2_alpha *alpha) 1788 { 1789 int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1; 1790 int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1; 1791 int src_color_mode = alpha_config->src_premulti_en ? 1792 ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL; 1793 int dst_color_mode = alpha_config->dst_premulti_en ? 1794 ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL; 1795 1796 alpha->src_color_ctrl.val = 0; 1797 alpha->dst_color_ctrl.val = 0; 1798 alpha->src_alpha_ctrl.val = 0; 1799 alpha->dst_alpha_ctrl.val = 0; 1800 1801 if (!alpha_config->src_pixel_alpha_en) 1802 alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; 1803 else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en) 1804 alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX; 1805 else 1806 alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; 1807 1808 alpha->src_color_ctrl.bits.alpha_en = 1; 1809 1810 if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) { 1811 alpha->src_color_ctrl.bits.color_mode = src_color_mode; 1812 alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; 1813 } else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) { 1814 alpha->src_color_ctrl.bits.color_mode = src_color_mode; 1815 alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE; 1816 } else { 1817 alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL; 1818 alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; 1819 } 1820 alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8; 1821 alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; 1822 alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; 1823 1824 alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; 1825 alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; 1826 alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; 1827 alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8; 1828 alpha->dst_color_ctrl.bits.color_mode = dst_color_mode; 1829 alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; 1830 1831 alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; 1832 alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode; 1833 alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; 1834 alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE; 1835 1836 alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; 1837 if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en) 1838 alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX; 1839 else 1840 alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; 1841 alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION; 1842 alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; 1843 } 1844 1845 static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, u8 port_id) 1846 { 1847 struct vop2_video_port *vp; 1848 int used_layer = 0; 1849 int i; 1850 1851 for (i = 0; i < port_id; i++) { 1852 vp = &vop2->vps[i]; 1853 used_layer += hweight32(vp->win_mask); 1854 } 1855 1856 return used_layer; 1857 } 1858 1859 static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_win) 1860 { 1861 struct vop2_alpha_config alpha_config; 1862 struct vop2_alpha alpha; 1863 struct drm_plane_state *bottom_win_pstate; 1864 bool src_pixel_alpha_en = false; 1865 u16 src_glb_alpha_val, dst_glb_alpha_val; 1866 u32 src_color_ctrl_reg, dst_color_ctrl_reg, src_alpha_ctrl_reg, dst_alpha_ctrl_reg; 1867 u32 offset = 0; 1868 bool premulti_en = false; 1869 bool swap = false; 1870 1871 /* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */ 1872 bottom_win_pstate = main_win->base.state; 1873 src_glb_alpha_val = 0; 1874 dst_glb_alpha_val = main_win->base.state->alpha; 1875 1876 if (!bottom_win_pstate->fb) 1877 return; 1878 1879 alpha_config.src_premulti_en = premulti_en; 1880 alpha_config.dst_premulti_en = false; 1881 alpha_config.src_pixel_alpha_en = src_pixel_alpha_en; 1882 alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ 1883 alpha_config.src_glb_alpha_value = src_glb_alpha_val; 1884 alpha_config.dst_glb_alpha_value = dst_glb_alpha_val; 1885 vop2_parse_alpha(&alpha_config, &alpha); 1886 1887 alpha.src_color_ctrl.bits.src_dst_swap = swap; 1888 1889 switch (main_win->data->phys_id) { 1890 case ROCKCHIP_VOP2_CLUSTER0: 1891 offset = 0x0; 1892 break; 1893 case ROCKCHIP_VOP2_CLUSTER1: 1894 offset = 0x10; 1895 break; 1896 case ROCKCHIP_VOP2_CLUSTER2: 1897 offset = 0x20; 1898 break; 1899 case ROCKCHIP_VOP2_CLUSTER3: 1900 offset = 0x30; 1901 break; 1902 } 1903 1904 if (vop2->version <= VOP_VERSION_RK3588) { 1905 src_color_ctrl_reg = RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL; 1906 dst_color_ctrl_reg = RK3568_CLUSTER0_MIX_DST_COLOR_CTRL; 1907 src_alpha_ctrl_reg = RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL; 1908 dst_alpha_ctrl_reg = RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL; 1909 } else { 1910 src_color_ctrl_reg = RK3576_CLUSTER0_MIX_SRC_COLOR_CTRL; 1911 dst_color_ctrl_reg = RK3576_CLUSTER0_MIX_DST_COLOR_CTRL; 1912 src_alpha_ctrl_reg = RK3576_CLUSTER0_MIX_SRC_ALPHA_CTRL; 1913 dst_alpha_ctrl_reg = RK3576_CLUSTER0_MIX_DST_ALPHA_CTRL; 1914 } 1915 1916 vop2_writel(vop2, src_color_ctrl_reg + offset, alpha.src_color_ctrl.val); 1917 vop2_writel(vop2, dst_color_ctrl_reg + offset, alpha.dst_color_ctrl.val); 1918 vop2_writel(vop2, src_alpha_ctrl_reg + offset, alpha.src_alpha_ctrl.val); 1919 vop2_writel(vop2, dst_alpha_ctrl_reg + offset, alpha.dst_alpha_ctrl.val); 1920 } 1921 1922 static void vop2_setup_alpha(struct vop2_video_port *vp) 1923 { 1924 struct vop2 *vop2 = vp->vop2; 1925 struct drm_framebuffer *fb; 1926 struct vop2_alpha_config alpha_config; 1927 struct vop2_alpha alpha; 1928 struct drm_plane *plane; 1929 int pixel_alpha_en; 1930 int premulti_en, gpremulti_en = 0; 1931 int mixer_id; 1932 u32 src_color_ctrl_reg, dst_color_ctrl_reg, src_alpha_ctrl_reg, dst_alpha_ctrl_reg; 1933 u32 offset; 1934 bool bottom_layer_alpha_en = false; 1935 u32 dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE; 1936 1937 if (vop2->version <= VOP_VERSION_RK3588) 1938 mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id); 1939 else 1940 mixer_id = 0; 1941 1942 alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ 1943 1944 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { 1945 struct vop2_win *win = to_vop2_win(plane); 1946 1947 if (plane->state->normalized_zpos == 0 && 1948 !is_opaque(plane->state->alpha) && 1949 !vop2_cluster_window(win)) { 1950 /* 1951 * If bottom layer have global alpha effect [except cluster layer, 1952 * because cluster have deal with bottom layer global alpha value 1953 * at cluster mix], bottom layer mix need deal with global alpha. 1954 */ 1955 bottom_layer_alpha_en = true; 1956 dst_global_alpha = plane->state->alpha; 1957 } 1958 } 1959 1960 if (vop2->version <= VOP_VERSION_RK3588) { 1961 src_color_ctrl_reg = RK3568_MIX0_SRC_COLOR_CTRL; 1962 dst_color_ctrl_reg = RK3568_MIX0_DST_COLOR_CTRL; 1963 src_alpha_ctrl_reg = RK3568_MIX0_SRC_ALPHA_CTRL; 1964 dst_alpha_ctrl_reg = RK3568_MIX0_DST_ALPHA_CTRL; 1965 } else { 1966 src_color_ctrl_reg = RK3576_OVL_MIX0_SRC_COLOR_CTRL(vp->id); 1967 dst_color_ctrl_reg = RK3576_OVL_MIX0_DST_COLOR_CTRL(vp->id); 1968 src_alpha_ctrl_reg = RK3576_OVL_MIX0_SRC_ALPHA_CTRL(vp->id); 1969 dst_alpha_ctrl_reg = RK3576_OVL_MIX0_DST_ALPHA_CTRL(vp->id); 1970 } 1971 1972 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { 1973 struct vop2_win *win = to_vop2_win(plane); 1974 int zpos = plane->state->normalized_zpos; 1975 1976 /* 1977 * Need to configure alpha from second layer. 1978 */ 1979 if (zpos == 0) 1980 continue; 1981 1982 if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) 1983 premulti_en = 1; 1984 else 1985 premulti_en = 0; 1986 1987 plane = &win->base; 1988 fb = plane->state->fb; 1989 1990 pixel_alpha_en = fb->format->has_alpha; 1991 1992 alpha_config.src_premulti_en = premulti_en; 1993 1994 if (bottom_layer_alpha_en && zpos == 1) { 1995 gpremulti_en = premulti_en; 1996 /* Cd = Cs + (1 - As) * Cd * Agd */ 1997 alpha_config.dst_premulti_en = false; 1998 alpha_config.src_pixel_alpha_en = pixel_alpha_en; 1999 alpha_config.src_glb_alpha_value = plane->state->alpha; 2000 alpha_config.dst_glb_alpha_value = dst_global_alpha; 2001 } else if (vop2_cluster_window(win)) { 2002 /* Mix output data only have pixel alpha */ 2003 alpha_config.dst_premulti_en = true; 2004 alpha_config.src_pixel_alpha_en = true; 2005 alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; 2006 alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; 2007 } else { 2008 /* Cd = Cs + (1 - As) * Cd */ 2009 alpha_config.dst_premulti_en = true; 2010 alpha_config.src_pixel_alpha_en = pixel_alpha_en; 2011 alpha_config.src_glb_alpha_value = plane->state->alpha; 2012 alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; 2013 } 2014 2015 vop2_parse_alpha(&alpha_config, &alpha); 2016 2017 offset = (mixer_id + zpos - 1) * 0x10; 2018 2019 vop2_writel(vop2, src_color_ctrl_reg + offset, alpha.src_color_ctrl.val); 2020 vop2_writel(vop2, dst_color_ctrl_reg + offset, alpha.dst_color_ctrl.val); 2021 vop2_writel(vop2, src_alpha_ctrl_reg + offset, alpha.src_alpha_ctrl.val); 2022 vop2_writel(vop2, dst_alpha_ctrl_reg + offset, alpha.dst_alpha_ctrl.val); 2023 } 2024 2025 if (vp->id == 0) { 2026 if (vop2->version <= VOP_VERSION_RK3588) { 2027 src_color_ctrl_reg = RK3568_HDR0_SRC_COLOR_CTRL; 2028 dst_color_ctrl_reg = RK3568_HDR0_DST_COLOR_CTRL; 2029 src_alpha_ctrl_reg = RK3568_HDR0_SRC_ALPHA_CTRL; 2030 dst_alpha_ctrl_reg = RK3568_HDR0_DST_ALPHA_CTRL; 2031 } else { 2032 src_color_ctrl_reg = RK3576_OVL_HDR_SRC_COLOR_CTRL(vp->id); 2033 dst_color_ctrl_reg = RK3576_OVL_HDR_DST_COLOR_CTRL(vp->id); 2034 src_alpha_ctrl_reg = RK3576_OVL_HDR_SRC_ALPHA_CTRL(vp->id); 2035 dst_alpha_ctrl_reg = RK3576_OVL_HDR_DST_ALPHA_CTRL(vp->id); 2036 } 2037 2038 if (bottom_layer_alpha_en) { 2039 /* Transfer pixel alpha to hdr mix */ 2040 alpha_config.src_premulti_en = gpremulti_en; 2041 alpha_config.dst_premulti_en = true; 2042 alpha_config.src_pixel_alpha_en = true; 2043 alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; 2044 alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; 2045 2046 vop2_parse_alpha(&alpha_config, &alpha); 2047 2048 vop2_writel(vop2, src_color_ctrl_reg, alpha.src_color_ctrl.val); 2049 vop2_writel(vop2, dst_color_ctrl_reg, alpha.dst_color_ctrl.val); 2050 vop2_writel(vop2, src_alpha_ctrl_reg, alpha.src_alpha_ctrl.val); 2051 vop2_writel(vop2, dst_alpha_ctrl_reg, alpha.dst_alpha_ctrl.val); 2052 } else { 2053 vop2_writel(vop2, src_color_ctrl_reg, 0); 2054 } 2055 } 2056 } 2057 2058 static u32 rk3568_vop2_read_port_mux(struct vop2 *vop2) 2059 { 2060 return vop2_readl(vop2, RK3568_OVL_PORT_SEL); 2061 } 2062 2063 static void rk3568_vop2_wait_for_port_mux_done(struct vop2 *vop2) 2064 { 2065 u32 port_mux_sel; 2066 int ret; 2067 2068 /* 2069 * Spin until the previous port_mux figuration is done. 2070 */ 2071 ret = readx_poll_timeout_atomic(rk3568_vop2_read_port_mux, vop2, port_mux_sel, 2072 port_mux_sel == vop2->old_port_sel, 0, 50 * 1000); 2073 if (ret) 2074 DRM_DEV_ERROR(vop2->dev, "wait port_mux done timeout: 0x%x--0x%x\n", 2075 port_mux_sel, vop2->old_port_sel); 2076 } 2077 2078 static u32 rk3568_vop2_read_layer_cfg(struct vop2 *vop2) 2079 { 2080 return vop2_readl(vop2, RK3568_OVL_LAYER_SEL); 2081 } 2082 2083 static void rk3568_vop2_wait_for_layer_cfg_done(struct vop2 *vop2, u32 cfg) 2084 { 2085 u32 atv_layer_cfg; 2086 int ret; 2087 2088 /* 2089 * Spin until the previous layer configuration is done. 2090 */ 2091 ret = readx_poll_timeout_atomic(rk3568_vop2_read_layer_cfg, vop2, atv_layer_cfg, 2092 atv_layer_cfg == cfg, 0, 50 * 1000); 2093 if (ret) 2094 DRM_DEV_ERROR(vop2->dev, "wait layer cfg done timeout: 0x%x--0x%x\n", 2095 atv_layer_cfg, cfg); 2096 } 2097 2098 static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp) 2099 { 2100 struct vop2 *vop2 = vp->vop2; 2101 struct drm_plane *plane; 2102 u32 layer_sel = 0; 2103 u32 port_sel; 2104 u32 old_layer_sel = 0; 2105 u32 atv_layer_sel = 0; 2106 u32 old_port_sel = 0; 2107 u8 layer_id; 2108 u8 old_layer_id; 2109 u8 layer_sel_id; 2110 unsigned int ofs; 2111 u32 ovl_ctrl; 2112 int i; 2113 struct vop2_video_port *vp0 = &vop2->vps[0]; 2114 struct vop2_video_port *vp1 = &vop2->vps[1]; 2115 struct vop2_video_port *vp2 = &vop2->vps[2]; 2116 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); 2117 2118 mutex_lock(&vop2->ovl_lock); 2119 ovl_ctrl = vop2_readl(vop2, RK3568_OVL_CTRL); 2120 ovl_ctrl &= ~RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD; 2121 ovl_ctrl &= ~RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL; 2122 2123 if (vcstate->yuv_overlay) 2124 ovl_ctrl |= RK3568_OVL_CTRL__YUV_MODE(vp->id); 2125 else 2126 ovl_ctrl &= ~RK3568_OVL_CTRL__YUV_MODE(vp->id); 2127 2128 old_port_sel = vop2->old_port_sel; 2129 port_sel = old_port_sel; 2130 port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT; 2131 2132 if (vp0->nlayers) 2133 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, 2134 vp0->nlayers - 1); 2135 else 2136 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, 8); 2137 2138 if (vp1->nlayers) 2139 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 2140 (vp0->nlayers + vp1->nlayers - 1)); 2141 else 2142 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8); 2143 2144 if (vp2->nlayers) 2145 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, 2146 (vp2->nlayers + vp1->nlayers + vp0->nlayers - 1)); 2147 else 2148 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, 8); 2149 2150 /* Fixed value for rk3588 */ 2151 if (vop2->version == VOP_VERSION_RK3588) 2152 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SET__PORT3_MUX, 7); 2153 2154 atv_layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); 2155 old_layer_sel = vop2->old_layer_sel; 2156 layer_sel = old_layer_sel; 2157 2158 ofs = 0; 2159 for (i = 0; i < vp->id; i++) 2160 ofs += vop2->vps[i].nlayers; 2161 2162 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { 2163 struct vop2_win *win = to_vop2_win(plane); 2164 struct vop2_win *old_win; 2165 2166 layer_id = (u8)(plane->state->normalized_zpos + ofs); 2167 /* 2168 * Find the layer this win bind in old state. 2169 */ 2170 for (old_layer_id = 0; old_layer_id < vop2->data->win_size; old_layer_id++) { 2171 layer_sel_id = (layer_sel >> (4 * old_layer_id)) & 0xf; 2172 if (layer_sel_id == win->data->layer_sel_id[vp->id]) 2173 break; 2174 } 2175 2176 /* 2177 * Find the win bind to this layer in old state 2178 */ 2179 for (i = 0; i < vop2->data->win_size; i++) { 2180 old_win = &vop2->win[i]; 2181 layer_sel_id = (layer_sel >> (4 * layer_id)) & 0xf; 2182 if (layer_sel_id == old_win->data->layer_sel_id[vp->id]) 2183 break; 2184 } 2185 2186 switch (win->data->phys_id) { 2187 case ROCKCHIP_VOP2_CLUSTER0: 2188 port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER0; 2189 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER0, vp->id); 2190 break; 2191 case ROCKCHIP_VOP2_CLUSTER1: 2192 port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER1; 2193 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id); 2194 break; 2195 case ROCKCHIP_VOP2_CLUSTER2: 2196 port_sel &= ~RK3588_OVL_PORT_SEL__CLUSTER2; 2197 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER2, vp->id); 2198 break; 2199 case ROCKCHIP_VOP2_CLUSTER3: 2200 port_sel &= ~RK3588_OVL_PORT_SEL__CLUSTER3; 2201 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__CLUSTER3, vp->id); 2202 break; 2203 case ROCKCHIP_VOP2_ESMART0: 2204 port_sel &= ~RK3568_OVL_PORT_SEL__ESMART0; 2205 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id); 2206 break; 2207 case ROCKCHIP_VOP2_ESMART1: 2208 port_sel &= ~RK3568_OVL_PORT_SEL__ESMART1; 2209 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id); 2210 break; 2211 case ROCKCHIP_VOP2_ESMART2: 2212 port_sel &= ~RK3588_OVL_PORT_SEL__ESMART2; 2213 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART2, vp->id); 2214 break; 2215 case ROCKCHIP_VOP2_ESMART3: 2216 port_sel &= ~RK3588_OVL_PORT_SEL__ESMART3; 2217 port_sel |= FIELD_PREP(RK3588_OVL_PORT_SEL__ESMART3, vp->id); 2218 break; 2219 case ROCKCHIP_VOP2_SMART0: 2220 port_sel &= ~RK3568_OVL_PORT_SEL__SMART0; 2221 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id); 2222 break; 2223 case ROCKCHIP_VOP2_SMART1: 2224 port_sel &= ~RK3568_OVL_PORT_SEL__SMART1; 2225 port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART1, vp->id); 2226 break; 2227 } 2228 2229 layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(layer_id, 0x7); 2230 layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(layer_id, win->data->layer_sel_id[vp->id]); 2231 /* 2232 * When we bind a window from layerM to layerN, we also need to move the old 2233 * window on layerN to layerM to avoid one window selected by two or more layers. 2234 */ 2235 layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(old_layer_id, 0x7); 2236 layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(old_layer_id, 2237 old_win->data->layer_sel_id[vp->id]); 2238 } 2239 2240 vop2->old_layer_sel = layer_sel; 2241 vop2->old_port_sel = port_sel; 2242 /* 2243 * As the RK3568_OVL_LAYER_SEL and RK3568_OVL_PORT_SEL are shared by all Video Ports, 2244 * and the configuration take effect by one Video Port's vsync. 2245 * When performing layer migration or change the zpos of layers, there are two things 2246 * to be observed and followed: 2247 * 1. When a layer is migrated from one VP to another, the configuration of the layer 2248 * can only take effect after the Port mux configuration is enabled. 2249 * 2250 * 2. When we change the zpos of layers, we must ensure that the change for the previous 2251 * VP takes effect before we proceed to change the next VP. Otherwise, the new 2252 * configuration might overwrite the previous one for the previous VP, or it could 2253 * lead to the configuration of the previous VP being take effect along with the VSYNC 2254 * of the new VP. 2255 */ 2256 if (layer_sel != old_layer_sel || port_sel != old_port_sel) 2257 ovl_ctrl |= FIELD_PREP(RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL, vp->id); 2258 vop2_writel(vop2, RK3568_OVL_CTRL, ovl_ctrl); 2259 2260 if (port_sel != old_port_sel) { 2261 vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel); 2262 vop2_cfg_done(vp); 2263 rk3568_vop2_wait_for_port_mux_done(vop2); 2264 } 2265 2266 if (layer_sel != old_layer_sel && atv_layer_sel != old_layer_sel) 2267 rk3568_vop2_wait_for_layer_cfg_done(vop2, vop2->old_layer_sel); 2268 2269 vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel); 2270 mutex_unlock(&vop2->ovl_lock); 2271 } 2272 2273 static void rk3568_vop2_setup_dly_for_windows(struct vop2_video_port *vp) 2274 { 2275 struct vop2 *vop2 = vp->vop2; 2276 struct vop2_win *win; 2277 int i = 0; 2278 u32 cdly = 0, sdly = 0; 2279 2280 for (i = 0; i < vop2->data->win_size; i++) { 2281 u32 dly; 2282 2283 win = &vop2->win[i]; 2284 dly = win->delay; 2285 2286 switch (win->data->phys_id) { 2287 case ROCKCHIP_VOP2_CLUSTER0: 2288 cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_0, dly); 2289 cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_1, dly); 2290 break; 2291 case ROCKCHIP_VOP2_CLUSTER1: 2292 cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_0, dly); 2293 cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_1, dly); 2294 break; 2295 case ROCKCHIP_VOP2_ESMART0: 2296 sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART0, dly); 2297 break; 2298 case ROCKCHIP_VOP2_ESMART1: 2299 sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART1, dly); 2300 break; 2301 case ROCKCHIP_VOP2_SMART0: 2302 case ROCKCHIP_VOP2_ESMART2: 2303 sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART0, dly); 2304 break; 2305 case ROCKCHIP_VOP2_SMART1: 2306 case ROCKCHIP_VOP2_ESMART3: 2307 sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART1, dly); 2308 break; 2309 } 2310 } 2311 2312 vop2_writel(vop2, RK3568_CLUSTER_DLY_NUM, cdly); 2313 vop2_writel(vop2, RK3568_SMART_DLY_NUM, sdly); 2314 } 2315 2316 static void rk3568_vop2_setup_overlay(struct vop2_video_port *vp) 2317 { 2318 struct vop2 *vop2 = vp->vop2; 2319 struct drm_crtc *crtc = &vp->crtc; 2320 struct drm_plane *plane; 2321 2322 vp->win_mask = 0; 2323 2324 drm_atomic_crtc_for_each_plane(plane, crtc) { 2325 struct vop2_win *win = to_vop2_win(plane); 2326 2327 win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT]; 2328 2329 vp->win_mask |= BIT(win->data->phys_id); 2330 2331 if (vop2_cluster_window(win)) 2332 vop2_setup_cluster_alpha(vop2, win); 2333 } 2334 2335 if (!vp->win_mask) 2336 return; 2337 2338 rk3568_vop2_setup_layer_mixer(vp); 2339 vop2_setup_alpha(vp); 2340 rk3568_vop2_setup_dly_for_windows(vp); 2341 } 2342 2343 static void rk3576_vop2_setup_layer_mixer(struct vop2_video_port *vp) 2344 { 2345 struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); 2346 struct vop2 *vop2 = vp->vop2; 2347 struct drm_plane *plane; 2348 u32 layer_sel = 0xffff; /* 0xf means this layer is disabled */ 2349 u32 ovl_ctrl; 2350 2351 ovl_ctrl = vop2_readl(vop2, RK3576_OVL_CTRL(vp->id)); 2352 if (vcstate->yuv_overlay) 2353 ovl_ctrl |= RK3576_OVL_CTRL__YUV_MODE; 2354 else 2355 ovl_ctrl &= ~RK3576_OVL_CTRL__YUV_MODE; 2356 2357 vop2_writel(vop2, RK3576_OVL_CTRL(vp->id), ovl_ctrl); 2358 2359 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { 2360 struct vop2_win *win = to_vop2_win(plane); 2361 2362 layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos, 2363 0xf); 2364 layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos, 2365 win->data->layer_sel_id[vp->id]); 2366 } 2367 2368 vop2_writel(vop2, RK3576_OVL_LAYER_SEL(vp->id), layer_sel); 2369 } 2370 2371 static void rk3576_vop2_setup_dly_for_windows(struct vop2_video_port *vp) 2372 { 2373 struct drm_plane *plane; 2374 struct vop2_win *win; 2375 2376 drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { 2377 win = to_vop2_win(plane); 2378 vop2_win_write(win, VOP2_WIN_DLY_NUM, 0); 2379 } 2380 } 2381 2382 static void rk3576_vop2_setup_overlay(struct vop2_video_port *vp) 2383 { 2384 struct vop2 *vop2 = vp->vop2; 2385 struct drm_crtc *crtc = &vp->crtc; 2386 struct drm_plane *plane; 2387 2388 vp->win_mask = 0; 2389 2390 drm_atomic_crtc_for_each_plane(plane, crtc) { 2391 struct vop2_win *win = to_vop2_win(plane); 2392 2393 win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT]; 2394 vp->win_mask |= BIT(win->data->phys_id); 2395 2396 if (vop2_cluster_window(win)) 2397 vop2_setup_cluster_alpha(vop2, win); 2398 } 2399 2400 if (!vp->win_mask) 2401 return; 2402 2403 rk3576_vop2_setup_layer_mixer(vp); 2404 vop2_setup_alpha(vp); 2405 rk3576_vop2_setup_dly_for_windows(vp); 2406 } 2407 2408 static void rk3568_vop2_setup_bg_dly(struct vop2_video_port *vp) 2409 { 2410 struct drm_crtc *crtc = &vp->crtc; 2411 struct drm_display_mode *mode = &crtc->state->adjusted_mode; 2412 u16 hdisplay = mode->crtc_hdisplay; 2413 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 2414 u32 bg_dly; 2415 u32 pre_scan_dly; 2416 2417 bg_dly = vp->data->pre_scan_max_dly[3]; 2418 vop2_writel(vp->vop2, RK3568_VP_BG_MIX_CTRL(vp->id), 2419 FIELD_PREP(RK3568_VP_BG_MIX_CTRL__BG_DLY, bg_dly)); 2420 2421 pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len; 2422 vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly); 2423 } 2424 2425 static void rk3576_vop2_setup_bg_dly(struct vop2_video_port *vp) 2426 { 2427 struct drm_crtc *crtc = &vp->crtc; 2428 struct drm_display_mode *mode = &crtc->state->adjusted_mode; 2429 u16 hdisplay = mode->crtc_hdisplay; 2430 u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 2431 u32 bg_dly; 2432 u32 pre_scan_dly; 2433 2434 bg_dly = vp->data->pre_scan_max_dly[VOP2_DLY_WIN] + 2435 vp->data->pre_scan_max_dly[VOP2_DLY_LAYER_MIX] + 2436 vp->data->pre_scan_max_dly[VOP2_DLY_HDR_MIX]; 2437 2438 vop2_writel(vp->vop2, RK3576_OVL_BG_MIX_CTRL(vp->id), 2439 FIELD_PREP(RK3576_OVL_BG_MIX_CTRL__BG_DLY, bg_dly)); 2440 2441 pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len; 2442 vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly); 2443 } 2444 2445 static const struct vop2_ops rk3568_vop_ops = { 2446 .setup_intf_mux = rk3568_set_intf_mux, 2447 .setup_bg_dly = rk3568_vop2_setup_bg_dly, 2448 .setup_overlay = rk3568_vop2_setup_overlay, 2449 }; 2450 2451 static const struct vop2_ops rk3576_vop_ops = { 2452 .setup_intf_mux = rk3576_set_intf_mux, 2453 .setup_bg_dly = rk3576_vop2_setup_bg_dly, 2454 .setup_overlay = rk3576_vop2_setup_overlay, 2455 }; 2456 2457 static const struct vop2_ops rk3588_vop_ops = { 2458 .setup_intf_mux = rk3588_set_intf_mux, 2459 .setup_bg_dly = rk3568_vop2_setup_bg_dly, 2460 .setup_overlay = rk3568_vop2_setup_overlay, 2461 }; 2462 2463 static const struct vop2_data rk3566_vop = { 2464 .version = VOP_VERSION_RK3568, 2465 .feature = VOP2_FEATURE_HAS_SYS_GRF, 2466 .nr_vps = 3, 2467 .max_input = { 4096, 2304 }, 2468 .max_output = { 4096, 2304 }, 2469 .vp = rk3568_vop_video_ports, 2470 .win = rk3568_vop_win_data, 2471 .win_size = ARRAY_SIZE(rk3568_vop_win_data), 2472 .cluster_reg = rk3568_vop_cluster_regs, 2473 .nr_cluster_regs = ARRAY_SIZE(rk3568_vop_cluster_regs), 2474 .smart_reg = rk3568_vop_smart_regs, 2475 .nr_smart_regs = ARRAY_SIZE(rk3568_vop_smart_regs), 2476 .regs_dump = rk3568_regs_dump, 2477 .regs_dump_size = ARRAY_SIZE(rk3568_regs_dump), 2478 .ops = &rk3568_vop_ops, 2479 .soc_id = 3566, 2480 }; 2481 2482 static const struct vop2_data rk3568_vop = { 2483 .version = VOP_VERSION_RK3568, 2484 .feature = VOP2_FEATURE_HAS_SYS_GRF, 2485 .nr_vps = 3, 2486 .max_input = { 4096, 2304 }, 2487 .max_output = { 4096, 2304 }, 2488 .vp = rk3568_vop_video_ports, 2489 .win = rk3568_vop_win_data, 2490 .win_size = ARRAY_SIZE(rk3568_vop_win_data), 2491 .cluster_reg = rk3568_vop_cluster_regs, 2492 .nr_cluster_regs = ARRAY_SIZE(rk3568_vop_cluster_regs), 2493 .smart_reg = rk3568_vop_smart_regs, 2494 .nr_smart_regs = ARRAY_SIZE(rk3568_vop_smart_regs), 2495 .regs_dump = rk3568_regs_dump, 2496 .regs_dump_size = ARRAY_SIZE(rk3568_regs_dump), 2497 .ops = &rk3568_vop_ops, 2498 .soc_id = 3568, 2499 }; 2500 2501 static const struct vop2_data rk3576_vop = { 2502 .version = VOP_VERSION_RK3576, 2503 .feature = VOP2_FEATURE_HAS_SYS_PMU, 2504 .nr_vps = 3, 2505 .max_input = { 4096, 4320 }, 2506 .max_output = { 4096, 4320 }, 2507 .vp = rk3576_vop_video_ports, 2508 .win = rk3576_vop_win_data, 2509 .win_size = ARRAY_SIZE(rk3576_vop_win_data), 2510 .cluster_reg = rk3576_vop_cluster_regs, 2511 .nr_cluster_regs = ARRAY_SIZE(rk3576_vop_cluster_regs), 2512 .smart_reg = rk3576_vop_smart_regs, 2513 .nr_smart_regs = ARRAY_SIZE(rk3576_vop_smart_regs), 2514 .regs_dump = rk3576_regs_dump, 2515 .regs_dump_size = ARRAY_SIZE(rk3576_regs_dump), 2516 .ops = &rk3576_vop_ops, 2517 .soc_id = 3576, 2518 }; 2519 2520 static const struct vop2_data rk3588_vop = { 2521 .version = VOP_VERSION_RK3588, 2522 .feature = VOP2_FEATURE_HAS_SYS_GRF | VOP2_FEATURE_HAS_VO1_GRF | 2523 VOP2_FEATURE_HAS_VOP_GRF | VOP2_FEATURE_HAS_SYS_PMU, 2524 .nr_vps = 4, 2525 .max_input = { 4096, 4320 }, 2526 .max_output = { 4096, 4320 }, 2527 .vp = rk3588_vop_video_ports, 2528 .win = rk3588_vop_win_data, 2529 .win_size = ARRAY_SIZE(rk3588_vop_win_data), 2530 .cluster_reg = rk3568_vop_cluster_regs, 2531 .nr_cluster_regs = ARRAY_SIZE(rk3568_vop_cluster_regs), 2532 .smart_reg = rk3568_vop_smart_regs, 2533 .nr_smart_regs = ARRAY_SIZE(rk3568_vop_smart_regs), 2534 .regs_dump = rk3588_regs_dump, 2535 .regs_dump_size = ARRAY_SIZE(rk3588_regs_dump), 2536 .ops = &rk3588_vop_ops, 2537 .soc_id = 3588, 2538 }; 2539 2540 static const struct of_device_id vop2_dt_match[] = { 2541 { 2542 .compatible = "rockchip,rk3566-vop", 2543 .data = &rk3566_vop, 2544 }, { 2545 .compatible = "rockchip,rk3568-vop", 2546 .data = &rk3568_vop, 2547 }, { 2548 .compatible = "rockchip,rk3576-vop", 2549 .data = &rk3576_vop, 2550 }, { 2551 .compatible = "rockchip,rk3588-vop", 2552 .data = &rk3588_vop 2553 }, { 2554 }, 2555 }; 2556 MODULE_DEVICE_TABLE(of, vop2_dt_match); 2557 2558 static int vop2_probe(struct platform_device *pdev) 2559 { 2560 struct device *dev = &pdev->dev; 2561 2562 return component_add(dev, &vop2_component_ops); 2563 } 2564 2565 static void vop2_remove(struct platform_device *pdev) 2566 { 2567 component_del(&pdev->dev, &vop2_component_ops); 2568 } 2569 2570 struct platform_driver vop2_platform_driver = { 2571 .probe = vop2_probe, 2572 .remove = vop2_remove, 2573 .driver = { 2574 .name = "rockchip-vop2", 2575 .of_match_table = vop2_dt_match, 2576 }, 2577 }; 2578