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