drm: msm: sde: Add support for SPR V2

Introduce support for SPR V2 features. Full validation
has been performed.

Change-Id: Ia83c06b30729fef12cae014ee5ce4792236a0a8a
Signed-off-by: Christopher Braga <quic_cbraga@quicinc.com>
This commit is contained in:
Christopher Braga
2022-10-20 11:57:01 -04:00
parent be07875590
commit d617e25729
12 changed files with 910 additions and 162 deletions

View File

@@ -587,11 +587,11 @@ struct drm_msm_ltm_buffer {
#define SPR_INIT_PARAM_SIZE_3 16
#define SPR_INIT_PARAM_SIZE_4 24
#define SPR_INIT_PARAM_SIZE_5 32
#define SPR_INIT_PARAM_SIZE_6 7
#define SPR_FLAG_BYPASS (1 << 0)
/**
* struct drm_msm_spr_init_cfg - SPR initial configuration structure
*
*/
struct drm_msm_spr_init_cfg {
__u64 flags;
@@ -613,8 +613,25 @@ struct drm_msm_spr_init_cfg {
__u16 cfg15[SPR_INIT_PARAM_SIZE_5];
int cfg16[SPR_INIT_PARAM_SIZE_3];
int cfg17[SPR_INIT_PARAM_SIZE_4];
__u16 cfg18_en;
__u8 cfg18[SPR_INIT_PARAM_SIZE_6];
};
/**
* struct drm_msm_spr_udc_cfg - SPR UDC configuration structure
*/
#define SPR_UDC_PARAM_SIZE_1 27
#define SPR_UDC_PARAM_SIZE_2 1536
struct drm_msm_spr_udc_cfg {
__u64 flags;
__u16 init_cfg4;
__u16 init_cfg11[SPR_INIT_PARAM_SIZE_1];
__u16 cfg1[SPR_UDC_PARAM_SIZE_1];
__u16 cfg2[SPR_UDC_PARAM_SIZE_2];
};
#define FEATURE_DEM
#define CFG0_PARAM_LEN 8
#define CFG1_PARAM_LEN 8

View File

@@ -736,6 +736,52 @@ static int _check_rc_mask_feature(struct sde_hw_dspp *hw_dspp,
return ret;
}
static int _check_spr_init_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
{
int ret = 0;
if (!hw_dspp || !hw_cfg || !sde_crtc) {
DRM_ERROR("invalid arguments");
return -EINVAL;
}
if (!hw_dspp->ops.validate_spr_init_config) {
DRM_ERROR("invalid spr validate op");
return -EINVAL;
}
ret = hw_dspp->ops.validate_spr_init_config(hw_dspp, hw_cfg);
if (ret)
DRM_ERROR("failed to validate spr config %d", ret);
return ret;
}
static int _check_spr_udc_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
{
int ret = 0;
if (!hw_dspp || !hw_cfg || !sde_crtc) {
DRM_ERROR("invalid arguments");
return -EINVAL;
}
if (!hw_dspp->ops.validate_spr_udc_config) {
DRM_ERROR("invalid spr udc validate op");
return -EINVAL;
}
ret = hw_dspp->ops.validate_spr_udc_config(hw_dspp, hw_cfg);
if (ret)
DRM_ERROR("failed to validate spr udc config %d", ret);
return ret;
}
static int _set_rc_mask_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
@@ -912,6 +958,23 @@ static int _set_spr_init_feature(struct sde_hw_dspp *hw_dspp,
return ret;
}
static int _set_spr_udc_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
{
int ret = 0;
if (!sde_crtc || !hw_dspp) {
DRM_ERROR("invalid arguments\n");
ret = -EINVAL;
} else {
if (hw_dspp->ops.setup_spr_udc_config)
hw_dspp->ops.setup_spr_udc_config(hw_dspp, hw_cfg);
}
return ret;
}
static int _set_demura_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
@@ -948,6 +1011,8 @@ feature_wrapper check_crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES];
do { \
memset(wrappers, 0, sizeof(wrappers)); \
wrappers[SDE_CP_CRTC_DSPP_RC_MASK] = _check_rc_mask_feature; \
wrappers[SDE_CP_CRTC_DSPP_SPR_INIT] = _check_spr_init_feature; \
wrappers[SDE_CP_CRTC_DSPP_SPR_UDC] = _check_spr_udc_feature; \
} while (0)
feature_wrapper set_crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES];
@@ -993,6 +1058,7 @@ do { \
wrappers[SDE_CP_CRTC_DSPP_LTM_HIST_CTL] = _set_ltm_hist_crtl_feature; \
wrappers[SDE_CP_CRTC_DSPP_RC_MASK] = _set_rc_mask_feature; \
wrappers[SDE_CP_CRTC_DSPP_SPR_INIT] = _set_spr_init_feature; \
wrappers[SDE_CP_CRTC_DSPP_SPR_UDC] = _set_spr_udc_feature; \
wrappers[SDE_CP_CRTC_DSPP_DEMURA_INIT] = _set_demura_feature; \
} while (0)
@@ -1784,6 +1850,7 @@ static const int dspp_feature_to_sub_blk_tbl[SDE_CP_CRTC_MAX_FEATURES] = {
[SDE_CP_CRTC_DSPP_LTM_VLUT] = SDE_DSPP_LTM,
[SDE_CP_CRTC_DSPP_SB] = SDE_DSPP_SB,
[SDE_CP_CRTC_DSPP_SPR_INIT] = SDE_DSPP_SPR,
[SDE_CP_CRTC_DSPP_SPR_UDC] = SDE_DSPP_SPR,
[SDE_CP_CRTC_DSPP_RC_MASK] = SDE_DSPP_RC,
[SDE_CP_CRTC_DSPP_DEMURA_INIT] = SDE_DSPP_DEMURA,
[SDE_CP_CRTC_DSPP_DEMURA_BACKLIGHT] = SDE_DSPP_DEMURA,
@@ -2190,15 +2257,6 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
goto exit;
}
rc = _sde_cp_crtc_update_pu_features(crtc, &need_flush);
if (rc) {
DRM_ERROR("failed to set pu features, skip cp updates\n");
goto exit;
} else if (need_flush) {
set_dspp_flush = true;
set_lm_flush = true;
}
list_for_each_entry_safe(prop_node, n, &sde_crtc->cp_dirty_list,
cp_dirty_list) {
_sde_cp_crtc_commit_feature(prop_node, sde_crtc);
@@ -2210,6 +2268,15 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
set_lm_flush = true;
}
rc = _sde_cp_crtc_update_pu_features(crtc, &need_flush);
if (rc) {
DRM_ERROR("failed to set pu features, skip cp updates\n");
goto exit;
} else if (need_flush) {
set_dspp_flush = true;
set_lm_flush = true;
}
_sde_cp_dspp_flush_helper(sde_crtc, SDE_CP_CRTC_DSPP_SB);
if (!list_empty(&sde_crtc->ad_active)) {
@@ -3194,6 +3261,7 @@ static void _dspp_rc_install_property(struct drm_crtc *crtc)
static void _dspp_spr_install_property(struct drm_crtc *crtc)
{
char feature_name[256];
struct sde_kms *kms = NULL;
u32 version = 0;
@@ -3205,8 +3273,22 @@ static void _dspp_spr_install_property(struct drm_crtc *crtc)
version = kms->catalog->dspp[0].sblk->spr.version >> 16;
switch (version) {
case 2:
snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d",
"SDE_SPR_UDC_CFG_V", version);
_sde_cp_crtc_install_blob_property(crtc, feature_name,
SDE_CP_CRTC_DSPP_SPR_UDC,
sizeof(struct drm_msm_spr_udc_cfg));
snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d",
"SDE_SPR_INIT_CFG_V", version);
_sde_cp_crtc_install_blob_property(crtc, feature_name,
SDE_CP_CRTC_DSPP_SPR_INIT,
sizeof(struct drm_msm_spr_init_cfg));
break;
case 1:
_sde_cp_crtc_install_blob_property(crtc, "SDE_SPR_INIT_CFG_V1",
snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d",
"SDE_SPR_INIT_CFG_V", version);
_sde_cp_crtc_install_blob_property(crtc, feature_name,
SDE_CP_CRTC_DSPP_SPR_INIT,
sizeof(struct drm_msm_spr_init_cfg));
break;

View File

@@ -104,6 +104,7 @@ enum sde_cp_crtc_features {
SDE_CP_CRTC_DSPP_SB,
SDE_CP_CRTC_DSPP_RC_MASK,
SDE_CP_CRTC_DSPP_SPR_INIT,
SDE_CP_CRTC_DSPP_SPR_UDC,
SDE_CP_CRTC_DSPP_DEMURA_INIT,
SDE_CP_CRTC_DSPP_DEMURA_BACKLIGHT,
SDE_CP_CRTC_DSPP_DEMURA_BOOT_PLANE,

View File

@@ -473,6 +473,18 @@ enum {
SDE_LTM_MAX
};
/**
* SPR sub-features
* @SDE_SPR_INIT SPR INIT feature
* @SDE_SPR_UDC SPR UDC feature
* @SDE_SPR_MAX maximum value
*/
enum {
SDE_SPR_INIT = 0x1,
SDE_SPR_UDC,
SDE_SPR_MAX
};
/**
* PINGPONG sub-blocks
* @SDE_PINGPONG_TE Tear check block

View File

@@ -746,6 +746,123 @@ void sde_demura_pu_cfg(struct sde_hw_dspp *dspp, void *cfg)
((hw_cfg) ? hw_cfg->panel_height : -1));
}
int sde_spr_check_init_cfg(struct sde_hw_dspp *ctx, void *cfg)
{
struct drm_msm_spr_init_cfg *spr_payload;
struct sde_hw_cp_cfg *hw_cfg = cfg;
int rc = 0;
if (!ctx || !cfg)
return -EINVAL;
if (!hw_cfg->payload)
return 0;
spr_payload = hw_cfg->payload;
if (spr_payload->cfg18_en) {
bool invalid = spr_payload->cfg11[0] != 1 || spr_payload->cfg11[1] != 0 ||
spr_payload->cfg11[2] != 1;
if (spr_payload->cfg4 || invalid) {
DRM_ERROR("CFG18 can't be enabled with this config. CFG4: %u CFG11: %u\n",
spr_payload->cfg4, invalid);
return -EINVAL;
}
}
return rc;
}
int sde_spr_check_udc_cfg(struct sde_hw_dspp *ctx, void *cfg)
{
uint32_t j = 0, i = 0;
struct drm_msm_spr_udc_cfg *spr_payload;
struct sde_hw_cp_cfg *hw_cfg = cfg;
bool invalid = false;
if (!ctx || !cfg)
return -EINVAL;
if (!hw_cfg->payload)
return 0;
spr_payload = hw_cfg->payload;
invalid = !(spr_payload->init_cfg11[0] || spr_payload->init_cfg11[1] ||
spr_payload->init_cfg11[2]);
if (spr_payload->init_cfg4 || invalid) {
DRM_ERROR("SPR UDC can not be used with this config. CFG4: %u CFG11: %u",
spr_payload->init_cfg4, invalid);
return -EINVAL;
}
for (i = 0; i < 3; i++) {
uint32_t max_h, max_v, limit;
uint32_t cfg_1_start = (SPR_UDC_PARAM_SIZE_2 / 3) * i;
uint32_t x1 =
spr_payload->cfg1[(SPR_UDC_PARAM_SIZE_1 / 3) * i] & 0xffff;
uint32_t y1 =
spr_payload->cfg1[(SPR_UDC_PARAM_SIZE_1 / 3) * i + 1] & 0xffff;
uint32_t w = spr_payload->cfg1[(SPR_UDC_PARAM_SIZE_1 / 3) * i + 2];
uint32_t lines = spr_payload->cfg1[(SPR_UDC_PARAM_SIZE_1 / 3) * i + 3];
uint32_t x2 = x1 + w;
uint32_t y2 = y1 + lines;
switch (spr_payload->init_cfg11[i]) {
case 0:
max_h = hw_cfg->panel_width;
max_v = hw_cfg->panel_height;
break;
case 1:
max_h = (hw_cfg->panel_width + 1) >> 1;
max_v = hw_cfg->panel_height;
break;
case 2:
max_h = (hw_cfg->panel_width * 2 + 2) / 3;
max_v = hw_cfg->panel_height;
break;
default:
DRM_ERROR("Can't calculate decimation");
return -EINVAL;
}
if (x2 >= max_h) {
DRM_ERROR("Invalid CFG1 - C%u x2 %u", i, x2);
return -EINVAL;
} else if (y2 >= max_v) {
DRM_ERROR("Invalid CFG1 - C%u y2 %u", i, y2);
return -EINVAL;
} else if (lines < 2 || lines > 256) {
DRM_ERROR("Invalid CFG1 - C%u Lines %u", i, lines);
return -EINVAL;
} else if (w < 2 || w > 512) {
DRM_ERROR("Invalid CFG1 - C%u W %u", i, w);
return -EINVAL;
}
j = 0;
limit = (w >> 1) + 1;
for (j = 0; j < lines; j++) {
uint32_t o1 = spr_payload->cfg2[cfg_1_start + (j*2)];
uint32_t o2 = spr_payload->cfg2[cfg_1_start + (j*2) + 1];
if (o1 > limit) {
DRM_ERROR("Invalid CFG2 - C%u L%u, o1 exceeds limits",
i, j);
return -EINVAL;
} else if (o2 > limit) {
DRM_ERROR("Invalid CFG2 - C%u L%u, o2 exceeds limits",
i, j);
return -EINVAL;
}
}
}
return 0;
}
int sde_spr_read_opr_value(struct sde_hw_dspp *ctx, uint32_t *opr_value)
{
uint32_t reg_off;

View File

@@ -154,6 +154,20 @@ void sde_setup_fp16_unmultv1(struct sde_hw_pipe *ctx,
*/
void sde_demura_pu_cfg(struct sde_hw_dspp *ctx, void *cfg);
/**
* sde_spr_check_init_cfg - api to validate the SPR configuration for the frame
* @ctx: pointer to dspp object.
* @cfg: spr configuration for the frame.
*/
int sde_spr_check_init_cfg(struct sde_hw_dspp *ctx, void *cfg);
/**
* sde_spr_check_udc_cfg - api to validate the SPR UDC configuration for the frame
* @ctx: pointer to dspp object.
* @cfg: spr UDC configuration for the frame.
*/
int sde_spr_check_udc_cfg(struct sde_hw_dspp *ctx, void *cfg);
/**
* sde_spr_read_opr_value - api to read spr opr value
* @ctx: pointer to dspp object.

View File

@@ -331,11 +331,15 @@ static void dspp_spr(struct sde_hw_dspp *c)
return;
}
c->ops.validate_spr_init_config = NULL;
c->ops.validate_spr_udc_config = NULL;
c->ops.setup_spr_init_config = NULL;
c->ops.setup_spr_udc_config = NULL;
c->ops.setup_spr_pu_config = NULL;
c->ops.read_spr_opr_value = NULL;
if (c->cap->sblk->spr.version == SDE_COLOR_PROCESS_VER(0x1, 0x0)) {
ret = reg_dmav1_init_dspp_op_v4(SDE_DSPP_SPR, c->idx);
ret = reg_dmav2_init_spr_op_v1(SDE_SPR_INIT, c->idx);
if (ret) {
SDE_ERROR("regdma init failed for spr, ret %d\n", ret);
return;
@@ -344,6 +348,25 @@ static void dspp_spr(struct sde_hw_dspp *c)
c->ops.setup_spr_init_config = reg_dmav1_setup_spr_init_cfgv1;
c->ops.setup_spr_pu_config = reg_dmav1_setup_spr_pu_cfgv1;
c->ops.read_spr_opr_value = sde_spr_read_opr_value;
} else if (c->cap->sblk->spr.version == SDE_COLOR_PROCESS_VER(0x2, 0x0)) {
ret = reg_dmav2_init_spr_op_v1(SDE_SPR_INIT, c->idx);
if (ret) {
SDE_ERROR("regdma init failed for spr, ret %d\n", ret);
return;
}
ret = reg_dmav2_init_spr_op_v1(SDE_SPR_UDC, c->idx);
if (ret) {
SDE_ERROR("regdma init failed for spr udc, ret %d\n", ret);
return;
}
c->ops.validate_spr_init_config = sde_spr_check_init_cfg;
c->ops.validate_spr_udc_config = sde_spr_check_udc_cfg;
c->ops.setup_spr_init_config = reg_dmav1_setup_spr_init_cfgv2;
c->ops.setup_spr_udc_config = reg_dmav1_setup_spr_udc_cfgv2;
c->ops.setup_spr_pu_config = reg_dmav1_setup_spr_pu_cfgv2;
c->ops.read_spr_opr_value = sde_spr_read_opr_value;
}
}

View File

@@ -256,6 +256,22 @@ struct sde_hw_dspp_ops {
*/
int (*setup_rc_data)(struct sde_hw_dspp *ctx, void *cfg);
/**
* validate_spr_init_config - Validate SPR configuration
* @ctx: Pointer to dspp context.
* @cfg: Pointer to configuration.
* Return: 0 on success, non-zero otherwise.
*/
int (*validate_spr_init_config)(struct sde_hw_dspp *ctx, void *cfg);
/**
* validate_spr_udc_config - Validate SPR configuration
* @ctx: Pointer to dspp context.
* @cfg: Pointer to configuration.
* Return: 0 on success, non-zero otherwise.
*/
int (*validate_spr_udc_config)(struct sde_hw_dspp *ctx, void *cfg);
/**
* setup_spr_init_config - function to configure spr hw block
* @ctx: Pointer to dspp context
@@ -263,6 +279,13 @@ struct sde_hw_dspp_ops {
*/
void (*setup_spr_init_config)(struct sde_hw_dspp *ctx, void *cfg);
/**
* setup_spr_udc_config - function to configure spr hw block
* @ctx: Pointer to dspp context
* @cfg: Pointer to configuration
*/
void (*setup_spr_udc_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
@@ -315,6 +338,7 @@ struct sde_hw_dspp_ops {
* @sb_dma_in_use: hint indicating if sb dma is being used for this dspp
* @ops: Pointer to operations possible for this DSPP
* @ltm_checksum_support: flag to check if checksum present
* @spr_cfg_18_default: Default SPR cfg 18 HW details. Needed for PU handling
*/
struct sde_hw_dspp {
struct sde_hw_blk_reg_map hw;
@@ -327,6 +351,7 @@ struct sde_hw_dspp {
const struct sde_dspp_cfg *cap;
bool sb_dma_in_use;
bool ltm_checksum_support;
u32 spr_cfg_18_default;
/* Ops */
struct sde_hw_dspp_ops ops;

View File

@@ -908,6 +908,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_UDC] = (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;

View File

@@ -44,6 +44,8 @@
#define REG_DMA_LTM_VLUT_DISABLE_OP_MASK 0xFEFF8CAD
#define REG_DMA_LTM_UPDATE_REQ_MASK 0xFFFFFFFE
#define REG_DMA_SPR_CONFIG_MASK ~0xFDFFFFFF
#define GAMUT_LUT_MEM_SIZE ((sizeof(struct drm_msm_3d_gamut)) + \
REG_DMA_HEADERS_BUFFER_SZ)
#define GAMUT_SCALE_OFF_LEN (GAMUT_3D_SCALE_OFF_SZ * sizeof(u32))
@@ -81,6 +83,8 @@
REG_DMA_HEADERS_BUFFER_SZ)
#define SPR_INIT_MEM_SIZE ((sizeof(struct drm_msm_spr_init_cfg)) + \
REG_DMA_HEADERS_BUFFER_SZ)
#define SPR_UDC_MEM_SIZE ((sizeof(struct drm_msm_spr_udc_cfg)) + \
REG_DMA_HEADERS_BUFFER_SZ)
#define DEMURA_MEM_SIZE ((sizeof(struct drm_msm_dem_cfg)) + \
REG_DMA_HEADERS_BUFFER_SZ)
@@ -350,16 +354,6 @@ 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],
@@ -4853,6 +4847,51 @@ exit:
kvfree(data);
}
int reg_dmav2_init_spr_op_v1(int feature, enum sde_dspp dspp_idx)
{
int rc = -EOPNOTSUPP;
struct sde_hw_reg_dma_ops *dma_ops;
bool is_supported = false;
enum sde_reg_dma_features dma_features[2];
u32 i, blk, buffer_size, dma_feature_cnt = 0;
/* SPR blocks are hardwired to DSPP blocks */
if (feature >= SDE_SPR_MAX || dspp_idx >= DSPP_MAX) {
DRM_ERROR("invalid feature %x max %x dspp idx %x max %xd\n",
feature, SDE_SPR_MAX, dspp_idx, DSPP_MAX);
return rc;
}
dma_ops = sde_reg_dma_get_ops();
if (IS_ERR_OR_NULL(dma_ops))
return -EOPNOTSUPP;
if (feature == SDE_SPR_INIT) {
dma_features[dma_feature_cnt++] = SPR_INIT;
dma_features[dma_feature_cnt++] = SPR_PU_CFG;
buffer_size = SPR_INIT_MEM_SIZE;
} else if (feature == SDE_SPR_UDC) {
dma_features[dma_feature_cnt++] = SPR_UDC;
buffer_size = SPR_UDC_MEM_SIZE;
}
rc = 0;
blk = dspp_mapping[dspp_idx];
for (i = 0; (i < dma_feature_cnt) && !rc; i++) {
rc = dma_ops->check_support(dma_features[i], blk, &is_supported);
if (!rc) {
if (is_supported)
rc = reg_dma_buf_init(&dspp_buf[dma_features[i]][dspp_idx],
buffer_size);
else
rc = -EOPNOTSUPP;
}
}
return rc;
}
int reg_dmav1_setup_spr_cfg3_params(struct sde_hw_dspp *ctx,
struct drm_msm_spr_init_cfg *payload,
struct sde_reg_dma_setup_ops_cfg *dma_write_cfg,
@@ -4932,13 +4971,65 @@ int reg_dmav1_setup_spr_cfg4_params(struct sde_hw_dspp *ctx,
return rc;
}
int reg_dmav1_setup_spr_cfg5_params(struct sde_hw_dspp *ctx,
struct drm_msm_spr_init_cfg *payload,
struct sde_reg_dma_setup_ops_cfg *dma_write_cfg,
struct sde_hw_reg_dma_ops *dma_ops)
{
uint32_t reg_off, base_off, i;
uint32_t reg[1];
int rc = 0;
if (!payload->cfg18_en) {
ctx->spr_cfg_18_default = 0;
return rc;
}
reg[0] = APPLY_MASK_AND_SHIFT(payload->cfg18[0], 3, 16) |
APPLY_MASK_AND_SHIFT(payload->cfg18[1], 3, 20) |
APPLY_MASK_AND_SHIFT(payload->cfg18[2], 3, 24);
for (i = 0; i < 4; i++) {
uint32_t val = 0;
switch (payload->cfg18[3 + i]) {
case 0:
val = 0;
break;
case 2:
val = 1;
break;
case 4:
val = 2;
break;
default:
DRM_ERROR("Invalid payload for cfg18. Val %u\n", payload->cfg18[3 + i]);
break;
}
reg[0] |= APPLY_MASK_AND_SHIFT(val, 2, 4 * i);
}
base_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base;
reg_off = base_off + 0x7C;
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 spr cfg18 failed ret %d\n", rc);
else
ctx->spr_cfg_18_default = reg[0];
return rc;
}
void reg_dmav1_disable_spr(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_off, reg = 0;
uint32_t reg_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base + 0x4;
uint32_t reg = 0;
int rc = 0;
dma_ops = sde_reg_dma_get_ops();
@@ -4952,10 +5043,9 @@ void reg_dmav1_disable_spr(struct sde_hw_dspp *ctx, void *cfg)
DRM_ERROR("spr write decode select failed ret %d\n", rc);
return;
}
SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY);
reg_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base + 0x04;
REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, &reg,
sizeof(u32), REG_BLK_WRITE_SINGLE, 0, 0, 0);
REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, &reg, sizeof(u32),
REG_SINGLE_MODIFY, 0, 0, REG_DMA_SPR_CONFIG_MASK);
rc = dma_ops->setup_payload(&dma_write_cfg);
if (rc) {
DRM_ERROR("write spr disable failed ret %d\n", rc);
@@ -4971,102 +5061,19 @@ void reg_dmav1_disable_spr(struct sde_hw_dspp *ctx, void *cfg)
DRM_ERROR("failed to kick off ret %d\n", rc);
return;
}
ctx->spr_cfg_18_default = 0;
}
void reg_dmav1_setup_spr_init_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
int reg_dmav1_setup_spr_init_common(struct sde_hw_dspp *ctx,
struct drm_msm_spr_init_cfg *payload,
struct sde_reg_dma_setup_ops_cfg *dma_write_cfg,
struct sde_hw_reg_dma_ops *dma_ops)
{
struct drm_msm_spr_init_cfg *payload = NULL;
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_off, reg_cnt, base_off;
uint32_t reg_off, reg_cnt;
uint32_t reg[16];
uint32_t base_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base;
int i, index, rc = 0;
bool spr_bypass = false;
rc = reg_dma_dspp_check(ctx, cfg, SPR_INIT);
if (rc)
return;
if (!hw_cfg->payload) {
LOG_FEATURE_OFF;
return reg_dmav1_disable_spr(ctx, cfg);
}
if (hw_cfg->len != sizeof(struct drm_msm_spr_init_cfg)) {
DRM_ERROR("invalid payload size len %d exp %zd\n", hw_cfg->len,
sizeof(struct drm_msm_spr_init_cfg));
return;
}
payload = hw_cfg->payload;
base_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base;
dma_ops = sde_reg_dma_get_ops();
dma_ops->reset_reg_dma_buf(dspp_buf[SPR_INIT][ctx->idx]);
REG_DMA_INIT_OPS(dma_write_cfg, MDSS, SPR_INIT,
dspp_buf[SPR_INIT][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;
}
spr_bypass = (payload->flags & SPR_FLAG_BYPASS) ? true : false;
reg_cnt = 2;
reg_off = base_off + 0x04;
reg[0] = APPLY_MASK_AND_SHIFT(payload->cfg0, 1, 0) |
APPLY_MASK_AND_SHIFT(payload->cfg1, 1, 1) |
APPLY_MASK_AND_SHIFT(payload->cfg2, 1, 2) |
APPLY_MASK_AND_SHIFT(payload->cfg4, 1, 3) |
APPLY_MASK_AND_SHIFT(payload->cfg3, 1, 24);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg5, 4, 16);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg6, 3, 20);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg7, 2, 4);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg8, 2, 6);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg11[0], 2, 8);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg11[1], 2, 10);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg11[2], 2, 12);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg11[3], 1, 14);
if (spr_bypass)
reg[0] = APPLY_MASK_AND_SHIFT(payload->cfg1, 1, 1) |
APPLY_MASK_AND_SHIFT(payload->cfg2, 1, 2) |
APPLY_MASK_AND_SHIFT(payload->cfg3, 1, 24);
reg[1] = 0;
if (hw_cfg->num_of_mixers == 2)
reg[1] = 1;
else if (hw_cfg->num_of_mixers == 4)
reg[1] = 3;
REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, reg,
reg_cnt * sizeof(u32), REG_BLK_WRITE_SINGLE, 0, 0, 0);
rc = dma_ops->setup_payload(&dma_write_cfg);
if (rc) {
DRM_ERROR("write spr config failed ret %d\n", rc);
return;
}
if (spr_bypass)
goto bypass;
reg_cnt = 1;
reg_off = base_off + 0x54;
reg[0] = 0;
for (i = 0; i < ARRAY_SIZE(payload->cfg14); i++)
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg14[i], 5, 5 * i);
REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, reg,
reg_cnt * sizeof(u32), REG_SINGLE_WRITE, 0, 0, 0);
rc = dma_ops->setup_payload(&dma_write_cfg);
if (rc) {
DRM_ERROR("write spr cfg14 failed ret %d\n", rc);
return;
}
reg_cnt = ARRAY_SIZE(payload->cfg17) / 6;
reg_off = base_off + 0x24;
@@ -5081,12 +5088,12 @@ void reg_dmav1_setup_spr_init_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
}
reg[reg_cnt - 1] &= 0x3FF;
REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, reg,
REG_DMA_SETUP_OPS(*dma_write_cfg, reg_off, reg,
reg_cnt * sizeof(u32), REG_BLK_WRITE_SINGLE, 0, 0, 0);
rc = dma_ops->setup_payload(&dma_write_cfg);
rc = dma_ops->setup_payload(dma_write_cfg);
if (rc) {
DRM_ERROR("write spr cfg17 failed ret %d\n", rc);
return;
return rc;
}
reg_cnt = ARRAY_SIZE(payload->cfg16) / 2;
@@ -5097,81 +5104,407 @@ void reg_dmav1_setup_spr_init_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
APPLY_MASK_AND_SHIFT(payload->cfg16[index + 1], 11, 16);
}
REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, reg, reg_cnt * sizeof(u32),
REG_DMA_SETUP_OPS(*dma_write_cfg, reg_off, reg, reg_cnt * sizeof(u32),
REG_BLK_WRITE_SINGLE, 0, 0, 0);
rc = dma_ops->setup_payload(&dma_write_cfg);
rc = dma_ops->setup_payload(dma_write_cfg);
if (rc) {
DRM_ERROR("write spr cfg16 failed ret %d\n", rc);
return;
return rc;
}
rc = reg_dmav1_setup_spr_cfg3_params(ctx, payload,
&dma_write_cfg, dma_ops);
dma_write_cfg, dma_ops);
if (rc)
return;
return rc;
rc = reg_dmav1_setup_spr_cfg4_params(ctx, payload,
&dma_write_cfg, dma_ops);
if (rc)
return;
dma_write_cfg, dma_ops);
return rc;
}
int reg_dmav1_get_spr_target(struct sde_hw_dspp *ctx, void *cfg,
struct sde_hw_reg_dma_ops **dma_ops, uint32_t *base_off,
struct sde_reg_dma_buffer **buffer, bool *disable)
{
struct sde_hw_cp_cfg *hw_cfg = cfg;
int rc = reg_dma_dspp_check(ctx, cfg, SPR_INIT);
if (rc) {
return rc;
}
*base_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base;
*buffer = dspp_buf[SPR_INIT][ctx->idx];
*dma_ops = sde_reg_dma_get_ops();
(*dma_ops)->reset_reg_dma_buf(*buffer);
if (!hw_cfg->payload) {
*disable = true;
} else {
*disable = false;
if (hw_cfg->len != sizeof(struct drm_msm_spr_init_cfg)) {
DRM_ERROR("invalid payload size len %d exp %zd\n", hw_cfg->len,
sizeof(struct drm_msm_spr_init_cfg));
rc = -EINVAL;
}
}
return rc;
}
int reg_dmav1_setup_spr_init_kickoff(uint32_t version, uint32_t base_off,
struct sde_hw_reg_dma_ops *dma_ops,
struct sde_hw_cp_cfg *hw_cfg,
struct drm_msm_spr_init_cfg *payload,
struct sde_reg_dma_setup_ops_cfg *dma_write_cfg)
{
struct sde_reg_dma_kickoff_cfg kick_off;
uint32_t reg[2];
uint32_t reg_off;
int rc = 0;
if ((payload->flags & SPR_FLAG_BYPASS)) {
reg[0] = APPLY_MASK_AND_SHIFT(payload->cfg1, 1, 1) |
APPLY_MASK_AND_SHIFT(payload->cfg2, 1, 2) |
APPLY_MASK_AND_SHIFT(payload->cfg3, 1, 24);
} else {
reg[0] = APPLY_MASK_AND_SHIFT(payload->cfg0, 1, 0) |
APPLY_MASK_AND_SHIFT(payload->cfg1, 1, 1) |
APPLY_MASK_AND_SHIFT(payload->cfg2, 1, 2) |
APPLY_MASK_AND_SHIFT(payload->cfg4, 1, 3) |
APPLY_MASK_AND_SHIFT(payload->cfg3, 1, 24);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg5, 4, 16);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg6, 3, 20);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg7, 2, 4);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg8, 2, 6);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg11[0], 2, 8);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg11[1], 2, 10);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg11[2], 2, 12);
reg[0] |= APPLY_MASK_AND_SHIFT(payload->cfg11[3], 1, 14);
if (version == 2) {
reg[0] |= payload->cfg18_en ? (1 << 26) : 0;
reg[0] |= payload->cfg7 & 0x4 ? (1 << 15) : 0;
}
}
reg[1] = 0;
if (hw_cfg->num_of_mixers == 2)
reg[1] = 1;
else if (hw_cfg->num_of_mixers == 4)
reg[1] = 3;
reg_off = base_off + 0x04;
REG_DMA_SETUP_OPS(*dma_write_cfg, reg_off, &reg[0], sizeof(u32),
REG_SINGLE_MODIFY, 0, 0, REG_DMA_SPR_CONFIG_MASK);
rc = dma_ops->setup_payload(dma_write_cfg);
if (rc) {
DRM_ERROR("write spr config pt1 failed ret %d\n", rc);
return rc;
}
reg_off = base_off + 0x08;
REG_DMA_SETUP_OPS(*dma_write_cfg, reg_off, &reg[1], sizeof(u32),
REG_BLK_WRITE_SINGLE, 0, 0, 0);
rc = dma_ops->setup_payload(dma_write_cfg);
if (rc) {
DRM_ERROR("write spr config failed ret %d\n", rc);
return rc;
}
bypass:
REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl,
dspp_buf[SPR_INIT][ctx->idx],
dma_write_cfg->dma_buf,
REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE,
SPR_INIT);
LOG_FEATURE_ON;
rc = dma_ops->kick_off(&kick_off);
if (rc) {
DRM_ERROR("failed to kick off ret %d\n", rc);
return;
}
SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
return rc;
}
void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
return rc;
}
void reg_dmav1_setup_spr_init_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
{
struct drm_msm_spr_init_cfg *payload = NULL;
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;
struct sde_reg_dma_buffer *buffer;
uint32_t base_off;
int rc = 0;
bool disable = false;
rc = reg_dma_dspp_check(ctx, cfg, SPR_PU_CFG);
if (reg_dmav1_get_spr_target(ctx, cfg, &dma_ops, &base_off,
&buffer, &disable))
return;
if (disable) {
LOG_FEATURE_OFF;
return reg_dmav1_disable_spr(ctx, cfg);
}
payload = hw_cfg->payload;
REG_DMA_INIT_OPS(dma_write_cfg, MDSS, SPR_INIT, buffer);
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;
}
if (!(payload->flags & SPR_FLAG_BYPASS)) {
rc = reg_dmav1_setup_spr_init_common(ctx, payload, &dma_write_cfg, dma_ops);
if (rc)
return;
}
if (!reg_dmav1_setup_spr_init_kickoff(1, base_off, dma_ops, hw_cfg,
payload, &dma_write_cfg))
LOG_FEATURE_ON;
}
void reg_dmav1_setup_spr_init_cfgv2(struct sde_hw_dspp *ctx, void *cfg)
{
struct drm_msm_spr_init_cfg *payload = NULL;
struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
struct sde_hw_cp_cfg *hw_cfg = cfg;
struct sde_hw_reg_dma_ops *dma_ops;
struct sde_reg_dma_buffer *buffer;
uint32_t base_off;
int rc = 0;
bool disable = false;
if (reg_dmav1_get_spr_target(ctx, cfg, &dma_ops, &base_off, &buffer, &disable))
return;
if (disable) {
LOG_FEATURE_OFF;
return reg_dmav1_disable_spr(ctx, cfg);
}
payload = hw_cfg->payload;
REG_DMA_INIT_OPS(dma_write_cfg, MDSS, SPR_INIT, buffer);
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;
}
if (!(payload->flags & SPR_FLAG_BYPASS)) {
rc = reg_dmav1_setup_spr_init_common(ctx, payload, &dma_write_cfg, dma_ops);
if (rc)
return;
if (!hw_cfg->payload || hw_cfg->len != sizeof(struct sde_drm_roi_v1)) {
rc = reg_dmav1_setup_spr_cfg5_params(ctx, payload, &dma_write_cfg, dma_ops);
if (rc)
return;
} else {
ctx->spr_cfg_18_default = 0;
}
if (!reg_dmav1_setup_spr_init_kickoff(2, base_off, dma_ops, hw_cfg,
payload, &dma_write_cfg))
LOG_FEATURE_ON;
}
#define SPR_UDC_MAX_REG_CNT 128
#define SPR_UDC_TARGET (1 << 25)
void reg_dmav1_setup_spr_udc_cfgv2(struct sde_hw_dspp *ctx, void *cfg)
{
size_t UDC_LENGTH = sizeof(uint32_t) * SPR_UDC_PARAM_SIZE_2 / 4;
struct drm_msm_spr_udc_cfg *payload = NULL;
struct sde_reg_dma_kickoff_cfg kick_off;
struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
struct sde_hw_cp_cfg *hw_cfg = cfg;
struct sde_hw_reg_dma_ops *dma_ops;
struct sde_reg_dma_buffer *buffer;
uint32_t base_off, reg_off, reg_cnt;
uint32_t *reg = kvzalloc(UDC_LENGTH, GFP_KERNEL);
int rc = 0;
bool disable = false;
if (reg == NULL) {
DRM_ERROR("Unable to allocate memory for UDC mask programming\n");
return;
}
if (!hw_cfg->payload) {
disable = true;
} else {
disable = false;
if (hw_cfg->len != sizeof(struct drm_msm_spr_udc_cfg)) {
DRM_ERROR("invalid payload size len %d exp %zd\n", hw_cfg->len,
sizeof(struct drm_msm_spr_udc_cfg));
goto cleanup;
}
}
if (reg_dma_dspp_check(ctx, cfg, SPR_UDC))
goto cleanup;
dma_ops = sde_reg_dma_get_ops();
buffer = dspp_buf[SPR_UDC][ctx->idx];
payload = hw_cfg->payload;
base_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base;
dma_ops->reset_reg_dma_buf(buffer);
REG_DMA_INIT_OPS(dma_write_cfg, MDSS, SPR_UDC, buffer);
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);
goto cleanup;
}
if (disable) {
reg[0] = 0;
} else {
uint32_t lines[3];
uint32_t index = 0;
uint32_t i = 0, j = 0;
for (i = 0; i < 3; i++) {
index = i * 4;
reg[index++] = APPLY_MASK_AND_SHIFT(payload->cfg1[j], 16, 0) |
APPLY_MASK_AND_SHIFT(payload->cfg1[j + 1], 16, 16);
j += 2;
lines[i] = APPLY_MASK_AND_SHIFT(payload->cfg1[j + 1], 9, 0);
reg[index++] =
APPLY_MASK_AND_SHIFT(payload->cfg1[j], 10, 0) | lines[i] << 16;
j += 2;
reg[index++] = APPLY_MASK_AND_SHIFT(payload->cfg1[j], 4, 0) |
APPLY_MASK_AND_SHIFT(payload->cfg1[j + 1], 4, 8) |
APPLY_MASK_AND_SHIFT(payload->cfg1[j + 2], 4, 16) |
APPLY_MASK_AND_SHIFT(payload->cfg1[j + 3], 4, 24);
j += 4;
reg[index++] = APPLY_MASK_AND_SHIFT(payload->cfg1[j++], 11, 0);
}
reg_off = base_off + 0x120;
reg_cnt = index;
REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, reg,
reg_cnt * sizeof(u32), REG_BLK_WRITE_SINGLE, 0, 0, 0);
rc = dma_ops->setup_payload(&dma_write_cfg);
if (rc) {
DRM_ERROR("write spr udc cfg p1 failed ret %d\n", rc);
goto cleanup;
}
reg_off = base_off + 0x150;
reg[0] = 0;
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 spr udc cfg p2 failed - ret %d\n", rc);
goto cleanup;
}
memset(reg, 0, UDC_LENGTH);
for (i = 0; i < 3; i++) {
uint32_t line = 0;
uint32_t index = i * (SPR_UDC_PARAM_SIZE_2 / 3);
uint32_t line_cnt = (lines[i] + 1) >> 1;
if (i == 0)
j = (SPR_UDC_PARAM_SIZE_2 / 12) * 2;
else if (i == 1)
j = 0;
else
j = (SPR_UDC_PARAM_SIZE_2 / 12);
for (line = 0; line < line_cnt; line++) {
reg[j++] = (payload->cfg2[index] & 0xff) |
((payload->cfg2[index + 1] & 0xff) << 8) |
((payload->cfg2[index + 2] & 0xff) << 16) |
((payload->cfg2[index + 3] & 0xff) << 24);
index += 4;
}
}
reg_off = base_off + 0x154;
REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, reg, UDC_LENGTH,
REG_BLK_WRITE_INC, 0, 0, 0);
rc = dma_ops->setup_payload(&dma_write_cfg);
if (rc) {
DRM_ERROR("write spr udc cfg p3 failed - L%d\t ret %d\n", i, rc);
goto cleanup;
}
reg[0] = SPR_UDC_TARGET;
}
reg_off = base_off + 0x4;
REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, reg, sizeof(u32),
REG_SINGLE_MODIFY, 0, 0, ~SPR_UDC_TARGET);
rc = dma_ops->setup_payload(&dma_write_cfg);
if (rc) {
DRM_ERROR("write spr udc config failed ret %d\n", rc);
goto cleanup;
}
REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl,
dma_write_cfg.dma_buf,
REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE, SPR_UDC);
rc = dma_ops->kick_off(&kick_off);
if (rc) {
DRM_ERROR("failed to kick off ret %d\n", rc);
goto cleanup;
}
if (disable)
LOG_FEATURE_OFF;
else
LOG_FEATURE_ON;
cleanup:
kvfree(reg);
}
int reg_dmav1_setup_spr_pu_common(struct sde_hw_dspp *ctx, struct sde_hw_cp_cfg *hw_cfg,
struct msm_roi_list *roi_list,
struct sde_hw_reg_dma_ops *dma_ops, struct sde_reg_dma_buffer *buffer)
{
struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
uint32_t reg, reg_off, base_off;
int rc = 0;
if (!roi_list) {
DRM_DEBUG("invalid payload of pu rects\n");
reg = 0;
} else {
roi_list = hw_cfg->payload;
if (roi_list->num_rects > 1) {
DRM_ERROR("multiple pu regions not supported with spr\n");
return;
return -EINVAL;
}
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;
return -EINVAL;
}
reg = APPLY_MASK_AND_SHIFT(roi_list->roi[0].x1, 16, 0) |
APPLY_MASK_AND_SHIFT(roi_list->roi[0].y1, 16, 16);
}
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_INIT_OPS(dma_write_cfg, MDSS, SPR_PU_CFG, buffer);
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;
return rc;
}
base_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base;
@@ -5182,14 +5515,42 @@ void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
rc = dma_ops->setup_payload(&dma_write_cfg);
if (rc) {
DRM_ERROR("write pu config failed ret %d\n", rc);
return;
}
return rc;
}
void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *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;
struct sde_reg_dma_buffer *buffer;
struct msm_roi_list *roi_list = NULL;
int rc = 0;
rc = reg_dma_dspp_check(ctx, cfg, SPR_PU_CFG);
if (rc)
return;
buffer = dspp_buf[SPR_PU_CFG][ctx->idx];
dma_ops = sde_reg_dma_get_ops();
if (dma_ops == NULL)
return;
SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY);
dma_ops->reset_reg_dma_buf(buffer);
if (hw_cfg->payload && hw_cfg->len == sizeof(struct sde_drm_roi_v1))
roi_list = hw_cfg->payload;
rc = reg_dmav1_setup_spr_pu_common(ctx, cfg, roi_list, dma_ops, buffer);
if (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,
SPR_PU_CFG);
LOG_FEATURE_ON;
buffer, REG_DMA_WRITE, DMA_CTL_QUEUE0,
WRITE_IMMEDIATE, SPR_PU_CFG);
rc = dma_ops->kick_off(&kick_off);
if (rc) {
DRM_ERROR("failed to kick off ret %d\n", rc);
@@ -5198,6 +5559,71 @@ void reg_dmav1_setup_spr_pu_cfgv1(struct sde_hw_dspp *ctx, void *cfg)
SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
}
void reg_dmav1_setup_spr_pu_cfgv2(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;
struct sde_reg_dma_buffer *buffer;
uint32_t reg_off, base_off;
struct msm_roi_list *roi_list = NULL;
int rc;
rc = reg_dma_dspp_check(ctx, cfg, SPR_PU_CFG);
if (rc)
return;
buffer = dspp_buf[SPR_PU_CFG][ctx->idx];
dma_ops = sde_reg_dma_get_ops();
if (dma_ops == NULL)
return;
SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY);
dma_ops->reset_reg_dma_buf(buffer);
if (hw_cfg->payload && hw_cfg->len == sizeof(struct sde_drm_roi_v1))
roi_list = hw_cfg->payload;
rc = reg_dmav1_setup_spr_pu_common(ctx, cfg, roi_list, dma_ops, buffer);
if (rc)
return;
if (ctx->spr_cfg_18_default != 0) {
uint32_t reg = ctx->spr_cfg_18_default;
//No ROI list means full screen update so apply without modification
if (roi_list && roi_list->roi[0].y1 != 0)
reg &= 0xFFFFFFFC;
if (roi_list && roi_list->roi[0].y2 != hw_cfg->displayv)
reg &= 0xFFFFFFCF;
base_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base;
reg_off = base_off + 0x7C;
REG_DMA_INIT_OPS(dma_write_cfg, MDSS, SPR_PU_CFG, buffer);
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("SPR V2 PU failed ret %d\n", rc);
return;
}
}
REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl,
buffer, REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE, SPR_PU_CFG);
rc = dma_ops->kick_off(&kick_off);
if (rc) {
DRM_ERROR("failed to kick off ret %d\n", rc);
return;
}
SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
}
static void reg_dma_demura_off(struct sde_hw_dspp *ctx,
struct sde_hw_cp_cfg *hw_cfg)
{

View File

@@ -311,6 +311,13 @@ void reg_dmav2_setup_dspp_3d_gamutv43(struct sde_hw_dspp *ctx, void *cfg);
*/
void reg_dmav2_setup_vig_gamutv61(struct sde_hw_pipe *ctx, void *cfg);
/**
* reg_dmav2_init_spr_op_v1() - initialize spr sub-feature buffer for reg dma v2.
* @feature: SPR sub-feature
* @dspp_idx: dspp idx to allocate for
*/
int reg_dmav2_init_spr_op_v1(int feature, enum sde_dspp dspp_idx);
/**
* reg_dmav1_setup_spr_init_cfgv1 - function to configure spr through LUTDMA
* @ctx: Pointer to dspp context
@@ -318,6 +325,20 @@ void reg_dmav2_setup_vig_gamutv61(struct sde_hw_pipe *ctx, void *cfg);
*/
void reg_dmav1_setup_spr_init_cfgv1(struct sde_hw_dspp *ctx, void *cfg);
/**
* reg_dmav1_setup_spr_init_cfgv2 - function to configure spr v2 through LUTDMA
* @ctx: Pointer to dspp context
* @cfg: Pointer to configuration
*/
void reg_dmav1_setup_spr_init_cfgv2(struct sde_hw_dspp *ctx, void *cfg);
/**
* reg_dmav1_setup_spr_udc_cfgv2 - function to configure spr v2 UDC through LUTDMA
* @ctx: Pointer to dspp context
* @cfg: Pointer to configuration
*/
void reg_dmav1_setup_spr_udc_cfgv2(struct sde_hw_dspp *ctx, void *cfg);
/**
* reg_dmav1_setup_spr_pu_cfgv1 - function to configure spr pu through LUTDMA
* @ctx: Pointer to dspp context
@@ -325,6 +346,13 @@ 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);
/**
* reg_dmav1_setup_spr_pu_cfgv2 - function to configure spr v2 pu through LUTDMA
* @ctx: Pointer to dspp context
* @cfg: Pointer to configuration
*/
void reg_dmav1_setup_spr_pu_cfgv2(struct sde_hw_dspp *ctx, void *cfg);
/**
* reg_dmav1_setup_demurav1() - function to set up the demurav1 configuration.
* @ctx: dspp ctx info

View File

@@ -78,6 +78,7 @@ enum sde_reg_dma_features {
HSIC,
GC,
SPR_INIT,
SPR_UDC,
SPR_PU_CFG,
LTM_INIT,
LTM_ROI,