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