drm/msm/sde: add prepare_commit callback to sde encoder

Allow the sde encoder to react to prepare_commit at the
beginning of an atomic commit sequence to support features like
autorefresh which need to be disabled before any other register
writes take place.

Change-Id: I2891eeba0cc9cdb6f3c6a5c2cc3542d74fa3ba1e
Signed-off-by: Lloyd Atkinson <latkinso@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 5ccd385..f6e1db6 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -2228,6 +2228,25 @@
 	return 0;
 }
 
+void sde_encoder_prepare_commit(struct drm_encoder *drm_enc)
+{
+	struct sde_encoder_virt *sde_enc;
+	struct sde_encoder_phys *phys;
+	int i;
+
+	if (!drm_enc) {
+		SDE_ERROR("invalid encoder\n");
+		return;
+	}
+	sde_enc = to_sde_encoder_virt(drm_enc);
+
+	for (i = 0; i < sde_enc->num_phys_encs; i++) {
+		phys = sde_enc->phys_encs[i];
+		if (phys && phys->ops.prepare_commit)
+			phys->ops.prepare_commit(phys);
+	}
+}
+
 #ifdef CONFIG_DEBUG_FS
 static int _sde_encoder_status_show(struct seq_file *s, void *data)
 {
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h
index d3a9bb4..28b6e1c 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.h
@@ -179,4 +179,11 @@
  */
 void sde_encoder_destroy(struct drm_encoder *drm_enc);
 
+/**
+ * sde_encoder_prepare_commit - prepare encoder at the very beginning of an
+ *	atomic commit, before any registers are written
+ * @drm_enc:    Pointer to previously created drm encoder structure
+ */
+void sde_encoder_prepare_commit(struct drm_encoder *drm_enc);
+
 #endif /* __SDE_ENCODER_H__ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index c2ef28d..4fd82da 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -94,6 +94,7 @@
  * struct sde_encoder_phys_ops - Interface the physical encoders provide to
  *	the containing virtual encoder.
  * @late_register:		DRM Call. Add Userspace interfaces, debugfs.
+ * @prepare_commit:		MSM Atomic Call, start of atomic commit sequence
  * @is_master:			Whether this phys_enc is the current master
  *				encoder. Can be switched at enable time. Based
  *				on split_role and current mode (CMD/VID).
@@ -127,6 +128,7 @@
 struct sde_encoder_phys_ops {
 	int (*late_register)(struct sde_encoder_phys *encoder,
 			struct dentry *debugfs_root);
+	void (*prepare_commit)(struct sde_encoder_phys *encoder);
 	bool (*is_master)(struct sde_encoder_phys *encoder);
 	bool (*mode_fixup)(struct sde_encoder_phys *encoder,
 			const struct drm_display_mode *mode,
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index 7adab09..a954b25 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -864,9 +864,15 @@
 	_sde_encoder_phys_cmd_update_flush_mask(phys_enc);
 }
 
+static void sde_encoder_phys_cmd_prepare_commit(
+		struct sde_encoder_phys *phys_enc)
+{
+}
+
 static void sde_encoder_phys_cmd_init_ops(
 		struct sde_encoder_phys_ops *ops)
 {
+	ops->prepare_commit = sde_encoder_phys_cmd_prepare_commit;
 	ops->is_master = sde_encoder_phys_cmd_is_master;
 	ops->mode_set = sde_encoder_phys_cmd_mode_set;
 	ops->mode_fixup = sde_encoder_phys_cmd_mode_fixup;
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index c783ab0..d33a5dc 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -353,16 +353,24 @@
 {
 	struct sde_kms *sde_kms;
 	struct msm_drm_private *priv;
+	struct drm_device *dev;
+	struct drm_encoder *encoder;
 
 	if (!kms)
 		return;
 	sde_kms = to_sde_kms(kms);
+	dev = sde_kms->dev;
 
-	if (!sde_kms->dev || !sde_kms->dev->dev_private)
+	if (!dev || !dev->dev_private)
 		return;
-	priv = sde_kms->dev->dev_private;
+	priv = dev->dev_private;
 
 	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+		if (encoder->crtc != NULL)
+			sde_encoder_prepare_commit(encoder);
+
 }
 
 static void sde_kms_commit(struct msm_kms *kms,