diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 9b72804010fb..127e4f9f7df7 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -984,6 +984,52 @@ static int analogix_dp_fast_link_train_detection(struct analogix_dp_device *dp) return 0; } +static int analogix_dp_link_power_up(struct analogix_dp_device *dp) +{ + u8 value; + int ret; + + if (dp->dpcd[DP_DPCD_REV] < 0x11) + return 0; + + ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value); + if (ret < 0) + return ret; + + value &= ~DP_SET_POWER_MASK; + value |= DP_SET_POWER_D0; + + ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value); + if (ret < 0) + return ret; + + usleep_range(1000, 2000); + + return 0; +} + +static int analogix_dp_link_power_down(struct analogix_dp_device *dp) +{ + u8 value; + int ret; + + if (dp->dpcd[DP_DPCD_REV] < 0x11) + return 0; + + ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value); + if (ret < 0) + return ret; + + value &= ~DP_SET_POWER_MASK; + value |= DP_SET_POWER_D3; + + ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value); + if (ret < 0) + return ret; + + return 0; +} + static int analogix_dp_commit(struct analogix_dp_device *dp) { struct video_info *video = &dp->video_info; @@ -995,6 +1041,12 @@ static int analogix_dp_commit(struct analogix_dp_device *dp) return ret; } + ret = analogix_dp_link_power_up(dp); + if (ret) { + dev_err(dp->dev, "failed to power up link: %d\n", ret); + return ret; + } + if (device_property_read_bool(dp->dev, "panel-self-test")) return drm_dp_dpcd_writeb(&dp->aux, DP_EDP_CONFIGURATION_SET, DP_PANEL_SELF_TEST_ENABLE); @@ -1445,6 +1497,9 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) } } + if (!analogix_dp_get_plug_in_status(dp)) + analogix_dp_link_power_down(dp); + disable_irq(dp->irq); if (dp->plat_data->power_off)