Explorar el Código

disp: msm: sde: add partial update support for spr block

This change adds support for regdma accelerated programming of
partial update offsets for SPR hw block and validation of ROI
during atomic check based on SPR hw block limitations.

Change-Id: I9e20af4ba7752e8a4af5e9738612c57603163744
Signed-off-by: Prabhanjan Kandula <[email protected]>
Prabhanjan Kandula hace 5 años
padre
commit
ebc5d6c7da

+ 44 - 0
msm/sde/sde_color_processing.c

@@ -185,6 +185,7 @@ enum sde_cp_crtc_features {
 
 enum sde_cp_crtc_pu_features {
 	SDE_CP_CRTC_DSPP_RC_PU,
+	SDE_CP_CRTC_DSPP_SPR_PU,
 	SDE_CP_CRTC_MAX_PU_FEATURES,
 };
 
@@ -814,6 +815,45 @@ static int check_rc_pu_feature(struct sde_hw_dspp *hw_dspp,
 	return ret;
 }
 
+static int set_spr_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_spr_pu_config)
+		hw_dspp->ops.setup_spr_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)
+{
+	struct msm_roi_list *roi_list;
+
+	if (!hw_cfg || hw_cfg->len != sizeof(struct sde_drm_roi_v1)) {
+		SDE_ERROR("invalid payload\n");
+		return -EINVAL;
+	}
+
+	roi_list = hw_cfg->payload;
+	if (roi_list->num_rects > 1) {
+		SDE_ERROR("multiple pu regions not supported with spr\n");
+		return -EINVAL;
+	}
+
+	if ((roi_list->roi[0].x2 - roi_list->roi[0].x1) != hw_cfg->displayh) {
+		SDE_ERROR("pu region not full width %d\n",
+				(roi_list->roi[0].x2 - roi_list->roi[0].x1));
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int set_spr_init_feature(struct sde_hw_dspp *hw_dspp,
 				struct sde_hw_cp_cfg *hw_cfg,
 				struct sde_crtc *sde_crtc)
@@ -825,6 +865,8 @@ static int set_spr_init_feature(struct sde_hw_dspp *hw_dspp,
 		ret = -EINVAL;
 	} else {
 		hw_dspp->ops.setup_spr_init_config(hw_dspp, hw_cfg);
+		update_pu_feature_enable(sde_crtc, SDE_CP_CRTC_DSPP_SPR_PU,
+				hw_cfg->payload != NULL);
 	}
 
 	return ret;
@@ -902,6 +944,7 @@ feature_wrapper set_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES];
 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; \
 } while (0)
 
 feature_wrapper check_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES];
@@ -909,6 +952,7 @@ feature_wrapper check_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES];
 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; \
 } while (0)
 
 #define INIT_PROP_ATTACH(p, crtc, prop, node, feature, val) \

+ 17 - 3
msm/sde/sde_hw_dspp.c

@@ -276,11 +276,25 @@ static void dspp_rc(struct sde_hw_dspp *c)
 
 static void dspp_spr(struct sde_hw_dspp *c)
 {
+	int ret = 0;
+
+	if (!c) {
+		SDE_ERROR("invalid arguments\n");
+		return;
+	}
+
+	c->ops.setup_spr_init_config = NULL;
+	c->ops.setup_spr_pu_config = NULL;
+
 	if (c->cap->sblk->spr.version == SDE_COLOR_PROCESS_VER(0x1, 0x0)) {
-		reg_dmav1_init_dspp_op_v4(SDE_DSPP_SPR, c->idx);
+		ret = reg_dmav1_init_dspp_op_v4(SDE_DSPP_SPR, c->idx);
+		if (ret) {
+			SDE_ERROR("regdma init failed for spr, ret %d\n", ret);
+			return;
+		}
+
 		c->ops.setup_spr_init_config = reg_dmav1_setup_spr_init_cfgv1;
-	} else {
-		c->ops.setup_spr_init_config = NULL;
+		c->ops.setup_spr_pu_config = reg_dmav1_setup_spr_pu_cfgv1;
 	}
 }
 

+ 6 - 0
msm/sde/sde_hw_dspp.h

@@ -257,6 +257,12 @@ struct sde_hw_dspp_ops {
 	 */
 	void (*setup_spr_init_config)(struct sde_hw_dspp *ctx, void *cfg);
 
+	/**
+	 * setup_spr_pu_config - function to configure spr hw block pu offsets
+	 * @ctx: Pointer to dspp context
+	 * @cfg: Pointer to configuration
+	 */
+	void (*setup_spr_pu_config)(struct sde_hw_dspp *ctx, void *cfg);
 	/**
 	 * setup_demura_cfg - function to program demura cfg
 	 * @ctx: Pointer to dspp context

+ 2 - 0
msm/sde/sde_hw_reg_dma_v1.c

@@ -827,6 +827,8 @@ int init_v12(struct sde_hw_reg_dma *cfg)
 			GRP_MDSS_HW_BLK_SELECT);
 	v1_supported[SPR_INIT] = (GRP_DSPP_HW_BLK_SELECT |
 			GRP_MDSS_HW_BLK_SELECT);
+	v1_supported[SPR_PU_CFG] = (GRP_DSPP_HW_BLK_SELECT |
+			GRP_MDSS_HW_BLK_SELECT);
 	v1_supported[DEMURA_CFG] = MDSS | DSPP0 | DSPP1;
 
 	return 0;

+ 77 - 0
msm/sde/sde_hw_reg_dma_v1_color_proc.c

@@ -139,6 +139,7 @@ static u32 feature_map[SDE_DSPP_MAX] = {
 	/* MEMCOLOR can be mapped to any MEMC_SKIN/SKY/FOLIAGE/PROT*/
 	[SDE_DSPP_MEMCOLOR] = MEMC_SKIN,
 	[SDE_DSPP_SIXZONE] = SIX_ZONE,
+	/* SPR can be mapped to SPR_INIT & SPR_PU_CFG */
 	[SDE_DSPP_SPR] = SPR_INIT,
 	[SDE_DSPP_DITHER] = REG_DMA_FEATURES_MAX,
 	[SDE_DSPP_HIST] = REG_DMA_FEATURES_MAX,
@@ -335,6 +336,16 @@ static int _reg_dma_init_dspp_feature_buf(int feature, enum sde_dspp idx)
 		rc = reg_dma_buf_init(
 			&dspp_buf[MEMC_PROT][idx],
 			feature_reg_dma_sz[feature]);
+	} else if (feature == SDE_DSPP_SPR) {
+		rc = reg_dma_buf_init(
+			&dspp_buf[SPR_INIT][idx],
+			feature_reg_dma_sz[feature]);
+		if (rc)
+			return rc;
+
+		rc = reg_dma_buf_init(
+			&dspp_buf[SPR_PU_CFG][idx],
+			feature_reg_dma_sz[feature]);
 	} else {
 		rc = reg_dma_buf_init(
 			&dspp_buf[feature_map[feature]][idx],
@@ -4698,6 +4709,72 @@ void reg_dmav1_setup_spr_init_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
 	}
 }
 
+void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
+{
+	struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
+	struct sde_hw_cp_cfg *hw_cfg = cfg;
+	struct sde_reg_dma_kickoff_cfg kick_off;
+	struct sde_hw_reg_dma_ops *dma_ops;
+	uint32_t reg, reg_off, base_off;
+	struct msm_roi_list *roi_list;
+	int rc = 0;
+
+	rc = reg_dma_dspp_check(ctx, cfg, SPR_PU_CFG);
+	if (rc)
+		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;
+	}
+
+	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;
+	}
+
+	dma_ops = sde_reg_dma_get_ops();
+	dma_ops->reset_reg_dma_buf(dspp_buf[SPR_PU_CFG][ctx->idx]);
+
+	REG_DMA_INIT_OPS(dma_write_cfg, MDSS, SPR_PU_CFG,
+			dspp_buf[SPR_PU_CFG][ctx->idx]);
+	REG_DMA_SETUP_OPS(dma_write_cfg, 0, NULL, 0, HW_BLK_SELECT, 0, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("spr write decode select failed ret %d\n", rc);
+		return;
+	}
+
+	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);
+
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("write pu config failed ret %d\n", rc);
+		return;
+	}
+
+	REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl,
+			dspp_buf[SPR_PU_CFG][ctx->idx],
+			REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE);
+	rc = dma_ops->kick_off(&kick_off);
+	if (rc) {
+		DRM_ERROR("failed to kick off ret %d\n", rc);
+		return;
+	}
+}
+
 static void reg_dma_demura_off(struct sde_hw_dspp *ctx,
 		struct sde_hw_cp_cfg *hw_cfg)
 {

+ 7 - 0
msm/sde/sde_hw_reg_dma_v1_color_proc.h

@@ -295,6 +295,13 @@ void reg_dmav2_setup_vig_gamutv61(struct sde_hw_pipe *ctx, void *cfg);
  */
 void reg_dmav1_setup_spr_init_cfgv1(struct sde_hw_dspp *ctx, void *cfg);
 
+/**
+ * reg_dmav1_setup_spr_pu_cfgv1 - function to configure spr pu through LUTDMA
+ * @ctx: Pointer to dspp context
+ * @cfg: Pointer to configuration
+ */
+void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg);
+
 /**
  * reg_dmav1_setup_demurav1() - function to set up the demurav1 configuration.
  * @ctx: dspp ctx info

+ 2 - 0
msm/sde/sde_reg_dma.h

@@ -55,6 +55,7 @@ enum sde_reg_dma_read_sel {
  * @HSIC: Hue, saturation and contrast
  * @GC: gamma correction
  * @SPR_INIT: Sub pixel rendering init feature
+ * @SPR_PU: Sub pixel rendering partial update feature
  * @LTM_INIT: LTM INIT
  * @LTM_ROI: LTM ROI
  * @LTM_VLUT: LTM VLUT
@@ -76,6 +77,7 @@ enum sde_reg_dma_features {
 	HSIC,
 	GC,
 	SPR_INIT,
+	SPR_PU_CFG,
 	LTM_INIT,
 	LTM_ROI,
 	LTM_VLUT,