drm/msm/sde: fixup mdp top split pipe control

Complete implementation of mdp top pipe control with support
for full control of upper and lower pipe settings, for command
and video modes. Fixes support for dual DSI panels.

Change-Id: I38abba32ee23fd0ef2c7825fc1bd6e0687cc6556
Signed-off-by: Abhijit Kulkarni <kabhijit@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index b1d0066..642c668 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -39,7 +39,7 @@
 
 static struct msm_bus_vectors mdp_bus_vectors[] = {
 	MDP_BUS_VECTOR_ENTRY(0, 0),
-	MDP_BUS_VECTOR_ENTRY(2000000000, 2000000000),
+	MDP_BUS_VECTOR_ENTRY(8000000000, 8000000000),
 };
 
 static struct msm_bus_paths mdp_bus_usecases[] = { {
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index 79765a7..0530ea2 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -492,8 +492,13 @@
 			sde_kms->catalog);
 	struct split_pipe_cfg cfg;
 
-	cfg.en = true;
+	cfg.en = enable;
+
 	cfg.mode = INTF_MODE_VIDEO;
+	cfg.intf = INTF_1;
+	cfg.pp_split = false;
+	cfg.split_flush_en = true;
+
 	if (!IS_ERR_OR_NULL(mdp))
 		mdp->ops.setup_split_pipe(mdp, &cfg);
 }
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.c b/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.c
index 71c7dd5..9b1d0d5 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.c
@@ -14,31 +14,54 @@
 #include "sde_hw_catalog.h"
 #include "sde_hw_mdp_top.h"
 
+#define SSPP_SPARE                        0x24
 #define SPLIT_DISPLAY_ENABLE              0x2F4
+
 #define LOWER_PIPE_CTRL                   0x2F8
+#define FLD_SPLIT_DISPLAY_CMD             BIT(1)
+#define FLD_SMART_PANEL_FREE_RUN          BIT(2)
+#define FLD_INTF_1_SW_TRG_MUX             BIT(4)
+#define FLD_INTF_2_SW_TRG_MUX             BIT(8)
+#define FLD_TE_LINE_INTER_WATERLEVEL_MASK 0xFFFF
+
 #define UPPER_PIPE_CTRL                   0x3F0
 #define TE_LINE_INTERVAL                  0x3F4
 
 static void sde_hw_setup_split_pipe_control(struct sde_hw_mdp *mdp,
-		 struct split_pipe_cfg *cfg)
+		struct split_pipe_cfg *cfg)
 {
 	struct sde_hw_blk_reg_map *c = &mdp->hw;
-	u32 upper_pipe;
-	u32 lower_pipe;
+	u32 upper_pipe = 0;
+	u32 lower_pipe = 0;
 
 	if (cfg->en) {
-		upper_pipe = BIT(8);
-		lower_pipe = BIT(8);
-
 		if (cfg->mode == INTF_MODE_CMD) {
-			upper_pipe |= BIT(0);
-			lower_pipe |= BIT(0);
-		}
+			lower_pipe = FLD_SPLIT_DISPLAY_CMD;
+			/* interface controlling sw trigger */
+			if (cfg->intf == INTF_2)
+				lower_pipe |= FLD_INTF_1_SW_TRG_MUX;
+			else
+				lower_pipe |= FLD_INTF_2_SW_TRG_MUX;
 
-		SDE_REG_WRITE(c, LOWER_PIPE_CTRL, lower_pipe);
-		SDE_REG_WRITE(c, UPPER_PIPE_CTRL, upper_pipe);
+			/* free run */
+			if (cfg->pp_split)
+				lower_pipe = FLD_SMART_PANEL_FREE_RUN;
+
+			upper_pipe = lower_pipe;
+		} else {
+			if (cfg->intf == INTF_2) {
+				lower_pipe = FLD_INTF_1_SW_TRG_MUX;
+				upper_pipe = FLD_INTF_2_SW_TRG_MUX;
+			} else {
+				lower_pipe = FLD_INTF_2_SW_TRG_MUX;
+				upper_pipe = FLD_INTF_1_SW_TRG_MUX;
+			}
+		}
 	}
 
+	SDE_REG_WRITE(c, SSPP_SPARE, (cfg->split_flush_en) ? 0x1 : 0x0);
+	SDE_REG_WRITE(c, LOWER_PIPE_CTRL, lower_pipe);
+	SDE_REG_WRITE(c, UPPER_PIPE_CTRL, upper_pipe);
 	SDE_REG_WRITE(c, SPLIT_DISPLAY_ENABLE, cfg->en & 0x1);
 }
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.h b/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.h
index 10c008c..b29abb9 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.h
@@ -23,10 +23,17 @@
  * struct split_pipe_cfg - pipe configuration for dual display panels
  * @en        : Enable/disable dual pipe confguration
  * @mode      : Panel interface mode
+ * @intf      : Interface id for main control path
+ * @pp_split  : Ping pong split is enabled or disabled
+ * @split_flush_en: Allows both the paths to be flushed when master path is
+ *              flushed
  */
 struct split_pipe_cfg {
 	bool en;
 	enum sde_intf_mode mode;
+	enum sde_intf intf;
+	bool pp_split;
+	bool split_flush_en;
 };
 
 /**
@@ -35,6 +42,11 @@
  * @setup_split_pipe : Programs the pipe control registers
  */
 struct sde_hw_mdp_ops {
+	/** setup_split_pipe() : Regsiters are not double buffered, thisk
+	 * function should be called before timing control enable
+	 * @mdp  : mdp top context driver
+	 * @cfg  : upper and lower part of pipe configuration
+	 */
 	void (*setup_split_pipe)(struct sde_hw_mdp *mdp,
 			struct split_pipe_cfg *p);
 };