Merge "drm/msm/sde: add secure fb translation mode for writeback"
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index f27785f..537a883 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -176,6 +176,7 @@ enum msm_mdp_conn_property {
 	CONNECTOR_PROP_TOPOLOGY_CONTROL,
 	CONNECTOR_PROP_AUTOREFRESH,
 	CONNECTOR_PROP_LP,
+	CONNECTOR_PROP_FB_TRANSLATION_MODE,
 
 	/* total # of properties */
 	CONNECTOR_PROP_COUNT
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 946adbb..60a7e77 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -522,7 +522,6 @@ static void _sde_connector_destroy_fb(struct sde_connector *c_conn,
 		return;
 	}
 
-	msm_framebuffer_cleanup(c_state->out_fb, c_state->aspace);
 	drm_framebuffer_unreference(c_state->out_fb);
 	c_state->out_fb = NULL;
 
@@ -603,7 +602,6 @@ sde_connector_atomic_duplicate_state(struct drm_connector *connector)
 {
 	struct sde_connector *c_conn;
 	struct sde_connector_state *c_state, *c_oldstate;
-	int rc;
 
 	if (!connector || !connector->state) {
 		SDE_ERROR("invalid connector %pK\n", connector);
@@ -624,13 +622,8 @@ sde_connector_atomic_duplicate_state(struct drm_connector *connector)
 			&c_state->property_state, c_state->property_values);
 
 	/* additional handling for drm framebuffer objects */
-	if (c_state->out_fb) {
+	if (c_state->out_fb)
 		drm_framebuffer_reference(c_state->out_fb);
-		rc = msm_framebuffer_prepare(c_state->out_fb,
-				c_state->aspace);
-		if (rc)
-			SDE_ERROR("failed to prepare fb, %d\n", rc);
-	}
 
 	return &c_state->base;
 }
@@ -795,18 +788,6 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
 		} else {
 			msm_framebuffer_set_kmap(c_state->out_fb,
 					c_conn->fb_kmap);
-
-			if (c_state->out_fb->flags & DRM_MODE_FB_SECURE)
-				c_state->aspace =
-				c_conn->aspace[SDE_IOMMU_DOMAIN_SECURE];
-			else
-				c_state->aspace =
-				c_conn->aspace[SDE_IOMMU_DOMAIN_UNSECURE];
-
-			rc = msm_framebuffer_prepare(c_state->out_fb,
-					c_state->aspace);
-			if (rc)
-				SDE_ERROR("prep fb failed, %d\n", rc);
 		}
 		break;
 	default:
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 69c7e8b0..b44bfae 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -322,7 +322,6 @@ struct sde_connector {
  * struct sde_connector_state - private connector status structure
  * @base: Base drm connector structure
  * @out_fb: Pointer to output frame buffer, if applicable
- * @aspace: Address space for accessing frame buffer objects, if applicable
  * @property_state: Local storage for msm_prop properties
  * @property_values: Local cache of current connector property values
  * @rois: Regions of interest structure for mapping CRTC to Connector output
@@ -331,7 +330,6 @@ struct sde_connector {
 struct sde_connector_state {
 	struct drm_connector_state base;
 	struct drm_framebuffer *out_fb;
-	struct msm_gem_address_space *aspace;
 	struct msm_property_state property_state;
 	struct msm_property_value property_values[CONNECTOR_PROP_COUNT];
 
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index ae63aaad..5a78e4d 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -350,6 +350,8 @@ struct sde_encoder_phys_cmd {
  * @intf_cfg:		Interface hardware configuration
  * @wb_roi:		Writeback region-of-interest
  * @wb_fmt:		Writeback pixel format
+ * @wb_fb:		Pointer to current writeback framebuffer
+ * @wb_aspace:		Pointer to current writeback address space
  * @frame_count:	Counter of completed writeback operations
  * @kickoff_count:	Counter of issued writeback operations
  * @aspace:		address space identifier for non-secure/secure domain
@@ -372,6 +374,8 @@ struct sde_encoder_phys_wb {
 	struct sde_hw_intf_cfg intf_cfg;
 	struct sde_rect wb_roi;
 	const struct sde_format *wb_fmt;
+	struct drm_framebuffer *wb_fb;
+	struct msm_gem_address_space *wb_aspace;
 	u32 frame_count;
 	u32 kickoff_count;
 	struct msm_gem_address_space *aspace[SDE_IOMMU_DOMAIN_MAX];
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
index afef192..240e521 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
@@ -13,6 +13,7 @@
 
 #define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
 #include <linux/debugfs.h>
+#include <uapi/drm/sde_drm.h>
 
 #include "sde_encoder_phys.h"
 #include "sde_formats.h"
@@ -263,8 +264,10 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc,
 	const struct msm_format *format;
 	int ret;
 	struct msm_gem_address_space *aspace;
+	u32 fb_mode;
 
-	if (!phys_enc || !phys_enc->sde_kms || !phys_enc->sde_kms->catalog) {
+	if (!phys_enc || !phys_enc->sde_kms || !phys_enc->sde_kms->catalog ||
+			!phys_enc->connector) {
 		SDE_ERROR("invalid encoder\n");
 		return;
 	}
@@ -275,13 +278,32 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc,
 	memset(wb_cfg, 0, sizeof(struct sde_hw_wb_cfg));
 
 	wb_cfg->intf_mode = phys_enc->intf_mode;
-	wb_cfg->is_secure = (fb->flags & DRM_MODE_FB_SECURE) ? true : false;
+
+	fb_mode = sde_connector_get_property(phys_enc->connector->state,
+			CONNECTOR_PROP_FB_TRANSLATION_MODE);
+	if (phys_enc->enable_state == SDE_ENC_DISABLING)
+		wb_cfg->is_secure = false;
+	else if (fb_mode == SDE_DRM_FB_SEC)
+		wb_cfg->is_secure = true;
+	else
+		wb_cfg->is_secure = false;
+
 	aspace = (wb_cfg->is_secure) ?
 			wb_enc->aspace[SDE_IOMMU_DOMAIN_SECURE] :
 			wb_enc->aspace[SDE_IOMMU_DOMAIN_UNSECURE];
 
 	SDE_DEBUG("[fb_secure:%d]\n", wb_cfg->is_secure);
 
+	ret = msm_framebuffer_prepare(fb, aspace);
+	if (ret) {
+		SDE_ERROR("prep fb failed, %d\n", ret);
+		return;
+	}
+
+	/* cache framebuffer for cleanup in writeback done */
+	wb_enc->wb_fb = fb;
+	wb_enc->wb_aspace = aspace;
+
 	format = msm_framebuffer_format(fb);
 	if (!format) {
 		SDE_DEBUG("invalid format for fb\n");
@@ -577,6 +599,10 @@ static void sde_encoder_phys_wb_setup(
 
 	memset(wb_roi, 0, sizeof(struct sde_rect));
 
+	/* clear writeback framebuffer - will be updated in setup_fb */
+	wb_enc->wb_fb = NULL;
+	wb_enc->wb_aspace = NULL;
+
 	if (phys_enc->enable_state == SDE_ENC_DISABLING) {
 		fb = wb_enc->fb_disable;
 		wb_roi->w = 0;
@@ -874,6 +900,13 @@ static int sde_encoder_phys_wb_wait_for_commit_done(
 			wb_enc->wb_dev->wb_idx - WB_0, wb_time);
 	}
 
+	/* cleanup writeback framebuffer */
+	if (wb_enc->wb_fb && wb_enc->wb_aspace) {
+		msm_framebuffer_cleanup(wb_enc->wb_fb, wb_enc->wb_aspace);
+		wb_enc->wb_fb = NULL;
+		wb_enc->wb_aspace = NULL;
+	}
+
 	SDE_EVT32(DRMID(phys_enc->parent), WBID(wb_enc), wb_enc->frame_count,
 			wb_time, event, rc);
 
diff --git a/drivers/gpu/drm/msm/sde/sde_wb.c b/drivers/gpu/drm/msm/sde/sde_wb.c
index 145acea..576a8f3 100644
--- a/drivers/gpu/drm/msm/sde/sde_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_wb.c
@@ -13,6 +13,8 @@
 
 #define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
 
+#include <uapi/drm/sde_drm.h>
+
 #include "msm_kms.h"
 #include "sde_kms.h"
 #include "sde_wb.h"
@@ -318,6 +320,10 @@ int sde_wb_connector_post_init(struct drm_connector *connector,
 	struct sde_connector *c_conn;
 	struct sde_wb_device *wb_dev = display;
 	const struct sde_format_extended *format_list;
+	static const struct drm_prop_enum_list e_fb_translation_mode[] = {
+		{SDE_DRM_FB_NON_SEC, "non_sec"},
+		{SDE_DRM_FB_SEC, "sec"},
+	};
 
 	if (!connector || !info || !display || !wb_dev->wb_cfg) {
 		SDE_ERROR("invalid params\n");
@@ -342,6 +348,12 @@ int sde_wb_connector_post_init(struct drm_connector *connector,
 			0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_DST_W);
 	msm_property_install_range(&c_conn->property_info, "DST_H",
 			0x0, 0, UINT_MAX, 0, CONNECTOR_PROP_DST_H);
+	msm_property_install_enum(&c_conn->property_info,
+			"fb_translation_mode",
+			0x0,
+			0, e_fb_translation_mode,
+			ARRAY_SIZE(e_fb_translation_mode),
+			CONNECTOR_PROP_FB_TRANSLATION_MODE);
 
 	/*
 	 * Populate info buffer
diff --git a/include/uapi/drm/sde_drm.h b/include/uapi/drm/sde_drm.h
index 439a925..285508a 100644
--- a/include/uapi/drm/sde_drm.h
+++ b/include/uapi/drm/sde_drm.h
@@ -67,7 +67,7 @@
 #define SDE_DRM_BITMASK_COUNT       64
 
 /**
- * Framebuffer modes for "fb_translation_mode" PLANE property
+ * Framebuffer modes for "fb_translation_mode" PLANE and CONNECTOR property
  *
  * @SDE_DRM_FB_NON_SEC:          IOMMU configuration for this framebuffer mode
  *                               is non-secure domain and requires