From 04edecd2691214abaa539bd6f875153defe9a14c Mon Sep 17 00:00:00 2001 From: Mahadevan Date: Wed, 9 Mar 2022 22:00:33 +0530 Subject: [PATCH] disp: msm: sde: proper allocation of dcwb for LMs During dcwb mixer allocation, resource manager allocates the first available mixer in the free list. In dual display uses case with 1 1 1 topology if only secondary is running CWB then, resource manager allocates DCWB0 which leads to wb timeout due to HW does not have the connection between LM1 and DCWB0. This change allocates proper dcwb for the LMs in RM. Change-Id: I0c8b04b46ccad5a7d7dd591fbfa3ea0915eccdc6 Signed-off-by: Mahadevan --- msm/sde/sde_connector.c | 3 +- msm/sde/sde_connector.h | 2 + msm/sde/sde_hw_catalog.c | 8 +++- msm/sde/sde_hw_catalog.h | 14 ++++--- msm/sde/sde_rm.c | 81 ++++++++++++++++++++++++++++------------ 5 files changed, 75 insertions(+), 33 deletions(-) diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index 50c1276975..9a25008690 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -2108,7 +2108,8 @@ static int _sde_connector_lm_preference(struct sde_connector *sde_conn, return -EINVAL; } - sde_hw_mixer_set_preference(sde_kms->catalog, num_lm, disp_type); + sde_conn->lm_mask = sde_hw_mixer_set_preference(sde_kms->catalog, + num_lm, disp_type); return ret; } diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index f18e2584e8..2a6b8ca7c9 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -542,6 +542,7 @@ struct sde_misr_sign { * @hdr_min_luminance: desired min luminance obtained from HDR block * @hdr_supported: does the sink support HDR content * @color_enc_fmt: Colorimetry encoding formats of sink + * @lm_mask: preferred LM mask for connector * @allow_bl_update: Flag to indicate if BL update is allowed currently or not * @dimming_bl_notify_enabled: Flag to indicate if dimming bl notify is enabled or not * @qsync_mode: Cached Qsync mode, 0=disabled, 1=continuous mode @@ -616,6 +617,7 @@ struct sde_connector { bool hdr_supported; u32 color_enc_fmt; + u32 lm_mask; u8 hdr_plus_app_ver; u32 qsync_mode; diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index 3c246d87e9..eeaeadbaf0 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -2045,10 +2045,10 @@ static int sde_ctl_parse_dt(struct device_node *np, return 0; } -void sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, +u32 sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, uint32_t disp_type) { - u32 i, cnt = 0, sec_cnt = 0; + u32 i, cnt = 0, sec_cnt = 0, lm_mask = 0; if (disp_type == SDE_CONNECTOR_PRIMARY) { for (i = 0; i < sde_cfg->mixer_count; i++) { @@ -2067,6 +2067,7 @@ void sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, if (cnt < num_lm) { set_bit(SDE_DISP_PRIMARY_PREF, &sde_cfg->mixer[i].features); + lm_mask |= BIT(sde_cfg->mixer[i].id - 1); cnt++; } @@ -2105,10 +2106,13 @@ void sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, BIT(SDE_DISP_PRIMARY_PREF))) { set_bit(SDE_DISP_SECONDARY_PREF, &sde_cfg->mixer[i].features); + lm_mask |= BIT(sde_cfg->mixer[i].id - 1); cnt++; } } } + + return lm_mask; } static int sde_mixer_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index 623a981b3b..af2cea4477 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/msm/sde/sde_hw_catalog.h @@ -1998,13 +1998,15 @@ struct sde_mdss_hw_cfg_handler { #define BLK_RC(s) ((s)->rc) /** - * sde_hw_set_preference: populate the individual hw lm preferences, - * overwrite if exists - * @sde_cfg: pointer to sspp cfg - * @num_lm: num lms to set preference - * @disp_type: is the given display primary/secondary + * sde_hw_mixer_set_preference: populate the individual hw lm preferences, + * overwrite if exists + * @sde_cfg: pointer to sspp cfg + * @num_lm: num lms to set preference + * @disp_type: is the given display primary/secondary + * + * Return: layer mixer mask allocated for the disp_type */ -void sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, +u32 sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, uint32_t disp_type); /** diff --git a/msm/sde/sde_rm.c b/msm/sde/sde_rm.c index 76df522d1b..77ae1e57c8 100644 --- a/msm/sde/sde_rm.c +++ b/msm/sde/sde_rm.c @@ -131,11 +131,13 @@ char sde_hw_blk_str[SDE_HW_BLK_MAX][SDE_HW_BLK_NAME_LEN] = { * @top_ctrl: topology control preference from kernel client * @top: selected topology for the display * @hw_res: Hardware resources required as reported by the encoders + * @conn_lm_mask: preferred LM mask of cwb requested display */ struct sde_rm_requirements { uint64_t top_ctrl; const struct sde_rm_topology_def *topology; struct sde_encoder_hw_resources hw_res; + u32 conn_lm_mask; }; /** @@ -1157,7 +1159,8 @@ static bool _sde_rm_check_lm_and_get_connected_blks( struct sde_rm_hw_blk **dspp, struct sde_rm_hw_blk **ds, struct sde_rm_hw_blk **pp, - struct sde_rm_hw_blk *primary_lm) + struct sde_rm_hw_blk *primary_lm, + u32 conn_lm_mask) { const struct sde_lm_cfg *lm_cfg = to_sde_hw_mixer(lm->hw)->cap; const struct sde_pingpong_cfg *pp_cfg; @@ -1212,6 +1215,11 @@ static bool _sde_rm_check_lm_and_get_connected_blks( } else if (!RM_RQ_DCWB(reqs) && dcwb_pref) { SDE_DEBUG("fail: dcwb supported dummy lm incorrectly allocated\n"); return false; + } else if (RM_RQ_DCWB(reqs) && dcwb_pref && + ((ffs(conn_lm_mask) % 2) == ((lm_cfg->id + 1) % 2))) { + SDE_DEBUG("fail: dcwb:%d trying to match lm:%d\n", + lm_cfg->id, ffs(conn_lm_mask)); + return false; } } else if ((!is_conn_primary && lm_primary_pref) || (!is_conn_secondary && lm_secondary_pref)) { @@ -1258,7 +1266,7 @@ static int _sde_rm_reserve_lms( struct sde_rm_hw_blk *ds[MAX_BLOCKS]; struct sde_rm_hw_blk *pp[MAX_BLOCKS]; struct sde_rm_hw_iter iter_i, iter_j; - u32 lm_mask = 0; + u32 lm_mask = 0, conn_lm_mask = 0; int lm_count = 0; int i, rc = 0; @@ -1267,6 +1275,8 @@ static int _sde_rm_reserve_lms( return 0; } + if (RM_RQ_DCWB(reqs)) + conn_lm_mask = reqs->conn_lm_mask; /* Find a primary mixer */ sde_rm_init_hw_iter(&iter_i, 0, SDE_HW_BLK_LM); while (lm_count != reqs->topology->num_lm && @@ -1290,7 +1300,7 @@ static int _sde_rm_reserve_lms( if (!_sde_rm_check_lm_and_get_connected_blks( rm, rsvp, reqs, lm[lm_count], &dspp[lm_count], &ds[lm_count], - &pp[lm_count], NULL)) + &pp[lm_count], NULL, conn_lm_mask)) continue; lm_mask |= (1 << iter_i.blk->id); @@ -1300,6 +1310,9 @@ static int _sde_rm_reserve_lms( if (lm_count == reqs->topology->num_lm) break; + if (RM_RQ_DCWB(reqs)) + conn_lm_mask = conn_lm_mask & ~BIT(ffs(conn_lm_mask) - 1); + /* Valid primary mixer found, find matching peers */ sde_rm_init_hw_iter(&iter_j, 0, SDE_HW_BLK_LM); @@ -1315,7 +1328,8 @@ static int _sde_rm_reserve_lms( if (!_sde_rm_check_lm_and_get_connected_blks( rm, rsvp, reqs, iter_j.blk, &dspp[lm_count], &ds[lm_count], - &pp[lm_count], iter_i.blk)) + &pp[lm_count], iter_i.blk, + conn_lm_mask)) continue; SDE_DEBUG("blk id = %d, _lm_ids[%d] = %d\n", @@ -1328,6 +1342,10 @@ static int _sde_rm_reserve_lms( lm_mask |= (1 << iter_j.blk->id); ++lm_count; + + if (RM_RQ_DCWB(reqs)) + conn_lm_mask = conn_lm_mask & ~BIT(ffs(conn_lm_mask) - 1); + break; } @@ -2278,6 +2296,26 @@ int sde_rm_cont_splash_res_init(struct msm_drm_private *priv, return 0; } +static struct drm_connector *_sde_rm_get_connector( + struct drm_encoder *enc) +{ + struct drm_connector *conn = NULL, *conn_search; + struct sde_connector *c_conn = NULL; + struct drm_connector_list_iter conn_iter; + + drm_connector_list_iter_begin(enc->dev, &conn_iter); + drm_for_each_connector_iter(conn_search, &conn_iter) { + c_conn = to_sde_connector(conn_search); + if (c_conn->encoder == enc) { + conn = conn_search; + break; + } + } + drm_connector_list_iter_end(&conn_iter); + + return conn; +} + static int _sde_rm_populate_requirements( struct sde_rm *rm, struct drm_encoder *enc, @@ -2287,6 +2325,8 @@ static int _sde_rm_populate_requirements( struct sde_rm_requirements *reqs) { const struct drm_display_mode *mode = &crtc_state->mode; + struct drm_encoder *encoder_iter; + struct drm_connector *conn; int i, num_lm; reqs->top_ctrl = sde_connector_get_property(conn_state, @@ -2353,6 +2393,19 @@ static int _sde_rm_populate_requirements( reqs->topology->top_name, reqs->topology->num_ctl); } + if (RM_RQ_DCWB(reqs)) { + drm_for_each_encoder_mask(encoder_iter, enc->dev, + crtc_state->encoder_mask) { + if (drm_encoder_mask(encoder_iter) == drm_encoder_mask(enc)) + continue; + + conn = _sde_rm_get_connector(encoder_iter); + if (conn) + reqs->conn_lm_mask = to_sde_connector(conn)->lm_mask; + break; + } + } + SDE_DEBUG("top_ctrl: 0x%llX num_h_tiles: %d\n", reqs->top_ctrl, reqs->hw_res.display_num_of_h_tiles); SDE_DEBUG("num_lm: %d num_ctl: %d topology: %d split_display: %d\n", @@ -2395,26 +2448,6 @@ static struct sde_rm_rsvp *_sde_rm_get_rsvp_cur(struct sde_rm *rm, struct drm_en return _sde_rm_get_rsvp(rm, enc, false); } -static struct drm_connector *_sde_rm_get_connector( - struct drm_encoder *enc) -{ - struct drm_connector *conn = NULL, *conn_search; - struct sde_connector *c_conn = NULL; - struct drm_connector_list_iter conn_iter; - - drm_connector_list_iter_begin(enc->dev, &conn_iter); - drm_for_each_connector_iter(conn_search, &conn_iter) { - c_conn = to_sde_connector(conn_search); - if (c_conn->encoder == enc) { - conn = conn_search; - break; - } - } - drm_connector_list_iter_end(&conn_iter); - - return conn; -} - int sde_rm_update_topology(struct sde_rm *rm, struct drm_connector_state *conn_state, struct msm_display_topology *topology)