1 /* 2 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd 3 * Author:Mark Yao <mark.yao@rock-chips.com> 4 * 5 * This software is licensed under the terms of the GNU General Public 6 * License version 2, as published by the Free Software Foundation, and 7 * may be copied, distributed, and modified under those terms. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15 #include <drm/drmP.h> 16 17 #include <linux/kernel.h> 18 #include <linux/component.h> 19 20 #include "rockchip_drm_vop.h" 21 #include "rockchip_vop_reg.h" 22 23 #define _VOP_REG(off, _mask, _shift, _write_mask, _relaxed) \ 24 { \ 25 .offset = off, \ 26 .mask = _mask, \ 27 .shift = _shift, \ 28 .write_mask = _write_mask, \ 29 .relaxed = _relaxed, \ 30 } 31 32 #define VOP_REG(off, _mask, _shift) \ 33 _VOP_REG(off, _mask, _shift, false, true) 34 35 #define VOP_REG_SYNC(off, _mask, _shift) \ 36 _VOP_REG(off, _mask, _shift, false, false) 37 38 #define VOP_REG_MASK_SYNC(off, _mask, _shift) \ 39 _VOP_REG(off, _mask, _shift, true, false) 40 41 static const uint32_t formats_win_full[] = { 42 DRM_FORMAT_XRGB8888, 43 DRM_FORMAT_ARGB8888, 44 DRM_FORMAT_XBGR8888, 45 DRM_FORMAT_ABGR8888, 46 DRM_FORMAT_RGB888, 47 DRM_FORMAT_BGR888, 48 DRM_FORMAT_RGB565, 49 DRM_FORMAT_BGR565, 50 DRM_FORMAT_NV12, 51 DRM_FORMAT_NV16, 52 DRM_FORMAT_NV24, 53 }; 54 55 static const uint32_t formats_win_lite[] = { 56 DRM_FORMAT_XRGB8888, 57 DRM_FORMAT_ARGB8888, 58 DRM_FORMAT_XBGR8888, 59 DRM_FORMAT_ABGR8888, 60 DRM_FORMAT_RGB888, 61 DRM_FORMAT_BGR888, 62 DRM_FORMAT_RGB565, 63 DRM_FORMAT_BGR565, 64 }; 65 66 static const struct vop_scl_regs rk3036_win_scl = { 67 .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 68 .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 69 .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 70 .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 71 }; 72 73 static const struct vop_win_phy rk3036_win0_data = { 74 .scl = &rk3036_win_scl, 75 .data_formats = formats_win_full, 76 .nformats = ARRAY_SIZE(formats_win_full), 77 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0), 78 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3), 79 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15), 80 .act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0), 81 .dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0), 82 .dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0), 83 .yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0), 84 .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0), 85 .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0), 86 .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16), 87 }; 88 89 static const struct vop_win_phy rk3036_win1_data = { 90 .data_formats = formats_win_lite, 91 .nformats = ARRAY_SIZE(formats_win_lite), 92 .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1), 93 .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6), 94 .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19), 95 .act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0), 96 .dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0), 97 .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0), 98 .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0), 99 .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0), 100 }; 101 102 static const struct vop_win_data rk3036_vop_win_data[] = { 103 { .base = 0x00, .phy = &rk3036_win0_data, 104 .type = DRM_PLANE_TYPE_PRIMARY }, 105 { .base = 0x00, .phy = &rk3036_win1_data, 106 .type = DRM_PLANE_TYPE_CURSOR }, 107 }; 108 109 static const int rk3036_vop_intrs[] = { 110 DSP_HOLD_VALID_INTR, 111 FS_INTR, 112 LINE_FLAG_INTR, 113 BUS_ERROR_INTR, 114 }; 115 116 static const struct vop_intr rk3036_intr = { 117 .intrs = rk3036_vop_intrs, 118 .nintrs = ARRAY_SIZE(rk3036_vop_intrs), 119 .line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12), 120 .status = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 0), 121 .enable = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 4), 122 .clear = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 8), 123 }; 124 125 static const struct vop_modeset rk3036_modeset = { 126 .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 127 .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0), 128 .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 129 .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0), 130 }; 131 132 static const struct vop_output rk3036_output = { 133 .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4), 134 }; 135 136 static const struct vop_common rk3036_common = { 137 .standby = VOP_REG_SYNC(RK3036_SYS_CTRL, 0x1, 30), 138 .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0), 139 .dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24), 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 struct vop_scl_extension rk3288_win_full_scl_ext = { 181 .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31), 182 .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30), 183 .cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28), 184 .cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26), 185 .cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24), 186 .yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23), 187 .yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22), 188 .yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20), 189 .yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18), 190 .yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16), 191 .line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15), 192 .cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12), 193 .yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8), 194 .vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7), 195 .vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6), 196 .vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5), 197 .vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4), 198 .bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2), 199 .cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1), 200 .yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0), 201 .lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5), 202 }; 203 204 static const struct vop_scl_regs rk3288_win_full_scl = { 205 .ext = &rk3288_win_full_scl_ext, 206 .scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 207 .scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 208 .scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 209 .scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 210 }; 211 212 static const struct vop_win_phy rk3288_win01_data = { 213 .scl = &rk3288_win_full_scl, 214 .data_formats = formats_win_full, 215 .nformats = ARRAY_SIZE(formats_win_full), 216 .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), 217 .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), 218 .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), 219 .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), 220 .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), 221 .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), 222 .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), 223 .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), 224 .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), 225 .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), 226 .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), 227 .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), 228 .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), 229 }; 230 231 static const struct vop_win_phy rk3288_win23_data = { 232 .data_formats = formats_win_lite, 233 .nformats = ARRAY_SIZE(formats_win_lite), 234 .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4), 235 .gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0), 236 .format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1), 237 .rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12), 238 .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0), 239 .dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0), 240 .yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0), 241 .yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0), 242 .src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0), 243 .dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0), 244 }; 245 246 static const struct vop_modeset rk3288_modeset = { 247 .htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 248 .hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0), 249 .vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 250 .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0), 251 .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0), 252 .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0), 253 }; 254 255 static const struct vop_output rk3288_output = { 256 .pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4), 257 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 258 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 259 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 260 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 261 }; 262 263 static const struct vop_common rk3288_common = { 264 .standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22), 265 .gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23), 266 .mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20), 267 .dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1), 268 .dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6), 269 .data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19), 270 .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18), 271 .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0), 272 .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), 273 }; 274 275 /* 276 * Note: rk3288 has a dedicated 'cursor' window, however, that window requires 277 * special support to get alpha blending working. For now, just use overlay 278 * window 3 for the drm cursor. 279 * 280 */ 281 static const struct vop_win_data rk3288_vop_win_data[] = { 282 { .base = 0x00, .phy = &rk3288_win01_data, 283 .type = DRM_PLANE_TYPE_PRIMARY }, 284 { .base = 0x40, .phy = &rk3288_win01_data, 285 .type = DRM_PLANE_TYPE_OVERLAY }, 286 { .base = 0x00, .phy = &rk3288_win23_data, 287 .type = DRM_PLANE_TYPE_OVERLAY }, 288 { .base = 0x50, .phy = &rk3288_win23_data, 289 .type = DRM_PLANE_TYPE_CURSOR }, 290 }; 291 292 static const int rk3288_vop_intrs[] = { 293 DSP_HOLD_VALID_INTR, 294 FS_INTR, 295 LINE_FLAG_INTR, 296 BUS_ERROR_INTR, 297 }; 298 299 static const struct vop_intr rk3288_vop_intr = { 300 .intrs = rk3288_vop_intrs, 301 .nintrs = ARRAY_SIZE(rk3288_vop_intrs), 302 .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12), 303 .status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0), 304 .enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4), 305 .clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8), 306 }; 307 308 static const struct vop_data rk3288_vop = { 309 .version = VOP_VERSION(3, 1), 310 .feature = VOP_FEATURE_OUTPUT_RGB10, 311 .intr = &rk3288_vop_intr, 312 .common = &rk3288_common, 313 .modeset = &rk3288_modeset, 314 .output = &rk3288_output, 315 .win = rk3288_vop_win_data, 316 .win_size = ARRAY_SIZE(rk3288_vop_win_data), 317 }; 318 319 static const int rk3368_vop_intrs[] = { 320 FS_INTR, 321 0, 0, 322 LINE_FLAG_INTR, 323 0, 324 BUS_ERROR_INTR, 325 0, 0, 0, 0, 0, 0, 0, 326 DSP_HOLD_VALID_INTR, 327 }; 328 329 static const struct vop_intr rk3368_vop_intr = { 330 .intrs = rk3368_vop_intrs, 331 .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 332 .line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0), 333 .line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16), 334 .status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0), 335 .enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0), 336 .clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0), 337 }; 338 339 static const struct vop_win_phy rk3368_win23_data = { 340 .data_formats = formats_win_lite, 341 .nformats = ARRAY_SIZE(formats_win_lite), 342 .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0), 343 .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4), 344 .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5), 345 .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20), 346 .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0), 347 .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0), 348 .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0), 349 .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0), 350 .src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0), 351 .dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0), 352 }; 353 354 static const struct vop_win_data rk3368_vop_win_data[] = { 355 { .base = 0x00, .phy = &rk3288_win01_data, 356 .type = DRM_PLANE_TYPE_PRIMARY }, 357 { .base = 0x40, .phy = &rk3288_win01_data, 358 .type = DRM_PLANE_TYPE_OVERLAY }, 359 { .base = 0x00, .phy = &rk3368_win23_data, 360 .type = DRM_PLANE_TYPE_OVERLAY }, 361 { .base = 0x50, .phy = &rk3368_win23_data, 362 .type = DRM_PLANE_TYPE_CURSOR }, 363 }; 364 365 static const struct vop_output rk3368_output = { 366 .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16), 367 .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20), 368 .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24), 369 .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28), 370 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 371 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 372 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 373 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 374 }; 375 376 static const struct vop_misc rk3368_misc = { 377 .global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11), 378 }; 379 380 static const struct vop_data rk3368_vop = { 381 .version = VOP_VERSION(3, 2), 382 .intr = &rk3368_vop_intr, 383 .common = &rk3288_common, 384 .modeset = &rk3288_modeset, 385 .output = &rk3368_output, 386 .misc = &rk3368_misc, 387 .win = rk3368_vop_win_data, 388 .win_size = ARRAY_SIZE(rk3368_vop_win_data), 389 }; 390 391 static const struct vop_intr rk3366_vop_intr = { 392 .intrs = rk3368_vop_intrs, 393 .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 394 .line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0), 395 .line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16), 396 .status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0), 397 .enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0), 398 .clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0), 399 }; 400 401 static const struct vop_data rk3366_vop = { 402 .version = VOP_VERSION(3, 4), 403 .intr = &rk3366_vop_intr, 404 .common = &rk3288_common, 405 .modeset = &rk3288_modeset, 406 .output = &rk3368_output, 407 .misc = &rk3368_misc, 408 .win = rk3368_vop_win_data, 409 .win_size = ARRAY_SIZE(rk3368_vop_win_data), 410 }; 411 412 static const struct vop_output rk3399_output = { 413 .dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16), 414 .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16), 415 .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20), 416 .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24), 417 .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28), 418 .dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11), 419 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 420 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 421 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 422 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 423 }; 424 425 static const struct vop_data rk3399_vop_big = { 426 .version = VOP_VERSION(3, 5), 427 .feature = VOP_FEATURE_OUTPUT_RGB10, 428 .intr = &rk3366_vop_intr, 429 .common = &rk3288_common, 430 .modeset = &rk3288_modeset, 431 .output = &rk3399_output, 432 .misc = &rk3368_misc, 433 .win = rk3368_vop_win_data, 434 .win_size = ARRAY_SIZE(rk3368_vop_win_data), 435 }; 436 437 static const struct vop_win_data rk3399_vop_lit_win_data[] = { 438 { .base = 0x00, .phy = &rk3288_win01_data, 439 .type = DRM_PLANE_TYPE_PRIMARY }, 440 { .base = 0x00, .phy = &rk3368_win23_data, 441 .type = DRM_PLANE_TYPE_CURSOR}, 442 }; 443 444 static const struct vop_data rk3399_vop_lit = { 445 .version = VOP_VERSION(3, 6), 446 .intr = &rk3366_vop_intr, 447 .common = &rk3288_common, 448 .modeset = &rk3288_modeset, 449 .output = &rk3399_output, 450 .misc = &rk3368_misc, 451 .win = rk3399_vop_lit_win_data, 452 .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data), 453 }; 454 455 static const struct vop_win_data rk3228_vop_win_data[] = { 456 { .base = 0x00, .phy = &rk3288_win01_data, 457 .type = DRM_PLANE_TYPE_PRIMARY }, 458 { .base = 0x40, .phy = &rk3288_win01_data, 459 .type = DRM_PLANE_TYPE_CURSOR }, 460 }; 461 462 static const struct vop_data rk3228_vop = { 463 .version = VOP_VERSION(3, 7), 464 .feature = VOP_FEATURE_OUTPUT_RGB10, 465 .intr = &rk3366_vop_intr, 466 .common = &rk3288_common, 467 .modeset = &rk3288_modeset, 468 .output = &rk3399_output, 469 .misc = &rk3368_misc, 470 .win = rk3228_vop_win_data, 471 .win_size = ARRAY_SIZE(rk3228_vop_win_data), 472 }; 473 474 static const struct vop_modeset rk3328_modeset = { 475 .htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 476 .hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0), 477 .vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 478 .vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0), 479 .hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0), 480 .vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0), 481 }; 482 483 static const struct vop_output rk3328_output = { 484 .rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12), 485 .hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13), 486 .edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14), 487 .mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15), 488 .rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 16), 489 .hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 20), 490 .edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 24), 491 .mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 28), 492 }; 493 494 static const struct vop_misc rk3328_misc = { 495 .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11), 496 }; 497 498 static const struct vop_common rk3328_common = { 499 .standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22), 500 .dither_down = VOP_REG(RK3328_DSP_CTRL1, 0xf, 1), 501 .dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6), 502 .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18), 503 .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0), 504 .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), 505 }; 506 507 static const struct vop_intr rk3328_vop_intr = { 508 .intrs = rk3368_vop_intrs, 509 .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 510 .line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0), 511 .line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16), 512 .status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0), 513 .enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0), 514 .clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0), 515 }; 516 517 static const struct vop_win_data rk3328_vop_win_data[] = { 518 { .base = 0xd0, .phy = &rk3288_win01_data, 519 .type = DRM_PLANE_TYPE_PRIMARY }, 520 { .base = 0x1d0, .phy = &rk3288_win01_data, 521 .type = DRM_PLANE_TYPE_OVERLAY }, 522 { .base = 0x2d0, .phy = &rk3288_win01_data, 523 .type = DRM_PLANE_TYPE_CURSOR }, 524 }; 525 526 static const struct vop_data rk3328_vop = { 527 .version = VOP_VERSION(3, 8), 528 .feature = VOP_FEATURE_OUTPUT_RGB10, 529 .intr = &rk3328_vop_intr, 530 .common = &rk3328_common, 531 .modeset = &rk3328_modeset, 532 .output = &rk3328_output, 533 .misc = &rk3328_misc, 534 .win = rk3328_vop_win_data, 535 .win_size = ARRAY_SIZE(rk3328_vop_win_data), 536 }; 537 538 static const struct of_device_id vop_driver_dt_match[] = { 539 { .compatible = "rockchip,rk3036-vop", 540 .data = &rk3036_vop }, 541 { .compatible = "rockchip,rk3126-vop", 542 .data = &rk3126_vop }, 543 { .compatible = "rockchip,rk3288-vop", 544 .data = &rk3288_vop }, 545 { .compatible = "rockchip,rk3368-vop", 546 .data = &rk3368_vop }, 547 { .compatible = "rockchip,rk3366-vop", 548 .data = &rk3366_vop }, 549 { .compatible = "rockchip,rk3399-vop-big", 550 .data = &rk3399_vop_big }, 551 { .compatible = "rockchip,rk3399-vop-lit", 552 .data = &rk3399_vop_lit }, 553 { .compatible = "rockchip,rk3228-vop", 554 .data = &rk3228_vop }, 555 { .compatible = "rockchip,rk3328-vop", 556 .data = &rk3328_vop }, 557 {}, 558 }; 559 MODULE_DEVICE_TABLE(of, vop_driver_dt_match); 560 561 static int vop_probe(struct platform_device *pdev) 562 { 563 struct device *dev = &pdev->dev; 564 565 if (!dev->of_node) { 566 DRM_DEV_ERROR(dev, "can't find vop devices\n"); 567 return -ENODEV; 568 } 569 570 return component_add(dev, &vop_component_ops); 571 } 572 573 static int vop_remove(struct platform_device *pdev) 574 { 575 component_del(&pdev->dev, &vop_component_ops); 576 577 return 0; 578 } 579 580 struct platform_driver vop_platform_driver = { 581 .probe = vop_probe, 582 .remove = vop_remove, 583 .driver = { 584 .name = "rockchip-vop", 585 .of_match_table = of_match_ptr(vop_driver_dt_match), 586 }, 587 }; 588