Skip to content

Commit d62686b

Browse files
StanFox1984jnikula
authored andcommitted
drm/i915/adl_p: CDCLK crawl support for ADL
CDCLK crawl feature allows to change CDCLK frequency without disabling the actual PLL and doesn't require a full modeset. v2: - Added has_cdclk_crawl as a feature flag to intel_device_info(Matt Roper) - s/gen13_cdclk_pll_crawl/adlp_cdclk_pll_crawl/ (Matt Roper) Cc: Mika Kahola <[email protected]> Reviewed-by: Mika Kahola <[email protected]> Signed-off-by: Stanislav Lisovskiy <[email protected]> Signed-off-by: Gwan-gyeong Mun <[email protected]> Signed-off-by: Jani Nikula <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 5131743 commit d62686b

File tree

4 files changed

+68
-9
lines changed

4 files changed

+68
-9
lines changed

drivers/gpu/drm/i915/display/intel_cdclk.c

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,6 +1548,35 @@ static void cnl_cdclk_pll_enable(struct drm_i915_private *dev_priv, int vco)
15481548
dev_priv->cdclk.hw.vco = vco;
15491549
}
15501550

1551+
static bool has_cdclk_crawl(struct drm_i915_private *i915)
1552+
{
1553+
return INTEL_INFO(i915)->has_cdclk_crawl;
1554+
}
1555+
1556+
static void adlp_cdclk_pll_crawl(struct drm_i915_private *dev_priv, int vco)
1557+
{
1558+
int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
1559+
u32 val;
1560+
1561+
/* Write PLL ratio without disabling */
1562+
val = CNL_CDCLK_PLL_RATIO(ratio) | BXT_DE_PLL_PLL_ENABLE;
1563+
intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
1564+
1565+
/* Submit freq change request */
1566+
val |= BXT_DE_PLL_FREQ_REQ;
1567+
intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
1568+
1569+
/* Timeout 200us */
1570+
if (intel_de_wait_for_set(dev_priv, BXT_DE_PLL_ENABLE,
1571+
BXT_DE_PLL_LOCK | BXT_DE_PLL_FREQ_REQ_ACK, 1))
1572+
DRM_ERROR("timeout waiting for FREQ change request ack\n");
1573+
1574+
val &= ~BXT_DE_PLL_FREQ_REQ;
1575+
intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
1576+
1577+
dev_priv->cdclk.hw.vco = vco;
1578+
}
1579+
15511580
static u32 bxt_cdclk_cd2x_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
15521581
{
15531582
if (DISPLAY_VER(dev_priv) >= 12) {
@@ -1620,14 +1649,16 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
16201649
return;
16211650
}
16221651

1623-
if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) {
1652+
if (has_cdclk_crawl(dev_priv) && dev_priv->cdclk.hw.vco > 0 && vco > 0) {
1653+
if (dev_priv->cdclk.hw.vco != vco)
1654+
adlp_cdclk_pll_crawl(dev_priv, vco);
1655+
} else if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) {
16241656
if (dev_priv->cdclk.hw.vco != 0 &&
16251657
dev_priv->cdclk.hw.vco != vco)
16261658
cnl_cdclk_pll_disable(dev_priv);
16271659

16281660
if (dev_priv->cdclk.hw.vco != vco)
16291661
cnl_cdclk_pll_enable(dev_priv, vco);
1630-
16311662
} else {
16321663
if (dev_priv->cdclk.hw.vco != 0 &&
16331664
dev_priv->cdclk.hw.vco != vco)
@@ -1820,6 +1851,28 @@ void intel_cdclk_uninit_hw(struct drm_i915_private *i915)
18201851
skl_cdclk_uninit_hw(i915);
18211852
}
18221853

1854+
static bool intel_cdclk_can_crawl(struct drm_i915_private *dev_priv,
1855+
const struct intel_cdclk_config *a,
1856+
const struct intel_cdclk_config *b)
1857+
{
1858+
int a_div, b_div;
1859+
1860+
if (!has_cdclk_crawl(dev_priv))
1861+
return false;
1862+
1863+
/*
1864+
* The vco and cd2x divider will change independently
1865+
* from each, so we disallow cd2x change when crawling.
1866+
*/
1867+
a_div = DIV_ROUND_CLOSEST(a->vco, a->cdclk);
1868+
b_div = DIV_ROUND_CLOSEST(b->vco, b->cdclk);
1869+
1870+
return a->vco != 0 && b->vco != 0 &&
1871+
a->vco != b->vco &&
1872+
a_div == b_div &&
1873+
a->ref == b->ref;
1874+
}
1875+
18231876
/**
18241877
* intel_cdclk_needs_modeset - Determine if changong between the CDCLK
18251878
* configurations requires a modeset on all pipes
@@ -2475,7 +2528,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
24752528
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
24762529
const struct intel_cdclk_state *old_cdclk_state;
24772530
struct intel_cdclk_state *new_cdclk_state;
2478-
enum pipe pipe;
2531+
enum pipe pipe = INVALID_PIPE;
24792532
int ret;
24802533

24812534
new_cdclk_state = intel_atomic_get_cdclk_state(state);
@@ -2527,15 +2580,18 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
25272580

25282581
if (drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
25292582
pipe = INVALID_PIPE;
2530-
} else {
2531-
pipe = INVALID_PIPE;
25322583
}
25332584

2534-
if (pipe != INVALID_PIPE) {
2585+
if (intel_cdclk_can_crawl(dev_priv,
2586+
&old_cdclk_state->actual,
2587+
&new_cdclk_state->actual)) {
2588+
drm_dbg_kms(&dev_priv->drm,
2589+
"Can change cdclk via crawl\n");
2590+
} else if (pipe != INVALID_PIPE) {
25352591
new_cdclk_state->pipe = pipe;
25362592

25372593
drm_dbg_kms(&dev_priv->drm,
2538-
"Can change cdclk with pipe %c active\n",
2594+
"Can change cdclk cd2x divider with pipe %c active\n",
25392595
pipe_name(pipe));
25402596
} else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual,
25412597
&new_cdclk_state->actual)) {
@@ -2544,8 +2600,6 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
25442600
if (ret)
25452601
return ret;
25462602

2547-
new_cdclk_state->pipe = INVALID_PIPE;
2548-
25492603
drm_dbg_kms(&dev_priv->drm,
25502604
"Modeset required for cdclk change\n");
25512605
}

drivers/gpu/drm/i915/i915_pci.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,7 @@ static const struct intel_device_info adl_p_info = {
953953
GEN12_FEATURES,
954954
XE_LPD_FEATURES,
955955
PLATFORM(INTEL_ALDERLAKE_P),
956+
.has_cdclk_crawl = 1,
956957
.require_force_probe = 1,
957958
.display.has_modular_fia = 1,
958959
.platform_engine_mask =

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10981,6 +10981,8 @@ enum skl_power_gate {
1098110981
#define BXT_DE_PLL_ENABLE _MMIO(0x46070)
1098210982
#define BXT_DE_PLL_PLL_ENABLE (1 << 31)
1098310983
#define BXT_DE_PLL_LOCK (1 << 30)
10984+
#define BXT_DE_PLL_FREQ_REQ (1 << 23)
10985+
#define BXT_DE_PLL_FREQ_REQ_ACK (1 << 22)
1098410986
#define CNL_CDCLK_PLL_RATIO(x) (x)
1098510987
#define CNL_CDCLK_PLL_RATIO_MASK 0xff
1098610988

drivers/gpu/drm/i915/intel_device_info.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ struct intel_device_info {
185185

186186
u8 abox_mask;
187187

188+
u8 has_cdclk_crawl; /* does support CDCLK crawling */
189+
188190
#define DEFINE_FLAG(name) u8 name:1
189191
DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG);
190192
#undef DEFINE_FLAG

0 commit comments

Comments
 (0)