1a67719d1SMark Yao /* 2a67719d1SMark Yao * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd 3a67719d1SMark Yao * Author:Mark Yao <mark.yao@rock-chips.com> 4a67719d1SMark Yao * 5a67719d1SMark Yao * This software is licensed under the terms of the GNU General Public 6a67719d1SMark Yao * License version 2, as published by the Free Software Foundation, and 7a67719d1SMark Yao * may be copied, distributed, and modified under those terms. 8a67719d1SMark Yao * 9a67719d1SMark Yao * This program is distributed in the hope that it will be useful, 10a67719d1SMark Yao * but WITHOUT ANY WARRANTY; without even the implied warranty of 11a67719d1SMark Yao * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12a67719d1SMark Yao * GNU General Public License for more details. 13a67719d1SMark Yao */ 14a67719d1SMark Yao 15a67719d1SMark Yao #include <drm/drmP.h> 16a67719d1SMark Yao 17a67719d1SMark Yao #include <linux/kernel.h> 18a67719d1SMark Yao #include <linux/component.h> 19a67719d1SMark Yao 20a67719d1SMark Yao #include "rockchip_drm_vop.h" 21a67719d1SMark Yao #include "rockchip_vop_reg.h" 22a67719d1SMark Yao 239548e1b4SMark yao #define _VOP_REG(off, _mask, _shift, _write_mask, _relaxed) \ 249548e1b4SMark yao { \ 259548e1b4SMark yao .offset = off, \ 26a67719d1SMark Yao .mask = _mask, \ 279548e1b4SMark yao .shift = _shift, \ 289548e1b4SMark yao .write_mask = _write_mask, \ 299548e1b4SMark yao .relaxed = _relaxed, \ 309548e1b4SMark yao } 31d49463ecSMark Yao 329548e1b4SMark yao #define VOP_REG(off, _mask, _shift) \ 339548e1b4SMark yao _VOP_REG(off, _mask, _shift, false, true) 349548e1b4SMark yao 359548e1b4SMark yao #define VOP_REG_SYNC(off, _mask, _shift) \ 369548e1b4SMark yao _VOP_REG(off, _mask, _shift, false, false) 379548e1b4SMark yao 389548e1b4SMark yao #define VOP_REG_MASK_SYNC(off, _mask, _shift) \ 399548e1b4SMark yao _VOP_REG(off, _mask, _shift, true, false) 40a67719d1SMark Yao 41f7673453SMark Yao static const uint32_t formats_win_full[] = { 42a67719d1SMark Yao DRM_FORMAT_XRGB8888, 43a67719d1SMark Yao DRM_FORMAT_ARGB8888, 44a67719d1SMark Yao DRM_FORMAT_XBGR8888, 45a67719d1SMark Yao DRM_FORMAT_ABGR8888, 46a67719d1SMark Yao DRM_FORMAT_RGB888, 47a67719d1SMark Yao DRM_FORMAT_BGR888, 48a67719d1SMark Yao DRM_FORMAT_RGB565, 49a67719d1SMark Yao DRM_FORMAT_BGR565, 50a67719d1SMark Yao DRM_FORMAT_NV12, 51a67719d1SMark Yao DRM_FORMAT_NV16, 52a67719d1SMark Yao DRM_FORMAT_NV24, 53a67719d1SMark Yao }; 54a67719d1SMark Yao 55f7673453SMark Yao static const uint32_t formats_win_lite[] = { 56a67719d1SMark Yao DRM_FORMAT_XRGB8888, 57a67719d1SMark Yao DRM_FORMAT_ARGB8888, 58a67719d1SMark Yao DRM_FORMAT_XBGR8888, 59a67719d1SMark Yao DRM_FORMAT_ABGR8888, 60a67719d1SMark Yao DRM_FORMAT_RGB888, 61a67719d1SMark Yao DRM_FORMAT_BGR888, 62a67719d1SMark Yao DRM_FORMAT_RGB565, 63a67719d1SMark Yao DRM_FORMAT_BGR565, 64a67719d1SMark Yao }; 65a67719d1SMark Yao 66b51502adSMark Yao static const struct vop_scl_regs rk3036_win_scl = { 67b51502adSMark Yao .scale_yrgb_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 68b51502adSMark Yao .scale_yrgb_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 69b51502adSMark Yao .scale_cbcr_x = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 70b51502adSMark Yao .scale_cbcr_y = VOP_REG(RK3036_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 71b51502adSMark Yao }; 72b51502adSMark Yao 73b51502adSMark Yao static const struct vop_win_phy rk3036_win0_data = { 74b51502adSMark Yao .scl = &rk3036_win_scl, 75b51502adSMark Yao .data_formats = formats_win_full, 76b51502adSMark Yao .nformats = ARRAY_SIZE(formats_win_full), 77b51502adSMark Yao .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 0), 78b51502adSMark Yao .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 3), 79b51502adSMark Yao .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 15), 80b51502adSMark Yao .act_info = VOP_REG(RK3036_WIN0_ACT_INFO, 0x1fff1fff, 0), 81b51502adSMark Yao .dsp_info = VOP_REG(RK3036_WIN0_DSP_INFO, 0x0fff0fff, 0), 82b51502adSMark Yao .dsp_st = VOP_REG(RK3036_WIN0_DSP_ST, 0x1fff1fff, 0), 83b51502adSMark Yao .yrgb_mst = VOP_REG(RK3036_WIN0_YRGB_MST, 0xffffffff, 0), 84b51502adSMark Yao .uv_mst = VOP_REG(RK3036_WIN0_CBR_MST, 0xffffffff, 0), 85b51502adSMark Yao .yrgb_vir = VOP_REG(RK3036_WIN0_VIR, 0xffff, 0), 86b51502adSMark Yao .uv_vir = VOP_REG(RK3036_WIN0_VIR, 0x1fff, 16), 87b51502adSMark Yao }; 88b51502adSMark Yao 89b51502adSMark Yao static const struct vop_win_phy rk3036_win1_data = { 90b51502adSMark Yao .data_formats = formats_win_lite, 91b51502adSMark Yao .nformats = ARRAY_SIZE(formats_win_lite), 92b51502adSMark Yao .enable = VOP_REG(RK3036_SYS_CTRL, 0x1, 1), 93b51502adSMark Yao .format = VOP_REG(RK3036_SYS_CTRL, 0x7, 6), 94b51502adSMark Yao .rb_swap = VOP_REG(RK3036_SYS_CTRL, 0x1, 19), 95b51502adSMark Yao .act_info = VOP_REG(RK3036_WIN1_ACT_INFO, 0x1fff1fff, 0), 96b51502adSMark Yao .dsp_info = VOP_REG(RK3036_WIN1_DSP_INFO, 0x0fff0fff, 0), 97b51502adSMark Yao .dsp_st = VOP_REG(RK3036_WIN1_DSP_ST, 0x1fff1fff, 0), 98b51502adSMark Yao .yrgb_mst = VOP_REG(RK3036_WIN1_MST, 0xffffffff, 0), 99b51502adSMark Yao .yrgb_vir = VOP_REG(RK3036_WIN1_VIR, 0xffff, 0), 100b51502adSMark Yao }; 101b51502adSMark Yao 102b51502adSMark Yao static const struct vop_win_data rk3036_vop_win_data[] = { 103b51502adSMark Yao { .base = 0x00, .phy = &rk3036_win0_data, 104b51502adSMark Yao .type = DRM_PLANE_TYPE_PRIMARY }, 105b51502adSMark Yao { .base = 0x00, .phy = &rk3036_win1_data, 106b51502adSMark Yao .type = DRM_PLANE_TYPE_CURSOR }, 107b51502adSMark Yao }; 108b51502adSMark Yao 109b51502adSMark Yao static const int rk3036_vop_intrs[] = { 110b51502adSMark Yao DSP_HOLD_VALID_INTR, 111b51502adSMark Yao FS_INTR, 112b51502adSMark Yao LINE_FLAG_INTR, 113b51502adSMark Yao BUS_ERROR_INTR, 114b51502adSMark Yao }; 115b51502adSMark Yao 116b51502adSMark Yao static const struct vop_intr rk3036_intr = { 117b51502adSMark Yao .intrs = rk3036_vop_intrs, 118b51502adSMark Yao .nintrs = ARRAY_SIZE(rk3036_vop_intrs), 119ac6560dfSMark yao .line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12), 1209a61c54bSMark yao .status = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 0), 1219a61c54bSMark yao .enable = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 4), 1229a61c54bSMark yao .clear = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 8), 123b51502adSMark Yao }; 124b51502adSMark Yao 1259a61c54bSMark yao static const struct vop_modeset rk3036_modeset = { 126b51502adSMark Yao .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 127b51502adSMark Yao .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0), 128b51502adSMark Yao .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 129b51502adSMark Yao .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0), 1309a61c54bSMark yao }; 1319a61c54bSMark yao 1329a61c54bSMark yao static const struct vop_output rk3036_output = { 1339a61c54bSMark yao .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4), 1349a61c54bSMark yao }; 1359a61c54bSMark yao 1369a61c54bSMark yao static const struct vop_common rk3036_common = { 1379a61c54bSMark yao .standby = VOP_REG_SYNC(RK3036_SYS_CTRL, 0x1, 30), 1389a61c54bSMark yao .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0), 1399a61c54bSMark yao .dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24), 1409548e1b4SMark yao .cfg_done = VOP_REG_SYNC(RK3036_REG_CFG_DONE, 0x1, 0), 141b51502adSMark Yao }; 142b51502adSMark Yao 143b51502adSMark Yao static const struct vop_data rk3036_vop = { 144b51502adSMark Yao .intr = &rk3036_intr, 1459a61c54bSMark yao .common = &rk3036_common, 1469a61c54bSMark yao .modeset = &rk3036_modeset, 1479a61c54bSMark yao .output = &rk3036_output, 148b51502adSMark Yao .win = rk3036_vop_win_data, 149b51502adSMark Yao .win_size = ARRAY_SIZE(rk3036_vop_win_data), 150b51502adSMark Yao }; 151b51502adSMark Yao 152f7673453SMark Yao static const struct vop_scl_extension rk3288_win_full_scl_ext = { 153f7673453SMark Yao .cbcr_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 31), 154f7673453SMark Yao .cbcr_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 30), 155f7673453SMark Yao .cbcr_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 28), 156f7673453SMark Yao .cbcr_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 26), 157f7673453SMark Yao .cbcr_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 24), 158f7673453SMark Yao .yrgb_vsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 23), 159f7673453SMark Yao .yrgb_vsu_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 22), 160f7673453SMark Yao .yrgb_hsd_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 20), 161f7673453SMark Yao .yrgb_ver_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 18), 162f7673453SMark Yao .yrgb_hor_scl_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 16), 163f7673453SMark Yao .line_load_mode = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 15), 164f7673453SMark Yao .cbcr_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0x7, 12), 165f7673453SMark Yao .yrgb_axi_gather_num = VOP_REG(RK3288_WIN0_CTRL1, 0xf, 8), 166f7673453SMark Yao .vsd_cbcr_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 7), 167f7673453SMark Yao .vsd_cbcr_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 6), 168f7673453SMark Yao .vsd_yrgb_gt2 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 5), 169f7673453SMark Yao .vsd_yrgb_gt4 = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 4), 170f7673453SMark Yao .bic_coe_sel = VOP_REG(RK3288_WIN0_CTRL1, 0x3, 2), 171f7673453SMark Yao .cbcr_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 1), 172f7673453SMark Yao .yrgb_axi_gather_en = VOP_REG(RK3288_WIN0_CTRL1, 0x1, 0), 173f7673453SMark Yao .lb_mode = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 5), 1741194fffbSMark Yao }; 1751194fffbSMark Yao 176f7673453SMark Yao static const struct vop_scl_regs rk3288_win_full_scl = { 177f7673453SMark Yao .ext = &rk3288_win_full_scl_ext, 178f7673453SMark Yao .scale_yrgb_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), 179f7673453SMark Yao .scale_yrgb_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), 180f7673453SMark Yao .scale_cbcr_x = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 0x0), 181f7673453SMark Yao .scale_cbcr_y = VOP_REG(RK3288_WIN0_SCL_FACTOR_CBR, 0xffff, 16), 182a67719d1SMark Yao }; 183a67719d1SMark Yao 184f7673453SMark Yao static const struct vop_win_phy rk3288_win01_data = { 185f7673453SMark Yao .scl = &rk3288_win_full_scl, 186f7673453SMark Yao .data_formats = formats_win_full, 187f7673453SMark Yao .nformats = ARRAY_SIZE(formats_win_full), 188f7673453SMark Yao .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), 189f7673453SMark Yao .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), 190f7673453SMark Yao .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), 191f7673453SMark Yao .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), 192f7673453SMark Yao .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), 193f7673453SMark Yao .dsp_st = VOP_REG(RK3288_WIN0_DSP_ST, 0x1fff1fff, 0), 194f7673453SMark Yao .yrgb_mst = VOP_REG(RK3288_WIN0_YRGB_MST, 0xffffffff, 0), 195f7673453SMark Yao .uv_mst = VOP_REG(RK3288_WIN0_CBR_MST, 0xffffffff, 0), 196f7673453SMark Yao .yrgb_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 0), 197f7673453SMark Yao .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), 198f7673453SMark Yao .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), 199f7673453SMark Yao .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), 2009dd2aca4SMark yao .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), 201a67719d1SMark Yao }; 202a67719d1SMark Yao 203f7673453SMark Yao static const struct vop_win_phy rk3288_win23_data = { 204f7673453SMark Yao .data_formats = formats_win_lite, 205f7673453SMark Yao .nformats = ARRAY_SIZE(formats_win_lite), 20660b7ae7fSMark yao .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4), 20760b7ae7fSMark yao .gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0), 208f7673453SMark Yao .format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1), 209f7673453SMark Yao .rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12), 210f7673453SMark Yao .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0), 211f7673453SMark Yao .dsp_st = VOP_REG(RK3288_WIN2_DSP_ST0, 0x1fff1fff, 0), 212f7673453SMark Yao .yrgb_mst = VOP_REG(RK3288_WIN2_MST0, 0xffffffff, 0), 213f7673453SMark Yao .yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 0), 214f7673453SMark Yao .src_alpha_ctl = VOP_REG(RK3288_WIN2_SRC_ALPHA_CTRL, 0xff, 0), 215f7673453SMark Yao .dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0), 216a67719d1SMark Yao }; 217a67719d1SMark Yao 2189a61c54bSMark yao static const struct vop_modeset rk3288_modeset = { 219f7673453SMark Yao .htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 220f7673453SMark Yao .hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0), 221f7673453SMark Yao .vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 222f7673453SMark Yao .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0), 223f7673453SMark Yao .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0), 224f7673453SMark Yao .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0), 2259a61c54bSMark yao }; 2269a61c54bSMark yao 2279a61c54bSMark yao static const struct vop_output rk3288_output = { 2289a61c54bSMark yao .pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4), 2299a61c54bSMark yao .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 2309a61c54bSMark yao .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 2319a61c54bSMark yao .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 2329a61c54bSMark yao .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 2339a61c54bSMark yao }; 2349a61c54bSMark yao 2359a61c54bSMark yao static const struct vop_common rk3288_common = { 2369a61c54bSMark yao .standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22), 2379a61c54bSMark yao .gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23), 2389a61c54bSMark yao .mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20), 2399a61c54bSMark yao .dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1), 2409a61c54bSMark yao .dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6), 2419a61c54bSMark yao .data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19), 2429a61c54bSMark yao .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18), 2439a61c54bSMark yao .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0), 2449548e1b4SMark yao .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), 245a67719d1SMark Yao }; 246a67719d1SMark Yao 247a67719d1SMark Yao /* 248a67719d1SMark Yao * Note: rk3288 has a dedicated 'cursor' window, however, that window requires 249a67719d1SMark Yao * special support to get alpha blending working. For now, just use overlay 250a67719d1SMark Yao * window 3 for the drm cursor. 251a67719d1SMark Yao * 252a67719d1SMark Yao */ 253a67719d1SMark Yao static const struct vop_win_data rk3288_vop_win_data[] = { 254f7673453SMark Yao { .base = 0x00, .phy = &rk3288_win01_data, 255f7673453SMark Yao .type = DRM_PLANE_TYPE_PRIMARY }, 256f7673453SMark Yao { .base = 0x40, .phy = &rk3288_win01_data, 257f7673453SMark Yao .type = DRM_PLANE_TYPE_OVERLAY }, 258f7673453SMark Yao { .base = 0x00, .phy = &rk3288_win23_data, 259f7673453SMark Yao .type = DRM_PLANE_TYPE_OVERLAY }, 260f7673453SMark Yao { .base = 0x50, .phy = &rk3288_win23_data, 261f7673453SMark Yao .type = DRM_PLANE_TYPE_CURSOR }, 262a67719d1SMark Yao }; 263a67719d1SMark Yao 264a67719d1SMark Yao static const int rk3288_vop_intrs[] = { 265a67719d1SMark Yao DSP_HOLD_VALID_INTR, 266a67719d1SMark Yao FS_INTR, 267a67719d1SMark Yao LINE_FLAG_INTR, 268a67719d1SMark Yao BUS_ERROR_INTR, 269a67719d1SMark Yao }; 270a67719d1SMark Yao 271a67719d1SMark Yao static const struct vop_intr rk3288_vop_intr = { 272a67719d1SMark Yao .intrs = rk3288_vop_intrs, 273a67719d1SMark Yao .nintrs = ARRAY_SIZE(rk3288_vop_intrs), 274ac6560dfSMark yao .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12), 275f7673453SMark Yao .status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0), 276f7673453SMark Yao .enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4), 277f7673453SMark Yao .clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8), 278a67719d1SMark Yao }; 279a67719d1SMark Yao 280a67719d1SMark Yao static const struct vop_data rk3288_vop = { 281eb5cb6aaSMark yao .version = VOP_VERSION(3, 1), 282efd11cc8SMark yao .feature = VOP_FEATURE_OUTPUT_RGB10, 283a67719d1SMark Yao .intr = &rk3288_vop_intr, 2849a61c54bSMark yao .common = &rk3288_common, 2859a61c54bSMark yao .modeset = &rk3288_modeset, 2869a61c54bSMark yao .output = &rk3288_output, 287a67719d1SMark Yao .win = rk3288_vop_win_data, 288a67719d1SMark Yao .win_size = ARRAY_SIZE(rk3288_vop_win_data), 289a67719d1SMark Yao }; 290a67719d1SMark Yao 291eb5cb6aaSMark yao static const int rk3368_vop_intrs[] = { 2920a63bfd0SMark Yao FS_INTR, 2930a63bfd0SMark Yao 0, 0, 2940a63bfd0SMark Yao LINE_FLAG_INTR, 2950a63bfd0SMark Yao 0, 2960a63bfd0SMark Yao BUS_ERROR_INTR, 2970a63bfd0SMark Yao 0, 0, 0, 0, 0, 0, 0, 2980a63bfd0SMark Yao DSP_HOLD_VALID_INTR, 299f7673453SMark Yao }; 300f7673453SMark Yao 301eb5cb6aaSMark yao static const struct vop_intr rk3368_vop_intr = { 302eb5cb6aaSMark yao .intrs = rk3368_vop_intrs, 303eb5cb6aaSMark yao .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 304eb5cb6aaSMark yao .line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0), 305eb5cb6aaSMark yao .line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16), 306eb5cb6aaSMark yao .status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0), 307eb5cb6aaSMark yao .enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0), 308eb5cb6aaSMark yao .clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0), 309eb5cb6aaSMark yao }; 310eb5cb6aaSMark yao 311eb5cb6aaSMark yao static const struct vop_win_phy rk3368_win23_data = { 312eb5cb6aaSMark yao .data_formats = formats_win_lite, 313eb5cb6aaSMark yao .nformats = ARRAY_SIZE(formats_win_lite), 314eb5cb6aaSMark yao .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0), 315eb5cb6aaSMark yao .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4), 316eb5cb6aaSMark yao .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5), 317eb5cb6aaSMark yao .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20), 318eb5cb6aaSMark yao .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0), 319eb5cb6aaSMark yao .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0), 320eb5cb6aaSMark yao .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0), 321eb5cb6aaSMark yao .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0), 322eb5cb6aaSMark yao .src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0), 323eb5cb6aaSMark yao .dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0), 324eb5cb6aaSMark yao }; 325eb5cb6aaSMark yao 326eb5cb6aaSMark yao static const struct vop_win_data rk3368_vop_win_data[] = { 327eb5cb6aaSMark yao { .base = 0x00, .phy = &rk3288_win01_data, 328eb5cb6aaSMark yao .type = DRM_PLANE_TYPE_PRIMARY }, 329eb5cb6aaSMark yao { .base = 0x40, .phy = &rk3288_win01_data, 330eb5cb6aaSMark yao .type = DRM_PLANE_TYPE_OVERLAY }, 331eb5cb6aaSMark yao { .base = 0x00, .phy = &rk3368_win23_data, 332eb5cb6aaSMark yao .type = DRM_PLANE_TYPE_OVERLAY }, 333eb5cb6aaSMark yao { .base = 0x50, .phy = &rk3368_win23_data, 334eb5cb6aaSMark yao .type = DRM_PLANE_TYPE_CURSOR }, 335eb5cb6aaSMark yao }; 336eb5cb6aaSMark yao 337eb5cb6aaSMark yao static const struct vop_output rk3368_output = { 338eb5cb6aaSMark yao .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16), 339eb5cb6aaSMark yao .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20), 340eb5cb6aaSMark yao .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24), 341eb5cb6aaSMark yao .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28), 342eb5cb6aaSMark yao .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 343eb5cb6aaSMark yao .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 344eb5cb6aaSMark yao .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 345eb5cb6aaSMark yao .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 346eb5cb6aaSMark yao }; 347eb5cb6aaSMark yao 348eb5cb6aaSMark yao static const struct vop_misc rk3368_misc = { 349eb5cb6aaSMark yao .global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11), 350eb5cb6aaSMark yao }; 351eb5cb6aaSMark yao 352eb5cb6aaSMark yao static const struct vop_data rk3368_vop = { 353eb5cb6aaSMark yao .version = VOP_VERSION(3, 2), 354eb5cb6aaSMark yao .intr = &rk3368_vop_intr, 355eb5cb6aaSMark yao .common = &rk3288_common, 356eb5cb6aaSMark yao .modeset = &rk3288_modeset, 357eb5cb6aaSMark yao .output = &rk3368_output, 358eb5cb6aaSMark yao .misc = &rk3368_misc, 359eb5cb6aaSMark yao .win = rk3368_vop_win_data, 360eb5cb6aaSMark yao .win_size = ARRAY_SIZE(rk3368_vop_win_data), 361eb5cb6aaSMark yao }; 362eb5cb6aaSMark yao 363eb5cb6aaSMark yao static const struct vop_intr rk3366_vop_intr = { 364eb5cb6aaSMark yao .intrs = rk3368_vop_intrs, 365eb5cb6aaSMark yao .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 366eb5cb6aaSMark yao .line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0), 367eb5cb6aaSMark yao .line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16), 368eb5cb6aaSMark yao .status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0), 369eb5cb6aaSMark yao .enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0), 370eb5cb6aaSMark yao .clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0), 371eb5cb6aaSMark yao }; 372eb5cb6aaSMark yao 373eb5cb6aaSMark yao static const struct vop_data rk3366_vop = { 374eb5cb6aaSMark yao .version = VOP_VERSION(3, 4), 375eb5cb6aaSMark yao .intr = &rk3366_vop_intr, 376eb5cb6aaSMark yao .common = &rk3288_common, 377eb5cb6aaSMark yao .modeset = &rk3288_modeset, 378eb5cb6aaSMark yao .output = &rk3368_output, 379eb5cb6aaSMark yao .misc = &rk3368_misc, 380eb5cb6aaSMark yao .win = rk3368_vop_win_data, 381eb5cb6aaSMark yao .win_size = ARRAY_SIZE(rk3368_vop_win_data), 382f7673453SMark Yao }; 383f7673453SMark Yao 3849a61c54bSMark yao static const struct vop_output rk3399_output = { 3859a61c54bSMark yao .dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16), 386eb5cb6aaSMark yao .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16), 387eb5cb6aaSMark yao .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20), 388eb5cb6aaSMark yao .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24), 389eb5cb6aaSMark yao .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28), 3909a61c54bSMark yao .dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11), 3919a61c54bSMark yao .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), 3929a61c54bSMark yao .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), 3939a61c54bSMark yao .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), 3949a61c54bSMark yao .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), 3959a61c54bSMark yao }; 3969a61c54bSMark yao 3970a63bfd0SMark Yao static const struct vop_data rk3399_vop_big = { 398eb5cb6aaSMark yao .version = VOP_VERSION(3, 5), 399efd11cc8SMark yao .feature = VOP_FEATURE_OUTPUT_RGB10, 400eb5cb6aaSMark yao .intr = &rk3366_vop_intr, 4019a61c54bSMark yao .common = &rk3288_common, 4029a61c54bSMark yao .modeset = &rk3288_modeset, 4039a61c54bSMark yao .output = &rk3399_output, 404eb5cb6aaSMark yao .misc = &rk3368_misc, 405eb5cb6aaSMark yao .win = rk3368_vop_win_data, 406eb5cb6aaSMark yao .win_size = ARRAY_SIZE(rk3368_vop_win_data), 4070a63bfd0SMark Yao }; 4080a63bfd0SMark Yao 4090a63bfd0SMark Yao static const struct vop_win_data rk3399_vop_lit_win_data[] = { 4100a63bfd0SMark Yao { .base = 0x00, .phy = &rk3288_win01_data, 411f7673453SMark Yao .type = DRM_PLANE_TYPE_PRIMARY }, 412eb5cb6aaSMark yao { .base = 0x00, .phy = &rk3368_win23_data, 413f7673453SMark Yao .type = DRM_PLANE_TYPE_CURSOR}, 414f7673453SMark Yao }; 415f7673453SMark Yao 4160a63bfd0SMark Yao static const struct vop_data rk3399_vop_lit = { 417eb5cb6aaSMark yao .version = VOP_VERSION(3, 6), 418eb5cb6aaSMark yao .intr = &rk3366_vop_intr, 4199a61c54bSMark yao .common = &rk3288_common, 4209a61c54bSMark yao .modeset = &rk3288_modeset, 4219a61c54bSMark yao .output = &rk3399_output, 422eb5cb6aaSMark yao .misc = &rk3368_misc, 4230a63bfd0SMark Yao .win = rk3399_vop_lit_win_data, 4240a63bfd0SMark Yao .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data), 425f7673453SMark Yao }; 426f7673453SMark Yao 427eb5cb6aaSMark yao static const struct vop_win_data rk3228_vop_win_data[] = { 428eb5cb6aaSMark yao { .base = 0x00, .phy = &rk3288_win01_data, 429eb5cb6aaSMark yao .type = DRM_PLANE_TYPE_PRIMARY }, 430eb5cb6aaSMark yao { .base = 0x40, .phy = &rk3288_win01_data, 431eb5cb6aaSMark yao .type = DRM_PLANE_TYPE_CURSOR }, 432eb5cb6aaSMark yao }; 433eb5cb6aaSMark yao 434eb5cb6aaSMark yao static const struct vop_data rk3228_vop = { 435eb5cb6aaSMark yao .version = VOP_VERSION(3, 7), 436eb5cb6aaSMark yao .feature = VOP_FEATURE_OUTPUT_RGB10, 437eb5cb6aaSMark yao .intr = &rk3366_vop_intr, 438eb5cb6aaSMark yao .common = &rk3288_common, 439eb5cb6aaSMark yao .modeset = &rk3288_modeset, 440eb5cb6aaSMark yao .output = &rk3399_output, 441eb5cb6aaSMark yao .misc = &rk3368_misc, 442eb5cb6aaSMark yao .win = rk3228_vop_win_data, 443eb5cb6aaSMark yao .win_size = ARRAY_SIZE(rk3228_vop_win_data), 444eb5cb6aaSMark yao }; 445eb5cb6aaSMark yao 446eb5cb6aaSMark yao static const struct vop_modeset rk3328_modeset = { 447eb5cb6aaSMark yao .htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), 448eb5cb6aaSMark yao .hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0), 449eb5cb6aaSMark yao .vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), 450eb5cb6aaSMark yao .vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0), 451eb5cb6aaSMark yao .hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0), 452eb5cb6aaSMark yao .vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0), 453eb5cb6aaSMark yao }; 454eb5cb6aaSMark yao 455eb5cb6aaSMark yao static const struct vop_output rk3328_output = { 456eb5cb6aaSMark yao .rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12), 457eb5cb6aaSMark yao .hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13), 458eb5cb6aaSMark yao .edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14), 459eb5cb6aaSMark yao .mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15), 460eb5cb6aaSMark yao .rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 16), 461eb5cb6aaSMark yao .hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 20), 462eb5cb6aaSMark yao .edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 24), 463eb5cb6aaSMark yao .mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 28), 464eb5cb6aaSMark yao }; 465eb5cb6aaSMark yao 466eb5cb6aaSMark yao static const struct vop_misc rk3328_misc = { 467eb5cb6aaSMark yao .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11), 468eb5cb6aaSMark yao }; 469eb5cb6aaSMark yao 470eb5cb6aaSMark yao static const struct vop_common rk3328_common = { 471eb5cb6aaSMark yao .standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22), 472eb5cb6aaSMark yao .dither_down = VOP_REG(RK3328_DSP_CTRL1, 0xf, 1), 473eb5cb6aaSMark yao .dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6), 474eb5cb6aaSMark yao .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18), 475eb5cb6aaSMark yao .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0), 476eb5cb6aaSMark yao .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), 477eb5cb6aaSMark yao }; 478eb5cb6aaSMark yao 479eb5cb6aaSMark yao static const struct vop_intr rk3328_vop_intr = { 480eb5cb6aaSMark yao .intrs = rk3368_vop_intrs, 481eb5cb6aaSMark yao .nintrs = ARRAY_SIZE(rk3368_vop_intrs), 482eb5cb6aaSMark yao .line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0), 483eb5cb6aaSMark yao .line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16), 484eb5cb6aaSMark yao .status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0), 485eb5cb6aaSMark yao .enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0), 486eb5cb6aaSMark yao .clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0), 487eb5cb6aaSMark yao }; 488eb5cb6aaSMark yao 489eb5cb6aaSMark yao static const struct vop_win_data rk3328_vop_win_data[] = { 490eb5cb6aaSMark yao { .base = 0xd0, .phy = &rk3288_win01_data, 491eb5cb6aaSMark yao .type = DRM_PLANE_TYPE_PRIMARY }, 492eb5cb6aaSMark yao { .base = 0x1d0, .phy = &rk3288_win01_data, 493eb5cb6aaSMark yao .type = DRM_PLANE_TYPE_OVERLAY }, 494eb5cb6aaSMark yao { .base = 0x2d0, .phy = &rk3288_win01_data, 495eb5cb6aaSMark yao .type = DRM_PLANE_TYPE_CURSOR }, 496eb5cb6aaSMark yao }; 497eb5cb6aaSMark yao 498eb5cb6aaSMark yao static const struct vop_data rk3328_vop = { 499eb5cb6aaSMark yao .version = VOP_VERSION(3, 8), 500eb5cb6aaSMark yao .feature = VOP_FEATURE_OUTPUT_RGB10, 501eb5cb6aaSMark yao .intr = &rk3328_vop_intr, 502eb5cb6aaSMark yao .common = &rk3328_common, 503eb5cb6aaSMark yao .modeset = &rk3328_modeset, 504eb5cb6aaSMark yao .output = &rk3328_output, 505eb5cb6aaSMark yao .misc = &rk3328_misc, 506eb5cb6aaSMark yao .win = rk3328_vop_win_data, 507eb5cb6aaSMark yao .win_size = ARRAY_SIZE(rk3328_vop_win_data), 508eb5cb6aaSMark yao }; 509eb5cb6aaSMark yao 510a67719d1SMark Yao static const struct of_device_id vop_driver_dt_match[] = { 511f7673453SMark Yao { .compatible = "rockchip,rk3036-vop", 512f7673453SMark Yao .data = &rk3036_vop }, 513b51502adSMark Yao { .compatible = "rockchip,rk3288-vop", 514b51502adSMark Yao .data = &rk3288_vop }, 515eb5cb6aaSMark yao { .compatible = "rockchip,rk3368-vop", 516eb5cb6aaSMark yao .data = &rk3368_vop }, 517eb5cb6aaSMark yao { .compatible = "rockchip,rk3366-vop", 518eb5cb6aaSMark yao .data = &rk3366_vop }, 5190a63bfd0SMark Yao { .compatible = "rockchip,rk3399-vop-big", 5200a63bfd0SMark Yao .data = &rk3399_vop_big }, 5210a63bfd0SMark Yao { .compatible = "rockchip,rk3399-vop-lit", 5220a63bfd0SMark Yao .data = &rk3399_vop_lit }, 523eb5cb6aaSMark yao { .compatible = "rockchip,rk3228-vop", 524eb5cb6aaSMark yao .data = &rk3228_vop }, 525eb5cb6aaSMark yao { .compatible = "rockchip,rk3328-vop", 526eb5cb6aaSMark yao .data = &rk3328_vop }, 527a67719d1SMark Yao {}, 528a67719d1SMark Yao }; 529a67719d1SMark Yao MODULE_DEVICE_TABLE(of, vop_driver_dt_match); 530a67719d1SMark Yao 531a67719d1SMark Yao static int vop_probe(struct platform_device *pdev) 532a67719d1SMark Yao { 533a67719d1SMark Yao struct device *dev = &pdev->dev; 534a67719d1SMark Yao 535a67719d1SMark Yao if (!dev->of_node) { 536a67719d1SMark Yao dev_err(dev, "can't find vop devices\n"); 537a67719d1SMark Yao return -ENODEV; 538a67719d1SMark Yao } 539a67719d1SMark Yao 540a67719d1SMark Yao return component_add(dev, &vop_component_ops); 541a67719d1SMark Yao } 542a67719d1SMark Yao 543a67719d1SMark Yao static int vop_remove(struct platform_device *pdev) 544a67719d1SMark Yao { 545a67719d1SMark Yao component_del(&pdev->dev, &vop_component_ops); 546a67719d1SMark Yao 547a67719d1SMark Yao return 0; 548a67719d1SMark Yao } 549a67719d1SMark Yao 5508820b68bSJeffy Chen struct platform_driver vop_platform_driver = { 551a67719d1SMark Yao .probe = vop_probe, 552a67719d1SMark Yao .remove = vop_remove, 553a67719d1SMark Yao .driver = { 554a67719d1SMark Yao .name = "rockchip-vop", 555a67719d1SMark Yao .of_match_table = of_match_ptr(vop_driver_dt_match), 556a67719d1SMark Yao }, 557a67719d1SMark Yao }; 558