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 .pre_dither_down = VOP_REG(RK3288_DSP_CTRL1, 0x1, 1), 268 .dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1), 269 .dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6), 270 .data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19), 271 .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18), 272 .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0), 273 .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), 274 }; 275 276 /* 277 * Note: rk3288 has a dedicated 'cursor' window, however, that window requires 278 * special support to get alpha blending working. For now, just use overlay 279 * window 3 for the drm cursor. 280 * 281 */ 282 static const struct vop_win_data rk3288_vop_win_data[] = { 283 { .base = 0x00, .phy = &rk3288_win01_data, 284 .type = DRM_PLANE_TYPE_PRIMARY }, 285 { .base = 0x40, .phy = &rk3288_win01_data, 286 .type = DRM_PLANE_TYPE_OVERLAY }, 287 { .base = 0x00, .phy = &rk3288_win23_data, 288 .type = DRM_PLANE_TYPE_OVERLAY }, 289 { .base = 0x50, .phy = &rk3288_win23_data, 290 .type = DRM_PLANE_TYPE_CURSOR }, 291 }; 292 293 static const int rk3288_vop_intrs[] = { 294 DSP_HOLD_VALID_INTR, 295 FS_INTR, 296 LINE_FLAG_INTR, 297 BUS_ERROR_INTR, 298 }; 299 300 static const struct vop_intr rk3288_vop_intr = { 301 .intrs = rk3288_vop_intrs, 302 .nintrs = ARRAY_SIZE(rk3288_vop_intrs), 303 .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12), 304 .status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0), 305 .enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4), 306 .clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8), 307 }; 308 309 static const struct vop_data rk3288_vop = { 310 .version = VOP_VERSION(3, 1), 311 .feature = VOP_FEATURE_OUTPUT_RGB10, 312 .intr = &rk3288_vop_intr, 313 .common = &rk3288_common, 314 .modeset = &rk3288_modeset, 315 .output = &rk3288_output, 316 .win = rk3288_vop_win_data, 317 .win_size = ARRAY_SIZE(rk3288_vop_win_data), 318 }; 319 320 static const int rk3368_vop_intrs[] = { 321 FS_INTR, 322 0, 0, 323 LINE_FLAG_INTR, 324 0, 325 BUS_ERROR_INTR, 326 0, 0, 0, 0, 0, 0, 0, 327 DSP_HOLD_VALID_INTR, 328 }; 329 330 static const struct vop_intr rk3368_vop_intr = { 331 .intrs = rk3368_vop_intrs, 332 .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 333 .line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0), 334 .line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16), 335 .status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0), 336 .enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0), 337 .clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0), 338 }; 339 340 static const struct vop_win_phy rk3368_win23_data = { 341 .data_formats = formats_win_lite, 342 .nformats = ARRAY_SIZE(formats_win_lite), 343 .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0), 344 .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4), 345 .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5), 346 .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20), 347 .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0), 348 .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0), 349 .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0), 350 .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0), 351 .src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0), 352 .dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0), 353 }; 354 355 static const struct vop_win_data rk3368_vop_win_data[] = { 356 { .base = 0x00, .phy = &rk3288_win01_data, 357 .type = DRM_PLANE_TYPE_PRIMARY }, 358 { .base = 0x40, .phy = &rk3288_win01_data, 359 .type = DRM_PLANE_TYPE_OVERLAY }, 360 { .base = 0x00, .phy = &rk3368_win23_data, 361 .type = DRM_PLANE_TYPE_OVERLAY }, 362 { .base = 0x50, .phy = &rk3368_win23_data, 363 .type = DRM_PLANE_TYPE_CURSOR }, 364 }; 365 366 static const struct vop_output rk3368_output = { 367 .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16), 368 .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20), 369 .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24), 370 .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28), 371 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 372 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 373 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 374 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 375 }; 376 377 static const struct vop_misc rk3368_misc = { 378 .global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11), 379 }; 380 381 static const struct vop_data rk3368_vop = { 382 .version = VOP_VERSION(3, 2), 383 .intr = &rk3368_vop_intr, 384 .common = &rk3288_common, 385 .modeset = &rk3288_modeset, 386 .output = &rk3368_output, 387 .misc = &rk3368_misc, 388 .win = rk3368_vop_win_data, 389 .win_size = ARRAY_SIZE(rk3368_vop_win_data), 390 }; 391 392 static const struct vop_intr rk3366_vop_intr = { 393 .intrs = rk3368_vop_intrs, 394 .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 395 .line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0), 396 .line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16), 397 .status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0), 398 .enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0), 399 .clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0), 400 }; 401 402 static const struct vop_data rk3366_vop = { 403 .version = VOP_VERSION(3, 4), 404 .intr = &rk3366_vop_intr, 405 .common = &rk3288_common, 406 .modeset = &rk3288_modeset, 407 .output = &rk3368_output, 408 .misc = &rk3368_misc, 409 .win = rk3368_vop_win_data, 410 .win_size = ARRAY_SIZE(rk3368_vop_win_data), 411 }; 412 413 static const struct vop_output rk3399_output = { 414 .dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16), 415 .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16), 416 .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20), 417 .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24), 418 .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28), 419 .dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11), 420 .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 421 .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 422 .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 423 .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 424 }; 425 426 static const struct vop_data rk3399_vop_big = { 427 .version = VOP_VERSION(3, 5), 428 .feature = VOP_FEATURE_OUTPUT_RGB10, 429 .intr = &rk3366_vop_intr, 430 .common = &rk3288_common, 431 .modeset = &rk3288_modeset, 432 .output = &rk3399_output, 433 .misc = &rk3368_misc, 434 .win = rk3368_vop_win_data, 435 .win_size = ARRAY_SIZE(rk3368_vop_win_data), 436 }; 437 438 static const struct vop_win_data rk3399_vop_lit_win_data[] = { 439 { .base = 0x00, .phy = &rk3288_win01_data, 440 .type = DRM_PLANE_TYPE_PRIMARY }, 441 { .base = 0x00, .phy = &rk3368_win23_data, 442 .type = DRM_PLANE_TYPE_CURSOR}, 443 }; 444 445 static const struct vop_data rk3399_vop_lit = { 446 .version = VOP_VERSION(3, 6), 447 .intr = &rk3366_vop_intr, 448 .common = &rk3288_common, 449 .modeset = &rk3288_modeset, 450 .output = &rk3399_output, 451 .misc = &rk3368_misc, 452 .win = rk3399_vop_lit_win_data, 453 .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data), 454 }; 455 456 static const struct vop_win_data rk3228_vop_win_data[] = { 457 { .base = 0x00, .phy = &rk3288_win01_data, 458 .type = DRM_PLANE_TYPE_PRIMARY }, 459 { .base = 0x40, .phy = &rk3288_win01_data, 460 .type = DRM_PLANE_TYPE_CURSOR }, 461 }; 462 463 static const struct vop_data rk3228_vop = { 464 .version = VOP_VERSION(3, 7), 465 .feature = VOP_FEATURE_OUTPUT_RGB10, 466 .intr = &rk3366_vop_intr, 467 .common = &rk3288_common, 468 .modeset = &rk3288_modeset, 469 .output = &rk3399_output, 470 .misc = &rk3368_misc, 471 .win = rk3228_vop_win_data, 472 .win_size = ARRAY_SIZE(rk3228_vop_win_data), 473 }; 474 475 static const struct vop_modeset rk3328_modeset = { 476 .htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 477 .hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0), 478 .vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 479 .vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0), 480 .hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0), 481 .vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0), 482 }; 483 484 static const struct vop_output rk3328_output = { 485 .rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12), 486 .hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13), 487 .edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14), 488 .mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15), 489 .rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 16), 490 .hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 20), 491 .edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 24), 492 .mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 28), 493 }; 494 495 static const struct vop_misc rk3328_misc = { 496 .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11), 497 }; 498 499 static const struct vop_common rk3328_common = { 500 .standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22), 501 .dither_down = VOP_REG(RK3328_DSP_CTRL1, 0xf, 1), 502 .dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6), 503 .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18), 504 .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0), 505 .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), 506 }; 507 508 static const struct vop_intr rk3328_vop_intr = { 509 .intrs = rk3368_vop_intrs, 510 .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 511 .line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0), 512 .line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16), 513 .status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0), 514 .enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0), 515 .clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0), 516 }; 517 518 static const struct vop_win_data rk3328_vop_win_data[] = { 519 { .base = 0xd0, .phy = &rk3288_win01_data, 520 .type = DRM_PLANE_TYPE_PRIMARY }, 521 { .base = 0x1d0, .phy = &rk3288_win01_data, 522 .type = DRM_PLANE_TYPE_OVERLAY }, 523 { .base = 0x2d0, .phy = &rk3288_win01_data, 524 .type = DRM_PLANE_TYPE_CURSOR }, 525 }; 526 527 static const struct vop_data rk3328_vop = { 528 .version = VOP_VERSION(3, 8), 529 .feature = VOP_FEATURE_OUTPUT_RGB10, 530 .intr = &rk3328_vop_intr, 531 .common = &rk3328_common, 532 .modeset = &rk3328_modeset, 533 .output = &rk3328_output, 534 .misc = &rk3328_misc, 535 .win = rk3328_vop_win_data, 536 .win_size = ARRAY_SIZE(rk3328_vop_win_data), 537 }; 538 539 static const struct of_device_id vop_driver_dt_match[] = { 540 { .compatible = "rockchip,rk3036-vop", 541 .data = &rk3036_vop }, 542 { .compatible = "rockchip,rk3126-vop", 543 .data = &rk3126_vop }, 544 { .compatible = "rockchip,rk3288-vop", 545 .data = &rk3288_vop }, 546 { .compatible = "rockchip,rk3368-vop", 547 .data = &rk3368_vop }, 548 { .compatible = "rockchip,rk3366-vop", 549 .data = &rk3366_vop }, 550 { .compatible = "rockchip,rk3399-vop-big", 551 .data = &rk3399_vop_big }, 552 { .compatible = "rockchip,rk3399-vop-lit", 553 .data = &rk3399_vop_lit }, 554 { .compatible = "rockchip,rk3228-vop", 555 .data = &rk3228_vop }, 556 { .compatible = "rockchip,rk3328-vop", 557 .data = &rk3328_vop }, 558 {}, 559 }; 560 MODULE_DEVICE_TABLE(of, vop_driver_dt_match); 561 562 static int vop_probe(struct platform_device *pdev) 563 { 564 struct device *dev = &pdev->dev; 565 566 if (!dev->of_node) { 567 DRM_DEV_ERROR(dev, "can't find vop devices\n"); 568 return -ENODEV; 569 } 570 571 return component_add(dev, &vop_component_ops); 572 } 573 574 static int vop_remove(struct platform_device *pdev) 575 { 576 component_del(&pdev->dev, &vop_component_ops); 577 578 return 0; 579 } 580 581 struct platform_driver vop_platform_driver = { 582 .probe = vop_probe, 583 .remove = vop_remove, 584 .driver = { 585 .name = "rockchip-vop", 586 .of_match_table = of_match_ptr(vop_driver_dt_match), 587 }, 588 }; 589