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

Commit f82bb939 authored by Ping Li's avatar Ping Li
Browse files

drm/msm/sde: update programming sequence for VIG IGC



This change updates programming sequence for VIG IGC on sdm855,
adds data range check for DMA IGC and fix minor input check for
PP dither setup.

Change-Id: I7458c80fe75a577fff9df42c9ce4f783b9bfb7b6
Signed-off-by: default avatarPing Li <pingli@codeaurora.org>
parent 967c44cd
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -328,8 +328,9 @@ int sde_connector_get_dither_cfg(struct drm_connector *conn,
	struct sde_connector *c_conn = NULL;
	struct sde_connector_state *c_state = NULL;
	size_t dither_sz = 0;
	u32 *p = (u32 *)cfg;

	if (!conn || !state || !(*cfg))
	if (!conn || !state || !p)
		return -EINVAL;

	c_conn = to_sde_connector(conn);
+58 −30
Original line number Diff line number Diff line
@@ -68,6 +68,8 @@
#define DMA_1D_LUT_IGC_LEN 128
#define DMA_1D_LUT_GC_LEN 128
#define DMA_1D_LUT_IGC_DITHER_OFF 0x408
#define VIG_1D_LUT_IGC_LEN 128
#define VIG_IGC_DATA_MASK (BIT(10) - 1)

#define QSEED3_DE_OFFSET 0x24
#define QSEED3_COEF_LUT_OFF                    0x100
@@ -1824,9 +1826,10 @@ static void vig_igcv5_off(struct sde_hw_pipe *ctx, void *cfg)
void reg_dmav1_setup_vig_igcv5(struct sde_hw_pipe *ctx, void *cfg)
{
	int rc;
	u32 i = 0, reg = 0, index = 0;
	u32 i = 0, j = 0, reg = 0, index = 0;
	u32 offset = 0;
	u32 data[3] = {0};
	u32 lut_sel = 0, lut_enable = 0;
	u32 *data = NULL, *data_ptr = NULL;
	struct drm_msm_igc_lut *igc_lut;
	struct sde_hw_cp_cfg *hw_cfg = cfg;
	struct sde_hw_reg_dma_ops *dma_ops;
@@ -1864,44 +1867,64 @@ void reg_dmav1_setup_vig_igcv5(struct sde_hw_pipe *ctx, void *cfg)
		return;
	}

	data = kzalloc(VIG_1D_LUT_IGC_LEN * sizeof(u32), GFP_KERNEL);
	if (!data)
		return;

	reg = SDE_REG_READ(&ctx->hw, igc_base);
	lut_enable = (reg >> 8) & BIT(0);
	lut_sel = (reg >> 9) & BIT(0);
	/* select LUT table (0 or 1) when 1D LUT is in active mode */
	if (lut_enable)
		lut_sel = (~lut_sel) && BIT(0);

	for (i = 0; i < IGC_TBL_NUM; i++) {
		/* write 0 to the index register */
		index = 0;
		REG_DMA_SETUP_OPS(dma_write_cfg, igc_base + 0x1B0,
			&index, sizeof(index), REG_SINGLE_WRITE, 0, 0, 0);
		rc = dma_ops->setup_payload(&dma_write_cfg);
		if (rc) {
			DRM_ERROR("VIG IGC index write failed ret %d\n", rc);
			goto exit;
		}

		offset = igc_base + 0x1B4 + i * sizeof(u32);
		data_ptr = igc_lut->c0 + (ARRAY_SIZE(igc_lut->c0) * i);
		for (j = 0; j < VIG_1D_LUT_IGC_LEN; j++)
			data[j] = (data_ptr[2 * j] & VIG_IGC_DATA_MASK) |
				(data_ptr[2 * j + 1] & VIG_IGC_DATA_MASK) << 16;

	/* writing to color2_LUT will auto trigger an index update */
	offset = igc_base + 0x1B4;
	for (i = 0; i < IGC_TBL_LEN; i += 2) {
		data[0] = igc_lut->c0[i] | (igc_lut->c0[i + 1] << 16);
		data[1] = igc_lut->c1[i] | (igc_lut->c1[i + 1] << 16);
		data[2] = igc_lut->c2[i] | (igc_lut->c2[i + 1] << 16);
		REG_DMA_SETUP_OPS(dma_write_cfg, offset, data,
			sizeof(data), REG_BLK_WRITE_INC, 3, 0, 0);
				VIG_1D_LUT_IGC_LEN * sizeof(u32),
				REG_BLK_WRITE_INC, 0, 0, 0);
		rc = dma_ops->setup_payload(&dma_write_cfg);
		if (rc) {
			DRM_ERROR("lut write failed ret %d\n", rc);
			return;
			goto exit;
		}
	}
	if (igc_lut->flags & IGC_DITHER_ENABLE) {
		reg = igc_lut->strength & IGC_DITHER_DATA_MASK;
		reg |= BIT(4);
	} else {
		reg = 0;
	}
	REG_DMA_SETUP_OPS(dma_write_cfg, igc_base + 0x1C0,
			&reg, sizeof(reg), REG_SINGLE_WRITE, 0, 0, 0);
	rc = dma_ops->setup_payload(&dma_write_cfg);
	if (rc) {
		DRM_ERROR("dither strength failed ret %d\n", rc);
			return;
		}
		goto exit;
	}

	reg = BIT(8);
	reg = BIT(8) | (lut_sel << 9);
	REG_DMA_SETUP_OPS(dma_write_cfg, igc_base, &reg, sizeof(reg),
		REG_SINGLE_MODIFY, 0, 0, REG_DMA_VIG_IGC_OP_MASK);
	rc = dma_ops->setup_payload(&dma_write_cfg);
	if (rc) {
		DRM_ERROR("setting opcode failed ret %d\n", rc);
		return;
		goto exit;
	}

	REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, sspp_buf[IGC][ctx->idx],
@@ -1909,6 +1932,8 @@ void reg_dmav1_setup_vig_igcv5(struct sde_hw_pipe *ctx, void *cfg)
	rc = dma_ops->kick_off(&kick_off);
	if (rc)
		DRM_ERROR("failed to kick off ret %d\n", rc);
exit:
	kfree(data);
}

static void dma_igcv5_off(struct sde_hw_pipe *ctx, void *cfg,
@@ -2011,7 +2036,8 @@ void reg_dmav1_setup_dma_igcv5(struct sde_hw_pipe *ctx, void *cfg,
	}

	for (i = 0; i < DMA_1D_LUT_IGC_LEN; i++)
		data[i] = igc_lut->c0[2 * i] | (igc_lut->c0[2 * i + 1] << 16);
		data[i] = (igc_lut->c0[2 * i] & IGC_DATA_MASK) |
			((igc_lut->c0[2 * i + 1] & IGC_DATA_MASK) << 16);

	if (idx == SDE_SSPP_RECT_SOLO || idx == SDE_SSPP_RECT_0) {
		igc_base = ctx->cap->sblk->igc_blk[0].base -
@@ -2036,6 +2062,9 @@ void reg_dmav1_setup_dma_igcv5(struct sde_hw_pipe *ctx, void *cfg,
	if (igc_lut->flags & IGC_DITHER_ENABLE) {
		reg = igc_lut->strength & IGC_DITHER_DATA_MASK;
		reg |= BIT(4);
	} else {
		reg = 0;
	}
	REG_DMA_SETUP_OPS(dma_write_cfg, igc_dither_off, &reg,
			sizeof(reg), REG_SINGLE_WRITE, 0, 0, 0);
	rc = dma_ops->setup_payload(&dma_write_cfg);
@@ -2043,7 +2072,6 @@ void reg_dmav1_setup_dma_igcv5(struct sde_hw_pipe *ctx, void *cfg,
		DRM_ERROR("failed to set dither strength %d\n", rc);
		goto igc_exit;
	}
	}

	reg = BIT(1);
	REG_DMA_SETUP_OPS(dma_write_cfg, igc_opmode_off, &reg, sizeof(reg),