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