msm: mdss: Restrict SMP buffer reservation

Given two line latency buffer requirement for performance, in
some cases, three or more SMP blocks get reserved. This happens
typically for the usecases involving higher resolution layers
(e.g. 1080P). For these usecases required number of SMP blocks
exceed total number of SMP blocks available, thus causing SMP
reservation failures. These failures are often encountered in
8x26 target as it has in total, only seven SMP blocks available.

Restrict SMP buffer reservation to two SMP blocks, based on an
optionable device tree property, to be able to support most of
the usecases. This restriction is not applicable to horizontal
flip cases where two line latency buffer reservation is
necessary.

Change-Id: I7d57568b4b2710df0142bbc16749e56a9b492dfe
Signed-off-by: Mayank Chopra <makchopra@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 514160e..7093fb8 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -126,6 +126,11 @@
 - qcom,mdss-has-wfd-blk: Boolean property to indicate the presence of dedicated
 			writeback wfd block in MDSS as opposed to writeback
 			block that is shared between rotator and wfd.
+- qcom,mdss-smp-mb-per-pipe:	Maximum number of shared memory pool blocks
+				restricted for a source surface pipe. If this
+				property is not specified, no such restriction
+				would be applied.
+
 Optional subnodes:
 Child nodes representing the frame buffer virtual devices.
 
@@ -161,6 +166,7 @@
 		qcom,mdss-pipe-dma-fetch-id = <10 13>;
 		qcom,mdss-smp-data = <22 4096>;
 		qcom,mdss-rot-block-size = <64>;
+		qcom,mdss-smp-mb-per-pipe = <2>;
 		qcom,mdss-has-bwc;
 		qcom,mdss-has-decimation;
 		qcom,mdss-has-wfd-blk;
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 078960b..840af17 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -89,6 +89,7 @@
 
 	u32 smp_mb_cnt;
 	u32 smp_mb_size;
+	u32 smp_mb_per_pipe;
 
 	u32 rot_block_size;
 
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 56a4ac4..0a41ef8 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1511,10 +1511,16 @@
 
 	rc = mdss_mdp_smp_setup(mdata, data[0], data[1]);
 
-	if (rc)
+	if (rc) {
 		pr_err("unable to setup smp data\n");
+		return rc;
+	}
 
-	return rc;
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-smp-mb-per-pipe", data);
+	mdata->smp_mb_per_pipe = (!rc ? data[0] : 0);
+
+	return 0;
 }
 
 static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 137da66..bda836f 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -193,6 +193,11 @@
 
 			if (mdata->mdp_rev == MDSS_MDP_HW_REV_100)
 				num_blks = roundup_pow_of_two(num_blks);
+
+			if (mdata->smp_mb_per_pipe &&
+				(num_blks > mdata->smp_mb_per_pipe) &&
+				!(pipe->flags & MDP_FLIP_LR))
+				num_blks = mdata->smp_mb_per_pipe;
 		}
 
 		pr_debug("reserving %d mmb for pnum=%d plane=%d\n",