mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
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 <bivvy.bi@rock-chips.com>
This commit is contained in:
@@ -161,7 +161,7 @@ analogix_dp_set_lane_lane_pre_emphasis(struct analogix_dp_device *dp,
|
||||
|
||||
static int analogix_dp_link_start(struct analogix_dp_device *dp)
|
||||
{
|
||||
u8 buf[4];
|
||||
u8 buf[4], dpcd = 0;
|
||||
int lane, lane_count, pll_tries, retval;
|
||||
|
||||
lane_count = dp->link_train.lane_count;
|
||||
@@ -183,6 +183,30 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp)
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
/* possibly enable downspread on the sink */
|
||||
retval = drm_dp_dpcd_readb(&dp->aux, DP_MAX_DOWNSPREAD, &dpcd);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
if (dpcd & DP_MAX_DOWNSPREAD_0_5) {
|
||||
DRM_DEV_INFO(dp->dev, "Enable downspread on the sink\n");
|
||||
|
||||
analogix_dp_ssc_enable(dp);
|
||||
|
||||
retval = drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL,
|
||||
DP_SPREAD_AMP_0_5);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
} else {
|
||||
DRM_DEV_INFO(dp->dev, "Disable downspread on the sink\n");
|
||||
|
||||
analogix_dp_ssc_disable(dp);
|
||||
|
||||
retval = drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL, 0);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Set TX pre-emphasis to minimum */
|
||||
for (lane = 0; lane < lane_count; lane++)
|
||||
analogix_dp_set_lane_lane_pre_emphasis(dp,
|
||||
|
||||
@@ -251,4 +251,6 @@ void analogix_dp_set_video_format(struct analogix_dp_device *dp);
|
||||
void analogix_dp_video_bist_enable(struct analogix_dp_device *dp);
|
||||
ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
|
||||
struct drm_dp_aux_msg *msg);
|
||||
void analogix_dp_ssc_enable(struct analogix_dp_device *dp);
|
||||
void analogix_dp_ssc_disable(struct analogix_dp_device *dp);
|
||||
#endif /* _ANALOGIX_DP_CORE_H */
|
||||
|
||||
@@ -1076,3 +1076,29 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
|
||||
|
||||
return num_transferred;
|
||||
}
|
||||
|
||||
void analogix_dp_ssc_enable(struct analogix_dp_device *dp)
|
||||
{
|
||||
u8 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);
|
||||
}
|
||||
|
||||
void analogix_dp_ssc_disable(struct analogix_dp_device *dp)
|
||||
{
|
||||
u8 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);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,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_LANE_MAP 0x35C
|
||||
|
||||
Reference in New Issue
Block a user