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