소스 검색

disp: msm: dp: update main link training params

Update DP PHY tx drive level and pre-emphasis information
for mainlink training.

Move parameters from code to dtsi and add parameter parsing.

Change-Id: I7527327e39952d76184ea22adade7949c64d3734
Signed-off-by: Nisarg Bhavsar <[email protected]>
Nisarg Bhavsar 2 년 전
부모
커밋
2c11ea7025
5개의 변경된 파일132개의 추가작업 그리고 46개의 파일을 삭제
  1. 16 0
      msm/dp/dp_catalog.c
  2. 6 0
      msm/dp/dp_catalog.h
  3. 8 44
      msm/dp/dp_catalog_v420.c
  4. 87 1
      msm/dp/dp_parser.c
  5. 15 1
      msm/dp/dp_parser.h

+ 16 - 0
msm/dp/dp_catalog.c

@@ -3091,6 +3091,22 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser)
 
 	strlcpy(catalog->exe_mode, "hw", sizeof(catalog->exe_mode));
 
+	if (parser->valid_lt_params) {
+		ctrl.swing_hbr2_3 = parser->swing_hbr2_3;
+		ctrl.pre_emp_hbr2_3 = parser->pre_emp_hbr2_3;
+
+		ctrl.swing_hbr_rbr = parser->swing_hbr_rbr;
+		ctrl.pre_emp_hbr_rbr = parser->pre_emp_hbr_rbr;
+		ctrl.valid_lt_params = true;
+	} else {
+		ctrl.swing_hbr2_3 = NULL;
+		ctrl.pre_emp_hbr2_3 = NULL;
+
+		ctrl.swing_hbr_rbr = NULL;
+		ctrl.pre_emp_hbr_rbr = NULL;
+		ctrl.valid_lt_params = false;
+	}
+
 	dp_catalog = &catalog->dp_catalog;
 
 	dp_catalog->aux   = aux;

+ 6 - 0
msm/dp/dp_catalog.h

@@ -93,6 +93,12 @@ struct dp_catalog_ctrl {
 	u32 isr5;
 	u32 isr6;
 
+	u8 *swing_hbr2_3;
+	u8 *pre_emp_hbr2_3;
+	u8 *swing_hbr_rbr;
+	u8 *pre_emp_hbr_rbr;
+	bool valid_lt_params;
+
 	void (*state_ctrl)(struct dp_catalog_ctrl *ctrl, u32 state);
 	void (*config_ctrl)(struct dp_catalog_ctrl *ctrl, u8 ln_cnt);
 	void (*lane_mapping)(struct dp_catalog_ctrl *ctrl, bool flipped,

+ 8 - 44
msm/dp/dp_catalog_v420.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-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.
  */
 
 
@@ -45,41 +45,6 @@ static u8 const vm_voltage_swing[MAX_VOLTAGE_LEVELS][MAX_PRE_EMP_LEVELS] = {
 	{0xFF, 0xFF, 0xFF, 0xFF}  /* sw1, 1.2 v, optional */
 };
 
-static u8 const dp_pre_emp_hbr2_hbr3[MAX_VOLTAGE_LEVELS][MAX_PRE_EMP_LEVELS] = {
-	{0x00, 0x0C, 0x15, 0x1B}, /* pe0, 0 db */
-	{0x02, 0x0E, 0x16, 0xFF}, /* pe1, 3.5 db */
-	{0x02, 0x11, 0xFF, 0xFF}, /* pe2, 6.0 db */
-	{0x04, 0xFF, 0xFF, 0xFF}  /* pe3, 9.5 db */
-};
-
-static u8 const dp_swing_hbr2_hbr3[MAX_VOLTAGE_LEVELS][MAX_PRE_EMP_LEVELS] = {
-	{0x02, 0x12, 0x16, 0x1A}, /* sw0, 0.4v  */
-	{0x09, 0x19, 0x1F, 0xFF}, /* sw1, 0.6v */
-	{0x10, 0x1F, 0xFF, 0xFF}, /* sw1, 0.8v */
-	{0x1F, 0xFF, 0xFF, 0xFF}  /* sw1, 1.2v */
-};
-
-static u8 const dp_pre_emp_hbr_rbr[MAX_VOLTAGE_LEVELS][MAX_PRE_EMP_LEVELS] = {
-	{0x00, 0x0D, 0x14, 0x1A}, /* pe0, 0 db */
-	{0x00, 0x0E, 0x15, 0xFF}, /* pe1, 3.5 db */
-	{0x00, 0x0E, 0xFF, 0xFF}, /* pe2, 6.0 db */
-	{0x03, 0xFF, 0xFF, 0xFF}  /* pe3, 9.5 db */
-};
-
-static u8 const dp_swing_hbr_rbr[MAX_VOLTAGE_LEVELS][MAX_PRE_EMP_LEVELS] = {
-	{0x08, 0x0F, 0x16, 0x1F}, /* sw0, 0.4v */
-	{0x11, 0x1E, 0x1F, 0xFF}, /* sw1, 0.6v */
-	{0x16, 0x1F, 0xFF, 0xFF}, /* sw1, 0.8v */
-	{0x1F, 0xFF, 0xFF, 0xFF}  /* sw1, 1.2v */
-};
-
-static const u8 dp_pre_emp_hbr_rbr_v600[MAX_VOLTAGE_LEVELS][MAX_PRE_EMP_LEVELS] = {
-	{0x00, 0x0D, 0x14, 0x1A}, /* pe0, 0 db */
-	{0x00, 0x0E, 0x15, 0xFF}, /* pe1, 3.5 db */
-	{0x00, 0x0E, 0xFF, 0xFF}, /* pe2, 6.0 db */
-	{0x02, 0xFF, 0xFF, 0xFF}  /* pe3, 9.5 db */
-};
-
 struct dp_catalog_private_v420 {
 	struct device *dev;
 	struct dp_catalog_sub sub;
@@ -249,6 +214,7 @@ static void dp_catalog_ctrl_update_vx_px_v420(struct dp_catalog_ctrl *ctrl,
 	u8 value0, value1;
 	u32 version;
 	u32 phy_version;
+	int idx;
 
 	if (!ctrl || !((v_level < MAX_VOLTAGE_LEVELS)
 		&& (p_level < MAX_PRE_EMP_LEVELS))) {
@@ -268,16 +234,14 @@ static void dp_catalog_ctrl_update_vx_px_v420(struct dp_catalog_ctrl *ctrl,
 	/*
 	 * For DP controller versions >= 1.2.3
 	 */
-	if (version >= 0x10020003) {
+	if (version >= 0x10020003 && ctrl->valid_lt_params) {
+		idx = v_level * MAX_VOLTAGE_LEVELS + p_level;
 		if (high) {
-			value0 = dp_swing_hbr2_hbr3[v_level][p_level];
-			value1 = dp_pre_emp_hbr2_hbr3[v_level][p_level];
+			value0 = ctrl->swing_hbr2_3[idx];
+			value1 = ctrl->pre_emp_hbr2_3[idx];
 		} else {
-			value0 = dp_swing_hbr_rbr[v_level][p_level];
-			if (phy_version >= 0x60000000)
-				value1 = dp_pre_emp_hbr_rbr_v600[v_level][p_level];
-			else
-				value1 = dp_pre_emp_hbr_rbr[v_level][p_level];
+			value0 = ctrl->swing_hbr_rbr[idx];
+			value1 = ctrl->pre_emp_hbr_rbr[idx];
 		}
 	} else {
 		value0 = vm_voltage_swing[v_level][p_level];

+ 87 - 1
msm/dp/dp_parser.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -761,6 +761,90 @@ static void dp_parser_widebus(struct dp_parser *parser)
 			parser->has_widebus);
 }
 
+static int parse_lt_param(struct device *dev, u8 **ptr, char *property) {
+	int ret = 0, i = 0, j = 0, index = 0;
+	u32 out_val = 0;
+	u32 expected_elems = MAX_SWING_LEVELS * MAX_PRE_EMP_LEVELS;
+	u8 parsed_val = 0;
+
+	ret = of_property_count_u32_elems(dev->of_node, property);
+	if (ret != expected_elems) {
+		return ret;
+	}
+
+	*ptr = devm_kzalloc(dev, sizeof(u8) * expected_elems, GFP_KERNEL);
+	if (!*ptr)
+		return -ENOMEM;
+
+	for (i = 0; i < MAX_SWING_LEVELS; i++) {
+		for (j = 0; j < MAX_PRE_EMP_LEVELS; j++) {
+			index = i * MAX_SWING_LEVELS + j;
+
+			ret = of_property_read_u32_index(dev->of_node, property, index, &out_val);
+			if (ret)
+				return ret;
+
+			parsed_val = out_val & 0xFF;
+
+			((u8 *)*ptr)[index] = parsed_val;
+		}
+	}
+
+	return ret;
+}
+
+static void dp_parser_clear_link_training_params(struct dp_parser *dp_parser)
+{
+	devm_kfree(&dp_parser->pdev->dev, dp_parser->swing_hbr2_3);
+	devm_kfree(&dp_parser->pdev->dev, dp_parser->pre_emp_hbr2_3);
+	devm_kfree(&dp_parser->pdev->dev, dp_parser->swing_hbr_rbr);
+	devm_kfree(&dp_parser->pdev->dev, dp_parser->pre_emp_hbr_rbr);
+
+	dp_parser->swing_hbr2_3 = NULL;
+	dp_parser->pre_emp_hbr2_3 = NULL;
+	dp_parser->swing_hbr_rbr = NULL;
+	dp_parser->pre_emp_hbr_rbr = NULL;
+
+	dp_parser->valid_lt_params = false;
+}
+
+static void dp_parser_link_training_params(struct dp_parser *parser)
+{
+	struct device *dev = &parser->pdev->dev;
+	int ret = 0;
+
+	ret = parse_lt_param(dev, &parser->swing_hbr2_3, "qcom,hbr2-3-voltage-swing");
+	if (ret)
+		goto early_exit;
+
+	ret = parse_lt_param(dev, &parser->pre_emp_hbr2_3, "qcom,hbr2-3-pre-emphasis");
+	if (ret)
+		goto early_exit;
+
+	ret = parse_lt_param(dev, &parser->swing_hbr_rbr, "qcom,hbr-rbr-voltage-swing");
+	if (ret)
+		goto early_exit;
+
+	ret = parse_lt_param(dev, &parser->pre_emp_hbr_rbr, "qcom,hbr-rbr-pre-emphasis");
+	if (ret)
+		goto early_exit;
+
+	parser->valid_lt_params = true;
+
+	DP_DEBUG("link training parameters parsing success\n");
+	goto end;
+
+early_exit:
+	if(ret == -EINVAL)
+		DP_WARN("link training parameters not found - using default values\n");
+	else
+		DP_ERR("link training parameters parsing failure ret: %d\n", ret);
+
+	dp_parser_clear_link_training_params(parser);
+end:
+	return;
+}
+
 static int dp_parser_parse(struct dp_parser *parser)
 {
 	int rc = 0;
@@ -815,6 +899,7 @@ static int dp_parser_parse(struct dp_parser *parser)
 	dp_parser_fec(parser);
 	dp_parser_widebus(parser);
 	dp_parser_qos(parser);
+	dp_parser_link_training_params(parser);
 err:
 	return rc;
 }
@@ -922,6 +1007,7 @@ void dp_parser_put(struct dp_parser *parser)
 		dp_parser_put_gpio_data(&parser->pdev->dev, &power[i]);
 	}
 
+	dp_parser_clear_link_training_params(parser);
 	dp_parser_clear_io_buf(parser);
 	devm_kfree(&parser->pdev->dev, parser->io.data);
 	devm_kfree(&parser->pdev->dev, parser);

+ 15 - 1
msm/dp/dp_parser.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -14,6 +14,8 @@
 #define DP_MAX_PIXEL_CLK_KHZ	675000
 #define DP_MAX_LINK_CLK_KHZ	810000
 #define MAX_DP_MST_STREAMS	2
+#define MAX_SWING_LEVELS 4
+#define MAX_PRE_EMP_LEVELS 4
 
 enum dp_pm_type {
 	DP_CORE_PM,
@@ -202,6 +204,11 @@ static inline char *dp_phy_aux_config_type_to_string(u32 cfg_type)
   *@mst_fixed_port: mst port_num reserved for fixed topology
  * @qos_cpu_mask: CPU mask for QOS
  * @qos_cpu_latency: CPU Latency setting for QOS
+ * @swing_hbr2_3: Voltage swing levels for HBR2 and HBR3 rates
+ * @pre_emp_hbr2_3: Pre-emphasis for HBR2 and HBR3 rates
+ * @swing_hbr_rbr: Voltage swing levels for HBR and RBR rates
+ * @pre_emp_hbr_rbr: Pre-emphasis for HBR and RBR rates
+ * @valid_lt_params: valid lt params
  * @parse: function to be called by client to parse device tree.
  * @get_io: function to be called by client to get io data.
  * @get_io_buf: function to be called by client to get io buffers.
@@ -232,6 +239,13 @@ struct dp_parser {
 	u32 qos_cpu_mask;
 	unsigned long qos_cpu_latency;
 
+	u8 *swing_hbr2_3;
+	u8 *pre_emp_hbr2_3;
+
+	u8 *swing_hbr_rbr;
+	u8 *pre_emp_hbr_rbr;
+	bool valid_lt_params;
+
 	int (*parse)(struct dp_parser *parser);
 	struct dp_io_data *(*get_io)(struct dp_parser *parser, char *name);
 	void (*get_io_buf)(struct dp_parser *parser, char *name);