disp: msm: sde: Validate transaction counts for LUTDMA abs writes
Existing LUTDMA hardware runs into issues when an odd number of LUTDMA absolute address writes are executed before a GDSC power collapse. Update LUTDMA logic to force absolute write payloads to always contain an even number of writes. Change-Id: I476feeab550f4b176d0adccaa5f2d38041e87657 Signed-off-by: Christopher Braga <cbraga@codeaurora.org>
This commit is contained in:
@@ -1351,6 +1351,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 {
|
||||
@@ -1360,6 +1361,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;
|
||||
};
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -4556,7 +4556,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"),
|
||||
@@ -4650,6 +4652,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) {
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user