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