Selaa lähdekoodia

disp: msm: sde: expose system cache support for writeback

Add a custom cache_enable property in writeback connector to allow
user-mode to control the cache setting on a frame basis. Configure
the hw and activate/deactivate the llcc based on the property. The
custom property is added based on the availability of the system
cache for writeback.

Change-Id: I812b31955eb36c75c33ac279b56502a13f7cdcbf
Signed-off-by: Veera Sundaram Sankaran <[email protected]>
Veera Sundaram Sankaran 4 vuotta sitten
vanhempi
sitoutus
993f61c91d

+ 1 - 0
msm/msm_drv.h

@@ -230,6 +230,7 @@ enum msm_mdp_conn_property {
 	CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE,
 	CONNECTOR_PROP_SET_PANEL_MODE,
 	CONNECTOR_PROP_AVR_STEP,
+	CONNECTOR_PROP_CACHE_STATE,
 	CONNECTOR_PROP_DSC_MODE,
 
 	/* total # of properties */

+ 1 - 1
msm/sde/sde_crtc.c

@@ -7004,7 +7004,7 @@ static int _sde_crtc_init_events(struct sde_crtc *sde_crtc)
 }
 
 void sde_crtc_static_img_control(struct drm_crtc *crtc,
-		enum sde_crtc_cache_state state,
+		enum sde_sys_cache_state state,
 		bool is_vidmode)
 {
 	struct drm_plane *plane;

+ 2 - 20
msm/sde/sde_crtc.h

@@ -75,24 +75,6 @@ enum sde_crtc_idle_pc_state {
 	IDLE_PC_DISABLE,
 };
 
-/**
- * enum sde_crtc_cache_state: states of disp system cache
- * CACHE_STATE_DISABLED: sys cache has been disabled
- * CACHE_STATE_ENABLED: sys cache has been enabled
- * CACHE_STATE_NORMAL: sys cache is normal state
- * CACHE_STATE_PRE_CACHE: frame cache is being prepared
- * CACHE_STATE_FRAME_WRITE: sys cache is being written to
- * CACHE_STATE_FRAME_READ: sys cache is being read
- */
-enum sde_crtc_cache_state {
-	CACHE_STATE_DISABLED,
-	CACHE_STATE_ENABLED,
-	CACHE_STATE_NORMAL,
-	CACHE_STATE_PRE_CACHE,
-	CACHE_STATE_FRAME_WRITE,
-	CACHE_STATE_FRAME_READ
-};
-
 /**
  * enum sde_crtc_vm_req: request for VM operations
  * @VM_REQ_NONE: no request. Normal VM operations.
@@ -426,7 +408,7 @@ struct sde_crtc {
 	int target_bpp;
 
 	struct kthread_delayed_work static_cache_read_work;
-	enum sde_crtc_cache_state cache_state;
+	enum sde_sys_cache_state cache_state;
 
 	struct drm_property_blob *dspp_blob_info;
 	u32 cached_encoder_mask;
@@ -1031,7 +1013,7 @@ static inline void sde_crtc_set_bpp(struct sde_crtc *sde_crtc, int src_bpp,
  * @is_vidmode: if encoder is video mode
  */
 void sde_crtc_static_img_control(struct drm_crtc *crtc,
-		enum sde_crtc_cache_state state, bool is_vidmode);
+		enum sde_sys_cache_state state, bool is_vidmode);
 
 /**
  * sde_crtc_static_cache_read_kickoff - kickoff cache read work

+ 2 - 0
msm/sde/sde_encoder_phys.h

@@ -436,6 +436,7 @@ struct sde_encoder_phys_cmd {
  * @wb_dev:		Pointer to writeback device
  * @bo_disable:		Buffer object(s) to use during the disabling state
  * @fb_disable:		Frame buffer to use during the disabling state
+ * @sc_cfg:		Stores wb system cache config
  * @crtc		Pointer to drm_crtc
  * @prog_line:		Cached programmable line value used to trigger early wb-fence
  */
@@ -455,6 +456,7 @@ struct sde_encoder_phys_wb {
 	struct sde_wb_device *wb_dev;
 	struct drm_gem_object *bo_disable[SDE_MAX_PLANES];
 	struct drm_framebuffer *fb_disable;
+	struct sde_hw_wb_sc_cfg sc_cfg;
 	struct drm_crtc *crtc;
 	u32 prog_line;
 };

+ 58 - 0
msm/sde/sde_encoder_phys_wb.c

@@ -961,6 +961,49 @@ static int sde_encoder_phys_wb_atomic_check(
 	return rc;
 }
 
+static void _sde_encoder_phys_wb_setup_cache(struct sde_encoder_phys_wb *wb_enc)
+{
+	struct sde_wb_device *wb_dev = wb_enc->wb_dev;
+	struct drm_connector_state *state = wb_dev->connector->state;
+	struct sde_hw_wb *hw_wb = wb_enc->hw_wb;
+	struct sde_crtc *sde_crtc = to_sde_crtc(wb_enc->crtc);
+	struct sde_sc_cfg *sc_cfg = &hw_wb->catalog->sc_cfg[SDE_SYS_CACHE_DISP_WB];
+	struct sde_hw_wb_sc_cfg *cfg  = &wb_enc->sc_cfg;
+	u32 cache_enable;
+
+	if (!sc_cfg->has_sys_cache) {
+		SDE_DEBUG("sys cache feature not enabled\n");
+		return;
+	}
+
+	if (!hw_wb || !hw_wb->ops.setup_sys_cache) {
+		SDE_DEBUG("unsupported ops: setup_sys_cache WB %d\n", WBID(wb_enc));
+		return;
+	}
+
+	cache_enable = sde_connector_get_property(state, CONNECTOR_PROP_CACHE_STATE);
+
+	if (!cfg->wr_en && !cache_enable)
+		return;
+
+	cfg->wr_en = cache_enable;
+	cfg->flags = SYS_CACHE_EN_FLAG | SYS_CACHE_SCID;
+
+	if (cache_enable) {
+		cfg->wr_scid = sc_cfg->llcc_scid;
+		cfg->type = SDE_SYS_CACHE_DISP_WB;
+	} else {
+		cfg->wr_scid = 0x0;
+		cfg->type = SDE_SYS_CACHE_NONE;
+	}
+
+	sde_crtc->new_perf.llcc_active[SDE_SYS_CACHE_DISP_WB] = cache_enable;
+	sde_core_perf_crtc_update_llcc(wb_enc->crtc);
+
+	hw_wb->ops.setup_sys_cache(hw_wb, cfg);
+	SDE_EVT32(WBID(wb_enc), cfg->wr_scid, cfg->flags, cfg->type, cache_enable);
+}
+
 static void _sde_encoder_phys_wb_update_cwb_flush(
 		struct sde_encoder_phys *phys_enc, bool enable)
 {
@@ -1236,6 +1279,8 @@ static void sde_encoder_phys_wb_setup(
 
 	sde_encoder_phys_wb_setup_cdp(phys_enc, wb_enc->wb_fmt);
 
+	_sde_encoder_phys_wb_setup_cache(wb_enc);
+
 	_sde_encoder_phys_wb_setup_cwb(phys_enc, true);
 
 	_sde_encoder_phys_wb_setup_prog_line(phys_enc);
@@ -1915,6 +1960,8 @@ static void sde_encoder_phys_wb_disable(struct sde_encoder_phys *phys_enc)
 {
 	struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc);
 	struct sde_hw_wb *hw_wb = wb_enc->hw_wb;
+	struct sde_crtc *sde_crtc = to_sde_crtc(wb_enc->crtc);
+	int i;
 
 	if (phys_enc->enable_state == SDE_ENC_DISABLED) {
 		SDE_ERROR("encoder is already disabled\n");
@@ -1931,6 +1978,17 @@ static void sde_encoder_phys_wb_disable(struct sde_encoder_phys *phys_enc)
 		goto exit;
 	}
 
+	/* reset system cache properties */
+	if (wb_enc->sc_cfg.wr_en) {
+		memset(&wb_enc->sc_cfg, 0, sizeof(struct sde_hw_wb_sc_cfg));
+		if (hw_wb->ops.setup_sys_cache)
+			hw_wb->ops.setup_sys_cache(hw_wb, &wb_enc->sc_cfg);
+
+		for (i = 0; i < SDE_SYS_CACHE_MAX; i++)
+			sde_crtc->new_perf.llcc_active[i] = 0;
+		sde_core_perf_crtc_update_llcc(wb_enc->crtc);
+	}
+
 	if (phys_enc->in_clone_mode) {
 		_sde_encoder_phys_wb_setup_cwb(phys_enc, false);
 		_sde_encoder_phys_wb_update_cwb_flush(phys_enc, false);

+ 18 - 0
msm/sde/sde_hw_mdss.h

@@ -468,6 +468,24 @@ enum sde_3d_blend_mode {
 	BLEND_3D_MAX
 };
 
+/**
+ * enum sde_sys_cache_state: states of disp system cache
+ * CACHE_STATE_DISABLED: sys cache has been disabled
+ * CACHE_STATE_ENABLED: sys cache has been enabled
+ * CACHE_STATE_NORMAL: sys cache is normal state
+ * CACHE_STATE_PRE_CACHE: frame cache is being prepared
+ * CACHE_STATE_FRAME_WRITE: sys cache is being written to
+ * CACHE_STATE_FRAME_READ: sys cache is being read
+ */
+enum sde_sys_cache_state {
+	CACHE_STATE_DISABLED,
+	CACHE_STATE_ENABLED,
+	CACHE_STATE_NORMAL,
+	CACHE_STATE_PRE_CACHE,
+	CACHE_STATE_FRAME_WRITE,
+	CACHE_STATE_FRAME_READ
+};
+
 /** struct sde_format - defines the format configuration which
  * allows SDE HW to correctly fetch and decode the format
  * @base: base msm_format struture containing fourcc code

+ 1 - 1
msm/sde/sde_plane.c

@@ -2812,7 +2812,7 @@ static void _sde_plane_sspp_setup_sys_cache(struct sde_plane *psde,
 }
 
 void sde_plane_static_img_control(struct drm_plane *plane,
-		enum sde_crtc_cache_state state)
+		enum sde_sys_cache_state state)
 {
 	struct sde_plane *psde;
 	struct sde_plane_state *pstate;

+ 1 - 1
msm/sde/sde_plane.h

@@ -356,7 +356,7 @@ bool sde_plane_is_cache_required(struct drm_plane *plane,
  * @state: state to set
  */
 void sde_plane_static_img_control(struct drm_plane *plane,
-		enum sde_crtc_cache_state state);
+		enum sde_sys_cache_state state);
 
 void sde_plane_add_data_to_minidump_va(struct drm_plane *plane);
 #endif /* _SDE_PLANE_H_ */

+ 24 - 1
msm/sde/sde_wb.c

@@ -530,20 +530,43 @@ int sde_wb_connector_post_init(struct drm_connector *connector, void *display)
 {
 	struct sde_connector *c_conn;
 	struct sde_wb_device *wb_dev = display;
+	struct msm_drm_private *priv;
+	struct sde_kms *sde_kms;
+	struct sde_mdss_cfg *catalog;
+	struct sde_sc_cfg *sde_cfg;
 	static const struct drm_prop_enum_list e_fb_translation_mode[] = {
 		{SDE_DRM_FB_NON_SEC, "non_sec"},
 		{SDE_DRM_FB_SEC, "sec"},
 	};
+	static const struct drm_prop_enum_list e_cache_state[] = {
+		{CACHE_STATE_DISABLED, "cache_state_disabled"},
+		{CACHE_STATE_ENABLED, "cache_state_enabled"},
+	};
 
-	if (!connector || !display || !wb_dev->wb_cfg) {
+	if (!connector || !display || !wb_dev->wb_cfg || !wb_dev->drm_dev->dev_private) {
 		SDE_ERROR("invalid params\n");
 		return -EINVAL;
 	}
 
+	priv = wb_dev->drm_dev->dev_private;
+	sde_kms = to_sde_kms(priv->kms);
+	if (!sde_kms || !sde_kms->catalog) {
+		SDE_ERROR("invalid sde_kms\n");
+		return -EINVAL;
+	}
+
+	catalog = sde_kms->catalog;
+	sde_cfg = &catalog->sc_cfg[SDE_SYS_CACHE_DISP_WB];
+
 	c_conn = to_sde_connector(connector);
 	wb_dev->connector = connector;
 	wb_dev->detect_status = connector_status_connected;
 
+	if (sde_cfg->has_sys_cache)
+		msm_property_install_enum(&c_conn->property_info, "cache_state",
+			0x0, 0, e_cache_state, ARRAY_SIZE(e_cache_state),
+			0, CONNECTOR_PROP_CACHE_STATE);
+
 	/*
 	 * Add extra connector properties
 	 */