Эх сурвалжийг харах

msm: sde: Add partial update support for demura

Demura HW block needs to be programmed with different sequence for
partial update use-cases. Change adds support for partial update
programming sequence.

Change-Id: I3ea38354b1120d7c545f6680562c47304cd1126b
Gopikrishnaiah Anandan 4 жил өмнө
parent
commit
9161487a45

+ 88 - 14
msm/sde/sde_color_processing.c

@@ -142,6 +142,7 @@ static void _lm_gc_install_property(struct drm_crtc *crtc);
 enum sde_cp_crtc_pu_features {
 	SDE_CP_CRTC_DSPP_RC_PU,
 	SDE_CP_CRTC_DSPP_SPR_PU,
+	SDE_CP_CRTC_DSPP_DEMURA_PU,
 	SDE_CP_CRTC_MAX_PU_FEATURES,
 };
 
@@ -149,6 +150,10 @@ static enum sde_cp_crtc_pu_features
 		sde_cp_crtc_pu_to_feature[SDE_CP_CRTC_MAX_PU_FEATURES] = {
 	[SDE_CP_CRTC_DSPP_RC_PU] =
 		(enum sde_cp_crtc_pu_features) SDE_CP_CRTC_DSPP_RC_MASK,
+	[SDE_CP_CRTC_DSPP_SPR_PU] =
+		(enum sde_cp_crtc_pu_features) SDE_CP_CRTC_DSPP_SPR_INIT,
+	[SDE_CP_CRTC_DSPP_DEMURA_PU] =
+		(enum sde_cp_crtc_pu_features) SDE_CP_CRTC_DSPP_DEMURA_INIT,
 };
 
 /* explicitly set the features that needs to be treated during handoff */
@@ -829,6 +834,20 @@ static int _set_spr_pu_feature(struct sde_hw_dspp *hw_dspp,
 	return 0;
 }
 
+static int _set_demura_pu_feature(struct sde_hw_dspp *hw_dspp,
+	struct sde_hw_cp_cfg *hw_cfg, struct sde_crtc *sde_crtc)
+{
+	if (!hw_dspp || !hw_cfg || !sde_crtc) {
+		DRM_ERROR("invalid argumets\n");
+		return -EINVAL;
+	}
+
+	if (hw_dspp->ops.setup_demura_pu_config)
+		hw_dspp->ops.setup_demura_pu_config(hw_dspp, hw_cfg);
+
+	return 0;
+}
+
 static int _check_spr_pu_feature(struct sde_hw_dspp *hw_dspp,
 	struct sde_hw_cp_cfg *hw_cfg, struct sde_crtc *sde_crtc)
 {
@@ -874,14 +893,17 @@ static int _set_spr_init_feature(struct sde_hw_dspp *hw_dspp,
 
 static int _set_demura_feature(struct sde_hw_dspp *hw_dspp,
 				   struct sde_hw_cp_cfg *hw_cfg,
-				   struct sde_crtc *hw_crtc)
+				   struct sde_crtc *sde_crtc)
 {
 	int ret = 0;
 
-	if (!hw_dspp || !hw_dspp->ops.setup_demura_cfg)
+	if (!hw_dspp || !hw_dspp->ops.setup_demura_cfg) {
 		ret = -EINVAL;
-	else
+	} else {
 		hw_dspp->ops.setup_demura_cfg(hw_dspp, hw_cfg);
+		_update_pu_feature_enable(sde_crtc, SDE_CP_CRTC_DSPP_DEMURA_PU,
+				hw_cfg->payload != NULL);
+	}
 
 	return ret;
 }
@@ -945,6 +967,7 @@ do { \
 	memset(wrappers, 0, sizeof(wrappers)); \
 	wrappers[SDE_CP_CRTC_DSPP_RC_PU] = _set_rc_pu_feature; \
 	wrappers[SDE_CP_CRTC_DSPP_SPR_PU] = _set_spr_pu_feature; \
+	wrappers[SDE_CP_CRTC_DSPP_DEMURA_PU] = _set_demura_pu_feature; \
 } while (0)
 
 feature_wrapper check_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES];
@@ -953,6 +976,7 @@ do { \
 	memset(wrappers, 0, sizeof(wrappers)); \
 	wrappers[SDE_CP_CRTC_DSPP_RC_PU] = _check_rc_pu_feature; \
 	wrappers[SDE_CP_CRTC_DSPP_SPR_PU] = _check_spr_pu_feature; \
+	wrappers[SDE_CP_CRTC_DSPP_DEMURA_PU] = _check_spr_pu_feature; \
 } while (0)
 
 #define INIT_PROP_ATTACH(p, crtc, prop, node, feature, val) \
@@ -1606,6 +1630,9 @@ static void _sde_cp_crtc_commit_feature(struct sde_cp_node *prop_node,
 	_sde_cp_get_cached_payload(prop_node, &hw_cfg, &feature_enabled);
 	hw_cfg.num_of_mixers = sde_crtc->num_mixers;
 	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;
+	SDE_EVT32(hw_cfg.panel_width, hw_cfg.panel_height);
 
 	for (i = 0; i < num_mixers; i++) {
 		hw_dspp = sde_crtc->mixers[i].hw_dspp;
@@ -1945,23 +1972,23 @@ static int _sde_cp_crtc_update_pu_features(struct drm_crtc *crtc, bool *need_flu
 		DRM_DEBUG_DRIVER("no partial update required\n");
 		memset(&sde_crtc_state->cached_user_roi_list, 0,
 				sizeof(struct msm_roi_list));
-		return 0;
-	}
-
-	sde_kms_rect_merge_rectangles(&sde_crtc_state->user_roi_list,
-			&user_rect);
-	sde_kms_rect_merge_rectangles(&sde_crtc_state->cached_user_roi_list,
-			&cached_rect);
-	if (sde_kms_rect_is_equal(&user_rect, &cached_rect)) {
-		DRM_DEBUG_DRIVER("no change in list of ROIs\n");
-		return 0;
+	} else {
+		sde_kms_rect_merge_rectangles(&sde_crtc_state->user_roi_list,
+				&user_rect);
+		sde_kms_rect_merge_rectangles(&sde_crtc_state->cached_user_roi_list,
+				&cached_rect);
+		if (sde_kms_rect_is_equal(&user_rect, &cached_rect)) {
+			DRM_DEBUG_DRIVER("no change in list of ROIs\n");
+			return 0;
+		}
 	}
 
 	catalog = get_kms(&sde_crtc->base)->catalog;
 	memset(&hw_cfg, 0, sizeof(hw_cfg));
 	hw_cfg.num_of_mixers = sde_crtc->num_mixers;
 	hw_cfg.broadcast_disabled = catalog->dma_cfg.broadcast_disabled;
-	hw_cfg.payload = &sde_crtc_state->user_roi_list;
+	hw_cfg.payload = (sde_crtc_state->user_roi_list.num_rects) ?
+		&sde_crtc_state->user_roi_list : NULL;
 	hw_cfg.len = sizeof(sde_crtc_state->user_roi_list);
 	for (i = 0; i < hw_cfg.num_of_mixers; i++)
 		hw_cfg.dspp[i] = sde_crtc->mixers[i].hw_dspp;
@@ -2315,6 +2342,7 @@ int sde_cp_crtc_set_property(struct drm_crtc *crtc,
 			prop_node->feature;
 	}
 	cstate->cp_prop_values[prop_node->feature].prop_val = val;
+	SDE_EVT32(prop_node->feature, val);
 	ret = _sde_cp_crtc_set_range_prop(cstate, prop_node,
 				property,
 				prop_node->feature, val);
@@ -2351,6 +2379,7 @@ static int _sde_cp_flush_properties(struct drm_crtc *crtc)
 		cstate->cp_prop_values[feature].prop = 0;
 		cstate->cp_prop_values[feature].cp_node = 0;
 		cstate->cp_prop_values[feature].prop_val = 0;
+		SDE_EVT32(feature, val);
 		_sde_cp_crtc_cache_property(crtc, cstate, prop_node,
 					property, val);
 	}
@@ -2562,6 +2591,50 @@ void sde_cp_crtc_resume(struct drm_crtc *crtc)
 	/* placeholder for operations needed during resume */
 }
 
+static void _sde_cp_disable_features(struct sde_crtc *sde_crtc)
+{
+	struct sde_hw_cp_cfg hw_cfg;
+	struct sde_hw_mixer *hw_lm;
+	struct sde_hw_dspp *hw_dspp;
+	feature_wrapper set_feature;
+	int i = 0, ret = 0;
+	u32 num_mixers = sde_crtc->num_mixers;
+
+	set_feature =
+		set_crtc_feature_wrappers[SDE_CP_CRTC_DSPP_DEMURA_INIT];
+	SDE_EVT32(num_mixers);
+	if (!set_feature)
+		return;
+
+	memset(&hw_cfg, 0, sizeof(hw_cfg));
+
+	for (i = 0; i < num_mixers; i++) {
+		hw_dspp = sde_crtc->mixers[i].hw_dspp;
+		if (!hw_dspp || i >= DSPP_MAX)
+			continue;
+		hw_cfg.dspp[i] = hw_dspp;
+	}
+
+	hw_cfg.payload = NULL;
+	for (i = 0; i < num_mixers && !ret; i++) {
+		hw_lm = sde_crtc->mixers[i].hw_lm;
+		hw_dspp = sde_crtc->mixers[i].hw_dspp;
+		if (!hw_lm) {
+			ret = -EINVAL;
+			continue;
+		}
+		hw_cfg.ctl = sde_crtc->mixers[i].hw_ctl;
+		hw_cfg.mixer_info = hw_lm;
+		hw_cfg.displayh = num_mixers * hw_lm->cfg.out_width;
+		hw_cfg.displayv = hw_lm->cfg.out_height;
+		hw_cfg.panel_height = sde_crtc->base.state->adjusted_mode.vdisplay;
+		hw_cfg.panel_width = sde_crtc->base.state->adjusted_mode.hdisplay;
+		ret = set_feature(hw_dspp, &hw_cfg, sde_crtc);
+		if (ret)
+			break;
+	}
+}
+
 void sde_cp_crtc_clear(struct drm_crtc *crtc)
 {
 	struct sde_crtc *sde_crtc = NULL;
@@ -2579,6 +2652,7 @@ void sde_cp_crtc_clear(struct drm_crtc *crtc)
 	}
 
 	mutex_lock(&sde_crtc->crtc_cp_lock);
+	_sde_cp_disable_features(sde_crtc);
 	list_del_init(&sde_crtc->cp_active_list);
 	list_del_init(&sde_crtc->cp_dirty_list);
 	list_del_init(&sde_crtc->ad_active);

+ 31 - 0
msm/sde/sde_hw_color_proc_v4.c

@@ -5,6 +5,7 @@
 #include <drm/msm_drm_pp.h>
 #include "sde_hw_color_proc_common_v4.h"
 #include "sde_hw_color_proc_v4.h"
+#include "sde_dbg.h"
 
 static int sde_write_3d_gamut(struct sde_hw_blk_reg_map *hw,
 		struct drm_msm_3d_gamut *payload, u32 base,
@@ -636,3 +637,33 @@ void sde_demura_read_plane_status(struct sde_hw_dspp *ctx, u32 *status)
 			*status = DEM_FETCH_DMA3_RECT1;
 	}
 }
+
+void sde_demura_pu_cfg(struct sde_hw_dspp *dspp, void *cfg)
+{
+	u32 demura_base;
+	struct sde_hw_cp_cfg *hw_cfg = cfg;
+	struct msm_roi_list *roi_list = NULL;
+	u32 temp;
+
+	if (!dspp) {
+		DRM_ERROR("invalid parameter ctx %pK", dspp);
+		return;
+	}
+	demura_base = dspp->cap->sblk->demura.base;
+	if (!cfg || !hw_cfg->payload) {
+		temp = 0;
+	} else {
+		roi_list = hw_cfg->payload;
+		if (hw_cfg->panel_width < hw_cfg->panel_height)
+			temp = (16 * (1 << 21)) / hw_cfg->panel_height;
+		else
+			temp = (8 * (1 << 21)) / hw_cfg->panel_height;
+		temp = temp * (roi_list->roi[0].y1);
+	}
+	SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->demura.base + 0x60,
+			temp);
+
+	SDE_EVT32(0x60, temp, dspp->idx, ((roi_list) ? roi_list->roi[0].y1 : -1),
+			((roi_list) ? roi_list->roi[0].y2 : -1),
+			((hw_cfg) ? hw_cfg->panel_height : -1));
+}

+ 7 - 0
msm/sde/sde_hw_color_proc_v4.h

@@ -121,4 +121,11 @@ void sde_setup_fp16_igcv1(struct sde_hw_pipe *ctx,
  */
 void sde_setup_fp16_unmultv1(struct sde_hw_pipe *ctx,
 		enum sde_sspp_multirect_index index, void *data);
+
+/**
+ * sde_demura_pu_cfg - api to set the partial update information for demura
+ * @ctx: pointer to dspp object.
+ * @cfg: partial update configuraton for the frame.
+*/
+void sde_demura_pu_cfg(struct sde_hw_dspp *ctx, void *cfg);
 #endif /* _SDE_HW_COLOR_PROC_V4_H_ */

+ 1 - 0
msm/sde/sde_hw_dspp.c

@@ -331,6 +331,7 @@ static void dspp_demura(struct sde_hw_dspp *c)
 					sde_demura_backlight_cfg;
 			c->ops.demura_read_plane_status =
 					sde_demura_read_plane_status;
+			c->ops.setup_demura_pu_config = sde_demura_pu_cfg;
 		}
 	}
 }

+ 6 - 0
msm/sde/sde_hw_dspp.h

@@ -283,6 +283,12 @@ struct sde_hw_dspp_ops {
 	 * @status: Demura plane used by DSPP. demura_fetch_planes enum value.
 	 */
 	void (*demura_read_plane_status)(struct sde_hw_dspp *ctx, u32 *status);
+	/**
+	 * setup_demura_pu_config - function to configure demura hw block pu offsets
+	 * @ctx: Pointer to dspp context
+	 * @cfg: Pointer to configuration
+	 */
+	void (*setup_demura_pu_config)(struct sde_hw_dspp *ctx, void *cfg);
 };
 
 /**

+ 4 - 0
msm/sde/sde_hw_mdss.h

@@ -582,6 +582,8 @@ struct sde_mdss_color {
  * @dspp[DSPP_MAX]: array of hw_dspp pointers associated with crtc.
  * @broadcast_disabled: flag indicating if broadcast should be avoided when
  *			using LUTDMA
+ * @panel_height: height of display panel in pixels.
+ * @panel_width: width of display panel in pixels.
  */
 struct sde_hw_cp_cfg {
 	void *payload;
@@ -594,6 +596,8 @@ struct sde_hw_cp_cfg {
 	u32 displayh;
 	struct sde_hw_dspp *dspp[DSPP_MAX];
 	bool broadcast_disabled;
+	u32 panel_height;
+	u32 panel_width;
 };
 
 /**

+ 29 - 27
msm/sde/sde_hw_reg_dma_v1_color_proc.c

@@ -4547,7 +4547,7 @@ void reg_dmav1_disable_spr(struct sde_hw_dspp *ctx, void *cfg)
 		DRM_ERROR("spr write decode select failed ret %d\n", rc);
 		return;
 	}
-
+	SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY);
 	reg_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base + 0x04;
 	REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, &reg,
 			sizeof(u32), REG_BLK_WRITE_SINGLE, 0, 0, 0);
@@ -4706,6 +4706,7 @@ void reg_dmav1_setup_spr_init_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
 		DRM_ERROR("failed to kick off ret %d\n", rc);
 		return;
 	}
+	SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
 }
 
 void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
@@ -4723,20 +4724,22 @@ void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
 		return;
 
 	if (!hw_cfg->payload || hw_cfg->len != sizeof(struct sde_drm_roi_v1)) {
-		DRM_ERROR("invalid payload of pu rects\n");
-		return;
-	}
-
-	roi_list = hw_cfg->payload;
-	if (roi_list->num_rects > 1) {
-		DRM_ERROR("multiple pu regions not supported with spr\n");
-		return;
-	}
+		DRM_DEBUG("invalid payload of pu rects\n");
+		reg = 0;
+	} else {
+		roi_list = hw_cfg->payload;
+		if (roi_list->num_rects > 1) {
+			DRM_ERROR("multiple pu regions not supported with spr\n");
+			return;
+		}
 
-	if ((roi_list->roi[0].x2 - roi_list->roi[0].x1) != hw_cfg->displayh) {
-		DRM_ERROR("pu region not full width %d\n",
-				(roi_list->roi[0].x2 - roi_list->roi[0].x1));
-		return;
+		if ((roi_list->roi[0].x2 - roi_list->roi[0].x1) != hw_cfg->displayh) {
+			DRM_ERROR("pu region not full width %d\n",
+					(roi_list->roi[0].x2 - roi_list->roi[0].x1));
+			return;
+		}
+		reg = APPLY_MASK_AND_SHIFT(roi_list->roi[0].x1, 16, 0) |
+			APPLY_MASK_AND_SHIFT(roi_list->roi[0].y1, 16, 16);
 	}
 
 	dma_ops = sde_reg_dma_get_ops();
@@ -4753,8 +4756,6 @@ void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
 
 	base_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base;
 	reg_off = base_off + 0x20;
-	reg = APPLY_MASK_AND_SHIFT(roi_list->roi[0].x1, 16, 0) |
-		APPLY_MASK_AND_SHIFT(roi_list->roi[0].y1, 16, 16);
 	REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, &reg,
 			sizeof(__u32), REG_SINGLE_WRITE, 0, 0, 0);
 
@@ -4773,6 +4774,7 @@ void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
 		DRM_ERROR("failed to kick off ret %d\n", rc);
 		return;
 	}
+	SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
 }
 
 static void reg_dma_demura_off(struct sde_hw_dspp *ctx,
@@ -4805,7 +4807,7 @@ static void reg_dma_demura_off(struct sde_hw_dspp *ctx,
 		DRM_ERROR("off(0x4): REG_SINGLE_WRITE failed ret %d\n", rc);
 		return;
 	}
-
+	SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY);
 	REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl,
 			dspp_buf[DEMURA_CFG][ctx->idx],
 			REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE,
@@ -4986,7 +4988,7 @@ static int __reg_dmav1_setup_demurav1_cfg0(struct sde_hw_dspp *ctx,
 			goto quit;
 	}
 
-	width = hw_cfg->displayh >> 1;
+	width = hw_cfg->panel_width >> 1;
 	DRM_DEBUG_DRIVER("0x80: value %x\n", width);
 	REG_DMA_SETUP_OPS(*dma_write_cfg, demura_base + 0x80,
 		&width, sizeof(width), REG_SINGLE_WRITE, 0, 0, 0);
@@ -5078,14 +5080,14 @@ static int __reg_dmav1_setup_demurav1_cfg1(struct sde_hw_dspp *ctx,
 		goto quit;
 	}
 
-	width = hw_cfg->displayh;
+	width = hw_cfg->panel_width;
 	DRM_DEBUG_DRIVER("width for LFC calculation is %d\n", width);
-	if (hw_cfg->displayh < hw_cfg->displayv) {
+	if (hw_cfg->panel_width < hw_cfg->panel_height) {
 		temp[0] = (8 * (1 << 21)) / width;
-		temp[1] = (16 * (1 << 21)) / hw_cfg->displayv;
+		temp[1] = (16 * (1 << 21)) / hw_cfg->panel_height;
 	} else {
 		temp[0] = (16 * (1 << 21)) / width;
-		temp[1] = (8 * (1 << 21)) / hw_cfg->displayv;
+		temp[1] = (8 * (1 << 21)) / hw_cfg->panel_height;
 	}
 	temp[0] = (dcfg->pentile) ? ((temp[0]) | BIT(31)) : temp[0];
 
@@ -5233,7 +5235,7 @@ static int __reg_dmav1_setup_demurav1_en(struct sde_hw_dspp *ctx,
 	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);
 	REG_DMA_SETUP_OPS(*dma_write_cfg, demura_base + 0x4,
 		&en, sizeof(en), REG_SINGLE_WRITE, 0, 0, 0);
 	rc = dma_ops->setup_payload(dma_write_cfg);
@@ -5258,12 +5260,12 @@ static int __reg_dmav1_setup_demurav1_dual_pipe(struct sde_hw_dspp *ctx,
 	if (dspp->idx == ctx->idx) {
 		temp = 0;
 	} else {
-		if (hw_cfg->displayh < hw_cfg->displayv)
-			temp = (8 * (1 << 21)) / hw_cfg->displayh;
+		if (hw_cfg->panel_width < hw_cfg->panel_height)
+			temp = (8 * (1 << 21)) / hw_cfg->panel_width;
 		else
-			temp = (16 * (1 << 21)) / hw_cfg->displayh;
+			temp = (16 * (1 << 21)) / hw_cfg->panel_width;
 
-		temp = temp * (hw_cfg->displayh >> 1);
+		temp = temp * (hw_cfg->panel_width >> 1);
 	}
 	REG_DMA_SETUP_OPS(*dma_write_cfg, demura_base + 0x58,
 		&temp, sizeof(temp), REG_SINGLE_WRITE, 0, 0, 0);