Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
0004  * Author:Mark Yao <mark.yao@rock-chips.com>
0005  */
0006 
0007 #include <linux/component.h>
0008 #include <linux/mod_devicetable.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/platform_device.h>
0012 
0013 #include <drm/drm_fourcc.h>
0014 #include <drm/drm_plane.h>
0015 #include <drm/drm_print.h>
0016 
0017 #include "rockchip_drm_vop.h"
0018 #include "rockchip_vop_reg.h"
0019 #include "rockchip_drm_drv.h"
0020 
0021 #define _VOP_REG(off, _mask, _shift, _write_mask, _relaxed) \
0022         { \
0023          .offset = off, \
0024          .mask = _mask, \
0025          .shift = _shift, \
0026          .write_mask = _write_mask, \
0027          .relaxed = _relaxed, \
0028         }
0029 
0030 #define VOP_REG(off, _mask, _shift) \
0031         _VOP_REG(off, _mask, _shift, false, true)
0032 
0033 #define VOP_REG_SYNC(off, _mask, _shift) \
0034         _VOP_REG(off, _mask, _shift, false, false)
0035 
0036 #define VOP_REG_MASK_SYNC(off, _mask, _shift) \
0037         _VOP_REG(off, _mask, _shift, true, false)
0038 
0039 static const uint32_t formats_win_full[] = {
0040     DRM_FORMAT_XRGB8888,
0041     DRM_FORMAT_ARGB8888,
0042     DRM_FORMAT_XBGR8888,
0043     DRM_FORMAT_ABGR8888,
0044     DRM_FORMAT_RGB888,
0045     DRM_FORMAT_BGR888,
0046     DRM_FORMAT_RGB565,
0047     DRM_FORMAT_BGR565,
0048     DRM_FORMAT_NV12,
0049     DRM_FORMAT_NV21,
0050     DRM_FORMAT_NV16,
0051     DRM_FORMAT_NV61,
0052     DRM_FORMAT_NV24,
0053     DRM_FORMAT_NV42,
0054 };
0055 
0056 static const uint64_t format_modifiers_win_full[] = {
0057     DRM_FORMAT_MOD_LINEAR,
0058     DRM_FORMAT_MOD_INVALID,
0059 };
0060 
0061 static const uint64_t format_modifiers_win_full_afbc[] = {
0062     ROCKCHIP_AFBC_MOD,
0063     DRM_FORMAT_MOD_LINEAR,
0064     DRM_FORMAT_MOD_INVALID,
0065 };
0066 
0067 static const uint32_t formats_win_lite[] = {
0068     DRM_FORMAT_XRGB8888,
0069     DRM_FORMAT_ARGB8888,
0070     DRM_FORMAT_XBGR8888,
0071     DRM_FORMAT_ABGR8888,
0072     DRM_FORMAT_RGB888,
0073     DRM_FORMAT_BGR888,
0074     DRM_FORMAT_RGB565,
0075     DRM_FORMAT_BGR565,
0076 };
0077 
0078 static const uint64_t format_modifiers_win_lite[] = {
0079     DRM_FORMAT_MOD_LINEAR,
0080     DRM_FORMAT_MOD_INVALID,
0081 };
0082 
0083 static const struct vop_scl_regs rk3036_win0_scl = {
0084     .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
0085     .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
0086     .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
0087     .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
0088 };
0089 
0090 static const struct vop_scl_regs rk3036_win1_scl = {
0091     .scale_yrgb_x = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 0x0),
0092     .scale_yrgb_y = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 16),
0093 };
0094 
0095 static const struct vop_win_phy rk3036_win0_data = {
0096     .scl = &rk3036_win0_scl,
0097     .data_formats = formats_win_full,
0098     .nformats = ARRAY_SIZE(formats_win_full),
0099     .format_modifiers = format_modifiers_win_full,
0100     .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
0101     .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
0102     .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
0103     .act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
0104     .dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
0105     .dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
0106     .yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
0107     .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
0108     .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
0109     .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16),
0110     .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 18),
0111     .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 0),
0112     .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29),
0113 };
0114 
0115 static const struct vop_win_phy rk3036_win1_data = {
0116     .scl = &rk3036_win1_scl,
0117     .data_formats = formats_win_lite,
0118     .nformats = ARRAY_SIZE(formats_win_lite),
0119     .format_modifiers = format_modifiers_win_lite,
0120     .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
0121     .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
0122     .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
0123     .act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
0124     .dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
0125     .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
0126     .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
0127     .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
0128     .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19),
0129     .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1),
0130     .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29),
0131 };
0132 
0133 static const struct vop_win_data rk3036_vop_win_data[] = {
0134     { .base = 0x00, .phy = &rk3036_win0_data,
0135       .type = DRM_PLANE_TYPE_PRIMARY },
0136     { .base = 0x00, .phy = &rk3036_win1_data,
0137       .type = DRM_PLANE_TYPE_CURSOR },
0138 };
0139 
0140 static const int rk3036_vop_intrs[] = {
0141     DSP_HOLD_VALID_INTR,
0142     FS_INTR,
0143     LINE_FLAG_INTR,
0144     BUS_ERROR_INTR,
0145 };
0146 
0147 static const struct vop_intr rk3036_intr = {
0148     .intrs = rk3036_vop_intrs,
0149     .nintrs = ARRAY_SIZE(rk3036_vop_intrs),
0150     .line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12),
0151     .status = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 0),
0152     .enable = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 4),
0153     .clear = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 8),
0154 };
0155 
0156 static const struct vop_modeset rk3036_modeset = {
0157     .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
0158     .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
0159     .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
0160     .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
0161 };
0162 
0163 static const struct vop_output rk3036_output = {
0164     .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
0165 };
0166 
0167 static const struct vop_common rk3036_common = {
0168     .standby = VOP_REG_SYNC(RK3036_SYS_CTRL, 0x1, 30),
0169     .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
0170     .dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24),
0171     .dither_down_sel = VOP_REG(RK3036_DSP_CTRL0, 0x1, 27),
0172     .dither_down_en = VOP_REG(RK3036_DSP_CTRL0, 0x1, 11),
0173     .dither_down_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 10),
0174     .cfg_done = VOP_REG_SYNC(RK3036_REG_CFG_DONE, 0x1, 0),
0175 };
0176 
0177 static const struct vop_data rk3036_vop = {
0178     .intr = &rk3036_intr,
0179     .common = &rk3036_common,
0180     .modeset = &rk3036_modeset,
0181     .output = &rk3036_output,
0182     .win = rk3036_vop_win_data,
0183     .win_size = ARRAY_SIZE(rk3036_vop_win_data),
0184 };
0185 
0186 static const struct vop_win_phy rk3126_win1_data = {
0187     .data_formats = formats_win_lite,
0188     .nformats = ARRAY_SIZE(formats_win_lite),
0189     .format_modifiers = format_modifiers_win_lite,
0190     .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
0191     .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
0192     .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
0193     .dsp_info = VOP_REG(RK3126_WIN1_DSP_INFO, 0x0fff0fff, 0),
0194     .dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0),
0195     .yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0),
0196     .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
0197     .alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19),
0198     .alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1),
0199     .alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29),
0200 };
0201 
0202 static const struct vop_win_data rk3126_vop_win_data[] = {
0203     { .base = 0x00, .phy = &rk3036_win0_data,
0204       .type = DRM_PLANE_TYPE_PRIMARY },
0205     { .base = 0x00, .phy = &rk3126_win1_data,
0206       .type = DRM_PLANE_TYPE_CURSOR },
0207 };
0208 
0209 static const struct vop_data rk3126_vop = {
0210     .intr = &rk3036_intr,
0211     .common = &rk3036_common,
0212     .modeset = &rk3036_modeset,
0213     .output = &rk3036_output,
0214     .win = rk3126_vop_win_data,
0215     .win_size = ARRAY_SIZE(rk3126_vop_win_data),
0216 };
0217 
0218 static const int px30_vop_intrs[] = {
0219     FS_INTR,
0220     0, 0,
0221     LINE_FLAG_INTR,
0222     0,
0223     BUS_ERROR_INTR,
0224     0, 0,
0225     DSP_HOLD_VALID_INTR,
0226 };
0227 
0228 static const struct vop_intr px30_intr = {
0229     .intrs = px30_vop_intrs,
0230     .nintrs = ARRAY_SIZE(px30_vop_intrs),
0231     .line_flag_num[0] = VOP_REG(PX30_LINE_FLAG, 0xfff, 0),
0232     .status = VOP_REG_MASK_SYNC(PX30_INTR_STATUS, 0xffff, 0),
0233     .enable = VOP_REG_MASK_SYNC(PX30_INTR_EN, 0xffff, 0),
0234     .clear = VOP_REG_MASK_SYNC(PX30_INTR_CLEAR, 0xffff, 0),
0235 };
0236 
0237 static const struct vop_common px30_common = {
0238     .standby = VOP_REG_SYNC(PX30_SYS_CTRL2, 0x1, 1),
0239     .out_mode = VOP_REG(PX30_DSP_CTRL2, 0xf, 16),
0240     .dsp_blank = VOP_REG(PX30_DSP_CTRL2, 0x1, 14),
0241     .dither_down_en = VOP_REG(PX30_DSP_CTRL2, 0x1, 8),
0242     .dither_down_sel = VOP_REG(PX30_DSP_CTRL2, 0x1, 7),
0243     .dither_down_mode = VOP_REG(PX30_DSP_CTRL2, 0x1, 6),
0244     .cfg_done = VOP_REG_SYNC(PX30_REG_CFG_DONE, 0x1, 0),
0245 };
0246 
0247 static const struct vop_modeset px30_modeset = {
0248     .htotal_pw = VOP_REG(PX30_DSP_HTOTAL_HS_END, 0x0fff0fff, 0),
0249     .hact_st_end = VOP_REG(PX30_DSP_HACT_ST_END, 0x0fff0fff, 0),
0250     .vtotal_pw = VOP_REG(PX30_DSP_VTOTAL_VS_END, 0x0fff0fff, 0),
0251     .vact_st_end = VOP_REG(PX30_DSP_VACT_ST_END, 0x0fff0fff, 0),
0252 };
0253 
0254 static const struct vop_output px30_output = {
0255     .rgb_dclk_pol = VOP_REG(PX30_DSP_CTRL0, 0x1, 1),
0256     .rgb_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0x7, 2),
0257     .rgb_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 0),
0258     .mipi_dclk_pol = VOP_REG(PX30_DSP_CTRL0, 0x1, 25),
0259     .mipi_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0x7, 26),
0260     .mipi_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 24),
0261 };
0262 
0263 static const struct vop_scl_regs px30_win_scl = {
0264     .scale_yrgb_x = VOP_REG(PX30_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
0265     .scale_yrgb_y = VOP_REG(PX30_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
0266     .scale_cbcr_x = VOP_REG(PX30_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
0267     .scale_cbcr_y = VOP_REG(PX30_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
0268 };
0269 
0270 static const struct vop_win_phy px30_win0_data = {
0271     .scl = &px30_win_scl,
0272     .data_formats = formats_win_full,
0273     .nformats = ARRAY_SIZE(formats_win_full),
0274     .format_modifiers = format_modifiers_win_full,
0275     .enable = VOP_REG(PX30_WIN0_CTRL0, 0x1, 0),
0276     .format = VOP_REG(PX30_WIN0_CTRL0, 0x7, 1),
0277     .rb_swap = VOP_REG(PX30_WIN0_CTRL0, 0x1, 12),
0278     .uv_swap = VOP_REG(PX30_WIN0_CTRL0, 0x1, 15),
0279     .act_info = VOP_REG(PX30_WIN0_ACT_INFO, 0xffffffff, 0),
0280     .dsp_info = VOP_REG(PX30_WIN0_DSP_INFO, 0xffffffff, 0),
0281     .dsp_st = VOP_REG(PX30_WIN0_DSP_ST, 0xffffffff, 0),
0282     .yrgb_mst = VOP_REG(PX30_WIN0_YRGB_MST0, 0xffffffff, 0),
0283     .uv_mst = VOP_REG(PX30_WIN0_CBR_MST0, 0xffffffff, 0),
0284     .yrgb_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 0),
0285     .uv_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 16),
0286     .alpha_pre_mul = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 2),
0287     .alpha_mode = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 1),
0288     .alpha_en = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 0),
0289 };
0290 
0291 static const struct vop_win_phy px30_win1_data = {
0292     .data_formats = formats_win_lite,
0293     .nformats = ARRAY_SIZE(formats_win_lite),
0294     .format_modifiers = format_modifiers_win_lite,
0295     .enable = VOP_REG(PX30_WIN1_CTRL0, 0x1, 0),
0296     .format = VOP_REG(PX30_WIN1_CTRL0, 0x7, 4),
0297     .rb_swap = VOP_REG(PX30_WIN1_CTRL0, 0x1, 12),
0298     .uv_swap = VOP_REG(PX30_WIN1_CTRL0, 0x1, 15),
0299     .dsp_info = VOP_REG(PX30_WIN1_DSP_INFO, 0xffffffff, 0),
0300     .dsp_st = VOP_REG(PX30_WIN1_DSP_ST, 0xffffffff, 0),
0301     .yrgb_mst = VOP_REG(PX30_WIN1_MST, 0xffffffff, 0),
0302     .yrgb_vir = VOP_REG(PX30_WIN1_VIR, 0x1fff, 0),
0303     .alpha_pre_mul = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 2),
0304     .alpha_mode = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 1),
0305     .alpha_en = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 0),
0306 };
0307 
0308 static const struct vop_win_phy px30_win2_data = {
0309     .data_formats = formats_win_lite,
0310     .nformats = ARRAY_SIZE(formats_win_lite),
0311     .format_modifiers = format_modifiers_win_lite,
0312     .gate = VOP_REG(PX30_WIN2_CTRL0, 0x1, 4),
0313     .enable = VOP_REG(PX30_WIN2_CTRL0, 0x1, 0),
0314     .format = VOP_REG(PX30_WIN2_CTRL0, 0x3, 5),
0315     .rb_swap = VOP_REG(PX30_WIN2_CTRL0, 0x1, 20),
0316     .dsp_info = VOP_REG(PX30_WIN2_DSP_INFO0, 0x0fff0fff, 0),
0317     .dsp_st = VOP_REG(PX30_WIN2_DSP_ST0, 0x1fff1fff, 0),
0318     .yrgb_mst = VOP_REG(PX30_WIN2_MST0, 0xffffffff, 0),
0319     .yrgb_vir = VOP_REG(PX30_WIN2_VIR0_1, 0x1fff, 0),
0320     .alpha_pre_mul = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 2),
0321     .alpha_mode = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 1),
0322     .alpha_en = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 0),
0323 };
0324 
0325 static const struct vop_win_data px30_vop_big_win_data[] = {
0326     { .base = 0x00, .phy = &px30_win0_data,
0327       .type = DRM_PLANE_TYPE_PRIMARY },
0328     { .base = 0x00, .phy = &px30_win1_data,
0329       .type = DRM_PLANE_TYPE_OVERLAY },
0330     { .base = 0x00, .phy = &px30_win2_data,
0331       .type = DRM_PLANE_TYPE_CURSOR },
0332 };
0333 
0334 static const struct vop_data px30_vop_big = {
0335     .version = VOP_VERSION(2, 6),
0336     .intr = &px30_intr,
0337     .feature = VOP_FEATURE_INTERNAL_RGB,
0338     .common = &px30_common,
0339     .modeset = &px30_modeset,
0340     .output = &px30_output,
0341     .win = px30_vop_big_win_data,
0342     .win_size = ARRAY_SIZE(px30_vop_big_win_data),
0343 };
0344 
0345 static const struct vop_win_data px30_vop_lit_win_data[] = {
0346     { .base = 0x00, .phy = &px30_win1_data,
0347       .type = DRM_PLANE_TYPE_PRIMARY },
0348 };
0349 
0350 static const struct vop_data px30_vop_lit = {
0351     .version = VOP_VERSION(2, 5),
0352     .intr = &px30_intr,
0353     .feature = VOP_FEATURE_INTERNAL_RGB,
0354     .common = &px30_common,
0355     .modeset = &px30_modeset,
0356     .output = &px30_output,
0357     .win = px30_vop_lit_win_data,
0358     .win_size = ARRAY_SIZE(px30_vop_lit_win_data),
0359 };
0360 
0361 static const struct vop_scl_regs rk3066_win_scl = {
0362     .scale_yrgb_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
0363     .scale_yrgb_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
0364     .scale_cbcr_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
0365     .scale_cbcr_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
0366 };
0367 
0368 static const struct vop_win_phy rk3066_win0_data = {
0369     .scl = &rk3066_win_scl,
0370     .data_formats = formats_win_full,
0371     .nformats = ARRAY_SIZE(formats_win_full),
0372     .format_modifiers = format_modifiers_win_full,
0373     .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0),
0374     .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 4),
0375     .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 19),
0376     .uv_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 22),
0377     .act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0),
0378     .dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0),
0379     .dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0),
0380     .yrgb_mst = VOP_REG(RK3066_WIN0_YRGB_MST0, 0xffffffff, 0),
0381     .uv_mst = VOP_REG(RK3066_WIN0_CBR_MST0, 0xffffffff, 0),
0382     .yrgb_vir = VOP_REG(RK3066_WIN0_VIR, 0xffff, 0),
0383     .uv_vir = VOP_REG(RK3066_WIN0_VIR, 0x1fff, 16),
0384     .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 21),
0385     .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 0),
0386 };
0387 
0388 static const struct vop_win_phy rk3066_win1_data = {
0389     .data_formats = formats_win_full,
0390     .nformats = ARRAY_SIZE(formats_win_full),
0391     .format_modifiers = format_modifiers_win_full,
0392     .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1),
0393     .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 7),
0394     .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 23),
0395     .uv_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 26),
0396     .act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0),
0397     .dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0),
0398     .dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0),
0399     .yrgb_mst = VOP_REG(RK3066_WIN1_YRGB_MST, 0xffffffff, 0),
0400     .uv_mst = VOP_REG(RK3066_WIN1_CBR_MST, 0xffffffff, 0),
0401     .yrgb_vir = VOP_REG(RK3066_WIN1_VIR, 0xffff, 0),
0402     .uv_vir = VOP_REG(RK3066_WIN1_VIR, 0x1fff, 16),
0403     .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 22),
0404     .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 1),
0405 };
0406 
0407 static const struct vop_win_phy rk3066_win2_data = {
0408     .data_formats = formats_win_lite,
0409     .nformats = ARRAY_SIZE(formats_win_lite),
0410     .format_modifiers = format_modifiers_win_lite,
0411     .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2),
0412     .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 10),
0413     .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 27),
0414     .dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0),
0415     .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0),
0416     .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0),
0417     .yrgb_vir = VOP_REG(RK3066_WIN2_VIR, 0xffff, 0),
0418     .alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 23),
0419     .alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 2),
0420 };
0421 
0422 static const struct vop_modeset rk3066_modeset = {
0423     .htotal_pw = VOP_REG(RK3066_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
0424     .hact_st_end = VOP_REG(RK3066_DSP_HACT_ST_END, 0x1fff1fff, 0),
0425     .vtotal_pw = VOP_REG(RK3066_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
0426     .vact_st_end = VOP_REG(RK3066_DSP_VACT_ST_END, 0x1fff1fff, 0),
0427 };
0428 
0429 static const struct vop_output rk3066_output = {
0430     .pin_pol = VOP_REG(RK3066_DSP_CTRL0, 0x7, 4),
0431 };
0432 
0433 static const struct vop_common rk3066_common = {
0434     .standby = VOP_REG(RK3066_SYS_CTRL0, 0x1, 1),
0435     .out_mode = VOP_REG(RK3066_DSP_CTRL0, 0xf, 0),
0436     .cfg_done = VOP_REG(RK3066_REG_CFG_DONE, 0x1, 0),
0437     .dither_down_en = VOP_REG(RK3066_DSP_CTRL0, 0x1, 11),
0438     .dither_down_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 10),
0439     .dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24),
0440     .dither_up = VOP_REG(RK3066_DSP_CTRL0, 0x1, 9),
0441     .dsp_lut_en = VOP_REG(RK3066_SYS_CTRL1, 0x1, 31),
0442     .data_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 25),
0443 };
0444 
0445 static const struct vop_win_data rk3066_vop_win_data[] = {
0446     { .base = 0x00, .phy = &rk3066_win0_data,
0447       .type = DRM_PLANE_TYPE_PRIMARY },
0448     { .base = 0x00, .phy = &rk3066_win1_data,
0449       .type = DRM_PLANE_TYPE_OVERLAY },
0450     { .base = 0x00, .phy = &rk3066_win2_data,
0451       .type = DRM_PLANE_TYPE_CURSOR },
0452 };
0453 
0454 static const int rk3066_vop_intrs[] = {
0455     /*
0456      * hs_start interrupt fires at frame-start, so serves
0457      * the same purpose as dsp_hold in the driver.
0458      */
0459     DSP_HOLD_VALID_INTR,
0460     FS_INTR,
0461     LINE_FLAG_INTR,
0462     BUS_ERROR_INTR,
0463 };
0464 
0465 static const struct vop_intr rk3066_intr = {
0466     .intrs = rk3066_vop_intrs,
0467     .nintrs = ARRAY_SIZE(rk3066_vop_intrs),
0468     .line_flag_num[0] = VOP_REG(RK3066_INT_STATUS, 0xfff, 12),
0469     .status = VOP_REG(RK3066_INT_STATUS, 0xf, 0),
0470     .enable = VOP_REG(RK3066_INT_STATUS, 0xf, 4),
0471     .clear = VOP_REG(RK3066_INT_STATUS, 0xf, 8),
0472 };
0473 
0474 static const struct vop_data rk3066_vop = {
0475     .version = VOP_VERSION(2, 1),
0476     .intr = &rk3066_intr,
0477     .common = &rk3066_common,
0478     .modeset = &rk3066_modeset,
0479     .output = &rk3066_output,
0480     .win = rk3066_vop_win_data,
0481     .win_size = ARRAY_SIZE(rk3066_vop_win_data),
0482 };
0483 
0484 static const struct vop_scl_regs rk3188_win_scl = {
0485     .scale_yrgb_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
0486     .scale_yrgb_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
0487     .scale_cbcr_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
0488     .scale_cbcr_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
0489 };
0490 
0491 static const struct vop_win_phy rk3188_win0_data = {
0492     .scl = &rk3188_win_scl,
0493     .data_formats = formats_win_full,
0494     .nformats = ARRAY_SIZE(formats_win_full),
0495     .format_modifiers = format_modifiers_win_full,
0496     .enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 0),
0497     .format = VOP_REG(RK3188_SYS_CTRL, 0x7, 3),
0498     .rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 15),
0499     .uv_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 18),
0500     .act_info = VOP_REG(RK3188_WIN0_ACT_INFO, 0x1fff1fff, 0),
0501     .dsp_info = VOP_REG(RK3188_WIN0_DSP_INFO, 0x0fff0fff, 0),
0502     .dsp_st = VOP_REG(RK3188_WIN0_DSP_ST, 0x1fff1fff, 0),
0503     .yrgb_mst = VOP_REG(RK3188_WIN0_YRGB_MST0, 0xffffffff, 0),
0504     .uv_mst = VOP_REG(RK3188_WIN0_CBR_MST0, 0xffffffff, 0),
0505     .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 0),
0506     .alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 18),
0507     .alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 0),
0508     .alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29),
0509 };
0510 
0511 static const struct vop_win_phy rk3188_win1_data = {
0512     .data_formats = formats_win_lite,
0513     .nformats = ARRAY_SIZE(formats_win_lite),
0514     .format_modifiers = format_modifiers_win_lite,
0515     .enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 1),
0516     .format = VOP_REG(RK3188_SYS_CTRL, 0x7, 6),
0517     .rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 19),
0518     /* no act_info on window1 */
0519     .dsp_info = VOP_REG(RK3188_WIN1_DSP_INFO, 0x07ff07ff, 0),
0520     .dsp_st = VOP_REG(RK3188_WIN1_DSP_ST, 0x0fff0fff, 0),
0521     .yrgb_mst = VOP_REG(RK3188_WIN1_MST, 0xffffffff, 0),
0522     .yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 16),
0523     .alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 19),
0524     .alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 1),
0525     .alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29),
0526 };
0527 
0528 static const struct vop_modeset rk3188_modeset = {
0529     .htotal_pw = VOP_REG(RK3188_DSP_HTOTAL_HS_END, 0x0fff0fff, 0),
0530     .hact_st_end = VOP_REG(RK3188_DSP_HACT_ST_END, 0x0fff0fff, 0),
0531     .vtotal_pw = VOP_REG(RK3188_DSP_VTOTAL_VS_END, 0x0fff0fff, 0),
0532     .vact_st_end = VOP_REG(RK3188_DSP_VACT_ST_END, 0x0fff0fff, 0),
0533 };
0534 
0535 static const struct vop_output rk3188_output = {
0536     .pin_pol = VOP_REG(RK3188_DSP_CTRL0, 0xf, 4),
0537 };
0538 
0539 static const struct vop_common rk3188_common = {
0540     .gate_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 31),
0541     .standby = VOP_REG(RK3188_SYS_CTRL, 0x1, 30),
0542     .out_mode = VOP_REG(RK3188_DSP_CTRL0, 0xf, 0),
0543     .cfg_done = VOP_REG(RK3188_REG_CFG_DONE, 0x1, 0),
0544     .dither_down_sel = VOP_REG(RK3188_DSP_CTRL0, 0x1, 27),
0545     .dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11),
0546     .dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10),
0547     .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 24),
0548     .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9),
0549     .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28),
0550     .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25),
0551 };
0552 
0553 static const struct vop_win_data rk3188_vop_win_data[] = {
0554     { .base = 0x00, .phy = &rk3188_win0_data,
0555       .type = DRM_PLANE_TYPE_PRIMARY },
0556     { .base = 0x00, .phy = &rk3188_win1_data,
0557       .type = DRM_PLANE_TYPE_CURSOR },
0558 };
0559 
0560 static const int rk3188_vop_intrs[] = {
0561     /*
0562      * hs_start interrupt fires at frame-start, so serves
0563      * the same purpose as dsp_hold in the driver.
0564      */
0565     DSP_HOLD_VALID_INTR,
0566     FS_INTR,
0567     LINE_FLAG_INTR,
0568     BUS_ERROR_INTR,
0569 };
0570 
0571 static const struct vop_intr rk3188_vop_intr = {
0572     .intrs = rk3188_vop_intrs,
0573     .nintrs = ARRAY_SIZE(rk3188_vop_intrs),
0574     .line_flag_num[0] = VOP_REG(RK3188_INT_STATUS, 0xfff, 12),
0575     .status = VOP_REG(RK3188_INT_STATUS, 0xf, 0),
0576     .enable = VOP_REG(RK3188_INT_STATUS, 0xf, 4),
0577     .clear = VOP_REG(RK3188_INT_STATUS, 0xf, 8),
0578 };
0579 
0580 static const struct vop_data rk3188_vop = {
0581     .intr = &rk3188_vop_intr,
0582     .common = &rk3188_common,
0583     .modeset = &rk3188_modeset,
0584     .output = &rk3188_output,
0585     .win = rk3188_vop_win_data,
0586     .win_size = ARRAY_SIZE(rk3188_vop_win_data),
0587     .feature = VOP_FEATURE_INTERNAL_RGB,
0588 };
0589 
0590 static const struct vop_scl_extension rk3288_win_full_scl_ext = {
0591     .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
0592     .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
0593     .cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28),
0594     .cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26),
0595     .cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24),
0596     .yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23),
0597     .yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22),
0598     .yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20),
0599     .yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18),
0600     .yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16),
0601     .line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15),
0602     .cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12),
0603     .yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8),
0604     .vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7),
0605     .vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6),
0606     .vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5),
0607     .vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4),
0608     .bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2),
0609     .cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1),
0610     .yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0),
0611     .lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5),
0612 };
0613 
0614 static const struct vop_scl_regs rk3288_win_full_scl = {
0615     .ext = &rk3288_win_full_scl_ext,
0616     .scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
0617     .scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
0618     .scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
0619     .scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
0620 };
0621 
0622 static const struct vop_win_phy rk3288_win01_data = {
0623     .scl = &rk3288_win_full_scl,
0624     .data_formats = formats_win_full,
0625     .nformats = ARRAY_SIZE(formats_win_full),
0626     .format_modifiers = format_modifiers_win_full,
0627     .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
0628     .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
0629     .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
0630     .uv_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 15),
0631     .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
0632     .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
0633     .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
0634     .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
0635     .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
0636     .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
0637     .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
0638     .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
0639     .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
0640     .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0),
0641 };
0642 
0643 static const struct vop_win_phy rk3288_win23_data = {
0644     .data_formats = formats_win_lite,
0645     .nformats = ARRAY_SIZE(formats_win_lite),
0646     .format_modifiers = format_modifiers_win_lite,
0647     .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4),
0648     .gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
0649     .format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
0650     .rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
0651     .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
0652     .dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0),
0653     .yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0),
0654     .yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0),
0655     .src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
0656     .dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
0657 };
0658 
0659 static const struct vop_modeset rk3288_modeset = {
0660     .htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
0661     .hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0),
0662     .vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
0663     .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
0664     .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
0665     .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
0666 };
0667 
0668 static const struct vop_output rk3288_output = {
0669     .pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4),
0670     .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
0671     .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
0672     .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
0673     .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
0674 };
0675 
0676 static const struct vop_common rk3288_common = {
0677     .standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22),
0678     .gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
0679     .mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20),
0680     .dither_down_sel = VOP_REG(RK3288_DSP_CTRL1, 0x1, 4),
0681     .dither_down_mode = VOP_REG(RK3288_DSP_CTRL1, 0x1, 3),
0682     .dither_down_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 2),
0683     .pre_dither_down = VOP_REG(RK3288_DSP_CTRL1, 0x1, 1),
0684     .dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6),
0685     .dsp_lut_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 0),
0686     .data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19),
0687     .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18),
0688     .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
0689     .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0),
0690 };
0691 
0692 /*
0693  * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
0694  * special support to get alpha blending working.  For now, just use overlay
0695  * window 3 for the drm cursor.
0696  *
0697  */
0698 static const struct vop_win_data rk3288_vop_win_data[] = {
0699     { .base = 0x00, .phy = &rk3288_win01_data,
0700       .type = DRM_PLANE_TYPE_PRIMARY },
0701     { .base = 0x40, .phy = &rk3288_win01_data,
0702       .type = DRM_PLANE_TYPE_OVERLAY },
0703     { .base = 0x00, .phy = &rk3288_win23_data,
0704       .type = DRM_PLANE_TYPE_OVERLAY },
0705     { .base = 0x50, .phy = &rk3288_win23_data,
0706       .type = DRM_PLANE_TYPE_CURSOR },
0707 };
0708 
0709 static const int rk3288_vop_intrs[] = {
0710     DSP_HOLD_VALID_INTR,
0711     FS_INTR,
0712     LINE_FLAG_INTR,
0713     BUS_ERROR_INTR,
0714 };
0715 
0716 static const struct vop_intr rk3288_vop_intr = {
0717     .intrs = rk3288_vop_intrs,
0718     .nintrs = ARRAY_SIZE(rk3288_vop_intrs),
0719     .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12),
0720     .status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0),
0721     .enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4),
0722     .clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8),
0723 };
0724 
0725 static const struct vop_data rk3288_vop = {
0726     .version = VOP_VERSION(3, 1),
0727     .feature = VOP_FEATURE_OUTPUT_RGB10,
0728     .intr = &rk3288_vop_intr,
0729     .common = &rk3288_common,
0730     .modeset = &rk3288_modeset,
0731     .output = &rk3288_output,
0732     .win = rk3288_vop_win_data,
0733     .win_size = ARRAY_SIZE(rk3288_vop_win_data),
0734     .lut_size = 1024,
0735 };
0736 
0737 static const int rk3368_vop_intrs[] = {
0738     FS_INTR,
0739     0, 0,
0740     LINE_FLAG_INTR,
0741     0,
0742     BUS_ERROR_INTR,
0743     0, 0, 0, 0, 0, 0, 0,
0744     DSP_HOLD_VALID_INTR,
0745 };
0746 
0747 static const struct vop_intr rk3368_vop_intr = {
0748     .intrs = rk3368_vop_intrs,
0749     .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
0750     .line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0),
0751     .line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16),
0752     .status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0),
0753     .enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0),
0754     .clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0),
0755 };
0756 
0757 static const struct vop_win_phy rk3368_win01_data = {
0758     .scl = &rk3288_win_full_scl,
0759     .data_formats = formats_win_full,
0760     .nformats = ARRAY_SIZE(formats_win_full),
0761     .format_modifiers = format_modifiers_win_full,
0762     .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0),
0763     .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1),
0764     .rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12),
0765     .uv_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 15),
0766     .x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21),
0767     .y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22),
0768     .act_info = VOP_REG(RK3368_WIN0_ACT_INFO, 0x1fff1fff, 0),
0769     .dsp_info = VOP_REG(RK3368_WIN0_DSP_INFO, 0x0fff0fff, 0),
0770     .dsp_st = VOP_REG(RK3368_WIN0_DSP_ST, 0x1fff1fff, 0),
0771     .yrgb_mst = VOP_REG(RK3368_WIN0_YRGB_MST, 0xffffffff, 0),
0772     .uv_mst = VOP_REG(RK3368_WIN0_CBR_MST, 0xffffffff, 0),
0773     .yrgb_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 0),
0774     .uv_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 16),
0775     .src_alpha_ctl = VOP_REG(RK3368_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
0776     .dst_alpha_ctl = VOP_REG(RK3368_WIN0_DST_ALPHA_CTRL, 0xff, 0),
0777     .channel = VOP_REG(RK3368_WIN0_CTRL2, 0xff, 0),
0778 };
0779 
0780 static const struct vop_win_phy rk3368_win23_data = {
0781     .data_formats = formats_win_lite,
0782     .nformats = ARRAY_SIZE(formats_win_lite),
0783     .format_modifiers = format_modifiers_win_lite,
0784     .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0),
0785     .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4),
0786     .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5),
0787     .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20),
0788     .y_mir_en = VOP_REG(RK3368_WIN2_CTRL1, 0x1, 15),
0789     .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0),
0790     .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0),
0791     .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0),
0792     .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0),
0793     .src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
0794     .dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0),
0795 };
0796 
0797 static const struct vop_win_data rk3368_vop_win_data[] = {
0798     { .base = 0x00, .phy = &rk3368_win01_data,
0799       .type = DRM_PLANE_TYPE_PRIMARY },
0800     { .base = 0x40, .phy = &rk3368_win01_data,
0801       .type = DRM_PLANE_TYPE_OVERLAY },
0802     { .base = 0x00, .phy = &rk3368_win23_data,
0803       .type = DRM_PLANE_TYPE_OVERLAY },
0804     { .base = 0x50, .phy = &rk3368_win23_data,
0805       .type = DRM_PLANE_TYPE_CURSOR },
0806 };
0807 
0808 static const struct vop_output rk3368_output = {
0809     .rgb_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 19),
0810     .hdmi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 23),
0811     .edp_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 27),
0812     .mipi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 31),
0813     .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 16),
0814     .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 20),
0815     .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 24),
0816     .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 28),
0817     .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
0818     .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
0819     .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
0820     .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
0821 };
0822 
0823 static const struct vop_misc rk3368_misc = {
0824     .global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11),
0825 };
0826 
0827 static const struct vop_data rk3368_vop = {
0828     .version = VOP_VERSION(3, 2),
0829     .intr = &rk3368_vop_intr,
0830     .common = &rk3288_common,
0831     .modeset = &rk3288_modeset,
0832     .output = &rk3368_output,
0833     .misc = &rk3368_misc,
0834     .win = rk3368_vop_win_data,
0835     .win_size = ARRAY_SIZE(rk3368_vop_win_data),
0836 };
0837 
0838 static const struct vop_intr rk3366_vop_intr = {
0839     .intrs = rk3368_vop_intrs,
0840     .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
0841     .line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0),
0842     .line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16),
0843     .status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0),
0844     .enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0),
0845     .clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0),
0846 };
0847 
0848 static const struct vop_data rk3366_vop = {
0849     .version = VOP_VERSION(3, 4),
0850     .intr = &rk3366_vop_intr,
0851     .common = &rk3288_common,
0852     .modeset = &rk3288_modeset,
0853     .output = &rk3368_output,
0854     .misc = &rk3368_misc,
0855     .win = rk3368_vop_win_data,
0856     .win_size = ARRAY_SIZE(rk3368_vop_win_data),
0857 };
0858 
0859 static const struct vop_output rk3399_output = {
0860     .dp_dclk_pol = VOP_REG(RK3399_DSP_CTRL1, 0x1, 19),
0861     .rgb_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 19),
0862     .hdmi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 23),
0863     .edp_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 27),
0864     .mipi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 31),
0865     .dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0x7, 16),
0866     .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 16),
0867     .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 20),
0868     .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 24),
0869     .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 28),
0870     .dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11),
0871     .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
0872     .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
0873     .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
0874     .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
0875     .mipi_dual_channel_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 3),
0876 };
0877 
0878 static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win01_data = {
0879     .y2r_coefficients = {
0880         VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 0),
0881         VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 16),
0882         VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 0),
0883         VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 16),
0884         VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 0),
0885         VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 16),
0886         VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 0),
0887         VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 16),
0888         VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 16, 0xffff, 0),
0889         VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 20, 0xffffffff, 0),
0890         VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 24, 0xffffffff, 0),
0891         VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 28, 0xffffffff, 0),
0892     },
0893 };
0894 
0895 static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win23_data = { };
0896 
0897 static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = {
0898     { .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
0899       .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1) },
0900     { .base = 0x60, .phy = &rk3399_yuv2yuv_win01_data,
0901       .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9) },
0902     { .base = 0xC0, .phy = &rk3399_yuv2yuv_win23_data },
0903     { .base = 0x120, .phy = &rk3399_yuv2yuv_win23_data },
0904 
0905 };
0906 
0907 static const struct vop_win_phy rk3399_win01_data = {
0908     .scl = &rk3288_win_full_scl,
0909     .data_formats = formats_win_full,
0910     .nformats = ARRAY_SIZE(formats_win_full),
0911     .format_modifiers = format_modifiers_win_full_afbc,
0912     .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
0913     .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
0914     .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
0915     .uv_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 15),
0916     .x_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 21),
0917     .y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22),
0918     .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
0919     .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
0920     .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
0921     .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
0922     .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
0923     .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
0924     .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
0925     .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
0926     .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
0927     .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0),
0928 };
0929 
0930 /*
0931  * rk3399 vop big windows register layout is same as rk3288, but we
0932  * have a separate rk3399 win data array here so that we can advertise
0933  * AFBC on the primary plane.
0934  */
0935 static const struct vop_win_data rk3399_vop_win_data[] = {
0936     { .base = 0x00, .phy = &rk3399_win01_data,
0937       .type = DRM_PLANE_TYPE_PRIMARY },
0938     { .base = 0x40, .phy = &rk3368_win01_data,
0939       .type = DRM_PLANE_TYPE_OVERLAY },
0940     { .base = 0x00, .phy = &rk3368_win23_data,
0941       .type = DRM_PLANE_TYPE_OVERLAY },
0942     { .base = 0x50, .phy = &rk3368_win23_data,
0943       .type = DRM_PLANE_TYPE_CURSOR },
0944 };
0945 
0946 static const struct vop_afbc rk3399_vop_afbc = {
0947     .rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3),
0948     .enable = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0),
0949     .win_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1),
0950     .format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16),
0951     .hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21),
0952     .hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0),
0953     .pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0),
0954 };
0955 
0956 static const struct vop_data rk3399_vop_big = {
0957     .version = VOP_VERSION(3, 5),
0958     .feature = VOP_FEATURE_OUTPUT_RGB10,
0959     .intr = &rk3366_vop_intr,
0960     .common = &rk3288_common,
0961     .modeset = &rk3288_modeset,
0962     .output = &rk3399_output,
0963     .afbc = &rk3399_vop_afbc,
0964     .misc = &rk3368_misc,
0965     .win = rk3399_vop_win_data,
0966     .win_size = ARRAY_SIZE(rk3399_vop_win_data),
0967     .win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data,
0968 };
0969 
0970 static const struct vop_win_data rk3399_vop_lit_win_data[] = {
0971     { .base = 0x00, .phy = &rk3368_win01_data,
0972       .type = DRM_PLANE_TYPE_PRIMARY },
0973     { .base = 0x00, .phy = &rk3368_win23_data,
0974       .type = DRM_PLANE_TYPE_CURSOR},
0975 };
0976 
0977 static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = {
0978     { .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
0979       .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1)},
0980     { .base = 0x60, .phy = &rk3399_yuv2yuv_win23_data },
0981 };
0982 
0983 static const struct vop_data rk3399_vop_lit = {
0984     .version = VOP_VERSION(3, 6),
0985     .intr = &rk3366_vop_intr,
0986     .common = &rk3288_common,
0987     .modeset = &rk3288_modeset,
0988     .output = &rk3399_output,
0989     .misc = &rk3368_misc,
0990     .win = rk3399_vop_lit_win_data,
0991     .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data),
0992     .win_yuv2yuv = rk3399_vop_lit_win_yuv2yuv_data,
0993 };
0994 
0995 static const struct vop_win_data rk3228_vop_win_data[] = {
0996     { .base = 0x00, .phy = &rk3288_win01_data,
0997       .type = DRM_PLANE_TYPE_PRIMARY },
0998     { .base = 0x40, .phy = &rk3288_win01_data,
0999       .type = DRM_PLANE_TYPE_CURSOR },
1000 };
1001 
1002 static const struct vop_data rk3228_vop = {
1003     .version = VOP_VERSION(3, 7),
1004     .feature = VOP_FEATURE_OUTPUT_RGB10,
1005     .intr = &rk3366_vop_intr,
1006     .common = &rk3288_common,
1007     .modeset = &rk3288_modeset,
1008     .output = &rk3399_output,
1009     .misc = &rk3368_misc,
1010     .win = rk3228_vop_win_data,
1011     .win_size = ARRAY_SIZE(rk3228_vop_win_data),
1012 };
1013 
1014 static const struct vop_modeset rk3328_modeset = {
1015     .htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
1016     .hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0),
1017     .vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
1018     .vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0),
1019     .hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
1020     .vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
1021 };
1022 
1023 static const struct vop_output rk3328_output = {
1024     .rgb_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 19),
1025     .hdmi_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 23),
1026     .edp_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 27),
1027     .mipi_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 31),
1028     .rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12),
1029     .hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13),
1030     .edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14),
1031     .mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15),
1032     .rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 16),
1033     .hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 20),
1034     .edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 24),
1035     .mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 28),
1036 };
1037 
1038 static const struct vop_misc rk3328_misc = {
1039     .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11),
1040 };
1041 
1042 static const struct vop_common rk3328_common = {
1043     .standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22),
1044     .dither_down_sel = VOP_REG(RK3328_DSP_CTRL1, 0x1, 4),
1045     .dither_down_mode = VOP_REG(RK3328_DSP_CTRL1, 0x1, 3),
1046     .dither_down_en = VOP_REG(RK3328_DSP_CTRL1, 0x1, 2),
1047     .pre_dither_down = VOP_REG(RK3328_DSP_CTRL1, 0x1, 1),
1048     .dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6),
1049     .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18),
1050     .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0),
1051     .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0),
1052 };
1053 
1054 static const struct vop_intr rk3328_vop_intr = {
1055     .intrs = rk3368_vop_intrs,
1056     .nintrs = ARRAY_SIZE(rk3368_vop_intrs),
1057     .line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0),
1058     .line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16),
1059     .status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0),
1060     .enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0),
1061     .clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0),
1062 };
1063 
1064 static const struct vop_win_data rk3328_vop_win_data[] = {
1065     { .base = 0xd0, .phy = &rk3368_win01_data,
1066       .type = DRM_PLANE_TYPE_PRIMARY },
1067     { .base = 0x1d0, .phy = &rk3368_win01_data,
1068       .type = DRM_PLANE_TYPE_OVERLAY },
1069     { .base = 0x2d0, .phy = &rk3368_win01_data,
1070       .type = DRM_PLANE_TYPE_CURSOR },
1071 };
1072 
1073 static const struct vop_data rk3328_vop = {
1074     .version = VOP_VERSION(3, 8),
1075     .feature = VOP_FEATURE_OUTPUT_RGB10,
1076     .intr = &rk3328_vop_intr,
1077     .common = &rk3328_common,
1078     .modeset = &rk3328_modeset,
1079     .output = &rk3328_output,
1080     .misc = &rk3328_misc,
1081     .win = rk3328_vop_win_data,
1082     .win_size = ARRAY_SIZE(rk3328_vop_win_data),
1083 };
1084 
1085 static const struct of_device_id vop_driver_dt_match[] = {
1086     { .compatible = "rockchip,rk3036-vop",
1087       .data = &rk3036_vop },
1088     { .compatible = "rockchip,rk3126-vop",
1089       .data = &rk3126_vop },
1090     { .compatible = "rockchip,px30-vop-big",
1091       .data = &px30_vop_big },
1092     { .compatible = "rockchip,px30-vop-lit",
1093       .data = &px30_vop_lit },
1094     { .compatible = "rockchip,rk3066-vop",
1095       .data = &rk3066_vop },
1096     { .compatible = "rockchip,rk3188-vop",
1097       .data = &rk3188_vop },
1098     { .compatible = "rockchip,rk3288-vop",
1099       .data = &rk3288_vop },
1100     { .compatible = "rockchip,rk3368-vop",
1101       .data = &rk3368_vop },
1102     { .compatible = "rockchip,rk3366-vop",
1103       .data = &rk3366_vop },
1104     { .compatible = "rockchip,rk3399-vop-big",
1105       .data = &rk3399_vop_big },
1106     { .compatible = "rockchip,rk3399-vop-lit",
1107       .data = &rk3399_vop_lit },
1108     { .compatible = "rockchip,rk3228-vop",
1109       .data = &rk3228_vop },
1110     { .compatible = "rockchip,rk3328-vop",
1111       .data = &rk3328_vop },
1112     {},
1113 };
1114 MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
1115 
1116 static int vop_probe(struct platform_device *pdev)
1117 {
1118     struct device *dev = &pdev->dev;
1119 
1120     if (!dev->of_node) {
1121         DRM_DEV_ERROR(dev, "can't find vop devices\n");
1122         return -ENODEV;
1123     }
1124 
1125     return component_add(dev, &vop_component_ops);
1126 }
1127 
1128 static int vop_remove(struct platform_device *pdev)
1129 {
1130     component_del(&pdev->dev, &vop_component_ops);
1131 
1132     return 0;
1133 }
1134 
1135 struct platform_driver vop_platform_driver = {
1136     .probe = vop_probe,
1137     .remove = vop_remove,
1138     .driver = {
1139         .name = "rockchip-vop",
1140         .of_match_table = vop_driver_dt_match,
1141     },
1142 };