Jelajahi Sumber

disp: msm: dsi: update DSI PHY configuration to support splitlink

Change updates DSI PHY programming sequence for splitlink configuration.

Change-Id: I708cf83717c6f640c918d41cc122794a10f979ba
Signed-off-by: Vara Reddy <[email protected]>
Vara Reddy 4 tahun lalu
induk
melakukan
fcb3849c69
4 mengubah file dengan 56 tambahan dan 5 penghapusan
  1. 2 0
      msm/dsi/dsi_defs.h
  2. 5 0
      msm/dsi/dsi_display.c
  3. 2 0
      msm/dsi/dsi_phy_hw.h
  4. 47 5
      msm/dsi/dsi_phy_hw_v4_0.c

+ 2 - 0
msm/dsi/dsi_defs.h

@@ -448,12 +448,14 @@ struct dsi_mode_info {
  * @num_sublinks:     Number of sublinks.
  * @lanes_per_sublink:   Number of lanes per sublink.
  * @panel_mode: Specifies cmd or video mode.
+ * @lanes_enabled: Specifies what all lanes are enabled.
  */
 struct dsi_split_link_config {
 	bool enabled;
 	bool sublink_swap;
 	u32 num_sublinks;
 	u32 lanes_per_sublink;
+	u8 lanes_enabled;
 	enum dsi_op_mode panel_mode;
 };
 

+ 5 - 0
msm/dsi/dsi_display.c

@@ -4104,6 +4104,7 @@ static int dsi_display_res_init(struct dsi_display *display)
 
 	display_for_each_ctrl(i, display) {
 		struct msm_dsi_phy *phy = display->ctrl[i].phy;
+		struct dsi_host_common_cfg *host = &display->panel->host_config;
 
 		phy->cfg.force_clk_lane_hs =
 			display->panel->host_config.force_hs_clk_lane;
@@ -4117,6 +4118,10 @@ static int dsi_display_res_init(struct dsi_display *display)
 		if ((display->panel->dyn_clk_caps.dyn_clk_support) &&
 				(display->panel->panel_mode == DSI_OP_VIDEO_MODE))
 			dsi_phy_pll_parse_dfps_data(phy);
+
+		phy->cfg.split_link.enabled = host->split_link.enabled;
+		phy->cfg.split_link.num_sublinks = host->split_link.num_sublinks;
+		phy->cfg.split_link.lanes_per_sublink = host->split_link.lanes_per_sublink;
 	}
 
 	rc = dsi_display_parse_lane_map(display);

+ 2 - 0
msm/dsi/dsi_phy_hw.h

@@ -116,6 +116,7 @@ struct dsi_phy_per_lane_cfgs {
  * @force_clk_lane_hs:Boolean whether to force clock lane in HS mode.
  * @phy_type:         Phy-type (Dphy/Cphy).
  * @bit_clk_rate_hz: DSI bit clk rate in HZ.
+ * @split_link:       DSI split link config data.
  */
 struct dsi_phy_cfg {
 	struct dsi_phy_per_lane_cfgs lanecfg;
@@ -128,6 +129,7 @@ struct dsi_phy_cfg {
 	bool force_clk_lane_hs;
 	enum dsi_phy_type phy_type;
 	unsigned long bit_clk_rate_hz;
+	struct dsi_split_link_config split_link;
 };
 
 struct dsi_phy_hw;

+ 47 - 5
msm/dsi/dsi_phy_hw_v4_0.c

@@ -7,6 +7,7 @@
 #include <linux/delay.h>
 #include <linux/iopoll.h>
 #include "dsi_hw.h"
+#include "dsi_defs.h"
 #include "dsi_phy_hw.h"
 #include "dsi_catalog.h"
 
@@ -61,6 +62,7 @@
 #define DSIPHY_CMN_LANE_STATUS0						0x148
 #define DSIPHY_CMN_LANE_STATUS1						0x14C
 #define DSIPHY_CMN_GLBL_DIGTOP_SPARE10                                  0x1AC
+#define DSIPHY_CMN_CMN_SL_DSI_LANE_CTRL1                                0x1B4
 
 /* n = 0..3 for data lanes and n = 4 for clock lane */
 #define DSIPHY_LNX_CFG0(n)                         (0x200 + (0x80 * (n)))
@@ -156,12 +158,17 @@ static void dsi_phy_hw_v4_0_lane_settings(struct dsi_phy_hw *phy,
 	u8 tx_dctrl_v4[] = {0x00, 0x00, 0x00, 0x04, 0x01};
 	u8 tx_dctrl_v4_1[] = {0x40, 0x40, 0x40, 0x46, 0x41};
 	u8 *tx_dctrl;
+	bool split_link_enabled;
+	u32 lanes_per_sublink;
 
 	if (phy->version >= DSI_PHY_VERSION_4_1)
 		tx_dctrl = &tx_dctrl_v4_1[0];
 	else
 		tx_dctrl = &tx_dctrl_v4[0];
 
+	split_link_enabled = cfg->split_link.enabled;
+	lanes_per_sublink = cfg->split_link.lanes_per_sublink;
+
 	/* Strength ctrl settings */
 	for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) {
 		/*
@@ -182,6 +189,19 @@ static void dsi_phy_hw_v4_0_lane_settings(struct dsi_phy_hw *phy,
 		DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(i), tx_dctrl[i]);
 	}
 
+	/* remove below check if cphy splitlink is enabled */
+	if (split_link_enabled && (cfg->phy_type == DSI_PHY_TYPE_CPHY))
+		return;
+
+	/* Configure the splitlink clock lane with clk lane settings */
+	if (split_link_enabled) {
+		DSI_W32(phy, DSIPHY_LNX_LPRX_CTRL(5), 0x0);
+		DSI_W32(phy, DSIPHY_LNX_PIN_SWAP(5), 0x0);
+		DSI_W32(phy, DSIPHY_LNX_CFG0(5), cfg->lanecfg.lane[4][0]);
+		DSI_W32(phy, DSIPHY_LNX_CFG1(5), cfg->lanecfg.lane[4][1]);
+		DSI_W32(phy, DSIPHY_LNX_CFG2(5), cfg->lanecfg.lane[4][2]);
+		DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(5), tx_dctrl[4]);
+	}
 }
 
 void dsi_phy_hw_v4_0_commit_phy_timing(struct dsi_phy_hw *phy,
@@ -331,6 +351,8 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy,
 	u32 glbl_hstx_str_ctrl_0 = 0;
 	u32 glbl_rescode_top_ctrl = 0;
 	u32 glbl_rescode_bot_ctrl = 0;
+	bool split_link_enabled;
+	u32 lanes_per_sublink;
 
 	/* Alter PHY configurations if data rate less than 1.5GHZ*/
 	if (cfg->bit_clk_rate_hz <= 1500000000)
@@ -356,10 +378,17 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy,
 		glbl_rescode_bot_ctrl = 0x3c;
 	}
 
+	split_link_enabled = cfg->split_link.enabled;
+	lanes_per_sublink = cfg->split_link.lanes_per_sublink;
 	/* de-assert digital and pll power down */
 	data = BIT(6) | BIT(5);
 	DSI_W32(phy, DSIPHY_CMN_CTRL_0, data);
 
+	if (split_link_enabled) {
+		data = DSI_R32(phy, DSIPHY_CMN_GLBL_CTRL);
+		/* set SPLIT_LINK_ENABLE in global control */
+		DSI_W32(phy, DSIPHY_CMN_GLBL_CTRL, (data | BIT(5)));
+	}
 	/* Assert PLL core reset */
 	DSI_W32(phy, DSIPHY_CMN_PLL_CNTRL, 0x00);
 
@@ -389,10 +418,23 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy,
 			glbl_rescode_bot_ctrl);
 	DSI_W32(phy, DSIPHY_CMN_GLBL_LPTX_STR_CTRL, 0x55);
 
-	/* Remove power down from all blocks */
-	DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f);
+	if (split_link_enabled) {
+		if (lanes_per_sublink == 1) {
+			/* remove Lane1 and Lane3 configs */
+			DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0xed);
+			DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x35);
+		} else {
+			/* enable all together with sublink clock */
+			DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0xff);
+			DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x3F);
+		}
 
-	DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x1F);
+		DSI_W32(phy, DSIPHY_CMN_CMN_SL_DSI_LANE_CTRL1, 0x03);
+	} else {
+		/* Remove power down from all blocks */
+		DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f);
+		DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x1F);
+	}
 
 	/* Select full-rate mode */
 	DSI_W32(phy, DSIPHY_CMN_CTRL_2, 0x40);
@@ -472,8 +514,8 @@ void dsi_phy_hw_v4_0_disable(struct dsi_phy_hw *phy,
 	dsi_phy_hw_v4_0_config_lpcdrx(phy, cfg, false);
 
 	data = DSI_R32(phy, DSIPHY_CMN_CTRL_0);
-	/* disable all lanes */
-	data &= ~0x1F;
+	/* disable all lanes and splitlink clk lane*/
+	data &= ~0x9F;
 	DSI_W32(phy, DSIPHY_CMN_CTRL_0, data);
 	DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0);