Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
   4 * Author:Mark Yao <mark.yao@rock-chips.com>
   5 */
   6
   7#include <linux/component.h>
   8#include <linux/mod_devicetable.h>
   9#include <linux/module.h>
  10#include <linux/of.h>
  11#include <linux/platform_device.h>
  12
  13#include <drm/drm_fourcc.h>
  14#include <drm/drm_plane.h>
  15#include <drm/drm_print.h>
  16
  17#include "rockchip_drm_vop.h"
  18#include "rockchip_vop_reg.h"
  19#include "rockchip_drm_drv.h"
  20
  21#define _VOP_REG(off, _mask, _shift, _write_mask, _relaxed) \
  22		{ \
  23		 .offset = off, \
  24		 .mask = _mask, \
  25		 .shift = _shift, \
  26		 .write_mask = _write_mask, \
  27		 .relaxed = _relaxed, \
  28		}
  29
  30#define VOP_REG(off, _mask, _shift) \
  31		_VOP_REG(off, _mask, _shift, false, true)
  32
  33#define VOP_REG_SYNC(off, _mask, _shift) \
  34		_VOP_REG(off, _mask, _shift, false, false)
  35
  36#define VOP_REG_MASK_SYNC(off, _mask, _shift) \
  37		_VOP_REG(off, _mask, _shift, true, false)
  38
  39static const uint32_t formats_win_full[] = {
  40	DRM_FORMAT_XRGB8888,
  41	DRM_FORMAT_ARGB8888,
  42	DRM_FORMAT_XBGR8888,
  43	DRM_FORMAT_ABGR8888,
  44	DRM_FORMAT_RGB888,
  45	DRM_FORMAT_BGR888,
  46	DRM_FORMAT_RGB565,
  47	DRM_FORMAT_BGR565,
  48	DRM_FORMAT_NV12,
  49	DRM_FORMAT_NV21,
  50	DRM_FORMAT_NV16,
  51	DRM_FORMAT_NV61,
  52	DRM_FORMAT_NV24,
  53	DRM_FORMAT_NV42,
  54};
  55
  56static const uint64_t format_modifiers_win_full[] = {
  57	DRM_FORMAT_MOD_LINEAR,
  58	DRM_FORMAT_MOD_INVALID,
  59};
  60
  61static const uint64_t format_modifiers_win_full_afbc[] = {
  62	ROCKCHIP_AFBC_MOD,
  63	DRM_FORMAT_MOD_LINEAR,
  64	DRM_FORMAT_MOD_INVALID,
  65};
  66
  67static const uint32_t formats_win_lite[] = {
  68	DRM_FORMAT_XRGB8888,
  69	DRM_FORMAT_ARGB8888,
  70	DRM_FORMAT_XBGR8888,
  71	DRM_FORMAT_ABGR8888,
  72	DRM_FORMAT_RGB888,
  73	DRM_FORMAT_BGR888,
  74	DRM_FORMAT_RGB565,
  75	DRM_FORMAT_BGR565,
  76};
  77
  78static const uint64_t format_modifiers_win_lite[] = {
  79	DRM_FORMAT_MOD_LINEAR,
  80	DRM_FORMAT_MOD_INVALID,
  81};
  82
  83static const struct vop_scl_regs rk3036_win0_scl = {
  84	.scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
  85	.scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
  86	.scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
  87	.scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
  88};
  89
  90static const struct vop_scl_regs rk3036_win1_scl = {
  91	.scale_yrgb_x = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 0x0),
  92	.scale_yrgb_y = VOP_REG(RK3036_WIN1_SCL_FACTOR_YRGB, 0xffff, 16),
  93};
  94
  95static const struct vop_win_phy rk3036_win0_data = {
  96	.scl = &rk3036_win0_scl,
  97	.data_formats = formats_win_full,
  98	.nformats = ARRAY_SIZE(formats_win_full),
  99	.format_modifiers = format_modifiers_win_full,
 100	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0),
 101	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3),
 102	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15),
 103	.act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0),
 104	.dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0),
 105	.dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0),
 106	.yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0),
 107	.uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0),
 108	.yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0),
 109	.uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16),
 110	.alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 18),
 111	.alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 0),
 112	.alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29),
 113};
 114
 115static const struct vop_win_phy rk3036_win1_data = {
 116	.scl = &rk3036_win1_scl,
 117	.data_formats = formats_win_lite,
 118	.nformats = ARRAY_SIZE(formats_win_lite),
 119	.format_modifiers = format_modifiers_win_lite,
 120	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
 121	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
 122	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
 123	.act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0),
 124	.dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0),
 125	.dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0),
 126	.yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0),
 127	.yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
 128	.alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19),
 129	.alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1),
 130	.alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29),
 131};
 132
 133static const struct vop_win_data rk3036_vop_win_data[] = {
 134	{ .base = 0x00, .phy = &rk3036_win0_data,
 135	  .type = DRM_PLANE_TYPE_PRIMARY },
 136	{ .base = 0x00, .phy = &rk3036_win1_data,
 137	  .type = DRM_PLANE_TYPE_CURSOR },
 138};
 139
 140static const int rk3036_vop_intrs[] = {
 141	DSP_HOLD_VALID_INTR,
 142	FS_INTR,
 143	LINE_FLAG_INTR,
 144	BUS_ERROR_INTR,
 145};
 146
 147static const struct vop_intr rk3036_intr = {
 148	.intrs = rk3036_vop_intrs,
 149	.nintrs = ARRAY_SIZE(rk3036_vop_intrs),
 150	.line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12),
 151	.status = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 0),
 152	.enable = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 4),
 153	.clear = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 8),
 154};
 155
 156static const struct vop_modeset rk3036_modeset = {
 157	.htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
 158	.hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0),
 159	.vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
 160	.vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0),
 161};
 162
 163static const struct vop_output rk3036_output = {
 164	.pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4),
 165};
 166
 167static const struct vop_common rk3036_common = {
 168	.standby = VOP_REG_SYNC(RK3036_SYS_CTRL, 0x1, 30),
 169	.out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0),
 170	.dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24),
 171	.dither_down_sel = VOP_REG(RK3036_DSP_CTRL0, 0x1, 27),
 172	.dither_down_en = VOP_REG(RK3036_DSP_CTRL0, 0x1, 11),
 173	.dither_down_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 10),
 174	.cfg_done = VOP_REG_SYNC(RK3036_REG_CFG_DONE, 0x1, 0),
 175};
 176
 177static const struct vop_data rk3036_vop = {
 178	.intr = &rk3036_intr,
 179	.common = &rk3036_common,
 180	.modeset = &rk3036_modeset,
 181	.output = &rk3036_output,
 182	.win = rk3036_vop_win_data,
 183	.win_size = ARRAY_SIZE(rk3036_vop_win_data),
 184};
 185
 186static const struct vop_win_phy rk3126_win1_data = {
 187	.data_formats = formats_win_lite,
 188	.nformats = ARRAY_SIZE(formats_win_lite),
 189	.format_modifiers = format_modifiers_win_lite,
 190	.enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1),
 191	.format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6),
 192	.rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19),
 193	.dsp_info = VOP_REG(RK3126_WIN1_DSP_INFO, 0x0fff0fff, 0),
 194	.dsp_st = VOP_REG(RK3126_WIN1_DSP_ST, 0x1fff1fff, 0),
 195	.yrgb_mst = VOP_REG(RK3126_WIN1_MST, 0xffffffff, 0),
 196	.yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0),
 197	.alpha_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 19),
 198	.alpha_en = VOP_REG(RK3036_ALPHA_CTRL, 0x1, 1),
 199	.alpha_pre_mul = VOP_REG(RK3036_DSP_CTRL0, 0x1, 29),
 200};
 201
 202static const struct vop_win_data rk3126_vop_win_data[] = {
 203	{ .base = 0x00, .phy = &rk3036_win0_data,
 204	  .type = DRM_PLANE_TYPE_PRIMARY },
 205	{ .base = 0x00, .phy = &rk3126_win1_data,
 206	  .type = DRM_PLANE_TYPE_CURSOR },
 207};
 208
 209static const struct vop_data rk3126_vop = {
 210	.intr = &rk3036_intr,
 211	.common = &rk3036_common,
 212	.modeset = &rk3036_modeset,
 213	.output = &rk3036_output,
 214	.win = rk3126_vop_win_data,
 215	.win_size = ARRAY_SIZE(rk3126_vop_win_data),
 216};
 217
 218static const int px30_vop_intrs[] = {
 219	FS_INTR,
 220	0, 0,
 221	LINE_FLAG_INTR,
 222	0,
 223	BUS_ERROR_INTR,
 224	0, 0,
 225	DSP_HOLD_VALID_INTR,
 226};
 227
 228static const struct vop_intr px30_intr = {
 229	.intrs = px30_vop_intrs,
 230	.nintrs = ARRAY_SIZE(px30_vop_intrs),
 231	.line_flag_num[0] = VOP_REG(PX30_LINE_FLAG, 0xfff, 0),
 232	.status = VOP_REG_MASK_SYNC(PX30_INTR_STATUS, 0xffff, 0),
 233	.enable = VOP_REG_MASK_SYNC(PX30_INTR_EN, 0xffff, 0),
 234	.clear = VOP_REG_MASK_SYNC(PX30_INTR_CLEAR, 0xffff, 0),
 235};
 236
 237static const struct vop_common px30_common = {
 238	.standby = VOP_REG_SYNC(PX30_SYS_CTRL2, 0x1, 1),
 239	.out_mode = VOP_REG(PX30_DSP_CTRL2, 0xf, 16),
 240	.dsp_blank = VOP_REG(PX30_DSP_CTRL2, 0x1, 14),
 241	.dither_down_en = VOP_REG(PX30_DSP_CTRL2, 0x1, 8),
 242	.dither_down_sel = VOP_REG(PX30_DSP_CTRL2, 0x1, 7),
 243	.dither_down_mode = VOP_REG(PX30_DSP_CTRL2, 0x1, 6),
 244	.cfg_done = VOP_REG_SYNC(PX30_REG_CFG_DONE, 0x1, 0),
 245};
 246
 247static const struct vop_modeset px30_modeset = {
 248	.htotal_pw = VOP_REG(PX30_DSP_HTOTAL_HS_END, 0x0fff0fff, 0),
 249	.hact_st_end = VOP_REG(PX30_DSP_HACT_ST_END, 0x0fff0fff, 0),
 250	.vtotal_pw = VOP_REG(PX30_DSP_VTOTAL_VS_END, 0x0fff0fff, 0),
 251	.vact_st_end = VOP_REG(PX30_DSP_VACT_ST_END, 0x0fff0fff, 0),
 252};
 253
 254static const struct vop_output px30_output = {
 255	.rgb_dclk_pol = VOP_REG(PX30_DSP_CTRL0, 0x1, 1),
 256	.rgb_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0x7, 2),
 257	.rgb_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 0),
 258	.mipi_dclk_pol = VOP_REG(PX30_DSP_CTRL0, 0x1, 25),
 259	.mipi_pin_pol = VOP_REG(PX30_DSP_CTRL0, 0x7, 26),
 260	.mipi_en = VOP_REG(PX30_DSP_CTRL0, 0x1, 24),
 261};
 262
 263static const struct vop_scl_regs px30_win_scl = {
 264	.scale_yrgb_x = VOP_REG(PX30_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
 265	.scale_yrgb_y = VOP_REG(PX30_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
 266	.scale_cbcr_x = VOP_REG(PX30_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
 267	.scale_cbcr_y = VOP_REG(PX30_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
 268};
 269
 270static const struct vop_win_phy px30_win0_data = {
 271	.scl = &px30_win_scl,
 272	.data_formats = formats_win_full,
 273	.nformats = ARRAY_SIZE(formats_win_full),
 274	.format_modifiers = format_modifiers_win_full,
 275	.enable = VOP_REG(PX30_WIN0_CTRL0, 0x1, 0),
 276	.format = VOP_REG(PX30_WIN0_CTRL0, 0x7, 1),
 277	.rb_swap = VOP_REG(PX30_WIN0_CTRL0, 0x1, 12),
 278	.uv_swap = VOP_REG(PX30_WIN0_CTRL0, 0x1, 15),
 279	.act_info = VOP_REG(PX30_WIN0_ACT_INFO, 0xffffffff, 0),
 280	.dsp_info = VOP_REG(PX30_WIN0_DSP_INFO, 0xffffffff, 0),
 281	.dsp_st = VOP_REG(PX30_WIN0_DSP_ST, 0xffffffff, 0),
 282	.yrgb_mst = VOP_REG(PX30_WIN0_YRGB_MST0, 0xffffffff, 0),
 283	.uv_mst = VOP_REG(PX30_WIN0_CBR_MST0, 0xffffffff, 0),
 284	.yrgb_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 0),
 285	.uv_vir = VOP_REG(PX30_WIN0_VIR, 0x1fff, 16),
 286	.alpha_pre_mul = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 2),
 287	.alpha_mode = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 1),
 288	.alpha_en = VOP_REG(PX30_WIN0_ALPHA_CTRL, 0x1, 0),
 289};
 290
 291static const struct vop_win_phy px30_win1_data = {
 292	.data_formats = formats_win_lite,
 293	.nformats = ARRAY_SIZE(formats_win_lite),
 294	.format_modifiers = format_modifiers_win_lite,
 295	.enable = VOP_REG(PX30_WIN1_CTRL0, 0x1, 0),
 296	.format = VOP_REG(PX30_WIN1_CTRL0, 0x7, 4),
 297	.rb_swap = VOP_REG(PX30_WIN1_CTRL0, 0x1, 12),
 298	.uv_swap = VOP_REG(PX30_WIN1_CTRL0, 0x1, 15),
 299	.dsp_info = VOP_REG(PX30_WIN1_DSP_INFO, 0xffffffff, 0),
 300	.dsp_st = VOP_REG(PX30_WIN1_DSP_ST, 0xffffffff, 0),
 301	.yrgb_mst = VOP_REG(PX30_WIN1_MST, 0xffffffff, 0),
 302	.yrgb_vir = VOP_REG(PX30_WIN1_VIR, 0x1fff, 0),
 303	.alpha_pre_mul = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 2),
 304	.alpha_mode = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 1),
 305	.alpha_en = VOP_REG(PX30_WIN1_ALPHA_CTRL, 0x1, 0),
 306};
 307
 308static const struct vop_win_phy px30_win2_data = {
 309	.data_formats = formats_win_lite,
 310	.nformats = ARRAY_SIZE(formats_win_lite),
 311	.format_modifiers = format_modifiers_win_lite,
 312	.gate = VOP_REG(PX30_WIN2_CTRL0, 0x1, 4),
 313	.enable = VOP_REG(PX30_WIN2_CTRL0, 0x1, 0),
 314	.format = VOP_REG(PX30_WIN2_CTRL0, 0x3, 5),
 315	.rb_swap = VOP_REG(PX30_WIN2_CTRL0, 0x1, 20),
 316	.dsp_info = VOP_REG(PX30_WIN2_DSP_INFO0, 0x0fff0fff, 0),
 317	.dsp_st = VOP_REG(PX30_WIN2_DSP_ST0, 0x1fff1fff, 0),
 318	.yrgb_mst = VOP_REG(PX30_WIN2_MST0, 0xffffffff, 0),
 319	.yrgb_vir = VOP_REG(PX30_WIN2_VIR0_1, 0x1fff, 0),
 320	.alpha_pre_mul = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 2),
 321	.alpha_mode = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 1),
 322	.alpha_en = VOP_REG(PX30_WIN2_ALPHA_CTRL, 0x1, 0),
 323};
 324
 325static const struct vop_win_data px30_vop_big_win_data[] = {
 326	{ .base = 0x00, .phy = &px30_win0_data,
 327	  .type = DRM_PLANE_TYPE_PRIMARY },
 328	{ .base = 0x00, .phy = &px30_win1_data,
 329	  .type = DRM_PLANE_TYPE_OVERLAY },
 330	{ .base = 0x00, .phy = &px30_win2_data,
 331	  .type = DRM_PLANE_TYPE_CURSOR },
 332};
 333
 334static const struct vop_data px30_vop_big = {
 335	.version = VOP_VERSION(2, 6),
 336	.intr = &px30_intr,
 337	.feature = VOP_FEATURE_INTERNAL_RGB,
 338	.common = &px30_common,
 339	.modeset = &px30_modeset,
 340	.output = &px30_output,
 341	.win = px30_vop_big_win_data,
 342	.win_size = ARRAY_SIZE(px30_vop_big_win_data),
 343};
 344
 345static const struct vop_win_data px30_vop_lit_win_data[] = {
 346	{ .base = 0x00, .phy = &px30_win1_data,
 347	  .type = DRM_PLANE_TYPE_PRIMARY },
 348};
 349
 350static const struct vop_data px30_vop_lit = {
 351	.version = VOP_VERSION(2, 5),
 352	.intr = &px30_intr,
 353	.feature = VOP_FEATURE_INTERNAL_RGB,
 354	.common = &px30_common,
 355	.modeset = &px30_modeset,
 356	.output = &px30_output,
 357	.win = px30_vop_lit_win_data,
 358	.win_size = ARRAY_SIZE(px30_vop_lit_win_data),
 359};
 360
 361static const struct vop_scl_regs rk3066_win_scl = {
 362	.scale_yrgb_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
 363	.scale_yrgb_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
 364	.scale_cbcr_x = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
 365	.scale_cbcr_y = VOP_REG(RK3066_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
 366};
 367
 368static const struct vop_win_phy rk3066_win0_data = {
 369	.scl = &rk3066_win_scl,
 370	.data_formats = formats_win_full,
 371	.nformats = ARRAY_SIZE(formats_win_full),
 372	.format_modifiers = format_modifiers_win_full,
 373	.enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0),
 374	.format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 4),
 375	.rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 19),
 376	.uv_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 22),
 377	.act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0),
 378	.dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0),
 379	.dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0),
 380	.yrgb_mst = VOP_REG(RK3066_WIN0_YRGB_MST0, 0xffffffff, 0),
 381	.uv_mst = VOP_REG(RK3066_WIN0_CBR_MST0, 0xffffffff, 0),
 382	.yrgb_vir = VOP_REG(RK3066_WIN0_VIR, 0xffff, 0),
 383	.uv_vir = VOP_REG(RK3066_WIN0_VIR, 0x1fff, 16),
 384	.alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 21),
 385	.alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 0),
 386};
 387
 388static const struct vop_win_phy rk3066_win1_data = {
 389	.data_formats = formats_win_full,
 390	.nformats = ARRAY_SIZE(formats_win_full),
 391	.format_modifiers = format_modifiers_win_full,
 392	.enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1),
 393	.format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 7),
 394	.rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 23),
 395	.uv_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 26),
 396	.act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0),
 397	.dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0),
 398	.dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0),
 399	.yrgb_mst = VOP_REG(RK3066_WIN1_YRGB_MST, 0xffffffff, 0),
 400	.uv_mst = VOP_REG(RK3066_WIN1_CBR_MST, 0xffffffff, 0),
 401	.yrgb_vir = VOP_REG(RK3066_WIN1_VIR, 0xffff, 0),
 402	.uv_vir = VOP_REG(RK3066_WIN1_VIR, 0x1fff, 16),
 403	.alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 22),
 404	.alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 1),
 405};
 406
 407static const struct vop_win_phy rk3066_win2_data = {
 408	.data_formats = formats_win_lite,
 409	.nformats = ARRAY_SIZE(formats_win_lite),
 410	.format_modifiers = format_modifiers_win_lite,
 411	.enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2),
 412	.format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 10),
 413	.rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 27),
 414	.dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0),
 415	.dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0),
 416	.yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0),
 417	.yrgb_vir = VOP_REG(RK3066_WIN2_VIR, 0xffff, 0),
 418	.alpha_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 23),
 419	.alpha_en = VOP_REG(RK3066_BLEND_CTRL, 0x1, 2),
 420};
 421
 422static const struct vop_modeset rk3066_modeset = {
 423	.htotal_pw = VOP_REG(RK3066_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
 424	.hact_st_end = VOP_REG(RK3066_DSP_HACT_ST_END, 0x1fff1fff, 0),
 425	.vtotal_pw = VOP_REG(RK3066_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
 426	.vact_st_end = VOP_REG(RK3066_DSP_VACT_ST_END, 0x1fff1fff, 0),
 427};
 428
 429static const struct vop_output rk3066_output = {
 430	.pin_pol = VOP_REG(RK3066_DSP_CTRL0, 0x7, 4),
 431};
 432
 433static const struct vop_common rk3066_common = {
 434	.standby = VOP_REG(RK3066_SYS_CTRL0, 0x1, 1),
 435	.out_mode = VOP_REG(RK3066_DSP_CTRL0, 0xf, 0),
 436	.cfg_done = VOP_REG(RK3066_REG_CFG_DONE, 0x1, 0),
 437	.dither_down_en = VOP_REG(RK3066_DSP_CTRL0, 0x1, 11),
 438	.dither_down_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 10),
 439	.dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24),
 440	.dither_up = VOP_REG(RK3066_DSP_CTRL0, 0x1, 9),
 441	.dsp_lut_en = VOP_REG(RK3066_SYS_CTRL1, 0x1, 31),
 442	.data_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 25),
 443};
 444
 445static const struct vop_win_data rk3066_vop_win_data[] = {
 446	{ .base = 0x00, .phy = &rk3066_win0_data,
 447	  .type = DRM_PLANE_TYPE_PRIMARY },
 448	{ .base = 0x00, .phy = &rk3066_win1_data,
 449	  .type = DRM_PLANE_TYPE_OVERLAY },
 450	{ .base = 0x00, .phy = &rk3066_win2_data,
 451	  .type = DRM_PLANE_TYPE_CURSOR },
 452};
 453
 454static const int rk3066_vop_intrs[] = {
 455	/*
 456	 * hs_start interrupt fires at frame-start, so serves
 457	 * the same purpose as dsp_hold in the driver.
 458	 */
 459	DSP_HOLD_VALID_INTR,
 460	FS_INTR,
 461	LINE_FLAG_INTR,
 462	BUS_ERROR_INTR,
 463};
 464
 465static const struct vop_intr rk3066_intr = {
 466	.intrs = rk3066_vop_intrs,
 467	.nintrs = ARRAY_SIZE(rk3066_vop_intrs),
 468	.line_flag_num[0] = VOP_REG(RK3066_INT_STATUS, 0xfff, 12),
 469	.status = VOP_REG(RK3066_INT_STATUS, 0xf, 0),
 470	.enable = VOP_REG(RK3066_INT_STATUS, 0xf, 4),
 471	.clear = VOP_REG(RK3066_INT_STATUS, 0xf, 8),
 472};
 473
 474static const struct vop_data rk3066_vop = {
 475	.version = VOP_VERSION(2, 1),
 476	.intr = &rk3066_intr,
 477	.common = &rk3066_common,
 478	.modeset = &rk3066_modeset,
 479	.output = &rk3066_output,
 480	.win = rk3066_vop_win_data,
 481	.win_size = ARRAY_SIZE(rk3066_vop_win_data),
 482};
 483
 484static const struct vop_scl_regs rk3188_win_scl = {
 485	.scale_yrgb_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
 486	.scale_yrgb_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
 487	.scale_cbcr_x = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
 488	.scale_cbcr_y = VOP_REG(RK3188_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
 489};
 490
 491static const struct vop_win_phy rk3188_win0_data = {
 492	.scl = &rk3188_win_scl,
 493	.data_formats = formats_win_full,
 494	.nformats = ARRAY_SIZE(formats_win_full),
 495	.format_modifiers = format_modifiers_win_full,
 496	.enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 0),
 497	.format = VOP_REG(RK3188_SYS_CTRL, 0x7, 3),
 498	.rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 15),
 499	.uv_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 18),
 500	.act_info = VOP_REG(RK3188_WIN0_ACT_INFO, 0x1fff1fff, 0),
 501	.dsp_info = VOP_REG(RK3188_WIN0_DSP_INFO, 0x0fff0fff, 0),
 502	.dsp_st = VOP_REG(RK3188_WIN0_DSP_ST, 0x1fff1fff, 0),
 503	.yrgb_mst = VOP_REG(RK3188_WIN0_YRGB_MST0, 0xffffffff, 0),
 504	.uv_mst = VOP_REG(RK3188_WIN0_CBR_MST0, 0xffffffff, 0),
 505	.yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 0),
 506	.alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 18),
 507	.alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 0),
 508	.alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29),
 509};
 510
 511static const struct vop_win_phy rk3188_win1_data = {
 512	.data_formats = formats_win_lite,
 513	.nformats = ARRAY_SIZE(formats_win_lite),
 514	.format_modifiers = format_modifiers_win_lite,
 515	.enable = VOP_REG(RK3188_SYS_CTRL, 0x1, 1),
 516	.format = VOP_REG(RK3188_SYS_CTRL, 0x7, 6),
 517	.rb_swap = VOP_REG(RK3188_SYS_CTRL, 0x1, 19),
 518	/* no act_info on window1 */
 519	.dsp_info = VOP_REG(RK3188_WIN1_DSP_INFO, 0x07ff07ff, 0),
 520	.dsp_st = VOP_REG(RK3188_WIN1_DSP_ST, 0x0fff0fff, 0),
 521	.yrgb_mst = VOP_REG(RK3188_WIN1_MST, 0xffffffff, 0),
 522	.yrgb_vir = VOP_REG(RK3188_WIN_VIR, 0x1fff, 16),
 523	.alpha_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 19),
 524	.alpha_en = VOP_REG(RK3188_ALPHA_CTRL, 0x1, 1),
 525	.alpha_pre_mul = VOP_REG(RK3188_DSP_CTRL0, 0x1, 29),
 526};
 527
 528static const struct vop_modeset rk3188_modeset = {
 529	.htotal_pw = VOP_REG(RK3188_DSP_HTOTAL_HS_END, 0x0fff0fff, 0),
 530	.hact_st_end = VOP_REG(RK3188_DSP_HACT_ST_END, 0x0fff0fff, 0),
 531	.vtotal_pw = VOP_REG(RK3188_DSP_VTOTAL_VS_END, 0x0fff0fff, 0),
 532	.vact_st_end = VOP_REG(RK3188_DSP_VACT_ST_END, 0x0fff0fff, 0),
 533};
 534
 535static const struct vop_output rk3188_output = {
 536	.pin_pol = VOP_REG(RK3188_DSP_CTRL0, 0xf, 4),
 537};
 538
 539static const struct vop_common rk3188_common = {
 540	.gate_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 31),
 541	.standby = VOP_REG(RK3188_SYS_CTRL, 0x1, 30),
 542	.out_mode = VOP_REG(RK3188_DSP_CTRL0, 0xf, 0),
 543	.cfg_done = VOP_REG(RK3188_REG_CFG_DONE, 0x1, 0),
 544	.dither_down_sel = VOP_REG(RK3188_DSP_CTRL0, 0x1, 27),
 545	.dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11),
 546	.dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10),
 547	.dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 24),
 548	.dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9),
 549	.dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28),
 550	.data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25),
 551};
 552
 553static const struct vop_win_data rk3188_vop_win_data[] = {
 554	{ .base = 0x00, .phy = &rk3188_win0_data,
 555	  .type = DRM_PLANE_TYPE_PRIMARY },
 556	{ .base = 0x00, .phy = &rk3188_win1_data,
 557	  .type = DRM_PLANE_TYPE_CURSOR },
 558};
 559
 560static const int rk3188_vop_intrs[] = {
 561	/*
 562	 * hs_start interrupt fires at frame-start, so serves
 563	 * the same purpose as dsp_hold in the driver.
 564	 */
 565	DSP_HOLD_VALID_INTR,
 566	FS_INTR,
 567	LINE_FLAG_INTR,
 568	BUS_ERROR_INTR,
 569};
 570
 571static const struct vop_intr rk3188_vop_intr = {
 572	.intrs = rk3188_vop_intrs,
 573	.nintrs = ARRAY_SIZE(rk3188_vop_intrs),
 574	.line_flag_num[0] = VOP_REG(RK3188_INT_STATUS, 0xfff, 12),
 575	.status = VOP_REG(RK3188_INT_STATUS, 0xf, 0),
 576	.enable = VOP_REG(RK3188_INT_STATUS, 0xf, 4),
 577	.clear = VOP_REG(RK3188_INT_STATUS, 0xf, 8),
 578};
 579
 580static const struct vop_data rk3188_vop = {
 581	.intr = &rk3188_vop_intr,
 582	.common = &rk3188_common,
 583	.modeset = &rk3188_modeset,
 584	.output = &rk3188_output,
 585	.win = rk3188_vop_win_data,
 586	.win_size = ARRAY_SIZE(rk3188_vop_win_data),
 587	.feature = VOP_FEATURE_INTERNAL_RGB,
 588};
 589
 590static const struct vop_scl_extension rk3288_win_full_scl_ext = {
 591	.cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31),
 592	.cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30),
 593	.cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28),
 594	.cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26),
 595	.cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24),
 596	.yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23),
 597	.yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22),
 598	.yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20),
 599	.yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18),
 600	.yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16),
 601	.line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15),
 602	.cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12),
 603	.yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8),
 604	.vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7),
 605	.vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6),
 606	.vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5),
 607	.vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4),
 608	.bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2),
 609	.cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1),
 610	.yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0),
 611	.lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5),
 612};
 613
 614static const struct vop_scl_regs rk3288_win_full_scl = {
 615	.ext = &rk3288_win_full_scl_ext,
 616	.scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
 617	.scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
 618	.scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
 619	.scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16),
 620};
 621
 622static const struct vop_win_phy rk3288_win01_data = {
 623	.scl = &rk3288_win_full_scl,
 624	.data_formats = formats_win_full,
 625	.nformats = ARRAY_SIZE(formats_win_full),
 626	.format_modifiers = format_modifiers_win_full,
 627	.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
 628	.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
 629	.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
 630	.uv_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 15),
 631	.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
 632	.dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
 633	.dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
 634	.yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
 635	.uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
 636	.yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
 637	.uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
 638	.src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
 639	.dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
 640	.channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0),
 641};
 642
 643static const struct vop_win_phy rk3288_win23_data = {
 644	.data_formats = formats_win_lite,
 645	.nformats = ARRAY_SIZE(formats_win_lite),
 646	.format_modifiers = format_modifiers_win_lite,
 647	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4),
 648	.gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
 649	.format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
 650	.rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
 651	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
 652	.dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0),
 653	.yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0),
 654	.yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0),
 655	.src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
 656	.dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
 657};
 658
 659static const struct vop_modeset rk3288_modeset = {
 660	.htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
 661	.hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0),
 662	.vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
 663	.vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0),
 664	.hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
 665	.vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
 666};
 667
 668static const struct vop_output rk3288_output = {
 669	.pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4),
 670	.rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
 671	.hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
 672	.edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
 673	.mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
 674};
 675
 676static const struct vop_common rk3288_common = {
 677	.standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22),
 678	.gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
 679	.mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20),
 680	.dither_down_sel = VOP_REG(RK3288_DSP_CTRL1, 0x1, 4),
 681	.dither_down_mode = VOP_REG(RK3288_DSP_CTRL1, 0x1, 3),
 682	.dither_down_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 2),
 683	.pre_dither_down = VOP_REG(RK3288_DSP_CTRL1, 0x1, 1),
 684	.dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6),
 685	.dsp_lut_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 0),
 686	.data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19),
 687	.dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18),
 688	.out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0),
 689	.cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0),
 690};
 691
 692/*
 693 * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
 694 * special support to get alpha blending working.  For now, just use overlay
 695 * window 3 for the drm cursor.
 696 *
 697 */
 698static const struct vop_win_data rk3288_vop_win_data[] = {
 699	{ .base = 0x00, .phy = &rk3288_win01_data,
 700	  .type = DRM_PLANE_TYPE_PRIMARY },
 701	{ .base = 0x40, .phy = &rk3288_win01_data,
 702	  .type = DRM_PLANE_TYPE_OVERLAY },
 703	{ .base = 0x00, .phy = &rk3288_win23_data,
 704	  .type = DRM_PLANE_TYPE_OVERLAY },
 705	{ .base = 0x50, .phy = &rk3288_win23_data,
 706	  .type = DRM_PLANE_TYPE_CURSOR },
 707};
 708
 709static const int rk3288_vop_intrs[] = {
 710	DSP_HOLD_VALID_INTR,
 711	FS_INTR,
 712	LINE_FLAG_INTR,
 713	BUS_ERROR_INTR,
 714};
 715
 716static const struct vop_intr rk3288_vop_intr = {
 717	.intrs = rk3288_vop_intrs,
 718	.nintrs = ARRAY_SIZE(rk3288_vop_intrs),
 719	.line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12),
 720	.status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0),
 721	.enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4),
 722	.clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8),
 723};
 724
 725static const struct vop_data rk3288_vop = {
 726	.version = VOP_VERSION(3, 1),
 727	.feature = VOP_FEATURE_OUTPUT_RGB10,
 728	.intr = &rk3288_vop_intr,
 729	.common = &rk3288_common,
 730	.modeset = &rk3288_modeset,
 731	.output = &rk3288_output,
 732	.win = rk3288_vop_win_data,
 733	.win_size = ARRAY_SIZE(rk3288_vop_win_data),
 734	.lut_size = 1024,
 735};
 736
 737static const int rk3368_vop_intrs[] = {
 738	FS_INTR,
 739	0, 0,
 740	LINE_FLAG_INTR,
 741	0,
 742	BUS_ERROR_INTR,
 743	0, 0, 0, 0, 0, 0, 0,
 744	DSP_HOLD_VALID_INTR,
 745};
 746
 747static const struct vop_intr rk3368_vop_intr = {
 748	.intrs = rk3368_vop_intrs,
 749	.nintrs = ARRAY_SIZE(rk3368_vop_intrs),
 750	.line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0),
 751	.line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16),
 752	.status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0),
 753	.enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0),
 754	.clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0),
 755};
 756
 757static const struct vop_win_phy rk3368_win01_data = {
 758	.scl = &rk3288_win_full_scl,
 759	.data_formats = formats_win_full,
 760	.nformats = ARRAY_SIZE(formats_win_full),
 761	.format_modifiers = format_modifiers_win_full,
 762	.enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0),
 763	.format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1),
 764	.rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12),
 765	.uv_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 15),
 766	.x_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 21),
 767	.y_mir_en = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 22),
 768	.act_info = VOP_REG(RK3368_WIN0_ACT_INFO, 0x1fff1fff, 0),
 769	.dsp_info = VOP_REG(RK3368_WIN0_DSP_INFO, 0x0fff0fff, 0),
 770	.dsp_st = VOP_REG(RK3368_WIN0_DSP_ST, 0x1fff1fff, 0),
 771	.yrgb_mst = VOP_REG(RK3368_WIN0_YRGB_MST, 0xffffffff, 0),
 772	.uv_mst = VOP_REG(RK3368_WIN0_CBR_MST, 0xffffffff, 0),
 773	.yrgb_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 0),
 774	.uv_vir = VOP_REG(RK3368_WIN0_VIR, 0x3fff, 16),
 775	.src_alpha_ctl = VOP_REG(RK3368_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
 776	.dst_alpha_ctl = VOP_REG(RK3368_WIN0_DST_ALPHA_CTRL, 0xff, 0),
 777	.channel = VOP_REG(RK3368_WIN0_CTRL2, 0xff, 0),
 778};
 779
 780static const struct vop_win_phy rk3368_win23_data = {
 781	.data_formats = formats_win_lite,
 782	.nformats = ARRAY_SIZE(formats_win_lite),
 783	.format_modifiers = format_modifiers_win_lite,
 784	.gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0),
 785	.enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4),
 786	.format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5),
 787	.rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20),
 788	.y_mir_en = VOP_REG(RK3368_WIN2_CTRL1, 0x1, 15),
 789	.dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0),
 790	.dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0),
 791	.yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0),
 792	.yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0),
 793	.src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0),
 794	.dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0),
 795};
 796
 797static const struct vop_win_data rk3368_vop_win_data[] = {
 798	{ .base = 0x00, .phy = &rk3368_win01_data,
 799	  .type = DRM_PLANE_TYPE_PRIMARY },
 800	{ .base = 0x40, .phy = &rk3368_win01_data,
 801	  .type = DRM_PLANE_TYPE_OVERLAY },
 802	{ .base = 0x00, .phy = &rk3368_win23_data,
 803	  .type = DRM_PLANE_TYPE_OVERLAY },
 804	{ .base = 0x50, .phy = &rk3368_win23_data,
 805	  .type = DRM_PLANE_TYPE_CURSOR },
 806};
 807
 808static const struct vop_output rk3368_output = {
 809	.rgb_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 19),
 810	.hdmi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 23),
 811	.edp_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 27),
 812	.mipi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 31),
 813	.rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 16),
 814	.hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 20),
 815	.edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 24),
 816	.mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 28),
 817	.rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
 818	.hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
 819	.edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
 820	.mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
 821};
 822
 823static const struct vop_misc rk3368_misc = {
 824	.global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11),
 825};
 826
 827static const struct vop_data rk3368_vop = {
 828	.version = VOP_VERSION(3, 2),
 829	.intr = &rk3368_vop_intr,
 830	.common = &rk3288_common,
 831	.modeset = &rk3288_modeset,
 832	.output = &rk3368_output,
 833	.misc = &rk3368_misc,
 834	.win = rk3368_vop_win_data,
 835	.win_size = ARRAY_SIZE(rk3368_vop_win_data),
 836};
 837
 838static const struct vop_intr rk3366_vop_intr = {
 839	.intrs = rk3368_vop_intrs,
 840	.nintrs = ARRAY_SIZE(rk3368_vop_intrs),
 841	.line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0),
 842	.line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16),
 843	.status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0),
 844	.enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0),
 845	.clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0),
 846};
 847
 848static const struct vop_data rk3366_vop = {
 849	.version = VOP_VERSION(3, 4),
 850	.intr = &rk3366_vop_intr,
 851	.common = &rk3288_common,
 852	.modeset = &rk3288_modeset,
 853	.output = &rk3368_output,
 854	.misc = &rk3368_misc,
 855	.win = rk3368_vop_win_data,
 856	.win_size = ARRAY_SIZE(rk3368_vop_win_data),
 857};
 858
 859static const struct vop_output rk3399_output = {
 860	.dp_dclk_pol = VOP_REG(RK3399_DSP_CTRL1, 0x1, 19),
 861	.rgb_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 19),
 862	.hdmi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 23),
 863	.edp_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 27),
 864	.mipi_dclk_pol = VOP_REG(RK3368_DSP_CTRL1, 0x1, 31),
 865	.dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0x7, 16),
 866	.rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 16),
 867	.hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 20),
 868	.edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 24),
 869	.mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0x7, 28),
 870	.dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11),
 871	.rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12),
 872	.hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13),
 873	.edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14),
 874	.mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15),
 875	.mipi_dual_channel_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 3),
 876};
 877
 878static const struct vop_common rk3399_common = {
 879	.standby = VOP_REG_SYNC(RK3399_SYS_CTRL, 0x1, 22),
 880	.gate_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 23),
 881	.mmu_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 20),
 882	.dither_down_sel = VOP_REG(RK3399_DSP_CTRL1, 0x1, 4),
 883	.dither_down_mode = VOP_REG(RK3399_DSP_CTRL1, 0x1, 3),
 884	.dither_down_en = VOP_REG(RK3399_DSP_CTRL1, 0x1, 2),
 885	.pre_dither_down = VOP_REG(RK3399_DSP_CTRL1, 0x1, 1),
 886	.dither_up = VOP_REG(RK3399_DSP_CTRL1, 0x1, 6),
 887	.dsp_lut_en = VOP_REG(RK3399_DSP_CTRL1, 0x1, 0),
 888	.update_gamma_lut = VOP_REG(RK3399_DSP_CTRL1, 0x1, 7),
 889	.lut_buffer_index = VOP_REG(RK3399_DBG_POST_REG1, 0x1, 1),
 890	.data_blank = VOP_REG(RK3399_DSP_CTRL0, 0x1, 19),
 891	.dsp_blank = VOP_REG(RK3399_DSP_CTRL0, 0x3, 18),
 892	.out_mode = VOP_REG(RK3399_DSP_CTRL0, 0xf, 0),
 893	.cfg_done = VOP_REG_SYNC(RK3399_REG_CFG_DONE, 0x1, 0),
 894};
 895
 896static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win01_data = {
 897	.y2r_coefficients = {
 898		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 0),
 899		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 0, 0xffff, 16),
 900		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 0),
 901		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 4, 0xffff, 16),
 902		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 0),
 903		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 8, 0xffff, 16),
 904		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 0),
 905		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 12, 0xffff, 16),
 906		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 16, 0xffff, 0),
 907		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 20, 0xffffffff, 0),
 908		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 24, 0xffffffff, 0),
 909		VOP_REG(RK3399_WIN0_YUV2YUV_Y2R + 28, 0xffffffff, 0),
 910	},
 911};
 912
 913static const struct vop_yuv2yuv_phy rk3399_yuv2yuv_win23_data = { };
 914
 915static const struct vop_win_yuv2yuv_data rk3399_vop_big_win_yuv2yuv_data[] = {
 916	{ .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
 917	  .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1) },
 918	{ .base = 0x60, .phy = &rk3399_yuv2yuv_win01_data,
 919	  .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9) },
 920	{ .base = 0xC0, .phy = &rk3399_yuv2yuv_win23_data },
 921	{ .base = 0x120, .phy = &rk3399_yuv2yuv_win23_data },
 922
 923};
 924
 925static const struct vop_win_phy rk3399_win01_data = {
 926	.scl = &rk3288_win_full_scl,
 927	.data_formats = formats_win_full,
 928	.nformats = ARRAY_SIZE(formats_win_full),
 929	.format_modifiers = format_modifiers_win_full_afbc,
 930	.enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
 931	.format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
 932	.rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
 933	.uv_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 15),
 934	.x_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 21),
 935	.y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22),
 936	.act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0),
 937	.dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0),
 938	.dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0),
 939	.yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0),
 940	.uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0),
 941	.yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0),
 942	.uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16),
 943	.src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0),
 944	.dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0),
 945	.channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0),
 946};
 947
 948/*
 949 * rk3399 vop big windows register layout is same as rk3288, but we
 950 * have a separate rk3399 win data array here so that we can advertise
 951 * AFBC on the primary plane.
 952 */
 953static const struct vop_win_data rk3399_vop_win_data[] = {
 954	{ .base = 0x00, .phy = &rk3399_win01_data,
 955	  .type = DRM_PLANE_TYPE_PRIMARY },
 956	{ .base = 0x40, .phy = &rk3368_win01_data,
 957	  .type = DRM_PLANE_TYPE_OVERLAY },
 958	{ .base = 0x00, .phy = &rk3368_win23_data,
 959	  .type = DRM_PLANE_TYPE_OVERLAY },
 960	{ .base = 0x50, .phy = &rk3368_win23_data,
 961	  .type = DRM_PLANE_TYPE_CURSOR },
 962};
 963
 964static const struct vop_afbc rk3399_vop_afbc = {
 965	.rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3),
 966	.enable = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0),
 967	.win_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1),
 968	.format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16),
 969	.hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21),
 970	.hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0),
 971	.pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0),
 972};
 973
 974static const struct vop_data rk3399_vop_big = {
 975	.version = VOP_VERSION(3, 5),
 976	.feature = VOP_FEATURE_OUTPUT_RGB10,
 977	.intr = &rk3366_vop_intr,
 978	.common = &rk3399_common,
 979	.modeset = &rk3288_modeset,
 980	.output = &rk3399_output,
 981	.afbc = &rk3399_vop_afbc,
 982	.misc = &rk3368_misc,
 983	.win = rk3399_vop_win_data,
 984	.win_size = ARRAY_SIZE(rk3399_vop_win_data),
 985	.win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data,
 986	.lut_size = 1024,
 987};
 988
 989static const struct vop_win_data rk3399_vop_lit_win_data[] = {
 990	{ .base = 0x00, .phy = &rk3368_win01_data,
 991	  .type = DRM_PLANE_TYPE_PRIMARY },
 992	{ .base = 0x00, .phy = &rk3368_win23_data,
 993	  .type = DRM_PLANE_TYPE_CURSOR},
 994};
 995
 996static const struct vop_win_yuv2yuv_data rk3399_vop_lit_win_yuv2yuv_data[] = {
 997	{ .base = 0x00, .phy = &rk3399_yuv2yuv_win01_data,
 998	  .y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1)},
 999	{ .base = 0x60, .phy = &rk3399_yuv2yuv_win23_data },
1000};
1001
1002static const struct vop_data rk3399_vop_lit = {
1003	.version = VOP_VERSION(3, 6),
1004	.intr = &rk3366_vop_intr,
1005	.common = &rk3399_common,
1006	.modeset = &rk3288_modeset,
1007	.output = &rk3399_output,
1008	.misc = &rk3368_misc,
1009	.win = rk3399_vop_lit_win_data,
1010	.win_size = ARRAY_SIZE(rk3399_vop_lit_win_data),
1011	.win_yuv2yuv = rk3399_vop_lit_win_yuv2yuv_data,
1012	.lut_size = 256,
1013};
1014
1015static const struct vop_win_data rk3228_vop_win_data[] = {
1016	{ .base = 0x00, .phy = &rk3288_win01_data,
1017	  .type = DRM_PLANE_TYPE_PRIMARY },
1018	{ .base = 0x40, .phy = &rk3288_win01_data,
1019	  .type = DRM_PLANE_TYPE_CURSOR },
1020};
1021
1022static const struct vop_data rk3228_vop = {
1023	.version = VOP_VERSION(3, 7),
1024	.feature = VOP_FEATURE_OUTPUT_RGB10,
1025	.intr = &rk3366_vop_intr,
1026	.common = &rk3288_common,
1027	.modeset = &rk3288_modeset,
1028	.output = &rk3399_output,
1029	.misc = &rk3368_misc,
1030	.win = rk3228_vop_win_data,
1031	.win_size = ARRAY_SIZE(rk3228_vop_win_data),
1032};
1033
1034static const struct vop_modeset rk3328_modeset = {
1035	.htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
1036	.hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0),
1037	.vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
1038	.vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0),
1039	.hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
1040	.vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
1041};
1042
1043static const struct vop_output rk3328_output = {
1044	.rgb_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 19),
1045	.hdmi_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 23),
1046	.edp_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 27),
1047	.mipi_dclk_pol = VOP_REG(RK3328_DSP_CTRL1, 0x1, 31),
1048	.rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12),
1049	.hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13),
1050	.edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14),
1051	.mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15),
1052	.rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 16),
1053	.hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 20),
1054	.edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 24),
1055	.mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0x7, 28),
1056};
1057
1058static const struct vop_misc rk3328_misc = {
1059	.global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11),
1060};
1061
1062static const struct vop_common rk3328_common = {
1063	.standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22),
1064	.dither_down_sel = VOP_REG(RK3328_DSP_CTRL1, 0x1, 4),
1065	.dither_down_mode = VOP_REG(RK3328_DSP_CTRL1, 0x1, 3),
1066	.dither_down_en = VOP_REG(RK3328_DSP_CTRL1, 0x1, 2),
1067	.pre_dither_down = VOP_REG(RK3328_DSP_CTRL1, 0x1, 1),
1068	.dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6),
1069	.dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18),
1070	.out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0),
1071	.cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0),
1072};
1073
1074static const struct vop_intr rk3328_vop_intr = {
1075	.intrs = rk3368_vop_intrs,
1076	.nintrs = ARRAY_SIZE(rk3368_vop_intrs),
1077	.line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0),
1078	.line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16),
1079	.status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0),
1080	.enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0),
1081	.clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0),
1082};
1083
1084static const struct vop_win_data rk3328_vop_win_data[] = {
1085	{ .base = 0xd0, .phy = &rk3368_win01_data,
1086	  .type = DRM_PLANE_TYPE_PRIMARY },
1087	{ .base = 0x1d0, .phy = &rk3368_win01_data,
1088	  .type = DRM_PLANE_TYPE_OVERLAY },
1089	{ .base = 0x2d0, .phy = &rk3368_win01_data,
1090	  .type = DRM_PLANE_TYPE_CURSOR },
1091};
1092
1093static const struct vop_data rk3328_vop = {
1094	.version = VOP_VERSION(3, 8),
1095	.feature = VOP_FEATURE_OUTPUT_RGB10,
1096	.intr = &rk3328_vop_intr,
1097	.common = &rk3328_common,
1098	.modeset = &rk3328_modeset,
1099	.output = &rk3328_output,
1100	.misc = &rk3328_misc,
1101	.win = rk3328_vop_win_data,
1102	.win_size = ARRAY_SIZE(rk3328_vop_win_data),
1103};
1104
1105static const struct of_device_id vop_driver_dt_match[] = {
1106	{ .compatible = "rockchip,rk3036-vop",
1107	  .data = &rk3036_vop },
1108	{ .compatible = "rockchip,rk3126-vop",
1109	  .data = &rk3126_vop },
1110	{ .compatible = "rockchip,px30-vop-big",
1111	  .data = &px30_vop_big },
1112	{ .compatible = "rockchip,px30-vop-lit",
1113	  .data = &px30_vop_lit },
1114	{ .compatible = "rockchip,rk3066-vop",
1115	  .data = &rk3066_vop },
1116	{ .compatible = "rockchip,rk3188-vop",
1117	  .data = &rk3188_vop },
1118	{ .compatible = "rockchip,rk3288-vop",
1119	  .data = &rk3288_vop },
1120	{ .compatible = "rockchip,rk3368-vop",
1121	  .data = &rk3368_vop },
1122	{ .compatible = "rockchip,rk3366-vop",
1123	  .data = &rk3366_vop },
1124	{ .compatible = "rockchip,rk3399-vop-big",
1125	  .data = &rk3399_vop_big },
1126	{ .compatible = "rockchip,rk3399-vop-lit",
1127	  .data = &rk3399_vop_lit },
1128	{ .compatible = "rockchip,rk3228-vop",
1129	  .data = &rk3228_vop },
1130	{ .compatible = "rockchip,rk3328-vop",
1131	  .data = &rk3328_vop },
1132	{},
1133};
1134MODULE_DEVICE_TABLE(of, vop_driver_dt_match);
1135
1136static int vop_probe(struct platform_device *pdev)
1137{
1138	struct device *dev = &pdev->dev;
1139
1140	if (!dev->of_node) {
1141		DRM_DEV_ERROR(dev, "can't find vop devices\n");
1142		return -ENODEV;
1143	}
1144
1145	return component_add(dev, &vop_component_ops);
1146}
1147
1148static int vop_remove(struct platform_device *pdev)
1149{
1150	component_del(&pdev->dev, &vop_component_ops);
1151
1152	return 0;
1153}
1154
1155struct platform_driver vop_platform_driver = {
1156	.probe = vop_probe,
1157	.remove = vop_remove,
1158	.driver = {
1159		.name = "rockchip-vop",
1160		.of_match_table = vop_driver_dt_match,
1161	},
1162};