[PATCH 02/13] drm/i915/cdclk: Fix voltage_level programming edge case

2024-03-27 Thread Ville Syrjala
From: Ville Syrjälä 

Currently we only consider the relationship of the
old and new CDCLK frequencies when determining whether
to do the repgramming from intel_set_cdclk_pre_plane_update()
or intel_set_cdclk_post_plane_update().

It is technically possible to have a situation where the
CDCLK frequency is decreasing, but the voltage_level is
increasing due a DDI port. In this case we should bump
the voltage level already in intel_set_cdclk_pre_plane_update()
(so that the voltage_level will have been increased by the
time the port gets enabled), while leaving the CDCLK frequency
unchanged (as active planes/etc. may still depend on it).
We can then reduce the CDCLK frequency to its final value
from intel_set_cdclk_post_plane_update().

In order to handle that correctly we shall construct a
suitable amalgam of the old and new cdclk states in
intel_set_cdclk_pre_plane_update().

And we can simply call intel_set_cdclk() unconditionally
in both places as it will not do anything if nothing actually
changes vs. the current hw state.

v2: Handle cdclk_state->disable_pipes

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_cdclk.c | 27 +-
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c 
b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 619529dba095..504c5cbbcfff 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -2600,6 +2600,7 @@ intel_set_cdclk_pre_plane_update(struct 
intel_atomic_state *state)
intel_atomic_get_old_cdclk_state(state);
const struct intel_cdclk_state *new_cdclk_state =
intel_atomic_get_new_cdclk_state(state);
+   struct intel_cdclk_config cdclk_config;
 
if (!intel_cdclk_changed(&old_cdclk_state->actual,
 &new_cdclk_state->actual))
@@ -2608,13 +2609,21 @@ intel_set_cdclk_pre_plane_update(struct 
intel_atomic_state *state)
if (IS_DG2(i915))
intel_cdclk_pcode_pre_notify(state);
 
-   if (new_cdclk_state->disable_pipes ||
-   old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) {
-   drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
+   if (new_cdclk_state->disable_pipes) {
+   cdclk_config = new_cdclk_state->actual;
+   } else {
+   if (new_cdclk_state->actual.cdclk >= 
old_cdclk_state->actual.cdclk)
+   cdclk_config = new_cdclk_state->actual;
+   else
+   cdclk_config = old_cdclk_state->actual;
 
-   intel_set_cdclk(i915, &new_cdclk_state->actual,
-   new_cdclk_state->pipe);
+   cdclk_config.voltage_level = 
max(new_cdclk_state->actual.voltage_level,
+
old_cdclk_state->actual.voltage_level);
}
+
+   drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
+
+   intel_set_cdclk(i915, &cdclk_config, new_cdclk_state->pipe);
 }
 
 /**
@@ -2640,13 +2649,9 @@ intel_set_cdclk_post_plane_update(struct 
intel_atomic_state *state)
if (IS_DG2(i915))
intel_cdclk_pcode_post_notify(state);
 
-   if (!new_cdclk_state->disable_pipes &&
-   old_cdclk_state->actual.cdclk > new_cdclk_state->actual.cdclk) {
-   drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
+   drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
 
-   intel_set_cdclk(i915, &new_cdclk_state->actual,
-   new_cdclk_state->pipe);
-   }
+   intel_set_cdclk(i915, &new_cdclk_state->actual, new_cdclk_state->pipe);
 }
 
 static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state)
-- 
2.43.2



RE: [PATCH 02/13] drm/i915/cdclk: Fix voltage_level programming edge case

2024-03-28 Thread Shankar, Uma


> -Original Message-
> From: Intel-gfx  On Behalf Of Ville
> Syrjala
> Sent: Wednesday, March 27, 2024 11:16 PM
> To: intel-gfx@lists.freedesktop.org
> Subject: [PATCH 02/13] drm/i915/cdclk: Fix voltage_level programming edge case
> 
> From: Ville Syrjälä 
> 
> Currently we only consider the relationship of the old and new CDCLK 
> frequencies
> when determining whether to do the repgramming from
> intel_set_cdclk_pre_plane_update()
> or intel_set_cdclk_post_plane_update().
> 
> It is technically possible to have a situation where the CDCLK frequency is
> decreasing, but the voltage_level is increasing due a DDI port. In this case 
> we
> should bump the voltage level already in intel_set_cdclk_pre_plane_update()
> (so that the voltage_level will have been increased by the time the port gets
> enabled), while leaving the CDCLK frequency unchanged (as active planes/etc.
> may still depend on it).
> We can then reduce the CDCLK frequency to its final value from
> intel_set_cdclk_post_plane_update().
> 
> In order to handle that correctly we shall construct a suitable amalgam of 
> the old
> and new cdclk states in intel_set_cdclk_pre_plane_update().
> 
> And we can simply call intel_set_cdclk() unconditionally in both places as it 
> will
> not do anything if nothing actually changes vs. the current hw state.
> 
> v2: Handle cdclk_state->disable_pipes

Looks Good to me.
Reviewed-by: Uma Shankar 

> Signed-off-by: Ville Syrjälä 
> ---
>  drivers/gpu/drm/i915/display/intel_cdclk.c | 27 +-
>  1 file changed, 16 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c
> b/drivers/gpu/drm/i915/display/intel_cdclk.c
> index 619529dba095..504c5cbbcfff 100644
> --- a/drivers/gpu/drm/i915/display/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
> @@ -2600,6 +2600,7 @@ intel_set_cdclk_pre_plane_update(struct
> intel_atomic_state *state)
>   intel_atomic_get_old_cdclk_state(state);
>   const struct intel_cdclk_state *new_cdclk_state =
>   intel_atomic_get_new_cdclk_state(state);
> + struct intel_cdclk_config cdclk_config;
> 
>   if (!intel_cdclk_changed(&old_cdclk_state->actual,
>&new_cdclk_state->actual))
> @@ -2608,13 +2609,21 @@ intel_set_cdclk_pre_plane_update(struct
> intel_atomic_state *state)
>   if (IS_DG2(i915))
>   intel_cdclk_pcode_pre_notify(state);
> 
> - if (new_cdclk_state->disable_pipes ||
> - old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) {
> - drm_WARN_ON(&i915->drm, !new_cdclk_state-
> >base.changed);
> + if (new_cdclk_state->disable_pipes) {
> + cdclk_config = new_cdclk_state->actual;
> + } else {
> + if (new_cdclk_state->actual.cdclk >= old_cdclk_state-
> >actual.cdclk)
> + cdclk_config = new_cdclk_state->actual;
> + else
> + cdclk_config = old_cdclk_state->actual;
> 
> - intel_set_cdclk(i915, &new_cdclk_state->actual,
> - new_cdclk_state->pipe);
> + cdclk_config.voltage_level = max(new_cdclk_state-
> >actual.voltage_level,
> +  old_cdclk_state-
> >actual.voltage_level);
>   }
> +
> + drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
> +
> + intel_set_cdclk(i915, &cdclk_config, new_cdclk_state->pipe);
>  }
> 
>  /**
> @@ -2640,13 +2649,9 @@ intel_set_cdclk_post_plane_update(struct
> intel_atomic_state *state)
>   if (IS_DG2(i915))
>   intel_cdclk_pcode_post_notify(state);
> 
> - if (!new_cdclk_state->disable_pipes &&
> - old_cdclk_state->actual.cdclk > new_cdclk_state->actual.cdclk) {
> - drm_WARN_ON(&i915->drm, !new_cdclk_state-
> >base.changed);
> + drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
> 
> - intel_set_cdclk(i915, &new_cdclk_state->actual,
> - new_cdclk_state->pipe);
> - }
> + intel_set_cdclk(i915, &new_cdclk_state->actual,
> +new_cdclk_state->pipe);
>  }
> 
>  static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state 
> *crtc_state)
> --
> 2.43.2



Re: [PATCH 02/13] drm/i915/cdclk: Fix voltage_level programming edge case

2024-03-29 Thread Gustavo Sousa
Quoting Ville Syrjala (2024-03-27 14:45:33-03:00)
>From: Ville Syrjälä 
>
>Currently we only consider the relationship of the
>old and new CDCLK frequencies when determining whether
>to do the repgramming from intel_set_cdclk_pre_plane_update()
>or intel_set_cdclk_post_plane_update().
>
>It is technically possible to have a situation where the
>CDCLK frequency is decreasing, but the voltage_level is
>increasing due a DDI port. In this case we should bump
>the voltage level already in intel_set_cdclk_pre_plane_update()
>(so that the voltage_level will have been increased by the
>time the port gets enabled), while leaving the CDCLK frequency
>unchanged (as active planes/etc. may still depend on it).
>We can then reduce the CDCLK frequency to its final value
>from intel_set_cdclk_post_plane_update().
>
>In order to handle that correctly we shall construct a
>suitable amalgam of the old and new cdclk states in
>intel_set_cdclk_pre_plane_update().
>
>And we can simply call intel_set_cdclk() unconditionally
>in both places as it will not do anything if nothing actually
>changes vs. the current hw state.
>
>v2: Handle cdclk_state->disable_pipes
>
>Signed-off-by: Ville Syrjälä 
>---
> drivers/gpu/drm/i915/display/intel_cdclk.c | 27 +-
> 1 file changed, 16 insertions(+), 11 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c 
>b/drivers/gpu/drm/i915/display/intel_cdclk.c
>index 619529dba095..504c5cbbcfff 100644
>--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
>+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
>@@ -2600,6 +2600,7 @@ intel_set_cdclk_pre_plane_update(struct 
>intel_atomic_state *state)
> intel_atomic_get_old_cdclk_state(state);
> const struct intel_cdclk_state *new_cdclk_state =
> intel_atomic_get_new_cdclk_state(state);
>+struct intel_cdclk_config cdclk_config;
> 
> if (!intel_cdclk_changed(&old_cdclk_state->actual,
>  &new_cdclk_state->actual))
>@@ -2608,13 +2609,21 @@ intel_set_cdclk_pre_plane_update(struct 
>intel_atomic_state *state)
> if (IS_DG2(i915))
> intel_cdclk_pcode_pre_notify(state);
> 
>-if (new_cdclk_state->disable_pipes ||
>-old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) {
>-drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
>+if (new_cdclk_state->disable_pipes) {
>+cdclk_config = new_cdclk_state->actual;
>+} else {
>+if (new_cdclk_state->actual.cdclk >= 
>old_cdclk_state->actual.cdclk)
>+cdclk_config = new_cdclk_state->actual;
>+else
>+cdclk_config = old_cdclk_state->actual;
> 
>-intel_set_cdclk(i915, &new_cdclk_state->actual,
>-new_cdclk_state->pipe);
>+cdclk_config.voltage_level = 
>max(new_cdclk_state->actual.voltage_level,
>+ 
>old_cdclk_state->actual.voltage_level);
> }
>+
>+drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
>+
>+intel_set_cdclk(i915, &cdclk_config, new_cdclk_state->pipe);

Not sure if there could be unwanted side effects with passing
new_cdclk_state->pipe when using old_cdclk_state->actual. Because
voltage_level might have changed, parts of the cdclk change sequence end
up being exercised even when cdclk_config == old_cdclk_state->actual.

Well, even if those side effects might be harmless, I wonder if it would
be better if we used INVALID_PIPE when using old_cdclk_state->actual.

--
Gustavo Sousa

> }
> 
> /**
>@@ -2640,13 +2649,9 @@ intel_set_cdclk_post_plane_update(struct 
>intel_atomic_state *state)
> if (IS_DG2(i915))
> intel_cdclk_pcode_post_notify(state);
> 
>-if (!new_cdclk_state->disable_pipes &&
>-old_cdclk_state->actual.cdclk > new_cdclk_state->actual.cdclk) {
>-drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
>+drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
> 
>-intel_set_cdclk(i915, &new_cdclk_state->actual,
>-new_cdclk_state->pipe);
>-}
>+intel_set_cdclk(i915, &new_cdclk_state->actual, 
>new_cdclk_state->pipe);
> }
> 
> static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state 
> *crtc_state)
>-- 
>2.43.2
>


Re: [PATCH 02/13] drm/i915/cdclk: Fix voltage_level programming edge case

2024-04-02 Thread Ville Syrjälä
On Fri, Mar 29, 2024 at 02:04:55PM -0300, Gustavo Sousa wrote:
> Quoting Ville Syrjala (2024-03-27 14:45:33-03:00)
> >From: Ville Syrjälä 
> >
> >Currently we only consider the relationship of the
> >old and new CDCLK frequencies when determining whether
> >to do the repgramming from intel_set_cdclk_pre_plane_update()
> >or intel_set_cdclk_post_plane_update().
> >
> >It is technically possible to have a situation where the
> >CDCLK frequency is decreasing, but the voltage_level is
> >increasing due a DDI port. In this case we should bump
> >the voltage level already in intel_set_cdclk_pre_plane_update()
> >(so that the voltage_level will have been increased by the
> >time the port gets enabled), while leaving the CDCLK frequency
> >unchanged (as active planes/etc. may still depend on it).
> >We can then reduce the CDCLK frequency to its final value
> >from intel_set_cdclk_post_plane_update().
> >
> >In order to handle that correctly we shall construct a
> >suitable amalgam of the old and new cdclk states in
> >intel_set_cdclk_pre_plane_update().
> >
> >And we can simply call intel_set_cdclk() unconditionally
> >in both places as it will not do anything if nothing actually
> >changes vs. the current hw state.
> >
> >v2: Handle cdclk_state->disable_pipes
> >
> >Signed-off-by: Ville Syrjälä 
> >---
> > drivers/gpu/drm/i915/display/intel_cdclk.c | 27 +-
> > 1 file changed, 16 insertions(+), 11 deletions(-)
> >
> >diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c 
> >b/drivers/gpu/drm/i915/display/intel_cdclk.c
> >index 619529dba095..504c5cbbcfff 100644
> >--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
> >+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
> >@@ -2600,6 +2600,7 @@ intel_set_cdclk_pre_plane_update(struct 
> >intel_atomic_state *state)
> > intel_atomic_get_old_cdclk_state(state);
> > const struct intel_cdclk_state *new_cdclk_state =
> > intel_atomic_get_new_cdclk_state(state);
> >+struct intel_cdclk_config cdclk_config;
> > 
> > if (!intel_cdclk_changed(&old_cdclk_state->actual,
> >  &new_cdclk_state->actual))
> >@@ -2608,13 +2609,21 @@ intel_set_cdclk_pre_plane_update(struct 
> >intel_atomic_state *state)
> > if (IS_DG2(i915))
> > intel_cdclk_pcode_pre_notify(state);
> > 
> >-if (new_cdclk_state->disable_pipes ||
> >-old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) 
> >{
> >-drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
> >+if (new_cdclk_state->disable_pipes) {
> >+cdclk_config = new_cdclk_state->actual;
> >+} else {
> >+if (new_cdclk_state->actual.cdclk >= 
> >old_cdclk_state->actual.cdclk)
> >+cdclk_config = new_cdclk_state->actual;
> >+else
> >+cdclk_config = old_cdclk_state->actual;
> > 
> >-intel_set_cdclk(i915, &new_cdclk_state->actual,
> >-new_cdclk_state->pipe);
> >+cdclk_config.voltage_level = 
> >max(new_cdclk_state->actual.voltage_level,
> >+ 
> >old_cdclk_state->actual.voltage_level);
> > }
> >+
> >+drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
> >+
> >+intel_set_cdclk(i915, &cdclk_config, new_cdclk_state->pipe);
> 
> Not sure if there could be unwanted side effects with passing
> new_cdclk_state->pipe when using old_cdclk_state->actual. Because
> voltage_level might have changed, parts of the cdclk change sequence end
> up being exercised even when cdclk_config == old_cdclk_state->actual.
> 
> Well, even if those side effects might be harmless, I wonder if it would
> be better if we used INVALID_PIPE when using old_cdclk_state->actual.

Yeah. I doubt there should be any really bad side effects, but
probably a good idea to sidestep the whole question by passing
in INVALID_PIPE.

-- 
Ville Syrjälä
Intel