drm/bridge: analogix_dp: add support for ASSR mode

According to the eDP v1.3 chapter 3.6 Table 3-15, Alternative
Scramble Seed Reset(ASSR) is a recommended way for eDP Sink devices
to support Display Authentication and Content Protection as Method
3a, while Method 1 HDCP is normally not expected in an eDP Sink
device.

In addition, the ASSR support capability should be the bit 0 of
DPCD register 0000Dh according to the eDP v1.4 'Revision History'
table 2:

......
Table 3-4: Corrected reference to DPCD Address 0000Dh, bit 0 (was bit 4)
......

Change-Id: Iafad97755fd4c9e688c47164d099b290af905036
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
This commit is contained in:
Damon Ding
2025-01-15 11:57:34 +08:00
committed by Tao Huang
parent 8281b215f4
commit 3ae279210e
4 changed files with 78 additions and 0 deletions

View File

@@ -341,6 +341,43 @@ static bool analogix_dp_get_vrr_capable(struct analogix_dp_device *dp)
return true;
}
static int analogix_dp_enable_sink_to_assr_mode(struct analogix_dp_device *dp, bool enable)
{
u8 data;
int ret;
ret = drm_dp_dpcd_readb(&dp->aux, DP_EDP_CONFIGURATION_SET, &data);
if (ret != 1)
return ret;
if (enable)
ret = drm_dp_dpcd_writeb(&dp->aux, DP_EDP_CONFIGURATION_SET,
data | DP_ALTERNATE_SCRAMBLER_RESET_ENABLE);
else
ret = drm_dp_dpcd_writeb(&dp->aux, DP_LANE_COUNT_SET,
data & ~DP_ALTERNATE_SCRAMBLER_RESET_ENABLE);
return ret < 0 ? ret : 0;
}
static int analogix_dp_set_assr_mode(struct analogix_dp_device *dp)
{
bool assr_en;
int ret;
assr_en = drm_dp_alternate_scrambler_reset_cap(dp->dpcd);
ret = analogix_dp_enable_sink_to_assr_mode(dp, assr_en);
if (ret < 0)
return ret;
analogix_dp_enable_assr_mode(dp, assr_en);
dp->link_train.assr = assr_en;
return 0;
}
static int analogix_dp_link_start(struct analogix_dp_device *dp)
{
u8 buf[4];
@@ -380,6 +417,13 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp)
if (retval < 0)
return retval;
/* set ASSR if available */
retval = analogix_dp_set_assr_mode(dp);
if (retval < 0) {
dev_err(dp->dev, "failed to set assr mode\n");
return retval;
}
/* set enhanced mode if available */
retval = analogix_dp_set_enhanced_mode(dp);
if (retval < 0) {
@@ -908,6 +952,7 @@ static int analogix_dp_fast_link_train(struct analogix_dp_device *dp)
analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
analogix_dp_set_lane_count(dp, dp->link_train.lane_count);
analogix_dp_set_lane_link_training(dp);
analogix_dp_enable_assr_mode(dp, dp->link_train.assr);
analogix_dp_enable_enhanced_mode(dp, dp->link_train.enhanced_framing);
/* source Set training pattern 1 */
@@ -2392,6 +2437,7 @@ static void analogix_dp_link_train_restore(struct analogix_dp_device *dp)
dp->link_train.link_rate = link_rate;
dp->link_train.lane_count = lane_count;
dp->link_train.assr = analogix_dp_get_assr_mode(dp);
dp->link_train.enhanced_framing = analogix_dp_get_enhanced_mode(dp);
dp->link_train.ssc = !!(spread & DP_MAX_DOWNSPREAD_0_5);

View File

@@ -160,6 +160,7 @@ struct link_train {
u8 training_lane[4];
bool ssc;
bool enhanced_framing;
bool assr;
enum link_training_state lt_state;
};
@@ -279,5 +280,7 @@ void analogix_dp_init(struct analogix_dp_device *dp);
void analogix_dp_irq_handler(struct analogix_dp_device *dp);
void analogix_dp_phy_test(struct analogix_dp_device *dp);
void analogix_dp_check_device_service_irq(struct analogix_dp_device *dp);
void analogix_dp_enable_assr_mode(struct analogix_dp_device *dp, bool enable);
bool analogix_dp_get_assr_mode(struct analogix_dp_device *dp);
#endif /* _ANALOGIX_DP_CORE_H */

View File

@@ -1390,3 +1390,27 @@ void analogix_dp_init(struct analogix_dp_device *dp)
analogix_dp_init_hpd(dp);
analogix_dp_init_aux(dp);
}
void analogix_dp_enable_assr_mode(struct analogix_dp_device *dp, bool enable)
{
u32 reg;
if (enable) {
reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_POLICY);
reg |= ALTERNATE_SR_ENABLE;
analogix_dp_write(dp, ANALOGIX_DP_LINK_POLICY, reg);
} else {
reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_POLICY);
reg &= ~ALTERNATE_SR_ENABLE;
analogix_dp_write(dp, ANALOGIX_DP_LINK_POLICY, reg);
}
}
bool analogix_dp_get_assr_mode(struct analogix_dp_device *dp)
{
u32 reg;
reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_POLICY);
return !!(reg & ALTERNATE_SR_ENABLE);
}

View File

@@ -146,6 +146,8 @@
#define ANALOGIX_DP_CRC_CON 0x890
#define ANALOGIX_DP_I2S_CTRL 0x9C8
#define ANALOGIX_DP_LINK_POLICY 0x9D8
/* ANALOGIX_DP_TX_SW_RESET */
#define RESET_DP_TX (0x1 << 0)
@@ -515,4 +517,7 @@
/* ANALOGIX_DP_I2S_CTRL */
#define I2S_EN (0x1 << 4)
/* ANALOGIX_DP_LINK_POLICY */
#define ALTERNATE_SR_ENABLE (0x1 << 7)
#endif /* _ANALOGIX_DP_REG_H */