From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: Anusha Srivatsa <anusha.srivatsa@intel.com>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [Intel-gfx] [PATCH 1/2] drm/i915/display: Do both crawl and squash when changing cdclk
Date: Thu, 20 Oct 2022 14:32:43 +0300 [thread overview]
Message-ID: <Y1Ex2z6BMloyzLWa@intel.com> (raw)
In-Reply-To: <20221013233223.103381-1-anusha.srivatsa@intel.com>
On Thu, Oct 13, 2022 at 04:32:22PM -0700, Anusha Srivatsa wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> For MTL, changing cdclk from between certain frequencies has
> both squash and crawl. Use the current cdclk config and
> the new(desired) cdclk config to construtc a mid cdclk config.
> Set the cdclk twice:
> - Current cdclk -> mid cdclk
> - mid cdclk -> desired cdclk
>
> v2: Add check in intel_modeset_calc_cdclk() to avoid cdclk
> change via modeset for platforms that support squash_crawl sequences(Ville)
>
> v3: Add checks for:
> - scenario where only slow clock is used and
> cdclk is actually 0 (bringing up display).
> - PLLs are on before looking up the waveform.
> - Squash and crawl capability checks.(Ville)
>
> Signed-off-by: Anusha Srivatsa <anusha.srivatsa@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_cdclk.c | 157 +++++++++++++++++----
> 1 file changed, 128 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
> index ad401357ab66..430b4cb0a8ab 100644
> --- a/drivers/gpu/drm/i915/display/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
> @@ -1675,7 +1675,7 @@ static u32 cdclk_squash_waveform(struct drm_i915_private *dev_priv,
> const struct intel_cdclk_vals *table = dev_priv->display.cdclk.table;
> int i;
>
> - if (cdclk == dev_priv->display.cdclk.hw.bypass)
> + if (cdclk == dev_priv->display.cdclk.hw.bypass || cdclk == 0)
cdclk should never be zero. Why is that needed? Hmm. Ah, we do set it to
zero during sanitation. But that shouldn't matter since we shouldn't
call this in that case...
> return 0;
>
> for (i = 0; table[i].refclk; i++)
> @@ -1689,37 +1689,72 @@ static u32 cdclk_squash_waveform(struct drm_i915_private *dev_priv,
> return 0xffff;
> }
>
> -static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
> - const struct intel_cdclk_config *cdclk_config,
> - enum pipe pipe)
> +static int cdclk_squash_divider(u16 waveform)
> +{
> + return hweight16(waveform ?: 0xffff);
> +}
> +
> +static bool cdclk_crawl_and_squash(struct drm_i915_private *i915,
> + const struct intel_cdclk_config *old_cdclk_config,
> + const struct intel_cdclk_config *new_cdclk_config,
> + struct intel_cdclk_config *mid_cdclk_config)
> +{
> + u16 old_waveform = cdclk_squash_waveform(i915, old_cdclk_config->cdclk);
> + u16 new_waveform = cdclk_squash_waveform(i915, new_cdclk_config->cdclk);
... but here we do call it. Just moving these to be called after
the vco checks should take care of that issue.
> + u16 mid_waveform;
> + int size = 16;
> + int div = 2;
> +
> + /* Return if both Squash and Crawl are not present */
> + if (!HAS_CDCLK_CRAWL(i915) || !has_cdclk_squasher(i915))
> + return false;
> +
> + /* Return if Squash only or Crawl only is the desired action */
> + if (old_cdclk_config->vco <= 0 || new_cdclk_config->vco <= 0 ||
> + old_cdclk_config->vco == new_cdclk_config->vco ||
> + old_waveform == new_waveform)
> + return false;
> +
> + *mid_cdclk_config = *new_cdclk_config;
> +
> + /* If moving to a higher cdclk(squash) the mid cdclk config
> + * should have the new (squash) waveform.
> + * If moving to a lower cdclk (crawl) the mid cdclk config
> + * should have the new vco.
> + */
> +
> + if (cdclk_squash_divider(new_waveform) > cdclk_squash_divider(old_waveform)) {
> + mid_cdclk_config->vco = old_cdclk_config->vco;
> + mid_waveform = new_waveform;
> + } else {
> + mid_cdclk_config->vco = new_cdclk_config->vco;
> + mid_waveform = old_waveform;
> + }
> +
> + mid_cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_squash_divider(mid_waveform) *
> + mid_cdclk_config->vco, size * div);
> +
> + /* make sure the mid clock came out sane */
> +
> + drm_WARN_ON(&i915->drm, mid_cdclk_config->cdclk <
> + min(old_cdclk_config->cdclk, new_cdclk_config->cdclk));
> + drm_WARN_ON(&i915->drm, mid_cdclk_config->cdclk >
> + i915->display.cdclk.max_cdclk_freq);
> + drm_WARN_ON(&i915->drm, cdclk_squash_waveform(i915, mid_cdclk_config->cdclk) !=
> + mid_waveform);
> +
> + return true;
> +}
> +
> +static void _bxt_set_cdclk(struct drm_i915_private *dev_priv,
> + const struct intel_cdclk_config *cdclk_config,
> + enum pipe pipe)
> {
> int cdclk = cdclk_config->cdclk;
> int vco = cdclk_config->vco;
> u32 val;
> u16 waveform;
> int clock;
> - int ret;
> -
> - /* Inform power controller of upcoming frequency change. */
> - if (DISPLAY_VER(dev_priv) >= 11)
> - ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
> - SKL_CDCLK_PREPARE_FOR_CHANGE,
> - SKL_CDCLK_READY_FOR_CHANGE,
> - SKL_CDCLK_READY_FOR_CHANGE, 3);
> - else
> - /*
> - * BSpec requires us to wait up to 150usec, but that leads to
> - * timeouts; the 2ms used here is based on experiment.
> - */
> - ret = snb_pcode_write_timeout(&dev_priv->uncore,
> - HSW_PCODE_DE_WRITE_FREQ_REQ,
> - 0x80000000, 150, 2);
> - if (ret) {
> - drm_err(&dev_priv->drm,
> - "Failed to inform PCU about cdclk change (err %d, freq %d)\n",
> - ret, cdclk);
> - return;
> - }
>
> if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0) {
> if (dev_priv->display.cdclk.hw.vco != vco)
> @@ -1772,6 +1807,44 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
>
> if (pipe != INVALID_PIPE)
> intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(dev_priv, pipe));
> +}
> +
> +static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
> + const struct intel_cdclk_config *cdclk_config,
> + enum pipe pipe)
> +{
> + struct intel_cdclk_config mid_cdclk_config;
> + int cdclk = cdclk_config->cdclk;
> + int ret;
> +
> + /* Inform power controller of upcoming frequency change. */
> + if (DISPLAY_VER(dev_priv) >= 11)
> + ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
> + SKL_CDCLK_PREPARE_FOR_CHANGE,
> + SKL_CDCLK_READY_FOR_CHANGE,
> + SKL_CDCLK_READY_FOR_CHANGE, 3);
> + else
> + /*
> + * BSpec requires us to wait up to 150usec, but that leads to
> + * timeouts; the 2ms used here is based on experiment.
> + */
> + ret = snb_pcode_write_timeout(&dev_priv->uncore,
> + HSW_PCODE_DE_WRITE_FREQ_REQ,
> + 0x80000000, 150, 2);
> + if (ret) {
> + drm_err(&dev_priv->drm,
> + "Failed to inform PCU about cdclk change (err %d, freq %d)\n",
> + ret, cdclk);
> + return;
> + }
> +
> + if (cdclk_crawl_and_squash(dev_priv, &dev_priv->display.cdclk.hw,
> + cdclk_config, &mid_cdclk_config)) {
> + _bxt_set_cdclk(dev_priv, &mid_cdclk_config, pipe);
> + _bxt_set_cdclk(dev_priv, cdclk_config, pipe);
> + } else {
> + _bxt_set_cdclk(dev_priv, cdclk_config, pipe);
> + }
>
> if (DISPLAY_VER(dev_priv) >= 11) {
> ret = snb_pcode_write(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
> @@ -1944,6 +2017,27 @@ void intel_cdclk_uninit_hw(struct drm_i915_private *i915)
> skl_cdclk_uninit_hw(i915);
> }
>
> +static bool intel_cdclk_can_crawl_and_squash(struct drm_i915_private *i915,
> + const struct intel_cdclk_config *a,
> + const struct intel_cdclk_config *b)
> +{
> + u16 old_waveform;
> + u16 new_waveform;
> +
> + if (a->vco == 0 || b->vco == 0)
> + return false;
> +
> + if (HAS_CDCLK_CRAWL(i915) && has_cdclk_squasher(i915)) {
> + old_waveform = cdclk_squash_waveform(i915, a->cdclk);
> + new_waveform = cdclk_squash_waveform(i915, b->cdclk);
> + } else {
> + return false;
> + }
A bit of weird construct this. I would make it
if (!has_crawl || !has_squash)
return false;
...
just like you had in the other function.
And doing that check before the vco checks would also be
more consistent with the other function.
> +
> + return a->vco != b->vco &&
> + old_waveform != new_waveform;
> +}
> +
> static bool intel_cdclk_can_crawl(struct drm_i915_private *dev_priv,
> const struct intel_cdclk_config *a,
> const struct intel_cdclk_config *b)
> @@ -2750,9 +2844,14 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
> pipe = INVALID_PIPE;
> }
>
> - if (intel_cdclk_can_squash(dev_priv,
> - &old_cdclk_state->actual,
> - &new_cdclk_state->actual)) {
> + if (intel_cdclk_can_crawl_and_squash(dev_priv,
> + &old_cdclk_state->actual,
> + &new_cdclk_state->actual)) {
> + drm_dbg_kms(&dev_priv->drm,
> + "Can change cdclk via crawler and squasher\n");
"crawler" is a bit weird term here. Maybe we should fix up all of thse
to use the terms "crawling" and "squashing" or something along those
lines. I'd make that a separate patch though.
> + } else if (intel_cdclk_can_squash(dev_priv,
> + &old_cdclk_state->actual,
> + &new_cdclk_state->actual)) {
> drm_dbg_kms(&dev_priv->drm,
> "Can change cdclk via squasher\n");
> } else if (intel_cdclk_can_crawl(dev_priv,
> --
> 2.25.1
--
Ville Syrjälä
Intel
next prev parent reply other threads:[~2022-10-20 11:32 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-13 23:32 [Intel-gfx] [PATCH 1/2] drm/i915/display: Do both crawl and squash when changing cdclk Anusha Srivatsa
2022-10-13 23:32 ` [Intel-gfx] [PATCH 2/2] drm/i915/display: Add CDCLK Support for MTL Anusha Srivatsa
2022-10-14 0:35 ` [Intel-gfx] ✓ Fi.CI.BAT: success for series starting with [1/2] drm/i915/display: Do both crawl and squash when changing cdclk Patchwork
2022-10-14 4:57 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork
2022-10-14 16:54 ` Srivatsa, Anusha
2022-10-20 11:32 ` Ville Syrjälä [this message]
2022-10-20 19:37 ` [Intel-gfx] [PATCH 1/2] " Srivatsa, Anusha
2022-10-20 14:42 ` Balasubramani Vivekanandan
2022-10-20 15:14 ` Ville Syrjälä
2022-10-20 19:43 ` Srivatsa, Anusha
2022-10-20 19:40 ` Srivatsa, Anusha
-- strict thread matches above, loose matches on Subject: below --
2022-11-04 22:26 Anusha Srivatsa
2022-11-08 23:42 ` Matt Roper
2022-11-08 23:56 ` Srivatsa, Anusha
2022-11-09 0:24 ` Matt Roper
2022-11-09 11:29 ` Ville Syrjälä
2022-11-09 21:49 ` Srivatsa, Anusha
2022-10-31 22:56 Anusha Srivatsa
2022-10-28 21:32 Anusha Srivatsa
2022-10-26 23:22 Anusha Srivatsa
2022-10-28 9:05 ` Ville Syrjälä
2022-10-28 21:27 ` Srivatsa, Anusha
2022-09-30 21:34 Anusha Srivatsa
2022-09-28 19:04 Anusha Srivatsa
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Y1Ex2z6BMloyzLWa@intel.com \
--to=ville.syrjala@linux.intel.com \
--cc=anusha.srivatsa@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox