From 10aad71a4dba121e2011dd93bb8f19b0dbdd4df2 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Wed, 9 Jan 2019 10:05:25 +0800 Subject: [PATCH] drm/bridge: analogix_dp: Add support for SSC (Spread-Spectrum Clock) DPTX implements the programmable SSC down-spreading with up to 0.5% modulation amplitude and 30k/33k modulation frequency. Change-Id: I2c3eae8f27c84eb1b22eac8973691e0276c1588e Signed-off-by: Wyon Bi --- .../gpu/drm/bridge/analogix/analogix_dp_reg.c | 31 +++++++++++++++++++ .../gpu/drm/bridge/analogix/analogix_dp_reg.h | 1 + .../gpu/drm/rockchip/analogix_dp-rockchip.c | 3 ++ 3 files changed, 35 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index 04195f798316..d5038fcd3668 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -618,6 +618,32 @@ int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp, return retval; } +static void analogix_dp_ssc_enable(struct analogix_dp_device *dp) +{ + u32 reg; + + /* 4500ppm */ + writel(0x19, dp->reg_base + ANALOIGX_DP_SSC_REG); + /* + * To apply updated SSC parameters into SSC operation, + * firmware must disable and enable this bit. + */ + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); + reg |= SSC_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); + reg &= ~SSC_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); +} + +static void analogix_dp_ssc_disable(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); + reg |= SSC_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); +} + bool analogix_dp_ssc_supported(struct analogix_dp_device *dp) { /* Check if SSC is supported by both sides */ @@ -648,6 +674,11 @@ void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype) __func__, ret); return; } + } else { + if (analogix_dp_ssc_supported(dp)) + analogix_dp_ssc_enable(dp); + else + analogix_dp_ssc_disable(dp); } ret = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status, diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h index f7362d7a09a3..1ca8f955b960 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h @@ -48,6 +48,7 @@ #define ANALOGIX_DP_PLL_REG_4 0x9ec #define ANALOGIX_DP_PLL_REG_5 0xa00 +#define ANALOIGX_DP_SSC_REG 0x104 #define ANALOGIX_DP_PD 0x12c #define ANALOGIX_DP_IF_TYPE 0x244 diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 0d5926dbf947..84a6c3068371 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -678,10 +678,12 @@ static const struct rockchip_dp_chip_data rk3399_edp = { .lcdsel_big = HIWORD_UPDATE(0, RK3399_EDP_LCDC_SEL), .lcdsel_lit = HIWORD_UPDATE(RK3399_EDP_LCDC_SEL, RK3399_EDP_LCDC_SEL), .chip_type = RK3399_EDP, + .ssc = true, }; static const struct rockchip_dp_chip_data rk3368_edp = { .chip_type = RK3368_EDP, + .ssc = true, }; static const struct rockchip_dp_chip_data rk3288_dp = { @@ -689,6 +691,7 @@ static const struct rockchip_dp_chip_data rk3288_dp = { .lcdsel_big = HIWORD_UPDATE(0, RK3288_EDP_LCDC_SEL), .lcdsel_lit = HIWORD_UPDATE(RK3288_EDP_LCDC_SEL, RK3288_EDP_LCDC_SEL), .chip_type = RK3288_DP, + .ssc = true, }; static const struct rockchip_dp_chip_data rk3568_edp = {