瀏覽代碼

disp: msm: sde: account for pref lm when exposing avail resources

If an external display, such as DP, requests for the available
resources, resource manager (RM) will provide a count of all unused
mixers. If the primary/secondary display(s) are not active, the RM
will report the associated preferred mixers as free resources.
However, RM will not allow preferred mixers to be allocated to other
displays. DP driver could look at these available resources and assume
a high resolution mode is possible and fail during resource allocation.

This change updates the available resources info API to account for
primary/secondary preferences while exposing available resources.

Change-Id: I134a1047f24ac9f1fcee695aa14a1d3e43c1571f
Signed-off-by: Nilaan Gunabalachandran <[email protected]>
Nilaan Gunabalachandran 3 年之前
父節點
當前提交
711eabbf43
共有 3 個文件被更改,包括 42 次插入4 次删除
  1. 9 0
      msm/sde/sde_encoder.c
  2. 10 2
      msm/sde/sde_encoder.h
  3. 23 2
      msm/sde/sde_rm.c

+ 9 - 0
msm/sde/sde_encoder.c

@@ -342,6 +342,15 @@ bool sde_encoder_is_primary_display(struct drm_encoder *drm_enc)
 		SDE_CONNECTOR_PRIMARY);
 }
 
+bool sde_encoder_is_built_in_display(struct drm_encoder *drm_enc)
+{
+	struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
+
+	return sde_enc &&
+		(sde_enc->disp_info.display_type == SDE_CONNECTOR_PRIMARY ||
+		sde_enc->disp_info.display_type == SDE_CONNECTOR_SECONDARY);
+}
+
 bool sde_encoder_is_dsi_display(struct drm_encoder *drm_enc)
 {
 	struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);

+ 10 - 2
msm/sde/sde_encoder.h

@@ -512,15 +512,23 @@ bool sde_encoder_is_cwb_disabling(struct drm_encoder *drm_enc,
  * sde_encoder_is_primary_display - checks if underlying display is primary
  *     display or not.
  * @drm_enc:    Pointer to drm encoder structure
- * @Return:     true if it is primary display. false if secondary display
+ * @Return:     true if it is primary display. false otherwise
  */
 bool sde_encoder_is_primary_display(struct drm_encoder *enc);
 
+/**
+ * sde_encoder_is_built_in_display - checks if underlying display is built in
+ *     display or not.
+ * @drm_enc:    Pointer to drm encoder structure
+ * @Return:     true if it is a built in display. false otherwise
+ */
+bool sde_encoder_is_built_in_display(struct drm_encoder *enc);
+
 /**
  * sde_encoder_is_dsi_display - checks if underlying display is DSI
  *     display or not.
  * @drm_enc:    Pointer to drm encoder structure
- * @Return:     true if it is primary display. false if secondary display
+ * @Return:     true if it is a dsi display. false otherwise
  */
 bool sde_encoder_is_dsi_display(struct drm_encoder *enc);
 

+ 23 - 2
msm/sde/sde_rm.c

@@ -277,19 +277,40 @@ void sde_rm_get_resource_info(struct sde_rm *rm,
 	struct sde_rm_hw_blk *blk;
 	enum sde_hw_blk_type type;
 	struct sde_rm_rsvp rsvp;
+	const struct sde_lm_cfg *lm_cfg;
+	bool is_built_in, is_pref;
+	u32 lm_pref = (BIT(SDE_DISP_PRIMARY_PREF) | BIT(SDE_DISP_SECONDARY_PREF));
 
+	/* Get all currently available resources */
 	memcpy(avail_res, &rm->avail_res,
 			sizeof(rm->avail_res));
 
 	if (!drm_enc)
 		return;
 
+	is_built_in = sde_encoder_is_built_in_display(drm_enc);
+
 	rsvp.enc_id = drm_enc->base.id;
 
-	for (type = 0; type < SDE_HW_BLK_MAX; type++)
-		list_for_each_entry(blk, &rm->hw_blks[type], list)
+	for (type = 0; type < SDE_HW_BLK_MAX; type++) {
+		list_for_each_entry(blk, &rm->hw_blks[type], list) {
+			/* Add back resources allocated to the given encoder */
 			if (blk->rsvp && blk->rsvp->enc_id == rsvp.enc_id)
 				_sde_rm_inc_resource_info(rm, avail_res, blk);
+
+			/**
+			 * Remove unallocated preferred lms that cannot reserved
+			 * by non built-in displays.
+			 */
+			if (type == SDE_HW_BLK_LM) {
+				lm_cfg = to_sde_hw_mixer(blk->hw)->cap;
+				is_pref = lm_cfg->features & lm_pref;
+
+				if (!blk->rsvp && !is_built_in && is_pref)
+					_sde_rm_dec_resource_info(rm, avail_res, blk);
+			}
+		}
+	}
 }
 
 static void _sde_rm_print_rsvps(