[Freedreno] [PATCH] drm/msm/dp: power off DP phy base on mainlink status at suspend
khsieh at codeaurora.org
khsieh at codeaurora.org
Wed May 26 23:56:15 UTC 2021
On 2021-05-26 15:30, Stephen Boyd wrote:
> Quoting Kuogee Hsieh (2021-05-26 11:08:23)
>> DP mainlink can be either enabled or disabled at the time of suspend
>> happen. Therefore DP phy teared down at suspend should base on
>> mainlink
>> status at that instance.
>
> Please add some more details here. The system crashes if you plug in
> the
> HDMI cable during system wide suspend. That seems to be because the DP
> phy isn't powered down during suspend if the HDMI cable is disconnected
> so we try to process the hpd plug event on the path to suspend instead
> of wait to bring up the phy and then the display?
>
> I'm trying to find the case when we would be entering suspend and only
> have called phy_init() without calling phy_exit(). What path is that? I
> guess it is dp_ctrl_off_link_stream() called when the sink count goes
> to
> 0? So plug in HDMI cable to apple dongle, unplug HDMI cable to apple
> dongle and phy_power_off() followed by phy_exit() followed by
> phy_init()
> and then enter suspend so we want to call phy_exit(). Then we only call
> phy_power_off() if we've called dp_ctrl_on()? I think I followed it
> all.
>
ok, will do
>>
>> Signed-off-by: Kuogee Hsieh <khsieh at codeaurora.org>
>> ---
>> drivers/gpu/drm/msm/dp/dp_ctrl.c | 5 ++++-
>> drivers/gpu/drm/msm/dp/dp_ctrl.h | 2 +-
>> drivers/gpu/drm/msm/dp/dp_display.c | 9 ++++++++-
>> 3 files changed, 13 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> b/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> index dbd8943..5115c05 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> @@ -1398,7 +1398,7 @@ int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl,
>> bool flip, bool reset)
>> * Perform required steps to uninitialize DP controller
>> * and its resources.
>> */
>> -void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl)
>> +void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl, bool mainlink_on)
>> {
>> struct dp_ctrl_private *ctrl;
>> struct dp_io *dp_io;
>> @@ -1414,6 +1414,9 @@ void dp_ctrl_host_deinit(struct dp_ctrl
>> *dp_ctrl)
>> phy = dp_io->phy;
>>
>> dp_catalog_ctrl_enable_irq(ctrl->catalog, false);
>> + if (mainlink_on)
>> + phy_power_off(phy);
>> +
>> phy_exit(phy);
>>
>> DRM_DEBUG_DP("Host deinitialized successfully\n");
>> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h
>> b/drivers/gpu/drm/msm/dp/dp_ctrl.h
>> index 25e4f75..a23ee2b 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
>> @@ -20,7 +20,7 @@ struct dp_ctrl {
>> };
>>
>> int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool
>> reset);
>> -void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl);
>> +void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl, bool mainlink_on);
>> int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl);
>> int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl);
>> int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl);
>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
>> b/drivers/gpu/drm/msm/dp/dp_display.c
>> index cdec0a3..88eeeb5 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>> @@ -104,6 +104,8 @@ struct dp_display_private {
>>
>> bool encoder_mode_set;
>>
>> + bool mainlink_on;
>> +
>
> Is there a reason why this can't be stashed away in dp_ctrl.c in the
> 'struct dp_ctrl'? It seems to follow closely with dp_ctrl_*() APIs.
yes, I will do that.
>
>> /* wait for audio signaling */
>> struct completion audio_comp;
>>
>> @@ -353,11 +355,14 @@ static int dp_display_process_hpd_high(struct
>> dp_display_private *dp)
>> dp_link_psm_config(dp->link, &dp->panel->link_info, false);
>>
>> dp_link_reset_phy_params_vx_px(dp->link);
>> +
>> + dp->mainlink_on = false;
>
> Isn't this too late to be setting it to false? i.e. it should be false
> by default, and then set to false when a dp_ctrl_off() call is made?
>
>> rc = dp_ctrl_on_link(dp->ctrl);
>> if (rc) {
>> DRM_ERROR("failed to complete DP link training\n");
>> goto end;
>> }
>> + dp->mainlink_on = true;
>>
>> dp_add_event(dp, EV_USER_NOTIFICATION, true, 0);
>>
>> @@ -392,7 +397,7 @@ static void dp_display_host_deinit(struct
>> dp_display_private *dp)
>> return;
>> }
>>
>> - dp_ctrl_host_deinit(dp->ctrl);
>> + dp_ctrl_host_deinit(dp->ctrl, dp->mainlink_on);
>> dp_aux_deinit(dp->aux);
>> dp_power_deinit(dp->power);
>>
>> @@ -941,6 +946,8 @@ static int dp_display_disable(struct
>> dp_display_private *dp, u32 data)
>> dp->core_initialized = false;
>> }
>>
>> + dp->mainlink_on = false;
>> +
>> dp_display->power_on = false;
>>
>> return 0;
>
> It would certainly help to keep it contained to one file instead of
> two.
agree,
More information about the Freedreno
mailing list