diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index da9dd52460..1690621f30 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -155,7 +155,8 @@ #define SDE_UIDLE_FAL10_TARGET_IDLE 50 #define SDE_UIDLE_FAL1_TARGET_IDLE 40 #define SDE_UIDLE_FAL1_MAX_THRESHOLD 15 -#define SDE_UIDLE_REV102_FAL1_MAX_THRESHOLD 255 +#define SDE_UIDLE_FAL1_MAX_THRESHOLD_EXT_REV_102 255 +#define SDE_UIDLE_FAL1_MAX_THRESHOLD_EXT_REV_103 255 #define SDE_UIDLE_FAL10_THRESHOLD_60 12 #define SDE_UIDLE_FAL10_THRESHOLD_90 13 #define SDE_UIDLE_MAX_DWNSCALE 1500 @@ -1838,8 +1839,11 @@ static void sde_sspp_set_features(struct sde_mdss_cfg *sde_cfg, &sspp->perf_features); } - if (sde_cfg->uidle_cfg.uidle_rev) + if (sde_cfg->uidle_cfg.uidle_rev) { set_bit(SDE_PERF_SSPP_UIDLE, &sspp->perf_features); + if (sde_cfg->uidle_cfg.uidle_rev >= SDE_UIDLE_VERSION_1_0_3) + set_bit(SDE_PERF_SSPP_UIDLE_FILL_LVL_SCALE, &sspp->perf_features); + } if (sde_cfg->sc_cfg[SDE_SYS_CACHE_DISP].has_sys_cache) set_bit(SDE_PERF_SSPP_SYS_CACHE, &sspp->perf_features); @@ -4756,42 +4760,40 @@ static void _sde_hw_setup_uidle(struct sde_uidle_cfg *uidle_cfg) if (!uidle_cfg->uidle_rev) return; - if ((IS_SDE_UIDLE_REV_102(uidle_cfg->uidle_rev)) || - (IS_SDE_UIDLE_REV_101(uidle_cfg->uidle_rev)) || - (IS_SDE_UIDLE_REV_100(uidle_cfg->uidle_rev))) { - uidle_cfg->fal10_exit_cnt = SDE_UIDLE_FAL10_EXIT_CNT; - uidle_cfg->fal10_exit_danger = SDE_UIDLE_FAL10_EXIT_DANGER; - uidle_cfg->fal10_danger = SDE_UIDLE_FAL10_DANGER; - uidle_cfg->fal10_target_idle_time = SDE_UIDLE_FAL10_TARGET_IDLE; - uidle_cfg->fal1_target_idle_time = SDE_UIDLE_FAL1_TARGET_IDLE; - uidle_cfg->max_dwnscale = SDE_UIDLE_MAX_DWNSCALE; - uidle_cfg->debugfs_ctrl = true; - uidle_cfg->fal1_max_threshold = SDE_UIDLE_FAL1_MAX_THRESHOLD; + uidle_cfg->fal10_exit_cnt = SDE_UIDLE_FAL10_EXIT_CNT; + uidle_cfg->fal10_exit_danger = SDE_UIDLE_FAL10_EXIT_DANGER; + uidle_cfg->fal10_danger = SDE_UIDLE_FAL10_DANGER; + uidle_cfg->fal10_target_idle_time = SDE_UIDLE_FAL10_TARGET_IDLE; + uidle_cfg->fal1_target_idle_time = SDE_UIDLE_FAL1_TARGET_IDLE; + uidle_cfg->max_dwnscale = SDE_UIDLE_MAX_DWNSCALE; + uidle_cfg->debugfs_ctrl = true; + uidle_cfg->fal1_max_threshold = SDE_UIDLE_FAL1_MAX_THRESHOLD; - if (IS_SDE_UIDLE_REV_100(uidle_cfg->uidle_rev)) { - uidle_cfg->fal10_threshold = - SDE_UIDLE_FAL10_THRESHOLD_60; - uidle_cfg->max_fps = SDE_UIDLE_MAX_FPS_60; - } else if (IS_SDE_UIDLE_REV_101(uidle_cfg->uidle_rev)) { - set_bit(SDE_UIDLE_QACTIVE_OVERRIDE, - &uidle_cfg->features); - uidle_cfg->fal10_threshold = - SDE_UIDLE_FAL10_THRESHOLD_90; - uidle_cfg->max_fps = SDE_UIDLE_MAX_FPS_90; - } else if (IS_SDE_UIDLE_REV_102(uidle_cfg->uidle_rev)) { - set_bit(SDE_UIDLE_QACTIVE_OVERRIDE, - &uidle_cfg->features); - uidle_cfg->fal10_threshold = - SDE_UIDLE_FAL10_THRESHOLD_90; - uidle_cfg->max_fps = SDE_UIDLE_MAX_FPS_90; - uidle_cfg->max_fal1_fps = SDE_UIDLE_MAX_FPS_240; - uidle_cfg->fal1_max_threshold = - SDE_UIDLE_REV102_FAL1_MAX_THRESHOLD; - } - } else { - pr_err("invalid uidle rev:0x%x, disabling uidle\n", - uidle_cfg->uidle_rev); - uidle_cfg->uidle_rev = 0; + if (IS_SDE_UIDLE_REV_100(uidle_cfg->uidle_rev)) { + uidle_cfg->fal10_threshold = + SDE_UIDLE_FAL10_THRESHOLD_60; + uidle_cfg->max_fps = SDE_UIDLE_MAX_FPS_60; + } else if (IS_SDE_UIDLE_REV_101(uidle_cfg->uidle_rev)) { + set_bit(SDE_UIDLE_QACTIVE_OVERRIDE, + &uidle_cfg->features); + uidle_cfg->fal10_threshold = + SDE_UIDLE_FAL10_THRESHOLD_90; + uidle_cfg->max_fps = SDE_UIDLE_MAX_FPS_90; + } else if (IS_SDE_UIDLE_REV_102(uidle_cfg->uidle_rev)) { + set_bit(SDE_UIDLE_QACTIVE_OVERRIDE, + &uidle_cfg->features); + uidle_cfg->fal10_threshold = + SDE_UIDLE_FAL10_THRESHOLD_90; + uidle_cfg->max_fps = SDE_UIDLE_MAX_FPS_90; + uidle_cfg->max_fal1_fps = SDE_UIDLE_MAX_FPS_240; + uidle_cfg->fal1_max_threshold = + SDE_UIDLE_FAL1_MAX_THRESHOLD_EXT_REV_102; + } else if (IS_SDE_UIDLE_REV_103(uidle_cfg->uidle_rev)) { + set_bit(SDE_UIDLE_QACTIVE_OVERRIDE, &uidle_cfg->features); + uidle_cfg->max_fps = SDE_UIDLE_MAX_FPS_240; + uidle_cfg->max_fal1_fps = SDE_UIDLE_MAX_FPS_240; + uidle_cfg->fal1_max_threshold = SDE_UIDLE_FAL1_MAX_THRESHOLD_EXT_REV_103; + uidle_cfg->fal10_threshold = SDE_UIDLE_FAL10_THRESHOLD_60; } } @@ -5146,7 +5148,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->ts_prefill_rev = 2; sde_cfg->ctl_rev = SDE_CTL_CFG_VERSION_1_0_0; sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_2_0_1; - sde_cfg->uidle_cfg.uidle_rev = SDE_UIDLE_VERSION_1_0_2; + sde_cfg->uidle_cfg.uidle_rev = SDE_UIDLE_VERSION_1_0_3; sde_cfg->mdss_hw_block_size = 0x158; sde_cfg->demura_supported[SSPP_DMA1][0] = 0; sde_cfg->demura_supported[SSPP_DMA1][1] = 1; diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index 91cf4da165..1e80a16171 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/msm/sde/sde_hw_catalog.h @@ -148,6 +148,7 @@ #define SDE_UIDLE_VERSION_1_0_0 0x100 #define SDE_UIDLE_VERSION_1_0_1 0x101 #define SDE_UIDLE_VERSION_1_0_2 0x102 +#define SDE_UIDLE_VERSION_1_0_3 0x103 #define IS_SDE_UIDLE_REV_100(rev) \ ((rev) == SDE_UIDLE_VERSION_1_0_0) @@ -155,6 +156,8 @@ ((rev) == SDE_UIDLE_VERSION_1_0_1) #define IS_SDE_UIDLE_REV_102(rev) \ ((rev) == SDE_UIDLE_VERSION_1_0_2) +#define IS_SDE_UIDLE_REV_103(rev) \ + ((rev) == SDE_UIDLE_VERSION_1_0_3) #define SDE_UIDLE_MAJOR(rev) ((rev) >> 8) @@ -345,6 +348,7 @@ enum { * @SDE_PERF_SSPP_CDP Supports client driven prefetch * @SDE_PERF_SSPP_SYS_CACHE, SSPP supports system cache * @SDE_PERF_SSPP_UIDLE, sspp supports uidle + * @SDE_PERF_SSPP_UIDLE_FILL_LVL_SCALE, sspp supports uidle fill level scaling * @SDE_PERF_SSPP_MAX Maximum value */ enum { @@ -355,6 +359,7 @@ enum { SDE_PERF_SSPP_CDP, SDE_PERF_SSPP_SYS_CACHE, SDE_PERF_SSPP_UIDLE, + SDE_PERF_SSPP_UIDLE_FILL_LVL_SCALE, SDE_PERF_SSPP_MAX }; diff --git a/msm/sde/sde_hw_sspp.c b/msm/sde/sde_hw_sspp.c index 2276de5c20..282763385d 100644 --- a/msm/sde/sde_hw_sspp.c +++ b/msm/sde/sde_hw_sspp.c @@ -46,6 +46,7 @@ #define SSPP_UIDLE_CTRL_VALUE 0x1f0 #define SSPP_UIDLE_CTRL_VALUE_REC1 0x1f4 +#define SSPP_FILL_LEVEL_SCALE 0x1f8 /* SSPP_DGM */ #define SSPP_DGM_0 0x9F0 @@ -1167,6 +1168,22 @@ static void sde_hw_sspp_setup_sys_cache(struct sde_hw_pipe *ctx, SDE_REG_WRITE(&ctx->hw, SSPP_SYS_CACHE_MODE + idx, val); } +static void sde_hw_sspp_setup_uidle_fill_scale(struct sde_hw_pipe *ctx, + struct sde_hw_pipe_uidle_cfg *cfg) +{ + u32 idx, fill_lvl; + + if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx)) + return; + + /* duplicate the v1 scale values for V2 and fal10 exit */ + fill_lvl = cfg->fill_level_scale & 0xF; + fill_lvl |= (cfg->fill_level_scale & 0xF) << 8; + fill_lvl |= (cfg->fill_level_scale & 0xF) << 16; + + SDE_REG_WRITE(&ctx->hw, SSPP_FILL_LEVEL_SCALE + idx, fill_lvl); +} + static void sde_hw_sspp_setup_uidle(struct sde_hw_pipe *ctx, struct sde_hw_pipe_uidle_cfg *cfg, enum sde_sspp_multirect_index index) @@ -1501,8 +1518,11 @@ static void _setup_layer_ops(struct sde_hw_pipe *c, if (test_bit(SDE_PERF_SSPP_CDP, &perf_features)) c->ops.setup_cdp = sde_hw_sspp_setup_cdp; - if (test_bit(SDE_PERF_SSPP_UIDLE, &perf_features)) + if (test_bit(SDE_PERF_SSPP_UIDLE, &perf_features)) { c->ops.setup_uidle = sde_hw_sspp_setup_uidle; + if (test_bit(SDE_PERF_SSPP_UIDLE_FILL_LVL_SCALE, &perf_features)) + c->ops.setup_uidle_fill_scale = sde_hw_sspp_setup_uidle_fill_scale; + } _setup_layer_ops_colorproc(c, features, is_virtual_pipe); diff --git a/msm/sde/sde_hw_sspp.h b/msm/sde/sde_hw_sspp.h index e69d7dd104..65557e6bdf 100644 --- a/msm/sde/sde_hw_sspp.h +++ b/msm/sde/sde_hw_sspp.h @@ -265,6 +265,7 @@ struct sde_hw_pipe_sc_cfg { * @fal10_exit_threshold: number of lines to indicate fal_10_exit is okay * @fal10_threshold: number of lines where fal_10_is okay * @fal1_threshold: number of lines where fal_1 is okay + * @fill_level_scale: scale factor on the fal10 threshold */ struct sde_hw_pipe_uidle_cfg { u32 enable; @@ -272,6 +273,7 @@ struct sde_hw_pipe_uidle_cfg { u32 fal10_exit_threshold; u32 fal10_threshold; u32 fal1_threshold; + u32 fill_level_scale; }; /** @@ -534,6 +536,14 @@ struct sde_hw_sspp_ops { struct sde_hw_pipe_uidle_cfg *cfg, enum sde_sspp_multirect_index index); + /** + * setup_uidle_fill_scale - set uidle fill scale factor + * @ctx: Pointer to pipe context + * @cfg: Pointer to uidle configuration + */ + void (*setup_uidle_fill_scale)(struct sde_hw_pipe *ctx, + struct sde_hw_pipe_uidle_cfg *cfg); + /** * setup_ts_prefill - setup prefill traffic shaper * @ctx: Pointer to pipe context diff --git a/msm/sde/sde_plane.c b/msm/sde/sde_plane.c index f63b6a0745..6e0f0d4c01 100644 --- a/msm/sde/sde_plane.c +++ b/msm/sde/sde_plane.c @@ -2942,6 +2942,28 @@ static void _sde_plane_setup_uidle(struct drm_crtc *crtc, psde->catalog->uidle_cfg.fal1_max_threshold); cfg.fal_allowed_threshold = fal10_threshold + (fal10_target_idle_time_ns*1000/line_time*2)/1000; + cfg.fill_level_scale = 0; + + /* + * if uidle fill scale is supported, determing the scale value + * and adjust fal10 thresholds to their scaled values. + * fal1 thresholds and fal_allowed are not scaled. + */ + if (psde->pipe_hw->ops.setup_uidle_fill_scale) { + u32 fl_require0 = psde->catalog->qos_target_time_ns / line_time * 2; + u32 fl_require = max(fal10_threshold * 1000, fl_require0); + u32 fl_scale = fl_require / fal10_threshold; + u32 fal10_threshold_noscale; + + cfg.fill_level_scale = (fl_scale <= 1) ? 0 : (32 / fl_scale); + + if (cfg.fill_level_scale) { + fal10_threshold_noscale = fal10_threshold * + 32/cfg.fill_level_scale; + cfg.fal_allowed_threshold = fal10_threshold_noscale + + (fal10_target_idle_time_ns * 1000 / line_time * 2) / 1000; + } + } } else { SDE_ERROR("invalid settings, will disable UIDLE %d %d %d %d\n", line_time, fal10_threshold, fal10_target_idle_time_ns, @@ -2950,9 +2972,10 @@ static void _sde_plane_setup_uidle(struct drm_crtc *crtc, } SDE_DEBUG_PLANE(psde, - "tholds: fal10=%d fal10_exit=%d fal1=%d fal_allowed=%d\n", + "tholds: fal10=%d fal10_exit=%d fal1=%d fal_allowed=%d fill_scale=%d\n", cfg.fal10_threshold, cfg.fal10_exit_threshold, - cfg.fal1_threshold, cfg.fal_allowed_threshold); + cfg.fal1_threshold, cfg.fal_allowed_threshold, + cfg.fill_level_scale); SDE_DEBUG_PLANE(psde, "times: line:%d fal1_idle:%d fal10_idle:%d dwnscale:%d\n", line_time, fal1_target_idle_time_ns, @@ -2961,7 +2984,10 @@ static void _sde_plane_setup_uidle(struct drm_crtc *crtc, SDE_EVT32_VERBOSE(cfg.enable, cfg.fal10_threshold, cfg.fal10_exit_threshold, cfg.fal1_threshold, cfg.fal_allowed_threshold, - psde->catalog->uidle_cfg.max_dwnscale); + cfg.fill_level_scale, psde->catalog->uidle_cfg.max_dwnscale); + + if (psde->pipe_hw->ops.setup_uidle_fill_scale) + psde->pipe_hw->ops.setup_uidle_fill_scale(psde->pipe_hw, &cfg); psde->pipe_hw->ops.setup_uidle( psde->pipe_hw, &cfg,