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

Reply via email to