diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index 2bccc818a6..e236e08806 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -185,6 +185,7 @@ enum sde_cp_crtc_features { enum sde_cp_crtc_pu_features { SDE_CP_CRTC_DSPP_RC_PU, + SDE_CP_CRTC_DSPP_SPR_PU, SDE_CP_CRTC_MAX_PU_FEATURES, }; @@ -814,6 +815,45 @@ static int check_rc_pu_feature(struct sde_hw_dspp *hw_dspp, return ret; } +static int set_spr_pu_feature(struct sde_hw_dspp *hw_dspp, + struct sde_hw_cp_cfg *hw_cfg, struct sde_crtc *sde_crtc) +{ + if (!hw_dspp || !hw_cfg || !sde_crtc) { + DRM_ERROR("invalid argumets\n"); + return -EINVAL; + } + + if (hw_dspp->ops.setup_spr_pu_config) + hw_dspp->ops.setup_spr_pu_config(hw_dspp, hw_cfg); + + return 0; +} + +static int check_spr_pu_feature(struct sde_hw_dspp *hw_dspp, + struct sde_hw_cp_cfg *hw_cfg, struct sde_crtc *sde_crtc) +{ + struct msm_roi_list *roi_list; + + if (!hw_cfg || hw_cfg->len != sizeof(struct sde_drm_roi_v1)) { + SDE_ERROR("invalid payload\n"); + return -EINVAL; + } + + roi_list = hw_cfg->payload; + if (roi_list->num_rects > 1) { + SDE_ERROR("multiple pu regions not supported with spr\n"); + return -EINVAL; + } + + if ((roi_list->roi[0].x2 - roi_list->roi[0].x1) != hw_cfg->displayh) { + SDE_ERROR("pu region not full width %d\n", + (roi_list->roi[0].x2 - roi_list->roi[0].x1)); + return -EINVAL; + } + + return 0; +} + static int set_spr_init_feature(struct sde_hw_dspp *hw_dspp, struct sde_hw_cp_cfg *hw_cfg, struct sde_crtc *sde_crtc) @@ -825,6 +865,8 @@ static int set_spr_init_feature(struct sde_hw_dspp *hw_dspp, ret = -EINVAL; } else { hw_dspp->ops.setup_spr_init_config(hw_dspp, hw_cfg); + update_pu_feature_enable(sde_crtc, SDE_CP_CRTC_DSPP_SPR_PU, + hw_cfg->payload != NULL); } return ret; @@ -902,6 +944,7 @@ feature_wrapper set_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES]; do { \ memset(wrappers, 0, sizeof(wrappers)); \ wrappers[SDE_CP_CRTC_DSPP_RC_PU] = set_rc_pu_feature; \ + wrappers[SDE_CP_CRTC_DSPP_SPR_PU] = set_spr_pu_feature; \ } while (0) feature_wrapper check_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES]; @@ -909,6 +952,7 @@ feature_wrapper check_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES]; do { \ memset(wrappers, 0, sizeof(wrappers)); \ wrappers[SDE_CP_CRTC_DSPP_RC_PU] = check_rc_pu_feature; \ + wrappers[SDE_CP_CRTC_DSPP_SPR_PU] = check_spr_pu_feature; \ } while (0) #define INIT_PROP_ATTACH(p, crtc, prop, node, feature, val) \ diff --git a/msm/sde/sde_hw_dspp.c b/msm/sde/sde_hw_dspp.c index 5cbc39700f..17649cdf76 100644 --- a/msm/sde/sde_hw_dspp.c +++ b/msm/sde/sde_hw_dspp.c @@ -276,11 +276,25 @@ static void dspp_rc(struct sde_hw_dspp *c) static void dspp_spr(struct sde_hw_dspp *c) { + int ret = 0; + + if (!c) { + SDE_ERROR("invalid arguments\n"); + return; + } + + c->ops.setup_spr_init_config = NULL; + c->ops.setup_spr_pu_config = NULL; + if (c->cap->sblk->spr.version == SDE_COLOR_PROCESS_VER(0x1, 0x0)) { - reg_dmav1_init_dspp_op_v4(SDE_DSPP_SPR, c->idx); + ret = reg_dmav1_init_dspp_op_v4(SDE_DSPP_SPR, c->idx); + if (ret) { + SDE_ERROR("regdma init failed for spr, ret %d\n", ret); + return; + } + c->ops.setup_spr_init_config = reg_dmav1_setup_spr_init_cfgv1; - } else { - c->ops.setup_spr_init_config = NULL; + c->ops.setup_spr_pu_config = reg_dmav1_setup_spr_pu_cfgv1; } } diff --git a/msm/sde/sde_hw_dspp.h b/msm/sde/sde_hw_dspp.h index 885502c8b9..5c204d3f77 100644 --- a/msm/sde/sde_hw_dspp.h +++ b/msm/sde/sde_hw_dspp.h @@ -257,6 +257,12 @@ struct sde_hw_dspp_ops { */ void (*setup_spr_init_config)(struct sde_hw_dspp *ctx, void *cfg); + /** + * setup_spr_pu_config - function to configure spr hw block pu offsets + * @ctx: Pointer to dspp context + * @cfg: Pointer to configuration + */ + void (*setup_spr_pu_config)(struct sde_hw_dspp *ctx, void *cfg); /** * setup_demura_cfg - function to program demura cfg * @ctx: Pointer to dspp context diff --git a/msm/sde/sde_hw_reg_dma_v1.c b/msm/sde/sde_hw_reg_dma_v1.c index 433c3bb7dc..4fbcf7424d 100644 --- a/msm/sde/sde_hw_reg_dma_v1.c +++ b/msm/sde/sde_hw_reg_dma_v1.c @@ -827,6 +827,8 @@ int init_v12(struct sde_hw_reg_dma *cfg) GRP_MDSS_HW_BLK_SELECT); v1_supported[SPR_INIT] = (GRP_DSPP_HW_BLK_SELECT | GRP_MDSS_HW_BLK_SELECT); + v1_supported[SPR_PU_CFG] = (GRP_DSPP_HW_BLK_SELECT | + GRP_MDSS_HW_BLK_SELECT); v1_supported[DEMURA_CFG] = MDSS | DSPP0 | DSPP1; return 0; diff --git a/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/msm/sde/sde_hw_reg_dma_v1_color_proc.c index bf1ed69281..936ac07267 100644 --- a/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -139,6 +139,7 @@ static u32 feature_map[SDE_DSPP_MAX] = { /* MEMCOLOR can be mapped to any MEMC_SKIN/SKY/FOLIAGE/PROT*/ [SDE_DSPP_MEMCOLOR] = MEMC_SKIN, [SDE_DSPP_SIXZONE] = SIX_ZONE, + /* SPR can be mapped to SPR_INIT & SPR_PU_CFG */ [SDE_DSPP_SPR] = SPR_INIT, [SDE_DSPP_DITHER] = REG_DMA_FEATURES_MAX, [SDE_DSPP_HIST] = REG_DMA_FEATURES_MAX, @@ -335,6 +336,16 @@ static int _reg_dma_init_dspp_feature_buf(int feature, enum sde_dspp idx) rc = reg_dma_buf_init( &dspp_buf[MEMC_PROT][idx], feature_reg_dma_sz[feature]); + } else if (feature == SDE_DSPP_SPR) { + rc = reg_dma_buf_init( + &dspp_buf[SPR_INIT][idx], + feature_reg_dma_sz[feature]); + if (rc) + return rc; + + rc = reg_dma_buf_init( + &dspp_buf[SPR_PU_CFG][idx], + feature_reg_dma_sz[feature]); } else { rc = reg_dma_buf_init( &dspp_buf[feature_map[feature]][idx], @@ -4698,6 +4709,72 @@ void reg_dmav1_setup_spr_init_cfgv1(struct sde_hw_dspp *ctx, void *cfg) } } +void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg) +{ + struct sde_reg_dma_setup_ops_cfg dma_write_cfg; + struct sde_hw_cp_cfg *hw_cfg = cfg; + struct sde_reg_dma_kickoff_cfg kick_off; + struct sde_hw_reg_dma_ops *dma_ops; + uint32_t reg, reg_off, base_off; + struct msm_roi_list *roi_list; + int rc = 0; + + rc = reg_dma_dspp_check(ctx, cfg, SPR_PU_CFG); + if (rc) + return; + + if (!hw_cfg->payload || hw_cfg->len != sizeof(struct sde_drm_roi_v1)) { + DRM_ERROR("invalid payload of pu rects\n"); + return; + } + + roi_list = hw_cfg->payload; + if (roi_list->num_rects > 1) { + DRM_ERROR("multiple pu regions not supported with spr\n"); + return; + } + + if ((roi_list->roi[0].x2 - roi_list->roi[0].x1) != hw_cfg->displayh) { + DRM_ERROR("pu region not full width %d\n", + (roi_list->roi[0].x2 - roi_list->roi[0].x1)); + return; + } + + dma_ops = sde_reg_dma_get_ops(); + dma_ops->reset_reg_dma_buf(dspp_buf[SPR_PU_CFG][ctx->idx]); + + REG_DMA_INIT_OPS(dma_write_cfg, MDSS, SPR_PU_CFG, + dspp_buf[SPR_PU_CFG][ctx->idx]); + REG_DMA_SETUP_OPS(dma_write_cfg, 0, NULL, 0, HW_BLK_SELECT, 0, 0, 0); + rc = dma_ops->setup_payload(&dma_write_cfg); + if (rc) { + DRM_ERROR("spr write decode select failed ret %d\n", rc); + return; + } + + base_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base; + reg_off = base_off + 0x20; + reg = APPLY_MASK_AND_SHIFT(roi_list->roi[0].x1, 16, 0) | + APPLY_MASK_AND_SHIFT(roi_list->roi[0].y1, 16, 16); + REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, ®, + sizeof(__u32), REG_SINGLE_WRITE, 0, 0, 0); + + rc = dma_ops->setup_payload(&dma_write_cfg); + if (rc) { + DRM_ERROR("write pu config failed ret %d\n", rc); + return; + } + + REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, + dspp_buf[SPR_PU_CFG][ctx->idx], + REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE); + rc = dma_ops->kick_off(&kick_off); + if (rc) { + DRM_ERROR("failed to kick off ret %d\n", rc); + return; + } +} + static void reg_dma_demura_off(struct sde_hw_dspp *ctx, struct sde_hw_cp_cfg *hw_cfg) { diff --git a/msm/sde/sde_hw_reg_dma_v1_color_proc.h b/msm/sde/sde_hw_reg_dma_v1_color_proc.h index a1be23c4f0..12fbe22883 100644 --- a/msm/sde/sde_hw_reg_dma_v1_color_proc.h +++ b/msm/sde/sde_hw_reg_dma_v1_color_proc.h @@ -295,6 +295,13 @@ void reg_dmav2_setup_vig_gamutv61(struct sde_hw_pipe *ctx, void *cfg); */ void reg_dmav1_setup_spr_init_cfgv1(struct sde_hw_dspp *ctx, void *cfg); +/** + * reg_dmav1_setup_spr_pu_cfgv1 - function to configure spr pu through LUTDMA + * @ctx: Pointer to dspp context + * @cfg: Pointer to configuration + */ +void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg); + /** * reg_dmav1_setup_demurav1() - function to set up the demurav1 configuration. * @ctx: dspp ctx info diff --git a/msm/sde/sde_reg_dma.h b/msm/sde/sde_reg_dma.h index ab705b066b..b86ea34367 100644 --- a/msm/sde/sde_reg_dma.h +++ b/msm/sde/sde_reg_dma.h @@ -55,6 +55,7 @@ enum sde_reg_dma_read_sel { * @HSIC: Hue, saturation and contrast * @GC: gamma correction * @SPR_INIT: Sub pixel rendering init feature + * @SPR_PU: Sub pixel rendering partial update feature * @LTM_INIT: LTM INIT * @LTM_ROI: LTM ROI * @LTM_VLUT: LTM VLUT @@ -76,6 +77,7 @@ enum sde_reg_dma_features { HSIC, GC, SPR_INIT, + SPR_PU_CFG, LTM_INIT, LTM_ROI, LTM_VLUT,