Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ebc5d6c7 authored by Prabhanjan Kandula's avatar Prabhanjan Kandula Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarPrabhanjan Kandula <pkandula@codeaurora.org>
parent d94c7aef
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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)
{
Loading