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 <quic_mahap@quicinc.com>
Tento commit je obsažen v:
Mahadevan
2022-03-09 22:00:33 +05:30
rodič 887b222de9
revize 04edecd269
5 změnil soubory, kde provedl 75 přidání a 33 odebrání

Zobrazit soubor

@@ -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;
}

Zobrazit soubor

@@ -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;

Zobrazit soubor

@@ -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)

Zobrazit soubor

@@ -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);
/**

Zobrazit soubor

@@ -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)