drm/msm/sde: enable MISR during secure-ui session

Enable MISR before transitioning into secure mode and
disable it while transitioning back to non-secure mode
based on secure-ui-misr feature flag set in the catalog.
Add a vote on the core-clks to make sure all the resources
are up and ensuring there is no power-collapse during the
session, so MISR can be read throughout the session.

Change-Id: I18f4fb6f60b3a64b3c28b05525224a59b08055a9
Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 1a1ebac..3a23fd9 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -1787,6 +1787,7 @@
 	struct drm_encoder *encoder;
 	struct sde_crtc *sde_crtc;
 	struct sde_kms *sde_kms;
+	struct sde_mdss_cfg *catalog;
 	struct sde_kms_smmu_state_data *smmu_state;
 	uint32_t translation_mode = 0, secure_level;
 	int ops  = 0;
@@ -1804,6 +1805,7 @@
 	smmu_state = &sde_kms->smmu_state;
 	sde_crtc = to_sde_crtc(crtc);
 	secure_level = sde_crtc_get_secure_level(crtc, crtc->state);
+	catalog = sde_kms->catalog;
 
 	SDE_DEBUG("crtc%d, secure_level%d old_valid_fb%d\n",
 			crtc->base.id, secure_level, old_valid_fb);
@@ -1858,6 +1860,9 @@
 				ops |= (SDE_KMS_OPS_WAIT_FOR_TX_DONE  |
 					SDE_KMS_OPS_CLEANUP_PLANE_FB);
 			}
+			if (catalog->sui_misr_supported)
+				smmu_state->sui_misr_state =
+						SUI_MISR_ENABLE_REQ;
 		/* secure camera usecase */
 		} else if (smmu_state->state == ATTACHED) {
 			smmu_state->state = DETACH_SEC_REQ;
@@ -1885,6 +1890,9 @@
 			if (old_valid_fb)
 				ops |= (SDE_KMS_OPS_WAIT_FOR_TX_DONE |
 				 SDE_KMS_OPS_CLEANUP_PLANE_FB);
+			if (catalog->sui_misr_supported)
+				smmu_state->sui_misr_state =
+						SUI_MISR_DISABLE_REQ;
 		}
 		break;
 
@@ -5295,6 +5303,46 @@
 	return ret;
 }
 
+void sde_crtc_misr_setup(struct drm_crtc *crtc, bool enable, u32 frame_count)
+{
+	struct sde_kms *sde_kms;
+	struct sde_crtc *sde_crtc;
+	struct sde_crtc_mixer *m;
+	int i;
+
+	if (!crtc) {
+		SDE_ERROR("invalid argument\n");
+		return;
+	}
+	sde_crtc = to_sde_crtc(crtc);
+
+	sde_kms = _sde_crtc_get_kms(crtc);
+	if (!sde_kms) {
+		SDE_ERROR("invalid sde_kms\n");
+		return;
+	}
+
+	mutex_lock(&sde_crtc->crtc_lock);
+	if (sde_kms_is_secure_session_inprogress(sde_kms)) {
+		SDE_DEBUG("crtc:%d misr enable/disable not allowed\n",
+				DRMID(crtc));
+		mutex_unlock(&sde_crtc->crtc_lock);
+		return;
+	}
+
+	sde_crtc->misr_enable = enable;
+	sde_crtc->misr_frame_count = frame_count;
+	for (i = 0; i < sde_crtc->num_mixers; ++i) {
+		sde_crtc->misr_data[i] = 0;
+		m = &sde_crtc->mixers[i];
+		if (!m->hw_lm || !m->hw_lm->ops.setup_misr)
+			continue;
+
+		m->hw_lm->ops.setup_misr(m->hw_lm, enable, frame_count);
+	}
+	mutex_unlock(&sde_crtc->crtc_lock);
+}
+
 #ifdef CONFIG_DEBUG_FS
 static int _sde_debugfs_status_show(struct seq_file *s, void *data)
 {
@@ -5442,9 +5490,9 @@
 static ssize_t _sde_crtc_misr_setup(struct file *file,
 		const char __user *user_buf, size_t count, loff_t *ppos)
 {
+	struct drm_crtc *crtc;
 	struct sde_crtc *sde_crtc;
-	struct sde_crtc_mixer *m;
-	int i = 0, rc;
+	int rc;
 	char buf[MISR_BUFF_SIZE + 1];
 	u32 frame_count, enable;
 	size_t buff_copy;
@@ -5453,6 +5501,8 @@
 		return -EINVAL;
 
 	sde_crtc = file->private_data;
+	crtc = &sde_crtc->base;
+
 	buff_copy = min_t(size_t, count, MISR_BUFF_SIZE);
 	if (copy_from_user(buf, user_buf, buff_copy)) {
 		SDE_ERROR("buffer copy failed\n");
@@ -5468,18 +5518,7 @@
 	if (rc)
 		return rc;
 
-	mutex_lock(&sde_crtc->crtc_lock);
-	sde_crtc->misr_enable = enable;
-	sde_crtc->misr_frame_count = frame_count;
-	for (i = 0; i < sde_crtc->num_mixers; ++i) {
-		sde_crtc->misr_data[i] = 0;
-		m = &sde_crtc->mixers[i];
-		if (!m->hw_lm || !m->hw_lm->ops.setup_misr)
-			continue;
-
-		m->hw_lm->ops.setup_misr(m->hw_lm, enable, frame_count);
-	}
-	mutex_unlock(&sde_crtc->crtc_lock);
+	sde_crtc_misr_setup(crtc, enable, frame_count);
 	_sde_crtc_power_enable(sde_crtc, false);
 
 	return count;
@@ -5488,7 +5527,9 @@
 static ssize_t _sde_crtc_misr_read(struct file *file,
 		char __user *user_buff, size_t count, loff_t *ppos)
 {
+	struct drm_crtc *crtc;
 	struct sde_crtc *sde_crtc;
+	struct sde_kms *sde_kms;
 	struct sde_crtc_mixer *m;
 	int i = 0, rc;
 	u32 misr_status;
@@ -5502,11 +5543,21 @@
 		return -EINVAL;
 
 	sde_crtc = file->private_data;
+	crtc = &sde_crtc->base;
+	sde_kms = _sde_crtc_get_kms(crtc);
+	if (!sde_kms)
+		return -EINVAL;
+
 	rc = _sde_crtc_power_enable(sde_crtc, true);
 	if (rc)
 		return rc;
 
 	mutex_lock(&sde_crtc->crtc_lock);
+	if (sde_kms_is_secure_session_inprogress(sde_kms)) {
+		SDE_DEBUG("crtc:%d misr read not allowed\n", DRMID(crtc));
+		goto end;
+	}
+
 	if (!sde_crtc->misr_enable) {
 		len += snprintf(buf + len, MISR_BUFF_SIZE - len,
 			"disabled\n");
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index d66812b..bc1614c 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -741,4 +741,12 @@
  */
 uint64_t sde_crtc_get_sbuf_clk(struct drm_crtc_state *state);
 
+/**
+ * sde_crtc_misr_setup - to configure and enable/disable MISR
+ * @crtc: Pointer to drm crtc structure
+ * @enable: boolean to indicate enable/disable misr
+ * @frame_count: frame_count to be configured
+ */
+void sde_crtc_misr_setup(struct drm_crtc *crtc, bool enable, u32 frame_count);
+
 #endif /* _SDE_CRTC_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 0bb61b3..0cb14d1 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -932,6 +932,7 @@
  * @wb_formats         Supported formats for wb
  * @vbif_qos_nlvl      number of vbif QoS priority level
  * @ts_prefill_rev     prefill traffic shaper feature revision
+ * @sui_misr_supported  indicate if secure-ui-misr is supported
  */
 struct sde_mdss_cfg {
 	u32 hwversion;
@@ -962,6 +963,8 @@
 	u32 vbif_qos_nlvl;
 	u32 ts_prefill_rev;
 
+	bool sui_misr_supported;
+
 	bool has_hdr;
 	u32 mdss_count;
 	struct sde_mdss_base_cfg mdss[MAX_BLOCKS];
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 2bdded6..652be26 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -546,6 +546,31 @@
 	return ret;
 }
 
+static int _sde_kms_sui_misr_ctrl(struct sde_kms *sde_kms,
+		struct drm_crtc *crtc, bool enable)
+{
+	struct drm_device *dev = sde_kms->dev;
+	struct msm_drm_private *priv = dev->dev_private;
+	int ret;
+
+	if (enable) {
+		ret = sde_power_resource_enable(&priv->phandle,
+					sde_kms->core_client, true);
+		if (ret) {
+			SDE_ERROR("failed to enable resource, ret:%d\n", ret);
+			return ret;
+		}
+		sde_crtc_misr_setup(crtc, true, 1);
+
+	} else {
+		sde_crtc_misr_setup(crtc, false, 0);
+		sde_power_resource_enable(&priv->phandle,
+					sde_kms->core_client, false);
+	}
+
+	return 0;
+}
+
 static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,
 		bool post_commit)
 {
@@ -559,13 +584,21 @@
 	}
 
 	SDE_EVT32(DRMID(crtc), smmu_state->state, smmu_state->transition_type,
-			post_commit, SDE_EVTLOG_FUNC_ENTRY);
+			post_commit, smmu_state->sui_misr_state,
+			SDE_EVTLOG_FUNC_ENTRY);
 
 	if ((!smmu_state->transition_type) ||
 	    ((smmu_state->transition_type == POST_COMMIT) && !post_commit))
 		/* Bail out */
 		return 0;
 
+	/* enable sui misr if requested, before the transition */
+	if (smmu_state->sui_misr_state == SUI_MISR_ENABLE_REQ) {
+		ret = _sde_kms_sui_misr_ctrl(sde_kms, crtc, true);
+		if (ret)
+			goto end;
+	}
+
 	mutex_lock(&sde_kms->secure_transition_lock);
 	switch (smmu_state->state) {
 	/* Secure UI use case enable */
@@ -605,6 +638,15 @@
 	}
 	mutex_unlock(&sde_kms->secure_transition_lock);
 
+	/* disable sui misr if requested, after the transition */
+	if (!ret && (smmu_state->sui_misr_state == SUI_MISR_DISABLE_REQ)) {
+		ret = _sde_kms_sui_misr_ctrl(sde_kms, crtc, false);
+		if (ret)
+			goto end;
+	}
+
+end:
+	smmu_state->sui_misr_state = NONE;
 	smmu_state->transition_type = NONE;
 	smmu_state->transition_error = ret ? true : false;
 
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index e4353e7..fa0d7f4 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -146,6 +146,18 @@
 };
 
 /**
+ * enum sde_kms_sui_misr_state: state request for enabling/disabling MISR
+ * @NONE: no request
+ * @ENABLE_SUI_MISR_REQ: request to enable sui MISR
+ * @DISABLE_SUI_MISR_REQ: request to disable sui MISR
+ */
+enum sde_kms_sui_misr_state {
+	SUI_MISR_NONE,
+	SUI_MISR_ENABLE_REQ,
+	SUI_MISR_DISABLE_REQ
+};
+
+/**
  * struct sde_kms_smmu_state_data: stores the smmu state and transition type
  * @state: current state of smmu context banks
  * @transition_type: transition request type
@@ -155,6 +167,7 @@
 	uint32_t state;
 	uint32_t transition_type;
 	uint32_t transition_error;
+	uint32_t sui_misr_state;
 };
 
 /*
@@ -351,8 +364,7 @@
 		return false;
 
 	mutex_lock(&sde_kms->secure_transition_lock);
-	if ((sde_kms->smmu_state.state == DETACHED) ||
-			(sde_kms->smmu_state.state == DETACH_ALL_REQ))
+	if (sde_kms->smmu_state.state == DETACHED)
 		ret = true;
 	mutex_unlock(&sde_kms->secure_transition_lock);