File Index
Files and directories
Sign in
FILE

rockchip_vop2_reg.c

File preview with syntax highlighting.

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