mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
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:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user