Эх сурвалжийг харах

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 <[email protected]>
Ping Li 6 жил өмнө
parent
commit
652b195ba4

+ 13 - 1
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",

+ 32 - 0
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;
+}

+ 25 - 0
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 */

+ 29 - 0
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

+ 3 - 1
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;