msm: mdss: Parse ping pong register from device tree

Ping Pong register bases are different between
8974 v1/v2 and 8x26. Add support to parse ping pong register
bases from device tree.

Change-Id: I2109d1bdc360ef858660fd2ccf49985eaacee8a8
Signed-off-by: Siddhartha Agrawal <agrawals@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 6b95625..5bf6b8b 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -75,6 +75,12 @@
 				The number of dspp blocks should match the
 				number of mixers driving data to interface
 				defined in property: qcom,mdss-mixer-intf-off
+- qcom,mdss-pingpong-off:	Array of offset addresses for the available
+				pingpong blocks. These offsets are calculated
+				from regsiter "mdp_phys" defined in reg property.
+				The number of pingpong blocks should match the
+				number of mixers driving data to interface
+				defined in property: qcom,mdss-mixer-intf-off
 - qcom,mdss-mixer-wb-off: 	Array of offset addresses for the available
 				mixer blocks that can be drive data to writeback
 				block.  These offsets will be calculated from
@@ -138,6 +144,7 @@
 					    0x00003A00>;
 		qcom,mdss-mixer-wb-off = <0x00003E00 0x00004200>;
 		qcom,mdss-dspp-off = <0x00004600 0x00004A00 0x00004E00>;
+		qcom,mdss-pingpong-off = <0x00012D00 0x00012E00 0x00012F00>;
 		qcom,mdss-wb-off = <0x00011100 0x00013100 0x00015100
 				    0x00017100 0x00019100>;
 		qcom,mdss-intf-off = <0x00021100 0x00021300
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index ef8cb700..06fcb21 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -32,6 +32,7 @@
 		qcom,mdss-mixer-intf-off = <0x00003200>;
 		qcom,mdss-mixer-wb-off = <0x00003E00>;
 		qcom,mdss-dspp-off = <0x00004600>;
+		qcom,mdss-pingpong-off = <0x00021B00>;
 		qcom,mdss-wb-off = <0x00011100 0x00013100>;
 		qcom,mdss-intf-off = <0x00000000 0x00021300>;
 
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index bccf0fe..ae8cf83 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -56,6 +56,10 @@
 	qcom,write-64bit;
 };
 
+&mdss_mdp {
+	qcom,mdss-pingpong-off = <0x00021B00 0x00021C00 0x00021D00>;
+};
+
 &msm_vidc {
 	qcom,vidc-cp-map = <0x1000000 0x3f000000>;
 	qcom,vidc-ns-map = <0x40000000 0x40000000>;
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 16cdeb1..61f2c4f 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -64,6 +64,7 @@
 			    0x00011900 0x00011D00 0x00012100>;
 	qcom,mdss-intf-off = <0x00012500 0x00012700
 			      0x00012900 0x00012b00>;
+	qcom,mdss-pingpong-off = <0x00012D00 0x00012E00 0x00012F00>;
 };
 
 &msm_vidc {
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 0e68e3d..98b99b2 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1205,9 +1205,10 @@
 static int mdss_mdp_parse_dt_mixer(struct platform_device *pdev)
 {
 
-	u32 nmixers, ndspp;
+	u32 nmixers, ndspp, npingpong;
 	int rc = 0;
-	u32 *mixer_offsets = NULL, *dspp_offsets = NULL;
+	u32 *mixer_offsets = NULL, *dspp_offsets = NULL,
+	    *pingpong_offsets = NULL;
 
 	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
 
@@ -1217,6 +1218,8 @@
 				"qcom,mdss-mixer-wb-off");
 	ndspp = mdss_mdp_parse_dt_prop_len(pdev,
 				"qcom,mdss-dspp-off");
+	npingpong = mdss_mdp_parse_dt_prop_len(pdev,
+				"qcom,mdss-pingpong-off");
 	nmixers = mdata->nmixers_intf + mdata->nmixers_wb;
 
 	if (mdata->nmixers_intf != ndspp) {
@@ -1224,6 +1227,11 @@
 		return -EINVAL;
 	}
 
+	if (mdata->nmixers_intf != npingpong) {
+		pr_err("device tree err: unequal no of pingpong and intf mixers\n");
+		return -EINVAL;
+	}
+
 	mixer_offsets = kzalloc(sizeof(u32) * nmixers, GFP_KERNEL);
 	if (!mixer_offsets) {
 		pr_err("no mem assigned: kzalloc fail\n");
@@ -1236,6 +1244,12 @@
 		rc = -ENOMEM;
 		goto dspp_alloc_fail;
 	}
+	pingpong_offsets = kzalloc(sizeof(u32) * npingpong, GFP_KERNEL);
+	if (!pingpong_offsets) {
+		pr_err("no mem assigned: kzalloc fail\n");
+		rc = -ENOMEM;
+		goto pingpong_alloc_fail;
+	}
 
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-mixer-intf-off",
 		mixer_offsets, mdata->nmixers_intf);
@@ -1252,19 +1266,26 @@
 	if (rc)
 		goto parse_done;
 
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pingpong-off",
+		pingpong_offsets, npingpong);
+	if (rc)
+		goto parse_done;
+
 	rc = mdss_mdp_mixer_addr_setup(mdata, mixer_offsets,
-			dspp_offsets, MDSS_MDP_MIXER_TYPE_INTF,
-			mdata->nmixers_intf);
+			dspp_offsets, pingpong_offsets,
+			MDSS_MDP_MIXER_TYPE_INTF, mdata->nmixers_intf);
 	if (rc)
 		goto parse_done;
 
 	rc = mdss_mdp_mixer_addr_setup(mdata, mixer_offsets +
-			mdata->nmixers_intf, NULL,
+			mdata->nmixers_intf, NULL, NULL,
 			MDSS_MDP_MIXER_TYPE_WRITEBACK, mdata->nmixers_wb);
 	if (rc)
 		goto parse_done;
 
 parse_done:
+	kfree(pingpong_offsets);
+pingpong_alloc_fail:
 	kfree(dspp_offsets);
 dspp_alloc_fail:
 	kfree(mixer_offsets);
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 67f1750..8af3cc0 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -156,6 +156,7 @@
 	u32 ref_cnt;
 	char __iomem *base;
 	char __iomem *dspp_base;
+	char __iomem *pingpong_base;
 	u8 type;
 	u8 params_changed;
 	u16 width;
@@ -295,6 +296,17 @@
 	return readl_relaxed(ctl->base + reg);
 }
 
+static inline void mdss_mdp_pingpong_write(struct mdss_mdp_mixer *mixer,
+				      u32 reg, u32 val)
+{
+	writel_relaxed(val, mixer->pingpong_base + reg);
+}
+
+static inline u32 mdss_mdp_pingpong_read(struct mdss_mdp_mixer *mixer, u32 reg)
+{
+	return readl_relaxed(mixer->pingpong_base + reg);
+}
+
 irqreturn_t mdss_mdp_isr(int irq, void *ptr);
 int mdss_iommu_attach(struct mdss_data_type *mdata);
 int mdss_mdp_copy_splash_screen(struct mdss_panel_data *pdata);
@@ -401,7 +413,7 @@
 int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata, u32 *offsets,
 		u32 *ftch_y_id, u32 type, u32 num_base, u32 len);
 int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata, u32 *mixer_offsets,
-		u32 *dspp_offsets, u32 type, u32 len);
+		u32 *dspp_offsets, u32 *pingpong_offsets, u32 type, u32 len);
 int mdss_mdp_ctl_addr_setup(struct mdss_data_type *mdata, u32 *ctl_offsets,
 		u32 *wb_offsets, u32 len);
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 7e0243b..66e1a0c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1041,7 +1041,8 @@
 }
 
 int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata,
-	 u32 *mixer_offsets, u32 *dspp_offsets, u32 type, u32 len)
+	 u32 *mixer_offsets, u32 *dspp_offsets, u32 *pingpong_offsets,
+	 u32 type, u32 len)
 {
 	struct mdss_mdp_mixer *head;
 	u32 i;
@@ -1061,8 +1062,11 @@
 		head[i].base = mdata->mdp_base + mixer_offsets[i];
 		head[i].ref_cnt = 0;
 		head[i].num = i;
-		if (type == MDSS_MDP_MIXER_TYPE_INTF)
+		if (type == MDSS_MDP_MIXER_TYPE_INTF) {
 			head[i].dspp_base = mdata->mdp_base + dspp_offsets[i];
+			head[i].pingpong_base = mdata->mdp_base +
+				pingpong_offsets[i];
+		}
 	}
 
 	switch (type) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index f8cd0ce..a89740a 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -428,8 +428,6 @@
 	MDSS_MDP_MAX_PINGPONG
 };
 
-#define MDSS_MDP_REG_PP_OFFSET(pp)	(0x21B00 + ((pp) * 0x100))
-
 #define MDSS_MDP_REG_PP_TEAR_CHECK_EN			0x000
 #define MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC		0x004
 #define MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT		0x008
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index ebcc5ca..d6b0fb2 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -39,29 +39,27 @@
 
 struct mdss_mdp_cmd_ctx mdss_mdp_cmd_ctx_list[MAX_SESSIONS];
 
-static int mdss_mdp_cmd_tearcheck_cfg(u32 pp_num,
+static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_mixer *mixer,
 			struct mdss_mdp_cmd_ctx *ctx, int enable)
 {
-	u32 off, cfg;
-
-	off = MDSS_MDP_REG_PP_OFFSET(pp_num);
+	u32 cfg;
 
 	cfg = BIT(19); /* VSYNC_COUNTER_EN */
 	if (ctx->tear_check)
 		cfg |= BIT(20);	/* VSYNC_IN_EN */
 	cfg |= ctx->vsync_cnt;
 
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT,
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT,
 				0xfff0); /* set to verh height */
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_PP_VSYNC_INIT_VAL, 0);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_PP_RD_PTR_IRQ, 0);
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_VSYNC_INIT_VAL, 0);
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_RD_PTR_IRQ, 0);
 
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_PP_START_POS, ctx->v_porch);
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_PP_SYNC_THRESH,
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_START_POS, ctx->v_porch);
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_THRESH,
 			   (CONTINUE_TRESHOLD << 16) | (START_THRESHOLD));
 
-	MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_PP_TEAR_CHECK_EN, enable);
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_TEAR_CHECK_EN, enable);
 	return 0;
 }
 
@@ -111,11 +109,11 @@
 
 	mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
 	if (mixer)
-		mdss_mdp_cmd_tearcheck_cfg(mixer->num, ctx, enable);
+		mdss_mdp_cmd_tearcheck_cfg(mixer, ctx, enable);
 
 	mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_RIGHT);
 	if (mixer)
-		mdss_mdp_cmd_tearcheck_cfg(mixer->num, ctx, enable);
+		mdss_mdp_cmd_tearcheck_cfg(mixer, ctx, enable);
 
 	return 0;
 }