Merge "drm/msm/sde: assign ctls based on capability requirements" into msm-4.8
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 5cdd86b..38e27f4 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -146,6 +146,18 @@
};
/**
+ * CTL sub-blocks
+ * @SDE_CTL_SPLIT_DISPLAY CTL supports video mode split display
+ * @SDE_CTL_PINGPONG_SPLIT CTL supports pingpong split
+ * @SDE_CTL_MAX
+ */
+enum {
+ SDE_CTL_SPLIT_DISPLAY = 0x1,
+ SDE_CTL_PINGPONG_SPLIT,
+ SDE_CTL_MAX
+};
+
+/**
* WB sub-blocks and features
* @SDE_WB_LINE_MODE Writeback module supports line/linear mode
* @SDE_WB_BLOCK_MODE Writeback module supports block mode read
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
index 76c3fee..93ac6b6 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
@@ -363,11 +363,19 @@
},
.ctl_count = 5,
.ctl = {
- {.id = CTL_0, .base = 0x00002000},
- {.id = CTL_1, .base = 0x00002200},
- {.id = CTL_2, .base = 0x00002400},
- {.id = CTL_3, .base = 0x00002600},
- {.id = CTL_4, .base = 0x00002800},
+ {.id = CTL_0,
+ .base = 0x00002000,
+ .features = BIT(SDE_CTL_SPLIT_DISPLAY) |
+ BIT(SDE_CTL_PINGPONG_SPLIT) },
+ {.id = CTL_1,
+ .base = 0x00002200,
+ .features = BIT(SDE_CTL_SPLIT_DISPLAY) },
+ {.id = CTL_2,
+ .base = 0x00002400},
+ {.id = CTL_3,
+ .base = 0x00002600},
+ {.id = CTL_4,
+ .base = 0x00002800},
},
/* 4 VIG, + 4 RGB + 2 DMA + 2 CURSOR */
.sspp_count = 12,
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c
index 0039a00..d4712ef 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.c
+++ b/drivers/gpu/drm/msm/sde/sde_rm.c
@@ -42,6 +42,8 @@
enum sde_rm_topology_name top_name;
uint64_t top_ctrl;
int num_lm;
+ int num_ctl;
+ bool needs_split_display;
struct sde_encoder_hw_resources hw_res;
};
@@ -622,29 +624,48 @@
struct sde_rm_rsvp *rsvp,
struct sde_rm_requirements *reqs)
{
+ struct sde_rm_hw_blk *ctls[MAX_BLOCKS];
struct sde_rm_hw_iter iter;
- int num_ctls;
- int count = 0;
+ int i = 0;
- num_ctls = (reqs->top_name == SDE_RM_TOPOLOGY_DUALPIPE) ? 2 : 1;
+ memset(&ctls, 0, sizeof(ctls));
- memset(&iter, 0, sizeof(iter));
- iter.type = SDE_HW_BLK_CTL;
+ sde_rm_init_hw_iter(&iter, 0, SDE_HW_BLK_CTL);
while (sde_rm_get_hw(rm, &iter)) {
+ unsigned long caps;
+ bool has_split_display, has_ppsplit;
+
if (RESERVED_BY_OTHER(iter.blk, rsvp))
continue;
- iter.blk->rsvp_nxt = rsvp;
- MSM_EVTMSG(rm->dev, iter.blk->type_name, rsvp->enc_id,
- iter.blk->id);
+ caps = ((struct sde_ctl_cfg *)iter.blk->catalog)->features;
+ has_split_display = BIT(SDE_CTL_SPLIT_DISPLAY) & caps;
+ has_ppsplit = BIT(SDE_CTL_PINGPONG_SPLIT) & caps;
- if (++count == num_ctls)
+ SDE_DEBUG("ctl %d caps 0x%lX\n", iter.blk->id, caps);
+
+ if (reqs->needs_split_display != has_split_display)
+ continue;
+
+ if (reqs->top_name == SDE_RM_TOPOLOGY_PPSPLIT && !has_ppsplit)
+ continue;
+
+ ctls[i] = iter.blk;
+ SDE_DEBUG("ctl %d match\n", iter.blk->id);
+
+ if (++i == reqs->num_ctl)
break;
}
- if (count != num_ctls)
+ if (i != reqs->num_ctl)
return -ENAVAIL;
+ for (i = 0; i < ARRAY_SIZE(ctls) && i < reqs->num_ctl; i++) {
+ ctls[i]->rsvp_nxt = rsvp;
+ MSM_EVTMSG(rm->dev, ctls[i]->type_name, rsvp->enc_id,
+ ctls[i]->id);
+ }
+
return 0;
}
@@ -783,7 +804,7 @@
* Assign LMs and blocks whose usage is tied to them: DSPP & Pingpong.
* Do assignment preferring to give away low-resource mixers first:
* - Check mixers without DSPPs
- * - Only then check mixers with DSPPs
+ * - Only then allow to grab from mixers with DSPP capability
*/
ret = _sde_rm_reserve_lms(rm, rsvp, reqs);
if (ret && !RM_RQ_DSPP(reqs)) {
@@ -796,9 +817,20 @@
return ret;
}
+ /*
+ * Do assignment preferring to give away low-resource CTLs first:
+ * - Check mixers without Split Display
+ * - Only then allow to grab from CTLs with split display capability
+ */
_sde_rm_reserve_ctls(rm, rsvp, reqs);
- if (ret)
+ if (ret && !reqs->needs_split_display) {
+ reqs->needs_split_display = true;
+ _sde_rm_reserve_ctls(rm, rsvp, reqs);
+ }
+ if (ret) {
+ SDE_ERROR("unable to find appropriate CTL\n");
return ret;
+ }
/* Assign INTFs, WBs, and blks whose usage is tied to them: CTL & CDM */
ret = _sde_rm_reserve_intf_related_hw(rm, rsvp, &reqs->hw_res);
@@ -862,9 +894,13 @@
/* user requests serving dual display with 1 lm */
reqs->top_name = SDE_RM_TOPOLOGY_PPSPLIT;
reqs->num_lm = 1;
+ reqs->num_ctl = 1;
+ reqs->needs_split_display = true;
} else {
/* dual display, serve with 2 lms */
reqs->top_name = SDE_RM_TOPOLOGY_DUALPIPE;
+ reqs->num_ctl = 2;
+ reqs->needs_split_display = true;
}
} else if (reqs->num_lm == 1) {
@@ -872,13 +908,19 @@
/* wide display, must split across 2 lm and merge */
reqs->top_name = SDE_RM_TOPOLOGY_DUALPIPEMERGE;
reqs->num_lm = 2;
+ reqs->num_ctl = 1;
+ reqs->needs_split_display = false;
} else if (RM_RQ_FORCE_TILING(reqs)) {
/* thin display, but user requests 2 lm and merge */
reqs->top_name = SDE_RM_TOPOLOGY_DUALPIPEMERGE;
reqs->num_lm = 2;
+ reqs->num_ctl = 1;
+ reqs->needs_split_display = false;
} else {
/* thin display, serve with only 1 lm */
reqs->top_name = SDE_RM_TOPOLOGY_SINGLEPIPE;
+ reqs->num_ctl = 1;
+ reqs->needs_split_display = false;
}
} else {
@@ -891,8 +933,8 @@
reqs->hw_res.display_num_of_h_tiles);
SDE_DEBUG("display_max_width %d rm->lm_max_width %d\n",
mode->hdisplay, rm->lm_max_width);
- SDE_DEBUG("num_lm %d topology_name %d\n", reqs->num_lm,
- reqs->top_name);
+ SDE_DEBUG("num_lm %d num_ctl %d topology_name %d\n", reqs->num_lm,
+ reqs->num_ctl, reqs->top_name);
MSM_EVT(rm->dev, mode->hdisplay, rm->lm_max_width);
MSM_EVT(rm->dev, reqs->num_lm, reqs->top_ctrl);
MSM_EVT(rm->dev, reqs->top_name, 0);