From 652b195ba40341a6a58813a98a1cbafd29693672 Mon Sep 17 00:00:00 2001 From: Ping Li Date: Wed, 5 Jun 2019 13:18:40 -0700 Subject: [PATCH] disp: msm: sde: Add LTM sw fuse check support Add checks for LTM sw fuse value to only install the LTM properties when the LTM sw fuse is set to enable. Change-Id: I6876bfcf12ddb912e7b7a80e07c33108fd4b85b9 Signed-off-by: Ping Li --- msm/sde/sde_color_processing.c | 14 +++++++++++++- msm/sde/sde_hw_top.c | 32 ++++++++++++++++++++++++++++++++ msm/sde/sde_hw_top.h | 25 +++++++++++++++++++++++++ msm/sde/sde_kms.c | 29 +++++++++++++++++++++++++++++ msm/sde/sde_kms.h | 4 +++- 5 files changed, 102 insertions(+), 2 deletions(-) diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index 9c093ce371..2f827a8feb 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -1883,9 +1883,21 @@ static void dspp_ltm_install_property(struct drm_crtc *crtc) char feature_name[256]; struct sde_kms *kms = NULL; struct sde_mdss_cfg *catalog = NULL; - u32 version; + u32 version = 0, ltm_sw_fuse = 0; kms = get_kms(crtc); + if (!kms || !kms->hw_sw_fuse) { + DRM_ERROR("!kms = %d\n", !kms); + return; + } + + ltm_sw_fuse = sde_hw_get_ltm_sw_fuse_value(kms->hw_sw_fuse); + DRM_DEBUG_DRIVER("ltm_sw_fuse value: 0x%x\n", ltm_sw_fuse); + if (ltm_sw_fuse != SW_FUSE_ENABLE) { + pr_info("ltm_sw_fuse is not enabled: 0x%x\n", ltm_sw_fuse); + return; + } + catalog = kms->catalog; version = catalog->dspp[0].sblk->ltm.version >> 16; snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d", diff --git a/msm/sde/sde_hw_top.c b/msm/sde/sde_hw_top.c index 7c2de6c3d0..0be2bf56ab 100644 --- a/msm/sde/sde_hw_top.c +++ b/msm/sde/sde_hw_top.c @@ -47,6 +47,8 @@ #define MDP_WD_TIMER_4_CTL2 0x444 #define MDP_WD_TIMER_4_LOAD_VALUE 0x448 +#define LTM_SW_FUSE_OFFSET 0x10 + #define MDP_TICK_COUNT 16 #define XO_CLK_RATE 19200 #define MS_TICKS_IN_SEC 1000 @@ -620,3 +622,33 @@ void sde_hw_mdp_destroy(struct sde_hw_mdp *mdp) kfree(mdp); } +struct sde_hw_sw_fuse *sde_hw_sw_fuse_init(void __iomem *addr, + u32 sw_fuse_len, const struct sde_mdss_cfg *m) +{ + struct sde_hw_sw_fuse *c; + + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) + return ERR_PTR(-ENOMEM); + + c->hw.base_off = addr; + c->hw.blk_off = 0; + c->hw.length = sw_fuse_len; + c->hw.hwversion = m->hwversion; + + return c; +} + +void sde_hw_sw_fuse_destroy(struct sde_hw_sw_fuse *sw_fuse) +{ + kfree(sw_fuse); +} + +u32 sde_hw_get_ltm_sw_fuse_value(struct sde_hw_sw_fuse *sw_fuse) +{ + u32 ltm_sw_fuse = 0; + + if (sw_fuse) + ltm_sw_fuse = SDE_REG_READ(&sw_fuse->hw, LTM_SW_FUSE_OFFSET); + return ltm_sw_fuse; +} diff --git a/msm/sde/sde_hw_top.h b/msm/sde/sde_hw_top.h index bda4da7de6..80888329ae 100644 --- a/msm/sde/sde_hw_top.h +++ b/msm/sde/sde_hw_top.h @@ -234,6 +234,12 @@ struct sde_hw_sid { struct sde_hw_blk_reg_map hw; }; +#define SW_FUSE_ENABLE 0x1 +struct sde_hw_sw_fuse { + /* sw fuse base */ + struct sde_hw_blk_reg_map hw; +}; + /** * sde_hw_sid_rotator_set - initialize the sid blk reg map * @addr: Mapped register io address @@ -271,4 +277,23 @@ struct sde_hw_mdp *sde_hw_mdptop_init(enum sde_mdp idx, void sde_hw_mdp_destroy(struct sde_hw_mdp *mdp); +/** + * sde_hw_sw_fuse_init - initialize the sw fuse blk reg map + * @addr: Mapped register io address + * @sw_fuse_len: Length of block + * @m: Pointer to mdss catalog data + */ +struct sde_hw_sw_fuse *sde_hw_sw_fuse_init(void __iomem *addr, + u32 sw_fuse_len, const struct sde_mdss_cfg *m); +/** + * sde_hw_sw_fuse_destroy - free memory for sw fuse + * @sw_fuse: sde_hw_sw_fuse + */ +void sde_hw_sw_fuse_destroy(struct sde_hw_sw_fuse *sw_fuse); + +/** + * sde_hw_get_ltm_sw_fuse_value - read LTM sw fuse register value + * @sw_fuse: sde_hw_sw_fuse + */ +u32 sde_hw_get_ltm_sw_fuse_value(struct sde_hw_sw_fuse *sw_fuse); #endif /*_SDE_HW_TOP_H */ diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index cddf8220a3..f531691032 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1691,6 +1691,11 @@ static void _sde_kms_hw_destroy(struct sde_kms *sde_kms, msm_iounmap(pdev, sde_kms->sid); sde_kms->sid = NULL; + if (sde_kms->sw_fuse) + msm_iounmap(pdev, sde_kms->sw_fuse); + sde_hw_sw_fuse_destroy(sde_kms->sw_fuse); + sde_kms->sw_fuse = NULL; + if (sde_kms->reg_dma) msm_iounmap(pdev, sde_kms->reg_dma); sde_kms->reg_dma = NULL; @@ -3095,6 +3100,19 @@ static int _sde_kms_hw_init_ioremap(struct sde_kms *sde_kms, if (rc) SDE_ERROR("dbg base register sid failed: %d\n", rc); + sde_kms->sw_fuse = msm_ioremap(platformdev, "swfuse_phys", + "swfuse_phys"); + if (IS_ERR(sde_kms->sw_fuse)) { + sde_kms->sw_fuse = NULL; + SDE_DEBUG("sw_fuse is not defined"); + } else { + sde_kms->sw_fuse_len = msm_iomap_size(platformdev, + "swfuse_phys"); + rc = sde_dbg_reg_register_base("sw_fuse", sde_kms->sw_fuse, + sde_kms->sw_fuse_len); + if (rc) + SDE_ERROR("dbg base register sw_fuse failed: %d\n", rc); + } error: return rc; } @@ -3279,6 +3297,17 @@ static int _sde_kms_hw_init_blocks(struct sde_kms *sde_kms, goto perf_err; } + if (sde_kms->sw_fuse) { + sde_kms->hw_sw_fuse = sde_hw_sw_fuse_init(sde_kms->sw_fuse, + sde_kms->sw_fuse_len, sde_kms->catalog); + if (IS_ERR(sde_kms->hw_sw_fuse)) { + SDE_ERROR("failed to init sw_fuse %ld\n", + PTR_ERR(sde_kms->hw_sw_fuse)); + sde_kms->hw_sw_fuse = NULL; + } + } else { + sde_kms->hw_sw_fuse = NULL; + } /* * _sde_kms_drm_obj_init should create the DRM related objects * i.e. CRTCs, planes, encoders, connectors and so forth diff --git a/msm/sde/sde_kms.h b/msm/sde/sde_kms.h index 909c3b0ae1..a330b13d4d 100644 --- a/msm/sde/sde_kms.h +++ b/msm/sde/sde_kms.h @@ -244,8 +244,9 @@ struct sde_kms { struct dentry *debugfs_vbif; /* io/register spaces: */ - void __iomem *mmio, *vbif[VBIF_MAX], *reg_dma, *sid; + void __iomem *mmio, *vbif[VBIF_MAX], *reg_dma, *sid, *sw_fuse; unsigned long mmio_len, vbif_len[VBIF_MAX], reg_dma_len, sid_len; + unsigned long sw_fuse_len; struct regulator *vdd; struct regulator *mmagic; @@ -271,6 +272,7 @@ struct sde_kms { struct sde_hw_mdp *hw_mdp; struct sde_hw_uidle *hw_uidle; struct sde_hw_sid *hw_sid; + struct sde_hw_sw_fuse *hw_sw_fuse; int dsi_display_count; void **dsi_displays; int wb_display_count;