phy/rockchip: samsung-hdptx: add support for rate R216/R243/R324/R432

R216/R243/R324/R432 are the new recommended link rates in
eDP v1.4, which may be read from DPCD SUPPORTED_LINK_RATES
(0x00010h through 0x0001fh). And set the link rate by DPCD
LINK_BW_SET(0x00100h).

Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
Change-Id: Ib692d18cd79765eb172fb0455cbc1bc1f0594d79
This commit is contained in:
Damon Ding
2024-05-21 15:13:45 +08:00
parent 617e6880cd
commit da33ef8e9e

View File

@@ -342,6 +342,13 @@ enum {
DP_BW_HBR3,
};
enum {
EDP_BW_2_16,
EDP_BW_2_43,
EDP_BW_3_24,
EDP_BW_4_32,
};
struct tx_drv_ctrl {
u8 tx_drv_lvl_ctrl;
u8 tx_drv_post_lvl_ctrl;
@@ -351,6 +358,19 @@ struct tx_drv_ctrl {
u8 ana_tx_drv_accdrv_ctrl;
} __packed;
struct tx_pll_ctrl {
u8 mdiv;
u8 sdiv;
u8 sdm_denominator;
u8 sdm_numerator_sign;
u8 sdm_numerator;
u8 sdc_clock_div;
u8 sdc_numerator;
u8 sdc_denominator;
u8 ssc_deviation;
u8 ssc_freq;
} __packed;
static struct tx_drv_ctrl tx_drv_ctrl_rbr[4][4] = {
/* voltage swing 0, pre-emphasis 0->3 */
{
@@ -435,6 +455,14 @@ static struct tx_drv_ctrl tx_drv_ctrl_hbr2[4][4] = {
}
};
/* pll configurations for link rate R216/R243/R324/R432 */
static struct tx_pll_ctrl tx_pll_ctrl_extra[4] = {
{ 0x5a, 0x01, 0x32, 0x00, 0x00, 0x00, 0x01, 0x04, 0x0f, 0x18 }, /* R216 */
{ 0x65, 0x01, 0x60, 0x00, 0x10, 0x01, 0x13, 0x18, 0x20, 0x0b }, /* R243 */
{ 0x87, 0x01, 0x21, 0x00, 0x00, 0x02, 0x03, 0x08, 0x0e, 0x1a }, /* R324 */
{ 0x5a, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0f, 0x18 }, /* R432 */
};
static int rockchip_hdptx_phy_parse_training_table(struct device *dev)
{
size_t size = sizeof(struct tx_drv_ctrl) * 10;
@@ -492,7 +520,11 @@ static int rockchip_hdptx_phy_verify_config(struct rockchip_hdptx_phy *hdptx,
if (dp->set_rate) {
switch (dp->link_rate) {
case 1620:
case 2160:
case 2430:
case 2700:
case 3240:
case 4320:
case 5400:
break;
default:
@@ -536,12 +568,16 @@ static void rockchip_hdptx_phy_set_voltage(struct rockchip_hdptx_phy *hdptx,
LN_TX_SER_40BIT_EN_RBR,
FIELD_PREP(LN_TX_SER_40BIT_EN_RBR, 0x1));
break;
case 2160:
case 2430:
case 2700:
ctrl = &tx_drv_ctrl_hbr[dp->voltage[lane]][dp->pre[lane]];
regmap_update_bits(hdptx->regmap, LANE_REG(lane, 0x0c44),
LN_TX_SER_40BIT_EN_HBR,
FIELD_PREP(LN_TX_SER_40BIT_EN_HBR, 0x1));
break;
case 3240:
case 4320:
case 5400:
default:
ctrl = &tx_drv_ctrl_hbr2[dp->voltage[lane]][dp->pre[lane]];
@@ -647,10 +683,24 @@ static int rockchip_hdptx_phy_set_lanes(struct rockchip_hdptx_phy *hdptx,
return 0;
}
static bool is_extra_recommended_link_rate(u32 link_rate)
{
switch (link_rate) {
case 2160:
case 2430:
case 3240:
case 4320:
return true;
}
return false;
}
static int rockchip_hdptx_phy_set_rate(struct rockchip_hdptx_phy *hdptx,
struct phy_configure_opts_dp *dp)
{
u32 bw, status;
u32 bw_extra = 0;
int ret;
rockchip_grf_write(hdptx->grf, HDPTXPHY_GRF_CON0, PLL_EN,
@@ -660,9 +710,25 @@ static int rockchip_hdptx_phy_set_rate(struct rockchip_hdptx_phy *hdptx,
case 1620:
bw = DP_BW_RBR;
break;
case 2160:
bw_extra = EDP_BW_2_16;
bw = DP_BW_HBR;
break;
case 2430:
bw_extra = EDP_BW_2_43;
bw = DP_BW_HBR;
break;
case 2700:
bw = DP_BW_HBR;
break;
case 3240:
bw_extra = EDP_BW_3_24;
bw = DP_BW_HBR2;
break;
case 4320:
bw_extra = EDP_BW_4_32;
bw = DP_BW_HBR2;
break;
case 5400:
bw = DP_BW_HBR2;
break;
@@ -670,6 +736,47 @@ static int rockchip_hdptx_phy_set_rate(struct rockchip_hdptx_phy *hdptx,
return -EINVAL;
}
if (is_extra_recommended_link_rate(dp->link_rate)) {
const struct tx_pll_ctrl *pll_ctrl = &tx_pll_ctrl_extra[bw_extra];
regmap_write(hdptx->regmap, 0x0144 + bw * 0x4,
FIELD_PREP(ROPLL_PMS_MDIV, pll_ctrl->mdiv));
regmap_write(hdptx->regmap, 0x0180 + bw * 0x4,
FIELD_PREP(ROPLL_SDM_DENOMINATOR, pll_ctrl->sdm_denominator));
regmap_write(hdptx->regmap, 0x0194 + bw * 0x4,
FIELD_PREP(ROPLL_SDM_NUMERATOR, pll_ctrl->sdm_numerator));
regmap_write(hdptx->regmap, 0x01b0 + bw * 0x4,
FIELD_PREP(ROPLL_SDC_NUMERATOR, pll_ctrl->sdc_numerator));
regmap_write(hdptx->regmap, 0x01c0 + bw * 0x4,
FIELD_PREP(ROPLL_SDC_DENOMINATOR, pll_ctrl->sdc_denominator));
if (bw == DP_BW_RBR) {
regmap_update_bits(hdptx->regmap, 0x0168, ROPLL_PMS_SDIV_RBR,
FIELD_PREP(ROPLL_PMS_SDIV_RBR, pll_ctrl->sdiv));
regmap_update_bits(hdptx->regmap, 0x0190, ROPLL_SDM_NUMERATOR_SIGN_RBR,
FIELD_PREP(ROPLL_SDM_NUMERATOR_SIGN_RBR,
pll_ctrl->sdm_numerator_sign));
regmap_update_bits(hdptx->regmap, 0x01a4, ROPLL_SDC_N_RBR,
FIELD_PREP(ROPLL_SDC_N_RBR, pll_ctrl->sdc_clock_div));
} else if (bw == DP_BW_HBR) {
regmap_update_bits(hdptx->regmap, 0x0168, ROPLL_PMS_SDIV_HBR,
FIELD_PREP(ROPLL_PMS_SDIV_HBR, pll_ctrl->sdiv));
regmap_update_bits(hdptx->regmap, 0x0190, ROPLL_SDM_NUMERATOR_SIGN_HBR,
FIELD_PREP(ROPLL_SDM_NUMERATOR_SIGN_HBR,
pll_ctrl->sdm_numerator_sign));
regmap_update_bits(hdptx->regmap, 0x01a8, ROPLL_SDC_N_HBR,
FIELD_PREP(ROPLL_SDC_N_HBR, pll_ctrl->sdc_clock_div));
} else {
regmap_update_bits(hdptx->regmap, 0x016c, ROPLL_PMS_SDIV_HBR2,
FIELD_PREP(ROPLL_PMS_SDIV_HBR2, pll_ctrl->sdiv));
regmap_update_bits(hdptx->regmap, 0x0190, ROPLL_SDM_NUMERATOR_SIGN_HBR2,
FIELD_PREP(ROPLL_SDM_NUMERATOR_SIGN_HBR2,
pll_ctrl->sdm_numerator_sign));
regmap_update_bits(hdptx->regmap, 0x01a8, ROPLL_SDC_N_HBR2,
FIELD_PREP(ROPLL_SDC_N_HBR2, pll_ctrl->sdc_clock_div));
}
}
regmap_update_bits(hdptx->regmap, 0x0254, DP_TX_LINK_BW,
FIELD_PREP(DP_TX_LINK_BW, bw));
@@ -678,11 +785,23 @@ static int rockchip_hdptx_phy_set_rate(struct rockchip_hdptx_phy *hdptx,
OVRD_ROPLL_SSC_EN | ROPLL_SSC_EN,
FIELD_PREP(OVRD_ROPLL_SSC_EN, 0x1) |
FIELD_PREP(ROPLL_SSC_EN, 0x1));
regmap_write(hdptx->regmap, 0x01d4,
FIELD_PREP(ANA_ROPLL_SSC_FM_DEVIATION, 0xc));
regmap_update_bits(hdptx->regmap, 0x01d8,
ANA_ROPLL_SSC_FM_FREQ,
FIELD_PREP(ANA_ROPLL_SSC_FM_FREQ, 0x1f));
if (is_extra_recommended_link_rate(dp->link_rate)) {
const struct tx_pll_ctrl *pll_ctrl = &tx_pll_ctrl_extra[bw_extra];
regmap_write(hdptx->regmap, 0x01d4,
FIELD_PREP(ANA_ROPLL_SSC_FM_DEVIATION,
pll_ctrl->ssc_deviation));
regmap_update_bits(hdptx->regmap, 0x01d8,
ANA_ROPLL_SSC_FM_FREQ,
FIELD_PREP(ANA_ROPLL_SSC_FM_FREQ,
pll_ctrl->ssc_freq));
} else {
regmap_write(hdptx->regmap, 0x01d4,
FIELD_PREP(ANA_ROPLL_SSC_FM_DEVIATION, 0xc));
regmap_update_bits(hdptx->regmap, 0x01d8,
ANA_ROPLL_SSC_FM_FREQ,
FIELD_PREP(ANA_ROPLL_SSC_FM_FREQ, 0x1f));
}
regmap_update_bits(hdptx->regmap, 0x0264, SSC_EN,
FIELD_PREP(SSC_EN, 0x2));
} else {