diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index 11ab6d21..e8b0d18a 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -142,6 +142,7 @@ static void _lm_gc_install_property(struct drm_crtc *crtc); enum sde_cp_crtc_pu_features { SDE_CP_CRTC_DSPP_RC_PU, SDE_CP_CRTC_DSPP_SPR_PU, + SDE_CP_CRTC_DSPP_DEMURA_PU, SDE_CP_CRTC_MAX_PU_FEATURES, }; @@ -149,6 +150,10 @@ static enum sde_cp_crtc_pu_features sde_cp_crtc_pu_to_feature[SDE_CP_CRTC_MAX_PU_FEATURES] = { [SDE_CP_CRTC_DSPP_RC_PU] = (enum sde_cp_crtc_pu_features) SDE_CP_CRTC_DSPP_RC_MASK, + [SDE_CP_CRTC_DSPP_SPR_PU] = + (enum sde_cp_crtc_pu_features) SDE_CP_CRTC_DSPP_SPR_INIT, + [SDE_CP_CRTC_DSPP_DEMURA_PU] = + (enum sde_cp_crtc_pu_features) SDE_CP_CRTC_DSPP_DEMURA_INIT, }; /* explicitly set the features that needs to be treated during handoff */ @@ -829,6 +834,20 @@ static int _set_spr_pu_feature(struct sde_hw_dspp *hw_dspp, return 0; } +static int _set_demura_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_demura_pu_config) + hw_dspp->ops.setup_demura_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) { @@ -874,14 +893,17 @@ static int _set_spr_init_feature(struct sde_hw_dspp *hw_dspp, static int _set_demura_feature(struct sde_hw_dspp *hw_dspp, struct sde_hw_cp_cfg *hw_cfg, - struct sde_crtc *hw_crtc) + struct sde_crtc *sde_crtc) { int ret = 0; - if (!hw_dspp || !hw_dspp->ops.setup_demura_cfg) + if (!hw_dspp || !hw_dspp->ops.setup_demura_cfg) { ret = -EINVAL; - else + } else { hw_dspp->ops.setup_demura_cfg(hw_dspp, hw_cfg); + _update_pu_feature_enable(sde_crtc, SDE_CP_CRTC_DSPP_DEMURA_PU, + hw_cfg->payload != NULL); + } return ret; } @@ -945,6 +967,7 @@ 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; \ + wrappers[SDE_CP_CRTC_DSPP_DEMURA_PU] = _set_demura_pu_feature; \ } while (0) feature_wrapper check_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES]; @@ -953,6 +976,7 @@ 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; \ + wrappers[SDE_CP_CRTC_DSPP_DEMURA_PU] = _check_spr_pu_feature; \ } while (0) #define INIT_PROP_ATTACH(p, crtc, prop, node, feature, val) \ @@ -1606,6 +1630,9 @@ static void _sde_cp_crtc_commit_feature(struct sde_cp_node *prop_node, _sde_cp_get_cached_payload(prop_node, &hw_cfg, &feature_enabled); hw_cfg.num_of_mixers = sde_crtc->num_mixers; hw_cfg.last_feature = 0; + hw_cfg.panel_width = sde_crtc->base.state->adjusted_mode.hdisplay; + hw_cfg.panel_height = sde_crtc->base.state->adjusted_mode.vdisplay; + SDE_EVT32(hw_cfg.panel_width, hw_cfg.panel_height); for (i = 0; i < num_mixers; i++) { hw_dspp = sde_crtc->mixers[i].hw_dspp; @@ -1945,23 +1972,23 @@ static int _sde_cp_crtc_update_pu_features(struct drm_crtc *crtc, bool *need_flu DRM_DEBUG_DRIVER("no partial update required\n"); memset(&sde_crtc_state->cached_user_roi_list, 0, sizeof(struct msm_roi_list)); - return 0; - } - - sde_kms_rect_merge_rectangles(&sde_crtc_state->user_roi_list, - &user_rect); - sde_kms_rect_merge_rectangles(&sde_crtc_state->cached_user_roi_list, - &cached_rect); - if (sde_kms_rect_is_equal(&user_rect, &cached_rect)) { - DRM_DEBUG_DRIVER("no change in list of ROIs\n"); - return 0; + } else { + sde_kms_rect_merge_rectangles(&sde_crtc_state->user_roi_list, + &user_rect); + sde_kms_rect_merge_rectangles(&sde_crtc_state->cached_user_roi_list, + &cached_rect); + if (sde_kms_rect_is_equal(&user_rect, &cached_rect)) { + DRM_DEBUG_DRIVER("no change in list of ROIs\n"); + return 0; + } } catalog = get_kms(&sde_crtc->base)->catalog; memset(&hw_cfg, 0, sizeof(hw_cfg)); hw_cfg.num_of_mixers = sde_crtc->num_mixers; hw_cfg.broadcast_disabled = catalog->dma_cfg.broadcast_disabled; - hw_cfg.payload = &sde_crtc_state->user_roi_list; + hw_cfg.payload = (sde_crtc_state->user_roi_list.num_rects) ? + &sde_crtc_state->user_roi_list : NULL; hw_cfg.len = sizeof(sde_crtc_state->user_roi_list); for (i = 0; i < hw_cfg.num_of_mixers; i++) hw_cfg.dspp[i] = sde_crtc->mixers[i].hw_dspp; @@ -2315,6 +2342,7 @@ int sde_cp_crtc_set_property(struct drm_crtc *crtc, prop_node->feature; } cstate->cp_prop_values[prop_node->feature].prop_val = val; + SDE_EVT32(prop_node->feature, val); ret = _sde_cp_crtc_set_range_prop(cstate, prop_node, property, prop_node->feature, val); @@ -2351,6 +2379,7 @@ static int _sde_cp_flush_properties(struct drm_crtc *crtc) cstate->cp_prop_values[feature].prop = 0; cstate->cp_prop_values[feature].cp_node = 0; cstate->cp_prop_values[feature].prop_val = 0; + SDE_EVT32(feature, val); _sde_cp_crtc_cache_property(crtc, cstate, prop_node, property, val); } @@ -2562,6 +2591,50 @@ void sde_cp_crtc_resume(struct drm_crtc *crtc) /* placeholder for operations needed during resume */ } +static void _sde_cp_disable_features(struct sde_crtc *sde_crtc) +{ + struct sde_hw_cp_cfg hw_cfg; + struct sde_hw_mixer *hw_lm; + struct sde_hw_dspp *hw_dspp; + feature_wrapper set_feature; + int i = 0, ret = 0; + u32 num_mixers = sde_crtc->num_mixers; + + set_feature = + set_crtc_feature_wrappers[SDE_CP_CRTC_DSPP_DEMURA_INIT]; + SDE_EVT32(num_mixers); + if (!set_feature) + return; + + memset(&hw_cfg, 0, sizeof(hw_cfg)); + + for (i = 0; i < num_mixers; i++) { + hw_dspp = sde_crtc->mixers[i].hw_dspp; + if (!hw_dspp || i >= DSPP_MAX) + continue; + hw_cfg.dspp[i] = hw_dspp; + } + + hw_cfg.payload = NULL; + for (i = 0; i < num_mixers && !ret; i++) { + hw_lm = sde_crtc->mixers[i].hw_lm; + hw_dspp = sde_crtc->mixers[i].hw_dspp; + if (!hw_lm) { + ret = -EINVAL; + continue; + } + hw_cfg.ctl = sde_crtc->mixers[i].hw_ctl; + hw_cfg.mixer_info = hw_lm; + hw_cfg.displayh = num_mixers * hw_lm->cfg.out_width; + hw_cfg.displayv = hw_lm->cfg.out_height; + hw_cfg.panel_height = sde_crtc->base.state->adjusted_mode.vdisplay; + hw_cfg.panel_width = sde_crtc->base.state->adjusted_mode.hdisplay; + ret = set_feature(hw_dspp, &hw_cfg, sde_crtc); + if (ret) + break; + } +} + void sde_cp_crtc_clear(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc = NULL; @@ -2579,6 +2652,7 @@ void sde_cp_crtc_clear(struct drm_crtc *crtc) } mutex_lock(&sde_crtc->crtc_cp_lock); + _sde_cp_disable_features(sde_crtc); list_del_init(&sde_crtc->cp_active_list); list_del_init(&sde_crtc->cp_dirty_list); list_del_init(&sde_crtc->ad_active); diff --git a/msm/sde/sde_hw_color_proc_v4.c b/msm/sde/sde_hw_color_proc_v4.c index 6972e8ab..1ddcd4ed 100644 --- a/msm/sde/sde_hw_color_proc_v4.c +++ b/msm/sde/sde_hw_color_proc_v4.c @@ -5,6 +5,7 @@ #include #include "sde_hw_color_proc_common_v4.h" #include "sde_hw_color_proc_v4.h" +#include "sde_dbg.h" static int sde_write_3d_gamut(struct sde_hw_blk_reg_map *hw, struct drm_msm_3d_gamut *payload, u32 base, @@ -636,3 +637,33 @@ void sde_demura_read_plane_status(struct sde_hw_dspp *ctx, u32 *status) *status = DEM_FETCH_DMA3_RECT1; } } + +void sde_demura_pu_cfg(struct sde_hw_dspp *dspp, void *cfg) +{ + u32 demura_base; + struct sde_hw_cp_cfg *hw_cfg = cfg; + struct msm_roi_list *roi_list = NULL; + u32 temp; + + if (!dspp) { + DRM_ERROR("invalid parameter ctx %pK", dspp); + return; + } + demura_base = dspp->cap->sblk->demura.base; + if (!cfg || !hw_cfg->payload) { + temp = 0; + } else { + roi_list = hw_cfg->payload; + if (hw_cfg->panel_width < hw_cfg->panel_height) + temp = (16 * (1 << 21)) / hw_cfg->panel_height; + else + temp = (8 * (1 << 21)) / hw_cfg->panel_height; + temp = temp * (roi_list->roi[0].y1); + } + SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->demura.base + 0x60, + temp); + + SDE_EVT32(0x60, temp, dspp->idx, ((roi_list) ? roi_list->roi[0].y1 : -1), + ((roi_list) ? roi_list->roi[0].y2 : -1), + ((hw_cfg) ? hw_cfg->panel_height : -1)); +} diff --git a/msm/sde/sde_hw_color_proc_v4.h b/msm/sde/sde_hw_color_proc_v4.h index 64d0083c..a064c1f3 100644 --- a/msm/sde/sde_hw_color_proc_v4.h +++ b/msm/sde/sde_hw_color_proc_v4.h @@ -121,4 +121,11 @@ void sde_setup_fp16_igcv1(struct sde_hw_pipe *ctx, */ void sde_setup_fp16_unmultv1(struct sde_hw_pipe *ctx, enum sde_sspp_multirect_index index, void *data); + +/** + * sde_demura_pu_cfg - api to set the partial update information for demura + * @ctx: pointer to dspp object. + * @cfg: partial update configuraton for the frame. +*/ +void sde_demura_pu_cfg(struct sde_hw_dspp *ctx, void *cfg); #endif /* _SDE_HW_COLOR_PROC_V4_H_ */ diff --git a/msm/sde/sde_hw_dspp.c b/msm/sde/sde_hw_dspp.c index e413ca82..24150f6a 100644 --- a/msm/sde/sde_hw_dspp.c +++ b/msm/sde/sde_hw_dspp.c @@ -331,6 +331,7 @@ static void dspp_demura(struct sde_hw_dspp *c) sde_demura_backlight_cfg; c->ops.demura_read_plane_status = sde_demura_read_plane_status; + c->ops.setup_demura_pu_config = sde_demura_pu_cfg; } } } diff --git a/msm/sde/sde_hw_dspp.h b/msm/sde/sde_hw_dspp.h index a3b03289..9d8160ae 100644 --- a/msm/sde/sde_hw_dspp.h +++ b/msm/sde/sde_hw_dspp.h @@ -283,6 +283,12 @@ struct sde_hw_dspp_ops { * @status: Demura plane used by DSPP. demura_fetch_planes enum value. */ void (*demura_read_plane_status)(struct sde_hw_dspp *ctx, u32 *status); + /** + * setup_demura_pu_config - function to configure demura hw block pu offsets + * @ctx: Pointer to dspp context + * @cfg: Pointer to configuration + */ + void (*setup_demura_pu_config)(struct sde_hw_dspp *ctx, void *cfg); }; /** diff --git a/msm/sde/sde_hw_mdss.h b/msm/sde/sde_hw_mdss.h index 063af3cc..b6406f5c 100644 --- a/msm/sde/sde_hw_mdss.h +++ b/msm/sde/sde_hw_mdss.h @@ -582,6 +582,8 @@ struct sde_mdss_color { * @dspp[DSPP_MAX]: array of hw_dspp pointers associated with crtc. * @broadcast_disabled: flag indicating if broadcast should be avoided when * using LUTDMA + * @panel_height: height of display panel in pixels. + * @panel_width: width of display panel in pixels. */ struct sde_hw_cp_cfg { void *payload; @@ -594,6 +596,8 @@ struct sde_hw_cp_cfg { u32 displayh; struct sde_hw_dspp *dspp[DSPP_MAX]; bool broadcast_disabled; + u32 panel_height; + u32 panel_width; }; /** 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 ba645d29..bdc12f5a 100644 --- a/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -4547,7 +4547,7 @@ void reg_dmav1_disable_spr(struct sde_hw_dspp *ctx, void *cfg) DRM_ERROR("spr write decode select failed ret %d\n", rc); return; } - + SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY); reg_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base + 0x04; REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, ®, sizeof(u32), REG_BLK_WRITE_SINGLE, 0, 0, 0); @@ -4706,6 +4706,7 @@ void reg_dmav1_setup_spr_init_cfgv1(struct sde_hw_dspp *ctx, void *cfg) DRM_ERROR("failed to kick off ret %d\n", rc); return; } + SDE_EVT32(SDE_EVTLOG_FUNC_EXIT); } void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg) @@ -4723,20 +4724,22 @@ void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg) return; if (!hw_cfg->payload || hw_cfg->len != sizeof(struct sde_drm_roi_v1)) { - DRM_ERROR("invalid payload of pu rects\n"); - return; - } + DRM_DEBUG("invalid payload of pu rects\n"); + reg = 0; + } else { + roi_list = hw_cfg->payload; + if (roi_list->num_rects > 1) { + DRM_ERROR("multiple pu regions not supported with spr\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; + 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; + } + reg = APPLY_MASK_AND_SHIFT(roi_list->roi[0].x1, 16, 0) | + APPLY_MASK_AND_SHIFT(roi_list->roi[0].y1, 16, 16); } dma_ops = sde_reg_dma_get_ops(); @@ -4753,8 +4756,6 @@ void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg) 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); @@ -4773,6 +4774,7 @@ void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg) DRM_ERROR("failed to kick off ret %d\n", rc); return; } + SDE_EVT32(SDE_EVTLOG_FUNC_EXIT); } static void reg_dma_demura_off(struct sde_hw_dspp *ctx, @@ -4805,7 +4807,7 @@ static void reg_dma_demura_off(struct sde_hw_dspp *ctx, DRM_ERROR("off(0x4): REG_SINGLE_WRITE failed ret %d\n", rc); return; } - + SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY); REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[DEMURA_CFG][ctx->idx], REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE, @@ -4986,7 +4988,7 @@ static int __reg_dmav1_setup_demurav1_cfg0(struct sde_hw_dspp *ctx, goto quit; } - width = hw_cfg->displayh >> 1; + width = hw_cfg->panel_width >> 1; DRM_DEBUG_DRIVER("0x80: value %x\n", width); REG_DMA_SETUP_OPS(*dma_write_cfg, demura_base + 0x80, &width, sizeof(width), REG_SINGLE_WRITE, 0, 0, 0); @@ -5078,14 +5080,14 @@ static int __reg_dmav1_setup_demurav1_cfg1(struct sde_hw_dspp *ctx, goto quit; } - width = hw_cfg->displayh; + width = hw_cfg->panel_width; DRM_DEBUG_DRIVER("width for LFC calculation is %d\n", width); - if (hw_cfg->displayh < hw_cfg->displayv) { + if (hw_cfg->panel_width < hw_cfg->panel_height) { temp[0] = (8 * (1 << 21)) / width; - temp[1] = (16 * (1 << 21)) / hw_cfg->displayv; + temp[1] = (16 * (1 << 21)) / hw_cfg->panel_height; } else { temp[0] = (16 * (1 << 21)) / width; - temp[1] = (8 * (1 << 21)) / hw_cfg->displayv; + temp[1] = (8 * (1 << 21)) / hw_cfg->panel_height; } temp[0] = (dcfg->pentile) ? ((temp[0]) | BIT(31)) : temp[0]; @@ -5233,7 +5235,7 @@ static int __reg_dmav1_setup_demurav1_en(struct sde_hw_dspp *ctx, en |= (dcfg->cfg0_en) ? BIT(2) : 0; en |= (dcfg->cfg1_en) ? BIT(1) : 0; DRM_DEBUG_DRIVER("demura en %x\n", en); - + SDE_EVT32(en); REG_DMA_SETUP_OPS(*dma_write_cfg, demura_base + 0x4, &en, sizeof(en), REG_SINGLE_WRITE, 0, 0, 0); rc = dma_ops->setup_payload(dma_write_cfg); @@ -5258,12 +5260,12 @@ static int __reg_dmav1_setup_demurav1_dual_pipe(struct sde_hw_dspp *ctx, if (dspp->idx == ctx->idx) { temp = 0; } else { - if (hw_cfg->displayh < hw_cfg->displayv) - temp = (8 * (1 << 21)) / hw_cfg->displayh; + if (hw_cfg->panel_width < hw_cfg->panel_height) + temp = (8 * (1 << 21)) / hw_cfg->panel_width; else - temp = (16 * (1 << 21)) / hw_cfg->displayh; + temp = (16 * (1 << 21)) / hw_cfg->panel_width; - temp = temp * (hw_cfg->displayh >> 1); + temp = temp * (hw_cfg->panel_width >> 1); } REG_DMA_SETUP_OPS(*dma_write_cfg, demura_base + 0x58, &temp, sizeof(temp), REG_SINGLE_WRITE, 0, 0, 0);