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