Преглед изворни кода

Merge "disp: msm: dsi: Only enable lanes required during phy enable"

qctecmdr пре 1 година
родитељ
комит
5994f9a99d
5 измењених фајлова са 68 додато и 21 уклоњено
  1. 3 3
      msm/dsi/dsi_phy.c
  2. 0 2
      msm/dsi/dsi_phy.h
  3. 3 1
      msm/dsi/dsi_phy_hw.h
  4. 31 8
      msm/dsi/dsi_phy_hw_v4_0.c
  5. 31 7
      msm/dsi/dsi_phy_hw_v5_0.c

+ 3 - 3
msm/dsi/dsi_phy.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/of_device.h>
@@ -803,7 +803,7 @@ static inline int dsi_phy_get_data_lanes_count(struct msm_dsi_phy *phy)
 	int num_of_lanes = 0;
 	enum dsi_data_lanes dlanes;
 
-	dlanes = phy->data_lanes;
+	dlanes = phy->cfg.data_lanes;
 
 	/**
 	  * For split link use case effective data lines need to be used
@@ -1028,8 +1028,8 @@ int dsi_phy_enable(struct msm_dsi_phy *phy,
 
 	memcpy(&phy->mode, &config->video_timing, sizeof(phy->mode));
 	memcpy(&phy->cfg.lane_map, &config->lane_map, sizeof(config->lane_map));
-	phy->data_lanes = config->common_config.data_lanes;
 	phy->dst_format = config->common_config.dst_format;
+	phy->cfg.data_lanes = config->common_config.data_lanes;
 	phy->cfg.pll_source = pll_source;
 	phy->cfg.bit_clk_rate_hz = config->bit_clk_rate_hz;
 

+ 0 - 2
msm/dsi/dsi_phy.h

@@ -70,7 +70,6 @@ enum phy_ulps_return_type {
  * @power_state:       True if PHY is powered on.
  * @dsi_phy_state:     PHY state information.
  * @mode:              Current mode.
- * @data_lanes:        Number of data lanes used.
  * @dst_format:        Destination format.
  * @pll:	       Pointer to PLL resource.
  * @allow_phy_power_off: True if PHY is allowed to power off when idle
@@ -97,7 +96,6 @@ struct msm_dsi_phy {
 	enum phy_engine_state dsi_phy_state;
 	bool power_state;
 	struct dsi_mode_info mode;
-	enum dsi_data_lanes data_lanes;
 	enum dsi_pixel_format dst_format;
 
 	struct dsi_pll_resource *pll;

+ 3 - 1
msm/dsi/dsi_phy_hw.h

@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _DSI_PHY_HW_H_
@@ -116,6 +116,7 @@ struct dsi_phy_per_lane_cfgs {
  * @is_phy_timing_present:	Boolean whether phy timings are defined.
  * @regulators:       Regulator settings for lanes.
  * @pll_source:       PLL source.
+ * @data_lanes:       Bitmask of enum dsi_data_lanes.
  * @lane_map:         DSI logical to PHY lane mapping.
  * @force_clk_lane_hs:Boolean whether to force clock lane in HS mode.
  * @phy_type:         Phy-type (Dphy/Cphy).
@@ -134,6 +135,7 @@ struct dsi_phy_cfg {
 	enum dsi_phy_type phy_type;
 	unsigned long bit_clk_rate_hz;
 	struct dsi_split_link_config split_link;
+	u32 data_lanes;
 };
 
 struct dsi_phy_hw;

+ 31 - 8
msm/dsi/dsi_phy_hw_v4_0.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/math64.h>
@@ -234,6 +234,26 @@ void dsi_phy_hw_v4_0_commit_phy_timing(struct dsi_phy_hw *phy,
 	DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_13, timing->lane_v4[13]);
 }
 
+/**
+ * calc_cmn_lane_ctrl0() - Calculate the value to be set for
+ *			   DSIPHY_CMN_LANE_CTRL0 register.
+ * @cfg:      Per lane configurations for timing, strength and lane
+ *	      configurations.
+ */
+static inline u32 dsi_phy_hw_calc_cmn_lane_ctrl0(struct dsi_phy_cfg *cfg)
+{
+	u32 cmn_lane_ctrl0 = 0;
+
+	/* Only enable lanes that are required */
+	cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_0) ? BIT(0) : 0);
+	cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_1) ? BIT(1) : 0);
+	cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_2) ? BIT(2) : 0);
+	cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_3) ? BIT(3) : 0);
+	cmn_lane_ctrl0 |= BIT(4);
+
+	return cmn_lane_ctrl0;
+}
+
 /**
  * cphy_enable() - Enable CPHY hardware
  * @phy:      Pointer to DSI PHY hardware object.
@@ -254,6 +274,7 @@ static void dsi_phy_hw_cphy_enable(struct dsi_phy_hw *phy,
 	u32 glbl_rescode_top_ctrl = 0;
 	u32 glbl_rescode_bot_ctrl = 0;
 	bool less_than_1500_mhz = false;
+	u32 cmn_lane_ctrl0 = 0;
 
 	/* Alter PHY configurations if data rate less than 1.5GHZ*/
 	if (cfg->bit_clk_rate_hz <= 1500000000)
@@ -317,7 +338,8 @@ static void dsi_phy_hw_cphy_enable(struct dsi_phy_hw *phy,
 	/* Remove power down from all blocks */
 	DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f);
 
-	DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x17);
+	cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg);
+	DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, cmn_lane_ctrl0);
 
 	switch (cfg->pll_source) {
 	case DSI_PLL_SOURCE_STANDALONE:
@@ -370,6 +392,7 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy,
 	u32 glbl_rescode_bot_ctrl = 0;
 	bool split_link_enabled;
 	u32 lanes_per_sublink;
+	u32 cmn_lane_ctrl0 = 0;
 
 	/* Alter PHY configurations if data rate less than 1.5GHZ*/
 	if (cfg->bit_clk_rate_hz <= 1500000000)
@@ -458,7 +481,8 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy,
 	} else {
 		/* Remove power down from all blocks */
 		DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f);
-		DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x1F);
+		cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg);
+		DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, cmn_lane_ctrl0);
 	}
 
 	/* Select full-rate mode */
@@ -764,8 +788,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy,
 					struct dsi_phy_cfg *cfg, bool is_master)
 {
 	u32 reg;
-	bool is_cphy = (cfg->phy_type == DSI_PHY_TYPE_CPHY) ?
-			true : false;
+	u32 cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg);
 
 	if (is_master) {
 		DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL19,
@@ -791,7 +814,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy,
 			  cfg->timing.lane_v4[12], cfg->timing.lane_v4[13]);
 		DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL26,
 			  DSIPHY_CMN_CTRL_0, DSIPHY_CMN_LANE_CTRL0,
-			  0x7f, is_cphy ? 0x17 : 0x1f);
+			  0x7f, cmn_lane_ctrl0);
 
 	} else {
 		reg = DSI_R32(phy, DSIPHY_CMN_CLK_CFG1);
@@ -826,7 +849,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy,
 			  cfg->timing.lane_v4[13], 0x7f);
 		DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL9,
 			  DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_2,
-			  is_cphy ? 0x17 : 0x1f, 0x40);
+			  cmn_lane_ctrl0, 0x40);
 		/*
 		 * fill with dummy register writes since controller will blindly
 		 * send these values to DSI PHY.
@@ -835,7 +858,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy,
 		while (reg <= DSI_DYN_REFRESH_PLL_CTRL29) {
 			DSI_DYN_REF_REG_W(phy->dyn_pll_base, reg,
 				  DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_0,
-				  is_cphy ? 0x17 : 0x1f, 0x7f);
+				  cmn_lane_ctrl0, 0x7f);
 			reg += 0x4;
 		}
 

+ 31 - 7
msm/dsi/dsi_phy_hw_v5_0.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/math64.h>
@@ -229,6 +229,26 @@ void dsi_phy_hw_v5_0_commit_phy_timing(struct dsi_phy_hw *phy,
 	DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_13, timing->lane_v4[13]);
 }
 
+/**
+ * calc_cmn_lane_ctrl0() - Calculate the value to be set for
+ *			   DSIPHY_CMN_LANE_CTRL0 register.
+ * @cfg:      Per lane configurations for timing, strength and lane
+ *	      configurations.
+ */
+static inline u32 dsi_phy_hw_calc_cmn_lane_ctrl0(struct dsi_phy_cfg *cfg)
+{
+	u32 cmn_lane_ctrl0 = 0;
+
+	/* Only enable lanes that are required */
+	cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_0) ? BIT(0) : 0);
+	cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_1) ? BIT(1) : 0);
+	cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_2) ? BIT(2) : 0);
+	cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_3) ? BIT(3) : 0);
+	cmn_lane_ctrl0 |= BIT(4);
+
+	return cmn_lane_ctrl0;
+}
+
 /**
  * cphy_enable() - Enable CPHY hardware
  * @phy:      Pointer to DSI PHY hardware object.
@@ -242,6 +262,7 @@ static void dsi_phy_hw_cphy_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *c
 	/* For C-PHY, no low power settings for lower clk rate */
 	u32 glbl_str_swi_cal_sel_ctrl = 0;
 	u32 glbl_hstx_str_ctrl_0 = 0;
+	u32 cmn_lane_ctrl0 = 0;
 
 	/* de-assert digital and pll power down */
 	data = BIT(6) | BIT(5);
@@ -275,7 +296,8 @@ static void dsi_phy_hw_cphy_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *c
 	/* Remove power down from all blocks */
 	DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f);
 
-	DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x17);
+	cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg);
+	DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, cmn_lane_ctrl0);
 
 	switch (cfg->pll_source) {
 	case DSI_PLL_SOURCE_STANDALONE:
@@ -325,6 +347,7 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *c
 	u32 glbl_rescode_bot_ctrl = 0;
 	bool split_link_enabled;
 	u32 lanes_per_sublink;
+	u32 cmn_lane_ctrl0 = 0;
 
 	/* Alter PHY configurations if data rate less than 1.5GHZ*/
 	if (cfg->bit_clk_rate_hz <= 1500000000)
@@ -389,7 +412,8 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *c
 	} else {
 		/* Remove power down from all blocks */
 		DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f);
-		DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x1F);
+		cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg);
+		DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, cmn_lane_ctrl0);
 	}
 
 	/* Select full-rate mode */
@@ -701,7 +725,7 @@ void dsi_phy_hw_v5_0_dyn_refresh_config(struct dsi_phy_hw *phy,
 					struct dsi_phy_cfg *cfg, bool is_master)
 {
 	u32 reg;
-	bool is_cphy = (cfg->phy_type == DSI_PHY_TYPE_CPHY) ? true : false;
+	u32 cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg);
 
 	if (is_master) {
 		DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL19,
@@ -727,7 +751,7 @@ void dsi_phy_hw_v5_0_dyn_refresh_config(struct dsi_phy_hw *phy,
 				cfg->timing.lane_v4[12], cfg->timing.lane_v4[13]);
 		DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL26,
 				DSIPHY_CMN_CTRL_0, DSIPHY_CMN_LANE_CTRL0, 0x7f,
-				is_cphy ? 0x17 : 0x1f);
+				cmn_lane_ctrl0);
 
 	} else {
 		reg = DSI_R32(phy, DSIPHY_CMN_CLK_CFG1);
@@ -761,7 +785,7 @@ void dsi_phy_hw_v5_0_dyn_refresh_config(struct dsi_phy_hw *phy,
 				cfg->timing.lane_v4[13], 0x7f);
 		DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL9,
 				DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_2,
-				is_cphy ? 0x17 : 0x1f, 0x40);
+				cmn_lane_ctrl0, 0x40);
 		/*
 		 * fill with dummy register writes since controller will blindly
 		 * send these values to DSI PHY.
@@ -769,7 +793,7 @@ void dsi_phy_hw_v5_0_dyn_refresh_config(struct dsi_phy_hw *phy,
 		reg = DSI_DYN_REFRESH_PLL_CTRL11;
 		while (reg <= DSI_DYN_REFRESH_PLL_CTRL29) {
 			DSI_DYN_REF_REG_W(phy->dyn_pll_base, reg, DSIPHY_CMN_LANE_CTRL0,
-					DSIPHY_CMN_CTRL_0, is_cphy ? 0x17 : 0x1f, 0x7f);
+					DSIPHY_CMN_CTRL_0, cmn_lane_ctrl0, 0x7f);
 			reg += 0x4;
 		}