phy: qcom: edp: Add PHY-specific LDO config for eDP low vdiff

For eDP low vdiff, the LDO setting depends on the PHY version rather
than being a simple 0x0 or 0x1 value. Introduce a PHY callback to program
the correct LDO setting according to the HPG.

Since SC7280/SC8180X uses different LDO settings from SA8775P/SC8280XP,
introduce qcom_edp_phy_ops_v3 to keep the LDO setting correct.

Cc: stable@vger.kernel.org
Fixes: f199223cb4 ("phy: qcom: Introduce new eDP PHY driver")
Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Tested-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> # SC8280XP X13s
Link: https://patch.msgid.link/20260427-edp_phy-v5-5-3bb876824475@oss.qualcomm.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Yongxing Mou 2026-04-27 14:35:23 +08:00 committed by Vinod Koul
parent bf237a9fcb
commit 519a228ee4

View File

@ -81,6 +81,7 @@ struct phy_ver_ops {
int (*com_clk_fwd_cfg)(const struct qcom_edp *edp);
int (*com_configure_pll)(const struct qcom_edp *edp);
int (*com_configure_ssc)(const struct qcom_edp *edp);
int (*com_ldo_config)(const struct qcom_edp *edp);
};
struct qcom_edp_phy_cfg {
@ -352,7 +353,7 @@ static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configur
const struct qcom_edp_swing_pre_emph_cfg *cfg;
unsigned int v_level = 0;
unsigned int p_level = 0;
u8 ldo_config;
int ret;
u8 swing;
u8 emph;
int i;
@ -378,13 +379,13 @@ static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configur
if (swing == 0xff || emph == 0xff)
return -EINVAL;
ldo_config = edp->is_edp ? 0x0 : 0x1;
ret = edp->cfg->ver_ops->com_ldo_config(edp);
if (ret)
return ret;
writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
writel(swing, edp->tx0 + TXn_TX_DRV_LVL);
writel(emph, edp->tx0 + TXn_TX_EMP_POST1_LVL);
writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG);
writel(swing, edp->tx1 + TXn_TX_DRV_LVL);
writel(emph, edp->tx1 + TXn_TX_EMP_POST1_LVL);
@ -608,6 +609,52 @@ static int qcom_edp_com_configure_pll_v4(const struct qcom_edp *edp)
return 0;
}
static int qcom_edp_ldo_config_v3(const struct qcom_edp *edp)
{
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
u32 ldo_config;
if (!edp->is_edp)
ldo_config = 0x0;
else if (dp_opts->link_rate <= 2700)
ldo_config = 0x81;
else
ldo_config = 0x41;
writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
writel(dp_opts->lanes > 2 ? ldo_config : 0x00, edp->tx1 + TXn_LDO_CONFIG);
return 0;
}
static int qcom_edp_ldo_config_v4(const struct qcom_edp *edp)
{
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
u32 ldo_config;
if (!edp->is_edp)
ldo_config = 0x0;
else if (dp_opts->link_rate <= 2700)
ldo_config = 0xc1;
else
ldo_config = 0x81;
writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
writel(dp_opts->lanes > 2 ? ldo_config : 0x00, edp->tx1 + TXn_LDO_CONFIG);
return 0;
}
static const struct phy_ver_ops qcom_edp_phy_ops_v3 = {
.com_power_on = qcom_edp_phy_power_on_v4,
.com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v4,
.com_bias_en_clkbuflr = qcom_edp_com_bias_en_clkbuflr_v4,
.com_clk_fwd_cfg = qcom_edp_com_clk_fwd_cfg_v4,
.com_configure_pll = qcom_edp_com_configure_pll_v4,
.com_configure_ssc = qcom_edp_com_configure_ssc_v4,
.com_ldo_config = qcom_edp_ldo_config_v3,
};
static const struct phy_ver_ops qcom_edp_phy_ops_v4 = {
.com_power_on = qcom_edp_phy_power_on_v4,
.com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v4,
@ -615,6 +662,7 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v4 = {
.com_clk_fwd_cfg = qcom_edp_com_clk_fwd_cfg_v4,
.com_configure_pll = qcom_edp_com_configure_pll_v4,
.com_configure_ssc = qcom_edp_com_configure_ssc_v4,
.com_ldo_config = qcom_edp_ldo_config_v4,
};
static const struct qcom_edp_phy_cfg sa8775p_dp_phy_cfg = {
@ -631,7 +679,7 @@ static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = {
.vco_div_cfg = edp_phy_vco_div_cfg_v4,
.dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
.edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v3,
.ver_ops = &qcom_edp_phy_ops_v4,
.ver_ops = &qcom_edp_phy_ops_v3,
};
static const struct qcom_edp_phy_cfg sc8180x_dp_phy_cfg = {
@ -639,7 +687,7 @@ static const struct qcom_edp_phy_cfg sc8180x_dp_phy_cfg = {
.vco_div_cfg = edp_phy_vco_div_cfg_v4,
.dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg_v2,
.edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v2,
.ver_ops = &qcom_edp_phy_ops_v4,
.ver_ops = &qcom_edp_phy_ops_v3,
};
static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = {
@ -824,6 +872,24 @@ static int qcom_edp_com_configure_pll_v6(const struct qcom_edp *edp)
return 0;
}
static int qcom_edp_ldo_config_v6(const struct qcom_edp *edp)
{
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
u32 ldo_config;
if (!edp->is_edp)
ldo_config = 0x0;
else if (dp_opts->link_rate <= 2700)
ldo_config = 0x51;
else
ldo_config = 0x91;
writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
writel(dp_opts->lanes > 2 ? ldo_config : 0x00, edp->tx1 + TXn_LDO_CONFIG);
return 0;
}
static const struct phy_ver_ops qcom_edp_phy_ops_v6 = {
.com_power_on = qcom_edp_phy_power_on_v6,
.com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v6,
@ -831,6 +897,7 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v6 = {
.com_clk_fwd_cfg = qcom_edp_com_clk_fwd_cfg_v4,
.com_configure_pll = qcom_edp_com_configure_pll_v6,
.com_configure_ssc = qcom_edp_com_configure_ssc_v6,
.com_ldo_config = qcom_edp_ldo_config_v6,
};
static struct qcom_edp_phy_cfg x1e80100_phy_cfg = {
@ -1011,6 +1078,7 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v8 = {
.com_clk_fwd_cfg = qcom_edp_com_clk_fwd_cfg_v8,
.com_configure_pll = qcom_edp_com_configure_pll_v8,
.com_configure_ssc = qcom_edp_com_configure_ssc_v8,
.com_ldo_config = qcom_edp_ldo_config_v6,
};
static struct qcom_edp_phy_cfg glymur_phy_cfg = {
@ -1026,7 +1094,6 @@ static int qcom_edp_phy_power_on(struct phy *phy)
const struct qcom_edp *edp = phy_get_drvdata(phy);
u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
unsigned long pixel_freq;
u8 ldo_config = 0x0;
int ret;
u32 val;
u8 cfg1;
@ -1035,11 +1102,10 @@ static int qcom_edp_phy_power_on(struct phy *phy)
if (ret)
return ret;
if (edp->cfg->edp_swing_pre_emph_cfg && !edp->is_edp)
ldo_config = 0x1;
ret = edp->cfg->ver_ops->com_ldo_config(edp);
if (ret)
return ret;
writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG);
writel(0x00, edp->tx0 + TXn_LANE_MODE_1);
writel(0x00, edp->tx1 + TXn_LANE_MODE_1);