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 <quic_bhavsar@quicinc.com>
This commit is contained in:
Nisarg Bhavsar
2023-03-21 07:57:37 -07:00
vanhempi 3049c6a494
commit 2c11ea7025
5 muutettua tiedostoa jossa 132 lisäystä ja 46 poistoa

Näytä tiedosto

@@ -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;

Näytä tiedosto

@@ -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,

Näytä tiedosto

@@ -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];

Näytä tiedosto

@@ -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);

Näytä tiedosto

@@ -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);