Kaynağa Gözat

Merge "disp: msm: sde: reserve dscs considering hw pairs"

qctecmdr 6 yıl önce
ebeveyn
işleme
ed6f9809d2
3 değiştirilmiş dosya ile 93 ekleme ve 16 silme
  1. 8 1
      msm/sde/sde_hw_catalog.c
  2. 3 0
      msm/sde/sde_hw_catalog.h
  3. 82 15
      msm/sde/sde_rm.c

+ 8 - 1
msm/sde/sde_hw_catalog.c

@@ -297,6 +297,7 @@ enum {
 enum {
 	DSC_OFF,
 	DSC_LEN,
+	DSC_PAIR_MASK,
 	DSC_PROP_MAX,
 };
 
@@ -684,6 +685,7 @@ static struct sde_prop_type pp_prop[] = {
 static struct sde_prop_type dsc_prop[] = {
 	{DSC_OFF, "qcom,sde-dsc-off", false, PROP_TYPE_U32_ARRAY},
 	{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[] = {
@@ -2559,7 +2561,7 @@ static int sde_dsc_parse_dt(struct device_node *np,
 	int rc, prop_count[MAX_BLOCKS], i;
 	struct sde_prop_value *prop_value = NULL;
 	bool prop_exists[DSC_PROP_MAX];
-	u32 off_count;
+	u32 off_count, dsc_pair_mask;
 	struct sde_dsc_cfg *dsc;
 
 	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))
 			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:

+ 3 - 0
msm/sde/sde_hw_catalog.h

@@ -13,6 +13,7 @@
 #include <linux/msm-bus.h>
 #include <linux/of_fdt.h>
 #include <drm/drmP.h>
+#include "sde_hw_mdss.h"
 
 /**
  * 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
  * @len:               length of hardware block
  * @features           bit mask identifying sub-blocks/features
+ * @dsc_pair_mask:     Bitmask of DSCs that can be controlled by same CTL
  */
 struct sde_dsc_cfg {
 	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;
 }
 
+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(
 		struct sde_rm *rm,
 		struct sde_rm_rsvp *rsvp,
 		const struct sde_rm_topology_def *top,
 		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 num_dsc_enc = top->num_lm;
+	int num_dsc_enc = top->num_comp_enc;
+	int i;
 
 	if (!top->num_comp_enc)
 		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;
 
 		SDE_DEBUG("blk id = %d, _dsc_ids[%d] = %d\n",
-			iter.blk->id,
+			iter_i.blk->id,
 			alloc_count,
 			_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(