Re: [PATCH v2 2/2] drm/atomic: Force bridge self-refresh-exit on CRTC switch

2022-02-28 Thread Liu Ying
On Mon, 2022-02-28 at 12:25 -0800, Brian Norris wrote:
> It's possible to change which CRTC is in use for a given
> connector/encoder/bridge while we're in self-refresh without fully
> disabling the connector/encoder/bridge along the way. This can confuse
> the bridge encoder/bridge, because
> (a) it needs to track the SR state (trying to perform "active"
> operations while the panel is still in SR can be Bad(TM)); and
> (b) it tracks the SR state via the CRTC state (and after the switch, the
> previous SR state is lost).
> 
> Thus, we need to either somehow carry the self-refresh state over to the
> new CRTC, or else force an encoder/bridge self-refresh transition during
> such a switch.
> 
> I choose the latter, so we disable the encoder (and exit PSR) before
> attaching it to the new CRTC (where we can continue to assume a clean
> (non-self-refresh) state).
> 
> This fixes PSR issues seen on Rockchip RK3399 systems with
> drivers/gpu/drm/bridge/analogix/analogix_dp_core.c.
> 
> Change in v2:
> 
> - Drop "->enable" condition; this could possibly be "->active" to
>   reflect the intended hardware state, but it also is a little
>   over-specific. We want to make a transition through "disabled" any
>   time we're exiting PSR at the same time as a CRTC switch.

Cool. I don't see any particular issue regarding the drop.

Liu Ying

>   (Thanks Liu Ying)
> 
> Cc: Liu Ying 
> Cc: 
> Fixes: 1452c25b0e60 ("drm: Add helpers to kick off self refresh mode in 
> drivers")
> Signed-off-by: Brian Norris 
> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 16 +---
>  1 file changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> b/drivers/gpu/drm/drm_atomic_helper.c
> index 9603193d2fa1..987e4b212e9f 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -1011,9 +1011,19 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
>   return drm_atomic_crtc_effectively_active(old_state);
>  
>   /*
> -  * We need to run through the crtc_funcs->disable() function if the CRTC
> -  * is currently on, if it's transitioning to self refresh mode, or if
> -  * it's in self refresh mode and needs to be fully disabled.
> +  * We need to disable bridge(s) and CRTC if we're transitioning out of
> +  * self-refresh and changing CRTCs at the same time, because the
> +  * bridge tracks self-refresh status via CRTC state.
> +  */
> + if (old_state->self_refresh_active &&
> + old_state->crtc != new_state->crtc)
> + return true;
> +
> + /*
> +  * We also need to run through the crtc_funcs->disable() function if
> +  * the CRTC is currently on, if it's transitioning to self refresh
> +  * mode, or if it's in self refresh mode and needs to be fully
> +  * disabled.
>*/
>   return old_state->active ||
>  (old_state->self_refresh_active && !new_state->active) ||



[PATCH v2 2/2] drm/atomic: Force bridge self-refresh-exit on CRTC switch

2022-02-28 Thread Brian Norris
It's possible to change which CRTC is in use for a given
connector/encoder/bridge while we're in self-refresh without fully
disabling the connector/encoder/bridge along the way. This can confuse
the bridge encoder/bridge, because
(a) it needs to track the SR state (trying to perform "active"
operations while the panel is still in SR can be Bad(TM)); and
(b) it tracks the SR state via the CRTC state (and after the switch, the
previous SR state is lost).

Thus, we need to either somehow carry the self-refresh state over to the
new CRTC, or else force an encoder/bridge self-refresh transition during
such a switch.

I choose the latter, so we disable the encoder (and exit PSR) before
attaching it to the new CRTC (where we can continue to assume a clean
(non-self-refresh) state).

This fixes PSR issues seen on Rockchip RK3399 systems with
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c.

Change in v2:

- Drop "->enable" condition; this could possibly be "->active" to
  reflect the intended hardware state, but it also is a little
  over-specific. We want to make a transition through "disabled" any
  time we're exiting PSR at the same time as a CRTC switch.
  (Thanks Liu Ying)

Cc: Liu Ying 
Cc: 
Fixes: 1452c25b0e60 ("drm: Add helpers to kick off self refresh mode in 
drivers")
Signed-off-by: Brian Norris 
---
 drivers/gpu/drm/drm_atomic_helper.c | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 9603193d2fa1..987e4b212e9f 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1011,9 +1011,19 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
return drm_atomic_crtc_effectively_active(old_state);
 
/*
-* We need to run through the crtc_funcs->disable() function if the CRTC
-* is currently on, if it's transitioning to self refresh mode, or if
-* it's in self refresh mode and needs to be fully disabled.
+* We need to disable bridge(s) and CRTC if we're transitioning out of
+* self-refresh and changing CRTCs at the same time, because the
+* bridge tracks self-refresh status via CRTC state.
+*/
+   if (old_state->self_refresh_active &&
+   old_state->crtc != new_state->crtc)
+   return true;
+
+   /*
+* We also need to run through the crtc_funcs->disable() function if
+* the CRTC is currently on, if it's transitioning to self refresh
+* mode, or if it's in self refresh mode and needs to be fully
+* disabled.
 */
return old_state->active ||
   (old_state->self_refresh_active && !new_state->active) ||
-- 
2.35.1.574.g5d30c73bfb-goog