Browse Source

disp: msm: sde: add checks for hfc feature enablement of demura

HFC feature of demura needs a skip blend plane to be set. If skip blend
plane is not set and HFC feature is requested to be enabled, driver
should skip turning on HFC demura feature. Change adds checks to ensure
that HFC is always enabled with skip blend plane staged.

Change-Id: I923359c7cb143867660b4c1e667f56ed42fa51c9
Gopikrishnaiah Anandan 4 years ago
parent
commit
1d39b8a5a9

+ 37 - 0
msm/sde/sde_color_processing.c

@@ -1632,6 +1632,11 @@ static void _sde_cp_crtc_commit_feature(struct sde_cp_node *prop_node,
 	hw_cfg.last_feature = 0;
 	hw_cfg.panel_width = sde_crtc->base.state->adjusted_mode.hdisplay;
 	hw_cfg.panel_height = sde_crtc->base.state->adjusted_mode.vdisplay;
+	hw_cfg.valid_skip_blend_plane = sde_crtc->valid_skip_blend_plane;
+	hw_cfg.skip_blend_plane = sde_crtc->skip_blend_plane;
+	hw_cfg.skip_blend_plane_h = sde_crtc->skip_blend_plane_h;
+	hw_cfg.skip_blend_plane_w = sde_crtc->skip_blend_plane_w;
+
 	SDE_EVT32(hw_cfg.panel_width, hw_cfg.panel_height);
 
 	for (i = 0; i < num_mixers; i++) {
@@ -4709,6 +4714,10 @@ void sde_cp_crtc_disable(struct drm_crtc *drm_crtc)
 				&crtc->dspp_blob_info,
 			info->data, SDE_KMS_INFO_DATALEN(info),
 			CRTC_PROP_DSPP_INFO);
+	crtc->valid_skip_blend_plane = false;
+	crtc->skip_blend_plane = SSPP_NONE;
+	crtc->skip_blend_plane_h = 0;
+	crtc->skip_blend_plane_w = 0;
 	mutex_unlock(&crtc->crtc_cp_lock);
 	kfree(info);
 }
@@ -4770,3 +4779,31 @@ void sde_cp_duplicate_state_info(struct drm_crtc_state *drm_old_state,
 			  curr_state->cp_range_payload[i].len);
 	}
 }
+
+void sde_cp_set_skip_blend_plane_info(struct drm_crtc *drm_crtc,
+	struct sde_cp_crtc_skip_blend_plane *skip_blend)
+{
+	struct sde_crtc *crtc;
+
+	if (!drm_crtc || !skip_blend) {
+		DRM_ERROR("invalid crtc handle drm_crtc %pK skip_blend %pK\n",
+			drm_crtc, skip_blend);
+		return;
+	}
+	crtc = to_sde_crtc(drm_crtc);
+	mutex_lock(&crtc->crtc_cp_lock);
+	if (!skip_blend->valid_plane) {
+		crtc->valid_skip_blend_plane = false;
+		crtc->skip_blend_plane = SSPP_NONE;
+		crtc->skip_blend_plane_h = 0;
+		crtc->skip_blend_plane_w = 0;
+		mutex_unlock(&crtc->crtc_cp_lock);
+		return;
+	}
+	crtc->valid_skip_blend_plane = true;
+	crtc->skip_blend_plane = skip_blend->plane;
+	crtc->skip_blend_plane_h = skip_blend->height;
+	crtc->skip_blend_plane_w = skip_blend->width;
+	mutex_unlock(&crtc->crtc_cp_lock);
+}
+

+ 28 - 1
msm/sde/sde_color_processing.h

@@ -5,6 +5,7 @@
 
 #ifndef _SDE_COLOR_PROCESSING_H
 #define _SDE_COLOR_PROCESSING_H
+#include "sde_hw_mdss.h"
 #include <drm/drm_crtc.h>
 
 struct sde_irq_callback;
@@ -139,6 +140,21 @@ struct sde_cp_crtc_range_prop_payload {
 	u32 len;
 };
 
+/**
+ * struct sde_cp_crtc_skip_blend_plane: struct to define skip blend plane configuration
+ * @valid_plane: flag to indicate plane is valid
+ * @plane: plane that has been enabled and skipped blending
+ * @width: plane width
+ * @height: plane height
+ */
+
+struct sde_cp_crtc_skip_blend_plane {
+	bool valid_plane;
+	enum sde_sspp plane;
+	u32 width;
+	u32 height;
+};
+
 /**
  * sde_cp_crtc_init(): Initialize color processing lists for a crtc.
  *                     Should be called during crtc initialization.
@@ -330,7 +346,18 @@ void sde_cp_clear_state_info(struct drm_crtc_state *state);
  */
 void sde_cp_duplicate_state_info(struct drm_crtc_state *old_state,
 				struct drm_crtc_state *state);
-
+/**
+ * sde_cp_disable_features(): disable cp features
+ * @crtc: Pointer to drm_crtc.
+ */
 void sde_cp_disable_features(struct drm_crtc *crtc);
+/**
+ * sde_cp_set_skip_blend_plane_info(): set/clear the skip blend plane
+ * @crtc: Pointer to drm_crtc.
+ * @skip_blend: Pointer to sde_cp_crtc_skip_blend_plane
+ */
+
+void sde_cp_set_skip_blend_plane_info(struct drm_crtc *crtc,
+		struct sde_cp_crtc_skip_blend_plane *skip_blend);
 
 #endif /*_SDE_COLOR_PROCESSING_H */

+ 13 - 1
msm/sde/sde_crtc.c

@@ -1511,6 +1511,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
 	int i, mode, cnt = 0;
 	bool bg_alpha_enable = false;
 	u32 blend_type;
+	struct sde_cp_crtc_skip_blend_plane skip_blend_plane;
 	DECLARE_BITMAP(fetch_active, SSPP_MAX);
 
 	if (!sde_crtc || !crtc->state || !mixer) {
@@ -1564,6 +1565,14 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
 		blend_type = sde_plane_get_property(pstate,
 					PLANE_PROP_BLEND_OP);
 
+		if (blend_type == SDE_DRM_BLEND_OP_SKIP) {
+			skip_blend_plane.valid_plane = true;
+			skip_blend_plane.plane = sde_plane_pipe(plane);
+			skip_blend_plane.height = plane_crtc_roi.h;
+			skip_blend_plane.width = plane_crtc_roi.w;
+			sde_cp_set_skip_blend_plane_info(crtc, &skip_blend_plane);
+		}
+
 		if (blend_type != SDE_DRM_BLEND_OP_SKIP) {
 			if (pstate->stage == SDE_STAGE_BASE &&
 					format->alpha_enable)
@@ -4819,6 +4828,7 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc,
 	int rc = 0, multirect_count = 0, i, mixer_width, mixer_height;
 	int inc_sde_stage = 0;
 	struct sde_kms *kms;
+	u32 blend_type;
 
 	sde_crtc = to_sde_crtc(crtc);
 	cstate = to_sde_crtc_state(state);
@@ -4853,6 +4863,8 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc,
 		pstates[*cnt].stage = sde_plane_get_property(
 				pstates[*cnt].sde_pstate, PLANE_PROP_ZPOS);
 		pstates[*cnt].pipe_id = sde_plane_pipe(plane);
+		blend_type = sde_plane_get_property(pstates[*cnt].sde_pstate,
+			PLANE_PROP_BLEND_OP);
 
 		if (!kms->catalog->has_base_layer)
 			inc_sde_stage = SDE_STAGE_0;
@@ -4893,7 +4905,7 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc,
 			return -E2BIG;
 		}
 
-		if (cstate->num_ds_enabled &&
+		if (blend_type != SDE_DRM_BLEND_OP_SKIP && cstate->num_ds_enabled &&
 				((pstate->crtc_h > mixer_height) ||
 				(pstate->crtc_w > mixer_width))) {
 			SDE_ERROR("plane w/h:%x*%x > mixer w/h:%x*%x\n",

+ 10 - 0
msm/sde/sde_crtc.h

@@ -296,6 +296,11 @@ struct sde_crtc_misr_info {
  * @cache_state     : Current static image cache state
  * @dspp_blob_info  : blob containing dspp hw capability information
  * @cached_encoder_mask : cached encoder_mask for vblank work
+ * @valid_skip_blend_plane: flag to indicate if skip blend plane is valid
+ * @skip_blend_plane: enabled plane that has skip blending
+ * @skip_blend_plane_w: skip blend plane width
+ * @skip_blend_plane_h: skip blend plane height
+ *
  */
 struct sde_crtc {
 	struct drm_crtc base;
@@ -387,6 +392,11 @@ struct sde_crtc {
 
 	struct drm_property_blob *dspp_blob_info;
 	u32 cached_encoder_mask;
+
+	bool valid_skip_blend_plane;
+	enum sde_sspp skip_blend_plane;
+	u32 skip_blend_plane_w;
+	u32 skip_blend_plane_h;
 };
 
 enum sde_crtc_dirty_flags {

+ 8 - 0
msm/sde/sde_hw_mdss.h

@@ -584,6 +584,10 @@ struct sde_mdss_color {
  *			using LUTDMA
  * @panel_height: height of display panel in pixels.
  * @panel_width: width of display panel in pixels.
+ * @valid_skip_blend_plane: true if skip plane params are valid
+ * @skip_blend_plane: plane which has been skipped staging into layer mixer
+ * @skip_blend_plane_w: skip plane width
+ * @skip_blend_plane_h: skip plane height
  */
 struct sde_hw_cp_cfg {
 	void *payload;
@@ -598,6 +602,10 @@ struct sde_hw_cp_cfg {
 	bool broadcast_disabled;
 	u32 panel_height;
 	u32 panel_width;
+	bool valid_skip_blend_plane;
+	enum sde_sspp skip_blend_plane;
+	u32 skip_blend_plane_w;
+	u32 skip_blend_plane_h;
 };
 
 /**

+ 46 - 3
msm/sde/sde_hw_reg_dma_v1_color_proc.c

@@ -5260,14 +5260,54 @@ static int __reg_dmav1_setup_demurav1_cfg5(struct sde_hw_dspp *ctx,
 	return rc;
 }
 
+static bool __reg_dmav1_valid_hfc_en_cfg(struct drm_msm_dem_cfg *dcfg,
+			struct sde_hw_cp_cfg *hw_cfg)
+{
+	u32 h, w, temp;
+	if (!hw_cfg->valid_skip_blend_plane) {
+		DRM_ERROR("HFC plane not set\n");
+		return false;
+	}
+
+	h = hw_cfg->panel_height;
+	w = hw_cfg->panel_width;
+	temp = hw_cfg->panel_width / 2;
+	if (dcfg->pentile) {
+		w = dcfg->c0_depth * (temp / 2) + dcfg->c1_depth * temp +
+			dcfg->c2_depth * (temp / 2);
+		if (w % 32)
+			w = 32 - (w % 32) + w;
+		w = 2 * (w / 32);
+		w = w / (hw_cfg->num_of_mixers ? hw_cfg->num_of_mixers : 1);
+	}
+	if (h != hw_cfg->skip_blend_plane_h || w != hw_cfg->skip_blend_plane_w) {
+		DRM_ERROR("invalid hfc cfg exp h %d exp w %d act h %d act w %d\n",
+			h, w, hw_cfg->skip_blend_plane_h, hw_cfg->skip_blend_plane_w);
+		DRM_ERROR("c0_depth %d c1_depth %d c2 depth %d hw_cfg->panel_width %d\n",
+			dcfg->c0_depth, dcfg->c1_depth, dcfg->c2_depth, hw_cfg->panel_width);
+		return false;
+	}
+
+	if (dcfg->src_id == BIT(3) && hw_cfg->skip_blend_plane == SSPP_DMA3)
+		return true;
+
+	if (dcfg->src_id == BIT(1) && hw_cfg->skip_blend_plane == SSPP_DMA1)
+		return true;
+
+	DRM_ERROR("invalid HFC plane dcfg->src_id %d hw_cfg->skip_blend_plane %d\n",
+		dcfg->src_id, hw_cfg->skip_blend_plane);
+	return false;
+}
 
 static int __reg_dmav1_setup_demurav1_en(struct sde_hw_dspp *ctx,
 		struct drm_msm_dem_cfg *dcfg,
 		struct sde_reg_dma_setup_ops_cfg *dma_write_cfg,
-		struct sde_hw_reg_dma_ops *dma_ops)
+		struct sde_hw_reg_dma_ops *dma_ops,
+		struct sde_hw_cp_cfg *hw_cfg)
 {
 	u32 en = 0, backl;
 	int rc;
+	bool valid_hfc_cfg = false;
 	u32 demura_base = ctx->cap->sblk->demura.base + ctx->hw.blk_off;
 
 	backl = (1024 << 16) | 1024;
@@ -5288,7 +5328,10 @@ static int __reg_dmav1_setup_demurav1_en(struct sde_hw_dspp *ctx,
 	en |= (dcfg->cfg3_en) ? BIT(5) : 0;
 	en |= (dcfg->cfg4_en) ? BIT(4) : 0;
 	en |= (dcfg->cfg2_en) ? BIT(3) : 0;
-	en |= (dcfg->cfg0_en) ? BIT(2) : 0;
+	if (dcfg->cfg0_en)
+		valid_hfc_cfg = __reg_dmav1_valid_hfc_en_cfg(dcfg, hw_cfg);
+	if (valid_hfc_cfg)
+		en |= (dcfg->cfg0_en) ? BIT(2) : 0;
 	en |= (dcfg->cfg1_en) ? BIT(1) : 0;
 	DRM_DEBUG_DRIVER("demura en %x\n", en);
 	SDE_EVT32(en);
@@ -5404,7 +5447,7 @@ void reg_dmav1_setup_demurav1(struct sde_hw_dspp *ctx, void *cfx)
 	}
 
 	rc = __reg_dmav1_setup_demurav1_en(ctx, dcfg, &dma_write_cfg,
-			dma_ops);
+			dma_ops, hw_cfg);
 	if (rc) {
 		DRM_ERROR("failed setup_demurav1_en rc %d", rc);
 		return;

+ 6 - 1
msm/sde/sde_plane.c

@@ -3336,6 +3336,7 @@ static void _sde_plane_atomic_disable(struct drm_plane *plane,
 	struct drm_plane_state *state;
 	struct sde_plane_state *pstate;
 	u32 multirect_index = SDE_SSPP_RECT_0;
+	struct sde_cp_crtc_skip_blend_plane skip_blend_plane;
 	u32 blend_type;
 
 	if (!plane) {
@@ -3358,8 +3359,12 @@ static void _sde_plane_atomic_disable(struct drm_plane *plane,
 	/* some of the color features are dependent on plane with skip blend.
 	 * if skip blend plane is being disabled, we need to disable color properties.
 	*/
-	if (blend_type == SDE_DRM_BLEND_OP_SKIP && old_state->crtc)
+	if (blend_type == SDE_DRM_BLEND_OP_SKIP && old_state->crtc) {
+		skip_blend_plane.valid_plane = false;
+		skip_blend_plane.plane = SSPP_NONE;
+		sde_cp_set_skip_blend_plane_info(old_state->crtc, &skip_blend_plane);
 		sde_crtc_disable_cp_features(old_state->crtc);
+	}
 
 	SDE_EVT32(DRMID(plane), is_sde_plane_virtual(plane),
 			pstate->multirect_mode);