2022-08-10 04:21:34

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 0/5] phy: qcom: edp: Introduce SC8280XP support

What the subject says.

Bjorn Andersson (5):
dt-bindings: phy: qcom-edp: Add SC8280XP PHY compatibles
phy: qcom: edp: Generate unique clock names
phy: qcom: edp: Perform lane configuration
phy: qcom: edp: Introduce support for DisplayPort
phy: qcom: edp: Add SC8280XP eDP and DP PHYs

.../devicetree/bindings/phy/qcom,edp-phy.yaml | 2 +
drivers/phy/qualcomm/phy-qcom-edp.c | 193 +++++++++++++++++-
2 files changed, 184 insertions(+), 11 deletions(-)

--
2.35.1


2022-08-10 04:21:59

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 2/5] phy: qcom: edp: Generate unique clock names

With multiple Displayport PHYs the hard coded clock names collides,
generate unique clock names based on the device name instead.

Signed-off-by: Bjorn Andersson <[email protected]>
---
drivers/phy/qualcomm/phy-qcom-edp.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c
index 7e3570789845..41aa28291cea 100644
--- a/drivers/phy/qualcomm/phy-qcom-edp.c
+++ b/drivers/phy/qualcomm/phy-qcom-edp.c
@@ -571,21 +571,24 @@ static int qcom_edp_clks_register(struct qcom_edp *edp, struct device_node *np)
{
struct clk_hw_onecell_data *data;
struct clk_init_data init = { };
+ char name[64];
int ret;

data = devm_kzalloc(edp->dev, struct_size(data, hws, 2), GFP_KERNEL);
if (!data)
return -ENOMEM;

+ snprintf(name, sizeof(name), "%s::link_clk", dev_name(edp->dev));
init.ops = &qcom_edp_dp_link_clk_ops;
- init.name = "edp_phy_pll_link_clk";
+ init.name = name;
edp->dp_link_hw.init = &init;
ret = devm_clk_hw_register(edp->dev, &edp->dp_link_hw);
if (ret)
return ret;

+ snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(edp->dev));
init.ops = &qcom_edp_dp_pixel_clk_ops;
- init.name = "edp_phy_pll_vco_div_clk";
+ init.name = name;
edp->dp_pixel_hw.init = &init;
ret = devm_clk_hw_register(edp->dev, &edp->dp_pixel_hw);
if (ret)
--
2.35.1

2022-08-10 04:24:47

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 4/5] phy: qcom: edp: Introduce support for DisplayPort

The eDP phy can be used to drive either eDP or DP output, with some
minor variations in some of the configuration and seemingly a need for
implementing swing and pre_emphasis calibration.

Introduce a config object, indicating if the phy is operating in eDP or
DP mode and swing/pre-emphasis calibration to support this.

Signed-off-by: Bjorn Andersson <[email protected]>
---
drivers/phy/qualcomm/phy-qcom-edp.c | 80 +++++++++++++++++++++++++++--
1 file changed, 76 insertions(+), 4 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c
index 32614fb838b5..301ac422d2fe 100644
--- a/drivers/phy/qualcomm/phy-qcom-edp.c
+++ b/drivers/phy/qualcomm/phy-qcom-edp.c
@@ -70,8 +70,19 @@

#define TXn_TRAN_DRVR_EMP_EN 0x0078

+struct qcom_edp_cfg {
+ bool is_dp;
+
+ /* DP PHY swing and pre_emphasis tables */
+ const u8 (*swing_hbr_rbr)[4][4];
+ const u8 (*swing_hbr3_hbr2)[4][4];
+ const u8 (*pre_emphasis_hbr_rbr)[4][4];
+ const u8 (*pre_emphasis_hbr3_hbr2)[4][4];
+};
+
struct qcom_edp {
struct device *dev;
+ const struct qcom_edp_cfg *cfg;

struct phy *phy;

@@ -92,7 +103,9 @@ struct qcom_edp {
static int qcom_edp_phy_init(struct phy *phy)
{
struct qcom_edp *edp = phy_get_drvdata(phy);
+ const struct qcom_edp_cfg *cfg = edp->cfg;
int ret;
+ u8 cfg8;

ret = regulator_bulk_enable(ARRAY_SIZE(edp->supplies), edp->supplies);
if (ret)
@@ -117,6 +130,13 @@ static int qcom_edp_phy_init(struct phy *phy)
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
edp->edp + DP_PHY_PD_CTL);

+ if (cfg && cfg->is_dp)
+ cfg8 = 0xb7;
+ else
+ cfg8 = 0x37;
+
+ writel(0xfc, edp->edp + DP_PHY_MODE);
+
writel(0x00, edp->edp + DP_PHY_AUX_CFG0);
writel(0x13, edp->edp + DP_PHY_AUX_CFG1);
writel(0x24, edp->edp + DP_PHY_AUX_CFG2);
@@ -125,7 +145,7 @@ static int qcom_edp_phy_init(struct phy *phy)
writel(0x26, edp->edp + DP_PHY_AUX_CFG5);
writel(0x0a, edp->edp + DP_PHY_AUX_CFG6);
writel(0x03, edp->edp + DP_PHY_AUX_CFG7);
- writel(0x37, edp->edp + DP_PHY_AUX_CFG8);
+ writel(cfg8, edp->edp + DP_PHY_AUX_CFG8);
writel(0x03, edp->edp + DP_PHY_AUX_CFG9);

writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
@@ -142,14 +162,60 @@ static int qcom_edp_phy_init(struct phy *phy)
return ret;
}

+static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configure_opts_dp *dp_opts)
+{
+ const struct qcom_edp_cfg *cfg = edp->cfg;
+ unsigned int v_level = 0;
+ unsigned int p_level = 0;
+ u8 ldo_config;
+ u8 swing;
+ u8 emph;
+ int i;
+
+ if (!cfg)
+ return 0;
+
+ for (i = 0; i < dp_opts->lanes; i++) {
+ v_level = max(v_level, dp_opts->voltage[i]);
+ p_level = max(p_level, dp_opts->pre[i]);
+ }
+
+ if (dp_opts->link_rate <= 2700) {
+ swing = (*cfg->swing_hbr_rbr)[v_level][p_level];
+ emph = (*cfg->pre_emphasis_hbr_rbr)[v_level][p_level];
+ } else {
+ swing = (*cfg->swing_hbr3_hbr2)[v_level][p_level];
+ emph = (*cfg->pre_emphasis_hbr3_hbr2)[v_level][p_level];
+ }
+
+ if (swing == 0xff || emph == 0xff)
+ return -EINVAL;
+
+ ldo_config = (cfg && cfg->is_dp) ? 0x1 : 0x0;
+
+ 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);
+
+ return 0;
+}
+
static int qcom_edp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
{
const struct phy_configure_opts_dp *dp_opts = &opts->dp;
struct qcom_edp *edp = phy_get_drvdata(phy);
+ int ret = 0;

memcpy(&edp->dp_opts, dp_opts, sizeof(*dp_opts));

- return 0;
+ if (dp_opts->set_voltages)
+ ret = qcom_edp_set_voltages(edp, dp_opts);
+
+ return ret;
}

static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
@@ -315,7 +381,9 @@ static int qcom_edp_set_vco_div(const struct qcom_edp *edp)
static int qcom_edp_phy_power_on(struct phy *phy)
{
const struct qcom_edp *edp = phy_get_drvdata(phy);
+ const struct qcom_edp_cfg *cfg = edp->cfg;
u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
+ u8 ldo_config;
int timeout;
int ret;
u32 val;
@@ -332,8 +400,11 @@ static int qcom_edp_phy_power_on(struct phy *phy)
if (timeout)
return timeout;

- writel(0x01, edp->tx0 + TXn_LDO_CONFIG);
- writel(0x01, edp->tx1 + TXn_LDO_CONFIG);
+
+ ldo_config = (cfg && cfg->is_dp) ? 0x1 : 0x0;
+
+ 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);

@@ -635,6 +706,7 @@ static int qcom_edp_phy_probe(struct platform_device *pdev)
return -ENOMEM;

edp->dev = dev;
+ edp->cfg = of_device_get_match_data(&pdev->dev);

edp->edp = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(edp->edp))
--
2.35.1

2022-08-30 05:41:47

by Vinod Koul

[permalink] [raw]
Subject: Re: [PATCH 0/5] phy: qcom: edp: Introduce SC8280XP support

On 09-08-22, 21:07, Bjorn Andersson wrote:
> What the subject says.

:-)


Applied, thanks

--
~Vinod

2023-10-02 09:13:25

by Johan Hovold

[permalink] [raw]
Subject: Re: [PATCH 4/5] phy: qcom: edp: Introduce support for DisplayPort

On Tue, Aug 09, 2022 at 09:07:44PM -0700, Bjorn Andersson wrote:
> The eDP phy can be used to drive either eDP or DP output, with some
> minor variations in some of the configuration and seemingly a need for
> implementing swing and pre_emphasis calibration.
>
> Introduce a config object, indicating if the phy is operating in eDP or
> DP mode and swing/pre-emphasis calibration to support this.
>
> Signed-off-by: Bjorn Andersson <[email protected]>
> ---
> drivers/phy/qualcomm/phy-qcom-edp.c | 80 +++++++++++++++++++++++++++--
> 1 file changed, 76 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c
> index 32614fb838b5..301ac422d2fe 100644
> --- a/drivers/phy/qualcomm/phy-qcom-edp.c
> +++ b/drivers/phy/qualcomm/phy-qcom-edp.c
> @@ -70,8 +70,19 @@
>
> #define TXn_TRAN_DRVR_EMP_EN 0x0078
>
> +struct qcom_edp_cfg {
> + bool is_dp;
> +
> + /* DP PHY swing and pre_emphasis tables */
> + const u8 (*swing_hbr_rbr)[4][4];
> + const u8 (*swing_hbr3_hbr2)[4][4];
> + const u8 (*pre_emphasis_hbr_rbr)[4][4];
> + const u8 (*pre_emphasis_hbr3_hbr2)[4][4];
> +};

> static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
> @@ -315,7 +381,9 @@ static int qcom_edp_set_vco_div(const struct qcom_edp *edp)
> static int qcom_edp_phy_power_on(struct phy *phy)
> {
> const struct qcom_edp *edp = phy_get_drvdata(phy);
> + const struct qcom_edp_cfg *cfg = edp->cfg;
> u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
> + u8 ldo_config;
> int timeout;
> int ret;
> u32 val;
> @@ -332,8 +400,11 @@ static int qcom_edp_phy_power_on(struct phy *phy)
> if (timeout)
> return timeout;
>
> - writel(0x01, edp->tx0 + TXn_LDO_CONFIG);
> - writel(0x01, edp->tx1 + TXn_LDO_CONFIG);
> +
> + ldo_config = (cfg && cfg->is_dp) ? 0x1 : 0x0;
> +
> + writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
> + writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG);

When reviewing a patch from Konrad which will start using the eDP
configuration on the X13s, I noticed that this patch inverted these bits
for older SoCs (e.g. sc7280 and sc8180xp). They used to be set to 1,
but after this patch they will be set to 0.

Was that intentional even if it was never mentioned in the commit
message? Or was it a mistake that should be fixed?

Johan

2023-10-02 10:56:08

by Konrad Dybcio

[permalink] [raw]
Subject: Re: [PATCH 4/5] phy: qcom: edp: Introduce support for DisplayPort



On 10/2/23 11:06, Johan Hovold wrote:
> On Tue, Aug 09, 2022 at 09:07:44PM -0700, Bjorn Andersson wrote:
>> The eDP phy can be used to drive either eDP or DP output, with some
>> minor variations in some of the configuration and seemingly a need for
>> implementing swing and pre_emphasis calibration.
>>
>> Introduce a config object, indicating if the phy is operating in eDP or
>> DP mode and swing/pre-emphasis calibration to support this.
>>
>> Signed-off-by: Bjorn Andersson <[email protected]>
>> ---
>> drivers/phy/qualcomm/phy-qcom-edp.c | 80 +++++++++++++++++++++++++++--
>> 1 file changed, 76 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c
>> index 32614fb838b5..301ac422d2fe 100644
>> --- a/drivers/phy/qualcomm/phy-qcom-edp.c
>> +++ b/drivers/phy/qualcomm/phy-qcom-edp.c
>> @@ -70,8 +70,19 @@
>>
>> #define TXn_TRAN_DRVR_EMP_EN 0x0078
>>
>> +struct qcom_edp_cfg {
>> + bool is_dp;
>> +
>> + /* DP PHY swing and pre_emphasis tables */
>> + const u8 (*swing_hbr_rbr)[4][4];
>> + const u8 (*swing_hbr3_hbr2)[4][4];
>> + const u8 (*pre_emphasis_hbr_rbr)[4][4];
>> + const u8 (*pre_emphasis_hbr3_hbr2)[4][4];
>> +};
>
>> static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
>> @@ -315,7 +381,9 @@ static int qcom_edp_set_vco_div(const struct qcom_edp *edp)
>> static int qcom_edp_phy_power_on(struct phy *phy)
>> {
>> const struct qcom_edp *edp = phy_get_drvdata(phy);
>> + const struct qcom_edp_cfg *cfg = edp->cfg;
>> u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
>> + u8 ldo_config;
>> int timeout;
>> int ret;
>> u32 val;
>> @@ -332,8 +400,11 @@ static int qcom_edp_phy_power_on(struct phy *phy)
>> if (timeout)
>> return timeout;
>>
>> - writel(0x01, edp->tx0 + TXn_LDO_CONFIG);
>> - writel(0x01, edp->tx1 + TXn_LDO_CONFIG);
>> +
>> + ldo_config = (cfg && cfg->is_dp) ? 0x1 : 0x0;
>> +
>> + writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
>> + writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG);
>
> When reviewing a patch from Konrad which will start using the eDP
> configuration on the X13s, I noticed that this patch inverted these bits
> for older SoCs (e.g. sc7280 and sc8180xp). They used to be set to 1,
> but after this patch they will be set to 0.
>
> Was that intentional even if it was never mentioned in the commit
> message? Or was it a mistake that should be fixed?
+Abhinav, Jessica

Konrad