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