diff --git a/include/uapi/display/drm/msm_drm_pp.h b/include/uapi/display/drm/msm_drm_pp.h index d2eb1f2a5d..2db4ed2eaa 100644 --- a/include/uapi/display/drm/msm_drm_pp.h +++ b/include/uapi/display/drm/msm_drm_pp.h @@ -561,6 +561,38 @@ struct drm_msm_ltm_buffer { __u32 status; }; +#define SPR_INIT_PARAM_SIZE_1 4 +#define SPR_INIT_PARAM_SIZE_2 5 +#define SPR_INIT_PARAM_SIZE_3 16 +#define SPR_INIT_PARAM_SIZE_4 24 +#define SPR_INIT_PARAM_SIZE_5 32 + +/** + * struct drm_msm_spr_init_cfg - SPR initial configuration structure + * + */ +struct drm_msm_spr_init_cfg { + __u64 flags; + __u16 cfg0; + __u16 cfg1; + __u16 cfg2; + __u16 cfg3; + __u16 cfg4; + __u16 cfg5; + __u16 cfg6; + __u16 cfg7; + __u16 cfg8; + __u16 cfg9; + __u32 cfg10; + __u16 cfg11[SPR_INIT_PARAM_SIZE_1]; + __u16 cfg12[SPR_INIT_PARAM_SIZE_1]; + __u16 cfg13[SPR_INIT_PARAM_SIZE_1]; + __u16 cfg14[SPR_INIT_PARAM_SIZE_2]; + __u16 cfg15[SPR_INIT_PARAM_SIZE_5]; + int cfg16[SPR_INIT_PARAM_SIZE_3]; + int cfg17[SPR_INIT_PARAM_SIZE_4]; +}; + /** * struct drm_msm_ad4_manual_str_cfg - ad4 manual strength config set * by user-space client. diff --git a/msm/dsi/dsi_drm.c b/msm/dsi/dsi_drm.c index 90f03add80..fbea1f3e2e 100644 --- a/msm/dsi/dsi_drm.c +++ b/msm/dsi/dsi_drm.c @@ -650,6 +650,10 @@ int dsi_conn_set_info_blob(struct drm_connector *connector, break; } + if (panel->spr_info.enable) + sde_kms_info_add_keystr(info, "spr_pack_type", + msm_spr_pack_type_str[panel->spr_info.pack_type]); + if (mode_info && mode_info->roi_caps.enabled) { sde_kms_info_add_keyint(info, "partial_update_num_roi", mode_info->roi_caps.num_roi); diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index 3e872e04f1..02a7f87b89 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -1860,6 +1860,8 @@ error: static int dsi_panel_parse_misc_features(struct dsi_panel *panel) { struct dsi_parser_utils *utils = &panel->utils; + const char *string; + int i, rc = 0; panel->ulps_feature_enabled = utils->read_bool(utils->data, "qcom,ulps-enabled"); @@ -1881,6 +1883,29 @@ static int dsi_panel_parse_misc_features(struct dsi_panel *panel) panel->lp11_init = utils->read_bool(utils->data, "qcom,mdss-dsi-lp11-init"); + + panel->spr_info.enable = false; + panel->spr_info.pack_type = MSM_DISPLAY_SPR_TYPE_MAX; + + rc = utils->read_string(utils->data, "qcom,spr-pack-type", &string); + if (!rc) { + // find match for pack-type string + for (i = 0; i < MSM_DISPLAY_SPR_TYPE_MAX; i++) { + if (msm_spr_pack_type_str[i] && + (!strcmp(string, msm_spr_pack_type_str[i]))) { + panel->spr_info.enable = true; + panel->spr_info.pack_type = i; + break; + } + } + } + + pr_debug("%s source side spr packing, pack-type %s\n", + panel->spr_info.enable ? "enable" : "disable", + panel->spr_info.enable ? + msm_spr_pack_type_str[panel->spr_info.pack_type] : "none"); + + return 0; } diff --git a/msm/dsi/dsi_panel.h b/msm/dsi/dsi_panel.h index 946bbf0bcb..07d00450e4 100644 --- a/msm/dsi/dsi_panel.h +++ b/msm/dsi/dsi_panel.h @@ -155,6 +155,11 @@ struct drm_panel_esd_config { u32 groups; }; +struct dsi_panel_spr_info { + bool enable; + enum msm_display_spr_pack_type pack_type; +}; + struct dsi_panel { const char *name; const char *type; @@ -203,6 +208,8 @@ struct dsi_panel { char dce_pps_cmd[DSI_CMD_PPS_SIZE]; enum dsi_dms_mode dms_mode; + struct dsi_panel_spr_info spr_info; + bool sync_broadcast_en; int panel_test_gpio; diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 59c72000b2..24bb320c5c 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -231,6 +231,32 @@ enum msm_display_compression_type { #define MSM_DISPLAY_COMPRESSION_RATIO_NONE 1 #define MSM_DISPLAY_COMPRESSION_RATIO_MAX 5 +/** + * enum msm_display_spr_pack_type - sub pixel rendering pack patterns supported + * @MSM_DISPLAY_SPR_TYPE_NONE: Bypass, no special packing + * @MSM_DISPLAY_SPR_TYPE_PENTILE: pentile pack pattern + * @MSM_DISPLAY_SPR_TYPE_RGBW: RGBW pack pattern + * @MSM_DISPLAY_SPR_TYPE_YYGM: YYGM pack pattern + * @MSM_DISPLAY_SPR_TYPE_YYGW: YYGW pack patterm + * @MSM_DISPLAY_SPR_TYPE_MAX: max and invalid + */ +enum msm_display_spr_pack_type { + MSM_DISPLAY_SPR_TYPE_NONE, + MSM_DISPLAY_SPR_TYPE_PENTILE, + MSM_DISPLAY_SPR_TYPE_RGBW, + MSM_DISPLAY_SPR_TYPE_YYGM, + MSM_DISPLAY_SPR_TYPE_YYGW, + MSM_DISPLAY_SPR_TYPE_MAX +}; + +static const char *msm_spr_pack_type_str[MSM_DISPLAY_SPR_TYPE_MAX] = { + [MSM_DISPLAY_SPR_TYPE_NONE] = "", + [MSM_DISPLAY_SPR_TYPE_PENTILE] = "pentile", + [MSM_DISPLAY_SPR_TYPE_RGBW] = "rgbw", + [MSM_DISPLAY_SPR_TYPE_YYGM] = "yygm", + [MSM_DISPLAY_SPR_TYPE_YYGW] = "yygw" +}; + /** * enum msm_display_caps - features/capabilities supported by displays * @MSM_DISPLAY_CAP_VID_MODE: Video or "active" mode supported diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index 9448420119..d67fa5f5f2 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -58,6 +58,8 @@ static void dspp_ltm_install_property(struct drm_crtc *crtc); static void dspp_rc_install_property(struct drm_crtc *crtc); +static void dspp_spr_install_property(struct drm_crtc *crtc); + static void dspp_vlut_install_property(struct drm_crtc *crtc); static void dspp_gamut_install_property(struct drm_crtc *crtc); @@ -108,6 +110,7 @@ do { \ func[SDE_DSPP_SIXZONE] = dspp_sixzone_install_property; \ func[SDE_DSPP_AD] = dspp_ad_install_property; \ func[SDE_DSPP_LTM] = dspp_ltm_install_property; \ + func[SDE_DSPP_SPR] = dspp_spr_install_property; \ func[SDE_DSPP_VLUT] = dspp_vlut_install_property; \ func[SDE_DSPP_GAMUT] = dspp_gamut_install_property; \ func[SDE_DSPP_GC] = dspp_gc_install_property; \ @@ -164,6 +167,7 @@ enum sde_cp_crtc_features { SDE_CP_CRTC_DSPP_LTM_VLUT, SDE_CP_CRTC_DSPP_SB, SDE_CP_CRTC_DSPP_RC_MASK, + SDE_CP_CRTC_DSPP_SPR_INIT, SDE_CP_CRTC_DSPP_MAX, /* DSPP features end */ @@ -790,6 +794,22 @@ static int check_rc_pu_feature(struct sde_hw_dspp *hw_dspp, return ret; } +static int set_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 (!sde_crtc || !hw_dspp || !hw_dspp->ops.setup_spr_init_config) { + DRM_ERROR("invalid arguments\n"); + ret = -EINVAL; + } else { + hw_dspp->ops.setup_spr_init_config(hw_dspp, hw_cfg); + } + + return ret; +} + feature_wrapper check_crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES]; #define setup_check_crtc_feature_wrappers(wrappers) \ do { \ @@ -839,6 +859,7 @@ do { \ wrappers[SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3] = set_ltm_queue_buf_feature; \ 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; \ } while (0) feature_wrapper set_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES]; @@ -1499,6 +1520,7 @@ static const int dspp_feature_to_sub_blk_tbl[SDE_CP_CRTC_MAX_FEATURES] = { [SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3] = SDE_DSPP_LTM, [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_RC_MASK] = SDE_DSPP_RC, [SDE_CP_CRTC_DSPP_MAX] = SDE_DSPP_MAX, [SDE_CP_CRTC_LM_GC] = SDE_DSPP_MAX, @@ -2550,6 +2572,30 @@ static void dspp_rc_install_property(struct drm_crtc *crtc) } } +static void dspp_spr_install_property(struct drm_crtc *crtc) +{ + struct sde_kms *kms = NULL; + u32 version = 0; + + kms = get_kms(crtc); + if (!kms) { + DRM_ERROR("!kms = %d\n ", !kms); + return; + } + + version = kms->catalog->dspp[0].sblk->spr.version >> 16; + switch (version) { + case 1: + sde_cp_crtc_install_blob_property(crtc, "SDE_SPR_INIT_CFG_V1", + SDE_CP_CRTC_DSPP_SPR_INIT, + sizeof(struct drm_msm_spr_init_cfg)); + break; + default: + DRM_ERROR("version %d not supported\n", version); + break; + } +} + static void lm_gc_install_property(struct drm_crtc *crtc) { char feature_name[256]; diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index f34ab017c4..262f65b8c6 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -397,6 +397,13 @@ enum { RC_PROP_MAX, }; +enum { + SPR_OFF, + SPR_LEN, + SPR_VERSION, + SPR_PROP_MAX, +}; + enum { MIXER_OFF, MIXER_LEN, @@ -717,6 +724,12 @@ static struct sde_prop_type rc_prop[] = { {RC_MEM_TOTAL_SIZE, "qcom,sde-dspp-rc-mem-size", false, PROP_TYPE_U32}, }; +static struct sde_prop_type spr_prop[] = { + {SPR_OFF, "qcom,sde-dspp-spr-off", false, PROP_TYPE_U32_ARRAY}, + {SPR_LEN, "qcom,sde-dspp-spr-size", false, PROP_TYPE_U32}, + {SPR_VERSION, "qcom,sde-dspp-spr-version", false, PROP_TYPE_U32}, +}; + static struct sde_prop_type ds_top_prop[] = { {DS_TOP_OFF, "qcom,sde-dest-scaler-top-off", false, PROP_TYPE_U32}, {DS_TOP_LEN, "qcom,sde-dest-scaler-top-size", false, PROP_TYPE_U32}, @@ -2489,6 +2502,46 @@ end: return rc; } +static int _sde_dspp_spr_parse_dt(struct device_node *np, + struct sde_mdss_cfg *sde_cfg) +{ + int off_count, i; + struct sde_dt_props *props; + struct sde_dspp_cfg *dspp; + struct sde_dspp_sub_blks *sblk; + + props = sde_get_dt_props(np, SPR_PROP_MAX, spr_prop, + ARRAY_SIZE(spr_prop), &off_count); + if (IS_ERR(props)) + return PTR_ERR(props); + + sde_cfg->spr_count = off_count; + if (off_count > sde_cfg->dspp_count) { + SDE_ERROR("limiting %d spr blocks to %d DSPP instances\n", + off_count, sde_cfg->dspp_count); + sde_cfg->spr_count = sde_cfg->dspp_count; + } + + for (i = 0; i < sde_cfg->dspp_count; i++) { + dspp = &sde_cfg->dspp[i]; + sblk = sde_cfg->dspp[i].sblk; + + sblk->spr.id = SDE_DSPP_SPR; + if (props->exists[SPR_OFF] && i < off_count) { + sblk->spr.base = PROP_VALUE_ACCESS(props->values, + SPR_OFF, i); + sblk->spr.len = PROP_VALUE_ACCESS(props->values, + SPR_LEN, 0); + sblk->spr.version = PROP_VALUE_ACCESS(props->values, + SPR_VERSION, 0); + set_bit(SDE_DSPP_SPR, &dspp->features); + } + } + + sde_put_dt_props(props); + return 0; +} + static int _sde_rc_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) { @@ -2669,8 +2722,11 @@ static int sde_dspp_parse_dt(struct device_node *np, if (rc) goto end; - rc = _sde_rc_parse_dt(np, sde_cfg); + rc = _sde_dspp_spr_parse_dt(np, sde_cfg); + if (rc) + goto end; + rc = _sde_rc_parse_dt(np, sde_cfg); end: return rc; } diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index fd6314e8c6..9c200ea066 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/msm/sde/sde_hw_catalog.h @@ -765,6 +765,7 @@ struct sde_dspp_sub_blks { struct sde_pp_blk hist; struct sde_pp_blk ad; struct sde_pp_blk ltm; + struct sde_pp_blk spr; struct sde_pp_blk vlut; struct sde_dspp_rc rc; }; @@ -1545,6 +1546,7 @@ struct sde_mdss_cfg { u32 ad_count; u32 ltm_count; u32 rc_count; + u32 spr_count; u32 merge_3d_count; struct sde_merge_3d_cfg merge_3d[MAX_BLOCKS]; diff --git a/msm/sde/sde_hw_dspp.c b/msm/sde/sde_hw_dspp.c index 8ec284e133..a349abcbfa 100644 --- a/msm/sde/sde_hw_dspp.c +++ b/msm/sde/sde_hw_dspp.c @@ -274,6 +274,16 @@ static void dspp_rc(struct sde_hw_dspp *c) } } +static void dspp_spr(struct sde_hw_dspp *c) +{ + if (c->cap->sblk->spr.version == SDE_COLOR_PROCESS_VER(0x1, 0x0)) { + reg_dmav1_init_dspp_op_v4(SDE_DSPP_SPR, c->idx); + c->ops.setup_spr_init_config = reg_dmav1_setup_spr_init_cfgv1; + } else { + c->ops.setup_spr_init_config = NULL; + } +} + static void (*dspp_blocks[SDE_DSPP_MAX])(struct sde_hw_dspp *c); static void _init_dspp_ops(void) @@ -291,6 +301,7 @@ static void _init_dspp_ops(void) dspp_blocks[SDE_DSPP_AD] = dspp_ad; dspp_blocks[SDE_DSPP_LTM] = dspp_ltm; dspp_blocks[SDE_DSPP_RC] = dspp_rc; + dspp_blocks[SDE_DSPP_SPR] = dspp_spr; } static void _setup_dspp_ops(struct sde_hw_dspp *c, unsigned long features) @@ -371,6 +382,14 @@ struct sde_hw_dspp *sde_hw_dspp_init(enum sde_dspp idx, c->hw.blk_off + cfg->sblk->rc.base + cfg->sblk->rc.len, c->hw.xin_id); } + + if ((cfg->sblk->spr.id == SDE_DSPP_SPR) && cfg->sblk->spr.base) { + snprintf(buf, ARRAY_SIZE(buf), "%s_%d", "spr", c->idx - DSPP_0); + sde_dbg_reg_register_dump_range(SDE_DBG_NAME, buf, + c->hw.blk_off + cfg->sblk->spr.base, + c->hw.blk_off + cfg->sblk->spr.base + + cfg->sblk->spr.len, c->hw.xin_id); + } return c; blk_init_error: diff --git a/msm/sde/sde_hw_dspp.h b/msm/sde/sde_hw_dspp.h index 0b493e5906..003b2522bd 100644 --- a/msm/sde/sde_hw_dspp.h +++ b/msm/sde/sde_hw_dspp.h @@ -249,6 +249,13 @@ struct sde_hw_dspp_ops { * Return: 0 on success, non-zero otherwise. */ int (*setup_rc_data)(struct sde_hw_dspp *ctx, void *cfg); + + /** + * setup_spr_init_config - function to configure spr hw block + * @ctx: Pointer to dspp context + * @cfg: Pointer to configuration + */ + void (*setup_spr_init_config)(struct sde_hw_dspp *ctx, void *cfg); }; /** diff --git a/msm/sde/sde_hw_reg_dma_v1.c b/msm/sde/sde_hw_reg_dma_v1.c index 2f39de3627..b8d77f54fc 100644 --- a/msm/sde/sde_hw_reg_dma_v1.c +++ b/msm/sde/sde_hw_reg_dma_v1.c @@ -808,6 +808,8 @@ int init_v12(struct sde_hw_reg_dma *cfg) v1_supported[LTM_VLUT] = GRP_LTM_HW_BLK_SELECT; v1_supported[RC_DATA] = (GRP_DSPP_HW_BLK_SELECT | GRP_MDSS_HW_BLK_SELECT); + v1_supported[SPR_INIT] = (GRP_DSPP_HW_BLK_SELECT | + GRP_MDSS_HW_BLK_SELECT); return 0; } diff --git a/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/msm/sde/sde_hw_reg_dma_v1_color_proc.c index 78899a9ac5..e6da88c17c 100644 --- a/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -78,9 +78,12 @@ REG_DMA_HEADERS_BUFFER_SZ) #define LTM_VLUT_MEM_SIZE ((sizeof(struct drm_msm_ltm_data)) + \ REG_DMA_HEADERS_BUFFER_SZ) +#define SPR_INIT_MEM_SIZE ((sizeof(struct drm_msm_spr_init_cfg)) + \ + REG_DMA_HEADERS_BUFFER_SZ) #define REG_MASK(n) ((BIT(n)) - 1) #define REG_MASK_SHIFT(n, shift) ((REG_MASK(n)) << (shift)) +#define APPLY_MASK_AND_SHIFT(x, n, shift) ((x & (REG_MASK(n))) << (shift)) #define REG_DMA_VIG_GAMUT_OP_MASK 0x300 #define REG_DMA_VIG_IGC_OP_MASK 0x1001F #define DMA_DGM_0_OP_MODE_OFF 0x604 @@ -134,6 +137,7 @@ static u32 feature_map[SDE_DSPP_MAX] = { /* MEMCOLOR can be mapped to any MEMC_SKIN/SKY/FOLIAGE/PROT*/ [SDE_DSPP_MEMCOLOR] = MEMC_SKIN, [SDE_DSPP_SIXZONE] = SIX_ZONE, + [SDE_DSPP_SPR] = SPR_INIT, [SDE_DSPP_DITHER] = REG_DMA_FEATURES_MAX, [SDE_DSPP_HIST] = REG_DMA_FEATURES_MAX, [SDE_DSPP_AD] = REG_DMA_FEATURES_MAX, @@ -165,6 +169,7 @@ static u32 feature_reg_dma_sz[SDE_DSPP_MAX] = { [SDE_DSPP_SIXZONE] = SIXZONE_MEM_SIZE, [SDE_DSPP_MEMCOLOR] = MEMCOLOR_MEM_SIZE, [SDE_DSPP_RC] = RC_MEM_SIZE, + [SDE_DSPP_SPR] = SPR_INIT_MEM_SIZE, }; static u32 sspp_feature_reg_dma_sz[SDE_SSPP_MAX] = { @@ -4430,3 +4435,261 @@ void reg_dmav2_setup_vig_gamutv61(struct sde_hw_pipe *ctx, void *cfg) exit: kfree(data); } + +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, + struct sde_hw_reg_dma_ops *dma_ops) +{ + uint32_t reg_off, reg_cnt, base_off; + uint32_t reg[16]; + int i, index, rc = 0; + + if (!payload->cfg3) + return rc; + + base_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base; + reg_cnt = 2; + reg_off = base_off + 0x70; + reg[0] = APPLY_MASK_AND_SHIFT(payload->cfg13[0], 10, 0) | + APPLY_MASK_AND_SHIFT(payload->cfg13[1], 10, 10) | + APPLY_MASK_AND_SHIFT(payload->cfg13[2], 10, 20); + reg[1] = payload->cfg10 & REG_MASK(30); + + 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 cfg13 failed ret %d\n", rc); + return rc; + } + + reg_cnt = ARRAY_SIZE(payload->cfg15) / 2; + reg_off = base_off + 0xA0; + for (i = 0; i < reg_cnt; i++) { + index = 2 * i; + reg[i] = APPLY_MASK_AND_SHIFT(payload->cfg15[index], 12, 0) | + APPLY_MASK_AND_SHIFT(payload->cfg15[index + 1], 12, 16); + } + + 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 cfg15 failed ret %d\n", rc); + return rc; + } + + return rc; +} + +int reg_dmav1_setup_spr_cfg4_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, reg_cnt, base_off; + uint32_t reg[16]; + int rc = 0; + + if (!payload->cfg4) + return rc; + + reg_cnt = 3; + base_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base; + reg_off = base_off + 0x60; + reg[0] = payload->cfg9 & 0x0F; + reg[1] = APPLY_MASK_AND_SHIFT(payload->cfg12[3], 10, 0) | + APPLY_MASK_AND_SHIFT(payload->cfg12[0], 11, 16); + reg[2] = APPLY_MASK_AND_SHIFT(payload->cfg12[1], 11, 0) | + APPLY_MASK_AND_SHIFT(payload->cfg12[2], 11, 16); + + 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 cfg12 failed ret %d\n", rc); + return rc; + } + + 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; + int rc = 0; + + 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; + } + + reg_off = ctx->hw.blk_off + ctx->cap->sblk->spr.base + 0x04; + REG_DMA_SETUP_OPS(dma_write_cfg, reg_off, ®, + sizeof(u32), REG_BLK_WRITE_SINGLE, 0, 0, 0); + rc = dma_ops->setup_payload(&dma_write_cfg); + if (rc) { + DRM_ERROR("write spr disable failed ret %d\n", rc); + return; + } + + REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, + dspp_buf[SPR_INIT][ctx->idx], + REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE); + rc = dma_ops->kick_off(&kick_off); + if (rc) { + DRM_ERROR("failed to kick off ret %d\n", rc); + return; + } +} + +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_off, reg_cnt, base_off; + uint32_t reg[16]; + int i, index, rc = 0; + + rc = reg_dma_dspp_check(ctx, cfg, SPR_INIT); + if (rc) + return; + + if (!hw_cfg->payload) + 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; + } + + 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); + + 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; + } + + 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; + for (i = 0; i < reg_cnt; i++) { + index = 6 * i; + reg[i] = APPLY_MASK_AND_SHIFT(payload->cfg17[index], 5, 0) | + APPLY_MASK_AND_SHIFT(payload->cfg17[index + 1], 5, 5) | + APPLY_MASK_AND_SHIFT(payload->cfg17[index + 2], 5, 10) | + APPLY_MASK_AND_SHIFT(payload->cfg17[index + 3], 5, 15) | + APPLY_MASK_AND_SHIFT(payload->cfg17[index + 4], 5, 20) | + APPLY_MASK_AND_SHIFT(payload->cfg17[index + 5], 5, 25); + } + reg[reg_cnt - 1] &= 0x3FF; + + 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 cfg17 failed ret %d\n", rc); + return; + } + + reg_cnt = ARRAY_SIZE(payload->cfg16) / 2; + reg_off = base_off + 0x34; + for (i = 0; i < reg_cnt; i++) { + index = 2 * i; + reg[i] = APPLY_MASK_AND_SHIFT(payload->cfg16[index], 11, 0) | + 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_BLK_WRITE_SINGLE, 0, 0, 0); + rc = dma_ops->setup_payload(&dma_write_cfg); + if (rc) { + DRM_ERROR("write spr cfg16 failed ret %d\n", rc); + return; + } + + rc = reg_dmav1_setup_spr_cfg3_params(ctx, payload, + &dma_write_cfg, dma_ops); + if (rc) + return; + + rc = reg_dmav1_setup_spr_cfg4_params(ctx, payload, + &dma_write_cfg, dma_ops); + if (rc) + return; + + REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, + dspp_buf[SPR_INIT][ctx->idx], + REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE); + rc = dma_ops->kick_off(&kick_off); + if (rc) { + DRM_ERROR("failed to kick off ret %d\n", rc); + return; + } +} diff --git a/msm/sde/sde_hw_reg_dma_v1_color_proc.h b/msm/sde/sde_hw_reg_dma_v1_color_proc.h index af6378836e..c949e9fb00 100644 --- a/msm/sde/sde_hw_reg_dma_v1_color_proc.h +++ b/msm/sde/sde_hw_reg_dma_v1_color_proc.h @@ -288,5 +288,11 @@ 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_dmav1_setup_spr_init_cfgv1 - function to configure spr through LUTDMA + * @ctx: Pointer to dspp context + * @cfg: Pointer to configuration + */ +void reg_dmav1_setup_spr_init_cfgv1(struct sde_hw_dspp *ctx, void *cfg); #endif /* _SDE_HW_REG_DMA_V1_COLOR_PROC_H */ diff --git a/msm/sde/sde_reg_dma.h b/msm/sde/sde_reg_dma.h index 428cbcff6a..5c83b5022a 100644 --- a/msm/sde/sde_reg_dma.h +++ b/msm/sde/sde_reg_dma.h @@ -54,6 +54,7 @@ enum sde_reg_dma_read_sel { * @SIX_ZONE: six zone * @HSIC: Hue, saturation and contrast * @GC: gamma correction + * @SPR_INIT: Sub pixel rendering init feature * @LTM_INIT: LTM INIT * @LTM_ROI: LTM ROI * @LTM_VLUT: LTM VLUT @@ -73,6 +74,7 @@ enum sde_reg_dma_features { SIX_ZONE, HSIC, GC, + SPR_INIT, LTM_INIT, LTM_ROI, LTM_VLUT,