From da892c0b91b9d6a6af9a7b5f5e50b3b9f1d497d7 Mon Sep 17 00:00:00 2001 From: Tatenda Chipeperekwa Date: Thu, 12 Sep 2019 16:43:14 -0700 Subject: [PATCH] disp: msm: update topology based on clock requirement Update the topology allocation by considering the required mode clock (vtotal x htotal x fps * fudge factor). Modes with a clock that exceeds the maximum SDE clock will be denoted as requiring a topology that uses two layer mixers. Change-Id: I3c773598b0d79cb6fea9d3a0e04d89ff84d67e13 Signed-off-by: Tatenda Chipeperekwa --- msm/dp/dp_display.c | 9 +++++++-- msm/dp/dp_drm.c | 18 ++++++++++++----- msm/msm_drv.c | 27 +++++++++++++++++++++++++ msm/msm_drv.h | 4 ++++ msm/msm_kms.h | 4 ++++ msm/sde/sde_kms.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 103 insertions(+), 7 deletions(-) diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index d8bb0a0714..bee9567d19 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.c @@ -2060,6 +2060,7 @@ static enum drm_mode_status dp_display_validate_mode( struct dp_display_mode dp_mode; bool dsc_en; u32 num_lm = 0; + int rc = 0; if (!dp_display || !mode || !panel || !avail_res || !avail_res->max_mixer_width) { @@ -2105,8 +2106,12 @@ static enum drm_mode_status dp_display_validate_mode( goto end; } - num_lm = (avail_res->max_mixer_width <= mode->hdisplay) ? - 2 : 1; + rc = msm_get_mixer_count(dp->priv, mode, avail_res, &num_lm); + if (rc) { + DP_ERR("error getting mixer count. rc:%d\n", rc); + goto end; + } + if (num_lm > avail_res->num_lm || (num_lm == 2 && !avail_res->num_3dmux)) { DP_MST_DEBUG("num_lm:%d, req lm:%d 3dmux:%d\n", num_lm, diff --git a/msm/dp/dp_drm.c b/msm/dp/dp_drm.c index 08e61dc839..976e0ebb8f 100644 --- a/msm/dp/dp_drm.c +++ b/msm/dp/dp_drm.c @@ -376,8 +376,6 @@ int dp_connector_get_mode_info(struct drm_connector *connector, struct msm_mode_info *mode_info, void *display, const struct msm_resource_caps_info *avail_res) { - const u32 dual_lm = 2; - const u32 single_lm = 1; const u32 single_intf = 1; const u32 no_enc = 0; struct msm_display_topology *topology; @@ -385,9 +383,12 @@ int dp_connector_get_mode_info(struct drm_connector *connector, struct dp_panel *dp_panel; struct dp_display_mode dp_mode; struct dp_display *dp_disp = display; + struct msm_drm_private *priv; + int rc = 0; if (!drm_mode || !mode_info || !avail_res || - !avail_res->max_mixer_width || !connector || !display) { + !avail_res->max_mixer_width || !connector || !display || + !connector->dev || !connector->dev->dev_private) { DP_ERR("invalid params\n"); return -EINVAL; } @@ -396,10 +397,17 @@ int dp_connector_get_mode_info(struct drm_connector *connector, sde_conn = to_sde_connector(connector); dp_panel = sde_conn->drv_panel; + priv = connector->dev->dev_private; topology = &mode_info->topology; - topology->num_lm = (avail_res->max_mixer_width < drm_mode->hdisplay) ? - dual_lm : single_lm; + + rc = msm_get_mixer_count(priv, drm_mode, avail_res, + &topology->num_lm); + if (rc) { + DP_ERR("error getting mixer count. rc:%d\n", rc); + return rc; + } + topology->num_enc = no_enc; topology->num_intf = single_intf; diff --git a/msm/msm_drv.c b/msm/msm_drv.c index e6529d16cb..b592817ece 100644 --- a/msm/msm_drv.c +++ b/msm/msm_drv.c @@ -1938,6 +1938,33 @@ msm_gem_smmu_address_space_get(struct drm_device *dev, return funcs->get_address_space(priv->kms, domain); } +int msm_get_mixer_count(struct msm_drm_private *priv, + const struct drm_display_mode *mode, + const struct msm_resource_caps_info *res, u32 *num_lm) +{ + struct msm_kms *kms; + const struct msm_kms_funcs *funcs; + + if (!priv) { + DRM_ERROR("invalid drm private struct\n"); + return -EINVAL; + } + + kms = priv->kms; + if (!kms) { + DRM_ERROR("invalid msm kms struct\n"); + return -EINVAL; + } + + funcs = kms->funcs; + if (!funcs || !funcs->get_mixer_count) { + DRM_ERROR("invalid function pointers\n"); + return -EINVAL; + } + + return funcs->get_mixer_count(priv->kms, mode, res, num_lm); +} + static int msm_drm_bind(struct device *dev) { return msm_drm_init(dev, &msm_driver); diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 1cf63841aa..419b7c6b94 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -1029,4 +1029,8 @@ static inline unsigned long timeout_to_jiffies(const ktime_t *timeout) return remaining_jiffies; } +int msm_get_mixer_count(struct msm_drm_private *priv, + const struct drm_display_mode *mode, + const struct msm_resource_caps_info *res, u32 *num_lm); + #endif /* __MSM_DRV_H__ */ diff --git a/msm/msm_kms.h b/msm/msm_kms.h index f1c1169393..961018c6df 100644 --- a/msm/msm_kms.h +++ b/msm/msm_kms.h @@ -122,6 +122,10 @@ struct msm_kms_funcs { int (*cont_splash_config)(struct msm_kms *kms); /* check for continuous splash status */ bool (*check_for_splash)(struct msm_kms *kms); + /* topology information */ + int (*get_mixer_count)(const struct msm_kms *kms, + const struct drm_display_mode *mode, + const struct msm_resource_caps_info *res, u32 *num_lm); }; struct msm_kms { diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 7b71897bb8..1ce5ff7e84 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -19,6 +19,7 @@ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ #include +#include #include #include #include @@ -2468,6 +2469,52 @@ static bool sde_kms_check_for_splash(struct msm_kms *kms) return sde_kms->splash_data.num_splash_displays; } +static int sde_kms_get_mixer_count(const struct msm_kms *kms, + const struct drm_display_mode *mode, + const struct msm_resource_caps_info *res, u32 *num_lm) +{ + struct sde_kms *sde_kms; + s64 mode_clock_hz = 0; + s64 max_mdp_clock_hz = 0; + s64 mdp_fudge_factor = 0; + s64 temp = 0; + s64 htotal_fp = 0; + s64 vtotal_fp = 0; + s64 vrefresh_fp = 0; + + if (!num_lm) { + SDE_ERROR("invalid num_lm pointer\n"); + return -EINVAL; + } + + *num_lm = 1; + if (!kms || !mode || !res) { + SDE_ERROR("invalid input args\n"); + return -EINVAL; + } + + sde_kms = to_sde_kms(kms); + + max_mdp_clock_hz = drm_fixp_from_fraction( + sde_kms->perf.max_core_clk_rate, 1); + mdp_fudge_factor = drm_fixp_from_fraction(105, 100); /* 1.05 */ + htotal_fp = drm_fixp_from_fraction(mode->htotal, 1); + vtotal_fp = drm_fixp_from_fraction(mode->vtotal, 1); + vrefresh_fp = drm_fixp_from_fraction(mode->vrefresh, 1); + + temp = drm_fixp_mul(htotal_fp, vtotal_fp); + temp = drm_fixp_mul(temp, vrefresh_fp); + mode_clock_hz = drm_fixp_mul(temp, mdp_fudge_factor); + if (mode_clock_hz > max_mdp_clock_hz || + mode->hdisplay > res->max_mixer_width) + *num_lm = 2; + SDE_DEBUG("[%s] h=%d, v=%d, fps=%d, max_mdp_clk_hz=%llu, num_lm=%d\n", + mode->name, mode->htotal, mode->vtotal, mode->vrefresh, + sde_kms->perf.max_core_clk_rate, *num_lm); + + return 0; +} + static void _sde_kms_null_commit(struct drm_device *dev, struct drm_encoder *enc) { @@ -2778,6 +2825,7 @@ static const struct msm_kms_funcs kms_funcs = { .get_address_space_device = _sde_kms_get_address_space_device, .postopen = _sde_kms_post_open, .check_for_splash = sde_kms_check_for_splash, + .get_mixer_count = sde_kms_get_mixer_count, }; /* the caller api needs to turn on clock before calling it */