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