Bladeren bron

Merge "disp: msm: sde: Add a new major version of sixzone in Kalama for SB LUTDMA"

qctecmdr 3 jaren geleden
bovenliggende
commit
4927d28629

+ 1 - 0
msm/sde/sde_color_processing.c

@@ -2937,6 +2937,7 @@ static void _dspp_sixzone_install_property(struct drm_crtc *crtc)
 	version = catalog->dspp[0].sblk->sixzone.version >> 16;
 	switch (version) {
 	case 1:
+	case 2:
 		snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d",
 			"SDE_DSPP_PA_SIXZONE_V", version);
 		_sde_cp_crtc_install_blob_property(crtc, feature_name,

+ 6 - 0
msm/sde/sde_hw_color_proc_common_v4.h

@@ -99,6 +99,7 @@ enum {
 #define PA_SIXZONE_HUE_EN BIT(29)
 #define PA_SIXZONE_SAT_EN BIT(30)
 #define PA_SIXZONE_VAL_EN BIT(31)
+#define PA_SIXZONE_SV_EN BIT(0)
 
 #define PA_HIST_EN BIT(16)
 
@@ -127,6 +128,11 @@ enum {
 
 #define SIXZONE_ADJ_CURVE_P1_OFF 0x4
 #define SIXZONE_THRESHOLDS_OFF 0x8
+#define SIXZONE_ADJ_PWL0_OFF 0xC
+#define SIXZONE_ADJ_PWL1_OFF 0x10
+#define SIXZONE_SAT_PWL0_OFF 0x14
+#define SIXZONE_SAT_PWL1_OFF 0x18
+#define SIXZONE_SV_CTL_OFF 0x20
 
 #define MEMCOL_SIZE0 20
 #define MEMCOL_SIZE1 8

+ 6 - 0
msm/sde/sde_hw_dspp.c

@@ -151,6 +151,12 @@ static void dspp_sixzone(struct sde_hw_dspp *c)
 			c->ops.setup_sixzone = reg_dmav1_setup_dspp_sixzonev17;
 		else
 			c->ops.setup_sixzone = sde_setup_dspp_sixzone_v17;
+	} else if (c->cap->sblk->sixzone.version ==
+			SDE_COLOR_PROCESS_VER(0x2, 0x0)) {
+		c->ops.setup_sixzone = NULL;
+		ret = reg_dmav2_init_dspp_op_v4(SDE_DSPP_SIXZONE, c->idx);
+		if (!ret)
+			c->ops.setup_sixzone = reg_dmav2_setup_dspp_sixzonev2;
 	}
 }
 

+ 2 - 1
msm/sde/sde_hw_reg_dma_v1.c

@@ -443,7 +443,8 @@ static int validate_blk_lut_write(struct sde_reg_dma_setup_ops_cfg *cfg)
 	if (cfg->table_sel >= LUTBUS_TABLE_SELECT_MAX ||
 			cfg->block_sel >= LUTBUS_BLOCK_MAX ||
 			(cfg->trans_size != LUTBUS_IGC_TRANS_SIZE &&
-			cfg->trans_size != LUTBUS_GAMUT_TRANS_SIZE)) {
+			cfg->trans_size != LUTBUS_GAMUT_TRANS_SIZE &&
+			cfg->trans_size != LUTBUS_SIXZONE_TRANS_SIZE)) {
 		DRM_ERROR("invalid table_sel %d block_sel %d trans_size %d\n",
 				cfg->table_sel, cfg->block_sel,
 				cfg->trans_size);

+ 197 - 2
msm/sde/sde_hw_reg_dma_v1_color_proc.c

@@ -262,6 +262,10 @@ static int reg_dma_sspp_check(struct sde_hw_pipe *ctx, void *cfg,
 		enum sde_sspp_multirect_index idx);
 static int reg_dma_ltm_check(struct sde_hw_dspp *ctx, void *cfg,
 		enum sde_reg_dma_features feature);
+static void _perform_sbdma_kickoff(struct sde_hw_dspp *ctx,
+		struct sde_hw_cp_cfg *hw_cfg,
+		struct sde_hw_reg_dma_ops *dma_ops,
+		u32 blk, enum sde_reg_dma_features feature);
 
 static int reg_dma_buf_init(struct sde_reg_dma_buffer **buf, u32 size)
 {
@@ -1766,6 +1770,198 @@ void reg_dmav1_setup_dspp_sixzonev17(struct sde_hw_dspp *ctx, void *cfg)
 		DRM_ERROR("failed to kick off ret %d\n", rc);
 }
 
+void reg_dmav2_setup_dspp_sixzonev2(struct sde_hw_dspp *ctx, void *cfg)
+{
+	struct sde_hw_reg_dma_ops *dma_ops;
+	struct sde_hw_cp_cfg *hw_cfg = cfg;
+	struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
+	struct drm_msm_sixzone *sixzone;
+	struct sde_hw_dspp *dspp_list[DSPP_MAX];
+	u32 local_opcode = 0, local_hold = 0, sv_ctl = 0;
+	u32 num_of_mixers, blk = 0, len, transfer_size_bytes;
+	u16 *data = NULL;
+	int i, rc, j, k;
+
+	rc = reg_dma_validate_sixzone_config(ctx, cfg, &num_of_mixers, &blk, dspp_list);
+	if (rc) {
+		return;
+	}
+
+	sixzone = hw_cfg->payload;
+
+	dma_ops = sde_reg_dma_get_ops();
+	dma_ops->reset_reg_dma_buf(dspp_buf[SIX_ZONE][ctx->idx]);
+
+	REG_DMA_INIT_OPS(dma_write_cfg, blk, SIX_ZONE,
+		dspp_buf[SIX_ZONE][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("write decode select for sixzone failed ret %d\n", rc);
+		return;
+	}
+
+	/* 384 LUT entries * 5 components (hue, sat_low, sat_med, sat_high, value)
+	* 16 bit per LUT entry */
+	len = SIXZONE_LUT_SIZE * 5 * sizeof(u16);
+	/* Data size must be aligned with word size AND LUT transfer size */
+	transfer_size_bytes = LUTBUS_SIXZONE_TRANS_SIZE * sizeof(u32);
+	if (len % transfer_size_bytes)
+		len = len + (transfer_size_bytes - len % transfer_size_bytes);
+
+	data = kvzalloc(len, GFP_KERNEL);
+	if (!data) {
+		DRM_ERROR("Allocating memory for sixzone data failed!");
+		return;
+	}
+
+	for (j = 0, k = 0; j < SIXZONE_LUT_SIZE; j++) {
+		/* p0 --> hue, p1 --> sat_low/value, p2 --> sat_mid/sat_high */
+		/* 16 bit per LUT entry and MSB aligned to allow expansion,
+		* hence, sw need to left shift 4 bits before sending to HW.
+		*/
+		data[k++] = (u16) (sixzone->curve[j].p0 << 4);
+		data[k++] = (u16) ((sixzone->curve[j].p1 >> 16) << 4);
+		data[k++] = (u16) (sixzone->curve_p2[j] << 4);
+		data[k++] = (u16) ((sixzone->curve_p2[j] >> 16) << 4);
+		data[k++] = (u16) (sixzone->curve[j].p1 << 4);
+	}
+
+	REG_DMA_SETUP_OPS(dma_write_cfg, 0, (u32 *)data, len,
+			REG_BLK_LUT_WRITE, 0, 0, 0);
+	/* table select is only relevant to SSPP Gamut */
+	dma_write_cfg.table_sel = 0;
+	dma_write_cfg.block_sel = LUTBUS_BLOCK_SIXZONE;
+	dma_write_cfg.trans_size = LUTBUS_SIXZONE_TRANS_SIZE;
+	dma_write_cfg.lut_size = len / transfer_size_bytes;
+
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("lut write for sixzone failed ret %d\n", rc);
+		goto exit;
+	}
+
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->sixzone.base + SIXZONE_THRESHOLDS_OFF,
+		&sixzone->threshold, sizeof(u32),
+		REG_SINGLE_WRITE, 0, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("write sixzone threshold failed ret %d\n", rc);
+		goto exit;
+	}
+
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->sixzone.base + SIXZONE_ADJ_PWL0_OFF,
+		&sixzone->adjust_p0, sizeof(u32),
+		REG_SINGLE_WRITE, 0, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("write sixzone adjust p0 failed ret %d\n", rc);
+		goto exit;
+	}
+
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->sixzone.base + SIXZONE_ADJ_PWL1_OFF,
+		&sixzone->adjust_p1, sizeof(u32),
+		REG_SINGLE_WRITE, 0, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("write sixzone adjust p1 failed ret %d\n", rc);
+		goto exit;
+	}
+
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->sixzone.base + SIXZONE_SAT_PWL0_OFF,
+		&sixzone->sat_adjust_p0, sizeof(u32),
+		REG_SINGLE_WRITE, 0, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("write sixzone saturation adjust p0 failed ret %d\n", rc);
+		goto exit;
+	}
+
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->sixzone.base + SIXZONE_SAT_PWL1_OFF,
+		&sixzone->sat_adjust_p1, sizeof(u32),
+		REG_SINGLE_WRITE, 0, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("write sixzone saturation adjust p1 failed ret %d\n", rc);
+		goto exit;
+	}
+
+	if (sixzone->flags & SIXZONE_SV_ENABLE) {
+		sv_ctl |= PA_SIXZONE_SV_EN;
+	}
+
+	REG_DMA_SETUP_OPS(dma_write_cfg,
+		ctx->cap->sblk->sixzone.base + SIXZONE_SV_CTL_OFF,
+		&sv_ctl, sizeof(sv_ctl), REG_SINGLE_WRITE, 0, 0, 0);
+	rc = dma_ops->setup_payload(&dma_write_cfg);
+	if (rc) {
+		DRM_ERROR("sv enable write failed for sixzone ret %d\n", rc);
+		goto exit;
+	}
+
+	local_hold = ((sixzone->sat_hold & REG_MASK(2)) << 12);
+	local_hold |= ((sixzone->val_hold & REG_MASK(2)) << 14);
+	if (sixzone->flags & SIXZONE_HUE_ENABLE)
+		local_opcode |= PA_SIXZONE_HUE_EN;
+	if (sixzone->flags & SIXZONE_SAT_ENABLE)
+		local_opcode |= PA_SIXZONE_SAT_EN;
+	if (sixzone->flags & SIXZONE_VAL_ENABLE)
+		local_opcode |= PA_SIXZONE_VAL_EN;
+
+	if (local_opcode) {
+		local_opcode |= PA_EN;
+	} else {
+		DRM_ERROR("Invalid six zone config 0x%x\n", local_opcode);
+		goto exit;
+	}
+
+	for (i = 0; i < num_of_mixers; i++) {
+		blk = dspp_mapping[dspp_list[i]->idx];
+		REG_DMA_INIT_OPS(dma_write_cfg, blk, SIX_ZONE,
+			dspp_buf[SIX_ZONE][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("write decode select failed for sixzone ret %d\n", rc);
+			goto exit;
+		}
+
+		REG_DMA_SETUP_OPS(dma_write_cfg,
+			ctx->cap->sblk->hsic.base + PA_PWL_HOLD_OFF, &local_hold,
+			sizeof(local_hold), REG_SINGLE_MODIFY, 0, 0,
+			REG_DMA_PA_PWL_HOLD_SZONE_MASK);
+		rc = dma_ops->setup_payload(&dma_write_cfg);
+		if (rc) {
+			DRM_ERROR("setting local_hold failed for sixzone ret %d\n", rc);
+			goto exit;
+		}
+
+		REG_DMA_SETUP_OPS(dma_write_cfg,
+			ctx->cap->sblk->hsic.base, &local_opcode,
+			sizeof(local_opcode), REG_SINGLE_MODIFY, 0, 0,
+			REG_DMA_PA_MODE_SZONE_MASK);
+		rc = dma_ops->setup_payload(&dma_write_cfg);
+		if (rc) {
+			DRM_ERROR("setting local_opcode failed for sixzone ret %d\n", rc);
+			goto exit;
+		}
+	}
+
+	LOG_FEATURE_ON;
+	_perform_sbdma_kickoff(ctx, hw_cfg, dma_ops, blk, SIX_ZONE);
+
+exit:
+	kvfree(data);
+}
+
 int reg_dmav1_deinit_dspp_ops(enum sde_dspp idx)
 {
 	int i;
@@ -4097,7 +4293,6 @@ int reg_dmav2_init_dspp_op_v4(int feature, enum sde_dspp idx)
 	return rc;
 }
 
-
 /* Attempt to submit a feature buffer to SB DMA.
  * Note that if SB DMA is not supported, this function
  * will quitely attempt to fallback to DB DMA
@@ -4110,7 +4305,7 @@ static void _perform_sbdma_kickoff(struct sde_hw_dspp *ctx,
 	int rc, i;
 	struct sde_reg_dma_kickoff_cfg kick_off;
 
-	if ((feature != GAMUT && feature != IGC) ||
+	if ((feature != GAMUT && feature != IGC && feature != SIX_ZONE) ||
 			!(blk & (DSPP0 | DSPP1 | DSPP2 | DSPP3))) {
 		DRM_ERROR("SB DMA invalid for feature / block - %d/%d\n",
 				feature, blk);

+ 7 - 0
msm/sde/sde_hw_reg_dma_v1_color_proc.h

@@ -91,6 +91,13 @@ void reg_dmav1_setup_dspp_pa_hsicv17(struct sde_hw_dspp *ctx, void *cfg);
  */
 void reg_dmav1_setup_dspp_sixzonev17(struct sde_hw_dspp *ctx, void *cfg);
 
+/**
+ * reg_dmav2_setup_dspp_sixzonev2() - sixzone v2 impl using reg dma v2.
+ * @ctx: dspp ctx info
+ * @cfg: pointer to struct sde_hw_cp_cfg
+ */
+void reg_dmav2_setup_dspp_sixzonev2(struct sde_hw_dspp *ctx, void *cfg);
+
 /**
  * reg_dmav1_setup_dspp_memcol_skinv17() - memcol skin v17 impl using
  * reg dma v1.

+ 3 - 0
msm/sde/sde_reg_dma.h

@@ -102,16 +102,19 @@ enum sde_reg_dma_queue {
 #define LUTBUS_TABLE_SELECT_MAX 2
 #define LUTBUS_IGC_TRANS_SIZE 3
 #define LUTBUS_GAMUT_TRANS_SIZE 6
+#define LUTBUS_SIXZONE_TRANS_SIZE 5
 
 /**
  * enum sde_reg_dma_lutbus_block - block select values for lutbus op
  * @LUTBUS_BLOCK_IGC: select IGC block
  * @LUTBUS_BLOCK_GAMUT: select GAMUT block
+ * @LUTBUS_BLOCK_SIXZONE: select SIXZONE block
  * @LUTBUS_BLOCK_MAX: invalid selection
  */
 enum sde_reg_dma_lutbus_block {
 	LUTBUS_BLOCK_IGC = 0,
 	LUTBUS_BLOCK_GAMUT,
+	LUTBUS_BLOCK_SIXZONE = 3,
 	LUTBUS_BLOCK_MAX,
 };