Browse Source

disp: msm: sde: reserve dscs considering hw pairs

RM does not currently check dsc pairs while reserving, but
this could lead to an incompatible pair being allocated. The
hw restrictions are populated from dtsi and checked during
rm reservation.

Change-Id: If561e2bd64c7643ed9ee71a255242eab84576673
Signed-off-by: Nilaan Gunabalachandran <[email protected]>
Nilaan Gunabalachandran 6 năm trước cách đây
mục cha
commit
962d240b95

+ 8 - 1
msm/sde/sde_hw_catalog.c

@@ -297,6 +297,7 @@ enum {
 enum {
 enum {
 	DSC_OFF,
 	DSC_OFF,
 	DSC_LEN,
 	DSC_LEN,
+	DSC_PAIR_MASK,
 	DSC_PROP_MAX,
 	DSC_PROP_MAX,
 };
 };
 
 
@@ -684,6 +685,7 @@ static struct sde_prop_type pp_prop[] = {
 static struct sde_prop_type dsc_prop[] = {
 static struct sde_prop_type dsc_prop[] = {
 	{DSC_OFF, "qcom,sde-dsc-off", false, PROP_TYPE_U32_ARRAY},
 	{DSC_OFF, "qcom,sde-dsc-off", false, PROP_TYPE_U32_ARRAY},
 	{DSC_LEN, "qcom,sde-dsc-size", false, PROP_TYPE_U32},
 	{DSC_LEN, "qcom,sde-dsc-size", false, PROP_TYPE_U32},
+	{DSC_PAIR_MASK, "qcom,sde-dsc-pair-mask", false, PROP_TYPE_U32_ARRAY},
 };
 };
 
 
 static struct sde_prop_type cdm_prop[] = {
 static struct sde_prop_type cdm_prop[] = {
@@ -2559,7 +2561,7 @@ static int sde_dsc_parse_dt(struct device_node *np,
 	int rc, prop_count[MAX_BLOCKS], i;
 	int rc, prop_count[MAX_BLOCKS], i;
 	struct sde_prop_value *prop_value = NULL;
 	struct sde_prop_value *prop_value = NULL;
 	bool prop_exists[DSC_PROP_MAX];
 	bool prop_exists[DSC_PROP_MAX];
-	u32 off_count;
+	u32 off_count, dsc_pair_mask;
 	struct sde_dsc_cfg *dsc;
 	struct sde_dsc_cfg *dsc;
 
 
 	if (!sde_cfg) {
 	if (!sde_cfg) {
@@ -2600,6 +2602,11 @@ static int sde_dsc_parse_dt(struct device_node *np,
 
 
 		if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev))
 		if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev))
 			set_bit(SDE_DSC_OUTPUT_CTRL, &dsc->features);
 			set_bit(SDE_DSC_OUTPUT_CTRL, &dsc->features);
+
+		dsc_pair_mask = PROP_VALUE_ACCESS(prop_value,
+				DSC_PAIR_MASK, i);
+		if (dsc_pair_mask)
+			set_bit(dsc_pair_mask, dsc->dsc_pair_mask);
 	}
 	}
 
 
 end:
 end:

+ 3 - 0
msm/sde/sde_hw_catalog.h

@@ -13,6 +13,7 @@
 #include <linux/msm-bus.h>
 #include <linux/msm-bus.h>
 #include <linux/of_fdt.h>
 #include <linux/of_fdt.h>
 #include <drm/drmP.h>
 #include <drm/drmP.h>
+#include "sde_hw_mdss.h"
 
 
 /**
 /**
  * Max hardware block count: For ex: max 12 SSPP pipes or
  * Max hardware block count: For ex: max 12 SSPP pipes or
@@ -915,9 +916,11 @@ struct sde_pingpong_cfg  {
  * @base               register offset of this block
  * @base               register offset of this block
  * @len:               length of hardware block
  * @len:               length of hardware block
  * @features           bit mask identifying sub-blocks/features
  * @features           bit mask identifying sub-blocks/features
+ * @dsc_pair_mask:     Bitmask of DSCs that can be controlled by same CTL
  */
  */
 struct sde_dsc_cfg {
 struct sde_dsc_cfg {
 	SDE_HW_BLK_INFO;
 	SDE_HW_BLK_INFO;
+	DECLARE_BITMAP(dsc_pair_mask, DSC_MAX);
 };
 };
 
 
 /**
 /**

+ 82 - 15
msm/sde/sde_rm.c

@@ -1201,44 +1201,111 @@ static int _sde_rm_reserve_ctls(
 	return 0;
 	return 0;
 }
 }
 
 
+static bool _sde_rm_check_dsc(struct sde_rm *rm,
+		struct sde_rm_rsvp *rsvp,
+		struct sde_rm_hw_blk *dsc,
+		struct sde_rm_hw_blk *paired_dsc)
+{
+	const struct sde_dsc_cfg *dsc_cfg = to_sde_hw_dsc(dsc->hw)->caps;
+
+	/* Already reserved? */
+	if (RESERVED_BY_OTHER(dsc, rsvp)) {
+		SDE_DEBUG("dsc %d already reserved\n", dsc_cfg->id);
+		return false;
+	}
+
+	/* Check if this dsc is a peer of the proposed paired DSC */
+	if (paired_dsc) {
+		const struct sde_dsc_cfg *paired_dsc_cfg =
+				to_sde_hw_dsc(paired_dsc->hw)->caps;
+
+		if (!test_bit(dsc_cfg->id, paired_dsc_cfg->dsc_pair_mask)) {
+			SDE_DEBUG("dsc %d not peer of dsc %d\n", dsc_cfg->id,
+					paired_dsc_cfg->id);
+			return false;
+		}
+	}
+
+	return true;
+}
+
 static int _sde_rm_reserve_dsc(
 static int _sde_rm_reserve_dsc(
 		struct sde_rm *rm,
 		struct sde_rm *rm,
 		struct sde_rm_rsvp *rsvp,
 		struct sde_rm_rsvp *rsvp,
 		const struct sde_rm_topology_def *top,
 		const struct sde_rm_topology_def *top,
 		u8 *_dsc_ids)
 		u8 *_dsc_ids)
 {
 {
-	struct sde_rm_hw_iter iter;
+	struct sde_rm_hw_iter iter_i, iter_j;
+	struct sde_rm_hw_blk *dsc[MAX_BLOCKS];
 	int alloc_count = 0;
 	int alloc_count = 0;
-	int num_dsc_enc = top->num_lm;
+	int num_dsc_enc = top->num_comp_enc;
+	int i;
 
 
 	if (!top->num_comp_enc)
 	if (!top->num_comp_enc)
 		return 0;
 		return 0;
 
 
-	sde_rm_init_hw_iter(&iter, 0, SDE_HW_BLK_DSC);
+	sde_rm_init_hw_iter(&iter_i, 0, SDE_HW_BLK_DSC);
 
 
-	while (_sde_rm_get_hw_locked(rm, &iter)) {
-		if (RESERVED_BY_OTHER(iter.blk, rsvp))
+	/* Find a first DSC */
+	while (alloc_count != num_dsc_enc &&
+			_sde_rm_get_hw_locked(rm, &iter_i)) {
+		memset(&dsc, 0, sizeof(dsc));
+		alloc_count = 0;
+
+		if (_dsc_ids && (iter_i.blk->id != _dsc_ids[alloc_count]))
+			continue;
+
+		if (!_sde_rm_check_dsc(rm, rsvp, iter_i.blk, NULL))
 			continue;
 			continue;
 
 
 		SDE_DEBUG("blk id = %d, _dsc_ids[%d] = %d\n",
 		SDE_DEBUG("blk id = %d, _dsc_ids[%d] = %d\n",
-			iter.blk->id,
+			iter_i.blk->id,
 			alloc_count,
 			alloc_count,
 			_dsc_ids ? _dsc_ids[alloc_count] : -1);
 			_dsc_ids ? _dsc_ids[alloc_count] : -1);
 
 
-		if (_dsc_ids && (iter.blk->id != _dsc_ids[alloc_count]))
-			continue;
+		dsc[alloc_count++] = iter_i.blk;
 
 
-		iter.blk->rsvp_nxt = rsvp;
-		SDE_EVT32(iter.blk->type, rsvp->enc_id, iter.blk->id);
+		/* Valid first dsc found, find matching peers */
+		sde_rm_init_hw_iter(&iter_j, 0, SDE_HW_BLK_DSC);
 
 
-		if (++alloc_count == num_dsc_enc)
-			return 0;
+		while (alloc_count != num_dsc_enc &&
+				_sde_rm_get_hw_locked(rm, &iter_j)) {
+			if (iter_i.blk == iter_j.blk)
+				continue;
+
+			if (_dsc_ids && (iter_j.blk->id !=
+					_dsc_ids[alloc_count]))
+				continue;
+
+			if (!_sde_rm_check_dsc(rm, rsvp,
+					iter_j.blk, iter_i.blk))
+				continue;
+
+			SDE_DEBUG("blk id = %d, _dsc_ids[%d] = %d\n",
+				iter_j.blk->id,
+				alloc_count,
+				_dsc_ids ? _dsc_ids[alloc_count] : -1);
+
+			dsc[alloc_count++] = iter_j.blk;
+		}
 	}
 	}
 
 
-	SDE_ERROR("couldn't reserve %d dsc blocks for enc id %d\n",
-		num_dsc_enc, rsvp->enc_id);
+	if (alloc_count != num_dsc_enc) {
+		SDE_ERROR("couldn't reserve %d dsc blocks for enc id %d\n",
+			num_dsc_enc, rsvp->enc_id);
+		return -EINVAL;
+	}
 
 
-	return -ENAVAIL;
+	for (i = 0; i < ARRAY_SIZE(dsc); i++) {
+		if (!dsc[i])
+			break;
+
+		dsc[i]->rsvp_nxt = rsvp;
+
+		SDE_EVT32(dsc[i]->type, rsvp->enc_id, dsc[i]->id);
+	}
+
+	return 0;
 }
 }
 
 
 static int _sde_rm_reserve_qdss(
 static int _sde_rm_reserve_qdss(