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