From 8379fd75553ac334e0c8e314602cd85d6bf7de0a Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Wed, 13 Sep 2023 17:17:21 +0800 Subject: [PATCH] drm/rockchip: vop2: add support rk3576 RK3576 VOP have 2 Cluster win and 4 Esmart win, this win be used by 3 video ports as following roles: * VP0 can use Cluster0/1 and Esmart0/2 * VP1 can use Cluster0/1 and Esmart1/3 * VP2 can use Esmart0/1/2/3 In additions, RK3576 VOP can support DCI/ACM/CSC/HDR/SHARP/GAMMA/3D LUT/POST SCALE/BCSH etc. post process. Signed-off-by: Sandy Huang Change-Id: I89f656e847f758f9d3d57ee0c137b29196de6737 --- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 98 +- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 836 ++++++++++++-- drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 1088 ++++++++++++++++++ drivers/gpu/drm/rockchip/rockchip_vop_reg.h | 73 +- 5 files changed, 2012 insertions(+), 84 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 323c8fcbc2d7..e8c521ff6cbb 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -53,6 +53,7 @@ struct iommu_domain; #define VOP_OUTPUT_IF_DP1 BIT(10) #define VOP_OUTPUT_IF_HDMI0 BIT(11) #define VOP_OUTPUT_IF_HDMI1 BIT(12) +#define VOP_OUTPUT_IF_DP2 BIT(13) #ifndef DRM_FORMAT_NV20 #define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') /* 2x1 subsampled Cr:Cb plane */ diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index abc4b08fb586..6497d6e6dce7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -29,6 +29,7 @@ #define VOP_VERSION_RK3528 VOP2_VERSION(0x50, 0x17, 0x1263) #define VOP_VERSION_RK3562 VOP2_VERSION(0x50, 0x17, 0x4350) #define VOP_VERSION_RK3568 VOP2_VERSION(0x40, 0x15, 0x8023) +#define VOP_VERSION_RK3576 VOP2_VERSION(0x50, 0x19, 0x9765) #define VOP_VERSION_RK3588 VOP2_VERSION(0x40, 0x17, 0x6786) /* register one connector */ @@ -56,6 +57,8 @@ #define VOP_FEATURE_VIVID_HDR BIT(7) #define VOP_FEATURE_POST_ACM BIT(8) #define VOP_FEATURE_POST_CSC BIT(9) +#define VOP_FEATURE_POST_FRC_V2 BIT(10) +#define VOP_FEATURE_POST_SHARP BIT(11) #define VOP_FEATURE_OUTPUT_10BIT VOP_FEATURE_OUTPUT_RGB10 @@ -78,6 +81,7 @@ #define WIN_FEATURE_MIRROR BIT(6) #define WIN_FEATURE_MULTI_AREA BIT(7) #define WIN_FEATURE_Y2R_13BIT_DEPTH BIT(8) +#define WIN_FEATURE_DCI BIT(9) #define VOP2_SOC_VARIANT 4 @@ -124,6 +128,8 @@ enum vop3_esmart_lb_mode { VOP3_ESMART_4K_4K_MODE, VOP3_ESMART_4K_2K_2K_MODE, VOP3_ESMART_2K_2K_2K_2K_MODE, + VOP3_ESMART_4K_4K_4K_MODE, + VOP3_ESMART_4K_4K_2K_2K_MODE, }; /* @@ -144,6 +150,7 @@ enum vop3_esmart_lb_mode { #define VOP2_PD_DSC_8K BIT(5) #define VOP2_PD_DSC_4K BIT(6) #define VOP2_PD_ESMART BIT(7) +#define VOP2_PD_CLUSTER BIT(8) /* * vop2 submem power gate, @@ -238,6 +245,10 @@ struct vop_afbc { struct vop_reg transform_offset; struct vop_reg hdr_ptr; struct vop_reg half_block_en; + struct vop_reg pld_offset_en; + struct vop_reg pld_ptr_offset; + struct vop_reg pld_range_en; + struct vop_reg pld_ptr_range; struct vop_reg xmirror; struct vop_reg ymirror; struct vop_reg rotate_270; @@ -725,6 +736,8 @@ struct vop2_scl_regs { struct vop_reg cbcr_hscl_filter_mode; struct vop_reg cbcr_hor_scl_mode; struct vop_reg cbcr_vscl_filter_mode; + struct vop_reg zme_dering_en; + struct vop_reg zme_dering_para; struct vop_reg vsd_cbcr_gt2; struct vop_reg vsd_cbcr_gt4; struct vop_reg vsd_yrgb_gt2; @@ -745,6 +758,7 @@ struct vop2_win_regs { struct vop_reg gate; struct vop_reg enable; struct vop_reg format; + struct vop_reg format_argb1555; struct vop_reg tile_mode; struct vop_reg csc_mode; struct vop_reg csc_13bit_en; @@ -762,6 +776,7 @@ struct vop2_win_regs { struct vop_reg yuv_clip; struct vop_reg lb_mode; struct vop_reg y2r_en; + struct vop_reg csc_y2r_path_sel; struct vop_reg r2y_en; struct vop_reg channel; struct vop_reg dst_alpha_ctl; @@ -811,14 +826,15 @@ struct vop2_video_port_regs { struct vop_reg dither_up_en; struct vop_reg bg_dly; - struct vop_reg core_dclk_div; struct vop_reg p2i_en; struct vop_reg dual_channel_en; struct vop_reg dual_channel_swap; struct vop_reg dsp_lut_en; - struct vop_reg dclk_div2; - struct vop_reg dclk_div2_phase_lock; + struct vop_reg core_dclk_div; /* dclk core */ + struct vop_reg dclk_div2; /* dclk out */ + + struct vop_reg dclk_div2_phase_lock; /* used to adjust phase when yuv420 output */ struct vop_reg hdr10_en; struct vop_reg hdr_lut_update_en; @@ -937,6 +953,7 @@ struct vop2_power_domain_regs { struct vop_reg pd; struct vop_reg status; struct vop_reg bisr_en_status; + struct vop_reg otp_bisr_en_status; struct vop_reg pmu_status; }; @@ -995,11 +1012,15 @@ struct vop2_wb_regs { struct vop_reg scale_y_en; struct vop_reg axi_yrgb_id; struct vop_reg axi_uv_id; + struct vop_reg vir_stride; + struct vop_reg vir_stride_en; + struct vop_reg act_width; + struct vop_reg one_frame_mode; }; struct vop2_power_domain_data { - uint8_t id; - uint8_t parent_id; + uint16_t id; + uint16_t parent_id; /* * @module_id_mask: module id of which module this power domain is belongs to. * PD_CLUSTER0,1,2,3 only belongs to CLUSTER0/1/2/3, PD_Esmart0 shared by Esmart1/2/3 @@ -1029,7 +1050,7 @@ struct vop2_win_data { const char *name; uint8_t phys_id; uint8_t splice_win_id; - uint8_t pd_id; + uint16_t pd_id; uint8_t axi_id; uint8_t axi_yrgb_id; uint8_t axi_uv_id; @@ -1074,7 +1095,7 @@ struct dsc_error_info { struct vop2_dsc_data { uint8_t id; - uint8_t pd_id; + uint16_t pd_id; uint8_t max_slice_num; uint8_t max_linebuf_depth; /* used to generate the bitstream */ uint8_t min_bits_per_pixel; /* bit num after encoder compress */ @@ -1103,6 +1124,7 @@ struct vop3_ovl_mix_regs { struct vop3_ovl_regs { const struct vop3_ovl_mix_regs *layer_mix_regs; const struct vop3_ovl_mix_regs *hdr_mix_regs; + const struct vop3_ovl_mix_regs *extra_mix_regs; }; struct vop2_video_port_data { @@ -1121,6 +1143,7 @@ struct vop2_video_port_data { const u8 layer_mix_dly; const u8 hdr_mix_dly; const u8 win_dly; + const u8 pixel_rate; const struct vop_intr *intr; const struct vop_hdr_table *hdr_table; const struct vop2_video_port_regs *regs; @@ -1208,16 +1231,21 @@ struct vop2_ctrl { struct vop_reg version; struct vop_reg standby; struct vop_reg dma_stop; + struct vop_reg rkmmu_v2_en; + struct vop_reg rkmmu_v2_sel_axi; struct vop_reg dsp_vs_t_sel; struct vop_reg lut_dma_en; struct vop_reg axi_outstanding_max_num; struct vop_reg axi_max_outstanding_en; struct vop_reg hdmi_dclk_out_en; + struct vop_reg hdmi0_r2y_en; + struct vop_reg hdmi0_r2y_mode; struct vop_reg rgb_en; struct vop_reg hdmi0_en; struct vop_reg hdmi1_en; struct vop_reg dp0_en; struct vop_reg dp1_en; + struct vop_reg dp2_en; struct vop_reg edp0_en; struct vop_reg edp1_en; struct vop_reg mipi0_en; @@ -1244,10 +1272,13 @@ struct vop2_ctrl { struct vop_reg dp0_pin_pol; struct vop_reg dp1_dclk_pol; struct vop_reg dp1_pin_pol; + struct vop_reg dp2_dclk_pol; + struct vop_reg dp2_pin_pol; /* This will be reference by win_phy_id */ struct vop_reg win_vp_id[16]; struct vop_reg win_dly[16]; + struct vop_reg win_alpha_map[16]; /* connector mux */ struct vop_reg rgb_mux; @@ -1255,6 +1286,7 @@ struct vop2_ctrl { struct vop_reg hdmi1_mux; struct vop_reg dp0_mux; struct vop_reg dp1_mux; + struct vop_reg dp2_mux; struct vop_reg edp0_mux; struct vop_reg edp1_mux; struct vop_reg mipi0_mux; @@ -1270,9 +1302,10 @@ struct vop2_ctrl { struct vop_reg edp_dual_en; struct vop_reg hdmi_dual_en; struct vop_reg mipi_dual_en; + struct vop_reg rgb_dual_en; struct vop_reg hdmi0_dclk_div; - struct vop_reg hdmi0_pixclk_div; + struct vop_reg hdmi0_pixclk_div;/* crtc last pipeline clk to connector */ struct vop_reg edp0_dclk_div; struct vop_reg edp0_pixclk_div; @@ -1286,6 +1319,18 @@ struct vop2_ctrl { struct vop_reg mipi0_ds_mode; struct vop_reg mipi1_ds_mode; + struct vop_reg hdmi0_dclk_sel;/* sel from dclk_core or dclk_out */ + struct vop_reg edp0_dclk_sel; + struct vop_reg mipi0_dclk_sel; + struct vop_reg rgb_dclk_sel; + struct vop_reg dp0_dclk_sel; + struct vop_reg dp1_dclk_sel; + struct vop_reg dp2_dclk_sel; + + struct vop_reg dp0_pixclk_div;/* crtc last pipeline clk to connector */ + struct vop_reg dp1_pixclk_div; + struct vop_reg dp2_pixclk_div; + struct vop_reg src_color_ctrl; struct vop_reg dst_color_ctrl; struct vop_reg src_alpha_ctrl; @@ -1296,8 +1341,31 @@ struct vop2_ctrl { struct vop_reg gamma_port_sel; struct vop_reg pd_off_imd; + struct vop_reg mipi0_regdone_imd_en; + struct vop_reg mipi0_data1_sel; + struct vop_reg mipi0_dclk_out_en; + struct vop_reg hdmi0_regdone_imd_en; + struct vop_reg hdmi0_data1_sel; + struct vop_reg hdmi0_dclk_out_en; + struct vop_reg edp0_regdone_imd_en; + struct vop_reg edp0_data1_sel; + struct vop_reg edp0_dclk_out_en; + struct vop_reg dp0_regdone_imd_en; + struct vop_reg dp0_data1_sel; + struct vop_reg dp0_dclk_out_en; + struct vop_reg dp1_regdone_imd_en; + struct vop_reg dp1_data1_sel; + struct vop_reg dp1_dclk_out_en; + struct vop_reg dp2_regdone_imd_en; + struct vop_reg dp2_data1_sel; + struct vop_reg dp2_dclk_out_en; + struct vop_reg rgb_regdone_imd_en; + struct vop_reg rgb_data1_sel; + struct vop_reg rgb_dclk_out_en; + struct vop_reg otp_en; struct vop_reg esmart_lb_mode; + struct vop_reg vp_intr_merge_en; struct vop_reg reg_done_frm; struct vop_reg cfg_done; }; @@ -1307,6 +1375,7 @@ struct vop_dump_regs { const char *name; struct vop_reg state; bool enable_state; + uint32_t size; }; struct vop2_vp_plane_mask { @@ -1315,6 +1384,11 @@ struct vop2_vp_plane_mask { u8 attached_layers[ROCKCHIP_MAX_LAYER]; }; +struct vop2_esmart_lb_map { + u8 lb_mode; + u8 lb_map_value; +}; + /** * VOP2 data structe * @@ -1337,6 +1411,8 @@ struct vop2_data { uint8_t nr_mem_pgs; uint8_t esmart_lb_mode; bool delayed_pd; + uint8_t esmart_lb_mode_num; + const struct vop2_esmart_lb_map *esmart_lb_mode_map; const struct vop_intr *axi_intr; const struct vop2_ctrl *ctrl; const struct vop2_dsc_data *dsc; @@ -1355,6 +1431,7 @@ struct vop2_data { const struct vop_grf_ctrl *grf; const struct vop_grf_ctrl *vo0_grf; const struct vop_grf_ctrl *vo1_grf; + const struct vop_grf_ctrl *ioc_grf; const struct vop_dump_regs *dump_regs; uint32_t dump_regs_size; struct vop_rect max_input; @@ -1388,6 +1465,7 @@ struct vop2_data { #define WB_UV_FIFO_FULL_INTR BIT(17) #define WB_YRGB_FIFO_FULL_INTR BIT(18) #define WB_COMPLETE_INTR BIT(19) +#define MMU_EN_INTR BIT(20) #define INTR_MASK (DSP_HOLD_VALID_INTR | FS_INTR | \ LINE_FLAG_INTR | BUS_ERROR_INTR | \ @@ -1397,7 +1475,7 @@ struct vop2_data { HWC_EMPTY_INTR | \ POST_BUF_EMPTY_INTR | \ DMA_FINISH_INTR | FS_FIELD_INTR | \ - FE_INTR) + FE_INTR | WB_COMPLETE_INTR | MMU_EN_INTR) #define DSP_HOLD_VALID_INTR_EN(x) ((x) << 4) #define FS_INTR_EN(x) ((x) << 5) #define LINE_FLAG_INTR_EN(x) ((x) << 6) @@ -1525,12 +1603,14 @@ enum vop2_scale_up_mode { VOP2_SCALE_UP_NRST_NBOR, VOP2_SCALE_UP_BIL, VOP2_SCALE_UP_BIC, + VOP2_SCALE_UP_ZME, }; enum vop2_scale_down_mode { VOP2_SCALE_DOWN_NRST_NBOR, VOP2_SCALE_DOWN_BIL, VOP2_SCALE_DOWN_AVG, + VOP2_SCALE_DOWN_ZME, }; enum vop3_pre_scale_down_mode { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index e8c61d8fbbb6..3919c66bcf00 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -150,7 +150,7 @@ #define to_vop2_plane_state(x) container_of(x, struct vop2_plane_state, base) #define to_wb_state(x) container_of(x, struct vop2_wb_connector_state, base) #define output_if_is_hdmi(x) (x & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) -#define output_if_is_dp(x) (x & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1)) +#define output_if_is_dp(x) (x & (VOP_OUTPUT_IF_DP0 | VOP_OUTPUT_IF_DP1 | VOP_OUTPUT_IF_DP2)) #define output_if_is_edp(x) (x & (VOP_OUTPUT_IF_eDP0 | VOP_OUTPUT_IF_eDP1)) #define output_if_is_mipi(x) (x & (VOP_OUTPUT_IF_MIPI0 | VOP_OUTPUT_IF_MIPI1)) #define output_if_is_lvds(x) (x & (VOP_OUTPUT_IF_LVDS0 | VOP_OUTPUT_IF_LVDS1)) @@ -354,6 +354,7 @@ struct vop2_plane_state { struct drm_rect dest; dma_addr_t yrgb_mst; dma_addr_t uv_mst; + dma_addr_t mst_end;/* current fb last address */ bool afbc_en; bool hdr_in; bool hdr2sdr_en; @@ -462,7 +463,8 @@ struct vop2_win { unsigned int max_upscale_factor; unsigned int max_downscale_factor; unsigned int supported_rotations; - const uint8_t *dly; + const uint8_t *dly; /* hardware dly cycle */ + uint16_t dly_num; /* calculated dly_num used to config register win_dly_num */ /* * vertical/horizontal scale up/down filter mode */ @@ -716,6 +718,11 @@ struct vop2_video_port { */ bool loader_protect; + /** + * @dclk_div: dclk div = pixel_clock / dclk_request_from_pll + */ + u8 dclk_div; + /** * @plane_mask: show the plane attach to this vp, * it maybe init at dts file or uboot driver @@ -783,6 +790,15 @@ struct vop2_video_port { * @refresh_rate_change: indicate whether refresh rate change */ bool refresh_rate_change; + + /** + * @has_extra_layer: like rk3576, the vp1 layer can merge into vp0 layer after overlay + */ + bool has_extra_layer; + /** + * @irq: independent irq for each vp + */ + int irq; }; struct vop2_extend_pll { @@ -838,6 +854,7 @@ struct vop2 { bool aclk_rate_reset; unsigned long aclk_current_freq; + bool merge_irq; const struct vop2_data *data; /* Number of win that registered as plane, @@ -861,6 +878,7 @@ struct vop2 { struct regmap *vo0_grf; struct regmap *vo1_grf; struct regmap *sys_pmu; + struct regmap *ioc_grf; /* physical map length of vop2 register */ uint32_t len; @@ -1175,7 +1193,7 @@ static struct vop2_win *vop2_find_win_by_phys_id(struct vop2 *vop2, uint8_t phys return NULL; } -static struct vop2_power_domain *vop2_find_pd_by_id(struct vop2 *vop2, uint8_t id) +static struct vop2_power_domain *vop2_find_pd_by_id(struct vop2 *vop2, uint16_t id) { struct vop2_power_domain *pd, *n; @@ -1371,7 +1389,7 @@ static void vop2_wait_for_fs_by_done_bit_status(struct vop2_video_port *vp) int ret; ret = readx_poll_timeout_atomic(vop2_vp_done_bit_status, vp, done_bit, - done_bit, 0, 50 * 1000); + done_bit, 0, 100 * 1000); if (ret) DRM_DEV_ERROR(vop2->dev, "wait vp%d done bit status timeout, vcnt: %d\n", vp->id, vop2_read_vcnt(vp)); @@ -1657,6 +1675,17 @@ static uint32_t vop2_power_domain_can_off_by_vsync(struct vop2_power_domain *pd) return false; } +static uint32_t rk3576_power_domain_status(struct vop2_power_domain *pd) +{ + struct vop2 *vop2 = pd->vop2; + + if (vop2_read_grf_reg(vop2->sys_pmu, &pd->data->regs->bisr_en_status) && + vop2_read_grf_reg(vop2->sys_grf, &pd->data->regs->otp_bisr_en_status)) + return vop2_read_grf_reg(vop2->sys_pmu, &pd->data->regs->pmu_status); + else + return vop2_read_grf_reg(vop2->sys_pmu, &pd->data->regs->status) ? 0 : 1; +} + /* * Read VOP internal power domain on/off status. * We should query BISR_STS register in PMU for @@ -1667,6 +1696,9 @@ static uint32_t vop2_power_domain_status(struct vop2_power_domain *pd) { struct vop2 *vop2 = pd->vop2; + if (vop2->version == VOP_VERSION_RK3576) + return rk3576_power_domain_status(pd); + if (vop2_read_grf_reg(vop2->sys_pmu, &pd->data->regs->bisr_en_status)) return vop2_read_grf_reg(vop2->sys_pmu, &pd->data->regs->pmu_status); else @@ -1806,7 +1838,8 @@ static void vop2_win_enable(struct vop2_win *win) */ if (!VOP_WIN_GET_REG_BAK(win->vop2, win, enable)) { if (win->pd) { - if (win->pd->data->id == VOP2_PD_ESMART) + if ((win->pd->data->id == VOP2_PD_ESMART && win->vop2->version == VOP_VERSION_RK3588) || + win->vop2->version == VOP_VERSION_RK3576) return; vop2_power_domain_get(win->pd); @@ -1840,6 +1873,16 @@ static void vop2_win_disable(struct vop2_win *win, bool skip_splice_win) if (VOP_WIN_GET(vop2, win, enable) || VOP_WIN_GET_REG_BAK(vop2, win, enable)) { VOP_WIN_SET(vop2, win, enable, 0); + /* + * at rk3576 platform, the esmart1/3 can merge from vp1, but the enable bit: port0_extra_alpha_en + * will take effect immediately, this will lead to esmart1/3 close failed when config esmart1/3 + * mst_en=0 and port0_extra_alpha_en=0[this take effect immediately and lead to esmat less fs], + * so we set win_port_sel to 0 to avoid esmart1/3 close failed. + */ + if (vop2->version == VOP_VERSION_RK3576 && win->vp_mask == BIT(0) && + (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3)) + VOP_CTRL_SET(vop2, win_vp_id[win->phys_id], 0); + if (win->feature & WIN_FEATURE_CLUSTER_MAIN) { struct vop2_win *sub_win; int i = 0; @@ -1853,6 +1896,7 @@ static void vop2_win_disable(struct vop2_win *win, bool skip_splice_win) } VOP_CLUSTER_SET(vop2, win, enable, 0); + VOP_CLUSTER_SET(vop2, win, afbc_enable, 0); } /* @@ -1864,7 +1908,7 @@ static void vop2_win_disable(struct vop2_win *win, bool skip_splice_win) if (win->pd) { /* - * Don't dynamic turn on/off PD_ESMART. + * Don't dynamic turn on/off PD_ESMART at RK3588. * (1) There is a design issue for PD_EMSART when attached * on VP1/2/3, we found it will trigger POST_BUF_EMPTY irq at vp0 * in splice mode. @@ -1873,7 +1917,8 @@ static void vop2_win_disable(struct vop2_win *win, bool skip_splice_win) * maybe lead to PD_ESMART closed at wrong time and display error. * (3) PD_ESMART power up maybe have 4 us delay, this will lead to POST_BUF_EMPTY. */ - if (win->pd->data->id == VOP2_PD_ESMART) + if ((win->pd->data->id == VOP2_PD_ESMART && vop2->version == VOP_VERSION_RK3588) || + vop2->version == VOP_VERSION_RK3576) return; vop2_power_domain_put(win->pd); @@ -1909,6 +1954,19 @@ static bool is_linear_10bit_yuv(uint32_t format) } } +static bool is_argb1555_format(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_XBGR1555: + return true; + default: + return false; + } +} + static enum vop2_data_format vop2_convert_format(uint32_t format) { switch (format) { @@ -1927,6 +1985,10 @@ static enum vop2_data_format vop2_convert_format(uint32_t format) return VOP2_FMT_RGB888; case DRM_FORMAT_RGB565: case DRM_FORMAT_BGR565: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_XBGR1555: return VOP2_FMT_RGB565; case DRM_FORMAT_NV12: case DRM_FORMAT_NV21: @@ -2090,6 +2152,8 @@ static bool vop2_win_rb_swap(uint32_t format) case DRM_FORMAT_ABGR8888: case DRM_FORMAT_BGR888: case DRM_FORMAT_BGR565: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_ABGR1555: return true; default: return false; @@ -2144,6 +2208,10 @@ static bool vop2_win_dither_up(uint32_t format) switch (format) { case DRM_FORMAT_BGR565: case DRM_FORMAT_RGB565: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_XBGR1555: return true; default: return false; @@ -2225,8 +2293,12 @@ static bool is_yuv_output(uint32_t bus_format) static bool is_alpha_support(uint32_t format) { switch (format) { + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_ABGR1555: return true; default: return false; @@ -2267,6 +2339,23 @@ static inline bool rockchip_tiled(struct drm_plane *plane, u64 modifier) return (i < plane->modifier_count) ? true : false; } +static inline bool rockchip_rfbc(struct drm_plane *plane, u64 modifier) +{ + int i; + + if (modifier == DRM_FORMAT_MOD_LINEAR) + return false; + + if (!IS_ROCKCHIP_RFBC_MOD(modifier)) + return false; + + for (i = 0 ; i < plane->modifier_count; i++) + if (plane->modifiers[i] == modifier) + break; + + return (i < plane->modifier_count) ? true : false; +} + static bool rockchip_vop2_mod_supported(struct drm_plane *plane, u32 format, u64 modifier) { if (modifier == DRM_FORMAT_MOD_INVALID) @@ -2275,7 +2364,9 @@ static bool rockchip_vop2_mod_supported(struct drm_plane *plane, u32 format, u64 if (modifier == DRM_FORMAT_MOD_LINEAR) return true; - if (!rockchip_afbc(plane, modifier) && !rockchip_tiled(plane, modifier)) { + if (!rockchip_afbc(plane, modifier) && + !rockchip_rfbc(plane, modifier) && + !rockchip_tiled(plane, modifier)) { DRM_ERROR("%s unsupported format modifier 0x%llx\n", plane->name, modifier); return false; @@ -2307,12 +2398,20 @@ static inline bool vop2_has_feature(struct vop2 *vop2, uint64_t feature) } /* + * rk356x/rk3588/rk3528: * 0: Full mode, 16 lines for one tail * 1: half block mode + * + * rk3576: + * 0: 4 line per tail line for rfbc[64x4] + * 1: 8 line per tail line for afbc[32x8] */ static int vop2_afbc_half_block_enable(struct vop2_plane_state *vpstate) { - if (vpstate->rotate_270_en || vpstate->rotate_90_en) + struct drm_framebuffer *fb = vpstate->base.fb; + + if (vpstate->rotate_270_en || vpstate->rotate_90_en || + IS_ROCKCHIP_RFBC_MOD(fb->modifier)) return 0; else return 1; @@ -2602,12 +2701,22 @@ static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win *win, uint32_t val; if (is_vop3(vop2)) { - if (src_w >= (4 * dst_w)) { - xgt4 = 1; - src_w >>= 2; - } else if (src_w >= (2 * dst_w)) { - xgt2 = 1; - src_w >>= 1; + if (vop2->version == VOP_VERSION_RK3576 && vop2_cluster_window(win)) { + if (src_w >= (8 * dst_w)) { + xgt4 = 1; + src_w >>= 2; + } else if (src_w >= (4 * dst_w)) { + xgt2 = 1; + src_w >>= 1; + } + } else { + if (src_w >= (4 * dst_w)) { + xgt4 = 1; + src_w >>= 2; + } else if (src_w >= (2 * dst_w)) { + xgt2 = 1; + src_w >>= 1; + } } } @@ -2628,12 +2737,22 @@ static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win *win, src_h >>= 1; } } else { - if (src_h >= (4 * dst_h)) { - ygt4 = 1; - src_h >>= 2; - } else if (src_h >= (2 * dst_h)) { - ygt2 = 1; - src_h >>= 1; + if (win_data->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) { + if (src_h >= (8 * dst_h)) { + ygt4 = 1; + src_h >>= 2; + } else if (src_h >= (4 * dst_h)) { + ygt2 = 1; + src_h >>= 1; + } + } else { + if (src_h >= (4 * dst_h)) { + ygt4 = 1; + src_h >>= 2; + } else if (src_h >= (2 * dst_h)) { + ygt2 = 1; + src_h >>= 1; + } } } @@ -2674,6 +2793,16 @@ static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win *win, else xgt_en = xgt2 || xgt4; + if (vop2->version == VOP_VERSION_RK3576) { + bool zme_dering_en = false; + + if ((yrgb_hor_scl_mode == SCALE_UP && hscl_filter_mode == VOP2_SCALE_UP_ZME) || + (yrgb_ver_scl_mode == SCALE_UP && vscl_filter_mode == VOP2_SCALE_UP_ZME)) + zme_dering_en = true; + + VOP_SCL_SET(vop2, win, zme_dering_para, 0x04100d10);/* Recommended configuration from the algorithm */ + VOP_SCL_SET(vop2, win, zme_dering_en, zme_dering_en); + } VOP_SCL_SET(vop2, win, xgt_en, xgt_en); VOP_SCL_SET(vop2, win, xavg_en, xavg_en); VOP_SCL_SET(vop2, win, xgt_mode, xgt2 ? 0 : 1); @@ -2717,10 +2846,17 @@ static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win *win, else if ((cbcr_src_h >= 100 * dst_h / 65) && (cbcr_src_h < 100 * dst_h / 35)) ygt2 = 1; } else { - if (cbcr_src_h >= (4 * dst_h)) - ygt4 = 1; - else if (cbcr_src_h >= (2 * dst_h)) - ygt2 = 1; + if (win_data->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) { + if (cbcr_src_h >= (8 * dst_h)) + ygt4 = 1; + else if (cbcr_src_h >= (4 * dst_h)) + ygt2 = 1; + } else { + if (cbcr_src_h >= (4 * dst_h)) + ygt4 = 1; + else if (cbcr_src_h >= (2 * dst_h)) + ygt2 = 1; + } } if (ygt4) @@ -2945,7 +3081,7 @@ static void vop2_axi_irqs_enable(struct vop2 *vop2) { const struct vop2_data *vop2_data = vop2->data; const struct vop_intr *intr; - uint32_t irqs = BUS_ERROR_INTR; + uint32_t irqs = BUS_ERROR_INTR | MMU_EN_INTR; uint32_t i; for (i = 0; i < vop2_data->nr_axi_intr; i++) { @@ -2959,7 +3095,7 @@ static uint32_t vop2_read_and_clear_axi_irqs(struct vop2 *vop2, int index) { const struct vop2_data *vop2_data = vop2->data; const struct vop_intr *intr = &vop2_data->axi_intr[index]; - uint32_t irqs = BUS_ERROR_INTR; + uint32_t irqs = BUS_ERROR_INTR | MMU_EN_INTR; uint32_t val; val = VOP_INTR_GET_TYPE(vop2, intr, status, irqs); @@ -3390,7 +3526,22 @@ static void vop2_wb_commit(struct drm_crtc *crtc) VOP_MODULE_SET(vop2, wb, scale_x_en, wb_state->scale_x_en); VOP_MODULE_SET(vop2, wb, scale_y_en, wb_state->scale_y_en); VOP_MODULE_SET(vop2, wb, r2y_en, r2y); - VOP_MODULE_SET(vop2, wb, enable, 1); + if (vop2->version == VOP_VERSION_RK3576) { + bool enable_one_frame_mode = true; + + VOP_MODULE_SET(vop2, wb, act_width, fb->width - 1); + VOP_MODULE_SET(vop2, wb, vir_stride, fb->pitches[0] >> 2); + VOP_MODULE_SET(vop2, wb, vir_stride_en, 1); + + if (enable_one_frame_mode) { + VOP_MODULE_SET(vop2, wb, one_frame_mode, 1); + vop2_write_reg_uncached(vop2, &wb->regs->enable, 1); + } else { + VOP_MODULE_SET(vop2, wb, enable, 1); + } + } else { + VOP_MODULE_SET(vop2, wb, enable, 1); + } vop2_wb_irqs_enable(vop2); VOP_CTRL_SET(vop2, wb_dma_finish_and_en, 1); } @@ -3829,6 +3980,26 @@ static void rk3588_vop2_regsbak(struct vop2 *vop2) vop2->regsbak[i] = base[i]; } +static int vop3_get_esmart_lb_mode(struct vop2 *vop2) +{ + int i; + const struct vop2_esmart_lb_map *esmart_lb_mode_map = vop2->data->esmart_lb_mode_map; + + if (!esmart_lb_mode_map) + return vop2->esmart_lb_mode; + + for (i = 0; i < vop2->data->esmart_lb_mode_num; i++) { + if (vop2->esmart_lb_mode == esmart_lb_mode_map->lb_mode) + return esmart_lb_mode_map->lb_map_value; + esmart_lb_mode_map++; + } + + if (i == vop2->data->esmart_lb_mode_num) + DRM_WARN("Unsupported esmart_lb_mode:%d\n", vop2->esmart_lb_mode); + + return vop2->data->esmart_lb_mode_map[0].lb_map_value; +} + static void vop2_initial(struct drm_crtc *crtc) { struct vop2_video_port *vp = to_vop2_video_port(crtc); @@ -3867,7 +4038,7 @@ static void vop2_initial(struct drm_crtc *crtc) if (is_vop3(vop2)) { VOP_CTRL_SET(vop2, dsp_vs_t_sel, 0); - VOP_CTRL_SET(vop2, esmart_lb_mode, vop2->esmart_lb_mode); + VOP_CTRL_SET(vop2, esmart_lb_mode, vop3_get_esmart_lb_mode(vop2)); } /* @@ -3877,6 +4048,22 @@ static void vop2_initial(struct drm_crtc *crtc) if (vop2->version == VOP_VERSION_RK3528 || vop2->version == VOP_VERSION_RK3562) vop2_mask_write(vop2, 0x700, 0x3, 4, 0, 0, true); + if (vop2->version == VOP_VERSION_RK3576) { + /* Default use rkiommu 2.0 for axi0 */ + VOP_CTRL_SET(vop2, rkmmu_v2_en, 1); + + /* Init frc2.0 config */ + vop2_writel(vop2, 0xca0, 0xc8); + vop2_writel(vop2, 0xca4, 0x01000100); + vop2_writel(vop2, 0xca8, 0x03ff0100); + vop2_writel(vop2, 0xda0, 0xc8); + vop2_writel(vop2, 0xda4, 0x01000100); + vop2_writel(vop2, 0xda8, 0x03ff0100); + + if (vop2->version == VOP_VERSION_RK3576 && vop2->merge_irq == true) + VOP_CTRL_SET(vop2, vp_intr_merge_en, 1); + } + VOP_CTRL_SET(vop2, cfg_done_en, 1); /* * Disable auto gating, this is a workaround to @@ -3906,7 +4093,17 @@ static void vop2_initial(struct drm_crtc *crtc) esmart_pd->on = true; else vop2_power_domain_on(esmart_pd); + } else { + struct vop2_power_domain *pd, *n; + + list_for_each_entry_safe_reverse(pd, n, &vop2->pd_list_head, list) { + if (vop2_power_domain_status(pd)) + pd->on = true; + else + vop2_power_domain_on(pd); + } } + vop2_layer_map_initial(vop2, current_vp_id); vop2_axi_irqs_enable(vop2); vop2->is_enabled = true; @@ -3965,7 +4162,7 @@ static void vop2_power_domain_off_by_disabled_vp(struct vop2_power_domain *pd) if (pd->data->id == VOP2_PD_CLUSTER0 || pd->data->id == VOP2_PD_CLUSTER1 || pd->data->id == VOP2_PD_CLUSTER2 || pd->data->id == VOP2_PD_CLUSTER3 || - pd->data->id == VOP2_PD_ESMART) { + pd->data->id == VOP2_PD_CLUSTER || pd->data->id == VOP2_PD_ESMART) { phys_id = ffs(pd->data->module_id_mask) - 1; win = vop2_find_win_by_phys_id(vop2, phys_id); vp_id = ffs(win->vp_mask) - 1; @@ -3992,7 +4189,7 @@ static void vop2_power_domain_off_by_disabled_vp(struct vop2_power_domain *pd) reinit_completion(&vp->dsp_hold_completion); vop2_dsp_hold_valid_irq_enable(crtc); VOP_MODULE_SET(vop2, vp, standby, 1); - ret = wait_for_completion_timeout(&vp->dsp_hold_completion, msecs_to_jiffies(50)); + ret = wait_for_completion_timeout(&vp->dsp_hold_completion, msecs_to_jiffies(100)); if (!ret) DRM_DEV_INFO(vop2->dev, "wait for vp%d dsp_hold timeout\n", vp->id); @@ -4031,7 +4228,7 @@ static void vop2_disable(struct drm_crtc *crtc) rockchip_drm_dma_detach_device(vop2->drm_dev, vop2->dev); vop2->is_iommu_enabled = false; } - if (vop2->version == VOP_VERSION_RK3588) + if (vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576) vop2_power_off_all_pd(vop2); vop2->is_enabled = false; @@ -4499,7 +4696,7 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, spin_unlock(&vop2->reg_lock); - ret = wait_for_completion_timeout(&vp->dsp_hold_completion, msecs_to_jiffies(50)); + ret = wait_for_completion_timeout(&vp->dsp_hold_completion, msecs_to_jiffies(100)); if (!ret) DRM_DEV_INFO(vop2->dev, "wait for vp%d dsp_hold timeout\n", vp->id); @@ -4867,7 +5064,7 @@ static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_st return -EINVAL; } - if (rockchip_afbc(plane, fb->modifier)) + if (rockchip_afbc(plane, fb->modifier) || rockchip_rfbc(plane, fb->modifier)) vpstate->afbc_en = true; else vpstate->afbc_en = false; @@ -4968,6 +5165,7 @@ static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_st if (vpstate->tiled_en == ROCKCHIP_TILED_BLOCK_SIZE_4x4_MODE0) vpstate->yrgb_mst += offset; } + vpstate->mst_end = rk_obj->dma_addr + rk_obj->size; return 0; } @@ -5159,7 +5357,7 @@ static const char *modifier_to_string(uint64_t modifier) case DRM_FORMAT_MOD_ROCKCHIP_TILED(ROCKCHIP_TILED_BLOCK_SIZE_4x4_MODE1): return "[TILE_4x4_M1]"; default: - return drm_is_afbc(modifier) ? "[AFBC]" : ""; + return drm_is_afbc(modifier) ? "[AFBC]" : IS_ROCKCHIP_RFBC_MOD(modifier) ? "[RFBC]" : ""; } } @@ -5305,28 +5503,43 @@ static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, s if (vop2->version != VOP_VERSION_RK3568) rk3588_vop2_win_cfg_axi(win); - if (!win->parent && !vop2_cluster_window(win) && is_vop3(vop2)) - VOP_WIN_SET(vop2, win, scale_engine_num, win->scale_engine_num); + if (is_vop3(vop2)) { + if (!win->parent && !vop2_cluster_window(win)) + VOP_WIN_SET(vop2, win, scale_engine_num, win->scale_engine_num); + + if (!win->parent) { + VOP_CTRL_SET(vop2, win_vp_id[win->phys_id], vp->id); + VOP_CTRL_SET(vop2, win_dly[win->phys_id], win->dly_num); + } + + /* Merge esmart1/3 from vp1 post to vp0 */ + if (vop2->version == VOP_VERSION_RK3576 && vp->id == 0 && !win->parent && + (win->phys_id == ROCKCHIP_VOP2_ESMART1 || win->phys_id == ROCKCHIP_VOP2_ESMART3)) + VOP_CTRL_SET(vop2, win_vp_id[win->phys_id], 1); + } if (vpstate->afbc_en) { + u8 block_w = IS_ROCKCHIP_RFBC_MOD(fb->modifier) ? 64 : fb->modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 ? 32 : 16; + /* the afbc superblock is 16 x 16 */ afbc_format = vop2_convert_afbc_format(fb->format->format); /* Enable color transform for YTR */ if (fb->modifier & AFBC_FORMAT_MOD_YTR) afbc_format |= (1 << 4); - afbc_tile_num = ALIGN(actual_w, 16) >> 4; /* The right win should have a src offset in splice mode */ afbc_xoffset = (src->x1 >> 16); + afbc_tile_num = ALIGN(actual_w + afbc_xoffset % block_w, block_w) / block_w; /* AFBC pic_vir_width is count by pixel, this is different * with WIN_VIR_STRIDE. */ stride = (fb->pitches[0] << 3) / bpp; - if ((stride & 0x3f) && + if ((stride & (block_w - 1)) && (vpstate->xmirror_en || vpstate->rotate_90_en || vpstate->rotate_270_en)) DRM_ERROR("vp%d %s stride[%d] must align as 64 pixel when enable xmirror/rotate_90/rotate_270[0x%x]\n", vp->id, win->name, stride, pstate->rotation); - + /* It's for head stride, each head size is 16 byte */ + stride = ALIGN(stride, block_w) / block_w * 16; rb_swap = vop2_afbc_rb_swap(fb->format->format); uv_swap = vop2_afbc_uv_swap(fb->format->format); vpstate->afbc_half_block_en = afbc_half_block_en; @@ -5341,7 +5554,10 @@ static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, s VOP_AFBC_SET(vop2, win, auto_gating_en, 0); else VOP_AFBC_SET(vop2, win, auto_gating_en, 1); - VOP_AFBC_SET(vop2, win, block_split_en, 0); + if (fb->modifier & AFBC_FORMAT_MOD_SPLIT) + VOP_AFBC_SET(vop2, win, block_split_en, 1); + else + VOP_AFBC_SET(vop2, win, block_split_en, 0); VOP_AFBC_SET(vop2, win, hdr_ptr, vpstate->yrgb_mst); VOP_AFBC_SET(vop2, win, pic_size, act_info); VOP_AFBC_SET(vop2, win, transform_offset, transform_offset); @@ -5353,6 +5569,11 @@ static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, s VOP_AFBC_SET(vop2, win, ymirror, vpstate->ymirror_en); VOP_AFBC_SET(vop2, win, rotate_270, vpstate->rotate_270_en); VOP_AFBC_SET(vop2, win, rotate_90, vpstate->rotate_90_en); + + VOP_AFBC_SET(vop2, win, pld_offset_en, 1); /* use relative address by default */ + VOP_AFBC_SET(vop2, win, pld_ptr_offset, vpstate->yrgb_mst); + VOP_AFBC_SET(vop2, win, pld_range_en, 1); + VOP_AFBC_SET(vop2, win, pld_ptr_range, vpstate->mst_end); } else { VOP_CLUSTER_SET(vop2, win, afbc_enable, 0); transform_offset = vop2_tile_transform_offset(vpstate, vpstate->tiled_en); @@ -5373,6 +5594,11 @@ static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, s VOP_AFBC_SET(vop2, win, half_block_en, afbc_half_block_en); VOP_WIN_SET(vop2, win, format, format); + VOP_WIN_SET(vop2, win, format_argb1555, is_argb1555_format(fb->format->format)); + + if (!win->parent && win->feature & WIN_FEATURE_MULTI_AREA) + VOP_CTRL_SET(vop2, win_alpha_map[win->phys_id], 0x8000ff00); + VOP_WIN_SET(vop2, win, yrgb_mst, yrgb_mst); rb_swap = vop2_win_rb_swap(fb->format->format); @@ -6388,7 +6614,7 @@ static void vop2_crtc_regs_dump(struct drm_crtc *crtc, struct seq_file *s) const struct vop2_data *vop2_data = vop2->data; struct drm_crtc_state *cstate = crtc->state; const struct vop_dump_regs *regs = vop2->data->dump_regs; - uint32_t buf[68]; + uint32_t buf[128]; uint32_t len = ARRAY_SIZE(buf); unsigned int n, i, j; resource_size_t offset_addr; @@ -6413,6 +6639,9 @@ static void vop2_crtc_regs_dump(struct drm_crtc *crtc, struct seq_file *s) for (i = 0; i < n; i++) { base = regs[i].offset; offset_addr = vop2->res->start + base; + len = ARRAY_SIZE(buf); + if (regs[i].size) + len = min(len, regs[i].size >> 2); DEBUG_PRINT("\n%s:\n", regs[i].name); for (j = 0; j < len;) { DEBUG_PRINT("%08x: %08x %08x %08x %08x\n", (u32)offset_addr + j * 4, @@ -6432,7 +6661,7 @@ static void vop2_crtc_active_regs_dump(struct drm_crtc *crtc, struct seq_file *s const struct vop2_data *vop2_data = vop2->data; struct drm_crtc_state *cstate = crtc->state; const struct vop_dump_regs *regs = vop2->data->dump_regs; - uint32_t buf[68]; + uint32_t buf[128]; uint32_t len = ARRAY_SIZE(buf); unsigned int n, i, j; resource_size_t offset_addr; @@ -6460,6 +6689,9 @@ static void vop2_crtc_active_regs_dump(struct drm_crtc *crtc, struct seq_file *s continue; base = regs[i].offset; offset_addr = vop2->res->start + base; + len = ARRAY_SIZE(buf); + if (regs[i].size) + len = min(len, regs[i].size >> 2); DEBUG_PRINT("\n%s:\n", regs[i].name); for (j = 0; j < len;) { DEBUG_PRINT("%08x: %08x %08x %08x %08x\n", (u32)offset_addr + j * 4, @@ -6935,6 +7167,8 @@ static void vop2_dither_setup(struct rockchip_crtc_state *vcstate, struct drm_cr { struct vop2_video_port *vp = to_vop2_video_port(crtc); struct vop2 *vop2 = vp->vop2; + const struct vop2_data *vop2_data = vop2->data; + const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; bool pre_dither_down_en = false; switch (vcstate->bus_format) { @@ -6974,11 +7208,17 @@ static void vop2_dither_setup(struct rockchip_crtc_state *vcstate, struct drm_cr break; } - if (is_yuv_output(vcstate->bus_format)) + if (is_yuv_output(vcstate->bus_format) && ((vp_data->feature & VOP_FEATURE_POST_FRC_V2) == 0)) pre_dither_down_en = false; - VOP_MODULE_SET(vop2, vp, pre_dither_down_en, pre_dither_down_en); - VOP_MODULE_SET(vop2, vp, dither_down_sel, DITHER_DOWN_ALLEGRO); + if (vp_data->feature & VOP_FEATURE_POST_FRC_V2 && pre_dither_down_en) { + VOP_MODULE_SET(vop2, vp, pre_dither_down_en, 0); + VOP_MODULE_SET(vop2, vp, dither_down_en, 1);/* enable frc2.0 do 10->8 */ + VOP_MODULE_SET(vop2, vp, dither_down_sel, DITHER_DOWN_FRC); + } else { + VOP_MODULE_SET(vop2, vp, pre_dither_down_en, pre_dither_down_en); + VOP_MODULE_SET(vop2, vp, dither_down_sel, DITHER_DOWN_ALLEGRO); + } } static void vop2_post_config(struct drm_crtc *crtc) @@ -7325,18 +7565,119 @@ static int vop2_calc_dsc_clk(struct drm_crtc *crtc) return 0; } +static int vop3_calc_cru_cfg(struct drm_crtc *crtc) +{ + struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct vop2 *vop2 = vp->vop2; + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); + struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; + u8 port_pix_rate = vop2->data->vp[vp->id].pixel_rate; + bool split_mode = !!(vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE); + bool post_dclk_core_sel = 0, pix_half_rate = 0, post_dclk_out_sel = 0; + bool interface_dclk_sel, interface_pix_clk_sel = 0; + bool double_pixel = adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK || vcstate->output_if & VOP_OUTPUT_IF_BT656; + + if (double_pixel || vp->id == 1 || vp->id == 2 || + (vp->id == 0 && vcstate->output_if & VOP_OUTPUT_IF_eDP0 && split_mode == 0)) + vp->dclk_div = 1;/* no div */ + else + vp->dclk_div = 2;/* div2 */ + + if (double_pixel || + (vp->id == 0 && vcstate->output_if & VOP_OUTPUT_IF_eDP0 && split_mode == 0)) + post_dclk_core_sel = 1;/* div2 */ + else + post_dclk_core_sel = 0;/* no div */ + + if (split_mode || (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420)) { + pix_half_rate = 1; + post_dclk_out_sel = 1; + } + + if (vcstate->output_if & VOP_OUTPUT_IF_RGB) { + interface_dclk_sel = pix_half_rate == 1 ? 1 : 0; + /* RGB interface_pix_clk_sel will auto config according to rgb_en/bt1120_en/bt656_en */ + } else if (vcstate->output_if & VOP_OUTPUT_IF_eDP0) { + interface_dclk_sel = pix_half_rate == 1 ? 1 : 0; + interface_pix_clk_sel = port_pix_rate == 2 ? 1 : 0; + } else { + interface_dclk_sel = pix_half_rate == 1 ? 1 : 0; + interface_pix_clk_sel = port_pix_rate == 1 ? 1 : 0; + } + + VOP_MODULE_SET(vop2, vp, core_dclk_div, post_dclk_core_sel);/* dclk_core */ + VOP_MODULE_SET(vop2, vp, dclk_div2, post_dclk_out_sel);/* dclk_out */ + + if (output_if_is_dpi(vcstate->output_if)) + VOP_CTRL_SET(vop2, rgb_dclk_sel, interface_dclk_sel);/* 0: dclk_core, 1: dclk_out */ + + if (vcstate->output_if & VOP_OUTPUT_IF_MIPI0) { + VOP_CTRL_SET(vop2, mipi0_dclk_sel, interface_dclk_sel); + VOP_CTRL_SET(vop2, mipi0_pixclk_div, interface_pix_clk_sel);/* 0: div2, 1: div4 */ + } + + if (vcstate->output_if & VOP_OUTPUT_IF_eDP0) { + VOP_CTRL_SET(vop2, edp0_dclk_sel, interface_dclk_sel); + VOP_CTRL_SET(vop2, edp0_pixclk_div, interface_pix_clk_sel);/* 0: dclk, 1: port0_dclk */ + } + + if (vcstate->output_if & VOP_OUTPUT_IF_HDMI0) { + VOP_CTRL_SET(vop2, hdmi0_dclk_sel, interface_dclk_sel); + VOP_CTRL_SET(vop2, hdmi0_pixclk_div, interface_pix_clk_sel);/* 0: div2, 1: div4 */ + } + + if (vcstate->output_if & VOP_OUTPUT_IF_DP0) { + VOP_CTRL_SET(vop2, dp0_dclk_sel, interface_dclk_sel); + VOP_CTRL_SET(vop2, dp0_pixclk_div, interface_pix_clk_sel);/* 0: no div, 1: div2 */ + } + + if (vcstate->output_if & VOP_OUTPUT_IF_DP1) { + VOP_CTRL_SET(vop2, dp1_dclk_sel, interface_dclk_sel); + VOP_CTRL_SET(vop2, dp1_pixclk_div, interface_pix_clk_sel);/* 0: no div, 1: div2 */ + } + + if (vcstate->output_if & VOP_OUTPUT_IF_DP2) { + VOP_CTRL_SET(vop2, dp2_dclk_sel, interface_dclk_sel); + VOP_CTRL_SET(vop2, dp2_pixclk_div, interface_pix_clk_sel);/* 0: no div, 1: div2 */ + } + + return 0; +} + static int vop2_calc_cru_cfg(struct drm_crtc *crtc, int conn_id, struct vop2_clk **if_pixclk, struct vop2_clk **if_dclk) { struct vop2_video_port *vp = to_vop2_video_port(crtc); struct vop2 *vop2 = vp->vop2; + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); + struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; const struct vop2_connector_if_data *if_data; struct vop2_clk *if_clk_src, *if_clk_parent; char clk_name[32]; int ret; - if (vop2->version != VOP_VERSION_RK3588) + if (vop2->version == VOP_VERSION_RK3528 || + vop2->version == VOP_VERSION_RK3562 || + vop2->version == VOP_VERSION_RK3568) { + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK || vcstate->output_if & VOP_OUTPUT_IF_BT656) + VOP_MODULE_SET(vop2, vp, core_dclk_div, 1); + else + VOP_MODULE_SET(vop2, vp, core_dclk_div, 0); + + if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420) { + VOP_MODULE_SET(vop2, vp, dclk_div2, 1); + VOP_MODULE_SET(vop2, vp, dclk_div2_phase_lock, 1); + } else { + VOP_MODULE_SET(vop2, vp, dclk_div2, 0); + VOP_MODULE_SET(vop2, vp, dclk_div2_phase_lock, 0); + } + return 0; + } else if (vop2->version == VOP_VERSION_RK3576) { + vop3_calc_cru_cfg(crtc); + + return 0; + } if_data = vop2_find_connector_if_data(vop2, conn_id); if_clk_src = vop2_clk_get(vop2, if_data->clk_src_name); @@ -7670,7 +8011,7 @@ static void vop2_post_color_swap(struct drm_crtc *crtc) vop3_output_rb_swap(vcstate->bus_format, vcstate->output_mode)) data_swap = DSP_RB_SWAP; - if (vop2->version == VOP_VERSION_RK3588 && + if ((vop2->version == VOP_VERSION_RK3588 || vop2->version == VOP_VERSION_RK3576) && (output_if_is_hdmi(output_if) || output_if_is_dp(output_if)) && (vcstate->bus_format == MEDIA_BUS_FMT_YUV8_1X24 || vcstate->bus_format == MEDIA_BUS_FMT_YUV10_1X30)) @@ -7681,12 +8022,12 @@ static void vop2_post_color_swap(struct drm_crtc *crtc) /* * For vop3 video port0, if hdr_vivid is not enable, the pipe delay time as follow: - * win_dly + config_win_dly + layer_mix_dly + sdr2hdr_dly + * hdr_mix_dly = config_bg_dly + * win_dly + config_win_dly + layer_mix_dly + sdr2hdr_dly + hdr_mix_dly = config_bg_dly * * if hdr_vivid is enable, the hdr layer's pipe delay time as follow: * win_dly + config_win_dly +hdrvivid_dly + hdr_mix_dly = config_bg_dly * - * If hdrvivid and sdr2hdr bot enable, the time arrivr hdr_mix should be the same: + * If hdrvivid and sdr2hdr both enable, the time arrive hdr_mix should be the same: * win_dly + config_win_dly0 + hdrvivid_dly = win_dly + config_win_dly1 + laer_mix_dly + * sdr2hdr_dly * @@ -7695,7 +8036,7 @@ static void vop2_post_color_swap(struct drm_crtc *crtc) * * Here, win_dly, layer_mix_dly, sdr2hdr_dly, hdr_mix_dly, hdrvivid_dly is the hardware * delay cycles. Config_win_dly and config_bg_dly is the register value that we can config. - * Different hdr vivid mode have different hdrvivid_dly. For sdr2hdr_dly, only sde2hdr + * Different hdr vivid mode have different hdrvivid_dly. For sdr2hdr_dly, only sdr2hdr * enable, it will delay, otherwise, the sdr2hdr_dly is 0. * * For default, the config_win_dly will be 0, it just user to make the pipe to arrive @@ -7777,7 +8118,7 @@ static void vop3_setup_pipe_dly(struct vop2_video_port *vp, const struct vop2_zp if (vop2_cluster_window(win)) dly |= dly << 8; - VOP_CTRL_SET(vop2, win_dly[win->phys_id], dly); + win->dly_num = dly; } } @@ -7870,16 +8211,20 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); vp->output_if = vcstate->output_if; + vp->dclk_div = 1; if (vcstate->output_if & VOP_OUTPUT_IF_RGB) { ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_RGB, &if_pixclk, &if_dclk); if (ret < 0) goto out; + VOP_CTRL_SET(vop2, rgb_regdone_imd_en, 1); + VOP_CTRL_SET(vop2, rgb_dclk_out_en, 1); VOP_CTRL_SET(vop2, rgb_en, 1); VOP_CTRL_SET(vop2, rgb_mux, vp_data->id); VOP_CTRL_SET(vop2, rgb_pin_pol, val); VOP_GRF_SET(vop2, sys_grf, grf_dclk_inv, dclk_inv); + VOP_GRF_SET(vop2, ioc_grf, grf_dclk_inv, dclk_inv); } if (vcstate->output_if & VOP_OUTPUT_IF_BT1120) { @@ -7887,6 +8232,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta if (ret < 0) goto out; + VOP_CTRL_SET(vop2, rgb_regdone_imd_en, 1); + VOP_CTRL_SET(vop2, rgb_dclk_out_en, 1); if (vop2->version == VOP_VERSION_RK3588) { VOP_CTRL_SET(vop2, bt1120_en, 3); } else { @@ -7895,6 +8242,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta } VOP_CTRL_SET(vop2, rgb_mux, vp_data->id); VOP_GRF_SET(vop2, sys_grf, grf_bt1120_clk_inv, !dclk_inv); + VOP_GRF_SET(vop2, ioc_grf, grf_bt1120_clk_inv, !dclk_inv); VOP_CTRL_SET(vop2, bt1120_dclk_pol, !dclk_inv); yc_swap = vop2_output_yc_swap(vcstate->bus_format); VOP_CTRL_SET(vop2, bt1120_yc_swap, yc_swap); @@ -7905,6 +8253,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta if (ret < 0) goto out; + VOP_CTRL_SET(vop2, rgb_regdone_imd_en, 1); + VOP_CTRL_SET(vop2, rgb_dclk_out_en, 1); if (vop2->version == VOP_VERSION_RK3588) { VOP_CTRL_SET(vop2, bt656_en, 1); } else { @@ -7913,6 +8263,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta } VOP_CTRL_SET(vop2, rgb_mux, vp_data->id); VOP_GRF_SET(vop2, sys_grf, grf_bt656_clk_inv, !dclk_inv); + VOP_GRF_SET(vop2, ioc_grf, grf_bt656_clk_inv, !dclk_inv); VOP_CTRL_SET(vop2, bt656_dclk_pol, !dclk_inv); yc_swap = vop2_output_yc_swap(vcstate->bus_format); VOP_CTRL_SET(vop2, bt656_yc_swap, yc_swap); @@ -7936,6 +8287,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_MIPI0, &if_pixclk, &if_dclk); if (ret < 0) goto out; + VOP_CTRL_SET(vop2, mipi0_regdone_imd_en, 1); + VOP_CTRL_SET(vop2, mipi0_dclk_out_en, 1); if (if_pixclk) VOP_CTRL_SET(vop2, mipi0_pixclk_div, if_pixclk->div_val); @@ -7945,6 +8298,12 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta port_mux = vop2_get_mipi_port_mux(vop2, vp_data->id); VOP_CTRL_SET(vop2, mipi0_en, 1); VOP_CTRL_SET(vop2, mipi0_mux, port_mux); + /* + * RK3576 DSI CTRL hsync/vsync polarity is positive and can't update, + * so set VOP hsync/vsync polarity as positive by default. + */ + if (vop2->version == VOP_VERSION_RK3576) + val = BIT(HSYNC_POSITIVE) | BIT(VSYNC_POSITIVE); VOP_CTRL_SET(vop2, mipi_pin_pol, val); VOP_CTRL_SET(vop2, mipi_dclk_pol, dclk_inv); if (vcstate->hold_mode) { @@ -7983,6 +8342,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_eDP0, &if_pixclk, &if_dclk); if (ret < 0) goto out; + VOP_CTRL_SET(vop2, edp0_regdone_imd_en, 1); + VOP_CTRL_SET(vop2, edp0_dclk_out_en, 1); if (if_pixclk && if_dclk) { VOP_CTRL_SET(vop2, edp0_pixclk_div, if_pixclk->div_val); VOP_CTRL_SET(vop2, edp0_dclk_div, if_dclk->div_val); @@ -8015,6 +8376,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_DP0, &if_pixclk, &if_dclk); if (ret < 0) goto out; + VOP_CTRL_SET(vop2, dp0_regdone_imd_en, 1); + VOP_CTRL_SET(vop2, dp0_dclk_out_en, 1); VOP_CTRL_SET(vop2, dp0_en, 1); VOP_CTRL_SET(vop2, dp0_mux, vp_data->id); VOP_CTRL_SET(vop2, dp0_dclk_pol, 0); @@ -8022,20 +8385,37 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta } if (vcstate->output_if & VOP_OUTPUT_IF_DP1) { - ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_DP0, &if_pixclk, &if_dclk); + ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_DP1, &if_pixclk, &if_dclk); if (ret < 0) goto out; + VOP_CTRL_SET(vop2, dp1_regdone_imd_en, 1); + VOP_CTRL_SET(vop2, dp1_dclk_out_en, 1); VOP_CTRL_SET(vop2, dp1_en, 1); VOP_CTRL_SET(vop2, dp1_mux, vp_data->id); VOP_CTRL_SET(vop2, dp1_dclk_pol, 0); VOP_CTRL_SET(vop2, dp1_pin_pol, val); } + if (vcstate->output_if & VOP_OUTPUT_IF_DP2) { + ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_DP2, &if_pixclk, &if_dclk); + if (ret < 0) + goto out; + + VOP_CTRL_SET(vop2, dp2_regdone_imd_en, 1); + VOP_CTRL_SET(vop2, dp2_dclk_out_en, 1); + VOP_CTRL_SET(vop2, dp2_en, 1); + VOP_CTRL_SET(vop2, dp2_mux, vp_data->id); + VOP_CTRL_SET(vop2, dp2_dclk_pol, 0); + VOP_CTRL_SET(vop2, dp2_pin_pol, val); + } + if (vcstate->output_if & VOP_OUTPUT_IF_HDMI0) { ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_HDMI0, &if_pixclk, &if_dclk); if (ret < 0) goto out; + VOP_CTRL_SET(vop2, hdmi0_regdone_imd_en, 1); + VOP_CTRL_SET(vop2, hdmi0_dclk_out_en, 1); if (if_pixclk && if_dclk) { VOP_CTRL_SET(vop2, hdmi0_pixclk_div, if_pixclk->div_val); VOP_CTRL_SET(vop2, hdmi0_dclk_div, if_dclk->div_val); @@ -8123,20 +8503,6 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta if (vcstate->max_refresh_rate && vcstate->min_refresh_rate) VOP_MODULE_SET(vop2, vp, sw_dsp_vtotal_imd, 1); - if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK || - vcstate->output_if & VOP_OUTPUT_IF_BT656) - VOP_MODULE_SET(vop2, vp, core_dclk_div, 1); - else - VOP_MODULE_SET(vop2, vp, core_dclk_div, 0); - - if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420) { - VOP_MODULE_SET(vop2, vp, dclk_div2, 1); - VOP_MODULE_SET(vop2, vp, dclk_div2_phase_lock, 1); - } else { - VOP_MODULE_SET(vop2, vp, dclk_div2, 0); - VOP_MODULE_SET(vop2, vp, dclk_div2_phase_lock, 0); - } - snprintf(clk_name, sizeof(clk_name), "dclk_out%d", vp->id); dclk_out = vop2_clk_get(vop2, clk_name); snprintf(clk_name, sizeof(clk_name), "dclk_core%d", vp->id); @@ -8166,7 +8532,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta __clk_get_name(vp->dclk), dclk->rate, clk_get_rate(vp->dclk)); } else { rockchip_drm_dclk_set_rate(vop2->version, vp->dclk, - adjusted_mode->crtc_clock * 1000); + adjusted_mode->crtc_clock * 1000 / vp->dclk_div); } if (vp_data->feature & VOP_FEATURE_OVERSCAN) @@ -8965,6 +9331,105 @@ static void vop2_setup_alpha(struct vop2_video_port *vp, } } +static void rk3576_extra_alpha(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos) +{ + struct vop2 *vop2 = vp->vop2; + const struct vop3_ovl_regs *ovl_regs = vop2->data->vp[1].ovl_regs; + uint32_t src_color_ctrl_offset = ovl_regs->layer_mix_regs->src_color_ctrl.offset; + uint32_t dst_color_ctrl_offset = ovl_regs->layer_mix_regs->dst_color_ctrl.offset; + uint32_t src_alpha_ctrl_offset = ovl_regs->layer_mix_regs->src_alpha_ctrl.offset; + uint32_t dst_alpha_ctrl_offset = ovl_regs->layer_mix_regs->dst_alpha_ctrl.offset; + const struct vop2_zpos *zpos; + struct vop2_plane_state *vpstate; + struct vop2_alpha_config alpha_config; + struct vop2_alpha alpha; + struct vop2_win *extra_win = NULL, *win; + struct drm_plane_state *pstate; + struct drm_framebuffer *fb; + uint32_t offset; + int i = 0; + + if (vp->has_extra_layer) { + /* get the extra win: esmart1/3 */ + for (i = 0; i < vp->nr_layers; i++) { + zpos = &vop2_zpos[i]; + extra_win = vop2_find_win_by_phys_id(vop2, zpos->win_phys_id); + if (extra_win->phys_id == ROCKCHIP_VOP2_ESMART1 || + extra_win->phys_id == ROCKCHIP_VOP2_ESMART3) + break; + } + + /* check other win which zpos is higher than extra_win only can be esmart 1/3*/ + for (; i < vp->nr_layers; i++) { + zpos = &vop2_zpos[i]; + win = vop2_find_win_by_phys_id(vop2, zpos->win_phys_id); + if (win->phys_id != ROCKCHIP_VOP2_ESMART1 && win->phys_id != ROCKCHIP_VOP2_ESMART3) + DRM_ERROR("Only esmart1/3 can overlay from vp1: %s[%d],extra win:%s[%d]\n", + win->name, win->zpos, extra_win->name, extra_win->zpos); + } + + if (!extra_win) + return; + pstate = extra_win->base.state; + vpstate = to_vop2_plane_state(pstate); + fb = pstate->fb; + if (pstate->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) + alpha_config.src_premulti_en = 1; + else + alpha_config.src_premulti_en = 0; + + alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ + alpha_config.dst_premulti_en = true; + alpha_config.src_pixel_alpha_en = is_alpha_support(fb->format->format); + alpha_config.src_glb_alpha_value = vpstate->global_alpha; + alpha_config.dst_glb_alpha_value = 0xff; + vop2_parse_alpha(&alpha_config, &alpha); + + /* config vp1 overlay alpha */ + for (i = 1; i < vop2->data->nr_layers; i++) { + offset = (i - 1) * 0x10; + vop2_writel(vop2, src_color_ctrl_offset + offset, alpha.src_color_ctrl.val); + vop2_writel(vop2, dst_color_ctrl_offset + offset, alpha.dst_color_ctrl.val); + vop2_writel(vop2, src_alpha_ctrl_offset + offset, alpha.src_alpha_ctrl.val); + vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val); + } + + /* config vp0 extra alpha */ + ovl_regs = vop2->data->vp[0].ovl_regs; + src_color_ctrl_offset = ovl_regs->extra_mix_regs->src_color_ctrl.offset; + dst_color_ctrl_offset = ovl_regs->extra_mix_regs->dst_color_ctrl.offset; + src_alpha_ctrl_offset = ovl_regs->extra_mix_regs->src_alpha_ctrl.offset; + dst_alpha_ctrl_offset = ovl_regs->extra_mix_regs->dst_alpha_ctrl.offset; + + vop2_writel(vop2, src_color_ctrl_offset, alpha.src_color_ctrl.val); + vop2_writel(vop2, dst_color_ctrl_offset, alpha.dst_color_ctrl.val); + vop2_writel(vop2, src_alpha_ctrl_offset, alpha.src_alpha_ctrl.val); + vop2_writel(vop2, dst_alpha_ctrl_offset, alpha.dst_alpha_ctrl.val); + + vop2_writel(vop2, 0x500, 1);/* enable port0_extra_alpha_en */ + } else { + alpha_config.dst_pixel_alpha_en = false; + alpha_config.dst_premulti_en = false; + alpha_config.src_pixel_alpha_en = false; + alpha_config.src_glb_alpha_value = 0xff; + alpha_config.dst_glb_alpha_value = 0xff; + vop2_parse_alpha(&alpha_config, &alpha); + + /* config vp0 extra alpha */ + ovl_regs = vop2->data->vp[0].ovl_regs; + src_color_ctrl_offset = ovl_regs->extra_mix_regs->src_color_ctrl.offset; + dst_color_ctrl_offset = ovl_regs->extra_mix_regs->dst_color_ctrl.offset; + src_alpha_ctrl_offset = ovl_regs->extra_mix_regs->src_alpha_ctrl.offset; + dst_alpha_ctrl_offset = ovl_regs->extra_mix_regs->dst_alpha_ctrl.offset; + + vop2_writel(vop2, src_color_ctrl_offset, alpha.src_color_ctrl.val); + vop2_writel(vop2, dst_color_ctrl_offset, alpha.dst_color_ctrl.val); + vop2_writel(vop2, src_alpha_ctrl_offset, alpha.src_alpha_ctrl.val); + vop2_writel(vop2, dst_alpha_ctrl_offset, alpha.dst_alpha_ctrl.val); + vop2_writel(vop2, 0x500, 0);/* disable port0_extra_alpha_en */ + } +} + static void vop3_setup_alpha(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos) { @@ -9103,6 +9568,9 @@ static void vop3_setup_alpha(struct vop2_video_port *vp, bg_alpha_ctrl.bits.alpha_en = 0; VOP_MODULE_SET(vop2, vp, bg_mix_ctrl, bg_alpha_ctrl.val); + + if (vop2->version == VOP_VERSION_RK3576 && vp->id == 0) + rk3576_extra_alpha(vp, vop2_zpos); } static u32 vop2_layer_cfg_update(struct vop2_layer *layer, u32 old_layer_cfg, u8 win_layer_id) @@ -9246,6 +9714,49 @@ static void vop2_setup_layer_mixer_for_vp(struct vop2_video_port *vp, VOP_CTRL_SET(vop2, ovl_port_mux_cfg_done_imd, 0); } +static void rk3576_extra_layer_sel_for_vp(struct vop2_video_port *vp, + const struct vop2_zpos *vop2_zpos) +{ + struct vop2 *vop2 = vp->vop2; + struct vop2_video_port *vp1 = &vop2->vps[1]; + const struct vop2_zpos *zpos; + struct vop2_win *win; + u32 layer_sel = 0; + u8 layer_sel_id, vp0_nr_layers; + u8 layer_sel_none = 0xff; + int i = 0; + + vp->has_extra_layer = false; + for (i = 0; i < vp->nr_layers; i++) { + zpos = &vop2_zpos[i]; + win = vop2_find_win_by_phys_id(vop2, zpos->win_phys_id); + + if (win->phys_id == ROCKCHIP_VOP2_ESMART1 || + win->phys_id == ROCKCHIP_VOP2_ESMART3) { + vp->has_extra_layer = true; + break; + } + } + + if (vp->has_extra_layer == false) + return; + vp0_nr_layers = i; + + for (i = 0; i < vop2->data->nr_layers; i++) { + layer_sel_id = layer_sel_none; + if (i < vp->nr_layers - vp0_nr_layers) { + zpos = &vop2_zpos[vp0_nr_layers + i]; + win = vop2_find_win_by_phys_id(vop2, zpos->win_phys_id); + if (win->old_vp_mask != win->vp_mask && VOP_WIN_GET(vop2, win, enable)) + DRM_ERROR("must wait %s disabled and change vp_mask[0x%x->0x%x]\n", + win->name, win->old_vp_mask, win->vp_mask); + layer_sel_id = win->layer_sel_id[vp1->id]; + } + layer_sel |= layer_sel_id << i * 4; + } + VOP_MODULE_SET(vop2, vp1, layer_sel, layer_sel); +} + static void vop3_setup_layer_sel_for_vp(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos) { @@ -9253,7 +9764,6 @@ static void vop3_setup_layer_sel_for_vp(struct vop2_video_port *vp, const struct vop2_zpos *zpos; struct vop2_win *win; u32 layer_sel = 0; - u8 port_id = vp->id; u8 layer_sel_id; u8 layer_sel_none = 0xff; int i; @@ -9266,12 +9776,14 @@ static void vop3_setup_layer_sel_for_vp(struct vop2_video_port *vp, if (win->old_vp_mask != win->vp_mask && VOP_WIN_GET(vop2, win, enable)) DRM_ERROR("must wait %s disabled and change vp_mask[0x%x->0x%x]\n", win->name, win->old_vp_mask, win->vp_mask); - VOP_CTRL_SET(vop2, win_vp_id[win->phys_id], port_id); layer_sel_id = win->layer_sel_id[vp->id]; } layer_sel |= layer_sel_id << i * 4; } VOP_MODULE_SET(vop2, vp, layer_sel, layer_sel); + + if (vp->id == 0 && vop2->version == VOP_VERSION_RK3576) + rk3576_extra_layer_sel_for_vp(vp, vop2_zpos); } /* @@ -10087,8 +10599,9 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_stat struct vop2_wb *wb = &vop2->wb; struct drm_writeback_connector *wb_conn = &wb->conn; struct drm_connector_state *conn_state = wb_conn->base.state; + bool wb_oneframe_mode = VOP_MODULE_GET(vop2, wb, one_frame_mode); - if (conn_state && conn_state->writeback_job && conn_state->writeback_job->fb) { + if (conn_state && conn_state->writeback_job && conn_state->writeback_job->fb && !wb_oneframe_mode) { u16 vtotal = VOP_MODULE_GET(vop2, vp, dsp_vtotal); u32 current_line = vop2_read_vcnt(vp); @@ -10654,6 +11167,7 @@ static void vop2_wb_handler(struct vop2_video_port *vp) uint8_t wb_en; uint8_t wb_vp_id; uint8_t i; + bool wb_oneframe_mode = VOP_MODULE_GET(vop2, wb, one_frame_mode); wb_en = vop2_readl(vop2, RK3568_WB_CTRL) & 0x01; wb_vp_id = (vop2_readl(vop2, RK3568_LUT_PORT_SEL) >> 8) & 0x3; @@ -10663,7 +11177,7 @@ static void vop2_wb_handler(struct vop2_video_port *vp) * The write back should work in one shot mode, * stop when write back complete in next vsync. */ - if (wb_en) + if (wb_en && !wb_oneframe_mode) vop2_wb_disable(vp); spin_lock_irqsave(&wb->job_lock, flags); @@ -10846,6 +11360,147 @@ out: return ret; } +static irqreturn_t vop3_sys_isr(int irq, void *data) +{ + struct vop2 *vop2 = data; + const struct vop2_data *vop2_data = vop2->data; + int ret = IRQ_NONE; + size_t axi_max = min_t(size_t, vop2_data->nr_axi_intr, VOP2_SYS_AXI_BUS_NUM); + uint32_t axi_irqs[VOP2_SYS_AXI_BUS_NUM]; + uint32_t wb_irqs, active_irqs; + unsigned long flags; + int i = 0; + +#define SYS_ERROR_HANDLER(x) \ + do { \ + if (active_irqs & x##_INTR) {\ + DRM_DEV_ERROR_RATELIMITED(vop2->dev, #x " irq err\n"); \ + active_irqs &= ~x##_INTR; \ + ret = IRQ_HANDLED; \ + } \ + } while (0) + + /* + * The irq is shared with the iommu. If the runtime-pm state of the + * vop2-device is disabled the irq has to be targeted at the iommu. + */ + if (!pm_runtime_get_if_in_use(vop2->dev)) + return IRQ_NONE; + + if (vop2_core_clks_enable(vop2)) { + DRM_DEV_ERROR(vop2->dev, "couldn't enable clocks\n"); + goto out; + } + + /* + * interrupt register has interrupt status, enable and clear bits, we + * must hold irq_lock to avoid a race with enable/disable_vblank(). + */ + spin_lock_irqsave(&vop2->irq_lock, flags); + wb_irqs = vop2_read_and_clear_wb_irqs(vop2); + for (i = 0; i < axi_max; i++) + axi_irqs[i] = vop2_read_and_clear_axi_irqs(vop2, i); + spin_unlock_irqrestore(&vop2->irq_lock, flags); + + if (wb_irqs) { + active_irqs = wb_irqs; + SYS_ERROR_HANDLER(WB_UV_FIFO_FULL); + SYS_ERROR_HANDLER(WB_YRGB_FIFO_FULL); + SYS_ERROR_HANDLER(WB_COMPLETE); + } + + for (i = 0; i < axi_max; i++) { + active_irqs = axi_irqs[i]; + + SYS_ERROR_HANDLER(BUS_ERROR); + SYS_ERROR_HANDLER(MMU_EN); + + /* Unhandled irqs are spurious. */ + if (active_irqs) + DRM_ERROR("Unknown axi_bus%d IRQs: %02x\n", i, active_irqs); + } + + vop2_core_clks_disable(vop2); +out: + pm_runtime_put(vop2->dev); + + return ret; +} + +static irqreturn_t vop3_vp_isr(int irq, void *data) +{ + struct vop2_video_port *vp = data; + struct vop2 *vop2 = vp->vop2; + struct drm_crtc *crtc = &vp->rockchip_crtc.crtc; + uint32_t vp_irqs, active_irqs; + int ret = IRQ_NONE; + unsigned long flags; + + /* + * The irq is shared with the iommu. If the runtime-pm state of the + * vop2-device is disabled the irq has to be targeted at the iommu. + */ + if (!pm_runtime_get_if_in_use(vop2->dev)) + return IRQ_NONE; + + if (vop2_core_clks_enable(vop2)) { + DRM_DEV_ERROR(vop2->dev, "couldn't enable clocks\n"); + goto out; + } + + /* + * interrupt register has interrupt status, enable and clear bits, we + * must hold irq_lock to avoid a race with enable/disable_vblank(). + */ + spin_lock_irqsave(&vop2->irq_lock, flags); + vp_irqs = vop2_read_and_clear_active_vp_irqs(vop2, vp->id); + spin_unlock_irqrestore(&vop2->irq_lock, flags); + + active_irqs = vp_irqs; + if (active_irqs & DSP_HOLD_VALID_INTR) { + complete(&vp->dsp_hold_completion); + active_irqs &= ~DSP_HOLD_VALID_INTR; + ret = IRQ_HANDLED; + } + + if (active_irqs & LINE_FLAG_INTR) { + complete(&vp->line_flag_completion); + active_irqs &= ~LINE_FLAG_INTR; + ret = IRQ_HANDLED; + } + + if (active_irqs & LINE_FLAG1_INTR) { + vop2_handle_vcnt(crtc); + active_irqs &= ~LINE_FLAG1_INTR; + ret = IRQ_HANDLED; + } + + if (active_irqs & FS_FIELD_INTR) { + rockchip_drm_dbg(vop2->dev, VOP_DEBUG_VSYNC, "vsync_vp%d\n", vp->id); + vop2_wb_handler(vp); + drm_crtc_handle_vblank(crtc); + vop2_handle_vblank(vop2, crtc); + active_irqs &= ~FS_FIELD_INTR; + ret = IRQ_HANDLED; + } + + if (active_irqs & POST_BUF_EMPTY_INTR) { + DRM_DEV_ERROR_RATELIMITED(vop2->dev, "POST_BUF_EMPTY_INTR irq err at vp%d\n", vp->id); + active_irqs &= ~POST_BUF_EMPTY_INTR; + ret = IRQ_HANDLED; + } + + /* Unhandled irqs are spurious. */ + if (active_irqs) + DRM_ERROR("Unknown video_port%d IRQs: %02x\n", vp->id, active_irqs); + + vop2_core_clks_disable(vop2); +out: + pm_runtime_put(vop2->dev); + + return ret; +} + static int vop2_plane_create_name_property(struct vop2 *vop2, struct vop2_win *win) { struct drm_prop_enum_list *props = vop2->plane_name_list; @@ -10911,6 +11566,9 @@ static bool vop3_ignore_plane(struct vop2 *vop2, struct vop2_win *win) else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE && win->phys_id == ROCKCHIP_VOP2_ESMART1) return true; + else if (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_4K_MODE && + win->phys_id == ROCKCHIP_VOP2_ESMART3) + return true; else return false; } @@ -10921,7 +11579,9 @@ static u32 vop3_esmart_linebuffer_size(struct vop2 *vop2, struct vop2_win *win) return vop2->data->max_output.width; if (vop2->esmart_lb_mode == VOP3_ESMART_2K_2K_2K_2K_MODE || - (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE && win->phys_id != ROCKCHIP_VOP2_ESMART0)) + (vop2->esmart_lb_mode == VOP3_ESMART_4K_2K_2K_MODE && win->phys_id != ROCKCHIP_VOP2_ESMART0) || + (vop2->esmart_lb_mode == VOP3_ESMART_4K_4K_2K_2K_MODE && + (win->phys_id == ROCKCHIP_VOP2_ESMART2 || win->phys_id == ROCKCHIP_VOP2_ESMART3))) return vop2->data->max_output.width / 2; else return vop2->data->max_output.width; @@ -12209,6 +12869,7 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) vop2->disable_afbc_win = of_property_read_bool(dev->of_node, "disable-afbc-win"); vop2->disable_win_move = of_property_read_bool(dev->of_node, "disable-win-move"); vop2->skip_ref_fb = of_property_read_bool(dev->of_node, "skip-ref-fb"); + vop2->merge_irq = of_property_read_bool(dev->of_node, "rockchip,vop-merge-irq"); ret = vop2_pd_data_init(vop2); if (ret) @@ -12267,6 +12928,7 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vop-grf"); vop2->vo1_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vo1-grf"); vop2->sys_pmu = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,pmu"); + vop2->ioc_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,ioc-grf"); vop2->hclk = devm_clk_get(vop2->dev, "hclk_vop"); if (IS_ERR(vop2->hclk)) { @@ -12375,7 +13037,10 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) INIT_WORK(&vop2->post_buf_empty_work, post_buf_empty_work_event); } - ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2); + if (vop2->version == VOP_VERSION_RK3576 && vop2->merge_irq == false) + ret = devm_request_irq(dev, vop2->irq, vop3_sys_isr, IRQF_SHARED, dev_name(dev), vop2); + else + ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2); if (ret) return ret; @@ -12385,6 +13050,29 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) if (registered_num_crtcs <= 0) return -ENODEV; + if (vop2->version == VOP_VERSION_RK3576 && vop2->merge_irq == false) { + struct drm_crtc *crtc; + char irq_name[12]; + + drm_for_each_crtc(crtc, drm_dev) { + struct vop2_video_port *vp = to_vop2_video_port(crtc); + + snprintf(irq_name, sizeof(irq_name), "vop-vp%d", vp->id); + + vp->irq = platform_get_irq_byname(pdev, irq_name); + if (vp->irq < 0) { + DRM_DEV_ERROR(dev, "cannot find irq for vop2 vp%d\n", vp->id); + return vp->irq; + } + + ret = devm_request_irq(dev, vp->irq, vop3_vp_isr, IRQF_SHARED, dev_name(dev), vp); + if (ret) { + DRM_DEV_ERROR(dev, "request irq for vop2 vp%d failed\n", vp->id); + return ret; + } + } + } + ret = vop2_gamma_init(vop2); if (ret) return ret; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index e973036cc806..9671b894b2a1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -125,6 +125,42 @@ static const uint32_t formats_for_rk356x_esmart[] = { DRM_FORMAT_UYVY, /* yuv422_8bit[UYVY] linear mode */ }; +/* used from rk3576, add argb1555 format */ +static const uint32_t formats_for_vop3_esmart[] = { + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_BGR888, + DRM_FORMAT_RGB565, + DRM_FORMAT_BGR565, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ABGR1555, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_XBGR1555, + DRM_FORMAT_NV12, /* yuv420_8bit linear mode, 2 plane */ + DRM_FORMAT_NV21, /* yvu420_8bit linear mode, 2 plane */ + DRM_FORMAT_NV16, /* yuv422_8bit linear mode, 2 plane */ + DRM_FORMAT_NV61, /* yvu422_8bit linear mode, 2 plane */ + DRM_FORMAT_NV24, /* yuv444_8bit linear mode, 2 plane */ + DRM_FORMAT_NV42, /* yvu444_8bit linear mode, 2 plane */ + DRM_FORMAT_NV15, /* yuv420_10bit linear mode, 2 plane, no padding */ +#ifdef CONFIG_NO_GKI + DRM_FORMAT_NV20, /* yuv422_10bit linear mode, 2 plane, no padding */ + DRM_FORMAT_NV30, /* yuv444_10bit linear mode, 2 plane, no padding */ +#endif + DRM_FORMAT_YVYU, /* yuv422_8bit[YVYU] linear mode */ + DRM_FORMAT_VYUY, /* yuv422_8bit[VYUY] linear mode */ + DRM_FORMAT_YUYV, /* yuv422_8bit[YUYV] linear mode */ + DRM_FORMAT_UYVY, /* yuv422_8bit[UYVY] linear mode */ + DRM_FORMAT_VUY888, /* linear mode, 1 plane */ +}; + static const uint32_t formats_for_smart[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, @@ -267,6 +303,60 @@ static const uint64_t format_modifiers_afbc_tiled[] = { DRM_FORMAT_MOD_INVALID, }; +/* used from rk3576, afbc 32*8 half mode and rkfbc 64x4 */ +static const uint64_t format_modifiers_afbc_tiled_for_vop3[] = { + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_SPARSE | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_YTR | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_CBR | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_YTR | + AFBC_FORMAT_MOD_SPARSE | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_CBR | + AFBC_FORMAT_MOD_SPARSE | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_YTR | + AFBC_FORMAT_MOD_CBR | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_YTR | + AFBC_FORMAT_MOD_CBR | + AFBC_FORMAT_MOD_SPARSE | + AFBC_FORMAT_MOD_SPLIT), + + /* SPLIT mandates SPARSE, RGB modes mandates YTR */ + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | + AFBC_FORMAT_MOD_YTR | + AFBC_FORMAT_MOD_SPARSE | + AFBC_FORMAT_MOD_SPLIT), + + DRM_FORMAT_MOD_ROCKCHIP_RFBC(ROCKCHIP_RFBC_BLOCK_SIZE_64x4), + + DRM_FORMAT_MOD_ROCKCHIP_TILED(ROCKCHIP_TILED_BLOCK_SIZE_8x8), + DRM_FORMAT_MOD_ROCKCHIP_TILED(ROCKCHIP_TILED_BLOCK_SIZE_4x4_MODE0), + DRM_FORMAT_MOD_ROCKCHIP_TILED(ROCKCHIP_TILED_BLOCK_SIZE_4x4_MODE1), + + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID, +}; + static const u32 sdr2hdr_bt1886eotf_yn_for_hlg_hdr[65] = { 0, 1, 7, 17, 35, @@ -508,6 +598,17 @@ static const int rk3568_vop_axi_intrs[] = { }; +static const int rk3576_vop_axi_intrs[] = { + 0, + BUS_ERROR_INTR, + 0, + WB_UV_FIFO_FULL_INTR, + WB_YRGB_FIFO_FULL_INTR, + WB_COMPLETE_INTR, + 0, + MMU_EN_INTR, +}; + static const struct vop_intr rk3528_vop_axi_intr[] = { { .intrs = rk3568_vop_axi_intrs, @@ -536,6 +637,24 @@ static const struct vop_intr rk3568_vop_axi_intr[] = { }, }; +static const struct vop_intr rk3576_vop_axi_intr[] = { + { + .intrs = rk3576_vop_axi_intrs, + .nintrs = ARRAY_SIZE(rk3576_vop_axi_intrs), + .status = VOP_REG(RK3568_SYS0_INT_STATUS, 0xfe, 0), + .enable = VOP_REG_MASK(RK3568_SYS0_INT_EN, 0xfe, 0), + .clear = VOP_REG_MASK(RK3568_SYS0_INT_CLR, 0xfe, 0), + }, + + { + .intrs = rk3576_vop_axi_intrs, + .nintrs = ARRAY_SIZE(rk3576_vop_axi_intrs), + .status = VOP_REG(RK3568_SYS1_INT_STATUS, 0xfe, 0), + .enable = VOP_REG_MASK(RK3568_SYS1_INT_EN, 0xfe, 0), + .clear = VOP_REG_MASK(RK3568_SYS1_INT_CLR, 0xfe, 0), + }, +}; + static const int rk3568_vop_intrs[] = { FS_INTR, FS_NEW_INTR, @@ -769,6 +888,34 @@ static const struct vop2_wb_data rk3568_vop_wb_data = { .regs = &rk3568_vop_wb_regs, }; +static const struct vop2_wb_regs rk3576_vop_wb_regs = { + .enable = VOP_REG(RK3576_WB_CTRL, 0x1, 0), + .format = VOP_REG(RK3576_WB_CTRL, 0x7, 1), + .dither_en = VOP_REG(RK3576_WB_CTRL, 0x1, 4), + .r2y_en = VOP_REG(RK3576_WB_CTRL, 0x1, 5), + .scale_x_en = VOP_REG(RK3576_WB_CTRL, 0x1, 7), + .scale_y_en = VOP_REG(RK3576_WB_CTRL, 0x1, 8), + .one_frame_mode = VOP_REG(RK3576_WB_CTRL, 0x1, 12), + .axi_yrgb_id = VOP_REG(RK3576_WB_CTRL, 0xff, 20), + .axi_uv_id = VOP_REG(RK3576_WB_CTRL, 0x1f, 24), + .vp_id = VOP_REG(RK3576_WB_CTRL, 0x3, 30), + .fifo_throd = VOP_REG(RK3576_WB_XSCAL_FACTOR, 0x3ff, 0), + .scale_x_factor = VOP_REG(RK3576_WB_XSCAL_FACTOR, 0x3fff, 16), + .yrgb_mst = VOP_REG(RK3576_WB_YRGB_MST, 0xffffffff, 0), + .uv_mst = VOP_REG(RK3576_WB_CBR_MST, 0xffffffff, 0), + .vir_stride = VOP_REG(RK3576_WB_VIR_STRIDE, 0x1fff, 0), + .vir_stride_en = VOP_REG(RK3576_WB_VIR_STRIDE, 0x1, 15), + .act_width = VOP_REG(RK3576_WB_VIR_STRIDE, 0x1fff, 16), +}; + +static const struct vop2_wb_data rk3576_vop_wb_data = { + .formats = formats_wb, + .nformats = ARRAY_SIZE(formats_wb), + .max_output = { 1920, 1080 }, + .fifo_depth = 1920 * 4 / 16, + .regs = &rk3576_vop_wb_regs, +}; + static const struct vop2_video_port_regs rk3528_vop_vp0_regs = { .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 0), .overlay_mode = VOP_REG(RK3528_OVL_PORT0_CTRL, 0x1, 0), @@ -899,6 +1046,13 @@ static const struct vop2_video_port_regs rk3528_vop_vp1_regs = { .color_bar_en = VOP_REG(RK3568_VP1_COLOR_BAR_CTRL, 0x1, 0), }; +static const struct vop3_ovl_mix_regs rk3576_vop_extra_mix_regs = { + .src_color_ctrl = VOP_REG(RK3576_EXTRA_SRC_COLOR_CTRL, 0xffffffff, 0), + .dst_color_ctrl = VOP_REG(RK3576_EXTRA_DST_COLOR_CTRL, 0xffffffff, 0), + .src_alpha_ctrl = VOP_REG(RK3576_EXTRA_SRC_ALPHA_CTRL, 0xffffffff, 0), + .dst_alpha_ctrl = VOP_REG(RK3576_EXTRA_DST_ALPHA_CTRL, 0xffffffff, 0), +}; + static const struct vop3_ovl_mix_regs rk3528_vop_hdr_mix_regs = { .src_color_ctrl = VOP_REG(RK3528_HDR_SRC_COLOR_CTRL, 0xffffffff, 0), .dst_color_ctrl = VOP_REG(RK3528_HDR_DST_COLOR_CTRL, 0xffffffff, 0), @@ -920,6 +1074,13 @@ static const struct vop3_ovl_mix_regs rk3528_vop_vp1_layer_mix_regs = { .dst_alpha_ctrl = VOP_REG(RK3528_OVL_PORT1_MIX0_DST_ALPHA_CTRL, 0xffffffff, 0), }; +static const struct vop3_ovl_mix_regs rk3576_vop_vp2_layer_mix_regs = { + .src_color_ctrl = VOP_REG(RK3576_OVL_PORT2_MIX0_SRC_COLOR_CTRL, 0xffffffff, 0), + .dst_color_ctrl = VOP_REG(RK3576_OVL_PORT2_MIX0_DST_COLOR_CTRL, 0xffffffff, 0), + .src_alpha_ctrl = VOP_REG(RK3576_OVL_PORT2_MIX0_SRC_ALPHA_CTRL, 0xffffffff, 0), + .dst_alpha_ctrl = VOP_REG(RK3576_OVL_PORT2_MIX0_DST_ALPHA_CTRL, 0xffffffff, 0), +}; + static const struct vop3_ovl_regs rk3528_vop_vp0_ovl_regs = { .layer_mix_regs = &rk3528_vop_vp0_layer_mix_regs, .hdr_mix_regs = &rk3528_vop_hdr_mix_regs, @@ -929,6 +1090,10 @@ static const struct vop3_ovl_regs rk3528_vop_vp1_ovl_regs = { .layer_mix_regs = &rk3528_vop_vp1_layer_mix_regs, }; +static const struct vop3_ovl_regs rk3576_vop_vp2_ovl_regs = { + .layer_mix_regs = &rk3576_vop_vp2_layer_mix_regs, +}; + static const struct vop2_video_port_data rk3528_vop_video_ports[] = { { .id = 0, @@ -1282,6 +1447,314 @@ static const struct vop2_video_port_data rk3568_vop_video_ports[] = { }, }; +static const struct vop2_video_port_regs rk3576_vop_vp0_regs = { + .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 0), + .overlay_mode = VOP_REG(RK3528_OVL_PORT0_CTRL, 0x1, 0), + .dsp_background = VOP_REG(RK3568_VP0_DSP_BG, 0xffffffff, 0), + .out_mode = VOP_REG(RK3568_VP0_DSP_CTRL, 0xf, 0), + .core_dclk_div = VOP_REG(RK3568_VP0_CLK_CTRL, 0x1, 0), + .dclk_div2 = VOP_REG(RK3568_VP0_CLK_CTRL, 0x1, 2), + .p2i_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 5), + .dsp_filed_pol = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 6), + .dsp_interlace = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 7), + .dsp_data_swap = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1f, 8), + .dsp_x_mir_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 13), + .post_dsp_out_r2y = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 15), + .pre_dither_down_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 16), + .dither_down_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 17), + .dither_down_sel = VOP_REG(RK3568_VP0_DSP_CTRL, 0x3, 18), + .dither_down_mode = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 20), + .gamma_update_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 22), + .dsp_lut_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 28), + .standby = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 31), + + .dual_channel_en = VOP_REG(RK3568_VP0_DUAL_CHANNEL_CTRL, 0x1, 20), + .dual_channel_swap = VOP_REG(RK3568_VP0_DUAL_CHANNEL_CTRL, 0x1, 21), + .edpi_te_en = VOP_REG(RK3568_VP0_DUAL_CHANNEL_CTRL, 0x1, 28), + .edpi_wms_hold_en = VOP_REG(RK3568_VP0_DUAL_CHANNEL_CTRL, 0x1, 30), + .edpi_wms_fs = VOP_REG(RK3568_VP0_DUAL_CHANNEL_CTRL, 0x1, 31), + + .bg_mix_ctrl = VOP_REG(RK3528_OVL_PORT0_BG_MIX_CTRL, 0xffff, 0), + .bg_dly = VOP_REG(RK3528_OVL_PORT0_BG_MIX_CTRL, 0xff, 24), + .pre_scan_htiming = VOP_REG(RK3568_VP0_PRE_SCAN_HTIMING, 0x1fff1fff, 0), + .hpost_st_end = VOP_REG(RK3568_VP0_POST_DSP_HACT_INFO, 0x1fff1fff, 0), + .vpost_st_end = VOP_REG(RK3568_VP0_POST_DSP_VACT_INFO, 0x1fff1fff, 0), + .post_scl_factor = VOP_REG(RK3568_VP0_POST_SCL_FACTOR_YRGB, 0xffffffff, 0), + .post_scl_ctrl = VOP_REG(RK3568_VP0_POST_SCL_CTRL, 0x3, 0), + .htotal_pw = VOP_REG(RK3568_VP0_DSP_HTOTAL_HS_END, 0xffffffff, 0), + .hact_st_end = VOP_REG(RK3568_VP0_DSP_HACT_ST_END, 0xffffffff, 0), + .dsp_vtotal = VOP_REG(RK3568_VP0_DSP_VTOTAL_VS_END, 0x1fff, 16), + .sw_dsp_vtotal_imd = VOP_REG(RK3568_VP0_DSP_VTOTAL_VS_END, 0x1, 15), + .dsp_vs_end = VOP_REG(RK3568_VP0_DSP_VTOTAL_VS_END, 0x1fff, 0), + .vact_st_end = VOP_REG(RK3568_VP0_DSP_VACT_ST_END, 0x1fff1fff, 0), + .vact_st_end_f1 = VOP_REG(RK3568_VP0_DSP_VACT_ST_END_F1, 0x1fff1fff, 0), + .vs_st_end_f1 = VOP_REG(RK3568_VP0_DSP_VS_ST_END_F1, 0x1fff1fff, 0), + .vpost_st_end_f1 = VOP_REG(RK3568_VP0_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0), + .lut_dma_rid = VOP_REG(RK3568_SYS_AXI_LUT_CTRL, 0x1f, 4), + .layer_sel = VOP_REG(RK3528_OVL_PORT0_LAYER_SEL, 0xffff, 0), + .hdr_src_color_ctrl = VOP_REG(RK3528_HDR_SRC_COLOR_CTRL, 0xffffffff, 0), + .hdr_dst_color_ctrl = VOP_REG(RK3528_HDR_DST_COLOR_CTRL, 0xffffffff, 0), + .hdr_src_alpha_ctrl = VOP_REG(RK3528_HDR_SRC_ALPHA_CTRL, 0xffffffff, 0), + .hdr_dst_alpha_ctrl = VOP_REG(RK3528_HDR_DST_ALPHA_CTRL, 0xffffffff, 0), + .hdr_lut_update_en = VOP_REG(RK3568_HDR_LUT_CTRL, 0x1, 0), + .hdr_lut_mode = VOP_REG(RK3568_HDR_LUT_CTRL, 0x1, 1), + .hdr_lut_mst = VOP_REG(RK3568_HDR_LUT_MST, 0xffffffff, 0), + .hdr_lut_fetch_done = VOP_REG(RK3528_HDR_LUT_STATUS, 0x1, 0), + .hdr10_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 4), + .sdr2hdr_path_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 5), + .sdr2hdr_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 0), + .sdr2hdr_auto_gating_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 1), + .sdr2hdr_bypass_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 2), + .sdr2hdr_dstmode = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 3), + .hdr_vivid_en = VOP_REG(RK3528_HDRVIVID_CTRL, 0x1, 0), + .hdr_vivid_bypass_en = VOP_REG(RK3528_HDRVIVID_CTRL, 0x1, 2), + .hdr_vivid_path_mode = VOP_REG(RK3528_HDRVIVID_CTRL, 0x7, 3), + .hdr_vivid_dstgamut = VOP_REG(RK3528_HDRVIVID_CTRL, 0x1, 6), + .acm_bypass_en = VOP_REG(RK3528_VP0_ACM_CTRL, 0x1, 0), + .csc_en = VOP_REG(RK3528_VP0_ACM_CTRL, 0x1, 1), + .acm_r2y_en = VOP_REG(RK3528_VP0_ACM_CTRL, 0x1, 2), + .csc_mode = VOP_REG(RK3528_VP0_ACM_CTRL, 0x7, 3), + .acm_r2y_mode = VOP_REG(RK3528_VP0_ACM_CTRL, 0x7, 8), + .csc_coe00 = VOP_REG(RK3528_VP0_ACM_CTRL, 0xffff, 16), + .csc_coe01 = VOP_REG(RK3528_VP0_CSC_COE01_02, 0xffff, 0), + .csc_coe02 = VOP_REG(RK3528_VP0_CSC_COE01_02, 0xffff, 16), + .csc_coe10 = VOP_REG(RK3528_VP0_CSC_COE10_11, 0xffff, 0), + .csc_coe11 = VOP_REG(RK3528_VP0_CSC_COE10_11, 0xffff, 16), + .csc_coe12 = VOP_REG(RK3528_VP0_CSC_COE12_20, 0xffff, 0), + .csc_coe20 = VOP_REG(RK3528_VP0_CSC_COE12_20, 0xffff, 16), + .csc_coe21 = VOP_REG(RK3528_VP0_CSC_COE21_22, 0xffff, 0), + .csc_coe22 = VOP_REG(RK3528_VP0_CSC_COE21_22, 0xffff, 16), + .csc_offset0 = VOP_REG(RK3528_VP0_CSC_OFFSET0, 0xffffffff, 0), + .csc_offset1 = VOP_REG(RK3528_VP0_CSC_OFFSET1, 0xffffffff, 0), + .csc_offset2 = VOP_REG(RK3528_VP0_CSC_OFFSET2, 0xffffffff, 0), + .color_bar_mode = VOP_REG(RK3568_VP0_COLOR_BAR_CTRL, 0x1, 1), + .color_bar_en = VOP_REG(RK3568_VP0_COLOR_BAR_CTRL, 0x1, 0), + + .cubic_lut_en = VOP_REG(RK3568_VP0_3D_LUT_CTRL, 0x1, 0), + .cubic_lut_update_en = VOP_REG(RK3568_VP0_3D_LUT_CTRL, 0x1, 2), + .cubic_lut_mst = VOP_REG(RK3568_VP0_3D_LUT_MST, 0xffffffff, 0), + + .mcu_pix_total = VOP_REG(RK3562_VP0_MCU_CTRL, 0x3f, 0), + .mcu_cs_pst = VOP_REG(RK3562_VP0_MCU_CTRL, 0xf, 6), + .mcu_cs_pend = VOP_REG(RK3562_VP0_MCU_CTRL, 0x3f, 10), + .mcu_rw_pst = VOP_REG(RK3562_VP0_MCU_CTRL, 0xf, 16), + .mcu_rw_pend = VOP_REG(RK3562_VP0_MCU_CTRL, 0x3f, 20), + .mcu_hold_mode = VOP_REG(RK3562_VP0_MCU_CTRL, 0x1, 27), + .mcu_frame_st = VOP_REG(RK3562_VP0_MCU_CTRL, 0x1, 28), + .mcu_rs = VOP_REG(RK3562_VP0_MCU_CTRL, 0x1, 29), + .mcu_bypass = VOP_REG(RK3562_VP0_MCU_CTRL, 0x1, 30), + .mcu_type = VOP_REG(RK3562_VP0_MCU_CTRL, 0x1, 31), + .mcu_rw_bypass_port = VOP_REG(RK3562_VP0_MCU_RW_BYPASS_PORT, 0xffffffff, 0), +}; + +static const struct vop2_video_port_regs rk3576_vop_vp1_regs = { + .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 1), + .overlay_mode = VOP_REG(RK3528_OVL_PORT1_CTRL, 0x1, 0), + .dsp_background = VOP_REG(RK3568_VP1_DSP_BG, 0xffffffff, 0), + .out_mode = VOP_REG(RK3568_VP1_DSP_CTRL, 0xf, 0), + .core_dclk_div = VOP_REG(RK3568_VP1_CLK_CTRL, 0x1, 0), + .dclk_div2 = VOP_REG(RK3568_VP1_CLK_CTRL, 0x1, 2), + .p2i_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 5), + .dsp_filed_pol = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 6), + .dsp_interlace = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 7), + .dsp_data_swap = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1f, 8), + .dsp_x_mir_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 13), + .post_dsp_out_r2y = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 15), + .pre_dither_down_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 16), + .dither_down_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 17), + .dither_down_sel = VOP_REG(RK3568_VP1_DSP_CTRL, 0x3, 18), + .dither_down_mode = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 20), + .gamma_update_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 22), + .dsp_lut_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 28), + .standby = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 31), + + .dual_channel_en = VOP_REG(RK3568_VP1_DUAL_CHANNEL_CTRL, 0x1, 20), + .dual_channel_swap = VOP_REG(RK3568_VP1_DUAL_CHANNEL_CTRL, 0x1, 21), + .edpi_te_en = VOP_REG(RK3568_VP1_DUAL_CHANNEL_CTRL, 0x1, 28), + .edpi_wms_hold_en = VOP_REG(RK3568_VP1_DUAL_CHANNEL_CTRL, 0x1, 30), + .edpi_wms_fs = VOP_REG(RK3568_VP1_DUAL_CHANNEL_CTRL, 0x1, 31), + + .bg_mix_ctrl = VOP_REG(RK3528_OVL_PORT1_BG_MIX_CTRL, 0xffff, 0), + .bg_dly = VOP_REG(RK3528_OVL_PORT1_BG_MIX_CTRL, 0xff, 24), + .pre_scan_htiming = VOP_REG(RK3568_VP1_PRE_SCAN_HTIMING, 0x1fff1fff, 0), + .hpost_st_end = VOP_REG(RK3568_VP1_POST_DSP_HACT_INFO, 0x1fff1fff, 0), + .vpost_st_end = VOP_REG(RK3568_VP1_POST_DSP_VACT_INFO, 0x1fff1fff, 0), + .post_scl_factor = VOP_REG(RK3568_VP1_POST_SCL_FACTOR_YRGB, 0xffffffff, 0), + .post_scl_ctrl = VOP_REG(RK3568_VP1_POST_SCL_CTRL, 0x3, 0), + .htotal_pw = VOP_REG(RK3568_VP1_DSP_HTOTAL_HS_END, 0xffffffff, 0), + .hact_st_end = VOP_REG(RK3568_VP1_DSP_HACT_ST_END, 0xffffffff, 0), + .dsp_vtotal = VOP_REG(RK3568_VP1_DSP_VTOTAL_VS_END, 0x1fff, 16), + .sw_dsp_vtotal_imd = VOP_REG(RK3568_VP1_DSP_VTOTAL_VS_END, 0x1, 15), + .dsp_vs_end = VOP_REG(RK3568_VP1_DSP_VTOTAL_VS_END, 0x1fff, 0), + .vact_st_end = VOP_REG(RK3568_VP1_DSP_VACT_ST_END, 0x1fff1fff, 0), + .vact_st_end_f1 = VOP_REG(RK3568_VP1_DSP_VACT_ST_END_F1, 0x1fff1fff, 0), + .vs_st_end_f1 = VOP_REG(RK3568_VP1_DSP_VS_ST_END_F1, 0x1fff1fff, 0), + .vpost_st_end_f1 = VOP_REG(RK3568_VP1_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0), + .lut_dma_rid = VOP_REG(RK3568_SYS_AXI_LUT_CTRL, 0x1f, 4), + .layer_sel = VOP_REG(RK3528_OVL_PORT1_LAYER_SEL, 0xffff, 0), + .color_bar_mode = VOP_REG(RK3568_VP1_COLOR_BAR_CTRL, 0x1, 1), + .color_bar_en = VOP_REG(RK3568_VP1_COLOR_BAR_CTRL, 0x1, 0), + .bcsh_brightness = VOP_REG(RK3568_VP1_BCSH_BCS, 0xff, 0), + .bcsh_contrast = VOP_REG(RK3568_VP1_BCSH_BCS, 0x1ff, 8), + .bcsh_sat_con = VOP_REG(RK3568_VP1_BCSH_BCS, 0x3ff, 20), + .bcsh_out_mode = VOP_REG(RK3568_VP1_BCSH_BCS, 0x3, 30), + .bcsh_sin_hue = VOP_REG(RK3568_VP1_BCSH_H, 0x1ff, 0), + .bcsh_cos_hue = VOP_REG(RK3568_VP1_BCSH_H, 0x1ff, 16), + .bcsh_r2y_csc_mode = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x3, 6), + .bcsh_r2y_en = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x1, 4), + .bcsh_y2r_csc_mode = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x3, 2), + .bcsh_y2r_en = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x1, 0), + .bcsh_en = VOP_REG(RK3568_VP1_BCSH_COLOR_BAR, 0x1, 31), + + .mcu_pix_total = VOP_REG(RK3562_VP1_MCU_CTRL, 0x3f, 0), + .mcu_cs_pst = VOP_REG(RK3562_VP1_MCU_CTRL, 0xf, 6), + .mcu_cs_pend = VOP_REG(RK3562_VP1_MCU_CTRL, 0x3f, 10), + .mcu_rw_pst = VOP_REG(RK3562_VP1_MCU_CTRL, 0xf, 16), + .mcu_rw_pend = VOP_REG(RK3562_VP1_MCU_CTRL, 0x3f, 20), + .mcu_hold_mode = VOP_REG(RK3562_VP1_MCU_CTRL, 0x1, 27), + .mcu_frame_st = VOP_REG(RK3562_VP1_MCU_CTRL, 0x1, 28), + .mcu_rs = VOP_REG(RK3562_VP1_MCU_CTRL, 0x1, 29), + .mcu_bypass = VOP_REG(RK3562_VP1_MCU_CTRL, 0x1, 30), + .mcu_type = VOP_REG(RK3562_VP1_MCU_CTRL, 0x1, 31), + .mcu_rw_bypass_port = VOP_REG(RK3562_VP1_MCU_RW_BYPASS_PORT, 0xffffffff, 0), +}; + +static const struct vop2_video_port_regs rk3576_vop_vp2_regs = { + .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 2), + .overlay_mode = VOP_REG(RK3576_OVL_PORT2_CTRL, 0x1, 0), + .dsp_background = VOP_REG(RK3568_VP2_DSP_BG, 0xffffffff, 0), + .out_mode = VOP_REG(RK3568_VP2_DSP_CTRL, 0xf, 0), + .core_dclk_div = VOP_REG(RK3568_VP2_CLK_CTRL, 0x1, 0), + .dclk_div2 = VOP_REG(RK3568_VP2_CLK_CTRL, 0x1, 2), + .p2i_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 5), + .dsp_filed_pol = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 6), + .dsp_interlace = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 7), + .dsp_data_swap = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1f, 8), + .dsp_x_mir_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 13), + .post_dsp_out_r2y = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 15), + .pre_dither_down_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 16), + .dither_down_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 17), + .dither_down_sel = VOP_REG(RK3568_VP2_DSP_CTRL, 0x3, 18), + .dither_down_mode = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 20), + .gamma_update_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 22), + .dsp_lut_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 28), + .standby = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 31), + + .dual_channel_en = VOP_REG(RK3568_VP2_DUAL_CHANNEL_CTRL, 0x1, 20), + .dual_channel_swap = VOP_REG(RK3568_VP2_DUAL_CHANNEL_CTRL, 0x1, 21), + .edpi_te_en = VOP_REG(RK3568_VP2_DUAL_CHANNEL_CTRL, 0x1, 28), + .edpi_wms_hold_en = VOP_REG(RK3568_VP2_DUAL_CHANNEL_CTRL, 0x1, 30), + .edpi_wms_fs = VOP_REG(RK3568_VP2_DUAL_CHANNEL_CTRL, 0x1, 31), + + .bg_mix_ctrl = VOP_REG(RK3576_OVL_PORT2_BG_MIX_CTRL, 0xffff, 0), + .bg_dly = VOP_REG(RK3576_OVL_PORT2_BG_MIX_CTRL, 0xff, 24), + .pre_scan_htiming = VOP_REG(RK3568_VP2_PRE_SCAN_HTIMING, 0x1fff1fff, 0), + .hpost_st_end = VOP_REG(RK3568_VP2_POST_DSP_HACT_INFO, 0x1fff1fff, 0), + .vpost_st_end = VOP_REG(RK3568_VP2_POST_DSP_VACT_INFO, 0x1fff1fff, 0), + .post_scl_factor = VOP_REG(RK3568_VP2_POST_SCL_FACTOR_YRGB, 0xffffffff, 0), + .post_scl_ctrl = VOP_REG(RK3568_VP2_POST_SCL_CTRL, 0x3, 0), + .htotal_pw = VOP_REG(RK3568_VP2_DSP_HTOTAL_HS_END, 0xffffffff, 0), + .hact_st_end = VOP_REG(RK3568_VP2_DSP_HACT_ST_END, 0xffffffff, 0), + .dsp_vtotal = VOP_REG(RK3568_VP2_DSP_VTOTAL_VS_END, 0x1fff, 16), + .sw_dsp_vtotal_imd = VOP_REG(RK3568_VP2_DSP_VTOTAL_VS_END, 0x1, 15), + .dsp_vs_end = VOP_REG(RK3568_VP2_DSP_VTOTAL_VS_END, 0x1fff, 0), + .vact_st_end = VOP_REG(RK3568_VP2_DSP_VACT_ST_END, 0x1fff1fff, 0), + .vact_st_end_f1 = VOP_REG(RK3568_VP2_DSP_VACT_ST_END_F1, 0x1fff1fff, 0), + .vs_st_end_f1 = VOP_REG(RK3568_VP2_DSP_VS_ST_END_F1, 0x1fff1fff, 0), + .vpost_st_end_f1 = VOP_REG(RK3568_VP2_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0), + .lut_dma_rid = VOP_REG(RK3568_SYS_AXI_LUT_CTRL, 0x1f, 4), + .layer_sel = VOP_REG(RK3576_OVL_PORT2_LAYER_SEL, 0xffff, 0), + .color_bar_mode = VOP_REG(RK3568_VP2_COLOR_BAR_CTRL, 0x1, 1), + .color_bar_en = VOP_REG(RK3568_VP2_COLOR_BAR_CTRL, 0x1, 0), + .bcsh_brightness = VOP_REG(RK3568_VP2_BCSH_BCS, 0xff, 0), + .bcsh_contrast = VOP_REG(RK3568_VP2_BCSH_BCS, 0x1ff, 8), + .bcsh_sat_con = VOP_REG(RK3568_VP2_BCSH_BCS, 0x3ff, 20), + .bcsh_out_mode = VOP_REG(RK3568_VP2_BCSH_BCS, 0x3, 30), + .bcsh_sin_hue = VOP_REG(RK3568_VP2_BCSH_H, 0x1ff, 0), + .bcsh_cos_hue = VOP_REG(RK3568_VP2_BCSH_H, 0x1ff, 16), + .bcsh_r2y_csc_mode = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x3, 6), + .bcsh_r2y_en = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x1, 4), + .bcsh_y2r_csc_mode = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x3, 2), + .bcsh_y2r_en = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x1, 0), + .bcsh_en = VOP_REG(RK3568_VP2_BCSH_COLOR_BAR, 0x1, 31), + + .mcu_pix_total = VOP_REG(RK3576_VP2_MCU_CTRL, 0x3f, 0), + .mcu_cs_pst = VOP_REG(RK3576_VP2_MCU_CTRL, 0xf, 6), + .mcu_cs_pend = VOP_REG(RK3576_VP2_MCU_CTRL, 0x3f, 10), + .mcu_rw_pst = VOP_REG(RK3576_VP2_MCU_CTRL, 0xf, 16), + .mcu_rw_pend = VOP_REG(RK3576_VP2_MCU_CTRL, 0x3f, 20), + .mcu_hold_mode = VOP_REG(RK3576_VP2_MCU_CTRL, 0x1, 27), + .mcu_frame_st = VOP_REG(RK3576_VP2_MCU_CTRL, 0x1, 28), + .mcu_rs = VOP_REG(RK3576_VP2_MCU_CTRL, 0x1, 29), + .mcu_bypass = VOP_REG(RK3576_VP2_MCU_CTRL, 0x1, 30), + .mcu_type = VOP_REG(RK3576_VP2_MCU_CTRL, 0x1, 31), + .mcu_rw_bypass_port = VOP_REG(RK3576_VP2_MCU_RW_BYPASS_PORT, 0xffffffff, 0), +}; + +static const struct vop3_ovl_regs rk3576_vop_vp0_ovl_regs = { + .layer_mix_regs = &rk3528_vop_vp0_layer_mix_regs, + .hdr_mix_regs = &rk3528_vop_hdr_mix_regs, + .extra_mix_regs = &rk3576_vop_extra_mix_regs, +}; + +static const struct vop2_video_port_data rk3576_vop_video_ports[] = { + { + .id = 0, + .soc_id = { 0x3576, 0x3576 }, + .lut_dma_rid = 0x10, + .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_VIVID_HDR | + VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC | VOP_FEATURE_OUTPUT_10BIT | + VOP_FEATURE_POST_FRC_V2 | VOP_FEATURE_POST_SHARP, + .gamma_lut_len = 1024, + .cubic_lut_len = 729, /* 9x9x9 */ + .max_output = { 4096, 4096 }, + .hdrvivid_dly = {17, 29, 32, 44, 15, 38, 1, 29, 0, 0}, + .sdr2hdr_dly = 21, + .layer_mix_dly = 8, + .hdr_mix_dly = 2, + .win_dly = 10, + .pixel_rate = 2, + .intr = &rk3568_vp0_intr, + .regs = &rk3576_vop_vp0_regs, + .ovl_regs = &rk3576_vop_vp0_ovl_regs, + }, + { + .id = 1, + .soc_id = { 0x3576, 0x3576 }, + .lut_dma_rid = 0x11, + .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN | VOP_FEATURE_OUTPUT_10BIT | + VOP_FEATURE_POST_FRC_V2, + .gamma_lut_len = 1024, + .max_output = { 2560, 2560 }, + .hdrvivid_dly = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + .sdr2hdr_dly = 0, + .layer_mix_dly = 6, + .hdr_mix_dly = 0, + .win_dly = 10, + .pixel_rate = 1, + .intr = &rk3568_vp1_intr, + .regs = &rk3576_vop_vp1_regs, + .ovl_regs = &rk3528_vop_vp1_ovl_regs, + }, + { + .id = 2, + .soc_id = { 0x3576, 0x3576 }, + .lut_dma_rid = 0x12, + .feature = VOP_FEATURE_ALPHA_SCALE | VOP_FEATURE_OVERSCAN, + .gamma_lut_len = 1024, + .max_output = { 1920, 1920 }, + .hdrvivid_dly = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + .sdr2hdr_dly = 0, + .layer_mix_dly = 6, + .hdr_mix_dly = 0, + .win_dly = 10, + .pixel_rate = 1, + .intr = &rk3568_vp2_intr, + .regs = &rk3576_vop_vp2_regs, + .ovl_regs = &rk3576_vop_vp2_ovl_regs, + }, +}; + static const struct vop2_video_port_regs rk3588_vop_vp0_regs = { .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 0), .overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 0), @@ -1899,6 +2372,18 @@ static const struct vop2_cluster_regs rk3568_vop_cluster1 = { .dst_alpha_ctrl = VOP_REG(RK3568_CLUSTER1_MIX_DST_ALPHA_CTRL, 0xffffffff, 0), }; +static const struct vop2_cluster_regs rk3576_vop_cluster1 = { + .afbc_enable = VOP_REG(RK3568_CLUSTER1_CTRL, 0x1, 1), + .enable = VOP_REG(RK3568_CLUSTER1_CTRL, 1, 0), + .lb_mode = VOP_REG(RK3568_CLUSTER1_CTRL, 0xf, 4), + .scl_lb_mode = VOP_REG(RK3568_CLUSTER1_CTRL, 0x3, 9), + .frm_reset_en = VOP_REG(RK3568_CLUSTER1_CTRL, 1, 31), + .src_color_ctrl = VOP_REG(RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL, 0xffffffff, 0), + .dst_color_ctrl = VOP_REG(RK3576_CLUSTER1_MIX_DST_COLOR_CTRL, 0xffffffff, 0), + .src_alpha_ctrl = VOP_REG(RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL, 0xffffffff, 0), + .dst_alpha_ctrl = VOP_REG(RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL, 0xffffffff, 0), +}; + static const struct vop2_cluster_regs rk3588_vop_cluster2 = { .afbc_enable = VOP_REG(RK3588_CLUSTER2_CTRL, 0x1, 1), .enable = VOP_REG(RK3588_CLUSTER2_CTRL, 1, 0), @@ -1941,6 +2426,30 @@ static const struct vop_afbc rk3568_cluster0_afbc = { .ymirror = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE, 0x1, 3), }; +static const struct vop_afbc rk3576_cluster0_afbc = { + .format = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_CTRL, 0x1f, 2), + .rb_swap = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_CTRL, 0x1, 9), + .uv_swap = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_CTRL, 0x1, 10), + .auto_gating_en = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_OUTPUT_CTRL, 0x1, 4), + .half_block_en = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_CTRL, 0x1, 7), + .block_split_en = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_CTRL, 0x1, 8), + .pld_offset_en = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_CTRL, 0x1, 16), + .pld_ptr_offset = VOP_REG(RK3576_CLUSTER0_WIN0_PLD_PTR_OFFSET, 0xffffffff, 0), + .pld_range_en = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_CTRL, 0x1, 17), + .pld_ptr_range = VOP_REG(RK3576_CLUSTER0_WIN0_PLD_PTR_RANGE, 0xffffffff, 0), + .hdr_ptr = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR, 0xffffffff, 0), + .pic_size = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_PIC_SIZE, 0xffffffff, 0), + .pic_vir_width = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH, 0xffff, 0), + .tile_num = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_VIR_WIDTH, 0xffff, 16), + .pic_offset = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET, 0xffffffff, 0), + .dsp_offset = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET, 0xffffffff, 0), + .transform_offset = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_TRANSFORM_OFFSET, 0xffffffff, 0), + .rotate_90 = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE, 0x1, 0), + .rotate_270 = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE, 0x1, 1), + .xmirror = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE, 0x1, 2), + .ymirror = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE, 0x1, 3), +}; + static const struct vop2_scl_regs rk3528_cluster0_win_scl = { .scale_yrgb_x = VOP_REG(RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), .scale_yrgb_y = VOP_REG(RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), @@ -1992,6 +2501,30 @@ static const struct vop_afbc rk3568_cluster1_afbc = { .ymirror = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE, 0x1, 3), }; +static const struct vop_afbc rk3576_cluster1_afbc = { + .format = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_CTRL, 0x1f, 2), + .rb_swap = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_CTRL, 0x1, 9), + .uv_swap = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_CTRL, 0x1, 10), + .auto_gating_en = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_OUTPUT_CTRL, 0x1, 4), + .half_block_en = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_CTRL, 0x1, 7), + .block_split_en = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_CTRL, 0x1, 8), + .pld_offset_en = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_CTRL, 0x1, 16), + .pld_ptr_offset = VOP_REG(RK3576_CLUSTER1_WIN0_PLD_PTR_OFFSET, 0xffffffff, 0), + .pld_range_en = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_CTRL, 0x1, 17), + .pld_ptr_range = VOP_REG(RK3576_CLUSTER1_WIN0_PLD_PTR_RANGE, 0xffffffff, 0), + .hdr_ptr = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR, 0xffffffff, 0), + .pic_size = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_PIC_SIZE, 0xffffffff, 0), + .pic_vir_width = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH, 0xffff, 0), + .tile_num = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_VIR_WIDTH, 0xffff, 16), + .pic_offset = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET, 0xffffffff, 0), + .dsp_offset = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET, 0xffffffff, 0), + .transform_offset = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_TRANSFORM_OFFSET, 0xffffffff, 0), + .rotate_90 = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE, 0x1, 0), + .rotate_270 = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE, 0x1, 1), + .xmirror = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE, 0x1, 2), + .ymirror = VOP_REG(RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE, 0x1, 3), +}; + static const struct vop2_scl_regs rk3568_cluster1_win_scl = { .scale_yrgb_x = VOP_REG(RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), .scale_yrgb_y = VOP_REG(RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), @@ -2327,6 +2860,7 @@ static const struct vop2_win_regs rk3568_esmart_win_data = { .axi_id = VOP_REG(RK3568_ESMART0_AXI_CTRL, 0x1, 1), .enable = VOP_REG(RK3568_ESMART0_REGION0_CTRL, 0x1, 0), .format = VOP_REG(RK3568_ESMART0_REGION0_CTRL, 0x1f, 1), + .format_argb1555 = VOP_REG(RK3568_ESMART0_REGION0_CTRL, 0x1, 7), .dither_up = VOP_REG(RK3568_ESMART0_REGION0_CTRL, 0x1, 12), .rb_swap = VOP_REG(RK3568_ESMART0_REGION0_CTRL, 0x1, 14), .uv_swap = VOP_REG(RK3568_ESMART0_REGION0_CTRL, 0x1, 16), @@ -2345,6 +2879,7 @@ static const struct vop2_win_regs rk3568_esmart_win_data = { .color_key = VOP_REG(RK3568_ESMART0_COLOR_KEY_CTRL, 0x3fffffff, 0), .color_key_en = VOP_REG(RK3568_ESMART0_COLOR_KEY_CTRL, 0x1, 31), .scale_engine_num = VOP_REG(RK3568_ESMART0_CTRL0, 0x3, 12),/* supported from vop3 */ + .csc_y2r_path_sel = VOP_REG(RK3568_ESMART0_CTRL0, 0x1, 24), }; /* @@ -2855,6 +3390,390 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { }, }; +static const struct vop2_scl_regs rk3576_cluster0_win_scl = { + .scale_yrgb_x = VOP_REG(RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), + .scale_yrgb_y = VOP_REG(RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), + .yrgb_ver_scl_mode = VOP_REG(RK3528_CLUSTER0_WIN0_CTRL1, 0x3, 14), + .yrgb_hor_scl_mode = VOP_REG(RK3528_CLUSTER0_WIN0_CTRL1, 0x3, 22), + + .yrgb_vscl_filter_mode = VOP_REG(RK3528_CLUSTER0_WIN0_CTRL1, 0x3, 12),/* supported from vop3 */ + .yrgb_hscl_filter_mode = VOP_REG(RK3528_CLUSTER0_WIN0_CTRL1, 0x3, 20),/* supported from vop3 */ + + .vsd_yrgb_gt2 = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL1, 0x1, 28), + .vsd_yrgb_gt4 = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL1, 0x1, 29), + .vsd_cbcr_gt2 = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL1, 0x1, 30), + .vsd_cbcr_gt4 = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL1, 0x1, 31), + + .vsd_avg2 = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL1, 0x1, 18),/* supported from vop3 */ + .vsd_avg4 = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL1, 0x1, 19), + + .xavg_en = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL1, 0x1, 27), + .xgt_en = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL1, 0x1, 24), + .xgt_mode = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL1, 0x3, 25), + .zme_dering_en = VOP_REG(RK3576_CLUSTER0_WIN0_ZME_CTRL, 0x1, 3), + .zme_dering_para = VOP_REG(RK3576_CLUSTER0_WIN0_ZME_DERING_PARA, 0xffffffff, 0), +}; + +static const struct vop2_win_regs rk3576_cluster0_win_data = { + .scl = &rk3576_cluster0_win_scl, + .afbc = &rk3576_cluster0_afbc, + .cluster = &rk3528_vop_cluster0, + .enable = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0), + .format = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL0, 0x3f, 1), + .tile_mode = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 7), + .rb_swap = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 14), + .uv_swap = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 17), + .dither_up = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 18), + .act_info = VOP_REG(RK3568_CLUSTER0_WIN0_ACT_INFO, 0x1fff1fff, 0), + .dsp_info = VOP_REG(RK3568_CLUSTER0_WIN0_DSP_INFO, 0x0fff0fff, 0), + .dsp_st = VOP_REG(RK3568_CLUSTER0_WIN0_DSP_ST, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(RK3568_CLUSTER0_WIN0_YRGB_MST, 0xffffffff, 0), + .uv_mst = VOP_REG(RK3568_CLUSTER0_WIN0_CBR_MST, 0xffffffff, 0), + .yuv_clip = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 19), + .yrgb_vir = VOP_REG(RK3568_CLUSTER0_WIN0_VIR, 0xffff, 0), + .uv_vir = VOP_REG(RK3568_CLUSTER0_WIN0_VIR, 0xffff, 16), + .y2r_en = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 8), + .r2y_en = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 9), + .csc_mode = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL0, 0x7, 10), + .axi_yrgb_id = VOP_REG(RK3528_CLUSTER0_WIN0_CTRL2, 0x1f, 0), + .axi_uv_id = VOP_REG(RK3528_CLUSTER0_WIN0_CTRL2, 0x1f, 5), + .csc_y2r_path_sel = VOP_REG(RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 24), +}; + +static const struct vop2_scl_regs rk3576_cluster1_win_scl = { + .scale_yrgb_x = VOP_REG(RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0), + .scale_yrgb_y = VOP_REG(RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB, 0xffff, 16), + .yrgb_ver_scl_mode = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x3, 14), + .yrgb_hor_scl_mode = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x3, 22), + + .yrgb_vscl_filter_mode = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x3, 12),/* supported from vop3 */ + .yrgb_hscl_filter_mode = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x3, 20),/* supported from vop3 */ + + .vsd_yrgb_gt2 = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x1, 28), + .vsd_yrgb_gt4 = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x1, 29), + .vsd_cbcr_gt2 = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x1, 30), + .vsd_cbcr_gt4 = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x1, 31), + + .vsd_avg2 = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x1, 18),/* supported from vop3 */ + .vsd_avg4 = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x1, 19), + + .xavg_en = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x1, 27), + .xgt_en = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x1, 24), + .xgt_mode = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL1, 0x3, 25), + + .zme_dering_en = VOP_REG(RK3576_CLUSTER1_WIN0_ZME_CTRL, 0x1, 3), + .zme_dering_para = VOP_REG(RK3576_CLUSTER1_WIN0_ZME_DERING_PARA, 0xffffffff, 0), +}; + +static const struct vop2_win_regs rk3576_cluster1_win_data = { + .scl = &rk3576_cluster1_win_scl, + .afbc = &rk3576_cluster1_afbc, + .cluster = &rk3576_vop_cluster1, + .enable = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0), + .format = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL0, 0x3f, 1), + .tile_mode = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 7), + .rb_swap = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 14), + .uv_swap = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 17), + .dither_up = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 18), + .act_info = VOP_REG(RK3568_CLUSTER1_WIN0_ACT_INFO, 0x1fff1fff, 0), + .dsp_info = VOP_REG(RK3568_CLUSTER1_WIN0_DSP_INFO, 0x0fff0fff, 0), + .dsp_st = VOP_REG(RK3568_CLUSTER1_WIN0_DSP_ST, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(RK3568_CLUSTER1_WIN0_YRGB_MST, 0xffffffff, 0), + .uv_mst = VOP_REG(RK3568_CLUSTER1_WIN0_CBR_MST, 0xffffffff, 0), + .yuv_clip = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 19), + .yrgb_vir = VOP_REG(RK3568_CLUSTER1_WIN0_VIR, 0xffff, 0), + .uv_vir = VOP_REG(RK3568_CLUSTER1_WIN0_VIR, 0xffff, 16), + .y2r_en = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 8), + .r2y_en = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 9), + .csc_mode = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL0, 0x7, 10), + .axi_yrgb_id = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL2, 0x1f, 0), + .axi_uv_id = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL2, 0x1f, 5), + .csc_y2r_path_sel = VOP_REG(RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 24), +}; + +/* + * RK3576 VOP with 2 Cluster win and 4 Esmart win. + * Every Esmart win support 4 multi-region. + * VP0 can use Cluster0/1 and Esmart0/2 + * VP1 can use Cluster0/1 and Esmart1/3 + * VP2 can use Esmart0/1/2/3 + * + * Scale filter mode: + * + * * Cluster: + * * Support prescale down: + * * H/V: gt2/avg2 or gt4/avg4 + * * After prescale down: + * * nearest-neighbor/bilinear/multi-phase filter for scale up + * * nearest-neighbor/bilinear/multi-phase filter for scale down + * + * * Esmart: + * * Support prescale down: + * * H: gt2/avg2 or gt4/avg4 + * * V: gt2 or gt4 + * * After prescale down: + * * nearest-neighbor/bilinear/bicubic for scale up + * * nearest-neighbor/bilinear for scale down + */ +static const struct vop2_win_data rk3576_vop_win_data[] = { + { + .name = "Esmart0-win0", + .phys_id = ROCKCHIP_VOP2_ESMART0, + .formats = formats_for_vop3_esmart, + .nformats = ARRAY_SIZE(formats_for_vop3_esmart), + .format_modifiers = format_modifiers, + .base = 0x0, + .layer_sel_id = { 2, 0xff, 0, 0xff }, + .supported_rotations = DRM_MODE_REFLECT_Y, + .hsu_filter_mode = VOP2_SCALE_UP_BIC, + .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .vsu_filter_mode = VOP2_SCALE_UP_BIL, + .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ + .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ + .regs = &rk3568_esmart_win_data, + .area = rk3568_area_data, + .area_size = ARRAY_SIZE(rk3568_area_data), + .pd_id = VOP2_PD_ESMART, + .type = DRM_PLANE_TYPE_PRIMARY, + .axi_id = 0, + .axi_yrgb_id = 0x0a, + .axi_uv_id = 0x0b, + .possible_crtcs = 0x5,/* vp0 or vp2 */ + .max_upscale_factor = 8, + .max_downscale_factor = 8, + .feature = WIN_FEATURE_MULTI_AREA | WIN_FEATURE_Y2R_13BIT_DEPTH, + }, + + { + .name = "Esmart1-win0", + .phys_id = ROCKCHIP_VOP2_ESMART1, + .formats = formats_for_vop3_esmart, + .nformats = ARRAY_SIZE(formats_for_vop3_esmart), + .format_modifiers = format_modifiers, + .base = 0x200, + .layer_sel_id = { 0xff, 2, 1, 0xff }, + .supported_rotations = DRM_MODE_REFLECT_Y, + .hsu_filter_mode = VOP2_SCALE_UP_BIC, + .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .vsu_filter_mode = VOP2_SCALE_UP_BIL, + .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ + .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ + .regs = &rk3568_esmart_win_data, + .area = rk3568_area_data, + .area_size = ARRAY_SIZE(rk3568_area_data), + .pd_id = VOP2_PD_ESMART, + .type = DRM_PLANE_TYPE_PRIMARY, + .axi_id = 0, + .axi_yrgb_id = 0x0c, + .axi_uv_id = 0x0d, + .possible_crtcs = 0x6,/* vp1 or vp2 */ + .max_upscale_factor = 8, + .max_downscale_factor = 8, + .feature = WIN_FEATURE_MULTI_AREA, + }, + + { + .name = "Esmart2-win0", + .phys_id = ROCKCHIP_VOP2_ESMART2, + .base = 0x400, + .formats = formats_for_vop3_esmart, + .nformats = ARRAY_SIZE(formats_for_vop3_esmart), + .format_modifiers = format_modifiers, + .layer_sel_id = { 3, 0xff, 2, 0xff }, + .supported_rotations = DRM_MODE_REFLECT_Y, + .hsu_filter_mode = VOP2_SCALE_UP_BIC, + .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .vsu_filter_mode = VOP2_SCALE_UP_BIL, + .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ + .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ + .regs = &rk3568_esmart_win_data, + .area = rk3568_area_data, + .area_size = ARRAY_SIZE(rk3568_area_data), + .pd_id = VOP2_PD_ESMART, + .type = DRM_PLANE_TYPE_PRIMARY, + .axi_id = 0, + .axi_yrgb_id = 0x0a, + .axi_uv_id = 0x0b, + .possible_crtcs = 0x5,/* vp0 or vp2 */ + .max_upscale_factor = 8, + .max_downscale_factor = 8, + .feature = WIN_FEATURE_MULTI_AREA, + }, + + { + .name = "Esmart3-win0", + .phys_id = ROCKCHIP_VOP2_ESMART3, + .formats = formats_for_vop3_esmart, + .nformats = ARRAY_SIZE(formats_for_vop3_esmart), + .format_modifiers = format_modifiers, + .base = 0x600, + .layer_sel_id = { 0xff, 3, 3, 0xff }, + .supported_rotations = DRM_MODE_REFLECT_Y, + .hsu_filter_mode = VOP2_SCALE_UP_BIC, + .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .vsu_filter_mode = VOP2_SCALE_UP_BIL, + .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ + .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_GT,/* gt only */ + .regs = &rk3568_esmart_win_data, + .area = rk3568_area_data, + .area_size = ARRAY_SIZE(rk3568_area_data), + .pd_id = VOP2_PD_ESMART, + .type = DRM_PLANE_TYPE_OVERLAY, + .axi_id = 0, + .axi_yrgb_id = 0x0c, + .axi_uv_id = 0x0d, + .possible_crtcs = 0x6,/* vp1 or vp2 */ + .max_upscale_factor = 8, + .max_downscale_factor = 8, + .feature = WIN_FEATURE_MULTI_AREA, + }, + + { + .name = "Cluster0-win0", + .phys_id = ROCKCHIP_VOP2_CLUSTER0, + .base = 0x00, + .formats = formats_for_vop3_cluster, + .nformats = ARRAY_SIZE(formats_for_vop3_cluster), + .format_modifiers = format_modifiers_afbc_tiled_for_vop3, + .layer_sel_id = { 0, 0, 0xff, 0xff }, + .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, + .hsu_filter_mode = VOP2_SCALE_UP_BIL, + .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .vsu_filter_mode = VOP2_SCALE_UP_BIL, + .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ + .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ + .regs = &rk3576_cluster0_win_data, + .pd_id = VOP2_PD_CLUSTER, + .axi_yrgb_id = 0x02, + .axi_uv_id = 0x03, + .possible_crtcs = 0x3,/* vp0 or vp1 */ + .max_upscale_factor = 8, + .max_downscale_factor = 8, + .type = DRM_PLANE_TYPE_OVERLAY, + .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | + WIN_FEATURE_Y2R_13BIT_DEPTH | WIN_FEATURE_DCI, + }, + + { + .name = "Cluster0-win1", + .phys_id = ROCKCHIP_VOP2_CLUSTER0, + .base = 0x80, + .layer_sel_id = { 0, 0, 0xff, 0xff }, + .formats = formats_for_cluster, + .nformats = ARRAY_SIZE(formats_for_cluster), + .format_modifiers = format_modifiers_afbc_tiled_for_vop3, + .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, + .hsu_filter_mode = VOP2_SCALE_UP_BIL, + .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .vsu_filter_mode = VOP2_SCALE_UP_BIL, + .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ + .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ + .regs = &rk3576_cluster0_win_data, + .axi_yrgb_id = 0x04, + .axi_uv_id = 0x05, + .possible_crtcs = 0x3,/* vp0 or vp1 */ + .max_upscale_factor = 8, + .max_downscale_factor = 8, + .type = DRM_PLANE_TYPE_OVERLAY, + .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_SUB, + }, + + { + .name = "Cluster1-win0", + .phys_id = ROCKCHIP_VOP2_CLUSTER1, + .base = 0x00, + .formats = formats_for_vop3_cluster, + .nformats = ARRAY_SIZE(formats_for_vop3_cluster), + .format_modifiers = format_modifiers_afbc_tiled_for_vop3, + .layer_sel_id = { 1, 1, 0xff, 0xff }, + .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, + .hsu_filter_mode = VOP2_SCALE_UP_BIL, + .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .vsu_filter_mode = VOP2_SCALE_UP_BIL, + .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ + .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ + .regs = &rk3576_cluster1_win_data, + .pd_id = VOP2_PD_CLUSTER, + .axi_yrgb_id = 0x06, + .axi_uv_id = 0x07, + .possible_crtcs = 0x3,/* vp0 or vp1 */ + .max_upscale_factor = 8, + .max_downscale_factor = 8, + .type = DRM_PLANE_TYPE_OVERLAY, + .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | WIN_FEATURE_Y2R_13BIT_DEPTH, + }, + + { + .name = "Cluster1-win1", + .phys_id = ROCKCHIP_VOP2_CLUSTER1, + .base = 0x80, + .layer_sel_id = { 1, 1, 0xff, 0xff }, + .formats = formats_for_cluster, + .nformats = ARRAY_SIZE(formats_for_cluster), + .format_modifiers = format_modifiers_afbc_tiled_for_vop3, + .supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, + .hsu_filter_mode = VOP2_SCALE_UP_BIL, + .hsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .vsu_filter_mode = VOP2_SCALE_UP_BIL, + .vsd_filter_mode = VOP2_SCALE_DOWN_BIL, + .hsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ + .vsd_pre_filter_mode = VOP3_PRE_SCALE_DOWN_AVG,/* gt or avg */ + .regs = &rk3576_cluster1_win_data, + .axi_yrgb_id = 0x08, + .axi_uv_id = 0x09, + .possible_crtcs = 0x3,/* vp0 or vp1 */ + .max_upscale_factor = 8, + .max_downscale_factor = 8, + .type = DRM_PLANE_TYPE_OVERLAY, + .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_SUB, + }, +}; + +const struct vop2_power_domain_regs rk3576_cluster_pd_regs = { + .pd = VOP_REG_MASK(RK3576_SYS_CLUSTER_PD_CTRL_IMD, 0x1, 0), + .status = VOP_REG(RK3576_PMU_PWR_GATE_STS, 0x1, 13), + .pmu_status = VOP_REG(RK3576_PMU_BISR_PWR_REPAIR_STATUS0, 0x1, 13), + .bisr_en_status = VOP_REG(RK3576_PMU_BISR_PDGEN_CON0, 0x1, 13), + .otp_bisr_en_status = VOP_REG(RK3576_SYS_GRF_MEMFAULT_STATUS0, 0x1, 13), +}; + +const struct vop2_power_domain_regs rk3576_esmart_pd_regs = { + .pd = VOP_REG_MASK(RK3568_SYS_PD_CTRL, 0x1, 0), + .status = VOP_REG(RK3576_PMU_PWR_GATE_STS, 0x1, 12), + .pmu_status = VOP_REG(RK3576_PMU_BISR_PWR_REPAIR_STATUS0, 0x1, 12), + .bisr_en_status = VOP_REG(RK3576_PMU_BISR_PDGEN_CON0, 0x1, 12), + .otp_bisr_en_status = VOP_REG(RK3576_SYS_GRF_MEMFAULT_STATUS0, 0x1, 12), +}; + +/* + * There are 2 internal power domains on rk3576 vop, + * + * Cluster0/1 share one pd VOP2_PD_CLUSTER. + * + * Esmart0/1/2/3 share one pd VOP2_PD_ESMART. + */ +static const struct vop2_power_domain_data rk3576_vop_pd_data[] = { + { + .id = VOP2_PD_CLUSTER, + .module_id_mask = BIT(ROCKCHIP_VOP2_CLUSTER0) | BIT(ROCKCHIP_VOP2_CLUSTER1), + .regs = &rk3576_cluster_pd_regs, + }, + + { + .id = VOP2_PD_ESMART, + .module_id_mask = BIT(ROCKCHIP_VOP2_ESMART0) | BIT(ROCKCHIP_VOP2_ESMART1) | + BIT(ROCKCHIP_VOP2_ESMART2) | BIT(ROCKCHIP_VOP2_ESMART3), + .regs = &rk3576_esmart_pd_regs, + }, +}; + const struct vop2_power_domain_regs rk3588_cluster0_pd_regs = { .pd = VOP_REG(RK3568_SYS_PD_CTRL, 0x1, 0), .status = VOP_REG(RK3568_SYS_STATUS0, 0x1, 8), @@ -3533,6 +4452,125 @@ static const struct vop2_ctrl rk3568_vop_ctrl = { .otp_en = VOP_REG(RK3568_OTP_WIN_EN, 0x1, 0), }; +static const struct vop_grf_ctrl rk3576_ioc_grf_ctrl = { + .grf_bt656_clk_inv = VOP_REG(RK3576_VCCIO_IOC_MISC_CON8, 0x1, 9), + .grf_bt1120_clk_inv = VOP_REG(RK3576_VCCIO_IOC_MISC_CON8, 0x1, 9), + .grf_dclk_inv = VOP_REG(RK3576_VCCIO_IOC_MISC_CON8, 0x1, 9), +}; + +static const struct vop2_ctrl rk3576_vop_ctrl = { + .cfg_done_en = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 15), + .wb_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 14), + .auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 31), + .aclk_pre_auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 7), + .version = VOP_REG(RK3568_VERSION_INFO, 0xffff, 16), + .lut_dma_en = VOP_REG(RK3568_SYS_AXI_LUT_CTRL, 0x1, 0), + .dsp_vs_t_sel = VOP_REG(RK3576_SYS_PORT_CTRL_IMD, 0x1, 4), + .rkmmu_v2_en = VOP_REG_MASK(RK3576_SYS_MMU_CTRL_IMD, 0x1, 0), + .rkmmu_v2_sel_axi = VOP_REG_MASK(RK3576_SYS_MMU_CTRL_IMD, 0x1, 1), + + /* MIPI DSI0 */ + .mipi0_en = VOP_REG(RK3576_MIPI0_IF_CTRL, 0x1, 0), + .mipi0_dclk_out_en = VOP_REG(RK3576_MIPI0_IF_CTRL, 0x1, 1), + .mipi0_mux = VOP_REG(RK3576_MIPI0_IF_CTRL, 0x3, 2), + .mipi_pin_pol = VOP_REG(RK3576_MIPI0_IF_CTRL, 0x3, 4), + .mipi_dual_en = VOP_REG(RK3576_MIPI0_IF_CTRL, 0x1, 8), + .mipi0_data1_sel = VOP_REG(RK3576_MIPI0_IF_CTRL, 0x1, 9), + .mipi0_ds_mode = VOP_REG(RK3576_MIPI0_IF_CTRL, 0x1, 11), + .mipi0_regdone_imd_en = VOP_REG(RK3576_MIPI0_IF_CTRL, 0x1, 31), + .mipi0_pixclk_div = VOP_REG(RK3576_MIPI0_IF_CTRL, 0x1, 20), + .mipi0_dclk_sel = VOP_REG(RK3576_MIPI0_IF_CTRL, 0x1, 21), + + /* HDMI0 */ + .hdmi0_en = VOP_REG(RK3576_HDMI0_IF_CTRL, 0x1, 0), + .hdmi0_dclk_out_en = VOP_REG(RK3576_HDMI0_IF_CTRL, 0x1, 1), + .hdmi0_mux = VOP_REG(RK3576_HDMI0_IF_CTRL, 0x3, 2), + .hdmi_pin_pol = VOP_REG(RK3576_HDMI0_IF_CTRL, 0x3, 4), + .hdmi_dual_en = VOP_REG(RK3576_HDMI0_IF_CTRL, 0x1, 8), + .hdmi0_data1_sel = VOP_REG(RK3576_HDMI0_IF_CTRL, 0x1, 9), + .hdmi0_r2y_en = VOP_REG(RK3576_HDMI0_IF_CTRL, 0x1, 12), + .hdmi0_r2y_mode = VOP_REG(RK3576_HDMI0_IF_CTRL, 0x3, 14), + .hdmi0_regdone_imd_en = VOP_REG(RK3576_HDMI0_IF_CTRL, 0x1, 31), + .hdmi0_pixclk_div = VOP_REG(RK3576_HDMI0_IF_CTRL, 0x1, 20), + .hdmi0_dclk_sel = VOP_REG(RK3576_HDMI0_IF_CTRL, 0x1, 21), + + /* eDP0 */ + .edp0_en = VOP_REG(RK3576_EDP0_IF_CTRL, 0x1, 0), + .edp0_dclk_out_en = VOP_REG(RK3576_EDP0_IF_CTRL, 0x1, 1), + .edp0_mux = VOP_REG(RK3576_EDP0_IF_CTRL, 0x3, 2), + .edp_pin_pol = VOP_REG(RK3576_EDP0_IF_CTRL, 0x3, 4), + .edp_dual_en = VOP_REG(RK3576_EDP0_IF_CTRL, 0x1, 8), + .edp0_data1_sel = VOP_REG(RK3576_EDP0_IF_CTRL, 0x1, 9), + .edp0_regdone_imd_en = VOP_REG(RK3576_EDP0_IF_CTRL, 0x1, 31), + .edp0_pixclk_div = VOP_REG(RK3576_EDP0_IF_CTRL, 0x1, 20),/* pixel clk sel, 0: dclk, 1: port0_dclk */ + .edp0_dclk_sel = VOP_REG(RK3576_EDP0_IF_CTRL, 0x1, 21),/*0: dclk_core, 1: dclk_out */ + + /* DP0 */ + .dp0_en = VOP_REG(RK3576_DP0_IF_CTRL, 0x1, 0), + .dp0_dclk_out_en = VOP_REG(RK3576_DP0_IF_CTRL, 0x1, 1), + .dp0_mux = VOP_REG(RK3576_DP0_IF_CTRL, 0x3, 2), + .dp0_pin_pol = VOP_REG(RK3576_DP0_IF_CTRL, 0x3, 4), + .dp_dual_en = VOP_REG(RK3576_DP0_IF_CTRL, 0x1, 8), + .dp0_data1_sel = VOP_REG(RK3576_DP0_IF_CTRL, 0x1, 9), + .dp0_regdone_imd_en = VOP_REG(RK3576_DP0_IF_CTRL, 0x1, 31), + .dp0_pixclk_div = VOP_REG(RK3576_DP0_IF_CTRL, 0x1, 20), + .dp0_dclk_sel = VOP_REG(RK3576_DP0_IF_CTRL, 0x1, 21), + + /* DP1 */ + .dp1_en = VOP_REG(RK3576_DP1_IF_CTRL, 0x1, 0), + .dp1_dclk_out_en = VOP_REG(RK3576_DP1_IF_CTRL, 0x1, 1), + .dp1_mux = VOP_REG(RK3576_DP1_IF_CTRL, 0x3, 2), + .dp1_pin_pol = VOP_REG(RK3576_DP1_IF_CTRL, 0x3, 4), + .dp1_data1_sel = VOP_REG(RK3576_DP1_IF_CTRL, 0x1, 9), + .dp1_regdone_imd_en = VOP_REG(RK3576_DP1_IF_CTRL, 0x1, 31), + .dp1_pixclk_div = VOP_REG(RK3576_DP1_IF_CTRL, 0x1, 20), + .dp1_dclk_sel = VOP_REG(RK3576_DP1_IF_CTRL, 0x1, 21), + + /* DP2 */ + .dp2_en = VOP_REG(RK3576_DP2_IF_CTRL, 0x1, 0), + .dp2_dclk_out_en = VOP_REG(RK3576_DP2_IF_CTRL, 0x1, 1), + .dp2_mux = VOP_REG(RK3576_DP2_IF_CTRL, 0x3, 2), + .dp2_pin_pol = VOP_REG(RK3576_DP2_IF_CTRL, 0x3, 4), + .dp2_data1_sel = VOP_REG(RK3576_DP2_IF_CTRL, 0x1, 9), + .dp2_regdone_imd_en = VOP_REG(RK3576_DP2_IF_CTRL, 0x1, 31), + .dp2_pixclk_div = VOP_REG(RK3576_DP2_IF_CTRL, 0x1, 20), + .dp2_dclk_sel = VOP_REG(RK3576_DP2_IF_CTRL, 0x1, 21), + + /* RGB */ + .rgb_en = VOP_REG(RK3576_RGB_IF_CTRL, 0x1, 0), + .rgb_dclk_out_en = VOP_REG(RK3576_RGB_IF_CTRL, 0x1, 1), + .rgb_mux = VOP_REG(RK3576_RGB_IF_CTRL, 0x3, 2), + .rgb_pin_pol = VOP_REG(RK3576_RGB_IF_CTRL, 0x7, 4), + .rgb_dual_en = VOP_REG(RK3576_RGB_IF_CTRL, 0x1, 8), + .rgb_data1_sel = VOP_REG(RK3576_RGB_IF_CTRL, 0x1, 9), + .bt656_en = VOP_REG(RK3576_RGB_IF_CTRL, 0x1, 12), + .bt656_yc_swap = VOP_REG(RK3576_RGB_IF_CTRL, 0x1, 14), + .bt1120_en = VOP_REG(RK3576_RGB_IF_CTRL, 0x1, 16), + .bt1120_yc_swap = VOP_REG(RK3576_RGB_IF_CTRL, 0x1, 18), + .rgb_regdone_imd_en = VOP_REG(RK3576_RGB_IF_CTRL, 0x1, 31), + .rgb_dclk_sel = VOP_REG(RK3576_RGB_IF_CTRL, 0x1, 21), + + .gamma_port_sel = VOP_REG_MASK(RK3568_LUT_PORT_SEL, 0x3, 12), + .esmart_lb_mode = VOP_REG(RK3568_SYS_PD_CTRL, 0x3, 6), + .vp_intr_merge_en = VOP_REG_MASK(RK3576_SYS_PORT_CTRL_IMD, 0x1, 14), + .win_vp_id[ROCKCHIP_VOP2_CLUSTER0] = VOP_REG(RK3576_CLUSTER0_PORT_SEL_IMD, 0x3, 0), + .win_vp_id[ROCKCHIP_VOP2_CLUSTER1] = VOP_REG(RK3576_CLUSTER1_PORT_SEL_IMD, 0x3, 0), + .win_vp_id[ROCKCHIP_VOP2_ESMART0] = VOP_REG(RK3576_ESMART0_PORT_SEL_IMD, 0x3, 0), + .win_vp_id[ROCKCHIP_VOP2_ESMART1] = VOP_REG(RK3576_ESMART1_PORT_SEL_IMD, 0x3, 0), + .win_vp_id[ROCKCHIP_VOP2_ESMART2] = VOP_REG(RK3576_ESMART2_PORT_SEL_IMD, 0x3, 0), + .win_vp_id[ROCKCHIP_VOP2_ESMART3] = VOP_REG(RK3576_ESMART3_PORT_SEL_IMD, 0x3, 0), + .win_dly[ROCKCHIP_VOP2_CLUSTER0] = VOP_REG(RK3576_CLUSTER0_DLY_NUM, 0xffff, 0), + .win_dly[ROCKCHIP_VOP2_CLUSTER1] = VOP_REG(RK3576_CLUSTER1_DLY_NUM, 0xffff, 0), + .win_dly[ROCKCHIP_VOP2_ESMART0] = VOP_REG(RK3576_ESMART0_DLY_NUM, 0xff, 0), + .win_dly[ROCKCHIP_VOP2_ESMART1] = VOP_REG(RK3576_ESMART1_DLY_NUM, 0xff, 0), + .win_dly[ROCKCHIP_VOP2_ESMART2] = VOP_REG(RK3576_ESMART2_DLY_NUM, 0xff, 0), + .win_dly[ROCKCHIP_VOP2_ESMART3] = VOP_REG(RK3576_ESMART3_DLY_NUM, 0xff, 0), + .win_alpha_map[ROCKCHIP_VOP2_ESMART0] = VOP_REG(RK3576_ESMART0_ALPHA_MAP, 0xffffffff, 0), + .win_alpha_map[ROCKCHIP_VOP2_ESMART1] = VOP_REG(RK3576_ESMART1_ALPHA_MAP, 0xffffffff, 0), + .win_alpha_map[ROCKCHIP_VOP2_ESMART2] = VOP_REG(RK3576_ESMART2_ALPHA_MAP, 0xffffffff, 0), + .win_alpha_map[ROCKCHIP_VOP2_ESMART3] = VOP_REG(RK3576_ESMART3_ALPHA_MAP, 0xffffffff, 0), +}; + static const struct vop_grf_ctrl rk3588_sys_grf_ctrl = { .grf_bt656_clk_inv = VOP_REG(RK3588_GRF_SOC_CON1, 0x1, 14), .grf_bt1120_clk_inv = VOP_REG(RK3588_GRF_SOC_CON1, 0x1, 14), @@ -3679,6 +4717,24 @@ static const struct vop_dump_regs rk3568_dump_regs[] = { { RK3568_HDR_LUT_CTRL, "HDR", {0}, 0 }, }; +static const struct vop_dump_regs rk3576_dump_regs[] = { + { RK3568_REG_CFG_DONE, "SYS", {0}, 0, 0x200 }, + { RK3528_OVL_SYS, "OVL_SYS", {0}, 0, 0x50 }, + { RK3528_OVL_PORT0_CTRL, "OVL_VP0", VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 31), 0, 0x80 }, + { RK3528_OVL_PORT1_CTRL, "OVL_VP1", VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 31), 0, 0x80 }, + { RK3576_OVL_PORT2_CTRL, "OVL_VP2", VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 31), 0, 0x80 }, + { RK3568_VP0_DSP_CTRL, "VP0", VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 31), 0, 0x100 }, + { RK3568_VP1_DSP_CTRL, "VP1", VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 31), 0, 0x100 }, + { RK3568_VP2_DSP_CTRL, "VP2", VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 31), 0, 0x100 }, + { RK3568_CLUSTER0_WIN0_CTRL0, "Cluster0", VOP_REG(RK3568_CLUSTER0_WIN0_CTRL0, 0x1, 0), 1, 0x200 }, + { RK3568_CLUSTER1_WIN0_CTRL0, "Cluster1", VOP_REG(RK3568_CLUSTER1_WIN0_CTRL0, 0x1, 0), 1, 0x200 }, + { RK3568_ESMART0_CTRL0, "Esmart0", VOP_REG(RK3568_ESMART0_REGION0_CTRL, 0x1, 0), 1, 0x100 }, + { RK3568_ESMART1_CTRL0, "Esmart1", VOP_REG(RK3568_ESMART1_REGION0_CTRL, 0x1, 0), 1, 0x100 }, + { RK3568_SMART0_CTRL0, "Esmart2", VOP_REG(RK3568_SMART0_REGION0_CTRL, 0x1, 0), 1, 0x100 }, + { RK3568_SMART1_CTRL0, "Esmart3", VOP_REG(RK3568_SMART1_REGION0_CTRL, 0x1, 0), 1, 0x100 }, + { RK3528_HDR_LUT_CTRL, "HDR", {0}, 0, 0x100 }, +}; + static const struct vop_dump_regs rk3588_dump_regs[] = { { RK3568_REG_CFG_DONE, "SYS", {0}, 0 }, { RK3568_OVL_CTRL, "OVL", {0}, 0 }, @@ -3864,6 +4920,11 @@ static struct vop2_vp_plane_mask rk3588_vp_plane_mask[ROCKCHIP_MAX_CRTC][ROCKCHI }; +static const struct vop2_esmart_lb_map rk3576_esmart_lb_mode_map[] = { + {VOP3_ESMART_4K_4K_4K_MODE, 2}, + {VOP3_ESMART_4K_4K_2K_2K_MODE, 3} +}; + static const struct vop2_data rk3528_vop = { .version = VOP_VERSION_RK3528, .nr_vps = 2, @@ -3928,6 +4989,31 @@ static const struct vop2_data rk3568_vop = { .plane_mask_base = RK3568_PLANE_MASK_BASE, }; +static const struct vop2_data rk3576_vop = { + .version = VOP_VERSION_RK3576, + .nr_vps = 3, + .nr_mixers = 4, + .nr_layers = 4, + .nr_gammas = 3, + .esmart_lb_mode = VOP3_ESMART_4K_4K_2K_2K_MODE, + .esmart_lb_mode_num = ARRAY_SIZE(rk3576_esmart_lb_mode_map), + .esmart_lb_mode_map = rk3576_esmart_lb_mode_map, + .max_input = { 4096, 4096 }, + .max_output = { 4096, 4096 }, + .ioc_grf = &rk3576_ioc_grf_ctrl, + .ctrl = &rk3576_vop_ctrl, + .axi_intr = rk3576_vop_axi_intr, + .nr_axi_intr = ARRAY_SIZE(rk3576_vop_axi_intr), + .vp = rk3576_vop_video_ports, + .wb = &rk3576_vop_wb_data, + .win = rk3576_vop_win_data, + .win_size = ARRAY_SIZE(rk3576_vop_win_data), + .pd = rk3576_vop_pd_data, + .nr_pds = ARRAY_SIZE(rk3576_vop_pd_data), + .dump_regs = rk3576_dump_regs, + .dump_regs_size = ARRAY_SIZE(rk3576_dump_regs), +}; + static const struct vop2_data rk3588_vop = { .version = VOP_VERSION_RK3588, .feature = VOP_FEATURE_SPLICE, @@ -3973,6 +5059,8 @@ static const struct of_device_id vop2_dt_match[] = { .data = &rk3562_vop }, { .compatible = "rockchip,rk3568-vop", .data = &rk3568_vop }, + { .compatible = "rockchip,rk3576-vop", + .data = &rk3576_vop }, { .compatible = "rockchip,rk3588-vop", .data = &rk3588_vop }, diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h index a917bb9608d0..498e0edbe131 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h @@ -1050,9 +1050,12 @@ #define RK3568_VOP2_GLB_CFG_DONE_EN BIT(15) #define RK3568_VERSION_INFO 0x004 #define RK3568_SYS_AUTO_GATING_CTRL 0x008 +#define RK3576_SYS_MMU_CTRL_IMD 0x020 #define RK3568_SYS_AXI_LUT_CTRL 0x024 #define RK3568_DSP_IF_EN 0x028 +#define RK3576_SYS_PORT_CTRL_IMD 0x028 #define RK3568_DSP_IF_CTRL 0x02c +#define RK3576_SYS_CLUSTER_PD_CTRL_IMD 0x030 #define RK3568_DSP_IF_POL 0x030 #define RK3568_SYS_PD_CTRL 0x034 #define RK3588_SYS_VAR_FREQ_CTRL 0x038 @@ -1091,6 +1094,19 @@ #define RK3588_VP3_INT_EN 0xD0 #define RK3588_VP3_INT_CLR 0xD4 #define RK3588_VP3_INT_STATUS 0xD8 +#define RK3576_WB_CTRL 0x100 +#define RK3576_WB_XSCAL_FACTOR 0x104 +#define RK3576_WB_YRGB_MST 0x108 +#define RK3576_WB_CBR_MST 0x10C +#define RK3576_WB_VIR_STRIDE 0x110 +#define RK3576_WB_TIMEOUT_CTRL 0x114 +#define RK3576_MIPI0_IF_CTRL 0x180 +#define RK3576_HDMI0_IF_CTRL 0x184 +#define RK3576_EDP0_IF_CTRL 0x188 +#define RK3576_DP0_IF_CTRL 0x18C +#define RK3576_RGB_IF_CTRL 0x194 +#define RK3576_DP1_IF_CTRL 0x1A4 +#define RK3576_DP2_IF_CTRL 0x1B0 #define RK3588_DSC_8K_SYS_CTRL 0x200 #define RK3588_DSC_8K_RST 0x204 @@ -1202,6 +1218,8 @@ #define RK3568_VP2_BCSH_BCS 0xE64 #define RK3568_VP2_BCSH_H 0xE68 #define RK3568_VP2_BCSH_COLOR_BAR 0xE6C +#define RK3576_VP2_MCU_CTRL 0xEF8 +#define RK3576_VP2_MCU_RW_BYPASS_PORT 0xEFC #define RK3588_VP3_DSP_CTRL 0xF00 #define RK3588_VP3_DUAL_CHANNEL_CTRL 0xF04 @@ -1238,6 +1256,10 @@ #define RK3528_CLUSTER0_MIX_DST_COLOR_CTRL 0x534 #define RK3528_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x538 #define RK3528_CLUSTER0_MIX_DST_ALPHA_CTRL 0x53c +#define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL 0x540 +#define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL 0x544 +#define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL 0x548 +#define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL 0x54c #define RK3528_OVL_PORT0_CTRL 0x600 #define RK3528_OVL_PORT0_LAYER_SEL 0x604 #define RK3528_OVL_PORT0_MIX0_SRC_COLOR_CTRL 0x620 @@ -1252,6 +1274,10 @@ #define RK3528_OVL_PORT0_MIX2_DST_COLOR_CTRL 0x644 #define RK3528_OVL_PORT0_MIX2_SRC_ALPHA_CTRL 0x648 #define RK3528_OVL_PORT0_MIX2_DST_ALPHA_CTRL 0x64C +#define RK3576_EXTRA_SRC_COLOR_CTRL 0x650 +#define RK3576_EXTRA_DST_COLOR_CTRL 0x654 +#define RK3576_EXTRA_SRC_ALPHA_CTRL 0x658 +#define RK3576_EXTRA_DST_ALPHA_CTRL 0x65C #define RK3528_HDR_SRC_COLOR_CTRL 0x660 #define RK3528_HDR_DST_COLOR_CTRL 0x664 #define RK3528_HDR_SRC_ALPHA_CTRL 0x668 @@ -1272,6 +1298,13 @@ #define RK3528_OVL_PORT1_MIX2_SRC_ALPHA_CTRL 0x748 #define RK3528_OVL_PORT1_MIX2_DST_ALPHA_CTRL 0x74C #define RK3528_OVL_PORT1_BG_MIX_CTRL 0x770 +#define RK3576_OVL_PORT2_CTRL 0x800 +#define RK3576_OVL_PORT2_LAYER_SEL 0x804 +#define RK3576_OVL_PORT2_MIX0_SRC_COLOR_CTRL 0x820 +#define RK3576_OVL_PORT2_MIX0_DST_COLOR_CTRL 0x824 +#define RK3576_OVL_PORT2_MIX0_SRC_ALPHA_CTRL 0x828 +#define RK3576_OVL_PORT2_MIX0_DST_ALPHA_CTRL 0x82C +#define RK3576_OVL_PORT2_BG_MIX_CTRL 0x870 /* Overlay registers definition */ #define RK3568_OVL_CTRL 0x600 @@ -1327,6 +1360,8 @@ #define RK3568_CLUSTER0_WIN0_DSP_ST 0x1028 #define RK3568_CLUSTER0_WIN0_SCL_FACTOR_YRGB 0x1030 #define RK3568_CLUSTER0_WIN0_AFBCD_TRANSFORM_OFFSET 0x103C +#define RK3576_CLUSTER0_WIN0_ZME_CTRL 0x1040 +#define RK3576_CLUSTER0_WIN0_ZME_DERING_PARA 0x1044 #define RK3568_CLUSTER0_WIN0_AFBCD_OUTPUT_CTRL 0x1050 #define RK3568_CLUSTER0_WIN0_AFBCD_ROTATE_MODE 0x1054 #define RK3568_CLUSTER0_WIN0_AFBCD_HDR_PTR 0x1058 @@ -1335,6 +1370,8 @@ #define RK3568_CLUSTER0_WIN0_AFBCD_PIC_OFFSET 0x1064 #define RK3568_CLUSTER0_WIN0_AFBCD_DSP_OFFSET 0x1068 #define RK3568_CLUSTER0_WIN0_AFBCD_CTRL 0x106C +#define RK3576_CLUSTER0_WIN0_PLD_PTR_OFFSET 0x1078 +#define RK3576_CLUSTER0_WIN0_PLD_PTR_RANGE 0x107C #define RK3568_CLUSTER0_WIN1_CTRL0 0x1080 #define RK3568_CLUSTER0_WIN1_CTRL1 0x1084 @@ -1355,8 +1392,12 @@ #define RK3568_CLUSTER0_WIN1_AFBCD_PIC_OFFSET 0x10E4 #define RK3568_CLUSTER0_WIN1_AFBCD_DSP_OFFSET 0x10E8 #define RK3568_CLUSTER0_WIN1_AFBCD_CTRL 0x10EC +#define RK3576_CLUSTER0_WIN1_PLD_PTR_OFFSET 0x10F8 +#define RK3576_CLUSTER0_WIN1_PLD_PTR_RANGE 0x10FC #define RK3568_CLUSTER0_CTRL 0x1100 +#define RK3576_CLUSTER0_PORT_SEL_IMD 0x11F4 +#define RK3576_CLUSTER0_DLY_NUM 0x11F8 #define RK3568_CLUSTER1_WIN0_CTRL0 0x1200 #define RK3568_CLUSTER1_WIN0_CTRL1 0x1204 @@ -1369,6 +1410,8 @@ #define RK3568_CLUSTER1_WIN0_DSP_ST 0x1228 #define RK3568_CLUSTER1_WIN0_SCL_FACTOR_YRGB 0x1230 #define RK3568_CLUSTER1_WIN0_AFBCD_TRANSFORM_OFFSET 0x123C +#define RK3576_CLUSTER1_WIN0_ZME_CTRL 0x1240 +#define RK3576_CLUSTER1_WIN0_ZME_DERING_PARA 0x1244 #define RK3568_CLUSTER1_WIN0_AFBCD_OUTPUT_CTRL 0x1250 #define RK3568_CLUSTER1_WIN0_AFBCD_ROTATE_MODE 0x1254 #define RK3568_CLUSTER1_WIN0_AFBCD_HDR_PTR 0x1258 @@ -1377,6 +1420,8 @@ #define RK3568_CLUSTER1_WIN0_AFBCD_PIC_OFFSET 0x1264 #define RK3568_CLUSTER1_WIN0_AFBCD_DSP_OFFSET 0x1268 #define RK3568_CLUSTER1_WIN0_AFBCD_CTRL 0x126C +#define RK3576_CLUSTER1_WIN0_PLD_PTR_OFFSET 0x1278 +#define RK3576_CLUSTER1_WIN0_PLD_PTR_RANGE 0x127C #define RK3568_CLUSTER1_WIN1_CTRL0 0x1280 #define RK3568_CLUSTER1_WIN1_CTRL1 0x1284 @@ -1395,8 +1440,12 @@ #define RK3568_CLUSTER1_WIN1_AFBCD_PIC_OFFSET 0x12E4 #define RK3568_CLUSTER1_WIN1_AFBCD_DSP_OFFSET 0x12E8 #define RK3568_CLUSTER1_WIN1_AFBCD_CTRL 0x12EC +#define RK3576_CLUSTER1_WIN1_PLD_PTR_OFFSET 0x12F8 +#define RK3576_CLUSTER1_WIN1_PLD_PTR_RANGE 0x12FC #define RK3568_CLUSTER1_CTRL 0x1300 +#define RK3576_CLUSTER1_PORT_SEL_IMD 0x13F4 +#define RK3576_CLUSTER1_DLY_NUM 0x13F8 #define RK3588_CLUSTER2_WIN0_CTRL0 0x1400 #define RK3588_CLUSTER2_WIN0_CTRL1 0x1404 @@ -1527,6 +1576,9 @@ #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8 #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC #define RK3568_ESMART0_COLOR_KEY_CTRL 0x18D0 +#define RK3576_ESMART0_ALPHA_MAP 0x18D8 +#define RK3576_ESMART0_PORT_SEL_IMD 0x18F4 +#define RK3576_ESMART0_DLY_NUM 0x18F8 #define RK3568_ESMART1_CTRL0 0x1A00 #define RK3568_ESMART1_CTRL1 0x1A04 @@ -1574,6 +1626,9 @@ #define RK3568_ESMART1_REGION3_SCL_FACTOR_YRGB 0x1AC4 #define RK3568_ESMART1_REGION3_SCL_FACTOR_CBR 0x1AC8 #define RK3568_ESMART1_REGION3_SCL_OFFSET 0x1ACC +#define RK3576_ESMART1_ALPHA_MAP 0x1AD8 +#define RK3576_ESMART1_PORT_SEL_IMD 0x1AF4 +#define RK3576_ESMART1_DLY_NUM 0x1AF8 #define RK3568_SMART0_CTRL0 0x1C00 #define RK3568_SMART0_CTRL1 0x1C04 @@ -1621,6 +1676,9 @@ #define RK3568_SMART0_REGION3_SCL_FACTOR_YRGB 0x1CC4 #define RK3568_SMART0_REGION3_SCL_FACTOR_CBR 0x1CC8 #define RK3568_SMART0_REGION3_SCL_OFFSET 0x1CCC +#define RK3576_ESMART2_ALPHA_MAP 0x1CD8 +#define RK3576_ESMART2_PORT_SEL_IMD 0x1CF4 +#define RK3576_ESMART2_DLY_NUM 0x1CF8 #define RK3568_SMART1_CTRL0 0x1E00 #define RK3568_SMART1_CTRL1 0x1E04 @@ -1668,6 +1726,9 @@ #define RK3568_SMART1_REGION3_SCL_FACTOR_YRGB 0x1EC4 #define RK3568_SMART1_REGION3_SCL_FACTOR_CBR 0x1EC8 #define RK3568_SMART1_REGION3_SCL_OFFSET 0x1ECC +#define RK3576_ESMART3_ALPHA_MAP 0x1ED8 +#define RK3576_ESMART3_PORT_SEL_IMD 0x1EF4 +#define RK3576_ESMART3_DLY_NUM 0x1EF8 /* HDR register definition */ #define RK3568_HDR_LUT_CTRL 0x2000 @@ -1700,11 +1761,21 @@ #define RK3588_DSC_4K_STS0 0x41A8 #define RK3588_DSC_4K_ERS 0x41C4 +/* Base SYS_GRF: 0x2600a000 */ +#define RK3576_SYS_GRF_MEMFAULT_STATUS0 0x0148 + +/* Base IOC_GRF: 0x26040000 */ +#define RK3576_VCCIO_IOC_MISC_CON8 0x6420 + +/* Base PMU2: 0x27380000 */ +#define RK3576_PMU_PWR_GATE_STS 0x0230 +#define RK3576_PMU_BISR_PDGEN_CON0 0x0510 +#define RK3576_PMU_BISR_PWR_REPAIR_STATUS0 0x0570 + #define RK3588_GRF_SOC_CON1 0x0304 #define RK3588_GRF_VOP_CON2 0x08 #define RK3588_GRF_VO1_CON0 0x00 - #define RK3588_PMU_PWR_GATE_CON1 0x150 #define RK3588_PMU_SUBMEM_PWR_GATE_CON1 0x1B4 #define RK3588_PMU_SUBMEM_PWR_GATE_CON2 0x1B8