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>
This commit is contained in:
Mahadevan
2022-03-09 22:00:33 +05:30
szülő 887b222de9
commit 04edecd269
5 fájl változott, egészen pontosan 75 új sor hozzáadva és 33 régi sor törölve

Fájl megtekintése

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