diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 9f3ece523202..62d4e8f1ddbe 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1110,9 +1110,20 @@ static int analogix_dp_enable_psr(struct analogix_dp_device *dp) psr_vsc.db[1] = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; ret = analogix_dp_send_psr_spd(dp, &psr_vsc, true); - if (!ret) + if (!ret) { analogix_dp_set_analog_power_down(dp, POWER_ALL, true); + if (dp->phy) { + union phy_configure_opts phy_cfg = {0}; + + phy_cfg.dp.lanes = 0; + phy_cfg.dp.set_lanes = true; + ret = phy_configure(dp->phy, &phy_cfg); + if (ret) + return ret; + } + } + return ret; } @@ -1793,6 +1804,25 @@ int analogix_dp_audio_get_eld(struct analogix_dp_device *dp, u8 *buf, size_t len } EXPORT_SYMBOL_GPL(analogix_dp_audio_get_eld); +static void analogix_dp_link_train_restore(struct analogix_dp_device *dp) +{ + u32 link_rate, lane_count; + u8 lane, spread; + + analogix_dp_get_link_bandwidth(dp, &link_rate); + analogix_dp_get_lane_count(dp, &lane_count); + drm_dp_dpcd_readb(&dp->aux, DP_MAX_DOWNSPREAD, &spread); + + dp->link_train.link_rate = link_rate; + dp->link_train.lane_count = lane_count; + dp->link_train.enhanced_framing = analogix_dp_get_enhanced_mode(dp); + dp->link_train.ssc = !!(spread & DP_MAX_DOWNSPREAD_0_5); + + for (lane = 0; lane < 4; lane++) + dp->link_train.training_lane[lane] = + analogix_dp_get_lane_link_training(dp, lane); +} + int analogix_dp_loader_protect(struct analogix_dp_device *dp) { int ret; @@ -1807,6 +1837,18 @@ int analogix_dp_loader_protect(struct analogix_dp_device *dp) dp->dpms_mode = DRM_MODE_DPMS_ON; + analogix_dp_link_train_restore(dp); + + ret = analogix_dp_fast_link_train_detection(dp); + if (ret) + return ret; + + if (analogix_dp_detect_sink_psr(dp)) { + ret = analogix_dp_enable_sink_psr(dp); + if (ret) + return ret; + } + return 0; } EXPORT_SYMBOL_GPL(analogix_dp_loader_protect); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index 804a87d59fb4..15fcce9a165f 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -221,6 +221,7 @@ void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count); void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count); void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, bool enable); +bool analogix_dp_get_enhanced_mode(struct analogix_dp_device *dp); void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, enum pattern_set pattern); void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index dfbb5d519412..863cce70e374 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -699,6 +699,15 @@ void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, } } +bool analogix_dp_get_enhanced_mode(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_4); + + return !!(reg & ENHANCED); +} + void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, enum pattern_set pattern) { @@ -978,6 +987,24 @@ static ssize_t analogix_dp_get_psr_status(struct analogix_dp_device *dp) return status; } +static void analogix_dp_reuse_spd(struct analogix_dp_device *dp) +{ + u32 reg, val; + + switch (dp->plat_data->dev_type) { + case RK3588_EDP: + reg = ANALOGIX_DP_SPDIF_AUDIO_CTL_0; + break; + default: + reg = ANALOGIX_DP_VIDEO_CTL_3; + break; + } + + val = analogix_dp_read(dp, reg); + val |= REUSE_SPD_EN; + analogix_dp_write(dp, reg, val); +} + int analogix_dp_send_psr_spd(struct analogix_dp_device *dp, struct dp_sdp *vsc, bool blocking) { @@ -1010,10 +1037,13 @@ int analogix_dp_send_psr_spd(struct analogix_dp_device *dp, analogix_dp_write(dp, ANALOGIX_DP_VSC_SHADOW_DB0, vsc->db[0]); analogix_dp_write(dp, ANALOGIX_DP_VSC_SHADOW_DB1, vsc->db[1]); + /* configure PB0 / PB1 values */ + analogix_dp_write(dp, ANALOGIX_DP_VSC_SHADOW_PB0, + vsc->db[1] ? 0x8d : 0x00); + analogix_dp_write(dp, ANALOGIX_DP_VSC_SHADOW_PB1, 0x00); + /* set reuse spd inforframe */ - val = analogix_dp_read(dp, ANALOGIX_DP_VIDEO_CTL_3); - val |= REUSE_SPD_EN; - analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_3, val); + analogix_dp_reuse_spd(dp); /* mark info frame update */ val = analogix_dp_read(dp, ANALOGIX_DP_PKT_SEND_CTL); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h index df88f1ad0883..7658ff853dcc 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h @@ -63,6 +63,8 @@ #define ANALOGIX_DP_PSR_FRAME_UPDATE_CTRL 0x318 #define ANALOGIX_DP_VSC_SHADOW_DB0 0x31C #define ANALOGIX_DP_VSC_SHADOW_DB1 0x320 +#define ANALOGIX_DP_VSC_SHADOW_PB0 0x33C +#define ANALOGIX_DP_VSC_SHADOW_PB1 0x340 #define ANALOGIX_DP_LANE_MAP 0x35C