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