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

Merge "disp: msm: sde: Validate transaction counts for LUTDMA abs writes"

qctecmdr 3 жил өмнө
parent
commit
b8a102735a

+ 2 - 0
msm/sde/sde_hw_catalog.h

@@ -1353,6 +1353,7 @@ struct sde_reg_dma_blk_info {
  * @broadcast_disabled flag indicating if broadcast usage should be avoided
  * @xin_id             VBIF xin client-id for LUTDMA
  * @vbif_idx           VBIF id (RT/NRT)
+ * @base_off           Base offset of LUTDMA from the MDSS root
  * @clk_ctrl           VBIF xin client clk-ctrl
  */
 struct sde_reg_dma_cfg {
@@ -1362,6 +1363,7 @@ struct sde_reg_dma_cfg {
 	u32 broadcast_disabled;
 	u32 xin_id;
 	u32 vbif_idx;
+	u32 base_off;
 	enum sde_clk_ctrl_type clk_ctrl;
 };
 

+ 34 - 2
msm/sde/sde_hw_reg_dma_v1.c

@@ -14,7 +14,7 @@
 #define GUARD_BYTES (BIT(8) - 1)
 #define ALIGNED_OFFSET (U32_MAX & ~(GUARD_BYTES))
 #define ADDR_ALIGN BIT(8)
-#define MAX_RELATIVE_OFF (BIT(20) - 1)
+#define MAX_RELATIVE_OFF (BIT(21) - 1)
 #define ABSOLUTE_RANGE BIT(27)
 
 #define DECODE_SEL_OP (BIT(HW_BLK_SELECT))
@@ -254,6 +254,9 @@ static int write_multi_reg(struct sde_reg_dma_setup_ops_cfg *cfg)
 	cfg->dma_buf->next_op_allowed = REG_WRITE_OP | DECODE_SEL_OP;
 	cfg->dma_buf->ops_completed |= REG_WRITE_OP;
 
+	if (cfg->blk == MDSS)
+		cfg->dma_buf->abs_write_cnt += SIZE_DWORD(cfg->data_size);
+
 	return 0;
 }
 
@@ -319,8 +322,10 @@ static int write_single_reg(struct sde_reg_dma_setup_ops_cfg *cfg)
 			cfg->dma_buf->index);
 	loc[0] = SINGLE_REG_WRITE_OPCODE;
 	loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF);
-	if (cfg->blk == MDSS)
+	if (cfg->blk == MDSS) {
 		loc[0] |= ABSOLUTE_RANGE;
+		cfg->dma_buf->abs_write_cnt++;
+	}
 
 	loc[1] = *cfg->data;
 	cfg->dma_buf->index += ops_mem_size[cfg->ops];
@@ -624,6 +629,32 @@ static int validate_kick_off_v1(struct sde_reg_dma_kickoff_cfg *cfg)
 		return -EINVAL;
 	}
 
+	if ((cfg->dma_buf->abs_write_cnt % 2) != 0) {
+		/* Touch up buffer to avoid HW issues with odd number of abs writes */
+		u32 reg = 0;
+		struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
+
+		dma_write_cfg.dma_buf = cfg->dma_buf;
+		dma_write_cfg.blk = MDSS;
+		dma_write_cfg.feature = REG_DMA_FEATURES_MAX;
+		dma_write_cfg.ops = HW_BLK_SELECT;
+		if (validate_write_decode_sel(&dma_write_cfg) || write_decode_sel(&dma_write_cfg)) {
+			DRM_ERROR("Failed setting MDSS decode select for LUTDMA touch up\n");
+			return -EINVAL;
+		}
+
+		/* Perform dummy write on LUTDMA RO version reg */
+		dma_write_cfg.ops = REG_SINGLE_WRITE;
+		dma_write_cfg.blk_offset = reg_dma->caps->base_off +
+				reg_dma->caps->reg_dma_blks[cfg->dma_type].base;
+		dma_write_cfg.data = ®
+		dma_write_cfg.data_size = sizeof(uint32_t);
+		if (validate_write_reg(&dma_write_cfg) || write_single_reg(&dma_write_cfg)) {
+			DRM_ERROR("Failed to add touch up write to LUTDMA buffer\n");
+			return -EINVAL;
+		}
+	}
+
 	return 0;
 }
 
@@ -1110,6 +1141,7 @@ static int reset_reg_dma_buffer_v1(struct sde_reg_dma_buffer *lut_buf)
 	lut_buf->index = 0;
 	lut_buf->ops_completed = 0;
 	lut_buf->next_op_allowed = DECODE_SEL_OP;
+	lut_buf->abs_write_cnt = 0;
 	return 0;
 }
 

+ 3 - 0
msm/sde/sde_kms.c

@@ -4557,7 +4557,9 @@ static int _sde_kms_hw_init_ioremap(struct sde_kms *sde_kms,
 		sde_kms->reg_dma = NULL;
 		SDE_DEBUG("REG_DMA is not defined");
 	} else {
+		unsigned long mdp_addr = msm_get_phys_addr(platformdev, "mdp_phys");
 		sde_kms->reg_dma_len = msm_iomap_size(platformdev, "regdma_phys");
+		sde_kms->reg_dma_off = msm_get_phys_addr(platformdev, "regdma_phys") - mdp_addr;
 		rc =  sde_dbg_reg_register_base("reg_dma", sde_kms->reg_dma,
 				sde_kms->reg_dma_len,
 				msm_get_phys_addr(platformdev, "regdma_phys"),
@@ -4651,6 +4653,7 @@ static int _sde_kms_hw_init_blocks(struct sde_kms *sde_kms,
 	}
 
 	/* Initialize reg dma block which is a singleton */
+	sde_kms->catalog->dma_cfg.base_off = sde_kms->reg_dma_off;
 	rc = sde_reg_dma_init(sde_kms->reg_dma, sde_kms->catalog,
 			sde_kms->dev);
 	if (rc) {

+ 1 - 0
msm/sde/sde_kms.h

@@ -262,6 +262,7 @@ struct sde_kms {
 	/* io/register spaces: */
 	void __iomem *mmio, *vbif[VBIF_MAX], *reg_dma, *sid;
 	unsigned long mmio_len, vbif_len[VBIF_MAX], reg_dma_len, sid_len;
+	unsigned long reg_dma_off;
 
 	struct regulator *vdd;
 	struct regulator *mmagic;

+ 3 - 1
msm/sde/sde_reg_dma.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _SDE_REG_DMA_H
@@ -232,6 +232,7 @@ enum sde_reg_dma_last_cmd_mode {
  * @vaddr: cpu address
  * @next_op_allowed: operation allowed on the buffer
  * @ops_completed: operations completed on buffer
+ * @abs_write_cnt: count of mdss absolute addr writes in the current buffer
  */
 struct sde_reg_dma_buffer {
 	struct drm_gem_object *buf;
@@ -242,6 +243,7 @@ struct sde_reg_dma_buffer {
 	void *vaddr;
 	u32 next_op_allowed;
 	u32 ops_completed;
+	u32 abs_write_cnt;
 };
 
 /**