From 89a141df9fa06c786a433b9f5d66cc37828dcd98 Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Wed, 3 Jul 2019 22:59:28 -0700 Subject: [PATCH 1/5] disp: msm: sde: add support for mdss spr hw block This change parses SPR hw block entries from device tree and populate SPR block as sub block of DSPP block. Change also enables register dump by registering sub blocks with sde driver register dump routine. Change-Id: Ic603cd3cc001dddce5dfea61341c166a5fec1682 Signed-off-by: Prabhanjan Kandula --- msm/sde/sde_hw_catalog.c | 58 +++++++++++++++++++++++++++++++++++++++- msm/sde/sde_hw_catalog.h | 2 ++ msm/sde/sde_hw_dspp.c | 8 ++++++ 3 files changed, 67 insertions(+), 1 deletion(-) 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..decf736d99 100644 --- a/msm/sde/sde_hw_dspp.c +++ b/msm/sde/sde_hw_dspp.c @@ -371,6 +371,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: From 45af4566d91697c3c48df9d08324c99146fbd585 Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Mon, 23 Sep 2019 19:24:20 -0700 Subject: [PATCH 2/5] disp: msm: dsi: add support for spr enable from panel config This change parses SPR enable entry from panel device tree and populates SPR specific information in panel data structure. Valid entry of SPR pack type is treated as panel requirement to enable SPR for specified pack type from source end. This change also populate connector capabilities blob with SPR pack type. Change-Id: I9d9ab8a990476fba281e12890bf3f7b17a174d79 Signed-off-by: Prabhanjan Kandula --- msm/dsi/dsi_drm.c | 4 ++++ msm/dsi/dsi_panel.c | 25 +++++++++++++++++++++++++ msm/dsi/dsi_panel.h | 7 +++++++ msm/msm_drv.h | 26 ++++++++++++++++++++++++++ 4 files changed, 62 insertions(+) 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 From b3a61a8922b60c9c8bc3a0943a477a0d7b8352d5 Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Mon, 3 Feb 2020 15:52:10 -0800 Subject: [PATCH 3/5] uapi/drm: add data structure for spr block programming This change defines data structure for user mode program to configure SPR block of MDSS hw. Change-Id: Ia4edb5af757541309c50047f4b7476cac8ddd39f Signed-off-by: Prabhanjan Kandula --- include/uapi/display/drm/msm_drm_pp.h | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) 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. From 7469563793bc6a85902e287b4530b97155aed604 Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Mon, 8 Jul 2019 15:03:50 -0700 Subject: [PATCH 4/5] disp: msm: sde: install crtc color property for spr programming This change installs blob property on each crtc for client to program SPR block configuration based on display panel SPR pattern. Property installation is conditional only if MDSS hw has SPR block entries. Change-Id: Ie85423d83b7badc547e75e6eb07ee6b9945f8834 Signed-off-by: Prabhanjan Kandula --- msm/sde/sde_color_processing.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index 97b8df157c..c56a803211 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 */ @@ -2549,6 +2553,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]; From 8120e65f95615118f318e45245b4514c704b75fc Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Tue, 3 Sep 2019 15:58:37 -0700 Subject: [PATCH 5/5] disp: msm: sde: add support for spr hw block configuration This change adds support for programming SPR hw block as per the client configuration from the respective color property blob. Currently only reg dma accelerated path is provided. Change-Id: Ib8559ec2c392be7b69ca43c6364e701fab877a28 Signed-off-by: Prabhanjan Kandula --- msm/sde/sde_color_processing.c | 18 ++ msm/sde/sde_hw_dspp.c | 11 ++ msm/sde/sde_hw_dspp.h | 7 + msm/sde/sde_hw_reg_dma_v1.c | 2 + msm/sde/sde_hw_reg_dma_v1_color_proc.c | 263 +++++++++++++++++++++++++ msm/sde/sde_hw_reg_dma_v1_color_proc.h | 6 + msm/sde/sde_reg_dma.h | 2 + 7 files changed, 309 insertions(+) diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index c56a803211..33b04c0415 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -794,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 { \ @@ -843,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]; @@ -1503,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, diff --git a/msm/sde/sde_hw_dspp.c b/msm/sde/sde_hw_dspp.c index decf736d99..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) 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 a22787f6bf..2809674d0a 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] = { @@ -4417,3 +4422,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,