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