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