Add support for honoring the set_voltages request to set the voltage swing and preemphasis values in the .configure() callback.
For proper hardware cleanup, reset both in the .reset() callback. Signed-off-by: AngeloGioacchino Del Regno <[email protected]> --- drivers/phy/mediatek/phy-mtk-dp.c | 41 ++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c index a2cd22b9da06..17d871530cca 100644 --- a/drivers/phy/mediatek/phy-mtk-dp.c +++ b/drivers/phy/mediatek/phy-mtk-dp.c @@ -48,6 +48,11 @@ /* DP_PHYD_TX_CTL_0 */ #define PHYD_TX_LN_EN GENMASK(7, 4) +/* DP_PHYD_DRIVING_FORCE */ +#define PHYD_DP_TX_FORCE_VOLT_SWING_EN BIT(0) +#define PHYD_DP_TX_FORCE_VOLT_SWING_VAL GENMASK(2, 1) +#define PHYD_DP_TX_FORCE_PRE_EMPH_VAL GENMASK(4, 3) + #define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT BIT(4) #define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT (BIT(10) | BIT(12)) #define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT GENMASK(20, 19) @@ -101,6 +106,7 @@ enum mtk_dp_phya_ana_glb_regidx { }; enum mtk_dp_phyd_dig_lane_regidx { + DP_PHYD_LAN_DRIVING_FORCE, DP_PHYD_LAN_DRIVING_PARAM_0, DP_PHYD_LAN_MAX }; @@ -121,6 +127,7 @@ static const u8 mt8195_phy_ana_glb_regs[DP_PHYA_GLOBAL_MAX] = { }; static const u8 mt8195_phy_dig_lane_regs[DP_PHYD_LAN_MAX] = { + [DP_PHYD_LAN_DRIVING_FORCE] = 0x18, [DP_PHYD_LAN_DRIVING_PARAM_0] = 0x2c, }; @@ -235,6 +242,28 @@ static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts) PHYD_TX_LN_EN, val); } + if (opts->dp.set_voltages) { + const u32 reg_drv_force = pdata->regs_dig_lane[DP_PHYD_LAN_DRIVING_FORCE]; + + if (opts->dp.lanes > 4) { + dev_err(&phy->dev, "Wrong lanes config %u\n", opts->dp.lanes); + return -EINVAL; + } + + for (i = 0; i < opts->dp.lanes; i++) { + const u32 off_dig_lane = pdata->off_dig_lane[i]; + u32 val; + + val = FIELD_PREP(PHYD_DP_TX_FORCE_VOLT_SWING_VAL, opts->dp.voltage[i]); + val |= FIELD_PREP(PHYD_DP_TX_FORCE_PRE_EMPH_VAL, opts->dp.pre[i]); + + regmap_update_bits(dp_phy->regmap, off_dig_lane + reg_drv_force, + PHYD_DP_TX_FORCE_VOLT_SWING_VAL | + PHYD_DP_TX_FORCE_PRE_EMPH_VAL, + val); + } + } + regmap_update_bits(dp_phy->regmap, pdata->off_dig_glb + pdata->regs_dig_glb[DP_PHYD_PLL_CTL_1], TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN : 0); @@ -329,7 +358,8 @@ static int mtk_dp_phy_reset(struct phy *phy) struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy); const struct mtk_dp_phy_pdata *pdata = dp_phy->pdata; const u32 reg_rst = pdata->regs_dig_glb[DP_PHYD_SW_RST]; - int ret; + const u32 reg_drv_force = pdata->regs_dig_lane[DP_PHYD_LAN_DRIVING_FORCE]; + int i, ret; /* Clearing bits sets reset state */ regmap_clear_bits(dp_phy->regmap, pdata->off_dig_glb + reg_rst, DP_GLB_SW_RST_PHYD); @@ -345,6 +375,15 @@ static int mtk_dp_phy_reset(struct phy *phy) if (ret) dev_err(dp_phy->dev, "Could not disable lanes during reset!\n"); + /* Reset Voltage Swing and Preemphasis values */ + for (i = 0; i < MTK_DP_PHY_MAX_LANES; i++) { + const u32 off_dig_lane = pdata->off_dig_lane[i]; + + regmap_clear_bits(dp_phy->regmap, off_dig_lane + reg_drv_force, + PHYD_DP_TX_FORCE_VOLT_SWING_VAL | + PHYD_DP_TX_FORCE_PRE_EMPH_VAL); + } + return 0; } -- 2.54.0
